From: tb Date: Tue, 10 Jul 2018 21:52:07 +0000 (+0000) Subject: Provide BN_swap_ct(), a constant time function that conditionally swaps X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=bbd58ad841bba56e008bae48456c0bea752a9f41;p=openbsd Provide BN_swap_ct(), a constant time function that conditionally swaps two bignums. It's saner and substantially less ugly than the existing public BN_constantime_swap() function and will be used in forthcoming work on constant time ECC code. From Billy Brumley and his team. Thanks! ok jsing --- diff --git a/lib/libcrypto/bn/bn_lcl.h b/lib/libcrypto/bn/bn_lcl.h index c010410cd15..ad9427fddc2 100644 --- a/lib/libcrypto/bn/bn_lcl.h +++ b/lib/libcrypto/bn/bn_lcl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bn_lcl.h,v 1.27 2017/01/25 06:15:44 beck Exp $ */ +/* $OpenBSD: bn_lcl.h,v 1.28 2018/07/10 21:52:07 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -605,5 +605,8 @@ BIGNUM *BN_mod_inverse_nonct(BIGNUM *ret, const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx); int BN_gcd_ct(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); int BN_gcd_nonct(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); + +int BN_swap_ct(BN_ULONG swap, BIGNUM *a, BIGNUM *b, int nwords); + __END_HIDDEN_DECLS #endif diff --git a/lib/libcrypto/bn/bn_lib.c b/lib/libcrypto/bn/bn_lib.c index c480ae8b9db..610e2447d30 100644 --- a/lib/libcrypto/bn/bn_lib.c +++ b/lib/libcrypto/bn/bn_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bn_lib.c,v 1.40 2018/05/12 17:31:41 jsing Exp $ */ +/* $OpenBSD: bn_lib.c,v 1.41 2018/07/10 21:52:07 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -889,6 +889,54 @@ BN_consttime_swap(BN_ULONG condition, BIGNUM *a, BIGNUM *b, int nwords) #undef BN_CONSTTIME_SWAP } +/* + * Constant-time conditional swap of a and b. + * a and b are swapped if condition is not 0. + * The code assumes that at most one bit of condition is set. XXX add check! + * nwords is the number of words to swap. + */ +int +BN_swap_ct(BN_ULONG condition, BIGNUM *a, BIGNUM *b, int nwords) +{ + BN_ULONG t; + int i; + + if (a == b) + return 1; + if (bn_wexpand(a, nwords) == NULL || bn_wexpand(b, nwords) == NULL) + return 0; + if (a->top > nwords || b->top > nwords) { + BNerror(BN_R_INVALID_LENGTH); + return 0; + } + + condition = ((condition - 1) >> (BN_BITS2 - 1)) - 1; + + /* swap top field */ + t = (a->top ^ b->top) & condition; + a->top ^= t; + b->top ^= t; + + /* swap neg field */ + t = (a->neg ^ b->neg) & condition; + a->neg ^= t; + b->neg ^= t; + + /* swap BN_FLG_CONSTTIME from flag field */ + t = ((a->flags ^ b->flags) & BN_FLG_CONSTTIME) & condition; + a->flags ^= t; + b->flags ^= t; + + /* swap the data */ + for (i = 0; i < nwords; i++) { + t = (a->d[i] ^ b->d[i]) & condition; + a->d[i] ^= t; + b->d[i] ^= t; + } + + return 1; +} + BN_GENCB * BN_GENCB_new(void) {