Bug 927016 - Create EV testsuite in xpcshell. r=keeler

This commit is contained in:
Camilo Viecco 2013-11-21 13:40:31 -08:00
parent 3d01d25dc6
commit c372fc1c9c
23 changed files with 406 additions and 4 deletions

View File

@ -269,6 +269,8 @@ CertVerifier::VerifyCert(CERTCertificate * cert,
("VerifyCert: successful CERT_PKIXVerifyCert(ev) \n"));
goto pkix_done;
}
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
("VerifyCert: failed CERT_PKIXVerifyCert(ev)\n"));
if (validationChain && *validationChain) {
// There SHOULD not be a validation chain on failure, asserion here for

View File

@ -111,8 +111,15 @@ static struct nsMyTrustedEVInfo myTrustedEVInfos[] = {
* as an existing entry, then please use the same oid_name.
*/
#ifdef DEBUG
/* Debug EV certificates should all use the OID (repeating EV OID is OK):
* 1.3.6.1.4.1.13769.666.666.666.1.500.9.1.
* If you add or remove debug EV certs you must also modify IdentityInfoInit
* (there is another #ifdef DEBUG section there) so that the correct number of
* certs are skipped as these debug EV certs are NOT part of the default trust
* store.
*/
{
// This is the testing EV signature.
// This is the testing EV signature. (mochitest)
// C=US, ST=CA, L=Mountain View, O=Mozilla - EV debug test CA, OU=Security Engineering, CN=EV Testing (untrustworthy) CA/name=ev-test-ca/emailAddress=charlatan@testing.example.com
"1.3.6.1.4.1.13769.666.666.666.1.500.9.1",
"DEBUGtesting EV OID",
@ -126,6 +133,20 @@ static struct nsMyTrustedEVInfo myTrustedEVInfos[] = {
"AK/FPSJmJkky",
nullptr
},
{
// This is the testing EV signature (xpcshell) (RSA)
// CN=XPCShell EV Testing (untrustworthy) CA,OU=Security Engineering,O=Mozilla - EV debug test CA,L=Mountain View,ST=CA,C=US"
"1.3.6.1.4.1.13769.666.666.666.1.500.9.1",
"DEBUGtesting EV OID",
SEC_OID_UNKNOWN,
"9C:62:EF:DB:AE:F9:EB:36:58:FB:3B:D3:47:64:93:9D:86:29:6A:E0",
"MIGnMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWlu"
"IFZpZXcxIzAhBgNVBAoMGk1vemlsbGEgLSBFViBkZWJ1ZyB0ZXN0IENBMR0wGwYD"
"VQQLDBRTZWN1cml0eSBFbmdpbmVlcmluZzEvMC0GA1UEAwwmWFBDU2hlbGwgRVYg"
"VGVzdGluZyAodW50cnVzdHdvcnRoeSkgQ0E=",
"At+3zdo=",
nullptr
},
#endif
{
// OU=Security Communication EV RootCA1,O="SECOM Trust Systems CO.,LTD.",C=JP
@ -1111,8 +1132,8 @@ nsNSSComponent::IdentityInfoInit()
entry.cert = CERT_FindCertByIssuerAndSN(nullptr, &ias);
#ifdef DEBUG
// The debug CA info is at position 0, and is NOT on the NSS root db
if (iEV != 0) {
// The debug CA certs are at positions 0-1, and are NOT in the NSS root db.
if (iEV > 1) {
NS_ASSERTION(entry.cert, "Could not find EV root in NSS storage");
}
#endif

View File

@ -15,6 +15,9 @@ let { ctypes } = Cu.import("resource://gre/modules/ctypes.jsm");
let gIsWindows = ("@mozilla.org/windows-registry-key;1" in Cc);
const isDebugBuild = Cc["@mozilla.org/xpcom/debug;1"]
.getService(Ci.nsIDebug2).isDebugBuild;
const SEC_ERROR_BASE = Ci.nsINSSErrorsService.NSS_SEC_ERROR_BASE;
// Sort in numerical order

View File

@ -6,6 +6,7 @@
import os
import random
import pexpect
def init_dsa(db_dir):
"""
@ -17,7 +18,7 @@ def init_dsa(db_dir):
db_dir -- location of the temporary params for the certificate
"""
dsa_key_params = db_dir + "/dsa_param.pem"
os.system ("openssl dsaparam -out "+ dsa_key_params + " 2048")
os.system("openssl dsaparam -out " + dsa_key_params + " 2048")
def generate_cert_generic(db_dir, dest_dir, serial_num, key_type, name,
@ -136,4 +137,38 @@ def generate_int_and_ee(db_dir, dest_dir, ca_key, ca_cert, name, int_ext_text,
return int_key, int_cert, ee_key, ee_cert
def generate_pkcs12(db_dir, dest_dir, der_cert_filename, key_pem_filename,
prefix):
"""
Generate a pkcs12 file for a given certificate name (in der format) and
a key filename (key in pem format). The output file will have an empty
password.
Arguments:
input:
db_dir -- location of the temporary params for the certificate
dest_dir -- location of the x509 cert
der_cert_filename -- the filename of the certificate to be included in the
output file (DER format)
key_pem_filename -- the filename of the private key of the certificate to
(PEM format)
prefix -- the name to be prepended to the output pkcs12 file.
output:
pk12_filename -- the filename of the outgoing pkcs12 output file
"""
#make pem cert file from der filename
pem_cert_filename = db_dir + "/" + prefix + ".pem"
pk12_filename = dest_dir + "/" + prefix + ".p12"
os.system("openssl x509 -inform der -in " + der_cert_filename + " -out " +
pem_cert_filename )
#now make pkcs12 file
child = pexpect.spawn("openssl pkcs12 -export -in " + pem_cert_filename +
" -inkey " + key_pem_filename + " -out " +
pk12_filename)
child.expect('Enter Export Password:')
child.sendline('')
child.expect('Verifying - Enter Export Password:')
child.sendline('')
child.expect(pexpect.EOF)
return pk12_filename

View File

@ -0,0 +1,103 @@
// -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
"use strict";
do_get_profile(); // must be called before getting nsIX509CertDB
const certdb = Cc["@mozilla.org/security/x509certdb;1"]
.getService(Ci.nsIX509CertDB);
// This is the list of certificates needed for the test
// The certificates prefixed by 'int-' are intermediates
let certList = [
// Test for successful EV validation
'int-ev-valid',
'ev-valid',
// Testing a root that looks like EV but is not EV enabled
'int-non-ev-root',
'non-ev-root',
]
function load_ca(ca_name) {
var ca_filename = ca_name + ".der";
addCertFromFile(certdb, "test_ev_certs/" + ca_filename, 'CTu,CTu,CTu');
}
var gHttpServer;
var gOCSPResponseCounter = 0;
function start_ocsp_responder() {
const SERVER_PORT = 8888;
gHttpServer = new HttpServer();
gHttpServer.registerPrefixHandler("/",
function handleServerCallback(aRequest, aResponse) {
let cert_nick = aRequest.path.slice(1, aRequest.path.length - 1);
do_print("Generating ocsp response for '" + cert_nick + "'");
aResponse.setStatusLine(aRequest.httpVersion, 200, "OK");
aResponse.setHeader("Content-Type", "application/ocsp-response");
// now we generate the response
let ocsp_request_desc = new Array();
ocsp_request_desc.push("good");
ocsp_request_desc.push(cert_nick);
ocsp_request_desc.push("unused_arg");
let arg_array = new Array();
arg_array.push(ocsp_request_desc);
let retArray = generateOCSPResponses(arg_array, "test_ev_certs");
let responseBody = retArray[0];
aResponse.bodyOutputStream.write(responseBody, responseBody.length);
gOCSPResponseCounter++;
});
gHttpServer.identity.setPrimary("http", "www.example.com", SERVER_PORT);
gHttpServer.start(SERVER_PORT);
}
function check_ee_for_ev(cert_name, expected_ev) {
let cert = certdb.findCertByNickname(null, cert_name);
let hasEVPolicy = {};
let verifiedChain = {};
let error = certdb.verifyCertNow(cert, certificateUsageSSLServer,
0, verifiedChain, hasEVPolicy);
if (isDebugBuild) {
do_check_eq(hasEVPolicy.value, expected_ev);
} else {
do_check_false(hasEVPolicy.value);
}
do_check_eq(0, error);
}
function run_test() {
for (let i = 0 ; i < certList.length; i++) {
let cert_filename = certList[i] + ".der";
addCertFromFile(certdb, "test_ev_certs/" + cert_filename, ',,');
}
load_ca("evroot");
load_ca("non-evroot-ca");
// setup and start ocsp responder
Services.prefs.setCharPref("network.dns.localDomains", 'www.example.com');
start_ocsp_responder();
run_next_test();
}
add_test(function() {
check_ee_for_ev("ev-valid", true);
run_next_test();
});
add_test(function() {
check_ee_for_ev("non-ev-root", false);
run_next_test();
});
// The following test should be the last as it performs cleanups
add_test(function() {
do_check_eq(4, gOCSPResponseCounter);
gHttpServer.stop(run_next_test);
});

Binary file not shown.

View File

@ -0,0 +1,59 @@
#!/usr/bin/python
# after runing this file you MUST modify nsIdentityinfo.cpp to change the
# fingerprint of the evroot
import tempfile, os, sys
import random
import pexpect
import subprocess
import shutil
libpath = os.path.abspath('../psm_common_py')
sys.path.append(libpath)
import CertUtils
dest_dir = os.getcwd()
db = tempfile.mkdtemp()
CA_basic_constraints = "basicConstraints = critical, CA:TRUE\n"
CA_min_ku = "keyUsage = critical, digitalSignature, keyCertSign, cRLSign\n"
subject_key_ident = "subjectKeyIdentifier = hash\n"
def generate_root_cert(db_dir, dest_dir, prefix, ext_text):
serial_num = 12343299546
name = prefix
key_name = dest_dir + "/" + name + ".key"
os.system ("openssl genpkey -algorithm RSA -out " + key_name +
" -pkeyopt rsa_keygen_bits:2048")
csr_name = dest_dir + "/" + name + ".csr"
os.system ("openssl req -new -key " + key_name + " -days 3650" +
" -extensions v3_ca -batch -out " + csr_name +
" -utf8 -subj '/C=US/ST=CA/L=Mountain View" +
"/O=Mozilla - EV debug test CA/OU=Security Engineering" +
"/CN=XPCShell EV Testing (untrustworthy) CA'")
extensions_filename = db_dir + "/openssl-exts"
f = open(extensions_filename, 'w')
f.write(ext_text)
f.close()
cert_name = dest_dir + "/" + name + ".der"
signer_key_filename = key_name
os.system ("openssl x509 -req -sha256 -days 3650 -in " + csr_name +
" -signkey " + signer_key_filename +
" -set_serial " + str(serial_num) +
" -extfile " + extensions_filename +
" -outform DER -out " + cert_name)
return key_name, cert_name
prefix = "evroot"
[ca_key, ca_cert] = generate_root_cert(db, dest_dir, prefix,
CA_basic_constraints +
CA_min_ku + subject_key_ident)
CertUtils.generate_pkcs12(db, dest_dir, ca_cert, ca_key, prefix)
print ("You now MUST modify nsIdentityinfo.cpp to ensure the xpchell debug " +
"certificate there matches this newly generated one\n")

View File

@ -0,0 +1,18 @@
-----BEGIN CERTIFICATE REQUEST-----
MIIC7TCCAdUCAQAwgacxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UE
BwwNTW91bnRhaW4gVmlldzEjMCEGA1UECgwaTW96aWxsYSAtIEVWIGRlYnVnIHRl
c3QgQ0ExHTAbBgNVBAsMFFNlY3VyaXR5IEVuZ2luZWVyaW5nMS8wLQYDVQQDDCZY
UENTaGVsbCBFViBUZXN0aW5nICh1bnRydXN0d29ydGh5KSBDQTCCASIwDQYJKoZI
hvcNAQEBBQADggEPADCCAQoCggEBAJr67bfi/uwFBoNZUeL5XgA69ITW7zhPS429
1sMBJyiBizHzwPXE+IlmuEMJaP6VKaICX95zpA0yLCr4QxCckTUIMoHmlgSI7yiZ
Rfno4ck1O/U9rCUzzVzkOjyjw7HrOE+kdTeKJyNCDTURjtIgkz0vWVn9VsUcgwyV
IEyy22Wbaz/JyVgHT5GiIeE0b/ZkypU+BE9I2Pjrjk/PY8ANdJjsowxzZoBQvpfp
yRqPRI9D3Qulw+kTVbBqzV0vpHcNEji2qnfmIl2zEfdbMMVTmXX2iPUczRZ1eI/t
3m+fEH1sLr0JtT1zMZys8RgyPSP9aEskbfAasM/2vuqmmKO+Ew8CAwEAAaAAMA0G
CSqGSIb3DQEBBQUAA4IBAQANkAdB2CvolWXZzZT/aJapKym19Lqs7r1spDEWJO9L
ga7+vSoeVEaBoaWU+tb3HXv5jIw3yn+Vnlgg/jkO7m0dZGyPxd9H0aqMhv5f5vC9
te8d5BYwGtmPzbIILIxzoUx5uwSZNKbKu3poQnuoMQDy7h4fz2JYj03nh6ey/dyi
YmZJWiuOqhvh7wwwRvM8XPL3fEAxSbfA6gblTInt6r2wVOToKbCjGmiB7DSk+QQU
ZxHDdCKciW7GKRN8t6CoIcExbFLfQbmhFhH53d2YHDTExBCByMuvPtkx9rC38nZq
dY+Qkg/Rz9++y2+JXlg8/nnG5XdWDJSOI6fl+rk91RUD
-----END CERTIFICATE REQUEST-----

View File

@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQC1SYlcnQAQjRGh
+Z+HqePRpdtd+uzxiNpXv2QTaI8s5HIs/xCQOMF0Ask6Kkc9vShq7T/c02PPWikU
dwG92BjXYVv5NWvV08gzaqqMCXE2igbDzURhuT5RQk4XRLsuqtRqqzjOGWghlh+H
cUoWY2k/CXYc301roSXqzse+Jw04j3ifbN94rjFE7SjEXnkpOGOnoipImAo2pA5y
1XnJuSXf+MeTNi/9aJenwXVMXpfJZ8Pq3RquiqLMzjSKAWm4Diii1wwalgxvM18t
oJubZD9av7pJ6Kqpgelg4n2HSAvdVd2UF/oYUJ+7VUzPgaQ5fouoEoo0vfJ4ZcGJ
5XNPsikFAgMBAAECggEBAJg9VPlNb0x26yPW+T14UjUwz3Ow0WJUxueBdo1F9VaB
0dAvsr0qrGq8HDiYYJNcUqDY9BSCAQOUd4MUHYZL/zCANjilwBUlcK6dGPPYyhY+
+0dbDd3zLn4W7HVl5rteAlxBxcZuV6A87eVUIh+DBFNHosTEUcPc5Ha3h84MBXJE
vp4E7xMRjbuz1eCmzIcCnq/Upp7ZsUdZsV452KmITlb1TS+asBPw0V8xipq2svc9
HsPJ/idK6JQxoQZAvniZsAEcXlCToYNHCGid4QBjTaveYPvWqu+joz3zSh829gwE
MDa3SNHJ7pjEAxoK/sYO/aCpkL5ST1YU6sT9s0pS+VECgYEA6twssz5f8co3a72V
vWoXd9LPT6xHVF6S0RpiCbnV5N7UeDRYHBabPIhHQqCeoYdQXBylVBTY0ltJdjLV
7CqqBSM0MPrUmJJ3en1o4Dj1YaO4lp5gsKJj3vv9pIqbD/OdlbyIsVJnyK3pe1EH
lI5B5DMknYf32xCdXXRYTYa8wdcCgYEAxZrldqIWRwJI2USlW56b+TKZ2jQexW5V
jrqCGrzhv1e3nPQR0pBMd0+duh8VGF9gewV0oIIF1uwotmo21jQjLqry/qN1Yauv
nWRLaNs4yZZMuMluwKxh66ZNBbRGVC9COXb1rN5OzJVTbS31eJVPk/DP2cWPt4ui
p23VrChNyIMCgYEAwdLvOQYzHFKspkgR+f5CW+somDIvs9tRAyzo1+n8MiQL6SAZ
zySA/NXjKYNxJxGLKlmhv+BsiD46REfz8DHNmuvQuNNo/Hl0DSzOjq2zJN9/CR6v
4VZDYdVJILAbBHEjDl5H2T+O0zljxRe8T8ePbYsfnrqFvM7bcDMCZQjbYoUCgYEA
hSG421aU376ASjFfnvybZSdcVJCs8qNFbWXm5hC/n2R/xnUB1PV3LyMqxwzN75/C
pt+kFcfEG2r8evnQfDygP37ZPAnwuZ8sMEQ0Mi8QcXCbvBuqTJFXX6apWeB9SZaV
bZXiK1eTi25HyNUf/t/Jv4iM4NGj5CtlqJvtS5HT5fUCgYEA3El7BrkgyL4LAHe3
mOl37vdEqQ7Cxdfmy7IkSPrHLagaMxgODYoC6DFGDH/H/TphL3uZMLYbeZ+OkI5j
LpugQJtqpwsDo7p4dCYmO1vVhD34R27bXRT2qGE+uvW5zVykL1+9KALgjk5J5XCf
UVFRDKpassHG6z7+kpXRbowlyRY=
-----END PRIVATE KEY-----

View File

@ -0,0 +1,129 @@
#!/usr/bin/python
import tempfile, os, sys
import random
import pexpect
import subprocess
import shutil
libpath = os.path.abspath('../psm_common_py')
sys.path.append(libpath)
import CertUtils
srcdir = os.getcwd()
db = tempfile.mkdtemp()
CA_basic_constraints = "basicConstraints = critical, CA:TRUE\n"
EE_basic_constraints = "basicConstraints = CA:FALSE\n"
EE_full_ku = ("keyUsage = digitalSignature, nonRepudiation, keyEncipherment, " +
" dataEncipherment, keyAgreement, keyCertSign, cRLSign\n")
CA_eku = ("extendedKeyUsage = critical, serverAuth, clientAuth, " +
"1.3.6.1.5.5.7.3.9\n")
Server_eku = "extendedKeyUsage = critical, serverAuth, clientAuth\n"
authority_key_ident = "authorityKeyIdentifier = keyid, issuer\n"
subject_key_ident = "subjectKeyIdentifier = hash\n"
aia_prefix = "authorityInfoAccess = OCSP;URI:http://www.example.com:8888/"
aia_suffix ="/\n"
intermediate_crl = ("crlDistributionPoints = " +
"URI:http://crl.example.com/root-ev.crl\n")
endentity_crl = ("crlDistributionPoints = " +
"URI:http://crl.example.com/ee-crl.crl\n")
mozilla_testing_ev_policy = ("certificatePolicies = @v3_ca_ev_cp\n\n" +
"[ v3_ca_ev_cp ]\n" +
"policyIdentifier = " +
"1.3.6.1.4.1.13769.666.666.666.1.500.9.1\n\n" +
"CPS.1 = \"http://mytestdomain.local/cps\"")
def import_untrusted_cert(certfile, nickname):
os.system("certutil -A -d . -n " + nickname + " -i " + certfile +
" -t ',,'")
def import_cert_and_pkcs12(certfile, pkcs12file, nickname, trustflags):
os.system(" certutil -A -d . -n " + nickname + " -i " + certfile + " -t '" +
trustflags + "'")
child = pexpect.spawn("pk12util -i " + pkcs12file + " -d .")
child.expect('Enter password for PKCS12 file:')
child.sendline('')
child.expect(pexpect.EOF)
def init_nss_db():
nss_db_files = [ "cert8.db", "key3.db", "secmod.db" ]
for file in nss_db_files:
if os.path.isfile(file):
os.remove(file)
#now create DB
child = pexpect.spawn("certutil -N -d .")
child.expect("Enter new password:")
child.sendline('')
child.expect('Re-enter password:')
child.sendline('')
child.expect(pexpect.EOF)
import_cert_and_pkcs12("evroot.der", "evroot.p12", "evroot", "C,C,C")
def generate_certs():
init_nss_db()
ca_cert = 'evroot.der'
ca_key = 'evroot.key'
prefix = "ev-valid"
key_type = 'rsa'
ee_ext_text = (EE_basic_constraints + EE_full_ku + Server_eku +
authority_key_ident + aia_prefix + prefix + aia_suffix +
endentity_crl + mozilla_testing_ev_policy)
int_ext_text = (CA_basic_constraints + EE_full_ku + CA_eku +
authority_key_ident + subject_key_ident +
aia_prefix + "int-" + prefix + aia_suffix +
intermediate_crl + mozilla_testing_ev_policy)
[int_key, int_cert, ee_key, ee_cert] = CertUtils.generate_int_and_ee(db,
srcdir,
ca_key,
ca_cert,
prefix,
int_ext_text,
ee_ext_text,
key_type)
pk12file = CertUtils.generate_pkcs12(db, srcdir, int_cert, int_key,
"int-" + prefix)
import_cert_and_pkcs12(int_cert, pk12file, "int-" + prefix, ",,")
import_untrusted_cert(ee_cert, prefix)
[bad_ca_key, bad_ca_cert] = CertUtils.generate_cert_generic( db,
srcdir,
1,
'rsa',
'non-evroot-ca',
CA_basic_constraints + EE_full_ku +
authority_key_ident)
pk12file = CertUtils.generate_pkcs12(db, srcdir, bad_ca_cert, bad_ca_key,
"non-evroot-ca")
import_cert_and_pkcs12(bad_ca_cert, pk12file, "non-evroot-ca", "C,C,C")
prefix = "non-ev-root"
ee_ext_text = (EE_basic_constraints + EE_full_ku + Server_eku +
authority_key_ident + aia_prefix + prefix + aia_suffix +
endentity_crl + mozilla_testing_ev_policy)
int_ext_text = (CA_basic_constraints + EE_full_ku + CA_eku +
authority_key_ident + aia_prefix + "int-" + prefix +
aia_suffix + intermediate_crl + subject_key_ident +
mozilla_testing_ev_policy)
[int_key, int_cert, ee_key, ee_cert] = CertUtils.generate_int_and_ee(db,
srcdir,
bad_ca_key,
bad_ca_cert,
prefix,
int_ext_text,
ee_ext_text,
key_type)
pk12file = CertUtils.generate_pkcs12(db, srcdir, int_cert, int_key,
"int-" + prefix)
import_cert_and_pkcs12(int_cert, pk12file, "int-" + prefix, ",,")
import_untrusted_cert(ee_cert, prefix)
generate_certs()

Binary file not shown.

View File

@ -6,6 +6,7 @@ support-files =
test_signed_apps/**
tlsserver/**
test_cert_signatures/**
test_ev_certs/**
[test_certificate_usages.js]
# Bug 676972: test fails consistently on Android
@ -39,3 +40,6 @@ fail-if = os == "android"
[test_cert_signatures.js]
# Bug 676972: test fails consistently on Android
fail-if = os == "android"
[test_ev_certs.js]
# Bug 676972: test fails consistently on Android
fail-if = os == "android"