1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 var utils = require('utils');
6 var internalAPI = require('enterprise.platformKeys.internalAPI');
7 var intersect = require('platformKeys.utils').intersect;
8 var subtleCryptoModule = require('platformKeys.SubtleCrypto');
9 var SubtleCrypto = subtleCryptoModule.SubtleCrypto;
10 var SubtleCryptoImpl = subtleCryptoModule.SubtleCryptoImpl;
11 var KeyPair = require('enterprise.platformKeys.KeyPair').KeyPair;
12 var KeyUsage = require('platformKeys.Key').KeyUsage;
14 var normalizeAlgorithm =
15 requireNative('platform_keys_natives').NormalizeAlgorithm;
17 // This error is thrown by the internal and public API's token functions and
18 // must be rethrown by this custom binding. Keep this in sync with the C++ part
20 var errorInvalidToken = "The token is not valid.";
22 // The following errors are specified in WebCrypto.
23 // TODO(pneubeck): These should be DOMExceptions.
24 function CreateNotSupportedError() {
25 return new Error('The algorithm is not supported');
28 function CreateInvalidAccessError() {
29 return new Error('The requested operation is not valid for the provided key');
32 function CreateDataError() {
33 return new Error('Data provided to an operation does not meet requirements');
36 function CreateSyntaxError() {
37 return new Error('A required parameter was missing or out-of-range');
40 function CreateOperationError() {
41 return new Error('The operation failed for an operation-specific reason');
44 // Catches an |internalErrorInvalidToken|. If so, forwards it to |reject| and
46 function catchInvalidTokenError(reject) {
47 if (chrome.runtime.lastError &&
48 chrome.runtime.lastError.message == errorInvalidToken) {
49 reject(chrome.runtime.lastError);
55 // Returns true if |array| is a BigInteger describing the standard public
56 // exponent 65537. In particular, it ignores leading zeros as required by the
57 // BigInteger definition in WebCrypto.
58 function equalsStandardPublicExponent(array) {
59 var expected = [0x01, 0x00, 0x01];
60 if (array.length < expected.length)
62 for (var i = 0; i < array.length; i++) {
63 var expectedDigit = 0;
64 if (i < expected.length) {
65 // |expected| is symmetric, endianness doesn't matter.
66 expectedDigit = expected[i];
68 if (array[array.length - 1 - i] !== expectedDigit)
75 * Implementation of WebCrypto.SubtleCrypto used in enterprise.platformKeys.
76 * Derived from platformKeys.SubtleCrypto.
77 * @param {string} tokenId The id of the backing Token.
80 var EnterpriseSubtleCryptoImpl = function(tokenId) {
81 SubtleCryptoImpl.call(this, tokenId);
84 EnterpriseSubtleCryptoImpl.prototype =
85 Object.create(SubtleCryptoImpl.prototype);
87 EnterpriseSubtleCryptoImpl.prototype.generateKey =
88 function(algorithm, extractable, keyUsages) {
89 var subtleCrypto = this;
90 return new Promise(function(resolve, reject) {
91 // TODO(pneubeck): Apply the algorithm normalization of the WebCrypto
95 // Note: This deviates from WebCrypto.SubtleCrypto.
96 throw CreateNotSupportedError();
98 if (intersect(keyUsages, [KeyUsage.sign, KeyUsage.verify]).length !=
100 throw CreateDataError();
102 var normalizedAlgorithmParameters =
103 normalizeAlgorithm(algorithm, 'GenerateKey');
104 if (!normalizedAlgorithmParameters) {
105 // TODO(pneubeck): It's not clear from the WebCrypto spec which error to
107 throw CreateSyntaxError();
110 // normalizeAlgorithm returns an array, but publicExponent should be a
112 normalizedAlgorithmParameters.publicExponent =
113 new Uint8Array(normalizedAlgorithmParameters.publicExponent);
115 if (normalizedAlgorithmParameters.name !== 'RSASSA-PKCS1-v1_5' ||
116 !equalsStandardPublicExponent(
117 normalizedAlgorithmParameters.publicExponent)) {
118 // Note: This deviates from WebCrypto.SubtleCrypto.
119 throw CreateNotSupportedError();
122 internalAPI.generateKey(subtleCrypto.tokenId,
123 normalizedAlgorithmParameters.modulusLength,
125 if (catchInvalidTokenError(reject))
127 if (chrome.runtime.lastError) {
128 reject(CreateOperationError());
131 resolve(new KeyPair(spki, normalizedAlgorithmParameters, keyUsages));
136 exports.SubtleCrypto =
137 utils.expose('SubtleCrypto',
138 EnterpriseSubtleCryptoImpl,
140 superclass: SubtleCrypto,
141 functions: ['generateKey']
142 // ['sign', 'exportKey'] are exposed by the base class