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

Side by Side Diff: crypto/nss_key_util.cc

Issue 1106103003: Don't use RSAPrivateKey in NSS integration code. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@ocsp-refactor
Patch Set: pneubeck comments Created 5 years, 7 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
OLDNEW
(Empty)
1 // Copyright 2015 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.
4
5 #include "crypto/nss_key_util.h"
6
7 #include <cryptohi.h>
8 #include <keyhi.h>
9 #include <pk11pub.h>
10
11 #include "base/logging.h"
12 #include "base/stl_util.h"
13 #include "crypto/nss_util.h"
14
15 #if defined(USE_NSS_CERTS)
16 #include <secmod.h>
17 #include "crypto/nss_util_internal.h"
18 #endif
19
20 namespace crypto {
21
22 namespace {
23
24 #if defined(USE_NSS_CERTS)
25
26 struct PublicKeyInfoDeleter {
27 inline void operator()(CERTSubjectPublicKeyInfo* spki) {
28 SECKEY_DestroySubjectPublicKeyInfo(spki);
29 }
30 };
31
32 typedef scoped_ptr<CERTSubjectPublicKeyInfo, PublicKeyInfoDeleter>
33 ScopedPublicKeyInfo;
34
35 // Decodes |input| as a SubjectPublicKeyInfo and returns a SECItem containing
36 // the CKA_ID of that public key or nullptr on error.
37 ScopedSECItem MakeIDFromSPKI(const std::vector<uint8_t> input) {
38 // First, decode and save the public key.
39 SECItem key_der;
40 key_der.type = siBuffer;
41 key_der.data = const_cast<unsigned char*>(vector_as_array(&input));
42 key_der.len = input.size();
43
44 ScopedPublicKeyInfo spki(SECKEY_DecodeDERSubjectPublicKeyInfo(&key_der));
45 if (!spki)
46 return nullptr;
47
48 ScopedSECKEYPublicKey result(SECKEY_ExtractPublicKey(spki.get()));
49 if (!result)
50 return nullptr;
51
52 // See pk11_MakeIDFromPublicKey from NSS. For now, only RSA keys are
53 // supported.
54 if (SECKEY_GetPublicKeyType(result.get()) != rsaKey)
55 return nullptr;
56
57 return ScopedSECItem(PK11_MakeIDFromPubKey(&result->u.rsa.modulus));
58 }
59
60 #endif // defined(USE_NSS_CERTS)
61
62 } // namespace
63
64 bool GenerateRSAKeyPairNSS(PK11SlotInfo* slot,
65 uint16_t num_bits,
66 bool permanent,
67 ScopedSECKEYPublicKey* public_key,
68 ScopedSECKEYPrivateKey* private_key) {
69 PK11RSAGenParams param;
70 param.keySizeInBits = num_bits;
71 param.pe = 65537L;
72 SECKEYPublicKey* public_key_raw = nullptr;
73 private_key->reset(PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN,
74 &param, &public_key_raw, permanent,
75 permanent /* sensitive */, nullptr));
76 if (!*private_key)
77 return false;
78
79 public_key->reset(public_key_raw);
80 return true;
81 }
82
83 ScopedSECKEYPrivateKey ImportNSSKeyFromPrivateKeyInfo(
84 PK11SlotInfo* slot,
85 const std::vector<uint8_t>& input,
86 bool permanent) {
87 DCHECK(slot);
88
89 ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
90 DCHECK(arena);
91
92 // Excess data is illegal, but NSS silently accepts it, so first ensure that
93 // |input| consists of a single ASN.1 element.
94 SECItem input_item;
95 input_item.data = const_cast<unsigned char*>(vector_as_array(&input));
96 input_item.len = input.size();
97 SECItem der_private_key_info;
98 SECStatus rv =
99 SEC_QuickDERDecodeItem(arena.get(), &der_private_key_info,
100 SEC_ASN1_GET(SEC_AnyTemplate), &input_item);
101 if (rv != SECSuccess)
102 return nullptr;
103
104 // Allow the private key to be used for key unwrapping, data decryption,
105 // and signature generation.
106 const unsigned int key_usage =
107 KU_KEY_ENCIPHERMENT | KU_DATA_ENCIPHERMENT | KU_DIGITAL_SIGNATURE;
108 SECKEYPrivateKey* key_raw = nullptr;
109 rv = PK11_ImportDERPrivateKeyInfoAndReturnKey(
110 slot, &der_private_key_info, nullptr, nullptr, permanent,
111 permanent /* sensitive */, key_usage, &key_raw, nullptr);
112 if (rv != SECSuccess)
113 return nullptr;
114 return ScopedSECKEYPrivateKey(key_raw);
115 }
116
117 #if defined(USE_NSS_CERTS)
118
119 ScopedSECKEYPrivateKey FindNSSKeyFromPublicKeyInfo(
120 const std::vector<uint8_t>& input) {
121 EnsureNSSInit();
122
123 ScopedSECItem cka_id(MakeIDFromSPKI(input));
124 if (!cka_id)
125 return nullptr;
126
127 // Search all slots in all modules for the key with the given ID.
128 AutoSECMODListReadLock auto_lock;
129 const SECMODModuleList* head = SECMOD_GetDefaultModuleList();
130 for (const SECMODModuleList* item = head; item != nullptr;
131 item = item->next) {
132 int slot_count = item->module->loaded ? item->module->slotCount : 0;
133 for (int i = 0; i < slot_count; i++) {
134 // Look for the key in slot |i|.
135 ScopedSECKEYPrivateKey key(
136 PK11_FindKeyByKeyID(item->module->slots[i], cka_id.get(), nullptr));
137 if (key)
138 return key.Pass();
139 }
140 }
141
142 // The key wasn't found in any module.
143 return nullptr;
144 }
145
146 ScopedSECKEYPrivateKey FindNSSKeyFromPublicKeyInfoInSlot(
147 const std::vector<uint8_t>& input,
148 PK11SlotInfo* slot) {
149 DCHECK(slot);
150
151 ScopedSECItem cka_id(MakeIDFromSPKI(input));
152 if (!cka_id)
153 return nullptr;
154
155 return ScopedSECKEYPrivateKey(
156 PK11_FindKeyByKeyID(slot, cka_id.get(), nullptr));
157 }
158
159 #endif // defined(USE_NSS_CERTS)
160
161 } // namespace crypto
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698