| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |