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(); |