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

Side by Side Diff: crypto/rsa_private_key_nss.cc

Issue 1829933002: Move PrivateKeyInfoCodec to rsa_private_key_nss.cc (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 9 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 | « crypto/rsa_private_key.cc ('k') | 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) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "crypto/rsa_private_key.h" 5 #include "crypto/rsa_private_key.h"
6 6
7 #include <cryptohi.h> 7 #include <cryptohi.h>
8 #include <keyhi.h> 8 #include <keyhi.h>
9 #include <pk11pub.h> 9 #include <pk11pub.h>
10 #include <stdint.h> 10 #include <stdint.h>
11 11
12 #include <list> 12 #include <list>
13 13
14 #include "base/debug/leak_annotations.h" 14 #include "base/debug/leak_annotations.h"
15 #include "base/logging.h" 15 #include "base/logging.h"
16 #include "base/memory/scoped_ptr.h" 16 #include "base/memory/scoped_ptr.h"
17 #include "base/strings/string_util.h" 17 #include "base/strings/string_util.h"
18 #include "crypto/nss_key_util.h" 18 #include "crypto/nss_key_util.h"
19 #include "crypto/nss_util.h" 19 #include "crypto/nss_util.h"
20 #include "crypto/scoped_nss_types.h" 20 #include "crypto/scoped_nss_types.h"
21 21
22 // Helper for error handling during key import.
23 #define READ_ASSERT(truth) \
24 if (!(truth)) { \
25 NOTREACHED(); \
26 return false; \
27 }
28
22 // TODO(rafaelw): Consider using NSS's ASN.1 encoder. 29 // TODO(rafaelw): Consider using NSS's ASN.1 encoder.
23 namespace { 30 namespace {
24 31
25 static bool ReadAttribute(SECKEYPrivateKey* key, 32 static bool ReadAttribute(SECKEYPrivateKey* key,
26 CK_ATTRIBUTE_TYPE type, 33 CK_ATTRIBUTE_TYPE type,
27 std::vector<uint8_t>* output) { 34 std::vector<uint8_t>* output) {
28 SECItem item; 35 SECItem item;
29 SECStatus rv; 36 SECStatus rv;
30 rv = PK11_ReadRawAttribute(PK11_TypePrivKey, key, type, &item); 37 rv = PK11_ReadRawAttribute(PK11_TypePrivKey, key, type, &item);
31 if (rv != SECSuccess) { 38 if (rv != SECSuccess) {
32 NOTREACHED(); 39 NOTREACHED();
33 return false; 40 return false;
34 } 41 }
35 42
36 output->assign(item.data, item.data + item.len); 43 output->assign(item.data, item.data + item.len);
37 SECITEM_FreeItem(&item, PR_FALSE); 44 SECITEM_FreeItem(&item, PR_FALSE);
38 return true; 45 return true;
39 } 46 }
40 47
48 // Used internally by RSAPrivateKey for serializing and deserializing
49 // PKCS #8 PrivateKeyInfo and PublicKeyInfo.
50 class PrivateKeyInfoCodec {
51 public:
52 // ASN.1 encoding of the AlgorithmIdentifier from PKCS #8.
53 static const uint8_t kRsaAlgorithmIdentifier[];
54
55 // ASN.1 tags for some types we use.
56 static const uint8_t kBitStringTag = 0x03;
57 static const uint8_t kIntegerTag = 0x02;
58 static const uint8_t kNullTag = 0x05;
nharper 2016/03/23 22:08:14 iOS compile is complaining this is unused - I'd re
davidben 2016/03/23 22:23:50 Done.
59 static const uint8_t kOctetStringTag = 0x04;
60 static const uint8_t kSequenceTag = 0x30;
61
62 // |big_endian| here specifies the byte-significance of the integer components
63 // that will be parsed & serialized (modulus(), etc...) during Import(),
64 // Export() and ExportPublicKeyInfo() -- not the ASN.1 DER encoding of the
65 // PrivateKeyInfo/PublicKeyInfo (which is always big-endian).
66 explicit PrivateKeyInfoCodec(bool big_endian);
67
68 ~PrivateKeyInfoCodec();
69
70 // Exports the contents of the integer components to the ASN.1 DER encoding
71 // of the PrivateKeyInfo structure to |output|.
72 bool Export(std::vector<uint8_t>* output);
73
74 // Exports the contents of the integer components to the ASN.1 DER encoding
75 // of the PublicKeyInfo structure to |output|.
76 bool ExportPublicKeyInfo(std::vector<uint8_t>* output);
77
78 // Exports the contents of the integer components to the ASN.1 DER encoding
79 // of the RSAPublicKey structure to |output|.
80 bool ExportPublicKey(std::vector<uint8_t>* output);
81
82 // Parses the ASN.1 DER encoding of the PrivateKeyInfo structure in |input|
83 // and populates the integer components with |big_endian_| byte-significance.
84 // IMPORTANT NOTE: This is currently *not* security-approved for importing
85 // keys from unstrusted sources.
86 bool Import(const std::vector<uint8_t>& input);
87
88 // Accessors to the contents of the integer components of the PrivateKeyInfo
89 // structure.
90 std::vector<uint8_t>* modulus() { return &modulus_; }
91 std::vector<uint8_t>* public_exponent() { return &public_exponent_; }
92 std::vector<uint8_t>* private_exponent() { return &private_exponent_; }
93 std::vector<uint8_t>* prime1() { return &prime1_; }
94 std::vector<uint8_t>* prime2() { return &prime2_; }
95 std::vector<uint8_t>* exponent1() { return &exponent1_; }
96 std::vector<uint8_t>* exponent2() { return &exponent2_; }
97 std::vector<uint8_t>* coefficient() { return &coefficient_; }
98
99 private:
100 // Utility wrappers for PrependIntegerImpl that use the class's |big_endian_|
101 // value.
102 void PrependInteger(const std::vector<uint8_t>& in, std::list<uint8_t>* out);
103 void PrependInteger(uint8_t* val, int num_bytes, std::list<uint8_t>* data);
104
105 // Prepends the integer stored in |val| - |val + num_bytes| with |big_endian|
106 // byte-significance into |data| as an ASN.1 integer.
107 void PrependIntegerImpl(uint8_t* val,
108 int num_bytes,
109 std::list<uint8_t>* data,
110 bool big_endian);
111
112 // Utility wrappers for ReadIntegerImpl that use the class's |big_endian_|
113 // value.
114 bool ReadInteger(uint8_t** pos, uint8_t* end, std::vector<uint8_t>* out);
115 bool ReadIntegerWithExpectedSize(uint8_t** pos,
116 uint8_t* end,
117 size_t expected_size,
118 std::vector<uint8_t>* out);
119
120 // Reads an ASN.1 integer from |pos|, and stores the result into |out| with
121 // |big_endian| byte-significance.
122 bool ReadIntegerImpl(uint8_t** pos,
123 uint8_t* end,
124 std::vector<uint8_t>* out,
125 bool big_endian);
126
127 // Prepends the integer stored in |val|, starting a index |start|, for
128 // |num_bytes| bytes onto |data|.
129 void PrependBytes(uint8_t* val,
130 int start,
131 int num_bytes,
132 std::list<uint8_t>* data);
133
134 // Helper to prepend an ASN.1 length field.
135 void PrependLength(size_t size, std::list<uint8_t>* data);
136
137 // Helper to prepend an ASN.1 type header.
138 void PrependTypeHeaderAndLength(uint8_t type,
139 uint32_t length,
140 std::list<uint8_t>* output);
141
142 // Helper to prepend an ASN.1 bit string
143 void PrependBitString(uint8_t* val,
144 int num_bytes,
145 std::list<uint8_t>* output);
146
147 // Read an ASN.1 length field. This also checks that the length does not
148 // extend beyond |end|.
149 bool ReadLength(uint8_t** pos, uint8_t* end, uint32_t* result);
150
151 // Read an ASN.1 type header and its length.
152 bool ReadTypeHeaderAndLength(uint8_t** pos,
153 uint8_t* end,
154 uint8_t expected_tag,
155 uint32_t* length);
156
157 // Read an ASN.1 sequence declaration. This consumes the type header and
158 // length field, but not the contents of the sequence.
159 bool ReadSequence(uint8_t** pos, uint8_t* end);
160
161 // Read the RSA AlgorithmIdentifier.
162 bool ReadAlgorithmIdentifier(uint8_t** pos, uint8_t* end);
163
164 // Read one of the two version fields in PrivateKeyInfo.
165 bool ReadVersion(uint8_t** pos, uint8_t* end);
166
167 // The byte-significance of the stored components (modulus, etc..).
168 bool big_endian_;
169
170 // Component integers of the PrivateKeyInfo
171 std::vector<uint8_t> modulus_;
172 std::vector<uint8_t> public_exponent_;
173 std::vector<uint8_t> private_exponent_;
174 std::vector<uint8_t> prime1_;
175 std::vector<uint8_t> prime2_;
176 std::vector<uint8_t> exponent1_;
177 std::vector<uint8_t> exponent2_;
178 std::vector<uint8_t> coefficient_;
179
180 DISALLOW_COPY_AND_ASSIGN(PrivateKeyInfoCodec);
181 };
182
183 const uint8_t PrivateKeyInfoCodec::kRsaAlgorithmIdentifier[] = {
184 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86,
185 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00};
186
187 PrivateKeyInfoCodec::PrivateKeyInfoCodec(bool big_endian)
188 : big_endian_(big_endian) {}
189
190 PrivateKeyInfoCodec::~PrivateKeyInfoCodec() {}
191
192 bool PrivateKeyInfoCodec::Export(std::vector<uint8_t>* output) {
193 std::list<uint8_t> content;
194
195 // Version (always zero)
196 uint8_t version = 0;
197
198 PrependInteger(coefficient_, &content);
199 PrependInteger(exponent2_, &content);
200 PrependInteger(exponent1_, &content);
201 PrependInteger(prime2_, &content);
202 PrependInteger(prime1_, &content);
203 PrependInteger(private_exponent_, &content);
204 PrependInteger(public_exponent_, &content);
205 PrependInteger(modulus_, &content);
206 PrependInteger(&version, 1, &content);
207 PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content);
208 PrependTypeHeaderAndLength(kOctetStringTag, content.size(), &content);
209
210 // RSA algorithm OID
211 for (size_t i = sizeof(kRsaAlgorithmIdentifier); i > 0; --i)
212 content.push_front(kRsaAlgorithmIdentifier[i - 1]);
213
214 PrependInteger(&version, 1, &content);
215 PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content);
216
217 // Copy everying into the output.
218 output->reserve(content.size());
219 output->assign(content.begin(), content.end());
220
221 return true;
222 }
223
224 bool PrivateKeyInfoCodec::ExportPublicKeyInfo(std::vector<uint8_t>* output) {
225 // Create a sequence with the modulus (n) and public exponent (e).
226 std::vector<uint8_t> bit_string;
227 if (!ExportPublicKey(&bit_string))
228 return false;
229
230 // Add the sequence as the contents of a bit string.
231 std::list<uint8_t> content;
232 PrependBitString(&bit_string[0], static_cast<int>(bit_string.size()),
233 &content);
234
235 // Add the RSA algorithm OID.
236 for (size_t i = sizeof(kRsaAlgorithmIdentifier); i > 0; --i)
237 content.push_front(kRsaAlgorithmIdentifier[i - 1]);
238
239 // Finally, wrap everything in a sequence.
240 PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content);
241
242 // Copy everything into the output.
243 output->reserve(content.size());
244 output->assign(content.begin(), content.end());
245
246 return true;
247 }
248
249 bool PrivateKeyInfoCodec::ExportPublicKey(std::vector<uint8_t>* output) {
250 // Create a sequence with the modulus (n) and public exponent (e).
251 std::list<uint8_t> content;
252 PrependInteger(&public_exponent_[0],
253 static_cast<int>(public_exponent_.size()),
254 &content);
255 PrependInteger(&modulus_[0], static_cast<int>(modulus_.size()), &content);
256 PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content);
257
258 // Copy everything into the output.
259 output->reserve(content.size());
260 output->assign(content.begin(), content.end());
261
262 return true;
263 }
264
265 bool PrivateKeyInfoCodec::Import(const std::vector<uint8_t>& input) {
266 if (input.empty()) {
267 return false;
268 }
269
270 // Parse the private key info up to the public key values, ignoring
271 // the subsequent private key values.
272 uint8_t* src = const_cast<uint8_t*>(&input.front());
273 uint8_t* end = src + input.size();
274 if (!ReadSequence(&src, end) ||
275 !ReadVersion(&src, end) ||
276 !ReadAlgorithmIdentifier(&src, end) ||
277 !ReadTypeHeaderAndLength(&src, end, kOctetStringTag, NULL) ||
278 !ReadSequence(&src, end) ||
279 !ReadVersion(&src, end) ||
280 !ReadInteger(&src, end, &modulus_))
281 return false;
282
283 int mod_size = modulus_.size();
284 READ_ASSERT(mod_size % 2 == 0);
285 int primes_size = mod_size / 2;
286
287 if (!ReadIntegerWithExpectedSize(&src, end, 4, &public_exponent_) ||
288 !ReadIntegerWithExpectedSize(&src, end, mod_size, &private_exponent_) ||
289 !ReadIntegerWithExpectedSize(&src, end, primes_size, &prime1_) ||
290 !ReadIntegerWithExpectedSize(&src, end, primes_size, &prime2_) ||
291 !ReadIntegerWithExpectedSize(&src, end, primes_size, &exponent1_) ||
292 !ReadIntegerWithExpectedSize(&src, end, primes_size, &exponent2_) ||
293 !ReadIntegerWithExpectedSize(&src, end, primes_size, &coefficient_))
294 return false;
295
296 READ_ASSERT(src == end);
297
298
299 return true;
300 }
301
302 void PrivateKeyInfoCodec::PrependInteger(const std::vector<uint8_t>& in,
303 std::list<uint8_t>* out) {
304 uint8_t* ptr = const_cast<uint8_t*>(&in.front());
305 PrependIntegerImpl(ptr, in.size(), out, big_endian_);
306 }
307
308 // Helper to prepend an ASN.1 integer.
309 void PrivateKeyInfoCodec::PrependInteger(uint8_t* val,
310 int num_bytes,
311 std::list<uint8_t>* data) {
312 PrependIntegerImpl(val, num_bytes, data, big_endian_);
313 }
314
315 void PrivateKeyInfoCodec::PrependIntegerImpl(uint8_t* val,
316 int num_bytes,
317 std::list<uint8_t>* data,
318 bool big_endian) {
319 // Reverse input if little-endian.
320 std::vector<uint8_t> tmp;
321 if (!big_endian) {
322 tmp.assign(val, val + num_bytes);
323 std::reverse(tmp.begin(), tmp.end());
324 val = &tmp.front();
325 }
326
327 // ASN.1 integers are unpadded byte arrays, so skip any null padding bytes
328 // from the most-significant end of the integer.
329 int start = 0;
330 while (start < (num_bytes - 1) && val[start] == 0x00) {
331 start++;
332 num_bytes--;
333 }
334 PrependBytes(val, start, num_bytes, data);
335
336 // ASN.1 integers are signed. To encode a positive integer whose sign bit
337 // (the most significant bit) would otherwise be set and make the number
338 // negative, ASN.1 requires a leading null byte to force the integer to be
339 // positive.
340 uint8_t front = data->front();
341 if ((front & 0x80) != 0) {
342 data->push_front(0x00);
343 num_bytes++;
344 }
345
346 PrependTypeHeaderAndLength(kIntegerTag, num_bytes, data);
347 }
348
349 bool PrivateKeyInfoCodec::ReadInteger(uint8_t** pos,
350 uint8_t* end,
351 std::vector<uint8_t>* out) {
352 return ReadIntegerImpl(pos, end, out, big_endian_);
353 }
354
355 bool PrivateKeyInfoCodec::ReadIntegerWithExpectedSize(
356 uint8_t** pos,
357 uint8_t* end,
358 size_t expected_size,
359 std::vector<uint8_t>* out) {
360 std::vector<uint8_t> temp;
361 if (!ReadIntegerImpl(pos, end, &temp, true)) // Big-Endian
362 return false;
363
364 int pad = expected_size - temp.size();
365 int index = 0;
366 if (out->size() == expected_size + 1) {
367 READ_ASSERT(out->front() == 0x00);
368 pad++;
369 index++;
370 } else {
371 READ_ASSERT(out->size() <= expected_size);
372 }
373
374 out->insert(out->end(), pad, 0x00);
375 out->insert(out->end(), temp.begin(), temp.end());
376
377 // Reverse output if little-endian.
378 if (!big_endian_)
379 std::reverse(out->begin(), out->end());
380 return true;
381 }
382
383 bool PrivateKeyInfoCodec::ReadIntegerImpl(uint8_t** pos,
384 uint8_t* end,
385 std::vector<uint8_t>* out,
386 bool big_endian) {
387 uint32_t length = 0;
388 if (!ReadTypeHeaderAndLength(pos, end, kIntegerTag, &length) || !length)
389 return false;
390
391 // The first byte can be zero to force positiveness. We can ignore this.
392 if (**pos == 0x00) {
393 ++(*pos);
394 --length;
395 }
396
397 if (length)
398 out->insert(out->end(), *pos, (*pos) + length);
399
400 (*pos) += length;
401
402 // Reverse output if little-endian.
403 if (!big_endian)
404 std::reverse(out->begin(), out->end());
405 return true;
406 }
407
408 void PrivateKeyInfoCodec::PrependBytes(uint8_t* val,
409 int start,
410 int num_bytes,
411 std::list<uint8_t>* data) {
412 while (num_bytes > 0) {
413 --num_bytes;
414 data->push_front(val[start + num_bytes]);
415 }
416 }
417
418 void PrivateKeyInfoCodec::PrependLength(size_t size, std::list<uint8_t>* data) {
419 // The high bit is used to indicate whether additional octets are needed to
420 // represent the length.
421 if (size < 0x80) {
422 data->push_front(static_cast<uint8_t>(size));
423 } else {
424 uint8_t num_bytes = 0;
425 while (size > 0) {
426 data->push_front(static_cast<uint8_t>(size & 0xFF));
427 size >>= 8;
428 num_bytes++;
429 }
430 CHECK_LE(num_bytes, 4);
431 data->push_front(0x80 | num_bytes);
432 }
433 }
434
435 void PrivateKeyInfoCodec::PrependTypeHeaderAndLength(
436 uint8_t type,
437 uint32_t length,
438 std::list<uint8_t>* output) {
439 PrependLength(length, output);
440 output->push_front(type);
441 }
442
443 void PrivateKeyInfoCodec::PrependBitString(uint8_t* val,
444 int num_bytes,
445 std::list<uint8_t>* output) {
446 // Start with the data.
447 PrependBytes(val, 0, num_bytes, output);
448 // Zero unused bits.
449 output->push_front(0);
450 // Add the length.
451 PrependLength(num_bytes + 1, output);
452 // Finally, add the bit string tag.
453 output->push_front((uint8_t)kBitStringTag);
454 }
455
456 bool PrivateKeyInfoCodec::ReadLength(uint8_t** pos,
457 uint8_t* end,
458 uint32_t* result) {
459 READ_ASSERT(*pos < end);
460 int length = 0;
461
462 // If the MSB is not set, the length is just the byte itself.
463 if (!(**pos & 0x80)) {
464 length = **pos;
465 (*pos)++;
466 } else {
467 // Otherwise, the lower 7 indicate the length of the length.
468 int length_of_length = **pos & 0x7F;
469 READ_ASSERT(length_of_length <= 4);
470 (*pos)++;
471 READ_ASSERT(*pos + length_of_length < end);
472
473 length = 0;
474 for (int i = 0; i < length_of_length; ++i) {
475 length <<= 8;
476 length |= **pos;
477 (*pos)++;
478 }
479 }
480
481 READ_ASSERT(*pos + length <= end);
482 if (result) *result = length;
483 return true;
484 }
485
486 bool PrivateKeyInfoCodec::ReadTypeHeaderAndLength(uint8_t** pos,
487 uint8_t* end,
488 uint8_t expected_tag,
489 uint32_t* length) {
490 READ_ASSERT(*pos < end);
491 READ_ASSERT(**pos == expected_tag);
492 (*pos)++;
493
494 return ReadLength(pos, end, length);
495 }
496
497 bool PrivateKeyInfoCodec::ReadSequence(uint8_t** pos, uint8_t* end) {
498 return ReadTypeHeaderAndLength(pos, end, kSequenceTag, NULL);
499 }
500
501 bool PrivateKeyInfoCodec::ReadAlgorithmIdentifier(uint8_t** pos, uint8_t* end) {
502 READ_ASSERT(*pos + sizeof(kRsaAlgorithmIdentifier) < end);
503 READ_ASSERT(memcmp(*pos, kRsaAlgorithmIdentifier,
504 sizeof(kRsaAlgorithmIdentifier)) == 0);
505 (*pos) += sizeof(kRsaAlgorithmIdentifier);
506 return true;
507 }
508
509 bool PrivateKeyInfoCodec::ReadVersion(uint8_t** pos, uint8_t* end) {
510 uint32_t length = 0;
511 if (!ReadTypeHeaderAndLength(pos, end, kIntegerTag, &length))
512 return false;
513
514 // The version should be zero.
515 for (uint32_t i = 0; i < length; ++i) {
516 READ_ASSERT(**pos == 0x00);
517 (*pos)++;
518 }
519
520 return true;
521 }
522
41 } // namespace 523 } // namespace
42 524
43 namespace crypto { 525 namespace crypto {
44 526
45 RSAPrivateKey::~RSAPrivateKey() { 527 RSAPrivateKey::~RSAPrivateKey() {
46 if (key_) 528 if (key_)
47 SECKEY_DestroyPrivateKey(key_); 529 SECKEY_DestroyPrivateKey(key_);
48 if (public_key_) 530 if (public_key_)
49 SECKEY_DestroyPublicKey(public_key_); 531 SECKEY_DestroyPublicKey(public_key_);
50 } 532 }
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
143 625
144 output->assign(der_pubkey->data, der_pubkey->data + der_pubkey->len); 626 output->assign(der_pubkey->data, der_pubkey->data + der_pubkey->len);
145 return true; 627 return true;
146 } 628 }
147 629
148 RSAPrivateKey::RSAPrivateKey() : key_(NULL), public_key_(NULL) { 630 RSAPrivateKey::RSAPrivateKey() : key_(NULL), public_key_(NULL) {
149 EnsureNSSInit(); 631 EnsureNSSInit();
150 } 632 }
151 633
152 } // namespace crypto 634 } // namespace crypto
OLDNEW
« no previous file with comments | « crypto/rsa_private_key.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698