summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorjsing <>2023-03-08 05:35:51 +0000
committerjsing <>2023-03-08 05:35:51 +0000
commit803622911687b70848ed5277f86819fe63f7c372 (patch)
treeafede466818a45660427347494e39a5c69a48c47 /src/lib
parent8d29cc48fbbf1116295d560fac3a0b9be6f4c15e (diff)
downloadopenbsd-803622911687b70848ed5277f86819fe63f7c372.tar.gz
openbsd-803622911687b70848ed5277f86819fe63f7c372.tar.bz2
openbsd-803622911687b70848ed5277f86819fe63f7c372.zip
Stop trying to use EC_GFp_nist_method().
Currently, if compiled without OPENSSL_BN_ASM_MONT, EC_GROUP_new_curve_GFp() tries to use EC_GFp_nist_method(), falling back to EC_GFp_mont_method() if it is not a NIST curve (if OPENSSL_BN_ASM_MONT is defined we use EC_GFp_mont_method() unconditionally). Now that we have a reasonable non-assembly Montgomery implementation, the performance of EC_GFp_nist_method() is either similar or slower than EC_GFp_mont_method() (the exception being P-521, however if you're using that you're not doing it for performance reasons anyway). The EC_GFp_nist_method() uses rather scary BN NIST code (which would probably already be removed, if not for the BN and EC public APIs), it uses code paths that are currently less constant time, and there is additional overhead in checking to see if the curve is actually supported. Stop trying to use EC_GFp_nist_method() and unconditionally use EC_GFp_mont_method() in all cases. While here, factor out the common setup code and call it from both EC_GROUP_new_curve_GFp() and EC_GROUP_new_curve_GF2m(). ok beck@ tb@
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/libcrypto/ec/ec_cvt.c96
1 files changed, 20 insertions, 76 deletions
diff --git a/src/lib/libcrypto/ec/ec_cvt.c b/src/lib/libcrypto/ec/ec_cvt.c
index 365ca1aa7e..fff9ab99cb 100644
--- a/src/lib/libcrypto/ec/ec_cvt.c
+++ b/src/lib/libcrypto/ec/ec_cvt.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ec_cvt.c,v 1.8 2022/11/26 16:08:52 tb Exp $ */ 1/* $OpenBSD: ec_cvt.c,v 1.9 2023/03/08 05:35:51 jsing Exp $ */
2/* 2/*
3 * Originally written by Bodo Moeller for the OpenSSL project. 3 * Originally written by Bodo Moeller for the OpenSSL project.
4 */ 4 */
@@ -74,74 +74,31 @@
74#include <openssl/err.h> 74#include <openssl/err.h>
75#include "ec_local.h" 75#include "ec_local.h"
76 76
77EC_GROUP * 77static EC_GROUP *
78EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, 78ec_group_new_curve(const EC_METHOD *method, const BIGNUM *p, const BIGNUM *a,
79 BN_CTX *ctx) 79 const BIGNUM *b, BN_CTX *ctx)
80{ 80{
81 const EC_METHOD *meth; 81 EC_GROUP *group;
82 EC_GROUP *ret;
83
84#if defined(OPENSSL_BN_ASM_MONT)
85 /*
86 * This might appear controversial, but the fact is that generic
87 * prime method was observed to deliver better performance even
88 * for NIST primes on a range of platforms, e.g.: 60%-15%
89 * improvement on IA-64, ~25% on ARM, 30%-90% on P4, 20%-25%
90 * in 32-bit build and 35%--12% in 64-bit build on Core2...
91 * Coefficients are relative to optimized bn_nist.c for most
92 * intensive ECDSA verify and ECDH operations for 192- and 521-
93 * bit keys respectively. Choice of these boundary values is
94 * arguable, because the dependency of improvement coefficient
95 * from key length is not a "monotone" curve. For example while
96 * 571-bit result is 23% on ARM, 384-bit one is -1%. But it's
97 * generally faster, sometimes "respectfully" faster, sometimes
98 * "tolerably" slower... What effectively happens is that loop
99 * with bn_mul_add_words is put against bn_mul_mont, and the
100 * latter "wins" on short vectors. Correct solution should be
101 * implementing dedicated NxN multiplication subroutines for
102 * small N. But till it materializes, let's stick to generic
103 * prime method...
104 * <appro>
105 */
106 meth = EC_GFp_mont_method();
107#else
108 meth = EC_GFp_nist_method();
109#endif
110
111 ret = EC_GROUP_new(meth);
112 if (ret == NULL)
113 return NULL;
114
115 if (!EC_GROUP_set_curve(ret, p, a, b, ctx)) {
116 unsigned long err;
117
118 err = ERR_peek_last_error();
119 82
120 if (!(ERR_GET_LIB(err) == ERR_LIB_EC && 83 if ((group = EC_GROUP_new(method)) == NULL)
121 ((ERR_GET_REASON(err) == EC_R_NOT_A_NIST_PRIME) || 84 goto err;
122 (ERR_GET_REASON(err) == EC_R_NOT_A_SUPPORTED_NIST_PRIME)))) {
123 /* real error */
124 85
125 EC_GROUP_clear_free(ret); 86 if (!EC_GROUP_set_curve(group, p, a, b, ctx))
126 return NULL; 87 goto err;
127 }
128 /* not an actual error, we just cannot use EC_GFp_nist_method */
129 88
130 ERR_clear_error(); 89 return group;
131 90
132 EC_GROUP_clear_free(ret); 91 err:
133 meth = EC_GFp_mont_method(); 92 EC_GROUP_clear_free(group);
134 93
135 ret = EC_GROUP_new(meth); 94 return NULL;
136 if (ret == NULL) 95}
137 return NULL;
138 96
139 if (!EC_GROUP_set_curve(ret, p, a, b, ctx)) { 97EC_GROUP *
140 EC_GROUP_clear_free(ret); 98EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b,
141 return NULL; 99 BN_CTX *ctx)
142 } 100{
143 } 101 return ec_group_new_curve(EC_GFp_mont_method(), p, a, b, ctx);
144 return ret;
145} 102}
146 103
147#ifndef OPENSSL_NO_EC2M 104#ifndef OPENSSL_NO_EC2M
@@ -149,19 +106,6 @@ EC_GROUP *
149EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, 106EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b,
150 BN_CTX *ctx) 107 BN_CTX *ctx)
151{ 108{
152 const EC_METHOD *meth; 109 return ec_group_new_curve(EC_GF2m_simple_method(), p, a, b, ctx);
153 EC_GROUP *ret;
154
155 meth = EC_GF2m_simple_method();
156
157 ret = EC_GROUP_new(meth);
158 if (ret == NULL)
159 return NULL;
160
161 if (!EC_GROUP_set_curve(ret, p, a, b, ctx)) {
162 EC_GROUP_clear_free(ret);
163 return NULL;
164 }
165 return ret;
166} 110}
167#endif 111#endif