int /* return size of data, -1 on failure */ decrypt(X509* x509, EVP_PKEY* pkey, const char* enc_entity, char** data_out) { char* p; char buf[4096]; int i,n; BIO* wbio = NULL; BIO* p7bio = NULL; PKCS7 *p7 = NULL; if (data_out) *data_out = NULL; if (!x509 || !pkey || !enc_entity || !data_out) GOTO_ERR("NULL arg(s)"); LOG_PRINT("decrypt: get_pkcs7_from_pem"); if (!(p7 = get_pkcs7_from_pem(enc_entity))) goto err; /* Decrypt the symmetric key with private key and obtain symmetric * cipher stream (BIO). The cert is needed here to look up one of * possibly multiple recipient infos present in PKCS7 object. Issuer * and serial number must match (these two fields form unique ID for * cert). Actual public key part of the X509 cert is not used for * anything here. */ LOG_PRINT("decrypt: dataDecode"); if (!(p7bio=PKCS7_dataDecode(p7,pkey,NULL/*detached*/,x509))) GOTO_ERR("12 no recipient matches cert or private key could not decrypt, i.e. wrong key (PKCS7_dataDecode)"); LOG_PRINT("decrypt: ready to pump"); /* Pump data from p7bio to decrypt symmetric cipher */ if (!(wbio = BIO_new(BIO_s_mem()))) GOTO_ERR("no memory?"); for (;;) { if ((i=BIO_read(p7bio,buf,sizeof(buf))) <= 0) break; BIO_write(wbio,buf,i); } BIO_flush(wbio); BIO_free_all(p7bio); p7bio = NULL; PKCS7_free(p7); p7 = NULL; LOG_PRINT("decrypt: pump done"); /* Return data (this should now be easier because we just freed * some memory) */ n = get_written_BIO_data(wbio, data_out); BIO_free_all(wbio); return n; err: if (p7) PKCS7_free(p7); if (wbio) BIO_free_all(wbio); if (p7bio) BIO_free_all(p7bio); return -1; }
PKI_MEM *PKI_X509_PKCS7_decode ( PKI_X509_PKCS7 *p7, PKI_X509_KEYPAIR *k, PKI_X509_CERT *x ) { BIO *bio = NULL; PKI_MEM *mem = NULL; PKI_ID type = 0; PKI_X509_CERT_VALUE *x_val = NULL; PKI_X509_KEYPAIR_VALUE *pkey = NULL; if ( !p7 || !p7->value || !k || !k->value ) { PKI_log_debug("PKI_X509_PKCS7_decode()::Missing p7 or pkey!"); return ( NULL ); }; pkey = k->value; type = PKI_X509_PKCS7_get_type ( p7 ); switch ( type ) { case PKI_X509_PKCS7_TYPE_ENCRYPTED: case PKI_X509_PKCS7_TYPE_SIGNEDANDENCRYPTED: break; default: PKI_log_debug("PKI_X509_PKCS7_decode()::Wrong MSG type!"); return PKI_ERR; } if ( x ) x_val = x->value; if((bio = PKCS7_dataDecode(p7->value, pkey, NULL, x_val)) == NULL) { PKI_log_debug ( "PKI_X509_PKCS7_decode()::Decrypt error [%s]", ERR_error_string(ERR_get_error(), NULL )); return ( NULL ); } if((mem = PKI_MEM_new_bio( (PKI_IO *) bio, NULL )) == NULL ) { PKI_log_debug("PKI_X509_PKCS7_decode()::Memory Error!"); if( bio ) BIO_free_all ( bio ); return ( NULL ); } if (bio ) BIO_free_all ( bio ); return ( mem ); }