diff --git a/apps/cms.c b/apps/cms.c index 81112c5a38cca..98d0613c5ec54 100644 --- a/apps/cms.c +++ b/apps/cms.c @@ -138,13 +138,13 @@ const OPTIONS cms_options[] = { OPT_SECTION("Keys and passwords"), {"pwri_password", OPT_PWRI_PASSWORD, 's', - "Specific password for recipient"}, + "Specific password for encrpytion or decryption"}, {"secretkey", OPT_SECRETKEY, 's', "Use specified hex-encoded key to decrypt/encrypt recipients or content"}, {"secretkeyid", OPT_SECRETKEYID, 's', "Identity of the -secretkey for CMS \"KEKRecipientInfo\" object"}, {"inkey", OPT_INKEY, 's', - "Input private key (if not signer or recipient)"}, + "Input private key, used whend signing and decrypting"}, {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, {"keyopt", OPT_KEYOPT, 's', "Set public key parameters as n:v pairs"}, {"keyform", OPT_KEYFORM, 'f', @@ -157,7 +157,8 @@ const OPTIONS cms_options[] = { OPT_SECTION("Encryption and decryption"), {"originator", OPT_ORIGINATOR, 's', "Originator certificate file"}, - {"recip", OPT_RECIP, '<', "Recipient cert file"}, + {"recip", OPT_RECIP, '<', + "Recipient cert file; may contain fallback for related private key"}, {"cert...", OPT_PARAM, '.', "Recipient certs (optional; used only when encrypting)"}, {"", OPT_CIPHER, '-', @@ -172,8 +173,9 @@ const OPTIONS cms_options[] = { "Disable MMA protection, return error if no recipient found (see doc)"}, OPT_SECTION("Signing"), - {"md", OPT_MD, 's', "Digest algorithm to use"}, - {"signer", OPT_SIGNER, 's', "Signer certificate input file"}, + {"md", OPT_MD, 's', "Digest algorithm to use for (re-)signing"}, + {"signer", OPT_SIGNER, 's', + "Signer certificate input file; also used to load key if no -inkey"}, {"certfile", OPT_CERTFILE, '<', "Other certificates file"}, {"cades", OPT_CADES, '-', "Include signingCertificate attribute (CAdES-BES)"}, @@ -790,15 +792,15 @@ int cms_main(int argc, char **argv) keyfile = NULL; } else if (operation == SMIME_DECRYPT) { if (recipfile == NULL && keyfile == NULL - && secret_key == NULL && pwri_pass == NULL) { - BIO_printf(bio_err, - "No recipient certificate or key specified\n"); + && secret_key == NULL && pwri_pass == NULL) { + BIO_printf(bio_err, "No source of decryption key/password specified\n"); goto opthelp; } } else if (operation == SMIME_ENCRYPT) { if (*argv == NULL && secret_key == NULL - && pwri_pass == NULL && sk_X509_num(encerts) <= 0) { - BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n"); + && pwri_pass == NULL && sk_X509_num(encerts) <= 0) { + BIO_printf(bio_err, + "No recipient(s) certificate(s) or encryption key/password specified\n"); goto opthelp; } } else if (!operation) { @@ -873,7 +875,7 @@ int cms_main(int argc, char **argv) } } - if (recipfile != NULL && (operation == SMIME_DECRYPT)) { + if (recipfile != NULL && operation == SMIME_DECRYPT) { if ((recip = load_cert(recipfile, FORMAT_UNDEF, "recipient certificate file")) == NULL) { ERR_print_errors(bio_err); @@ -897,10 +899,10 @@ int cms_main(int argc, char **argv) } } - if ((operation == SMIME_DECRYPT) || (operation == SMIME_ENCRYPT)) { + if (operation == SMIME_DECRYPT || operation == SMIME_ENCRYPT) { if (keyfile == NULL) keyfile = recipfile; - } else if ((operation == SMIME_SIGN) || (operation == SMIME_SIGN_RECEIPT)) { + } else if (operation == SMIME_SIGN || operation == SMIME_SIGN_RECEIPT) { if (keyfile == NULL) keyfile = signerfile; } else { @@ -1098,6 +1100,7 @@ int cms_main(int argc, char **argv) CMS_SignerInfo *si; cms_key_param *kparam; int tflags = flags; + signerfile = sk_OPENSSL_STRING_value(sksigners, i); keyfile = sk_OPENSSL_STRING_value(skkeys, i); diff --git a/crypto/cms/cms_env.c b/crypto/cms/cms_env.c index 673880f6d9eaa..1472f9b9534e0 100644 --- a/crypto/cms/cms_env.c +++ b/crypto/cms/cms_env.c @@ -43,7 +43,7 @@ static int cms_get_enveloped_type(const CMS_ContentInfo *cms) } } -CMS_EnvelopedData *ossl_cms_get0_enveloped(CMS_ContentInfo *cms) +CMS_EnvelopedData *ossl_cms_get0_enveloped(const CMS_ContentInfo *cms) { if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_enveloped) { ERR_raise(ERR_LIB_CMS, CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA); @@ -1207,7 +1207,7 @@ BIO *ossl_cms_AuthEnvelopedData_init_bio(CMS_ContentInfo *cms) return NULL; } -int ossl_cms_EnvelopedData_final(CMS_ContentInfo *cms, BIO *chain) +int ossl_cms_EnvelopedData_final(const CMS_ContentInfo *cms, BIO *chain) { CMS_EnvelopedData *env = NULL; EVP_CIPHER_CTX *ctx = NULL; @@ -1249,7 +1249,7 @@ int ossl_cms_EnvelopedData_final(CMS_ContentInfo *cms, BIO *chain) return 1; } -int ossl_cms_AuthEnvelopedData_final(CMS_ContentInfo *cms, BIO *cmsbio) +int ossl_cms_AuthEnvelopedData_final(const CMS_ContentInfo *cms, BIO *cmsbio) { EVP_CIPHER_CTX *ctx; unsigned char *tag = NULL; diff --git a/crypto/cms/cms_lib.c b/crypto/cms/cms_lib.c index 4ad9302910f3e..73b1325e464b1 100644 --- a/crypto/cms/cms_lib.c +++ b/crypto/cms/cms_lib.c @@ -206,19 +206,20 @@ BIO *CMS_dataInit(CMS_ContentInfo *cms, BIO *icont) } /* unfortunately cannot constify SMIME_write_ASN1() due to this function */ -int CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio) +int CMS_dataFinal(const CMS_ContentInfo *cms, BIO *cmsbio) { - ASN1_OCTET_STRING **pos = CMS_get0_content(cms); + const ASN1_OCTET_STRING **const_pos = CMS_get0_const_content(cms); + ASN1_OCTET_STRING *embedded_content = NULL; if (pos == NULL) return 0; /* If embedded content find memory BIO and set content */ - if (*pos && ((*pos)->flags & ASN1_STRING_FLAG_CONT)) { - BIO *mbio; + if (*const_pos != NULL && ((*const_pos)->flags & ASN1_STRING_FLAG_CONT)) { + BIO *mbio = BIO_find_type(cmsbio, BIO_TYPE_MEM); unsigned char *cont; long contlen; - mbio = BIO_find_type(cmsbio, BIO_TYPE_MEM); - if (!mbio) { + + if (mbio == NULL) { ERR_raise(ERR_LIB_CMS, CMS_R_CONTENT_NOT_FOUND); return 0; } @@ -226,8 +227,11 @@ int CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio) /* Set bio as read only so its content can't be clobbered */ BIO_set_flags(mbio, BIO_FLAGS_MEM_RDONLY); BIO_set_mem_eof_return(mbio, 0); - ASN1_STRING_set0(*pos, cont, contlen); - (*pos)->flags &= ~ASN1_STRING_FLAG_CONT; + + if ((embedded_content = ASN1_STRING_new()) == NULL + || !ASN1_STRING_set(embedded_content, cont, contlen)) + return 0; + embedded_content->flags &= ~ASN1_STRING_FLAG_CONT; } switch (OBJ_obj2nid(cms->contentType)) { @@ -239,16 +243,16 @@ int CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio) return 1; case NID_pkcs7_enveloped: - return ossl_cms_EnvelopedData_final(cms, cmsbio); + return ossl_cms_EnvelopedData_final(cms, embedded_content, cmsbio); case NID_id_smime_ct_authEnvelopedData: - return ossl_cms_AuthEnvelopedData_final(cms, cmsbio); + return ossl_cms_AuthEnvelopedData_final(cms, embedded_content, cmsbio); case NID_pkcs7_signed: - return ossl_cms_SignedData_final(cms, cmsbio); + return ossl_cms_SignedData_final(cms, embedded_content, cmsbio); case NID_pkcs7_digest: - return ossl_cms_DigestedData_do_final(cms, cmsbio, 0); + return ossl_cms_DigestedData_do_final(cms, embedded_content, cmsbio, 0); default: ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_TYPE); @@ -257,11 +261,52 @@ int CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio) } /* - * Return an OCTET STRING pointer to content. This allows it to be accessed - * or set later. + * Return an ASN1_OCTET STRING pointer to content. + * This allows it to be accessed or set later. */ +ASN1_OCTET_STRING **CMS_get0_content(const CMS_ContentInfo *cms) +{ + switch (OBJ_obj2nid(cms->contentType)) { + + case NID_pkcs7_data: + return &cms->d.data; + + case NID_pkcs7_signed: + return &cms->d.signedData->encapContentInfo->eContent; + + case NID_pkcs7_enveloped: + return &cms->d.envelopedData->encryptedContentInfo->encryptedContent; + + case NID_pkcs7_digest: + return &cms->d.digestedData->encapContentInfo->eContent; + + case NID_pkcs7_encrypted: + return &cms->d.encryptedData->encryptedContentInfo->encryptedContent; -ASN1_OCTET_STRING **CMS_get0_content(CMS_ContentInfo *cms) + case NID_id_smime_ct_authEnvelopedData: + return &cms->d.authEnvelopedData->authEncryptedContentInfo + ->encryptedContent; + + case NID_id_smime_ct_authData: + return &cms->d.authenticatedData->encapContentInfo->eContent; + + case NID_id_smime_ct_compressedData: + return &cms->d.compressedData->encapContentInfo->eContent; + + default: + if (cms->d.other->type == V_ASN1_OCTET_STRING) + return &cms->d.other->value.octet_string; + ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_CONTENT_TYPE); + return NULL; + + } +} + +/* + * Return a const ASN1_OCTET STRING pointer to content. + * This allows it to be accessed read-only later. + */ +const ASN1_OCTET_STRING **CMS_get0_const_content(const CMS_ContentInfo *cms) { switch (OBJ_obj2nid(cms->contentType)) { diff --git a/crypto/cms/cms_local.h b/crypto/cms/cms_local.h index 15b4a29ce03dc..d664467af52c9 100644 --- a/crypto/cms/cms_local.h +++ b/crypto/cms/cms_local.h @@ -404,7 +404,7 @@ 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(const CMS_ContentInfo *cms, BIO *chain); 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, @@ -441,10 +441,10 @@ int ossl_cms_msgSigDigest_add1(CMS_SignerInfo *dest, CMS_SignerInfo *src); ASN1_OCTET_STRING *ossl_cms_encode_Receipt(CMS_SignerInfo *si); BIO *ossl_cms_EnvelopedData_init_bio(CMS_ContentInfo *cms); -int ossl_cms_EnvelopedData_final(CMS_ContentInfo *cms, BIO *chain); +int ossl_cms_EnvelopedData_final(const CMS_ContentInfo *cms, BIO *chain); BIO *ossl_cms_AuthEnvelopedData_init_bio(CMS_ContentInfo *cms); -int ossl_cms_AuthEnvelopedData_final(CMS_ContentInfo *cms, BIO *cmsbio); -CMS_EnvelopedData *ossl_cms_get0_enveloped(CMS_ContentInfo *cms); +int ossl_cms_AuthEnvelopedData_final(const CMS_ContentInfo *cms, BIO *cmsbio); +CMS_EnvelopedData *ossl_cms_get0_enveloped(const CMS_ContentInfo *cms); CMS_AuthEnvelopedData *ossl_cms_get0_auth_enveloped(CMS_ContentInfo *cms); CMS_EncryptedContentInfo *ossl_cms_get0_env_enc_content(const CMS_ContentInfo *cms); diff --git a/crypto/cms/cms_sd.c b/crypto/cms/cms_sd.c index 4fbe09ca5fef5..d37131abbb8de 100644 --- a/crypto/cms/cms_sd.c +++ b/crypto/cms/cms_sd.c @@ -316,12 +316,11 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms, ERR_raise(ERR_LIB_CMS, CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE); return NULL; } - sd = cms_signed_data_init(cms); - if (!sd) + if ((sd = cms_signed_data_init(cms)) == NULL) goto err; - si = M_ASN1_new_of(CMS_SignerInfo); - if (!si) + if ((si = M_ASN1_new_of(CMS_SignerInfo)) == NULL) goto merr; + /* Call for side-effect of computing hash and caching extensions */ X509_check_purpose(signer, -1, -1); @@ -354,20 +353,14 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms, if (md == NULL) { int def_nid; - if (EVP_PKEY_get_default_digest_nid(pk, &def_nid) <= 0) - goto err; - md = EVP_get_digestbynid(def_nid); - if (md == NULL) { + + if (EVP_PKEY_get_default_digest_nid(pk, &def_nid) <= 0 + || (md = EVP_get_digestbynid(def_nid)) == NULL) { ERR_raise(ERR_LIB_CMS, CMS_R_NO_DEFAULT_DIGEST); goto err; } } - if (!md) { - ERR_raise(ERR_LIB_CMS, CMS_R_NO_DIGEST_SET); - goto err; - } - if (md == NULL) { ERR_raise(ERR_LIB_CMS, CMS_R_NO_DIGEST_SET); goto err; @@ -667,7 +660,7 @@ ASN1_OCTET_STRING *CMS_SignerInfo_get0_signature(CMS_SignerInfo *si) return si->signature; } -static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms, +static int cms_SignerInfo_content_sign(const CMS_ContentInfo *cms, CMS_SignerInfo *si, BIO *chain) { EVP_MD_CTX *mctx = EVP_MD_CTX_new(); @@ -758,7 +751,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(const CMS_ContentInfo *cms, + const ASN1_OCTET_STRING *embedded_content, + BIO *chain) { STACK_OF(CMS_SignerInfo) *sinfos; CMS_SignerInfo *si; diff --git a/include/openssl/cms.h.in b/include/openssl/cms.h.in index da20ddf2f41d1..4ca48bd4691c6 100644 --- a/include/openssl/cms.h.in +++ b/include/openssl/cms.h.in @@ -96,9 +96,10 @@ CMS_ContentInfo *CMS_ContentInfo_new_ex(OSSL_LIB_CTX *libctx, const char *propq) const ASN1_OBJECT *CMS_get0_type(const CMS_ContentInfo *cms); BIO *CMS_dataInit(CMS_ContentInfo *cms, BIO *icont); -int CMS_dataFinal(CMS_ContentInfo *cms, BIO *bio); +int CMS_dataFinal(const CMS_ContentInfo *cms, BIO *bio); ASN1_OCTET_STRING **CMS_get0_content(CMS_ContentInfo *cms); +const ASN1_OCTET_STRING **CMS_get0_const_content(const CMS_ContentInfo *cms); int CMS_is_detached(CMS_ContentInfo *cms); int CMS_set_detached(CMS_ContentInfo *cms, int detached);