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

Side by Side Diff: net/base/keygen_handler_nss.cc

Issue 2824014: Move the Mozilla-derived code in net/base/keygen_handler_nss.cc... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Update URL in README.chromium. Created 10 years, 6 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | net/net.gyp » ('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) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 "net/base/keygen_handler.h" 5 #include "net/base/keygen_handler.h"
6 6
7 #include <pk11pub.h> 7 #include "net/third_party/mozilla_security_manager/nsKeygenHandler.h"
8 #include <secmod.h>
9 #include <ssl.h>
10 #include <secder.h> // DER_Encode()
11 #include <cryptohi.h> // SEC_DerSignData()
12 #include <keyhi.h> // SECKEY_CreateSubjectPublicKeyInfo()
13 8
14 #include "base/base64.h" 9 // PSM = Mozilla's Personal Security Manager.
15 #include "base/nss_util_internal.h" 10 namespace psm = mozilla_security_manager;
16 #include "base/nss_util.h"
17 #include "base/logging.h"
18 11
19 namespace net { 12 namespace net {
20 13
21 const int64 DEFAULT_RSA_PUBLIC_EXPONENT = 0x10001;
22
23 // Template for creating the signed public key structure to be sent to the CA.
24 DERTemplate SECAlgorithmIDTemplate[] = {
25 { DER_SEQUENCE,
26 0, NULL, sizeof(SECAlgorithmID) },
27 { DER_OBJECT_ID,
28 offsetof(SECAlgorithmID, algorithm), },
29 { DER_OPTIONAL | DER_ANY,
30 offsetof(SECAlgorithmID, parameters), },
31 { 0, }
32 };
33
34 DERTemplate CERTSubjectPublicKeyInfoTemplate[] = {
35 { DER_SEQUENCE,
36 0, NULL, sizeof(CERTSubjectPublicKeyInfo) },
37 { DER_INLINE,
38 offsetof(CERTSubjectPublicKeyInfo, algorithm),
39 SECAlgorithmIDTemplate, },
40 { DER_BIT_STRING,
41 offsetof(CERTSubjectPublicKeyInfo, subjectPublicKey), },
42 { 0, }
43 };
44
45 DERTemplate CERTPublicKeyAndChallengeTemplate[] = {
46 { DER_SEQUENCE,
47 0, NULL, sizeof(CERTPublicKeyAndChallenge) },
48 { DER_ANY,
49 offsetof(CERTPublicKeyAndChallenge, spki), },
50 { DER_IA5_STRING,
51 offsetof(CERTPublicKeyAndChallenge, challenge), },
52 { 0, }
53 };
54
55 void StoreKeyLocationInCache(const SECItem& public_key_info,
56 PK11SlotInfo *slot) {
57 KeygenHandler::Cache* cache = KeygenHandler::Cache::GetInstance();
58 KeygenHandler::KeyLocation key_location;
59 const char* slot_name = PK11_GetSlotName(slot);
60 key_location.slot_name.assign(slot_name);
61 cache->Insert(std::string(reinterpret_cast<char*>(public_key_info.data),
62 public_key_info.len), key_location);
63 }
64
65 bool KeygenHandler::KeyLocation::Equals( 14 bool KeygenHandler::KeyLocation::Equals(
66 const net::KeygenHandler::KeyLocation& location) const { 15 const net::KeygenHandler::KeyLocation& location) const {
67 return slot_name == location.slot_name; 16 return slot_name == location.slot_name;
68 } 17 }
69 18
70 // This function is largely copied from the Firefox's
71 // <keygen> implementation in security/manager/ssl/src/nsKeygenHandler.cpp
72 // FIXME(gauravsh): Do we need a copy of the Mozilla license here?
73
74 std::string KeygenHandler::GenKeyAndSignChallenge() { 19 std::string KeygenHandler::GenKeyAndSignChallenge() {
75 // Key pair generation mechanism - only RSA is supported at present. 20 return psm::GenKeyAndSignChallenge(key_size_in_bits_, challenge_,
76 PRUint32 keyGenMechanism = CKM_RSA_PKCS_KEY_PAIR_GEN; // from nss/pkcs11t.h 21 stores_key_);
77
78 // Temporary structures used for generating the result
79 // in the right format.
80 PK11SlotInfo *slot = NULL;
81 PK11RSAGenParams rsaKeyGenParams; // Keygen parameters.
82 SECOidTag algTag; // used by SEC_DerSignData().
83 SECKEYPrivateKey *privateKey = NULL;
84 SECKEYPublicKey *publicKey = NULL;
85 CERTSubjectPublicKeyInfo *spkInfo = NULL;
86 PRArenaPool *arena = NULL;
87 SECStatus sec_rv =SECFailure;
88 SECItem spkiItem;
89 SECItem pkacItem;
90 SECItem signedItem;
91 CERTPublicKeyAndChallenge pkac;
92 void *keyGenParams;
93 pkac.challenge.data = NULL;
94 bool isSuccess = true; // Set to false as soon as a step fails.
95
96 std::string result_blob; // the result.
97
98 // Ensure NSS is initialized.
99 base::EnsureNSSInit();
100
101 slot = base::GetDefaultNSSKeySlot();
102 if (!slot) {
103 LOG(ERROR) << "Couldn't get Internal key slot!";
104 isSuccess = false;
105 goto failure;
106 }
107
108 switch (keyGenMechanism) {
109 case CKM_RSA_PKCS_KEY_PAIR_GEN:
110 rsaKeyGenParams.keySizeInBits = key_size_in_bits_;
111 rsaKeyGenParams.pe = DEFAULT_RSA_PUBLIC_EXPONENT;
112 keyGenParams = &rsaKeyGenParams;
113
114 algTag = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION; // from <nss/secoidt.h>.
115 break;
116 default:
117 // TODO(gauravsh): If we ever support other mechanisms,
118 // this can be changed.
119 LOG(ERROR) << "Only RSA keygen mechanism is supported";
120 isSuccess = false;
121 goto failure;
122 break;
123 }
124
125 // Need to make sure that the token was initialized.
126 // Assume a null password.
127 sec_rv = PK11_Authenticate(slot, PR_TRUE, NULL);
128 if (SECSuccess != sec_rv) {
129 LOG(ERROR) << "Couldn't initialze PK11 token!";
130 isSuccess = false;
131 goto failure;
132 }
133
134 LOG(INFO) << "Creating key pair...";
135 privateKey = PK11_GenerateKeyPair(slot,
136 keyGenMechanism,
137 keyGenParams,
138 &publicKey,
139 PR_TRUE, // isPermanent?
140 PR_TRUE, // isSensitive?
141 NULL);
142 LOG(INFO) << "done.";
143
144 if (!privateKey) {
145 LOG(INFO) << "Generation of Keypair failed!";
146 isSuccess = false;
147 goto failure;
148 }
149
150 // The CA expects the signed public key in a specific format
151 // Let's create that now.
152
153 // Create a subject public key info from the public key.
154 spkInfo = SECKEY_CreateSubjectPublicKeyInfo(publicKey);
155 if (!spkInfo) {
156 LOG(ERROR) << "Couldn't create SubjectPublicKeyInfo from public key";
157 isSuccess = false;
158 goto failure;
159 }
160
161 // Temporary work store used by NSS.
162 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
163 if (!arena) {
164 LOG(ERROR) << "PORT_NewArena: Couldn't allocate memory";
165 isSuccess = false;
166 goto failure;
167 }
168
169 // DER encode the whole subjectPublicKeyInfo.
170 sec_rv = DER_Encode(arena, &spkiItem, CERTSubjectPublicKeyInfoTemplate,
171 spkInfo);
172 if (SECSuccess != sec_rv) {
173 LOG(ERROR) << "Couldn't DER Encode subjectPublicKeyInfo";
174 isSuccess = false;
175 goto failure;
176 }
177
178 // Set up the PublicKeyAndChallenge data structure, then DER encode it.
179 pkac.spki = spkiItem;
180 pkac.challenge.len = challenge_.length();
181 pkac.challenge.data = (unsigned char *)strdup(challenge_.c_str());
182 if (!pkac.challenge.data) {
183 LOG(ERROR) << "Out of memory while making a copy of challenge data";
184 isSuccess = false;
185 goto failure;
186 }
187 sec_rv = DER_Encode(arena, &pkacItem, CERTPublicKeyAndChallengeTemplate,
188 &pkac);
189 if (SECSuccess != sec_rv) {
190 LOG(ERROR) << "Couldn't DER Encode PublicKeyAndChallenge";
191 isSuccess = false;
192 goto failure;
193 }
194
195 // Sign the DER encoded PublicKeyAndChallenge.
196 sec_rv = SEC_DerSignData(arena, &signedItem, pkacItem.data, pkacItem.len,
197 privateKey, algTag);
198 if (SECSuccess != sec_rv) {
199 LOG(ERROR) << "Couldn't sign the DER encoded PublicKeyandChallenge";
200 isSuccess = false;
201 goto failure;
202 }
203
204 // Convert the signed public key and challenge into base64/ascii.
205 if (!base::Base64Encode(std::string(reinterpret_cast<char*>(signedItem.data),
206 signedItem.len),
207 &result_blob)) {
208 LOG(ERROR) << "Couldn't convert signed public key into base64";
209 isSuccess = false;
210 goto failure;
211 }
212
213 StoreKeyLocationInCache(spkiItem, slot);
214
215 failure:
216 if (!isSuccess) {
217 LOG(ERROR) << "SSL Keygen failed!";
218 } else {
219 LOG(INFO) << "SSL Keygen succeeded!";
220 }
221
222 // Do cleanups
223 if (privateKey) {
224 // On successful keygen we need to keep the private key, of course,
225 // or we won't be able to use the client certificate.
226 if (!isSuccess || !stores_key_) {
227 PK11_DestroyTokenObject(privateKey->pkcs11Slot, privateKey->pkcs11ID);
228 }
229 SECKEY_DestroyPrivateKey(privateKey);
230 }
231
232 if (publicKey) {
233 if (!isSuccess || !stores_key_) {
234 PK11_DestroyTokenObject(publicKey->pkcs11Slot, publicKey->pkcs11ID);
235 }
236 SECKEY_DestroyPublicKey(publicKey);
237 }
238 if (spkInfo) {
239 SECKEY_DestroySubjectPublicKeyInfo(spkInfo);
240 }
241 if (arena) {
242 PORT_FreeArena(arena, PR_TRUE);
243 }
244 if (slot != NULL) {
245 PK11_FreeSlot(slot);
246 }
247 if (pkac.challenge.data) {
248 free(pkac.challenge.data);
249 }
250
251 return (isSuccess ? result_blob : std::string());
252 } 22 }
253 23
254 } // namespace net 24 } // namespace net
OLDNEW
« no previous file with comments | « no previous file | net/net.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698