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 13 matching lines...) Expand all Loading... |
24 #include "cryptohi.h" | 24 #include "cryptohi.h" |
25 #include "keyhi.h" | 25 #include "keyhi.h" |
26 #include "nss.h" | 26 #include "nss.h" |
27 #include "pk11pub.h" | 27 #include "pk11pub.h" |
28 #include "sechash.h" | 28 #include "sechash.h" |
29 | 29 |
30 #include "webrtc/base/logging.h" | 30 #include "webrtc/base/logging.h" |
31 #include "webrtc/base/helpers.h" | 31 #include "webrtc/base/helpers.h" |
32 #include "webrtc/base/nssstreamadapter.h" | 32 #include "webrtc/base/nssstreamadapter.h" |
33 #include "webrtc/base/safe_conversions.h" | 33 #include "webrtc/base/safe_conversions.h" |
| 34 #include "webrtc/base/stringutils.h" |
34 | 35 |
35 namespace rtc { | 36 namespace rtc { |
36 | 37 |
37 // Certificate validity lifetime in seconds. | 38 // Certificate validity lifetime in seconds. |
38 static const int CERTIFICATE_LIFETIME = 60*60*24*30; // 30 days, arbitrarily | 39 static const int CERTIFICATE_LIFETIME = 60*60*24*30; // 30 days, arbitrarily |
39 // Certificate validity window in seconds. | 40 // Certificate validity window in seconds. |
40 // This is to compensate for slightly incorrect system clocks. | 41 // This is to compensate for slightly incorrect system clocks. |
41 static const int CERTIFICATE_WINDOW = -60*60*24; | 42 static const int CERTIFICATE_WINDOW = -60*60*24; |
42 | 43 |
43 NSSKeyPair::~NSSKeyPair() { | 44 NSSKeyPair::~NSSKeyPair() { |
44 if (privkey_) | 45 if (privkey_) |
45 SECKEY_DestroyPrivateKey(privkey_); | 46 SECKEY_DestroyPrivateKey(privkey_); |
46 if (pubkey_) | 47 if (pubkey_) |
47 SECKEY_DestroyPublicKey(pubkey_); | 48 SECKEY_DestroyPublicKey(pubkey_); |
48 } | 49 } |
49 | 50 |
50 NSSKeyPair *NSSKeyPair::Generate() { | 51 NSSKeyPair* NSSKeyPair::Generate(KeyType key_type) { |
51 SECKEYPrivateKey *privkey = NULL; | 52 SECKEYPrivateKey* privkey = nullptr; |
52 SECKEYPublicKey *pubkey = NULL; | 53 SECKEYPublicKey* pubkey = nullptr; |
53 PK11RSAGenParams rsaparams; | 54 SSLKEAType ssl_kea_type; |
54 rsaparams.keySizeInBits = 1024; | 55 if (key_type == KT_RSA) { |
55 rsaparams.pe = 0x010001; // 65537 -- a common RSA public exponent. | 56 PK11RSAGenParams rsa_params; |
| 57 rsa_params.keySizeInBits = 1024; |
| 58 rsa_params.pe = 0x010001; // 65537 -- a common RSA public exponent. |
56 | 59 |
57 privkey = PK11_GenerateKeyPair(NSSContext::GetSlot(), | 60 privkey = PK11_GenerateKeyPair( |
58 CKM_RSA_PKCS_KEY_PAIR_GEN, | 61 NSSContext::GetSlot(), CKM_RSA_PKCS_KEY_PAIR_GEN, &rsa_params, &pubkey, |
59 &rsaparams, &pubkey, PR_FALSE /*permanent*/, | 62 PR_FALSE /*permanent*/, PR_FALSE /*sensitive*/, nullptr); |
60 PR_FALSE /*sensitive*/, NULL); | 63 |
61 if (!privkey) { | 64 ssl_kea_type = ssl_kea_rsa; |
62 LOG(LS_ERROR) << "Couldn't generate key pair"; | 65 } else if (key_type == KT_ECDSA) { |
63 return NULL; | 66 unsigned char param_buf[12]; // OIDs are small |
| 67 SECItem ecdsa_params = {siBuffer, param_buf, sizeof(param_buf)}; |
| 68 SECOidData* oid_data = SECOID_FindOIDByTag(SEC_OID_SECG_EC_SECP256R1); |
| 69 if (!oid_data || oid_data->oid.len > sizeof(param_buf) - 2) { |
| 70 LOG(LS_ERROR) << "oid_data incorrect: " << oid_data->oid.len; |
| 71 return nullptr; |
| 72 } |
| 73 ecdsa_params.data[0] = SEC_ASN1_OBJECT_ID; |
| 74 ecdsa_params.data[1] = oid_data->oid.len; |
| 75 memcpy(ecdsa_params.data + 2, oid_data->oid.data, oid_data->oid.len); |
| 76 ecdsa_params.len = oid_data->oid.len + 2; |
| 77 |
| 78 privkey = PK11_GenerateKeyPair( |
| 79 NSSContext::GetSlot(), CKM_EC_KEY_PAIR_GEN, &ecdsa_params, &pubkey, |
| 80 PR_FALSE /*permanent*/, PR_FALSE /*sensitive*/, nullptr); |
| 81 |
| 82 ssl_kea_type = ssl_kea_ecdh; |
| 83 } else { |
| 84 LOG(LS_ERROR) << "Key type requested not understood"; |
| 85 return nullptr; |
64 } | 86 } |
65 | 87 |
66 return new NSSKeyPair(privkey, pubkey); | 88 if (!privkey) { |
| 89 LOG(LS_ERROR) << "Couldn't generate key pair: " << PORT_GetError(); |
| 90 return nullptr; |
| 91 } |
| 92 |
| 93 return new NSSKeyPair(privkey, pubkey, ssl_kea_type); |
67 } | 94 } |
68 | 95 |
69 // Just make a copy. | 96 // Just make a copy. |
70 NSSKeyPair *NSSKeyPair::GetReference() { | 97 NSSKeyPair* NSSKeyPair::GetReference() { |
71 SECKEYPrivateKey *privkey = SECKEY_CopyPrivateKey(privkey_); | 98 SECKEYPrivateKey* privkey = SECKEY_CopyPrivateKey(privkey_); |
72 if (!privkey) | 99 if (!privkey) |
73 return NULL; | 100 return nullptr; |
74 | 101 |
75 SECKEYPublicKey *pubkey = SECKEY_CopyPublicKey(pubkey_); | 102 SECKEYPublicKey* pubkey = SECKEY_CopyPublicKey(pubkey_); |
76 if (!pubkey) { | 103 if (!pubkey) { |
77 SECKEY_DestroyPrivateKey(privkey); | 104 SECKEY_DestroyPrivateKey(privkey); |
78 return NULL; | 105 return nullptr; |
79 } | 106 } |
80 | 107 |
81 return new NSSKeyPair(privkey, pubkey); | 108 return new NSSKeyPair(privkey, pubkey, ssl_kea_type_); |
82 } | 109 } |
83 | 110 |
84 NSSCertificate::NSSCertificate(CERTCertificate* cert) | 111 NSSCertificate::NSSCertificate(CERTCertificate* cert) |
85 : certificate_(CERT_DupCertificate(cert)) { | 112 : certificate_(CERT_DupCertificate(cert)) { |
86 ASSERT(certificate_ != NULL); | 113 ASSERT(certificate_ != nullptr); |
87 } | 114 } |
88 | 115 |
89 static void DeleteCert(SSLCertificate* cert) { | 116 static void DeleteCert(SSLCertificate* cert) { |
90 delete cert; | 117 delete cert; |
91 } | 118 } |
92 | 119 |
93 NSSCertificate::NSSCertificate(CERTCertList* cert_list) { | 120 NSSCertificate::NSSCertificate(CERTCertList* cert_list) { |
94 // Copy the first cert into certificate_. | 121 // Copy the first cert into certificate_. |
95 CERTCertListNode* node = CERT_LIST_HEAD(cert_list); | 122 CERTCertListNode* node = CERT_LIST_HEAD(cert_list); |
96 certificate_ = CERT_DupCertificate(node->cert); | 123 certificate_ = CERT_DupCertificate(node->cert); |
97 | 124 |
98 // Put any remaining certificates into the chain. | 125 // Put any remaining certificates into the chain. |
99 node = CERT_LIST_NEXT(node); | 126 node = CERT_LIST_NEXT(node); |
100 std::vector<SSLCertificate*> certs; | 127 std::vector<SSLCertificate*> certs; |
101 for (; !CERT_LIST_END(node, cert_list); node = CERT_LIST_NEXT(node)) { | 128 for (; !CERT_LIST_END(node, cert_list); node = CERT_LIST_NEXT(node)) { |
102 certs.push_back(new NSSCertificate(node->cert)); | 129 certs.push_back(new NSSCertificate(node->cert)); |
103 } | 130 } |
104 | 131 |
105 if (!certs.empty()) | 132 if (!certs.empty()) |
106 chain_.reset(new SSLCertChain(certs)); | 133 chain_.reset(new SSLCertChain(certs)); |
107 | 134 |
108 // The SSLCertChain constructor copies its input, so now we have to delete | 135 // The SSLCertChain constructor copies its input, so now we have to delete |
109 // the originals. | 136 // the originals. |
110 std::for_each(certs.begin(), certs.end(), DeleteCert); | 137 std::for_each(certs.begin(), certs.end(), DeleteCert); |
111 } | 138 } |
112 | 139 |
113 NSSCertificate::NSSCertificate(CERTCertificate* cert, SSLCertChain* chain) | 140 NSSCertificate::NSSCertificate(CERTCertificate* cert, SSLCertChain* chain) |
114 : certificate_(CERT_DupCertificate(cert)) { | 141 : certificate_(CERT_DupCertificate(cert)) { |
115 ASSERT(certificate_ != NULL); | 142 ASSERT(certificate_ != nullptr); |
116 if (chain) | 143 if (chain) |
117 chain_.reset(chain->Copy()); | 144 chain_.reset(chain->Copy()); |
118 } | 145 } |
119 | 146 |
120 NSSCertificate::~NSSCertificate() { | 147 NSSCertificate::~NSSCertificate() { |
121 if (certificate_) | 148 if (certificate_) |
122 CERT_DestroyCertificate(certificate_); | 149 CERT_DestroyCertificate(certificate_); |
123 } | 150 } |
124 | 151 |
125 NSSCertificate *NSSCertificate::FromPEMString(const std::string &pem_string) { | 152 NSSCertificate* NSSCertificate::FromPEMString(const std::string& pem_string) { |
126 std::string der; | 153 std::string der; |
127 if (!SSLIdentity::PemToDer(kPemTypeCertificate, pem_string, &der)) | 154 if (!SSLIdentity::PemToDer(kPemTypeCertificate, pem_string, &der)) |
128 return NULL; | 155 return nullptr; |
129 | 156 |
130 SECItem der_cert; | 157 SECItem der_cert; |
131 der_cert.data = reinterpret_cast<unsigned char *>(const_cast<char *>( | 158 der_cert.data = reinterpret_cast<unsigned char *>(const_cast<char *>( |
132 der.data())); | 159 der.data())); |
133 der_cert.len = checked_cast<unsigned int>(der.size()); | 160 der_cert.len = checked_cast<unsigned int>(der.size()); |
134 CERTCertificate *cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), | 161 CERTCertificate* cert = CERT_NewTempCertificate( |
135 &der_cert, NULL, PR_FALSE, PR_TRUE); | 162 CERT_GetDefaultCertDB(), &der_cert, nullptr, PR_FALSE, PR_TRUE); |
136 | 163 |
137 if (!cert) | 164 if (!cert) |
138 return NULL; | 165 return nullptr; |
139 | 166 |
140 NSSCertificate* ret = new NSSCertificate(cert); | 167 NSSCertificate* ret = new NSSCertificate(cert); |
141 CERT_DestroyCertificate(cert); | 168 CERT_DestroyCertificate(cert); |
142 return ret; | 169 return ret; |
143 } | 170 } |
144 | 171 |
145 NSSCertificate *NSSCertificate::GetReference() const { | 172 NSSCertificate* NSSCertificate::GetReference() const { |
146 return new NSSCertificate(certificate_, chain_.get()); | 173 return new NSSCertificate(certificate_, chain_.get()); |
147 } | 174 } |
148 | 175 |
149 std::string NSSCertificate::ToPEMString() const { | 176 std::string NSSCertificate::ToPEMString() const { |
150 return SSLIdentity::DerToPem(kPemTypeCertificate, | 177 return SSLIdentity::DerToPem(kPemTypeCertificate, |
151 certificate_->derCert.data, | 178 certificate_->derCert.data, |
152 certificate_->derCert.len); | 179 certificate_->derCert.len); |
153 } | 180 } |
154 | 181 |
155 void NSSCertificate::ToDER(Buffer* der_buffer) const { | 182 void NSSCertificate::ToDER(Buffer* der_buffer) const { |
(...skipping 17 matching lines...) Expand all Loading... |
173 return false; | 200 return false; |
174 | 201 |
175 // Extract the parent's public key, or fail if the key could not be read | 202 // Extract the parent's public key, or fail if the key could not be read |
176 // (e.g. certificate is corrupted). | 203 // (e.g. certificate is corrupted). |
177 SECKEYPublicKey* parent_key = CERT_ExtractPublicKey(parent); | 204 SECKEYPublicKey* parent_key = CERT_ExtractPublicKey(parent); |
178 if (!parent_key) | 205 if (!parent_key) |
179 return false; | 206 return false; |
180 | 207 |
181 // Check that the parent's privkey was actually used to generate the child's | 208 // Check that the parent's privkey was actually used to generate the child's |
182 // signature. | 209 // signature. |
183 SECStatus verified = CERT_VerifySignedDataWithPublicKey( | 210 SECStatus verified = CERT_VerifySignedDataWithPublicKey(&child->signatureWrap, |
184 &child->signatureWrap, parent_key, NULL); | 211 parent_key, nullptr); |
185 SECKEY_DestroyPublicKey(parent_key); | 212 SECKEY_DestroyPublicKey(parent_key); |
186 return verified == SECSuccess; | 213 return verified == SECSuccess; |
187 } | 214 } |
188 | 215 |
189 bool NSSCertificate::IsValidChain(const CERTCertList* cert_list) { | 216 bool NSSCertificate::IsValidChain(const CERTCertList* cert_list) { |
190 CERTCertListNode* child = CERT_LIST_HEAD(cert_list); | 217 CERTCertListNode* child = CERT_LIST_HEAD(cert_list); |
191 for (CERTCertListNode* parent = CERT_LIST_NEXT(child); | 218 for (CERTCertListNode* parent = CERT_LIST_NEXT(child); |
192 !CERT_LIST_END(parent, cert_list); | 219 !CERT_LIST_END(parent, cert_list); |
193 child = parent, parent = CERT_LIST_NEXT(parent)) { | 220 child = parent, parent = CERT_LIST_NEXT(parent)) { |
194 if (!Certifies(parent->cert, child->cert)) | 221 if (!Certifies(parent->cert, child->cert)) |
195 return false; | 222 return false; |
196 } | 223 } |
197 return true; | 224 return true; |
198 } | 225 } |
199 | 226 |
200 bool NSSCertificate::GetDigestLength(const std::string& algorithm, | 227 bool NSSCertificate::GetDigestLength(const std::string& algorithm, |
201 size_t* length) { | 228 size_t* length) { |
202 const SECHashObject *ho; | 229 const SECHashObject* ho = nullptr; |
203 | 230 |
204 if (!GetDigestObject(algorithm, &ho)) | 231 if (!GetDigestObject(algorithm, &ho)) |
205 return false; | 232 return false; |
206 | 233 |
207 *length = ho->length; | 234 *length = ho->length; |
208 | 235 |
209 return true; | 236 return true; |
210 } | 237 } |
211 | 238 |
212 bool NSSCertificate::GetSignatureDigestAlgorithm(std::string* algorithm) const { | 239 bool NSSCertificate::GetSignatureDigestAlgorithm(std::string* algorithm) const { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
254 algorithm->clear(); | 281 algorithm->clear(); |
255 return false; | 282 return false; |
256 } | 283 } |
257 return true; | 284 return true; |
258 } | 285 } |
259 | 286 |
260 bool NSSCertificate::ComputeDigest(const std::string& algorithm, | 287 bool NSSCertificate::ComputeDigest(const std::string& algorithm, |
261 unsigned char* digest, | 288 unsigned char* digest, |
262 size_t size, | 289 size_t size, |
263 size_t* length) const { | 290 size_t* length) const { |
264 const SECHashObject *ho; | 291 const SECHashObject* ho = nullptr; |
265 | 292 |
266 if (!GetDigestObject(algorithm, &ho)) | 293 if (!GetDigestObject(algorithm, &ho)) |
267 return false; | 294 return false; |
268 | 295 |
269 if (size < ho->length) // Sanity check for fit | 296 if (size < ho->length) // Sanity check for fit |
270 return false; | 297 return false; |
271 | 298 |
272 SECStatus rv = HASH_HashBuf(ho->type, digest, | 299 SECStatus rv = HASH_HashBuf(ho->type, digest, |
273 certificate_->derCert.data, | 300 certificate_->derCert.data, |
274 certificate_->derCert.len); | 301 certificate_->derCert.len); |
275 if (rv != SECSuccess) | 302 if (rv != SECSuccess) |
276 return false; | 303 return false; |
277 | 304 |
278 *length = ho->length; | 305 *length = ho->length; |
279 | 306 |
280 return true; | 307 return true; |
281 } | 308 } |
282 | 309 |
283 bool NSSCertificate::GetChain(SSLCertChain** chain) const { | 310 bool NSSCertificate::GetChain(SSLCertChain** chain) const { |
284 if (!chain_) | 311 if (!chain_) |
285 return false; | 312 return false; |
286 | 313 |
287 *chain = chain_->Copy(); | 314 *chain = chain_->Copy(); |
288 return true; | 315 return true; |
289 } | 316 } |
290 | 317 |
291 bool NSSCertificate::Equals(const NSSCertificate *tocompare) const { | 318 bool NSSCertificate::Equals(const NSSCertificate* tocompare) const { |
292 if (!certificate_->derCert.len) | 319 if (!certificate_->derCert.len) |
293 return false; | 320 return false; |
294 if (!tocompare->certificate_->derCert.len) | 321 if (!tocompare->certificate_->derCert.len) |
295 return false; | 322 return false; |
296 | 323 |
297 if (certificate_->derCert.len != tocompare->certificate_->derCert.len) | 324 if (certificate_->derCert.len != tocompare->certificate_->derCert.len) |
298 return false; | 325 return false; |
299 | 326 |
300 return memcmp(certificate_->derCert.data, | 327 return memcmp(certificate_->derCert.data, |
301 tocompare->certificate_->derCert.data, | 328 tocompare->certificate_->derCert.data, |
302 certificate_->derCert.len) == 0; | 329 certificate_->derCert.len) == 0; |
303 } | 330 } |
304 | 331 |
305 | 332 bool NSSCertificate::GetDigestObject(const std::string& algorithm, |
306 bool NSSCertificate::GetDigestObject(const std::string &algorithm, | 333 const SECHashObject** hop) { |
307 const SECHashObject **hop) { | 334 const SECHashObject* ho; |
308 const SECHashObject *ho; | |
309 HASH_HashType hash_type; | 335 HASH_HashType hash_type; |
310 | 336 |
311 if (algorithm == DIGEST_SHA_1) { | 337 if (algorithm == DIGEST_SHA_1) { |
312 hash_type = HASH_AlgSHA1; | 338 hash_type = HASH_AlgSHA1; |
313 // HASH_AlgSHA224 is not supported in the chromium linux build system. | 339 // HASH_AlgSHA224 is not supported in the chromium linux build system. |
314 #if 0 | 340 #if 0 |
315 } else if (algorithm == DIGEST_SHA_224) { | 341 } else if (algorithm == DIGEST_SHA_224) { |
316 hash_type = HASH_AlgSHA224; | 342 hash_type = HASH_AlgSHA224; |
317 #endif | 343 #endif |
318 } else if (algorithm == DIGEST_SHA_256) { | 344 } else if (algorithm == DIGEST_SHA_256) { |
(...skipping 13 matching lines...) Expand all Loading... |
332 | 358 |
333 return true; | 359 return true; |
334 } | 360 } |
335 | 361 |
336 NSSIdentity::NSSIdentity(NSSKeyPair* keypair, NSSCertificate* cert) | 362 NSSIdentity::NSSIdentity(NSSKeyPair* keypair, NSSCertificate* cert) |
337 : keypair_(keypair), certificate_(cert) { | 363 : keypair_(keypair), certificate_(cert) { |
338 } | 364 } |
339 | 365 |
340 NSSIdentity* NSSIdentity::GenerateInternal(const SSLIdentityParams& params) { | 366 NSSIdentity* NSSIdentity::GenerateInternal(const SSLIdentityParams& params) { |
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(params.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 SECOidTag sec_oid; |
409 SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION, NULL); | 435 if (params.key_type == KT_RSA) { |
410 if (rv != SECSuccess) | 436 sec_oid = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION; |
| 437 } else if (params.key_type == KT_ECDSA) { |
| 438 sec_oid = SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE; |
| 439 } else { |
| 440 // We should not arrive here since NSSKeyPair::Generate would have failed. |
| 441 // Play it safe in order to accomodate code changes. |
| 442 LOG(LS_ERROR) << "Key type requested not understood"; |
411 goto fail; | 443 goto fail; |
| 444 } |
| 445 |
| 446 rv = SECOID_SetAlgorithmID(arena, &certificate->signature, sec_oid, nullptr); |
| 447 if (rv != SECSuccess) { |
| 448 LOG(LS_ERROR) << "Couldn't set hashing algorithm"; |
| 449 goto fail; |
| 450 } |
412 | 451 |
413 // Set version to X509v3. | 452 // Set version to X509v3. |
414 *(certificate->version.data) = 2; | 453 *(certificate->version.data) = 2; |
415 certificate->version.len = 1; | 454 certificate->version.len = 1; |
416 | 455 |
417 if (!SEC_ASN1EncodeItem(arena, &inner_der, certificate, | 456 if (!SEC_ASN1EncodeItem(arena, &inner_der, certificate, |
418 SEC_ASN1_GET(CERT_CertificateTemplate))) | 457 SEC_ASN1_GET(CERT_CertificateTemplate))) { |
| 458 LOG(LS_ERROR) << "Couldn't encode certificate"; |
419 goto fail; | 459 goto fail; |
| 460 } |
420 | 461 |
421 rv = SEC_DerSignData(arena, &signed_cert, inner_der.data, inner_der.len, | 462 rv = SEC_DerSignData(arena, &signed_cert, inner_der.data, inner_der.len, |
422 keypair->privkey(), | 463 keypair->privkey(), sec_oid); |
423 SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION); | |
424 if (rv != SECSuccess) { | 464 if (rv != SECSuccess) { |
425 LOG(LS_ERROR) << "Couldn't sign certificate"; | 465 LOG(LS_ERROR) << "Couldn't sign certificate"; |
426 goto fail; | 466 goto fail; |
427 } | 467 } |
428 certificate->derCert = signed_cert; | 468 certificate->derCert = signed_cert; |
429 | 469 |
430 identity = new NSSIdentity(keypair, new NSSCertificate(certificate)); | 470 identity = new NSSIdentity(keypair, new NSSCertificate(certificate)); |
431 | 471 |
432 goto done; | 472 goto done; |
433 | 473 |
434 fail: | 474 fail: |
435 delete keypair; | 475 delete keypair; |
436 | 476 |
437 done: | 477 done: |
438 if (certificate) CERT_DestroyCertificate(certificate); | 478 if (certificate) CERT_DestroyCertificate(certificate); |
439 if (subject_name) CERT_DestroyName(subject_name); | 479 if (subject_name) CERT_DestroyName(subject_name); |
440 if (spki) SECKEY_DestroySubjectPublicKeyInfo(spki); | 480 if (spki) SECKEY_DestroySubjectPublicKeyInfo(spki); |
441 if (certreq) CERT_DestroyCertificateRequest(certreq); | 481 if (certreq) CERT_DestroyCertificateRequest(certreq); |
442 if (validity) CERT_DestroyValidity(validity); | 482 if (validity) CERT_DestroyValidity(validity); |
443 return identity; | 483 return identity; |
444 } | 484 } |
445 | 485 |
446 NSSIdentity* NSSIdentity::Generate(const std::string &common_name) { | 486 NSSIdentity* NSSIdentity::Generate(const std::string& common_name, |
| 487 KeyType key_type) { |
447 SSLIdentityParams params; | 488 SSLIdentityParams params; |
448 params.common_name = common_name; | 489 params.common_name = common_name; |
449 params.not_before = CERTIFICATE_WINDOW; | 490 params.not_before = CERTIFICATE_WINDOW; |
450 params.not_after = CERTIFICATE_LIFETIME; | 491 params.not_after = CERTIFICATE_LIFETIME; |
| 492 params.key_type = key_type; |
451 return GenerateInternal(params); | 493 return GenerateInternal(params); |
452 } | 494 } |
453 | 495 |
454 NSSIdentity* NSSIdentity::GenerateForTest(const SSLIdentityParams& params) { | 496 NSSIdentity* NSSIdentity::GenerateForTest(const SSLIdentityParams& params) { |
455 return GenerateInternal(params); | 497 return GenerateInternal(params); |
456 } | 498 } |
457 | 499 |
458 SSLIdentity* NSSIdentity::FromPEMStrings(const std::string& private_key, | 500 SSLIdentity* NSSIdentity::FromPEMStrings(const std::string& private_key, |
459 const std::string& certificate) { | 501 const std::string& certificate) { |
460 std::string private_key_der; | 502 std::string private_key_der; |
461 if (!SSLIdentity::PemToDer( | 503 if (!SSLIdentity::PemToDer( |
462 kPemTypeRsaPrivateKey, private_key, &private_key_der)) | 504 kPemTypeRsaPrivateKey, private_key, &private_key_der)) |
463 return NULL; | 505 return nullptr; |
464 | 506 |
465 SECItem private_key_item; | 507 SECItem private_key_item; |
466 private_key_item.data = reinterpret_cast<unsigned char *>( | 508 private_key_item.data = reinterpret_cast<unsigned char *>( |
467 const_cast<char *>(private_key_der.c_str())); | 509 const_cast<char *>(private_key_der.c_str())); |
468 private_key_item.len = checked_cast<unsigned int>(private_key_der.size()); | 510 private_key_item.len = checked_cast<unsigned int>(private_key_der.size()); |
469 | 511 |
470 const unsigned int key_usage = KU_KEY_ENCIPHERMENT | KU_DATA_ENCIPHERMENT | | 512 const unsigned int key_usage = KU_KEY_ENCIPHERMENT | KU_DATA_ENCIPHERMENT | |
471 KU_DIGITAL_SIGNATURE; | 513 KU_DIGITAL_SIGNATURE; |
472 | 514 |
473 SECKEYPrivateKey* privkey = NULL; | 515 SECKEYPrivateKey* privkey = nullptr; |
474 SECStatus rv = | 516 SECStatus rv = PK11_ImportDERPrivateKeyInfoAndReturnKey( |
475 PK11_ImportDERPrivateKeyInfoAndReturnKey(NSSContext::GetSlot(), | 517 NSSContext::GetSlot(), &private_key_item, nullptr, nullptr, PR_FALSE, |
476 &private_key_item, | 518 PR_FALSE, key_usage, &privkey, nullptr); |
477 NULL, NULL, PR_FALSE, PR_FALSE, | |
478 key_usage, &privkey, NULL); | |
479 if (rv != SECSuccess) { | 519 if (rv != SECSuccess) { |
480 LOG(LS_ERROR) << "Couldn't import private key"; | 520 LOG(LS_ERROR) << "Couldn't import private key"; |
481 return NULL; | 521 return nullptr; |
482 } | 522 } |
483 | 523 |
484 SECKEYPublicKey *pubkey = SECKEY_ConvertToPublicKey(privkey); | 524 SECKEYPublicKey* pubkey = SECKEY_ConvertToPublicKey(privkey); |
485 if (rv != SECSuccess) { | 525 if (rv != SECSuccess) { |
486 SECKEY_DestroyPrivateKey(privkey); | 526 SECKEY_DestroyPrivateKey(privkey); |
487 LOG(LS_ERROR) << "Couldn't convert private key to public key"; | 527 LOG(LS_ERROR) << "Couldn't convert private key to public key"; |
488 return NULL; | 528 return nullptr; |
| 529 } |
| 530 |
| 531 SSLKEAType ssl_kea_type; |
| 532 if (rtc::starts_with(private_key.c_str(), |
| 533 "-----BEGIN RSA PRIVATE KEY-----")) { |
| 534 ssl_kea_type = ssl_kea_rsa; |
| 535 } else { |
| 536 // We might want to check more key types here. But since we're moving to |
| 537 // Open/BoringSSL, don't bother. Besides, this will likely be correct for |
| 538 // any future key type, causing a test to do more harm than good. |
| 539 ssl_kea_type = ssl_kea_ecdh; |
489 } | 540 } |
490 | 541 |
491 // Assign to a scoped_ptr so we don't leak on error. | 542 // Assign to a scoped_ptr so we don't leak on error. |
492 scoped_ptr<NSSKeyPair> keypair(new NSSKeyPair(privkey, pubkey)); | 543 scoped_ptr<NSSKeyPair> keypair(new NSSKeyPair(privkey, pubkey, ssl_kea_type)); |
493 | 544 |
494 scoped_ptr<NSSCertificate> cert(NSSCertificate::FromPEMString(certificate)); | 545 scoped_ptr<NSSCertificate> cert(NSSCertificate::FromPEMString(certificate)); |
495 if (!cert) { | 546 if (!cert) { |
496 LOG(LS_ERROR) << "Couldn't parse certificate"; | 547 LOG(LS_ERROR) << "Couldn't parse certificate"; |
497 return NULL; | 548 return nullptr; |
498 } | 549 } |
499 | 550 |
500 // TODO(ekr@rtfm.com): Check the public key against the certificate. | 551 // TODO(ekr@rtfm.com): Check the public key against the certificate. |
501 | |
502 return new NSSIdentity(keypair.release(), cert.release()); | 552 return new NSSIdentity(keypair.release(), cert.release()); |
503 } | 553 } |
504 | 554 |
505 NSSIdentity::~NSSIdentity() { | 555 NSSIdentity::~NSSIdentity() { |
506 LOG(LS_INFO) << "Destroying NSS identity"; | 556 LOG(LS_INFO) << "Destroying NSS identity"; |
507 } | 557 } |
508 | 558 |
509 NSSIdentity *NSSIdentity::GetReference() const { | 559 NSSIdentity* NSSIdentity::GetReference() const { |
510 NSSKeyPair *keypair = keypair_->GetReference(); | 560 NSSKeyPair* keypair = keypair_->GetReference(); |
511 if (!keypair) | 561 if (!keypair) |
512 return NULL; | 562 return nullptr; |
513 | 563 |
514 NSSCertificate *certificate = certificate_->GetReference(); | 564 NSSCertificate* certificate = certificate_->GetReference(); |
515 if (!certificate) { | 565 if (!certificate) { |
516 delete keypair; | 566 delete keypair; |
517 return NULL; | 567 return nullptr; |
518 } | 568 } |
519 | 569 |
520 return new NSSIdentity(keypair, certificate); | 570 return new NSSIdentity(keypair, certificate); |
521 } | 571 } |
522 | 572 |
523 | 573 |
524 NSSCertificate &NSSIdentity::certificate() const { | 574 NSSCertificate &NSSIdentity::certificate() const { |
525 return *certificate_; | 575 return *certificate_; |
526 } | 576 } |
527 | 577 |
528 | 578 |
529 } // rtc namespace | 579 } // rtc namespace |
530 | 580 |
531 #endif // HAVE_NSS_SSL_H | 581 #endif // HAVE_NSS_SSL_H |
532 | |
OLD | NEW |