BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec) { BIO *b; EVP_CIPHER_CTX *ctx; const EVP_CIPHER *ciph; X509_ALGOR *calg = ec->contentEncryptionAlgorithm; unsigned char iv[EVP_MAX_IV_LENGTH], *piv = NULL; unsigned char *tkey = NULL; size_t tkeylen = 0; int ok = 0; int enc, keep_key = 0; enc = ec->cipher ? 1 : 0; b = BIO_new(BIO_f_cipher()); if (!b) { CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, ERR_R_MALLOC_FAILURE); return NULL; } BIO_get_cipher_ctx(b, &ctx); if (enc) { ciph = ec->cipher; /* * If not keeping key set cipher to NULL so subsequent calls decrypt. */ if (ec->key) ec->cipher = NULL; } else { ciph = EVP_get_cipherbyobj(calg->algorithm); if (!ciph) { CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, CMS_R_UNKNOWN_CIPHER); goto err; } } if (EVP_CipherInit_ex(ctx, ciph, NULL, NULL, NULL, enc) <= 0) { CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, CMS_R_CIPHER_INITIALISATION_ERROR); goto err; } if (enc) { int ivlen; calg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_type(ctx)); /* Generate a random IV if we need one */ ivlen = EVP_CIPHER_CTX_iv_length(ctx); if (ivlen > 0) { if (RAND_bytes(iv, ivlen) <= 0) goto err; piv = iv; } } else if (EVP_CIPHER_asn1_to_param(ctx, calg->parameter) <= 0) { CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR); goto err; } tkeylen = EVP_CIPHER_CTX_key_length(ctx); /* Generate random session key */ if (!enc || !ec->key) { tkey = OPENSSL_malloc(tkeylen); if (!tkey) { CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, ERR_R_MALLOC_FAILURE); goto err; } if (EVP_CIPHER_CTX_rand_key(ctx, tkey) <= 0) goto err; } if (!ec->key) { ec->key = tkey; ec->keylen = tkeylen; tkey = NULL; if (enc) keep_key = 1; else ERR_clear_error(); } if (ec->keylen != tkeylen) { /* If necessary set key length */ if (EVP_CIPHER_CTX_set_key_length(ctx, ec->keylen) <= 0) { /* * Only reveal failure if debugging so we don't leak information * which may be useful in MMA. */ if (enc || ec->debug) { CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, CMS_R_INVALID_KEY_LENGTH); goto err; } else { /* Use random key */ OPENSSL_clear_free(ec->key, ec->keylen); ec->key = tkey; ec->keylen = tkeylen; tkey = NULL; ERR_clear_error(); } } } if (EVP_CipherInit_ex(ctx, NULL, NULL, ec->key, piv, enc) <= 0) { CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, CMS_R_CIPHER_INITIALISATION_ERROR); goto err; } if (piv) { calg->parameter = ASN1_TYPE_new(); if (!calg->parameter) { CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, ERR_R_MALLOC_FAILURE); goto err; } if (EVP_CIPHER_param_to_asn1(ctx, calg->parameter) <= 0) { CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR); goto err; } } ok = 1; err: if (!keep_key) { OPENSSL_clear_free(ec->key, ec->keylen); ec->key = NULL; } OPENSSL_clear_free(tkey, tkeylen); if (ok) return b; BIO_free(b); return NULL; }
static int dh_cms_encrypt(CMS_RecipientInfo *ri) { EVP_PKEY_CTX *pctx; EVP_PKEY *pkey; EVP_CIPHER_CTX *ctx; int keylen; X509_ALGOR *talg, *wrap_alg = NULL; ASN1_OBJECT *aoid; ASN1_BIT_STRING *pubkey; ASN1_STRING *wrap_str; ASN1_OCTET_STRING *ukm; unsigned char *penc = NULL, *dukm = NULL; int penclen; size_t dukmlen = 0; int rv = 0; int kdf_type, wrap_nid; const EVP_MD *kdf_md; pctx = CMS_RecipientInfo_get0_pkey_ctx(ri); if (!pctx) return 0; /* Get ephemeral key */ pkey = EVP_PKEY_CTX_get0_pkey(pctx); if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &talg, &pubkey, NULL, NULL, NULL)) goto err; X509_ALGOR_get0(&aoid, NULL, NULL, talg); /* Is everything uninitialised? */ if (aoid == OBJ_nid2obj(NID_undef)) { ASN1_INTEGER *pubk; pubk = BN_to_ASN1_INTEGER(pkey->pkey.dh->pub_key, NULL); if (!pubk) goto err; /* Set the key */ penclen = i2d_ASN1_INTEGER(pubk, &penc); ASN1_INTEGER_free(pubk); if (penclen <= 0) goto err; ASN1_STRING_set0(pubkey, penc, penclen); pubkey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); pubkey->flags |= ASN1_STRING_FLAG_BITS_LEFT; penc = NULL; X509_ALGOR_set0(talg, OBJ_nid2obj(NID_dhpublicnumber), V_ASN1_UNDEF, NULL); } /* See if custom paraneters set */ kdf_type = EVP_PKEY_CTX_get_dh_kdf_type(pctx); if (kdf_type <= 0) goto err; if (!EVP_PKEY_CTX_get_dh_kdf_md(pctx, &kdf_md)) goto err; if (kdf_type == EVP_PKEY_DH_KDF_NONE) { kdf_type = EVP_PKEY_DH_KDF_X9_42; if (EVP_PKEY_CTX_set_dh_kdf_type(pctx, kdf_type) <= 0) goto err; } else if (kdf_type != EVP_PKEY_DH_KDF_X9_42) /* Unknown KDF */ goto err; if (kdf_md == NULL) { /* Only SHA1 supported */ kdf_md = EVP_sha1(); if (EVP_PKEY_CTX_set_dh_kdf_md(pctx, kdf_md) <= 0) goto err; } else if (EVP_MD_type(kdf_md) != NID_sha1) /* Unsupported digest */ goto err; if (!CMS_RecipientInfo_kari_get0_alg(ri, &talg, &ukm)) goto err; /* Get wrap NID */ ctx = CMS_RecipientInfo_kari_get0_ctx(ri); wrap_nid = EVP_CIPHER_CTX_type(ctx); if (EVP_PKEY_CTX_set0_dh_kdf_oid(pctx, OBJ_nid2obj(wrap_nid)) <= 0) goto err; keylen = EVP_CIPHER_CTX_key_length(ctx); /* Package wrap algorithm in an AlgorithmIdentifier */ wrap_alg = X509_ALGOR_new(); if (!wrap_alg) goto err; wrap_alg->algorithm = OBJ_nid2obj(wrap_nid); wrap_alg->parameter = ASN1_TYPE_new(); if (!wrap_alg->parameter) goto err; if (EVP_CIPHER_param_to_asn1(ctx, wrap_alg->parameter) <= 0) goto err; if (ASN1_TYPE_get(wrap_alg->parameter) == NID_undef) { ASN1_TYPE_free(wrap_alg->parameter); wrap_alg->parameter = NULL; } if (EVP_PKEY_CTX_set_dh_kdf_outlen(pctx, keylen) <= 0) goto err; if (ukm) { dukmlen = ASN1_STRING_length(ukm); dukm = BUF_memdup(ASN1_STRING_data(ukm), dukmlen); if (!dukm) goto err; } if (EVP_PKEY_CTX_set0_dh_kdf_ukm(pctx, dukm, dukmlen) <= 0) goto err; dukm = NULL; /* * Now need to wrap encoding of wrap AlgorithmIdentifier into parameter * of another AlgorithmIdentifier. */ penc = NULL; penclen = i2d_X509_ALGOR(wrap_alg, &penc); if (!penc || !penclen) goto err; wrap_str = ASN1_STRING_new(); if (!wrap_str) goto err; ASN1_STRING_set0(wrap_str, penc, penclen); penc = NULL; X509_ALGOR_set0(talg, OBJ_nid2obj(NID_id_smime_alg_ESDH), V_ASN1_SEQUENCE, wrap_str); rv = 1; err: if (penc) OPENSSL_free(penc); if (wrap_alg) X509_ALGOR_free(wrap_alg); return rv; }
BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) { int i; BIO *out = NULL, *btmp = NULL; X509_ALGOR *xa = NULL; const EVP_CIPHER *evp_cipher = NULL; STACK_OF(X509_ALGOR) *md_sk = NULL; STACK_OF(PKCS7_RECIP_INFO) *rsk = NULL; X509_ALGOR *xalg = NULL; PKCS7_RECIP_INFO *ri = NULL; ASN1_OCTET_STRING *os = NULL; if (p7 == NULL) { PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_INVALID_NULL_POINTER); return NULL; } /* * The content field in the PKCS7 ContentInfo is optional, but that really * only applies to inner content (precisely, detached signatures). * * When reading content, missing outer content is therefore treated as an * error. * * When creating content, PKCS7_content_new() must be called before * calling this method, so a NULL p7->d is always an error. */ if (p7->d.ptr == NULL) { PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_NO_CONTENT); return NULL; } i = OBJ_obj2nid(p7->type); p7->state = PKCS7_S_HEADER; switch (i) { case NID_pkcs7_signed: md_sk = p7->d.sign->md_algs; os = PKCS7_get_octet_string(p7->d.sign->contents); break; case NID_pkcs7_signedAndEnveloped: rsk = p7->d.signed_and_enveloped->recipientinfo; md_sk = p7->d.signed_and_enveloped->md_algs; xalg = p7->d.signed_and_enveloped->enc_data->algorithm; evp_cipher = p7->d.signed_and_enveloped->enc_data->cipher; if (evp_cipher == NULL) { PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_CIPHER_NOT_INITIALIZED); goto err; } break; case NID_pkcs7_enveloped: rsk = p7->d.enveloped->recipientinfo; xalg = p7->d.enveloped->enc_data->algorithm; evp_cipher = p7->d.enveloped->enc_data->cipher; if (evp_cipher == NULL) { PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_CIPHER_NOT_INITIALIZED); goto err; } break; case NID_pkcs7_digest: xa = p7->d.digest->md; os = PKCS7_get_octet_string(p7->d.digest->contents); break; case NID_pkcs7_data: break; default: PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_UNSUPPORTED_CONTENT_TYPE); goto err; } for (i = 0; i < sk_X509_ALGOR_num(md_sk); i++) if (!PKCS7_bio_add_digest(&out, sk_X509_ALGOR_value(md_sk, i))) goto err; if (xa && !PKCS7_bio_add_digest(&out, xa)) goto err; if (evp_cipher != NULL) { unsigned char key[EVP_MAX_KEY_LENGTH]; unsigned char iv[EVP_MAX_IV_LENGTH]; int keylen, ivlen; EVP_CIPHER_CTX *ctx; if ((btmp = BIO_new(BIO_f_cipher())) == NULL) { PKCS7err(PKCS7_F_PKCS7_DATAINIT, ERR_R_BIO_LIB); goto err; } BIO_get_cipher_ctx(btmp, &ctx); keylen = EVP_CIPHER_key_length(evp_cipher); ivlen = EVP_CIPHER_iv_length(evp_cipher); xalg->algorithm = OBJ_nid2obj(EVP_CIPHER_type(evp_cipher)); if (ivlen > 0) if (RAND_pseudo_bytes(iv, ivlen) <= 0) goto err; if (EVP_CipherInit_ex(ctx, evp_cipher, NULL, NULL, NULL, 1) <= 0) goto err; if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0) goto err; if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1) <= 0) goto err; if (ivlen > 0) { if (xalg->parameter == NULL) { xalg->parameter = ASN1_TYPE_new(); if (xalg->parameter == NULL) goto err; } if (EVP_CIPHER_param_to_asn1(ctx, xalg->parameter) < 0) goto err; } /* Lets do the pub key stuff :-) */ for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) { ri = sk_PKCS7_RECIP_INFO_value(rsk, i); if (pkcs7_encode_rinfo(ri, key, keylen) <= 0) goto err; } OPENSSL_cleanse(key, keylen); if (out == NULL) out = btmp; else BIO_push(out, btmp); btmp = NULL; } if (bio == NULL) { if (PKCS7_is_detached(p7)) bio = BIO_new(BIO_s_null()); else if (os && os->length > 0) bio = BIO_new_mem_buf(os->data, os->length); if (bio == NULL) { bio = BIO_new(BIO_s_mem()); if (bio == NULL) goto err; BIO_set_mem_eof_return(bio, 0); } } if (out) BIO_push(out, bio); else out = bio; bio = NULL; if (0) { err: if (out != NULL) BIO_free_all(out); if (btmp != NULL) BIO_free_all(btmp); out = NULL; } return (out); }
BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) { int i; BIO *out=NULL,*btmp=NULL; X509_ALGOR *xa = NULL; const EVP_CIPHER *evp_cipher=NULL; STACK_OF(X509_ALGOR) *md_sk=NULL; STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL; X509_ALGOR *xalg=NULL; PKCS7_RECIP_INFO *ri=NULL; EVP_PKEY *pkey; ASN1_OCTET_STRING *os=NULL; i=OBJ_obj2nid(p7->type); p7->state=PKCS7_S_HEADER; switch (i) { case NID_pkcs7_signed: md_sk=p7->d.sign->md_algs; os = PKCS7_get_octet_string(p7->d.sign->contents); break; case NID_pkcs7_signedAndEnveloped: rsk=p7->d.signed_and_enveloped->recipientinfo; md_sk=p7->d.signed_and_enveloped->md_algs; xalg=p7->d.signed_and_enveloped->enc_data->algorithm; evp_cipher=p7->d.signed_and_enveloped->enc_data->cipher; if (evp_cipher == NULL) { PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_CIPHER_NOT_INITIALIZED); goto err; } break; case NID_pkcs7_enveloped: rsk=p7->d.enveloped->recipientinfo; xalg=p7->d.enveloped->enc_data->algorithm; evp_cipher=p7->d.enveloped->enc_data->cipher; if (evp_cipher == NULL) { PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_CIPHER_NOT_INITIALIZED); goto err; } break; case NID_pkcs7_digest: xa = p7->d.digest->md; os = PKCS7_get_octet_string(p7->d.digest->contents); break; default: PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_UNSUPPORTED_CONTENT_TYPE); goto err; } for (i=0; i<sk_X509_ALGOR_num(md_sk); i++) if (!PKCS7_bio_add_digest(&out, sk_X509_ALGOR_value(md_sk, i))) goto err; if (xa && !PKCS7_bio_add_digest(&out, xa)) goto err; if (evp_cipher != NULL) { unsigned char key[EVP_MAX_KEY_LENGTH]; unsigned char iv[EVP_MAX_IV_LENGTH]; int keylen,ivlen; int jj,max; unsigned char *tmp; EVP_CIPHER_CTX *ctx; if ((btmp=BIO_new(BIO_f_cipher())) == NULL) { PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_BIO_LIB); goto err; } BIO_get_cipher_ctx(btmp, &ctx); keylen=EVP_CIPHER_key_length(evp_cipher); ivlen=EVP_CIPHER_iv_length(evp_cipher); xalg->algorithm = OBJ_nid2obj(EVP_CIPHER_type(evp_cipher)); if (ivlen > 0) RAND_pseudo_bytes(iv,ivlen); if (EVP_CipherInit_ex(ctx, evp_cipher, NULL, NULL, NULL, 1)<=0) goto err; if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0) goto err; if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1) <= 0) goto err; if (ivlen > 0) { if (xalg->parameter == NULL) xalg->parameter=ASN1_TYPE_new(); if(EVP_CIPHER_param_to_asn1(ctx, xalg->parameter) < 0) goto err; } /* Lets do the pub key stuff :-) */ max=0; for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) { ri=sk_PKCS7_RECIP_INFO_value(rsk,i); if (ri->cert == NULL) { PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_MISSING_CERIPEND_INFO); goto err; } pkey=X509_get_pubkey(ri->cert); jj=EVP_PKEY_size(pkey); EVP_PKEY_free(pkey); if (max < jj) max=jj; } if ((tmp=(unsigned char *)OPENSSL_malloc(max)) == NULL) { PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_MALLOC_FAILURE); goto err; } for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) { ri=sk_PKCS7_RECIP_INFO_value(rsk,i); pkey=X509_get_pubkey(ri->cert); jj=EVP_PKEY_encrypt(tmp,key,keylen,pkey); EVP_PKEY_free(pkey); if (jj <= 0) { PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_EVP_LIB); OPENSSL_free(tmp); goto err; } if (!M_ASN1_OCTET_STRING_set(ri->enc_key,tmp,jj)) { PKCS7err(PKCS7_F_PKCS7_DATAINIT, ERR_R_MALLOC_FAILURE); OPENSSL_free(tmp); goto err; } } OPENSSL_free(tmp); OPENSSL_cleanse(key, keylen); if (out == NULL) out=btmp; else BIO_push(out,btmp); btmp=NULL; } if (bio == NULL) { if (PKCS7_is_detached(p7)) bio=BIO_new(BIO_s_null()); else if (os && os->length > 0) bio = BIO_new_mem_buf(os->data, os->length); if(bio == NULL) { bio=BIO_new(BIO_s_mem()); BIO_set_mem_eof_return(bio,0); } } BIO_push(out,bio); bio=NULL; if (0) { err: if (out != NULL) BIO_free_all(out); if (btmp != NULL) BIO_free_all(btmp); out=NULL; } return(out); }
X509_ALGOR *PKCS5_pbe2_set_scrypt(const EVP_CIPHER *cipher, const unsigned char *salt, int saltlen, unsigned char *aiv, uint64_t N, uint64_t r, uint64_t p) { X509_ALGOR *scheme = NULL, *kalg = NULL, *ret = NULL; int alg_nid; size_t keylen = 0; EVP_CIPHER_CTX ctx; unsigned char iv[EVP_MAX_IV_LENGTH]; PBE2PARAM *pbe2 = NULL; ASN1_OBJECT *obj; if (!cipher) { ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT, ERR_R_PASSED_NULL_PARAMETER); goto err; } if (EVP_PBE_scrypt(NULL, 0, NULL, 0, N, r, p, 0, NULL, 0) == 0) { ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT, ASN1_R_INVALID_SCRYPT_PARAMETERS); goto err; } alg_nid = EVP_CIPHER_type(cipher); if (alg_nid == NID_undef) { ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT, ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER); goto err; } obj = OBJ_nid2obj(alg_nid); pbe2 = PBE2PARAM_new(); if (pbe2 == NULL) goto merr; /* Setup the AlgorithmIdentifier for the encryption scheme */ scheme = pbe2->encryption; scheme->algorithm = obj; scheme->parameter = ASN1_TYPE_new(); if (scheme->parameter == NULL) goto merr; /* Create random IV */ if (EVP_CIPHER_iv_length(cipher)) { if (aiv) memcpy(iv, aiv, EVP_CIPHER_iv_length(cipher)); else if (RAND_bytes(iv, EVP_CIPHER_iv_length(cipher)) < 0) goto err; } EVP_CIPHER_CTX_init(&ctx); /* Dummy cipherinit to just setup the IV */ if (EVP_CipherInit_ex(&ctx, cipher, NULL, NULL, iv, 0) == 0) goto err; if (EVP_CIPHER_param_to_asn1(&ctx, scheme->parameter) < 0) { ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT, ASN1_R_ERROR_SETTING_CIPHER_PARAMS); EVP_CIPHER_CTX_cleanup(&ctx); goto err; } EVP_CIPHER_CTX_cleanup(&ctx); /* If its RC2 then we'd better setup the key length */ if (alg_nid == NID_rc2_cbc) keylen = EVP_CIPHER_key_length(cipher); /* Setup keyfunc */ X509_ALGOR_free(pbe2->keyfunc); pbe2->keyfunc = pkcs5_scrypt_set(salt, saltlen, keylen, N, r, p); if (pbe2->keyfunc == NULL) goto merr; /* Now set up top level AlgorithmIdentifier */ ret = X509_ALGOR_new(); if (ret == NULL) goto merr; ret->algorithm = OBJ_nid2obj(NID_pbes2); /* Encode PBE2PARAM into parameter */ if (ASN1_TYPE_pack_sequence(ASN1_ITEM_rptr(PBE2PARAM), pbe2, &ret->parameter) == NULL) goto merr; PBE2PARAM_free(pbe2); pbe2 = NULL; return ret; merr: ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT, ERR_R_MALLOC_FAILURE); err: PBE2PARAM_free(pbe2); X509_ALGOR_free(kalg); X509_ALGOR_free(ret); return NULL; }
X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter, unsigned char *salt, int saltlen) { X509_ALGOR *scheme = NULL, *kalg = NULL, *ret = NULL; int alg_nid; EVP_CIPHER_CTX ctx; unsigned char iv[EVP_MAX_IV_LENGTH]; PBKDF2PARAM *kdf = NULL; PBE2PARAM *pbe2 = NULL; ASN1_OCTET_STRING *osalt = NULL; ASN1_OBJECT *obj; alg_nid = EVP_CIPHER_type(cipher); if(alg_nid == NID_undef) { ASN1err(ASN1_F_PKCS5_PBE2_SET, ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER); goto err; } obj = OBJ_nid2obj(alg_nid); if(!(pbe2 = PBE2PARAM_new())) goto merr; /* Setup the AlgorithmIdentifier for the encryption scheme */ scheme = pbe2->encryption; scheme->algorithm = obj; if(!(scheme->parameter = ASN1_TYPE_new())) goto merr; /* Create random IV */ if (RAND_pseudo_bytes(iv, EVP_CIPHER_iv_length(cipher)) < 0) goto err; /* Dummy cipherinit to just setup the IV */ EVP_CipherInit(&ctx, cipher, NULL, iv, 0); if(EVP_CIPHER_param_to_asn1(&ctx, scheme->parameter) < 0) { ASN1err(ASN1_F_PKCS5_PBE2_SET, ASN1_R_ERROR_SETTING_CIPHER_PARAMS); goto err; } EVP_CIPHER_CTX_cleanup(&ctx); if(!(kdf = PBKDF2PARAM_new())) goto merr; if(!(osalt = M_ASN1_OCTET_STRING_new())) goto merr; if (!saltlen) saltlen = PKCS5_SALT_LEN; if (!(osalt->data = OPENSSL_malloc (saltlen))) goto merr; osalt->length = saltlen; if (salt) memcpy (osalt->data, salt, saltlen); else if (RAND_pseudo_bytes (osalt->data, saltlen) < 0) goto merr; if(iter <= 0) iter = PKCS5_DEFAULT_ITER; if(!ASN1_INTEGER_set(kdf->iter, iter)) goto merr; /* Now include salt in kdf structure */ kdf->salt->value.octet_string = osalt; kdf->salt->type = V_ASN1_OCTET_STRING; osalt = NULL; /* If its RC2 then we'd better setup the key length */ if(alg_nid == NID_rc2_cbc) { if(!(kdf->keylength = M_ASN1_INTEGER_new())) goto merr; if(!ASN1_INTEGER_set (kdf->keylength, EVP_CIPHER_key_length(cipher))) goto merr; } /* prf can stay NULL because we are using hmacWithSHA1 */ /* Now setup the PBE2PARAM keyfunc structure */ pbe2->keyfunc->algorithm = OBJ_nid2obj(NID_id_pbkdf2); /* Encode PBKDF2PARAM into parameter of pbe2 */ if(!(pbe2->keyfunc->parameter = ASN1_TYPE_new())) goto merr; if(!ASN1_pack_string(kdf, (i2d_func_t)i2d_PBKDF2PARAM, &pbe2->keyfunc->parameter->value.sequence)) goto merr; pbe2->keyfunc->parameter->type = V_ASN1_SEQUENCE; PBKDF2PARAM_free(kdf); kdf = NULL; /* Now set up top level AlgorithmIdentifier */ if(!(ret = X509_ALGOR_new())) goto merr; if(!(ret->parameter = ASN1_TYPE_new())) goto merr; ret->algorithm = OBJ_nid2obj(NID_pbes2); /* Encode PBE2PARAM into parameter */ if(!ASN1_pack_string(pbe2, (i2d_func_t)i2d_PBE2PARAM, &ret->parameter->value.sequence)) goto merr; ret->parameter->type = V_ASN1_SEQUENCE; PBE2PARAM_free(pbe2); pbe2 = NULL; return ret; merr: ASN1err(ASN1_F_PKCS5_PBE2_SET,ERR_R_MALLOC_FAILURE); err: PBE2PARAM_free(pbe2); /* Note 'scheme' is freed as part of pbe2 */ M_ASN1_OCTET_STRING_free(osalt); PBKDF2PARAM_free(kdf); X509_ALGOR_free(kalg); X509_ALGOR_free(ret); return NULL; }
static int ecdh_cms_encrypt(CMS_RecipientInfo *ri) { EVP_PKEY_CTX *pctx; EVP_PKEY *pkey; EVP_CIPHER_CTX *ctx; int keylen; X509_ALGOR *talg, *wrap_alg = NULL; ASN1_OBJECT *aoid; ASN1_BIT_STRING *pubkey; ASN1_STRING *wrap_str; ASN1_OCTET_STRING *ukm; unsigned char *penc = NULL; int penclen; int rv = 0; int ecdh_nid, kdf_type, kdf_nid, wrap_nid; const EVP_MD *kdf_md; pctx = CMS_RecipientInfo_get0_pkey_ctx(ri); if (!pctx) return 0; /* Get ephemeral key */ pkey = EVP_PKEY_CTX_get0_pkey(pctx); if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &talg, &pubkey, NULL, NULL, NULL)) goto err; X509_ALGOR_get0(&aoid, NULL, NULL, talg); /* Is everything uninitialised? */ if (aoid == OBJ_nid2obj(NID_undef)) { EC_KEY *eckey = pkey->pkey.ec; /* Set the key */ unsigned char *p; penclen = i2o_ECPublicKey(eckey, NULL); if (penclen <= 0) goto err; penc = OPENSSL_malloc(penclen); if (!penc) goto err; p = penc; penclen = i2o_ECPublicKey(eckey, &p); if (penclen <= 0) goto err; ASN1_STRING_set0(pubkey, penc, penclen); pubkey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); pubkey->flags |= ASN1_STRING_FLAG_BITS_LEFT; penc = NULL; X509_ALGOR_set0(talg, OBJ_nid2obj(NID_X9_62_id_ecPublicKey), V_ASN1_UNDEF, NULL); } /* See if custom paraneters set */ kdf_type = EVP_PKEY_CTX_get_ecdh_kdf_type(pctx); if (kdf_type <= 0) goto err; if (!EVP_PKEY_CTX_get_ecdh_kdf_md(pctx, &kdf_md)) goto err; ecdh_nid = EVP_PKEY_CTX_get_ecdh_cofactor_mode(pctx); if (ecdh_nid < 0) goto err; else if (ecdh_nid == 0) ecdh_nid = NID_dh_std_kdf; else if (ecdh_nid == 1) ecdh_nid = NID_dh_cofactor_kdf; if (kdf_type == EVP_PKEY_ECDH_KDF_NONE) { kdf_type = EVP_PKEY_ECDH_KDF_X9_62; if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, kdf_type) <= 0) goto err; } else /* Uknown KDF */ goto err; if (kdf_md == NULL) { /* Fixme later for better MD */ kdf_md = EVP_sha1(); if (EVP_PKEY_CTX_set_ecdh_kdf_md(pctx, kdf_md) <= 0) goto err; } if (!CMS_RecipientInfo_kari_get0_alg(ri, &talg, &ukm)) goto err; /* Lookup NID for KDF+cofactor+digest */ if (!OBJ_find_sigid_by_algs(&kdf_nid, EVP_MD_type(kdf_md), ecdh_nid)) goto err; /* Get wrap NID */ ctx = CMS_RecipientInfo_kari_get0_ctx(ri); wrap_nid = EVP_CIPHER_CTX_type(ctx); keylen = EVP_CIPHER_CTX_key_length(ctx); /* Package wrap algorithm in an AlgorithmIdentifier */ wrap_alg = X509_ALGOR_new(); if (!wrap_alg) goto err; wrap_alg->algorithm = OBJ_nid2obj(wrap_nid); wrap_alg->parameter = ASN1_TYPE_new(); if (!wrap_alg->parameter) goto err; if (EVP_CIPHER_param_to_asn1(ctx, wrap_alg->parameter) <= 0) goto err; if (ASN1_TYPE_get(wrap_alg->parameter) == NID_undef) { ASN1_TYPE_free(wrap_alg->parameter); wrap_alg->parameter = NULL; } if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0) goto err; penclen = CMS_SharedInfo_encode(&penc, wrap_alg, ukm, keylen); if (!penclen) goto err; if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, penc, penclen) <= 0) goto err; penc = NULL; /* * Now need to wrap encoding of wrap AlgorithmIdentifier into parameter * of another AlgorithmIdentifier. */ penclen = i2d_X509_ALGOR(wrap_alg, &penc); if (!penc || !penclen) goto err; wrap_str = ASN1_STRING_new(); if (!wrap_str) goto err; ASN1_STRING_set0(wrap_str, penc, penclen); penc = NULL; X509_ALGOR_set0(talg, OBJ_nid2obj(kdf_nid), V_ASN1_SEQUENCE, wrap_str); rv = 1; err: OPENSSL_free(penc); X509_ALGOR_free(wrap_alg); return rv; }
X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter, unsigned char *salt, int saltlen, unsigned char *aiv, int prf_nid) { X509_ALGOR *scheme = NULL, *kalg = NULL, *ret = NULL; int alg_nid, keylen; EVP_CIPHER_CTX ctx; unsigned char iv[EVP_MAX_IV_LENGTH]; PBE2PARAM *pbe2 = NULL; ASN1_OBJECT *obj; alg_nid = EVP_CIPHER_type(cipher); if (alg_nid == NID_undef) { ASN1err(ASN1_F_PKCS5_PBE2_SET_IV, ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER); goto err; } obj = OBJ_nid2obj(alg_nid); if (!(pbe2 = PBE2PARAM_new())) goto merr; /* Setup the AlgorithmIdentifier for the encryption scheme */ scheme = pbe2->encryption; scheme->algorithm = obj; if (!(scheme->parameter = ASN1_TYPE_new())) goto merr; /* Create random IV */ if (EVP_CIPHER_iv_length(cipher)) { if (aiv) memcpy(iv, aiv, EVP_CIPHER_iv_length(cipher)); else if (RAND_pseudo_bytes(iv, EVP_CIPHER_iv_length(cipher)) < 0) goto err; } EVP_CIPHER_CTX_init(&ctx); /* Dummy cipherinit to just setup the IV, and PRF */ if (!EVP_CipherInit_ex(&ctx, cipher, NULL, NULL, iv, 0)) goto err; if (EVP_CIPHER_param_to_asn1(&ctx, scheme->parameter) < 0) { ASN1err(ASN1_F_PKCS5_PBE2_SET_IV, ASN1_R_ERROR_SETTING_CIPHER_PARAMS); EVP_CIPHER_CTX_cleanup(&ctx); goto err; } /* * If prf NID unspecified see if cipher has a preference. An error is OK * here: just means use default PRF. */ if ((prf_nid == -1) && EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_PBE_PRF_NID, 0, &prf_nid) <= 0) { ERR_clear_error(); prf_nid = NID_hmacWithSHA1; } EVP_CIPHER_CTX_cleanup(&ctx); /* If its RC2 then we'd better setup the key length */ if (alg_nid == NID_rc2_cbc) keylen = EVP_CIPHER_key_length(cipher); else keylen = -1; /* Setup keyfunc */ X509_ALGOR_free(pbe2->keyfunc); pbe2->keyfunc = PKCS5_pbkdf2_set(iter, salt, saltlen, prf_nid, keylen); if (!pbe2->keyfunc) goto merr; /* Now set up top level AlgorithmIdentifier */ if (!(ret = X509_ALGOR_new())) goto merr; if (!(ret->parameter = ASN1_TYPE_new())) goto merr; ret->algorithm = OBJ_nid2obj(NID_pbes2); /* Encode PBE2PARAM into parameter */ if (!ASN1_item_pack(pbe2, ASN1_ITEM_rptr(PBE2PARAM), &ret->parameter->value.sequence)) goto merr; ret->parameter->type = V_ASN1_SEQUENCE; PBE2PARAM_free(pbe2); pbe2 = NULL; return ret; merr: ASN1err(ASN1_F_PKCS5_PBE2_SET_IV, ERR_R_MALLOC_FAILURE); err: PBE2PARAM_free(pbe2); /* Note 'scheme' is freed as part of pbe2 */ X509_ALGOR_free(kalg); X509_ALGOR_free(ret); 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; }
X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter, unsigned char *salt, int saltlen, unsigned char *aiv, int prf_nid) { X509_ALGOR *scheme = NULL, *kalg = NULL, *ret = NULL; int alg_nid; EVP_CIPHER_CTX ctx; unsigned char iv[EVP_MAX_IV_LENGTH]; PBKDF2PARAM *kdf = NULL; PBE2PARAM *pbe2 = NULL; ASN1_OCTET_STRING *osalt = NULL; ASN1_OBJECT *obj; alg_nid = EVP_CIPHER_type(cipher); if(alg_nid == NID_undef) { ASN1err(ASN1_F_PKCS5_PBE2_SET_IV, ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER); goto err; } obj = OBJ_nid2obj(alg_nid); if(!(pbe2 = PBE2PARAM_new())) goto merr; /* Setup the AlgorithmIdentifier for the encryption scheme */ scheme = pbe2->encryption; scheme->algorithm = obj; if(!(scheme->parameter = ASN1_TYPE_new())) goto merr; /* Create random IV */ if (EVP_CIPHER_iv_length(cipher)) { if (aiv) TINYCLR_SSL_MEMCPY(iv, aiv, EVP_CIPHER_iv_length(cipher)); else if (RAND_pseudo_bytes(iv, EVP_CIPHER_iv_length(cipher)) < 0) goto err; } EVP_CIPHER_CTX_init(&ctx); /* Dummy cipherinit to just setup the IV, and PRF */ EVP_CipherInit_ex(&ctx, cipher, NULL, NULL, iv, 0); if(EVP_CIPHER_param_to_asn1(&ctx, scheme->parameter) < 0) { ASN1err(ASN1_F_PKCS5_PBE2_SET_IV, ASN1_R_ERROR_SETTING_CIPHER_PARAMS); EVP_CIPHER_CTX_cleanup(&ctx); goto err; } /* If prf NID unspecified see if cipher has a preference. * An error is OK here: just means use default PRF. */ if ((prf_nid == -1) && EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_PBE_PRF_NID, 0, &prf_nid) <= 0) { ERR_clear_error(); prf_nid = NID_hmacWithSHA1; } EVP_CIPHER_CTX_cleanup(&ctx); if(!(kdf = PBKDF2PARAM_new())) goto merr; if(!(osalt = M_ASN1_OCTET_STRING_new())) goto merr; if (!saltlen) saltlen = PKCS5_SALT_LEN; if (!(osalt->data = (unsigned char*)OPENSSL_malloc (saltlen))) goto merr; //MS: cast to unsigned char* osalt->length = saltlen; if (salt) TINYCLR_SSL_MEMCPY (osalt->data, salt, saltlen); else if (RAND_pseudo_bytes (osalt->data, saltlen) < 0) goto merr; if(iter <= 0) iter = PKCS5_DEFAULT_ITER; if(!ASN1_INTEGER_set(kdf->iter, iter)) goto merr; /* Now include salt in kdf structure */ kdf->salt->value.octet_string = osalt; kdf->salt->type = V_ASN1_OCTET_STRING; osalt = NULL; /* If its RC2 then we'd better setup the key length */ if(alg_nid == NID_rc2_cbc) { if(!(kdf->keylength = M_ASN1_INTEGER_new())) goto merr; if(!ASN1_INTEGER_set (kdf->keylength, EVP_CIPHER_key_length(cipher))) goto merr; } /* prf can stay NULL if we are using hmacWithSHA1 */ if (prf_nid != NID_hmacWithSHA1) { kdf->prf = X509_ALGOR_new(); if (!kdf->prf) goto merr; X509_ALGOR_set0(kdf->prf, OBJ_nid2obj(prf_nid), V_ASN1_NULL, NULL); } /* Now setup the PBE2PARAM keyfunc structure */ pbe2->keyfunc->algorithm = OBJ_nid2obj(NID_id_pbkdf2); /* Encode PBKDF2PARAM into parameter of pbe2 */ if(!(pbe2->keyfunc->parameter = ASN1_TYPE_new())) goto merr; if(!ASN1_item_pack(kdf, ASN1_ITEM_rptr(PBKDF2PARAM), &pbe2->keyfunc->parameter->value.sequence)) goto merr; pbe2->keyfunc->parameter->type = V_ASN1_SEQUENCE; PBKDF2PARAM_free(kdf); kdf = NULL; /* Now set up top level AlgorithmIdentifier */ if(!(ret = X509_ALGOR_new())) goto merr; if(!(ret->parameter = ASN1_TYPE_new())) goto merr; ret->algorithm = OBJ_nid2obj(NID_pbes2); /* Encode PBE2PARAM into parameter */ if(!ASN1_item_pack(pbe2, ASN1_ITEM_rptr(PBE2PARAM), &ret->parameter->value.sequence)) goto merr; ret->parameter->type = V_ASN1_SEQUENCE; PBE2PARAM_free(pbe2); pbe2 = NULL; return ret; merr: ASN1err(ASN1_F_PKCS5_PBE2_SET_IV,ERR_R_MALLOC_FAILURE); err: PBE2PARAM_free(pbe2); /* Note 'scheme' is freed as part of pbe2 */ M_ASN1_OCTET_STRING_free(osalt); PBKDF2PARAM_free(kdf); X509_ALGOR_free(kalg); X509_ALGOR_free(ret); return NULL; }