diff options
Diffstat (limited to 'crypto/ts/ts_rsp_verify.c')
| -rw-r--r-- | crypto/ts/ts_rsp_verify.c | 276 |
1 files changed, 71 insertions, 205 deletions
diff --git a/crypto/ts/ts_rsp_verify.c b/crypto/ts/ts_rsp_verify.c index 7fe3d27e74a2..792a27ce572b 100644 --- a/crypto/ts/ts_rsp_verify.c +++ b/crypto/ts/ts_rsp_verify.c @@ -1,26 +1,26 @@ /* * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html */ #include <stdio.h> -#include "internal/cryptlib.h" #include <openssl/objects.h> #include <openssl/ts.h> #include <openssl/pkcs7.h> +#include "internal/cryptlib.h" +#include "internal/sizes.h" +#include "crypto/ess.h" #include "ts_local.h" 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 ESS_SIGNING_CERT *ess_get_signing_cert(PKCS7_SIGNER_INFO *si); -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 ts_check_signing_certs(const PKCS7_SIGNER_INFO *si, + const STACK_OF(X509) *chain); + 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); @@ -37,8 +37,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); -static ESS_SIGNING_CERT_V2 *ess_get_signing_cert_v2(PKCS7_SIGNER_INFO *si); /* * This must be large enough to hold all values in ts_status_text (with @@ -92,6 +90,7 @@ int TS_RESP_verify_signature(PKCS7 *token, STACK_OF(X509) *certs, { STACK_OF(PKCS7_SIGNER_INFO) *sinfos = NULL; PKCS7_SIGNER_INFO *si; + STACK_OF(X509) *untrusted = NULL; STACK_OF(X509) *signers = NULL; X509 *signer; STACK_OF(X509) *chain = NULL; @@ -101,21 +100,21 @@ int TS_RESP_verify_signature(PKCS7 *token, STACK_OF(X509) *certs, /* Some sanity checks first. */ if (!token) { - TSerr(TS_F_TS_RESP_VERIFY_SIGNATURE, TS_R_INVALID_NULL_POINTER); + ERR_raise(ERR_LIB_TS, TS_R_INVALID_NULL_POINTER); goto err; } if (!PKCS7_type_is_signed(token)) { - TSerr(TS_F_TS_RESP_VERIFY_SIGNATURE, TS_R_WRONG_CONTENT_TYPE); + ERR_raise(ERR_LIB_TS, TS_R_WRONG_CONTENT_TYPE); goto err; } sinfos = PKCS7_get_signer_info(token); if (!sinfos || sk_PKCS7_SIGNER_INFO_num(sinfos) != 1) { - TSerr(TS_F_TS_RESP_VERIFY_SIGNATURE, TS_R_THERE_MUST_BE_ONE_SIGNER); + ERR_raise(ERR_LIB_TS, TS_R_THERE_MUST_BE_ONE_SIGNER); goto err; } si = sk_PKCS7_SIGNER_INFO_value(sinfos, 0); if (PKCS7_get_detached(token)) { - TSerr(TS_F_TS_RESP_VERIFY_SIGNATURE, TS_R_NO_CONTENT); + ERR_raise(ERR_LIB_TS, TS_R_NO_CONTENT); goto err; } @@ -128,7 +127,13 @@ int TS_RESP_verify_signature(PKCS7 *token, STACK_OF(X509) *certs, goto err; signer = sk_X509_value(signers, 0); - if (!ts_verify_cert(store, certs, signer, &chain)) + untrusted = sk_X509_new_reserve(NULL, sk_X509_num(certs) + + sk_X509_num(token->d.sign->cert)); + if (untrusted == NULL + || !X509_add_certs(untrusted, certs, 0) + || !X509_add_certs(untrusted, token->d.sign->cert, 0)) + goto err; + if (!ts_verify_cert(store, untrusted, signer, &chain)) goto err; if (!ts_check_signing_certs(si, chain)) goto err; @@ -140,7 +145,7 @@ int TS_RESP_verify_signature(PKCS7 *token, STACK_OF(X509) *certs, j = PKCS7_signatureVerify(p7bio, token, si, signer); if (j <= 0) { - TSerr(TS_F_TS_RESP_VERIFY_SIGNATURE, TS_R_SIGNATURE_FAILURE); + ERR_raise(ERR_LIB_TS, TS_R_SIGNATURE_FAILURE); goto err; } @@ -152,6 +157,7 @@ int TS_RESP_verify_signature(PKCS7 *token, STACK_OF(X509) *certs, err: BIO_free_all(p7bio); + sk_X509_free(untrusted); sk_X509_pop_free(chain, X509_free); sk_X509_free(signers); @@ -172,7 +178,7 @@ static int ts_verify_cert(X509_STORE *store, STACK_OF(X509) *untrusted, *chain = NULL; cert_ctx = X509_STORE_CTX_new(); if (cert_ctx == NULL) { - TSerr(TS_F_TS_VERIFY_CERT, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE); goto err; } if (!X509_STORE_CTX_init(cert_ctx, store, signer, untrusted)) @@ -181,9 +187,8 @@ static int ts_verify_cert(X509_STORE *store, STACK_OF(X509) *untrusted, i = X509_verify_cert(cert_ctx); if (i <= 0) { int j = X509_STORE_CTX_get_error(cert_ctx); - TSerr(TS_F_TS_VERIFY_CERT, TS_R_CERTIFICATE_VERIFY_ERROR); - ERR_add_error_data(2, "Verify error:", - X509_verify_cert_error_string(j)); + ERR_raise_data(ERR_LIB_TS, TS_R_CERTIFICATE_VERIFY_ERROR, + "Verify error:%s", X509_verify_cert_error_string(j)); goto err; } *chain = X509_STORE_CTX_get1_chain(cert_ctx); @@ -198,77 +203,20 @@ end: return ret; } -static int ts_check_signing_certs(PKCS7_SIGNER_INFO *si, - STACK_OF(X509) *chain) -{ - ESS_SIGNING_CERT *ss = ess_get_signing_cert(si); - STACK_OF(ESS_CERT_ID) *cert_ids = NULL; - ESS_SIGNING_CERT_V2 *ssv2 = ess_get_signing_cert_v2(si); - STACK_OF(ESS_CERT_ID_V2) *cert_ids_v2 = NULL; - X509 *cert; - int i = 0; - int ret = 0; - - if (ss != NULL) { - cert_ids = ss->cert_ids; - cert = sk_X509_value(chain, 0); - if (ts_find_cert(cert_ids, cert) != 0) - goto err; - - /* - * Check the other certificates of the chain if there are more than one - * certificate ids in cert_ids. - */ - 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) - 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) - goto err; - - /* - * Check the other certificates of the chain if there are more than one - * certificate ids in cert_ids. - */ - 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) - goto err; - } - } - } else { - goto err; - } - - ret = 1; - err: - if (!ret) - TSerr(TS_F_TS_CHECK_SIGNING_CERTS, - TS_R_ESS_SIGNING_CERTIFICATE_ERROR); - ESS_SIGNING_CERT_free(ss); - ESS_SIGNING_CERT_V2_free(ssv2); - return ret; -} - -static ESS_SIGNING_CERT *ess_get_signing_cert(PKCS7_SIGNER_INFO *si) +static ESS_SIGNING_CERT *ossl_ess_get_signing_cert(const 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); } -static ESS_SIGNING_CERT_V2 *ess_get_signing_cert_v2(PKCS7_SIGNER_INFO *si) +static +ESS_SIGNING_CERT_V2 *ossl_ess_get_signing_cert_v2(const PKCS7_SIGNER_INFO *si) { ASN1_TYPE *attr; const unsigned char *p; @@ -280,85 +228,16 @@ static ESS_SIGNING_CERT_V2 *ess_get_signing_cert_v2(PKCS7_SIGNER_INFO *si) return d2i_ESS_SIGNING_CERT_V2(NULL, &p, attr->value.sequence->length); } -/* 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) +static int ts_check_signing_certs(const PKCS7_SIGNER_INFO *si, + const STACK_OF(X509) *chain) { - 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; + ESS_SIGNING_CERT *ss = ossl_ess_get_signing_cert(si); + ESS_SIGNING_CERT_V2 *ssv2 = ossl_ess_get_signing_cert_v2(si); + int ret = OSSL_ESS_check_signing_certs(ss, ssv2, chain, 1) > 0; - 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; + ESS_SIGNING_CERT_free(ss); + ESS_SIGNING_CERT_V2_free(ssv2); + return ret; } /*- @@ -432,7 +311,7 @@ static int int_ts_RESP_verify_token(TS_VERIFY_CTX *ctx, goto err; if ((flags & TS_VFY_VERSION) && TS_TST_INFO_get_version(tst_info) != 1) { - TSerr(TS_F_INT_TS_RESP_VERIFY_TOKEN, TS_R_UNSUPPORTED_VERSION); + ERR_raise(ERR_LIB_TS, TS_R_UNSUPPORTED_VERSION); goto err; } if ((flags & TS_VFY_POLICY) @@ -452,12 +331,12 @@ static int int_ts_RESP_verify_token(TS_VERIFY_CTX *ctx, goto err; if ((flags & TS_VFY_SIGNER) && tsa_name && !ts_check_signer_name(tsa_name, signer)) { - TSerr(TS_F_INT_TS_RESP_VERIFY_TOKEN, TS_R_TSA_NAME_MISMATCH); + ERR_raise(ERR_LIB_TS, TS_R_TSA_NAME_MISMATCH); goto err; } if ((flags & TS_VFY_TSA_NAME) && !ts_check_signer_name(ctx->tsa_name, signer)) { - TSerr(TS_F_INT_TS_RESP_VERIFY_TOKEN, TS_R_TSA_UNTRUSTED); + ERR_raise(ERR_LIB_TS, TS_R_TSA_UNTRUSTED); goto err; } ret = 1; @@ -508,12 +387,11 @@ static int ts_check_status_info(TS_RESP *response) if (failure_text[0] == '\0') strcpy(failure_text, "unspecified"); - TSerr(TS_F_TS_CHECK_STATUS_INFO, TS_R_NO_TIME_STAMP_TOKEN); - ERR_add_error_data(6, - "status code: ", status_text, - ", status text: ", embedded_status_text ? - embedded_status_text : "unspecified", - ", failure codes: ", failure_text); + ERR_raise_data(ERR_LIB_TS, TS_R_NO_TIME_STAMP_TOKEN, + "status code: %s, status text: %s, failure codes: %s", + status_text, + embedded_status_text ? embedded_status_text : "unspecified", + failure_text); OPENSSL_free(embedded_status_text); return 0; @@ -521,34 +399,7 @@ static int ts_check_status_info(TS_RESP *response) static char *ts_get_status_text(STACK_OF(ASN1_UTF8STRING) *text) { - int i; - int length = 0; - char *result = NULL; - char *p; - - for (i = 0; i < sk_ASN1_UTF8STRING_num(text); ++i) { - ASN1_UTF8STRING *current = sk_ASN1_UTF8STRING_value(text, i); - if (ASN1_STRING_length(current) > TS_MAX_STATUS_LENGTH - length - 1) - return NULL; - length += ASN1_STRING_length(current); - length += 1; /* separator character */ - } - if ((result = OPENSSL_malloc(length)) == NULL) { - TSerr(TS_F_TS_GET_STATUS_TEXT, ERR_R_MALLOC_FAILURE); - return NULL; - } - - for (i = 0, p = result; i < sk_ASN1_UTF8STRING_num(text); ++i) { - ASN1_UTF8STRING *current = sk_ASN1_UTF8STRING_value(text, i); - length = ASN1_STRING_length(current); - if (i > 0) - *p++ = '/'; - strncpy(p, (const char *)ASN1_STRING_get0_data(current), length); - p += length; - } - *p = '\0'; - - return result; + return ossl_sk_ASN1_UTF8STRING2text(text, "/", TS_MAX_STATUS_LENGTH); } static int ts_check_policy(const ASN1_OBJECT *req_oid, @@ -557,7 +408,7 @@ static int ts_check_policy(const ASN1_OBJECT *req_oid, const ASN1_OBJECT *resp_oid = tst_info->policy_id; if (OBJ_cmp(req_oid, resp_oid) != 0) { - TSerr(TS_F_TS_CHECK_POLICY, TS_R_POLICY_MISMATCH); + ERR_raise(ERR_LIB_TS, TS_R_POLICY_MISMATCH); return 0; } @@ -570,9 +421,10 @@ static int ts_compute_imprint(BIO *data, TS_TST_INFO *tst_info, { TS_MSG_IMPRINT *msg_imprint = tst_info->msg_imprint; X509_ALGOR *md_alg_resp = msg_imprint->hash_algo; - const EVP_MD *md; + EVP_MD *md = NULL; EVP_MD_CTX *md_ctx = NULL; unsigned char buffer[4096]; + char name[OSSL_MAX_NAME_SIZE]; int length; *md_alg = NULL; @@ -580,26 +432,39 @@ static int ts_compute_imprint(BIO *data, TS_TST_INFO *tst_info, if ((*md_alg = X509_ALGOR_dup(md_alg_resp)) == NULL) goto err; - if ((md = EVP_get_digestbyobj((*md_alg)->algorithm)) == NULL) { - TSerr(TS_F_TS_COMPUTE_IMPRINT, TS_R_UNSUPPORTED_MD_ALGORITHM); + + OBJ_obj2txt(name, sizeof(name), md_alg_resp->algorithm, 0); + + (void)ERR_set_mark(); + md = EVP_MD_fetch(NULL, name, NULL); + + if (md == NULL) + md = (EVP_MD *)EVP_get_digestbyname(name); + + if (md == NULL) { + (void)ERR_clear_last_mark(); goto err; } - length = EVP_MD_size(md); + (void)ERR_pop_to_mark(); + + length = EVP_MD_get_size(md); if (length < 0) goto err; *imprint_len = length; if ((*imprint = OPENSSL_malloc(*imprint_len)) == NULL) { - TSerr(TS_F_TS_COMPUTE_IMPRINT, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE); goto err; } md_ctx = EVP_MD_CTX_new(); if (md_ctx == NULL) { - TSerr(TS_F_TS_COMPUTE_IMPRINT, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE); goto err; } if (!EVP_DigestInit(md_ctx, md)) goto err; + EVP_MD_free(md); + md = NULL; while ((length = BIO_read(data, buffer, sizeof(buffer))) > 0) { if (!EVP_DigestUpdate(md_ctx, buffer, length)) goto err; @@ -611,6 +476,7 @@ static int ts_compute_imprint(BIO *data, TS_TST_INFO *tst_info, return 1; err: EVP_MD_CTX_free(md_ctx); + EVP_MD_free(md); X509_ALGOR_free(*md_alg); *md_alg = NULL; OPENSSL_free(*imprint); @@ -643,7 +509,7 @@ static int ts_check_imprints(X509_ALGOR *algor_a, memcmp(imprint_a, ASN1_STRING_get0_data(b->hashed_msg), len_a) == 0; err: if (!ret) - TSerr(TS_F_TS_CHECK_IMPRINTS, TS_R_MESSAGE_IMPRINT_MISMATCH); + ERR_raise(ERR_LIB_TS, TS_R_MESSAGE_IMPRINT_MISMATCH); return ret; } @@ -652,13 +518,13 @@ static int ts_check_nonces(const ASN1_INTEGER *a, TS_TST_INFO *tst_info) const ASN1_INTEGER *b = tst_info->nonce; if (!b) { - TSerr(TS_F_TS_CHECK_NONCES, TS_R_NONCE_NOT_RETURNED); + ERR_raise(ERR_LIB_TS, TS_R_NONCE_NOT_RETURNED); return 0; } /* No error if a nonce is returned without being requested. */ if (ASN1_INTEGER_cmp(a, b) != 0) { - TSerr(TS_F_TS_CHECK_NONCES, TS_R_NONCE_MISMATCH); + ERR_raise(ERR_LIB_TS, TS_R_NONCE_MISMATCH); return 0; } |
