// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
'use strict';
var systemTokenEnabled;
var assertEq = chrome.test.assertEq;
var assertTrue = chrome.test.assertTrue;
var assertFalse = chrome.test.assertFalse;
var fail = chrome.test.fail;
var succeed = chrome.test.succeed;
var callbackPass = chrome.test.callbackPass;
var callbackFail = chrome.test.callbackFail;
var checkDeepEq = chrome.test.checkDeepEq;
// Each value is the path to a file in this extension's folder that will be
// loaded and replaced by a Uint8Array in the setUp() function below.
var data = {
// X.509 certificate in DER encoding issued by 'root.pem' which is set to be
// trusted by the test setup.
// Generated by create_test_certs.sh .
trusted_l1_leaf_cert: 'l1_leaf.der',
// X.509 intermediate CA certificate in DER encoding issued by 'root.pem'
// which is set to be trusted by the test setup.
// Generated by create_test_certs.sh .
trusted_l1_interm_cert: 'l1_interm.der',
// X.509 certificate in DER encoding issued by 'l1_interm'.
// Generated by create_test_certs.sh .
trusted_l2_leaf_cert: 'l2_leaf.der',
// X.509 client certificate in DER encoding.
// Algorithm in SPKI: rsaEncryption.
// Generated by create_test_certs.sh .
// Imported in the user token.
client_1: 'client_1.der',
// X.509 client certificate in DER encoding.
// Algorithm in SPKI: rsaEncryption.
// Generated by create_test_certs.sh .
// Imported in the system token (if available).
client_2: 'client_2.der',
// X.509 client certificate in DER encoding.
// Algorithm in SPKI: ECDSA Encryption.
// Generated by create_test_certs.sh.
// Imported in the user token.
client_3: 'client_3.der',
// The public key of client_1 as Subject Public Key Info in DER encoding.
// Generated by create_test_certs.sh .
client_1_spki: 'client_1_spki.der',
// The public key of ec_cert as Subject Public Key Info in DER encoding.
// Generated by create_test_certs.sh.
ec_spki: 'ec_spki.der',
// X.509 certificate in DER encoding for ec_spki.
// Generated by create_test_certs.sh.
ec_cert: 'ec_cert.der',
// The distinguished name of the CA that issued client_1 in DER encoding.
// Generated by create_test_certs.sh .
client_1_issuer_dn: 'client_1_issuer_dn.der',
// The string "hello world".
// Generated by create_test_certs.sh .
raw_data: 'data',
// A signature of raw_data using RSASSA-PKCS1-v1_5 with client_1, but treating
// raw_data as a raw digest and without adding the DigestInfo prefix.
// Generated by create_test_certs.sh .
signature_nohash_pkcs: 'signature_nohash_pkcs',
// A signature of raw_data using RSASSA-PKCS1-v1_5 with client_1, using SHA-1
// as the hash function.
// Generated by create_test_certs.sh .
signature_client1_sha1_pkcs: 'signature_client1_sha1_pkcs',
// A signature of raw_data using RSASSA-PKCS1-v1_5 with client_2, using SHA-1
// as the hash function.
// Generated by create_test_certs.sh .
signature_client2_sha1_pkcs: 'signature_client2_sha1_pkcs',
};
function readFile(path, callback) {
fetch(path)
.then((response) => {
return response.arrayBuffer();
})
.then((arrayBuffer) => {
callback(new Uint8Array(arrayBuffer));
})
.catch((e) => {
callback(null);
});
}
// For each key in dictionary, replaces the path dictionary[key] by the content
// of the resource located at that path stored in a Uint8Array.
function readData(dictionary, callback) {
var keys = Object.keys(dictionary);
function recurse(index) {
if (index >= keys.length) {
callback();
return;
}
var key = keys[index];
var path = dictionary[key];
readFile(path, function(array) {
assertTrue(!!array);
dictionary[key] = array;
recurse(index + 1);
});
}
recurse(0);
}
function setUp(callback) {
readData(data, callback);
}
// Some array comparison. Note: not lexicographical!
function compareArrays(array1, array2) {
if (array1.length < array2.length)
return -1;
if (array1.length > array2.length)
return 1;
for (var i = 0; i < array1.length; i++) {
if (array1[i] < array2[i])
return -1;
if (array1[i] > array2[i])
return 1;
}
return 0;
}
/**
* @param {ArrayBufferView[]} certs
* @return {ArrayBufferView[]} |certs| sorted in some order.
*/
function sortCerts(certs) {
return certs.sort(compareArrays);
}
function assertCertsSelected(details, expectedCerts) {
chrome.platformKeys.selectClientCertificates(
details, callbackPass(function(actualMatches) {
assertEq(
expectedCerts.length, actualMatches.length,
'Number of stored certs not as expected');
if (expectedCerts.length == actualMatches.length) {
var actualCerts = actualMatches.map(function(match) {
return new Uint8Array(match.certificate);
});
actualCerts = sortCerts(actualCerts);
expectedCerts = sortCerts(expectedCerts);
for (var i = 0; i < expectedCerts.length; i++) {
assertEq(
expectedCerts[i], actualCerts[i],
'Certs at index ' + i + ' differ');
}
}
}));
}
function checkRsaAlgorithmIsCopiedOnRead(key) {
const algorithm = key.algorithm;
const originalAlgorithm = {
name: algorithm.name,
modulusLength: algorithm.modulusLength,
publicExponent: algorithm.publicExponent,
hash: {name: algorithm.hash.name}
};
algorithm.hash.name = null;
algorithm.hash = null;
algorithm.name = null;
algorithm.modulusLength = null;
algorithm.publicExponent = null;
assertEq(originalAlgorithm, key.algorithm);
}
function checkEcAlgorithmIsCopiedOnRead(key) {
const algorithm = key.algorithm;
const originalAlgorithm = {
name: algorithm.name,
namedCurve: algorithm.namedCurve,
};
algorithm.name = null;
algorithm.namedCurve = null;
assertEq(originalAlgorithm, key.algorithm);
}
function checkAlgorithmIsCopiedOnRead(key) {
const algorithmName = key.algorithm.name;
if (algorithmName === 'RSASSA-PKCS1-v1_5') {
checkRsaAlgorithmIsCopiedOnRead(key);
} else if (algorithmName === 'ECDSA') {
checkEcAlgorithmIsCopiedOnRead(key);
} else {
fail('Unexpected algorithm name: ' + algorithmName);
}
}
function checkPropertyIsReadOnly(object, key) {
var original = object[key];
try {
object[key] = {};
fail(
'Expected the property ' + key +
' to be read-only and an exception to be thrown');
} catch (error) {
assertEq(original, object[key]);
}
}
function checkPrivateKeyFormat(privateKey) {
assertEq('private', privateKey.type);
assertFalse(privateKey.extractable);
checkPropertyIsReadOnly(privateKey, 'algorithm');
checkAlgorithmIsCopiedOnRead(privateKey);
}
function checkPublicKeyFormat(publicKey) {
assertEq('public', publicKey.type);
assertTrue(publicKey.extractable);
checkPropertyIsReadOnly(publicKey, 'algorithm');
checkAlgorithmIsCopiedOnRead(publicKey);
}
// TODO(b/288880151): Add tests for the |getSymKeyById()| method, after it's
// implemented in the internal API and exposed in the platformKeys API.
function testStaticMethods() {
assertTrue(!!chrome.platformKeys, 'No platformKeys namespace.');
assertTrue(
!!chrome.platformKeys.selectClientCertificates,
'No selectClientCertificates function.');
assertTrue(!!chrome.platformKeys.getKeyPair, 'No getKeyPair method.');
assertTrue(
!!chrome.platformKeys.getKeyPairBySpki, 'No getKeyPairBySpki method.');
assertTrue(!!chrome.platformKeys.subtleCrypto, 'No subtleCrypto getter.');
assertTrue(!!chrome.platformKeys.subtleCrypto(), 'No subtleCrypto object.');
assertTrue(!!chrome.platformKeys.subtleCrypto().sign, 'No sign method.');
assertTrue(
!!chrome.platformKeys.subtleCrypto().exportKey, 'No exportKey method.');
succeed();
}
var requestAll = {certificateTypes: [], certificateAuthorities: []};
// Depends on |data|, thus it cannot be created immediately.
function requestCA1() {
return {
certificateTypes: [],
certificateAuthorities: [data.client_1_issuer_dn.buffer]
};
}
function testSelectAllCerts() {
var expectedCerts = [data.client_1, data.client_3];
if (systemTokenEnabled)
expectedCerts.push(data.client_2);
assertCertsSelected({interactive: false, request: requestAll}, expectedCerts);
}
function testSelectWithInputClientCerts() {
var expectedCerts = [];
if (systemTokenEnabled)
expectedCerts.push(data.client_2);
assertCertsSelected(
{
interactive: false,
request: requestAll,
clientCerts: [data.client_2.buffer]
},
expectedCerts);
}
function testSelectCA1Certs() {
assertCertsSelected(
{interactive: false, request: requestCA1()}, [data.client_1]);
}
function testSelectAllReturnsNoCerts() {
assertCertsSelected(
{interactive: false, request: requestAll}, [] /* no certs selected */);
}
function testSelectAllReturnsClient1() {
assertCertsSelected(
{interactive: false, request: requestAll}, [data.client_1]);
}
function testInteractiveSelectNoCerts() {
assertCertsSelected(
{interactive: true, request: requestAll}, [] /* no certs selected */);
}
function testInteractiveSelectClient1() {
assertCertsSelected(
{interactive: true, request: requestAll}, [data.client_1]);
}
function testInteractiveSelectClient2() {
var expectedCerts = [];
if (systemTokenEnabled)
expectedCerts.push(data.client_2);
assertCertsSelected({interactive: true, request: requestAll}, expectedCerts);
}
function testInteractiveSelectClient3() {
assertCertsSelected(
{interactive: true, request: requestAll}, [data.client_3]);
}
function testMatchResultCA1() {
chrome.platformKeys.selectClientCertificates(
{interactive: false, request: requestCA1()},
callbackPass(function(matches) {
var expectedAlgorithm = {
modulusLength: 2048,
name: 'RSASSA-PKCS1-v1_5',
publicExponent: new Uint8Array([0x01, 0x00, 0x01])
};
var actualAlgorithm = matches[0].keyAlgorithm;
assertEq(
expectedAlgorithm, actualAlgorithm,
'Member algorithm of Match does not equal the expected algorithm');
}));
}
function testMatchResultECDSA() {
var requestECDSA = {
certificateTypes: ['ecdsaSign'],
certificateAuthorities: []
};
assertCertsSelected(
{interactive: false, request: requestECDSA}, [data.client_3]);
}
function testMatchResultRSA() {
var requestRSA = {certificateTypes: ['rsaSign'], certificateAuthorities: []};
chrome.platformKeys.selectClientCertificates(
{interactive: false, request: requestRSA},
callbackPass(function(matches) {
var expectedAlgorithm = {
modulusLength: 2048,
name: 'RSASSA-PKCS1-v1_5',
publicExponent: new Uint8Array([0x01, 0x00, 0x01])
};
var actualAlgorithm = matches[0].keyAlgorithm;
assertEq(
expectedAlgorithm, actualAlgorithm,
'Member algorithm of Match does not equal the expected algorithm');
}));
}
function verifyMissingAlgorithmError(getKeyFunction, buffer, name) {
var keyParams = {
// This is missing the algorithm name.
hash: {name: 'SHA-1'}
};
try {
getKeyFunction(buffer, keyParams, function(error) {
fail(`${name} call was expected to fail.`);
});
fail(`${name} did not throw error`);
} catch (e) {
assertEq('Algorithm: name: Missing or not a String', e.message);
succeed();
}
}
function testGetKeyPairMissingAlgorithmName() {
verifyMissingAlgorithmError(
chrome.platformKeys.getKeyPair, data.client_1.buffer, 'getKeyPair');
}
function testGetKeyPairBySpkiMissingAlgorithmName() {
verifyMissingAlgorithmError(
chrome.platformKeys.getKeyPairBySpki, data.client_1_spki.buffer,
'getKeyPairBySpki');
}
function testGetKeyPairRejectsRSAPSS() {
var keyParams = {name: 'RSA-PSS', hash: {name: 'SHA-1'}};
chrome.platformKeys.getKeyPair(
data.client_1.buffer, keyParams,
callbackFail('Algorithm not supported.'));
chrome.platformKeys.getKeyPairBySpki(
data.client_1_spki.buffer, keyParams,
callbackFail('Algorithm not supported.'));
}
function verifyRsaKeyPairValidity(publicKey, privateKey) {
var expectedAlgorithm = {
modulusLength: 2048,
name: 'RSASSA-PKCS1-v1_5',
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
hash: {name: 'SHA-1'}
};
assertEq(expectedAlgorithm, publicKey.algorithm);
assertEq(expectedAlgorithm, privateKey.algorithm);
checkPublicKeyFormat(publicKey);
checkPrivateKeyFormat(privateKey);
chrome.platformKeys.subtleCrypto()
.exportKey('spki', publicKey)
.then(
callbackPass(function(actualPublicKeySpki) {
assertTrue(
compareArrays(
data.client_1_spki, new Uint8Array(actualPublicKeySpki)) ==
0,
'Match did not contain correct public key');
}),
function(error) {
fail('Export failed: ' + error);
});
}
const RSA_KEY_PARAMS = {
name: 'RSASSA-PKCS1-V1_5',
hash: {name: 'SHA-1'}
};
const EC_KEY_PARAMS = {
name: 'ECDSA',
namedCurve: 'P-256'
};
const AES_KEY_PARAMS = {
name: 'AES-CBC',
length: 256
};
async function verifyEcKeyPairValidity(publicKey, privateKey) {
assertEq(EC_KEY_PARAMS, publicKey.algorithm);
assertEq(EC_KEY_PARAMS, privateKey.algorithm);
checkPublicKeyFormat(publicKey);
checkPrivateKeyFormat(privateKey);
let actualPublicKeySpki;
try {
actualPublicKeySpki =
await chrome.platformKeys.subtleCrypto().exportKey('spki', publicKey);
} catch (error) {
fail('Export failed: ' + error);
}
const actualPublicKeySpkiArray = new Uint8Array(actualPublicKeySpki);
assertEq(
data.ec_spki, actualPublicKeySpkiArray,
'Match did not contain correct public key');
succeed();
}
// TODO(b/288880151): Replace the 'Algorithm not supported.' errors below with a
// proper error, after modifying the internal API to support AES keys.
function testGetRsaKeyPairRejectsOtherAlgorithms() {
const rsa_key_cert = data.client_1;
chrome.platformKeys.getKeyPair(
rsa_key_cert.buffer, EC_KEY_PARAMS,
callbackFail(
'The requested Algorithm is not permitted by the certificate.'));
chrome.platformKeys.getKeyPair(
rsa_key_cert.buffer, AES_KEY_PARAMS,
callbackFail('Algorithm not supported.'));
}
function testGetEcKeyPairRejectsOtherAlgorithms() {
chrome.platformKeys.getKeyPair(
data.ec_cert.buffer, RSA_KEY_PARAMS,
callbackFail(
'The requested Algorithm is not permitted by the certificate.'));
chrome.platformKeys.getKeyPair(
data.ec_cert.buffer, AES_KEY_PARAMS,
callbackFail('Algorithm not supported.'));
}
function testGetRsaKeyPairBySpkiRejectsOtherAlgorithms() {
const rsa_key_spki = data.client_1_spki;
chrome.platformKeys.getKeyPairBySpki(
rsa_key_spki.buffer, EC_KEY_PARAMS,
callbackFail(
'The requested Algorithm is not permitted by the certificate.'));
chrome.platformKeys.getKeyPairBySpki(
rsa_key_spki.buffer, AES_KEY_PARAMS,
callbackFail('Algorithm not supported.'));
}
function testGetEcKeyPairBySpkiRejectsOtherAlgorithms() {
chrome.platformKeys.getKeyPairBySpki(
data.ec_spki.buffer, RSA_KEY_PARAMS,
callbackFail(
'The requested Algorithm is not permitted by the certificate.'));
chrome.platformKeys.getKeyPairBySpki(
data.ec_spki.buffer, AES_KEY_PARAMS,
callbackFail('Algorithm not supported.'));
}
function testGetRsaKeyPair() {
var keyParams = {
// Algorithm names are case-insensitive.
name: 'RSASSA-Pkcs1-V1_5',
hash: {name: 'sha-1'}
};
chrome.platformKeys.getKeyPair(
data.client_1.buffer, keyParams,
callbackPass(function(publicKey, privateKey) {
verifyRsaKeyPairValidity(publicKey, privateKey);
}));
chrome.platformKeys.getKeyPairBySpki(
data.client_1_spki.buffer, keyParams,
callbackPass(function(publicKey, privateKey) {
verifyRsaKeyPairValidity(publicKey, privateKey);
}));
}
function testGetEcKeyPair() {
chrome.platformKeys.getKeyPair(
data.ec_cert.buffer, EC_KEY_PARAMS, function(publicKey, privateKey) {
verifyEcKeyPairValidity(publicKey, privateKey);
});
chrome.platformKeys.getKeyPairBySpki(
data.ec_spki.buffer, EC_KEY_PARAMS, function(publicKey, privateKey) {
verifyEcKeyPairValidity(publicKey, privateKey);
});
}
function verifySignWithNoHash(privateKey, signParams) {
chrome.platformKeys.subtleCrypto()
.sign(signParams, privateKey, data.raw_data)
.then(callbackPass(function(signature) {
var actualSignature = new Uint8Array(signature);
assertTrue(
compareArrays(data.signature_nohash_pkcs, actualSignature) == 0,
'Incorrect signature');
}));
}
function testSignNoHash() {
var keyParams = {
// Algorithm names are case-insensitive.
name: 'RSASSA-PKCS1-V1_5',
hash: {name: 'NONE'}
};
var signParams = {name: 'RSASSA-PKCS1-v1_5'};
chrome.platformKeys.getKeyPair(
data.client_1.buffer, keyParams,
callbackPass(function(publicKey, privateKey) {
verifySignWithNoHash(privateKey, signParams);
}));
chrome.platformKeys.getKeyPairBySpki(
data.client_1_spki.buffer, keyParams,
callbackPass(function(publicKey, privateKey) {
verifySignWithNoHash(privateKey, signParams);
}));
}
function verifySignWithSha1(privateKey, signParams, client_signature) {
chrome.platformKeys.subtleCrypto()
.sign(signParams, privateKey, data.raw_data)
.then(callbackPass(function(signature) {
var actualSignature = new Uint8Array(signature);
assertTrue(
compareArrays(client_signature, actualSignature) == 0,
'Incorrect signature');
}));
}
function testSignSha1Client1() {
var keyParams = {
name: 'RSASSA-PKCS1-v1_5',
// Hash names are case-insensitive.
hash: {name: 'Sha-1'}
};
var signParams = {
// Algorithm names are case-insensitive.
name: 'RSASSA-Pkcs1-v1_5'
};
chrome.platformKeys.getKeyPair(
data.client_1.buffer, keyParams,
callbackPass(function(publicKey, privateKey) {
verifySignWithSha1(
privateKey, signParams, data.signature_client1_sha1_pkcs);
}));
chrome.platformKeys.getKeyPairBySpki(
data.client_1_spki.buffer, keyParams,
callbackPass(function(publicKey, privateKey) {
verifySignWithSha1(
privateKey, signParams, data.signature_client1_sha1_pkcs);
}));
}
function testSignSha1Client2() {
var keyParams = {
name: 'RSASSA-PKCS1-v1_5',
// Hash names are case-insensitive.
hash: {name: 'Sha-1'}
};
var signParams = {
// Algorithm names are case-insensitive.
name: 'RSASSA-Pkcs1-v1_5'
};
chrome.platformKeys.getKeyPair(
data.client_2.buffer, keyParams,
callbackPass(function(publicKey, privateKey) {
verifySignWithSha1(
privateKey, signParams, data.signature_client2_sha1_pkcs);
}));
}
function testSignSha1Client2OnSystemTokenOnly() {
if (systemTokenEnabled) {
testSignSha1Client2();
} else {
testSignClient2Fails();
}
}
function verifySignFail(privateKey, signParams) {
chrome.platformKeys.subtleCrypto()
.sign(signParams, privateKey, data.raw_data)
.then(function(signature) {
fail('Sign was expected to fail.');
}, callbackPass(function(error) {
assertTrue(error instanceof Error);
assertEq(
'The operation failed for an operation-specific reason',
error.message);
}));
}
// TODO(emaxx): Test this by verifying that no private key is returned,
// once that's implemented, see crbug.com/799410.
function testSignFails(cert, spki) {
var keyParams = {name: 'RSASSA-PKCS1-v1_5', hash: {name: 'SHA-1'}};
var signParams = {name: 'RSASSA-PKCS1-v1_5'};
chrome.platformKeys.getKeyPair(
cert.buffer, keyParams, callbackPass(function(publicKey, privateKey) {
verifySignFail(privateKey, signParams);
}));
if (spki) {
chrome.platformKeys.getKeyPairBySpki(
spki.buffer, keyParams, callbackPass(function(publicKey, privateKey) {
verifySignFail(privateKey, signParams);
}));
}
}
function testSignClient1Fails() {
testSignFails(data.client_1, data.client_1_spki);
}
function testSignClient2Fails() {
testSignFails(data.client_2);
}
function testBackgroundInteractiveSelect() {
var details = {interactive: true, request: requestAll};
chrome.platformKeys.selectClientCertificates(
details, function(actualMatches) {
assertEq(
chrome.runtime.lastError.message,
'Interactive calls must happen in the context of a ' +
'browser tab or a window.');
assertEq([], actualMatches);
chrome.test.succeed();
});
}
function testVerifyTrusted() {
var details = {
serverCertificateChain: [data.trusted_l1_leaf_cert.buffer],
hostname: 'l1_leaf'
};
chrome.platformKeys.verifyTLSServerCertificate(
details, callbackPass(function(result) {
assertTrue(result.trusted);
assertEq([], result.debug_errors);
}));
}
function testVerifyTrustedChain() {
var details = {
serverCertificateChain:
[data.trusted_l2_leaf_cert.buffer, data.trusted_l1_interm_cert.buffer],
hostname: 'l2_leaf'
};
chrome.platformKeys.verifyTLSServerCertificate(
details, callbackPass(function(result) {
assertTrue(result.trusted);
assertEq([], result.debug_errors);
}));
}
function testVerifyCommonNameInvalid() {
var details = {
serverCertificateChain:
[data.trusted_l2_leaf_cert.buffer, data.trusted_l1_interm_cert.buffer],
// Use any hostname not matching the common name 'l2_leaf' of the cert.
hostname: 'abc.example'
};
chrome.platformKeys.verifyTLSServerCertificate(
details, callbackPass(function(result) {
assertFalse(result.trusted);
assertEq(['COMMON_NAME_INVALID'], result.debug_errors);
}));
}
function testVerifyUntrusted() {
var details = {
serverCertificateChain: [data.client_1.buffer],
hostname: '127.0.0.1'
};
chrome.platformKeys.verifyTLSServerCertificate(
details, callbackPass(function(result) {
assertFalse(result.trusted);
assertEq(
['COMMON_NAME_INVALID', 'AUTHORITY_INVALID'], result.debug_errors);
}));
}
var testSuites = {
basicTests: function() {
var tests = [
testStaticMethods,
testSignSha1Client2OnSystemTokenOnly,
// Interactively select all clients to grant permissions for these
// certificates.
// TODO(crbug.com/40217298): We should move all interactive tests to
// a separate test suite.
testInteractiveSelectClient1,
testInteractiveSelectClient2,
testInteractiveSelectClient3,
// In non-interactive calls all certs must be returned now.
testSelectAllCerts,
testSelectWithInputClientCerts,
testSelectCA1Certs,
testInteractiveSelectNoCerts,
testMatchResultCA1,
testMatchResultECDSA,
testMatchResultRSA,
testGetKeyPairMissingAlgorithmName,
testGetKeyPairBySpkiMissingAlgorithmName,
testGetKeyPairRejectsRSAPSS,
testGetRsaKeyPairRejectsOtherAlgorithms,
testGetEcKeyPairRejectsOtherAlgorithms,
testGetRsaKeyPairBySpkiRejectsOtherAlgorithms,
testGetEcKeyPairBySpkiRejectsOtherAlgorithms,
testGetRsaKeyPair,
testGetEcKeyPair,
testSignNoHash,
testSignSha1Client1,
testVerifyTrusted,
testVerifyTrustedChain,
testVerifyCommonNameInvalid,
testVerifyUntrusted,
];
chrome.test.runTests(tests);
},
// On interactive selectClientCertificates calls, the simulated user selects
// client_1, if matching.
permissionTests: function() {
var tests = [
// Without permissions both sign attempts fail.
testSignClient1Fails,
testSignClient2Fails,
// Without permissions, non-interactive select calls return no certs.
testSelectAllReturnsNoCerts,
// Grant permission for client_1 by interactively selecting it.
testInteractiveSelectClient1,
// Verify that signing with client_1 is possible and with client_2 still
// fails.
testSignSha1Client1,
testSignClient2Fails,
// Verify that client_1 can still be selected interactively.
testInteractiveSelectClient1,
// Verify that client_1 but not client_2 is selected in non-interactive
// calls.
testSelectAllReturnsClient1,
];
chrome.test.runTests(tests);
},
managedProfile: function() {
var tests = [
// If the profile is managed, the user cannot grant permissions for any
// certificates.
testInteractiveSelectNoCerts
];
chrome.test.runTests(tests);
},
corporateKeyWithoutPermissionTests: function() {
var tests = [
// Directly trying to sign must fail.
testSignClient1Fails,
// Interactively selecting must not show any cert to the user.
testInteractiveSelectNoCerts,
// client_2 is on the system token and is thus implicitly a corporate key.
// The extension has no access to it.
testSignClient2Fails,
];
chrome.test.runTests(tests);
},
corporateKeyWithPermissionTests: function() {
var tests = [
// The extension has non-interactive access to all corporate keys, even
// without previous additional consent of the user.
testSignSha1Client1,
// Interactively selecting for client_1 will work as well.
testInteractiveSelectClient1,
// client_2 is on the system token and is thus implicitly a corporate key.
// The extension has access to it.
testSignSha1Client2OnSystemTokenOnly,
];
chrome.test.runTests(tests);
},
policyDoesGrantAccessToNonCorporateKey: function() {
// The permission from policy must not affect usage of non-corporate keys.
var tests = [
// Attempts to sign must fail.
testSignClient1Fails,
// Interactive selection must not prompt the user and not return any
// certificate.
testInteractiveSelectNoCerts,
];
chrome.test.runTests(tests);
},
backgroundInteractiveTest: function() {
var tests = [
// Tests that interactive calls are not allowed from the extension's
// background page.
testBackgroundInteractiveSelect,
];
chrome.test.runTests(tests);
},
};
chrome.test.getConfig(function(config) {
let customArg = JSON.parse(config.customArg);
let selectedTestSuite = customArg.testSuiteName;
systemTokenEnabled = customArg.systemTokenEnabled;
console.log(
'[SELECTED TEST SUITE] ' + selectedTestSuite +
', systemTokenEnabled: ' + systemTokenEnabled);
setUp(testSuites[selectedTestSuite]);
});