summaryrefslogtreecommitdiff
path: root/openssl/openssl-1.1.1-cve-2022-0778.patch
blob: 4e62b3f2e36325c53984547afdc8c10d8de654ec (plain)
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
From 3118eb64934499d93db3230748a452351d1d9a65 Mon Sep 17 00:00:00 2001
From: Tomas Mraz <[email protected]>
Date: Mon, 28 Feb 2022 18:26:21 +0100
Subject: [PATCH] Fix possible infinite loop in BN_mod_sqrt()

The calculation in some cases does not finish for non-prime p.

This fixes CVE-2022-0778.

Based on patch by David Benjamin <[email protected]>.

Reviewed-by: Paul Dale <[email protected]>
Reviewed-by: Matt Caswell <[email protected]>
---
 crypto/bn/bn_sqrt.c | 30 ++++++++++++++++++------------
 1 file changed, 18 insertions(+), 12 deletions(-)

From b5fcb7e133725b8b2eb66f63f5142710ed63a6d1 Mon Sep 17 00:00:00 2001
From: Tomas Mraz <[email protected]>
Date: Mon, 28 Feb 2022 18:26:30 +0100
Subject: [PATCH] Add documentation of BN_mod_sqrt()

Reviewed-by: Paul Dale <[email protected]>
Reviewed-by: Matt Caswell <[email protected]>
---
 doc/man3/BN_add.pod | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

From 3ef5c3034e5c545f34d6929568f3f2b10ac4bdf0 Mon Sep 17 00:00:00 2001
From: Tomas Mraz <[email protected]>
Date: Mon, 28 Feb 2022 18:26:35 +0100
Subject: [PATCH] Add a negative testcase for BN_mod_sqrt

Reviewed-by: Paul Dale <[email protected]>
Reviewed-by: Matt Caswell <[email protected]>
---
 test/bntest.c                          | 11 ++++++++++-
 test/recipes/10-test_bn_data/bnmod.txt | 12 ++++++++++++
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/crypto/bn/bn_sqrt.c b/crypto/bn/bn_sqrt.c
index 1723d5ded5a8..53b0f559855c 100644
--- a/crypto/bn/bn_sqrt.c
+++ b/crypto/bn/bn_sqrt.c
@@ -14,7 +14,8 @@ BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
 /*
  * Returns 'ret' such that ret^2 == a (mod p), using the Tonelli/Shanks
  * algorithm (cf. Henri Cohen, "A Course in Algebraic Computational Number
- * Theory", algorithm 1.5.1). 'p' must be prime!
+ * Theory", algorithm 1.5.1). 'p' must be prime, otherwise an error or
+ * an incorrect "result" will be returned.
  */
 {
     BIGNUM *ret = in;
@@ -301,18 +302,23 @@ BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
             goto vrfy;
         }
 
