]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Optimized RSA decryption. (Very) Much faster now
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Thu, 28 Mar 2002 09:44:34 +0000 (09:44 +0000)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Thu, 28 Mar 2002 09:44:34 +0000 (09:44 +0000)
lib/auth_rsa.c
lib/gnutls_cert.h
lib/gnutls_pk.c
lib/gnutls_privkey.c

index 6b3c77d84e4a56aaca346fac30d27ec104c19cc3..f33a7ba10a1803087736b3293a7d8860e3f41ec6 100644 (file)
@@ -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 */
index 3762ede75e5b0a80cee0ef2419d3e22abe761da4..719355c677622a52db7346eebcde95fa0fa17da2 100644 (file)
@@ -5,15 +5,16 @@
 #include <x509_asn1.h>
 #include <gnutls_ui.h>
 
-#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
index c490347e26604f29556cbbd64dc3932dd32f42f3..fdd08b64b0bca3c23d8cbf8a692aa92f8f2b74a7 100644 (file)
@@ -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 
index 3a060629e4eae1d2b978cb6c8270c6bd23c1ba12..5410373cac87ea194f24d3db3c328e0b8d7bc13d 100644 (file)
 /* 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<pkey.params_size;i++) {
-               _gnutls_mpi_release( &pkey.params[i]);
+       for (i = 0; i < pkey.params_size; i++) {
+               _gnutls_mpi_release(&pkey.params[i]);
        }
 
-       gnutls_free_datum( &pkey.raw);
+       gnutls_free_datum(&pkey.raw);
 
        return;
 }
-