int privkey_decrypt(struct privkey* pkey, const unsigned char* in, size_t inlen, unsigned char** out, size_t* outlen) { if(!pkey->m_decryptinit) m_privkey_decryptinit(pkey); int ret=0; ret=EVP_PKEY_decrypt(pkey->m_keydata.m_ctx, NULL, outlen, in, inlen); if(ret<=0) { fprintf(stderr, "Failed to get output buffer length\n"); return -1; } else { *out=(unsigned char*)malloc(*outlen); if(!*out) { fprintf(stderr, "Failed to allocate output buffer\n"); return -1; } ret=EVP_PKEY_decrypt(pkey->m_keydata.m_ctx, *out, outlen, in, inlen); if(ret<=0) { fprintf(stderr, "Failed to decrypt\n"); return -1; } } return 0; }
static int pkcs7_decrypt_rinfo(unsigned char **pek, int *peklen, PKCS7_RECIP_INFO *ri, EVP_PKEY *pkey) { EVP_PKEY_CTX *pctx = NULL; unsigned char *ek = NULL; size_t eklen; int ret = -1; pctx = EVP_PKEY_CTX_new(pkey, NULL); if (!pctx) return -1; if (EVP_PKEY_decrypt_init(pctx) <= 0) goto err; if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DECRYPT, EVP_PKEY_CTRL_PKCS7_DECRYPT, 0, ri) <= 0) { PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, PKCS7_R_CTRL_ERROR); goto err; } if (EVP_PKEY_decrypt(pctx, NULL, &eklen, ri->enc_key->data, ri->enc_key->length) <= 0) goto err; ek = OPENSSL_malloc(eklen); if (ek == NULL) { PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, ERR_R_MALLOC_FAILURE); goto err; } if (EVP_PKEY_decrypt(pctx, ek, &eklen, ri->enc_key->data, ri->enc_key->length) <= 0) { ret = 0; PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, ERR_R_EVP_LIB); goto err; } ret = 1; if (*pek) { OPENSSL_cleanse(*pek, *peklen); OPENSSL_free(*pek); } *pek = ek; *peklen = eklen; err: if (pctx) EVP_PKEY_CTX_free(pctx); if (!ret && ek) OPENSSL_free(ek); return ret; }
static int do_keyop(EVP_PKEY_CTX * ctx, int pkey_op, unsigned char *out, size_t * poutlen, unsigned char *in, size_t inlen) { int rv = 0; switch (pkey_op) { case EVP_PKEY_OP_VERIFYRECOVER: rv = EVP_PKEY_verify_recover(ctx, out, poutlen, in, inlen); break; case EVP_PKEY_OP_SIGN: rv = EVP_PKEY_sign(ctx, out, poutlen, in, inlen); break; case EVP_PKEY_OP_ENCRYPT: rv = EVP_PKEY_encrypt(ctx, out, poutlen, in, inlen); break; case EVP_PKEY_OP_DECRYPT: rv = EVP_PKEY_decrypt(ctx, out, poutlen, in, inlen); break; case EVP_PKEY_OP_DERIVE: rv = EVP_PKEY_derive(ctx, out, poutlen); break; } return rv; }
/* 7.3.32 */ int SAF_ImportEncedKey( void *hSymmKeyObj, unsigned char *pucSymmKey, unsigned int uiSymmKeyLen, void **phKeyHandle) { SAF_KEY *hkey = NULL; SAF_SYMMKEYOBJ *hobj = (SAF_SYMMKEYOBJ *)hSymmKeyObj; EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *pctx = NULL; char key_id[1024]; /* snprintf(key_id, sizeof(key_id), "%s.enc", hobj->pucContainerName); */ if (!(pkey = ENGINE_load_private_key(hobj->app->engine, key_id, NULL, NULL)) || !(pctx = EVP_PKEY_CTX_new(pkey, hobj->app->engine)) || EVP_PKEY_decrypt_init(pctx) <= 0 || EVP_PKEY_decrypt(pctx, hkey->key, &hkey->keylen, pucSymmKey, uiSymmKeyLen) <= 0) { goto end; } end: return 0; }
int EVP_PKEY_decrypt_old(unsigned char *out, const unsigned char *in, int inlen, EVP_PKEY *pkey) { int ret = 0; EVP_PKEY_CTX *ctx = NULL; size_t outlen; if (pkey->type == EVP_PKEY_RSA) { return ossl_EVP_PKEY_decrypt_old(out, in, inlen, pkey); } if (!(ctx = EVP_PKEY_CTX_new(pkey, NULL))) { return 0; } if (!EVP_PKEY_decrypt_init(ctx)) { goto end; } if (!EVP_PKEY_decrypt(ctx, out, &outlen, in, inlen)) { goto end; } ret = (int)outlen; end: EVP_PKEY_CTX_free(ctx); return ret; }
static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri) { CMS_KeyTransRecipientInfo *ktri = ri->d.ktri; unsigned char *ek = NULL; int eklen; int ret = 0; CMS_EncryptedContentInfo *ec; ec = cms->d.envelopedData->encryptedContentInfo; if (ktri->pkey == NULL) { CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_NO_PRIVATE_KEY); return 0; } eklen = EVP_PKEY_size(ktri->pkey); ek = OPENSSL_malloc(eklen); if (ek == NULL) { CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, ERR_R_MALLOC_FAILURE); goto err; } eklen = EVP_PKEY_decrypt(ek, ktri->encryptedKey->data, ktri->encryptedKey->length, ktri->pkey); if (eklen <= 0) { CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_CMS_LIB); goto err; } ret = 1; if (ec->key) { OPENSSL_cleanse(ec->key, ec->keylen); OPENSSL_free(ec->key); } ec->key = ek; ec->keylen = eklen; err: if (!ret && ek) OPENSSL_free(ek); return ret; }
static LUA_FUNCTION(openssl_pkey_decrypt) { size_t dlen = 0; EVP_PKEY *pkey = CHECK_OBJECT(1, EVP_PKEY, "openssl.evp_pkey"); const char *data = luaL_checklstring(L, 2, &dlen); int padding = auxiliar_checkoption(L, 3, "pkcs1", sPadding, iPadding); size_t clen = EVP_PKEY_size(pkey); EVP_PKEY_CTX *ctx = NULL; int ret = 0; if (pkey->type != EVP_PKEY_RSA && pkey->type != EVP_PKEY_RSA2) { luaL_argerror(L, 2, "EVP_PKEY must be of type RSA or RSA2"); return ret; } if (openssl_pkey_is_private(pkey)) { ctx = EVP_PKEY_CTX_new(pkey, pkey->engine); if (EVP_PKEY_decrypt_init(ctx) == 1) { if (EVP_PKEY_CTX_set_rsa_padding(ctx, padding) == 1) { byte* buf = malloc(clen); if (EVP_PKEY_decrypt(ctx, buf, &clen, (const unsigned char*)data, dlen) == 1) { lua_pushlstring(L, (const char*)buf, clen); ret = 1; } else ret = openssl_pushresult(L, 0); free(buf); } else ret = openssl_pushresult(L, 0); } else ret = openssl_pushresult(L, 0); EVP_PKEY_CTX_free(ctx); } else { luaL_argerror(L, 2, "EVP_PKEY must be private key"); } return ret; }
EXPORT_C int EVP_OpenInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, const unsigned char *ek, int ekl, const unsigned char *iv, EVP_PKEY *priv) { unsigned char *key=NULL; int i,size=0,ret=0; if(type) { EVP_CIPHER_CTX_init(ctx); if(!EVP_DecryptInit_ex(ctx,type,NULL, NULL,NULL)) return 0; } if(!priv) return 1; if (priv->type != EVP_PKEY_RSA) { EVPerr(EVP_F_EVP_OPENINIT,EVP_R_PUBLIC_KEY_NOT_RSA); goto err; } size=RSA_size(priv->pkey.rsa); key=(unsigned char *)OPENSSL_malloc(size+2); if (key == NULL) { /* ERROR */ EVPerr(EVP_F_EVP_OPENINIT,ERR_R_MALLOC_FAILURE); goto err; } i=EVP_PKEY_decrypt(key,ek,ekl,priv); if ((i <= 0) || !EVP_CIPHER_CTX_set_key_length(ctx, i)) { /* ERROR */ goto err; } if(!EVP_DecryptInit_ex(ctx,NULL,NULL,key,iv)) goto err; ret=1; err: if (key != NULL) OPENSSL_cleanse(key,size); OPENSSL_free(key); return(ret); }
CK_RV PKCS11_Encryption_OpenSSL::DecryptUpdate(Cryptoki_Session_Context* pSessionCtx, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) { OPENSSL_HEADER(); OpenSSLEncryptData *pDec; if(pSessionCtx == NULL || pSessionCtx->DecryptionCtx == NULL) return CKR_SESSION_CLOSED; pDec = (OpenSSLEncryptData*)pSessionCtx->DecryptionCtx; if(pDec->IsSymmetric) { int outLen = *pulPartLen; OPENSSL_CHECKRESULT(EVP_DecryptUpdate((EVP_CIPHER_CTX*)pDec->Key->ctx, pPart, &outLen, pEncryptedPart, ulEncryptedPartLen)); *pulPartLen = outLen; } else { size_t outLen = *pulPartLen; OPENSSL_CHECKRESULT(EVP_PKEY_decrypt((EVP_PKEY_CTX*)pDec->Key->ctx, pPart, &outLen, pEncryptedPart, ulEncryptedPartLen)); *pulPartLen = outLen; } OPENSSL_CLEANUP(); if(retVal != CKR_OK) { TINYCLR_SSL_FREE(pDec); pSessionCtx->DecryptionCtx = NULL; } OPENSSL_RETURN(); }
int main() { int ret = -1; int verbose = 0; BIO *out = NULL; int id = EVP_PKEY_SM2; const EVP_MD *md = EVP_sm3(); ENGINE *engine = NULL; EVP_PKEY_CTX *pkctx = NULL; EVP_PKEY *pkey = NULL; EVP_MD_CTX *mdctx = NULL; EVP_CIPHER_CTX *cpctx = NULL; unsigned char dgst[EVP_MAX_MD_SIZE] = "hello world"; size_t dgstlen = 32; unsigned char sig[256]; size_t siglen = sizeof(sig); unsigned char msg[] = "hello world this is the message"; size_t msglen = sizeof(msg); unsigned char cbuf[512]; size_t cbuflen = sizeof(cbuf); unsigned char mbuf[512]; size_t mbuflen = sizeof(mbuf); int len; unsigned int ulen; ERR_load_crypto_strings(); out = BIO_new_fp(stdout, BIO_NOCLOSE); if (!(pkctx = EVP_PKEY_CTX_new_id(id, engine))) { fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__); goto end; } if (!EVP_PKEY_keygen_init(pkctx)) { fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__); goto end; } if (!EVP_PKEY_keygen(pkctx, &pkey)) { fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__); goto end; } EVP_PKEY_CTX_free(pkctx); if (0) { EVP_PKEY_print_public(out, pkey, 4, NULL); BIO_printf(out, "\n"); EVP_PKEY_print_private(out, pkey, 4, NULL); BIO_printf(out, "\n"); } if (!(pkctx = EVP_PKEY_CTX_new(pkey, engine))) { fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__); goto end; } /* EVP_PKEY_sign() */ if (!EVP_PKEY_sign_init(pkctx)) { fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__); goto end; } bzero(sig, sizeof(sig)); siglen = sizeof(sig); dgstlen = 32; if (!EVP_PKEY_sign(pkctx, sig, &siglen, dgst, dgstlen)) { fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__); goto end; } if (verbose) { size_t i; printf("signature (%zu bytes) = ", siglen); for (i = 0; i < siglen; i++) { printf("%02X", sig[i]); } printf("\n"); } if (!EVP_PKEY_verify_init(pkctx)) { fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__); goto end; } if (EVP_PKEY_verify(pkctx, sig, siglen, dgst, dgstlen) != SM2_VERIFY_SUCCESS) { fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__); goto end; } if (verbose) { printf("signature verification success!\n"); } /* EVP_PKEY_encrypt() */ if (!EVP_PKEY_encrypt_init(pkctx)) { fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__); goto end; } cbuflen = sizeof(cbuf); if (!EVP_PKEY_encrypt(pkctx, cbuf, &cbuflen, msg, msglen)) { fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__); goto end; } if (verbose) { size_t i; printf("ciphertext (%zu bytes) = ", cbuflen); for (i = 0; i < cbuflen; i++) { printf("%02X", cbuf[i]); } printf("\n"); } if (!EVP_PKEY_decrypt_init(pkctx)) { fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__); goto end; } bzero(mbuf, sizeof(mbuf)); mbuflen = sizeof(mbuf); if (!EVP_PKEY_decrypt(pkctx, mbuf, &mbuflen, cbuf, cbuflen)) { fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__); goto end; } if (verbose) { printf("original message = %s\n", msg); printf("decrypted message = %s\n", mbuf); } /* EVP_PKEY_encrypt_old */ if ((len = EVP_PKEY_encrypt_old(cbuf, msg, (int)msglen, pkey)) <= 0) { fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__); goto end; } if (verbose) { int i; printf("ciphertext (%d bytes) = ", len); for (i = 0; i < len; i++) { printf("%02X", cbuf[i]); } printf("\n"); } bzero(mbuf, sizeof(mbuf)); if ((len = EVP_PKEY_decrypt_old(mbuf, cbuf, len, pkey)) <= 0) { fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__); goto end; } if (verbose) { printf("original message = %s\n", msg); printf("decrypted message = %s\n", mbuf); } if (!(mdctx = EVP_MD_CTX_create())) { fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__); goto end; } /* EVP_SignInit_ex/Update/Final_ex */ if (!EVP_SignInit_ex(mdctx, EVP_sm3(), engine)) { fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__); goto end; } if (!EVP_SignUpdate(mdctx, msg, msglen)) { fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__); goto end; } if (!EVP_SignFinal(mdctx, sig, &ulen, pkey)) { fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__); goto end; } siglen = ulen; if (verbose) { size_t i; printf("signature (%zu bytes) = ", siglen); for (i = 0; i < siglen; i++) { printf("%02X", sig[i]); } printf("\n"); } if (!EVP_VerifyInit_ex(mdctx, EVP_sm3(), engine)) { fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__); goto end; } if (!EVP_VerifyUpdate(mdctx, msg, msglen)) { fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__); goto end; } if (EVP_VerifyFinal(mdctx, sig, ulen, pkey) != SM2_VERIFY_SUCCESS) { fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__); goto end; } /* EVP_DigestSignInit/Update/Final() */ // FIXME: return values might be different, not just 1 or 0 if (!EVP_DigestSignInit(mdctx, &pkctx, md, engine, pkey)) { fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__); goto end; } if (!EVP_DigestSignUpdate(mdctx, msg, msglen)) { fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__); goto end; } siglen = sizeof(sig); if (!EVP_DigestSignFinal(mdctx, sig, &siglen)) { fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__); goto end; } pkctx = NULL; if (!EVP_DigestVerifyInit(mdctx, &pkctx, md, engine, pkey)) { ERR_print_errors_fp(stderr); fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__); goto end; } if (!EVP_DigestVerifyUpdate(mdctx, msg, msglen)) { fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__); goto end; } if (!EVP_DigestVerifyFinal(mdctx, sig, siglen)) { fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__); goto end; } /* EVP_SealInit/Update/Final() EVP_OpenInit/Update/Final() */ /* EVP_PKEY *pk[NUM_PKEYS] = {0}; unsigned char iv[16]; unsigned char ek[NUM_PKEYS][256]; int eklen[NUM_PKEYS]; RAND_pseudo_bytes(iv, sizeof(iv)); int i; for (i = 0; i < NUM_PKEYS; i++) { } if (!(cpctx = EVP_CIPHER_CTX_new())) { goto end; } if (!EVP_SealInit(cpctx, cipher, ek, &ekl, iv, pubk, npubk)) { goto end; } if (!EVP_SealUpdate(cpctx, msg, msglen)) { goto end; } if (!EVP_SealFinal(cpctx, cbuf, (int *)&cbuflen)) { goto end; } */ printf("test success!\n"); ret = 1; end: ERR_print_errors_fp(stderr); 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; 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 int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri) { CMS_KeyTransRecipientInfo *ktri = ri->d.ktri; EVP_PKEY_CTX *pctx = NULL; unsigned char *ek = NULL; size_t eklen; int ret = 0; CMS_EncryptedContentInfo *ec; ec = cms->d.envelopedData->encryptedContentInfo; if (ktri->pkey == NULL) { CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_NO_PRIVATE_KEY); return 0; } pctx = EVP_PKEY_CTX_new(ktri->pkey, NULL); if (!pctx) return 0; if (EVP_PKEY_decrypt_init(pctx) <= 0) goto err; if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DECRYPT, EVP_PKEY_CTRL_CMS_DECRYPT, 0, ri) <= 0) { CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_CTRL_ERROR); goto err; } if (EVP_PKEY_decrypt(pctx, NULL, &eklen, ktri->encryptedKey->data, ktri->encryptedKey->length) <= 0) goto err; ek = OPENSSL_malloc(eklen); if (ek == NULL) { CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, ERR_R_MALLOC_FAILURE); goto err; } if (EVP_PKEY_decrypt(pctx, ek, &eklen, ktri->encryptedKey->data, ktri->encryptedKey->length) <= 0) { CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_CMS_LIB); goto err; } ret = 1; if (ec->key) { OPENSSL_cleanse(ec->key, ec->keylen); OPENSSL_free(ec->key); } ec->key = ek; ec->keylen = eklen; err: if (pctx) EVP_PKEY_CTX_free(pctx); if (!ret && ek) OPENSSL_free(ek); return ret; }
static bool alg_wrap_unw(const jose_hook_alg_t *alg, jose_cfg_t *cfg, const json_t *jwe, const json_t *rcp, const json_t *jwk, json_t *cek) { openssl_auto(EVP_PKEY_CTX) *epc = NULL; openssl_auto(EVP_PKEY) *key = NULL; const uint8_t *tt = NULL; const EVP_MD *md = NULL; uint8_t *ct = NULL; uint8_t *pt = NULL; uint8_t *rt = NULL; bool ret = false; size_t ctl = 0; size_t ptl = 0; size_t rtl = 0; size_t ttl = 0; int pad = 0; switch (str2enum(alg->name, NAMES, NULL)) { case 0: pad = RSA_PKCS1_PADDING; md = EVP_sha1(); break; case 1: pad = RSA_PKCS1_OAEP_PADDING; md = EVP_sha1(); break; case 2: pad = RSA_PKCS1_OAEP_PADDING; md = EVP_sha256(); break; default: return false; } key = jose_openssl_jwk_to_EVP_PKEY(cfg, jwk); if (!key || EVP_PKEY_base_id(key) != EVP_PKEY_RSA) goto egress; ctl = jose_b64_dec(json_object_get(rcp, "encrypted_key"), NULL, 0); if (ctl == SIZE_MAX) goto egress; ct = malloc(ctl); if (!ct) goto egress; if (jose_b64_dec(json_object_get(rcp, "encrypted_key"), ct, ctl) != ctl) goto egress; ptl = ctl; pt = malloc(ptl); if (!pt) goto egress; epc = EVP_PKEY_CTX_new(key, NULL); if (!epc) goto egress; if (EVP_PKEY_decrypt_init(epc) <= 0) goto egress; if (EVP_PKEY_CTX_set_rsa_padding(epc, pad) <= 0) goto egress; if (pad == RSA_PKCS1_OAEP_PADDING) { if (EVP_PKEY_CTX_set_rsa_oaep_md(epc, md) <= 0) return false; if (EVP_PKEY_CTX_set_rsa_mgf1_md(epc, md) <= 0) goto egress; } /* Handle MMA Attack as prescribed by RFC 3218, always generate a * random buffer of appropriate length so that the same operations * are performed whether decrypt succeeds or not, in an attempt to * foil timing attacks */ rtl = ptl; rt = malloc(rtl); if (!rt) goto egress; if (RAND_bytes(rt, rtl) <= 0) goto egress; ret |= EVP_PKEY_decrypt(epc, pt, &ptl, ct, ctl) > 0; ttl = ret ? ptl : rtl; tt = ret ? pt : rt; ret |= pad == RSA_PKCS1_PADDING; if (json_object_set_new(cek, "k", jose_b64_enc(tt, ttl)) < 0) ret = false; egress: if (pt) { OPENSSL_cleanse(pt, ptl); free(pt); } if (rt) { OPENSSL_cleanse(rt, rtl); free(rt); } free(ct); return ret; }
static int test_EVP_SM2(void) { int ret = 0; EVP_PKEY *pkey = NULL; EVP_PKEY *params = NULL; EVP_PKEY_CTX *pctx = NULL; EVP_PKEY_CTX *kctx = NULL; EVP_PKEY_CTX *sctx = NULL; size_t sig_len = 0; unsigned char *sig = NULL; EVP_MD_CTX *md_ctx = NULL; EVP_MD_CTX *md_ctx_verify = NULL; EVP_PKEY_CTX *cctx = NULL; uint8_t ciphertext[128]; size_t ctext_len = sizeof(ciphertext); uint8_t plaintext[8]; size_t ptext_len = sizeof(plaintext); uint8_t sm2_id[] = {1, 2, 3, 4, 'l', 'e', 't', 't', 'e', 'r'}; pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); if (!TEST_ptr(pctx)) goto done; if (!TEST_true(EVP_PKEY_paramgen_init(pctx) == 1)) goto done; if (!TEST_true(EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, NID_sm2))) goto done; if (!TEST_true(EVP_PKEY_paramgen(pctx, ¶ms))) goto done; kctx = EVP_PKEY_CTX_new(params, NULL); if (!TEST_ptr(kctx)) goto done; if (!TEST_true(EVP_PKEY_keygen_init(kctx))) goto done; if (!TEST_true(EVP_PKEY_keygen(kctx, &pkey))) goto done; if (!TEST_true(EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2))) goto done; if (!TEST_ptr(md_ctx = EVP_MD_CTX_new())) goto done; if (!TEST_ptr(md_ctx_verify = EVP_MD_CTX_new())) goto done; if (!TEST_ptr(sctx = EVP_PKEY_CTX_new(pkey, NULL))) goto done; EVP_MD_CTX_set_pkey_ctx(md_ctx, sctx); EVP_MD_CTX_set_pkey_ctx(md_ctx_verify, sctx); if (!TEST_int_gt(EVP_PKEY_CTX_set1_id(sctx, sm2_id, sizeof(sm2_id)), 0)) goto done; if (!TEST_true(EVP_DigestSignInit(md_ctx, NULL, EVP_sm3(), NULL, pkey))) goto done; if(!TEST_true(EVP_DigestSignUpdate(md_ctx, kMsg, sizeof(kMsg)))) goto done; /* Determine the size of the signature. */ if (!TEST_true(EVP_DigestSignFinal(md_ctx, NULL, &sig_len))) goto done; if (!TEST_size_t_eq(sig_len, (size_t)EVP_PKEY_size(pkey))) goto done; if (!TEST_ptr(sig = OPENSSL_malloc(sig_len))) goto done; if (!TEST_true(EVP_DigestSignFinal(md_ctx, sig, &sig_len))) goto done; /* Ensure that the signature round-trips. */ if (!TEST_true(EVP_DigestVerifyInit(md_ctx_verify, NULL, EVP_sm3(), NULL, pkey))) goto done; if (!TEST_true(EVP_DigestVerifyUpdate(md_ctx_verify, kMsg, sizeof(kMsg)))) goto done; if (!TEST_true(EVP_DigestVerifyFinal(md_ctx_verify, sig, sig_len))) goto done; /* now check encryption/decryption */ if (!TEST_ptr(cctx = EVP_PKEY_CTX_new(pkey, NULL))) goto done; if (!TEST_true(EVP_PKEY_encrypt_init(cctx))) goto done; if (!TEST_true(EVP_PKEY_encrypt(cctx, ciphertext, &ctext_len, kMsg, sizeof(kMsg)))) goto done; if (!TEST_true(EVP_PKEY_decrypt_init(cctx))) goto done; if (!TEST_true(EVP_PKEY_decrypt(cctx, plaintext, &ptext_len, ciphertext, ctext_len))) goto done; if (!TEST_true(ptext_len == sizeof(kMsg))) goto done; if (!TEST_true(memcmp(plaintext, kMsg, sizeof(kMsg)) == 0)) goto done; ret = 1; done: EVP_PKEY_CTX_free(pctx); EVP_PKEY_CTX_free(kctx); EVP_PKEY_CTX_free(sctx); EVP_PKEY_CTX_free(cctx); EVP_PKEY_free(pkey); EVP_PKEY_free(params); EVP_MD_CTX_free(md_ctx); EVP_MD_CTX_free(md_ctx_verify); OPENSSL_free(sig); 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); }
U8_EXPORT ssize_t u8_cryptic (int do_encrypt,const char *cname, const unsigned char *key,int keylen, const unsigned char *iv,int ivlen, u8_block_reader reader,u8_block_writer writer, void *readstate,void *writestate, u8_context caller) { if (strncasecmp(cname,"rsa",3)==0) { ENGINE *eng=ENGINE_get_default_RSA(); EVP_PKEY _pkey, *pkey; EVP_PKEY_CTX *ctx; int pubkeyin=(strncasecmp(cname,"rsapub",6)==0); const unsigned char *scankey=key; struct U8_BYTEBUF bb; int retval=-1; if (pubkeyin) pkey=d2i_PUBKEY(NULL,&scankey,keylen); else pkey=d2i_PrivateKey((EVP_PKEY_RSA),NULL,&scankey,keylen); if (!(pkey)) ctx=NULL; else { #if (OPENSSL_VERSION_NUMBER>=0x1000204fL) ctx=EVP_PKEY_CTX_new(pkey,eng); #else ctx=EVP_PKEY_CTX_new(pkey,NULL); #endif } if (ctx) { memset(&bb,0,sizeof(bb)); bb.u8_direction=u8_output_buffer; bb.u8_buf=bb.u8_ptr=(u8_byte *)u8_malloc(1024); bb.u8_lim=(u8_byte *)(bb.u8_buf+1024); bb.u8_growbuf=1; fill_bytebuf(&bb,reader,readstate);} if (!(ctx)) {} else if ((pubkeyin)? ((do_encrypt)?((retval=EVP_PKEY_encrypt_init(ctx))<0): ((retval=EVP_PKEY_verify_recover_init(ctx))<0)): ((do_encrypt)?((retval=EVP_PKEY_sign_init(ctx))<0): ((retval=EVP_PKEY_decrypt_init(ctx))<0))) {} else { unsigned char *in=bb.u8_buf; size_t inlen=bb.u8_ptr-bb.u8_buf; unsigned char *out=NULL; size_t outlen; if (pubkeyin) { if (do_encrypt) retval=EVP_PKEY_encrypt(ctx,NULL,&outlen,in,inlen); else retval=EVP_PKEY_verify_recover(ctx,NULL,&outlen,in,inlen);} else if (do_encrypt) retval=EVP_PKEY_sign(ctx,NULL,&outlen,in,inlen); else retval=EVP_PKEY_decrypt(ctx,NULL,&outlen,in,inlen); if (retval<0) {} else if ((out=u8_malloc(outlen))==NULL) {} else if (pubkeyin) { if (do_encrypt) retval=EVP_PKEY_encrypt(ctx,out,&outlen,in,inlen); else retval=EVP_PKEY_verify_recover(ctx,out,&outlen,in,inlen);} else if (do_encrypt) retval=EVP_PKEY_sign(ctx,out,&outlen,in,inlen); else retval=EVP_PKEY_decrypt(ctx,out,&outlen,in,inlen); if (retval<0) {} else retval=writer(out,outlen,writestate); if (out) u8_free(out);} u8_free(bb.u8_buf); if (retval<0) { unsigned long err=ERR_get_error(); char buf[512]; buf[0]='\0'; ERR_error_string_n(err,buf,512); u8_seterr(u8_InternalCryptoError,OPENSSL_CRYPTIC,u8_fromlibc((char *)buf)); ERR_clear_error();} if (ctx) EVP_PKEY_CTX_free(ctx); if (pkey) EVP_PKEY_free(pkey); return retval;} else { EVP_CIPHER_CTX ctx; int inlen, outlen, retval=0; ssize_t totalout=0, totalin=0; unsigned char inbuf[1024], outbuf[1024+EVP_MAX_BLOCK_LENGTH]; const EVP_CIPHER *cipher=((cname)?(EVP_get_cipherbyname(cname)): (EVP_aes_128_cbc())); if (cipher) { int needkeylen=EVP_CIPHER_key_length(cipher); int needivlen=EVP_CIPHER_iv_length(cipher); int blocksize=EVP_CIPHER_block_size(cipher); if (blocksize>1024) blocksize=1024; u8_log(CRYPTO_LOGLEVEL,OPENSSL_CRYPTIC, " %s cipher=%s, keylen=%d/%d, ivlen=%d/%d, blocksize=%d\n", ((do_encrypt)?("encrypt"):("decrypt")), cname,keylen,needkeylen,ivlen,needivlen,blocksize); if ((needivlen)&&(ivlen)&&(ivlen!=needivlen)) return u8_reterr(u8_BadCryptoIV, ((caller)?(caller):(OPENSSL_CRYPTIC)), u8_mkstring("%d!=%d(%s)",ivlen,needivlen,cname)); memset(&ctx,0,sizeof(ctx)); EVP_CIPHER_CTX_init(&ctx); retval=EVP_CipherInit(&ctx, cipher, NULL, NULL, do_encrypt); if (retval==0) return u8_reterr(u8_CipherInit_Failed, ((caller)?(caller):(OPENSSL_CRYPTIC)), u8_strdup(cname)); retval=EVP_CIPHER_CTX_set_key_length(&ctx,keylen); if (retval==0) return u8_reterr(u8_BadCryptoKey, ((caller)?(caller):(OPENSSL_CRYPTIC)), u8_mkstring("%d!=%d(%s)",keylen,needkeylen,cname)); if ((needivlen)&&(ivlen!=needivlen)) return u8_reterr(u8_BadCryptoIV, ((caller)?(caller):(OPENSSL_CRYPTIC)), u8_mkstring("%d!=%d(%s)",ivlen,needivlen,cname)); retval=EVP_CipherInit(&ctx, cipher, key, iv, do_encrypt); if (retval==0) return u8_reterr(u8_CipherInit_Failed, ((caller)?(caller):(OPENSSL_CRYPTIC)), u8_strdup(cname)); while (1) { inlen = reader(inbuf,blocksize,readstate); if (inlen <= 0) { u8_log(CRYPTO_LOGLEVEL,OPENSSL_CRYPTIC, "Finished %s(%s) with %ld in, %ld out", ((do_encrypt)?("encrypt"):("decrypt")), cname,totalin,totalout); break;} else totalin=totalin+inlen; if (!(EVP_CipherUpdate(&ctx,outbuf,&outlen,inbuf,inlen))) { char *details=u8_malloc(256); unsigned long err=ERR_get_error(); ERR_error_string_n(err,details,256); EVP_CIPHER_CTX_cleanup(&ctx); return u8_reterr(u8_InternalCryptoError, ((caller)?(caller):((u8_context)"u8_cryptic")), details);} else { u8_log(CRYPTO_LOGLEVEL,OPENSSL_CRYPTIC, "%s(%s) consumed %d/%ld bytes, emitted %d/%ld bytes" " in=<%v>\n out=<%v>", ((do_encrypt)?("encrypt"):("decrypt")),cname, inlen,totalin,outlen,totalout+outlen, inbuf,inlen,outbuf,outlen); writer(outbuf,outlen,writestate); totalout=totalout+outlen;}} if (!(EVP_CipherFinal(&ctx,outbuf,&outlen))) { char *details=u8_malloc(256); unsigned long err=ERR_get_error(); ERR_error_string_n(err,details,256); EVP_CIPHER_CTX_cleanup(&ctx); return u8_reterr(u8_InternalCryptoError, ((caller)?(caller):(OPENSSL_CRYPTIC)), details);} else { writer(outbuf,outlen,writestate); u8_log(CRYPTO_LOGLEVEL,OPENSSL_CRYPTIC, "%s(%s) done after consuming %ld/%ld bytes, emitting %ld/%ld bytes" "\n final out=<%v>", ((do_encrypt)?("encrypt"):("decrypt")),cname, inlen,totalin,outlen,totalout+outlen, outbuf,outlen); EVP_CIPHER_CTX_cleanup(&ctx); totalout=totalout+outlen; return totalout;}} else { char *details=u8_malloc(256); unsigned long err=ERR_get_error(); ERR_error_string_n(err,details,256); return u8_reterr("Unknown cipher", ((caller)?(caller):((u8_context)"u8_cryptic")), details);} } }
soter_status_t soter_asym_cipher_decrypt(soter_asym_cipher_t* asym_cipher, const void* cipher_data, size_t cipher_data_length, void* plain_data, size_t* plain_data_length) { EVP_PKEY *pkey; RSA *rsa; int rsa_mod_size; size_t output_length; if ((!asym_cipher) || (!cipher_data) || (0 == cipher_data_length) || (!plain_data_length)) { return SOTER_INVALID_PARAMETER; } pkey = EVP_PKEY_CTX_get0_pkey(asym_cipher->pkey_ctx); if (!pkey) { return SOTER_INVALID_PARAMETER; } if (EVP_PKEY_RSA != EVP_PKEY_id(pkey)) { /* We can only do assymetric encryption with RSA algorithm */ return SOTER_INVALID_PARAMETER; } rsa = EVP_PKEY_get0(pkey); if (NULL == rsa) { return SOTER_FAIL; } rsa_mod_size = RSA_size(rsa); if (cipher_data_length < rsa_mod_size) { /* The cipherdata is too small for this key size */ return SOTER_INVALID_PARAMETER; } /* Currently we support only OAEP padding for RSA encryption */ /* TODO: should we support "no padding" or PKCS1.5 padding? */ if (!EVP_PKEY_decrypt_init(asym_cipher->pkey_ctx)) { return SOTER_FAIL; } /* TODO: This function automatically sets SHA1 as MGF digest for OAEP padding. Should we change it to SHA256? */ if (1 > EVP_PKEY_CTX_ctrl(asym_cipher->pkey_ctx, -1, -1, EVP_PKEY_CTRL_RSA_PADDING, RSA_PKCS1_OAEP_PADDING, NULL)) { return SOTER_FAIL; } /* We will check the size of the output buffer first */ if (EVP_PKEY_decrypt(asym_cipher->pkey_ctx, NULL, &output_length, (const unsigned char *)cipher_data, cipher_data_length)) { if (output_length > *plain_data_length) { *plain_data_length = output_length; return SOTER_BUFFER_TOO_SMALL; } } else { return SOTER_FAIL; } if (EVP_PKEY_decrypt(asym_cipher->pkey_ctx, (unsigned char *)plain_data, plain_data_length, (const unsigned char *)cipher_data, cipher_data_length)) { if (plain_data) { return SOTER_SUCCESS; } else { return SOTER_BUFFER_TOO_SMALL; } } else { return SOTER_FAIL; } }