mirror of https://github.com/openssl/openssl.git
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)
This commit is contained in:
parent
e4cdcb8bc4
commit
07342bad1b
44
apps/cms.c
44
apps/cms.c
|
@ -66,7 +66,7 @@ typedef enum OPTION_choice {
|
||||||
OPT_DECRYPT, OPT_SIGN, OPT_CADES, OPT_SIGN_RECEIPT, OPT_RESIGN,
|
OPT_DECRYPT, OPT_SIGN, OPT_CADES, OPT_SIGN_RECEIPT, OPT_RESIGN,
|
||||||
OPT_VERIFY, OPT_VERIFY_RETCODE, OPT_VERIFY_RECEIPT,
|
OPT_VERIFY, OPT_VERIFY_RETCODE, OPT_VERIFY_RECEIPT,
|
||||||
OPT_CMSOUT, OPT_DATA_OUT, OPT_DATA_CREATE, OPT_DIGEST_VERIFY,
|
OPT_CMSOUT, OPT_DATA_OUT, OPT_DATA_CREATE, OPT_DIGEST_VERIFY,
|
||||||
OPT_DIGEST_CREATE, OPT_COMPRESS, OPT_UNCOMPRESS,
|
OPT_DIGEST, OPT_DIGEST_CREATE, OPT_COMPRESS, OPT_UNCOMPRESS,
|
||||||
OPT_ED_DECRYPT, OPT_ED_ENCRYPT, OPT_DEBUG_DECRYPT, OPT_TEXT,
|
OPT_ED_DECRYPT, OPT_ED_ENCRYPT, OPT_DEBUG_DECRYPT, OPT_TEXT,
|
||||||
OPT_ASCIICRLF, OPT_NOINTERN, OPT_NOVERIFY, OPT_NOCERTS,
|
OPT_ASCIICRLF, OPT_NOINTERN, OPT_NOVERIFY, OPT_NOCERTS,
|
||||||
OPT_NOATTR, OPT_NODETACH, OPT_NOSMIMECAP, OPT_BINARY, OPT_KEYID,
|
OPT_NOATTR, OPT_NODETACH, OPT_NOSMIMECAP, OPT_BINARY, OPT_KEYID,
|
||||||
|
@ -106,6 +106,7 @@ const OPTIONS cms_options[] = {
|
||||||
"Generate a signed receipt for a message"},
|
"Generate a signed receipt for a message"},
|
||||||
{"verify_receipt", OPT_VERIFY_RECEIPT, '<',
|
{"verify_receipt", OPT_VERIFY_RECEIPT, '<',
|
||||||
"Verify receipts; exit if receipt signatures do not verify"},
|
"Verify receipts; exit if receipt signatures do not verify"},
|
||||||
|
{"digest", OPT_DIGEST, 's', "Sign a pre-computed digest in hex notation"},
|
||||||
{"digest_create", OPT_DIGEST_CREATE, '-',
|
{"digest_create", OPT_DIGEST_CREATE, '-',
|
||||||
"Create a CMS \"DigestedData\" object"},
|
"Create a CMS \"DigestedData\" object"},
|
||||||
{"digest_verify", OPT_DIGEST_VERIFY, '-',
|
{"digest_verify", OPT_DIGEST_VERIFY, '-',
|
||||||
|
@ -293,6 +294,9 @@ int cms_main(int argc, char **argv)
|
||||||
const char *CAfile = NULL, *CApath = NULL, *CAstore = NULL;
|
const char *CAfile = NULL, *CApath = NULL, *CAstore = NULL;
|
||||||
char *certsoutfile = NULL, *digestname = NULL, *wrapname = NULL;
|
char *certsoutfile = NULL, *digestname = NULL, *wrapname = NULL;
|
||||||
int noCAfile = 0, noCApath = 0, noCAstore = 0;
|
int noCAfile = 0, noCApath = 0, noCAstore = 0;
|
||||||
|
char *digesthex = NULL;
|
||||||
|
unsigned char *digestbin = NULL;
|
||||||
|
long digestlen = 0;
|
||||||
char *infile = NULL, *outfile = NULL, *rctfile = NULL;
|
char *infile = NULL, *outfile = NULL, *rctfile = NULL;
|
||||||
char *passinarg = NULL, *passin = NULL, *signerfile = NULL;
|
char *passinarg = NULL, *passin = NULL, *signerfile = NULL;
|
||||||
char *originatorfile = NULL, *recipfile = NULL, *ciphername = NULL;
|
char *originatorfile = NULL, *recipfile = NULL, *ciphername = NULL;
|
||||||
|
@ -367,6 +371,9 @@ int cms_main(int argc, char **argv)
|
||||||
case OPT_DIGEST_CREATE:
|
case OPT_DIGEST_CREATE:
|
||||||
operation = SMIME_DIGEST_CREATE;
|
operation = SMIME_DIGEST_CREATE;
|
||||||
break;
|
break;
|
||||||
|
case OPT_DIGEST:
|
||||||
|
digesthex = opt_arg();
|
||||||
|
break;
|
||||||
case OPT_DIGEST_VERIFY:
|
case OPT_DIGEST_VERIFY:
|
||||||
operation = SMIME_DIGEST_VERIFY;
|
operation = SMIME_DIGEST_VERIFY;
|
||||||
break;
|
break;
|
||||||
|
@ -885,10 +892,31 @@ int cms_main(int argc, char **argv)
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (digesthex != NULL) {
|
||||||
|
if (operation != SMIME_SIGN) {
|
||||||
|
BIO_printf(bio_err,
|
||||||
|
"Cannot use -digest for non-signing operation\n");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (infile != NULL
|
||||||
|
|| (flags & CMS_DETACHED) == 0
|
||||||
|
|| (flags & CMS_STREAM) != 0) {
|
||||||
|
BIO_printf(bio_err,
|
||||||
|
"Cannot use -digest when -in, -nodetach or streaming is used\n");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
digestbin = OPENSSL_hexstr2buf(digesthex, &digestlen);
|
||||||
|
if (digestbin == NULL) {
|
||||||
|
BIO_printf(bio_err,
|
||||||
|
"Invalid hex value after -digest\n");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
in = bio_open_default(infile, 'r',
|
in = bio_open_default(infile, 'r',
|
||||||
binary_files ? FORMAT_BINARY : informat);
|
binary_files ? FORMAT_BINARY : informat);
|
||||||
if (in == NULL)
|
if (in == NULL)
|
||||||
goto end;
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
if (operation & SMIME_IP) {
|
if (operation & SMIME_IP) {
|
||||||
cms = load_content_info(informat, in, flags, &indata, "SMIME");
|
cms = load_content_info(informat, in, flags, &indata, "SMIME");
|
||||||
|
@ -1037,12 +1065,12 @@ int cms_main(int argc, char **argv)
|
||||||
} else if (operation & SMIME_SIGNERS) {
|
} else if (operation & SMIME_SIGNERS) {
|
||||||
int i;
|
int i;
|
||||||
/*
|
/*
|
||||||
* If detached data content we enable streaming if S/MIME output
|
* If detached data content and not signing pre-computed digest, we
|
||||||
* format.
|
* enable streaming if S/MIME output format.
|
||||||
*/
|
*/
|
||||||
if (operation == SMIME_SIGN) {
|
if (operation == SMIME_SIGN) {
|
||||||
|
|
||||||
if (flags & CMS_DETACHED) {
|
if ((flags & CMS_DETACHED) != 0 && digestbin == NULL) {
|
||||||
if (outformat == FORMAT_SMIME)
|
if (outformat == FORMAT_SMIME)
|
||||||
flags |= CMS_STREAM;
|
flags |= CMS_STREAM;
|
||||||
}
|
}
|
||||||
|
@ -1103,7 +1131,12 @@ int cms_main(int argc, char **argv)
|
||||||
key = NULL;
|
key = NULL;
|
||||||
}
|
}
|
||||||
/* If not streaming or resigning finalize structure */
|
/* If not streaming or resigning finalize structure */
|
||||||
if ((operation == SMIME_SIGN) && !(flags & CMS_STREAM)) {
|
if (operation == SMIME_SIGN && digestbin != NULL
|
||||||
|
&& (flags & CMS_STREAM) == 0) {
|
||||||
|
/* Use pre-computed digest instead of content */
|
||||||
|
if (!CMS_final_digest(cms, digestbin, digestlen, NULL, flags))
|
||||||
|
goto end;
|
||||||
|
} else if (operation == SMIME_SIGN && (flags & CMS_STREAM) == 0) {
|
||||||
if (!CMS_final(cms, in, NULL, flags))
|
if (!CMS_final(cms, in, NULL, flags))
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
@ -1272,6 +1305,7 @@ int cms_main(int argc, char **argv)
|
||||||
BIO_free(in);
|
BIO_free(in);
|
||||||
BIO_free(indata);
|
BIO_free(indata);
|
||||||
BIO_free_all(out);
|
BIO_free_all(out);
|
||||||
|
OPENSSL_free(digestbin);
|
||||||
OPENSSL_free(passin);
|
OPENSSL_free(passin);
|
||||||
NCONF_free(conf);
|
NCONF_free(conf);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Generated by util/mkerr.pl DO NOT EDIT
|
* 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
|
* 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
|
* 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_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_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_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_PEER_KEY_ERROR), "peer key error"},
|
||||||
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE),
|
{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE),
|
||||||
"private key does not match certificate"},
|
"private key does not match certificate"},
|
||||||
|
|
|
@ -207,6 +207,13 @@ err:
|
||||||
|
|
||||||
/* unfortunately cannot constify SMIME_write_ASN1() due to this function */
|
/* unfortunately cannot constify SMIME_write_ASN1() due to this function */
|
||||||
int CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio)
|
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);
|
ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
|
||||||
|
|
||||||
|
@ -245,7 +252,7 @@ int CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio)
|
||||||
return ossl_cms_AuthEnvelopedData_final(cms, cmsbio);
|
return ossl_cms_AuthEnvelopedData_final(cms, cmsbio);
|
||||||
|
|
||||||
case NID_pkcs7_signed:
|
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:
|
case NID_pkcs7_digest:
|
||||||
return ossl_cms_DigestedData_do_final(cms, cmsbio, 0);
|
return ossl_cms_DigestedData_do_final(cms, cmsbio, 0);
|
||||||
|
|
|
@ -395,6 +395,9 @@ const char *ossl_cms_ctx_get0_propq(const CMS_CTX *ctx);
|
||||||
void ossl_cms_resolve_libctx(CMS_ContentInfo *ci);
|
void ossl_cms_resolve_libctx(CMS_ContentInfo *ci);
|
||||||
|
|
||||||
CMS_ContentInfo *ossl_cms_Data_create(OSSL_LIB_CTX *ctx, const char *propq);
|
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,
|
CMS_ContentInfo *ossl_cms_DigestedData_create(const EVP_MD *md,
|
||||||
OSSL_LIB_CTX *libctx,
|
OSSL_LIB_CTX *libctx,
|
||||||
|
@ -404,7 +407,9 @@ int ossl_cms_DigestedData_do_final(const CMS_ContentInfo *cms,
|
||||||
BIO *chain, int verify);
|
BIO *chain, int verify);
|
||||||
|
|
||||||
BIO *ossl_cms_SignedData_init_bio(CMS_ContentInfo *cms);
|
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 ossl_cms_set1_SignerIdentifier(CMS_SignerIdentifier *sid, X509 *cert,
|
||||||
int type, const CMS_CTX *ctx);
|
int type, const CMS_CTX *ctx);
|
||||||
int ossl_cms_SignerIdentifier_get0_signer_id(CMS_SignerIdentifier *sid,
|
int ossl_cms_SignerIdentifier_get0_signer_id(CMS_SignerIdentifier *sid,
|
||||||
|
|
|
@ -694,7 +694,9 @@ ASN1_OCTET_STRING *CMS_SignerInfo_get0_signature(CMS_SignerInfo *si)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms,
|
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();
|
EVP_MD_CTX *mctx = EVP_MD_CTX_new();
|
||||||
int r = 0;
|
int r = 0;
|
||||||
|
@ -722,11 +724,13 @@ static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (CMS_signed_get_attr_count(si) >= 0) {
|
if (CMS_signed_get_attr_count(si) >= 0) {
|
||||||
unsigned char md[EVP_MAX_MD_SIZE];
|
unsigned char computed_md[EVP_MAX_MD_SIZE];
|
||||||
unsigned int mdlen;
|
|
||||||
|
|
||||||
if (!EVP_DigestFinal_ex(mctx, md, &mdlen))
|
if (md == NULL) {
|
||||||
|
if (!EVP_DigestFinal_ex(mctx, computed_md, &mdlen))
|
||||||
goto err;
|
goto err;
|
||||||
|
md = computed_md;
|
||||||
|
}
|
||||||
if (!CMS_signed_add1_attr_by_NID(si, NID_pkcs9_messageDigest,
|
if (!CMS_signed_add1_attr_by_NID(si, NID_pkcs9_messageDigest,
|
||||||
V_ASN1_OCTET_STRING, md, mdlen))
|
V_ASN1_OCTET_STRING, md, mdlen))
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -739,12 +743,14 @@ static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms,
|
||||||
} else if (si->pctx) {
|
} else if (si->pctx) {
|
||||||
unsigned char *sig;
|
unsigned char *sig;
|
||||||
size_t siglen;
|
size_t siglen;
|
||||||
unsigned char md[EVP_MAX_MD_SIZE];
|
unsigned char computed_md[EVP_MAX_MD_SIZE];
|
||||||
unsigned int mdlen;
|
|
||||||
|
|
||||||
pctx = si->pctx;
|
pctx = si->pctx;
|
||||||
if (!EVP_DigestFinal_ex(mctx, md, &mdlen))
|
if (md == NULL) {
|
||||||
|
if (!EVP_DigestFinal_ex(mctx, computed_md, &mdlen))
|
||||||
goto err;
|
goto err;
|
||||||
|
md = computed_md;
|
||||||
|
}
|
||||||
siglen = EVP_PKEY_get_size(si->pkey);
|
siglen = EVP_PKEY_get_size(si->pkey);
|
||||||
sig = OPENSSL_malloc(siglen);
|
sig = OPENSSL_malloc(siglen);
|
||||||
if (sig == NULL) {
|
if (sig == NULL) {
|
||||||
|
@ -760,6 +766,10 @@ static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms,
|
||||||
unsigned char *sig;
|
unsigned char *sig;
|
||||||
unsigned int siglen;
|
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));
|
sig = OPENSSL_malloc(EVP_PKEY_get_size(si->pkey));
|
||||||
if (sig == NULL) {
|
if (sig == NULL) {
|
||||||
ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE);
|
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;
|
STACK_OF(CMS_SignerInfo) *sinfos;
|
||||||
CMS_SignerInfo *si;
|
CMS_SignerInfo *si;
|
||||||
|
@ -793,7 +805,7 @@ int ossl_cms_SignedData_final(CMS_ContentInfo *cms, BIO *chain)
|
||||||
sinfos = CMS_get0_SignerInfos(cms);
|
sinfos = CMS_get0_SignerInfos(cms);
|
||||||
for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
|
for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
|
||||||
si = sk_CMS_SignerInfo_value(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;
|
return 0;
|
||||||
}
|
}
|
||||||
cms->d.signedData->encapContentInfo->partial = 0;
|
cms->d.signedData->encapContentInfo->partial = 0;
|
||||||
|
|
|
@ -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
|
#ifdef ZLIB
|
||||||
|
|
||||||
int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
|
int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
|
||||||
|
|
|
@ -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_PUBLIC_KEY:134:no public key
|
||||||
CMS_R_NO_RECEIPT_REQUEST:168:no receipt request
|
CMS_R_NO_RECEIPT_REQUEST:168:no receipt request
|
||||||
CMS_R_NO_SIGNERS:135:no signers
|
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_PEER_KEY_ERROR:188:peer key error
|
||||||
CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE:136:\
|
CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE:136:\
|
||||||
private key does not match certificate
|
private key does not match certificate
|
||||||
|
|
|
@ -25,6 +25,7 @@ Operation options:
|
||||||
[B<-resign>]
|
[B<-resign>]
|
||||||
[B<-sign_receipt>]
|
[B<-sign_receipt>]
|
||||||
[B<-verify_receipt> I<receipt>]
|
[B<-verify_receipt> I<receipt>]
|
||||||
|
[B<-digest> I<digest>]
|
||||||
[B<-digest_create>]
|
[B<-digest_create>]
|
||||||
[B<-digest_verify>]
|
[B<-digest_verify>]
|
||||||
[B<-compress>]
|
[B<-compress>]
|
||||||
|
@ -207,6 +208,16 @@ Verify a signed receipt in filename B<receipt>. The input message B<must>
|
||||||
contain the original receipt request. Functionality is otherwise similar
|
contain the original receipt request. Functionality is otherwise similar
|
||||||
to the B<-verify> operation.
|
to the B<-verify> operation.
|
||||||
|
|
||||||
|
=item B<-digest> I<digest>
|
||||||
|
|
||||||
|
When used with B<-sign>, provides the digest in hexadecimal form instead of
|
||||||
|
computing it from the original message content. Cannot be combined with B<-in>
|
||||||
|
or B<-nodetach>.
|
||||||
|
|
||||||
|
This operation is the CMS equivalent of L<openssl-pkeyutl(1)> signing.
|
||||||
|
When signing a pre-computed digest, the security relies on the digest and its
|
||||||
|
computation from the original message being trusted.
|
||||||
|
|
||||||
=item B<-digest_create>
|
=item B<-digest_create>
|
||||||
|
|
||||||
Create a CMS B<DigestedData> type.
|
Create a CMS B<DigestedData> type.
|
||||||
|
@ -900,6 +911,8 @@ The B<-nameopt> option was added in OpenSSL 3.0.0.
|
||||||
|
|
||||||
The B<-engine> option was deprecated in OpenSSL 3.0.
|
The B<-engine> option was deprecated in OpenSSL 3.0.
|
||||||
|
|
||||||
|
The B<-digest> option was added in OpenSSL 3.1.
|
||||||
|
|
||||||
=head1 COPYRIGHT
|
=head1 COPYRIGHT
|
||||||
|
|
||||||
Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved.
|
Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved.
|
||||||
|
|
|
@ -2,13 +2,15 @@
|
||||||
|
|
||||||
=head1 NAME
|
=head1 NAME
|
||||||
|
|
||||||
CMS_final - finalise a CMS_ContentInfo structure
|
CMS_final, CMS_final_digest - finalise a CMS_ContentInfo structure
|
||||||
|
|
||||||
=head1 SYNOPSIS
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
#include <openssl/cms.h>
|
#include <openssl/cms.h>
|
||||||
|
|
||||||
int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont, unsigned int flags);
|
int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont, unsigned int flags);
|
||||||
|
int CMS_final_digest(CMS_ContentInfo *cms, const unsigned char *md,
|
||||||
|
unsigned int mdlen, BIO *dcont, unsigned int flags);
|
||||||
|
|
||||||
=head1 DESCRIPTION
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
@ -19,24 +21,37 @@ processed. The B<dcont> parameter contains a BIO to write content to after
|
||||||
processing: this is only used with detached data and will usually be set to
|
processing: this is only used with detached data and will usually be set to
|
||||||
NULL.
|
NULL.
|
||||||
|
|
||||||
|
CMS_final_digest() finalises the structure B<cms> using a pre-computed digest,
|
||||||
|
rather than computing the digest from the original data.
|
||||||
|
|
||||||
=head1 NOTES
|
=head1 NOTES
|
||||||
|
|
||||||
This function will normally be called when the B<CMS_PARTIAL> flag is used. It
|
These functions will normally be called when the B<CMS_PARTIAL> flag is used. It
|
||||||
should only be used when streaming is not performed because the streaming
|
should only be used when streaming is not performed because the streaming
|
||||||
I/O functions perform finalisation operations internally.
|
I/O functions perform finalisation operations internally.
|
||||||
|
|
||||||
|
To sign a pre-computed digest, L<CMS_sign(3)> or CMS_sign_ex() is called
|
||||||
|
with the B<data> parameter set to NULL before the CMS structure is finalised
|
||||||
|
with the digest provided to CMS_final_digest() in binary form.
|
||||||
|
When signing a pre-computed digest, the security relies on the digest and its
|
||||||
|
computation from the original message being trusted.
|
||||||
|
|
||||||
=head1 RETURN VALUES
|
=head1 RETURN VALUES
|
||||||
|
|
||||||
CMS_final() returns 1 for success or 0 for failure.
|
CMS_final() and CMS_final_digest() return 1 for success or 0 for failure.
|
||||||
|
|
||||||
=head1 SEE ALSO
|
=head1 SEE ALSO
|
||||||
|
|
||||||
L<ERR_get_error(3)>, L<CMS_sign(3)>,
|
L<ERR_get_error(3)>, L<CMS_sign(3)>,
|
||||||
L<CMS_encrypt(3)>
|
L<CMS_encrypt(3)>
|
||||||
|
|
||||||
|
=head1 HISTORY
|
||||||
|
|
||||||
|
CMS_final_digest() was added in OpenSSL 3.1.
|
||||||
|
|
||||||
=head1 COPYRIGHT
|
=head1 COPYRIGHT
|
||||||
|
|
||||||
Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
|
Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved.
|
||||||
|
|
||||||
Licensed under the Apache License 2.0 (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
|
this file except in compliance with the License. You can obtain a copy
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Generated by util/mkerr.pl DO NOT EDIT
|
* Generated by util/mkerr.pl DO NOT EDIT
|
||||||
* Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
|
* Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License 2.0 (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
|
* this file except in compliance with the License. You can obtain a copy
|
||||||
|
|
|
@ -119,6 +119,9 @@ int SMIME_write_CMS(BIO *bio, CMS_ContentInfo *cms, BIO *data, int flags);
|
||||||
|
|
||||||
int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont,
|
int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont,
|
||||||
unsigned int flags);
|
unsigned int flags);
|
||||||
|
int CMS_final_digest(CMS_ContentInfo *cms,
|
||||||
|
const unsigned char *md, unsigned int mdlen, BIO *dcont,
|
||||||
|
unsigned int flags);
|
||||||
|
|
||||||
CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey,
|
CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey,
|
||||||
STACK_OF(X509) *certs, BIO *data,
|
STACK_OF(X509) *certs, BIO *data,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Generated by util/mkerr.pl DO NOT EDIT
|
* 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
|
* 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
|
* this file except in compliance with the License. You can obtain a copy
|
||||||
|
@ -86,6 +86,7 @@
|
||||||
# define CMS_R_NO_PUBLIC_KEY 134
|
# define CMS_R_NO_PUBLIC_KEY 134
|
||||||
# define CMS_R_NO_RECEIPT_REQUEST 168
|
# define CMS_R_NO_RECEIPT_REQUEST 168
|
||||||
# define CMS_R_NO_SIGNERS 135
|
# define CMS_R_NO_SIGNERS 135
|
||||||
|
# define CMS_R_OPERATION_UNSUPPORTED 182
|
||||||
# define CMS_R_PEER_KEY_ERROR 188
|
# define CMS_R_PEER_KEY_ERROR 188
|
||||||
# define CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE 136
|
# define CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE 136
|
||||||
# define CMS_R_RECEIPT_DECODE_ERROR 169
|
# define CMS_R_RECEIPT_DECODE_ERROR 169
|
||||||
|
|
|
@ -50,7 +50,7 @@ my ($no_des, $no_dh, $no_dsa, $no_ec, $no_ec2m, $no_rc2, $no_zlib)
|
||||||
|
|
||||||
$no_rc2 = 1 if disabled("legacy");
|
$no_rc2 = 1 if disabled("legacy");
|
||||||
|
|
||||||
plan tests => 12;
|
plan tests => 14;
|
||||||
|
|
||||||
ok(run(test(["pkcs7_test"])), "test pkcs7");
|
ok(run(test(["pkcs7_test"])), "test pkcs7");
|
||||||
|
|
||||||
|
@ -847,6 +847,48 @@ subtest "CMS binary input tests\n" => sub {
|
||||||
"verify binary input with -binary missing -crlfeol");
|
"verify binary input with -binary missing -crlfeol");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
subtest "CMS signed digest, DER format" => sub {
|
||||||
|
plan tests => 2;
|
||||||
|
|
||||||
|
# Pre-computed SHA256 digest of $smcont in hexadecimal form
|
||||||
|
my $digest = "ff236ef61b396355f75a4cc6e1c306d4c309084ae271a9e2ad6888f10a101b32";
|
||||||
|
|
||||||
|
my $sig_file = "signature.der";
|
||||||
|
ok(run(app(["openssl", "cms", @prov, "-sign", "-digest", $digest,
|
||||||
|
"-outform", "DER",
|
||||||
|
"-certfile", catfile($smdir, "smroot.pem"),
|
||||||
|
"-signer", catfile($smdir, "smrsa1.pem"),
|
||||||
|
"-out", $sig_file])),
|
||||||
|
"CMS sign pre-computed digest, DER format");
|
||||||
|
|
||||||
|
ok(run(app(["openssl", "cms", @prov, "-verify", "-in", $sig_file,
|
||||||
|
"-inform", "DER",
|
||||||
|
"-CAfile", catfile($smdir, "smroot.pem"),
|
||||||
|
"-content", $smcont])),
|
||||||
|
"Verify CMS signed digest, DER format");
|
||||||
|
};
|
||||||
|
|
||||||
|
subtest "CMS signed digest, S/MIME format" => sub {
|
||||||
|
plan tests => 2;
|
||||||
|
|
||||||
|
# Pre-computed SHA256 digest of $smcont in hexadecimal form
|
||||||
|
my $digest = "ff236ef61b396355f75a4cc6e1c306d4c309084ae271a9e2ad6888f10a101b32";
|
||||||
|
|
||||||
|
my $sig_file = "signature.smime";
|
||||||
|
ok(run(app(["openssl", "cms", @prov, "-sign", "-digest", $digest,
|
||||||
|
"-outform", "SMIME",
|
||||||
|
"-certfile", catfile($smdir, "smroot.pem"),
|
||||||
|
"-signer", catfile($smdir, "smrsa1.pem"),
|
||||||
|
"-out", $sig_file])),
|
||||||
|
"CMS sign pre-computed digest, S/MIME format");
|
||||||
|
|
||||||
|
ok(run(app(["openssl", "cms", @prov, "-verify", "-in", $sig_file,
|
||||||
|
"-inform", "SMIME",
|
||||||
|
"-CAfile", catfile($smdir, "smroot.pem"),
|
||||||
|
"-content", $smcont])),
|
||||||
|
"Verify CMS signed digest, S/MIME format");
|
||||||
|
};
|
||||||
|
|
||||||
sub check_availability {
|
sub check_availability {
|
||||||
my $tnam = shift;
|
my $tnam = shift;
|
||||||
|
|
||||||
|
|
|
@ -5437,3 +5437,4 @@ BN_signed_bn2native ? 3_1_0 EXIST::FUNCTION:
|
||||||
ASYNC_set_mem_functions ? 3_1_0 EXIST::FUNCTION:
|
ASYNC_set_mem_functions ? 3_1_0 EXIST::FUNCTION:
|
||||||
ASYNC_get_mem_functions ? 3_1_0 EXIST::FUNCTION:
|
ASYNC_get_mem_functions ? 3_1_0 EXIST::FUNCTION:
|
||||||
BIO_ADDR_dup ? 3_1_0 EXIST::FUNCTION:SOCK
|
BIO_ADDR_dup ? 3_1_0 EXIST::FUNCTION:SOCK
|
||||||
|
CMS_final_digest ? 3_1_0 EXIST::FUNCTION:CMS
|
||||||
|
|
Loading…
Reference in New Issue