untrusted comment: verify with openbsd-63-base.pub
RWRxzbLwAd76ZQQlFRNKEfNompyJ2JhzSXXR7R2d9+Gs4IkEE7ZPyqk7JCTYl6cPwM/erVz13PKZwUJ9JVYTDn+7FdHLb13DAQI=
OpenBSD 6.3 errata 022, November 17, 2018:
Timing side channels may leak information about DSA and ECDSA private
keys.
Apply by doing:
signify -Vep /etc/signify/openbsd-63-base.pub -x 022_blinding.patch.sig \
-m - | (cd /usr/src && patch -p0)
And then rebuild and install libcrypto
cd /usr/src/lib/libcrypto
make obj
make
make install
Index: lib/libcrypto/dsa/dsa_ossl.c
===================================================================
RCS file: /var/cvs/src/lib/libcrypto/dsa/dsa_ossl.c,v
retrieving revision 1.30.2.1
diff -u -p -r1.30.2.1 dsa_ossl.c
--- lib/libcrypto/dsa/dsa_ossl.c 13 Jun 2018 15:08:08 -0000 1.30.2.1
+++ lib/libcrypto/dsa/dsa_ossl.c 11 Nov 2018 16:13:33 -0000
@@ -94,16 +94,17 @@ DSA_OpenSSL(void)
static DSA_SIG *
dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
{
- BIGNUM *kinv = NULL, *r = NULL, *s = NULL;
- BIGNUM m;
- BIGNUM xr;
+ BIGNUM b, bm, bxr, binv, m, *kinv = NULL, *r = NULL, *s = NULL;
BN_CTX *ctx = NULL;
int reason = ERR_R_BN_LIB;
DSA_SIG *ret = NULL;
int noredo = 0;
+ BN_init(&b);
+ BN_init(&binv);
+ BN_init(&bm);
+ BN_init(&bxr);
BN_init(&m);
- BN_init(&xr);
if (!dsa->p || !dsa->q || !dsa->g) {
reason = DSA_R_MISSING_PARAMETERS;
@@ -139,10 +140,36 @@ redo:
if (BN_bin2bn(dgst,dlen,&m) == NULL)
goto err;
- /* Compute s = inv(k) (m + xr) mod q */
- if (!BN_mod_mul(&xr, dsa->priv_key, r, dsa->q, ctx)) /* s = xr */
+ /*
+ * Compute:
+ *
+ * s = inv(k)(m + xr) mod q
+ *
+ * In order to reduce the possibility of a side-channel attack, the
+ * following is calculated using a blinding value:
+ *
+ * s = inv(k)inv(b)(bm + bxr) mod q
+ *
+ * Where b is a random value in the range [1, q-1].
+ */
+ if (!BN_sub(&bm, dsa->q, BN_value_one()))
+ goto err;
+ if (!BN_rand_range(&b, &bm))
+ goto err;
+ if (!BN_add(&b, &b, BN_value_one()))
+ goto err;
+ if (BN_mod_inverse_ct(&binv, &b, dsa->q, ctx) == NULL)
+ goto err;
+
+ if (!BN_mod_mul(&bxr, &b, dsa->priv_key, dsa->q, ctx)) /* bx */
+ goto err;
+ if (!BN_mod_mul(&bxr, &bxr, r, dsa->q, ctx)) /* bxr */
+ goto err;
+ if (!BN_mod_mul(&bm, &b, &m, dsa->q, ctx)) /* bm */
+ goto err;
+ if (!BN_mod_add(s, &bxr, &bm, dsa->q, ctx)) /* s = bm + bxr */
goto err;
- if (!BN_mod_add(s, &xr, &m, dsa->q, ctx)) /* s = m + xr */
+ if (!BN_mod_mul(s, s, &binv, dsa->q, ctx)) /* s = m + xr */
goto err;
if (!BN_mod_mul(s, s, kinv, dsa->q, ctx))
goto err;
@@ -171,8 +198,11 @@ err:
BN_free(s);
}
BN_CTX_free(ctx);
+ BN_clear_free(&b);
+ BN_clear_free(&bm);
+ BN_clear_free(&bxr);
+ BN_clear_free(&binv);
BN_clear_free(&m);
- BN_clear_free(&xr);
BN_clear_free(kinv);
return ret;
}
Index: lib/libcrypto/ecdsa/ecs_ossl.c
===================================================================
RCS file: /var/cvs/src/lib/libcrypto/ecdsa/ecs_ossl.c,v
retrieving revision 1.9.2.1
diff -u -p -r1.9.2.1 ecs_ossl.c
--- lib/libcrypto/ecdsa/ecs_ossl.c 13 Jun 2018 15:08:08 -0000 1.9.2.1
+++ lib/libcrypto/ecdsa/ecs_ossl.c 11 Nov 2018 16:13:48 -0000
@@ -1,4 +1,4 @@
-/* $OpenBSD: ecs_ossl.c,v 1.9.2.1 2018/06/13 15:08:08 jsing Exp $ */
+/* $OpenBSD: ecs_ossl.c,v 1.12 2018/06/14 18:51:01 tb Exp $ */
/*
* Written by Nils Larsch for the OpenSSL project
*/
@@ -204,14 +204,14 @@ static ECDSA_SIG *
ecdsa_do_sign(const unsigned char *dgst, int dgst_len,
const BIGNUM *in_kinv, const BIGNUM *in_r, EC_KEY *eckey)
{
- int ok = 0, i;
- BIGNUM *kinv = NULL, *s, *m = NULL, *tmp = NULL, *order = NULL;
- const BIGNUM *ckinv;
- BN_CTX *ctx = NULL;
- const EC_GROUP *group;
+ BIGNUM *b = NULL, *binv = NULL, *bm = NULL, *bxr = NULL;
+ BIGNUM *kinv = NULL, *m = NULL, *order = NULL, *range = NULL, *s;
+ const BIGNUM *ckinv, *priv_key;
+ BN_CTX *ctx = NULL;
+ const EC_GROUP *group;
ECDSA_SIG *ret;
ECDSA_DATA *ecdsa;
- const BIGNUM *priv_key;
+ int ok = 0, i;
ecdsa = ecdsa_check(eckey);
group = EC_KEY_get0_group(eckey);
@@ -230,7 +230,9 @@ ecdsa_do_sign(const unsigned char *dgst,
s = ret->s;
if ((ctx = BN_CTX_new()) == NULL || (order = BN_new()) == NULL ||
- (tmp = BN_new()) == NULL || (m = BN_new()) == NULL) {
+ (range = BN_new()) == NULL || (b = BN_new()) == NULL ||
+ (binv = BN_new()) == NULL || (bm = BN_new()) == NULL ||
+ (bxr = BN_new()) == NULL || (m = BN_new()) == NULL) {
ECDSAerror(ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -269,11 +271,53 @@ ecdsa_do_sign(const unsigned char *dgst,
}
}
- if (!BN_mod_mul(tmp, priv_key, ret->r, order, ctx)) {
+ /*
+ * Compute s = inv(k)(m + xr) mod order.
+ *
+ * In order to reduce the possibility of a side-channel attack,
+ * the following is calculated using a blinding value:
+ *
+ * s = inv(k)inv(b)(bm + bxr) mod order
+ *
+ * where b is a random value in the range [1, order-1].
+ */
+
+ /* Generate b in range [1, order-1]. */
+ if (!BN_sub(range, order, BN_value_one())) {
+ ECDSAerror(ERR_R_BN_LIB);
+ goto err;
+ }
+ if (!BN_rand_range(b, range)) {
ECDSAerror(ERR_R_BN_LIB);
goto err;
}
- if (!BN_mod_add(s, tmp, m, order, ctx)) {
+ if (!BN_add(b, b, BN_value_one())) {
+ ECDSAerror(ERR_R_BN_LIB);
+ goto err;
+ }
+
+ if (BN_mod_inverse_ct(binv, b, order, ctx) == NULL) {
+ ECDSAerror(ERR_R_BN_LIB);
+ goto err;
+ }
+
+ if (!BN_mod_mul(bxr, b, priv_key, order, ctx)) { /* bx */
+ ECDSAerror(ERR_R_BN_LIB);
+ goto err;
+ }
+ if (!BN_mod_mul(bxr, bxr, ret->r, order, ctx)) { /* bxr */
+ ECDSAerror(ERR_R_BN_LIB);
+ goto err;
+ }
+ if (!BN_mod_mul(bm, b, m, order, ctx)) { /* bm */
+ ECDSAerror(ERR_R_BN_LIB);
+ goto err;
+ }
+ if (!BN_mod_add(s, bm, bxr, order, ctx)) { /* s = bm + bxr */
+ ECDSAerror(ERR_R_BN_LIB);
+ goto err;
+ }
+ if (!BN_mod_mul(s, s, binv, order, ctx)) { /* s = m + xr */
ECDSAerror(ERR_R_BN_LIB);
goto err;
}
@@ -281,9 +325,12 @@ ecdsa_do_sign(const unsigned char *dgst,
ECDSAerror(ERR_R_BN_LIB);
goto err;
}
+
if (BN_is_zero(s)) {
- /* if kinv and r have been supplied by the caller
- * don't to generate new kinv and r values */
+ /*
+ * If kinv and r have been supplied by the caller,
+ * don't generate new kinv and r values
+ */
if (in_kinv != NULL && in_r != NULL) {
ECDSAerror(ECDSA_R_NEED_NEW_SETUP_VALUES);
goto err;
@@ -301,10 +348,14 @@ err:
ret = NULL;
}
BN_CTX_free(ctx);
+ BN_clear_free(b);
+ BN_clear_free(binv);
+ BN_clear_free(bm);
+ BN_clear_free(bxr);
+ BN_clear_free(kinv);
BN_clear_free(m);
- BN_clear_free(tmp);
BN_free(order);
- BN_clear_free(kinv);
+ BN_free(range);
return ret;
}