static int get_key(uint8_t key[KEYSIZE]) { EVP_PKEY *privkey, *pubkey; X509 *cert; uint8_t cryptedkey[KEYSIZE], plainkey[KEYSIZE]; SSL_library_init(); ERR_load_crypto_strings(); privkey = load_privkey("keys/server.key"); if (privkey==NULL) { perror("load_privkey()"); exit(1); } cert = load_x509("keys/server.crt"); if (cert==NULL) { perror("load_x509()"); exit(1); } pubkey = EVP_PKEY_IN_X509(cert); if (pubkey == NULL) { ERR_print_errors_fp(stderr); exit(1); } rand_sharedkey(key); if (RSA_public_encrypt(KEYSIZE, key, cryptedkey, RSA_IN_EVP_PKEY(pubkey), RSA_NO_PADDING)<0) { ERR_print_errors_fp(stderr); exit(1); } if (RSA_private_decrypt(KEYSIZE, cryptedkey, plainkey, RSA_IN_EVP_PKEY(privkey), RSA_NO_PADDING)<0) { ERR_print_errors_fp(stderr); exit(1); } if (memcmp(key, plainkey, SHAREDKEY_BYTESIZE)==0) { puts("RSA_public_encrypt/RSA_private_decrypt OK."); } else { puts("RSA_public_encrypt/RSA_private_decrypt FAILed."); } return 0; }
unsigned char *rsa_decrypt(unsigned char *ciphertext, int *len) { EVP_CIPHER_CTX ctx; EVP_CIPHER_CTX_init(&ctx); EVP_PKEY *pkey; unsigned char *encrypted_key; unsigned int encrypted_key_length; uint32_t eklen_n; unsigned char iv[EVP_MAX_IV_LENGTH]; pkey = load_privkey("private.pem"); encrypted_key = malloc(EVP_PKEY_size(pkey)); // plaintext will always be equal to or lesser than length of ciphertext int plaintext_len = *len; // the length of ciphertest is at most plaintext + ciphers block size. int ciphertext_len = plaintext_len + EVP_CIPHER_block_size(EVP_des_ede_cbc()); unsigned char *plaintext = (unsigned char *)malloc(ciphertext_len); /* First need to fetch the encrypted key length, encrypted key and IV */ int pos = 0; memcpy(&eklen_n, ciphertext + pos, sizeof(eklen_n)); pos += sizeof(eklen_n); encrypted_key_length = ntohl(eklen_n); memcpy(encrypted_key, ciphertext + pos, encrypted_key_length); pos += encrypted_key_length; memcpy(iv, ciphertext + pos, EVP_CIPHER_iv_length(EVP_des_ede_cbc())); pos += EVP_CIPHER_iv_length(EVP_des_ede_cbc()); // Now we have our encrypted_key and the iv we can decrypt the reamining // data if (!EVP_OpenInit(&ctx, EVP_des_ede_cbc(), encrypted_key, encrypted_key_length, iv, pkey)) { fprintf(stderr, "EVP_OpenInit: failed.\n"); goto out_free; } if (!EVP_OpenUpdate(&ctx, plaintext, &plaintext_len, ciphertext + pos, ciphertext_len)) { fprintf(stderr, "EVP_OpenUpdate: failed.\n"); goto out_free; } int total_len = plaintext_len; if (!EVP_OpenFinal(&ctx, plaintext + total_len, &plaintext_len)) { fprintf(stderr, "EVP_OpenFinal warning: failed.\n"); } out_free: EVP_PKEY_free(pkey); free(encrypted_key); EVP_CIPHER_CTX_cleanup(&ctx); *len = plaintext_len + total_len; return plaintext; }