OLD | NEW |
| (Empty) |
1 // Copyright 2006-2009 Google Inc. | |
2 // | |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
4 // you may not use this file except in compliance with the License. | |
5 // You may obtain a copy of the License at | |
6 // | |
7 // http://www.apache.org/licenses/LICENSE-2.0 | |
8 // | |
9 // Unless required by applicable law or agreed to in writing, software | |
10 // distributed under the License is distributed on an "AS IS" BASIS, | |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 // See the License for the specific language governing permissions and | |
13 // limitations under the License. | |
14 // ======================================================================== | |
15 | |
16 #include "rsa.h" | |
17 | |
18 #include <stddef.h> | |
19 #include <inttypes.h> | |
20 #include <string.h> | |
21 #include <stdio.h> | |
22 | |
23 #include "md5.h" | |
24 #include "aes.h" | |
25 #include "sha.h" | |
26 #include "rc4.h" | |
27 | |
28 #define DINV mod[0] | |
29 #define RR(i) mod[1 + 2*(i)] | |
30 #define MOD(i) (mod[2 + 2*(i)] + mod[1 + 2*(i)]) // +mod[1+2*(i)] to deobscure | |
31 | |
32 // | |
33 // a[] -= M | |
34 // | |
35 static void subM(uint32_t* a, const uint32_t* mod, int len) { | |
36 int64_t A = 0; | |
37 for (int i = 0; i < len; ++i) { | |
38 A += (uint64_t)a[i] - MOD(i); | |
39 a[i] = (uint32_t)A; | |
40 A >>= 32; | |
41 } | |
42 } | |
43 | |
44 // | |
45 // return a[] >= M | |
46 // | |
47 static bool geM(const uint32_t* a, const uint32_t* mod, int len) { | |
48 for (int i = len; i;) { | |
49 --i; | |
50 if (a[i] < MOD(i)) return false; | |
51 if (a[i] > MOD(i)) return true; | |
52 } | |
53 return true; // equal | |
54 } | |
55 | |
56 // | |
57 // montgomery c[] += a * b[] / R mod M | |
58 // | |
59 static void montMulAdd(uint32_t* c, | |
60 uint32_t a, | |
61 const uint32_t* b, | |
62 const uint32_t* mod, | |
63 int len) { | |
64 uint64_t A = (uint64_t)a * b[0] + c[0]; | |
65 uint32_t d0 = (uint32_t)A * DINV; | |
66 uint64_t B = (uint64_t)d0 * MOD(0) + (uint32_t)A; | |
67 | |
68 int i = 1; | |
69 for (; i < len; ++i) { | |
70 A = (A >> 32) + (uint64_t)a * b[i] + c[i]; | |
71 B = (B >> 32) + (uint64_t)d0 * MOD(i) + (uint32_t)A; | |
72 c[i - 1] = (uint32_t)B; | |
73 } | |
74 | |
75 A = (A >> 32) + (B >> 32); | |
76 | |
77 c[i - 1] = (uint32_t)A; | |
78 | |
79 if ((A >> 32)) { // proper probablistic padding could avoid this? | |
80 subM(c, mod, len); // or moduli without the highest bit set.. | |
81 } | |
82 } | |
83 | |
84 // | |
85 // montgomery c[] = a[] * R^2 / R mod M (= a[] * R mod M) | |
86 // | |
87 static void montMulR(uint32_t* c, | |
88 const uint32_t* a, | |
89 const uint32_t* mod, | |
90 int len) { | |
91 memset(c, 0, len * sizeof(uint32_t)); | |
92 | |
93 for (int i = 0; i < len; ++i) { | |
94 montMulAdd(c, RR(i), a, mod, len); | |
95 } | |
96 } | |
97 | |
98 // | |
99 // montgomery c[] = a[] * b[] / R mod M | |
100 // | |
101 static void montMul(uint32_t* c, | |
102 const uint32_t* a, | |
103 const uint32_t* b, | |
104 const uint32_t* mod, | |
105 int len) { | |
106 memset(c, 0, len * sizeof(uint32_t)); | |
107 | |
108 for (int i = 0; i < len; ++i) { | |
109 montMulAdd(c, a[i], b, mod, len); | |
110 } | |
111 } | |
112 | |
113 | |
114 // | |
115 // In-place public exponentiation. | |
116 // Input and output big-endian byte array. | |
117 // Returns 0 on failure or # uint8_t written in inout (always inout_len). | |
118 // | |
119 int RSA::raw(uint8_t* inout, int inout_len) const { | |
120 const uint32_t* mod = &pkey_[1]; | |
121 int len = *mod++; | |
122 | |
123 if (len > kMaxWords) | |
124 return 0; // Only work with up to 2048 bit moduli. | |
125 if ((len * 4) != inout_len) | |
126 return 0; // Input length should match modulus length. | |
127 | |
128 uint32_t a[kMaxWords]; | |
129 | |
130 // Convert from big endian byte array to little endian word array. | |
131 for (int i = 0; i < len; ++i) { | |
132 uint32_t tmp = | |
133 (inout[((len - 1 - i) * 4) + 0] << 24) | | |
134 (inout[((len - 1 - i) * 4) + 1] << 16) | | |
135 (inout[((len - 1 - i) * 4) + 2] << 8) | | |
136 (inout[((len - 1 - i) * 4) + 3] << 0); | |
137 a[i] = tmp; | |
138 } | |
139 | |
140 uint32_t aR[kMaxWords]; | |
141 uint32_t aaR[kMaxWords]; | |
142 uint32_t aaa[kMaxWords]; | |
143 | |
144 montMulR(aR, a, mod, len); // aR = a * R mod M | |
145 montMul(aaR, aR, aR, mod, len); // aaR = a^2 * R mod M | |
146 montMul(aaa, aaR, a, mod, len); // aaa = a^3 mod M | |
147 | |
148 // Make sure aaa < mod; aaa is at most 1x mod too large. | |
149 if (geM(aaa, mod, len)) { | |
150 subM(aaa, mod, len); | |
151 } | |
152 | |
153 // Convert to bigendian byte array | |
154 int reslen = 0; | |
155 | |
156 for (int i = len - 1; i >= 0; --i) { | |
157 uint32_t tmp = aaa[i]; | |
158 inout[reslen++] = tmp >> 24; | |
159 inout[reslen++] = tmp >> 16; | |
160 inout[reslen++] = tmp >> 8; | |
161 inout[reslen++] = tmp >> 0; | |
162 } | |
163 | |
164 return reslen; | |
165 } | |
166 | |
167 // | |
168 // Verify a Google style padded message recovery signature and return the | |
169 // message. | |
170 // | |
171 int RSA::verify(const uint8_t* data, int data_len, | |
172 void* output, int output_len) const { | |
173 uint8_t res[kMaxWords * 4]; | |
174 | |
175 if (data_len < 0 || data_len > (kMaxWords * 4)) | |
176 return 0; // Input too big, 2048 bit max. | |
177 | |
178 memcpy(res, data, data_len); | |
179 | |
180 int reslen = this->raw(res, data_len); | |
181 | |
182 if (!reslen) return 0; | |
183 | |
184 uint8_t md5[16]; | |
185 | |
186 MD5(res, reslen - 16, md5); | |
187 | |
188 for (int i = 0; i < 16; ++i) { | |
189 res[reslen - 16 + i] ^= md5[i]; | |
190 } | |
191 | |
192 // Unmask low part using high part as ofb key. | |
193 uint8_t iv[16] = {0}; | |
194 | |
195 for (int i = 0; i < reslen - 16; i++) { | |
196 if (!(i & 15)) | |
197 AES_encrypt_block(res + reslen - 16, iv, iv); | |
198 res[i] ^= iv[i & 15]; | |
199 } | |
200 | |
201 res[0] &= 127; | |
202 res[0] %= reslen - 16 - 16; | |
203 | |
204 bool result = true; | |
205 | |
206 // Verify high part is hash of random in low part. | |
207 MD5(res + 1, res[0] + 16, md5); | |
208 for (int i = 0; i < 16; ++i) { | |
209 result = result && (res[reslen - 16 + i] == md5[i]); | |
210 } | |
211 | |
212 if (!result) { | |
213 return 0; // verification failure | |
214 } | |
215 | |
216 // Copy message into output[] | |
217 if (res[0] > output_len) { | |
218 return 0; // output too small, return failure | |
219 } | |
220 | |
221 memcpy(output, res + 1, res[0]); | |
222 | |
223 return res[0]; | |
224 } | |
225 | |
226 // | |
227 // Hybrid encrypt message. | |
228 // Make up RC4 key using seed and hash of msg. | |
229 // Wrap key with RSA, encrypt msg with RC4. | |
230 // | |
231 int RSA::encrypt(const uint8_t* msg, int msg_len, | |
232 const void* seed, int seed_len, | |
233 uint8_t* output, int output_max) const { | |
234 int output_len = this->encryptedSize(msg_len); | |
235 if (output_max < 0 || output_max < output_len) | |
236 return 0; | |
237 | |
238 int header_size = output_len - msg_len; // Our added overhead. | |
239 | |
240 // Hash of message. Least significant SHA_DIGEST_SIZE bytes of RSA number. | |
241 uint8_t* hash = &output[header_size - SHA_DIGEST_SIZE]; | |
242 SHA(msg, msg_len, hash); | |
243 | |
244 // Hash(Hash(message) | seed). | |
245 SHA_CTX sha; | |
246 SHA_init(&sha); | |
247 SHA_update(&sha, hash, SHA_DIGEST_SIZE); | |
248 SHA_update(&sha, seed, seed_len); | |
249 | |
250 // Use this Hash(Hash(message) | seed) as RC4 key for prng. | |
251 RC4_CTX rc4; | |
252 RC4_setKey(&rc4, SHA_final(&sha), SHA_DIGEST_SIZE); | |
253 RC4_discard(&rc4, 1536); // Drop some to warm up RC4. | |
254 | |
255 uint8_t* key = &output[1 + 4]; | |
256 | |
257 // Prng conjure some bytes. | |
258 RC4_stream(&rc4, key, this->size() - SHA_DIGEST_SIZE); | |
259 key[0] &= 127; // Drop top bit to be less than modulus. | |
260 | |
261 // Mask plaintext hash with hash of prng part. | |
262 SHA_init(&sha); | |
263 SHA_update(&sha, key, this->size() - SHA_DIGEST_SIZE); | |
264 const uint8_t* mask = SHA_final(&sha); | |
265 for (int i = 0; i < SHA_DIGEST_SIZE; ++i) | |
266 hash[i] ^= mask[i]; | |
267 | |
268 // Use entire RSA number as content encryption key. | |
269 RC4_setKey(&rc4, key, this->size()); | |
270 RC4_discard(&rc4, 1536); // Warm up RC4. | |
271 | |
272 // Output wire-format version, single 0 byte. | |
273 output[0] = 0; | |
274 | |
275 // Output version, msb first. | |
276 uint32_t version = this->version(); | |
277 output[1] = version >> 24; | |
278 output[2] = version >> 16; | |
279 output[3] = version >> 8; | |
280 output[4] = version >> 0; | |
281 | |
282 // Wrap key data with public RSA key. | |
283 if (!this->raw(key, this->size())) | |
284 return 0; | |
285 | |
286 // Append encrypted message. | |
287 RC4_crypt(&rc4, msg, &output[header_size], msg_len); | |
288 | |
289 return output_len; | |
290 } | |
OLD | NEW |