blob: 171c437d3858bf3b5d20d5c0ad1ce705878f920f [file] [log] [blame]
xj123f7cc2022-06-06 11:35:21 +08001/* rsa.c
2**
3** Copyright 2012, The Android Open Source Project
4**
5** Redistribution and use in source and binary forms, with or without
6** modification, are permitted provided that the following conditions are met:
7** * Redistributions of source code must retain the above copyright
8** notice, this list of conditions and the following disclaimer.
9** * Redistributions in binary form must reproduce the above copyright
10** notice, this list of conditions and the following disclaimer in the
11** documentation and/or other materials provided with the distribution.
12** * Neither the name of Google Inc. nor the names of its contributors may
13** be used to endorse or promote products derived from this software
14** without specific prior written permission.
15**
16** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
17** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*/
27
28#include "mincrypt/rsa.h"
29#include "mincrypt/sha.h"
30#include "mincrypt/sha256.h"
31
32// a[] -= mod
33static void subM(const RSAPublicKey* key,
34 uint32_t* a) {
35 int64_t A = 0;
36 int i;
37 for (i = 0; i < key->len; ++i) {
38 A += (uint64_t)a[i] - key->n[i];
39 a[i] = (uint32_t)A;
40 A >>= 32;
41 }
42}
43
44// return a[] >= mod
45static int geM(const RSAPublicKey* key,
46 const uint32_t* a) {
47 int i;
48 for (i = key->len; i;) {
49 --i;
50 if (a[i] < key->n[i]) return 0;
51 if (a[i] > key->n[i]) return 1;
52 }
53 return 1; // equal
54}
55
56// montgomery c[] += a * b[] / R % mod
57static void montMulAdd(const RSAPublicKey* key,
58 uint32_t* c,
59 const uint32_t a,
60 const uint32_t* b) {
61 uint64_t A = (uint64_t)a * b[0] + c[0];
62 uint32_t d0 = (uint32_t)A * key->n0inv;
63 uint64_t B = (uint64_t)d0 * key->n[0] + (uint32_t)A;
64 int i;
65
66 for (i = 1; i < key->len; ++i) {
67 A = (A >> 32) + (uint64_t)a * b[i] + c[i];
68 B = (B >> 32) + (uint64_t)d0 * key->n[i] + (uint32_t)A;
69 c[i - 1] = (uint32_t)B;
70 }
71
72 A = (A >> 32) + (B >> 32);
73
74 c[i - 1] = (uint32_t)A;
75
76 if (A >> 32) {
77 subM(key, c);
78 }
79}
80
81// montgomery c[] = a[] * b[] / R % mod
82static void montMul(const RSAPublicKey* key,
83 uint32_t* c,
84 const uint32_t* a,
85 const uint32_t* b) {
86 int i;
87 for (i = 0; i < key->len; ++i) {
88 c[i] = 0;
89 }
90 for (i = 0; i < key->len; ++i) {
91 montMulAdd(key, c, a[i], b);
92 }
93}
94
95// In-place public exponentiation.
96// Input and output big-endian byte array in inout.
97static void modpow(const RSAPublicKey* key,
98 uint8_t* inout) {
99 uint32_t a[RSANUMWORDS];
100 uint32_t aR[RSANUMWORDS];
101 uint32_t aaR[RSANUMWORDS];
102 uint32_t* aaa = 0;
103 int i;
104
105 // Convert from big endian byte array to little endian word array.
106 for (i = 0; i < key->len; ++i) {
107 uint32_t tmp =
108 (inout[((key->len - 1 - i) * 4) + 0] << 24) |
109 (inout[((key->len - 1 - i) * 4) + 1] << 16) |
110 (inout[((key->len - 1 - i) * 4) + 2] << 8) |
111 (inout[((key->len - 1 - i) * 4) + 3] << 0);
112 a[i] = tmp;
113 }
114
115 if (key->exponent == 65537) {
116 aaa = aaR; // Re-use location.
117 montMul(key, aR, a, key->rr); // aR = a * RR / R mod M
118 for (i = 0; i < 16; i += 2) {
119 montMul(key, aaR, aR, aR); // aaR = aR * aR / R mod M
120 montMul(key, aR, aaR, aaR); // aR = aaR * aaR / R mod M
121 }
122 montMul(key, aaa, aR, a); // aaa = aR * a / R mod M
123 } else if (key->exponent == 3) {
124 aaa = aR; // Re-use location.
125 montMul(key, aR, a, key->rr); /* aR = a * RR / R mod M */
126 montMul(key, aaR, aR, aR); /* aaR = aR * aR / R mod M */
127 montMul(key, aaa, aaR, a); /* aaa = aaR * a / R mod M */
128 } else {
129 return; // avoid NULL aaa caused exceptions
130 }
131
132 // Make sure aaa < mod; aaa is at most 1x mod too large.
133 if (geM(key, aaa)) {
134 subM(key, aaa);
135 }
136
137 // Convert to bigendian byte array
138 for (i = key->len - 1; i >= 0; --i) {
139 uint32_t tmp = aaa[i];
140 *inout++ = tmp >> 24;
141 *inout++ = tmp >> 16;
142 *inout++ = tmp >> 8;
143 *inout++ = tmp >> 0;
144 }
145}
146
147// Expected PKCS1.5 signature padding bytes, for a keytool RSA signature.
148// Has the 0-length optional parameter encoded in the ASN1 (as opposed to the
149// other flavor which omits the optional parameter entirely). This code does not
150// accept signatures without the optional parameter.
151
152/*
153static const uint8_t sha_padding[RSANUMBYTES] = {
154 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
155 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
156 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
157 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
158 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
159 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
160 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
161 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
162 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
163 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
164 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
165 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
166 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
167 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
168 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
169 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
170 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
171 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
172 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
173 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
174 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
175 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
176 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
177 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
178 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
179 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
180 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
181 0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x21, 0x30,
182 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a,
183 0x05, 0x00, 0x04, 0x14,
184
185 // 20 bytes of hash go here.
186 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
187};
188*/
189
190// SHA-1 of PKCS1.5 signature sha_padding for 2048 bit, as above.
191// At the location of the bytes of the hash all 00 are hashed.
192static const uint8_t kExpectedPadShaRsa2048[SHA_DIGEST_SIZE] = {
193 0xdc, 0xbd, 0xbe, 0x42, 0xd5, 0xf5, 0xa7, 0x2e,
194 0x6e, 0xfc, 0xf5, 0x5d, 0xaf, 0x9d, 0xea, 0x68,
195 0x7c, 0xfb, 0xf1, 0x67
196};
197
198/*
199static const uint8_t sha256_padding[RSANUMBYTES] = {
200 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
201 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
202 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
203 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
204 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
205 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
206 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
207 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
208 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
209 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
210 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
211 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
212 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
213 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
214 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
215 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
216 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
217 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
218 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
219 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
220 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
221 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
222 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
223 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
224 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
225 0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x31, 0x30,
226 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
227 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20,
228
229 // 32 bytes of hash go here.
230 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
231 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
232};
233*/
234
235// SHA-256 of PKCS1.5 signature sha256_padding for 2048 bit, as above.
236// At the location of the bytes of the hash all 00 are hashed.
237static const uint8_t kExpectedPadSha256Rsa2048[SHA256_DIGEST_SIZE] = {
238 0xab, 0x28, 0x8d, 0x8a, 0xd7, 0xd9, 0x59, 0x92,
239 0xba, 0xcc, 0xf8, 0x67, 0x20, 0xe1, 0x15, 0x2e,
240 0x39, 0x8d, 0x80, 0x36, 0xd6, 0x6f, 0xf0, 0xfd,
241 0x90, 0xe8, 0x7d, 0x8b, 0xe1, 0x7c, 0x87, 0x59,
242};
243
244// Verify a 2048-bit RSA PKCS1.5 signature against an expected hash.
245// Both e=3 and e=65537 are supported. hash_len may be
246// SHA_DIGEST_SIZE (== 20) to indicate a SHA-1 hash, or
247// SHA256_DIGEST_SIZE (== 32) to indicate a SHA-256 hash. No other
248// values are supported.
249//
250// Returns 1 on successful verification, 0 on failure.
251int RSA_verify(const RSAPublicKey *key,
252 const uint8_t *signature,
253 const int len,
254 const uint8_t *hash,
255 const int hash_len) {
256 uint8_t buf[RSANUMBYTES];
257 int i;
258 const uint8_t* padding_hash;
259
260 if (key->len != RSANUMWORDS) {
261 return 0; // Wrong key passed in.
262 }
263
264 if (len != sizeof(buf)) {
265 return 0; // Wrong input length.
266 }
267
268 if (hash_len != SHA_DIGEST_SIZE &&
269 hash_len != SHA256_DIGEST_SIZE) {
270 return 0; // Unsupported hash.
271 }
272
273 if (key->exponent != 3 && key->exponent != 65537) {
274 return 0; // Unsupported exponent.
275 }
276
277 for (i = 0; i < len; ++i) { // Copy input to local workspace.
278 buf[i] = signature[i];
279 }
280
281 modpow(key, buf); // In-place exponentiation.
282
283 // Xor sha portion, so it all becomes 00 iff equal.
284 for (i = len - hash_len; i < len; ++i) {
285 buf[i] ^= *hash++;
286 }
287
288 // Hash resulting buf, in-place.
289 switch (hash_len) {
290 case SHA_DIGEST_SIZE:
291 padding_hash = kExpectedPadShaRsa2048;
292 SHA_hash(buf, len, buf);
293 break;
294 case SHA256_DIGEST_SIZE:
295 padding_hash = kExpectedPadSha256Rsa2048;
296 SHA256_hash(buf, len, buf);
297 break;
298 default:
299 return 0;
300 }
301
302 // Compare against expected hash value.
303 for (i = 0; i < hash_len; ++i) {
304 if (buf[i] != padding_hash[i]) {
305 return 0;
306 }
307 }
308
309 return 1; // All checked out OK.
310}