OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2012 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2012 The WebRTC Project Authors. All rights reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
(...skipping 29 matching lines...) Expand all Loading... | |
40 // This is to compensate for slightly incorrect system clocks. | 40 // This is to compensate for slightly incorrect system clocks. |
41 static const int CERTIFICATE_WINDOW = -60*60*24; | 41 static const int CERTIFICATE_WINDOW = -60*60*24; |
42 | 42 |
43 NSSKeyPair::~NSSKeyPair() { | 43 NSSKeyPair::~NSSKeyPair() { |
44 if (privkey_) | 44 if (privkey_) |
45 SECKEY_DestroyPrivateKey(privkey_); | 45 SECKEY_DestroyPrivateKey(privkey_); |
46 if (pubkey_) | 46 if (pubkey_) |
47 SECKEY_DestroyPublicKey(pubkey_); | 47 SECKEY_DestroyPublicKey(pubkey_); |
48 } | 48 } |
49 | 49 |
50 NSSKeyPair *NSSKeyPair::Generate() { | 50 NSSKeyPair* NSSKeyPair::Generate(KeyType key_type) { |
51 SECKEYPrivateKey *privkey = NULL; | 51 SECKEYPrivateKey* privkey = nullptr; |
52 SECKEYPublicKey *pubkey = NULL; | 52 SECKEYPublicKey* pubkey = nullptr; |
53 PK11RSAGenParams rsaparams; | 53 SSLKEAType ssl_kea_type; |
54 rsaparams.keySizeInBits = 1024; | 54 if (key_type == KT_RSA) { |
55 rsaparams.pe = 0x010001; // 65537 -- a common RSA public exponent. | 55 PK11RSAGenParams rsa_params; |
56 rsa_params.keySizeInBits = 1024; | |
57 rsa_params.pe = 0x010001; // 65537 -- a common RSA public exponent. | |
56 | 58 |
57 privkey = PK11_GenerateKeyPair(NSSContext::GetSlot(), | 59 privkey = PK11_GenerateKeyPair( |
58 CKM_RSA_PKCS_KEY_PAIR_GEN, | 60 NSSContext::GetSlot(), CKM_RSA_PKCS_KEY_PAIR_GEN, &rsa_params, &pubkey, |
59 &rsaparams, &pubkey, PR_FALSE /*permanent*/, | 61 PR_FALSE /*permanent*/, PR_FALSE /*sensitive*/, nullptr); |
60 PR_FALSE /*sensitive*/, NULL); | 62 |
61 if (!privkey) { | 63 ssl_kea_type = ssl_kea_rsa; |
62 LOG(LS_ERROR) << "Couldn't generate key pair"; | 64 } else if (key_type == KT_ECDSA) { |
63 return NULL; | 65 unsigned char param_buf[12]; // OIDs are small |
66 SECItem ecdsa_params = {siBuffer, param_buf, sizeof(param_buf)}; | |
67 SECOidData* oid_data = SECOID_FindOIDByTag(SEC_OID_SECG_EC_SECP256R1); | |
68 if (!oid_data || oid_data->oid.len > sizeof(param_buf) - 2) { | |
69 LOG(LS_ERROR) << "oid_data incorrect: " << oid_data->oid.len; | |
70 return nullptr; | |
71 } | |
72 ecdsa_params.data[0] = SEC_ASN1_OBJECT_ID; | |
73 ecdsa_params.data[1] = oid_data->oid.len; | |
74 memcpy(ecdsa_params.data + 2, oid_data->oid.data, oid_data->oid.len); | |
75 ecdsa_params.len = oid_data->oid.len + 2; | |
76 | |
77 privkey = PK11_GenerateKeyPair( | |
78 NSSContext::GetSlot(), CKM_EC_KEY_PAIR_GEN, &ecdsa_params, &pubkey, | |
79 PR_FALSE /*permanent*/, PR_FALSE /*sensitive*/, nullptr); | |
80 | |
81 ssl_kea_type = ssl_kea_ecdh; | |
82 } else { | |
83 LOG(LS_ERROR) << "Key type requested not understood"; | |
tommi
2015/06/15 21:02:42
What about having something like this at the top o
juberti1
2015/06/16 02:45:04
Seems kind of drastic. If we added another key typ
tommi
2015/06/16 14:38:01
If we add a new key type and don't need to handle
| |
84 return nullptr; | |
64 } | 85 } |
65 | 86 |
66 return new NSSKeyPair(privkey, pubkey); | 87 if (!privkey) { |
88 LOG(LS_ERROR) << "Couldn't generate key pair: " << PORT_GetError(); | |
89 return nullptr; | |
90 } | |
91 | |
92 return new NSSKeyPair(privkey, pubkey, ssl_kea_type); | |
67 } | 93 } |
68 | 94 |
69 // Just make a copy. | 95 // Just make a copy. |
70 NSSKeyPair *NSSKeyPair::GetReference() { | 96 NSSKeyPair* NSSKeyPair::GetReference() { |
71 SECKEYPrivateKey *privkey = SECKEY_CopyPrivateKey(privkey_); | 97 SECKEYPrivateKey* privkey = SECKEY_CopyPrivateKey(privkey_); |
72 if (!privkey) | 98 if (!privkey) |
73 return NULL; | 99 return nullptr; |
74 | 100 |
75 SECKEYPublicKey *pubkey = SECKEY_CopyPublicKey(pubkey_); | 101 SECKEYPublicKey* pubkey = SECKEY_CopyPublicKey(pubkey_); |
76 if (!pubkey) { | 102 if (!pubkey) { |
77 SECKEY_DestroyPrivateKey(privkey); | 103 SECKEY_DestroyPrivateKey(privkey); |
78 return NULL; | 104 return nullptr; |
79 } | 105 } |
80 | 106 |
81 return new NSSKeyPair(privkey, pubkey); | 107 return new NSSKeyPair(privkey, pubkey, ssl_kea_type_); |
82 } | 108 } |
83 | 109 |
84 NSSCertificate::NSSCertificate(CERTCertificate* cert) | 110 NSSCertificate::NSSCertificate(CERTCertificate* cert) |
85 : certificate_(CERT_DupCertificate(cert)) { | 111 : certificate_(CERT_DupCertificate(cert)) { |
86 ASSERT(certificate_ != NULL); | 112 ASSERT(certificate_ != nullptr); |
87 } | 113 } |
88 | 114 |
89 static void DeleteCert(SSLCertificate* cert) { | 115 static void DeleteCert(SSLCertificate* cert) { |
90 delete cert; | 116 delete cert; |
91 } | 117 } |
92 | 118 |
93 NSSCertificate::NSSCertificate(CERTCertList* cert_list) { | 119 NSSCertificate::NSSCertificate(CERTCertList* cert_list) { |
94 // Copy the first cert into certificate_. | 120 // Copy the first cert into certificate_. |
95 CERTCertListNode* node = CERT_LIST_HEAD(cert_list); | 121 CERTCertListNode* node = CERT_LIST_HEAD(cert_list); |
96 certificate_ = CERT_DupCertificate(node->cert); | 122 certificate_ = CERT_DupCertificate(node->cert); |
97 | 123 |
98 // Put any remaining certificates into the chain. | 124 // Put any remaining certificates into the chain. |
99 node = CERT_LIST_NEXT(node); | 125 node = CERT_LIST_NEXT(node); |
100 std::vector<SSLCertificate*> certs; | 126 std::vector<SSLCertificate*> certs; |
101 for (; !CERT_LIST_END(node, cert_list); node = CERT_LIST_NEXT(node)) { | 127 for (; !CERT_LIST_END(node, cert_list); node = CERT_LIST_NEXT(node)) { |
102 certs.push_back(new NSSCertificate(node->cert)); | 128 certs.push_back(new NSSCertificate(node->cert)); |
103 } | 129 } |
104 | 130 |
105 if (!certs.empty()) | 131 if (!certs.empty()) |
106 chain_.reset(new SSLCertChain(certs)); | 132 chain_.reset(new SSLCertChain(certs)); |
107 | 133 |
108 // The SSLCertChain constructor copies its input, so now we have to delete | 134 // The SSLCertChain constructor copies its input, so now we have to delete |
109 // the originals. | 135 // the originals. |
110 std::for_each(certs.begin(), certs.end(), DeleteCert); | 136 std::for_each(certs.begin(), certs.end(), DeleteCert); |
111 } | 137 } |
112 | 138 |
113 NSSCertificate::NSSCertificate(CERTCertificate* cert, SSLCertChain* chain) | 139 NSSCertificate::NSSCertificate(CERTCertificate* cert, SSLCertChain* chain) |
114 : certificate_(CERT_DupCertificate(cert)) { | 140 : certificate_(CERT_DupCertificate(cert)) { |
115 ASSERT(certificate_ != NULL); | 141 ASSERT(certificate_ != nullptr); |
tommi
2015/06/15 21:02:42
Can we switch over to using DCHECK instead of ASSE
juberti1
2015/06/16 02:45:04
I think that should be done globally (pthatcher/pb
| |
116 if (chain) | 142 if (chain) |
117 chain_.reset(chain->Copy()); | 143 chain_.reset(chain->Copy()); |
118 } | 144 } |
119 | 145 |
120 NSSCertificate::~NSSCertificate() { | 146 NSSCertificate::~NSSCertificate() { |
121 if (certificate_) | 147 if (certificate_) |
122 CERT_DestroyCertificate(certificate_); | 148 CERT_DestroyCertificate(certificate_); |
123 } | 149 } |
124 | 150 |
125 NSSCertificate *NSSCertificate::FromPEMString(const std::string &pem_string) { | 151 NSSCertificate* NSSCertificate::FromPEMString(const std::string& pem_string) { |
126 std::string der; | 152 std::string der; |
127 if (!SSLIdentity::PemToDer(kPemTypeCertificate, pem_string, &der)) | 153 if (!SSLIdentity::PemToDer(kPemTypeCertificate, pem_string, &der)) |
128 return NULL; | 154 return nullptr; |
129 | 155 |
130 SECItem der_cert; | 156 SECItem der_cert; |
131 der_cert.data = reinterpret_cast<unsigned char *>(const_cast<char *>( | 157 der_cert.data = reinterpret_cast<unsigned char *>(const_cast<char *>( |
132 der.data())); | 158 der.data())); |
133 der_cert.len = checked_cast<unsigned int>(der.size()); | 159 der_cert.len = checked_cast<unsigned int>(der.size()); |
134 CERTCertificate *cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), | 160 CERTCertificate* cert = CERT_NewTempCertificate( |
135 &der_cert, NULL, PR_FALSE, PR_TRUE); | 161 CERT_GetDefaultCertDB(), &der_cert, nullptr, PR_FALSE, PR_TRUE); |
136 | 162 |
137 if (!cert) | 163 if (!cert) |
138 return NULL; | 164 return nullptr; |
139 | 165 |
140 NSSCertificate* ret = new NSSCertificate(cert); | 166 NSSCertificate* ret = new NSSCertificate(cert); |
141 CERT_DestroyCertificate(cert); | 167 CERT_DestroyCertificate(cert); |
142 return ret; | 168 return ret; |
143 } | 169 } |
144 | 170 |
145 NSSCertificate *NSSCertificate::GetReference() const { | 171 NSSCertificate* NSSCertificate::GetReference() const { |
146 return new NSSCertificate(certificate_, chain_.get()); | 172 return new NSSCertificate(certificate_, chain_.get()); |
147 } | 173 } |
148 | 174 |
149 std::string NSSCertificate::ToPEMString() const { | 175 std::string NSSCertificate::ToPEMString() const { |
150 return SSLIdentity::DerToPem(kPemTypeCertificate, | 176 return SSLIdentity::DerToPem(kPemTypeCertificate, |
151 certificate_->derCert.data, | 177 certificate_->derCert.data, |
152 certificate_->derCert.len); | 178 certificate_->derCert.len); |
153 } | 179 } |
154 | 180 |
155 void NSSCertificate::ToDER(Buffer* der_buffer) const { | 181 void NSSCertificate::ToDER(Buffer* der_buffer) const { |
(...skipping 17 matching lines...) Expand all Loading... | |
173 return false; | 199 return false; |
174 | 200 |
175 // Extract the parent's public key, or fail if the key could not be read | 201 // Extract the parent's public key, or fail if the key could not be read |
176 // (e.g. certificate is corrupted). | 202 // (e.g. certificate is corrupted). |
177 SECKEYPublicKey* parent_key = CERT_ExtractPublicKey(parent); | 203 SECKEYPublicKey* parent_key = CERT_ExtractPublicKey(parent); |
178 if (!parent_key) | 204 if (!parent_key) |
179 return false; | 205 return false; |
180 | 206 |
181 // Check that the parent's privkey was actually used to generate the child's | 207 // Check that the parent's privkey was actually used to generate the child's |
182 // signature. | 208 // signature. |
183 SECStatus verified = CERT_VerifySignedDataWithPublicKey( | 209 SECStatus verified = CERT_VerifySignedDataWithPublicKey(&child->signatureWrap, |
184 &child->signatureWrap, parent_key, NULL); | 210 parent_key, nullptr); |
185 SECKEY_DestroyPublicKey(parent_key); | 211 SECKEY_DestroyPublicKey(parent_key); |
186 return verified == SECSuccess; | 212 return verified == SECSuccess; |
187 } | 213 } |
188 | 214 |
189 bool NSSCertificate::IsValidChain(const CERTCertList* cert_list) { | 215 bool NSSCertificate::IsValidChain(const CERTCertList* cert_list) { |
190 CERTCertListNode* child = CERT_LIST_HEAD(cert_list); | 216 CERTCertListNode* child = CERT_LIST_HEAD(cert_list); |
191 for (CERTCertListNode* parent = CERT_LIST_NEXT(child); | 217 for (CERTCertListNode* parent = CERT_LIST_NEXT(child); |
192 !CERT_LIST_END(parent, cert_list); | 218 !CERT_LIST_END(parent, cert_list); |
193 child = parent, parent = CERT_LIST_NEXT(parent)) { | 219 child = parent, parent = CERT_LIST_NEXT(parent)) { |
194 if (!Certifies(parent->cert, child->cert)) | 220 if (!Certifies(parent->cert, child->cert)) |
195 return false; | 221 return false; |
196 } | 222 } |
197 return true; | 223 return true; |
198 } | 224 } |
199 | 225 |
200 bool NSSCertificate::GetDigestLength(const std::string& algorithm, | 226 bool NSSCertificate::GetDigestLength(const std::string& algorithm, |
201 size_t* length) { | 227 size_t* length) { |
202 const SECHashObject *ho; | 228 const SECHashObject* ho; |
tommi
2015/06/15 21:02:42
nit: initialize to nullptr
torbjorng (webrtc)
2015/06/16 14:11:51
A cleanup in old code, but OK...
| |
203 | 229 |
204 if (!GetDigestObject(algorithm, &ho)) | 230 if (!GetDigestObject(algorithm, &ho)) |
205 return false; | 231 return false; |
206 | 232 |
207 *length = ho->length; | 233 *length = ho->length; |
208 | 234 |
209 return true; | 235 return true; |
210 } | 236 } |
211 | 237 |
212 bool NSSCertificate::GetSignatureDigestAlgorithm(std::string* algorithm) const { | 238 bool NSSCertificate::GetSignatureDigestAlgorithm(std::string* algorithm) const { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
254 algorithm->clear(); | 280 algorithm->clear(); |
255 return false; | 281 return false; |
256 } | 282 } |
257 return true; | 283 return true; |
258 } | 284 } |
259 | 285 |
260 bool NSSCertificate::ComputeDigest(const std::string& algorithm, | 286 bool NSSCertificate::ComputeDigest(const std::string& algorithm, |
261 unsigned char* digest, | 287 unsigned char* digest, |
262 size_t size, | 288 size_t size, |
263 size_t* length) const { | 289 size_t* length) const { |
264 const SECHashObject *ho; | 290 const SECHashObject* ho; |
265 | 291 |
266 if (!GetDigestObject(algorithm, &ho)) | 292 if (!GetDigestObject(algorithm, &ho)) |
267 return false; | 293 return false; |
268 | 294 |
269 if (size < ho->length) // Sanity check for fit | 295 if (size < ho->length) // Sanity check for fit |
270 return false; | 296 return false; |
271 | 297 |
272 SECStatus rv = HASH_HashBuf(ho->type, digest, | 298 SECStatus rv = HASH_HashBuf(ho->type, digest, |
273 certificate_->derCert.data, | 299 certificate_->derCert.data, |
274 certificate_->derCert.len); | 300 certificate_->derCert.len); |
275 if (rv != SECSuccess) | 301 if (rv != SECSuccess) |
276 return false; | 302 return false; |
277 | 303 |
278 *length = ho->length; | 304 *length = ho->length; |
279 | 305 |
280 return true; | 306 return true; |
281 } | 307 } |
282 | 308 |
283 bool NSSCertificate::GetChain(SSLCertChain** chain) const { | 309 bool NSSCertificate::GetChain(SSLCertChain** chain) const { |
284 if (!chain_) | 310 if (!chain_) |
285 return false; | 311 return false; |
286 | 312 |
287 *chain = chain_->Copy(); | 313 *chain = chain_->Copy(); |
288 return true; | 314 return true; |
289 } | 315 } |
290 | 316 |
291 bool NSSCertificate::Equals(const NSSCertificate *tocompare) const { | 317 bool NSSCertificate::Equals(const NSSCertificate* tocompare) const { |
tommi
2015/06/15 21:02:42
nit: to_compare
torbjorng (webrtc)
2015/06/16 14:11:51
I will defer this cleanup in old to separate CL.
torbjorng (webrtc)
2015/06/16 14:11:51
I don't understand this comment.
tommi
2015/06/16 14:38:01
the naming rules would be to use an underscore in
| |
292 if (!certificate_->derCert.len) | 318 if (!certificate_->derCert.len) |
293 return false; | 319 return false; |
294 if (!tocompare->certificate_->derCert.len) | 320 if (!tocompare->certificate_->derCert.len) |
295 return false; | 321 return false; |
296 | 322 |
297 if (certificate_->derCert.len != tocompare->certificate_->derCert.len) | 323 if (certificate_->derCert.len != tocompare->certificate_->derCert.len) |
298 return false; | 324 return false; |
299 | 325 |
300 return memcmp(certificate_->derCert.data, | 326 return memcmp(certificate_->derCert.data, |
301 tocompare->certificate_->derCert.data, | 327 tocompare->certificate_->derCert.data, |
302 certificate_->derCert.len) == 0; | 328 certificate_->derCert.len) == 0; |
303 } | 329 } |
304 | 330 |
305 | 331 bool NSSCertificate::GetDigestObject(const std::string& algorithm, |
306 bool NSSCertificate::GetDigestObject(const std::string &algorithm, | 332 const SECHashObject** hop) { |
307 const SECHashObject **hop) { | 333 const SECHashObject* ho; |
308 const SECHashObject *ho; | |
309 HASH_HashType hash_type; | 334 HASH_HashType hash_type; |
310 | 335 |
311 if (algorithm == DIGEST_SHA_1) { | 336 if (algorithm == DIGEST_SHA_1) { |
312 hash_type = HASH_AlgSHA1; | 337 hash_type = HASH_AlgSHA1; |
313 // HASH_AlgSHA224 is not supported in the chromium linux build system. | 338 // HASH_AlgSHA224 is not supported in the chromium linux build system. |
314 #if 0 | 339 #if 0 |
315 } else if (algorithm == DIGEST_SHA_224) { | 340 } else if (algorithm == DIGEST_SHA_224) { |
316 hash_type = HASH_AlgSHA224; | 341 hash_type = HASH_AlgSHA224; |
317 #endif | 342 #endif |
318 } else if (algorithm == DIGEST_SHA_256) { | 343 } else if (algorithm == DIGEST_SHA_256) { |
(...skipping 11 matching lines...) Expand all Loading... | |
330 ASSERT(ho->length >= 20); // Can't happen | 355 ASSERT(ho->length >= 20); // Can't happen |
331 *hop = ho; | 356 *hop = ho; |
332 | 357 |
333 return true; | 358 return true; |
334 } | 359 } |
335 | 360 |
336 NSSIdentity::NSSIdentity(NSSKeyPair* keypair, NSSCertificate* cert) | 361 NSSIdentity::NSSIdentity(NSSKeyPair* keypair, NSSCertificate* cert) |
337 : keypair_(keypair), certificate_(cert) { | 362 : keypair_(keypair), certificate_(cert) { |
338 } | 363 } |
339 | 364 |
340 NSSIdentity* NSSIdentity::GenerateInternal(const SSLIdentityParams& params) { | 365 NSSIdentity* NSSIdentity::GenerateInternal(const SSLIdentityParams& params, |
366 KeyType key_type) { | |
341 std::string subject_name_string = "CN=" + params.common_name; | 367 std::string subject_name_string = "CN=" + params.common_name; |
342 CERTName *subject_name = CERT_AsciiToName( | 368 CERTName* subject_name = |
343 const_cast<char *>(subject_name_string.c_str())); | 369 CERT_AsciiToName(const_cast<char*>(subject_name_string.c_str())); |
344 NSSIdentity *identity = NULL; | 370 NSSIdentity* identity = nullptr; |
345 CERTSubjectPublicKeyInfo *spki = NULL; | 371 CERTSubjectPublicKeyInfo* spki = nullptr; |
346 CERTCertificateRequest *certreq = NULL; | 372 CERTCertificateRequest* certreq = nullptr; |
347 CERTValidity *validity = NULL; | 373 CERTValidity* validity = nullptr; |
348 CERTCertificate *certificate = NULL; | 374 CERTCertificate* certificate = nullptr; |
349 NSSKeyPair *keypair = NSSKeyPair::Generate(); | 375 NSSKeyPair* keypair = NSSKeyPair::Generate(key_type); |
350 SECItem inner_der; | 376 SECItem inner_der; |
351 SECStatus rv; | 377 SECStatus rv; |
352 PLArenaPool* arena; | 378 PLArenaPool* arena; |
353 SECItem signed_cert; | 379 SECItem signed_cert; |
354 PRTime now = PR_Now(); | 380 PRTime now = PR_Now(); |
355 PRTime not_before = | 381 PRTime not_before = |
356 now + static_cast<PRTime>(params.not_before) * PR_USEC_PER_SEC; | 382 now + static_cast<PRTime>(params.not_before) * PR_USEC_PER_SEC; |
357 PRTime not_after = | 383 PRTime not_after = |
358 now + static_cast<PRTime>(params.not_after) * PR_USEC_PER_SEC; | 384 now + static_cast<PRTime>(params.not_after) * PR_USEC_PER_SEC; |
359 | 385 |
360 inner_der.len = 0; | 386 inner_der.len = 0; |
361 inner_der.data = NULL; | 387 inner_der.data = nullptr; |
362 | 388 |
363 if (!keypair) { | 389 if (!keypair) { |
364 LOG(LS_ERROR) << "Couldn't generate key pair"; | 390 LOG(LS_ERROR) << "Couldn't generate key pair"; |
365 goto fail; | 391 goto fail; |
366 } | 392 } |
367 | 393 |
368 if (!subject_name) { | 394 if (!subject_name) { |
369 LOG(LS_ERROR) << "Couldn't convert subject name " << subject_name; | 395 LOG(LS_ERROR) << "Couldn't convert subject name " << subject_name; |
370 goto fail; | 396 goto fail; |
371 } | 397 } |
372 | 398 |
373 spki = SECKEY_CreateSubjectPublicKeyInfo(keypair->pubkey()); | 399 spki = SECKEY_CreateSubjectPublicKeyInfo(keypair->pubkey()); |
374 if (!spki) { | 400 if (!spki) { |
375 LOG(LS_ERROR) << "Couldn't create SPKI"; | 401 LOG(LS_ERROR) << "Couldn't create SPKI"; |
376 goto fail; | 402 goto fail; |
377 } | 403 } |
378 | 404 |
379 certreq = CERT_CreateCertificateRequest(subject_name, spki, NULL); | 405 certreq = CERT_CreateCertificateRequest(subject_name, spki, nullptr); |
380 if (!certreq) { | 406 if (!certreq) { |
381 LOG(LS_ERROR) << "Couldn't create certificate signing request"; | 407 LOG(LS_ERROR) << "Couldn't create certificate signing request"; |
382 goto fail; | 408 goto fail; |
383 } | 409 } |
384 | 410 |
385 validity = CERT_CreateValidity(not_before, not_after); | 411 validity = CERT_CreateValidity(not_before, not_after); |
386 if (!validity) { | 412 if (!validity) { |
387 LOG(LS_ERROR) << "Couldn't create validity"; | 413 LOG(LS_ERROR) << "Couldn't create validity"; |
388 goto fail; | 414 goto fail; |
389 } | 415 } |
390 | 416 |
391 unsigned long serial; | 417 unsigned long serial; |
392 // Note: This serial in principle could collide, but it's unlikely | 418 // Note: This serial in principle could collide, but it's unlikely |
393 rv = PK11_GenerateRandom(reinterpret_cast<unsigned char *>(&serial), | 419 rv = PK11_GenerateRandom(reinterpret_cast<unsigned char *>(&serial), |
394 sizeof(serial)); | 420 sizeof(serial)); |
395 if (rv != SECSuccess) { | 421 if (rv != SECSuccess) { |
396 LOG(LS_ERROR) << "Couldn't generate random serial"; | 422 LOG(LS_ERROR) << "Couldn't generate random serial"; |
397 goto fail; | 423 goto fail; |
398 } | 424 } |
399 | 425 |
400 certificate = CERT_CreateCertificate(serial, subject_name, validity, certreq); | 426 certificate = CERT_CreateCertificate(serial, subject_name, validity, certreq); |
401 if (!certificate) { | 427 if (!certificate) { |
402 LOG(LS_ERROR) << "Couldn't create certificate"; | 428 LOG(LS_ERROR) << "Couldn't create certificate"; |
403 goto fail; | 429 goto fail; |
404 } | 430 } |
405 | 431 |
406 arena = certificate->arena; | 432 arena = certificate->arena; |
407 | 433 |
408 rv = SECOID_SetAlgorithmID(arena, &certificate->signature, | 434 rv = SECFailure; // Trigger failure for undefined key_type. |
409 SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION, NULL); | 435 if (key_type == KT_RSA) { |
410 if (rv != SECSuccess) | 436 rv = SECOID_SetAlgorithmID(arena, &certificate->signature, |
437 SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION, | |
juberti1
2015/06/16 02:45:04
This seems like it could be factored to simply set
torbjorng (webrtc)
2015/06/16 14:11:51
Done.
| |
438 nullptr); | |
439 } else if (key_type == KT_ECDSA) { | |
440 rv = | |
441 SECOID_SetAlgorithmID(arena, &certificate->signature, | |
442 SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE, nullptr); | |
443 } | |
444 if (rv != SECSuccess) { | |
445 LOG(LS_ERROR) << "Couldn't set hashing algorithm"; | |
tommi
2015/06/15 21:02:42
Are these errors something we should expect to hap
juberti1
2015/06/16 02:45:05
Caller needs to handle failure because keygen can
torbjorng (webrtc)
2015/06/16 14:11:51
Some of these "goto fail" could probably not happe
| |
411 goto fail; | 446 goto fail; |
447 } | |
412 | 448 |
413 // Set version to X509v3. | 449 // Set version to X509v3. |
414 *(certificate->version.data) = 2; | 450 *(certificate->version.data) = 2; |
415 certificate->version.len = 1; | 451 certificate->version.len = 1; |
416 | 452 |
417 if (!SEC_ASN1EncodeItem(arena, &inner_der, certificate, | 453 if (!SEC_ASN1EncodeItem(arena, &inner_der, certificate, |
418 SEC_ASN1_GET(CERT_CertificateTemplate))) | 454 SEC_ASN1_GET(CERT_CertificateTemplate))) { |
455 LOG(LS_ERROR) << "Couldn't encode certificate"; | |
419 goto fail; | 456 goto fail; |
457 } | |
420 | 458 |
421 rv = SEC_DerSignData(arena, &signed_cert, inner_der.data, inner_der.len, | 459 rv = SECFailure; // Trigger failure for undefined key_type. |
422 keypair->privkey(), | 460 if (key_type == KT_RSA) { |
423 SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION); | 461 rv = SEC_DerSignData(arena, &signed_cert, inner_der.data, inner_der.len, |
462 keypair->privkey(), | |
463 SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION); | |
464 } else if (key_type == KT_ECDSA) { | |
465 rv = SEC_DerSignData(arena, &signed_cert, inner_der.data, inner_der.len, | |
466 keypair->privkey(), | |
467 SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE); | |
468 } | |
469 | |
424 if (rv != SECSuccess) { | 470 if (rv != SECSuccess) { |
425 LOG(LS_ERROR) << "Couldn't sign certificate"; | 471 LOG(LS_ERROR) << "Couldn't sign certificate"; |
426 goto fail; | 472 goto fail; |
427 } | 473 } |
428 certificate->derCert = signed_cert; | 474 certificate->derCert = signed_cert; |
429 | 475 |
430 identity = new NSSIdentity(keypair, new NSSCertificate(certificate)); | 476 identity = new NSSIdentity(keypair, new NSSCertificate(certificate)); |
431 | 477 |
432 goto done; | 478 goto done; |
433 | 479 |
434 fail: | 480 fail: |
435 delete keypair; | 481 delete keypair; |
436 | 482 |
437 done: | 483 done: |
438 if (certificate) CERT_DestroyCertificate(certificate); | 484 if (certificate) CERT_DestroyCertificate(certificate); |
439 if (subject_name) CERT_DestroyName(subject_name); | 485 if (subject_name) CERT_DestroyName(subject_name); |
440 if (spki) SECKEY_DestroySubjectPublicKeyInfo(spki); | 486 if (spki) SECKEY_DestroySubjectPublicKeyInfo(spki); |
441 if (certreq) CERT_DestroyCertificateRequest(certreq); | 487 if (certreq) CERT_DestroyCertificateRequest(certreq); |
442 if (validity) CERT_DestroyValidity(validity); | 488 if (validity) CERT_DestroyValidity(validity); |
443 return identity; | 489 return identity; |
444 } | 490 } |
445 | 491 |
446 NSSIdentity* NSSIdentity::Generate(const std::string &common_name) { | 492 NSSIdentity* NSSIdentity::Generate(const std::string& common_name, |
493 KeyType key_type) { | |
447 SSLIdentityParams params; | 494 SSLIdentityParams params; |
448 params.common_name = common_name; | 495 params.common_name = common_name; |
449 params.not_before = CERTIFICATE_WINDOW; | 496 params.not_before = CERTIFICATE_WINDOW; |
450 params.not_after = CERTIFICATE_LIFETIME; | 497 params.not_after = CERTIFICATE_LIFETIME; |
451 return GenerateInternal(params); | 498 return GenerateInternal(params, key_type); |
452 } | 499 } |
453 | 500 |
454 NSSIdentity* NSSIdentity::GenerateForTest(const SSLIdentityParams& params) { | 501 NSSIdentity* NSSIdentity::GenerateForTest(const SSLIdentityParams& params, |
455 return GenerateInternal(params); | 502 KeyType key_type) { |
503 return GenerateInternal(params, key_type); | |
456 } | 504 } |
457 | 505 |
458 SSLIdentity* NSSIdentity::FromPEMStrings(const std::string& private_key, | 506 SSLIdentity* NSSIdentity::FromPEMStrings(const std::string& private_key, |
459 const std::string& certificate) { | 507 const std::string& certificate) { |
460 std::string private_key_der; | 508 std::string private_key_der; |
461 if (!SSLIdentity::PemToDer( | 509 if (!SSLIdentity::PemToDer( |
462 kPemTypeRsaPrivateKey, private_key, &private_key_der)) | 510 kPemTypeRsaPrivateKey, private_key, &private_key_der)) |
463 return NULL; | 511 return nullptr; |
464 | 512 |
465 SECItem private_key_item; | 513 SECItem private_key_item; |
466 private_key_item.data = reinterpret_cast<unsigned char *>( | 514 private_key_item.data = reinterpret_cast<unsigned char *>( |
467 const_cast<char *>(private_key_der.c_str())); | 515 const_cast<char *>(private_key_der.c_str())); |
468 private_key_item.len = checked_cast<unsigned int>(private_key_der.size()); | 516 private_key_item.len = checked_cast<unsigned int>(private_key_der.size()); |
469 | 517 |
470 const unsigned int key_usage = KU_KEY_ENCIPHERMENT | KU_DATA_ENCIPHERMENT | | 518 const unsigned int key_usage = KU_KEY_ENCIPHERMENT | KU_DATA_ENCIPHERMENT | |
471 KU_DIGITAL_SIGNATURE; | 519 KU_DIGITAL_SIGNATURE; |
472 | 520 |
473 SECKEYPrivateKey* privkey = NULL; | 521 SECKEYPrivateKey* privkey = nullptr; |
474 SECStatus rv = | 522 SECStatus rv = PK11_ImportDERPrivateKeyInfoAndReturnKey( |
475 PK11_ImportDERPrivateKeyInfoAndReturnKey(NSSContext::GetSlot(), | 523 NSSContext::GetSlot(), &private_key_item, nullptr, nullptr, PR_FALSE, |
476 &private_key_item, | 524 PR_FALSE, key_usage, &privkey, nullptr); |
477 NULL, NULL, PR_FALSE, PR_FALSE, | |
478 key_usage, &privkey, NULL); | |
479 if (rv != SECSuccess) { | 525 if (rv != SECSuccess) { |
480 LOG(LS_ERROR) << "Couldn't import private key"; | 526 LOG(LS_ERROR) << "Couldn't import private key"; |
481 return NULL; | 527 return nullptr; |
482 } | 528 } |
483 | 529 |
484 SECKEYPublicKey *pubkey = SECKEY_ConvertToPublicKey(privkey); | 530 SECKEYPublicKey* pubkey = SECKEY_ConvertToPublicKey(privkey); |
485 if (rv != SECSuccess) { | 531 if (rv != SECSuccess) { |
486 SECKEY_DestroyPrivateKey(privkey); | 532 SECKEY_DestroyPrivateKey(privkey); |
487 LOG(LS_ERROR) << "Couldn't convert private key to public key"; | 533 LOG(LS_ERROR) << "Couldn't convert private key to public key"; |
488 return NULL; | 534 return nullptr; |
535 } | |
536 | |
537 SSLKEAType ssl_kea_type; | |
538 if (private_key.find("-----BEGIN RSA PRIVATE KEY-----") == 0) { | |
tommi
2015/06/15 21:02:42
nit: could use startswith as suggested in the othe
torbjorng (webrtc)
2015/06/16 14:11:51
Done.
| |
539 ssl_kea_type = ssl_kea_rsa; | |
540 } else { | |
541 // We might want to check more key types here. But since we're moving to | |
542 // Open/BoringSSL, don't bother. Besides, this will likely be correct for | |
543 // any future key type, causing a test to do more harm than good. | |
544 ssl_kea_type = ssl_kea_ecdh; | |
489 } | 545 } |
490 | 546 |
491 // Assign to a scoped_ptr so we don't leak on error. | 547 // Assign to a scoped_ptr so we don't leak on error. |
492 scoped_ptr<NSSKeyPair> keypair(new NSSKeyPair(privkey, pubkey)); | 548 scoped_ptr<NSSKeyPair> keypair(new NSSKeyPair(privkey, pubkey, ssl_kea_type)); |
493 | 549 |
494 scoped_ptr<NSSCertificate> cert(NSSCertificate::FromPEMString(certificate)); | 550 scoped_ptr<NSSCertificate> cert(NSSCertificate::FromPEMString(certificate)); |
495 if (!cert) { | 551 if (!cert) { |
496 LOG(LS_ERROR) << "Couldn't parse certificate"; | 552 LOG(LS_ERROR) << "Couldn't parse certificate"; |
497 return NULL; | 553 return nullptr; |
498 } | 554 } |
499 | 555 |
500 // TODO(ekr@rtfm.com): Check the public key against the certificate. | 556 // TODO(ekr@rtfm.com): Check the public key against the certificate. |
501 | |
502 return new NSSIdentity(keypair.release(), cert.release()); | 557 return new NSSIdentity(keypair.release(), cert.release()); |
503 } | 558 } |
504 | 559 |
505 NSSIdentity::~NSSIdentity() { | 560 NSSIdentity::~NSSIdentity() { |
506 LOG(LS_INFO) << "Destroying NSS identity"; | 561 LOG(LS_INFO) << "Destroying NSS identity"; |
507 } | 562 } |
508 | 563 |
509 NSSIdentity *NSSIdentity::GetReference() const { | 564 NSSIdentity* NSSIdentity::GetReference() const { |
510 NSSKeyPair *keypair = keypair_->GetReference(); | 565 NSSKeyPair* keypair = keypair_->GetReference(); |
511 if (!keypair) | 566 if (!keypair) |
512 return NULL; | 567 return nullptr; |
513 | 568 |
514 NSSCertificate *certificate = certificate_->GetReference(); | 569 NSSCertificate* certificate = certificate_->GetReference(); |
515 if (!certificate) { | 570 if (!certificate) { |
516 delete keypair; | 571 delete keypair; |
517 return NULL; | 572 return nullptr; |
518 } | 573 } |
519 | 574 |
520 return new NSSIdentity(keypair, certificate); | 575 return new NSSIdentity(keypair, certificate); |
521 } | 576 } |
522 | 577 |
523 | 578 |
524 NSSCertificate &NSSIdentity::certificate() const { | 579 NSSCertificate &NSSIdentity::certificate() const { |
525 return *certificate_; | 580 return *certificate_; |
526 } | 581 } |
527 | 582 |
528 | 583 |
529 } // rtc namespace | 584 } // rtc namespace |
530 | 585 |
531 #endif // HAVE_NSS_SSL_H | 586 #endif // HAVE_NSS_SSL_H |
532 | |
OLD | NEW |