diff options
author | FdaSilvaYY <fdasilvayy@gmail.com> | 2019-06-12 19:52:39 +0200 |
---|---|---|
committer | Tomas Mraz <tmraz@fedoraproject.org> | 2020-05-27 13:16:30 +0200 |
commit | 9e3c510bde91350c5a40b7ba4e9e0945895e9368 (patch) | |
tree | 1720a2cfea2ffded3a4e374e2c6e110f2499dbc4 /crypto | |
parent | PROV: Use rsa_padding_add_PKCS1_OAEP_mgf1_with_libctx() in RSA-OAEP (diff) | |
download | openssl-9e3c510bde91350c5a40b7ba4e9e0945895e9368.tar.xz openssl-9e3c510bde91350c5a40b7ba4e9e0945895e9368.zip |
crypto/cms: add CAdES-BES signed attributes validation
for signing certificate V2 and signing certificate extensions.
CAdES: lowercase name for now internal methods.
crypto/cms: generated file changes.
Add some CHANGES entries.
[extended tests]
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
Reviewed-by: Tomas Mraz <tmraz@fedoraproject.org>
(Merged from https://github.com/openssl/openssl/pull/8098)
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/cms/cms_err.c | 4 | ||||
-rw-r--r-- | crypto/cms/cms_ess.c | 92 | ||||
-rw-r--r-- | crypto/cms/cms_local.h | 3 | ||||
-rw-r--r-- | crypto/cms/cms_smime.c | 43 | ||||
-rw-r--r-- | crypto/err/openssl.txt | 4 | ||||
-rw-r--r-- | crypto/ess/build.info | 9 | ||||
-rw-r--r-- | crypto/ess/ess_asn1.c | 62 | ||||
-rw-r--r-- | crypto/ess/ess_err.c | 2 | ||||
-rw-r--r-- | crypto/ess/ess_lib.c | 98 | ||||
-rw-r--r-- | crypto/ts/ts_rsp_verify.c | 93 |
10 files changed, 296 insertions, 114 deletions
diff --git a/crypto/cms/cms_err.c b/crypto/cms/cms_err.c index 526d77357e..16e25afc7f 100644 --- a/crypto/cms/cms_err.c +++ b/crypto/cms/cms_err.c @@ -52,6 +52,10 @@ static const ERR_STRING_DATA CMS_str_reasons[] = { {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_ERROR_SETTING_KEY), "error setting key"}, {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_ERROR_SETTING_RECIPIENTINFO), "error setting recipientinfo"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_ESS_NO_SIGNING_CERTID_ATTRIBUTE), + "ess no signing certid attribute"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_ESS_SIGNING_CERTID_MISMATCH_ERROR), + "ess signing certid mismatch error"}, {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_INVALID_ENCRYPTED_KEY_LENGTH), "invalid encrypted key length"}, {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER), diff --git a/crypto/cms/cms_ess.c b/crypto/cms/cms_ess.c index 3901074033..e3604f7db8 100644 --- a/crypto/cms/cms_ess.c +++ b/crypto/cms/cms_ess.c @@ -21,6 +21,9 @@ DEFINE_STACK_OF(GENERAL_NAMES) DEFINE_STACK_OF(CMS_SignerInfo) +DEFINE_STACK_OF(ESS_CERT_ID) +DEFINE_STACK_OF(ESS_CERT_ID_V2) +DEFINE_STACK_OF(X509) IMPLEMENT_ASN1_FUNCTIONS(CMS_ReceiptRequest) @@ -29,33 +32,100 @@ IMPLEMENT_ASN1_FUNCTIONS(CMS_ReceiptRequest) int CMS_get1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest **prr) { ASN1_STRING *str; - CMS_ReceiptRequest *rr = NULL; - if (prr) + CMS_ReceiptRequest *rr; + ASN1_OBJECT *obj = OBJ_nid2obj(NID_id_smime_aa_receiptRequest); + + if (prr != NULL) *prr = NULL; - str = CMS_signed_get0_data_by_OBJ(si, - OBJ_nid2obj - (NID_id_smime_aa_receiptRequest), -3, - V_ASN1_SEQUENCE); - if (!str) + str = CMS_signed_get0_data_by_OBJ(si, obj, -3, V_ASN1_SEQUENCE); + if (str == NULL) return 0; rr = ASN1_item_unpack(str, ASN1_ITEM_rptr(CMS_ReceiptRequest)); - if (!rr) + if (rr == NULL) return -1; - if (prr) + if (prr != NULL) *prr = rr; else CMS_ReceiptRequest_free(rr); return 1; } +/* + First, get the ESS_SIGNING_CERT(V2) signed attribute from |si|. + Then check matching of each cert of trust |chain| with one of + the |cert_ids|(Hash+IssuerID) list from this ESS_SIGNING_CERT. + Derived from ts_check_signing_certs() +*/ +int ess_check_signing_certs(CMS_SignerInfo *si, STACK_OF(X509) *chain) +{ + ESS_SIGNING_CERT *ss = NULL; + ESS_SIGNING_CERT_V2 *ssv2 = NULL; + X509 *cert; + int i = 0, ret = 0; + + if (cms_signerinfo_get_signing_cert(si, &ss) > 0 && ss->cert_ids != NULL) { + STACK_OF(ESS_CERT_ID) *cert_ids = ss->cert_ids; + + cert = sk_X509_value(chain, 0); + if (ess_find_cert(cert_ids, cert) != 0) + goto err; + + /* + * Check the other certificates of the chain. + * Fail if no signing certificate ids found for each certificate. + */ + if (sk_ESS_CERT_ID_num(cert_ids) > 1) { + /* for each chain cert, try to find its cert id */ + for (i = 1; i < sk_X509_num(chain); ++i) { + cert = sk_X509_value(chain, i); + if (ess_find_cert(cert_ids, cert) < 0) + goto err; + } + } + } else if (cms_signerinfo_get_signing_cert_v2(si, &ssv2) > 0 + && ssv2->cert_ids!= NULL) { + STACK_OF(ESS_CERT_ID_V2) *cert_ids_v2 = ssv2->cert_ids; + + cert = sk_X509_value(chain, 0); + if (ess_find_cert_v2(cert_ids_v2, cert) != 0) + goto err; + + /* + * Check the other certificates of the chain. + * Fail if no signing certificate ids found for each certificate. + */ + if (sk_ESS_CERT_ID_V2_num(cert_ids_v2) > 1) { + /* for each chain cert, try to find its cert id */ + for (i = 1; i < sk_X509_num(chain); ++i) { + cert = sk_X509_value(chain, i); + if (ess_find_cert_v2(cert_ids_v2, cert) < 0) + goto err; + } + } + } else { + CMSerr(CMS_F_ESS_CHECK_SIGNING_CERTS, + CMS_R_ESS_NO_SIGNING_CERTID_ATTRIBUTE); + return 0; + } + ret = 1; + err: + if (!ret) + CMSerr(CMS_F_ESS_CHECK_SIGNING_CERTS, + CMS_R_ESS_SIGNING_CERTID_MISMATCH_ERROR); + + ESS_SIGNING_CERT_free(ss); + ESS_SIGNING_CERT_V2_free(ssv2); + return ret; +} + CMS_ReceiptRequest *CMS_ReceiptRequest_create0(unsigned char *id, int idlen, int allorfirst, STACK_OF(GENERAL_NAMES) *receiptList, STACK_OF(GENERAL_NAMES) *receiptsTo) { - CMS_ReceiptRequest *rr = NULL; + CMS_ReceiptRequest *rr; rr = CMS_ReceiptRequest_new(); if (rr == NULL) @@ -145,6 +215,7 @@ static int cms_msgSigDigest(CMS_SignerInfo *si, unsigned char *dig, unsigned int *diglen) { const EVP_MD *md; + md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm); if (md == NULL) return 0; @@ -160,6 +231,7 @@ int cms_msgSigDigest_add1(CMS_SignerInfo *dest, CMS_SignerInfo *src) { unsigned char dig[EVP_MAX_MD_SIZE]; unsigned int diglen; + if (!cms_msgSigDigest(src, dig, &diglen)) { CMSerr(CMS_F_CMS_MSGSIGDIGEST_ADD1, CMS_R_MSGSIGDIGEST_ERROR); return 0; diff --git a/crypto/cms/cms_local.h b/crypto/cms/cms_local.h index 00ea9006c8..68c885622b 100644 --- a/crypto/cms/cms_local.h +++ b/crypto/cms/cms_local.h @@ -421,6 +421,9 @@ int cms_RecipientInfo_pwri_crypt(const CMS_ContentInfo *cms, CMS_RecipientInfo * /* SignerInfo routines */ int CMS_si_check_attributes(const CMS_SignerInfo *si); +/* ESS routines */ +int ess_check_signing_certs(CMS_SignerInfo *si, STACK_OF(X509) *chain); + DECLARE_ASN1_ITEM(CMS_CertificateChoices) DECLARE_ASN1_ITEM(CMS_DigestedData) DECLARE_ASN1_ITEM(CMS_EncryptedData) diff --git a/crypto/cms/cms_smime.c b/crypto/cms/cms_smime.c index dbdc815e97..a83edce0f7 100644 --- a/crypto/cms/cms_smime.c +++ b/crypto/cms/cms_smime.c @@ -233,7 +233,8 @@ CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher, static int cms_signerinfo_verify_cert(CMS_SignerInfo *si, X509_STORE *store, STACK_OF(X509) *certs, - STACK_OF(X509_CRL) *crls) + STACK_OF(X509_CRL) *crls, + STACK_OF(X509) **chain) { X509_STORE_CTX *ctx = X509_STORE_CTX_new(); X509 *signer; @@ -262,6 +263,10 @@ static int cms_signerinfo_verify_cert(CMS_SignerInfo *si, goto err; } r = 1; + + /* also send back the trust chain when required */ + if (chain != NULL) + *chain = X509_STORE_CTX_get1_chain(ctx); err: X509_STORE_CTX_free(ctx); return r; @@ -275,9 +280,11 @@ int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs, STACK_OF(CMS_SignerInfo) *sinfos; STACK_OF(X509) *cms_certs = NULL; STACK_OF(X509_CRL) *crls = NULL; + STACK_OF(X509) **si_chains = NULL; X509 *signer; int i, scount = 0, ret = 0; BIO *cmsbio = NULL, *tmpin = NULL, *tmpout = NULL; + int cadesVerify = (flags & CMS_CADES) != 0; if (!dcont && !check_content(cms)) return 0; @@ -312,27 +319,44 @@ int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs, } /* Attempt to verify all signers certs */ - - if (!(flags & CMS_NO_SIGNER_CERT_VERIFY)) { + /* at this point scount == sk_CMS_SignerInfo_num(sinfos) */ + + if ((flags & CMS_NO_SIGNER_CERT_VERIFY) == 0 || cadesVerify) { + if (cadesVerify) { + /* Certificate trust chain is required to check CAdES signature */ + si_chains = OPENSSL_zalloc(scount * sizeof(si_chains[0])); + if (si_chains == NULL) { + CMSerr(CMS_F_CMS_VERIFY, ERR_R_MALLOC_FAILURE); + goto err; + } + } cms_certs = CMS_get1_certs(cms); if (!(flags & CMS_NOCRL)) crls = CMS_get1_crls(cms); - for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) { + for (i = 0; i < scount; i++) { si = sk_CMS_SignerInfo_value(sinfos, i); - if (!cms_signerinfo_verify_cert(si, store, cms_certs, crls)) + + if (!cms_signerinfo_verify_cert(si, store, cms_certs, crls, + si_chains ? &si_chains[i] : NULL)) goto err; } } /* Attempt to verify all SignerInfo signed attribute signatures */ - if (!(flags & CMS_NO_ATTR_VERIFY)) { - for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) { + if ((flags & CMS_NO_ATTR_VERIFY) == 0 || cadesVerify) { + for (i = 0; i < scount; i++) { si = sk_CMS_SignerInfo_value(sinfos, i); if (CMS_signed_get_attr_count(si) < 0) continue; if (CMS_SignerInfo_verify(si) <= 0) goto err; + if (cadesVerify) { + STACK_OF(X509) *si_chain = si_chains ? si_chains[i] : NULL; + + if (ess_check_signing_certs(si, si_chain) <= 0) + goto err; + } } } @@ -420,6 +444,11 @@ int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs, BIO_free_all(tmpout); err2: + if (si_chains != NULL) { + for (i = 0; i < scount; ++i) + sk_X509_pop_free(si_chains[i], X509_free); + OPENSSL_free(si_chains); + } sk_X509_pop_free(cms_certs, X509_free); sk_X509_CRL_pop_free(crls, X509_CRL_free); diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 1b2c94b0a2..8afc67e747 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -320,6 +320,7 @@ CMS_F_CMS_SET_DETACHED:147:CMS_set_detached CMS_F_CMS_SIGN:148:CMS_sign CMS_F_CMS_SIGNED_DATA_INIT:149:cms_signed_data_init CMS_F_CMS_SIGNERINFO_CONTENT_SIGN:150:cms_SignerInfo_content_sign +CMS_F_CMS_SIGNERINFO_GET_CHAIN:184:cms_signerinfo_get_chain CMS_F_CMS_SIGNERINFO_SIGN:151:CMS_SignerInfo_sign CMS_F_CMS_SIGNERINFO_VERIFY:152:CMS_SignerInfo_verify CMS_F_CMS_SIGNERINFO_VERIFY_CERT:153:cms_signerinfo_verify_cert @@ -329,6 +330,7 @@ CMS_F_CMS_SI_CHECK_ATTRIBUTES:183:CMS_si_check_attributes CMS_F_CMS_STREAM:155:CMS_stream CMS_F_CMS_UNCOMPRESS:156:CMS_uncompress CMS_F_CMS_VERIFY:157:CMS_verify +CMS_F_ESS_CHECK_SIGNING_CERTS:185:ess_check_signing_certs CMS_F_KEK_UNWRAP_KEY:180:kek_unwrap_key COMP_F_BIO_ZLIB_FLUSH:99:bio_zlib_flush COMP_F_BIO_ZLIB_NEW:100:bio_zlib_new @@ -2188,6 +2190,8 @@ CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE:114:\ error reading messagedigest attribute CMS_R_ERROR_SETTING_KEY:115:error setting key CMS_R_ERROR_SETTING_RECIPIENTINFO:116:error setting recipientinfo +CMS_R_ESS_NO_SIGNING_CERTID_ATTRIBUTE:182:ess no signing certid attribute +CMS_R_ESS_SIGNING_CERTID_MISMATCH_ERROR:183:ess signing certid mismatch error CMS_R_INVALID_ENCRYPTED_KEY_LENGTH:117:invalid encrypted key length CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER:176:invalid key encryption parameter CMS_R_INVALID_KEY_LENGTH:118:invalid key length diff --git a/crypto/ess/build.info b/crypto/ess/build.info index 24fcecc8f5..fa2bc41d08 100644 --- a/crypto/ess/build.info +++ b/crypto/ess/build.info @@ -1,3 +1,8 @@ LIBS=../../libcrypto -SOURCE[../../libcrypto]= \ - ess_lib.c ess_asn1.c ess_err.c + +IF[{- !$disabled{'cms'} and !$disabled{'ts'} -}] + SOURCE[../../libcrypto]= ess_lib.c +ENDIF + +SOURCE[../../libcrypto]= ess_asn1.c ess_err.c + diff --git a/crypto/ess/ess_asn1.c b/crypto/ess/ess_asn1.c index 19589d97f3..a8d13a3a20 100644 --- a/crypto/ess/ess_asn1.c +++ b/crypto/ess/ess_asn1.c @@ -1,5 +1,5 @@ /* - * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -9,9 +9,11 @@ #include <openssl/err.h> #include <openssl/asn1t.h> +#include <openssl/cms.h> #include <openssl/ess.h> #include <openssl/x509v3.h> #include "crypto/ess.h" +#include "crypto/cms.h" /* ASN1 stuff for ESS Structure */ @@ -55,3 +57,61 @@ ASN1_SEQUENCE(ESS_SIGNING_CERT_V2) = { IMPLEMENT_ASN1_FUNCTIONS(ESS_SIGNING_CERT_V2) IMPLEMENT_ASN1_DUP_FUNCTION(ESS_SIGNING_CERT_V2) + +/* No cms support means no CMS_SignerInfo* definitions */ +#ifndef OPENSSL_NO_CMS + +/* + * Returns < 0 if attribute is not found, 1 if found, or + * -1 on attribute parsing failure. + */ +int cms_signerinfo_get_signing_cert_v2(CMS_SignerInfo *si, + ESS_SIGNING_CERT_V2 **psc) +{ + ASN1_STRING *str; + ESS_SIGNING_CERT_V2 *sc; + ASN1_OBJECT *obj = OBJ_nid2obj(NID_id_smime_aa_signingCertificateV2); + + if (psc != NULL) + *psc = NULL; + str = CMS_signed_get0_data_by_OBJ(si, obj, -3, V_ASN1_SEQUENCE); + if (str == NULL) + return 0; + + sc = ASN1_item_unpack(str, ASN1_ITEM_rptr(ESS_SIGNING_CERT_V2)); + if (sc == NULL) + return -1; + if (psc != NULL) + *psc = sc; + else + ESS_SIGNING_CERT_V2_free(sc); + return 1; +} + +/* + * Returns < 0 if attribute is not found, 1 if found, or + * -1 on attribute parsing failure. + */ +int cms_signerinfo_get_signing_cert(CMS_SignerInfo *si, + ESS_SIGNING_CERT **psc) +{ + ASN1_STRING *str; + ESS_SIGNING_CERT *sc; + ASN1_OBJECT *obj = OBJ_nid2obj(NID_id_smime_aa_signingCertificate); + + if (psc != NULL) + *psc = NULL; + str = CMS_signed_get0_data_by_OBJ(si, obj, -3, V_ASN1_SEQUENCE); + if (str == NULL) + return 0; + + sc = ASN1_item_unpack(str, ASN1_ITEM_rptr(ESS_SIGNING_CERT)); + if (sc == NULL) + return -1; + if (psc != NULL) + *psc = sc; + else + ESS_SIGNING_CERT_free(sc); + return 1; +} +#endif /* !OPENSSL_NO_CMS */ diff --git a/crypto/ess/ess_err.c b/crypto/ess/ess_err.c index b494aa246f..6547645fea 100644 --- a/crypto/ess/ess_err.c +++ b/crypto/ess/ess_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/ess/ess_lib.c b/crypto/ess/ess_lib.c index 9d9defa9d7..17f9db98ff 100644 --- a/crypto/ess/ess_lib.c +++ b/crypto/ess/ess_lib.c @@ -15,8 +15,8 @@ DEFINE_STACK_OF(ESS_CERT_ID) DEFINE_STACK_OF(ESS_CERT_ID_V2) -DEFINE_STACK_OF(X509) DEFINE_STACK_OF(GENERAL_NAME) +DEFINE_STACK_OF(X509) static ESS_CERT_ID *ESS_CERT_ID_new_init(X509 *cert, int issuer_needed); static ESS_CERT_ID_V2 *ESS_CERT_ID_V2_new_init(const EVP_MD *hash_alg, @@ -61,9 +61,12 @@ static ESS_CERT_ID *ESS_CERT_ID_new_init(X509 *cert, int issuer_needed) unsigned char cert_sha1[SHA_DIGEST_LENGTH]; /* Call for side-effect of computing hash and caching extensions */ - X509_check_purpose(cert, -1, 0); + if (!X509v3_cache_extensions(cert, NULL, NULL)) + return NULL; + if ((cid = ESS_CERT_ID_new()) == NULL) goto err; + /* TODO(3.0): fetch sha1 algorithm from providers */ if (!X509_digest(cert, EVP_sha1(), cert_sha1, NULL)) goto err; if (!ASN1_OCTET_STRING_set(cid->hash, cert_sha1, SHA_DIGEST_LENGTH)) @@ -85,8 +88,8 @@ static ESS_CERT_ID *ESS_CERT_ID_new_init(X509 *cert, int issuer_needed) goto err; name = NULL; /* Ownership is lost. */ ASN1_INTEGER_free(cid->issuer_serial->serial); - if (!(cid->issuer_serial->serial = - ASN1_INTEGER_dup(X509_get_serialNumber(cert)))) + if ((cid->issuer_serial->serial = + ASN1_INTEGER_dup(X509_get_serialNumber(cert))) == NULL) goto err; return cid; @@ -159,6 +162,7 @@ static ESS_CERT_ID_V2 *ESS_CERT_ID_V2_new_init(const EVP_MD *hash_alg, cid->hash_alg = NULL; } + /* TODO(3.0): fetch sha1 algorithm from providers */ if (!X509_digest(cert, hash_alg, hash, &hash_len)) goto err; @@ -196,8 +200,9 @@ ESS_SIGNING_CERT *ESS_SIGNING_CERT_get(PKCS7_SIGNER_INFO *si) { ASN1_TYPE *attr; const unsigned char *p; + attr = PKCS7_get_signed_attribute(si, NID_id_smime_aa_signingCertificate); - if (!attr) + if (attr == NULL) return NULL; p = attr->value.sequence->data; return d2i_ESS_SIGNING_CERT(NULL, &p, attr->value.sequence->length); @@ -273,3 +278,86 @@ int ESS_SIGNING_CERT_V2_add(PKCS7_SIGNER_INFO *si, OPENSSL_free(pp); return 0; } + +static int ess_issuer_serial_cmp(const ESS_ISSUER_SERIAL *is, const X509 *cert) +{ + GENERAL_NAME *issuer; + + if (is == NULL || cert == NULL || sk_GENERAL_NAME_num(is->issuer) != 1) + return -1; + + issuer = sk_GENERAL_NAME_value(is->issuer, 0); + if (issuer->type != GEN_DIRNAME + || X509_NAME_cmp(issuer->d.dirn, X509_get_issuer_name(cert)) != 0) + return -1; + + return ASN1_INTEGER_cmp(is->serial, X509_get0_serialNumber(cert)); +} + +/* Returns < 0 if certificate is not found, certificate index otherwise. */ +int ess_find_cert(const STACK_OF(ESS_CERT_ID) *cert_ids, X509 *cert) +{ + int i; + unsigned char cert_sha1[SHA_DIGEST_LENGTH]; + + if (cert_ids == NULL || cert == NULL) + return -1; + + /* Recompute SHA1 hash of certificate if necessary (side effect). */ + if (!X509v3_cache_extensions(cert, NULL, NULL)) + return -1; + + /* TODO(3.0): fetch sha1 algorithm from providers */ + if (!X509_digest(cert, EVP_sha1(), cert_sha1, NULL)) + return -1; + + /* Look for cert in the cert_ids vector. */ + for (i = 0; i < sk_ESS_CERT_ID_num(cert_ids); ++i) { + const ESS_CERT_ID *cid = sk_ESS_CERT_ID_value(cert_ids, i); + + if (cid->hash->length == SHA_DIGEST_LENGTH + && memcmp(cid->hash->data, cert_sha1, SHA_DIGEST_LENGTH) == 0) { + const ESS_ISSUER_SERIAL *is = cid->issuer_serial; + + if (is == NULL || ess_issuer_serial_cmp(is, cert) == 0) + return i; + } + } + + return -1; +} + +/* Returns < 0 if certificate is not found, certificate index otherwise. */ +int ess_find_cert_v2(const STACK_OF(ESS_CERT_ID_V2) *cert_ids, const X509 *cert) +{ + int i; + unsigned char cert_digest[EVP_MAX_MD_SIZE]; + unsigned int len; + + /* Look for cert in the cert_ids vector. */ + for (i = 0; i < sk_ESS_CERT_ID_V2_num(cert_ids); ++i) { + const ESS_CERT_ID_V2 *cid = sk_ESS_CERT_ID_V2_value(cert_ids, i); + const EVP_MD *md; + + if (cid != NULL && cid->hash_alg != NULL) + md = EVP_get_digestbyobj(cid->hash_alg->algorithm); + else + md = EVP_sha256(); + + /* TODO(3.0): fetch sha1 algorithm from providers */ + if (!X509_digest(cert, md, cert_digest, &len)) + return -1; + + if (cid->hash->length != (int)len) + return -1; + + if (memcmp(cid->hash->data, cert_digest, cid->hash->length) == 0) { + const ESS_ISSUER_SERIAL *is = cid->issuer_serial; + + if (is == NULL || ess_issuer_serial_cmp(is, cert) == 0) + return i; + } + } + + return -1; +} diff --git a/crypto/ts/ts_rsp_verify.c b/crypto/ts/ts_rsp_verify.c index b872f75bea..c909b211d4 100644 --- a/crypto/ts/ts_rsp_verify.c +++ b/crypto/ts/ts_rsp_verify.c @@ -26,8 +26,7 @@ static int ts_verify_cert(X509_STORE *store, STACK_OF(X509) *untrusted, X509 *signer, STACK_OF(X509) **chain); static int ts_check_signing_certs(PKCS7_SIGNER_INFO *si, STACK_OF(X509) *chain); -static int ts_find_cert(STACK_OF(ESS_CERT_ID) *cert_ids, X509 *cert); -static int ts_issuer_serial_cmp(ESS_ISSUER_SERIAL *is, X509 *cert); + static int int_ts_RESP_verify_token(TS_VERIFY_CTX *ctx, PKCS7 *token, TS_TST_INFO *tst_info); static int ts_check_status_info(TS_RESP *response); @@ -44,7 +43,6 @@ static int ts_check_nonces(const ASN1_INTEGER *a, TS_TST_INFO *tst_info); static int ts_check_signer_name(GENERAL_NAME *tsa_name, X509 *signer); static int ts_find_name(STACK_OF(GENERAL_NAME) *gen_names, GENERAL_NAME *name); -static int ts_find_cert_v2(STACK_OF(ESS_CERT_ID_V2) *cert_ids, X509 *cert); /* * This must be large enough to hold all values in ts_status_text (with @@ -218,7 +216,7 @@ static int ts_check_signing_certs(PKCS7_SIGNER_INFO *si, if (ss != NULL) { cert_ids = ss->cert_ids; cert = sk_X509_value(chain, 0); - if (ts_find_cert(cert_ids, cert) != 0) + if (ess_find_cert(cert_ids, cert) != 0) goto err; /* @@ -228,14 +226,14 @@ static int ts_check_signing_certs(PKCS7_SIGNER_INFO *si, if (sk_ESS_CERT_ID_num(cert_ids) > 1) { for (i = 1; i < sk_X509_num(chain); ++i) { cert = sk_X509_value(chain, i); - if (ts_find_cert(cert_ids, cert) < 0) + if (ess_find_cert(cert_ids, cert) < 0) goto err; } } } else if (ssv2 != NULL) { cert_ids_v2 = ssv2->cert_ids; cert = sk_X509_value(chain, 0); - if (ts_find_cert_v2(cert_ids_v2, cert) != 0) + if (ess_find_cert_v2(cert_ids_v2, cert) != 0) goto err; /* @@ -245,7 +243,7 @@ static int ts_check_signing_certs(PKCS7_SIGNER_INFO *si, if (sk_ESS_CERT_ID_V2_num(cert_ids_v2) > 1) { for (i = 1; i < sk_X509_num(chain); ++i) { cert = sk_X509_value(chain, i); - if (ts_find_cert_v2(cert_ids_v2, cert) < 0) + if (ess_find_cert_v2(cert_ids_v2, cert) < 0) goto err; } } @@ -263,87 +261,6 @@ static int ts_check_signing_certs(PKCS7_SIGNER_INFO *si, return ret; } -/* Returns < 0 if certificate is not found, certificate index otherwise. */ -static int ts_find_cert(STACK_OF(ESS_CERT_ID) *cert_ids, X509 *cert) -{ - int i; - unsigned char cert_sha1[SHA_DIGEST_LENGTH]; - - if (!cert_ids || !cert) - return -1; - - /* Recompute SHA1 hash of certificate if necessary (side effect). */ - X509_check_purpose(cert, -1, 0); - - if (!X509_digest(cert, EVP_sha1(), cert_sha1, NULL)) - return -1; - - /* Look for cert in the cert_ids vector. */ - for (i = 0; i < sk_ESS_CERT_ID_num(cert_ids); ++i) { - ESS_CERT_ID *cid = sk_ESS_CERT_ID_value(cert_ids, i); - - if (cid->hash->length == SHA_DIGEST_LENGTH - && memcmp(cid->hash->data, cert_sha1, SHA_DIGEST_LENGTH) == 0) { - ESS_ISSUER_SERIAL *is = cid->issuer_serial; - if (!is || !ts_issuer_serial_cmp(is, cert)) - return i; - } - } - - return -1; -} - -/* Returns < 0 if certificate is not found, certificate index otherwise. */ -static int ts_find_cert_v2(STACK_OF(ESS_CERT_ID_V2) *cert_ids, X509 *cert) -{ - int i; - unsigned char cert_digest[EVP_MAX_MD_SIZE]; - unsigned int len; - - /* Look for cert in the cert_ids vector. */ - for (i = 0; i < sk_ESS_CERT_ID_V2_num(cert_ids); ++i) { - ESS_CERT_ID_V2 *cid = sk_ESS_CERT_ID_V2_value(cert_ids, i); - const EVP_MD *md; - - if (cid->hash_alg != NULL) - md = EVP_get_digestbyobj(cid->hash_alg->algorithm); - else - md = EVP_sha256(); - - if (!X509_digest(cert, md, cert_digest, &len)) - return -1; - if (cid->hash->length != (int)len) - return -1; - - if (memcmp(cid->hash->data, cert_digest, cid->hash->length) == 0) { - ESS_ISSUER_SERIAL *is = cid->issuer_serial; - - if (is == NULL || !ts_issuer_serial_cmp(is, cert)) - return i; - } - } - - return -1; -} - -static int ts_issuer_serial_cmp(ESS_ISSUER_SERIAL *is, X509 *cert) -{ - GENERAL_NAME *issuer; - - if (!is || !cert || sk_GENERAL_NAME_num(is->issuer) != 1) - return -1; - - issuer = sk_GENERAL_NAME_value(is->issuer, 0); - if (issuer->type != GEN_DIRNAME - || X509_NAME_cmp(issuer->d.dirn, X509_get_issuer_name(cert))) - return -1; - - if (ASN1_INTEGER_cmp(is->serial, X509_get_serialNumber(cert))) - return -1; - - return 0; -} - /*- * Verifies whether 'response' contains a valid response with regards * to the settings of the context: |