Roll WebRTC 9745:9761, Libjingle 9742:9761
[chromium-blink-merge.git] / crypto / rsa_private_key_nss.cc
blob88e55fa576812a556ecb3361d449c48133f0df5d
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
3 // found in the LICENSE file.
5 #include "crypto/rsa_private_key.h"
7 #include <cryptohi.h>
8 #include <keyhi.h>
9 #include <pk11pub.h>
11 #include <list>
13 #include "base/debug/leak_annotations.h"
14 #include "base/logging.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/strings/string_util.h"
17 #include "crypto/nss_key_util.h"
18 #include "crypto/nss_util.h"
19 #include "crypto/scoped_nss_types.h"
21 // TODO(rafaelw): Consider using NSS's ASN.1 encoder.
22 namespace {
24 static bool ReadAttribute(SECKEYPrivateKey* key,
25 CK_ATTRIBUTE_TYPE type,
26 std::vector<uint8>* output) {
27 SECItem item;
28 SECStatus rv;
29 rv = PK11_ReadRawAttribute(PK11_TypePrivKey, key, type, &item);
30 if (rv != SECSuccess) {
31 NOTREACHED();
32 return false;
35 output->assign(item.data, item.data + item.len);
36 SECITEM_FreeItem(&item, PR_FALSE);
37 return true;
40 } // namespace
42 namespace crypto {
44 RSAPrivateKey::~RSAPrivateKey() {
45 if (key_)
46 SECKEY_DestroyPrivateKey(key_);
47 if (public_key_)
48 SECKEY_DestroyPublicKey(public_key_);
51 // static
52 RSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) {
53 EnsureNSSInit();
55 ScopedPK11Slot slot(PK11_GetInternalSlot());
56 if (!slot) {
57 NOTREACHED();
58 return nullptr;
61 ScopedSECKEYPublicKey public_key;
62 ScopedSECKEYPrivateKey private_key;
63 if (!GenerateRSAKeyPairNSS(slot.get(), num_bits, false /* not permanent */,
64 &public_key, &private_key)) {
65 return nullptr;
68 RSAPrivateKey* rsa_key = new RSAPrivateKey;
69 rsa_key->public_key_ = public_key.release();
70 rsa_key->key_ = private_key.release();
71 return rsa_key;
74 // static
75 RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo(
76 const std::vector<uint8>& input) {
77 EnsureNSSInit();
79 ScopedPK11Slot slot(PK11_GetInternalSlot());
80 if (!slot) {
81 NOTREACHED();
82 return nullptr;
84 ScopedSECKEYPrivateKey key(ImportNSSKeyFromPrivateKeyInfo(
85 slot.get(), input, false /* not permanent */));
86 if (!key || SECKEY_GetPrivateKeyType(key.get()) != rsaKey)
87 return nullptr;
88 return RSAPrivateKey::CreateFromKey(key.get());
91 // static
92 RSAPrivateKey* RSAPrivateKey::CreateFromKey(SECKEYPrivateKey* key) {
93 DCHECK(key);
94 if (SECKEY_GetPrivateKeyType(key) != rsaKey)
95 return NULL;
96 RSAPrivateKey* copy = new RSAPrivateKey();
97 copy->key_ = SECKEY_CopyPrivateKey(key);
98 copy->public_key_ = SECKEY_ConvertToPublicKey(key);
99 if (!copy->key_ || !copy->public_key_) {
100 NOTREACHED();
101 delete copy;
102 return NULL;
104 return copy;
107 RSAPrivateKey* RSAPrivateKey::Copy() const {
108 RSAPrivateKey* copy = new RSAPrivateKey();
109 copy->key_ = SECKEY_CopyPrivateKey(key_);
110 copy->public_key_ = SECKEY_CopyPublicKey(public_key_);
111 return copy;
114 bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8>* output) const {
115 PrivateKeyInfoCodec private_key_info(true);
117 // Manually read the component attributes of the private key and build up
118 // the PrivateKeyInfo.
119 if (!ReadAttribute(key_, CKA_MODULUS, private_key_info.modulus()) ||
120 !ReadAttribute(key_, CKA_PUBLIC_EXPONENT,
121 private_key_info.public_exponent()) ||
122 !ReadAttribute(key_, CKA_PRIVATE_EXPONENT,
123 private_key_info.private_exponent()) ||
124 !ReadAttribute(key_, CKA_PRIME_1, private_key_info.prime1()) ||
125 !ReadAttribute(key_, CKA_PRIME_2, private_key_info.prime2()) ||
126 !ReadAttribute(key_, CKA_EXPONENT_1, private_key_info.exponent1()) ||
127 !ReadAttribute(key_, CKA_EXPONENT_2, private_key_info.exponent2()) ||
128 !ReadAttribute(key_, CKA_COEFFICIENT, private_key_info.coefficient())) {
129 NOTREACHED();
130 return false;
133 return private_key_info.Export(output);
136 bool RSAPrivateKey::ExportPublicKey(std::vector<uint8>* output) const {
137 ScopedSECItem der_pubkey(SECKEY_EncodeDERSubjectPublicKeyInfo(public_key_));
138 if (!der_pubkey.get()) {
139 NOTREACHED();
140 return false;
143 output->assign(der_pubkey->data, der_pubkey->data + der_pubkey->len);
144 return true;
147 RSAPrivateKey::RSAPrivateKey() : key_(NULL), public_key_(NULL) {
148 EnsureNSSInit();
151 } // namespace crypto