Hi, crypto guys! I have problem with EVP_PKEY_decrypt() function and 4K RSA private key decrypting data encrypted with EVP_PKEY_encrypt() and corresponding public key. Keys generated using openssl CA shell script.
EVP_PKEY_decrypt() just returns -2 saying that this key is not supported. BUT! RSA_private_decrypt() works just fine with this key and successfully decrypts data encrypted by EVP_PKEY_encrypt()! Sign and verify operations works fine with EVP_PKEY_sign() and EVP_PKEY_verify() with the same keys. I use openssl 1.0.1c. The questions are: 1. Is there some meaningful limitation coded into EVP_PKEY_decrypt() that does not allow decrypt operation? 2. If no such limitations, how I can make it work with 4K RSA keys? Functions sources below. -------------------- EVP_PKEY *extract_pub_key(char *pem_key, size_t key_len) { BIO *bio; X509 *x509 = NULL; EVP_PKEY *pkey; //char *passwd=""; //pem_password_cb *key_passwd_func = &read_pvt_key_pass; bio = BIO_new_mem_buf(pem_key, key_len); if (!PEM_read_bio_X509(bio, &x509, NULL, NULL)) { //error return NULL; } else { //process X.509 pkey = X509_extract_key(x509); } X509_free(x509); BIO_free_all(bio); return pkey; } EVP_PKEY *extract_pvt_key(char *pem_key, size_t key_len) { EVP_PKEY *pkey = NULL; BIO *bio; char *passwd = "\0"; pem_password_cb *key_passwd_func = &read_pvt_key_pass; //put key into BIO for PEM reading functions bio = BIO_new_mem_buf(pem_key, key_len); pkey = PEM_read_bio_PrivateKey(bio, &pkey, key_passwd_func, (void*) passwd); BIO_free_all(bio); return pkey; } int encrypt_with_pubk(int handle, char *pem_key, size_t key_len, unsigned char *plain, int plain_len, unsigned char *encoded, int *encoded_len) { EVP_PKEY *pub_key; EVP_PKEY_CTX *ctx; size_t outlen; int res; pub_key = extract_pub_key(pem_key, key_len); if (pub_key == NULL) { crypto_set_err(handle); return -1; } ctx = EVP_PKEY_CTX_new(pub_key, NULL); if (!ctx) { crypto_set_err(handle); res = -1; } else if ( EVP_PKEY_encrypt_init(ctx) <= 0 || EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <=0){ crypto_set_err(handle); res = -1; } else if (EVP_PKEY_encrypt(ctx, NULL, &outlen, plain, plain_len) <= 0) { /* Determine buffer length */ crypto_set_err(handle); res = -1; } else if (outlen>*encoded_len) { crypto_set_err(handle); res = -2; } else if (EVP_PKEY_encrypt(ctx, encoded, &outlen, plain, plain_len) <= 0) { crypto_set_err(handle); res = -1; } else { res = outlen; } *encoded_len = res; EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(pub_key); return res; } /* OLD, works fine with new EVP_encrypt() */ int decrypt_with_pvtk(int handle, char *pem_key, size_t key_len, unsigned char *plain, int * plain_len, unsigned char *encoded, int encoded_len) { EVP_PKEY *pvt_key; int len; int rsa_key_len; int n_pieces; int i, idx; pvt_key = extract_pvt_key(pem_key, key_len); if (pvt_key == NULL) { crypto_set_err(handle); return -1; } rsa_key_len = RSA_size(pvt_key->pkey.rsa); //we have blocks of this size in encrypted text n_pieces = encoded_len / rsa_key_len; if((encoded_len % rsa_key_len)!=0) n_pieces++; if ((encoded_len % rsa_key_len) != 0) { return -2; //we must have n rsa_key_len pieces } len = 0; for (i = 0; i < n_pieces; i++) { idx = i*rsa_key_len; len = len + RSA_private_decrypt(rsa_key_len, (unsigned char *) &(encoded[idx]), &plain[len], pvt_key->pkey.rsa, RSA_PKCS1_PADDING); } EVP_PKEY_free(pvt_key); *plain_len=len; return len; } /* NEW. ATTENTION! This function does not work because EVP_PKEY_decrypt() returns -2 meaning "operation not supported for this keytype", though Key is RSA 4K and "old" function above works with new EVP_PLEY_encrypt(). */ int decrypt_with_pvtk(int handle, char *pem_key, size_t key_len, unsigned char *plain, int * plain_len, unsigned char *encoded, int encoded_len) { EVP_PKEY *pvt_key; EVP_PKEY_CTX *ctx; int outlen; int res; pvt_key = extract_pvt_key(pem_key, key_len); if (pvt_key == NULL) { crypto_set_err(handle); return -1; } ctx = EVP_PKEY_CTX_new(pvt_key, NULL); if (!ctx) { crypto_set_err(handle); return -1; } else if (EVP_PKEY_decrypt_init(ctx) <= 0) { crypto_set_err(handle); res = -1; } else if (EVP_PKEY_decrypt(ctx, NULL, (size_t *) & outlen, encoded, encoded_len) <= 0) { // Determine buffer length crypto_set_err(handle); res = -1; } else if (outlen>*plain_len) { crypto_set_err(handle); res = -2; } else if ((res=EVP_PKEY_decrypt(ctx, plain, (size_t *) & outlen, encoded, encoded_len)) <= 0) { crypto_set_err(handle); res = -1; } else { res = outlen; } *plain_len = res; EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(pvt_key); return res; } -- SY, Alex Lukin RIPE NIC HDL: LEXA1-RIPE ______________________________________________________________________ OpenSSL Project http://www.openssl.org User Support Mailing List openssl-users@openssl.org Automated List Manager majord...@openssl.org