diff options
author | Geoff Thorpe <geoff@openssl.org> | 2008-04-27 18:41:23 +0000 |
---|---|---|
committer | Geoff Thorpe <geoff@openssl.org> | 2008-04-27 18:41:23 +0000 |
commit | 5ee6f96cea73f39b2b391b001d755b94c763e2d4 (patch) | |
tree | f65d6a67caa40c16f2c22649ef5878f42d36dfe1 /engines/e_gmp.c | |
parent | dc634aff252943c5f61fa1a245a4206259cf941f (diff) |
Paul Sheer optimised the OpenSSL to/from libGMP conversions for the case
where they both use the same limb size. I've tweaked his patch slightly, so
blame me if it breaks.
Submitted by: Paul Sheer
Reviewed by: Geoff Thorpe
Diffstat (limited to 'engines/e_gmp.c')
-rw-r--r-- | engines/e_gmp.c | 66 |
1 files changed, 51 insertions, 15 deletions
diff --git a/engines/e_gmp.c b/engines/e_gmp.c index 3b1f4b9cb9..97bc2142a1 100644 --- a/engines/e_gmp.c +++ b/engines/e_gmp.c @@ -85,6 +85,8 @@ #include <openssl/crypto.h> #include <openssl/buffer.h> #include <openssl/engine.h> +#include <openssl/rsa.h> +#include <openssl/bn.h> #ifndef OPENSSL_NO_HW #ifndef OPENSSL_NO_GMP @@ -251,27 +253,61 @@ static int e_gmp_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void)) return to_return; } -/* HACK - use text I/O functions in openssl and GMP to handle conversions. This - * is vile. */ + +/* Most often limb sizes will be the same. If not, we use hex conversion + * which is neat, but extremely inefficient. */ static int bn2gmp(const BIGNUM *bn, mpz_t g) { - int toret; - char *tmpchar = BN_bn2hex(bn); - if(!tmpchar) return 0; - toret = (mpz_set_str(g, tmpchar, 16) == 0 ? 1 : 0); - OPENSSL_free(tmpchar); - return toret; + bn_check_top(bn); + if(((sizeof(bn->d[0]) * 8) == GMP_NUMB_BITS) && + (BN_BITS2 == GMP_NUMB_BITS)) + { + /* The common case */ + if(!_mpz_realloc (g, bn->top)) + return 0; + memcpy(&g->_mp_d[0], &bn->d[0], bn->top * sizeof(bn->d[0])); + g->_mp_size = bn->top; + if(bn->neg) + g->_mp_size = -g->_mp_size; + return 1; + } + else + { + int toret; + char *tmpchar = BN_bn2hex(bn); + if(!tmpchar) return 0; + toret = (mpz_set_str(g, tmpchar, 16) == 0 ? 1 : 0); + OPENSSL_free(tmpchar); + return toret; + } } static int gmp2bn(mpz_t g, BIGNUM *bn) { - int toret; - char *tmpchar = OPENSSL_malloc(mpz_sizeinbase(g, 16) + 10); - if(!tmpchar) return 0; - mpz_get_str(tmpchar, 16, g); - toret = BN_hex2bn(&bn, tmpchar); - OPENSSL_free(tmpchar); - return toret; + if(((sizeof(bn->d[0]) * 8) == GMP_NUMB_BITS) && + (BN_BITS2 == GMP_NUMB_BITS)) + { + /* The common case */ + int s = (g->_mp_size >= 0) ? g->_mp_size : -g->_mp_size; + BN_zero(bn); + if(bn_expand2 (bn, s) == NULL) + return 0; + bn->top = s; + memcpy(&bn->d[0], &g->_mp_d[0], s * sizeof(bn->d[0])); + bn_correct_top(bn); + bn->neg = g->_mp_size >= 0 ? 0 : 1; + return 1; + } + else + { + int toret; + char *tmpchar = OPENSSL_malloc(mpz_sizeinbase(g, 16) + 10); + if(!tmpchar) return 0; + mpz_get_str(tmpchar, 16, g); + toret = BN_hex2bn(&bn, tmpchar); + OPENSSL_free(tmpchar); + return toret; + } } #ifndef OPENSSL_NO_RSA |