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('enterprise.platformKeys.utils').intersect;
8 var KeyPair = require('enterprise.platformKeys.KeyPair').KeyPair;
9 var keyModule = require('enterprise.platformKeys.Key');
10 var getSpki = keyModule.getSpki;
11 var KeyUsage = keyModule.KeyUsage;
13 // This error is thrown by the internal and public API's token functions and
14 // must be rethrown by this custom binding. Keep this in sync with the C++ part
16 var errorInvalidToken = "The token is not valid.";
18 // The following errors are specified in WebCrypto.
19 // TODO(pneubeck): These should be DOMExceptions.
20 function CreateNotSupportedError() {
21 return new Error('The algorithm is not supported');
24 function CreateInvalidAccessError() {
25 return new Error('The requested operation is not valid for the provided key');
28 function CreateDataError() {
29 return new Error('Data provided to an operation does not meet requirements');
32 function CreateSyntaxError() {
33 return new Error('A required parameter was missing our out-of-range');
36 function CreateOperationError() {
37 return new Error('The operation failed for an operation-specific reason');
40 // Catches an |internalErrorInvalidToken|. If so, forwards it to |reject| and
42 function catchInvalidTokenError(reject) {
43 if (chrome.runtime.lastError &&
44 chrome.runtime.lastError.message == errorInvalidToken) {
45 reject(chrome.runtime.lastError);
52 * Implementation of WebCrypto.SubtleCrypto used in enterprise.platformKeys.
53 * @param {string} tokenId The id of the backing Token.
56 var SubtleCryptoImpl = function(tokenId) {
57 this.tokenId = tokenId;
60 SubtleCryptoImpl.prototype.generateKey =
61 function(algorithm, extractable, keyUsages) {
62 var subtleCrypto = this;
63 return new Promise(function(resolve, reject) {
64 // TODO(pneubeck): Apply the algorithm normalization of the WebCrypto
68 // Note: This deviates from WebCrypto.SubtleCrypto.
69 throw CreateNotSupportedError();
71 if (intersect(keyUsages, [KeyUsage.sign, KeyUsage.verify]).length !=
73 throw CreateDataError();
75 if (!algorithm.name) {
76 // TODO(pneubeck): It's not clear from the WebCrypto spec which error to
78 throw CreateSyntaxError();
81 if (algorithm.name.toUpperCase() !== 'RSASSA-PKCS1-V1_5') {
82 // Note: This deviates from WebCrypto.SubtleCrypto.
83 throw CreateNotSupportedError();
85 if (!algorithm.modulusLength || !algorithm.publicExponent)
86 throw CreateSyntaxError();
88 internalAPI.generateKey(
89 subtleCrypto.tokenId, algorithm.modulusLength, function(spki) {
90 if (catchInvalidTokenError(reject))
92 if (chrome.runtime.lastError) {
93 reject(CreateOperationError());
96 resolve(new KeyPair(spki, algorithm, keyUsages));
101 SubtleCryptoImpl.prototype.sign = function(algorithm, key, dataView) {
102 var subtleCrypto = this;
103 return new Promise(function(resolve, reject) {
104 if (key.type != 'private' || key.usages.indexOf(KeyUsage.sign) == -1)
105 throw CreateInvalidAccessError();
107 // Create an ArrayBuffer that equals the dataView. Note that dataView.buffer
108 // might contain more data than dataView.
109 var data = dataView.buffer.slice(dataView.byteOffset,
110 dataView.byteOffset + dataView.byteLength);
112 subtleCrypto.tokenId, getSpki(key), data, function(signature) {
113 if (catchInvalidTokenError(reject))
115 if (chrome.runtime.lastError) {
116 reject(CreateOperationError());
124 SubtleCryptoImpl.prototype.exportKey = function(format, key) {
125 return new Promise(function(resolve, reject) {
126 if (format == 'pkcs8') {
127 // Either key.type is not 'private' or the key is not extractable. In both
128 // cases the error is the same.
129 throw CreateInvalidAccessError();
130 } else if (format == 'spki') {
131 if (key.type != 'public')
132 throw CreateInvalidAccessError();
133 resolve(getSpki(key));
135 // TODO(pneubeck): It should be possible to export to format 'jwk'.
136 throw CreateNotSupportedError();
141 exports.SubtleCrypto =
142 utils.expose('SubtleCrypto',
144 {functions:['generateKey', 'sign', 'exportKey']});