diff options
author | tb <> | 2018-11-17 18:46:43 +0000 |
---|---|---|
committer | tb <> | 2018-11-17 18:46:43 +0000 |
commit | e62c65b7027fd19c83f1f0a8228cea389f0f329d (patch) | |
tree | 7e438079e24bfc85d16d7115569b7e6ddd73433a | |
parent | b4a1f1ba7fd6ed7aa2bd88d8973d2c7c031fd911 (diff) | |
download | openbsd-e62c65b7027fd19c83f1f0a8228cea389f0f329d.tar.gz openbsd-e62c65b7027fd19c83f1f0a8228cea389f0f329d.tar.bz2 openbsd-e62c65b7027fd19c83f1f0a8228cea389f0f329d.zip |
Use a blinding value when generating DSA and ECDSA signatures, in order to
reduce the possibility of a side-channel attack leaking the private key.
OpenBSD 6.3 errata 022
-rw-r--r-- | src/lib/libcrypto/dsa/dsa_ossl.c | 48 | ||||
-rw-r--r-- | src/lib/libcrypto/ecdsa/ecs_ossl.c | 79 |
2 files changed, 104 insertions, 23 deletions
diff --git a/src/lib/libcrypto/dsa/dsa_ossl.c b/src/lib/libcrypto/dsa/dsa_ossl.c index 4e75512df8..f29821059f 100644 --- a/src/lib/libcrypto/dsa/dsa_ossl.c +++ b/src/lib/libcrypto/dsa/dsa_ossl.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: dsa_ossl.c,v 1.30.2.1 2018/06/13 15:08:08 jsing Exp $ */ | 1 | /* $OpenBSD: dsa_ossl.c,v 1.30.2.2 2018/11/17 18:46:43 tb Exp $ */ |
2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
@@ -94,16 +94,17 @@ DSA_OpenSSL(void) | |||
94 | static DSA_SIG * | 94 | static DSA_SIG * |
95 | dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) | 95 | dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) |
96 | { | 96 | { |
97 | BIGNUM *kinv = NULL, *r = NULL, *s = NULL; | 97 | BIGNUM b, bm, bxr, binv, m, *kinv = NULL, *r = NULL, *s = NULL; |
98 | BIGNUM m; | ||
99 | BIGNUM xr; | ||
100 | BN_CTX *ctx = NULL; | 98 | BN_CTX *ctx = NULL; |
101 | int reason = ERR_R_BN_LIB; | 99 | int reason = ERR_R_BN_LIB; |
102 | DSA_SIG *ret = NULL; | 100 | DSA_SIG *ret = NULL; |
103 | int noredo = 0; | 101 | int noredo = 0; |
104 | 102 | ||
103 | BN_init(&b); | ||
104 | BN_init(&binv); | ||
105 | BN_init(&bm); | ||
106 | BN_init(&bxr); | ||
105 | BN_init(&m); | 107 | BN_init(&m); |
106 | BN_init(&xr); | ||
107 | 108 | ||
108 | if (!dsa->p || !dsa->q || !dsa->g) { | 109 | if (!dsa->p || !dsa->q || !dsa->g) { |
109 | reason = DSA_R_MISSING_PARAMETERS; | 110 | reason = DSA_R_MISSING_PARAMETERS; |
@@ -139,10 +140,36 @@ redo: | |||
139 | if (BN_bin2bn(dgst,dlen,&m) == NULL) | 140 | if (BN_bin2bn(dgst,dlen,&m) == NULL) |
140 | goto err; | 141 | goto err; |
141 | 142 | ||
142 | /* Compute s = inv(k) (m + xr) mod q */ | 143 | /* |
143 | if (!BN_mod_mul(&xr, dsa->priv_key, r, dsa->q, ctx)) /* s = xr */ | 144 | * Compute: |
145 | * | ||
146 | * s = inv(k)(m + xr) mod q | ||
147 | * | ||
148 | * In order to reduce the possibility of a side-channel attack, the | ||
149 | * following is calculated using a blinding value: | ||
150 | * | ||
151 | * s = inv(k)inv(b)(bm + bxr) mod q | ||
152 | * | ||
153 | * Where b is a random value in the range [1, q-1]. | ||
154 | */ | ||
155 | if (!BN_sub(&bm, dsa->q, BN_value_one())) | ||
156 | goto err; | ||
157 | if (!BN_rand_range(&b, &bm)) | ||
158 | goto err; | ||
159 | if (!BN_add(&b, &b, BN_value_one())) | ||
160 | goto err; | ||
161 | if (BN_mod_inverse_ct(&binv, &b, dsa->q, ctx) == NULL) | ||
162 | goto err; | ||
163 | |||
164 | if (!BN_mod_mul(&bxr, &b, dsa->priv_key, dsa->q, ctx)) /* bx */ | ||
165 | goto err; | ||
166 | if (!BN_mod_mul(&bxr, &bxr, r, dsa->q, ctx)) /* bxr */ | ||
167 | goto err; | ||
168 | if (!BN_mod_mul(&bm, &b, &m, dsa->q, ctx)) /* bm */ | ||
169 | goto err; | ||
170 | if (!BN_mod_add(s, &bxr, &bm, dsa->q, ctx)) /* s = bm + bxr */ | ||
144 | goto err; | 171 | goto err; |
145 | if (!BN_mod_add(s, &xr, &m, dsa->q, ctx)) /* s = m + xr */ | 172 | if (!BN_mod_mul(s, s, &binv, dsa->q, ctx)) /* s = m + xr */ |
146 | goto err; | 173 | goto err; |
147 | if (!BN_mod_mul(s, s, kinv, dsa->q, ctx)) | 174 | if (!BN_mod_mul(s, s, kinv, dsa->q, ctx)) |
148 | goto err; | 175 | goto err; |
@@ -171,8 +198,11 @@ err: | |||
171 | BN_free(s); | 198 | BN_free(s); |
172 | } | 199 | } |
173 | BN_CTX_free(ctx); | 200 | BN_CTX_free(ctx); |
201 | BN_clear_free(&b); | ||
202 | BN_clear_free(&bm); | ||
203 | BN_clear_free(&bxr); | ||
204 | BN_clear_free(&binv); | ||
174 | BN_clear_free(&m); | 205 | BN_clear_free(&m); |
175 | BN_clear_free(&xr); | ||
176 | BN_clear_free(kinv); | 206 | BN_clear_free(kinv); |
177 | return ret; | 207 | return ret; |
178 | } | 208 | } |
diff --git a/src/lib/libcrypto/ecdsa/ecs_ossl.c b/src/lib/libcrypto/ecdsa/ecs_ossl.c index 09f3bf8416..75ecb19557 100644 --- a/src/lib/libcrypto/ecdsa/ecs_ossl.c +++ b/src/lib/libcrypto/ecdsa/ecs_ossl.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ecs_ossl.c,v 1.9.2.1 2018/06/13 15:08:08 jsing Exp $ */ | 1 | /* $OpenBSD: ecs_ossl.c,v 1.9.2.2 2018/11/17 18:46:43 tb Exp $ */ |
2 | /* | 2 | /* |
3 | * Written by Nils Larsch for the OpenSSL project | 3 | * Written by Nils Larsch for the OpenSSL project |
4 | */ | 4 | */ |
@@ -204,14 +204,14 @@ static ECDSA_SIG * | |||
204 | ecdsa_do_sign(const unsigned char *dgst, int dgst_len, | 204 | ecdsa_do_sign(const unsigned char *dgst, int dgst_len, |
205 | const BIGNUM *in_kinv, const BIGNUM *in_r, EC_KEY *eckey) | 205 | const BIGNUM *in_kinv, const BIGNUM *in_r, EC_KEY *eckey) |
206 | { | 206 | { |
207 | int ok = 0, i; | 207 | BIGNUM *b = NULL, *binv = NULL, *bm = NULL, *bxr = NULL; |
208 | BIGNUM *kinv = NULL, *s, *m = NULL, *tmp = NULL, *order = NULL; | 208 | BIGNUM *kinv = NULL, *m = NULL, *order = NULL, *range = NULL, *s; |
209 | const BIGNUM *ckinv; | 209 | const BIGNUM *ckinv, *priv_key; |
210 | BN_CTX *ctx = NULL; | 210 | BN_CTX *ctx = NULL; |
211 | const EC_GROUP *group; | 211 | const EC_GROUP *group; |
212 | ECDSA_SIG *ret; | 212 | ECDSA_SIG *ret; |
213 | ECDSA_DATA *ecdsa; | 213 | ECDSA_DATA *ecdsa; |
214 | const BIGNUM *priv_key; | 214 | int ok = 0, i; |
215 | 215 | ||
216 | ecdsa = ecdsa_check(eckey); | 216 | ecdsa = ecdsa_check(eckey); |
217 | group = EC_KEY_get0_group(eckey); | 217 | group = EC_KEY_get0_group(eckey); |
@@ -230,7 +230,9 @@ ecdsa_do_sign(const unsigned char *dgst, int dgst_len, | |||
230 | s = ret->s; | 230 | s = ret->s; |
231 | 231 | ||
232 | if ((ctx = BN_CTX_new()) == NULL || (order = BN_new()) == NULL || | 232 | if ((ctx = BN_CTX_new()) == NULL || (order = BN_new()) == NULL || |
233 | (tmp = BN_new()) == NULL || (m = BN_new()) == NULL) { | 233 | (range = BN_new()) == NULL || (b = BN_new()) == NULL || |
234 | (binv = BN_new()) == NULL || (bm = BN_new()) == NULL || | ||
235 | (bxr = BN_new()) == NULL || (m = BN_new()) == NULL) { | ||
234 | ECDSAerror(ERR_R_MALLOC_FAILURE); | 236 | ECDSAerror(ERR_R_MALLOC_FAILURE); |
235 | goto err; | 237 | goto err; |
236 | } | 238 | } |
@@ -269,11 +271,53 @@ ecdsa_do_sign(const unsigned char *dgst, int dgst_len, | |||
269 | } | 271 | } |
270 | } | 272 | } |
271 | 273 | ||
272 | if (!BN_mod_mul(tmp, priv_key, ret->r, order, ctx)) { | 274 | /* |
275 | * Compute s = inv(k)(m + xr) mod order. | ||
276 | * | ||
277 | * In order to reduce the possibility of a side-channel attack, | ||
278 | * the following is calculated using a blinding value: | ||
279 | * | ||
280 | * s = inv(k)inv(b)(bm + bxr) mod order | ||
281 | * | ||
282 | * where b is a random value in the range [1, order-1]. | ||
283 | */ | ||
284 | |||
285 | /* Generate b in range [1, order-1]. */ | ||
286 | if (!BN_sub(range, order, BN_value_one())) { | ||
287 | ECDSAerror(ERR_R_BN_LIB); | ||
288 | goto err; | ||
289 | } | ||
290 | if (!BN_rand_range(b, range)) { | ||
273 | ECDSAerror(ERR_R_BN_LIB); | 291 | ECDSAerror(ERR_R_BN_LIB); |
274 | goto err; | 292 | goto err; |
275 | } | 293 | } |
276 | if (!BN_mod_add(s, tmp, m, order, ctx)) { | 294 | if (!BN_add(b, b, BN_value_one())) { |
295 | ECDSAerror(ERR_R_BN_LIB); | ||
296 | goto err; | ||
297 | } | ||
298 | |||
299 | if (BN_mod_inverse_ct(binv, b, order, ctx) == NULL) { | ||
300 | ECDSAerror(ERR_R_BN_LIB); | ||
301 | goto err; | ||
302 | } | ||
303 | |||
304 | if (!BN_mod_mul(bxr, b, priv_key, order, ctx)) { /* bx */ | ||
305 | ECDSAerror(ERR_R_BN_LIB); | ||
306 | goto err; | ||
307 | } | ||
308 | if (!BN_mod_mul(bxr, bxr, ret->r, order, ctx)) { /* bxr */ | ||
309 | ECDSAerror(ERR_R_BN_LIB); | ||
310 | goto err; | ||
311 | } | ||
312 | if (!BN_mod_mul(bm, b, m, order, ctx)) { /* bm */ | ||
313 | ECDSAerror(ERR_R_BN_LIB); | ||
314 | goto err; | ||
315 | } | ||
316 | if (!BN_mod_add(s, bm, bxr, order, ctx)) { /* s = bm + bxr */ | ||
317 | ECDSAerror(ERR_R_BN_LIB); | ||
318 | goto err; | ||
319 | } | ||
320 | if (!BN_mod_mul(s, s, binv, order, ctx)) { /* s = m + xr */ | ||
277 | ECDSAerror(ERR_R_BN_LIB); | 321 | ECDSAerror(ERR_R_BN_LIB); |
278 | goto err; | 322 | goto err; |
279 | } | 323 | } |
@@ -281,9 +325,12 @@ ecdsa_do_sign(const unsigned char *dgst, int dgst_len, | |||
281 | ECDSAerror(ERR_R_BN_LIB); | 325 | ECDSAerror(ERR_R_BN_LIB); |
282 | goto err; | 326 | goto err; |
283 | } | 327 | } |
328 | |||
284 | if (BN_is_zero(s)) { | 329 | if (BN_is_zero(s)) { |
285 | /* if kinv and r have been supplied by the caller | 330 | /* |
286 | * don't to generate new kinv and r values */ | 331 | * If kinv and r have been supplied by the caller, |
332 | * don't generate new kinv and r values | ||
333 | */ | ||
287 | if (in_kinv != NULL && in_r != NULL) { | 334 | if (in_kinv != NULL && in_r != NULL) { |
288 | ECDSAerror(ECDSA_R_NEED_NEW_SETUP_VALUES); | 335 | ECDSAerror(ECDSA_R_NEED_NEW_SETUP_VALUES); |
289 | goto err; | 336 | goto err; |
@@ -301,10 +348,14 @@ err: | |||
301 | ret = NULL; | 348 | ret = NULL; |
302 | } | 349 | } |
303 | BN_CTX_free(ctx); | 350 | BN_CTX_free(ctx); |
351 | BN_clear_free(b); | ||
352 | BN_clear_free(binv); | ||
353 | BN_clear_free(bm); | ||
354 | BN_clear_free(bxr); | ||
355 | BN_clear_free(kinv); | ||
304 | BN_clear_free(m); | 356 | BN_clear_free(m); |
305 | BN_clear_free(tmp); | ||
306 | BN_free(order); | 357 | BN_free(order); |
307 | BN_clear_free(kinv); | 358 | BN_free(range); |
308 | return ret; | 359 | return ret; |
309 | } | 360 | } |
310 | 361 | ||