From: Nikos Mavrogiannopoulos Date: Thu, 28 Mar 2002 09:44:34 +0000 (+0000) Subject: Optimized RSA decryption. (Very) Much faster now X-Git-Tag: gnutls_0_4_0~21 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=bc9236ebb61eaeb7b970d9f5753dbb5c8cff7b00;p=thirdparty%2Fgnutls.git Optimized RSA decryption. (Very) Much faster now --- diff --git a/lib/auth_rsa.c b/lib/auth_rsa.c index 6b3c77d84e..f33a7ba10a 100644 --- a/lib/auth_rsa.c +++ b/lib/auth_rsa.c @@ -66,7 +66,7 @@ MOD_AUTH_STRUCT rsa_auth_struct = { /* This function reads the RSA parameters from peer's certificate; */ -static int _gnutls_get_public_rsa_params(GNUTLS_STATE state) +static int _gnutls_get_public_rsa_params(GNUTLS_STATE state, MPI params[RSA_PUBLIC_PARAMS]) { int ret; CERTIFICATE_AUTH_INFO info = _gnutls_get_auth_info( state); @@ -101,7 +101,9 @@ gnutls_cert peer_cert; return GNUTLS_E_UNKNOWN_ERROR; } - + memcpy( params, peer_cert.params, sizeof(MPI)*RSA_PUBLIC_PARAMS); + +/* state->gnutls_key->a = gcry_mpi_copy( peer_cert.params[0]); if (state->gnutls_key->a==NULL) { @@ -116,13 +118,14 @@ gnutls_cert peer_cert; gnutls_free_cert( peer_cert); return GNUTLS_E_MEMORY_ERROR; } +*/ return 0; } /* This function reads the RSA parameters from the private key */ -static int _gnutls_get_private_rsa_params(GNUTLS_STATE state) +static int _gnutls_get_private_rsa_params(GNUTLS_STATE state, MPI params[RSA_PRIVATE_PARAMS]) { int index; const GNUTLS_CERTIFICATE_CREDENTIALS cred; @@ -138,6 +141,9 @@ const GNUTLS_CERTIFICATE_CREDENTIALS cred; return GNUTLS_E_UNKNOWN_ERROR; } + memcpy( params, cred->pkey[index].params, sizeof(MPI)*RSA_PRIVATE_PARAMS); + +/* state->gnutls_key->u = gcry_mpi_copy( cred->pkey[index].params[2]); if (state->gnutls_key->u==NULL) return GNUTLS_E_MEMORY_ERROR; @@ -146,6 +152,7 @@ const GNUTLS_CERTIFICATE_CREDENTIALS cred; _gnutls_mpi_release( &state->gnutls_key->u); return GNUTLS_E_MEMORY_ERROR; } +*/ return 0; } @@ -164,7 +171,7 @@ int proc_rsa_client_kx(GNUTLS_STATE state, opaque * data, int data_size) gnutls_sdatum plaintext; gnutls_datum ciphertext; int ret, dsize; - MPI params[RSA_PARAMS]; + MPI params[RSA_PRIVATE_PARAMS]; if (gnutls_protocol_get_version(state) == GNUTLS_SSL3) { /* SSL 3.0 */ @@ -181,14 +188,12 @@ int proc_rsa_client_kx(GNUTLS_STATE state, opaque * data, int data_size) ciphertext.size = dsize; } - ret = _gnutls_get_private_rsa_params(state); + ret = _gnutls_get_private_rsa_params(state, params); if (ret < 0) { gnutls_assert(); return ret; } - params[0] = state->gnutls_key->A; - params[1] = state->gnutls_key->u; ret = _gnutls_pkcs1_rsa_decrypt(&plaintext, ciphertext, params, 2); /* btype==2 */ if (ret < 0 || plaintext.size != TLS_MASTER_SIZE) { @@ -217,9 +222,7 @@ int proc_rsa_client_kx(GNUTLS_STATE state, opaque * data, int data_size) state->gnutls_key->key.size = plaintext.size; } - _gnutls_mpi_release(&state->gnutls_key->A); _gnutls_mpi_release(&state->gnutls_key->B); - _gnutls_mpi_release(&state->gnutls_key->u); return ret; } @@ -232,7 +235,7 @@ int gen_rsa_client_kx(GNUTLS_STATE state, opaque ** data) { CERTIFICATE_AUTH_INFO auth = state->gnutls_key->auth_info; gnutls_datum sdata; /* data to send */ - MPI params[RSA_PARAMS]; + MPI params[RSA_PUBLIC_PARAMS]; int ret; GNUTLS_Version ver; @@ -253,22 +256,17 @@ int gen_rsa_client_kx(GNUTLS_STATE state, opaque ** data) /* move RSA parameters to gnutls_key (state). */ if ((ret = - _gnutls_get_public_rsa_params(state)) < 0) { + _gnutls_get_public_rsa_params(state, params)) < 0) { gnutls_assert(); return ret; } - params[0] = state->gnutls_key->a; - params[1] = state->gnutls_key->x; if ((ret = _gnutls_pkcs1_rsa_encrypt(&sdata, state->gnutls_key->key, params, 2)) < 0) { gnutls_assert(); return ret; } - _gnutls_mpi_release(&state->gnutls_key->a); - _gnutls_mpi_release(&state->gnutls_key->x); - if (gnutls_protocol_get_version( state) == GNUTLS_SSL3) { /* SSL 3.0 */ diff --git a/lib/gnutls_cert.h b/lib/gnutls_cert.h index 3762ede75e..719355c677 100644 --- a/lib/gnutls_cert.h +++ b/lib/gnutls_cert.h @@ -5,15 +5,16 @@ #include #include -#define MAX_PARAMS_SIZE 5 /* ok for RSA and DSA */ +#define MAX_PARAMS_SIZE 6 /* ok for RSA and DSA */ /* parameters should not be larger than this limit */ #define MAX_PARAMETER_SIZE 1200 #define DSA_PRIVATE_PARAMS 5 #define DSA_PUBLIC_PARAMS 4 -#define RSA_PARAMS 3 +#define RSA_PRIVATE_PARAMS 6 +#define RSA_PUBLIC_PARAMS 2 -#if MAX_PARAMS_SIZE - RSA_PARAMS < 0 +#if MAX_PARAMS_SIZE - RSA_PRIVATE_PARAMS < 0 # error INCREASE MAX_PARAMS #endif @@ -67,6 +68,9 @@ typedef struct { * RSA: [0] is modulus * [1] is public exponent * [2] is private exponent + * [3] is prime1 (p) + * [4] is prime2 (q) + * [5] is coefficient (u == inverse of p mod q) * DSA: [0] is p * [1] is q * [2] is g diff --git a/lib/gnutls_pk.c b/lib/gnutls_pk.c index c490347e26..fdd08b64b0 100644 --- a/lib/gnutls_pk.c +++ b/lib/gnutls_pk.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001 Nikos Mavroyanopoulos + * Copyright (C) 2001,2002 Nikos Mavroyanopoulos * * This file is part of GNUTLS. * @@ -33,6 +33,7 @@ static int _gnutls_pk_sign(int algo, MPI* data, MPI hash, MPI * pkey); static int _gnutls_pk_verify(int algo, MPI hash, MPI* data, MPI *pkey); +static int _gnutls_pk_decrypt(int algo, MPI * resarr, MPI data, MPI * pkey); /* Do PKCS-1 RSA encryption. @@ -45,7 +46,7 @@ int _gnutls_pkcs1_rsa_encrypt(gnutls_datum * ciphertext, int k, psize, i, ret, pad; MPI m, res; opaque *edata, *ps; - MPI tmp_params[RSA_PARAMS]; + MPI tmp_params[RSA_PUBLIC_PARAMS]; k = gcry_mpi_get_nbits(params[0]) / 8; @@ -115,6 +116,7 @@ int _gnutls_pkcs1_rsa_encrypt(gnutls_datum * ciphertext, gnutls_free(edata); ret = _gnutls_pk_encrypt(GCRY_PK_RSA, &res, m, tmp_params); + _gnutls_mpi_release(&m); if (ret < 0) { @@ -176,7 +178,7 @@ int _gnutls_pkcs1_rsa_decrypt(gnutls_sdatum * plaintext, return GNUTLS_E_MPI_SCAN_FAILED; } - ret = _gnutls_pk_encrypt(GCRY_PK_RSA, &res, c, params); + ret = _gnutls_pk_decrypt(GCRY_PK_RSA, &res, c, params); _gnutls_mpi_release(&c); if (ret < 0) { @@ -539,6 +541,61 @@ int _gnutls_pk_encrypt(int algo, MPI * resarr, MPI data, MPI * pkey) return rc; } +static int _gnutls_pk_decrypt(int algo, MPI * resarr, MPI data, MPI * pkey) +{ + GCRY_SEXP s_plain, s_data, s_pkey; + int rc; + + /* make a sexp from pkey */ + switch (algo) { + case GCRY_PK_RSA: + rc = gcry_sexp_build(&s_pkey, NULL, + "(private-key(rsa((n%m)(e%m)(d%m)(p%m)(q%m)(u%m))))", + pkey[0], pkey[1], pkey[2], pkey[3], pkey[4], pkey[5]); + + break; + + default: + gnutls_assert(); + return GNUTLS_E_UNKNOWN_KX_ALGORITHM; + } + + if (rc != 0) { + gnutls_assert(); + return GNUTLS_E_UNKNOWN_ERROR; + } + + /* put the data into a simple list */ + if (gcry_sexp_build(&s_data, NULL, "(enc-val(rsa(a%m)))", data)) { + gnutls_assert(); + gcry_sexp_release(s_pkey); + return GNUTLS_E_UNKNOWN_ERROR; + } + + /* pass it to libgcrypt */ + rc = gcry_pk_decrypt(&s_plain, s_data, s_pkey); + gcry_sexp_release(s_data); + gcry_sexp_release(s_pkey); + + if (rc != 0) { + gnutls_assert(); + return GNUTLS_E_PK_ENCRYPTION_FAILED; + + } else { /* add better error handling or make gnupg use S-Exp directly */ + resarr[0] = gcry_sexp_nth_mpi(s_plain, 0, 0); + + if (resarr[0] == NULL) { + gnutls_assert(); + gcry_sexp_release(s_plain); + return GNUTLS_E_INTERNAL_ERROR; + } + } + + gcry_sexp_release(s_plain); + return rc; +} + + /* in case of DSA puts into data, r,s */ static diff --git a/lib/gnutls_privkey.c b/lib/gnutls_privkey.c index 3a060629e4..5410373cac 100644 --- a/lib/gnutls_privkey.c +++ b/lib/gnutls_privkey.c @@ -34,61 +34,126 @@ /* Converts an RSA PKCS#1 key to * an internal structure (gnutls_private_key) */ -int _gnutls_PKCS1key2gnutlsKey(gnutls_private_key * pkey, gnutls_datum raw_key) { +int _gnutls_PKCS1key2gnutlsKey(gnutls_private_key * pkey, + gnutls_datum raw_key) +{ int result; opaque str[MAX_PARAMETER_SIZE]; node_asn *pkey_asn; - + pkey->pk_algorithm = GNUTLS_PK_RSA; - - if ((result=asn1_create_structure( _gnutls_get_gnutls_asn(), "GNUTLS.RSAPrivateKey", &pkey_asn, "rsakey"))!=ASN_OK) { + + if ((result = + asn1_create_structure(_gnutls_get_gnutls_asn(), + "GNUTLS.RSAPrivateKey", &pkey_asn, + "rsakey")) != ASN_OK) { gnutls_assert(); return result; } - if ((sizeof( pkey->params)/sizeof(MPI)) < RSA_PARAMS) { + if ((sizeof(pkey->params) / sizeof(MPI)) < RSA_PRIVATE_PARAMS) { gnutls_assert(); /* internal error. Increase the MPIs in params */ return GNUTLS_E_INTERNAL_ERROR; } - result = asn1_get_der( pkey_asn, raw_key.data, raw_key.size); + result = asn1_get_der(pkey_asn, raw_key.data, raw_key.size); if (result != ASN_OK) { gnutls_assert(); return result; } - if ( (result=_gnutls_x509_read_int( pkey_asn, "rsakey.modulus", - str, sizeof(str)-1, &pkey->params[0])) < 0) { + if ((result = _gnutls_x509_read_int(pkey_asn, "rsakey.modulus", + str, sizeof(str) - 1, + &pkey->params[0])) < 0) { gnutls_assert(); asn1_delete_structure(pkey_asn); return result; } - if ( (result=_gnutls_x509_read_int( pkey_asn, "rsakey.publicExponent", - str, sizeof(str)-1, &pkey->params[1])) < 0) { + if ((result = + _gnutls_x509_read_int(pkey_asn, "rsakey.publicExponent", str, + sizeof(str) - 1, + &pkey->params[1])) < 0) { gnutls_assert(); asn1_delete_structure(pkey_asn); - _gnutls_mpi_release( &pkey->params[0]); + _gnutls_mpi_release(&pkey->params[0]); + return result; + } + + if ((result = + _gnutls_x509_read_int(pkey_asn, "rsakey.privateExponent", str, + sizeof(str) - 1, + &pkey->params[2])) < 0) { + gnutls_assert(); + _gnutls_mpi_release(&pkey->params[0]); + _gnutls_mpi_release(&pkey->params[1]); + asn1_delete_structure(pkey_asn); return result; } - if ( (result=_gnutls_x509_read_int( pkey_asn, "rsakey.privateExponent", - str, sizeof(str)-1, &pkey->params[2])) < 0) { + if ((result = _gnutls_x509_read_int(pkey_asn, "rsakey.prime1", + str, sizeof(str) - 1, + &pkey->params[3])) < 0) { + gnutls_assert(); + _gnutls_mpi_release(&pkey->params[0]); + _gnutls_mpi_release(&pkey->params[1]); + _gnutls_mpi_release(&pkey->params[2]); + asn1_delete_structure(pkey_asn); + return result; + } + + if ((result = _gnutls_x509_read_int(pkey_asn, "rsakey.prime2", + str, sizeof(str) - 1, + &pkey->params[4])) < 0) { + gnutls_assert(); + _gnutls_mpi_release(&pkey->params[0]); + _gnutls_mpi_release(&pkey->params[1]); + _gnutls_mpi_release(&pkey->params[2]); + _gnutls_mpi_release(&pkey->params[3]); + asn1_delete_structure(pkey_asn); + return result; + } + +#if 1 + /* Calculate the coefficient. This is because the gcrypt + * library is uses the p,q in the reverse order. + */ + pkey->params[5] = + gcry_mpi_snew(gcry_mpi_get_nbits(pkey->params[0])); + + if (pkey->params[5] == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + _gcry_mpi_invm(pkey->params[5], pkey->params[3], pkey->params[4]); + /* p, q */ +#else + if ( (result=_gnutls_x509_read_int( pkey_asn, "rsakey.coefficient", + str, sizeof(str)-1, &pkey->params[5])) < 0) { gnutls_assert(); _gnutls_mpi_release( &pkey->params[0]); _gnutls_mpi_release( &pkey->params[1]); + _gnutls_mpi_release( &pkey->params[2]); + _gnutls_mpi_release( &pkey->params[3]); + _gnutls_mpi_release( &pkey->params[4]); asn1_delete_structure(pkey_asn); return result; } - pkey->params_size = RSA_PARAMS; +#endif + + pkey->params_size = RSA_PRIVATE_PARAMS; asn1_delete_structure(pkey_asn); - if (gnutls_set_datum( &pkey->raw, raw_key.data, raw_key.size) < 0) { + if (gnutls_set_datum(&pkey->raw, raw_key.data, raw_key.size) < 0) { _gnutls_mpi_release(&pkey->params[0]); _gnutls_mpi_release(&pkey->params[1]); _gnutls_mpi_release(&pkey->params[2]); + _gnutls_mpi_release(&pkey->params[3]); + _gnutls_mpi_release(&pkey->params[4]); + _gnutls_mpi_release(&pkey->params[5]); gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; } @@ -98,79 +163,89 @@ int _gnutls_PKCS1key2gnutlsKey(gnutls_private_key * pkey, gnutls_datum raw_key) } -int _gnutls_DSAkey2gnutlsKey(gnutls_private_key * pkey, gnutls_datum raw_key) { +int _gnutls_DSAkey2gnutlsKey(gnutls_private_key * pkey, + gnutls_datum raw_key) +{ int result; opaque str[MAX_PARAMETER_SIZE]; node_asn *dsa_asn; - + pkey->pk_algorithm = GNUTLS_PK_DSA; - - if ((result=asn1_create_structure( _gnutls_get_gnutls_asn(), "GNUTLS.DSAPrivateKey", &dsa_asn, "dsakey"))!=ASN_OK) { + + if ((result = + asn1_create_structure(_gnutls_get_gnutls_asn(), + "GNUTLS.DSAPrivateKey", &dsa_asn, + "dsakey")) != ASN_OK) { gnutls_assert(); return result; } - if ((sizeof( pkey->params)/sizeof(MPI)) < DSA_PRIVATE_PARAMS) { + if ((sizeof(pkey->params) / sizeof(MPI)) < DSA_PRIVATE_PARAMS) { gnutls_assert(); /* internal error. Increase the MPIs in params */ return GNUTLS_E_INTERNAL_ERROR; } - result = asn1_get_der( dsa_asn, raw_key.data, raw_key.size); + result = asn1_get_der(dsa_asn, raw_key.data, raw_key.size); if (result != ASN_OK) { gnutls_assert(); return result; } - if ( (result=_gnutls_x509_read_int( dsa_asn, "dsakey.p", - str, sizeof(str)-1, &pkey->params[0])) < 0) { + if ((result = _gnutls_x509_read_int(dsa_asn, "dsakey.p", + str, sizeof(str) - 1, + &pkey->params[0])) < 0) { gnutls_assert(); asn1_delete_structure(dsa_asn); return result; } - if ( (result=_gnutls_x509_read_int( dsa_asn, "dsakey.q", - str, sizeof(str)-1, &pkey->params[1])) < 0) { + if ((result = _gnutls_x509_read_int(dsa_asn, "dsakey.q", + str, sizeof(str) - 1, + &pkey->params[1])) < 0) { gnutls_assert(); asn1_delete_structure(dsa_asn); - _gnutls_mpi_release( &pkey->params[0]); + _gnutls_mpi_release(&pkey->params[0]); return result; } - if ( (result=_gnutls_x509_read_int( dsa_asn, "dsakey.g", - str, sizeof(str)-1, &pkey->params[2])) < 0) { + if ((result = _gnutls_x509_read_int(dsa_asn, "dsakey.g", + str, sizeof(str) - 1, + &pkey->params[2])) < 0) { gnutls_assert(); asn1_delete_structure(dsa_asn); - _gnutls_mpi_release( &pkey->params[0]); - _gnutls_mpi_release( &pkey->params[1]); + _gnutls_mpi_release(&pkey->params[0]); + _gnutls_mpi_release(&pkey->params[1]); return result; } - if ( (result=_gnutls_x509_read_int( dsa_asn, "dsakey.Y", - str, sizeof(str)-1, &pkey->params[3])) < 0) { + if ((result = _gnutls_x509_read_int(dsa_asn, "dsakey.Y", + str, sizeof(str) - 1, + &pkey->params[3])) < 0) { gnutls_assert(); asn1_delete_structure(dsa_asn); - _gnutls_mpi_release( &pkey->params[0]); - _gnutls_mpi_release( &pkey->params[1]); - _gnutls_mpi_release( &pkey->params[2]); + _gnutls_mpi_release(&pkey->params[0]); + _gnutls_mpi_release(&pkey->params[1]); + _gnutls_mpi_release(&pkey->params[2]); return result; } - if ( (result=_gnutls_x509_read_int( dsa_asn, "dsakey.priv", - str, sizeof(str)-1, &pkey->params[4])) < 0) { + if ((result = _gnutls_x509_read_int(dsa_asn, "dsakey.priv", + str, sizeof(str) - 1, + &pkey->params[4])) < 0) { gnutls_assert(); asn1_delete_structure(dsa_asn); - _gnutls_mpi_release( &pkey->params[0]); - _gnutls_mpi_release( &pkey->params[1]); - _gnutls_mpi_release( &pkey->params[2]); - _gnutls_mpi_release( &pkey->params[3]); + _gnutls_mpi_release(&pkey->params[0]); + _gnutls_mpi_release(&pkey->params[1]); + _gnutls_mpi_release(&pkey->params[2]); + _gnutls_mpi_release(&pkey->params[3]); return result; } pkey->params_size = DSA_PRIVATE_PARAMS; asn1_delete_structure(dsa_asn); - if (gnutls_set_datum( &pkey->raw, raw_key.data, raw_key.size) < 0) { + if (gnutls_set_datum(&pkey->raw, raw_key.data, raw_key.size) < 0) { _gnutls_mpi_release(&pkey->params[0]); _gnutls_mpi_release(&pkey->params[1]); _gnutls_mpi_release(&pkey->params[2]); @@ -185,15 +260,15 @@ int _gnutls_DSAkey2gnutlsKey(gnutls_private_key * pkey, gnutls_datum raw_key) { } -void _gnutls_free_private_key( gnutls_private_key pkey) { -int i; +void _gnutls_free_private_key(gnutls_private_key pkey) +{ + int i; - for (i=0;i