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/ess | |
parent | f7f53d7d61bba235b8babf4cf580114d74183e3e (diff) |
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/ess')
-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 |
4 files changed, 162 insertions, 9 deletions
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; +} |