1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
From 5942c26888ba12ad5e0d92fb62f23d7cde6dc159 Mon Sep 17 00:00:00 2001
From: Ovidiu Panait <ovidiu.panait@windriver.com>
Date: Mon, 13 Jul 2020 06:25:56 +0000
Subject: [PATCH] Bug 1631576 - Force a fixed length for DSA exponentiation
r=pereida,bbrumley
Differential Revision: https://phabricator.services.mozilla.com/D72011
Upstream-Status: Backport [https://hg.mozilla.org/projects/nss/rev/daa823a4a29bcef0fec33a379ec83857429aea2e]
Authored-by: Robert Relyea <rrelyea@redhat.com>
Signed-off-by: Ovidiu Panait <ovidiu.panait@windriver.com>
---
nss/lib/freebl/dsa.c | 45 ++++++++++++++++++++++++++++++++++----------
1 file changed, 35 insertions(+), 10 deletions(-)
diff --git a/nss/lib/freebl/dsa.c b/nss/lib/freebl/dsa.c
index aef3539..389c9de 100644
--- a/nss/lib/freebl/dsa.c
+++ b/nss/lib/freebl/dsa.c
@@ -313,13 +313,14 @@ DSA_NewKeyFromSeed(const PQGParams *params,
static SECStatus
dsa_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest,
- const unsigned char *kb)
+ const unsigned char *kbytes)
{
mp_int p, q, g; /* PQG parameters */
mp_int x, k; /* private key & pseudo-random integer */
mp_int r, s; /* tuple (r, s) is signature) */
mp_int t; /* holding tmp values */
mp_int ar; /* holding blinding values */
+ mp_digit fuzz; /* blinding multiplier for q */
mp_err err = MP_OKAY;
SECStatus rv = SECSuccess;
unsigned int dsa_subprime_len, dsa_signature_len, offset;
@@ -373,6 +374,7 @@ dsa_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest,
CHECK_MPI_OK(mp_init(&s));
CHECK_MPI_OK(mp_init(&t));
CHECK_MPI_OK(mp_init(&ar));
+
/*
** Convert stored PQG and private key into MPI integers.
*/
@@ -380,14 +382,28 @@ dsa_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest,
SECITEM_TO_MPINT(key->params.subPrime, &q);
SECITEM_TO_MPINT(key->params.base, &g);
SECITEM_TO_MPINT(key->privateValue, &x);
- OCTETS_TO_MPINT(kb, &k, dsa_subprime_len);
+ OCTETS_TO_MPINT(kbytes, &k, dsa_subprime_len);
+
+ /* k blinding create a single value that has the high bit set in
+ * the mp_digit*/
+ if (RNG_GenerateGlobalRandomBytes(&fuzz, sizeof(mp_digit)) != SECSuccess) {
+ PORT_SetError(SEC_ERROR_NEED_RANDOM);
+ rv = SECFailure;
+ goto cleanup;
+ }
+ fuzz |= 1ULL << ((sizeof(mp_digit) * PR_BITS_PER_BYTE - 1));
/*
** FIPS 186-1, Section 5, Step 1
**
** r = (g**k mod p) mod q
*/
- CHECK_MPI_OK(mp_exptmod(&g, &k, &p, &r)); /* r = g**k mod p */
- CHECK_MPI_OK(mp_mod(&r, &q, &r)); /* r = r mod q */
+ CHECK_MPI_OK(mp_mul_d(&q, fuzz, &t)); /* t = q*fuzz */
+ CHECK_MPI_OK(mp_add(&k, &t, &t)); /* t = k+q*fuzz */
+ /* length of t is now fixed, bits in k have been blinded */
+ CHECK_MPI_OK(mp_exptmod(&g, &t, &p, &r)); /* r = g**t mod p */
+ /* r is now g**(k+q*fuzz) == g**k mod p */
+ CHECK_MPI_OK(mp_mod(&r, &q, &r)); /* r = r mod q */
+
/*
** FIPS 186-1, Section 5, Step 2
**
@@ -411,15 +427,24 @@ dsa_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest,
/* Using mp_invmod on k directly would leak bits from k. */
CHECK_MPI_OK(mp_mul(&k, &ar, &k)); /* k = k * ar */
CHECK_MPI_OK(mp_mulmod(&k, &t, &q, &k)); /* k = k * t mod q */
- CHECK_MPI_OK(mp_invmod(&k, &q, &k)); /* k = k**-1 mod q */
+ /* k is now k*t*ar */
+ CHECK_MPI_OK(mp_invmod(&k, &q, &k)); /* k = k**-1 mod q */
+ /* k is now (k*t*ar)**-1 */
CHECK_MPI_OK(mp_mulmod(&k, &t, &q, &k)); /* k = k * t mod q */
- SECITEM_TO_MPINT(localDigest, &s); /* s = HASH(M) */
+ /* k is now (k*ar)**-1 */
+ SECITEM_TO_MPINT(localDigest, &s); /* s = HASH(M) */
/* To avoid leaking secret bits here the addition is blinded. */
- CHECK_MPI_OK(mp_mul(&x, &ar, &x)); /* x = x * ar */
- CHECK_MPI_OK(mp_mulmod(&x, &r, &q, &x)); /* x = x * r mod q */
+ CHECK_MPI_OK(mp_mul(&x, &ar, &x)); /* x = x * ar */
+ /* x is now x*ar */
+ CHECK_MPI_OK(mp_mulmod(&x, &r, &q, &x)); /* x = x * r mod q */
+ /* x is now x*r*ar */
CHECK_MPI_OK(mp_mulmod(&s, &ar, &q, &t)); /* t = s * ar mod q */
- CHECK_MPI_OK(mp_add(&t, &x, &s)); /* s = t + x */
- CHECK_MPI_OK(mp_mulmod(&s, &k, &q, &s)); /* s = s * k mod q */
+ /* t is now hash(M)*ar */
+ CHECK_MPI_OK(mp_add(&t, &x, &s)); /* s = t + x */
+ /* s is now (HASH(M)+x*r)*ar */
+ CHECK_MPI_OK(mp_mulmod(&s, &k, &q, &s)); /* s = s * k mod q */
+ /* s is now (HASH(M)+x*r)*ar*(k*ar)**-1 = (k**-1)*(HASH(M)+x*r) */
+
/*
** verify r != 0 and s != 0
** mentioned as optional in FIPS 186-1.
--
2.18.1
|