[go: nahoru, domu]

blob: 2538a723ae4b8b05f768aadea5611ec61b3593b0 [file] [log] [blame]
levin@chromium.org3b63f8f42011-03-28 01:54:151// Copyright (c) 2011 The Chromium Authors. All rights reserved.
rafaelw@chromium.org71a9f842009-09-24 01:21:122// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
rvargas@google.com4b559b4d2011-04-14 17:37:145#include "crypto/rsa_private_key.h"
rafaelw@chromium.org71a9f842009-09-24 01:21:126
7#include <cryptohi.h>
8#include <keyhi.h>
9#include <pk11pub.h>
avidd373b8b2015-12-21 21:34:4310#include <stdint.h>
rafaelw@chromium.org71a9f842009-09-24 01:21:1211
rafaelw@chromium.org71a9f842009-09-24 01:21:1212#include <list>
thakisd1a18472016-04-08 22:30:4113#include <memory>
rafaelw@chromium.org71a9f842009-09-24 01:21:1214
brettw@chromium.org58580352010-10-26 04:07:5015#include "base/debug/leak_annotations.h"
rafaelw@chromium.org71a9f842009-09-24 01:21:1216#include "base/logging.h"
avi@chromium.org0d8db082013-06-11 07:27:0117#include "base/strings/string_util.h"
davidben85bad9e2015-05-11 20:20:1018#include "crypto/nss_key_util.h"
rvargas@google.com4b559b4d2011-04-14 17:37:1419#include "crypto/nss_util.h"
gspencer@google.comcfa46c02011-05-25 18:19:0820#include "crypto/scoped_nss_types.h"
rafaelw@chromium.org71a9f842009-09-24 01:21:1221
davidbenc8a44432016-03-23 23:55:1122// Helper for error handling during key import.
23#define READ_ASSERT(truth) \
24 if (!(truth)) { \
25 NOTREACHED(); \
26 return false; \
27 }
28
rsleevi@chromium.org5123d9c2013-06-27 09:18:4329// TODO(rafaelw): Consider using NSS's ASN.1 encoder.
rafaelw@chromium.org71a9f842009-09-24 01:21:1230namespace {
31
rafaelw@chromium.org308379a52009-10-07 02:46:3132static bool ReadAttribute(SECKEYPrivateKey* key,
33 CK_ATTRIBUTE_TYPE type,
avidd373b8b2015-12-21 21:34:4334 std::vector<uint8_t>* output) {
rafaelw@chromium.org71a9f842009-09-24 01:21:1235 SECItem item;
36 SECStatus rv;
37 rv = PK11_ReadRawAttribute(PK11_TypePrivKey, key, type, &item);
38 if (rv != SECSuccess) {
39 NOTREACHED();
40 return false;
41 }
42
rafaelw@chromium.org308379a52009-10-07 02:46:3143 output->assign(item.data, item.data + item.len);
rafaelw@chromium.org71a9f842009-09-24 01:21:1244 SECITEM_FreeItem(&item, PR_FALSE);
45 return true;
46}
47
davidbenc8a44432016-03-23 23:55:1148// Used internally by RSAPrivateKey for serializing and deserializing
49// PKCS #8 PrivateKeyInfo and PublicKeyInfo.
50class 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 kOctetStringTag = 0x04;
59 static const uint8_t kSequenceTag = 0x30;
60
61 // |big_endian| here specifies the byte-significance of the integer components
62 // that will be parsed & serialized (modulus(), etc...) during Import(),
63 // Export() and ExportPublicKeyInfo() -- not the ASN.1 DER encoding of the
64 // PrivateKeyInfo/PublicKeyInfo (which is always big-endian).
65 explicit PrivateKeyInfoCodec(bool big_endian);
66
67 ~PrivateKeyInfoCodec();
68
69 // Exports the contents of the integer components to the ASN.1 DER encoding
70 // of the PrivateKeyInfo structure to |output|.
71 bool Export(std::vector<uint8_t>* output);
72
73 // Exports the contents of the integer components to the ASN.1 DER encoding
74 // of the PublicKeyInfo structure to |output|.
75 bool ExportPublicKeyInfo(std::vector<uint8_t>* output);
76
77 // Exports the contents of the integer components to the ASN.1 DER encoding
78 // of the RSAPublicKey structure to |output|.
79 bool ExportPublicKey(std::vector<uint8_t>* output);
80
81 // Parses the ASN.1 DER encoding of the PrivateKeyInfo structure in |input|
82 // and populates the integer components with |big_endian_| byte-significance.
83 // IMPORTANT NOTE: This is currently *not* security-approved for importing
84 // keys from unstrusted sources.
85 bool Import(const std::vector<uint8_t>& input);
86
87 // Accessors to the contents of the integer components of the PrivateKeyInfo
88 // structure.
89 std::vector<uint8_t>* modulus() { return &modulus_; }
90 std::vector<uint8_t>* public_exponent() { return &public_exponent_; }
91 std::vector<uint8_t>* private_exponent() { return &private_exponent_; }
92 std::vector<uint8_t>* prime1() { return &prime1_; }
93 std::vector<uint8_t>* prime2() { return &prime2_; }
94 std::vector<uint8_t>* exponent1() { return &exponent1_; }
95 std::vector<uint8_t>* exponent2() { return &exponent2_; }
96 std::vector<uint8_t>* coefficient() { return &coefficient_; }
97
98 private:
99 // Utility wrappers for PrependIntegerImpl that use the class's |big_endian_|
100 // value.
101 void PrependInteger(const std::vector<uint8_t>& in, std::list<uint8_t>* out);
102 void PrependInteger(uint8_t* val, int num_bytes, std::list<uint8_t>* data);
103
104 // Prepends the integer stored in |val| - |val + num_bytes| with |big_endian|
105 // byte-significance into |data| as an ASN.1 integer.
106 void PrependIntegerImpl(uint8_t* val,
107 int num_bytes,
108 std::list<uint8_t>* data,
109 bool big_endian);
110
111 // Utility wrappers for ReadIntegerImpl that use the class's |big_endian_|
112 // value.
113 bool ReadInteger(uint8_t** pos, uint8_t* end, std::vector<uint8_t>* out);
114 bool ReadIntegerWithExpectedSize(uint8_t** pos,
115 uint8_t* end,
116 size_t expected_size,
117 std::vector<uint8_t>* out);
118
119 // Reads an ASN.1 integer from |pos|, and stores the result into |out| with
120 // |big_endian| byte-significance.
121 bool ReadIntegerImpl(uint8_t** pos,
122 uint8_t* end,
123 std::vector<uint8_t>* out,
124 bool big_endian);
125
126 // Prepends the integer stored in |val|, starting a index |start|, for
127 // |num_bytes| bytes onto |data|.
128 void PrependBytes(uint8_t* val,
129 int start,
130 int num_bytes,
131 std::list<uint8_t>* data);
132
133 // Helper to prepend an ASN.1 length field.
134 void PrependLength(size_t size, std::list<uint8_t>* data);
135
136 // Helper to prepend an ASN.1 type header.
137 void PrependTypeHeaderAndLength(uint8_t type,
138 uint32_t length,
139 std::list<uint8_t>* output);
140
141 // Helper to prepend an ASN.1 bit string
142 void PrependBitString(uint8_t* val,
143 int num_bytes,
144 std::list<uint8_t>* output);
145
146 // Read an ASN.1 length field. This also checks that the length does not
147 // extend beyond |end|.
148 bool ReadLength(uint8_t** pos, uint8_t* end, uint32_t* result);
149
150 // Read an ASN.1 type header and its length.
151 bool ReadTypeHeaderAndLength(uint8_t** pos,
152 uint8_t* end,
153 uint8_t expected_tag,
154 uint32_t* length);
155
156 // Read an ASN.1 sequence declaration. This consumes the type header and
157 // length field, but not the contents of the sequence.
158 bool ReadSequence(uint8_t** pos, uint8_t* end);
159
160 // Read the RSA AlgorithmIdentifier.
161 bool ReadAlgorithmIdentifier(uint8_t** pos, uint8_t* end);
162
163 // Read one of the two version fields in PrivateKeyInfo.
164 bool ReadVersion(uint8_t** pos, uint8_t* end);
165
166 // The byte-significance of the stored components (modulus, etc..).
167 bool big_endian_;
168
169 // Component integers of the PrivateKeyInfo
170 std::vector<uint8_t> modulus_;
171 std::vector<uint8_t> public_exponent_;
172 std::vector<uint8_t> private_exponent_;
173 std::vector<uint8_t> prime1_;
174 std::vector<uint8_t> prime2_;
175 std::vector<uint8_t> exponent1_;
176 std::vector<uint8_t> exponent2_;
177 std::vector<uint8_t> coefficient_;
178
179 DISALLOW_COPY_AND_ASSIGN(PrivateKeyInfoCodec);
180};
181
182const uint8_t PrivateKeyInfoCodec::kRsaAlgorithmIdentifier[] = {
183 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86,
184 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00};
185
186PrivateKeyInfoCodec::PrivateKeyInfoCodec(bool big_endian)
187 : big_endian_(big_endian) {}
188
189PrivateKeyInfoCodec::~PrivateKeyInfoCodec() {}
190
191bool PrivateKeyInfoCodec::Export(std::vector<uint8_t>* output) {
192 std::list<uint8_t> content;
193
194 // Version (always zero)
195 uint8_t version = 0;
196
197 PrependInteger(coefficient_, &content);
198 PrependInteger(exponent2_, &content);
199 PrependInteger(exponent1_, &content);
200 PrependInteger(prime2_, &content);
201 PrependInteger(prime1_, &content);
202 PrependInteger(private_exponent_, &content);
203 PrependInteger(public_exponent_, &content);
204 PrependInteger(modulus_, &content);
205 PrependInteger(&version, 1, &content);
206 PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content);
207 PrependTypeHeaderAndLength(kOctetStringTag, content.size(), &content);
208
209 // RSA algorithm OID
210 for (size_t i = sizeof(kRsaAlgorithmIdentifier); i > 0; --i)
211 content.push_front(kRsaAlgorithmIdentifier[i - 1]);
212
213 PrependInteger(&version, 1, &content);
214 PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content);
215
216 // Copy everying into the output.
217 output->reserve(content.size());
218 output->assign(content.begin(), content.end());
219
220 return true;
221}
222
223bool PrivateKeyInfoCodec::ExportPublicKeyInfo(std::vector<uint8_t>* output) {
224 // Create a sequence with the modulus (n) and public exponent (e).
225 std::vector<uint8_t> bit_string;
226 if (!ExportPublicKey(&bit_string))
227 return false;
228
229 // Add the sequence as the contents of a bit string.
230 std::list<uint8_t> content;
231 PrependBitString(&bit_string[0], static_cast<int>(bit_string.size()),
232 &content);
233
234 // Add the RSA algorithm OID.
235 for (size_t i = sizeof(kRsaAlgorithmIdentifier); i > 0; --i)
236 content.push_front(kRsaAlgorithmIdentifier[i - 1]);
237
238 // Finally, wrap everything in a sequence.
239 PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content);
240
241 // Copy everything into the output.
242 output->reserve(content.size());
243 output->assign(content.begin(), content.end());
244
245 return true;
246}
247
248bool PrivateKeyInfoCodec::ExportPublicKey(std::vector<uint8_t>* output) {
249 // Create a sequence with the modulus (n) and public exponent (e).
250 std::list<uint8_t> content;
251 PrependInteger(&public_exponent_[0],
252 static_cast<int>(public_exponent_.size()),
253 &content);
254 PrependInteger(&modulus_[0], static_cast<int>(modulus_.size()), &content);
255 PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content);
256
257 // Copy everything into the output.
258 output->reserve(content.size());
259 output->assign(content.begin(), content.end());
260
261 return true;
262}
263
264bool PrivateKeyInfoCodec::Import(const std::vector<uint8_t>& input) {
265 if (input.empty()) {
266 return false;
267 }
268
269 // Parse the private key info up to the public key values, ignoring
270 // the subsequent private key values.
271 uint8_t* src = const_cast<uint8_t*>(&input.front());
272 uint8_t* end = src + input.size();
273 if (!ReadSequence(&src, end) ||
274 !ReadVersion(&src, end) ||
275 !ReadAlgorithmIdentifier(&src, end) ||
276 !ReadTypeHeaderAndLength(&src, end, kOctetStringTag, NULL) ||
277 !ReadSequence(&src, end) ||
278 !ReadVersion(&src, end) ||
279 !ReadInteger(&src, end, &modulus_))
280 return false;
281
282 int mod_size = modulus_.size();
283 READ_ASSERT(mod_size % 2 == 0);
284 int primes_size = mod_size / 2;
285
286 if (!ReadIntegerWithExpectedSize(&src, end, 4, &public_exponent_) ||
287 !ReadIntegerWithExpectedSize(&src, end, mod_size, &private_exponent_) ||
288 !ReadIntegerWithExpectedSize(&src, end, primes_size, &prime1_) ||
289 !ReadIntegerWithExpectedSize(&src, end, primes_size, &prime2_) ||
290 !ReadIntegerWithExpectedSize(&src, end, primes_size, &exponent1_) ||
291 !ReadIntegerWithExpectedSize(&src, end, primes_size, &exponent2_) ||
292 !ReadIntegerWithExpectedSize(&src, end, primes_size, &coefficient_))
293 return false;
294
295 READ_ASSERT(src == end);
296
297
298 return true;
299}
300
301void PrivateKeyInfoCodec::PrependInteger(const std::vector<uint8_t>& in,
302 std::list<uint8_t>* out) {
303 uint8_t* ptr = const_cast<uint8_t*>(&in.front());
304 PrependIntegerImpl(ptr, in.size(), out, big_endian_);
305}
306
307// Helper to prepend an ASN.1 integer.
308void PrivateKeyInfoCodec::PrependInteger(uint8_t* val,
309 int num_bytes,
310 std::list<uint8_t>* data) {
311 PrependIntegerImpl(val, num_bytes, data, big_endian_);
312}
313
314void PrivateKeyInfoCodec::PrependIntegerImpl(uint8_t* val,
315 int num_bytes,
316 std::list<uint8_t>* data,
317 bool big_endian) {
318 // Reverse input if little-endian.
319 std::vector<uint8_t> tmp;
320 if (!big_endian) {
321 tmp.assign(val, val + num_bytes);
322 std::reverse(tmp.begin(), tmp.end());
323 val = &tmp.front();
324 }
325
326 // ASN.1 integers are unpadded byte arrays, so skip any null padding bytes
327 // from the most-significant end of the integer.
328 int start = 0;
329 while (start < (num_bytes - 1) && val[start] == 0x00) {
330 start++;
331 num_bytes--;
332 }
333 PrependBytes(val, start, num_bytes, data);
334
335 // ASN.1 integers are signed. To encode a positive integer whose sign bit
336 // (the most significant bit) would otherwise be set and make the number
337 // negative, ASN.1 requires a leading null byte to force the integer to be
338 // positive.
339 uint8_t front = data->front();
340 if ((front & 0x80) != 0) {
341 data->push_front(0x00);
342 num_bytes++;
343 }
344
345 PrependTypeHeaderAndLength(kIntegerTag, num_bytes, data);
346}
347
348bool PrivateKeyInfoCodec::ReadInteger(uint8_t** pos,
349 uint8_t* end,
350 std::vector<uint8_t>* out) {
351 return ReadIntegerImpl(pos, end, out, big_endian_);
352}
353
354bool PrivateKeyInfoCodec::ReadIntegerWithExpectedSize(
355 uint8_t** pos,
356 uint8_t* end,
357 size_t expected_size,
358 std::vector<uint8_t>* out) {
359 std::vector<uint8_t> temp;
360 if (!ReadIntegerImpl(pos, end, &temp, true)) // Big-Endian
361 return false;
362
363 int pad = expected_size - temp.size();
364 int index = 0;
365 if (out->size() == expected_size + 1) {
366 READ_ASSERT(out->front() == 0x00);
367 pad++;
368 index++;
369 } else {
370 READ_ASSERT(out->size() <= expected_size);
371 }
372
373 out->insert(out->end(), pad, 0x00);
374 out->insert(out->end(), temp.begin(), temp.end());
375
376 // Reverse output if little-endian.
377 if (!big_endian_)
378 std::reverse(out->begin(), out->end());
379 return true;
380}
381
382bool PrivateKeyInfoCodec::ReadIntegerImpl(uint8_t** pos,
383 uint8_t* end,
384 std::vector<uint8_t>* out,
385 bool big_endian) {
386 uint32_t length = 0;
387 if (!ReadTypeHeaderAndLength(pos, end, kIntegerTag, &length) || !length)
388 return false;
389
390 // The first byte can be zero to force positiveness. We can ignore this.
391 if (**pos == 0x00) {
392 ++(*pos);
393 --length;
394 }
395
396 if (length)
397 out->insert(out->end(), *pos, (*pos) + length);
398
399 (*pos) += length;
400
401 // Reverse output if little-endian.
402 if (!big_endian)
403 std::reverse(out->begin(), out->end());
404 return true;
405}
406
407void PrivateKeyInfoCodec::PrependBytes(uint8_t* val,
408 int start,
409 int num_bytes,
410 std::list<uint8_t>* data) {
411 while (num_bytes > 0) {
412 --num_bytes;
413 data->push_front(val[start + num_bytes]);
414 }
415}
416
417void PrivateKeyInfoCodec::PrependLength(size_t size, std::list<uint8_t>* data) {
418 // The high bit is used to indicate whether additional octets are needed to
419 // represent the length.
420 if (size < 0x80) {
421 data->push_front(static_cast<uint8_t>(size));
422 } else {
423 uint8_t num_bytes = 0;
424 while (size > 0) {
425 data->push_front(static_cast<uint8_t>(size & 0xFF));
426 size >>= 8;
427 num_bytes++;
428 }
429 CHECK_LE(num_bytes, 4);
430 data->push_front(0x80 | num_bytes);
431 }
432}
433
434void PrivateKeyInfoCodec::PrependTypeHeaderAndLength(
435 uint8_t type,
436 uint32_t length,
437 std::list<uint8_t>* output) {
438 PrependLength(length, output);
439 output->push_front(type);
440}
441
442void PrivateKeyInfoCodec::PrependBitString(uint8_t* val,
443 int num_bytes,
444 std::list<uint8_t>* output) {
445 // Start with the data.
446 PrependBytes(val, 0, num_bytes, output);
447 // Zero unused bits.
448 output->push_front(0);
449 // Add the length.
450 PrependLength(num_bytes + 1, output);
451 // Finally, add the bit string tag.
452 output->push_front((uint8_t)kBitStringTag);
453}
454
455bool PrivateKeyInfoCodec::ReadLength(uint8_t** pos,
456 uint8_t* end,
457 uint32_t* result) {
458 READ_ASSERT(*pos < end);
459 int length = 0;
460
461 // If the MSB is not set, the length is just the byte itself.
462 if (!(**pos & 0x80)) {
463 length = **pos;
464 (*pos)++;
465 } else {
466 // Otherwise, the lower 7 indicate the length of the length.
467 int length_of_length = **pos & 0x7F;
468 READ_ASSERT(length_of_length <= 4);
469 (*pos)++;
470 READ_ASSERT(*pos + length_of_length < end);
471
472 length = 0;
473 for (int i = 0; i < length_of_length; ++i) {
474 length <<= 8;
475 length |= **pos;
476 (*pos)++;
477 }
478 }
479
480 READ_ASSERT(*pos + length <= end);
481 if (result) *result = length;
482 return true;
483}
484
485bool PrivateKeyInfoCodec::ReadTypeHeaderAndLength(uint8_t** pos,
486 uint8_t* end,
487 uint8_t expected_tag,
488 uint32_t* length) {
489 READ_ASSERT(*pos < end);
490 READ_ASSERT(**pos == expected_tag);
491 (*pos)++;
492
493 return ReadLength(pos, end, length);
494}
495
496bool PrivateKeyInfoCodec::ReadSequence(uint8_t** pos, uint8_t* end) {
497 return ReadTypeHeaderAndLength(pos, end, kSequenceTag, NULL);
498}
499
500bool PrivateKeyInfoCodec::ReadAlgorithmIdentifier(uint8_t** pos, uint8_t* end) {
501 READ_ASSERT(*pos + sizeof(kRsaAlgorithmIdentifier) < end);
502 READ_ASSERT(memcmp(*pos, kRsaAlgorithmIdentifier,
503 sizeof(kRsaAlgorithmIdentifier)) == 0);
504 (*pos) += sizeof(kRsaAlgorithmIdentifier);
505 return true;
506}
507
508bool PrivateKeyInfoCodec::ReadVersion(uint8_t** pos, uint8_t* end) {
509 uint32_t length = 0;
510 if (!ReadTypeHeaderAndLength(pos, end, kIntegerTag, &length))
511 return false;
512
513 // The version should be zero.
514 for (uint32_t i = 0; i < length; ++i) {
515 READ_ASSERT(**pos == 0x00);
516 (*pos)++;
517 }
518
519 return true;
520}
521
rafaelw@chromium.org71a9f842009-09-24 01:21:12522} // namespace
rafaelw@chromium.org71a9f842009-09-24 01:21:12523
rvargas@google.com4b559b4d2011-04-14 17:37:14524namespace crypto {
rafaelw@chromium.org71a9f842009-09-24 01:21:12525
erg@google.comeae9c062011-01-11 00:50:59526RSAPrivateKey::~RSAPrivateKey() {
527 if (key_)
528 SECKEY_DestroyPrivateKey(key_);
529 if (public_key_)
530 SECKEY_DestroyPublicKey(public_key_);
rafaelw@chromium.org71a9f842009-09-24 01:21:12531}
532
533// static
avidd373b8b2015-12-21 21:34:43534RSAPrivateKey* RSAPrivateKey::Create(uint16_t num_bits) {
mattm@chromium.org6e7da44d2013-11-13 03:29:22535 EnsureNSSInit();
536
537 ScopedPK11Slot slot(PK11_GetInternalSlot());
davidben85bad9e2015-05-11 20:20:10538 if (!slot) {
539 NOTREACHED();
540 return nullptr;
541 }
542
543 ScopedSECKEYPublicKey public_key;
544 ScopedSECKEYPrivateKey private_key;
545 if (!GenerateRSAKeyPairNSS(slot.get(), num_bits, false /* not permanent */,
546 &public_key, &private_key)) {
547 return nullptr;
548 }
549
550 RSAPrivateKey* rsa_key = new RSAPrivateKey;
551 rsa_key->public_key_ = public_key.release();
552 rsa_key->key_ = private_key.release();
553 return rsa_key;
rafaelw@chromium.org71a9f842009-09-24 01:21:12554}
555
cmasone@google.com74648052010-08-10 19:37:51556// static
557RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo(
avidd373b8b2015-12-21 21:34:43558 const std::vector<uint8_t>& input) {
mattm@chromium.org6e7da44d2013-11-13 03:29:22559 EnsureNSSInit();
560
561 ScopedPK11Slot slot(PK11_GetInternalSlot());
davidben85bad9e2015-05-11 20:20:10562 if (!slot) {
563 NOTREACHED();
564 return nullptr;
565 }
566 ScopedSECKEYPrivateKey key(ImportNSSKeyFromPrivateKeyInfo(
567 slot.get(), input, false /* not permanent */));
568 if (!key || SECKEY_GetPrivateKeyType(key.get()) != rsaKey)
569 return nullptr;
570 return RSAPrivateKey::CreateFromKey(key.get());
rsleevi@chromium.org5123d9c2013-06-27 09:18:43571}
572
davidben2bcbc6b2015-04-22 02:36:41573// static
574RSAPrivateKey* RSAPrivateKey::CreateFromKey(SECKEYPrivateKey* key) {
575 DCHECK(key);
576 if (SECKEY_GetPrivateKeyType(key) != rsaKey)
577 return NULL;
578 RSAPrivateKey* copy = new RSAPrivateKey();
579 copy->key_ = SECKEY_CopyPrivateKey(key);
580 copy->public_key_ = SECKEY_ConvertToPublicKey(key);
581 if (!copy->key_ || !copy->public_key_) {
582 NOTREACHED();
583 delete copy;
584 return NULL;
585 }
586 return copy;
587}
cmasone@google.com74648052010-08-10 19:37:51588
sergeyu@chromium.org58782882011-12-03 01:12:08589RSAPrivateKey* RSAPrivateKey::Copy() const {
590 RSAPrivateKey* copy = new RSAPrivateKey();
591 copy->key_ = SECKEY_CopyPrivateKey(key_);
592 copy->public_key_ = SECKEY_CopyPublicKey(public_key_);
593 return copy;
594}
rafaelw@chromium.org71a9f842009-09-24 01:21:12595
avidd373b8b2015-12-21 21:34:43596bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8_t>* output) const {
rafaelw@chromium.org308379a52009-10-07 02:46:31597 PrivateKeyInfoCodec private_key_info(true);
rafaelw@chromium.org71a9f842009-09-24 01:21:12598
rafaelw@chromium.org308379a52009-10-07 02:46:31599 // Manually read the component attributes of the private key and build up
600 // the PrivateKeyInfo.
601 if (!ReadAttribute(key_, CKA_MODULUS, private_key_info.modulus()) ||
602 !ReadAttribute(key_, CKA_PUBLIC_EXPONENT,
603 private_key_info.public_exponent()) ||
604 !ReadAttribute(key_, CKA_PRIVATE_EXPONENT,
605 private_key_info.private_exponent()) ||
606 !ReadAttribute(key_, CKA_PRIME_1, private_key_info.prime1()) ||
607 !ReadAttribute(key_, CKA_PRIME_2, private_key_info.prime2()) ||
608 !ReadAttribute(key_, CKA_EXPONENT_1, private_key_info.exponent1()) ||
609 !ReadAttribute(key_, CKA_EXPONENT_2, private_key_info.exponent2()) ||
610 !ReadAttribute(key_, CKA_COEFFICIENT, private_key_info.coefficient())) {
rafaelw@chromium.org71a9f842009-09-24 01:21:12611 NOTREACHED();
612 return false;
613 }
rafaelw@chromium.org71a9f842009-09-24 01:21:12614
rafaelw@chromium.org308379a52009-10-07 02:46:31615 return private_key_info.Export(output);
rafaelw@chromium.org71a9f842009-09-24 01:21:12616}
617
avidd373b8b2015-12-21 21:34:43618bool RSAPrivateKey::ExportPublicKey(std::vector<uint8_t>* output) const {
gspencer@google.comcfa46c02011-05-25 18:19:08619 ScopedSECItem der_pubkey(SECKEY_EncodeDERSubjectPublicKeyInfo(public_key_));
620 if (!der_pubkey.get()) {
rafaelw@chromium.org71a9f842009-09-24 01:21:12621 NOTREACHED();
622 return false;
623 }
624
mattm@chromium.org9dd6a2d2011-11-15 04:45:16625 output->assign(der_pubkey->data, der_pubkey->data + der_pubkey->len);
rafaelw@chromium.org71a9f842009-09-24 01:21:12626 return true;
627}
628
erg@google.comeae9c062011-01-11 00:50:59629RSAPrivateKey::RSAPrivateKey() : key_(NULL), public_key_(NULL) {
630 EnsureNSSInit();
631}
spang9ce34582015-05-01 21:01:57632
rvargas@google.com4b559b4d2011-04-14 17:37:14633} // namespace crypto