Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:24
erlang
2543-crypto-3.0-API-in-rsa.c.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 2543-crypto-3.0-API-in-rsa.c.patch of Package erlang
From d54b49e9a071ea8a1f51cd5deb6d458b5539f218 Mon Sep 17 00:00:00 2001 From: Hans Nilsson <hans@erlang.org> Date: Tue, 1 Mar 2022 13:12:42 +0100 Subject: [PATCH 3/3] crypto: 3.0 API in rsa.c --- lib/crypto/c_src/rsa.c | 320 +++++++++++++++++++++++++++++------------ 1 file changed, 230 insertions(+), 90 deletions(-) diff --git a/lib/crypto/c_src/rsa.c b/lib/crypto/c_src/rsa.c index 3a1c4e75ac..f5f0ef2b6e 100644 --- a/lib/crypto/c_src/rsa.c +++ b/lib/crypto/c_src/rsa.c @@ -21,16 +21,93 @@ #include "rsa.h" #include "bn.h" -//#define(CHK_RSA_3_0) - static ERL_NIF_TERM rsa_generate_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -#if !defined(HAS_3_0_API) || defined(CHK_RSA_3_0) +#if !defined(HAS_3_0_API) static ERL_NIF_TERM put_rsa_private_key(ErlNifEnv* env, const RSA *rsa); #endif #if !defined(HAS_3_0_API) static int check_erlang_interrupt(int maj, int min, BN_GENCB *ctxt); #endif +#define PUT1(env,bn,t) \ + if (bn) {if ((t = bin_from_bn(env, bn)) == atom_error) goto err;} \ + else t = atom_undefined + + +// ERL_NIF_TERM debug_put_pkey(ErlNifEnv* env, EVP_PKEY *pkey); +// ERL_NIF_TERM debug_put_pkey(ErlNifEnv* env, EVP_PKEY *pkey) +// { +// const BIGNUM *e1 = NULL, *n1 = NULL, *d1 = NULL; +// RSA *rsa = NULL; +// ERL_NIF_TERM result[3]; +// +// rsa = EVP_PKEY_get1_RSA(pkey); +// RSA_get0_key(rsa, &n1, &e1, &d1); +// +// PUT1(env, e1, result[0]); // Exponent E +// PUT1(env, n1, result[1]); // Modulus N = p*q +// PUT1(env, d1, result[2]); +// +// return enif_make_list_from_array(env,result,3); +// +// err: +// return atom_error; +// } + + +#if !defined(HAS_3_0_API) +/* Creates a term which can be parsed by get_rsa_private_key(). This is a list of plain integer binaries (not mpints). */ +static ERL_NIF_TERM put_rsa_private_key(ErlNifEnv* env, const RSA *rsa) +{ + ERL_NIF_TERM result[8]; + const BIGNUM *n = NULL, *e = NULL, *d = NULL, *p = NULL, *q = NULL, *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL; + + /* Return at least [E,N,D] */ + RSA_get0_key(rsa, &n, &e, &d); + + if ((result[0] = bin_from_bn(env, e)) == atom_error) // Exponent E + goto err; + if ((result[1] = bin_from_bn(env, n)) == atom_error) // Modulus N = p*q + goto err; + if ((result[2] = bin_from_bn(env, d)) == atom_error) // Exponent D + goto err; + + /* Check whether the optional additional parameters are available */ + RSA_get0_factors(rsa, &p, &q); + RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp); + + if (p && q && dmp1 && dmq1 && iqmp) { + if ((result[3] = bin_from_bn(env, p)) == atom_error) // Factor p + goto err; + if ((result[4] = bin_from_bn(env, q)) == atom_error) // Factor q + goto err; + if ((result[5] = bin_from_bn(env, dmp1)) == atom_error) // D mod (p-1) + goto err; + if ((result[6] = bin_from_bn(env, dmq1)) == atom_error) // D mod (q-1) + goto err; + if ((result[7] = bin_from_bn(env, iqmp)) == atom_error) // (1/q) mod p + goto err; + + return enif_make_list_from_array(env, result, 8); + } else { + return enif_make_list_from_array(env, result, 3); + } + + err: + return enif_make_badarg(env); +} + +static int check_erlang_interrupt(int maj, int min, BN_GENCB *ctxt) +{ + ErlNifEnv *env = BN_GENCB_get_arg(ctxt); + + if (!enif_is_current_process_alive(env)) { + return 0; + } else { + return 1; + } +} + int get_rsa_private_key(ErlNifEnv* env, ERL_NIF_TERM key, EVP_PKEY **pkey) { /* key=[E,N,D]|[E,N,D,P1,P2,E1,E2,C] */ @@ -56,6 +133,7 @@ int get_rsa_private_key(ErlNifEnv* env, ERL_NIF_TERM key, EVP_PKEY **pkey) if ((rsa = RSA_new()) == NULL) goto err; + *pkey = EVP_PKEY_new(); if (!RSA_set0_key(rsa, n, e, d)) goto err; /* rsa now owns n, e, and d */ @@ -135,6 +213,7 @@ int get_rsa_private_key(ErlNifEnv* env, ERL_NIF_TERM key, EVP_PKEY **pkey) return 0; } + int get_rsa_public_key(ErlNifEnv* env, ERL_NIF_TERM key, EVP_PKEY **pkey) { /* key=[E,N] */ @@ -162,9 +241,11 @@ int get_rsa_public_key(ErlNifEnv* env, ERL_NIF_TERM key, EVP_PKEY **pkey) n = NULL; e = NULL; + *pkey = EVP_PKEY_new(); if (EVP_PKEY_assign_RSA(*pkey, rsa) != 1) goto err; + // enif_fprintf(stderr, "pkey = %T\r\n", debug_put_pkey(env,*pkey)); return 1; bad_arg: @@ -179,63 +260,6 @@ int get_rsa_public_key(ErlNifEnv* env, ERL_NIF_TERM key, EVP_PKEY **pkey) return 0; } -#if !defined(HAS_3_0_API) || defined(CHK_RSA_3_0) -/* Creates a term which can be parsed by get_rsa_private_key(). This is a list of plain integer binaries (not mpints). */ -static ERL_NIF_TERM put_rsa_private_key(ErlNifEnv* env, const RSA *rsa) -{ - ERL_NIF_TERM result[8]; - const BIGNUM *n = NULL, *e = NULL, *d = NULL, *p = NULL, *q = NULL, *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL; - - /* Return at least [E,N,D] */ - RSA_get0_key(rsa, &n, &e, &d); - - if ((result[0] = bin_from_bn(env, e)) == atom_error) // Exponent E - goto err; - if ((result[1] = bin_from_bn(env, n)) == atom_error) // Modulus N = p*q - goto err; - if ((result[2] = bin_from_bn(env, d)) == atom_error) // Exponent D - goto err; - - /* Check whether the optional additional parameters are available */ - RSA_get0_factors(rsa, &p, &q); - RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp); - - if (p && q && dmp1 && dmq1 && iqmp) { - if ((result[3] = bin_from_bn(env, p)) == atom_error) // Factor p - goto err; - if ((result[4] = bin_from_bn(env, q)) == atom_error) // Factor q - goto err; - if ((result[5] = bin_from_bn(env, dmp1)) == atom_error) // D mod (p-1) - goto err; - if ((result[6] = bin_from_bn(env, dmq1)) == atom_error) // D mod (q-1) - goto err; - if ((result[7] = bin_from_bn(env, iqmp)) == atom_error) // (1/q) mod p - goto err; - - return enif_make_list_from_array(env, result, 8); - } else { - return enif_make_list_from_array(env, result, 3); - } - - err: - return enif_make_badarg(env); -} -#endif - -#if !defined(HAS_3_0_API) -/* Legacy API deprecated from 3.0 is used */ - -static int check_erlang_interrupt(int maj, int min, BN_GENCB *ctxt) -{ - ErlNifEnv *env = BN_GENCB_get_arg(ctxt); - - if (!enif_is_current_process_alive(env)) { - return 0; - } else { - return 1; - } -} - static ERL_NIF_TERM rsa_generate_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (ModulusSize, PublicExponent) */ ERL_NIF_TERM ret; @@ -303,9 +327,127 @@ static ERL_NIF_TERM rsa_generate_key(ErlNifEnv* env, int argc, const ERL_NIF_TER return ret; } +int rsa_privkey_to_pubkey(ErlNifEnv* env, EVP_PKEY *pkey, ERL_NIF_TERM *ret) +{ + const BIGNUM *n = NULL, *e = NULL, *d = NULL; + ERL_NIF_TERM result[2]; + RSA *rsa = NULL; + + if ((rsa = EVP_PKEY_get1_RSA(pkey)) == NULL) + goto err; + + RSA_get0_key(rsa, &n, &e, &d); + + // Exponent E + if ((result[0] = bin_from_bn(env, e)) == atom_error) + goto err; + // Modulus N = p*q + if ((result[1] = bin_from_bn(env, n)) == atom_error) + goto err; + + *ret = enif_make_list_from_array(env, result, 2); + RSA_free(rsa); + return 1; + + err: + if (rsa) + RSA_free(rsa); + return 0; +} + + #else /* New 3.0 API is used */ +int get_rsa_private_key(ErlNifEnv* env, ERL_NIF_TERM key, EVP_PKEY **pkey) +{ + /* key=[E,N,D]|[E,N,D,P1,P2,E1,E2,C] */ + ERL_NIF_TERM head, tail; + OSSL_PARAM params[9]; + EVP_PKEY_CTX *ctx = NULL; + int i = 0; + + head = key; + + if (!get_ossl_param_from_bin_in_list(env, "e", &head, ¶ms[i++]) || // Exponent E + !get_ossl_param_from_bin_in_list(env, "n", &head, ¶ms[i++]) || // N = p*q + !get_ossl_param_from_bin_in_list(env, "d", &head, ¶ms[i++])) // Exponent D + goto bad_arg; + + tail = head; + + if (!enif_is_empty_list(env, tail)) { + if (!get_ossl_param_from_bin_in_list(env, "rsa-factor1", &head, ¶ms[i++]) || // p, Factor p + !get_ossl_param_from_bin_in_list(env, "rsa-factor2", &head, ¶ms[i++]) || // q, Factor q + !get_ossl_param_from_bin_in_list(env, "rsa-exponent1", &head, ¶ms[i++]) || // dmp1, D mod (p-1) + !get_ossl_param_from_bin_in_list(env, "rsa-exponent2", &head, ¶ms[i++]) || // dmq1, D mod (q-1) + !get_ossl_param_from_bin_in_list(env, "rsa-coefficient1", &head, ¶ms[i++]) ) // iqmp, (1/q) mod p + goto bad_arg; + + tail = head; + + if (!enif_is_empty_list(env, tail)) + goto bad_arg; + } + + params[i++] = OSSL_PARAM_construct_end(); + + if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL)) == NULL) + goto err; + if (EVP_PKEY_fromdata_init(ctx) <= 0) + goto err; + if (EVP_PKEY_fromdata(ctx, pkey, EVP_PKEY_KEYPAIR, params) <= 0) + goto bad_arg; + + if (ctx) EVP_PKEY_CTX_free(ctx); + return 1; + + bad_arg: + err: + if (ctx) EVP_PKEY_CTX_free(ctx); + return 0; +} + + +int get_rsa_public_key(ErlNifEnv* env, ERL_NIF_TERM key, EVP_PKEY **pkey) +{ + ERL_NIF_TERM head, tail; + OSSL_PARAM params[3]; + EVP_PKEY_CTX *ctx = NULL; + + head = key; + if (!get_ossl_param_from_bin_in_list(env, "e", &head, ¶ms[0]) ) + goto bad_arg; + + if (!get_ossl_param_from_bin_in_list(env, "n", &head, ¶ms[1]) ) + goto bad_arg; + + tail = head; + if (!enif_is_empty_list(env, tail)) + goto bad_arg; + + params[2] = OSSL_PARAM_construct_end(); + + if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL)) == NULL) + goto err; + if (EVP_PKEY_fromdata_init(ctx) <= 0) + goto err; + if (EVP_PKEY_fromdata(ctx, pkey, EVP_PKEY_PUBLIC_KEY, params) <= 0) + goto bad_arg; + + /* enif_fprintf(stderr, "pkey = %T\r\nn = %T\r\n", */ + /* debug_put_pkey(env,*pkey), */ + /* enif_make_binary(env,&tmp) */ + /* ); */ + if (ctx) EVP_PKEY_CTX_free(ctx); + return 1; + + bad_arg: + err: + if (ctx) EVP_PKEY_CTX_free(ctx); + return 0; +} + static ERL_NIF_TERM rsa_generate_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (ModulusSize, PublicExponent/binary, PublicExponent) */ ERL_NIF_TERM ret; @@ -378,58 +520,56 @@ static ERL_NIF_TERM rsa_generate_key(ErlNifEnv* env, int argc, const ERL_NIF_TER || ((result[7] = bin_from_bn(env, iqmp)) == atom_error) ) { ret = EXCP_ERROR(env, "Can't get RSA keys"); - goto ret; + goto local_ret; } - ret = enif_make_list_from_array(env, result, 8); - -#ifdef CHK_RSA_3_0 - {RSA *rsa = EVP_PKEY_get1_RSA(pkey); - if (!rsa) - ret = enif_make_tuple2(env, ret, atom_error); - else - ret = enif_make_tuple2(env, ret, put_rsa_private_key(env,rsa)); - } -#endif + local_ret: + if (e) BN_free(e); + if (n) BN_free(n); + if (d) BN_free(d); + if (p) BN_free(p); + if (q) BN_free(q); + if (dmp1) BN_free(dmp1); + if (dmq1) BN_free(dmq1); + if (iqmp) BN_free(iqmp); } ret: + if (pkey) EVP_PKEY_free(pkey); if (pctx) EVP_PKEY_CTX_free(pctx); return ret; } -#endif /* #else-part of #if !defined(HAS_3_0_API) */ - - int rsa_privkey_to_pubkey(ErlNifEnv* env, EVP_PKEY *pkey, ERL_NIF_TERM *ret) { - const BIGNUM *n = NULL, *e = NULL, *d = NULL; + BIGNUM *e = NULL, *n = NULL; ERL_NIF_TERM result[2]; - RSA *rsa = NULL; - - if ((rsa = EVP_PKEY_get1_RSA(pkey)) == NULL) - goto err; - - RSA_get0_key(rsa, &n, &e, &d); - // Exponent E - if ((result[0] = bin_from_bn(env, e)) == atom_error) - goto err; - // Modulus N = p*q - if ((result[1] = bin_from_bn(env, n)) == atom_error) + /* https://www.openssl.org/docs/man3.0/man7/EVP_PKEY-RSA.html */ + if ( + !EVP_PKEY_get_bn_param(pkey, "e", &e) // Exponent E + || !EVP_PKEY_get_bn_param(pkey, "n", &n) // Modulus N = p*q + || ((result[0] = bin_from_bn(env, e)) == atom_error) + || ((result[1] = bin_from_bn(env, n)) == atom_error) + ) goto err; - *ret = enif_make_list_from_array(env, result, 2); - RSA_free(rsa); + *ret = enif_make_list_from_array(env, result, 2); + if (e) BN_free(e); + if (n) BN_free(n); return 1; err: - if (rsa) - RSA_free(rsa); + if (e) BN_free(e); + if (n) BN_free(n); return 0; + } +#endif /* #else-part of #if !defined(HAS_3_0_API) (That is, end of defined(HAS_3_0_API)) */ + + ERL_NIF_TERM rsa_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { /* RSA key generation can take a long time (>1 sec for a large -- 2.34.1
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor