Chromium Code Reviews| Index: chrome/renderer/resources/extensions/enterprise_platform_keys_custom_bindings.js |
| diff --git a/chrome/renderer/resources/extensions/enterprise_platform_keys_custom_bindings.js b/chrome/renderer/resources/extensions/enterprise_platform_keys_custom_bindings.js |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..eaed0ad0518aeaa763b9401230b52d897ff75978 |
| --- /dev/null |
| +++ b/chrome/renderer/resources/extensions/enterprise_platform_keys_custom_bindings.js |
| @@ -0,0 +1,196 @@ |
| +// Copyright 2014 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +// Custom binding for the enterprise.platformKeys API. |
| + |
|
not at google - send to devlin
2014/05/02 18:31:56
could you explain what is going on here? there is
pneubeck (no reviews)
2014/05/05 20:09:35
Done.
|
| +var binding = require('binding').Binding.create('enterprise.platformKeys'); |
| +var internalAPI = require('binding') |
| + .Binding.create('enterprise.platformKeysInternal') |
| + .generate(); |
| + |
| +function intersect(a, b) { |
| + var result = []; |
| + for (var i = 0; i < a.length; i++) { |
| + if (b.indexOf(a[i]) >= 0) |
| + result.push(a[i]); |
| + } |
| + return result; |
| +}; |
| + |
| +// Key class definition. |
| +var Key = function(type, publicKeySpki, algorithm, keyUsages) { |
| + privates(this).type_ = type; |
|
not at google - send to devlin
2014/05/02 18:31:56
a nice idiom for privates(..) is to have a "KeyImp
pneubeck (no reviews)
2014/05/05 20:09:35
Done.
|
| + privates(this).spki_ = publicKeySpki; |
| + privates(this).algorithm_ = algorithm; |
| + privates(this).keyUsages_ = keyUsages; |
| +}; |
| + |
| +Object.defineProperty(Key.prototype, 'type', { |
| + get: function() { |
| + return privates(this).type_; |
| + }, |
| + enumerable : true |
| +}); |
| + |
| +// PublicKey class definition. |
| +var PublicKey = function(publicKeySpki, algorithm, keyUsages) { |
| + Key.call(this, "public", publicKeySpki, algorithm, keyUsages); |
| +}; |
| +PublicKey.prototype.__proto__ = Key.prototype; |
| + |
| +Object.defineProperty(PublicKey.prototype, 'extractable', { |
| + get: function() { |
| + return true; |
| + }, |
| + enumerable : true |
| +}); |
| + |
| +// PrivateKey class definition. |
| +var PrivateKey = function(publicKeySpki, algorithm, keyUsages) { |
| + Key.call(this, "private", publicKeySpki, algorithm, keyUsages); |
| +}; |
| +PrivateKey.prototype.__proto__ = Key.prototype; |
| + |
| +Object.defineProperty(PrivateKey.prototype, 'extractable', { |
| + get: function() { |
| + return false; |
| + }, |
| + enumerable : true |
| +}); |
| + |
| +// KeyPair class definition. |
| +var KeyPair = function(publicKeySpki, algorithm, keyUsages) { |
| + privates(this).publicKey_ = |
| + new PublicKey(publicKeySpki, algorithm, intersect(["verify"], keyUsages)); |
| + privates(this).privateKey_ = |
| + new PrivateKey(publicKeySpki, algorithm, intersect(["sign"], keyUsages)); |
| +}; |
| + |
| +Object.defineProperty(KeyPair.prototype, 'publicKey', { |
| + get: function() { |
| + return privates(this).publicKey_; |
| + }, |
| + enumerable : true |
| +}); |
| + |
| +Object.defineProperty(KeyPair.prototype, 'privateKey', { |
| + get: function() { |
| + return privates(this).privateKey_; |
| + }, |
| + enumerable : true |
| +}); |
| + |
| +// SublteCrypto implementation. |
| +var SubtleCrypto = function(tokenId) { |
| + privates(this).tokenId_ = tokenId; |
| +}; |
| + |
| +function addCryptoMethod(methodName, func) { |
| + SubtleCrypto.prototype[methodName] = function() { |
| + var subtleCrypto = this; |
| + var args = arguments; |
| + return new Promise(function(resolve, reject) { |
| + try { |
| + var tokenId = privates(subtleCrypto).tokenId_; |
| + if (!tokenId) |
| + throw new Error('Invalid token object'); |
| + |
| + var newArgs = [resolve, reject, tokenId]; |
| + for (var i = 0; i < args.length; i++) { |
| + newArgs.push(args[i]); |
| + } |
| + |
| + func.apply(null, newArgs); |
| + } |
| + catch (error) { |
|
not at google - send to devlin
2014/05/02 18:31:56
are exceptions not automatically propagated to fai
pneubeck (no reviews)
2014/05/05 20:09:35
Indeed they are.
|
| + reject(error); |
| + } |
| + }); |
| + } |
| +} |
| + |
| +// Token class definition. |
| +var Token = function(tokenId) { |
| + privates(this).tokenId_ = tokenId; |
| + privates(this).subtleCrypto_ = new SubtleCrypto(tokenId); |
| +}; |
| + |
| +Object.defineProperty(Token.prototype, 'id', { |
| + get: function() { |
| + return privates(this).tokenId_; |
| + }, |
| + enumerable : true |
| +}); |
| + |
| +Object.defineProperty(Token.prototype, 'subtleCrypto', { |
| + get: function() { |
| + return privates(this).subtleCrypto_; |
| + }, |
| + enumerable : true |
| +}); |
| + |
| +addCryptoMethod( |
| + 'generateKey', |
| + function(resolve, reject, tokenId, algorithm, extractable, keyUsages) { |
| + if (extractable) |
| + throw new Error('Extractable keys are not supported.'); |
| + if (intersect(keyUsages, ["sign", "verify"]).length != keyUsages.length) { |
| + throw new Error( |
| + 'Unsupported keyUsages. Only "sign" and "verify" supported.'); |
| + } |
| + if (algorithm.name != 'RSASSA-PKCS1-v1_5') |
| + throw new Error('The algorithm is not supported'); |
| + |
| + internalAPI.generateKey(tokenId, function(spki) { |
| + if (chrome.runtime.lastError) { |
| + reject(chrome.runtime.lastError.message); |
| + return; |
| + } |
| + resolve(new KeyPair(spki, algorithm, keyUsages)); |
| + }); |
| + }); |
| + |
| +addCryptoMethod('sign', |
| + function(resolve, reject, tokenId, algorithm, key, dataView) { |
| + if (!(key instanceof Key)) |
| + throw new Error('Invalid key.'); |
| + if (key.type != "private") |
| + throw new Error('Key type not supported.'); |
| + |
| + // Create an ArrayBuffer that equals the dataView. Note that dataView.buffer |
| + // might contain more data than dataView. |
| + var data = dataView.buffer.slice(dataView.byteOffset, |
| + dataView.byteOffset + dataView.byteLength); |
| + internalAPI.sign(tokenId, privates(key).spki_, data, function(signature) { |
| + if (chrome.runtime.lastError) { |
| + reject(chrome.runtime.lastError.message); |
| + return; |
| + } |
| + resolve(signature); |
| + }); |
| +}); |
| + |
| +addCryptoMethod('exportKey', function(resolve, reject, tokenId, format, key) { |
| + if (format != 'spki') |
| + throw new Error('Format not supported.'); |
| + if (!(key instanceof Key)) |
| + throw new Error('Invalid key.'); |
| + if (key.type != "public") |
| + throw new Error('Key type not supported.'); |
| + |
| + resolve(privates(key).spki_); |
| +}); |
| + |
| +binding.registerCustomHook(function(api) { |
| + var apiFunctions = api.apiFunctions; |
| + |
| + var ret = apiFunctions.setHandleRequest('getTokens', function(callback) { |
| + internalAPI.getTokens(function(tokenIds) { |
| + callback($Array.map(tokenIds, |
| + function(tokenId) { return new Token(tokenId); })); |
| + }); |
| + }); |
| +}); |
| + |
| +exports.binding = binding.generate(); |