Support generation of EC keys using P256 curve and support ECDSA certs.
This CL started life here: https://webrtc-codereview.appspot.com/51189004
BUG=webrtc:4685, webrtc:4686
R=hbos@webrtc.org, juberti@webrtc.org
Review URL: https://codereview.webrtc.org/1189583002 .
Cr-Commit-Position: refs/heads/master@{#9718}
diff --git a/webrtc/base/nssidentity.cc b/webrtc/base/nssidentity.cc
index bbcc73e..6511942 100644
--- a/webrtc/base/nssidentity.cc
+++ b/webrtc/base/nssidentity.cc
@@ -31,6 +31,7 @@
#include "webrtc/base/helpers.h"
#include "webrtc/base/nssstreamadapter.h"
#include "webrtc/base/safe_conversions.h"
+#include "webrtc/base/stringutils.h"
namespace rtc {
@@ -47,43 +48,69 @@
SECKEY_DestroyPublicKey(pubkey_);
}
-NSSKeyPair *NSSKeyPair::Generate() {
- SECKEYPrivateKey *privkey = NULL;
- SECKEYPublicKey *pubkey = NULL;
- PK11RSAGenParams rsaparams;
- rsaparams.keySizeInBits = 1024;
- rsaparams.pe = 0x010001; // 65537 -- a common RSA public exponent.
+NSSKeyPair* NSSKeyPair::Generate(KeyType key_type) {
+ SECKEYPrivateKey* privkey = nullptr;
+ SECKEYPublicKey* pubkey = nullptr;
+ SSLKEAType ssl_kea_type;
+ if (key_type == KT_RSA) {
+ PK11RSAGenParams rsa_params;
+ rsa_params.keySizeInBits = 1024;
+ rsa_params.pe = 0x010001; // 65537 -- a common RSA public exponent.
- privkey = PK11_GenerateKeyPair(NSSContext::GetSlot(),
- CKM_RSA_PKCS_KEY_PAIR_GEN,
- &rsaparams, &pubkey, PR_FALSE /*permanent*/,
- PR_FALSE /*sensitive*/, NULL);
- if (!privkey) {
- LOG(LS_ERROR) << "Couldn't generate key pair";
- return NULL;
+ privkey = PK11_GenerateKeyPair(
+ NSSContext::GetSlot(), CKM_RSA_PKCS_KEY_PAIR_GEN, &rsa_params, &pubkey,
+ PR_FALSE /*permanent*/, PR_FALSE /*sensitive*/, nullptr);
+
+ ssl_kea_type = ssl_kea_rsa;
+ } else if (key_type == KT_ECDSA) {
+ unsigned char param_buf[12]; // OIDs are small
+ SECItem ecdsa_params = {siBuffer, param_buf, sizeof(param_buf)};
+ SECOidData* oid_data = SECOID_FindOIDByTag(SEC_OID_SECG_EC_SECP256R1);
+ if (!oid_data || oid_data->oid.len > sizeof(param_buf) - 2) {
+ LOG(LS_ERROR) << "oid_data incorrect: " << oid_data->oid.len;
+ return nullptr;
+ }
+ ecdsa_params.data[0] = SEC_ASN1_OBJECT_ID;
+ ecdsa_params.data[1] = oid_data->oid.len;
+ memcpy(ecdsa_params.data + 2, oid_data->oid.data, oid_data->oid.len);
+ ecdsa_params.len = oid_data->oid.len + 2;
+
+ privkey = PK11_GenerateKeyPair(
+ NSSContext::GetSlot(), CKM_EC_KEY_PAIR_GEN, &ecdsa_params, &pubkey,
+ PR_FALSE /*permanent*/, PR_FALSE /*sensitive*/, nullptr);
+
+ ssl_kea_type = ssl_kea_ecdh;
+ } else {
+ LOG(LS_ERROR) << "Key type requested not understood";
+ return nullptr;
}
- return new NSSKeyPair(privkey, pubkey);
+ if (!privkey) {
+ LOG(LS_ERROR) << "Couldn't generate key pair: " << PORT_GetError();
+ return nullptr;
+ }
+
+ return new NSSKeyPair(privkey, pubkey, ssl_kea_type);
}
// Just make a copy.
-NSSKeyPair *NSSKeyPair::GetReference() {
- SECKEYPrivateKey *privkey = SECKEY_CopyPrivateKey(privkey_);
+NSSKeyPair* NSSKeyPair::GetReference() {
+ SECKEYPrivateKey* privkey = SECKEY_CopyPrivateKey(privkey_);
if (!privkey)
- return NULL;
+ return nullptr;
- SECKEYPublicKey *pubkey = SECKEY_CopyPublicKey(pubkey_);
+ SECKEYPublicKey* pubkey = SECKEY_CopyPublicKey(pubkey_);
if (!pubkey) {
SECKEY_DestroyPrivateKey(privkey);
- return NULL;
+ return nullptr;
}
- return new NSSKeyPair(privkey, pubkey);
+ return new NSSKeyPair(privkey, pubkey, ssl_kea_type_);
}
NSSCertificate::NSSCertificate(CERTCertificate* cert)
: certificate_(CERT_DupCertificate(cert)) {
- ASSERT(certificate_ != NULL);
+ ASSERT(certificate_ != nullptr);
}
static void DeleteCert(SSLCertificate* cert) {
@@ -112,7 +139,7 @@
NSSCertificate::NSSCertificate(CERTCertificate* cert, SSLCertChain* chain)
: certificate_(CERT_DupCertificate(cert)) {
- ASSERT(certificate_ != NULL);
+ ASSERT(certificate_ != nullptr);
if (chain)
chain_.reset(chain->Copy());
}
@@ -122,27 +149,27 @@
CERT_DestroyCertificate(certificate_);
}
-NSSCertificate *NSSCertificate::FromPEMString(const std::string &pem_string) {
+NSSCertificate* NSSCertificate::FromPEMString(const std::string& pem_string) {
std::string der;
if (!SSLIdentity::PemToDer(kPemTypeCertificate, pem_string, &der))
- return NULL;
+ return nullptr;
SECItem der_cert;
der_cert.data = reinterpret_cast<unsigned char *>(const_cast<char *>(
der.data()));
der_cert.len = checked_cast<unsigned int>(der.size());
- CERTCertificate *cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
- &der_cert, NULL, PR_FALSE, PR_TRUE);
+ CERTCertificate* cert = CERT_NewTempCertificate(
+ CERT_GetDefaultCertDB(), &der_cert, nullptr, PR_FALSE, PR_TRUE);
if (!cert)
- return NULL;
+ return nullptr;
NSSCertificate* ret = new NSSCertificate(cert);
CERT_DestroyCertificate(cert);
return ret;
}
-NSSCertificate *NSSCertificate::GetReference() const {
+NSSCertificate* NSSCertificate::GetReference() const {
return new NSSCertificate(certificate_, chain_.get());
}
@@ -180,8 +207,8 @@
// Check that the parent's privkey was actually used to generate the child's
// signature.
- SECStatus verified = CERT_VerifySignedDataWithPublicKey(
- &child->signatureWrap, parent_key, NULL);
+ SECStatus verified = CERT_VerifySignedDataWithPublicKey(&child->signatureWrap,
+ parent_key, nullptr);
SECKEY_DestroyPublicKey(parent_key);
return verified == SECSuccess;
}
@@ -199,7 +226,7 @@
bool NSSCertificate::GetDigestLength(const std::string& algorithm,
size_t* length) {
- const SECHashObject *ho;
+ const SECHashObject* ho = nullptr;
if (!GetDigestObject(algorithm, &ho))
return false;
@@ -261,7 +288,7 @@
unsigned char* digest,
size_t size,
size_t* length) const {
- const SECHashObject *ho;
+ const SECHashObject* ho = nullptr;
if (!GetDigestObject(algorithm, &ho))
return false;
@@ -288,7 +315,7 @@
return true;
}
-bool NSSCertificate::Equals(const NSSCertificate *tocompare) const {
+bool NSSCertificate::Equals(const NSSCertificate* tocompare) const {
if (!certificate_->derCert.len)
return false;
if (!tocompare->certificate_->derCert.len)
@@ -302,10 +329,9 @@
certificate_->derCert.len) == 0;
}
-
-bool NSSCertificate::GetDigestObject(const std::string &algorithm,
- const SECHashObject **hop) {
- const SECHashObject *ho;
+bool NSSCertificate::GetDigestObject(const std::string& algorithm,
+ const SECHashObject** hop) {
+ const SECHashObject* ho;
HASH_HashType hash_type;
if (algorithm == DIGEST_SHA_1) {
@@ -339,14 +365,14 @@
NSSIdentity* NSSIdentity::GenerateInternal(const SSLIdentityParams& params) {
std::string subject_name_string = "CN=" + params.common_name;
- CERTName *subject_name = CERT_AsciiToName(
- const_cast<char *>(subject_name_string.c_str()));
- NSSIdentity *identity = NULL;
- CERTSubjectPublicKeyInfo *spki = NULL;
- CERTCertificateRequest *certreq = NULL;
- CERTValidity *validity = NULL;
- CERTCertificate *certificate = NULL;
- NSSKeyPair *keypair = NSSKeyPair::Generate();
+ CERTName* subject_name =
+ CERT_AsciiToName(const_cast<char*>(subject_name_string.c_str()));
+ NSSIdentity* identity = nullptr;
+ CERTSubjectPublicKeyInfo* spki = nullptr;
+ CERTCertificateRequest* certreq = nullptr;
+ CERTValidity* validity = nullptr;
+ CERTCertificate* certificate = nullptr;
+ NSSKeyPair* keypair = NSSKeyPair::Generate(params.key_type);
SECItem inner_der;
SECStatus rv;
PLArenaPool* arena;
@@ -358,7 +384,7 @@
now + static_cast<PRTime>(params.not_after) * PR_USEC_PER_SEC;
inner_der.len = 0;
- inner_der.data = NULL;
+ inner_der.data = nullptr;
if (!keypair) {
LOG(LS_ERROR) << "Couldn't generate key pair";
@@ -376,7 +402,7 @@
goto fail;
}
- certreq = CERT_CreateCertificateRequest(subject_name, spki, NULL);
+ certreq = CERT_CreateCertificateRequest(subject_name, spki, nullptr);
if (!certreq) {
LOG(LS_ERROR) << "Couldn't create certificate signing request";
goto fail;
@@ -405,22 +431,36 @@
arena = certificate->arena;
- rv = SECOID_SetAlgorithmID(arena, &certificate->signature,
- SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION, NULL);
- if (rv != SECSuccess)
+ SECOidTag sec_oid;
+ if (params.key_type == KT_RSA) {
+ sec_oid = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
+ } else if (params.key_type == KT_ECDSA) {
+ sec_oid = SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE;
+ } else {
+ // We should not arrive here since NSSKeyPair::Generate would have failed.
+ // Play it safe in order to accomodate code changes.
+ LOG(LS_ERROR) << "Key type requested not understood";
goto fail;
+ }
+
+ rv = SECOID_SetAlgorithmID(arena, &certificate->signature, sec_oid, nullptr);
+ if (rv != SECSuccess) {
+ LOG(LS_ERROR) << "Couldn't set hashing algorithm";
+ goto fail;
+ }
// Set version to X509v3.
*(certificate->version.data) = 2;
certificate->version.len = 1;
if (!SEC_ASN1EncodeItem(arena, &inner_der, certificate,
- SEC_ASN1_GET(CERT_CertificateTemplate)))
+ SEC_ASN1_GET(CERT_CertificateTemplate))) {
+ LOG(LS_ERROR) << "Couldn't encode certificate";
goto fail;
+ }
rv = SEC_DerSignData(arena, &signed_cert, inner_der.data, inner_der.len,
- keypair->privkey(),
- SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION);
+ keypair->privkey(), sec_oid);
if (rv != SECSuccess) {
LOG(LS_ERROR) << "Couldn't sign certificate";
goto fail;
@@ -443,11 +483,13 @@
return identity;
}
-NSSIdentity* NSSIdentity::Generate(const std::string &common_name) {
+NSSIdentity* NSSIdentity::Generate(const std::string& common_name,
+ KeyType key_type) {
SSLIdentityParams params;
params.common_name = common_name;
params.not_before = CERTIFICATE_WINDOW;
params.not_after = CERTIFICATE_LIFETIME;
+ params.key_type = key_type;
return GenerateInternal(params);
}
@@ -460,7 +502,7 @@
std::string private_key_der;
if (!SSLIdentity::PemToDer(
kPemTypeRsaPrivateKey, private_key, &private_key_der))
- return NULL;
+ return nullptr;
SECItem private_key_item;
private_key_item.data = reinterpret_cast<unsigned char *>(
@@ -470,35 +512,43 @@
const unsigned int key_usage = KU_KEY_ENCIPHERMENT | KU_DATA_ENCIPHERMENT |
KU_DIGITAL_SIGNATURE;
- SECKEYPrivateKey* privkey = NULL;
- SECStatus rv =
- PK11_ImportDERPrivateKeyInfoAndReturnKey(NSSContext::GetSlot(),
- &private_key_item,
- NULL, NULL, PR_FALSE, PR_FALSE,
- key_usage, &privkey, NULL);
+ SECKEYPrivateKey* privkey = nullptr;
+ SECStatus rv = PK11_ImportDERPrivateKeyInfoAndReturnKey(
+ NSSContext::GetSlot(), &private_key_item, nullptr, nullptr, PR_FALSE,
+ PR_FALSE, key_usage, &privkey, nullptr);
if (rv != SECSuccess) {
LOG(LS_ERROR) << "Couldn't import private key";
- return NULL;
+ return nullptr;
}
- SECKEYPublicKey *pubkey = SECKEY_ConvertToPublicKey(privkey);
+ SECKEYPublicKey* pubkey = SECKEY_ConvertToPublicKey(privkey);
if (rv != SECSuccess) {
SECKEY_DestroyPrivateKey(privkey);
LOG(LS_ERROR) << "Couldn't convert private key to public key";
- return NULL;
+ return nullptr;
+ }
+
+ SSLKEAType ssl_kea_type;
+ if (rtc::starts_with(private_key.c_str(),
+ "-----BEGIN RSA PRIVATE KEY-----")) {
+ ssl_kea_type = ssl_kea_rsa;
+ } else {
+ // We might want to check more key types here. But since we're moving to
+ // Open/BoringSSL, don't bother. Besides, this will likely be correct for
+ // any future key type, causing a test to do more harm than good.
+ ssl_kea_type = ssl_kea_ecdh;
}
// Assign to a scoped_ptr so we don't leak on error.
- scoped_ptr<NSSKeyPair> keypair(new NSSKeyPair(privkey, pubkey));
+ scoped_ptr<NSSKeyPair> keypair(new NSSKeyPair(privkey, pubkey, ssl_kea_type));
scoped_ptr<NSSCertificate> cert(NSSCertificate::FromPEMString(certificate));
if (!cert) {
LOG(LS_ERROR) << "Couldn't parse certificate";
- return NULL;
+ return nullptr;
}
// TODO(ekr@rtfm.com): Check the public key against the certificate.
-
return new NSSIdentity(keypair.release(), cert.release());
}
@@ -506,15 +556,15 @@
LOG(LS_INFO) << "Destroying NSS identity";
}
-NSSIdentity *NSSIdentity::GetReference() const {
- NSSKeyPair *keypair = keypair_->GetReference();
+NSSIdentity* NSSIdentity::GetReference() const {
+ NSSKeyPair* keypair = keypair_->GetReference();
if (!keypair)
- return NULL;
+ return nullptr;
- NSSCertificate *certificate = certificate_->GetReference();
+ NSSCertificate* certificate = certificate_->GetReference();
if (!certificate) {
delete keypair;
- return NULL;
+ return nullptr;
}
return new NSSIdentity(keypair, certificate);
@@ -529,4 +579,3 @@
} // rtc namespace
#endif // HAVE_NSS_SSL_H
-
diff --git a/webrtc/base/nssidentity.h b/webrtc/base/nssidentity.h
index 8a304e9..9ac76bf 100644
--- a/webrtc/base/nssidentity.h
+++ b/webrtc/base/nssidentity.h
@@ -24,6 +24,12 @@
#include "hasht.h"
#include "keythi.h"
+#ifdef NSS_SSL_RELATIVE_PATH
+#include "ssl.h"
+#else
+#include "net/third_party/nss/ssl/ssl.h"
+#endif
+
#include "webrtc/base/common.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/scoped_ptr.h"
@@ -33,18 +39,24 @@
class NSSKeyPair {
public:
- NSSKeyPair(SECKEYPrivateKey* privkey, SECKEYPublicKey* pubkey) :
- privkey_(privkey), pubkey_(pubkey) {}
+ NSSKeyPair(SECKEYPrivateKey* privkey, SECKEYPublicKey* pubkey)
+ : privkey_(privkey), pubkey_(pubkey), ssl_kea_type_(ssl_kea_null) {}
+ NSSKeyPair(SECKEYPrivateKey* privkey,
+ SECKEYPublicKey* pubkey,
+ SSLKEAType ssl_kea_type)
+ : privkey_(privkey), pubkey_(pubkey), ssl_kea_type_(ssl_kea_type) {}
~NSSKeyPair();
// Generate a 1024-bit RSA key pair.
- static NSSKeyPair* Generate();
+ static NSSKeyPair* Generate(KeyType key_type);
NSSKeyPair* GetReference();
SECKEYPrivateKey* privkey() const { return privkey_; }
SECKEYPublicKey * pubkey() const { return pubkey_; }
+ SSLKEAType ssl_kea_type() const { return ssl_kea_type_; }
private:
+ SSLKEAType ssl_kea_type_;
SECKEYPrivateKey* privkey_;
SECKEYPublicKey* pubkey_;
@@ -103,7 +115,8 @@
// Represents a SSL key pair and certificate for NSS.
class NSSIdentity : public SSLIdentity {
public:
- static NSSIdentity* Generate(const std::string& common_name);
+ static NSSIdentity* Generate(const std::string& common_name,
+ KeyType key_type);
static NSSIdentity* GenerateForTest(const SSLIdentityParams& params);
static SSLIdentity* FromPEMStrings(const std::string& private_key,
const std::string& certificate);
diff --git a/webrtc/base/nssstreamadapter.cc b/webrtc/base/nssstreamadapter.cc
index 22f2a2e..2e78adf 100644
--- a/webrtc/base/nssstreamadapter.cc
+++ b/webrtc/base/nssstreamadapter.cc
@@ -68,9 +68,10 @@
// Ciphers to enable to get ECDHE encryption with endpoints that support it.
static const uint32_t kEnabledCiphers[] = {
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
-};
+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256};
// Default cipher used between NSS stream adapters.
// This needs to be updated when the default of the SSL library changes.
@@ -78,7 +79,10 @@
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA";
static const char kDefaultSslCipher12[] =
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256";
-
+static const char kDefaultSslEcCipher10[] =
+ "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA";
+static const char kDefaultSslEcCipher12[] =
+ "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256";
// Implementation of NSPR methods
static PRStatus StreamClose(PRFileDesc *socket) {
@@ -495,7 +499,7 @@
}
rv = SSL_ConfigSecureServer(ssl_fd_, identity->certificate().certificate(),
identity->keypair()->privkey(),
- kt_rsa);
+ identity->keypair()->ssl_kea_type());
if (rv != SECSuccess) {
Error("BeginSSL", -1, false);
return -1;
@@ -1093,14 +1097,28 @@
return true;
}
-std::string NSSStreamAdapter::GetDefaultSslCipher(SSLProtocolVersion version) {
- switch (version) {
- case SSL_PROTOCOL_TLS_10:
- case SSL_PROTOCOL_TLS_11:
- return kDefaultSslCipher10;
- case SSL_PROTOCOL_TLS_12:
- default:
- return kDefaultSslCipher12;
+std::string NSSStreamAdapter::GetDefaultSslCipher(SSLProtocolVersion version,
+ KeyType key_type) {
+ if (key_type == KT_RSA) {
+ switch (version) {
+ case SSL_PROTOCOL_TLS_10:
+ case SSL_PROTOCOL_TLS_11:
+ return kDefaultSslCipher10;
+ case SSL_PROTOCOL_TLS_12:
+ default:
+ return kDefaultSslCipher12;
+ }
+ } else if (key_type == KT_ECDSA) {
+ switch (version) {
+ case SSL_PROTOCOL_TLS_10:
+ case SSL_PROTOCOL_TLS_11:
+ return kDefaultSslEcCipher10;
+ case SSL_PROTOCOL_TLS_12:
+ default:
+ return kDefaultSslEcCipher12;
+ }
+ } else {
+ return std::string();
}
}
diff --git a/webrtc/base/nssstreamadapter.h b/webrtc/base/nssstreamadapter.h
index 65ac489..04c310e 100644
--- a/webrtc/base/nssstreamadapter.h
+++ b/webrtc/base/nssstreamadapter.h
@@ -91,7 +91,8 @@
static bool HaveDtls();
static bool HaveDtlsSrtp();
static bool HaveExporter();
- static std::string GetDefaultSslCipher(SSLProtocolVersion version);
+ static std::string GetDefaultSslCipher(SSLProtocolVersion version,
+ KeyType key_type);
protected:
// Override SSLStreamAdapter
diff --git a/webrtc/base/opensslidentity.cc b/webrtc/base/opensslidentity.cc
index dbb040e..de4e6a7 100644
--- a/webrtc/base/opensslidentity.cc
+++ b/webrtc/base/opensslidentity.cc
@@ -46,23 +46,40 @@
static const int CERTIFICATE_WINDOW = -60*60*24;
// Generate a key pair. Caller is responsible for freeing the returned object.
-static EVP_PKEY* MakeKey() {
+static EVP_PKEY* MakeKey(KeyType key_type) {
LOG(LS_INFO) << "Making key pair";
EVP_PKEY* pkey = EVP_PKEY_new();
- // RSA_generate_key is deprecated. Use _ex version.
- BIGNUM* exponent = BN_new();
- RSA* rsa = RSA_new();
- if (!pkey || !exponent || !rsa ||
- !BN_set_word(exponent, 0x10001) || // 65537 RSA exponent
- !RSA_generate_key_ex(rsa, KEY_LENGTH, exponent, NULL) ||
- !EVP_PKEY_assign_RSA(pkey, rsa)) {
- EVP_PKEY_free(pkey);
+ if (key_type == KT_RSA) {
+ BIGNUM* exponent = BN_new();
+ RSA* rsa = RSA_new();
+ if (!pkey || !exponent || !rsa ||
+ !BN_set_word(exponent, 0x10001) || // 65537 RSA exponent
+ !RSA_generate_key_ex(rsa, KEY_LENGTH, exponent, NULL) ||
+ !EVP_PKEY_assign_RSA(pkey, rsa)) {
+ EVP_PKEY_free(pkey);
+ BN_free(exponent);
+ RSA_free(rsa);
+ LOG(LS_ERROR) << "Failed to make RSA key pair";
+ return NULL;
+ }
+ // ownership of rsa struct was assigned, don't free it.
BN_free(exponent);
- RSA_free(rsa);
+ } else if (key_type == KT_ECDSA) {
+ EC_KEY* ec_key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
+ if (!pkey || !ec_key || !EC_KEY_generate_key(ec_key) ||
+ !EVP_PKEY_assign_EC_KEY(pkey, ec_key)) {
+ EVP_PKEY_free(pkey);
+ EC_KEY_free(ec_key);
+ LOG(LS_ERROR) << "Failed to make EC key pair";
+ return NULL;
+ }
+ // ownership of ec_key struct was assigned, don't free it.
+ } else {
+ EVP_PKEY_free(pkey);
+ LOG(LS_ERROR) << "Key type requested not understood";
return NULL;
}
- // ownership of rsa struct was assigned, don't free it.
- BN_free(exponent);
+
LOG(LS_INFO) << "Returning key pair";
return pkey;
}
@@ -138,8 +155,8 @@
}
}
-OpenSSLKeyPair* OpenSSLKeyPair::Generate() {
- EVP_PKEY* pkey = MakeKey();
+OpenSSLKeyPair* OpenSSLKeyPair::Generate(KeyType key_type) {
+ EVP_PKEY* pkey = MakeKey(key_type);
if (!pkey) {
LogSSLErrors("Generating key pair");
return NULL;
@@ -207,8 +224,7 @@
if (!bio)
return NULL;
BIO_set_mem_eof_return(bio, 0);
- X509 *x509 = PEM_read_bio_X509(bio, NULL, NULL,
- const_cast<char*>("\0"));
+ X509* x509 = PEM_read_bio_X509(bio, NULL, NULL, const_cast<char*>("\0"));
BIO_free(bio); // Frees the BIO, but not the pointed-to string.
if (!x509)
@@ -283,7 +299,7 @@
unsigned char* digest,
size_t size,
size_t* length) {
- const EVP_MD *md;
+ const EVP_MD* md;
unsigned int n;
if (!OpenSSLDigest::GetDigestEVP(algorithm, &md))
@@ -363,10 +379,10 @@
OpenSSLIdentity* OpenSSLIdentity::GenerateInternal(
const SSLIdentityParams& params) {
- OpenSSLKeyPair *key_pair = OpenSSLKeyPair::Generate();
+ OpenSSLKeyPair* key_pair = OpenSSLKeyPair::Generate(params.key_type);
if (key_pair) {
- OpenSSLCertificate *certificate = OpenSSLCertificate::Generate(
- key_pair, params);
+ OpenSSLCertificate* certificate =
+ OpenSSLCertificate::Generate(key_pair, params);
if (certificate)
return new OpenSSLIdentity(key_pair, certificate);
delete key_pair;
@@ -375,11 +391,13 @@
return NULL;
}
-OpenSSLIdentity* OpenSSLIdentity::Generate(const std::string& common_name) {
+OpenSSLIdentity* OpenSSLIdentity::Generate(const std::string& common_name,
+ KeyType key_type) {
SSLIdentityParams params;
params.common_name = common_name;
params.not_before = CERTIFICATE_WINDOW;
params.not_after = CERTIFICATE_LIFETIME;
+ params.key_type = key_type;
return GenerateInternal(params);
}
@@ -404,8 +422,8 @@
return NULL;
}
BIO_set_mem_eof_return(bio, 0);
- EVP_PKEY *pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL,
- const_cast<char*>("\0"));
+ EVP_PKEY* pkey =
+ PEM_read_bio_PrivateKey(bio, NULL, NULL, const_cast<char*>("\0"));
BIO_free(bio); // Frees the BIO, but not the pointed-to string.
if (!pkey) {
diff --git a/webrtc/base/opensslidentity.h b/webrtc/base/opensslidentity.h
index ee7aabe..72de6c0 100644
--- a/webrtc/base/opensslidentity.h
+++ b/webrtc/base/opensslidentity.h
@@ -32,7 +32,7 @@
ASSERT(pkey_ != NULL);
}
- static OpenSSLKeyPair* Generate();
+ static OpenSSLKeyPair* Generate(KeyType key_type);
virtual ~OpenSSLKeyPair();
@@ -99,7 +99,8 @@
// them consistently.
class OpenSSLIdentity : public SSLIdentity {
public:
- static OpenSSLIdentity* Generate(const std::string& common_name);
+ static OpenSSLIdentity* Generate(const std::string& common_name,
+ KeyType key_type);
static OpenSSLIdentity* GenerateForTest(const SSLIdentityParams& params);
static SSLIdentity* FromPEMStrings(const std::string& private_key,
const std::string& certificate);
diff --git a/webrtc/base/opensslstreamadapter.cc b/webrtc/base/opensslstreamadapter.cc
index 51921f1..3d17607 100644
--- a/webrtc/base/opensslstreamadapter.cc
+++ b/webrtc/base/opensslstreamadapter.cc
@@ -143,18 +143,26 @@
// This needs to be updated when the default of the SSL library changes.
static const char kDefaultSslCipher10[] =
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA";
+static const char kDefaultSslEcCipher10[] =
+ "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA";
#ifdef OPENSSL_IS_BORINGSSL
static const char kDefaultSslCipher12[] =
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256";
+static const char kDefaultSslEcCipher12[] =
+ "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256";
// Fallback cipher for DTLS 1.2 if hardware-accelerated AES-GCM is unavailable.
static const char kDefaultSslCipher12NoAesGcm[] =
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256";
+static const char kDefaultSslEcCipher12NoAesGcm[] =
+ "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256";
#else // !OPENSSL_IS_BORINGSSL
// OpenSSL sorts differently than BoringSSL, so the default cipher doesn't
// change between TLS 1.0 and TLS 1.2 with the current setup.
static const char kDefaultSslCipher12[] =
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA";
+static const char kDefaultSslEcCipher12[] =
+ "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA";
#endif
//////////////////////////////////////////////////////////////////////
@@ -1118,22 +1126,44 @@
}
std::string OpenSSLStreamAdapter::GetDefaultSslCipher(
- SSLProtocolVersion version) {
- switch (version) {
- case SSL_PROTOCOL_TLS_10:
- case SSL_PROTOCOL_TLS_11:
- return kDefaultSslCipher10;
- case SSL_PROTOCOL_TLS_12:
- default:
+ SSLProtocolVersion version,
+ KeyType key_type) {
+ if (key_type == KT_RSA) {
+ switch (version) {
+ case SSL_PROTOCOL_TLS_10:
+ case SSL_PROTOCOL_TLS_11:
+ return kDefaultSslCipher10;
+ case SSL_PROTOCOL_TLS_12:
+ default:
#ifdef OPENSSL_IS_BORINGSSL
- if (EVP_has_aes_hardware()) {
- return kDefaultSslCipher12;
- } else {
- return kDefaultSslCipher12NoAesGcm;
- }
+ if (EVP_has_aes_hardware()) {
+ return kDefaultSslCipher12;
+ } else {
+ return kDefaultSslCipher12NoAesGcm;
+ }
#else // !OPENSSL_IS_BORINGSSL
- return kDefaultSslCipher12;
+ return kDefaultSslCipher12;
#endif
+ }
+ } else if (key_type == KT_ECDSA) {
+ switch (version) {
+ case SSL_PROTOCOL_TLS_10:
+ case SSL_PROTOCOL_TLS_11:
+ return kDefaultSslEcCipher10;
+ case SSL_PROTOCOL_TLS_12:
+ default:
+#ifdef OPENSSL_IS_BORINGSSL
+ if (EVP_has_aes_hardware()) {
+ return kDefaultSslEcCipher12;
+ } else {
+ return kDefaultSslEcCipher12NoAesGcm;
+ }
+#else // !OPENSSL_IS_BORINGSSL
+ return kDefaultSslEcCipher12;
+#endif
+ }
+ } else {
+ return std::string();
}
}
diff --git a/webrtc/base/opensslstreamadapter.h b/webrtc/base/opensslstreamadapter.h
index 5cad3a1..cf332b1 100644
--- a/webrtc/base/opensslstreamadapter.h
+++ b/webrtc/base/opensslstreamadapter.h
@@ -110,7 +110,8 @@
static bool HaveDtls();
static bool HaveDtlsSrtp();
static bool HaveExporter();
- static std::string GetDefaultSslCipher(SSLProtocolVersion version);
+ static std::string GetDefaultSslCipher(SSLProtocolVersion version,
+ KeyType key_type);
protected:
void OnEvent(StreamInterface* stream, int events, int err) override;
diff --git a/webrtc/base/ssladapter_unittest.cc b/webrtc/base/ssladapter_unittest.cc
index 9a05486..9b69451 100644
--- a/webrtc/base/ssladapter_unittest.cc
+++ b/webrtc/base/ssladapter_unittest.cc
@@ -15,6 +15,7 @@
#include "webrtc/base/socketstream.h"
#include "webrtc/base/ssladapter.h"
#include "webrtc/base/sslstreamadapter.h"
+#include "webrtc/base/sslidentity.h"
#include "webrtc/base/stream.h"
#include "webrtc/base/virtualsocketserver.h"
@@ -129,10 +130,11 @@
class SSLAdapterTestDummyServer : public sigslot::has_slots<> {
public:
- explicit SSLAdapterTestDummyServer(const rtc::SSLMode& ssl_mode)
+ explicit SSLAdapterTestDummyServer(const rtc::SSLMode& ssl_mode,
+ const rtc::KeyType key_type)
: ssl_mode_(ssl_mode) {
// Generate a key pair and a certificate for this host.
- ssl_identity_.reset(rtc::SSLIdentity::Generate(GetHostname()));
+ ssl_identity_.reset(rtc::SSLIdentity::Generate(GetHostname(), key_type));
server_socket_.reset(CreateSocket(ssl_mode_));
@@ -268,13 +270,13 @@
class SSLAdapterTestBase : public testing::Test,
public sigslot::has_slots<> {
public:
- explicit SSLAdapterTestBase(const rtc::SSLMode& ssl_mode)
+ explicit SSLAdapterTestBase(const rtc::SSLMode& ssl_mode,
+ const rtc::KeyType key_type)
: ssl_mode_(ssl_mode),
ss_scope_(new rtc::VirtualSocketServer(NULL)),
- server_(new SSLAdapterTestDummyServer(ssl_mode_)),
+ server_(new SSLAdapterTestDummyServer(ssl_mode_, key_type)),
client_(new SSLAdapterTestDummyClient(ssl_mode_)),
- handshake_wait_(kTimeout) {
- }
+ handshake_wait_(kTimeout) {}
void SetHandshakeWait(int wait) {
handshake_wait_ = wait;
@@ -343,43 +345,78 @@
int handshake_wait_;
};
-class SSLAdapterTestTLS : public SSLAdapterTestBase {
+class SSLAdapterTestTLS_RSA : public SSLAdapterTestBase {
public:
- SSLAdapterTestTLS() : SSLAdapterTestBase(rtc::SSL_MODE_TLS) {}
+ SSLAdapterTestTLS_RSA()
+ : SSLAdapterTestBase(rtc::SSL_MODE_TLS, rtc::KT_RSA) {}
};
-class SSLAdapterTestDTLS : public SSLAdapterTestBase {
+class SSLAdapterTestTLS_ECDSA : public SSLAdapterTestBase {
public:
- SSLAdapterTestDTLS() : SSLAdapterTestBase(rtc::SSL_MODE_DTLS) {}
+ SSLAdapterTestTLS_ECDSA()
+ : SSLAdapterTestBase(rtc::SSL_MODE_TLS, rtc::KT_ECDSA) {}
+};
+
+class SSLAdapterTestDTLS_RSA : public SSLAdapterTestBase {
+ public:
+ SSLAdapterTestDTLS_RSA()
+ : SSLAdapterTestBase(rtc::SSL_MODE_DTLS, rtc::KT_RSA) {}
+};
+
+class SSLAdapterTestDTLS_ECDSA : public SSLAdapterTestBase {
+ public:
+ SSLAdapterTestDTLS_ECDSA()
+ : SSLAdapterTestBase(rtc::SSL_MODE_DTLS, rtc::KT_ECDSA) {}
};
#if SSL_USE_OPENSSL
// Basic tests: TLS
-// Test that handshake works
-TEST_F(SSLAdapterTestTLS, TestTLSConnect) {
+// Test that handshake works, using RSA
+TEST_F(SSLAdapterTestTLS_RSA, TestTLSConnect) {
TestHandshake(true);
}
-// Test transfer between client and server
-TEST_F(SSLAdapterTestTLS, TestTLSTransfer) {
+// Test that handshake works, using ECDSA
+TEST_F(SSLAdapterTestTLS_ECDSA, TestTLSConnect) {
+ TestHandshake(true);
+}
+
+// Test transfer between client and server, using RSA
+TEST_F(SSLAdapterTestTLS_RSA, TestTLSTransfer) {
+ TestHandshake(true);
+ TestTransfer("Hello, world!");
+}
+
+// Test transfer between client and server, using ECDSA
+TEST_F(SSLAdapterTestTLS_ECDSA, TestTLSTransfer) {
TestHandshake(true);
TestTransfer("Hello, world!");
}
// Basic tests: DTLS
-// Test that handshake works
-TEST_F(SSLAdapterTestDTLS, TestDTLSConnect) {
+// Test that handshake works, using RSA
+TEST_F(SSLAdapterTestDTLS_RSA, TestDTLSConnect) {
TestHandshake(true);
}
-// Test transfer between client and server
-TEST_F(SSLAdapterTestDTLS, TestDTLSTransfer) {
+// Test that handshake works, using ECDSA
+TEST_F(SSLAdapterTestDTLS_ECDSA, TestDTLSConnect) {
+ TestHandshake(true);
+}
+
+// Test transfer between client and server, using RSA
+TEST_F(SSLAdapterTestDTLS_RSA, TestDTLSTransfer) {
+ TestHandshake(true);
+ TestTransfer("Hello, world!");
+}
+
+// Test transfer between client and server, using ECDSA
+TEST_F(SSLAdapterTestDTLS_ECDSA, TestDTLSTransfer) {
TestHandshake(true);
TestTransfer("Hello, world!");
}
#endif // SSL_USE_OPENSSL
-
diff --git a/webrtc/base/sslidentity.cc b/webrtc/base/sslidentity.cc
index ea9f547..33b7387 100644
--- a/webrtc/base/sslidentity.cc
+++ b/webrtc/base/sslidentity.cc
@@ -37,6 +37,7 @@
const char kPemTypeCertificate[] = "CERTIFICATE";
const char kPemTypeRsaPrivateKey[] = "RSA PRIVATE KEY";
+const char kPemTypeEcPrivateKey[] = "EC PRIVATE KEY";
bool SSLIdentity::PemToDer(const std::string& pem_type,
const std::string& pem_string,
@@ -108,7 +109,8 @@
return NULL;
}
-SSLIdentity* SSLIdentity::Generate(const std::string& common_name) {
+SSLIdentity* SSLIdentity::Generate(const std::string& common_name,
+ KeyType key_type) {
return NULL;
}
@@ -127,8 +129,9 @@
return OpenSSLCertificate::FromPEMString(pem_string);
}
-SSLIdentity* SSLIdentity::Generate(const std::string& common_name) {
- return OpenSSLIdentity::Generate(common_name);
+SSLIdentity* SSLIdentity::Generate(const std::string& common_name,
+ KeyType key_type) {
+ return OpenSSLIdentity::Generate(common_name, key_type);
}
SSLIdentity* SSLIdentity::GenerateForTest(const SSLIdentityParams& params) {
@@ -146,8 +149,9 @@
return NSSCertificate::FromPEMString(pem_string);
}
-SSLIdentity* SSLIdentity::Generate(const std::string& common_name) {
- return NSSIdentity::Generate(common_name);
+SSLIdentity* SSLIdentity::Generate(const std::string& common_name,
+ KeyType key_type) {
+ return NSSIdentity::Generate(common_name, key_type);
}
SSLIdentity* SSLIdentity::GenerateForTest(const SSLIdentityParams& params) {
diff --git a/webrtc/base/sslidentity.h b/webrtc/base/sslidentity.h
index 59f87d0..15e23a3 100644
--- a/webrtc/base/sslidentity.h
+++ b/webrtc/base/sslidentity.h
@@ -117,6 +117,7 @@
std::string common_name;
int not_before; // in seconds.
int not_after; // in seconds.
+ KeyType key_type;
};
// Our identity in an SSL negotiation: a keypair and certificate (both
@@ -129,7 +130,8 @@
// subject and issuer name, otherwise a random string will be used.
// Returns NULL on failure.
// Caller is responsible for freeing the returned object.
- static SSLIdentity* Generate(const std::string& common_name);
+ static SSLIdentity* Generate(const std::string& common_name,
+ KeyType key_type);
// Generates an identity with the specified validity period.
static SSLIdentity* GenerateForTest(const SSLIdentityParams& params);
@@ -159,6 +161,7 @@
extern const char kPemTypeCertificate[];
extern const char kPemTypeRsaPrivateKey[];
+extern const char kPemTypeEcPrivateKey[];
} // namespace rtc
diff --git a/webrtc/base/sslidentity_unittest.cc b/webrtc/base/sslidentity_unittest.cc
index fd75411..b49d0d2 100644
--- a/webrtc/base/sslidentity_unittest.cc
+++ b/webrtc/base/sslidentity_unittest.cc
@@ -30,41 +30,75 @@
"itAE+OjGF+PFKbwX8Q==\n"
"-----END CERTIFICATE-----\n";
-const unsigned char kTestCertSha1[] = {0xA6, 0xC8, 0x59, 0xEA,
- 0xC3, 0x7E, 0x6D, 0x33,
- 0xCF, 0xE2, 0x69, 0x9D,
- 0x74, 0xE6, 0xF6, 0x8A,
- 0x9E, 0x47, 0xA7, 0xCA};
+const unsigned char kTestCertSha1[] = {
+ 0xA6, 0xC8, 0x59, 0xEA, 0xC3, 0x7E, 0x6D, 0x33,
+ 0xCF, 0xE2, 0x69, 0x9D, 0x74, 0xE6, 0xF6, 0x8A,
+ 0x9E, 0x47, 0xA7, 0xCA};
+const unsigned char kTestCertSha224[] = {
+ 0xd4, 0xce, 0xc6, 0xcf, 0x28, 0xcb, 0xe9, 0x77,
+ 0x38, 0x36, 0xcf, 0xb1, 0x3b, 0x4a, 0xd7, 0xbd,
+ 0xae, 0x24, 0x21, 0x08, 0xcf, 0x6a, 0x44, 0x0d,
+ 0x3f, 0x94, 0x2a, 0x5b};
+const unsigned char kTestCertSha256[] = {
+ 0x41, 0x6b, 0xb4, 0x93, 0x47, 0x79, 0x77, 0x24,
+ 0x77, 0x0b, 0x8b, 0x2e, 0xa6, 0x2b, 0xe0, 0xf9,
+ 0x0a, 0xed, 0x1f, 0x31, 0xa6, 0xf7, 0x5c, 0xa1,
+ 0x5a, 0xc4, 0xb0, 0xa2, 0xa4, 0x78, 0xb9, 0x76};
+const unsigned char kTestCertSha384[] = {
+ 0x42, 0x31, 0x9a, 0x79, 0x1d, 0xd6, 0x08, 0xbf,
+ 0x3b, 0xba, 0x36, 0xd8, 0x37, 0x4a, 0x9a, 0x75,
+ 0xd3, 0x25, 0x6e, 0x28, 0x92, 0xbe, 0x06, 0xb7,
+ 0xc5, 0xa0, 0x83, 0xe3, 0x86, 0xb1, 0x03, 0xfc,
+ 0x64, 0x47, 0xd6, 0xd8, 0xaa, 0xd9, 0x36, 0x60,
+ 0x04, 0xcc, 0xbe, 0x7d, 0x6a, 0xe8, 0x34, 0x49};
+const unsigned char kTestCertSha512[] = {
+ 0x51, 0x1d, 0xec, 0x02, 0x3d, 0x51, 0x45, 0xd3,
+ 0xd8, 0x1d, 0xa4, 0x9d, 0x43, 0xc9, 0xee, 0x32,
+ 0x6f, 0x4f, 0x37, 0xee, 0xab, 0x3f, 0x25, 0xdf,
+ 0x72, 0xfc, 0x61, 0x1a, 0xd5, 0x92, 0xff, 0x6b,
+ 0x28, 0x71, 0x58, 0xb3, 0xe1, 0x8a, 0x18, 0xcf,
+ 0x61, 0x33, 0x0e, 0x14, 0xc3, 0x04, 0xaa, 0x07,
+ 0xf6, 0xa5, 0xda, 0xdc, 0x42, 0x42, 0x22, 0x35,
+ 0xce, 0x26, 0x58, 0x4a, 0x33, 0x6d, 0xbc, 0xb6};
class SSLIdentityTest : public testing::Test {
public:
- SSLIdentityTest() :
- identity1_(), identity2_() {
- }
+ SSLIdentityTest() {}
~SSLIdentityTest() {
}
virtual void SetUp() {
- identity1_.reset(SSLIdentity::Generate("test1"));
- identity2_.reset(SSLIdentity::Generate("test2"));
+ identity_rsa1_.reset(SSLIdentity::Generate("test1", rtc::KT_RSA));
+ identity_rsa2_.reset(SSLIdentity::Generate("test2", rtc::KT_RSA));
+ identity_ecdsa1_.reset(SSLIdentity::Generate("test3", rtc::KT_ECDSA));
+ identity_ecdsa2_.reset(SSLIdentity::Generate("test4", rtc::KT_ECDSA));
- ASSERT_TRUE(identity1_);
- ASSERT_TRUE(identity2_);
+ ASSERT_TRUE(identity_rsa1_);
+ ASSERT_TRUE(identity_rsa2_);
+ ASSERT_TRUE(identity_ecdsa1_);
+ ASSERT_TRUE(identity_ecdsa2_);
- test_cert_.reset(
- rtc::SSLCertificate::FromPEMString(kTestCertificate));
+ test_cert_.reset(rtc::SSLCertificate::FromPEMString(kTestCertificate));
ASSERT_TRUE(test_cert_);
}
void TestGetSignatureDigestAlgorithm() {
std::string digest_algorithm;
- // Both NSSIdentity::Generate and OpenSSLIdentity::Generate are
- // hard-coded to generate RSA-SHA256 certificates.
- ASSERT_TRUE(identity1_->certificate().GetSignatureDigestAlgorithm(
+
+ ASSERT_TRUE(identity_rsa1_->certificate().GetSignatureDigestAlgorithm(
&digest_algorithm));
ASSERT_EQ(rtc::DIGEST_SHA_256, digest_algorithm);
- ASSERT_TRUE(identity2_->certificate().GetSignatureDigestAlgorithm(
+
+ ASSERT_TRUE(identity_rsa2_->certificate().GetSignatureDigestAlgorithm(
+ &digest_algorithm));
+ ASSERT_EQ(rtc::DIGEST_SHA_256, digest_algorithm);
+
+ ASSERT_TRUE(identity_ecdsa1_->certificate().GetSignatureDigestAlgorithm(
+ &digest_algorithm));
+ ASSERT_EQ(rtc::DIGEST_SHA_256, digest_algorithm);
+
+ ASSERT_TRUE(identity_ecdsa2_->certificate().GetSignatureDigestAlgorithm(
&digest_algorithm));
ASSERT_EQ(rtc::DIGEST_SHA_256, digest_algorithm);
@@ -73,58 +107,102 @@
ASSERT_EQ(rtc::DIGEST_MD5, digest_algorithm);
}
- void TestDigest(const std::string &algorithm, size_t expected_len,
- const unsigned char *expected_digest = NULL) {
- unsigned char digest1[64];
- unsigned char digest1b[64];
- unsigned char digest2[64];
- size_t digest1_len;
- size_t digest1b_len;
- size_t digest2_len;
+ typedef unsigned char DigestType[rtc::MessageDigest::kMaxSize];
+
+ void TestDigestHelper(DigestType digest,
+ const SSLIdentity* identity,
+ const std::string& algorithm,
+ size_t expected_len) {
+ DigestType digest1;
+ size_t digest_len;
bool rv;
- rv = identity1_->certificate().ComputeDigest(algorithm,
- digest1, sizeof(digest1),
- &digest1_len);
+ memset(digest, 0, expected_len);
+ rv = identity->certificate().ComputeDigest(algorithm, digest,
+ sizeof(DigestType), &digest_len);
EXPECT_TRUE(rv);
- EXPECT_EQ(expected_len, digest1_len);
+ EXPECT_EQ(expected_len, digest_len);
- rv = identity1_->certificate().ComputeDigest(algorithm,
- digest1b, sizeof(digest1b),
- &digest1b_len);
+ // Repeat digest computation for the identity as a sanity check.
+ memset(digest1, 0xff, expected_len);
+ rv = identity->certificate().ComputeDigest(algorithm, digest1,
+ sizeof(DigestType), &digest_len);
EXPECT_TRUE(rv);
- EXPECT_EQ(expected_len, digest1b_len);
- EXPECT_EQ(0, memcmp(digest1, digest1b, expected_len));
+ EXPECT_EQ(expected_len, digest_len);
+ EXPECT_EQ(0, memcmp(digest, digest1, expected_len));
+ }
- rv = identity2_->certificate().ComputeDigest(algorithm,
- digest2, sizeof(digest2),
- &digest2_len);
- EXPECT_TRUE(rv);
- EXPECT_EQ(expected_len, digest2_len);
- EXPECT_NE(0, memcmp(digest1, digest2, expected_len));
+ void TestDigestForGeneratedCert(const std::string& algorithm,
+ size_t expected_len) {
+ DigestType digest[4];
- // If we have an expected hash for the test cert, check it.
- if (expected_digest) {
- unsigned char digest3[64];
- size_t digest3_len;
+ ASSERT_TRUE(expected_len <= sizeof(DigestType));
- rv = test_cert_->ComputeDigest(algorithm, digest3, sizeof(digest3),
- &digest3_len);
- EXPECT_TRUE(rv);
- EXPECT_EQ(expected_len, digest3_len);
- EXPECT_EQ(0, memcmp(digest3, expected_digest, expected_len));
+ TestDigestHelper(digest[0], identity_rsa1_.get(), algorithm, expected_len);
+ TestDigestHelper(digest[1], identity_rsa2_.get(), algorithm, expected_len);
+ TestDigestHelper(digest[2], identity_ecdsa1_.get(), algorithm,
+ expected_len);
+ TestDigestHelper(digest[3], identity_ecdsa2_.get(), algorithm,
+ expected_len);
+
+ // Sanity check that all four digests are unique. This could theoretically
+ // fail, since cryptographic hash collisions have a non-zero probability.
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ if (i != j)
+ EXPECT_NE(0, memcmp(digest[i], digest[j], expected_len));
+ }
}
}
+ void TestDigestForFixedCert(const std::string& algorithm,
+ size_t expected_len,
+ const unsigned char* expected_digest) {
+ bool rv;
+ DigestType digest;
+ size_t digest_len;
+
+ ASSERT_TRUE(expected_len <= sizeof(DigestType));
+
+ rv = test_cert_->ComputeDigest(algorithm, digest, sizeof(digest),
+ &digest_len);
+ EXPECT_TRUE(rv);
+ EXPECT_EQ(expected_len, digest_len);
+ EXPECT_EQ(0, memcmp(digest, expected_digest, expected_len));
+ }
+
private:
- rtc::scoped_ptr<SSLIdentity> identity1_;
- rtc::scoped_ptr<SSLIdentity> identity2_;
+ rtc::scoped_ptr<SSLIdentity> identity_rsa1_;
+ rtc::scoped_ptr<SSLIdentity> identity_rsa2_;
+ rtc::scoped_ptr<SSLIdentity> identity_ecdsa1_;
+ rtc::scoped_ptr<SSLIdentity> identity_ecdsa2_;
rtc::scoped_ptr<rtc::SSLCertificate> test_cert_;
};
-TEST_F(SSLIdentityTest, DigestSHA1) {
- TestDigest(rtc::DIGEST_SHA_1, 20, kTestCertSha1);
+TEST_F(SSLIdentityTest, FixedDigestSHA1) {
+ TestDigestForFixedCert(rtc::DIGEST_SHA_1, 20, kTestCertSha1);
+}
+
+// HASH_AlgSHA224 is not supported in the chromium linux build.
+#if SSL_USE_NSS
+TEST_F(SSLIdentityTest, DISABLED_FixedDigestSHA224) {
+#else
+TEST_F(SSLIdentityTest, FixedDigestSHA224) {
+#endif
+ TestDigestForFixedCert(rtc::DIGEST_SHA_224, 28, kTestCertSha224);
+}
+
+TEST_F(SSLIdentityTest, FixedDigestSHA256) {
+ TestDigestForFixedCert(rtc::DIGEST_SHA_256, 32, kTestCertSha256);
+}
+
+TEST_F(SSLIdentityTest, FixedDigestSHA384) {
+ TestDigestForFixedCert(rtc::DIGEST_SHA_384, 48, kTestCertSha384);
+}
+
+TEST_F(SSLIdentityTest, FixedDigestSHA512) {
+ TestDigestForFixedCert(rtc::DIGEST_SHA_512, 64, kTestCertSha512);
}
// HASH_AlgSHA224 is not supported in the chromium linux build.
@@ -133,22 +211,22 @@
#else
TEST_F(SSLIdentityTest, DigestSHA224) {
#endif
- TestDigest(rtc::DIGEST_SHA_224, 28);
+ TestDigestForGeneratedCert(rtc::DIGEST_SHA_224, 28);
}
TEST_F(SSLIdentityTest, DigestSHA256) {
- TestDigest(rtc::DIGEST_SHA_256, 32);
+ TestDigestForGeneratedCert(rtc::DIGEST_SHA_256, 32);
}
TEST_F(SSLIdentityTest, DigestSHA384) {
- TestDigest(rtc::DIGEST_SHA_384, 48);
+ TestDigestForGeneratedCert(rtc::DIGEST_SHA_384, 48);
}
TEST_F(SSLIdentityTest, DigestSHA512) {
- TestDigest(rtc::DIGEST_SHA_512, 64);
+ TestDigestForGeneratedCert(rtc::DIGEST_SHA_512, 64);
}
-TEST_F(SSLIdentityTest, FromPEMStrings) {
+TEST_F(SSLIdentityTest, FromPEMStringsRSA) {
static const char kRSA_PRIVATE_KEY_PEM[] =
"-----BEGIN RSA PRIVATE KEY-----\n"
"MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMYRkbhmI7kVA/rM\n"
@@ -186,6 +264,39 @@
EXPECT_EQ(kCERT_PEM, identity->certificate().ToPEMString());
}
+#if SSL_USE_OPENSSL
+// This will not work on NSS as PK11_ImportDERPrivateKeyInfoAndReturnKey is not
+// ready for EC keys. Furthermore, NSSIdentity::FromPEMStrings is currently
+// hardwired for RSA (the header matching via kPemTypeRsaPrivateKey needs
+// trivial generalization).
+TEST_F(SSLIdentityTest, FromPEMStringsEC) {
+ static const char kRSA_PRIVATE_KEY_PEM[] =
+ "-----BEGIN EC PRIVATE KEY-----\n"
+ "MHcCAQEEIKkIztWLPbs4Y2zWv7VW2Ov4is2ifleCuPgRB8fRv3IkoAoGCCqGSM49\n"
+ "AwEHoUQDQgAEDPV33NrhSdhg9cBRkUWUXnVMXc3h17i9ARbSmNgminKcBXb8/y8L\n"
+ "A76cMWQPPM0ybHO8OS7ZVg2U/m+TwE1M2g==\n"
+ "-----END EC PRIVATE KEY-----\n";
+ static const char kCERT_PEM[] =
+ "-----BEGIN CERTIFICATE-----\n"
+ "MIIB0jCCAXmgAwIBAgIJAMCjpFt9t6LMMAoGCCqGSM49BAMCMEUxCzAJBgNVBAYT\n"
+ "AkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRn\n"
+ "aXRzIFB0eSBMdGQwIBcNMTUwNjMwMTMwMTIyWhgPMjI4OTA0MTMxMzAxMjJaMEUx\n"
+ "CzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRl\n"
+ "cm5ldCBXaWRnaXRzIFB0eSBMdGQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQM\n"
+ "9Xfc2uFJ2GD1wFGRRZRedUxdzeHXuL0BFtKY2CaKcpwFdvz/LwsDvpwxZA88zTJs\n"
+ "c7w5LtlWDZT+b5PATUzao1AwTjAdBgNVHQ4EFgQUYHq6nxNNIE832ZmaHc/noODO\n"
+ "rtAwHwYDVR0jBBgwFoAUYHq6nxNNIE832ZmaHc/noODOrtAwDAYDVR0TBAUwAwEB\n"
+ "/zAKBggqhkjOPQQDAgNHADBEAiAQRojsTyZG0BlKoU7gOt5h+yAMLl2cxmDtOIQr\n"
+ "GWP/PwIgJynB4AUDsPT0DWmethOXYijB5sY5UPd9DvgmiS/Mr6s=\n"
+ "-----END CERTIFICATE-----\n";
+
+ rtc::scoped_ptr<SSLIdentity> identity(
+ SSLIdentity::FromPEMStrings(kRSA_PRIVATE_KEY_PEM, kCERT_PEM));
+ EXPECT_TRUE(identity);
+ EXPECT_EQ(kCERT_PEM, identity->certificate().ToPEMString());
+}
+#endif
+
TEST_F(SSLIdentityTest, PemDerConversion) {
std::string der;
EXPECT_TRUE(SSLIdentity::PemToDer("CERTIFICATE", kTestCertificate, &der));
diff --git a/webrtc/base/sslstreamadapter.cc b/webrtc/base/sslstreamadapter.cc
index 3c27b10..39426cd 100644
--- a/webrtc/base/sslstreamadapter.cc
+++ b/webrtc/base/sslstreamadapter.cc
@@ -72,7 +72,8 @@
bool SSLStreamAdapter::HaveDtls() { return false; }
bool SSLStreamAdapter::HaveDtlsSrtp() { return false; }
bool SSLStreamAdapter::HaveExporter() { return false; }
-std::string SSLStreamAdapter::GetDefaultSslCipher(SSLProtocolVersion version) {
+std::string SSLStreamAdapter::GetDefaultSslCipher(SSLProtocolVersion version,
+ KeyType key_type) {
return std::string();
}
#elif SSL_USE_OPENSSL
@@ -85,8 +86,9 @@
bool SSLStreamAdapter::HaveExporter() {
return OpenSSLStreamAdapter::HaveExporter();
}
-std::string SSLStreamAdapter::GetDefaultSslCipher(SSLProtocolVersion version) {
- return OpenSSLStreamAdapter::GetDefaultSslCipher(version);
+std::string SSLStreamAdapter::GetDefaultSslCipher(SSLProtocolVersion version,
+ KeyType key_type) {
+ return OpenSSLStreamAdapter::GetDefaultSslCipher(version, key_type);
}
#elif SSL_USE_NSS
bool SSLStreamAdapter::HaveDtls() {
@@ -98,8 +100,9 @@
bool SSLStreamAdapter::HaveExporter() {
return NSSStreamAdapter::HaveExporter();
}
-std::string SSLStreamAdapter::GetDefaultSslCipher(SSLProtocolVersion version) {
- return NSSStreamAdapter::GetDefaultSslCipher(version);
+std::string SSLStreamAdapter::GetDefaultSslCipher(SSLProtocolVersion version,
+ KeyType key_type) {
+ return NSSStreamAdapter::GetDefaultSslCipher(version, key_type);
}
#endif // !SSL_USE_SCHANNEL && !SSL_USE_OPENSSL && !SSL_USE_NSS
diff --git a/webrtc/base/sslstreamadapter.h b/webrtc/base/sslstreamadapter.h
index dcb8029..4fb238a 100644
--- a/webrtc/base/sslstreamadapter.h
+++ b/webrtc/base/sslstreamadapter.h
@@ -167,7 +167,9 @@
// Returns the default Ssl cipher used between streams of this class
// for the given protocol version. This is used by the unit tests.
- static std::string GetDefaultSslCipher(SSLProtocolVersion version);
+ // TODO(torbjorng@webrtc.org): Fix callers to avoid default parameter.
+ static std::string GetDefaultSslCipher(SSLProtocolVersion version,
+ KeyType key_type = KT_DEFAULT);
private:
// If true, the server certificate need not match the configured
diff --git a/webrtc/base/sslstreamadapter_unittest.cc b/webrtc/base/sslstreamadapter_unittest.cc
index 6abaaa3..67658ba 100644
--- a/webrtc/base/sslstreamadapter_unittest.cc
+++ b/webrtc/base/sslstreamadapter_unittest.cc
@@ -23,6 +23,11 @@
#include "webrtc/base/stream.h"
#include "webrtc/test/testsupport/gtest_disable.h"
+using ::testing::WithParamInterface;
+using ::testing::Values;
+using ::testing::Combine;
+using ::testing::tuple;
+
static const int kBlockSize = 4096;
static const char kAES_CM_HMAC_SHA1_80[] = "AES_CM_128_HMAC_SHA1_80";
static const char kAES_CM_HMAC_SHA1_32[] = "AES_CM_128_HMAC_SHA1_32";
@@ -158,18 +163,27 @@
public:
SSLStreamAdapterTestBase(const std::string& client_cert_pem,
const std::string& client_private_key_pem,
- bool dtls) :
- client_buffer_(kFifoBufferSize), server_buffer_(kFifoBufferSize),
- client_stream_(
- new SSLDummyStream(this, "c2s", &client_buffer_, &server_buffer_)),
- server_stream_(
- new SSLDummyStream(this, "s2c", &server_buffer_, &client_buffer_)),
- client_ssl_(rtc::SSLStreamAdapter::Create(client_stream_)),
- server_ssl_(rtc::SSLStreamAdapter::Create(server_stream_)),
- client_identity_(NULL), server_identity_(NULL),
- delay_(0), mtu_(1460), loss_(0), lose_first_packet_(false),
- damage_(false), dtls_(dtls),
- handshake_wait_(5000), identities_set_(false) {
+ bool dtls,
+ rtc::KeyType client_key_type = rtc::KT_DEFAULT,
+ rtc::KeyType server_key_type = rtc::KT_DEFAULT)
+ : client_buffer_(kFifoBufferSize),
+ server_buffer_(kFifoBufferSize),
+ client_stream_(
+ new SSLDummyStream(this, "c2s", &client_buffer_, &server_buffer_)),
+ server_stream_(
+ new SSLDummyStream(this, "s2c", &server_buffer_, &client_buffer_)),
+ client_ssl_(rtc::SSLStreamAdapter::Create(client_stream_)),
+ server_ssl_(rtc::SSLStreamAdapter::Create(server_stream_)),
+ client_identity_(NULL),
+ server_identity_(NULL),
+ delay_(0),
+ mtu_(1460),
+ loss_(0),
+ lose_first_packet_(false),
+ damage_(false),
+ dtls_(dtls),
+ handshake_wait_(5000),
+ identities_set_(false) {
// Set use of the test RNG to get predictable loss patterns.
rtc::SetRandomTestMode(true);
@@ -181,9 +195,9 @@
client_identity_ = rtc::SSLIdentity::FromPEMStrings(
client_private_key_pem, client_cert_pem);
} else {
- client_identity_ = rtc::SSLIdentity::Generate("client");
+ client_identity_ = rtc::SSLIdentity::Generate("client", client_key_type);
}
- server_identity_ = rtc::SSLIdentity::Generate("server");
+ server_identity_ = rtc::SSLIdentity::Generate("server", server_key_type);
client_ssl_->SetIdentity(client_identity_);
server_ssl_->SetIdentity(server_identity_);
@@ -213,12 +227,14 @@
client_params.common_name = "client";
client_params.not_before = not_before;
client_params.not_after = not_after;
+ client_params.key_type = rtc::KT_DEFAULT;
client_identity_ = rtc::SSLIdentity::GenerateForTest(client_params);
rtc::SSLIdentityParams server_params;
server_params.common_name = "server";
server_params.not_before = not_before;
server_params.not_after = not_after;
+ server_params.key_type = rtc::KT_DEFAULT;
server_identity_ = rtc::SSLIdentity::GenerateForTest(server_params);
client_ssl_->SetIdentity(client_identity_);
@@ -444,11 +460,16 @@
bool identities_set_;
};
-class SSLStreamAdapterTestTLS : public SSLStreamAdapterTestBase {
+class SSLStreamAdapterTestTLS
+ : public SSLStreamAdapterTestBase,
+ public WithParamInterface<tuple<rtc::KeyType, rtc::KeyType>> {
public:
- SSLStreamAdapterTestTLS() :
- SSLStreamAdapterTestBase("", "", false) {
- };
+ SSLStreamAdapterTestTLS()
+ : SSLStreamAdapterTestBase("",
+ "",
+ false,
+ ::testing::get<0>(GetParam()),
+ ::testing::get<1>(GetParam())){};
// Test data transfer for TLS
virtual void TestTransfer(int size) {
@@ -547,12 +568,19 @@
rtc::MemoryStream recv_stream_;
};
-class SSLStreamAdapterTestDTLS : public SSLStreamAdapterTestBase {
+class SSLStreamAdapterTestDTLS
+ : public SSLStreamAdapterTestBase,
+ public WithParamInterface<tuple<rtc::KeyType, rtc::KeyType>> {
public:
- SSLStreamAdapterTestDTLS() :
- SSLStreamAdapterTestBase("", "", true),
- packet_size_(1000), count_(0), sent_(0) {
- }
+ SSLStreamAdapterTestDTLS()
+ : SSLStreamAdapterTestBase("",
+ "",
+ true,
+ ::testing::get<0>(GetParam()),
+ ::testing::get<1>(GetParam())),
+ packet_size_(1000),
+ count_(0),
+ sent_(0) {}
SSLStreamAdapterTestDTLS(const std::string& cert_pem,
const std::string& private_key_pem) :
@@ -677,7 +705,7 @@
// This test only applies to NSS because OpenSSL has passthrough
// semantics for I/O before the handshake is started.
#if SSL_USE_NSS
-TEST_F(SSLStreamAdapterTestTLS, TestNoReadWriteBeforeConnect) {
+TEST_P(SSLStreamAdapterTestTLS, TestNoReadWriteBeforeConnect) {
rtc::StreamResult rv;
char block[kBlockSize];
size_t dummy;
@@ -692,25 +720,25 @@
// Test that we can make a handshake work
-TEST_F(SSLStreamAdapterTestTLS, TestTLSConnect) {
+TEST_P(SSLStreamAdapterTestTLS, TestTLSConnect) {
TestHandshake();
};
// Test that closing the connection on one side updates the other side.
-TEST_F(SSLStreamAdapterTestTLS, TestTLSClose) {
+TEST_P(SSLStreamAdapterTestTLS, TestTLSClose) {
TestHandshake();
client_ssl_->Close();
EXPECT_EQ_WAIT(rtc::SS_CLOSED, server_ssl_->GetState(), handshake_wait_);
};
// Test transfer -- trivial
-TEST_F(SSLStreamAdapterTestTLS, TestTLSTransfer) {
+TEST_P(SSLStreamAdapterTestTLS, TestTLSTransfer) {
TestHandshake();
TestTransfer(100000);
};
// Test read-write after close.
-TEST_F(SSLStreamAdapterTestTLS, ReadWriteAfterClose) {
+TEST_P(SSLStreamAdapterTestTLS, ReadWriteAfterClose) {
TestHandshake();
TestTransfer(100000);
client_ssl_->Close();
@@ -729,7 +757,7 @@
};
// Test a handshake with a bogus peer digest
-TEST_F(SSLStreamAdapterTestTLS, TestTLSBogusDigest) {
+TEST_P(SSLStreamAdapterTestTLS, TestTLSBogusDigest) {
SetPeerIdentitiesByDigest(false);
TestHandshake(false);
};
@@ -738,7 +766,7 @@
// Basic tests: DTLS
// Test that we can make a handshake work
-TEST_F(SSLStreamAdapterTestDTLS, TestDTLSConnect) {
+TEST_P(SSLStreamAdapterTestDTLS, TestDTLSConnect) {
MAYBE_SKIP_TEST(HaveDtls);
TestHandshake();
};
@@ -746,15 +774,14 @@
// Test that we can make a handshake work if the first packet in
// each direction is lost. This gives us predictable loss
// rather than having to tune random
-TEST_F(SSLStreamAdapterTestDTLS, TestDTLSConnectWithLostFirstPacket) {
+TEST_P(SSLStreamAdapterTestDTLS, TestDTLSConnectWithLostFirstPacket) {
MAYBE_SKIP_TEST(HaveDtls);
SetLoseFirstPacket(true);
TestHandshake();
};
// Test a handshake with loss and delay
-TEST_F(SSLStreamAdapterTestDTLS,
- TestDTLSConnectWithLostFirstPacketDelay2s) {
+TEST_P(SSLStreamAdapterTestDTLS, TestDTLSConnectWithLostFirstPacketDelay2s) {
MAYBE_SKIP_TEST(HaveDtls);
SetLoseFirstPacket(true);
SetDelay(2000);
@@ -764,7 +791,7 @@
// Test a handshake with small MTU
// Disabled due to https://code.google.com/p/webrtc/issues/detail?id=3910
-TEST_F(SSLStreamAdapterTestDTLS, DISABLED_TestDTLSConnectWithSmallMtu) {
+TEST_P(SSLStreamAdapterTestDTLS, DISABLED_TestDTLSConnectWithSmallMtu) {
MAYBE_SKIP_TEST(HaveDtls);
SetMtu(700);
SetHandshakeWait(20000);
@@ -772,20 +799,20 @@
};
// Test transfer -- trivial
-TEST_F(SSLStreamAdapterTestDTLS, TestDTLSTransfer) {
+TEST_P(SSLStreamAdapterTestDTLS, TestDTLSTransfer) {
MAYBE_SKIP_TEST(HaveDtls);
TestHandshake();
TestTransfer(100);
};
-TEST_F(SSLStreamAdapterTestDTLS, TestDTLSTransferWithLoss) {
+TEST_P(SSLStreamAdapterTestDTLS, TestDTLSTransferWithLoss) {
MAYBE_SKIP_TEST(HaveDtls);
TestHandshake();
SetLoss(10);
TestTransfer(100);
};
-TEST_F(SSLStreamAdapterTestDTLS, TestDTLSTransferWithDamage) {
+TEST_P(SSLStreamAdapterTestDTLS, TestDTLSTransferWithDamage) {
MAYBE_SKIP_TEST(HaveDtls);
SetDamage(); // Must be called first because first packet
// write happens at end of handshake.
@@ -794,7 +821,7 @@
};
// Test DTLS-SRTP with all high ciphers
-TEST_F(SSLStreamAdapterTestDTLS, TestDTLSSrtpHigh) {
+TEST_P(SSLStreamAdapterTestDTLS, TestDTLSSrtpHigh) {
MAYBE_SKIP_TEST(HaveDtlsSrtp);
std::vector<std::string> high;
high.push_back(kAES_CM_HMAC_SHA1_80);
@@ -812,7 +839,7 @@
};
// Test DTLS-SRTP with all low ciphers
-TEST_F(SSLStreamAdapterTestDTLS, TestDTLSSrtpLow) {
+TEST_P(SSLStreamAdapterTestDTLS, TestDTLSSrtpLow) {
MAYBE_SKIP_TEST(HaveDtlsSrtp);
std::vector<std::string> low;
low.push_back(kAES_CM_HMAC_SHA1_32);
@@ -831,7 +858,7 @@
// Test DTLS-SRTP with a mismatch -- should not converge
-TEST_F(SSLStreamAdapterTestDTLS, TestDTLSSrtpHighLow) {
+TEST_P(SSLStreamAdapterTestDTLS, TestDTLSSrtpHighLow) {
MAYBE_SKIP_TEST(HaveDtlsSrtp);
std::vector<std::string> high;
high.push_back(kAES_CM_HMAC_SHA1_80);
@@ -848,7 +875,7 @@
};
// Test DTLS-SRTP with each side being mixed -- should select high
-TEST_F(SSLStreamAdapterTestDTLS, TestDTLSSrtpMixed) {
+TEST_P(SSLStreamAdapterTestDTLS, TestDTLSSrtpMixed) {
MAYBE_SKIP_TEST(HaveDtlsSrtp);
std::vector<std::string> mixed;
mixed.push_back(kAES_CM_HMAC_SHA1_80);
@@ -867,7 +894,7 @@
};
// Test an exporter
-TEST_F(SSLStreamAdapterTestDTLS, TestDTLSExporter) {
+TEST_P(SSLStreamAdapterTestDTLS, TestDTLSExporter) {
MAYBE_SKIP_TEST(HaveExporter);
TestHandshake();
unsigned char client_out[20];
@@ -890,7 +917,7 @@
}
// Test not yet valid certificates are not rejected.
-TEST_F(SSLStreamAdapterTestDTLS, TestCertNotYetValid) {
+TEST_P(SSLStreamAdapterTestDTLS, TestCertNotYetValid) {
MAYBE_SKIP_TEST(HaveDtls);
long one_day = 60 * 60 * 24;
// Make the certificates not valid until one day later.
@@ -899,7 +926,7 @@
}
// Test expired certificates are not rejected.
-TEST_F(SSLStreamAdapterTestDTLS, TestCertExpired) {
+TEST_P(SSLStreamAdapterTestDTLS, TestCertExpired) {
MAYBE_SKIP_TEST(HaveDtls);
long one_day = 60 * 60 * 24;
// Make the certificates already expired.
@@ -908,14 +935,14 @@
}
// Test data transfer using certs created from strings.
-TEST_F(SSLStreamAdapterTestDTLSFromPEMStrings, TestTransfer) {
+TEST_P(SSLStreamAdapterTestDTLSFromPEMStrings, TestTransfer) {
MAYBE_SKIP_TEST(HaveDtls);
TestHandshake();
TestTransfer(100);
}
// Test getting the remote certificate.
-TEST_F(SSLStreamAdapterTestDTLSFromPEMStrings, TestDTLSGetPeerCertificate) {
+TEST_P(SSLStreamAdapterTestDTLSFromPEMStrings, TestDTLSGetPeerCertificate) {
MAYBE_SKIP_TEST(HaveDtls);
// Peer certificates haven't been received yet.
@@ -955,7 +982,7 @@
// Test getting the used DTLS ciphers.
// DTLS 1.2 enabled for neither client nor server -> DTLS 1.0 will be used.
-TEST_F(SSLStreamAdapterTestDTLS, TestGetSslCipher) {
+TEST_P(SSLStreamAdapterTestDTLS, TestGetSslCipher) {
MAYBE_SKIP_TEST(HaveDtls);
SetupProtocolVersions(rtc::SSL_PROTOCOL_DTLS_10, rtc::SSL_PROTOCOL_DTLS_10);
TestHandshake();
@@ -966,14 +993,14 @@
ASSERT_TRUE(GetSslCipher(false, &server_cipher));
ASSERT_EQ(client_cipher, server_cipher);
- ASSERT_EQ(
- rtc::SSLStreamAdapter::GetDefaultSslCipher(rtc::SSL_PROTOCOL_DTLS_10),
- client_cipher);
+ ASSERT_EQ(rtc::SSLStreamAdapter::GetDefaultSslCipher(
+ rtc::SSL_PROTOCOL_DTLS_10, ::testing::get<1>(GetParam())),
+ server_cipher);
}
// Test getting the used DTLS 1.2 ciphers.
// DTLS 1.2 enabled for client and server -> DTLS 1.2 will be used.
-TEST_F(SSLStreamAdapterTestDTLS, TestGetSslCipherDtls12Both) {
+TEST_P(SSLStreamAdapterTestDTLS, TestGetSslCipherDtls12Both) {
MAYBE_SKIP_TEST(HaveDtls);
SetupProtocolVersions(rtc::SSL_PROTOCOL_DTLS_12, rtc::SSL_PROTOCOL_DTLS_12);
TestHandshake();
@@ -984,13 +1011,13 @@
ASSERT_TRUE(GetSslCipher(false, &server_cipher));
ASSERT_EQ(client_cipher, server_cipher);
- ASSERT_EQ(
- rtc::SSLStreamAdapter::GetDefaultSslCipher(rtc::SSL_PROTOCOL_DTLS_12),
- client_cipher);
+ ASSERT_EQ(rtc::SSLStreamAdapter::GetDefaultSslCipher(
+ rtc::SSL_PROTOCOL_DTLS_12, ::testing::get<1>(GetParam())),
+ server_cipher);
}
// DTLS 1.2 enabled for client only -> DTLS 1.0 will be used.
-TEST_F(SSLStreamAdapterTestDTLS, TestGetSslCipherDtls12Client) {
+TEST_P(SSLStreamAdapterTestDTLS, TestGetSslCipherDtls12Client) {
MAYBE_SKIP_TEST(HaveDtls);
SetupProtocolVersions(rtc::SSL_PROTOCOL_DTLS_10, rtc::SSL_PROTOCOL_DTLS_12);
TestHandshake();
@@ -1001,13 +1028,13 @@
ASSERT_TRUE(GetSslCipher(false, &server_cipher));
ASSERT_EQ(client_cipher, server_cipher);
- ASSERT_EQ(
- rtc::SSLStreamAdapter::GetDefaultSslCipher(rtc::SSL_PROTOCOL_DTLS_10),
- client_cipher);
+ ASSERT_EQ(rtc::SSLStreamAdapter::GetDefaultSslCipher(
+ rtc::SSL_PROTOCOL_DTLS_10, ::testing::get<1>(GetParam())),
+ server_cipher);
}
// DTLS 1.2 enabled for server only -> DTLS 1.0 will be used.
-TEST_F(SSLStreamAdapterTestDTLS, TestGetSslCipherDtls12Server) {
+TEST_P(SSLStreamAdapterTestDTLS, TestGetSslCipherDtls12Server) {
MAYBE_SKIP_TEST(HaveDtls);
SetupProtocolVersions(rtc::SSL_PROTOCOL_DTLS_12, rtc::SSL_PROTOCOL_DTLS_10);
TestHandshake();
@@ -1018,7 +1045,16 @@
ASSERT_TRUE(GetSslCipher(false, &server_cipher));
ASSERT_EQ(client_cipher, server_cipher);
- ASSERT_EQ(
- rtc::SSLStreamAdapter::GetDefaultSslCipher(rtc::SSL_PROTOCOL_DTLS_10),
- client_cipher);
+ ASSERT_EQ(rtc::SSLStreamAdapter::GetDefaultSslCipher(
+ rtc::SSL_PROTOCOL_DTLS_10, ::testing::get<1>(GetParam())),
+ server_cipher);
}
+
+INSTANTIATE_TEST_CASE_P(SSLStreamAdapterTestsTLS,
+ SSLStreamAdapterTestTLS,
+ Combine(Values(rtc::KT_RSA, rtc::KT_ECDSA),
+ Values(rtc::KT_RSA, rtc::KT_ECDSA)));
+INSTANTIATE_TEST_CASE_P(SSLStreamAdapterTestsDTLS,
+ SSLStreamAdapterTestDTLS,
+ Combine(Values(rtc::KT_RSA, rtc::KT_ECDSA),
+ Values(rtc::KT_RSA, rtc::KT_ECDSA)));
diff --git a/webrtc/p2p/base/dtlstransportchannel_unittest.cc b/webrtc/p2p/base/dtlstransportchannel_unittest.cc
index 8c1c21c..dfae0c8 100644
--- a/webrtc/p2p/base/dtlstransportchannel_unittest.cc
+++ b/webrtc/p2p/base/dtlstransportchannel_unittest.cc
@@ -62,8 +62,8 @@
void SetIceProtocol(cricket::TransportProtocol proto) {
protocol_ = proto;
}
- void CreateIdentity() {
- identity_.reset(rtc::SSLIdentity::Generate(name_));
+ void CreateIdentity(rtc::KeyType key_type) {
+ identity_.reset(rtc::SSLIdentity::Generate(name_, key_type));
}
rtc::SSLIdentity* identity() { return identity_.get(); }
void SetupSrtp() {
@@ -412,12 +412,12 @@
client2_.SetupMaxProtocolVersion(c2);
ssl_expected_version_ = std::min(c1, c2);
}
- void PrepareDtls(bool c1, bool c2) {
+ void PrepareDtls(bool c1, bool c2, rtc::KeyType key_type) {
if (c1) {
- client1_.CreateIdentity();
+ client1_.CreateIdentity(key_type);
}
if (c2) {
- client2_.CreateIdentity();
+ client2_.CreateIdentity(key_type);
}
if (c1 && c2)
use_dtls_ = true;
@@ -616,7 +616,7 @@
// Connect with DTLS, and transfer some data.
TEST_F(DtlsTransportChannelTest, TestTransferDtls) {
MAYBE_SKIP_TEST(HaveDtls);
- PrepareDtls(true, true);
+ PrepareDtls(true, true, rtc::KT_DEFAULT);
ASSERT_TRUE(Connect());
TestTransfer(0, 1000, 100, false);
}
@@ -625,7 +625,7 @@
TEST_F(DtlsTransportChannelTest, TestTransferDtlsTwoChannels) {
MAYBE_SKIP_TEST(HaveDtls);
SetChannelCount(2);
- PrepareDtls(true, true);
+ PrepareDtls(true, true, rtc::KT_DEFAULT);
ASSERT_TRUE(Connect());
TestTransfer(0, 1000, 100, false);
TestTransfer(1, 1000, 100, false);
@@ -633,14 +633,14 @@
// Connect with A doing DTLS and B not, and transfer some data.
TEST_F(DtlsTransportChannelTest, TestTransferDtlsRejected) {
- PrepareDtls(true, false);
+ PrepareDtls(true, false, rtc::KT_DEFAULT);
ASSERT_TRUE(Connect());
TestTransfer(0, 1000, 100, false);
}
// Connect with B doing DTLS and A not, and transfer some data.
TEST_F(DtlsTransportChannelTest, TestTransferDtlsNotOffered) {
- PrepareDtls(false, true);
+ PrepareDtls(false, true, rtc::KT_DEFAULT);
ASSERT_TRUE(Connect());
TestTransfer(0, 1000, 100, false);
}
@@ -649,7 +649,7 @@
TEST_F(DtlsTransportChannelTest, TestDtls12None) {
MAYBE_SKIP_TEST(HaveDtls);
SetChannelCount(2);
- PrepareDtls(true, true);
+ PrepareDtls(true, true, rtc::KT_DEFAULT);
SetMaxProtocolVersions(rtc::SSL_PROTOCOL_DTLS_10, rtc::SSL_PROTOCOL_DTLS_10);
ASSERT_TRUE(Connect());
}
@@ -658,7 +658,7 @@
TEST_F(DtlsTransportChannelTest, TestDtls12Both) {
MAYBE_SKIP_TEST(HaveDtls);
SetChannelCount(2);
- PrepareDtls(true, true);
+ PrepareDtls(true, true, rtc::KT_DEFAULT);
SetMaxProtocolVersions(rtc::SSL_PROTOCOL_DTLS_12, rtc::SSL_PROTOCOL_DTLS_12);
ASSERT_TRUE(Connect());
}
@@ -667,7 +667,7 @@
TEST_F(DtlsTransportChannelTest, TestDtls12Client1) {
MAYBE_SKIP_TEST(HaveDtls);
SetChannelCount(2);
- PrepareDtls(true, true);
+ PrepareDtls(true, true, rtc::KT_DEFAULT);
SetMaxProtocolVersions(rtc::SSL_PROTOCOL_DTLS_12, rtc::SSL_PROTOCOL_DTLS_10);
ASSERT_TRUE(Connect());
}
@@ -676,7 +676,7 @@
TEST_F(DtlsTransportChannelTest, TestDtls12Client2) {
MAYBE_SKIP_TEST(HaveDtls);
SetChannelCount(2);
- PrepareDtls(true, true);
+ PrepareDtls(true, true, rtc::KT_DEFAULT);
SetMaxProtocolVersions(rtc::SSL_PROTOCOL_DTLS_10, rtc::SSL_PROTOCOL_DTLS_12);
ASSERT_TRUE(Connect());
}
@@ -684,7 +684,7 @@
// Connect with DTLS, negotiate DTLS-SRTP, and transfer SRTP using bypass.
TEST_F(DtlsTransportChannelTest, TestTransferDtlsSrtp) {
MAYBE_SKIP_TEST(HaveDtlsSrtp);
- PrepareDtls(true, true);
+ PrepareDtls(true, true, rtc::KT_DEFAULT);
PrepareDtlsSrtp(true, true);
ASSERT_TRUE(Connect());
TestTransfer(0, 1000, 100, true);
@@ -694,7 +694,7 @@
// returned.
TEST_F(DtlsTransportChannelTest, TestTransferDtlsInvalidSrtpPacket) {
MAYBE_SKIP_TEST(HaveDtls);
- PrepareDtls(true, true);
+ PrepareDtls(true, true, rtc::KT_DEFAULT);
PrepareDtlsSrtp(true, true);
ASSERT_TRUE(Connect());
int result = client1_.SendInvalidSrtpPacket(0, 100);
@@ -704,7 +704,7 @@
// Connect with DTLS. A does DTLS-SRTP but B does not.
TEST_F(DtlsTransportChannelTest, TestTransferDtlsSrtpRejected) {
MAYBE_SKIP_TEST(HaveDtlsSrtp);
- PrepareDtls(true, true);
+ PrepareDtls(true, true, rtc::KT_DEFAULT);
PrepareDtlsSrtp(true, false);
ASSERT_TRUE(Connect());
}
@@ -712,7 +712,7 @@
// Connect with DTLS. B does DTLS-SRTP but A does not.
TEST_F(DtlsTransportChannelTest, TestTransferDtlsSrtpNotOffered) {
MAYBE_SKIP_TEST(HaveDtlsSrtp);
- PrepareDtls(true, true);
+ PrepareDtls(true, true, rtc::KT_DEFAULT);
PrepareDtlsSrtp(false, true);
ASSERT_TRUE(Connect());
}
@@ -721,7 +721,7 @@
TEST_F(DtlsTransportChannelTest, TestTransferDtlsSrtpTwoChannels) {
MAYBE_SKIP_TEST(HaveDtlsSrtp);
SetChannelCount(2);
- PrepareDtls(true, true);
+ PrepareDtls(true, true, rtc::KT_DEFAULT);
PrepareDtlsSrtp(true, true);
ASSERT_TRUE(Connect());
TestTransfer(0, 1000, 100, true);
@@ -731,7 +731,7 @@
// Create a single channel with DTLS, and send normal data and SRTP data on it.
TEST_F(DtlsTransportChannelTest, TestTransferDtlsSrtpDemux) {
MAYBE_SKIP_TEST(HaveDtlsSrtp);
- PrepareDtls(true, true);
+ PrepareDtls(true, true, rtc::KT_DEFAULT);
PrepareDtlsSrtp(true, true);
ASSERT_TRUE(Connect());
TestTransfer(0, 1000, 100, false);
@@ -742,7 +742,7 @@
TEST_F(DtlsTransportChannelTest, TestTransferDtlsAnswererIsPassive) {
MAYBE_SKIP_TEST(HaveDtlsSrtp);
SetChannelCount(2);
- PrepareDtls(true, true);
+ PrepareDtls(true, true, rtc::KT_DEFAULT);
PrepareDtlsSrtp(true, true);
ASSERT_TRUE(Connect(cricket::CONNECTIONROLE_ACTPASS,
cricket::CONNECTIONROLE_PASSIVE));
@@ -754,7 +754,7 @@
// In this case legacy is the answerer.
TEST_F(DtlsTransportChannelTest, TestDtlsSetupWithLegacyAsAnswerer) {
MAYBE_SKIP_TEST(HaveDtlsSrtp);
- PrepareDtls(true, true);
+ PrepareDtls(true, true, rtc::KT_DEFAULT);
NegotiateWithLegacy();
rtc::SSLRole channel1_role;
rtc::SSLRole channel2_role;
@@ -769,7 +769,7 @@
TEST_F(DtlsTransportChannelTest, TestDtlsReOfferFromOfferer) {
MAYBE_SKIP_TEST(HaveDtlsSrtp);
SetChannelCount(2);
- PrepareDtls(true, true);
+ PrepareDtls(true, true, rtc::KT_DEFAULT);
PrepareDtlsSrtp(true, true);
// Initial role for client1 is ACTPASS and client2 is ACTIVE.
ASSERT_TRUE(Connect(cricket::CONNECTIONROLE_ACTPASS,
@@ -786,7 +786,7 @@
TEST_F(DtlsTransportChannelTest, TestDtlsReOfferFromAnswerer) {
MAYBE_SKIP_TEST(HaveDtlsSrtp);
SetChannelCount(2);
- PrepareDtls(true, true);
+ PrepareDtls(true, true, rtc::KT_DEFAULT);
PrepareDtlsSrtp(true, true);
// Initial role for client1 is ACTPASS and client2 is ACTIVE.
ASSERT_TRUE(Connect(cricket::CONNECTIONROLE_ACTPASS,
@@ -804,7 +804,7 @@
TEST_F(DtlsTransportChannelTest, TestDtlsRoleReversal) {
MAYBE_SKIP_TEST(HaveDtlsSrtp);
SetChannelCount(2);
- PrepareDtls(true, true);
+ PrepareDtls(true, true, rtc::KT_DEFAULT);
PrepareDtlsSrtp(true, true);
ASSERT_TRUE(Connect(cricket::CONNECTIONROLE_ACTPASS,
cricket::CONNECTIONROLE_PASSIVE));
@@ -820,7 +820,7 @@
TEST_F(DtlsTransportChannelTest, TestDtlsReOfferWithDifferentSetupAttr) {
MAYBE_SKIP_TEST(HaveDtlsSrtp);
SetChannelCount(2);
- PrepareDtls(true, true);
+ PrepareDtls(true, true, rtc::KT_DEFAULT);
PrepareDtlsSrtp(true, true);
ASSERT_TRUE(Connect(cricket::CONNECTIONROLE_ACTPASS,
cricket::CONNECTIONROLE_PASSIVE));
@@ -836,7 +836,7 @@
TEST_F(DtlsTransportChannelTest, TestRenegotiateBeforeConnect) {
MAYBE_SKIP_TEST(HaveDtlsSrtp);
SetChannelCount(2);
- PrepareDtls(true, true);
+ PrepareDtls(true, true, rtc::KT_DEFAULT);
PrepareDtlsSrtp(true, true);
Negotiate();
@@ -853,7 +853,7 @@
// Test Certificates state after negotiation but before connection.
TEST_F(DtlsTransportChannelTest, TestCertificatesBeforeConnect) {
MAYBE_SKIP_TEST(HaveDtls);
- PrepareDtls(true, true);
+ PrepareDtls(true, true, rtc::KT_DEFAULT);
Negotiate();
rtc::scoped_ptr<rtc::SSLIdentity> identity1;
@@ -878,7 +878,7 @@
// Test Certificates state after connection.
TEST_F(DtlsTransportChannelTest, TestCertificatesAfterConnect) {
MAYBE_SKIP_TEST(HaveDtls);
- PrepareDtls(true, true);
+ PrepareDtls(true, true, rtc::KT_DEFAULT);
ASSERT_TRUE(Connect());
rtc::scoped_ptr<rtc::SSLIdentity> identity1;