Chromium Code Reviews| Index: content/renderer/webcrypto/webcrypto_impl.cc |
| diff --git a/content/renderer/webcrypto/webcrypto_impl.cc b/content/renderer/webcrypto/webcrypto_impl.cc |
| index f794c59ed8461beb0cbf1634d446e386980e15e5..2335401ec35823a845c9a78c6cfc343e8225151b 100644 |
| --- a/content/renderer/webcrypto/webcrypto_impl.cc |
| +++ b/content/renderer/webcrypto/webcrypto_impl.cc |
| @@ -4,15 +4,274 @@ |
| #include "content/renderer/webcrypto/webcrypto_impl.h" |
| +#include <algorithm> |
| +#include <map> |
| +#include "base/base64.h" |
| +#include "base/json/json_reader.h" |
| +#include "base/logging.h" |
| #include "base/memory/scoped_ptr.h" |
| +#include "base/strings/string_piece.h" |
| +#include "base/values.h" |
| #include "third_party/WebKit/public/platform/WebArrayBuffer.h" |
| #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" |
| +#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" |
| #include "third_party/WebKit/public/platform/WebCryptoKey.h" |
| namespace content { |
| +namespace { |
| + |
| +// FIXME! Need WebKit::WebCryptoAlgorithmIdNone |
|
eroman
2013/10/22 21:49:38
There are other ways of accomplishing this that I
Ryan Sleevi
2013/10/24 01:45:58
There are other formats that may have embedded alg
eroman
2013/10/24 02:35:04
I will make the necessary changes to Blink side.
padolph
2013/10/28 20:35:07
This is addressed by your recent Blink checkin. Th
|
| +const WebKit::WebCryptoAlgorithmId WebCryptoAlgorithmIdNone = |
| + (WebKit::WebCryptoAlgorithmId)99; |
| + |
| +// TODO(padolph) Similar Create*Algorithm() methods are in |
|
eroman
2013/10/22 21:49:38
What do you think about a renderer/webcrypto/webcr
padolph
2013/10/28 20:35:07
Done.
Should the stuff in webcrypto_util.[h|cc] b
|
| +// webcrypto_impl_unittest.cc. Find a common place to put these. |
| + |
| +WebKit::WebCryptoAlgorithm CreateAlgorithm(WebKit::WebCryptoAlgorithmId id) { |
| + return WebKit::WebCryptoAlgorithm::adoptParamsAndCreate(id, NULL); |
| +} |
| + |
| +WebKit::WebCryptoAlgorithm CreateAlgorithmWithInnerHash( |
| + WebKit::WebCryptoAlgorithmId algorithm_id, |
| + unsigned short hash_key_length) { |
| + WebKit::WebCryptoAlgorithmId hashId; |
|
eroman
2013/10/22 21:49:38
use hacker_style_variable_naming for chromium code
padolph
2013/10/28 20:35:07
Done.
|
| + switch (hash_key_length) { |
| + case 160: |
| + hashId = WebKit::WebCryptoAlgorithmIdSha1; |
| + break; |
| + case 224: |
| + hashId = WebKit::WebCryptoAlgorithmIdSha224; |
| + break; |
| + case 256: |
| + hashId = WebKit::WebCryptoAlgorithmIdSha256; |
| + break; |
| + case 384: |
| + hashId = WebKit::WebCryptoAlgorithmIdSha384; |
| + break; |
| + case 512: |
| + hashId = WebKit::WebCryptoAlgorithmIdSha384; |
| + break; |
| + } |
| + return WebKit::WebCryptoAlgorithm::adoptParamsAndCreate( |
|
eroman
2013/10/22 21:49:38
Please add a default case to the switch above (per
padolph
2013/10/28 20:35:07
Done.
|
| + algorithm_id, |
| + new WebKit::WebCryptoHmacParams(CreateAlgorithm(hashId))); |
| +} |
| + |
| +WebKit::WebCryptoAlgorithm CreateHmacAlgorithm(unsigned short hash_key_length) { |
| + return CreateAlgorithmWithInnerHash( |
| + WebKit::WebCryptoAlgorithmIdHmac, |
| + hash_key_length); |
| +} |
| + |
| +WebKit::WebCryptoAlgorithm CreateRsaSsaAlgorithm( |
| + unsigned short hash_key_length) { |
| + return CreateAlgorithmWithInnerHash( |
| + WebKit::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, |
| + hash_key_length); |
| +} |
| + |
| +WebKit::WebCryptoAlgorithm CreateRsaOaepAlgorithm( |
| + unsigned short hash_key_length) { |
| + return CreateAlgorithmWithInnerHash( |
| + WebKit::WebCryptoAlgorithmIdRsaOaep, |
| + hash_key_length); |
| +} |
| + |
| +WebKit::WebCryptoAlgorithm CreateAesAlgorithm( |
| + WebKit::WebCryptoAlgorithmId aes_alg_id, |
| + unsigned short length) { |
| + return WebKit::WebCryptoAlgorithm::adoptParamsAndCreate( |
| + aes_alg_id, |
| + new WebKit::WebCryptoAesKeyGenParams(length)); |
| +} |
| + |
| +WebKit::WebCryptoAlgorithm CreateAesCbcAlgorithm(unsigned short length) { |
| + return CreateAesAlgorithm(WebKit::WebCryptoAlgorithmIdAesCbc, length); |
| +} |
| + |
| +WebKit::WebCryptoAlgorithm CreateAesGcmAlgorithm(unsigned short length) { |
| + return CreateAesAlgorithm(WebKit::WebCryptoAlgorithmIdAesGcm, length); |
| +} |
| + |
| +bool Base64DecodeUrlSafe(const std::string& input, std::string* output) { |
|
eroman
2013/10/22 21:49:38
Please provide a comment pointing to the definitio
padolph
2013/10/28 20:35:07
Will do. 'base64url' encoding is relatively common
|
| + std::string base64EncodedText(input); |
| + std::replace(base64EncodedText.begin(), base64EncodedText.end(), '-', '+'); |
|
eroman
2013/10/22 21:49:38
Are these transformations enumerated int he JOSE s
padolph
2013/10/28 20:35:07
Yes, in RFC4648 Section 5.
|
| + std::replace(base64EncodedText.begin(), base64EncodedText.end(), '_', '/'); |
| + base64EncodedText.append((4 - base64EncodedText.size() % 4) % 4, '='); |
| + return base::Base64Decode(base64EncodedText, output); |
| +} |
| + |
| +// Identifiers for all JWK "alg" (algorithm) values handled by this code. The |
|
eroman
2013/10/22 21:49:38
There is enough JWK stuff, that I suggest moving t
padolph
2013/10/28 20:35:07
Most of this code went away with the function tabl
|
| +// "enum trick" is used to force int type, so a user type is not required in |
|
eroman
2013/10/22 21:49:38
Not sure I know what the "enum trick" refers to. Y
padolph
2013/10/28 20:35:07
This code went away with the function table refact
|
| +// web_crypto_impl.h |
| +enum { |
| + kJwkAlgorithmHs256, |
| + kJwkAlgorithmHs384, |
| + kJwkAlgorithmHs512, |
| + kJwkAlgorithmRs256, |
| + kJwkAlgorithmRs384, |
| + kJwkAlgorithmRs512, |
| + kJwkAlgorithmRsa1_5, |
| + kJwkAlgorithmRsaOaep, |
| + kJwkAlgorithmA128Kw, |
| + kJwkAlgorithmA256Kw, |
| + kJwkAlgorithmA128Gcm, |
| + kJwkAlgorithmA256Gcm, |
| + kJwkAlgorithmA128Cbc, |
| + kJwkAlgorithmA256Cbc, |
| + kJwkAlgorithmA384Cbc, |
| + kJwkAlgorithmA512Cbc |
| +}; |
| + |
| +WebKit::WebCryptoAlgorithmId JwkAlgIdToWebCryptoAlgId(int jwk_algorithm_id) { |
|
eroman
2013/10/22 21:49:38
This function appears to be unused
padolph
2013/10/28 20:35:07
Done.
|
| + switch (jwk_algorithm_id) { |
| + case kJwkAlgorithmHs256: |
| + case kJwkAlgorithmHs384: |
| + case kJwkAlgorithmHs512: |
| + return WebKit::WebCryptoAlgorithmIdHmac; |
| + case kJwkAlgorithmRs256: |
| + case kJwkAlgorithmRs384: |
| + case kJwkAlgorithmRs512: |
| + return WebKit::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5; |
| + case kJwkAlgorithmRsa1_5: |
| + return WebKit::WebCryptoAlgorithmIdRsaEsPkcs1v1_5; |
| + case kJwkAlgorithmRsaOaep: |
| + return WebKit::WebCryptoAlgorithmIdRsaOaep; |
| + case kJwkAlgorithmA128Kw: |
| + case kJwkAlgorithmA256Kw: |
| + // TODO(padolph) Support AES keywrap algorithm, required for JWK but not |
| + // present in the Web Crypto spec. |
| + return WebCryptoAlgorithmIdNone; |
| + case kJwkAlgorithmA128Gcm: |
| + case kJwkAlgorithmA256Gcm: |
| + return WebKit::WebCryptoAlgorithmIdAesGcm; |
| + case kJwkAlgorithmA128Cbc: |
| + case kJwkAlgorithmA256Cbc: |
| + case kJwkAlgorithmA384Cbc: |
| + case kJwkAlgorithmA512Cbc: |
| + return WebKit::WebCryptoAlgorithmIdAesCbc; |
| + default: |
| + DCHECK(false); |
| + return WebCryptoAlgorithmIdNone; |
| + } |
| +} |
| + |
| +unsigned short JwkAlgIdToKeyLengthBits(int jwk_algorithm_id) { |
| + switch (jwk_algorithm_id) { |
| + case kJwkAlgorithmA128Kw: |
| + case kJwkAlgorithmA128Gcm: |
| + case kJwkAlgorithmA128Cbc: |
| + return 128; |
| + case kJwkAlgorithmHs256: |
| + case kJwkAlgorithmA256Kw: |
| + case kJwkAlgorithmRs256: |
| + case kJwkAlgorithmA256Gcm: |
| + case kJwkAlgorithmA256Cbc: |
| + return 256; |
| + case kJwkAlgorithmHs384: |
| + case kJwkAlgorithmRs384: |
| + case kJwkAlgorithmA384Cbc: |
| + return 384; |
| + case kJwkAlgorithmHs512: |
| + case kJwkAlgorithmRs512: |
| + case kJwkAlgorithmA512Cbc: |
| + return 512; |
| + default: |
| + return 0; |
| + } |
| +} |
| + |
| +WebKit::WebCryptoAlgorithm CreateWebCryptoAlgorithmFromJwkAlgorithmId( |
|
eroman
2013/10/22 21:49:38
I think things would be more readable to have a si
padolph
2013/10/28 20:35:07
Done. But since the creation functions have differ
|
| + int jwk_algorithm_id) { |
| + const unsigned short key_length_bits = |
| + JwkAlgIdToKeyLengthBits(jwk_algorithm_id); |
| + DCHECK(key_length_bits); |
| + switch(jwk_algorithm_id) { |
| + case kJwkAlgorithmHs256: |
| + case kJwkAlgorithmHs384: |
| + case kJwkAlgorithmHs512: |
| + return CreateHmacAlgorithm(key_length_bits); |
| + case kJwkAlgorithmRs256: |
| + case kJwkAlgorithmRs384: |
| + case kJwkAlgorithmRs512: |
| + return CreateRsaSsaAlgorithm(key_length_bits); |
| + case kJwkAlgorithmRsa1_5: |
| + return CreateAlgorithm(WebKit::WebCryptoAlgorithmIdRsaEsPkcs1v1_5); |
| + case kJwkAlgorithmRsaOaep: |
| + return CreateRsaOaepAlgorithm(key_length_bits); |
| + case kJwkAlgorithmA128Kw: |
| + case kJwkAlgorithmA256Kw: |
| + // TODO(padolph) Support AES keywrap algorithm, required for JWK but not |
| + // present in the Web Crypto spec. |
| + return CreateAlgorithm(WebCryptoAlgorithmIdNone); |
| + case kJwkAlgorithmA128Gcm: |
| + case kJwkAlgorithmA256Gcm: |
| + return CreateAesGcmAlgorithm(key_length_bits); |
| + case kJwkAlgorithmA128Cbc: |
| + case kJwkAlgorithmA256Cbc: |
| + case kJwkAlgorithmA384Cbc: |
| + case kJwkAlgorithmA512Cbc: |
| + return CreateAesCbcAlgorithm(key_length_bits); |
| + default: |
| + DCHECK(false); |
|
eroman
2013/10/22 21:49:38
NOTREACHED()
padolph
2013/10/28 20:35:07
This code is now gone.
|
| + return CreateAlgorithm(WebCryptoAlgorithmIdNone); |
| + } |
| +} |
| + |
| +typedef std::map<std::string, int> StringIntMap; |
| + |
| +void InitJwkAlgorithmMap(StringIntMap& jwk_algorithm_map) |
|
eroman
2013/10/22 21:49:38
Chromium style (unlike Blink style) does not like
padolph
2013/10/28 20:35:07
This code is now gone.
|
| +{ |
| + // Note: A*CBC are not yet present in the JOSE JWA spec |
| + // http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-16 |
| + jwk_algorithm_map["HS256" ] = kJwkAlgorithmHs256; |
|
eroman
2013/10/22 21:49:38
style nit: remove the space padding (i personally
padolph
2013/10/28 20:35:07
Done.
|
| + jwk_algorithm_map["HS384" ] = kJwkAlgorithmHs384; |
| + jwk_algorithm_map["HS512" ] = kJwkAlgorithmHs512; |
| + jwk_algorithm_map["RS256" ] = kJwkAlgorithmRs256; |
| + jwk_algorithm_map["RS384" ] = kJwkAlgorithmRs384; |
| + jwk_algorithm_map["RS512" ] = kJwkAlgorithmRs512; |
| + jwk_algorithm_map["RSA1_5" ] = kJwkAlgorithmRsa1_5; |
| + jwk_algorithm_map["RSA-OAEP"] = kJwkAlgorithmRsaOaep; |
| + jwk_algorithm_map["A128KW" ] = kJwkAlgorithmA128Kw; |
| + jwk_algorithm_map["A256KW" ] = kJwkAlgorithmA256Kw; |
| + jwk_algorithm_map["A128GCM" ] = kJwkAlgorithmA128Gcm; |
| + jwk_algorithm_map["A256GCM" ] = kJwkAlgorithmA256Gcm; |
| + jwk_algorithm_map["A128CBC" ] = kJwkAlgorithmA128Cbc; |
| + jwk_algorithm_map["A256CBC" ] = kJwkAlgorithmA256Cbc; |
| + jwk_algorithm_map["A384CBC" ] = kJwkAlgorithmA384Cbc; |
| + jwk_algorithm_map["A512CBC" ] = kJwkAlgorithmA512Cbc; |
| +} |
| + |
| +// forward |
| +bool operator!=(const WebKit::WebCryptoAlgorithm& lhs, |
| + const WebKit::WebCryptoAlgorithm& rhs); |
| + |
| +// TODO(padolph) Verify this logic is sufficient to judge algorithm |
| +// "consistency" for JWK import, and for all supported algorithms. |
| +bool operator==(const WebKit::WebCryptoAlgorithm& lhs, |
|
eroman
2013/10/22 21:49:38
Chromium style guide doesn't like operator overloa
Ryan Sleevi
2013/10/24 01:45:58
Should WebKit::WebCryptoAlgorithm have an Equals()
eroman
2013/10/24 02:35:04
It isn't obvious what equality means, so I think t
padolph
2013/10/28 20:35:07
Function name changed. But I am also very confused
|
| + const WebKit::WebCryptoAlgorithm& rhs) { |
| + if (lhs.id() != rhs.id()) |
| + return false; |
| + if (lhs.id() == WebKit::WebCryptoAlgorithmIdHmac || |
| + lhs.id() == WebKit::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 || |
| + lhs.id() == WebKit::WebCryptoAlgorithmIdRsaOaep) { |
| + if (lhs.hmacParams()->hash() != rhs.hmacParams()->hash()) |
| + return false; |
| + } |
| + return true; |
|
eroman
2013/10/22 21:49:38
For the sake of future proofing, I would rather ha
padolph
2013/10/28 20:35:07
Done.
|
| +} |
| + |
| +bool operator!=(const WebKit::WebCryptoAlgorithm& lhs, |
| + const WebKit::WebCryptoAlgorithm& rhs) { |
| + return !(lhs == rhs); |
| +} |
| + |
| +} // namespace |
| + |
| WebCryptoImpl::WebCryptoImpl() { |
| Init(); |
| + InitJwkAlgorithmMap(jwk_algorithm_map_); |
|
eroman
2013/10/22 21:49:38
I would prefer lazy initialization, since JWK may
Ryan Sleevi
2013/10/24 01:45:58
Don't use a function-level static. They're forbidd
eroman
2013/10/24 02:35:04
My mistake! I got muddled with Blink style vs Chro
padolph
2013/10/28 20:35:07
LazyInstance used.
|
| } |
| void WebCryptoImpl::encrypt( |
| @@ -84,20 +343,30 @@ void WebCryptoImpl::importKey( |
| WebKit::WebCryptoKeyType type; |
| scoped_ptr<WebKit::WebCryptoKeyHandle> handle; |
| - if (!ImportKeyInternal(format, |
| - key_data, |
| - key_data_size, |
| - algorithm, |
| - usage_mask, |
| - &handle, |
| - &type)) { |
| - result.completeWithError(); |
| - return; |
| + if (format == WebKit::WebCryptoKeyFormatJwk) { |
| + if (!ImportKeyJwk(key_data, |
| + key_data_size, |
| + extractable, |
| + algorithm, |
| + usage_mask, |
| + &handle, |
| + &type)) { |
| + result.completeWithError(); |
| + } |
| + } else { |
| + if (!ImportKeyInternal(format, |
| + key_data, |
| + key_data_size, |
| + algorithm, |
| + usage_mask, |
| + &handle, |
| + &type)) { |
| + result.completeWithError(); |
| + } |
| } |
| - WebKit::WebCryptoKey key( |
| - WebKit::WebCryptoKey::create( |
| - handle.release(), type, extractable, algorithm, usage_mask)); |
| + WebKit::WebCryptoKey key(WebKit::WebCryptoKey::create( |
| + handle.release(), type, extractable, algorithm, usage_mask)); |
| result.completeWithKey(key); |
| } |
| @@ -138,4 +407,204 @@ void WebCryptoImpl::verifySignature( |
| } |
| } |
| +bool WebCryptoImpl::ImportKeyJwk( |
| + const unsigned char* key_data, |
| + unsigned key_data_size, |
| + bool extractable, |
| + const WebKit::WebCryptoAlgorithm& algorithm, |
| + WebKit::WebCryptoKeyUsageMask usage_mask, |
| + scoped_ptr<WebKit::WebCryptoKeyHandle>* handle, |
| + WebKit::WebCryptoKeyType* type) { |
| + |
| + // JSON Web Key Format (JWK) |
|
eroman
2013/10/22 21:49:38
This is a good comment block, thanks!
|
| + // http://tools.ietf.org/html/draft-ietf-jose-json-web-key-16 |
| + // TODO(padolph) Not all possible values are handled by this code right now |
| + // |
| + // A JWK is a simple JSON dictionary with the following entries |
| + // - "kty" (Key Type) Parameter, REQUIRED |
| + // - <kty-specific parameters, see below>, REQUIRED |
| + // - "use" (Key Use) Parameter, OPTIONAL |
| + // - "alg" (Algorithm) Parameter, OPTIONAL |
| + // - "extractable" (Key Exportability), OPTIONAL [NOTE: not yet part of JOSE] |
| + // (all other entries are ignored) |
| + // |
| + // Input key_data contains the JWK. To build a Web Crypto Key, the JWK values |
| + // are parsed out and used as follows: |
| + // Web Crypto Key type <-- (deduced) |
| + // Web Crypto Key extractable <-- extractable |
| + // Web Crypto Key algorithm <-- alg |
| + // Web Crypto Key keyUsage <-- usage |
| + // Web Crypto Key keying material <-- kty-specific parameters |
| + // |
| + // Values for each entry are case-sensitive and defined in |
| + // http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-16. |
| + // Note that not all values specified by JOSE are handled by this code. Only |
| + // handled values are listed. |
| + // - kty (Key Type) |
| + // +-------+--------------------------------------------------------------+ |
| + // | "RSA" | RSA [RFC3447] | |
| + // | "oct" | Octet sequence (used to represent symmetric keys) | |
| + // +-------+--------------------------------------------------------------+ |
| + // - use (Key Use) |
| + // +-------+--------------------------------------------------------------+ |
| + // | "enc" | encrypt and decrypt operations | |
| + // | "sig" | sign and verify (MAC) operations | |
| + // | "wrap"| key wrap and unwrap [not yet part of JOSE] | |
| + // +-------+--------------------------------------------------------------+ |
| + // - extractable (Key Exportability) |
| + // +-------+--------------------------------------------------------------+ |
| + // | true | Key may be exported from the trusted environment | |
| + // | false | Key cannot exit the trusted environment | |
| + // +-------+--------------------------------------------------------------+ |
| + // - alg (Algorithm) |
| + // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-16 |
| + // +--------------+-------------------------------------------------------+ |
| + // | Digital Signature or MAC Algorithm | |
| + // +--------------+-------------------------------------------------------+ |
| + // | "HS256" | HMAC using SHA-256 hash algorithm | |
| + // | "HS384" | HMAC using SHA-384 hash algorithm | |
| + // | "HS512" | HMAC using SHA-512 hash algorithm | |
| + // | "RS256" | RSASSA using SHA-256 hash algorithm | |
| + // | "RS384" | RSASSA using SHA-384 hash algorithm | |
| + // | "RS512" | RSASSA using SHA-512 hash algorithm | |
| + // +--------------+-------------------------------------------------------| |
| + // | Key Management Algorithm | |
| + // +--------------+-------------------------------------------------------+ |
| + // | "RSA1_5" | RSAES-PKCS1-V1_5 [RFC3447] | |
| + // | "RSA-OAEP" | RSAES using Optimal Asymmetric Encryption Padding | |
| + // | | (OAEP) [RFC3447], with the default parameters | |
| + // | | specified by RFC3447 in Section A.2.1 | |
| + // | "A128KW" | Advanced Encryption Standard (AES) Key Wrap Algorithm | |
| + // | | [RFC3394] using 128 bit keys | |
| + // | "A256KW" | AES Key Wrap Algorithm using 256 bit keys | |
| + // | "A128GCM" | AES in Galois/Counter Mode (GCM) [NIST.800-38D] using | |
| + // | | 128 bit keys | |
| + // | "A256GCM" | AES GCM using 256 bit keys | |
| + // | "A128CBC" | AES in Cipher Block Chaining Mode (CBC) with PKCS #5 | |
| + // | | padding [NIST.800-38A] [not yet part of JOSE] | |
| + // | "A256CBC" | AES CBC using 256 bit keys [not yet part of JOSE] | |
| + // | "A384CBC" | AES CBC using 384 bit keys [not yet part of JOSE] | |
| + // | "A512CBC" | AES CBC using 512 bit keys [not yet part of JOSE] | |
| + // +--------------+-------------------------------------------------------+ |
| + // |
| + // kty-specific parameters |
| + // The value of kty determines the type and content of the keying material |
| + // carried in the JWK to be imported. Currently only two possibilities are |
| + // supported: a raw key or an RSA public key. RSA private keys are not |
| + // supported because typical applications seldom need to import a private key, |
| + // and the large number of JWK parameters required to describe one. |
| + // - kty == "oct" (symmetric or other raw key) |
| + // +-------+--------------------------------------------------------------+ |
| + // | "k" | Contains the value of the symmetric (or other single-valued) | |
| + // | | key. It is represented as the base64url encoding of the | |
| + // | | octet sequence containing the key value. | |
| + // +-------+--------------------------------------------------------------+ |
| + // - kty == "RSA" (RSA public key) |
| + // +-------+--------------------------------------------------------------+ |
| + // | "n" | Contains the modulus value for the RSA public key. It is | |
| + // | | represented as the base64url encoding of the value's | |
| + // | | unsigned big endian representation as an octet sequence. | |
| + // +-------+--------------------------------------------------------------+ |
| + // | "e" | Contains the exponent value for the RSA public key. It is | |
| + // | | represented as the base64url encoding of the value's | |
| + // | | unsigned big endian representation as an octet sequence. | |
| + // +-------+--------------------------------------------------------------+ |
| + // |
| + // Conflict resolution |
| + // The type, algorithm, extractable, and usage_mask input parameters may be |
| + // different from similar values inside the JWK. The Web Crypto spec says that |
| + // if a JWK value is present, but is inconsistent with the input value, it is |
| + // an error and the operation must fail. |
| + |
| + const char* const foo = reinterpret_cast<const char *>(key_data); |
|
eroman
2013/10/22 21:49:38
Please use a variable name other than "foo".
padolph
2013/10/28 20:35:07
Done.
|
| + base::StringPiece json_string(foo, key_data_size); |
| + scoped_ptr<base::Value> value(base::JSONReader::Read(json_string)); |
| + // Note, bare pointer dict_value is ok since it points into scoped value. |
| + base::DictionaryValue* dict_value = NULL; |
| + if (!value.get() || !value->GetAsDictionary(&dict_value) || !dict_value) |
| + return false; |
| + |
| + // JWK "kty". Exit early if this required JWK parameter is missing. |
| + std::string jwk_kty_value; |
| + if (!dict_value->GetString("kty", &jwk_kty_value)) |
| + return false; |
| + |
| + // JWK "extractable" --> extractable parameter |
| + bool jwk_extractable_value; |
| + if (dict_value->GetBoolean("extractable", &jwk_extractable_value)) { |
| + // collision check |
| + if (jwk_extractable_value != extractable) |
| + return false; |
| + } |
| + |
| + // JWK "alg" --> algorithm parameter |
| + std::string jwk_alg_value; |
| + if (dict_value->GetString("alg", &jwk_alg_value)) { |
| + const StringIntMap::iterator pos = jwk_algorithm_map_.find(jwk_alg_value); |
|
eroman
2013/10/22 21:49:38
const_iterator?
padolph
2013/10/28 20:35:07
Done.
|
| + if (pos == jwk_algorithm_map_.end()) |
| + return false; |
| + const int jwk_algorithm_id = pos->second; |
| + WebKit::WebCryptoAlgorithm webcrypto_algorithm_from_jwk = |
| + CreateWebCryptoAlgorithmFromJwkAlgorithmId(jwk_algorithm_id); |
| + // collision check |
| + if (webcrypto_algorithm_from_jwk != algorithm) |
| + return false; |
| + } |
| + |
| + // JWK "use" --> usage_mask parameter |
| + std::string jwk_use_value; |
| + if (dict_value->GetString("use", &jwk_use_value)) { |
| + unsigned jwk_usage_mask; |
| + if (jwk_use_value == "enc") { |
| + jwk_usage_mask = |
| + WebKit::WebCryptoKeyUsageEncrypt | WebKit::WebCryptoKeyUsageDecrypt; |
| + } else if (jwk_use_value == "sig") { |
| + jwk_usage_mask = |
| + WebKit::WebCryptoKeyUsageSign | WebKit::WebCryptoKeyUsageVerify; |
| + } else if (jwk_use_value == "wrap") { |
| + jwk_usage_mask = |
| + WebKit::WebCryptoKeyUsageWrapKey | WebKit::WebCryptoKeyUsageUnwrapKey; |
| + } else { |
| + return false; |
| + } |
| + // collision check |
| + if (!(jwk_usage_mask & usage_mask)) |
|
eroman
2013/10/22 21:49:38
Do they need to match exactly?
Ryan Sleevi
2013/10/24 01:45:58
No.
The spec merely says that if they conflict in
eroman
2013/10/24 02:35:04
Thanks Ryan!
My understanding then is that we wan
padolph
2013/10/28 20:35:07
Yea, after thinking about it more, subset makes mo
|
| + return false; |
| + } |
| + |
| + // JWK keying material --> ImportKeyInternal() |
| + if (jwk_kty_value == "oct") { |
| + // collision check |
| + if (*type != WebKit::WebCryptoKeyTypeSecret) |
| + return false; |
| + std::string jwk_k_value_url64; |
| + if (!dict_value->GetString("k", &jwk_k_value_url64)) |
| + return false; |
| + std::string jwk_k_value; |
| + if (!Base64DecodeUrlSafe(jwk_k_value_url64, &jwk_k_value)) |
| + return false; |
| + const std::vector<uint8> data(jwk_k_value.begin(), jwk_k_value.end()); |
|
eroman
2013/10/22 21:49:38
Rather than copying into a std::vector<>, I believ
padolph
2013/10/28 20:35:07
Done.
|
| + if (!ImportKeyInternal(WebKit::WebCryptoKeyFormatRaw, |
| + &data[0], |
|
eroman
2013/10/22 21:49:38
Is data guaranteed to have at least 1 element?
padolph
2013/10/28 20:35:07
No. I added a check for that plus a unit test. Tha
|
| + data.size(), |
| + algorithm, |
| + usage_mask, |
| + handle, |
| + type)) { |
| + return false; |
| + } |
| + } else if (jwk_kty_value == "RSA") { |
| + // Only an RSA public key is currently handled. |
| + // collision check |
| + if (*type != WebKit::WebCryptoKeyTypePublic) |
| + return false; |
| + // TODO(padolph): JWK import RSA public key |
| + return false; |
| + } else { |
| + return false; |
| + } |
| + |
| + return true; |
| +} |
| + |
| } // namespace content |