This source file includes following definitions.
- CreateNSSCertHandleFromBytes
- VerifyCertificateSignature
- VerifyDomainBoundCert
- TEST
#include "net/cert/x509_util.h"
#include "net/cert/x509_util_nss.h"
#include <cert.h>
#include <secoid.h>
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "crypto/ec_private_key.h"
#include "crypto/scoped_nss_types.h"
#include "crypto/signature_verifier.h"
#include "net/cert/x509_certificate.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
namespace {
CERTCertificate* CreateNSSCertHandleFromBytes(const char* data, size_t length) {
SECItem der_cert;
der_cert.data = reinterpret_cast<unsigned char*>(const_cast<char*>(data));
der_cert.len = length;
der_cert.type = siDERCertBuffer;
return CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &der_cert, NULL,
PR_FALSE, PR_TRUE);
}
#if !defined(OS_WIN) && !defined(OS_MACOSX)
void VerifyCertificateSignature(const std::string& der_cert,
const std::vector<uint8>& der_spki) {
crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
CERTSignedData sd;
memset(&sd, 0, sizeof(sd));
SECItem der_cert_item = {
siDERCertBuffer,
reinterpret_cast<unsigned char*>(const_cast<char*>(der_cert.data())),
static_cast<unsigned int>(der_cert.size())
};
SECStatus rv = SEC_ASN1DecodeItem(arena.get(), &sd,
SEC_ASN1_GET(CERT_SignedDataTemplate),
&der_cert_item);
ASSERT_EQ(SECSuccess, rv);
SECItem* signature_algorithm = SEC_ASN1EncodeItem(
arena.get(),
NULL,
&sd.signatureAlgorithm,
SEC_ASN1_GET(SECOID_AlgorithmIDTemplate));
ASSERT_TRUE(signature_algorithm);
crypto::SignatureVerifier verifier;
bool ok = verifier.VerifyInit(
signature_algorithm->data,
signature_algorithm->len,
sd.signature.data,
sd.signature.len / 8,
&der_spki[0],
der_spki.size());
ASSERT_TRUE(ok);
verifier.VerifyUpdate(sd.data.data,
sd.data.len);
ok = verifier.VerifyFinal();
EXPECT_TRUE(ok);
}
#endif
void VerifyDomainBoundCert(const std::string& domain,
const std::string& der_cert) {
static const char oid_string[] = "1.3.6.1.4.1.11129.2.1.6";
SECItem extension_object = {
siAsciiString,
(unsigned char*)domain.data(),
static_cast<unsigned int>(domain.size())
};
PLArenaPool* arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
SECItem* expected = SEC_ASN1EncodeItem(arena,
NULL,
&extension_object,
SEC_ASN1_GET(SEC_IA5StringTemplate));
ASSERT_NE(static_cast<SECItem*>(NULL), expected);
SECItem ob_cert_oid = { siDEROID, NULL, 0 };
SECStatus ok = SEC_StringToOID(arena, &ob_cert_oid,
oid_string, 0);
ASSERT_EQ(SECSuccess, ok);
SECOidTag ob_cert_oid_tag = SECOID_FindOIDTag(&ob_cert_oid);
ASSERT_NE(SEC_OID_UNKNOWN, ob_cert_oid_tag);
CERTCertificate* nss_cert = CreateNSSCertHandleFromBytes(
der_cert.data(), der_cert.size());
char* common_name = CERT_GetCommonName(&nss_cert->subject);
ASSERT_TRUE(common_name);
EXPECT_STREQ("anonymous.invalid", common_name);
PORT_Free(common_name);
EXPECT_EQ(SECSuccess, CERT_CertTimesValid(nss_cert));
SECItem actual = { siBuffer, NULL, 0 };
ok = CERT_FindCertExtension(nss_cert,
ob_cert_oid_tag,
&actual);
CERT_DestroyCertificate(nss_cert);
ASSERT_EQ(SECSuccess, ok);
PRBool result = SECITEM_ItemsAreEqual(expected, &actual);
ASSERT_TRUE(result);
SECITEM_FreeItem(&actual, PR_FALSE);
PORT_FreeArena(arena, PR_FALSE);
}
}
TEST(X509UtilNSSTest, CreateKeyAndDomainBoundCertEC) {
std::string domain = "weborigin.com";
base::Time now = base::Time::Now();
scoped_ptr<crypto::ECPrivateKey> private_key;
std::string der_cert;
ASSERT_TRUE(x509_util::CreateKeyAndDomainBoundCertEC(
domain, 1,
now,
now + base::TimeDelta::FromDays(1),
&private_key,
&der_cert));
VerifyDomainBoundCert(domain, der_cert);
#if !defined(OS_WIN) && !defined(OS_MACOSX)
std::vector<uint8> spki;
ASSERT_TRUE(private_key->ExportPublicKey(&spki));
VerifyCertificateSignature(der_cert, spki);
#endif
}
}