From: Bodo Möller Date: Mon, 28 Oct 2002 14:02:19 +0000 (+0000) Subject: clean up new code for NIST primes X-Git-Tag: OpenSSL_0_9_7-beta4~18^2~109 X-Git-Url: https://git.openssl.org/?a=commitdiff_plain;h=19b8d06a7911d41ce8b3e347b4f58878e12d92ff;hp=5c6bf03117a26942327f43d02e9113e9870f7aba;p=openssl.git clean up new code for NIST primes create new lock CRYPTO_LOCK_BN to avoid race condition --- diff --git a/CHANGES b/CHANGES index c22b94553a..31ee94bff5 100644 --- a/CHANGES +++ b/CHANGES @@ -10,6 +10,9 @@ if applicable. [Nils Larsch ] + *) Add new lock type (CRYPTO_LOCK_BN). + [Bodo Moeller] + *) Change the ENGINE framework to automatically load engines dynamically from specific directories unless they could be found to already be built in or loaded. Move all the diff --git a/crypto/bn/bn.h b/crypto/bn/bn.h index 21a1a90143..2f203fe3a9 100644 --- a/crypto/bn/bn.h +++ b/crypto/bn/bn.h @@ -547,14 +547,6 @@ BIGNUM *bn_dup_expand(const BIGNUM *a, int words); } \ } -#define bn_clear_top2max(a) \ - { \ - int index = (a)->dmax - (a)->top; \ - BN_ULONG *ftl = &(a)->d[(a)->top-1]; \ - for (; index != 0; index--) \ - *(++ftl) = 0x0; \ - } - BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w); BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w); void bn_sqr_words(BN_ULONG *rp, const BN_ULONG *ap, int num); diff --git a/crypto/bn/bn_lcl.h b/crypto/bn/bn_lcl.h index 8a4dba375a..090a7a0d00 100644 --- a/crypto/bn/bn_lcl.h +++ b/crypto/bn/bn_lcl.h @@ -239,6 +239,16 @@ struct bignum_ctx #define Lw(t) (((BN_ULONG)(t))&BN_MASK2) #define Hw(t) (((BN_ULONG)((t)>>BN_BITS2))&BN_MASK2) + +#define bn_clear_top2max(a) \ + { \ + int index = (a)->dmax - (a)->top; \ + BN_ULONG *ftl = &(a)->d[(a)->top-1]; \ + for (; index != 0; index--) \ + *(++ftl) = 0x0; \ + } + + /* This is used for internal error checking and is not normally used */ #ifdef BN_DEBUG # include diff --git a/crypto/bn/bn_nist.c b/crypto/bn/bn_nist.c index 4e21a05456..19bd540725 100644 --- a/crypto/bn/bn_nist.c +++ b/crypto/bn/bn_nist.c @@ -54,11 +54,12 @@ */ #include "bn_lcl.h" +#include "cryptlib.h" #define BN_NIST_192_TOP (192+BN_BITS2-1)/BN_BITS2 #define BN_NIST_224_TOP (224+BN_BITS2-1)/BN_BITS2 #define BN_NIST_256_TOP (256+BN_BITS2-1)/BN_BITS2 -#define BN_NIST_384_TOP (384+BN_BITS2-1)/BN_BITS2 +#define BN_NIST_384_TOP (384+BN_BITS2-1)/BN_BITS2 #define BN_NIST_521_TOP (521+BN_BITS2-1)/BN_BITS2 #if BN_BITS2 == 64 @@ -314,7 +315,7 @@ int BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, if (top == 0) return BN_zero(r); else if (top > 0) - return (r == a)? 1 : !!BN_copy(r ,a); + return (r == a)? 1 : (BN_copy(r ,a) != NULL); if (r != a) if (!BN_ncopy(r, a, BN_NIST_192_TOP)) @@ -353,7 +354,7 @@ int BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, } r->top = BN_NIST_192_TOP; -#if 0 +#if 1 bn_clear_top2max(r); #endif bn_fix_top(r); @@ -393,7 +394,7 @@ int BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, if (tmp_int == 0) return BN_zero(r); else if (tmp_int > 0) - return (r == a)? 1 : !!BN_copy(r ,a); + return (r == a)? 1 : (BN_copy(r ,a) != NULL); if (r != a) if (!BN_ncopy(r, a, BN_NIST_224_TOP)) @@ -445,7 +446,7 @@ int BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, } r->top = BN_NIST_224_TOP; -#if 0 +#if 1 bn_clear_top2max(r); #endif bn_fix_top(r); @@ -503,13 +504,20 @@ int BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, BN_32_BIT_BUF(14) BN_32_BIT_BUF(15) if (!_is_set_256_data) - _init_256_data(); - + { + CRYPTO_w_lock(CRYPTO_LOCK_BN); + + if (!_is_set_256_data) + _init_256_data(); + + CRYPTO_w_unlock(CRYPTO_LOCK_BN); + } + tmp_int = BN_ucmp(field, a); if (tmp_int == 0) return BN_zero(r); else if (tmp_int > 0) - return (r == a)? 1 : !!BN_copy(r ,a); + return (r == a)? 1 : (BN_copy(r ,a) != NULL); if (r != a) if (!BN_ncopy(r, a, BN_NIST_256_TOP)) @@ -596,7 +604,7 @@ int BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, } r->top = BN_NIST_256_TOP; -#if 0 +#if 1 bn_clear_top2max(r); #endif bn_fix_top(r); @@ -657,13 +665,20 @@ int BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, BN_32_BIT_BUF(22) BN_32_BIT_BUF(23) if (!_is_set_384_data) - _init_384_data(); + { + CRYPTO_w_lock(CRYPTO_LOCK_BN); + + if (!_is_set_384_data) + _init_384_data(); + + CRYPTO_w_unlock(CRYPTO_LOCK_BN); + } tmp_int = BN_ucmp(field, a); if (tmp_int == 0) return BN_zero(r); else if (tmp_int > 0) - return (r == a)? 1 : !!BN_copy(r ,a); + return (r == a)? 1 : (BN_copy(r ,a) != NULL); if (r != a) if (!BN_ncopy(r, a, BN_NIST_384_TOP)) @@ -757,7 +772,7 @@ int BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, } r->top = BN_NIST_384_TOP; -#if 0 +#if 1 bn_clear_top2max(r); #endif bn_fix_top(r); @@ -793,7 +808,7 @@ int BN_nist_mod_521(BIGNUM *r, const BIGNUM *a, const BIGNUM *field, top = a->top; if (top < BN_NIST_521_TOP || ( top == BN_NIST_521_TOP && (!(a->d[BN_NIST_521_TOP-1] & ~(BN_NIST_521_TOP_MASK))))) - return (r == a)? 1 : !!BN_copy(r ,a); + return (r == a)? 1 : (BN_copy(r ,a) != NULL); BN_CTX_start(ctx); tmp = BN_CTX_get(ctx); diff --git a/crypto/cryptlib.c b/crypto/cryptlib.c index 5d8debd2c8..e16bbc6626 100644 --- a/crypto/cryptlib.c +++ b/crypto/cryptlib.c @@ -1,4 +1,57 @@ /* crypto/cryptlib.c */ +/* ==================================================================== + * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -112,7 +165,8 @@ static const char* lock_names[CRYPTO_NUM_LOCKS] = "ecdsa", "ec", "ecdh", -#if CRYPTO_NUM_LOCKS != 35 + "bn", +#if CRYPTO_NUM_LOCKS != 36 # error "Inconsistency between crypto.h and cryptlib.c" #endif }; diff --git a/crypto/crypto.h b/crypto/crypto.h index 1490db9aa4..f87262f517 100644 --- a/crypto/crypto.h +++ b/crypto/crypto.h @@ -1,4 +1,57 @@ /* crypto/crypto.h */ +/* ==================================================================== + * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -135,7 +188,8 @@ extern "C" { #define CRYPTO_LOCK_ECDSA 32 #define CRYPTO_LOCK_EC 33 #define CRYPTO_LOCK_ECDH 34 -#define CRYPTO_NUM_LOCKS 35 +#define CRYPTO_LOCK_BN 35 +#define CRYPTO_NUM_LOCKS 36 #define CRYPTO_LOCK 1 #define CRYPTO_UNLOCK 2 diff --git a/crypto/ec/ec.h b/crypto/ec/ec.h index 5abef25f09..1cd6d34b5a 100644 --- a/crypto/ec/ec.h +++ b/crypto/ec/ec.h @@ -486,6 +486,8 @@ void ERR_load_EC_strings(void); #define EC_R_INVALID_PRIVATE_KEY 123 #define EC_R_MISSING_PARAMETERS 124 #define EC_R_MISSING_PRIVATE_KEY 125 +#define EC_R_NOT_A_NIST_PRIME 135 +#define EC_R_NOT_A_SUPPORTED_NIST_PRIME 136 #define EC_R_NOT_IMPLEMENTED 126 #define EC_R_NOT_INITIALIZED 111 #define EC_R_NO_FIELD_MOD 133 @@ -494,7 +496,6 @@ void ERR_load_EC_strings(void); #define EC_R_PKPARAMETERS2GROUP_FAILURE 127 #define EC_R_POINT_AT_INFINITY 106 #define EC_R_POINT_IS_NOT_ON_CURVE 107 -#define EC_R_PRIME_IS_NOT_A_NIST_PRIME 135 #define EC_R_SLOT_FULL 108 #define EC_R_UNDEFINED_GENERATOR 113 #define EC_R_UNDEFINED_ORDER 128 diff --git a/crypto/ec/ec_cvt.c b/crypto/ec/ec_cvt.c index 20782569a9..7571a3c368 100644 --- a/crypto/ec/ec_cvt.c +++ b/crypto/ec/ec_cvt.c @@ -99,9 +99,25 @@ EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM if (!EC_GROUP_set_curve_GFp(ret, p, a, b, ctx)) { - /* remove the last error code form the error queue */ - ERR_get_error(); - /* try the normal mont method */ + unsigned long err; + + err = ERR_peek_last_error(); + + if (!(ERR_GET_LIB(err) == ERR_LIB_EC && + ((ERR_GET_REASON(err) == EC_R_NOT_A_NIST_PRIME) || + (ERR_GET_REASON(err) == EC_R_NOT_A_SUPPORTED_NIST_PRIME)))) + { + /* real error */ + + EC_GROUP_clear_free(ret); + return NULL; + } + + + /* not an actual error, we just cannot use EC_GFp_nist_method */ + + ERR_clear_error(); + EC_GROUP_clear_free(ret); meth = EC_GFp_mont_method(); @@ -119,6 +135,7 @@ EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM return ret; } + EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { const EC_METHOD *meth; diff --git a/crypto/ec/ec_err.c b/crypto/ec/ec_err.c index 71b1dcff22..58ae9d682d 100644 --- a/crypto/ec/ec_err.c +++ b/crypto/ec/ec_err.c @@ -195,6 +195,8 @@ static ERR_STRING_DATA EC_str_reasons[]= {EC_R_INVALID_PRIVATE_KEY ,"invalid private key"}, {EC_R_MISSING_PARAMETERS ,"missing parameters"}, {EC_R_MISSING_PRIVATE_KEY ,"missing private key"}, +{EC_R_NOT_A_NIST_PRIME ,"not a NIST prime"}, +{EC_R_NOT_A_SUPPORTED_NIST_PRIME ,"not a supported NIST prime"}, {EC_R_NOT_IMPLEMENTED ,"not implemented"}, {EC_R_NOT_INITIALIZED ,"not initialized"}, {EC_R_NO_FIELD_MOD ,"no field mod"}, @@ -203,7 +205,6 @@ static ERR_STRING_DATA EC_str_reasons[]= {EC_R_PKPARAMETERS2GROUP_FAILURE ,"pkparameters2group failure"}, {EC_R_POINT_AT_INFINITY ,"point at infinity"}, {EC_R_POINT_IS_NOT_ON_CURVE ,"point is not on curve"}, -{EC_R_PRIME_IS_NOT_A_NIST_PRIME ,"prime is not a nist prime"}, {EC_R_SLOT_FULL ,"slot full"}, {EC_R_UNDEFINED_GENERATOR ,"undefined generator"}, {EC_R_UNDEFINED_ORDER ,"undefined order"}, diff --git a/crypto/ec/ec_lcl.h b/crypto/ec/ec_lcl.h index 247c985a23..639d1743ec 100644 --- a/crypto/ec/ec_lcl.h +++ b/crypto/ec/ec_lcl.h @@ -227,6 +227,7 @@ struct ec_group_st { void *field_data1; /* method-specific (e.g., Montgomery structure) */ void *field_data2; /* method-specific */ + int (*field_mod_func)(BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *); /* method-specific */ } /* EC_GROUP */; diff --git a/crypto/ec/ecp_nist.c b/crypto/ec/ecp_nist.c index 3c2b4fa978..fb43510d52 100644 --- a/crypto/ec/ecp_nist.c +++ b/crypto/ec/ecp_nist.c @@ -109,9 +109,6 @@ const EC_METHOD *EC_GFp_nist_method(void) return &ret; } -#define ECP_MOD_CAST \ - (int (*)(BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *)) - #if BN_BITS2 == 64 && UINT_MAX != 4294967295UL && ULONG_MAX != 4294967295UL #define NO_32_BIT_TYPE #endif @@ -155,31 +152,34 @@ int ec_GFp_nist_group_set_curve(EC_GROUP *group, const BIGNUM *p, if ((tmp_bn = BN_CTX_get(ctx)) == NULL) goto err; if (BN_ucmp(BN_get0_nist_prime_192(), p) == 0) - group->field_data1 = (void *)BN_nist_mod_192; + group->field_mod_func = BN_nist_mod_192; else if (BN_ucmp(BN_get0_nist_prime_224(), p) == 0) -#if !defined(ECP_NO_32_BIT_TYPE) || defined(OPENSSL_NO_ASM) - group->field_data1 = (void *)BN_nist_mod_224; +#if !defined(NO_32_BIT_TYPE) || defined(OPENSSL_NO_ASM) + group->field_mod_func = BN_nist_mod_224; #else + ECerr(EC_F_EC_GFP_NIST_GROUP_SET_CURVE_GFP, EC_R_NOT_A_SUPPORTED_NIST_PRIME); goto err; #endif else if (BN_ucmp(BN_get0_nist_prime_256(), p) == 0) -#if !defined(ECP_NO_32_BIT_TYPE) || defined(OPENSSL_NO_ASM) - group->field_data1 = (void *)BN_nist_mod_256; +#if !defined(NO_32_BIT_TYPE) || defined(OPENSSL_NO_ASM) + group->field_mod_func = BN_nist_mod_256; #else + ECerr(EC_F_EC_GFP_NIST_GROUP_SET_CURVE_GFP, EC_R_NOT_A_SUPPORTED_NIST_PRIME); goto err; #endif else if (BN_ucmp(BN_get0_nist_prime_384(), p) == 0) -#if !defined(ECP_NO_32_BIT_TYPE) || defined(OPENSSL_NO_ASM) - group->field_data1 = (void *)BN_nist_mod_384; +#if !defined(NO_32_BIT_TYPE) || defined(OPENSSL_NO_ASM) + group->field_mod_func = BN_nist_mod_384; #else + ECerr(EC_F_EC_GFP_NIST_GROUP_SET_CURVE_GFP, EC_R_NOT_A_SUPPORTED_NIST_PRIME); goto err; #endif else if (BN_ucmp(BN_get0_nist_prime_521(), p) == 0) - group->field_data1 = (void *)BN_nist_mod_521; + /* this one works in the NO_32_BIT_TYPE case */ + group->field_mod_func = BN_nist_mod_521; else { - ECerr(EC_F_EC_GFP_NIST_GROUP_SET_CURVE_GFP, - EC_R_PRIME_IS_NOT_A_NIST_PRIME); + ECerr(EC_F_EC_GFP_NIST_GROUP_SET_CURVE_GFP, EC_R_NOT_A_NIST_PRIME); goto err; } @@ -188,10 +188,10 @@ int ec_GFp_nist_group_set_curve(EC_GROUP *group, const BIGNUM *p, group->field.neg = 0; /* group->a */ - (ECP_MOD_CAST group->field_data1)(&group->a, a, p, ctx); + if (!group->field_mod_func(&group->a, a, p, ctx)) goto err; /* group->b */ - (ECP_MOD_CAST group->field_data1)(&group->b, b, p, ctx); + if (!group->field_mod_func(&group->b, b, p, ctx)) goto err; /* group->a_is_minus3 */ if (!BN_add_word(tmp_bn, 3)) goto err; @@ -242,7 +242,7 @@ int ec_GFp_nist_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, if ((ctx_new = ctx = BN_CTX_new()) == NULL) goto err; if (!BN_mul(r, a, b, ctx)) goto err; - if (!(ECP_MOD_CAST group->field_data1)(r, r, &group->field, ctx)) + if (!group->field_mod_func(r, r, &group->field, ctx)) goto err; ret=1; @@ -267,7 +267,7 @@ int ec_GFp_nist_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, if ((ctx_new = ctx = BN_CTX_new()) == NULL) goto err; if (!BN_sqr(r, a, ctx)) goto err; - if (!(ECP_MOD_CAST group->field_data1)(r, r, &group->field, ctx)) + if (!group->field_mod_func(r, r, &group->field, ctx)) goto err; ret=1;