static int crypto_rsa_common(const BYTE* input, int length, UINT32 key_length, const BYTE* modulus, const BYTE* exponent, int exponent_size, BYTE* output) { BN_CTX* ctx; int output_length = -1; BYTE* input_reverse; BYTE* modulus_reverse; BYTE* exponent_reverse; BIGNUM mod, exp, x, y; input_reverse = (BYTE*) malloc(2 * key_length + exponent_size); if (!input_reverse) return -1; modulus_reverse = input_reverse + key_length; exponent_reverse = modulus_reverse + key_length; memcpy(modulus_reverse, modulus, key_length); crypto_reverse(modulus_reverse, key_length); memcpy(exponent_reverse, exponent, exponent_size); crypto_reverse(exponent_reverse, exponent_size); memcpy(input_reverse, input, length); crypto_reverse(input_reverse, length); ctx = BN_CTX_new(); if (!ctx) goto out_free_input_reverse; BN_init(&mod); BN_init(&exp); BN_init(&x); BN_init(&y); BN_bin2bn(modulus_reverse, key_length, &mod); BN_bin2bn(exponent_reverse, exponent_size, &exp); BN_bin2bn(input_reverse, length, &x); BN_mod_exp(&y, &x, &exp, &mod, ctx); output_length = BN_bn2bin(&y, output); crypto_reverse(output, output_length); if (output_length < (int) key_length) memset(output + output_length, 0, key_length - output_length); BN_free(&y); BN_clear_free(&x); BN_free(&exp); BN_free(&mod); BN_CTX_free(ctx); out_free_input_reverse: free(input_reverse); return output_length; }
static void crypto_rsa_common(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* exponent, int exponent_size, uint8* output) { BN_CTX* ctx; int output_length; uint8* input_reverse; uint8* modulus_reverse; uint8* exponent_reverse; BIGNUM mod, exp, x, y; input_reverse = (uint8*) xmalloc(2 * key_length + exponent_size); modulus_reverse = input_reverse + key_length; exponent_reverse = modulus_reverse + key_length; memcpy(modulus_reverse, modulus, key_length); crypto_reverse(modulus_reverse, key_length); memcpy(exponent_reverse, exponent, exponent_size); crypto_reverse(exponent_reverse, exponent_size); memcpy(input_reverse, input, length); crypto_reverse(input_reverse, length); ctx = BN_CTX_new(); BN_init(&mod); BN_init(&exp); BN_init(&x); BN_init(&y); BN_bin2bn(modulus_reverse, key_length, &mod); BN_bin2bn(exponent_reverse, exponent_size, &exp); BN_bin2bn(input_reverse, length, &x); BN_mod_exp(&y, &x, &exp, &mod, ctx); output_length = BN_bn2bin(&y, output); crypto_reverse(output, output_length); if (output_length < (int) key_length) memset(output + output_length, 0, key_length - output_length); BN_free(&y); BN_clear_free(&x); BN_free(&exp); BN_free(&mod); BN_CTX_free(ctx); xfree(input_reverse); }
void crypto_rsa_encrypt(uint8* input, int length, uint32 key_length, uint8* modulus, uint8* exponent, uint8* output) { BN_CTX* ctx; int output_length; uint8* input_reverse; uint8* modulus_reverse; uint8* exponent_reverse; BIGNUM mod, exp, x, y; input_reverse = (uint8*) xmalloc(2 * MODULUS_MAX_SIZE + EXPONENT_MAX_SIZE); modulus_reverse = input_reverse + MODULUS_MAX_SIZE; exponent_reverse = modulus_reverse + MODULUS_MAX_SIZE; memcpy(modulus_reverse, modulus, key_length); crypto_reverse(modulus_reverse, key_length); memcpy(exponent_reverse, exponent, EXPONENT_MAX_SIZE); crypto_reverse(exponent_reverse, EXPONENT_MAX_SIZE); memcpy(input_reverse, input, length); crypto_reverse(input_reverse, length); ctx = BN_CTX_new(); BN_init(&mod); BN_init(&exp); BN_init(&x); BN_init(&y); BN_bin2bn(modulus_reverse, key_length, &mod); BN_bin2bn(exponent_reverse, EXPONENT_MAX_SIZE, &exp); BN_bin2bn(input_reverse, length, &x); BN_mod_exp(&y, &x, &exp, &mod, ctx); output_length = BN_bn2bin(&y, output); crypto_reverse(output, output_length); if (output_length < (int) key_length) memset(output + output_length, 0, key_length - output_length); BN_free(&y); BN_clear_free(&x); BN_free(&exp); BN_free(&mod); BN_CTX_free(ctx); xfree(input_reverse); }
rdpRsaKey* key_new_from_content(const char* keycontent, const char* keyfile) { BIO* bio = NULL; RSA* rsa = NULL; rdpRsaKey* key = NULL; const BIGNUM* rsa_e = NULL; const BIGNUM* rsa_n = NULL; const BIGNUM* rsa_d = NULL; key = (rdpRsaKey*) calloc(1, sizeof(rdpRsaKey)); if (!key) return NULL; bio = BIO_new_mem_buf((void*)keycontent, strlen(keycontent)); if (!bio) goto out_free; rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL); BIO_free(bio); if (!rsa) { WLog_ERR(TAG, "unable to load RSA key from %s: %s.", keyfile, strerror(errno)); goto out_free; } switch (RSA_check_key(rsa)) { case 0: WLog_ERR(TAG, "invalid RSA key in %s", keyfile); goto out_free_rsa; case 1: /* Valid key. */ break; default: WLog_ERR(TAG, "unexpected error when checking RSA key from %s: %s.", keyfile, strerror(errno)); goto out_free_rsa; } RSA_get0_key(rsa, &rsa_n, &rsa_e, &rsa_d); if (BN_num_bytes(rsa_e) > 4) { WLog_ERR(TAG, "RSA public exponent too large in %s", keyfile); goto out_free_rsa; } key->ModulusLength = BN_num_bytes(rsa_n); key->Modulus = (BYTE*) malloc(key->ModulusLength); if (!key->Modulus) goto out_free_rsa; BN_bn2bin(rsa_n, key->Modulus); crypto_reverse(key->Modulus, key->ModulusLength); key->PrivateExponentLength = BN_num_bytes(rsa_d); key->PrivateExponent = (BYTE*) malloc(key->PrivateExponentLength); if (!key->PrivateExponent) goto out_free_modulus; BN_bn2bin(rsa_d, key->PrivateExponent); crypto_reverse(key->PrivateExponent, key->PrivateExponentLength); memset(key->exponent, 0, sizeof(key->exponent)); BN_bn2bin(rsa_e, key->exponent + sizeof(key->exponent) - BN_num_bytes(rsa_e)); crypto_reverse(key->exponent, sizeof(key->exponent)); RSA_free(rsa); return key; out_free_modulus: free(key->Modulus); out_free_rsa: RSA_free(rsa); out_free: free(key); return NULL; }
BOOL certificate_read_x509_certificate(rdpCertBlob* cert, rdpCertInfo* info) { wStream* s; int length; BYTE padding; UINT32 version; int modulus_length; int exponent_length; int error = 0; if (!cert || !info) return FALSE; memset(info, 0, sizeof(rdpCertInfo)); s = Stream_New(cert->data, cert->length); if (!s) return FALSE; info->Modulus = 0; if (!ber_read_sequence_tag(s, &length)) /* Certificate (SEQUENCE) */ goto error1; error++; if (!ber_read_sequence_tag(s, &length)) /* TBSCertificate (SEQUENCE) */ goto error1; error++; if (!ber_read_contextual_tag(s, 0, &length, TRUE)) /* Explicit Contextual Tag [0] */ goto error1; error++; if (!ber_read_integer(s, &version)) /* version (INTEGER) */ goto error1; error++; version++; /* serialNumber */ if (!ber_read_integer(s, NULL)) /* CertificateSerialNumber (INTEGER) */ goto error1; error++; /* signature */ if (!ber_read_sequence_tag(s, &length) || !Stream_SafeSeek(s, length)) /* AlgorithmIdentifier (SEQUENCE) */ goto error1; error++; /* issuer */ if (!ber_read_sequence_tag(s, &length) || !Stream_SafeSeek(s, length)) /* Name (SEQUENCE) */ goto error1; error++; /* validity */ if (!ber_read_sequence_tag(s, &length) || !Stream_SafeSeek(s, length)) /* Validity (SEQUENCE) */ goto error1; error++; /* subject */ if (!ber_read_sequence_tag(s, &length) || !Stream_SafeSeek(s, length)) /* Name (SEQUENCE) */ goto error1; error++; /* subjectPublicKeyInfo */ if (!ber_read_sequence_tag(s, &length)) /* SubjectPublicKeyInfo (SEQUENCE) */ goto error1; error++; /* subjectPublicKeyInfo::AlgorithmIdentifier */ if (!ber_read_sequence_tag(s, &length) || !Stream_SafeSeek(s, length)) /* AlgorithmIdentifier (SEQUENCE) */ goto error1; error++; /* subjectPublicKeyInfo::subjectPublicKey */ if (!ber_read_bit_string(s, &length, &padding)) /* BIT_STRING */ goto error1; error++; /* RSAPublicKey (SEQUENCE) */ if (!ber_read_sequence_tag(s, &length)) /* SEQUENCE */ goto error1; error++; if (!ber_read_integer_length(s, &modulus_length)) /* modulus (INTEGER) */ goto error1; error++; /* skip zero padding, if any */ do { if (Stream_GetRemainingLength(s) < 1) goto error1; Stream_Peek_UINT8(s, padding); if (padding == 0) { if (!Stream_SafeSeek(s, 1)) goto error1; modulus_length--; } } while (padding == 0); error++; if (((int) Stream_GetRemainingLength(s)) < modulus_length) goto error1; info->ModulusLength = modulus_length; info->Modulus = (BYTE*) malloc(info->ModulusLength); if (!info->Modulus) goto error1; Stream_Read(s, info->Modulus, info->ModulusLength); error++; if (!ber_read_integer_length(s, &exponent_length)) /* publicExponent (INTEGER) */ goto error2; error++; if ((((int) Stream_GetRemainingLength(s)) < exponent_length) || (exponent_length > 4)) goto error2; Stream_Read(s, &info->exponent[4 - exponent_length], exponent_length); crypto_reverse(info->Modulus, info->ModulusLength); crypto_reverse(info->exponent, 4); Stream_Free(s, FALSE); return TRUE; error2: free(info->Modulus); info->Modulus = 0; error1: WLog_ERR(TAG, "error reading when reading certificate: part=%s error=%d", certificate_read_errors[error], error); Stream_Free(s, FALSE); return FALSE; }
rdpRsaKey* key_new(const char* keyfile) { BIO* bio = NULL; FILE* fp = NULL; RSA* rsa = NULL; int length; BYTE* buffer = NULL; rdpRsaKey* key = NULL; key = (rdpRsaKey*) calloc(1, sizeof(rdpRsaKey)); if (!key) return NULL; fp = fopen(keyfile, "r+b"); if (!fp) { WLog_ERR(TAG, "unable to open RSA key file %s: %s.", keyfile, strerror(errno)); goto out_free; } fseek(fp, 0, SEEK_END); length = ftell(fp); fseek(fp, 0, SEEK_SET); buffer = (BYTE*) malloc(length); if (!buffer) goto out_free; fread((void*) buffer, length, 1, fp); fclose(fp); bio = BIO_new_mem_buf((void*) buffer, length); if (!bio) goto out_free; rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL); BIO_free(bio); free(buffer); buffer = NULL; if (!rsa) { WLog_ERR(TAG, "unable to load RSA key from %s: %s.", keyfile, strerror(errno)); goto out_free; } switch (RSA_check_key(rsa)) { case 0: WLog_ERR(TAG, "invalid RSA key in %s", keyfile); goto out_free_rsa; case 1: /* Valid key. */ break; default: WLog_ERR(TAG, "unexpected error when checking RSA key from %s: %s.", keyfile, strerror(errno)); goto out_free_rsa; } if (BN_num_bytes(rsa->e) > 4) { WLog_ERR(TAG, "RSA public exponent too large in %s", keyfile); goto out_free_rsa; } key->ModulusLength = BN_num_bytes(rsa->n); key->Modulus = (BYTE*) malloc(key->ModulusLength); if (!key->Modulus) goto out_free_rsa; BN_bn2bin(rsa->n, key->Modulus); crypto_reverse(key->Modulus, key->ModulusLength); key->PrivateExponentLength = BN_num_bytes(rsa->d); key->PrivateExponent = (BYTE*) malloc(key->PrivateExponentLength); if (!key->PrivateExponent) goto out_free_modulus; BN_bn2bin(rsa->d, key->PrivateExponent); crypto_reverse(key->PrivateExponent, key->PrivateExponentLength); memset(key->exponent, 0, sizeof(key->exponent)); BN_bn2bin(rsa->e, key->exponent + sizeof(key->exponent) - BN_num_bytes(rsa->e)); crypto_reverse(key->exponent, sizeof(key->exponent)); RSA_free(rsa); return key; out_free_modulus: free(key->Modulus); out_free_rsa: RSA_free(rsa); out_free: if (fp) fclose(fp); if (buffer) free(buffer); free(key); return NULL; }
void certificate_read_x509_certificate(rdpCertBlob* cert, rdpCertInfo* info) { STREAM* s; int length; uint8 padding; uint32 version; int modulus_length; int exponent_length; s = stream_new(0); s->p = s->data = cert->data; ber_read_sequence_tag(s, &length); /* Certificate (SEQUENCE) */ ber_read_sequence_tag(s, &length); /* TBSCertificate (SEQUENCE) */ /* Explicit Contextual Tag [0] */ ber_read_contextual_tag(s, 0, &length, true); ber_read_integer(s, &version); /* version (INTEGER) */ version++; /* serialNumber */ ber_read_integer(s, NULL); /* CertificateSerialNumber (INTEGER) */ /* signature */ ber_read_sequence_tag(s, &length); /* AlgorithmIdentifier (SEQUENCE) */ stream_seek(s, length); /* issuer */ ber_read_sequence_tag(s, &length); /* Name (SEQUENCE) */ stream_seek(s, length); /* validity */ ber_read_sequence_tag(s, &length); /* Validity (SEQUENCE) */ stream_seek(s, length); /* subject */ ber_read_sequence_tag(s, &length); /* Name (SEQUENCE) */ stream_seek(s, length); /* subjectPublicKeyInfo */ ber_read_sequence_tag(s, &length); /* SubjectPublicKeyInfo (SEQUENCE) */ /* subjectPublicKeyInfo::AlgorithmIdentifier */ ber_read_sequence_tag(s, &length); /* AlgorithmIdentifier (SEQUENCE) */ stream_seek(s, length); /* subjectPublicKeyInfo::subjectPublicKey */ ber_read_bit_string(s, &length, &padding); /* BIT_STRING */ /* RSAPublicKey (SEQUENCE) */ ber_read_sequence_tag(s, &length); /* SEQUENCE */ ber_read_integer_length(s, &modulus_length); /* modulus (INTEGER) */ /* skip zero padding, if any */ do { stream_peek_uint8(s, padding); if (padding == 0) { stream_seek(s, 1); modulus_length--; } } while (padding == 0); freerdp_blob_alloc(&info->modulus, modulus_length); stream_read(s, info->modulus.data, modulus_length); ber_read_integer_length(s, &exponent_length); /* publicExponent (INTEGER) */ stream_read(s, &info->exponent[4 - exponent_length], exponent_length); crypto_reverse(info->modulus.data, modulus_length); crypto_reverse(info->exponent, 4); }
rdpRsaKey* key_new(const char* keyfile) { FILE* fp; RSA* rsa; rdpRsaKey* key; key = (rdpRsaKey*) malloc(sizeof(rdpRsaKey)); ZeroMemory(key, sizeof(rdpRsaKey)); if (key == NULL) return NULL; fp = fopen(keyfile, "r"); if (fp == NULL) { fprintf(stderr, "unable to load RSA key from %s: %s.", keyfile, strerror(errno)); free(key) ; return NULL; } rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); if (rsa == NULL) { ERR_print_errors_fp(stdout); fclose(fp); free(key) ; return NULL; } fclose(fp); switch (RSA_check_key(rsa)) { case 0: RSA_free(rsa); fprintf(stderr, "invalid RSA key in %s", keyfile); free(key) ; return NULL; case 1: /* Valid key. */ break; default: ERR_print_errors_fp(stderr); RSA_free(rsa); free(key) ; return NULL; } if (BN_num_bytes(rsa->e) > 4) { RSA_free(rsa); fprintf(stderr, "RSA public exponent too large in %s", keyfile); free(key) ; return NULL; } key->ModulusLength = BN_num_bytes(rsa->n); key->Modulus = (BYTE*) malloc(key->ModulusLength); BN_bn2bin(rsa->n, key->Modulus); crypto_reverse(key->Modulus, key->ModulusLength); key->PrivateExponentLength = BN_num_bytes(rsa->d); key->PrivateExponent = (BYTE*) malloc(key->PrivateExponentLength); BN_bn2bin(rsa->d, key->PrivateExponent); crypto_reverse(key->PrivateExponent, key->PrivateExponentLength); memset(key->exponent, 0, sizeof(key->exponent)); BN_bn2bin(rsa->e, key->exponent + sizeof(key->exponent) - BN_num_bytes(rsa->e)); crypto_reverse(key->exponent, sizeof(key->exponent)); RSA_free(rsa); return key; }
BOOL certificate_read_x509_certificate(rdpCertBlob* cert, rdpCertInfo* info) { wStream* s; int length; BYTE padding; UINT32 version; int modulus_length; int exponent_length; int error = 0; s = stream_new(0); stream_attach(s, cert->data, cert->length); info->Modulus = 0; if(!ber_read_sequence_tag(s, &length)) /* Certificate (SEQUENCE) */ goto error1; error++; if(!ber_read_sequence_tag(s, &length)) /* TBSCertificate (SEQUENCE) */ goto error1; error++; if(!ber_read_contextual_tag(s, 0, &length, TRUE)) /* Explicit Contextual Tag [0] */ goto error1; error++; if(!ber_read_integer(s, &version)) /* version (INTEGER) */ goto error1; error++; version++; /* serialNumber */ if(!ber_read_integer(s, NULL)) /* CertificateSerialNumber (INTEGER) */ goto error1; error++; /* signature */ if(!ber_read_sequence_tag(s, &length) || !stream_skip(s, length)) /* AlgorithmIdentifier (SEQUENCE) */ goto error1; error++; /* issuer */ if(!ber_read_sequence_tag(s, &length) || !stream_skip(s, length)) /* Name (SEQUENCE) */ goto error1; error++; /* validity */ if(!ber_read_sequence_tag(s, &length) || !stream_skip(s, length)) /* Validity (SEQUENCE) */ goto error1; error++; /* subject */ if(!ber_read_sequence_tag(s, &length) || !stream_skip(s, length)) /* Name (SEQUENCE) */ goto error1; error++; /* subjectPublicKeyInfo */ if(!ber_read_sequence_tag(s, &length)) /* SubjectPublicKeyInfo (SEQUENCE) */ goto error1; error++; /* subjectPublicKeyInfo::AlgorithmIdentifier */ if(!ber_read_sequence_tag(s, &length) || !stream_skip(s, length)) /* AlgorithmIdentifier (SEQUENCE) */ goto error1; error++; /* subjectPublicKeyInfo::subjectPublicKey */ if(!ber_read_bit_string(s, &length, &padding)) /* BIT_STRING */ goto error1; error++; /* RSAPublicKey (SEQUENCE) */ if(!ber_read_sequence_tag(s, &length)) /* SEQUENCE */ goto error1; error++; if(!ber_read_integer_length(s, &modulus_length)) /* modulus (INTEGER) */ goto error1; error++; /* skip zero padding, if any */ do { if(stream_get_left(s) < 1) goto error1; stream_peek_BYTE(s, padding); if (padding == 0) { if(!stream_skip(s, 1)) goto error1; modulus_length--; } } while (padding == 0); error++; if(stream_get_left(s) < modulus_length) goto error1; info->ModulusLength = modulus_length; info->Modulus = (BYTE*) malloc(info->ModulusLength); stream_read(s, info->Modulus, info->ModulusLength); error++; if(!ber_read_integer_length(s, &exponent_length)) /* publicExponent (INTEGER) */ goto error2; error++; if(stream_get_left(s) < exponent_length || exponent_length > 4) goto error2; stream_read(s, &info->exponent[4 - exponent_length], exponent_length); crypto_reverse(info->Modulus, info->ModulusLength); crypto_reverse(info->exponent, 4); stream_detach(s); stream_free(s); return TRUE; error2: free(info->Modulus); info->Modulus = 0; error1: fprintf(stderr, "error reading when reading certificate: part=%s error=%d\n", certificate_read_errors[error], error); stream_detach(s); stream_free(s); return FALSE; }
rdpKey* key_new(const char* keyfile) { rdpKey* key; RSA *rsa; FILE *fp; key = (rdpKey*) xzalloc(sizeof(rdpKey)); if (key == NULL) return NULL; fp = fopen(keyfile, "r"); if (fp == NULL) { printf("unable to load RSA key from %s: %s.", keyfile, strerror(errno)); return NULL; } rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); if (rsa == NULL) { ERR_print_errors_fp(stdout); fclose(fp); return NULL; } fclose(fp); switch (RSA_check_key(rsa)) { case 0: RSA_free(rsa); printf("invalid RSA key in %s", keyfile); return NULL; case 1: /* Valid key. */ break; default: ERR_print_errors_fp(stdout); RSA_free(rsa); return NULL; } if (BN_num_bytes(rsa->e) > 4) { RSA_free(rsa); printf("RSA public exponent too large in %s", keyfile); return NULL; } freerdp_blob_alloc(&key->modulus, BN_num_bytes(rsa->n)); BN_bn2bin(rsa->n, key->modulus.data); crypto_reverse(key->modulus.data, key->modulus.length); freerdp_blob_alloc(&key->private_exponent, BN_num_bytes(rsa->d)); BN_bn2bin(rsa->d, key->private_exponent.data); crypto_reverse(key->private_exponent.data, key->private_exponent.length); memset(key->exponent, 0, sizeof(key->exponent)); BN_bn2bin(rsa->e, key->exponent + sizeof(key->exponent) - BN_num_bytes(rsa->e)); crypto_reverse(key->exponent, sizeof(key->exponent)); RSA_free(rsa); return key; }
rdpRsaKey* key_new(const char* keyfile) { FILE* fp; RSA* rsa; rdpRsaKey* key; key = (rdpRsaKey *)calloc(1, sizeof(rdpRsaKey)); if (!key) return NULL; fp = fopen(keyfile, "r"); if (fp == NULL) { fprintf(stderr, "%s: unable to open RSA key file %s: %s.", __FUNCTION__, keyfile, strerror(errno)); goto out_free; } rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); if (rsa == NULL) { fprintf(stderr, "%s: unable to load RSA key from %s: %s.", __FUNCTION__, keyfile, strerror(errno)); ERR_print_errors_fp(stderr); fclose(fp); goto out_free; } fclose(fp); switch (RSA_check_key(rsa)) { case 0: fprintf(stderr, "%s: invalid RSA key in %s\n", __FUNCTION__, keyfile); goto out_free_rsa; case 1: /* Valid key. */ break; default: fprintf(stderr, "%s: unexpected error when checking RSA key from %s: %s.", __FUNCTION__, keyfile, strerror(errno)); ERR_print_errors_fp(stderr); goto out_free_rsa; } if (BN_num_bytes(rsa->e) > 4) { fprintf(stderr, "%s: RSA public exponent too large in %s\n", __FUNCTION__, keyfile); goto out_free_rsa; } key->ModulusLength = BN_num_bytes(rsa->n); key->Modulus = (BYTE *)malloc(key->ModulusLength); if (!key->Modulus) goto out_free_rsa; BN_bn2bin(rsa->n, key->Modulus); crypto_reverse(key->Modulus, key->ModulusLength); key->PrivateExponentLength = BN_num_bytes(rsa->d); key->PrivateExponent = (BYTE *)malloc(key->PrivateExponentLength); if (!key->PrivateExponent) goto out_free_modulus; BN_bn2bin(rsa->d, key->PrivateExponent); crypto_reverse(key->PrivateExponent, key->PrivateExponentLength); memset(key->exponent, 0, sizeof(key->exponent)); BN_bn2bin(rsa->e, key->exponent + sizeof(key->exponent) - BN_num_bytes(rsa->e)); crypto_reverse(key->exponent, sizeof(key->exponent)); RSA_free(rsa); return key; out_free_modulus: free(key->Modulus); out_free_rsa: RSA_free(rsa); out_free: free(key); return NULL; }