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

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

Issue 652137: Mac: implement <keygen> support, including adding generated cert to the Keychain. (Closed)
Patch Set: Responding to review feedback. Created 10 years, 10 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
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 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 <pk11pub.h>
8 #include <secmod.h> 8 #include <secmod.h>
9 #include <ssl.h> 9 #include <ssl.h>
10 #include <nssb64.h> // NSSBase64_EncodeItem()
11 #include <secder.h> // DER_Encode() 10 #include <secder.h> // DER_Encode()
12 #include <cryptohi.h> // SEC_DerSignData() 11 #include <cryptohi.h> // SEC_DerSignData()
13 #include <keyhi.h> // SECKEY_CreateSubjectPublicKeyInfo() 12 #include <keyhi.h> // SECKEY_CreateSubjectPublicKeyInfo()
14 13
14 #include "base/base64.h"
15 #include "base/nss_util.h" 15 #include "base/nss_util.h"
16 #include "base/logging.h" 16 #include "base/logging.h"
17 17
18 namespace net { 18 namespace net {
19 19
20 const int64 DEFAULT_RSA_PUBLIC_EXPONENT = 0x10001; 20 const int64 DEFAULT_RSA_PUBLIC_EXPONENT = 0x10001;
21 21
22 // Template for creating the signed public key structure to be sent to the CA. 22 // Template for creating the signed public key structure to be sent to the CA.
23 DERTemplate SECAlgorithmIDTemplate[] = { 23 DERTemplate SECAlgorithmIDTemplate[] = {
24 { DER_SEQUENCE, 24 { DER_SEQUENCE,
(...skipping 19 matching lines...) Expand all
44 DERTemplate CERTPublicKeyAndChallengeTemplate[] = { 44 DERTemplate CERTPublicKeyAndChallengeTemplate[] = {
45 { DER_SEQUENCE, 45 { DER_SEQUENCE,
46 0, NULL, sizeof(CERTPublicKeyAndChallenge) }, 46 0, NULL, sizeof(CERTPublicKeyAndChallenge) },
47 { DER_ANY, 47 { DER_ANY,
48 offsetof(CERTPublicKeyAndChallenge, spki), }, 48 offsetof(CERTPublicKeyAndChallenge, spki), },
49 { DER_IA5_STRING, 49 { DER_IA5_STRING,
50 offsetof(CERTPublicKeyAndChallenge, challenge), }, 50 offsetof(CERTPublicKeyAndChallenge, challenge), },
51 { 0, } 51 { 0, }
52 }; 52 };
53 53
54 // This maps displayed strings indicating level of keysecurity in the <keygen>
55 // menu to the key size in bits.
56 // TODO(gauravsh): Should this mapping be moved else where?
57 int RSAkeySizeMap[] = {2048, 1024};
58
59 KeygenHandler::KeygenHandler(int key_size_index,
60 const std::string& challenge)
61 : key_size_index_(key_size_index),
62 challenge_(challenge) {
63 if (key_size_index_ < 0 ||
64 key_size_index_ >=
65 static_cast<int>(sizeof(RSAkeySizeMap) / sizeof(RSAkeySizeMap[0])))
66 key_size_index_ = 0;
67 }
68
69 // This function is largely copied from the Firefox's 54 // This function is largely copied from the Firefox's
70 // <keygen> implementation in security/manager/ssl/src/nsKeygenHandler.cpp 55 // <keygen> implementation in security/manager/ssl/src/nsKeygenHandler.cpp
71 // FIXME(gauravsh): Do we need a copy of the Mozilla license here? 56 // FIXME(gauravsh): Do we need a copy of the Mozilla license here?
72 57
73 std::string KeygenHandler::GenKeyAndSignChallenge() { 58 std::string KeygenHandler::GenKeyAndSignChallenge() {
74 // Key pair generation mechanism - only RSA is supported at present. 59 // Key pair generation mechanism - only RSA is supported at present.
75 PRUint32 keyGenMechanism = CKM_RSA_PKCS_KEY_PAIR_GEN; // from nss/pkcs11t.h 60 PRUint32 keyGenMechanism = CKM_RSA_PKCS_KEY_PAIR_GEN; // from nss/pkcs11t.h
76 char *keystring = NULL; // Temporary store for result/
77 61
78 // Temporary structures used for generating the result 62 // Temporary structures used for generating the result
79 // in the right format. 63 // in the right format.
80 PK11SlotInfo *slot = NULL; 64 PK11SlotInfo *slot = NULL;
81 PK11RSAGenParams rsaKeyGenParams; // Keygen parameters. 65 PK11RSAGenParams rsaKeyGenParams; // Keygen parameters.
82 SECOidTag algTag; // used by SEC_DerSignData(). 66 SECOidTag algTag; // used by SEC_DerSignData().
83 SECKEYPrivateKey *privateKey = NULL; 67 SECKEYPrivateKey *privateKey = NULL;
84 SECKEYPublicKey *publicKey = NULL; 68 SECKEYPublicKey *publicKey = NULL;
85 CERTSubjectPublicKeyInfo *spkInfo = NULL; 69 CERTSubjectPublicKeyInfo *spkInfo = NULL;
86 PRArenaPool *arena = NULL; 70 PRArenaPool *arena = NULL;
(...skipping 13 matching lines...) Expand all
100 84
101 slot = PK11_GetInternalKeySlot(); 85 slot = PK11_GetInternalKeySlot();
102 if (!slot) { 86 if (!slot) {
103 LOG(ERROR) << "Couldn't get Internal key slot!"; 87 LOG(ERROR) << "Couldn't get Internal key slot!";
104 isSuccess = false; 88 isSuccess = false;
105 goto failure; 89 goto failure;
106 } 90 }
107 91
108 switch (keyGenMechanism) { 92 switch (keyGenMechanism) {
109 case CKM_RSA_PKCS_KEY_PAIR_GEN: 93 case CKM_RSA_PKCS_KEY_PAIR_GEN:
110 rsaKeyGenParams.keySizeInBits = RSAkeySizeMap[key_size_index_]; 94 rsaKeyGenParams.keySizeInBits = key_size_in_bits_;
111 rsaKeyGenParams.pe = DEFAULT_RSA_PUBLIC_EXPONENT; 95 rsaKeyGenParams.pe = DEFAULT_RSA_PUBLIC_EXPONENT;
112 keyGenParams = &rsaKeyGenParams; 96 keyGenParams = &rsaKeyGenParams;
113 97
114 algTag = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION; // from <nss/secoidt.h>. 98 algTag = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION; // from <nss/secoidt.h>.
115 break; 99 break;
116 default: 100 default:
117 // TODO(gauravsh): If we ever support other mechanisms, 101 // TODO(gauravsh): If we ever support other mechanisms,
118 // this can be changed. 102 // this can be changed.
119 LOG(ERROR) << "Only RSA keygen mechanism is supported"; 103 LOG(ERROR) << "Only RSA keygen mechanism is supported";
120 isSuccess = false; 104 isSuccess = false;
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
195 // Sign the DER encoded PublicKeyAndChallenge. 179 // Sign the DER encoded PublicKeyAndChallenge.
196 sec_rv = SEC_DerSignData(arena, &signedItem, pkacItem.data, pkacItem.len, 180 sec_rv = SEC_DerSignData(arena, &signedItem, pkacItem.data, pkacItem.len,
197 privateKey, algTag); 181 privateKey, algTag);
198 if (SECSuccess != sec_rv) { 182 if (SECSuccess != sec_rv) {
199 LOG(ERROR) << "Couldn't sign the DER encoded PublicKeyandChallenge"; 183 LOG(ERROR) << "Couldn't sign the DER encoded PublicKeyandChallenge";
200 isSuccess = false; 184 isSuccess = false;
201 goto failure; 185 goto failure;
202 } 186 }
203 187
204 // Convert the signed public key and challenge into base64/ascii. 188 // Convert the signed public key and challenge into base64/ascii.
205 keystring = NSSBase64_EncodeItem(arena, 189 if (!base::Base64Encode(std::string(reinterpret_cast<char*>(signedItem.data),
206 NULL, // NSS will allocate a buffer for us. 190 signedItem.len),
207 0, 191 &result_blob)) {
208 &signedItem);
209 if (!keystring) {
210 LOG(ERROR) << "Couldn't convert signed public key into base64"; 192 LOG(ERROR) << "Couldn't convert signed public key into base64";
211 isSuccess = false; 193 isSuccess = false;
212 goto failure; 194 goto failure;
213 } 195 }
214 196
215 result_blob = keystring;
216
217 failure: 197 failure:
218 if (!isSuccess) { 198 if (!isSuccess) {
219 LOG(ERROR) << "SSL Keygen failed!"; 199 LOG(ERROR) << "SSL Keygen failed!";
220 } else { 200 } else {
221 LOG(INFO) << "SSl Keygen succeeded!"; 201 LOG(INFO) << "SSl Keygen succeeded!";
222 } 202 }
223 203
224 // Do cleanups 204 // Do cleanups
225 if (privateKey) { 205 if (privateKey) {
226 // TODO(gauravsh): We still need to maintain the private key because it's 206 if (!isSuccess || !stores_key_) {
227 // used for certificate enrollment checks. 207 PK11_DestroyTokenObject(privateKey->pkcs11Slot,privateKey->pkcs11ID);
228 208 SECKEY_DestroyPrivateKey(privateKey);
229 // PK11_DestroyTokenObject(privateKey->pkcs11Slot,privateKey->pkcs11ID); 209 }
230 // SECKEY_DestroyPrivateKey(privateKey); 210 // On successful keygen we need to keep the private key, of course,
211 // or we won't be able to use the client certificate.
231 } 212 }
232 213
233 if (publicKey) { 214 if (publicKey) {
234 PK11_DestroyTokenObject(publicKey->pkcs11Slot, publicKey->pkcs11ID); 215 PK11_DestroyTokenObject(publicKey->pkcs11Slot, publicKey->pkcs11ID);
235 } 216 }
236 if (spkInfo) { 217 if (spkInfo) {
237 SECKEY_DestroySubjectPublicKeyInfo(spkInfo); 218 SECKEY_DestroySubjectPublicKeyInfo(spkInfo);
238 } 219 }
239 if (publicKey) { 220 if (publicKey) {
240 SECKEY_DestroyPublicKey(publicKey); 221 SECKEY_DestroyPublicKey(publicKey);
241 } 222 }
242 if (arena) { 223 if (arena) {
243 PORT_FreeArena(arena, PR_TRUE); 224 PORT_FreeArena(arena, PR_TRUE);
244 } 225 }
245 if (slot != NULL) { 226 if (slot != NULL) {
246 PK11_FreeSlot(slot); 227 PK11_FreeSlot(slot);
247 } 228 }
248 if (pkac.challenge.data) { 229 if (pkac.challenge.data) {
249 free(pkac.challenge.data); 230 free(pkac.challenge.data);
250 } 231 }
251 232
252 return (isSuccess ? result_blob : std::string()); 233 return (isSuccess ? result_blob : std::string());
253 } 234 }
254 235
255 } // namespace net 236 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698