CMS_ContentInfo *cms_DigestedData_create(const EVP_MD *md) { CMS_ContentInfo *cms; CMS_DigestedData *dd; cms = CMS_ContentInfo_new(); if (!cms) return NULL; dd = M_ASN1_new_of(CMS_DigestedData); if (!dd) goto err; cms->contentType = OBJ_nid2obj(NID_pkcs7_digest); cms->d.digestedData = dd; dd->version = 0; dd->encapContentInfo->eContentType = OBJ_nid2obj(NID_pkcs7_data); cms_DigestAlgorithm_set(dd->digestAlgorithm, md); return cms; err: if (cms) CMS_ContentInfo_free(cms); return NULL; }
int CMS_EncryptedData_set1_key(CMS_ContentInfo *cms, const EVP_CIPHER *ciph, const unsigned char *key, size_t keylen) { CMS_EncryptedContentInfo *ec; if (!key || !keylen) { CMSerr(CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY, CMS_R_NO_KEY); return 0; } if (ciph) { cms->d.encryptedData = M_ASN1_new_of(CMS_EncryptedData); if (!cms->d.encryptedData) { CMSerr(CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY, ERR_R_MALLOC_FAILURE); return 0; } cms->contentType = OBJ_nid2obj(NID_pkcs7_encrypted); cms->d.encryptedData->version = 0; } else if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_encrypted) { CMSerr(CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY, CMS_R_NOT_ENCRYPTED_DATA); return 0; } ec = cms->d.encryptedData->encryptedContentInfo; return cms_EncryptedContent_init(ec, ciph, key, keylen); }
CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms, X509 *recip, unsigned int flags) { CMS_RecipientInfo *ri = NULL; CMS_EnvelopedData *env; EVP_PKEY *pk = NULL; env = cms_get0_enveloped(cms); if (!env) goto err; /* Initialize recipient info */ ri = M_ASN1_new_of(CMS_RecipientInfo); if (!ri) goto merr; pk = X509_get_pubkey(recip); if (!pk) { CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, CMS_R_ERROR_GETTING_PUBLIC_KEY); goto err; } switch (cms_pkey_get_ri_type(pk)) { case CMS_RECIPINFO_TRANS: if (!cms_RecipientInfo_ktri_init(ri, recip, pk, flags)) goto err; break; case CMS_RECIPINFO_AGREE: if (!cms_RecipientInfo_kari_init(ri, recip, pk, flags)) goto err; break; default: CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); goto err; } if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri)) goto merr; EVP_PKEY_free(pk); return ri; merr: CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, ERR_R_MALLOC_FAILURE); err: if (ri) M_ASN1_free_of(ri, CMS_RecipientInfo); if (pk) EVP_PKEY_free(pk); return NULL; }
int cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, X509 *recip, EVP_PKEY *pk, unsigned int flags) { CMS_KeyAgreeRecipientInfo *kari; CMS_RecipientEncryptedKey *rek = NULL; ri->d.kari = M_ASN1_new_of(CMS_KeyAgreeRecipientInfo); if (!ri->d.kari) return 0; ri->type = CMS_RECIPINFO_AGREE; kari = ri->d.kari; kari->version = 3; rek = M_ASN1_new_of(CMS_RecipientEncryptedKey); if (!sk_CMS_RecipientEncryptedKey_push(kari->recipientEncryptedKeys, rek)) { M_ASN1_free_of(rek, CMS_RecipientEncryptedKey); return 0; } if (flags & CMS_USE_KEYID) { rek->rid->type = CMS_REK_KEYIDENTIFIER; rek->rid->d.rKeyId = M_ASN1_new_of(CMS_RecipientKeyIdentifier); if (rek->rid->d.rKeyId == NULL) return 0; if (!cms_set1_keyid(&rek->rid->d.rKeyId->subjectKeyIdentifier, recip)) return 0; } else { rek->rid->type = CMS_REK_ISSUER_SERIAL; if (!cms_set1_ias(&rek->rid->d.issuerAndSerialNumber, recip)) return 0; } /* Create ephemeral key */ if (!cms_kari_create_ephemeral_key(kari, pk)) return 0; CRYPTO_add(&pk->references, 1, CRYPTO_LOCK_EVP_PKEY); rek->pkey = pk; return 1; }
int cms_RecipientInfo_kari_encrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri) { CMS_KeyAgreeRecipientInfo *kari; CMS_EncryptedContentInfo *ec; CMS_RecipientEncryptedKey *rek; STACK_OF(CMS_RecipientEncryptedKey) *reks; int i; if (ri->type != CMS_RECIPINFO_AGREE) { CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_ENCRYPT, CMS_R_NOT_KEY_AGREEMENT); return 0; } kari = ri->d.kari; reks = kari->recipientEncryptedKeys; ec = cms->d.envelopedData->encryptedContentInfo; /* Initialise wrap algorithm parameters */ if (!cms_wrap_init(kari, ec->cipher)) return 0; /* * If no orignator key set up initialise for ephemeral key the public key * ASN1 structure will set the actual public key value. */ if (kari->originator->type == -1) { CMS_OriginatorIdentifierOrKey *oik = kari->originator; oik->type = CMS_OIK_PUBKEY; oik->d.originatorKey = M_ASN1_new_of(CMS_OriginatorPublicKey); if (!oik->d.originatorKey) return 0; } /* Initialise KDF algorithm */ if (!cms_env_asn1_ctrl(ri, 0)) return 0; /* For each rek, derive KEK, encrypt CEK */ for (i = 0; i < sk_CMS_RecipientEncryptedKey_num(reks); i++) { unsigned char *enckey; size_t enckeylen; rek = sk_CMS_RecipientEncryptedKey_value(reks, i); if (EVP_PKEY_derive_set_peer(kari->pctx, rek->pkey) <= 0) return 0; if (!cms_kek_cipher(&enckey, &enckeylen, ec->key, ec->keylen, kari, 1)) return 0; ASN1_STRING_set0(rek->encryptedKey, enckey, enckeylen); } return 1; }
static CMS_EnvelopedData *cms_enveloped_data_init(CMS_ContentInfo *cms) { if (cms->d.other == NULL) { cms->d.envelopedData = M_ASN1_new_of(CMS_EnvelopedData); if (!cms->d.envelopedData) { CMSerr(CMS_F_CMS_ENVELOPED_DATA_INIT, ERR_R_MALLOC_FAILURE); return NULL; } cms->d.envelopedData->version = 0; cms->d.envelopedData->encryptedContentInfo->contentType = OBJ_nid2obj(NID_pkcs7_data); ASN1_OBJECT_free(cms->contentType); cms->contentType = OBJ_nid2obj(NID_pkcs7_enveloped); return cms->d.envelopedData; } return cms_get0_enveloped(cms); }
int cms_set1_SignerIdentifier(CMS_SignerIdentifier *sid, X509 *cert, int type) { switch(type) { case CMS_SIGNERINFO_ISSUER_SERIAL: sid->d.issuerAndSerialNumber = M_ASN1_new_of(CMS_IssuerAndSerialNumber); if (!sid->d.issuerAndSerialNumber) goto merr; if (!X509_NAME_set(&sid->d.issuerAndSerialNumber->issuer, X509_get_issuer_name(cert))) goto merr; ASN1_STRING_free(sid->d.issuerAndSerialNumber->serialNumber); sid->d.issuerAndSerialNumber->serialNumber = ASN1_STRING_dup(X509_get_serialNumber(cert)); if(!sid->d.issuerAndSerialNumber->serialNumber) goto merr; break; case CMS_SIGNERINFO_KEYIDENTIFIER: if (!cert->skid) { CMSerr(CMS_F_CMS_SET1_SIGNERIDENTIFIER, CMS_R_CERTIFICATE_HAS_NO_KEYID); return 0; } sid->d.subjectKeyIdentifier = ASN1_STRING_dup(cert->skid); if (!sid->d.subjectKeyIdentifier) goto merr; break; default: CMSerr(CMS_F_CMS_SET1_SIGNERIDENTIFIER, CMS_R_UNKNOWN_ID); return 0; } sid->type = type; return 1; merr: CMSerr(CMS_F_CMS_SET1_SIGNERIDENTIFIER, ERR_R_MALLOC_FAILURE); return 0; }
int cms_set1_ias(CMS_IssuerAndSerialNumber **pias, X509 *cert) { CMS_IssuerAndSerialNumber *ias; ias = M_ASN1_new_of(CMS_IssuerAndSerialNumber); if (!ias) goto err; if (!X509_NAME_set(&ias->issuer, X509_get_issuer_name(cert))) goto err; if (!ASN1_STRING_copy(ias->serialNumber, X509_get_serialNumber(cert))) goto err; M_ASN1_free_of(*pias, CMS_IssuerAndSerialNumber); *pias = ias; return 1; err: M_ASN1_free_of(ias, CMS_IssuerAndSerialNumber); CMSerr(CMS_F_CMS_SET1_IAS, ERR_R_MALLOC_FAILURE); return 0; }
static CMS_SignedData *cms_signed_data_init(CMS_ContentInfo *cms) { if (cms->d.other == NULL) { cms->d.signedData = M_ASN1_new_of(CMS_SignedData); if (!cms->d.signedData) { CMSerr(CMS_F_CMS_SIGNED_DATA_INIT, ERR_R_MALLOC_FAILURE); return NULL; } cms->d.signedData->version = 1; cms->d.signedData->encapContentInfo->eContentType = OBJ_nid2obj(NID_pkcs7_data); cms->d.signedData->encapContentInfo->partial = 1; ASN1_OBJECT_free(cms->contentType); cms->contentType = OBJ_nid2obj(NID_pkcs7_signed); return cms->d.signedData; } return cms_get0_signed(cms); }
static int cms_RecipientInfo_ktri_init(CMS_RecipientInfo *ri, X509 *recip, EVP_PKEY *pk, unsigned int flags) { CMS_KeyTransRecipientInfo *ktri; int idtype; ri->d.ktri = M_ASN1_new_of(CMS_KeyTransRecipientInfo); if (!ri->d.ktri) return 0; ri->type = CMS_RECIPINFO_TRANS; ktri = ri->d.ktri; if (flags & CMS_USE_KEYID) { ktri->version = 2; idtype = CMS_RECIPINFO_KEYIDENTIFIER; } else { ktri->version = 0; idtype = CMS_RECIPINFO_ISSUER_SERIAL; } /* * Not a typo: RecipientIdentifier and SignerIdentifier are the same * structure. */ if (!cms_set1_SignerIdentifier(ktri->rid, recip, idtype)) return 0; CRYPTO_add(&recip->references, 1, CRYPTO_LOCK_X509); CRYPTO_add(&pk->references, 1, CRYPTO_LOCK_EVP_PKEY); ktri->pkey = pk; ktri->recip = recip; if (flags & CMS_KEY_PARAM) { ktri->pctx = EVP_PKEY_CTX_new(ktri->pkey, NULL); if (!ktri->pctx) return 0; if (EVP_PKEY_encrypt_init(ktri->pctx) <= 0) return 0; } else if (!cms_env_asn1_ctrl(ri, 0)) return 0; return 1; }
CMS_ContentInfo *cms_CompressedData_create(int comp_nid) { CMS_ContentInfo *cms; CMS_CompressedData *cd; /* Will need something cleverer if there is ever more than one * compression algorithm or parameters have some meaning... */ if (comp_nid != NID_zlib_compression) { CMSerr(CMS_F_CMS_COMPRESSEDDATA_CREATE, CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM); return NULL; } cms = CMS_ContentInfo_new(); if (!cms) return NULL; cd = M_ASN1_new_of(CMS_CompressedData); if (!cd) goto err; cms->contentType = OBJ_nid2obj(NID_id_smime_ct_compressedData); cms->d.compressedData = cd; cd->version = 0; X509_ALGOR_set0(cd->compressionAlgorithm, OBJ_nid2obj(NID_zlib_compression), V_ASN1_UNDEF, NULL); cd->encapContentInfo->eContentType = OBJ_nid2obj(NID_pkcs7_data); return cms; err: if (cms) CMS_ContentInfo_free(cms); return NULL; }
CMS_RevocationInfoChoice *CMS_add0_RevocationInfoChoice(CMS_ContentInfo *cms) { STACK_OF(CMS_RevocationInfoChoice) **pcrls; CMS_RevocationInfoChoice *rch; pcrls = cms_get0_revocation_choices(cms); if (!pcrls) return NULL; if (!*pcrls) *pcrls = sk_CMS_RevocationInfoChoice_new_null(); if (!*pcrls) return NULL; rch = M_ASN1_new_of(CMS_RevocationInfoChoice); if (!rch) return NULL; if (!sk_CMS_RevocationInfoChoice_push(*pcrls, rch)) { M_ASN1_free_of(rch, CMS_RevocationInfoChoice); return NULL; } return rch; }
CMS_CertificateChoices *CMS_add0_CertificateChoices(CMS_ContentInfo *cms) { STACK_OF(CMS_CertificateChoices) **pcerts; CMS_CertificateChoices *cch; pcerts = cms_get0_certificate_choices(cms); if (!pcerts) return NULL; if (!*pcerts) *pcerts = sk_CMS_CertificateChoices_new_null(); if (!*pcerts) return NULL; cch = M_ASN1_new_of(CMS_CertificateChoices); if (!cch) return NULL; if (!sk_CMS_CertificateChoices_push(*pcerts, cch)) { M_ASN1_free_of(cch, CMS_CertificateChoices); return NULL; } return cch; }
CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms, X509 *signer, EVP_PKEY *pk, const EVP_MD *md, unsigned int flags) { CMS_SignedData *sd; CMS_SignerInfo *si = NULL; X509_ALGOR *alg; int i, type; if(!X509_check_private_key(signer, pk)) { CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE); return NULL; } sd = cms_signed_data_init(cms); if (!sd) goto err; si = M_ASN1_new_of(CMS_SignerInfo); if (!si) goto merr; X509_check_purpose(signer, -1, -1); CRYPTO_add(&pk->references, 1, CRYPTO_LOCK_EVP_PKEY); CRYPTO_add(&signer->references, 1, CRYPTO_LOCK_X509); si->pkey = pk; si->signer = signer; if (flags & CMS_USE_KEYID) { si->version = 3; if (sd->version < 3) sd->version = 3; type = CMS_SIGNERINFO_KEYIDENTIFIER; } else { type = CMS_SIGNERINFO_ISSUER_SERIAL; si->version = 1; } if (!cms_set1_SignerIdentifier(si->sid, signer, type)) goto err; /* Since no EVP_PKEY_METHOD in 0.9.8 hard code SHA1 as default */ if (md == NULL) md = EVP_sha1(); /* OpenSSL 0.9.8 only supports SHA1 with non-RSA keys */ if ((pk->type != EVP_PKEY_RSA) && (EVP_MD_type(md) != NID_sha1)) { CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); goto err; } cms_DigestAlgorithm_set(si->digestAlgorithm, md); /* See if digest is present in digestAlgorithms */ for (i = 0; i < sk_X509_ALGOR_num(sd->digestAlgorithms); i++) { ASN1_OBJECT *aoid; alg = sk_X509_ALGOR_value(sd->digestAlgorithms, i); X509_ALGOR_get0(&aoid, NULL, NULL, alg); if (OBJ_obj2nid(aoid) == EVP_MD_type(md)) break; } if (i == sk_X509_ALGOR_num(sd->digestAlgorithms)) { alg = X509_ALGOR_new(); if (!alg) goto merr; cms_DigestAlgorithm_set(alg, md); if (!sk_X509_ALGOR_push(sd->digestAlgorithms, alg)) { X509_ALGOR_free(alg); goto merr; } } /* Since we have no EVP_PKEY_ASN1_METHOD in OpenSSL 0.9.8, * hard code algorithm parameters. */ switch (pk->type) { case EVP_PKEY_RSA: X509_ALGOR_set0(si->signatureAlgorithm, OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0); break; case EVP_PKEY_DSA: X509_ALGOR_set0(si->signatureAlgorithm, OBJ_nid2obj(NID_dsaWithSHA1), V_ASN1_UNDEF, 0); break; case EVP_PKEY_EC: X509_ALGOR_set0(si->signatureAlgorithm, OBJ_nid2obj(NID_ecdsa_with_SHA1), V_ASN1_UNDEF, 0); break; default: CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); goto err; } if (!(flags & CMS_NOATTR)) { /* Initialialize signed attributes strutucture so other * attributes such as signing time etc are added later * even if we add none here. */ if (!si->signedAttrs) { si->signedAttrs = sk_X509_ATTRIBUTE_new_null(); if (!si->signedAttrs) goto merr; } if (!(flags & CMS_NOSMIMECAP)) { STACK_OF(X509_ALGOR) *smcap = NULL; i = CMS_add_standard_smimecap(&smcap); if (i) i = CMS_add_smimecap(si, smcap); sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free); if (!i) goto merr; } if (flags & CMS_REUSE_DIGEST) { if (!cms_copy_messageDigest(cms, si)) goto err; if (!(flags & CMS_PARTIAL) && !CMS_SignerInfo_sign(si)) goto err; } } if (!(flags & CMS_NOCERTS)) { /* NB ignore -1 return for duplicate cert */ if (!CMS_add1_cert(cms, signer)) goto merr; } if (!sd->signerInfos) sd->signerInfos = sk_CMS_SignerInfo_new_null(); if (!sd->signerInfos || !sk_CMS_SignerInfo_push(sd->signerInfos, si)) goto merr; return si; merr: CMSerr(CMS_F_CMS_ADD1_SIGNER, ERR_R_MALLOC_FAILURE); err: if (si) M_ASN1_free_of(si, CMS_SignerInfo); return NULL; }
CMS_RecipientInfo * CMS_add0_recipient_password(CMS_ContentInfo *cms, int iter, int wrap_nid, int pbe_nid, unsigned char *pass, ssize_t passlen, const EVP_CIPHER *kekciph) { CMS_RecipientInfo *ri = NULL; CMS_EnvelopedData *env; CMS_PasswordRecipientInfo *pwri; EVP_CIPHER_CTX ctx; X509_ALGOR *encalg = NULL; unsigned char iv[EVP_MAX_IV_LENGTH]; int ivlen; env = cms_get0_enveloped(cms); if (!env) return NULL; if (wrap_nid <= 0) wrap_nid = NID_id_alg_PWRI_KEK; if (pbe_nid <= 0) pbe_nid = NID_id_pbkdf2; /* Get from enveloped data */ if (kekciph == NULL) kekciph = env->encryptedContentInfo->cipher; if (kekciph == NULL) { CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, CMS_R_NO_CIPHER); return NULL; } if (wrap_nid != NID_id_alg_PWRI_KEK) { CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM); return NULL; } /* Setup algorithm identifier for cipher */ encalg = X509_ALGOR_new(); EVP_CIPHER_CTX_init(&ctx); if (EVP_EncryptInit_ex(&ctx, kekciph, NULL, NULL, NULL) <= 0) { CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_EVP_LIB); goto err; } ivlen = EVP_CIPHER_CTX_iv_length(&ctx); if (ivlen > 0) { arc4random_buf(iv, ivlen); if (EVP_EncryptInit_ex(&ctx, NULL, NULL, NULL, iv) <= 0) { CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_EVP_LIB); goto err; } encalg->parameter = ASN1_TYPE_new(); if (!encalg->parameter) { CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_MALLOC_FAILURE); goto err; } if (EVP_CIPHER_param_to_asn1(&ctx, encalg->parameter) <= 0) { CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR); goto err; } } encalg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_type(&ctx)); EVP_CIPHER_CTX_cleanup(&ctx); /* Initialize recipient info */ ri = M_ASN1_new_of(CMS_RecipientInfo); if (!ri) goto merr; ri->d.pwri = M_ASN1_new_of(CMS_PasswordRecipientInfo); if (!ri->d.pwri) goto merr; ri->type = CMS_RECIPINFO_PASS; pwri = ri->d.pwri; /* Since this is overwritten, free up empty structure already there */ X509_ALGOR_free(pwri->keyEncryptionAlgorithm); pwri->keyEncryptionAlgorithm = X509_ALGOR_new(); if (!pwri->keyEncryptionAlgorithm) goto merr; pwri->keyEncryptionAlgorithm->algorithm = OBJ_nid2obj(wrap_nid); pwri->keyEncryptionAlgorithm->parameter = ASN1_TYPE_new(); if (!pwri->keyEncryptionAlgorithm->parameter) goto merr; if (!ASN1_item_pack(encalg, ASN1_ITEM_rptr(X509_ALGOR), &pwri->keyEncryptionAlgorithm->parameter->value.sequence)) goto merr; pwri->keyEncryptionAlgorithm->parameter->type = V_ASN1_SEQUENCE; X509_ALGOR_free(encalg); encalg = NULL; /* Setup PBE algorithm */ pwri->keyDerivationAlgorithm = PKCS5_pbkdf2_set(iter, NULL, 0, -1, -1); if (!pwri->keyDerivationAlgorithm) goto err; CMS_RecipientInfo_set0_password(ri, pass, passlen); pwri->version = 0; if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri)) goto merr; return ri; merr: CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_MALLOC_FAILURE); err: EVP_CIPHER_CTX_cleanup(&ctx); if (ri) M_ASN1_free_of(ri, CMS_RecipientInfo); if (encalg) X509_ALGOR_free(encalg); return NULL; }
CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms, X509 *signer, EVP_PKEY *pk, const EVP_MD *md, unsigned int flags) { CMS_SignedData *sd; CMS_SignerInfo *si = NULL; X509_ALGOR *alg; int i, type; if (!X509_check_private_key(signer, pk)) { CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE); return NULL; } sd = cms_signed_data_init(cms); if (!sd) goto err; si = M_ASN1_new_of(CMS_SignerInfo); if (!si) goto merr; /* Call for side-effect of computing hash and caching extensions */ X509_check_purpose(signer, -1, -1); X509_up_ref(signer); EVP_PKEY_up_ref(pk); si->pkey = pk; si->signer = signer; si->mctx = EVP_MD_CTX_new(); si->pctx = NULL; if (si->mctx == NULL) { CMSerr(CMS_F_CMS_ADD1_SIGNER, ERR_R_MALLOC_FAILURE); goto err; } if (flags & CMS_USE_KEYID) { si->version = 3; if (sd->version < 3) sd->version = 3; type = CMS_SIGNERINFO_KEYIDENTIFIER; } else { type = CMS_SIGNERINFO_ISSUER_SERIAL; si->version = 1; } if (!cms_set1_SignerIdentifier(si->sid, signer, type)) goto err; 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) { CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_NO_DEFAULT_DIGEST); goto err; } } if (!md) { CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_NO_DIGEST_SET); goto err; } X509_ALGOR_set_md(si->digestAlgorithm, md); /* See if digest is present in digestAlgorithms */ for (i = 0; i < sk_X509_ALGOR_num(sd->digestAlgorithms); i++) { const ASN1_OBJECT *aoid; alg = sk_X509_ALGOR_value(sd->digestAlgorithms, i); X509_ALGOR_get0(&aoid, NULL, NULL, alg); if (OBJ_obj2nid(aoid) == EVP_MD_type(md)) break; } if (i == sk_X509_ALGOR_num(sd->digestAlgorithms)) { alg = X509_ALGOR_new(); if (alg == NULL) goto merr; X509_ALGOR_set_md(alg, md); if (!sk_X509_ALGOR_push(sd->digestAlgorithms, alg)) { X509_ALGOR_free(alg); goto merr; } } if (!(flags & CMS_KEY_PARAM) && !cms_sd_asn1_ctrl(si, 0)) goto err; if (!(flags & CMS_NOATTR)) { /* * Initialize signed attributes structure so other attributes * such as signing time etc are added later even if we add none here. */ if (!si->signedAttrs) { si->signedAttrs = sk_X509_ATTRIBUTE_new_null(); if (!si->signedAttrs) goto merr; } if (!(flags & CMS_NOSMIMECAP)) { STACK_OF(X509_ALGOR) *smcap = NULL; i = CMS_add_standard_smimecap(&smcap); if (i) i = CMS_add_smimecap(si, smcap); sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free); if (!i) goto merr; } if (flags & CMS_REUSE_DIGEST) { if (!cms_copy_messageDigest(cms, si)) goto err; if (!(flags & (CMS_PARTIAL | CMS_KEY_PARAM)) && !CMS_SignerInfo_sign(si)) goto err; } } if (!(flags & CMS_NOCERTS)) { /* NB ignore -1 return for duplicate cert */ if (!CMS_add1_cert(cms, signer)) goto merr; } if (flags & CMS_KEY_PARAM) { if (flags & CMS_NOATTR) { si->pctx = EVP_PKEY_CTX_new(si->pkey, NULL); if (si->pctx == NULL) goto err; if (EVP_PKEY_sign_init(si->pctx) <= 0) goto err; if (EVP_PKEY_CTX_set_signature_md(si->pctx, md) <= 0) goto err; } else if (EVP_DigestSignInit(si->mctx, &si->pctx, md, NULL, pk) <= 0) goto err; } if (!sd->signerInfos) sd->signerInfos = sk_CMS_SignerInfo_new_null(); if (!sd->signerInfos || !sk_CMS_SignerInfo_push(sd->signerInfos, si)) goto merr; return si; merr: CMSerr(CMS_F_CMS_ADD1_SIGNER, ERR_R_MALLOC_FAILURE); err: M_ASN1_free_of(si, CMS_SignerInfo); return NULL; }
CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms, X509 *recip, unsigned int flags) { CMS_RecipientInfo *ri = NULL; CMS_KeyTransRecipientInfo *ktri; CMS_EnvelopedData *env; EVP_PKEY *pk = NULL; int type; env = cms_get0_enveloped(cms); if (!env) goto err; /* Initialize recipient info */ ri = M_ASN1_new_of(CMS_RecipientInfo); if (!ri) goto merr; /* Initialize and add key transport recipient info */ ri->d.ktri = M_ASN1_new_of(CMS_KeyTransRecipientInfo); if (!ri->d.ktri) goto merr; ri->type = CMS_RECIPINFO_TRANS; ktri = ri->d.ktri; X509_check_purpose(recip, -1, -1); pk = X509_get_pubkey(recip); if (!pk) { CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, CMS_R_ERROR_GETTING_PUBLIC_KEY); goto err; } CRYPTO_add(&recip->references, 1, CRYPTO_LOCK_X509); ktri->pkey = pk; ktri->recip = recip; if (flags & CMS_USE_KEYID) { ktri->version = 2; type = CMS_RECIPINFO_KEYIDENTIFIER; } else { ktri->version = 0; type = CMS_RECIPINFO_ISSUER_SERIAL; } /* Not a typo: RecipientIdentifier and SignerIdentifier are the * same structure. */ if (!cms_set1_SignerIdentifier(ktri->rid, recip, type)) goto err; /* Since we have no EVP_PKEY_ASN1_METHOD in OpenSSL 0.9.8, * hard code algorithm parameters. */ if (pk->type == EVP_PKEY_RSA) { X509_ALGOR_set0(ktri->keyEncryptionAlgorithm, OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0); } else { CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); goto err; } if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri)) goto merr; return ri; merr: CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, ERR_R_MALLOC_FAILURE); err: if (ri) M_ASN1_free_of(ri, CMS_RecipientInfo); return NULL; }
CMS_RecipientInfo *CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid, unsigned char *key, size_t keylen, unsigned char *id, size_t idlen, ASN1_GENERALIZEDTIME *date, ASN1_OBJECT *otherTypeId, ASN1_TYPE *otherType) { CMS_RecipientInfo *ri = NULL; CMS_EnvelopedData *env; CMS_KEKRecipientInfo *kekri; env = cms_get0_enveloped(cms); if (!env) goto err; if (nid == NID_undef) { switch (keylen) { case 16: nid = NID_id_aes128_wrap; break; case 24: nid = NID_id_aes192_wrap; break; case 32: nid = NID_id_aes256_wrap; break; default: CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY, CMS_R_INVALID_KEY_LENGTH); goto err; } } else { size_t exp_keylen = aes_wrap_keylen(nid); if (!exp_keylen) { CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY, CMS_R_UNSUPPORTED_KEK_ALGORITHM); goto err; } if (keylen != exp_keylen) { CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY, CMS_R_INVALID_KEY_LENGTH); goto err; } } /* Initialize recipient info */ ri = M_ASN1_new_of(CMS_RecipientInfo); if (!ri) goto merr; ri->d.kekri = M_ASN1_new_of(CMS_KEKRecipientInfo); if (!ri->d.kekri) goto merr; ri->type = CMS_RECIPINFO_KEK; kekri = ri->d.kekri; if (otherTypeId) { kekri->kekid->other = M_ASN1_new_of(CMS_OtherKeyAttribute); if (kekri->kekid->other == NULL) goto merr; } if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri)) goto merr; /* After this point no calls can fail */ kekri->version = 4; kekri->key = key; kekri->keylen = keylen; ASN1_STRING_set0(kekri->kekid->keyIdentifier, id, idlen); kekri->kekid->date = date; if (kekri->kekid->other) { kekri->kekid->other->keyAttrId = otherTypeId; kekri->kekid->other->keyAttr = otherType; } X509_ALGOR_set0(kekri->keyEncryptionAlgorithm, OBJ_nid2obj(nid), V_ASN1_UNDEF, NULL); return ri; merr: CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY, ERR_R_MALLOC_FAILURE); err: if (ri) M_ASN1_free_of(ri, CMS_RecipientInfo); return NULL; }
CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms, X509 *recip, unsigned int flags) { CMS_RecipientInfo *ri = NULL; CMS_KeyTransRecipientInfo *ktri; CMS_EnvelopedData *env; EVP_PKEY *pk = NULL; int i, type; env = cms_get0_enveloped(cms); if (!env) goto err; /* Initialize recipient info */ ri = M_ASN1_new_of(CMS_RecipientInfo); if (!ri) goto merr; /* Initialize and add key transport recipient info */ ri->d.ktri = M_ASN1_new_of(CMS_KeyTransRecipientInfo); if (!ri->d.ktri) goto merr; ri->type = CMS_RECIPINFO_TRANS; ktri = ri->d.ktri; X509_check_purpose(recip, -1, -1); pk = X509_get_pubkey(recip); if (!pk) { CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, CMS_R_ERROR_GETTING_PUBLIC_KEY); goto err; } CRYPTO_add(&recip->references, 1, CRYPTO_LOCK_X509); ktri->pkey = pk; ktri->recip = recip; if (flags & CMS_USE_KEYID) { ktri->version = 2; if (env->version < 2) env->version = 2; type = CMS_RECIPINFO_KEYIDENTIFIER; } else { ktri->version = 0; type = CMS_RECIPINFO_ISSUER_SERIAL; } /* * Not a typo: RecipientIdentifier and SignerIdentifier are the same * structure. */ if (!cms_set1_SignerIdentifier(ktri->rid, recip, type)) goto err; if (pk->ameth && pk->ameth->pkey_ctrl) { i = pk->ameth->pkey_ctrl(pk, ASN1_PKEY_CTRL_CMS_ENVELOPE, 0, ri); if (i == -2) { CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); goto err; } if (i <= 0) { CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, CMS_R_CTRL_FAILURE); goto err; } } if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri)) goto merr; return ri; merr: CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, ERR_R_MALLOC_FAILURE); err: if (ri) M_ASN1_free_of(ri, CMS_RecipientInfo); return NULL; }
CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms, X509 *signer, EVP_PKEY *pk, const EVP_MD *md, unsigned int flags) { CMS_SignedData *sd; CMS_SignerInfo *si = NULL; X509_ALGOR *alg; int i, type; if (!X509_check_private_key(signer, pk)) { CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE); return NULL; } sd = cms_signed_data_init(cms); if (!sd) goto err; si = M_ASN1_new_of(CMS_SignerInfo); if (!si) goto merr; X509_check_purpose(signer, -1, -1); CRYPTO_add(&pk->references, 1, CRYPTO_LOCK_EVP_PKEY); CRYPTO_add(&signer->references, 1, CRYPTO_LOCK_X509); si->pkey = pk; si->signer = signer; if (flags & CMS_USE_KEYID) { si->version = 3; if (sd->version < 3) sd->version = 3; type = CMS_SIGNERINFO_KEYIDENTIFIER; } else { type = CMS_SIGNERINFO_ISSUER_SERIAL; si->version = 1; } if (!cms_set1_SignerIdentifier(si->sid, signer, type)) goto err; 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) { CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_NO_DEFAULT_DIGEST); goto err; } } if (!md) { CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_NO_DIGEST_SET); goto err; } cms_DigestAlgorithm_set(si->digestAlgorithm, md); /* See if digest is present in digestAlgorithms */ for (i = 0; i < sk_X509_ALGOR_num(sd->digestAlgorithms); i++) { ASN1_OBJECT *aoid; alg = sk_X509_ALGOR_value(sd->digestAlgorithms, i); X509_ALGOR_get0(&aoid, NULL, NULL, alg); if (OBJ_obj2nid(aoid) == EVP_MD_type(md)) break; } if (i == sk_X509_ALGOR_num(sd->digestAlgorithms)) { alg = X509_ALGOR_new(); if (!alg) goto merr; cms_DigestAlgorithm_set(alg, md); if (!sk_X509_ALGOR_push(sd->digestAlgorithms, alg)) { X509_ALGOR_free(alg); goto merr; } } if (pk->ameth && pk->ameth->pkey_ctrl) { i = pk->ameth->pkey_ctrl(pk, ASN1_PKEY_CTRL_CMS_SIGN, 0, si); if (i == -2) { CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); goto err; } if (i <= 0) { CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_CTRL_FAILURE); goto err; } } if (!(flags & CMS_NOATTR)) { /* * Initialialize signed attributes strutucture so other attributes * such as signing time etc are added later even if we add none here. */ if (!si->signedAttrs) { si->signedAttrs = sk_X509_ATTRIBUTE_new_null(); if (!si->signedAttrs) goto merr; } if (!(flags & CMS_NOSMIMECAP)) { STACK_OF(X509_ALGOR) *smcap = NULL; i = CMS_add_standard_smimecap(&smcap); if (i) i = CMS_add_smimecap(si, smcap); sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free); if (!i) goto merr; } if (flags & CMS_REUSE_DIGEST) { if (!cms_copy_messageDigest(cms, si)) goto err; if (!(flags & CMS_PARTIAL) && !CMS_SignerInfo_sign(si)) goto err; } } if (!(flags & CMS_NOCERTS)) { /* NB ignore -1 return for duplicate cert */ if (!CMS_add1_cert(cms, signer)) goto merr; } if (!sd->signerInfos) sd->signerInfos = sk_CMS_SignerInfo_new_null(); if (!sd->signerInfos || !sk_CMS_SignerInfo_push(sd->signerInfos, si)) goto merr; return si; merr: CMSerr(CMS_F_CMS_ADD1_SIGNER, ERR_R_MALLOC_FAILURE); err: if (si) M_ASN1_free_of(si, CMS_SignerInfo); return NULL; }