Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(135)

Side by Side Diff: base/security/rsa.cc

Issue 624713003: Keep only base/extractor.[cc|h]. (Closed) Base URL: https://chromium.googlesource.com/external/omaha.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/security/rsa.h ('k') | base/security/sha.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 }
OLDNEW
« no previous file with comments | « base/security/rsa.h ('k') | base/security/sha.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698