diff options
Diffstat (limited to '')
20 files changed, 632 insertions, 0 deletions
diff --git a/security/manager/ssl/tests/unit/test_content_signing.js b/security/manager/ssl/tests/unit/test_content_signing.js new file mode 100644 index 0000000000..7e96ea2df6 --- /dev/null +++ b/security/manager/ssl/tests/unit/test_content_signing.js @@ -0,0 +1,431 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 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"; + +// These tests ensure content signatures are working correctly. + +const TEST_DATA_DIR = "test_content_signing/"; + +const ONECRL_NAME = "oneCRL-signer.mozilla.org"; +const ABOUT_NEWTAB_NAME = "remotenewtab.content-signature.mozilla.org"; +var VERIFICATION_HISTOGRAM = Services.telemetry.getHistogramById( + "CONTENT_SIGNATURE_VERIFICATION_STATUS" +); +var ERROR_HISTOGRAM = Services.telemetry.getKeyedHistogramById( + "CONTENT_SIGNATURE_VERIFICATION_ERRORS" +); + +function getSignatureVerifier() { + return Cc["@mozilla.org/security/contentsignatureverifier;1"].getService( + Ci.nsIContentSignatureVerifier + ); +} + +function getCertHash(name) { + let cert = constructCertFromFile(`test_content_signing/${name}.pem`); + return cert.sha256Fingerprint.replace(/:/g, ""); +} + +function loadChain(prefix, names) { + let chain = []; + for (let name of names) { + let filename = `${prefix}_${name}.pem`; + chain.push(readFile(do_get_file(filename))); + } + return chain; +} + +function check_telemetry(expected_index, expected, expectedId) { + for (let i = 0; i < 10; i++) { + let expected_value = 0; + if (i == expected_index) { + expected_value = expected; + } + let errorSnapshot = ERROR_HISTOGRAM.snapshot(); + for (let k in errorSnapshot) { + // We clear the histogram every time so there should be only this one + // category. + equal(k, expectedId); + equal(errorSnapshot[k].values[i] || 0, expected_value); + } + equal( + VERIFICATION_HISTOGRAM.snapshot().values[i] || 0, + expected_value, + "count " + + i + + ": " + + VERIFICATION_HISTOGRAM.snapshot().values[i] + + " expected " + + expected_value + ); + } + VERIFICATION_HISTOGRAM.clear(); + ERROR_HISTOGRAM.clear(); +} + +add_task(async function run_test() { + // set up some data + const DATA = readFile(do_get_file(TEST_DATA_DIR + "test.txt")); + const GOOD_SIGNATURE = + "p384ecdsa=" + + readFile(do_get_file(TEST_DATA_DIR + "test.txt.signature")).trim(); + + const BAD_SIGNATURE = + "p384ecdsa=WqRXFQ7tnlVufpg7A-ZavXvWd2Zln0o4woHBy26C2r" + + "UWM4GJke4pE8ecHiXoi-7KnZXty6Pe3s4o3yAIyKDP9jUC52Ek1G" + + "q25j_X703nP5rk5gM1qz5Fe-qCWakPPl6L"; + + let remoteNewTabChain = loadChain(TEST_DATA_DIR + "content_signing", [ + "remote_newtab_ee", + "int", + ]); + + let oneCRLChain = loadChain(TEST_DATA_DIR + "content_signing", [ + "onecrl_ee", + "int", + ]); + + let oneCRLBadKeyChain = loadChain(TEST_DATA_DIR + "content_signing", [ + "onecrl_wrong_key_ee", + "int", + ]); + + let noSANChain = loadChain(TEST_DATA_DIR + "content_signing", [ + "onecrl_no_SAN_ee", + "int", + ]); + + let expiredOneCRLChain = loadChain(TEST_DATA_DIR + "content_signing", [ + "onecrl_ee_expired", + "int", + ]); + + let notValidYetOneCRLChain = loadChain(TEST_DATA_DIR + "content_signing", [ + "onecrl_ee_not_valid_yet", + "int", + ]); + + // Check signature verification works without throwing when using the wrong + // root + VERIFICATION_HISTOGRAM.clear(); + let chain1 = oneCRLChain.join("\n"); + let verifier = getSignatureVerifier(); + ok( + !(await verifier.asyncVerifyContentSignature( + DATA, + GOOD_SIGNATURE, + chain1, + ONECRL_NAME, + Ci.nsIContentSignatureVerifier.ContentSignatureProdRoot + )), + "using the wrong root, signatures should fail to verify but not throw." + ); + // Check for generic chain building error. + check_telemetry(6, 1, getCertHash("content_signing_onecrl_ee")); + + // Check good signatures from good certificates with the correct SAN + ok( + await verifier.asyncVerifyContentSignature( + DATA, + GOOD_SIGNATURE, + chain1, + ONECRL_NAME, + Ci.nsIX509CertDB.AppXPCShellRoot + ), + "A OneCRL signature should verify with the OneCRL chain" + ); + let chain2 = remoteNewTabChain.join("\n"); + ok( + await verifier.asyncVerifyContentSignature( + DATA, + GOOD_SIGNATURE, + chain2, + ABOUT_NEWTAB_NAME, + Ci.nsIX509CertDB.AppXPCShellRoot + ), + "A newtab signature should verify with the newtab chain" + ); + // Check for valid signature + check_telemetry(0, 2, getCertHash("content_signing_remote_newtab_ee")); + + // Check a bad signature when a good chain is provided + chain1 = oneCRLChain.join("\n"); + ok( + !(await verifier.asyncVerifyContentSignature( + DATA, + BAD_SIGNATURE, + chain1, + ONECRL_NAME, + Ci.nsIX509CertDB.AppXPCShellRoot + )), + "A bad signature should not verify" + ); + // Check for invalid signature + check_telemetry(1, 1, getCertHash("content_signing_onecrl_ee")); + + // Check a good signature from cert with good SAN but a different key than the + // one used to create the signature + let badKeyChain = oneCRLBadKeyChain.join("\n"); + ok( + !(await verifier.asyncVerifyContentSignature( + DATA, + GOOD_SIGNATURE, + badKeyChain, + ONECRL_NAME, + Ci.nsIX509CertDB.AppXPCShellRoot + )), + "A signature should not verify if the signing key is wrong" + ); + // Check for wrong key in cert. + check_telemetry(9, 1, getCertHash("content_signing_onecrl_wrong_key_ee")); + + // Check a good signature from cert with good SAN but a different key than the + // one used to create the signature (this time, an RSA key) + let rsaKeyChain = oneCRLBadKeyChain.join("\n"); + ok( + !(await verifier.asyncVerifyContentSignature( + DATA, + GOOD_SIGNATURE, + rsaKeyChain, + ONECRL_NAME, + Ci.nsIX509CertDB.AppXPCShellRoot + )), + "A signature should not verify if the signing key is wrong (RSA)" + ); + // Check for wrong key in cert. + check_telemetry(9, 1, getCertHash("content_signing_onecrl_wrong_key_ee")); + + // Check a good signature from cert with good SAN but with no path to root + let missingInt = [oneCRLChain[0], oneCRLChain[2]].join("\n"); + ok( + !(await verifier.asyncVerifyContentSignature( + DATA, + GOOD_SIGNATURE, + missingInt, + ONECRL_NAME, + Ci.nsIX509CertDB.AppXPCShellRoot + )), + "A signature should not verify if the chain is incomplete (missing int)" + ); + // Check for generic chain building error. + check_telemetry(6, 1, getCertHash("content_signing_onecrl_ee")); + + // Check good signatures from good certificates with the wrong SANs + chain1 = oneCRLChain.join("\n"); + ok( + !(await verifier.asyncVerifyContentSignature( + DATA, + GOOD_SIGNATURE, + chain1, + ABOUT_NEWTAB_NAME, + Ci.nsIX509CertDB.AppXPCShellRoot + )), + "A OneCRL signature should not verify if we require the newtab SAN" + ); + // Check for invalid EE cert. + check_telemetry(7, 1, getCertHash("content_signing_onecrl_ee")); + + chain2 = remoteNewTabChain.join("\n"); + ok( + !(await verifier.asyncVerifyContentSignature( + DATA, + GOOD_SIGNATURE, + chain2, + ONECRL_NAME, + Ci.nsIX509CertDB.AppXPCShellRoot + )), + "A newtab signature should not verify if we require the OneCRL SAN" + ); + // Check for invalid EE cert. + check_telemetry(7, 1, getCertHash("content_signing_remote_newtab_ee")); + + // Check good signatures with good chains with some other invalid names + ok( + !(await verifier.asyncVerifyContentSignature( + DATA, + GOOD_SIGNATURE, + chain1, + "", + Ci.nsIX509CertDB.AppXPCShellRoot + )), + "A signature should not verify if the SANs do not match an empty name" + ); + // Check for invalid EE cert. + check_telemetry(7, 1, getCertHash("content_signing_onecrl_ee")); + + // Test expired certificate. + let chainExpired = expiredOneCRLChain.join("\n"); + ok( + !(await verifier.asyncVerifyContentSignature( + DATA, + GOOD_SIGNATURE, + chainExpired, + "", + Ci.nsIX509CertDB.AppXPCShellRoot + )), + "A signature should not verify if the signing certificate is expired" + ); + // Check for expired cert. + check_telemetry(4, 1, getCertHash("content_signing_onecrl_ee_expired")); + + // Test not valid yet certificate. + let chainNotValidYet = notValidYetOneCRLChain.join("\n"); + ok( + !(await verifier.asyncVerifyContentSignature( + DATA, + GOOD_SIGNATURE, + chainNotValidYet, + "", + Ci.nsIX509CertDB.AppXPCShellRoot + )), + "A signature should not verify if the signing certificate is not valid yet" + ); + // Check for not yet valid cert. + check_telemetry(5, 1, getCertHash("content_signing_onecrl_ee_not_valid_yet")); + + let relatedName = "subdomain." + ONECRL_NAME; + ok( + !(await verifier.asyncVerifyContentSignature( + DATA, + GOOD_SIGNATURE, + chain1, + relatedName, + Ci.nsIX509CertDB.AppXPCShellRoot + )), + "A signature should not verify if the SANs do not match a related name" + ); + + let randomName = + "\xb1\x9bU\x1c\xae\xaa3\x19H\xdb\xed\xa1\xa1\xe0\x81\xfb" + + "\xb2\x8f\x1cP\xe5\x8b\x9c\xc2s\xd3\x1f\x8e\xbbN"; + ok( + !(await verifier.asyncVerifyContentSignature( + DATA, + GOOD_SIGNATURE, + chain1, + randomName, + Ci.nsIX509CertDB.AppXPCShellRoot + )), + "A signature should not verify if the SANs do not match a random name" + ); + + // check good signatures with chains that have strange or missing SANs + chain1 = noSANChain.join("\n"); + ok( + !(await verifier.asyncVerifyContentSignature( + DATA, + GOOD_SIGNATURE, + chain1, + ONECRL_NAME, + Ci.nsIX509CertDB.AppXPCShellRoot + )), + "A signature should not verify if the SANs do not match a supplied name" + ); + + // Check malformed signature data + chain1 = oneCRLChain.join("\n"); + let bad_signatures = [ + // wrong length + "p384ecdsa=WqRXFQ7tnlVufpg7A-ZavXvWd2Zln0o4woHBy26C2rUWM4GJke4pE8ecHiXoi-" + + "7KnZXty6Pe3s4o3yAIyKDP9jUC52Ek1Gq25j_X703nP5rk5gM1qz5Fe-qCWakPPl6L==", + // incorrectly encoded + "p384ecdsa='WqRXFQ7tnlVufpg7A-ZavXvWd2Zln0o4woHBy26C2rUWM4GJke4pE8ecHiXoi" + + "-7KnZXty6Pe3s4o3yAIyKDP9jUC52Ek1Gq25j_X703nP5rk5gM1qz5Fe-qCWakPPl6L=", + // missing directive + "other_directive=WqRXFQ7tnlVufpg7A-ZavXvWd2Zln0o4woHBy26C2rUWM4GJke4pE8ec" + + "HiXoi-7KnZXty6Pe3s4o3yAIyKDP9jUC52Ek1Gq25j_X703nP5rk5gM1qz5Fe-qCWakPPl6L", + // actually sha256 with RSA + "p384ecdsa=XS_jiQsS5qlzQyUKaA1nAnQn_OvxhvDfKybflB8Xe5gNH1wNmPGK1qN-jpeTfK" + + "6ob3l3gCTXrsMnOXMeht0kPP3wLfVgXbuuO135pQnsv0c-ltRMWLe56Cm4S4Z6E7WWKLPWaj" + + "jhAcG5dZxjffP9g7tuPP4lTUJztyc4d1z_zQZakEG7R0vN7P5_CaX9MiMzP4R7nC3H4Ba6yi" + + "yjlGvsZwJ_C5zDQzWWs95czUbMzbDScEZ_7AWnidw91jZn-fUK3xLb6m-Zb_b4GAqZ-vnXIf" + + "LpLB1Nzal42BQZn7i4rhAldYdcVvy7rOMlsTUb5Zz6vpVW9LCT9lMJ7Sq1xbU-0g==", + ]; + for (let badSig of bad_signatures) { + await Assert.rejects( + verifier.asyncVerifyContentSignature( + DATA, + badSig, + chain1, + ONECRL_NAME, + Ci.nsIX509CertDB.AppXPCShellRoot + ), + /NS_ERROR/, + `Bad or malformed signature "${badSig}" should be rejected` + ); + } + + // Check malformed and missing certificate chain data + let chainSuffix = [oneCRLChain[1], oneCRLChain[2]].join("\n"); + let badChains = [ + // no data + "", + // completely wrong data + "blah blah \n blah", + ]; + + let badSections = [ + // data that looks like PEM but isn't + "-----BEGIN CERTIFICATE-----\nBSsPRlYp5+gaFMRIczwUzaioRfteCjr94xyz0g==\n", + // data that will start to parse but won't base64decode + "-----BEGIN CERTIFICATE-----\nnon-base64-stuff\n-----END CERTIFICATE-----", + // data with garbage outside of PEM sections + "this data is garbage\n-----BEGIN CERTIFICATE-----\nnon-base64-stuff\n" + + "-----END CERTIFICATE-----", + ]; + + for (let badSection of badSections) { + // ensure we test each bad section on its own... + badChains.push(badSection); + // ... and as part of a chain with good certificates + badChains.push(badSection + "\n" + chainSuffix); + } + + for (let badChain of badChains) { + await Assert.rejects( + verifier.asyncVerifyContentSignature( + DATA, + GOOD_SIGNATURE, + badChain, + ONECRL_NAME, + Ci.nsIX509CertDB.AppXPCShellRoot + ), + /NS_ERROR/, + `Bad chain data starting "${badChain.substring(0, 80)}" ` + + "should be rejected" + ); + } + + ok( + !(await verifier.asyncVerifyContentSignature( + DATA + "appended data", + GOOD_SIGNATURE, + chain1, + ONECRL_NAME, + Ci.nsIX509CertDB.AppXPCShellRoot + )), + "A good signature should not verify if the data is tampered with (append)" + ); + ok( + !(await verifier.asyncVerifyContentSignature( + "prefixed data" + DATA, + GOOD_SIGNATURE, + chain1, + ONECRL_NAME, + Ci.nsIX509CertDB.AppXPCShellRoot + )), + "A good signature should not verify if the data is tampered with (prefix)" + ); + ok( + !(await verifier.asyncVerifyContentSignature( + DATA.replace(/e/g, "i"), + GOOD_SIGNATURE, + chain1, + ONECRL_NAME, + Ci.nsIX509CertDB.AppXPCShellRoot + )), + "A good signature should not verify if the data is tampered with (modify)" + ); +}); diff --git a/security/manager/ssl/tests/unit/test_content_signing/content_signing_int.pem b/security/manager/ssl/tests/unit/test_content_signing/content_signing_int.pem new file mode 100644 index 0000000000..d615eccf22 --- /dev/null +++ b/security/manager/ssl/tests/unit/test_content_signing/content_signing_int.pem @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC8TCCAdmgAwIBAgIUNZb51bNpKyzQtWTCj5zrdME7cKYwDQYJKoZIhvcNAQEL +BQAwKTEnMCUGA1UEAwweeHBjc2hlbGwgc2lnbmVkIGFwcHMgdGVzdCByb290MCIY +DzIwMjExMTI3MDAwMDAwWhgPMjAyNDAyMDUwMDAwMDBaMBExDzANBgNVBAMMBmlu +dC1DQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALqIUahEjhbWQf1u +togGNhA9PBPZ6uQ1SrTs9WhXbCR7wcclqODYH72xnAabbhqG8mvir1p1a2pkcQh6 +pVqnRYf3HNUknAJ+zUP8HmnQOCApk6sgw0nk27lMwmtsDu0Vgg/xfq1pGrHTAjqL +KkHup3DgDw2N/WYLK7AkkqR9uYhheZCxV5A90jvF4LhIH6g304hD7ycW2FW3Zlqq +fgKQLzp7EIAGJMwcbJetlmFbt+KWEsB1MaMMkd20yvf8rR0l0wnvuRcOp2jhs3sv +Im9p47SKlWEd7ibWJZ2rkQhONsscJAQsvxaLL+Xxj5kXMbiz/kkj+nJRxDHVA6za +GAo17Y0CAwEAAaMlMCMwDAYDVR0TBAUwAwEB/zATBgNVHSUEDDAKBggrBgEFBQcD +AzANBgkqhkiG9w0BAQsFAAOCAQEAefvKJnF/4qRY9sf/jYCPhWyngBx6JhWFJKiy +IUHmejn9q/LUX3nskHXA4gAt+KF9hfk9Nx5naL5DaYOkvETawdrSw55Hvphi4MB2 +yHManuj+yplqr8rtDh8Tb2Wm/AeiBqKMTa4AFN9xPbKOrUAVgU+VsXlEIUmOzEI+ +E0HeeIoPCCa6vWPpwhKb4LUlVupe3toJHVbFSp2KcD4gCRsgK60lyqZBosAG8Sat +Vk7XLPv152/jl7j+pYqnlwabF/LEyVSqegVvvr481kgX8RyEjiPx2wNYYqUF3CPG +SE2lDXWy629KUGwTH9rUpayMqbfL5bQ9fSGA5vE9pT7vlbBaRg== +-----END CERTIFICATE----- diff --git a/security/manager/ssl/tests/unit/test_content_signing/content_signing_int.pem.certspec b/security/manager/ssl/tests/unit/test_content_signing/content_signing_int.pem.certspec new file mode 100644 index 0000000000..fc9dfd47ae --- /dev/null +++ b/security/manager/ssl/tests/unit/test_content_signing/content_signing_int.pem.certspec @@ -0,0 +1,4 @@ +issuer:xpcshell signed apps test root +subject:int-CA +extension:basicConstraints:cA, +extension:extKeyUsage:codeSigning diff --git a/security/manager/ssl/tests/unit/test_content_signing/content_signing_onecrl_RSA_ee.pem b/security/manager/ssl/tests/unit/test_content_signing/content_signing_onecrl_RSA_ee.pem new file mode 100644 index 0000000000..041fa0ebc1 --- /dev/null +++ b/security/manager/ssl/tests/unit/test_content_signing/content_signing_onecrl_RSA_ee.pem @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC8TCCAdmgAwIBAgIUfVErdg1uvVM/D2oapMLb9gSeabswDQYJKoZIhvcNAQEL +BQAwETEPMA0GA1UEAwwGaW50LUNBMCIYDzIwMjExMTI3MDAwMDAwWhgPMjAyNDAy +MDUwMDAwMDBaMBExDzANBgNVBAMMBmVlLVJTQTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBALqIUahEjhbWQf1utogGNhA9PBPZ6uQ1SrTs9WhXbCR7wccl +qODYH72xnAabbhqG8mvir1p1a2pkcQh6pVqnRYf3HNUknAJ+zUP8HmnQOCApk6sg +w0nk27lMwmtsDu0Vgg/xfq1pGrHTAjqLKkHup3DgDw2N/WYLK7AkkqR9uYhheZCx +V5A90jvF4LhIH6g304hD7ycW2FW3ZlqqfgKQLzp7EIAGJMwcbJetlmFbt+KWEsB1 +MaMMkd20yvf8rR0l0wnvuRcOp2jhs3svIm9p47SKlWEd7ibWJZ2rkQhONsscJAQs +vxaLL+Xxj5kXMbiz/kkj+nJRxDHVA6zaGAo17Y0CAwEAAaM9MDswEwYDVR0lBAww +CgYIKwYBBQUHAwMwJAYDVR0RBB0wG4IZb25lQ1JMLXNpZ25lci5tb3ppbGxhLm9y +ZzANBgkqhkiG9w0BAQsFAAOCAQEAOLPmVQpsFu7rL6Tc6TUQdS1/wnBDZeO3Q8uq +x7FSm7tyvrMwCx2pGGJATWIdH33amhRDe3fH5IB7dvFiQx0qDewROnE900ooOQCu +dsjKDzYurpGmlpYsBHtdFz8tEVgN2CUzfFLRTrJK0wAio5OqbyuZQwb8QBl/HMyk +aqG33hm/1t8gR7NLn4c03XtaK/xbBGC07aCijsWTj09UB5wgtB12p9Wt7IWrkh2B +9omSirPYgCWaD0wWJP1d1PlheeNeOYweNbEncjQlH+ukYjMzzZ3IVm7zFN1kit/W +M7enx5fdED/84092ZzuDheLYKaA63ysJhQvCCzOovWr0PuOnLg== +-----END CERTIFICATE----- diff --git a/security/manager/ssl/tests/unit/test_content_signing/content_signing_onecrl_RSA_ee.pem.certspec b/security/manager/ssl/tests/unit/test_content_signing/content_signing_onecrl_RSA_ee.pem.certspec new file mode 100644 index 0000000000..7b2a02bdaf --- /dev/null +++ b/security/manager/ssl/tests/unit/test_content_signing/content_signing_onecrl_RSA_ee.pem.certspec @@ -0,0 +1,4 @@ +issuer:int-CA +subject:ee-RSA +extension:extKeyUsage:codeSigning +extension:subjectAlternativeName:oneCRL-signer.mozilla.org diff --git a/security/manager/ssl/tests/unit/test_content_signing/content_signing_onecrl_ee.pem b/security/manager/ssl/tests/unit/test_content_signing/content_signing_onecrl_ee.pem new file mode 100644 index 0000000000..6f15597b6a --- /dev/null +++ b/security/manager/ssl/tests/unit/test_content_signing/content_signing_onecrl_ee.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICPzCCASegAwIBAgIUSRecknZ3alfumVeo6yV/3O5nvrswDQYJKoZIhvcNAQEL +BQAwETEPMA0GA1UEAwwGaW50LUNBMCIYDzIwMjExMTI3MDAwMDAwWhgPMjAyNDAy +MDUwMDAwMDBaMA0xCzAJBgNVBAMMAmVlMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE +oWhyQzYrXHsYifN5FUYVocc/tI3uhj4CKRXbYI4lLeS3Ey2ozpjoMVNOapwMCwnI +1jmt6DIG5bqBNHOhH6Mw4F2oyW5Dg/4nhz2pcQO+KIjP8ALwWvcaH93Mg3SqbqnO +oz0wOzATBgNVHSUEDDAKBggrBgEFBQcDAzAkBgNVHREEHTAbghlvbmVDUkwtc2ln +bmVyLm1vemlsbGEub3JnMA0GCSqGSIb3DQEBCwUAA4IBAQBElZXLzQGRPdygDJ33 +2LuNJiDU8lFXdDulPXcZAQjVXo5gy9XQfMtbTLzf07dpPuQntzJNbGuS4ypboEal +ixi2jYZHy/Q3CCxFk8jWi18auKES+uRF6qI3PK9RsXXxm7Xt0vk9akYwmmnuAJl9 +eYTCNZ0VaXANvv5GjuFczMHF08XTW1j2x81s0epmblgagcaMIcaq5nKSNuFt/2j/ +hXtGzNfI1njHIT8X6Fp4QeGqQiSlW90WVPoDPxfUHh8VvE/9Y0fnnHcDwGICb7LH +on1mz76mcXNwOgA+dBmHKS/5t7/PBT/F7+UuORfYdoFKrnc7npVYhQmH06ENKHMS +9Bmv +-----END CERTIFICATE----- diff --git a/security/manager/ssl/tests/unit/test_content_signing/content_signing_onecrl_ee.pem.certspec b/security/manager/ssl/tests/unit/test_content_signing/content_signing_onecrl_ee.pem.certspec new file mode 100644 index 0000000000..ab22807b9e --- /dev/null +++ b/security/manager/ssl/tests/unit/test_content_signing/content_signing_onecrl_ee.pem.certspec @@ -0,0 +1,5 @@ +issuer:int-CA +subject:ee +subjectKey:secp384r1 +extension:extKeyUsage:codeSigning +extension:subjectAlternativeName:oneCRL-signer.mozilla.org diff --git a/security/manager/ssl/tests/unit/test_content_signing/content_signing_onecrl_ee_expired.pem b/security/manager/ssl/tests/unit/test_content_signing/content_signing_onecrl_ee_expired.pem new file mode 100644 index 0000000000..ef22669f4d --- /dev/null +++ b/security/manager/ssl/tests/unit/test_content_signing/content_signing_onecrl_ee_expired.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICTjCCATagAwIBAgIUOQNrYQz01j0SirgoHMLKbtGL9RowDQYJKoZIhvcNAQEL +BQAwETEPMA0GA1UEAwwGaW50LUNBMCIYDzIwMTMwMTAxMDAwMDAwWhgPMjAxNDAx +MDEwMDAwMDBaMBwxGjAYBgNVBAMMEWVlLWludC1DQS1leHBpcmVkMHYwEAYHKoZI +zj0CAQYFK4EEACIDYgAEoWhyQzYrXHsYifN5FUYVocc/tI3uhj4CKRXbYI4lLeS3 +Ey2ozpjoMVNOapwMCwnI1jmt6DIG5bqBNHOhH6Mw4F2oyW5Dg/4nhz2pcQO+KIjP +8ALwWvcaH93Mg3SqbqnOoz0wOzATBgNVHSUEDDAKBggrBgEFBQcDAzAkBgNVHREE +HTAbghlvbmVDUkwtc2lnbmVyLm1vemlsbGEub3JnMA0GCSqGSIb3DQEBCwUAA4IB +AQBZJPo4llgMe5588+BnRLnFguspIiwMWmTeqCfi8VQBx/tUwRiTizbU7J2Yh9bo +yZEPKfPSP2o8J0eSUgvXdVOxU1fNRuocsVfXUlveq5x10ddjXBT9X4AY1mtR7HJw +hl/7269N8b4itfrfvZmCBToJayjv0I2N84bqjpOnXJ/iB5YVdk8oZIJDXWi4SR3B +E9IejwA1fikpt++RjpJSZ1BSNU7FfiyGGUonxHDoP/29znaOJnpAqaH5LVJCRkfN +H12vePBbunZd+ay5r+mMJPaXR+V2sY8OaOfcrPSHQLa8Eb/EEhBuITMKkOucohjx +zqvM6S2iOI9GbwHClybEHRO7 +-----END CERTIFICATE----- diff --git a/security/manager/ssl/tests/unit/test_content_signing/content_signing_onecrl_ee_expired.pem.certspec b/security/manager/ssl/tests/unit/test_content_signing/content_signing_onecrl_ee_expired.pem.certspec new file mode 100644 index 0000000000..48fd9c8cc7 --- /dev/null +++ b/security/manager/ssl/tests/unit/test_content_signing/content_signing_onecrl_ee_expired.pem.certspec @@ -0,0 +1,6 @@ +issuer:int-CA +subject:ee-int-CA-expired +subjectKey:secp384r1 +validity:20130101-20140101 +extension:extKeyUsage:codeSigning +extension:subjectAlternativeName:oneCRL-signer.mozilla.org diff --git a/security/manager/ssl/tests/unit/test_content_signing/content_signing_onecrl_ee_not_valid_yet.pem b/security/manager/ssl/tests/unit/test_content_signing/content_signing_onecrl_ee_not_valid_yet.pem new file mode 100644 index 0000000000..6cf5c6a312 --- /dev/null +++ b/security/manager/ssl/tests/unit/test_content_signing/content_signing_onecrl_ee_not_valid_yet.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICVDCCATygAwIBAgIUbV+rBAfhGRv/bU22A92xneoAy3owDQYJKoZIhvcNAQEL +BQAwETEPMA0GA1UEAwwGaW50LUNBMCIYDzIwNTAwMTAxMDAwMDAwWhgPMjA1MTAx +MDEwMDAwMDBaMCIxIDAeBgNVBAMMF2VlLWludC1DQS1ub3QteWV0LXZhbGlkMHYw +EAYHKoZIzj0CAQYFK4EEACIDYgAEoWhyQzYrXHsYifN5FUYVocc/tI3uhj4CKRXb +YI4lLeS3Ey2ozpjoMVNOapwMCwnI1jmt6DIG5bqBNHOhH6Mw4F2oyW5Dg/4nhz2p +cQO+KIjP8ALwWvcaH93Mg3SqbqnOoz0wOzATBgNVHSUEDDAKBggrBgEFBQcDAzAk +BgNVHREEHTAbghlvbmVDUkwtc2lnbmVyLm1vemlsbGEub3JnMA0GCSqGSIb3DQEB +CwUAA4IBAQAjXmLNn2kLa/FzNp7F3PqcSXuAO2jT31Y2g4pZnVqCDfMqplsl2ZFn +oam3wyQnepm3q9DD4BOAW9JFYR3wqnl9cBRNHlSGyjGM4qBpuSD6WxAz7EdFcRO6 +fcA50245fAuB45UJeYJ58QvIBv7AwoBGnqAI7ZDN3eIGopZIL56jiH7vO9WyQPWj +XZAWrXTG68rEf0RxXRtjUv9coFiuInT8+oyXB3NwK2EbaI5IeR+x3qIDEgNKk+t+ +PlE3NrtaAiK19p0s9RtQQilBKNmo+5irrUq/OD2H1aurDaAXpLTM5vLUpfyN3/qD +HzuZujaUIeMsRiXsIRDNql1S+nq4oNRy +-----END CERTIFICATE----- diff --git a/security/manager/ssl/tests/unit/test_content_signing/content_signing_onecrl_ee_not_valid_yet.pem.certspec b/security/manager/ssl/tests/unit/test_content_signing/content_signing_onecrl_ee_not_valid_yet.pem.certspec new file mode 100644 index 0000000000..b2926dfc42 --- /dev/null +++ b/security/manager/ssl/tests/unit/test_content_signing/content_signing_onecrl_ee_not_valid_yet.pem.certspec @@ -0,0 +1,6 @@ +issuer:int-CA +subject:ee-int-CA-not-yet-valid +subjectKey:secp384r1 +validity:20500101-20510101 +extension:extKeyUsage:codeSigning +extension:subjectAlternativeName:oneCRL-signer.mozilla.org diff --git a/security/manager/ssl/tests/unit/test_content_signing/content_signing_onecrl_no_SAN_ee.pem b/security/manager/ssl/tests/unit/test_content_signing/content_signing_onecrl_no_SAN_ee.pem new file mode 100644 index 0000000000..6c35f2f377 --- /dev/null +++ b/security/manager/ssl/tests/unit/test_content_signing/content_signing_onecrl_no_SAN_ee.pem @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICIDCCAQigAwIBAgIUI9ZQ+lOT4QPSefKaSaGvSm4BzikwDQYJKoZIhvcNAQEL +BQAwETEPMA0GA1UEAwwGaW50LUNBMCIYDzIwMjExMTI3MDAwMDAwWhgPMjAyNDAy +MDUwMDAwMDBaMBQxEjAQBgNVBAMMCWVlLW5vLVNBTjB2MBAGByqGSM49AgEGBSuB +BAAiA2IABKFockM2K1x7GInzeRVGFaHHP7SN7oY+AikV22COJS3ktxMtqM6Y6DFT +TmqcDAsJyNY5regyBuW6gTRzoR+jMOBdqMluQ4P+J4c9qXEDviiIz/AC8Fr3Gh/d +zIN0qm6pzqMXMBUwEwYDVR0lBAwwCgYIKwYBBQUHAwMwDQYJKoZIhvcNAQELBQAD +ggEBABwtpcPoXa4bLLw8WCuLPMPm7RiWrj7ifWqeyNoQO+xIxIefZhFTxhs6yM0Y +H+B2jSzrCmfslRaX0eZPQ3BOPPI0CCo4eZOlq7oNaltXCLP3NwPodLfxd8pGlOIK +xpRB/+iyXu5bKHfG1v4XJ+g+yXPh8p0ykVJeH/hc/+kAhq4vey+0PB/KjIcpAsGo +S7Yvbal7pSr0CQCxDB4mTWJeE1/FeTQpeFiIiCtvkEyLD+igxRlP5lbLOd6Lt5Oh +BSJ6TnUdMajalOku3BufB5j4ynDBGNi9h935ZCOKWu3qgbFlIE1qZIJS+u7+2PTN +vIlU3orErRSmuAlusdo6Z9YtxbQ= +-----END CERTIFICATE----- diff --git a/security/manager/ssl/tests/unit/test_content_signing/content_signing_onecrl_no_SAN_ee.pem.certspec b/security/manager/ssl/tests/unit/test_content_signing/content_signing_onecrl_no_SAN_ee.pem.certspec new file mode 100644 index 0000000000..4a9b9a3ceb --- /dev/null +++ b/security/manager/ssl/tests/unit/test_content_signing/content_signing_onecrl_no_SAN_ee.pem.certspec @@ -0,0 +1,4 @@ +issuer:int-CA +subject:ee-no-SAN +subjectKey:secp384r1 +extension:extKeyUsage:codeSigning diff --git a/security/manager/ssl/tests/unit/test_content_signing/content_signing_onecrl_wrong_key_ee.pem b/security/manager/ssl/tests/unit/test_content_signing/content_signing_onecrl_wrong_key_ee.pem new file mode 100644 index 0000000000..d76f4501cb --- /dev/null +++ b/security/manager/ssl/tests/unit/test_content_signing/content_signing_onecrl_wrong_key_ee.pem @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICLDCCARSgAwIBAgIUV+E6VhJoKZrnCV22wV/aVW9aglwwDQYJKoZIhvcNAQEL +BQAwETEPMA0GA1UEAwwGaW50LUNBMCIYDzIwMjExMTI3MDAwMDAwWhgPMjAyNDAy +MDUwMDAwMDBaMBcxFTATBgNVBAMMDGVlLXdyb25nLWtleTBZMBMGByqGSM49AgEG +CCqGSM49AwEHA0IABE+/u7th4Pj5saYKWayHBOLsBQtCPjz3LpI/LE95S0VcKmnS +M0VsNsQRnQcG4A7tyNGTkNeZG3stB6ME6qBKpsCjPTA7MBMGA1UdJQQMMAoGCCsG +AQUFBwMDMCQGA1UdEQQdMBuCGW9uZUNSTC1zaWduZXIubW96aWxsYS5vcmcwDQYJ +KoZIhvcNAQELBQADggEBAFOgIZXl0sf1hEH0H5fqGPshlMemqjhFZKPBgLlWl+3W +wSIcuBPw5GSDkoQOdAxE/iIsLfZoC0PfYdee+twANQ13MMbwP0NmR78qJKLPOO4b +yWRiQFaIU6fTleU7wSD6tcDtIsKAfTDNF6EiC3czw3XuOiNh4r7A2EJ3GyGuUq7d +YgpwA5I2s3VjG/2lhRKP06UH/YGCpBTio23NUyzS2NINPhTnrLjyY2IWIp9EiXXj +d6QRQ8ytp6wU/rI3HAueWOWEQ6dDWR5hfe0Y/QDB0n9hEBgf+lUOtuqpTs/ZK0eM +HPC6swGdKVnJ1DCcfyzMsDIvGZKUyj8v6E2E7x8AdLk= +-----END CERTIFICATE----- diff --git a/security/manager/ssl/tests/unit/test_content_signing/content_signing_onecrl_wrong_key_ee.pem.certspec b/security/manager/ssl/tests/unit/test_content_signing/content_signing_onecrl_wrong_key_ee.pem.certspec new file mode 100644 index 0000000000..fbc8e603f4 --- /dev/null +++ b/security/manager/ssl/tests/unit/test_content_signing/content_signing_onecrl_wrong_key_ee.pem.certspec @@ -0,0 +1,5 @@ +issuer:int-CA +subject:ee-wrong-key +subjectKey:secp256r1 +extension:extKeyUsage:codeSigning +extension:subjectAlternativeName:oneCRL-signer.mozilla.org diff --git a/security/manager/ssl/tests/unit/test_content_signing/content_signing_remote_newtab_ee.pem b/security/manager/ssl/tests/unit/test_content_signing/content_signing_remote_newtab_ee.pem new file mode 100644 index 0000000000..b2e7d3cdbb --- /dev/null +++ b/security/manager/ssl/tests/unit/test_content_signing/content_signing_remote_newtab_ee.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICUDCCATigAwIBAgIUd9FOUg8KGZnunc6wzwp+21rSdVswDQYJKoZIhvcNAQEL +BQAwETEPMA0GA1UEAwwGaW50LUNBMCIYDzIwMjExMTI3MDAwMDAwWhgPMjAyNDAy +MDUwMDAwMDBaMA0xCzAJBgNVBAMMAmVlMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE +oWhyQzYrXHsYifN5FUYVocc/tI3uhj4CKRXbYI4lLeS3Ey2ozpjoMVNOapwMCwnI +1jmt6DIG5bqBNHOhH6Mw4F2oyW5Dg/4nhz2pcQO+KIjP8ALwWvcaH93Mg3SqbqnO +o04wTDATBgNVHSUEDDAKBggrBgEFBQcDAzA1BgNVHREELjAsgipyZW1vdGVuZXd0 +YWIuY29udGVudC1zaWduYXR1cmUubW96aWxsYS5vcmcwDQYJKoZIhvcNAQELBQAD +ggEBAJvuDgm64Fca8XKLPxCSaANEFXIQy3I0lvPqmRRFtkP8cNpgjaRQTNNwyRPL +eI6VZv9IfecgjMNMcSbrdUPSmETA5M0kzH0lVBPsgzcv1EO6FFS+B9uwip52nKot +HsWYhDIVKYFYLrFcBHS0qSaoPWUpRZ+igI0uBgzmSIBuZYLDbe0xcXzZmpdPnGYt +pjRmTuNtJ8R/Qvbp37aTpN279AwhOP/uF+x3HdPgI4M1pQKjZ/Oxk9JHIeSafjG5 +58D1rGivjWYq6Yl1vwzBWwlPJvDAgADWCQR4wWjlXc0Hzn/393QRs3rvbkCFWZfi +1GMOoGuxmHzb7VL+1Kf4igjHXcQ= +-----END CERTIFICATE----- diff --git a/security/manager/ssl/tests/unit/test_content_signing/content_signing_remote_newtab_ee.pem.certspec b/security/manager/ssl/tests/unit/test_content_signing/content_signing_remote_newtab_ee.pem.certspec new file mode 100644 index 0000000000..81e1eefe1d --- /dev/null +++ b/security/manager/ssl/tests/unit/test_content_signing/content_signing_remote_newtab_ee.pem.certspec @@ -0,0 +1,5 @@ +issuer:int-CA +subject:ee +subjectKey:secp384r1 +extension:extKeyUsage:codeSigning +extension:subjectAlternativeName:remotenewtab.content-signature.mozilla.org diff --git a/security/manager/ssl/tests/unit/test_content_signing/pysign.py b/security/manager/ssl/tests/unit/test_content_signing/pysign.py new file mode 100644 index 0000000000..23c6128aa2 --- /dev/null +++ b/security/manager/ssl/tests/unit/test_content_signing/pysign.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python +# +# 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/. + +""" +Create an ECDSA signature on the P-384 curve using the SHA-384 hash of data from +stdin. The key used for the signature is the secp384r1Encoded key used in pykey +and pycert. + +The certificates for the content signature tests make use of this program. +You can use pysign.py like this: + +cat test.txt | python pysign.py > test.txt.signature +""" + +import base64 +import binascii +import hashlib +import pathlib +import six +import sys + +import ecdsa + +# For pykey, find the relative file location and add it to path +toolsDir = (pathlib.Path(__file__).parents[4] / "tools").resolve() +sys.path.append(str(toolsDir)) +import pykey + +data = sys.stdin.buffer.read() + +key = pykey.ECCKey("secp384r1") +sig = key.signRaw(b"Content-Signature:\00" + data, pykey.HASH_SHA384) +print(str(base64.b64encode(sig)).replace("+", "-").replace("/", "_")) diff --git a/security/manager/ssl/tests/unit/test_content_signing/test.txt b/security/manager/ssl/tests/unit/test_content_signing/test.txt new file mode 100644 index 0000000000..2daac1cb00 --- /dev/null +++ b/security/manager/ssl/tests/unit/test_content_signing/test.txt @@ -0,0 +1 @@ +This is a test file to test content-signature verification with a PKI. diff --git a/security/manager/ssl/tests/unit/test_content_signing/test.txt.signature b/security/manager/ssl/tests/unit/test_content_signing/test.txt.signature new file mode 100644 index 0000000000..e613981473 --- /dev/null +++ b/security/manager/ssl/tests/unit/test_content_signing/test.txt.signature @@ -0,0 +1 @@ +hSvmvvA7_QLedDsjRJGBevqLwjPILx1EtWSPP4A0fepaWWPuuZRB8VfDT2j07bKDacRsbmJjmvg_R4CpKmnoWF8-2w5lSszlFFDqYSvQVQxpKhu-HMM_qquu_l0KecQ2 |