/* int max_len: for returned value */ int ASN1_TYPE_get_int_octetstring(ASN1_TYPE *a, long *num, unsigned char *data, int max_len) { int ret = -1, n; ASN1_INTEGER *ai = NULL; ASN1_OCTET_STRING *os = NULL; const unsigned char *p; long length; ASN1_const_CTX c; if ((a->type != V_ASN1_SEQUENCE) || (a->value.sequence == NULL)) { goto err; } p = M_ASN1_STRING_data(a->value.sequence); length = M_ASN1_STRING_length(a->value.sequence); c.pp = &p; c.p = p; c.max = p + length; c.error = ASN1_R_DATA_IS_WRONG; M_ASN1_D2I_start_sequence(); c.q = c.p; if ((ai = d2i_ASN1_INTEGER(NULL, &c.p, c.slen)) == NULL) goto err; c.slen -= (c.p - c.q); c.q = c.p; if ((os = d2i_ASN1_OCTET_STRING(NULL, &c.p, c.slen)) == NULL) goto err; c.slen -= (c.p - c.q); if (!M_ASN1_D2I_end_sequence()) goto err; if (num != NULL) *num = ASN1_INTEGER_get(ai); ret = M_ASN1_STRING_length(os); if (max_len > ret) n = ret; else n = max_len; if (data != NULL) memcpy(data, M_ASN1_STRING_data(os), n); if (0) { err: ASN1err(ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING, ASN1_R_DATA_IS_WRONG); } if (os != NULL) M_ASN1_OCTET_STRING_free(os); if (ai != NULL) M_ASN1_INTEGER_free(ai); return (ret); }
int CPK_PUBLIC_PARAMS_digest(CPK_PUBLIC_PARAMS *params, const EVP_MD *md, unsigned char *dgst, unsigned int *dgstlen) { if (!EVP_Digest(M_ASN1_STRING_data(params->public_factors), M_ASN1_STRING_length(params->public_factors), dgst, dgstlen, md, NULL)) { return 0; } return 1; }
int CPK_MASTER_SECRET_digest(CPK_MASTER_SECRET *master, const EVP_MD *md, unsigned char *dgst, unsigned int *dgstlen) { if (!EVP_Digest(M_ASN1_STRING_data(master->secret_factors), M_ASN1_STRING_length(master->secret_factors), dgst, dgstlen, md, NULL)) { return 0; } return 1; }
/* int max_len: for returned value */ int ASN1_TYPE_get_octetstring(ASN1_TYPE *a, unsigned char *data, int max_len) { int ret, num; unsigned char *p; if ((a->type != V_ASN1_OCTET_STRING) || (a->value.octet_string == NULL)) { ASN1err(ASN1_F_ASN1_TYPE_GET_OCTETSTRING, ASN1_R_DATA_IS_WRONG); return (-1); } p = M_ASN1_STRING_data(a->value.octet_string); ret = M_ASN1_STRING_length(a->value.octet_string); if (ret < max_len) num = ret; else num = max_len; sgx_memcpy(data, p, num); return (ret); }
// generate an LLSD from a certificate name (issuer or subject name). // the name will be strings indexed by the 'long form' LLSD cert_name_from_X509_NAME(X509_NAME* name) { LLSD result = LLSD::emptyMap(); int name_entries = X509_NAME_entry_count(name); for (int entry_index=0; entry_index < name_entries; entry_index++) { char buffer[32]; X509_NAME_ENTRY *entry = X509_NAME_get_entry(name, entry_index); std::string name_value = std::string((const char*)M_ASN1_STRING_data(X509_NAME_ENTRY_get_data(entry)), M_ASN1_STRING_length(X509_NAME_ENTRY_get_data(entry))); ASN1_OBJECT* name_obj = X509_NAME_ENTRY_get_object(entry); OBJ_obj2txt(buffer, sizeof(buffer), name_obj, 0); std::string obj_buffer_str = std::string(buffer); result[obj_buffer_str] = name_value; } return result; }
/* int */ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) { int i,j; BIO *out=NULL,*btmp=NULL,*etmp=NULL,*bio=NULL; unsigned char *tmp=NULL; X509_ALGOR *xa; ASN1_OCTET_STRING *data_body=NULL; const EVP_MD *evp_md; const EVP_CIPHER *evp_cipher=NULL; EVP_CIPHER_CTX *evp_ctx=NULL; X509_ALGOR *enc_alg=NULL; STACK_OF(X509_ALGOR) *md_sk=NULL; STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL; X509_ALGOR *xalg=NULL; PKCS7_RECIP_INFO *ri=NULL; i=OBJ_obj2nid(p7->type); p7->state=PKCS7_S_HEADER; switch (i) { case NID_pkcs7_signed: data_body=PKCS7_get_octet_string(p7->d.sign->contents); md_sk=p7->d.sign->md_algs; break; case NID_pkcs7_signedAndEnveloped: rsk=p7->d.signed_and_enveloped->recipientinfo; md_sk=p7->d.signed_and_enveloped->md_algs; data_body=p7->d.signed_and_enveloped->enc_data->enc_data; enc_alg=p7->d.signed_and_enveloped->enc_data->algorithm; evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm); if (evp_cipher == NULL) { PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE); goto err; } xalg=p7->d.signed_and_enveloped->enc_data->algorithm; break; case NID_pkcs7_enveloped: rsk=p7->d.enveloped->recipientinfo; enc_alg=p7->d.enveloped->enc_data->algorithm; data_body=p7->d.enveloped->enc_data->enc_data; evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm); if (evp_cipher == NULL) { PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE); goto err; } xalg=p7->d.enveloped->enc_data->algorithm; break; default: PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CONTENT_TYPE); goto err; } /* We will be checking the signature */ if (md_sk != NULL) { for (i=0; i<sk_X509_ALGOR_num(md_sk); i++) { xa=sk_X509_ALGOR_value(md_sk,i); if ((btmp=BIO_new(BIO_f_md())) == NULL) { PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB); goto err; } j=OBJ_obj2nid(xa->algorithm); evp_md=EVP_get_digestbynid(j); if (evp_md == NULL) { PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNKNOWN_DIGEST_TYPE); goto err; } BIO_set_md(btmp,evp_md); if (out == NULL) out=btmp; else BIO_push(out,btmp); btmp=NULL; } } if (evp_cipher != NULL) { #if 0 unsigned char key[EVP_MAX_KEY_LENGTH]; unsigned char iv[EVP_MAX_IV_LENGTH]; unsigned char *p; int keylen,ivlen; int max; X509_OBJECT ret; #endif int jj; if ((etmp=BIO_new(BIO_f_cipher())) == NULL) { PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB); goto err; } /* It was encrypted, we need to decrypt the secret key * with the private key */ /* Find the recipientInfo which matches the passed certificate * (if any) */ if (pcert) { for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) { ri=sk_PKCS7_RECIP_INFO_value(rsk,i); if (!pkcs7_cmp_ri(ri, pcert)) break; ri=NULL; } if (ri == NULL) { PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE); goto err; } } jj=EVP_PKEY_size(pkey); tmp=(unsigned char *)OPENSSL_malloc(jj+10); if (tmp == NULL) { PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_MALLOC_FAILURE); goto err; } /* If we haven't got a certificate try each ri in turn */ if (pcert == NULL) { for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) { ri=sk_PKCS7_RECIP_INFO_value(rsk,i); jj=EVP_PKEY_decrypt(tmp, M_ASN1_STRING_data(ri->enc_key), M_ASN1_STRING_length(ri->enc_key), pkey); if (jj > 0) break; ERR_clear_error(); ri = NULL; } if (ri == NULL) { PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_RECIPIENT_MATCHES_KEY); goto err; } } else { jj=EVP_PKEY_decrypt(tmp, M_ASN1_STRING_data(ri->enc_key), M_ASN1_STRING_length(ri->enc_key), pkey); if (jj <= 0) { PKCS7err(PKCS7_F_PKCS7_DATADECODE, ERR_R_EVP_LIB); goto err; } } evp_ctx=NULL; BIO_get_cipher_ctx(etmp,&evp_ctx); if (EVP_CipherInit_ex(evp_ctx,evp_cipher,NULL,NULL,NULL,0) <= 0) goto err; if (EVP_CIPHER_asn1_to_param(evp_ctx,enc_alg->parameter) < 0) goto err; if (jj != EVP_CIPHER_CTX_key_length(evp_ctx)) { /* Some S/MIME clients don't use the same key * and effective key length. The key length is * determined by the size of the decrypted RSA key. */ if(!EVP_CIPHER_CTX_set_key_length(evp_ctx, jj)) { PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH); goto err; } } if (EVP_CipherInit_ex(evp_ctx,NULL,NULL,tmp,NULL,0) <= 0) goto err; OPENSSL_cleanse(tmp,jj); if (out == NULL) out=etmp; else BIO_push(out,etmp); etmp=NULL; } #if 1 if (PKCS7_is_detached(p7) || (in_bio != NULL)) { bio=in_bio; } else { #if 0 bio=BIO_new(BIO_s_mem()); /* We need to set this so that when we have read all * the data, the encrypt BIO, if present, will read * EOF and encode the last few bytes */ BIO_set_mem_eof_return(bio,0); if (data_body->length > 0) BIO_write(bio,(char *)data_body->data,data_body->length); #else if (data_body->length > 0) bio = BIO_new_mem_buf(data_body->data,data_body->length); else { bio=BIO_new(BIO_s_mem()); BIO_set_mem_eof_return(bio,0); } #endif } BIO_push(out,bio); bio=NULL; #endif if (0) { err: if (out != NULL) BIO_free_all(out); if (btmp != NULL) BIO_free_all(btmp); if (etmp != NULL) BIO_free_all(etmp); if (bio != NULL) BIO_free_all(bio); out=NULL; } if (tmp != NULL) OPENSSL_free(tmp); return(out); }
static EC_KEY *extract_ec_pub_key(CPK_PUBLIC_PARAMS *param, const char *id) { int e = 1; EC_KEY *ec_key = NULL; const EC_GROUP *ec_group; EC_POINT *pub_key = NULL; EC_POINT *pt = NULL; BIGNUM *order = BN_new(); BIGNUM *bn = BN_new(); BN_CTX *ctx = BN_CTX_new(); int *index = NULL; int i, bn_size, pt_size, num_indexes, num_factors; if (!(ec_key = X509_ALGOR_get1_EC_KEY(param->pkey_algor))) { goto err; } ec_group = EC_KEY_get0_group(ec_key); if (!(pub_key = EC_POINT_new(ec_group))) { goto err; } if (!(pt = EC_POINT_new(ec_group))) { goto err; } if (!EC_GROUP_get_order(ec_group, order, ctx)) { goto err; } bn_size = BN_num_bytes(order); pt_size = bn_size + 1; if ((num_factors = CPK_MAP_num_factors(param->map_algor)) <= 0) { goto err; } if (M_ASN1_STRING_length(param->public_factors) != pt_size * num_factors) { goto err; } if ((num_indexes = CPK_MAP_num_indexes(param->map_algor)) <= 0) { goto err; } if (!(index = OPENSSL_malloc(sizeof(int) * num_indexes))) { goto err; } if (!CPK_MAP_str2index(param->map_algor, id, index)) { goto err; } if (!EC_POINT_set_to_infinity(ec_group, pub_key)) { goto err; } for (i = 0; i < num_indexes; i++) { const unsigned char *p = M_ASN1_STRING_data(param->public_factors) + pt_size * index[i]; if (!EC_POINT_oct2point(ec_group, pt, p, pt_size, ctx)) { goto err; } if (!EC_POINT_add(ec_group, pub_key, pub_key, pt, ctx)) { goto err; } } if (!EC_KEY_set_public_key(ec_key, pub_key)) { goto err; } e = 0; err: if (e && ec_key) { EC_KEY_free(ec_key); ec_key = NULL; } if (pub_key) EC_POINT_free(pub_key); if (order) BN_free(order); if (bn) BN_free(bn); if (ctx) BN_CTX_free(ctx); if (index) OPENSSL_free(index); return ec_key; }
static int extract_ec_params(CPK_MASTER_SECRET *master, CPK_PUBLIC_PARAMS *param) { int ret = 0; EC_KEY *ec_key = NULL; const EC_GROUP *ec_group; BIGNUM *bn = BN_new(); BIGNUM *order = BN_new(); BN_CTX *ctx = BN_CTX_new(); EC_POINT *pt = NULL; int i, bn_size, pt_size, num_factors; const unsigned char *bn_ptr; unsigned char *pt_ptr; if (!bn || !order || !ctx) { goto err; } if (!(ec_key = X509_ALGOR_get1_EC_KEY(master->pkey_algor))) { goto err; } ec_group = EC_KEY_get0_group(ec_key); if (!(EC_GROUP_get_order(ec_group, order, ctx))) { goto err; } bn_size = BN_num_bytes(order); pt_size = bn_size + 1; if ((num_factors = CPK_MAP_num_factors(master->map_algor)) <= 0) { goto err; } if (M_ASN1_STRING_length(master->secret_factors) != bn_size * num_factors) { goto err; } if (!ASN1_STRING_set(param->public_factors, NULL, pt_size * num_factors)) { goto err; } bn_ptr = M_ASN1_STRING_data(master->secret_factors); pt_ptr = M_ASN1_STRING_data(param->public_factors); memset(pt_ptr, 0, M_ASN1_STRING_length(param->public_factors)); if (!(pt = EC_POINT_new(ec_group))) { goto err; } for (i = 0; i < num_factors; i++) { if (!BN_bin2bn(bn_ptr, bn_size, bn)) { goto err; } if (BN_is_zero(bn) || BN_cmp(bn, order) >= 0) { goto err; } if (!EC_POINT_mul(ec_group, pt, bn, NULL, NULL, ctx)) { goto err; } if (!EC_POINT_point2oct(ec_group, pt, POINT_CONVERSION_COMPRESSED, pt_ptr, pt_size, ctx)) { goto err; } bn_ptr += bn_size; pt_ptr += pt_size; } ret = 1; err: if (ec_key) EC_KEY_free(ec_key); if (bn) BN_free(bn); if (order) BN_free(order); if (ctx) BN_CTX_free(ctx); if (pt) EC_POINT_free(pt); return ret; }
CPK_MASTER_SECRET *CPK_MASTER_SECRET_create(const char *domain_id, EVP_PKEY *pkey, X509_ALGOR *map_algor) { int e = 1; CPK_MASTER_SECRET *master = NULL; BIGNUM *bn = NULL, *order = NULL; X509_PUBKEY *pubkey = NULL; int pkey_type; int i, bn_size, num_factors; unsigned char *bn_ptr; if (strlen(domain_id) <= 0 || strlen(domain_id) > CPK_MAX_ID_LENGTH) { CPKerr(CPK_F_CPK_MASTER_SECRET_CREATE, CPK_R_INVALID_ID_LENGTH); goto err; } pkey_type = EVP_PKEY_id(pkey); if (pkey_type == EVP_PKEY_DSA) { if (!(order = ((DSA *)EVP_PKEY_get0(pkey))->q)) { CPKerr(CPK_F_CPK_MASTER_SECRET_CREATE, CPK_R_BAD_ARGUMENT); goto err; } } else if (pkey_type == EVP_PKEY_EC) { const EC_GROUP *ec_group; if (!(order = BN_new())) { CPKerr(CPK_F_CPK_MASTER_SECRET_CREATE, ERR_R_MALLOC_FAILURE); goto err; } ec_group = EC_KEY_get0_group((EC_KEY *)EVP_PKEY_get0(pkey)); if (!EC_GROUP_get_order(ec_group, order, NULL)) { CPKerr(CPK_F_CPK_MASTER_SECRET_CREATE, ERR_R_X509_LIB); goto err; } //FIXME OPENSSL_assert assert(EC_KEY_get0_public_key((EC_KEY *)EVP_PKEY_get0(pkey)) != NULL); } else { CPKerr(CPK_F_CPK_MASTER_SECRET_CREATE, CPK_R_INVALID_PKEY_TYPE); goto err; } if (!(master = CPK_MASTER_SECRET_new())) { CPKerr(CPK_F_CPK_MASTER_SECRET_CREATE, ERR_R_MALLOC_FAILURE); goto err; } master->version = 1; if (!X509_NAME_add_entry_by_NID(master->id, NID_organizationName, MBSTRING_UTF8, (unsigned char *)domain_id, -1, -1, 0)) { CPKerr(CPK_F_CPK_MASTER_SECRET_CREATE, ERR_R_X509_LIB); goto err; } /* * convert EVP_PKEY to X509_ALGOR through X509_PUBKEY_set * X509_ALGOR_set0() is another choice but require more code */ // FIXME: X509_PUBKEY require pkey has a public key if (!X509_PUBKEY_set(&pubkey, pkey)) { CPKerr(CPK_F_CPK_MASTER_SECRET_CREATE, ERR_R_X509_LIB); goto err; } X509_ALGOR_free(master->pkey_algor); if (!(master->pkey_algor = X509_ALGOR_dup(pubkey->algor))) { CPKerr(CPK_F_CPK_MASTER_SECRET_CREATE, ERR_R_X509_LIB); goto err; } //FIXME: check the validity of CPK_MAP X509_ALGOR_free(master->map_algor); if (!(master->map_algor = X509_ALGOR_dup(map_algor))) { CPKerr(CPK_F_CPK_MASTER_SECRET_CREATE, ERR_R_MALLOC_FAILURE); goto err; } if ((num_factors = CPK_MAP_num_factors(map_algor)) <= 0) { CPKerr(CPK_F_CPK_MASTER_SECRET_CREATE, CPK_R_INVALID_MAP_ALGOR); goto err; } /* * create secret factors, for both DSA and EC, * the private keys are both big integers, */ bn_size = BN_num_bytes(order); if (!ASN1_STRING_set(master->secret_factors, NULL, bn_size * num_factors)) { CPKerr(CPK_F_CPK_MASTER_SECRET_CREATE, ERR_R_ASN1_LIB); goto err; } bn_ptr = M_ASN1_STRING_data(master->secret_factors); memset(bn_ptr, 0, M_ASN1_STRING_length(master->secret_factors)); if (!(bn = BN_new())) { CPKerr(CPK_F_CPK_MASTER_SECRET_CREATE, ERR_R_MALLOC_FAILURE); goto err; } for (i = 0; i < num_factors; i++) { do { if (!BN_rand_range(bn, order)) { CPKerr(CPK_F_CPK_MASTER_SECRET_CREATE, ERR_R_RAND_LIB); goto err; } } while (BN_is_zero(bn)); if (!BN_bn2bin(bn, bn_ptr + bn_size - BN_num_bytes(bn))) { CPKerr(CPK_F_CPK_MASTER_SECRET_CREATE, ERR_R_BN_LIB); goto err; } bn_ptr += bn_size; } e = 0; err: if (e && master) { CPK_MASTER_SECRET_free(master); master = NULL; } if (pubkey) X509_PUBKEY_free(pubkey); if (order && pkey_type == EVP_PKEY_EC) BN_free(order); if (bn) BN_free(bn); return master; }
static int extract_dsa_params(CPK_MASTER_SECRET *master, CPK_PUBLIC_PARAMS *param) { int ret = 0; DSA *dsa = NULL; BIGNUM *pri = BN_new(); BIGNUM *pub = BN_new(); BN_CTX *ctx = BN_CTX_new(); int i, pri_size, pub_size, num_factors; const unsigned char *pri_ptr; unsigned char *pub_ptr; if (!pri || !pub || !ctx) { goto err; } if (!(dsa = (DSA *)X509_ALGOR_get1_DSA(master->pkey_algor))) { goto err; } pri_size = BN_num_bytes(dsa->q); pub_size = BN_num_bytes(dsa->p); if ((num_factors = CPK_MAP_num_factors(master->map_algor)) <= 0) { goto err; } if (M_ASN1_STRING_length(master->secret_factors) != pri_size * num_factors) { goto err; } ASN1_STRING_free(param->public_factors); if (!ASN1_STRING_set(param->public_factors, NULL, pub_size * num_factors)) { goto err; } pri_ptr = M_ASN1_STRING_data(master->secret_factors); pub_ptr = M_ASN1_STRING_data(param->public_factors); memset(pub_ptr, 0, M_ASN1_STRING_length(param->public_factors)); for (i = 0; i < num_factors; i++) { if (!BN_bin2bn(pri_ptr, pri_size, pri)) { goto err; } if (BN_is_zero(pri) || BN_cmp(pri, dsa->q) >= 0) { goto err; } if (!BN_mod_exp(pub, dsa->g, pri, dsa->p, ctx)) { goto err; } if (!BN_bn2bin(pub, pub_ptr + pub_size - BN_num_bytes(pub))) { goto err; } pri_ptr += pri_size; pub_ptr += pub_size; } ret = 1; err: if (dsa) DSA_free(dsa); if (pri) BN_free(pri); if (pub) BN_free(pub); if (ctx) BN_CTX_free(ctx); return ret; }
/* int */ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) { int i,j; BIO *out=NULL,*btmp=NULL,*etmp=NULL,*bio=NULL; unsigned char *tmp=NULL; X509_ALGOR *xa; ASN1_OCTET_STRING *data_body=NULL; const EVP_MD *evp_md; const EVP_CIPHER *evp_cipher=NULL; EVP_CIPHER_CTX *evp_ctx=NULL; X509_ALGOR *enc_alg=NULL; STACK_OF(X509_ALGOR) *md_sk=NULL; STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL; PKCS7_RECIP_INFO *ri=NULL; if (p7 == NULL) { PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_INVALID_NULL_POINTER); return NULL; } if (p7->d.ptr == NULL) { PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_CONTENT); return NULL; } i=OBJ_obj2nid(p7->type); p7->state=PKCS7_S_HEADER; switch (i) { case NID_pkcs7_signed: /* * p7->d.sign->contents is a PKCS7 structure consisting of a contentType * field and optional content. * data_body is NULL if that structure has no (=detached) content * or if the contentType is wrong (i.e., not "data"). */ data_body=PKCS7_get_octet_string(p7->d.sign->contents); md_sk=p7->d.sign->md_algs; break; case NID_pkcs7_signedAndEnveloped: rsk=p7->d.signed_and_enveloped->recipientinfo; md_sk=p7->d.signed_and_enveloped->md_algs; /* data_body is NULL if the optional EncryptedContent is missing. */ data_body=p7->d.signed_and_enveloped->enc_data->enc_data; enc_alg=p7->d.signed_and_enveloped->enc_data->algorithm; evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm); if (evp_cipher == NULL) { PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE); goto err; } break; case NID_pkcs7_enveloped: rsk=p7->d.enveloped->recipientinfo; enc_alg=p7->d.enveloped->enc_data->algorithm; /* data_body is NULL if the optional EncryptedContent is missing. */ data_body=p7->d.enveloped->enc_data->enc_data; evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm); if (evp_cipher == NULL) { PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE); goto err; } break; default: PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CONTENT_TYPE); goto err; } /* Detached content must be supplied via in_bio instead. */ if (data_body == NULL && in_bio == NULL) { PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_CONTENT); goto err; } /* We will be checking the signature */ if (md_sk != NULL) { for (i=0; i<sk_X509_ALGOR_num(md_sk); i++) { xa=sk_X509_ALGOR_value(md_sk,i); if ((btmp=BIO_new(BIO_f_md())) == NULL) { PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB); goto err; } j=OBJ_obj2nid(xa->algorithm); evp_md=EVP_get_digestbynid(j); if (evp_md == NULL) { PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNKNOWN_DIGEST_TYPE); goto err; } BIO_set_md(btmp,evp_md); if (out == NULL) out=btmp; else BIO_push(out,btmp); btmp=NULL; } } if (evp_cipher != NULL) { #if 0 unsigned char key[EVP_MAX_KEY_LENGTH]; unsigned char iv[EVP_MAX_IV_LENGTH]; unsigned char *p; int keylen,ivlen; int max; X509_OBJECT ret; #endif unsigned char *tkey = NULL; int tkeylen; int jj; if ((etmp=BIO_new(BIO_f_cipher())) == NULL) { PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB); goto err; } /* It was encrypted, we need to decrypt the secret key * with the private key */ /* Find the recipientInfo which matches the passed certificate * (if any) */ if (pcert) { for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) { ri=sk_PKCS7_RECIP_INFO_value(rsk,i); if (!pkcs7_cmp_ri(ri, pcert)) break; ri=NULL; } if (ri == NULL) { PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE); goto err; } } jj=EVP_PKEY_size(pkey); tmp=(unsigned char *)OPENSSL_malloc(jj+10); if (tmp == NULL) { PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_MALLOC_FAILURE); goto err; } /* If we haven't got a certificate try each ri in turn */ if (pcert == NULL) { /* Temporary storage in case EVP_PKEY_decrypt * overwrites output buffer on error. */ unsigned char *tmp2; tmp2 = OPENSSL_malloc(jj); if (!tmp2) goto err; jj = -1; /* Always attempt to decrypt all cases to avoid * leaking timing information about a successful * decrypt. */ for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) { int tret; ri=sk_PKCS7_RECIP_INFO_value(rsk,i); tret=EVP_PKEY_decrypt(tmp2, M_ASN1_STRING_data(ri->enc_key), M_ASN1_STRING_length(ri->enc_key), pkey); if (tret > 0) { memcpy(tmp, tmp2, tret); OPENSSL_cleanse(tmp2, tret); jj = tret; } ERR_clear_error(); } OPENSSL_free(tmp2); } else { jj=EVP_PKEY_decrypt(tmp, M_ASN1_STRING_data(ri->enc_key), M_ASN1_STRING_length(ri->enc_key), pkey); ERR_clear_error(); } evp_ctx=NULL; BIO_get_cipher_ctx(etmp,&evp_ctx); if (EVP_CipherInit_ex(evp_ctx,evp_cipher,NULL,NULL,NULL,0) <= 0) goto err; if (EVP_CIPHER_asn1_to_param(evp_ctx,enc_alg->parameter) < 0) goto err; /* Generate random key to counter MMA */ tkeylen = EVP_CIPHER_CTX_key_length(evp_ctx); tkey = OPENSSL_malloc(tkeylen); if (!tkey) goto err; if (EVP_CIPHER_CTX_rand_key(evp_ctx, tkey) <= 0) goto err; /* If we have no key use random key */ if (jj <= 0) { OPENSSL_free(tmp); jj = tkeylen; tmp = tkey; tkey = NULL; } if (jj != tkeylen) { /* Some S/MIME clients don't use the same key * and effective key length. The key length is * determined by the size of the decrypted RSA key. */ if(!EVP_CIPHER_CTX_set_key_length(evp_ctx, jj)) { /* As MMA defence use random key instead */ OPENSSL_cleanse(tmp, jj); OPENSSL_free(tmp); jj = tkeylen; tmp = tkey; tkey = NULL; } } ERR_clear_error(); if (EVP_CipherInit_ex(evp_ctx,NULL,NULL,tmp,NULL,0) <= 0) goto err; OPENSSL_cleanse(tmp,jj); if (tkey) { OPENSSL_cleanse(tkey, tkeylen); OPENSSL_free(tkey); } if (out == NULL) out=etmp; else BIO_push(out,etmp); etmp=NULL; } #if 1 if (in_bio != NULL) { bio=in_bio; } else { #if 0 bio=BIO_new(BIO_s_mem()); /* We need to set this so that when we have read all * the data, the encrypt BIO, if present, will read * EOF and encode the last few bytes */ BIO_set_mem_eof_return(bio,0); if (data_body->length > 0) BIO_write(bio,(char *)data_body->data,data_body->length); #else if (data_body->length > 0) bio = BIO_new_mem_buf(data_body->data,data_body->length); else { bio=BIO_new(BIO_s_mem()); BIO_set_mem_eof_return(bio,0); } if (bio == NULL) goto err; #endif } BIO_push(out,bio); bio=NULL; #endif if (0) { err: if (out != NULL) BIO_free_all(out); if (btmp != NULL) BIO_free_all(btmp); if (etmp != NULL) BIO_free_all(etmp); if (bio != NULL) BIO_free_all(bio); out=NULL; } if (tmp != NULL) OPENSSL_free(tmp); return(out); }