-        /* find smallest  i  such that  b^(2^i) = 1 */
-        i = 1;
-        if (!BN_mod_sqr(t, b, p, ctx))
-            goto end;
-        while (!BN_is_one(t)) {
-            i++;
-            if (i == e) {
-                BNerr(BN_F_BN_MOD_SQRT, BN_R_NOT_A_SQUARE);
-                goto end;
+        /* Find the smallest i, 0 < i < e, such that b^(2^i) = 1. */
+        for (i = 1; i < e; i++) {
+            if (i == 1) {
+                if (!BN_mod_sqr(t, b, p, ctx))
+                    goto end;
+
+            } else {
+                if (!BN_mod_mul(t, t, t, p, ctx))
+                    goto end;
             }
-            if (!BN_mod_mul(t, t, t, p, ctx))
-                goto end;
+            if (BN_is_one(t))
+                break;
+        }
+        /* If not found, a is not a square or p is not prime. */
+        if (i >= e) {
+            BNerr(BN_F_BN_MOD_SQRT, BN_R_NOT_A_SQUARE);
+            goto end;
         }
 
         /* t := y^2^(e - i - 1) */
diff --git a/doc/man3/BN_add.pod b/doc/man3/BN_add.pod
index dccd4790ede7..1f5e37a4d183 100644
--- a/doc/man3/BN_add.pod
+++ b/doc/man3/BN_add.pod
@@ -3,7 +3,7 @@
 =head1 NAME
 
 BN_add, BN_sub, BN_mul, BN_sqr, BN_div, BN_mod, BN_nnmod, BN_mod_add,
-BN_mod_sub, BN_mod_mul, BN_mod_sqr, BN_exp, BN_mod_exp, BN_gcd -
+BN_mod_sub, BN_mod_mul, BN_mod_sqr, BN_mod_sqrt, BN_exp, BN_mod_exp, BN_gcd -
 arithmetic operations on BIGNUMs
 
 =head1 SYNOPSIS
@@ -36,6 +36,8 @@ arithmetic operations on BIGNUMs
 
  int BN_mod_sqr(BIGNUM *r, BIGNUM *a, const BIGNUM *m, BN_CTX *ctx);
 
+ BIGNUM *BN_mod_sqrt(BIGNUM *in, BIGNUM *a, const BIGNUM *p, BN_CTX *ctx);
+
  int BN_exp(BIGNUM *r, BIGNUM *a, BIGNUM *p, BN_CTX *ctx);
 
  int BN_mod_exp(BIGNUM *r, BIGNUM *a, const BIGNUM *p,
@@ -87,6 +89,12 @@ L<BN_mod_mul_reciprocal(3)>.
 BN_mod_sqr() takes the square of I<a> modulo B<m> and places the
 result in I<r>.
 
+BN_mod_sqrt() returns the modular square root of I<a> such that
+C<in^2 = a (mod p)>. The modulus I<p> must be a
+prime, otherwise an error or an incorrect "result" will be returned.
+The result is stored into I<in> which can be NULL. The result will be
+newly allocated in that case.
+
 BN_exp() raises I<a> to the I<p>-th power and places the result in I<r>
 (C<r=a^p>). This function is faster than repeated applications of
 BN_mul().
@@ -108,7 +116,10 @@ the arguments.
 
 =head1 RETURN VALUES
 
-For all functions, 1 is returned for success, 0 on error. The return
+The BN_mod_sqrt() returns the result (possibly incorrect if I<p> is
+not a prime), or NULL.
+
+For all remaining functions, 1 is returned for success, 0 on error. The return
 value should always be checked (e.g., C<if (!BN_add(r,a,b)) goto err;>).
 The error codes can be obtained by L<ERR_get_error(3)>.
 
diff --git a/test/bntest.c b/test/bntest.c
index 390dd800733e..1cab660bcafb 100644
--- a/test/bntest.c
+++ b/test/bntest.c
@@ -1729,8 +1729,17 @@ static int file_modsqrt(STANZA *s)
             || !TEST_ptr(ret2 = BN_new()))
         goto err;
 
+    if (BN_is_negative(mod_sqrt)) {
+        /* A negative testcase */
+        if (!TEST_ptr_null(BN_mod_sqrt(ret, a, p, ctx)))
+            goto err;
+
+        st = 1;
+        goto err;
+    }
+
     /* There are two possible answers. */
-    if (!TEST_true(BN_mod_sqrt(ret, a, p, ctx))
+    if (!TEST_ptr(BN_mod_sqrt(ret, a, p, ctx))
             || !TEST_true(BN_sub(ret2, p, ret)))
         goto err;
 
diff --git a/test/recipes/10-test_bn_data/bnmod.txt b/test/recipes/10-test_bn_data/bnmod.txt
index 5ea4d031f271..e28cc6bfb02e 100644
--- a/test/recipes/10-test_bn_data/bnmod.txt
+++ b/test/recipes/10-test_bn_data/bnmod.txt
@@ -2799,3 +2799,15 @@ P = 9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e246b41c32f71e951f
 ModSqrt = a1d52989f12f204d3d2167d9b1e6c8a6174c0c786a979a5952383b7b8bd186
 A = 2eee37cf06228a387788188e650bc6d8a2ff402931443f69156a29155eca07dcb45f3aac238d92943c0c25c896098716baa433f25bd696a142f5a69d5d937e81
 P = 9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e246b41c32f71e951f
+
+# Negative testcases for BN_mod_sqrt()
+
+# This one triggers an infinite loop with unfixed implementation
+# It should just fail.
+ModSqrt = -1
+A = 20a7ee
+P = 460201
+
+ModSqrt = -1
+A = 65bebdb00a96fc814ec44b81f98b59fba3c30203928fa5214c51e0a97091645280c947b005847f239758482b9bfc45b066fde340d1fe32fc9c1bf02e1b2d0ed
+P = 9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e246b41c32f71e951f