Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/renderer/webcrypto/webcrypto_impl.h" | 5 #include "content/renderer/webcrypto/webcrypto_impl.h" |
| 6 | 6 |
| 7 #include <algorithm> | |
| 8 #include <map> | |
| 9 #include "base/base64.h" | |
| 10 #include "base/json/json_reader.h" | |
| 11 #include "base/logging.h" | |
| 7 #include "base/memory/scoped_ptr.h" | 12 #include "base/memory/scoped_ptr.h" |
| 13 #include "base/strings/string_piece.h" | |
| 14 #include "base/values.h" | |
| 8 #include "third_party/WebKit/public/platform/WebArrayBuffer.h" | 15 #include "third_party/WebKit/public/platform/WebArrayBuffer.h" |
| 9 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" | 16 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" |
| 17 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" | |
| 10 #include "third_party/WebKit/public/platform/WebCryptoKey.h" | 18 #include "third_party/WebKit/public/platform/WebCryptoKey.h" |
| 11 | 19 |
| 12 namespace content { | 20 namespace content { |
| 13 | 21 |
| 22 namespace { | |
| 23 | |
| 24 // TODO(padolph) Similar Create*Algorithm() methods are in | |
| 25 // webcrypto_impl_unittest.cc. Find a common place to put these. | |
| 26 | |
| 27 WebKit::WebCryptoAlgorithm CreateAlgorithm(WebKit::WebCryptoAlgorithmId id) { | |
| 28 return WebKit::WebCryptoAlgorithm::adoptParamsAndCreate(id, NULL); | |
| 29 } | |
| 30 | |
| 31 WebKit::WebCryptoAlgorithm CreateAlgorithmWithInnerHash( | |
| 32 WebKit::WebCryptoAlgorithmId algorithm_id, | |
| 33 unsigned short hash_key_length) { | |
| 34 WebKit::WebCryptoAlgorithmId hashId; | |
| 35 switch (hash_key_length) { | |
| 36 case 160: | |
| 37 hashId = WebKit::WebCryptoAlgorithmIdSha1; | |
| 38 break; | |
| 39 case 224: | |
| 40 hashId = WebKit::WebCryptoAlgorithmIdSha224; | |
| 41 break; | |
| 42 case 256: | |
| 43 hashId = WebKit::WebCryptoAlgorithmIdSha256; | |
| 44 break; | |
| 45 case 384: | |
| 46 hashId = WebKit::WebCryptoAlgorithmIdSha384; | |
| 47 break; | |
| 48 case 512: | |
| 49 hashId = WebKit::WebCryptoAlgorithmIdSha384; | |
| 50 break; | |
| 51 } | |
| 52 return WebKit::WebCryptoAlgorithm::adoptParamsAndCreate( | |
| 53 algorithm_id, | |
| 54 new WebKit::WebCryptoHmacParams(CreateAlgorithm(hashId))); | |
| 55 } | |
| 56 | |
| 57 WebKit::WebCryptoAlgorithm CreateHmacAlgorithm(unsigned short hash_key_length) { | |
| 58 return CreateAlgorithmWithInnerHash( | |
| 59 WebKit::WebCryptoAlgorithmIdHmac, | |
| 60 hash_key_length); | |
| 61 } | |
| 62 | |
| 63 WebKit::WebCryptoAlgorithm CreateRsaSsaAlgorithm( | |
| 64 unsigned short hash_key_length) { | |
| 65 return CreateAlgorithmWithInnerHash( | |
| 66 WebKit::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, | |
| 67 hash_key_length); | |
| 68 } | |
| 69 | |
| 70 WebKit::WebCryptoAlgorithm CreateRsaOaepAlgorithm( | |
| 71 unsigned short hash_key_length) { | |
| 72 return CreateAlgorithmWithInnerHash( | |
| 73 WebKit::WebCryptoAlgorithmIdRsaOaep, | |
| 74 hash_key_length); | |
| 75 } | |
| 76 | |
| 77 WebKit::WebCryptoAlgorithm CreateAesAlgorithm( | |
| 78 WebKit::WebCryptoAlgorithmId aes_alg_id, | |
| 79 unsigned short length) { | |
| 80 return WebKit::WebCryptoAlgorithm::adoptParamsAndCreate( | |
| 81 aes_alg_id, | |
| 82 new WebKit::WebCryptoAesKeyGenParams(length)); | |
| 83 } | |
| 84 | |
| 85 WebKit::WebCryptoAlgorithm CreateAesCbcAlgorithm(unsigned short length) { | |
| 86 return CreateAesAlgorithm(WebKit::WebCryptoAlgorithmIdAesCbc, length); | |
| 87 } | |
| 88 | |
| 89 WebKit::WebCryptoAlgorithm CreateAesGcmAlgorithm(unsigned short length) { | |
| 90 return CreateAesAlgorithm(WebKit::WebCryptoAlgorithmIdAesGcm, length); | |
| 91 } | |
| 92 | |
| 93 bool Base64DecodeUrlSafe(const std::string& input, std::string* output) { | |
| 94 std::string base64EncodedText(input); | |
| 95 std::replace(base64EncodedText.begin(), base64EncodedText.end(), '-', '+'); | |
| 96 std::replace(base64EncodedText.begin(), base64EncodedText.end(), '_', '/'); | |
| 97 base64EncodedText.append((4 - base64EncodedText.size() % 4) % 4, '='); | |
| 98 return base::Base64Decode(base64EncodedText, output); | |
| 99 } | |
| 100 | |
| 101 // Identifiers for all JWK "alg" (algorithm) values handled by this code. The | |
| 102 // "enum trick" is used to force int type, so a user type is not required in | |
| 103 // web_crypto_impl.h | |
| 104 enum { | |
| 105 kJwkAlgorithmHs256, | |
| 106 kJwkAlgorithmHs384, | |
| 107 kJwkAlgorithmHs512, | |
| 108 kJwkAlgorithmRs256, | |
| 109 kJwkAlgorithmRs384, | |
| 110 kJwkAlgorithmRs512, | |
| 111 kJwkAlgorithmRsa1_5, | |
| 112 kJwkAlgorithmRsaOaep, | |
| 113 kJwkAlgorithmA128Kw, | |
| 114 kJwkAlgorithmA256Kw, | |
| 115 kJwkAlgorithmA128Gcm, | |
| 116 kJwkAlgorithmA256Gcm, | |
| 117 kJwkAlgorithmA128Cbc, | |
| 118 kJwkAlgorithmA256Cbc, | |
| 119 kJwkAlgorithmA384Cbc, | |
| 120 kJwkAlgorithmA512Cbc | |
| 121 }; | |
| 122 | |
| 123 WebKit::WebCryptoAlgorithmId JwkAlgIdToWebCryptoAlgId(int jwk_algorithm_id) { | |
| 124 switch (jwk_algorithm_id) { | |
| 125 case kJwkAlgorithmHs256: | |
| 126 case kJwkAlgorithmHs384: | |
| 127 case kJwkAlgorithmHs512: | |
| 128 return WebKit::WebCryptoAlgorithmIdHmac; | |
| 129 case kJwkAlgorithmRs256: | |
| 130 case kJwkAlgorithmRs384: | |
| 131 case kJwkAlgorithmRs512: | |
| 132 return WebKit::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5; | |
| 133 case kJwkAlgorithmRsa1_5: | |
| 134 return WebKit::WebCryptoAlgorithmIdRsaEsPkcs1v1_5; | |
| 135 case kJwkAlgorithmRsaOaep: | |
| 136 return WebKit::WebCryptoAlgorithmIdRsaOaep; | |
| 137 case kJwkAlgorithmA128Kw: | |
| 138 case kJwkAlgorithmA256Kw: | |
| 139 // TODO(padolph) Support AES keywrap algorithm, required for JWK but not | |
| 140 // present in the Web Crypto spec. | |
| 141 return WebKit::WebCryptoAlgorithmIdNone; | |
| 142 case kJwkAlgorithmA128Gcm: | |
| 143 case kJwkAlgorithmA256Gcm: | |
| 144 return WebKit::WebCryptoAlgorithmIdAesGcm; | |
| 145 case kJwkAlgorithmA128Cbc: | |
| 146 case kJwkAlgorithmA256Cbc: | |
| 147 case kJwkAlgorithmA384Cbc: | |
| 148 case kJwkAlgorithmA512Cbc: | |
| 149 return WebKit::WebCryptoAlgorithmIdAesCbc; | |
| 150 default: | |
| 151 DCHECK(false); | |
| 152 return WebKit::WebCryptoAlgorithmIdNone; | |
| 153 } | |
| 154 } | |
| 155 | |
| 156 unsigned short JwkAlgIdToKeyLengthBits(int jwk_algorithm_id) { | |
| 157 switch (jwk_algorithm_id) { | |
| 158 case kJwkAlgorithmA128Kw: | |
| 159 case kJwkAlgorithmA128Gcm: | |
| 160 case kJwkAlgorithmA128Cbc: | |
| 161 return 128; | |
| 162 case kJwkAlgorithmHs256: | |
| 163 case kJwkAlgorithmA256Kw: | |
| 164 case kJwkAlgorithmRs256: | |
| 165 case kJwkAlgorithmA256Gcm: | |
| 166 case kJwkAlgorithmA256Cbc: | |
| 167 return 256; | |
| 168 case kJwkAlgorithmHs384: | |
| 169 case kJwkAlgorithmRs384: | |
| 170 case kJwkAlgorithmA384Cbc: | |
| 171 return 384; | |
| 172 case kJwkAlgorithmHs512: | |
| 173 case kJwkAlgorithmRs512: | |
| 174 case kJwkAlgorithmA512Cbc: | |
| 175 return 512; | |
| 176 default: | |
| 177 return 0; | |
| 178 } | |
| 179 } | |
| 180 | |
| 181 typedef std::map<std::string, int> StringIntMap; | |
| 182 | |
| 183 // Syntactic sugar to make runtime initialization of a std::map more palatable, | |
| 184 // similar to what you can do in C++11 or with Boost.Assign. | |
| 185 // Example: | |
| 186 // StringIntMap my_map; | |
| 187 // // instead of this | |
| 188 // my_map.insert(std::make_pair("a", 1); | |
| 189 // my_map.insert(std::make_pair("b", 2); | |
| 190 // my_map.insert(std::make_pair("c", 3); | |
| 191 // my_map.insert(std::make_pair("d", 4); | |
| 192 // // do this | |
| 193 // map_fill<StringIntMap> | |
| 194 // ("a", 1) | |
| 195 // ("b", 2) | |
| 196 // ("c", 3) | |
| 197 // ("d", 4) | |
| 198 // .to(my_map); | |
|
Ryan Sleevi
2013/10/04 23:19:11
Why is this syntactic sugar needed, when
my_map["
padolph
2013/10/05 02:57:42
Done.
| |
| 199 template <typename MapType> | |
| 200 class FillMap { | |
| 201 public: | |
| 202 typedef typename MapType::key_type KeyType; | |
| 203 typedef typename MapType::mapped_type MappedType; | |
| 204 FillMap(const KeyType& key, const MappedType& val) { operator()(key, val); } | |
| 205 FillMap& operator()(const KeyType& key, const MappedType& val) { | |
| 206 map_.insert(std::make_pair(key, val)); | |
| 207 return *this; | |
| 208 } | |
| 209 void to(MapType& map) { map.swap(map_); } | |
| 210 private: | |
| 211 MapType map_; | |
| 212 }; | |
| 213 | |
| 214 void InitJwkAlgorithmMap(StringIntMap& jwk_algorithm_map) | |
| 215 { | |
| 216 // Note: A*CBC are not yet present in the JOSE JWA spec | |
| 217 // http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-16 | |
| 218 FillMap<StringIntMap> | |
| 219 ("HS256" , kJwkAlgorithmHs256 ) | |
| 220 ("HS384" , kJwkAlgorithmHs384 ) | |
| 221 ("HS512" , kJwkAlgorithmHs512 ) | |
| 222 ("RS256" , kJwkAlgorithmRs256 ) | |
| 223 ("RS384" , kJwkAlgorithmRs384 ) | |
| 224 ("RS512" , kJwkAlgorithmRs512 ) | |
| 225 ("RSA1_5" , kJwkAlgorithmRsa1_5 ) | |
| 226 ("RSA-OAEP", kJwkAlgorithmRsaOaep) | |
| 227 ("A128KW" , kJwkAlgorithmA128Kw ) | |
| 228 ("A256KW" , kJwkAlgorithmA256Kw ) | |
| 229 ("A128GCM" , kJwkAlgorithmA128Gcm) | |
| 230 ("A256GCM" , kJwkAlgorithmA256Gcm) | |
| 231 ("A128CBC" , kJwkAlgorithmA128Cbc) | |
| 232 ("A256CBC" , kJwkAlgorithmA256Cbc) | |
| 233 ("A384CBC" , kJwkAlgorithmA384Cbc) | |
| 234 ("A512CBC" , kJwkAlgorithmA512Cbc) | |
| 235 .to(jwk_algorithm_map); | |
| 236 } | |
| 237 | |
| 238 } // namespace | |
| 239 | |
| 14 WebCryptoImpl::WebCryptoImpl() { | 240 WebCryptoImpl::WebCryptoImpl() { |
| 15 Init(); | 241 Init(); |
| 242 InitJwkAlgorithmMap(jwk_algorithm_map_); | |
| 16 } | 243 } |
| 17 | 244 |
| 18 void WebCryptoImpl::encrypt( | 245 void WebCryptoImpl::encrypt( |
| 19 const WebKit::WebCryptoAlgorithm& algorithm, | 246 const WebKit::WebCryptoAlgorithm& algorithm, |
| 20 const WebKit::WebCryptoKey& key, | 247 const WebKit::WebCryptoKey& key, |
| 21 const unsigned char* data, | 248 const unsigned char* data, |
| 22 unsigned data_size, | 249 unsigned data_size, |
| 23 WebKit::WebCryptoResult result) { | 250 WebKit::WebCryptoResult result) { |
| 24 WebKit::WebArrayBuffer buffer; | 251 WebKit::WebArrayBuffer buffer; |
| 25 if (!EncryptInternal(algorithm, key, data, data_size, &buffer)) { | 252 if (!EncryptInternal(algorithm, key, data, data_size, &buffer)) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 59 void WebCryptoImpl::importKey( | 286 void WebCryptoImpl::importKey( |
| 60 WebKit::WebCryptoKeyFormat format, | 287 WebKit::WebCryptoKeyFormat format, |
| 61 const unsigned char* key_data, | 288 const unsigned char* key_data, |
| 62 unsigned key_data_size, | 289 unsigned key_data_size, |
| 63 const WebKit::WebCryptoAlgorithm& algorithm, | 290 const WebKit::WebCryptoAlgorithm& algorithm, |
| 64 bool extractable, | 291 bool extractable, |
| 65 WebKit::WebCryptoKeyUsageMask usage_mask, | 292 WebKit::WebCryptoKeyUsageMask usage_mask, |
| 66 WebKit::WebCryptoResult result) { | 293 WebKit::WebCryptoResult result) { |
| 67 WebKit::WebCryptoKeyType type; | 294 WebKit::WebCryptoKeyType type; |
| 68 scoped_ptr<WebKit::WebCryptoKeyHandle> handle; | 295 scoped_ptr<WebKit::WebCryptoKeyHandle> handle; |
| 296 WebKit::WebCryptoAlgorithm modified_algorithm = algorithm; | |
| 69 | 297 |
| 70 if (!ImportKeyInternal(format, | 298 if (format == WebKit::WebCryptoKeyFormatJwk) { |
| 71 key_data, | 299 if (!ImportKeyJwk(key_data, |
| 72 key_data_size, | 300 key_data_size, |
| 73 algorithm, | 301 &handle, |
| 74 usage_mask, | 302 &type, |
| 75 &handle, | 303 &extractable, |
| 76 &type)) { | 304 &modified_algorithm, |
| 77 result.completeWithError(); | 305 &usage_mask)) { |
| 78 return; | 306 result.completeWithError(); |
| 307 } | |
| 308 } else { | |
| 309 if (!ImportKeyInternal(format, | |
| 310 key_data, | |
| 311 key_data_size, | |
| 312 modified_algorithm, | |
| 313 usage_mask, | |
| 314 &handle, | |
| 315 &type)) { | |
| 316 result.completeWithError(); | |
| 317 } | |
| 79 } | 318 } |
| 80 | 319 |
| 81 WebKit::WebCryptoKey key( | 320 WebKit::WebCryptoKey key(WebKit::WebCryptoKey::create( |
| 82 WebKit::WebCryptoKey::create( | 321 handle.release(), type, extractable, modified_algorithm, usage_mask)); |
| 83 handle.release(), type, extractable, algorithm, usage_mask)); | |
| 84 | 322 |
| 85 result.completeWithKey(key); | 323 result.completeWithKey(key); |
| 86 } | 324 } |
| 87 | 325 |
| 88 void WebCryptoImpl::sign( | 326 void WebCryptoImpl::sign( |
| 89 const WebKit::WebCryptoAlgorithm& algorithm, | 327 const WebKit::WebCryptoAlgorithm& algorithm, |
| 90 const WebKit::WebCryptoKey& key, | 328 const WebKit::WebCryptoKey& key, |
| 91 const unsigned char* data, | 329 const unsigned char* data, |
| 92 unsigned data_size, | 330 unsigned data_size, |
| 93 WebKit::WebCryptoResult result) { | 331 WebKit::WebCryptoResult result) { |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 114 signature_size, | 352 signature_size, |
| 115 data, | 353 data, |
| 116 data_size, | 354 data_size, |
| 117 &signature_match)) { | 355 &signature_match)) { |
| 118 result.completeWithError(); | 356 result.completeWithError(); |
| 119 } else { | 357 } else { |
| 120 result.completeWithBoolean(signature_match); | 358 result.completeWithBoolean(signature_match); |
| 121 } | 359 } |
| 122 } | 360 } |
| 123 | 361 |
| 362 bool WebCryptoImpl::ImportKeyJwk( | |
| 363 const unsigned char* key_data, | |
| 364 unsigned key_data_size, | |
| 365 scoped_ptr<WebKit::WebCryptoKeyHandle>* handle, | |
| 366 WebKit::WebCryptoKeyType* type, | |
| 367 bool* extractable, | |
| 368 WebKit::WebCryptoAlgorithm* algorithm, | |
| 369 WebKit::WebCryptoKeyUsageMask* usage_mask) { | |
| 370 | |
| 371 // JSON Web Key Format (JWK) | |
| 372 // http://self-issued.info/docs/draft-ietf-jose-json-web-key.html (JOSE) | |
|
Ryan Sleevi
2013/10/04 23:19:11
Let's refer to a canonical draft URL at the IETF,
padolph
2013/10/05 02:57:42
Done.
| |
| 373 // TODO(padolph) Not all possible values are handled by this code right now | |
| 374 // | |
| 375 // A JWK is a simple JSON dictionary with the following entries | |
| 376 // - "kty" (Key Type) Parameter, REQUIRED | |
| 377 // - <kty-specific parameters, see below>, REQUIRED | |
| 378 // - "use" (Key Use) Parameter, OPTIONAL | |
| 379 // - "alg" (Algorithm) Parameter, OPTIONAL | |
| 380 // - "extractable" (Key Exportability), OPTIONAL [NOTE: not yet part of JOSE] | |
| 381 // (all other entries are ignored) | |
| 382 // | |
| 383 // Input key_data contains the JWK. To build a Web Crypto Key, the JWK values | |
| 384 // are parsed out and used as follows: | |
| 385 // Web Crypto Key type <-- (deduced) | |
| 386 // Web Crypto Key extractable <-- extractable | |
| 387 // Web Crypto Key algorithm <-- alg | |
| 388 // Web Crypto Key keyUsage <-- usage | |
| 389 // Web Crypto Key keying material <-- kty-specific parameters | |
| 390 // | |
| 391 // Values for each entry are case-sensitive and defined in | |
| 392 // http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-16. | |
| 393 // Note that not all values specified by JOSE are handled by this code. Only | |
| 394 // handled values are listed. | |
| 395 // - kty (Key Type) | |
| 396 // +-------+--------------------------------------------------------------+ | |
| 397 // | "RSA" | RSA [RFC3447] | | |
| 398 // | "oct" | Octet sequence (used to represent symmetric keys) | | |
| 399 // +-------+--------------------------------------------------------------+ | |
| 400 // - use (Key Use) | |
| 401 // +-------+--------------------------------------------------------------+ | |
| 402 // | "enc" | encrypt and decrypt operations | | |
| 403 // | "sig" | sign and verify (MAC) operations | | |
| 404 // | "wrap"| key wrap and unwrap [not yet part of JOSE] | | |
| 405 // +-------+--------------------------------------------------------------+ | |
| 406 // - extractable (Key Exportability) | |
| 407 // +-------+--------------------------------------------------------------+ | |
| 408 // | true | Key may be exported from the trusted environment | | |
| 409 // | false | Key cannot exit the trusted environment | | |
| 410 // +-------+--------------------------------------------------------------+ | |
| 411 // - alg (Algorithm) | |
| 412 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-16 | |
| 413 // +--------------+-------------------------------------------------------+ | |
| 414 // | Digital Signature or MAC Algorithm | | |
| 415 // +--------------+-------------------------------------------------------+ | |
| 416 // | "HS256" | HMAC using SHA-256 hash algorithm | | |
| 417 // | "HS384" | HMAC using SHA-384 hash algorithm | | |
| 418 // | "HS512" | HMAC using SHA-512 hash algorithm | | |
| 419 // | "RS256" | RSASSA using SHA-256 hash algorithm | | |
| 420 // | "RS384" | RSASSA using SHA-384 hash algorithm | | |
| 421 // | "RS512" | RSASSA using SHA-512 hash algorithm | | |
| 422 // +--------------+-------------------------------------------------------| | |
| 423 // | Key Management Algorithm | | |
| 424 // +--------------+-------------------------------------------------------+ | |
| 425 // | "RSA1_5" | RSAES-PKCS1-V1_5 [RFC3447] | | |
| 426 // | "RSA-OAEP" | RSAES using Optimal Asymmetric Encryption Padding | | |
| 427 // | | (OAEP) [RFC3447], with the default parameters | | |
| 428 // | | specified by RFC3447 in Section A.2.1 | | |
| 429 // | "A128KW" | Advanced Encryption Standard (AES) Key Wrap Algorithm | | |
| 430 // | | [RFC3394] using 128 bit keys | | |
| 431 // | "A256KW" | AES Key Wrap Algorithm using 256 bit keys | | |
| 432 // | "A128GCM" | AES in Galois/Counter Mode (GCM) [NIST.800-38D] using | | |
| 433 // | | 128 bit keys | | |
| 434 // | "A256GCM" | AES GCM using 256 bit keys | | |
| 435 // | "A128CBC" | AES in Cipher Block Chaining Mode (CBC) with PKCS #5 | | |
| 436 // | | padding [NIST.800-38A] [not yet part of JOSE] | | |
| 437 // | "A256CBC" | AES CBC using 256 bit keys [not yet part of JOSE] | | |
| 438 // | "A384CBC" | AES CBC using 384 bit keys [not yet part of JOSE] | | |
| 439 // | "A512CBC" | AES CBC using 512 bit keys [not yet part of JOSE] | | |
| 440 // +--------------+-------------------------------------------------------+ | |
| 441 // | |
| 442 // kty-specific parameters | |
| 443 // The value of kty determines the type and content of the keying material | |
| 444 // carried in the JWK to be imported. Currently only two possibilities are | |
| 445 // supported: a raw key or an RSA public key. RSA private keys are not | |
| 446 // supported because typical applications seldom need to import a private key, | |
| 447 // and the large number of JWK parameters required to describe one. | |
| 448 // - kty == "oct" (symmetric or other raw key) | |
| 449 // +-------+--------------------------------------------------------------+ | |
| 450 // | "k" | Contains the value of the symmetric (or other single-valued) | | |
| 451 // | | key. It is represented as the base64url encoding of the | | |
| 452 // | | octet sequence containing the key value. | | |
| 453 // +-------+--------------------------------------------------------------+ | |
| 454 // - kty == "RSA" (RSA public key) | |
| 455 // +-------+--------------------------------------------------------------+ | |
| 456 // | "n" | Contains the modulus value for the RSA public key. It is | | |
| 457 // | | represented as the base64url encoding of the value's | | |
| 458 // | | unsigned big endian representation as an octet sequence. | | |
| 459 // +-------+--------------------------------------------------------------+ | |
| 460 // | "e" | Contains the exponent value for the RSA public key. It is | | |
| 461 // | | represented as the base64url encoding of the value's | | |
| 462 // | | unsigned big endian representation as an octet sequence. | | |
| 463 // +-------+--------------------------------------------------------------+ | |
| 464 // | |
| 465 // Conflict resolution | |
| 466 // The type, algorithm, extractable, and usage_mask input parameters may be | |
| 467 // different from similar values inside the JWK. Conflicts are resolved as | |
| 468 // follows: | |
| 469 // type: Deduce value from JWK contents only, ignore input value | |
| 470 // algorithm: Use JWK value if present, otherwise use input value | |
| 471 // extractable: If JWK value present, logical AND of the input and JWK values, | |
| 472 // otherwise use input value | |
| 473 // keyUsage: Use JWK value if present, otherwise use input value | |
|
Ryan Sleevi
2013/10/04 23:19:11
These are all things that should be in the spec be
padolph
2013/10/05 02:57:42
The other parameters are easy, but can you please
| |
| 474 | |
| 475 std::string jsonStr(key_data, key_data + key_data_size); | |
|
Ryan Sleevi
2013/10/04 23:19:11
json_str
However, you don't need to use std::stri
padolph
2013/10/05 02:57:42
Done.
| |
| 476 scoped_ptr<base::Value> value(base::JSONReader::Read(jsonStr)); | |
| 477 // Note, bare pointer dict_value is ok since it points into scoped value. | |
| 478 base::DictionaryValue* dict_value = NULL; | |
| 479 if (!value.get() || !value->GetAsDictionary(&dict_value) || !dict_value) | |
| 480 return false; | |
| 481 | |
| 482 // JWK "kty". Exit early if this required JWK parameter is missing. | |
| 483 std::string jwk_kty_value; | |
| 484 if (!dict_value->GetString("kty", &jwk_kty_value)) | |
| 485 return false; | |
| 486 | |
| 487 // JWK "extractable" --> extractable parameter | |
| 488 bool jwk_extractable_value; | |
| 489 if (dict_value->GetBoolean("extractable", &jwk_extractable_value)) { | |
| 490 *extractable &= jwk_extractable_value; | |
| 491 } | |
| 492 | |
| 493 // JWK "alg" --> algorithm parameter | |
| 494 std::string jwk_alg_value; | |
| 495 if (dict_value->GetString("alg", &jwk_alg_value)) { | |
| 496 const StringIntMap::iterator pos = jwk_algorithm_map_.find(jwk_alg_value); | |
| 497 if (pos == jwk_algorithm_map_.end()) | |
| 498 return false; | |
| 499 const int jwk_algorithm_id = pos->second; | |
| 500 const unsigned short key_length_bits = | |
| 501 JwkAlgIdToKeyLengthBits(jwk_algorithm_id); | |
| 502 const WebKit::WebCryptoAlgorithmId webcrypto_algorithm_id = | |
| 503 JwkAlgIdToWebCryptoAlgId(jwk_algorithm_id); | |
| 504 switch (webcrypto_algorithm_id) { | |
| 505 case WebKit::WebCryptoAlgorithmIdHmac: | |
| 506 *algorithm = CreateHmacAlgorithm(key_length_bits); | |
| 507 break; | |
| 508 case WebKit::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: | |
| 509 *algorithm = CreateRsaSsaAlgorithm(key_length_bits); | |
| 510 break; | |
| 511 case WebKit::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: | |
| 512 *algorithm = CreateAlgorithm(webcrypto_algorithm_id); | |
| 513 break; | |
| 514 case WebKit::WebCryptoAlgorithmIdRsaOaep: | |
| 515 *algorithm = CreateRsaOaepAlgorithm(key_length_bits); | |
| 516 break; | |
| 517 case WebKit::WebCryptoAlgorithmIdAesGcm: | |
| 518 *algorithm = CreateAesGcmAlgorithm(key_length_bits); | |
| 519 break; | |
| 520 case WebKit::WebCryptoAlgorithmIdAesCbc: | |
| 521 *algorithm = CreateAesCbcAlgorithm(key_length_bits); | |
| 522 break; | |
| 523 default: | |
| 524 return false; | |
| 525 } | |
| 526 } | |
| 527 | |
| 528 // JWK "use" --> usage_mask parameter | |
| 529 std::string jwk_use_value; | |
| 530 if (dict_value->GetString("use", &jwk_use_value)) { | |
| 531 if (jwk_use_value == "enc") { | |
| 532 *usage_mask = | |
| 533 WebKit::WebCryptoKeyUsageEncrypt | WebKit::WebCryptoKeyUsageDecrypt; | |
| 534 } else if (jwk_use_value == "sig") { | |
| 535 *usage_mask = | |
| 536 WebKit::WebCryptoKeyUsageSign | WebKit::WebCryptoKeyUsageVerify; | |
| 537 } else if (jwk_use_value == "wrap") { | |
| 538 *usage_mask = | |
| 539 WebKit::WebCryptoKeyUsageWrapKey | WebKit::WebCryptoKeyUsageUnwrapKey; | |
| 540 } else { | |
| 541 return false; | |
| 542 } | |
| 543 } | |
| 544 | |
| 545 // JWK keying material --> ImportKeyInternal() | |
| 546 if (jwk_kty_value == "oct") { | |
| 547 std::string jwk_k_value_url64; | |
| 548 if (!dict_value->GetString("k", &jwk_k_value_url64)) | |
| 549 return false; | |
| 550 std::string jwk_k_value; | |
| 551 if (!Base64DecodeUrlSafe(jwk_k_value_url64, &jwk_k_value)) | |
| 552 return false; | |
| 553 const std::vector<uint8> data(jwk_k_value.begin(), jwk_k_value.end()); | |
| 554 if (!ImportKeyInternal(WebKit::WebCryptoKeyFormatRaw, | |
| 555 &data[0], | |
| 556 data.size(), | |
| 557 *algorithm, | |
| 558 *usage_mask, | |
| 559 handle, | |
| 560 type)) | |
| 561 return false; | |
| 562 } else if (jwk_kty_value == "RSA") { | |
| 563 // TODO(padolph): RSA public key | |
| 564 return false; | |
| 565 } else { | |
| 566 return false; | |
| 567 } | |
| 568 | |
| 569 return true; | |
| 570 } | |
| 571 | |
| 124 } // namespace content | 572 } // namespace content |
| OLD | NEW |