| 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 11 matching lines...) Expand all Loading... |
| 330 ASSERT(ho->length >= 20); // Can't happen | 356 ASSERT(ho->length >= 20); // Can't happen |
| 331 *hop = ho; | 357 *hop = ho; |
| 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, |
| 367 KeyType key_type) { |
| 341 std::string subject_name_string = "CN=" + params.common_name; | 368 std::string subject_name_string = "CN=" + params.common_name; |
| 342 CERTName *subject_name = CERT_AsciiToName( | 369 CERTName* subject_name = |
| 343 const_cast<char *>(subject_name_string.c_str())); | 370 CERT_AsciiToName(const_cast<char*>(subject_name_string.c_str())); |
| 344 NSSIdentity *identity = NULL; | 371 NSSIdentity* identity = nullptr; |
| 345 CERTSubjectPublicKeyInfo *spki = NULL; | 372 CERTSubjectPublicKeyInfo* spki = nullptr; |
| 346 CERTCertificateRequest *certreq = NULL; | 373 CERTCertificateRequest* certreq = nullptr; |
| 347 CERTValidity *validity = NULL; | 374 CERTValidity* validity = nullptr; |
| 348 CERTCertificate *certificate = NULL; | 375 CERTCertificate* certificate = nullptr; |
| 349 NSSKeyPair *keypair = NSSKeyPair::Generate(); | 376 NSSKeyPair* keypair = NSSKeyPair::Generate(key_type); |
| 350 SECItem inner_der; | 377 SECItem inner_der; |
| 351 SECStatus rv; | 378 SECStatus rv; |
| 352 PLArenaPool* arena; | 379 PLArenaPool* arena; |
| 353 SECItem signed_cert; | 380 SECItem signed_cert; |
| 354 PRTime now = PR_Now(); | 381 PRTime now = PR_Now(); |
| 355 PRTime not_before = | 382 PRTime not_before = |
| 356 now + static_cast<PRTime>(params.not_before) * PR_USEC_PER_SEC; | 383 now + static_cast<PRTime>(params.not_before) * PR_USEC_PER_SEC; |
| 357 PRTime not_after = | 384 PRTime not_after = |
| 358 now + static_cast<PRTime>(params.not_after) * PR_USEC_PER_SEC; | 385 now + static_cast<PRTime>(params.not_after) * PR_USEC_PER_SEC; |
| 359 | 386 |
| 360 inner_der.len = 0; | 387 inner_der.len = 0; |
| 361 inner_der.data = NULL; | 388 inner_der.data = nullptr; |
| 362 | 389 |
| 363 if (!keypair) { | 390 if (!keypair) { |
| 364 LOG(LS_ERROR) << "Couldn't generate key pair"; | 391 LOG(LS_ERROR) << "Couldn't generate key pair"; |
| 365 goto fail; | 392 goto fail; |
| 366 } | 393 } |
| 367 | 394 |
| 368 if (!subject_name) { | 395 if (!subject_name) { |
| 369 LOG(LS_ERROR) << "Couldn't convert subject name " << subject_name; | 396 LOG(LS_ERROR) << "Couldn't convert subject name " << subject_name; |
| 370 goto fail; | 397 goto fail; |
| 371 } | 398 } |
| 372 | 399 |
| 373 spki = SECKEY_CreateSubjectPublicKeyInfo(keypair->pubkey()); | 400 spki = SECKEY_CreateSubjectPublicKeyInfo(keypair->pubkey()); |
| 374 if (!spki) { | 401 if (!spki) { |
| 375 LOG(LS_ERROR) << "Couldn't create SPKI"; | 402 LOG(LS_ERROR) << "Couldn't create SPKI"; |
| 376 goto fail; | 403 goto fail; |
| 377 } | 404 } |
| 378 | 405 |
| 379 certreq = CERT_CreateCertificateRequest(subject_name, spki, NULL); | 406 certreq = CERT_CreateCertificateRequest(subject_name, spki, nullptr); |
| 380 if (!certreq) { | 407 if (!certreq) { |
| 381 LOG(LS_ERROR) << "Couldn't create certificate signing request"; | 408 LOG(LS_ERROR) << "Couldn't create certificate signing request"; |
| 382 goto fail; | 409 goto fail; |
| 383 } | 410 } |
| 384 | 411 |
| 385 validity = CERT_CreateValidity(not_before, not_after); | 412 validity = CERT_CreateValidity(not_before, not_after); |
| 386 if (!validity) { | 413 if (!validity) { |
| 387 LOG(LS_ERROR) << "Couldn't create validity"; | 414 LOG(LS_ERROR) << "Couldn't create validity"; |
| 388 goto fail; | 415 goto fail; |
| 389 } | 416 } |
| 390 | 417 |
| 391 unsigned long serial; | 418 unsigned long serial; |
| 392 // Note: This serial in principle could collide, but it's unlikely | 419 // Note: This serial in principle could collide, but it's unlikely |
| 393 rv = PK11_GenerateRandom(reinterpret_cast<unsigned char *>(&serial), | 420 rv = PK11_GenerateRandom(reinterpret_cast<unsigned char *>(&serial), |
| 394 sizeof(serial)); | 421 sizeof(serial)); |
| 395 if (rv != SECSuccess) { | 422 if (rv != SECSuccess) { |
| 396 LOG(LS_ERROR) << "Couldn't generate random serial"; | 423 LOG(LS_ERROR) << "Couldn't generate random serial"; |
| 397 goto fail; | 424 goto fail; |
| 398 } | 425 } |
| 399 | 426 |
| 400 certificate = CERT_CreateCertificate(serial, subject_name, validity, certreq); | 427 certificate = CERT_CreateCertificate(serial, subject_name, validity, certreq); |
| 401 if (!certificate) { | 428 if (!certificate) { |
| 402 LOG(LS_ERROR) << "Couldn't create certificate"; | 429 LOG(LS_ERROR) << "Couldn't create certificate"; |
| 403 goto fail; | 430 goto fail; |
| 404 } | 431 } |
| 405 | 432 |
| 406 arena = certificate->arena; | 433 arena = certificate->arena; |
| 407 | 434 |
| 408 rv = SECOID_SetAlgorithmID(arena, &certificate->signature, | 435 SECOidTag sec_oid; |
| 409 SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION, NULL); | 436 if (key_type == KT_RSA) { |
| 410 if (rv != SECSuccess) | 437 sec_oid = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION; |
| 438 } else if (key_type == KT_ECDSA) { |
| 439 sec_oid = SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE; |
| 440 } else { |
| 441 // We should not arrive here since NSSKeyPair::Generate would have failed. |
| 442 // Play it safe in order to accomodate code changes. |
| 443 LOG(LS_ERROR) << "Key type requested not understood"; |
| 411 goto fail; | 444 goto fail; |
| 445 } |
| 446 |
| 447 rv = SECOID_SetAlgorithmID(arena, &certificate->signature, sec_oid, nullptr); |
| 448 if (rv != SECSuccess) { |
| 449 LOG(LS_ERROR) << "Couldn't set hashing algorithm"; |
| 450 goto fail; |
| 451 } |
| 412 | 452 |
| 413 // Set version to X509v3. | 453 // Set version to X509v3. |
| 414 *(certificate->version.data) = 2; | 454 *(certificate->version.data) = 2; |
| 415 certificate->version.len = 1; | 455 certificate->version.len = 1; |
| 416 | 456 |
| 417 if (!SEC_ASN1EncodeItem(arena, &inner_der, certificate, | 457 if (!SEC_ASN1EncodeItem(arena, &inner_der, certificate, |
| 418 SEC_ASN1_GET(CERT_CertificateTemplate))) | 458 SEC_ASN1_GET(CERT_CertificateTemplate))) { |
| 459 LOG(LS_ERROR) << "Couldn't encode certificate"; |
| 419 goto fail; | 460 goto fail; |
| 461 } |
| 420 | 462 |
| 421 rv = SEC_DerSignData(arena, &signed_cert, inner_der.data, inner_der.len, | 463 rv = SEC_DerSignData(arena, &signed_cert, inner_der.data, inner_der.len, |
| 422 keypair->privkey(), | 464 keypair->privkey(), sec_oid); |
| 423 SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION); | |
| 424 if (rv != SECSuccess) { | 465 if (rv != SECSuccess) { |
| 425 LOG(LS_ERROR) << "Couldn't sign certificate"; | 466 LOG(LS_ERROR) << "Couldn't sign certificate"; |
| 426 goto fail; | 467 goto fail; |
| 427 } | 468 } |
| 428 certificate->derCert = signed_cert; | 469 certificate->derCert = signed_cert; |
| 429 | 470 |
| 430 identity = new NSSIdentity(keypair, new NSSCertificate(certificate)); | 471 identity = new NSSIdentity(keypair, new NSSCertificate(certificate)); |
| 431 | 472 |
| 432 goto done; | 473 goto done; |
| 433 | 474 |
| 434 fail: | 475 fail: |
| 435 delete keypair; | 476 delete keypair; |
| 436 | 477 |
| 437 done: | 478 done: |
| 438 if (certificate) CERT_DestroyCertificate(certificate); | 479 if (certificate) CERT_DestroyCertificate(certificate); |
| 439 if (subject_name) CERT_DestroyName(subject_name); | 480 if (subject_name) CERT_DestroyName(subject_name); |
| 440 if (spki) SECKEY_DestroySubjectPublicKeyInfo(spki); | 481 if (spki) SECKEY_DestroySubjectPublicKeyInfo(spki); |
| 441 if (certreq) CERT_DestroyCertificateRequest(certreq); | 482 if (certreq) CERT_DestroyCertificateRequest(certreq); |
| 442 if (validity) CERT_DestroyValidity(validity); | 483 if (validity) CERT_DestroyValidity(validity); |
| 443 return identity; | 484 return identity; |
| 444 } | 485 } |
| 445 | 486 |
| 446 NSSIdentity* NSSIdentity::Generate(const std::string &common_name) { | 487 NSSIdentity* NSSIdentity::Generate(const std::string& common_name, |
| 488 KeyType key_type) { |
| 447 SSLIdentityParams params; | 489 SSLIdentityParams params; |
| 448 params.common_name = common_name; | 490 params.common_name = common_name; |
| 449 params.not_before = CERTIFICATE_WINDOW; | 491 params.not_before = CERTIFICATE_WINDOW; |
| 450 params.not_after = CERTIFICATE_LIFETIME; | 492 params.not_after = CERTIFICATE_LIFETIME; |
| 451 return GenerateInternal(params); | 493 return GenerateInternal(params, key_type); |
| 452 } | 494 } |
| 453 | 495 |
| 454 NSSIdentity* NSSIdentity::GenerateForTest(const SSLIdentityParams& params) { | 496 NSSIdentity* NSSIdentity::GenerateForTest(const SSLIdentityParams& params, |
| 455 return GenerateInternal(params); | 497 KeyType key_type) { |
| 498 return GenerateInternal(params, key_type); |
| 456 } | 499 } |
| 457 | 500 |
| 458 SSLIdentity* NSSIdentity::FromPEMStrings(const std::string& private_key, | 501 SSLIdentity* NSSIdentity::FromPEMStrings(const std::string& private_key, |
| 459 const std::string& certificate) { | 502 const std::string& certificate) { |
| 460 std::string private_key_der; | 503 std::string private_key_der; |
| 461 if (!SSLIdentity::PemToDer( | 504 if (!SSLIdentity::PemToDer( |
| 462 kPemTypeRsaPrivateKey, private_key, &private_key_der)) | 505 kPemTypeRsaPrivateKey, private_key, &private_key_der)) |
| 463 return NULL; | 506 return nullptr; |
| 464 | 507 |
| 465 SECItem private_key_item; | 508 SECItem private_key_item; |
| 466 private_key_item.data = reinterpret_cast<unsigned char *>( | 509 private_key_item.data = reinterpret_cast<unsigned char *>( |
| 467 const_cast<char *>(private_key_der.c_str())); | 510 const_cast<char *>(private_key_der.c_str())); |
| 468 private_key_item.len = checked_cast<unsigned int>(private_key_der.size()); | 511 private_key_item.len = checked_cast<unsigned int>(private_key_der.size()); |
| 469 | 512 |
| 470 const unsigned int key_usage = KU_KEY_ENCIPHERMENT | KU_DATA_ENCIPHERMENT | | 513 const unsigned int key_usage = KU_KEY_ENCIPHERMENT | KU_DATA_ENCIPHERMENT | |
| 471 KU_DIGITAL_SIGNATURE; | 514 KU_DIGITAL_SIGNATURE; |
| 472 | 515 |
| 473 SECKEYPrivateKey* privkey = NULL; | 516 SECKEYPrivateKey* privkey = nullptr; |
| 474 SECStatus rv = | 517 SECStatus rv = PK11_ImportDERPrivateKeyInfoAndReturnKey( |
| 475 PK11_ImportDERPrivateKeyInfoAndReturnKey(NSSContext::GetSlot(), | 518 NSSContext::GetSlot(), &private_key_item, nullptr, nullptr, PR_FALSE, |
| 476 &private_key_item, | 519 PR_FALSE, key_usage, &privkey, nullptr); |
| 477 NULL, NULL, PR_FALSE, PR_FALSE, | |
| 478 key_usage, &privkey, NULL); | |
| 479 if (rv != SECSuccess) { | 520 if (rv != SECSuccess) { |
| 480 LOG(LS_ERROR) << "Couldn't import private key"; | 521 LOG(LS_ERROR) << "Couldn't import private key"; |
| 481 return NULL; | 522 return nullptr; |
| 482 } | 523 } |
| 483 | 524 |
| 484 SECKEYPublicKey *pubkey = SECKEY_ConvertToPublicKey(privkey); | 525 SECKEYPublicKey* pubkey = SECKEY_ConvertToPublicKey(privkey); |
| 485 if (rv != SECSuccess) { | 526 if (rv != SECSuccess) { |
| 486 SECKEY_DestroyPrivateKey(privkey); | 527 SECKEY_DestroyPrivateKey(privkey); |
| 487 LOG(LS_ERROR) << "Couldn't convert private key to public key"; | 528 LOG(LS_ERROR) << "Couldn't convert private key to public key"; |
| 488 return NULL; | 529 return nullptr; |
| 530 } |
| 531 |
| 532 SSLKEAType ssl_kea_type; |
| 533 if (rtc::starts_with(private_key.c_str(), |
| 534 "-----BEGIN RSA PRIVATE KEY-----")) { |
| 535 ssl_kea_type = ssl_kea_rsa; |
| 536 } else { |
| 537 // We might want to check more key types here. But since we're moving to |
| 538 // Open/BoringSSL, don't bother. Besides, this will likely be correct for |
| 539 // any future key type, causing a test to do more harm than good. |
| 540 ssl_kea_type = ssl_kea_ecdh; |
| 489 } | 541 } |
| 490 | 542 |
| 491 // Assign to a scoped_ptr so we don't leak on error. | 543 // Assign to a scoped_ptr so we don't leak on error. |
| 492 scoped_ptr<NSSKeyPair> keypair(new NSSKeyPair(privkey, pubkey)); | 544 scoped_ptr<NSSKeyPair> keypair(new NSSKeyPair(privkey, pubkey, ssl_kea_type)); |
| 493 | 545 |
| 494 scoped_ptr<NSSCertificate> cert(NSSCertificate::FromPEMString(certificate)); | 546 scoped_ptr<NSSCertificate> cert(NSSCertificate::FromPEMString(certificate)); |
| 495 if (!cert) { | 547 if (!cert) { |
| 496 LOG(LS_ERROR) << "Couldn't parse certificate"; | 548 LOG(LS_ERROR) << "Couldn't parse certificate"; |
| 497 return NULL; | 549 return nullptr; |
| 498 } | 550 } |
| 499 | 551 |
| 500 // TODO(ekr@rtfm.com): Check the public key against the certificate. | 552 // TODO(ekr@rtfm.com): Check the public key against the certificate. |
| 501 | |
| 502 return new NSSIdentity(keypair.release(), cert.release()); | 553 return new NSSIdentity(keypair.release(), cert.release()); |
| 503 } | 554 } |
| 504 | 555 |
| 505 NSSIdentity::~NSSIdentity() { | 556 NSSIdentity::~NSSIdentity() { |
| 506 LOG(LS_INFO) << "Destroying NSS identity"; | 557 LOG(LS_INFO) << "Destroying NSS identity"; |
| 507 } | 558 } |
| 508 | 559 |
| 509 NSSIdentity *NSSIdentity::GetReference() const { | 560 NSSIdentity* NSSIdentity::GetReference() const { |
| 510 NSSKeyPair *keypair = keypair_->GetReference(); | 561 NSSKeyPair* keypair = keypair_->GetReference(); |
| 511 if (!keypair) | 562 if (!keypair) |
| 512 return NULL; | 563 return nullptr; |
| 513 | 564 |
| 514 NSSCertificate *certificate = certificate_->GetReference(); | 565 NSSCertificate* certificate = certificate_->GetReference(); |
| 515 if (!certificate) { | 566 if (!certificate) { |
| 516 delete keypair; | 567 delete keypair; |
| 517 return NULL; | 568 return nullptr; |
| 518 } | 569 } |
| 519 | 570 |
| 520 return new NSSIdentity(keypair, certificate); | 571 return new NSSIdentity(keypair, certificate); |
| 521 } | 572 } |
| 522 | 573 |
| 523 | 574 |
| 524 NSSCertificate &NSSIdentity::certificate() const { | 575 NSSCertificate &NSSIdentity::certificate() const { |
| 525 return *certificate_; | 576 return *certificate_; |
| 526 } | 577 } |
| 527 | 578 |
| 528 | 579 |
| 529 } // rtc namespace | 580 } // rtc namespace |
| 530 | 581 |
| 531 #endif // HAVE_NSS_SSL_H | 582 #endif // HAVE_NSS_SSL_H |
| 532 | |
| OLD | NEW |