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

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

Issue 242136: Refactor ASN1 parsing/serializationg (Closed)
Patch Set: more cr changes Created 11 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/crypto/rsa_private_key_nss.cc ('k') | base/crypto/signature_creator_unittest.cc » ('j') | 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"
11 #include "base/scoped_ptr.h" 11 #include "base/scoped_ptr.h"
12 #include "base/string_util.h" 12 #include "base/string_util.h"
13 13
14
15 // This file manually encodes and decodes RSA private keys using PrivateKeyInfo
16 // from PKCS #8 and RSAPrivateKey from PKCS #1. These structures are:
17 //
18 // PrivateKeyInfo ::= SEQUENCE {
19 // version Version,
20 // privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
21 // privateKey PrivateKey,
22 // attributes [0] IMPLICIT Attributes OPTIONAL
23 // }
24 //
25 // RSAPrivateKey ::= SEQUENCE {
26 // version Version,
27 // modulus INTEGER,
28 // publicExponent INTEGER,
29 // privateExponent INTEGER,
30 // prime1 INTEGER,
31 // prime2 INTEGER,
32 // exponent1 INTEGER,
33 // exponent2 INTEGER,
34 // coefficient INTEGER
35 // }
36
37
38 namespace { 14 namespace {
39 15 // Helper for error handling during key import.
40 // ASN.1 encoding of the AlgorithmIdentifier from PKCS #8.
41 const uint8 kRsaAlgorithmIdentifier[] = {
42 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01,
43 0x05, 0x00
44 };
45
46 // ASN.1 tags for some types we use.
47 const uint8 kSequenceTag = 0x30;
48 const uint8 kIntegerTag = 0x02;
49 const uint8 kNullTag = 0x05;
50 const uint8 kOctetStringTag = 0x04;
51
52 // Helper function to prepend an array of bytes into a list, reversing their
53 // order. This is needed because ASN.1 integers are big-endian, while CryptoAPI
54 // uses little-endian.
55 static void PrependBytesInReverseOrder(uint8* val, int num_bytes,
56 std::list<uint8>* data) {
57 for (int i = 0; i < num_bytes; ++i)
58 data->push_front(val[i]);
59 }
60
61 // Helper to prepend an ASN.1 length field.
62 static void PrependLength(size_t size, std::list<uint8>* data) {
63 // The high bit is used to indicate whether additional octets are needed to
64 // represent the length.
65 if (size < 0x80) {
66 data->push_front(static_cast<uint8>(size));
67 } else {
68 uint8 num_bytes = 0;
69 while (size > 0) {
70 data->push_front(static_cast<uint8>(size & 0xFF));
71 size >>= 8;
72 num_bytes++;
73 }
74 CHECK(num_bytes <= 4);
75 data->push_front(0x80 | num_bytes);
76 }
77 }
78
79 // Helper to prepend an ASN.1 type header.
80 static void PrependTypeHeaderAndLength(uint8 type, uint32 length,
81 std::list<uint8>* output) {
82 PrependLength(length, output);
83 output->push_front(type);
84 }
85
86 // Helper to prepend an ASN.1 integer.
87 static void PrependInteger(uint8* val, int num_bytes, std::list<uint8>* data) {
88 // Skip trailing null bytes off the MSB end, which is the tail since the input
89 // is little endian.
90 while (num_bytes > 1 && val[num_bytes - 1] == 0x00)
91 num_bytes--;
92
93 PrependBytesInReverseOrder(val, num_bytes, data);
94
95 // If the MSB is set, we need to add an extra null byte, otherwise the integer
96 // could be interpreted as negative.
97 if ((val[num_bytes - 1] & 0x80) != 0) {
98 data->push_front(0x00);
99 num_bytes++;
100 }
101
102 PrependTypeHeaderAndLength(kIntegerTag, num_bytes, data);
103 }
104
105 // Helper for error handling during key import.
106 #define READ_ASSERT(truth) \ 16 #define READ_ASSERT(truth) \
107 if (!(truth)) { \ 17 if (!(truth)) { \
108 NOTREACHED(); \ 18 NOTREACHED(); \
109 return false; \ 19 return false; \
110 } 20 }
111
112 // Read an ASN.1 length field. This also checks that the length does not extend
113 // beyond |end|.
114 static bool ReadLength(uint8** pos, uint8* end, uint32* result) {
115 READ_ASSERT(*pos < end);
116 int length = 0;
117
118 // If the MSB is not set, the length is just the byte itself.
119 if (!(**pos & 0x80)) {
120 length = **pos;
121 (*pos)++;
122 } else {
123 // Otherwise, the lower 7 indicate the length of the length.
124 int length_of_length = **pos & 0x7F;
125 READ_ASSERT(length_of_length <= 4);
126 (*pos)++;
127 READ_ASSERT(*pos + length_of_length < end);
128
129 length = 0;
130 for (int i = 0; i < length_of_length; ++i) {
131 length <<= 8;
132 length |= **pos;
133 (*pos)++;
134 }
135 }
136
137 READ_ASSERT(*pos + length <= end);
138 if (result) *result = length;
139 return true;
140 }
141
142 // Read an ASN.1 type header and its length.
143 static bool ReadTypeHeaderAndLength(uint8** pos, uint8* end,
144 uint8 expected_tag, uint32* length) {
145 READ_ASSERT(*pos < end);
146 READ_ASSERT(**pos == expected_tag);
147 (*pos)++;
148
149 return ReadLength(pos, end, length);
150 }
151
152 // Read an ASN.1 sequence declaration. This consumes the type header and length
153 // field, but not the contents of the sequence.
154 static bool ReadSequence(uint8** pos, uint8* end) {
155 return ReadTypeHeaderAndLength(pos, end, kSequenceTag, NULL);
156 }
157
158 // Read the RSA AlgorithmIdentifier.
159 static bool ReadAlgorithmIdentifier(uint8** pos, uint8* end) {
160 READ_ASSERT(*pos + sizeof(kRsaAlgorithmIdentifier) < end);
161 READ_ASSERT(memcmp(*pos, kRsaAlgorithmIdentifier,
162 sizeof(kRsaAlgorithmIdentifier)) == 0);
163 (*pos) += sizeof(kRsaAlgorithmIdentifier);
164 return true;
165 }
166
167 // Read one of the two version fields in PrivateKeyInfo.
168 static bool ReadVersion(uint8** pos, uint8* end) {
169 uint32 length = 0;
170 if (!ReadTypeHeaderAndLength(pos, end, kIntegerTag, &length))
171 return false;
172
173 // The version should be zero.
174 for (uint32 i = 0; i < length; ++i) {
175 READ_ASSERT(**pos == 0x00);
176 (*pos)++;
177 }
178
179 return true;
180 }
181
182 // Read an ASN.1 integer.
183 static bool ReadInteger(uint8** pos, uint8* end, std::vector<uint8>* out) {
184 uint32 length = 0;
185 if (!ReadTypeHeaderAndLength(pos, end, kIntegerTag, &length))
186 return false;
187
188 // Read the bytes out in reverse order because of endianness.
189 for (uint32 i = length - 1; i > 0; --i)
190 out->push_back(*(*pos + i));
191
192 // The last byte can be zero to force positiveness. We can ignore this.
193 if (**pos != 0x00)
194 out->push_back(**pos);
195
196 (*pos) += length;
197 return true;
198 }
199
200 static bool ReadIntegerWithExpectedSize(uint8** pos, uint8* end,
201 int expected_size,
202 std::vector<uint8>* out) {
203 if (!ReadInteger(pos, end, out))
204 return false;
205
206 if (out->size() == expected_size + 1) {
207 READ_ASSERT(out->back() == 0x00);
208 out->pop_back();
209 } else {
210 READ_ASSERT(out->size() <= expected_size);
211 }
212
213 // Pad out any missing bytes with null.
214 for (size_t i = out->size(); i < expected_size; ++i)
215 out->push_back(0x00);
216
217 return true;
218 }
219
220 } // namespace 21 } // namespace
221 22
222
223 namespace base { 23 namespace base {
224 24
225 // static 25 // static
226 RSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) { 26 RSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) {
227 scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); 27 scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey);
228 if (!result->InitProvider()) 28 if (!result->InitProvider())
229 return NULL; 29 return NULL;
230 30
231 DWORD flags = CRYPT_EXPORTABLE; 31 DWORD flags = CRYPT_EXPORTABLE;
232 32
233 // The size is encoded as the upper 16 bits of the flags. :: sigh ::. 33 // The size is encoded as the upper 16 bits of the flags. :: sigh ::.
234 flags |= (num_bits << 16); 34 flags |= (num_bits << 16);
235 if (!CryptGenKey(result->provider_, CALG_RSA_SIGN, flags, &result->key_)) 35 if (!CryptGenKey(result->provider_, CALG_RSA_SIGN, flags, &result->key_))
236 return NULL; 36 return NULL;
237 37
238 return result.release(); 38 return result.release();
239 } 39 }
240 40
241 // static 41 // static
242 RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo( 42 RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo(
243 const std::vector<uint8>& input) { 43 const std::vector<uint8>& input) {
244 scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); 44 scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey);
245 if (!result->InitProvider()) 45 if (!result->InitProvider())
246 return NULL; 46 return NULL;
247 47
248 uint8* src = const_cast<uint8*>(&input.front()); 48 PrivateKeyInfoCodec pki(false); // Little-Endian
249 uint8* end = src + input.size(); 49 pki.Import(input);
250 int version = -1;
251 std::vector<uint8> modulus;
252 std::vector<uint8> public_exponent;
253 std::vector<uint8> private_exponent;
254 std::vector<uint8> prime1;
255 std::vector<uint8> prime2;
256 std::vector<uint8> exponent1;
257 std::vector<uint8> exponent2;
258 std::vector<uint8> coefficient;
259 50
260 if (!ReadSequence(&src, end) || 51 int blob_size = sizeof(PUBLICKEYSTRUC) +
261 !ReadVersion(&src, end) || 52 sizeof(RSAPUBKEY) +
262 !ReadAlgorithmIdentifier(&src, end) || 53 pki.modulus()->size() +
263 !ReadTypeHeaderAndLength(&src, end, kOctetStringTag, NULL) || 54 pki.prime1()->size() +
264 !ReadSequence(&src, end) || 55 pki.prime2()->size() +
265 !ReadVersion(&src, end) || 56 pki.exponent1()->size() +
266 !ReadInteger(&src, end, &modulus)) 57 pki.exponent2()->size() +
267 return false; 58 pki.coefficient()->size() +
268 59 pki.private_exponent()->size();
269 int mod_size = modulus.size();
270 READ_ASSERT(mod_size % 2 == 0);
271 int primes_size = mod_size / 2;
272
273 if (!ReadIntegerWithExpectedSize(&src, end, 4, &public_exponent) ||
274 !ReadIntegerWithExpectedSize(&src, end, mod_size, &private_exponent) ||
275 !ReadIntegerWithExpectedSize(&src, end, primes_size, &prime1) ||
276 !ReadIntegerWithExpectedSize(&src, end, primes_size, &prime2) ||
277 !ReadIntegerWithExpectedSize(&src, end, primes_size, &exponent1) ||
278 !ReadIntegerWithExpectedSize(&src, end, primes_size, &exponent2) ||
279 !ReadIntegerWithExpectedSize(&src, end, primes_size, &coefficient))
280 return false;
281
282 READ_ASSERT(src == end);
283
284 int blob_size = sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY) + modulus.size() +
285 prime1.size() + prime2.size() +
286 exponent1.size() + exponent2.size() +
287 coefficient.size() + private_exponent.size();
288 scoped_array<BYTE> blob(new BYTE[blob_size]); 60 scoped_array<BYTE> blob(new BYTE[blob_size]);
289 61
290 uint8* dest = blob.get(); 62 uint8* dest = blob.get();
291 PUBLICKEYSTRUC* public_key_struc = reinterpret_cast<PUBLICKEYSTRUC*>(dest); 63 PUBLICKEYSTRUC* public_key_struc = reinterpret_cast<PUBLICKEYSTRUC*>(dest);
292 public_key_struc->bType = PRIVATEKEYBLOB; 64 public_key_struc->bType = PRIVATEKEYBLOB;
293 public_key_struc->bVersion = 0x02; 65 public_key_struc->bVersion = 0x02;
294 public_key_struc->reserved = 0; 66 public_key_struc->reserved = 0;
295 public_key_struc->aiKeyAlg = CALG_RSA_SIGN; 67 public_key_struc->aiKeyAlg = CALG_RSA_SIGN;
296 dest += sizeof(PUBLICKEYSTRUC); 68 dest += sizeof(PUBLICKEYSTRUC);
297 69
298 RSAPUBKEY* rsa_pub_key = reinterpret_cast<RSAPUBKEY*>(dest); 70 RSAPUBKEY* rsa_pub_key = reinterpret_cast<RSAPUBKEY*>(dest);
299 rsa_pub_key->magic = 0x32415352; 71 rsa_pub_key->magic = 0x32415352;
300 rsa_pub_key->bitlen = modulus.size() * 8; 72 rsa_pub_key->bitlen = pki.modulus()->size() * 8;
301 int public_exponent_int = 0; 73 int public_exponent_int = 0;
302 for (size_t i = public_exponent.size(); i > 0; --i) { 74 for (size_t i = pki.public_exponent()->size(); i > 0; --i) {
303 public_exponent_int <<= 8; 75 public_exponent_int <<= 8;
304 public_exponent_int |= public_exponent[i - 1]; 76 public_exponent_int |= (*pki.public_exponent())[i - 1];
305 } 77 }
306 rsa_pub_key->pubexp = public_exponent_int; 78 rsa_pub_key->pubexp = public_exponent_int;
307 dest += sizeof(RSAPUBKEY); 79 dest += sizeof(RSAPUBKEY);
308 80
309 memcpy(dest, &modulus.front(), modulus.size()); 81 memcpy(dest, &pki.modulus()->front(), pki.modulus()->size());
310 dest += modulus.size(); 82 dest += pki.modulus()->size();
311 memcpy(dest, &prime1.front(), prime1.size()); 83 memcpy(dest, &pki.prime1()->front(), pki.prime1()->size());
312 dest += prime1.size(); 84 dest += pki.prime1()->size();
313 memcpy(dest, &prime2.front(), prime2.size()); 85 memcpy(dest, &pki.prime2()->front(), pki.prime2()->size());
314 dest += prime2.size(); 86 dest += pki.prime2()->size();
315 memcpy(dest, &exponent1.front(), exponent1.size()); 87 memcpy(dest, &pki.exponent1()->front(), pki.exponent1()->size());
316 dest += exponent1.size(); 88 dest += pki.exponent1()->size();
317 memcpy(dest, &exponent2.front(), exponent2.size()); 89 memcpy(dest, &pki.exponent2()->front(), pki.exponent2()->size());
318 dest += exponent2.size(); 90 dest += pki.exponent2()->size();
319 memcpy(dest, &coefficient.front(), coefficient.size()); 91 memcpy(dest, &pki.coefficient()->front(), pki.coefficient()->size());
320 dest += coefficient.size(); 92 dest += pki.coefficient()->size();
321 memcpy(dest, &private_exponent.front(), private_exponent.size()); 93 memcpy(dest, &pki.private_exponent()->front(), pki.private_exponent()->size()) ;
322 dest += private_exponent.size(); 94 dest += pki.private_exponent()->size();
323 95
324 READ_ASSERT(dest == blob.get() + blob_size); 96 READ_ASSERT(dest == blob.get() + blob_size);
325 if (!CryptImportKey( 97 if (!CryptImportKey(
326 result->provider_, reinterpret_cast<uint8*>(public_key_struc), blob_size, 98 result->provider_, reinterpret_cast<uint8*>(public_key_struc), blob_size,
327 NULL, CRYPT_EXPORTABLE, &result->key_)) { 99 NULL, CRYPT_EXPORTABLE, &result->key_)) {
328 return NULL; 100 return NULL;
329 } 101 }
330 102
331 return result.release(); 103 return result.release();
332 } 104 }
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
368 uint8* pos = blob.get(); 140 uint8* pos = blob.get();
369 PUBLICKEYSTRUC *publickey_struct = reinterpret_cast<PUBLICKEYSTRUC*>(pos); 141 PUBLICKEYSTRUC *publickey_struct = reinterpret_cast<PUBLICKEYSTRUC*>(pos);
370 pos += sizeof(PUBLICKEYSTRUC); 142 pos += sizeof(PUBLICKEYSTRUC);
371 143
372 RSAPUBKEY *rsa_pub_key = reinterpret_cast<RSAPUBKEY*>(pos); 144 RSAPUBKEY *rsa_pub_key = reinterpret_cast<RSAPUBKEY*>(pos);
373 pos += sizeof(RSAPUBKEY); 145 pos += sizeof(RSAPUBKEY);
374 146
375 int mod_size = rsa_pub_key->bitlen / 8; 147 int mod_size = rsa_pub_key->bitlen / 8;
376 int primes_size = rsa_pub_key->bitlen / 16; 148 int primes_size = rsa_pub_key->bitlen / 16;
377 149
378 uint8* modulus = pos; 150 PrivateKeyInfoCodec pki(false); // Little-Endian
151
152 pki.modulus()->assign(pos, pos + mod_size);
379 pos += mod_size; 153 pos += mod_size;
380 154
381 uint8* prime1 = pos; 155 pki.prime1()->assign(pos, pos + primes_size);
382 pos += primes_size; 156 pos += primes_size;
383 uint8* prime2 = pos; 157 pki.prime2()->assign(pos, pos + primes_size);
384 pos += primes_size; 158 pos += primes_size;
385 159
386 uint8* exponent1 = pos; 160 pki.exponent1()->assign(pos, pos + primes_size);
387 pos += primes_size; 161 pos += primes_size;
388 uint8* exponent2 = pos; 162 pki.exponent2()->assign(pos, pos + primes_size);
389 pos += primes_size; 163 pos += primes_size;
390 164
391 uint8* coefficient = pos; 165 pki.coefficient()->assign(pos, pos + primes_size);
392 pos += primes_size; 166 pos += primes_size;
393 167
394 uint8* private_exponent = pos; 168 pki.private_exponent()->assign(pos, pos + mod_size);
395 pos += mod_size; 169 pos += mod_size;
396 170
171 pki.public_exponent()->assign(reinterpret_cast<uint8*>(&rsa_pub_key->pubexp),
172 reinterpret_cast<uint8*>(&rsa_pub_key->pubexp) + 4);
173
397 CHECK((pos - blob_length) == reinterpret_cast<BYTE*>(publickey_struct)); 174 CHECK((pos - blob_length) == reinterpret_cast<BYTE*>(publickey_struct));
398 175
399 std::list<uint8> content; 176 return pki.Export(output);
400
401 // Version (always zero)
402 uint8 version = 0;
403
404 // We build up the output in reverse order to prevent having to do copies to
405 // figure out the length.
406 PrependInteger(coefficient, primes_size, &content);
407 PrependInteger(exponent2, primes_size, &content);
408 PrependInteger(exponent1, primes_size, &content);
409 PrependInteger(prime2, primes_size, &content);
410 PrependInteger(prime1, primes_size, &content);
411 PrependInteger(private_exponent, mod_size, &content);
412 PrependInteger(reinterpret_cast<uint8*>(&rsa_pub_key->pubexp), 4, &content);
413 PrependInteger(modulus, mod_size, &content);
414 PrependInteger(&version, 1, &content);
415 PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content);
416 PrependTypeHeaderAndLength(kOctetStringTag, content.size(), &content);
417
418 // RSA algorithm OID
419 for (size_t i = sizeof(kRsaAlgorithmIdentifier); i > 0; --i)
420 content.push_front(kRsaAlgorithmIdentifier[i - 1]);
421
422 PrependInteger(&version, 1, &content);
423 PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content);
424
425 // Copy everying into the output.
426 output->reserve(content.size());
427 for (std::list<uint8>::iterator i = content.begin(); i != content.end(); ++i)
428 output->push_back(*i);
429
430 return true;
431 } 177 }
432 178
433 bool RSAPrivateKey::ExportPublicKey(std::vector<uint8>* output) { 179 bool RSAPrivateKey::ExportPublicKey(std::vector<uint8>* output) {
434 DWORD key_info_len; 180 DWORD key_info_len;
435 if (!CryptExportPublicKeyInfo( 181 if (!CryptExportPublicKeyInfo(
436 provider_, AT_SIGNATURE, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 182 provider_, AT_SIGNATURE, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
437 NULL, &key_info_len)) { 183 NULL, &key_info_len)) {
438 NOTREACHED(); 184 NOTREACHED();
439 return false; 185 return false;
440 } 186 }
(...skipping 24 matching lines...) Expand all
465 return false; 211 return false;
466 } 212 }
467 213
468 for (size_t i = 0; i < encoded_length; ++i) 214 for (size_t i = 0; i < encoded_length; ++i)
469 output->push_back(encoded[i]); 215 output->push_back(encoded[i]);
470 216
471 return true; 217 return true;
472 } 218 }
473 219
474 } // namespace base 220 } // namespace base
OLDNEW
« no previous file with comments | « base/crypto/rsa_private_key_nss.cc ('k') | base/crypto/signature_creator_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698