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

Side by Side Diff: base/crypto/rsa_private_key_win.cc

Issue 141036: Fix decoding bug in RSAPrivateKey. (Closed)
Patch Set: Simpler fix Created 11 years, 6 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 | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/crypto/rsa_private_key.h" 5 #include "base/crypto/rsa_private_key.h"
6 6
7 #include <iostream> 7 #include <iostream>
8 #include <list> 8 #include <list>
9 9
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
78 78
79 // Helper to prepend an ASN.1 type header. 79 // Helper to prepend an ASN.1 type header.
80 static void PrependTypeHeaderAndLength(uint8 type, uint32 length, 80 static void PrependTypeHeaderAndLength(uint8 type, uint32 length,
81 std::list<uint8>* output) { 81 std::list<uint8>* output) {
82 PrependLength(length, output); 82 PrependLength(length, output);
83 output->push_front(type); 83 output->push_front(type);
84 } 84 }
85 85
86 // Helper to prepend an ASN.1 integer. 86 // Helper to prepend an ASN.1 integer.
87 static void PrependInteger(uint8* val, int num_bytes, std::list<uint8>* data) { 87 static void PrependInteger(uint8* val, int num_bytes, std::list<uint8>* data) {
88 // If the MSB is set, we are supposed to add an extra null byte at the front. 88 // Skip any trailing null bytes since the input is little endian.
Evan Martin 2009/06/22 16:23:45 This comment is confusing. Something like "Strip
89 bool needs_null_byte = (val[num_bytes - 1] & 0x80) != 0; 89 while (num_bytes > 1 && val[num_bytes - 1] == 0x00)
90 int length = needs_null_byte ? num_bytes + 1 : num_bytes; 90 num_bytes--;
91 91
92 PrependBytesInReverseOrder(val, num_bytes, data); 92 PrependBytesInReverseOrder(val, num_bytes, data);
93 93
94 // Add a null byte to force the integer to be positive if necessary. 94 // If the MSB is set, we need to add an extra null byte, otherwise the integer
95 if (needs_null_byte) 95 // could be interpreted as negative.
96 if ((val[num_bytes - 1] & 0x80) != 0) {
wtc 2009/06/22 17:26:18 Nit: it's less confusing to test 'data' here: if
96 data->push_front(0x00); 97 data->push_front(0x00);
98 num_bytes++;
99 }
97 100
98 PrependTypeHeaderAndLength(kIntegerTag, length, data); 101 PrependTypeHeaderAndLength(kIntegerTag, num_bytes, data);
99 } 102 }
100 103
101 // Helper for error handling during key import. 104 // Helper for error handling during key import.
102 #define READ_ASSERT(truth) \ 105 #define READ_ASSERT(truth) \
103 if (!(truth)) { \ 106 if (!(truth)) { \
104 NOTREACHED(); \ 107 NOTREACHED(); \
105 return false; \ 108 return false; \
106 } 109 }
107 110
108 // Read an ASN.1 length field. This also checks that the length does not extend 111 // Read an ASN.1 length field. This also checks that the length does not extend
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
186 out->push_back(*(*pos + i)); 189 out->push_back(*(*pos + i));
187 190
188 // The last byte can be zero to force positiveness. We can ignore this. 191 // The last byte can be zero to force positiveness. We can ignore this.
189 if (**pos != 0x00) 192 if (**pos != 0x00)
190 out->push_back(**pos); 193 out->push_back(**pos);
191 194
192 (*pos) += length; 195 (*pos) += length;
193 return true; 196 return true;
194 } 197 }
195 198
199 static bool ReadIntegerWithExpectedSize(uint8** pos, uint8* end,
200 int expected_size,
201 std::vector<uint8>* out) {
202 if (!ReadInteger(pos, end, out))
203 return false;
204
205 if (out->size() == expected_size + 1) {
206 READ_ASSERT(out->back() == 0x00);
207 out->pop_back();
208 } else {
209 READ_ASSERT(out->size() <= expected_size);
210 }
211
212 // Pad out any missing bytes with null.
wtc 2009/06/22 17:26:18 Are you sure you want to allow missing bytes? I d
213 for (size_t i = out->size(); i < expected_size; ++i)
214 out->push_back(0x00);
215
216 return true;
217 }
218
196 } // namespace 219 } // namespace
197 220
198 221
199 namespace base { 222 namespace base {
200 223
201 // static 224 // static
202 RSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) { 225 RSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) {
203 scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); 226 scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey);
204 if (!result->InitProvider()) 227 if (!result->InitProvider())
205 return NULL; 228 return NULL;
206 229
207 DWORD flags = CRYPT_EXPORTABLE; 230 DWORD flags = CRYPT_EXPORTABLE;
208 231
209 // The size is encoded as the upper 16 bits of the flags. :: sigh ::. 232 // The size is encoded as the upper 16 bits of the flags. :: sigh ::.
210 flags |= (num_bits << 16); 233 flags |= (num_bits << 16);
211 if (!CryptGenKey(result->provider_, CALG_RSA_SIGN, flags, &result->key_)) 234 if (!CryptGenKey(result->provider_, CALG_RSA_SIGN, flags, &result->key_))
212 return NULL; 235 return NULL;
213 236
214 std::vector<uint8> out;
215 result->ExportPrivateKey(&out);
216 std::cout << "Generated random key: "
217 << HexEncode(&out.front(), out.size())
218 << "\n";
219
220 return result.release(); 237 return result.release();
221 } 238 }
222 239
223 // static 240 // static
224 RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo( 241 RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo(
225 const std::vector<uint8>& input) { 242 const std::vector<uint8>& input) {
226 scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); 243 scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey);
227 if (!result->InitProvider()) 244 if (!result->InitProvider())
228 return NULL; 245 return NULL;
229 246
230 uint8* src = const_cast<uint8*>(&input.front()); 247 uint8* src = const_cast<uint8*>(&input.front());
231 uint8* end = src + input.size(); 248 uint8* end = src + input.size();
232 int version = -1; 249 int version = -1;
233 std::vector<uint8> modulus; 250 std::vector<uint8> modulus;
234 std::vector<uint8> public_exponent; 251 std::vector<uint8> public_exponent;
235 std::vector<uint8> private_exponent; 252 std::vector<uint8> private_exponent;
236 std::vector<uint8> prime1; 253 std::vector<uint8> prime1;
237 std::vector<uint8> prime2; 254 std::vector<uint8> prime2;
238 std::vector<uint8> exponent1; 255 std::vector<uint8> exponent1;
239 std::vector<uint8> exponent2; 256 std::vector<uint8> exponent2;
240 std::vector<uint8> coefficient; 257 std::vector<uint8> coefficient;
241 258
242 if (!ReadSequence(&src, end) || 259 if (!ReadSequence(&src, end) ||
243 !ReadVersion(&src, end) || 260 !ReadVersion(&src, end) ||
244 !ReadAlgorithmIdentifier(&src, end) || 261 !ReadAlgorithmIdentifier(&src, end) ||
245 !ReadTypeHeaderAndLength(&src, end, kOctetStringTag, NULL) || 262 !ReadTypeHeaderAndLength(&src, end, kOctetStringTag, NULL) ||
246 !ReadSequence(&src, end) || 263 !ReadSequence(&src, end) ||
247 !ReadVersion(&src, end) || 264 !ReadVersion(&src, end) ||
248 !ReadInteger(&src, end, &modulus) || 265 !ReadInteger(&src, end, &modulus))
249 !ReadInteger(&src, end, &public_exponent) || 266 return false;
250 !ReadInteger(&src, end, &private_exponent) || 267
251 !ReadInteger(&src, end, &prime1) || 268 int mod_size = modulus.size();
252 !ReadInteger(&src, end, &prime2) || 269 READ_ASSERT(mod_size % 2 == 0);
253 !ReadInteger(&src, end, &exponent1) || 270 int primes_size = mod_size / 2;
254 !ReadInteger(&src, end, &exponent2) || 271
255 !ReadInteger(&src, end, &coefficient)) 272 if (!ReadIntegerWithExpectedSize(&src, end, 4, &public_exponent) ||
wtc 2009/06/22 17:26:18 The expected size of 4 for the public exponent ass
273 !ReadIntegerWithExpectedSize(&src, end, mod_size, &private_exponent) ||
274 !ReadIntegerWithExpectedSize(&src, end, primes_size, &prime1) ||
275 !ReadIntegerWithExpectedSize(&src, end, primes_size, &prime2) ||
276 !ReadIntegerWithExpectedSize(&src, end, primes_size, &exponent1) ||
277 !ReadIntegerWithExpectedSize(&src, end, primes_size, &exponent2) ||
278 !ReadIntegerWithExpectedSize(&src, end, primes_size, &coefficient))
256 return false; 279 return false;
257 280
258 READ_ASSERT(src == end); 281 READ_ASSERT(src == end);
259 282
260 int blob_size = sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY) + modulus.size() + 283 int blob_size = sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY) + modulus.size() +
261 prime1.size() + prime2.size() + 284 prime1.size() + prime2.size() +
262 exponent1.size() + exponent2.size() + 285 exponent1.size() + exponent2.size() +
263 coefficient.size() + private_exponent.size(); 286 coefficient.size() + private_exponent.size();
264 scoped_array<BYTE> blob(new BYTE[blob_size]); 287 scoped_array<BYTE> blob(new BYTE[blob_size]);
265 288
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
343 366
344 uint8* pos = blob.get(); 367 uint8* pos = blob.get();
345 PUBLICKEYSTRUC *publickey_struct = reinterpret_cast<PUBLICKEYSTRUC*>(pos); 368 PUBLICKEYSTRUC *publickey_struct = reinterpret_cast<PUBLICKEYSTRUC*>(pos);
346 pos += sizeof(PUBLICKEYSTRUC); 369 pos += sizeof(PUBLICKEYSTRUC);
347 370
348 RSAPUBKEY *rsa_pub_key = reinterpret_cast<RSAPUBKEY*>(pos); 371 RSAPUBKEY *rsa_pub_key = reinterpret_cast<RSAPUBKEY*>(pos);
349 pos += sizeof(RSAPUBKEY); 372 pos += sizeof(RSAPUBKEY);
350 373
351 int mod_size = rsa_pub_key->bitlen / 8; 374 int mod_size = rsa_pub_key->bitlen / 8;
352 int primes_size = rsa_pub_key->bitlen / 16; 375 int primes_size = rsa_pub_key->bitlen / 16;
353 int exponents_size = primes_size;
354 int coefficient_size = primes_size;
355 int private_exponent_size = mod_size;
356 376
357 uint8* modulus = pos; 377 uint8* modulus = pos;
358 pos += mod_size; 378 pos += mod_size;
359 379
360 uint8* prime1 = pos; 380 uint8* prime1 = pos;
361 pos += primes_size; 381 pos += primes_size;
362 uint8* prime2 = pos; 382 uint8* prime2 = pos;
363 pos += primes_size; 383 pos += primes_size;
364 384
365 uint8* exponent1 = pos; 385 uint8* exponent1 = pos;
366 pos += exponents_size; 386 pos += primes_size;
367 uint8* exponent2 = pos; 387 uint8* exponent2 = pos;
368 pos += exponents_size; 388 pos += primes_size;
369 389
370 uint8* coefficient = pos; 390 uint8* coefficient = pos;
371 pos += coefficient_size; 391 pos += primes_size;
372 392
373 uint8* private_exponent = pos; 393 uint8* private_exponent = pos;
374 pos += private_exponent_size; 394 pos += mod_size;
375 395
376 CHECK((pos - blob_length) == reinterpret_cast<BYTE*>(publickey_struct)); 396 CHECK((pos - blob_length) == reinterpret_cast<BYTE*>(publickey_struct));
377 397
378 std::list<uint8> content; 398 std::list<uint8> content;
379 399
380 // Version (always zero) 400 // Version (always zero)
381 uint8 version = 0; 401 uint8 version = 0;
382 402
383 // We build up the output in reverse order to prevent having to do copies to 403 // We build up the output in reverse order to prevent having to do copies to
384 // figure out the length. 404 // figure out the length.
385 PrependInteger(coefficient, coefficient_size, &content); 405 PrependInteger(coefficient, primes_size, &content);
386 PrependInteger(exponent2, exponents_size, &content); 406 PrependInteger(exponent2, primes_size, &content);
387 PrependInteger(exponent1, exponents_size, &content); 407 PrependInteger(exponent1, primes_size, &content);
388 PrependInteger(prime2, primes_size, &content); 408 PrependInteger(prime2, primes_size, &content);
389 PrependInteger(prime1, primes_size, &content); 409 PrependInteger(prime1, primes_size, &content);
390 PrependInteger(private_exponent, private_exponent_size, &content); 410 PrependInteger(private_exponent, mod_size, &content);
391 PrependInteger(reinterpret_cast<uint8*>(&rsa_pub_key->pubexp), 4, &content); 411 PrependInteger(reinterpret_cast<uint8*>(&rsa_pub_key->pubexp), 4, &content);
392 PrependInteger(modulus, mod_size, &content); 412 PrependInteger(modulus, mod_size, &content);
393 PrependInteger(&version, 1, &content); 413 PrependInteger(&version, 1, &content);
394 PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content); 414 PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content);
395 PrependTypeHeaderAndLength(kOctetStringTag, content.size(), &content); 415 PrependTypeHeaderAndLength(kOctetStringTag, content.size(), &content);
396 416
397 // RSA algorithm OID 417 // RSA algorithm OID
398 for (size_t i = sizeof(kRsaAlgorithmIdentifier); i > 0; --i) 418 for (size_t i = sizeof(kRsaAlgorithmIdentifier); i > 0; --i)
399 content.push_front(kRsaAlgorithmIdentifier[i - 1]); 419 content.push_front(kRsaAlgorithmIdentifier[i - 1]);
400 420
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
444 return false; 464 return false;
445 } 465 }
446 466
447 for (size_t i = 0; i < encoded_length; ++i) 467 for (size_t i = 0; i < encoded_length; ++i)
448 output->push_back(encoded[i]); 468 output->push_back(encoded[i]);
449 469
450 return true; 470 return true;
451 } 471 }
452 472
453 } // namespace base 473 } // namespace base
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698