diff options
author | Viktor Söderqvist <viktor.soderqvist@est.tech> | 2021-04-28 10:54:57 +0200 |
---|---|---|
committer | Todd Short <todd.short@me.com> | 2022-04-02 10:42:16 -0400 |
commit | 07342bad1bf850657e1a1f21188ee9a8a75e3a19 (patch) | |
tree | f9b918931dd10d5a1e58a3a7c039eb29b1e39a7c /crypto | |
parent | e4cdcb8bc44250aa4e0893dc4a7d64668f0fb949 (diff) |
CMS sign digest
CLI changes: New parameter -digest to CLI command openssl cms, to
provide pre-computed digest for use with -sign.
API changes: New function CMS_final_digest(), like CMS_final() but
uses a pre-computed digest instead of computing it from the data.
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: David von Oheimb <david.von.oheimb@siemens.com>
Reviewed-by: Todd Short <todd.short@me.com>
(Merged from https://github.com/openssl/openssl/pull/15348)
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/cms/cms_err.c | 4 | ||||
-rw-r--r-- | crypto/cms/cms_lib.c | 9 | ||||
-rw-r--r-- | crypto/cms/cms_local.h | 7 | ||||
-rw-r--r-- | crypto/cms/cms_sd.c | 34 | ||||
-rw-r--r-- | crypto/cms/cms_smime.c | 25 | ||||
-rw-r--r-- | crypto/err/openssl.txt | 1 |
6 files changed, 66 insertions, 14 deletions
diff --git a/crypto/cms/cms_err.c b/crypto/cms/cms_err.c index 1fba9d8502..293b65a1f4 100644 --- a/crypto/cms/cms_err.c +++ b/crypto/cms/cms_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2022 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 @@ -109,6 +109,8 @@ static const ERR_STRING_DATA CMS_str_reasons[] = { {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_PUBLIC_KEY), "no public key"}, {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_RECEIPT_REQUEST), "no receipt request"}, {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_SIGNERS), "no signers"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_OPERATION_UNSUPPORTED), + "operation unsupported"}, {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_PEER_KEY_ERROR), "peer key error"}, {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE), "private key does not match certificate"}, diff --git a/crypto/cms/cms_lib.c b/crypto/cms/cms_lib.c index 0b25bc234e..4d5a11624f 100644 --- a/crypto/cms/cms_lib.c +++ b/crypto/cms/cms_lib.c @@ -208,6 +208,13 @@ err: /* unfortunately cannot constify SMIME_write_ASN1() due to this function */ int CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio) { + return ossl_cms_DataFinal(cms, cmsbio, NULL, 0); +} + +int ossl_cms_DataFinal(CMS_ContentInfo *cms, BIO *cmsbio, + const unsigned char *precomp_md, + unsigned int precomp_mdlen) +{ ASN1_OCTET_STRING **pos = CMS_get0_content(cms); if (pos == NULL) @@ -245,7 +252,7 @@ int CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio) return ossl_cms_AuthEnvelopedData_final(cms, cmsbio); case NID_pkcs7_signed: - return ossl_cms_SignedData_final(cms, cmsbio); + return ossl_cms_SignedData_final(cms, cmsbio, precomp_md, precomp_mdlen); case NID_pkcs7_digest: return ossl_cms_DigestedData_do_final(cms, cmsbio, 0); diff --git a/crypto/cms/cms_local.h b/crypto/cms/cms_local.h index e9fb43715a..d44bf3b0a1 100644 --- a/crypto/cms/cms_local.h +++ b/crypto/cms/cms_local.h @@ -395,6 +395,9 @@ const char *ossl_cms_ctx_get0_propq(const CMS_CTX *ctx); void ossl_cms_resolve_libctx(CMS_ContentInfo *ci); CMS_ContentInfo *ossl_cms_Data_create(OSSL_LIB_CTX *ctx, const char *propq); +int ossl_cms_DataFinal(CMS_ContentInfo *cms, BIO *cmsbio, + const unsigned char *precomp_md, + unsigned int precomp_mdlen); CMS_ContentInfo *ossl_cms_DigestedData_create(const EVP_MD *md, OSSL_LIB_CTX *libctx, @@ -404,7 +407,9 @@ int ossl_cms_DigestedData_do_final(const CMS_ContentInfo *cms, BIO *chain, int verify); BIO *ossl_cms_SignedData_init_bio(CMS_ContentInfo *cms); -int ossl_cms_SignedData_final(CMS_ContentInfo *cms, BIO *chain); +int ossl_cms_SignedData_final(CMS_ContentInfo *cms, BIO *chain, + const unsigned char *precomp_md, + unsigned int precomp_mdlen); int ossl_cms_set1_SignerIdentifier(CMS_SignerIdentifier *sid, X509 *cert, int type, const CMS_CTX *ctx); int ossl_cms_SignerIdentifier_get0_signer_id(CMS_SignerIdentifier *sid, diff --git a/crypto/cms/cms_sd.c b/crypto/cms/cms_sd.c index d1e5ec8b4e..ee210eab29 100644 --- a/crypto/cms/cms_sd.c +++ b/crypto/cms/cms_sd.c @@ -694,7 +694,9 @@ ASN1_OCTET_STRING *CMS_SignerInfo_get0_signature(CMS_SignerInfo *si) } static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms, - CMS_SignerInfo *si, BIO *chain) + CMS_SignerInfo *si, BIO *chain, + const unsigned char *md, + unsigned int mdlen) { EVP_MD_CTX *mctx = EVP_MD_CTX_new(); int r = 0; @@ -722,11 +724,13 @@ static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms, */ if (CMS_signed_get_attr_count(si) >= 0) { - unsigned char md[EVP_MAX_MD_SIZE]; - unsigned int mdlen; + unsigned char computed_md[EVP_MAX_MD_SIZE]; - if (!EVP_DigestFinal_ex(mctx, md, &mdlen)) - goto err; + if (md == NULL) { + if (!EVP_DigestFinal_ex(mctx, computed_md, &mdlen)) + goto err; + md = computed_md; + } if (!CMS_signed_add1_attr_by_NID(si, NID_pkcs9_messageDigest, V_ASN1_OCTET_STRING, md, mdlen)) goto err; @@ -739,12 +743,14 @@ static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms, } else if (si->pctx) { unsigned char *sig; size_t siglen; - unsigned char md[EVP_MAX_MD_SIZE]; - unsigned int mdlen; + unsigned char computed_md[EVP_MAX_MD_SIZE]; pctx = si->pctx; - if (!EVP_DigestFinal_ex(mctx, md, &mdlen)) - goto err; + if (md == NULL) { + if (!EVP_DigestFinal_ex(mctx, computed_md, &mdlen)) + goto err; + md = computed_md; + } siglen = EVP_PKEY_get_size(si->pkey); sig = OPENSSL_malloc(siglen); if (sig == NULL) { @@ -760,6 +766,10 @@ static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms, unsigned char *sig; unsigned int siglen; + if (md != NULL) { + ERR_raise(ERR_LIB_CMS, CMS_R_OPERATION_UNSUPPORTED); + goto err; + } sig = OPENSSL_malloc(EVP_PKEY_get_size(si->pkey)); if (sig == NULL) { ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); @@ -784,7 +794,9 @@ static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms, } -int ossl_cms_SignedData_final(CMS_ContentInfo *cms, BIO *chain) +int ossl_cms_SignedData_final(CMS_ContentInfo *cms, BIO *chain, + const unsigned char *precomp_md, + unsigned int precomp_mdlen) { STACK_OF(CMS_SignerInfo) *sinfos; CMS_SignerInfo *si; @@ -793,7 +805,7 @@ int ossl_cms_SignedData_final(CMS_ContentInfo *cms, BIO *chain) sinfos = CMS_get0_SignerInfos(cms); for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) { si = sk_CMS_SignerInfo_value(sinfos, i); - if (!cms_SignerInfo_content_sign(cms, si, chain)) + if (!cms_SignerInfo_content_sign(cms, si, chain, precomp_md, precomp_mdlen)) return 0; } cms->d.signedData->encapContentInfo->partial = 0; diff --git a/crypto/cms/cms_smime.c b/crypto/cms/cms_smime.c index b82eee32cb..690ea3291b 100644 --- a/crypto/cms/cms_smime.c +++ b/crypto/cms/cms_smime.c @@ -897,6 +897,31 @@ err: } +int CMS_final_digest(CMS_ContentInfo *cms, + const unsigned char *md, unsigned int mdlen, + BIO *dcont, unsigned int flags) +{ + BIO *cmsbio; + int ret = 0; + + if ((cmsbio = CMS_dataInit(cms, dcont)) == NULL) { + ERR_raise(ERR_LIB_CMS, CMS_R_CMS_LIB); + return 0; + } + + (void)BIO_flush(cmsbio); + + if (!ossl_cms_DataFinal(cms, cmsbio, md, mdlen)) { + ERR_raise(ERR_LIB_CMS, CMS_R_CMS_DATAFINAL_ERROR); + goto err; + } + ret = 1; + +err: + do_free_upto(cmsbio, dcont); + return ret; +} + #ifdef ZLIB int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out, diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index c4a94f9559..27f7247235 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -343,6 +343,7 @@ CMS_R_NO_PRIVATE_KEY:133:no private key CMS_R_NO_PUBLIC_KEY:134:no public key CMS_R_NO_RECEIPT_REQUEST:168:no receipt request CMS_R_NO_SIGNERS:135:no signers +CMS_R_OPERATION_UNSUPPORTED:182:operation unsupported CMS_R_PEER_KEY_ERROR:188:peer key error CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE:136:\ private key does not match certificate |