Add new certificateProvider extension API.
[chromium-blink-merge.git] / chrome / renderer / resources / extensions / enterprise_platform_keys / subtle_crypto.js
blobece243057d53b71572d1ee2aaac21352edb083d6
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
19 // of this API.
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
45 // returns true.
46 function catchInvalidTokenError(reject) {
47   if (chrome.runtime.lastError &&
48       chrome.runtime.lastError.message == errorInvalidToken) {
49     reject(chrome.runtime.lastError);
50     return true;
51   }
52   return false;
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)
61     return false;
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];
67     }
68     if (array[array.length - 1 - i] !== expectedDigit)
69       return false;
70   }
71   return true;
74 /**
75  * Implementation of WebCrypto.SubtleCrypto used in enterprise.platformKeys.
76  * Derived from platformKeys.SubtleCrypto.
77  * @param {string} tokenId The id of the backing Token.
78  * @constructor
79  */
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
92     // implementation.
94     if (extractable) {
95       // Note: This deviates from WebCrypto.SubtleCrypto.
96       throw CreateNotSupportedError();
97     }
98     if (intersect(keyUsages, [KeyUsage.sign, KeyUsage.verify]).length !=
99         keyUsages.length) {
100       throw CreateDataError();
101     }
102     var normalizedAlgorithmParameters =
103         normalizeAlgorithm(algorithm, 'GenerateKey');
104     if (!normalizedAlgorithmParameters) {
105       // TODO(pneubeck): It's not clear from the WebCrypto spec which error to
106       // throw here.
107       throw CreateSyntaxError();
108     }
110     // normalizeAlgorithm returns an array, but publicExponent should be a
111     // Uint8Array.
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();
120     }
122     internalAPI.generateKey(subtleCrypto.tokenId,
123                             normalizedAlgorithmParameters.modulusLength,
124                             function(spki) {
125       if (catchInvalidTokenError(reject))
126         return;
127       if (chrome.runtime.lastError) {
128         reject(CreateOperationError());
129         return;
130       }
131       resolve(new KeyPair(spki, normalizedAlgorithmParameters, keyUsages));
132     });
133   });
136 exports.SubtleCrypto =
137     utils.expose('SubtleCrypto',
138                  EnterpriseSubtleCryptoImpl,
139                  {
140                    superclass: SubtleCrypto,
141                    functions: ['generateKey']
142                    // ['sign', 'exportKey'] are exposed by the base class
143                  });