| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 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 "jwk.h" | 5 #include "jwk.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <functional> | 8 #include <functional> |
| 9 #include <map> | 9 #include <map> |
| 10 | 10 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 39 // information. If the optional JWK entry is present, it will be validated | 39 // information. If the optional JWK entry is present, it will be validated |
| 40 // against the corresponding input parameter for consistency and combined with | 40 // against the corresponding input parameter for consistency and combined with |
| 41 // it according to rules defined below. | 41 // it according to rules defined below. |
| 42 // | 42 // |
| 43 // Input 'key_data' contains the JWK. To build a Web Crypto Key, the JWK | 43 // Input 'key_data' contains the JWK. To build a Web Crypto Key, the JWK |
| 44 // values are parsed out and combined with the method input parameters to | 44 // values are parsed out and combined with the method input parameters to |
| 45 // build a Web Crypto Key: | 45 // build a Web Crypto Key: |
| 46 // Web Crypto Key type <-- (deduced) | 46 // Web Crypto Key type <-- (deduced) |
| 47 // Web Crypto Key extractable <-- JWK ext + input extractable | 47 // Web Crypto Key extractable <-- JWK ext + input extractable |
| 48 // Web Crypto Key algorithm <-- JWK alg + input algorithm | 48 // Web Crypto Key algorithm <-- JWK alg + input algorithm |
| 49 // Web Crypto Key keyUsage <-- JWK use, key_ops + input usage_mask | 49 // Web Crypto Key keyUsage <-- JWK use, key_ops + input usages |
| 50 // Web Crypto Key keying material <-- kty-specific parameters | 50 // Web Crypto Key keying material <-- kty-specific parameters |
| 51 // | 51 // |
| 52 // Values for each JWK entry are case-sensitive and defined in | 52 // Values for each JWK entry are case-sensitive and defined in |
| 53 // http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18. | 53 // http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18. |
| 54 // Note that not all values specified by JOSE are handled by this code. Only | 54 // Note that not all values specified by JOSE are handled by this code. Only |
| 55 // handled values are listed. | 55 // handled values are listed. |
| 56 // - kty (Key Type) | 56 // - kty (Key Type) |
| 57 // +-------+--------------------------------------------------------------+ | 57 // +-------+--------------------------------------------------------------+ |
| 58 // | "RSA" | RSA [RFC3447] | | 58 // | "RSA" | RSA [RFC3447] | |
| 59 // | "oct" | Octet sequence (used to represent symmetric keys) | | 59 // | "oct" | Octet sequence (used to represent symmetric keys) | |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 176 // | | the value's unsigned big endian representation as an octet | | 176 // | | the value's unsigned big endian representation as an octet | |
| 177 // | | sequence. | | 177 // | | sequence. | |
| 178 // +-------+--------------------------------------------------------------+ | 178 // +-------+--------------------------------------------------------------+ |
| 179 // | "dq" | Contains the first CRT coefficient value for the RSA private | | 179 // | "dq" | Contains the first CRT coefficient value for the RSA private | |
| 180 // | | key. It is represented as the base64url encoding of the | | 180 // | | key. It is represented as the base64url encoding of the | |
| 181 // | | value's unsigned big endian representation as an octet | | 181 // | | value's unsigned big endian representation as an octet | |
| 182 // | | sequence. | | 182 // | | sequence. | |
| 183 // +-------+--------------------------------------------------------------+ | 183 // +-------+--------------------------------------------------------------+ |
| 184 // | 184 // |
| 185 // Consistency and conflict resolution | 185 // Consistency and conflict resolution |
| 186 // The 'algorithm', 'extractable', and 'usage_mask' input parameters | 186 // The 'algorithm', 'extractable', and 'usages' input parameters |
| 187 // may be different than the corresponding values inside the JWK. The Web | 187 // may be different than the corresponding values inside the JWK. The Web |
| 188 // Crypto spec says that if a JWK value is present but is inconsistent with | 188 // Crypto spec says that if a JWK value is present but is inconsistent with |
| 189 // the input value, it is an error and the operation must fail. If no | 189 // the input value, it is an error and the operation must fail. If no |
| 190 // inconsistency is found then the input parameters are used. | 190 // inconsistency is found then the input parameters are used. |
| 191 // | 191 // |
| 192 // algorithm | 192 // algorithm |
| 193 // If the JWK algorithm is provided, it must match the web crypto input | 193 // If the JWK algorithm is provided, it must match the web crypto input |
| 194 // algorithm (both the algorithm ID and inner hash if applicable). | 194 // algorithm (both the algorithm ID and inner hash if applicable). |
| 195 // | 195 // |
| 196 // extractable | 196 // extractable |
| 197 // If the JWK ext field is true but the input parameter is false, make the | 197 // If the JWK ext field is true but the input parameter is false, make the |
| 198 // Web Crypto Key non-extractable. Conversely, if the JWK ext field is | 198 // Web Crypto Key non-extractable. Conversely, if the JWK ext field is |
| 199 // false but the input parameter is true, it is an inconsistency. If both | 199 // false but the input parameter is true, it is an inconsistency. If both |
| 200 // are true or both are false, use that value. | 200 // are true or both are false, use that value. |
| 201 // | 201 // |
| 202 // usage_mask | 202 // usages |
| 203 // The input usage_mask must be a strict subset of the interpreted JWK use | 203 // The input usages must be a strict subset of the interpreted JWK use |
| 204 // value, else it is judged inconsistent. In all cases the input usage_mask | 204 // value, else it is judged inconsistent. In all cases the input usages |
| 205 // is used as the final usage_mask. | 205 // is used as the final usages. |
| 206 // | 206 // |
| 207 | 207 |
| 208 namespace content { | 208 namespace content { |
| 209 | 209 |
| 210 namespace webcrypto { | 210 namespace webcrypto { |
| 211 | 211 |
| 212 namespace { | 212 namespace { |
| 213 | 213 |
| 214 // Web Crypto equivalent usage mask for JWK 'use' = 'enc'. | 214 // Web Crypto equivalent usage mask for JWK 'use' = 'enc'. |
| 215 const blink::WebCryptoKeyUsageMask kJwkEncUsage = | 215 const blink::WebCryptoKeyUsageMask kJwkEncUsage = |
| 216 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt | | 216 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt | |
| 217 blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey | | 217 blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey | |
| 218 blink::WebCryptoKeyUsageDeriveKey | blink::WebCryptoKeyUsageDeriveBits; | 218 blink::WebCryptoKeyUsageDeriveKey | blink::WebCryptoKeyUsageDeriveBits; |
| 219 // Web Crypto equivalent usage mask for JWK 'use' = 'sig'. | 219 // Web Crypto equivalent usage mask for JWK 'use' = 'sig'. |
| 220 const blink::WebCryptoKeyUsageMask kJwkSigUsage = | 220 const blink::WebCryptoKeyUsageMask kJwkSigUsage = |
| 221 blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify; | 221 blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify; |
| 222 | 222 |
| 223 class JwkWriter { | 223 class JwkWriter { |
| 224 public: | 224 public: |
| 225 JwkWriter(const std::string& algorithm, | 225 JwkWriter(const std::string& algorithm, |
| 226 bool extractable, | 226 bool extractable, |
| 227 blink::WebCryptoKeyUsageMask usage_mask, | 227 blink::WebCryptoKeyUsageMask usages, |
| 228 const std::string& kty) { | 228 const std::string& kty) { |
| 229 dict_.SetString("alg", algorithm); | 229 dict_.SetString("alg", algorithm); |
| 230 dict_.Set("key_ops", CreateJwkKeyOpsFromWebCryptoUsages(usage_mask)); | 230 dict_.Set("key_ops", CreateJwkKeyOpsFromWebCryptoUsages(usages)); |
| 231 dict_.SetBoolean("ext", extractable); | 231 dict_.SetBoolean("ext", extractable); |
| 232 dict_.SetString("kty", kty); | 232 dict_.SetString("kty", kty); |
| 233 } | 233 } |
| 234 | 234 |
| 235 void Set(const std::string& key, const std::string& value) { | 235 void Set(const std::string& key, const std::string& value) { |
| 236 dict_.SetString(key, value); | 236 dict_.SetString(key, value); |
| 237 } | 237 } |
| 238 | 238 |
| 239 void SetBase64Encoded(const std::string& key, const CryptoData& value) { | 239 void SetBase64Encoded(const std::string& key, const CryptoData& value) { |
| 240 dict_.SetString(key, | 240 dict_.SetString(key, |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 371 bool has_jwk_ext; | 371 bool has_jwk_ext; |
| 372 Status status = GetOptionalJwkBool(dict, "ext", &jwk_ext_value, &has_jwk_ext); | 372 Status status = GetOptionalJwkBool(dict, "ext", &jwk_ext_value, &has_jwk_ext); |
| 373 if (status.IsError()) | 373 if (status.IsError()) |
| 374 return status; | 374 return status; |
| 375 if (has_jwk_ext && expected_extractable && !jwk_ext_value) | 375 if (has_jwk_ext && expected_extractable && !jwk_ext_value) |
| 376 return Status::ErrorJwkExtInconsistent(); | 376 return Status::ErrorJwkExtInconsistent(); |
| 377 return Status::Success(); | 377 return Status::Success(); |
| 378 } | 378 } |
| 379 | 379 |
| 380 Status VerifyUsages(base::DictionaryValue* dict, | 380 Status VerifyUsages(base::DictionaryValue* dict, |
| 381 blink::WebCryptoKeyUsageMask expected_usage_mask) { | 381 blink::WebCryptoKeyUsageMask expected_usages) { |
| 382 // JWK "key_ops" (optional) --> usage_mask parameter | 382 // JWK "key_ops" (optional) --> usages parameter |
| 383 base::ListValue* jwk_key_ops_value = NULL; | 383 base::ListValue* jwk_key_ops_value = NULL; |
| 384 bool has_jwk_key_ops; | 384 bool has_jwk_key_ops; |
| 385 Status status = | 385 Status status = |
| 386 GetOptionalJwkList(dict, "key_ops", &jwk_key_ops_value, &has_jwk_key_ops); | 386 GetOptionalJwkList(dict, "key_ops", &jwk_key_ops_value, &has_jwk_key_ops); |
| 387 if (status.IsError()) | 387 if (status.IsError()) |
| 388 return status; | 388 return status; |
| 389 blink::WebCryptoKeyUsageMask jwk_key_ops_mask = 0; | 389 blink::WebCryptoKeyUsageMask jwk_key_ops_mask = 0; |
| 390 if (has_jwk_key_ops) { | 390 if (has_jwk_key_ops) { |
| 391 status = | 391 status = |
| 392 GetWebCryptoUsagesFromJwkKeyOps(jwk_key_ops_value, &jwk_key_ops_mask); | 392 GetWebCryptoUsagesFromJwkKeyOps(jwk_key_ops_value, &jwk_key_ops_mask); |
| 393 if (status.IsError()) | 393 if (status.IsError()) |
| 394 return status; | 394 return status; |
| 395 // The input usage_mask must be a subset of jwk_key_ops_mask. | 395 // The input usages must be a subset of jwk_key_ops_mask. |
| 396 if (!ContainsKeyUsages(jwk_key_ops_mask, expected_usage_mask)) | 396 if (!ContainsKeyUsages(jwk_key_ops_mask, expected_usages)) |
| 397 return Status::ErrorJwkKeyopsInconsistent(); | 397 return Status::ErrorJwkKeyopsInconsistent(); |
| 398 } | 398 } |
| 399 | 399 |
| 400 // JWK "use" (optional) --> usage_mask parameter | 400 // JWK "use" (optional) --> usages parameter |
| 401 std::string jwk_use_value; | 401 std::string jwk_use_value; |
| 402 bool has_jwk_use; | 402 bool has_jwk_use; |
| 403 status = GetOptionalJwkString(dict, "use", &jwk_use_value, &has_jwk_use); | 403 status = GetOptionalJwkString(dict, "use", &jwk_use_value, &has_jwk_use); |
| 404 if (status.IsError()) | 404 if (status.IsError()) |
| 405 return status; | 405 return status; |
| 406 blink::WebCryptoKeyUsageMask jwk_use_mask = 0; | 406 blink::WebCryptoKeyUsageMask jwk_use_mask = 0; |
| 407 if (has_jwk_use) { | 407 if (has_jwk_use) { |
| 408 if (jwk_use_value == "enc") | 408 if (jwk_use_value == "enc") |
| 409 jwk_use_mask = kJwkEncUsage; | 409 jwk_use_mask = kJwkEncUsage; |
| 410 else if (jwk_use_value == "sig") | 410 else if (jwk_use_value == "sig") |
| 411 jwk_use_mask = kJwkSigUsage; | 411 jwk_use_mask = kJwkSigUsage; |
| 412 else | 412 else |
| 413 return Status::ErrorJwkUnrecognizedUse(); | 413 return Status::ErrorJwkUnrecognizedUse(); |
| 414 // The input usage_mask must be a subset of jwk_use_mask. | 414 // The input usages must be a subset of jwk_use_mask. |
| 415 if (!ContainsKeyUsages(jwk_use_mask, expected_usage_mask)) | 415 if (!ContainsKeyUsages(jwk_use_mask, expected_usages)) |
| 416 return Status::ErrorJwkUseInconsistent(); | 416 return Status::ErrorJwkUseInconsistent(); |
| 417 } | 417 } |
| 418 | 418 |
| 419 // If both 'key_ops' and 'use' are present, ensure they are consistent. | 419 // If both 'key_ops' and 'use' are present, ensure they are consistent. |
| 420 if (has_jwk_key_ops && has_jwk_use && | 420 if (has_jwk_key_ops && has_jwk_use && |
| 421 !ContainsKeyUsages(jwk_use_mask, jwk_key_ops_mask)) | 421 !ContainsKeyUsages(jwk_use_mask, jwk_key_ops_mask)) |
| 422 return Status::ErrorJwkUseAndKeyopsInconsistent(); | 422 return Status::ErrorJwkUseAndKeyopsInconsistent(); |
| 423 | 423 |
| 424 return Status::Success(); | 424 return Status::Success(); |
| 425 } | 425 } |
| 426 | 426 |
| 427 Status VerifyAlg(base::DictionaryValue* dict, | 427 Status VerifyAlg(base::DictionaryValue* dict, |
| 428 const std::string& expected_algorithm) { | 428 const std::string& expected_algorithm) { |
| 429 // JWK "alg" --> algorithm parameter | 429 // JWK "alg" --> algorithm parameter |
| 430 bool has_jwk_alg; | 430 bool has_jwk_alg; |
| 431 std::string jwk_alg_value; | 431 std::string jwk_alg_value; |
| 432 Status status = | 432 Status status = |
| 433 GetOptionalJwkString(dict, "alg", &jwk_alg_value, &has_jwk_alg); | 433 GetOptionalJwkString(dict, "alg", &jwk_alg_value, &has_jwk_alg); |
| 434 if (status.IsError()) | 434 if (status.IsError()) |
| 435 return status; | 435 return status; |
| 436 | 436 |
| 437 if (has_jwk_alg && jwk_alg_value != expected_algorithm) | 437 if (has_jwk_alg && jwk_alg_value != expected_algorithm) |
| 438 return Status::ErrorJwkAlgorithmInconsistent(); | 438 return Status::ErrorJwkAlgorithmInconsistent(); |
| 439 | 439 |
| 440 return Status::Success(); | 440 return Status::Success(); |
| 441 } | 441 } |
| 442 | 442 |
| 443 Status ParseJwkCommon(const CryptoData& bytes, | 443 Status ParseJwkCommon(const CryptoData& bytes, |
| 444 bool expected_extractable, | 444 bool expected_extractable, |
| 445 blink::WebCryptoKeyUsageMask expected_usage_mask, | 445 blink::WebCryptoKeyUsageMask expected_usages, |
| 446 std::string* kty, | 446 std::string* kty, |
| 447 scoped_ptr<base::DictionaryValue>* dict) { | 447 scoped_ptr<base::DictionaryValue>* dict) { |
| 448 // Parse the incoming JWK JSON. | 448 // Parse the incoming JWK JSON. |
| 449 base::StringPiece json_string(reinterpret_cast<const char*>(bytes.bytes()), | 449 base::StringPiece json_string(reinterpret_cast<const char*>(bytes.bytes()), |
| 450 bytes.byte_length()); | 450 bytes.byte_length()); |
| 451 | 451 |
| 452 scoped_ptr<base::Value> value(base::JSONReader::Read(json_string)); | 452 scoped_ptr<base::Value> value(base::JSONReader::Read(json_string)); |
| 453 base::DictionaryValue* dict_value = NULL; | 453 base::DictionaryValue* dict_value = NULL; |
| 454 | 454 |
| 455 if (!value.get() || !value->GetAsDictionary(&dict_value) || !dict_value) | 455 if (!value.get() || !value->GetAsDictionary(&dict_value) || !dict_value) |
| 456 return Status::ErrorJwkNotDictionary(); | 456 return Status::ErrorJwkNotDictionary(); |
| 457 | 457 |
| 458 // Release |value|, as ownership will be transferred to |dict| via | 458 // Release |value|, as ownership will be transferred to |dict| via |
| 459 // |dict_value|, which points to the same object as |value|. | 459 // |dict_value|, which points to the same object as |value|. |
| 460 ignore_result(value.release()); | 460 ignore_result(value.release()); |
| 461 dict->reset(dict_value); | 461 dict->reset(dict_value); |
| 462 | 462 |
| 463 // JWK "kty". Exit early if this required JWK parameter is missing. | 463 // JWK "kty". Exit early if this required JWK parameter is missing. |
| 464 Status status = GetJwkString(dict_value, "kty", kty); | 464 Status status = GetJwkString(dict_value, "kty", kty); |
| 465 if (status.IsError()) | 465 if (status.IsError()) |
| 466 return status; | 466 return status; |
| 467 | 467 |
| 468 status = VerifyExt(dict_value, expected_extractable); | 468 status = VerifyExt(dict_value, expected_extractable); |
| 469 if (status.IsError()) | 469 if (status.IsError()) |
| 470 return status; | 470 return status; |
| 471 | 471 |
| 472 status = VerifyUsages(dict_value, expected_usage_mask); | 472 status = VerifyUsages(dict_value, expected_usages); |
| 473 if (status.IsError()) | 473 if (status.IsError()) |
| 474 return status; | 474 return status; |
| 475 | 475 |
| 476 return Status::Success(); | 476 return Status::Success(); |
| 477 } | 477 } |
| 478 | 478 |
| 479 Status ReadSecretKeyNoExpectedAlg( | 479 Status ReadSecretKeyNoExpectedAlg(const CryptoData& key_data, |
| 480 const CryptoData& key_data, | 480 bool expected_extractable, |
| 481 bool expected_extractable, | 481 blink::WebCryptoKeyUsageMask expected_usages, |
| 482 blink::WebCryptoKeyUsageMask expected_usage_mask, | 482 std::vector<uint8_t>* raw_key_data, |
| 483 std::vector<uint8_t>* raw_key_data, | 483 scoped_ptr<base::DictionaryValue>* dict) { |
| 484 scoped_ptr<base::DictionaryValue>* dict) { | |
| 485 if (!key_data.byte_length()) | 484 if (!key_data.byte_length()) |
| 486 return Status::ErrorImportEmptyKeyData(); | 485 return Status::ErrorImportEmptyKeyData(); |
| 487 | 486 |
| 488 std::string kty; | 487 std::string kty; |
| 489 Status status = ParseJwkCommon( | 488 Status status = ParseJwkCommon( |
| 490 key_data, expected_extractable, expected_usage_mask, &kty, dict); | 489 key_data, expected_extractable, expected_usages, &kty, dict); |
| 491 if (status.IsError()) | 490 if (status.IsError()) |
| 492 return status; | 491 return status; |
| 493 | 492 |
| 494 if (kty != "oct") | 493 if (kty != "oct") |
| 495 return Status::ErrorJwkUnexpectedKty("oct"); | 494 return Status::ErrorJwkUnexpectedKty("oct"); |
| 496 | 495 |
| 497 std::string jwk_k_value; | 496 std::string jwk_k_value; |
| 498 status = GetJwkBytes(dict->get(), "k", &jwk_k_value); | 497 status = GetJwkBytes(dict->get(), "k", &jwk_k_value); |
| 499 if (status.IsError()) | 498 if (status.IsError()) |
| 500 return status; | 499 return status; |
| 501 raw_key_data->assign(jwk_k_value.begin(), jwk_k_value.end()); | 500 raw_key_data->assign(jwk_k_value.begin(), jwk_k_value.end()); |
| 502 | 501 |
| 503 return Status::Success(); | 502 return Status::Success(); |
| 504 } | 503 } |
| 505 | 504 |
| 506 } // namespace | 505 } // namespace |
| 507 | 506 |
| 508 void WriteSecretKeyJwk(const CryptoData& raw_key_data, | 507 void WriteSecretKeyJwk(const CryptoData& raw_key_data, |
| 509 const std::string& algorithm, | 508 const std::string& algorithm, |
| 510 bool extractable, | 509 bool extractable, |
| 511 blink::WebCryptoKeyUsageMask usage_mask, | 510 blink::WebCryptoKeyUsageMask usages, |
| 512 std::vector<uint8_t>* jwk_key_data) { | 511 std::vector<uint8_t>* jwk_key_data) { |
| 513 JwkWriter writer(algorithm, extractable, usage_mask, "oct"); | 512 JwkWriter writer(algorithm, extractable, usages, "oct"); |
| 514 writer.SetBase64Encoded("k", raw_key_data); | 513 writer.SetBase64Encoded("k", raw_key_data); |
| 515 writer.ToBytes(jwk_key_data); | 514 writer.ToBytes(jwk_key_data); |
| 516 } | 515 } |
| 517 | 516 |
| 518 Status ReadSecretKeyJwk(const CryptoData& key_data, | 517 Status ReadSecretKeyJwk(const CryptoData& key_data, |
| 519 const std::string& expected_algorithm, | 518 const std::string& expected_algorithm, |
| 520 bool expected_extractable, | 519 bool expected_extractable, |
| 521 blink::WebCryptoKeyUsageMask expected_usage_mask, | 520 blink::WebCryptoKeyUsageMask expected_usages, |
| 522 std::vector<uint8_t>* raw_key_data) { | 521 std::vector<uint8_t>* raw_key_data) { |
| 523 scoped_ptr<base::DictionaryValue> dict; | 522 scoped_ptr<base::DictionaryValue> dict; |
| 524 Status status = ReadSecretKeyNoExpectedAlg( | 523 Status status = ReadSecretKeyNoExpectedAlg( |
| 525 key_data, expected_extractable, expected_usage_mask, raw_key_data, &dict); | 524 key_data, expected_extractable, expected_usages, raw_key_data, &dict); |
| 526 if (status.IsError()) | 525 if (status.IsError()) |
| 527 return status; | 526 return status; |
| 528 return VerifyAlg(dict.get(), expected_algorithm); | 527 return VerifyAlg(dict.get(), expected_algorithm); |
| 529 } | 528 } |
| 530 | 529 |
| 531 std::string MakeJwkAesAlgorithmName(const std::string& suffix, | 530 std::string MakeJwkAesAlgorithmName(const std::string& suffix, |
| 532 unsigned int keylen_bytes) { | 531 unsigned int keylen_bytes) { |
| 533 if (keylen_bytes == 16) | 532 if (keylen_bytes == 16) |
| 534 return std::string("A128") + suffix; | 533 return std::string("A128") + suffix; |
| 535 if (keylen_bytes == 24) | 534 if (keylen_bytes == 24) |
| 536 return std::string("A192") + suffix; | 535 return std::string("A192") + suffix; |
| 537 if (keylen_bytes == 32) | 536 if (keylen_bytes == 32) |
| 538 return std::string("A256") + suffix; | 537 return std::string("A256") + suffix; |
| 539 return std::string(); | 538 return std::string(); |
| 540 } | 539 } |
| 541 | 540 |
| 542 Status ReadAesSecretKeyJwk(const CryptoData& key_data, | 541 Status ReadAesSecretKeyJwk(const CryptoData& key_data, |
| 543 const std::string& algorithm_name_suffix, | 542 const std::string& algorithm_name_suffix, |
| 544 bool expected_extractable, | 543 bool expected_extractable, |
| 545 blink::WebCryptoKeyUsageMask expected_usage_mask, | 544 blink::WebCryptoKeyUsageMask expected_usages, |
| 546 std::vector<uint8_t>* raw_key_data) { | 545 std::vector<uint8_t>* raw_key_data) { |
| 547 scoped_ptr<base::DictionaryValue> dict; | 546 scoped_ptr<base::DictionaryValue> dict; |
| 548 Status status = ReadSecretKeyNoExpectedAlg( | 547 Status status = ReadSecretKeyNoExpectedAlg( |
| 549 key_data, expected_extractable, expected_usage_mask, raw_key_data, &dict); | 548 key_data, expected_extractable, expected_usages, raw_key_data, &dict); |
| 550 if (status.IsError()) | 549 if (status.IsError()) |
| 551 return status; | 550 return status; |
| 552 | 551 |
| 553 bool has_jwk_alg; | 552 bool has_jwk_alg; |
| 554 std::string jwk_alg; | 553 std::string jwk_alg; |
| 555 status = GetOptionalJwkString(dict.get(), "alg", &jwk_alg, &has_jwk_alg); | 554 status = GetOptionalJwkString(dict.get(), "alg", &jwk_alg, &has_jwk_alg); |
| 556 if (status.IsError()) | 555 if (status.IsError()) |
| 557 return status; | 556 return status; |
| 558 | 557 |
| 559 if (has_jwk_alg) { | 558 if (has_jwk_alg) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 572 } | 571 } |
| 573 | 572 |
| 574 return Status::Success(); | 573 return Status::Success(); |
| 575 } | 574 } |
| 576 | 575 |
| 577 // Writes an RSA public key to a JWK dictionary | 576 // Writes an RSA public key to a JWK dictionary |
| 578 void WriteRsaPublicKeyJwk(const CryptoData& n, | 577 void WriteRsaPublicKeyJwk(const CryptoData& n, |
| 579 const CryptoData& e, | 578 const CryptoData& e, |
| 580 const std::string& algorithm, | 579 const std::string& algorithm, |
| 581 bool extractable, | 580 bool extractable, |
| 582 blink::WebCryptoKeyUsageMask usage_mask, | 581 blink::WebCryptoKeyUsageMask usages, |
| 583 std::vector<uint8_t>* jwk_key_data) { | 582 std::vector<uint8_t>* jwk_key_data) { |
| 584 JwkWriter writer(algorithm, extractable, usage_mask, "RSA"); | 583 JwkWriter writer(algorithm, extractable, usages, "RSA"); |
| 585 writer.SetBase64Encoded("n", n); | 584 writer.SetBase64Encoded("n", n); |
| 586 writer.SetBase64Encoded("e", e); | 585 writer.SetBase64Encoded("e", e); |
| 587 writer.ToBytes(jwk_key_data); | 586 writer.ToBytes(jwk_key_data); |
| 588 } | 587 } |
| 589 | 588 |
| 590 // Writes an RSA private key to a JWK dictionary | 589 // Writes an RSA private key to a JWK dictionary |
| 591 void WriteRsaPrivateKeyJwk(const CryptoData& n, | 590 void WriteRsaPrivateKeyJwk(const CryptoData& n, |
| 592 const CryptoData& e, | 591 const CryptoData& e, |
| 593 const CryptoData& d, | 592 const CryptoData& d, |
| 594 const CryptoData& p, | 593 const CryptoData& p, |
| 595 const CryptoData& q, | 594 const CryptoData& q, |
| 596 const CryptoData& dp, | 595 const CryptoData& dp, |
| 597 const CryptoData& dq, | 596 const CryptoData& dq, |
| 598 const CryptoData& qi, | 597 const CryptoData& qi, |
| 599 const std::string& algorithm, | 598 const std::string& algorithm, |
| 600 bool extractable, | 599 bool extractable, |
| 601 blink::WebCryptoKeyUsageMask usage_mask, | 600 blink::WebCryptoKeyUsageMask usages, |
| 602 std::vector<uint8_t>* jwk_key_data) { | 601 std::vector<uint8_t>* jwk_key_data) { |
| 603 JwkWriter writer(algorithm, extractable, usage_mask, "RSA"); | 602 JwkWriter writer(algorithm, extractable, usages, "RSA"); |
| 604 | 603 |
| 605 writer.SetBase64Encoded("n", n); | 604 writer.SetBase64Encoded("n", n); |
| 606 writer.SetBase64Encoded("e", e); | 605 writer.SetBase64Encoded("e", e); |
| 607 writer.SetBase64Encoded("d", d); | 606 writer.SetBase64Encoded("d", d); |
| 608 // Although these are "optional" in the JWA, WebCrypto spec requires them to | 607 // Although these are "optional" in the JWA, WebCrypto spec requires them to |
| 609 // be emitted. | 608 // be emitted. |
| 610 writer.SetBase64Encoded("p", p); | 609 writer.SetBase64Encoded("p", p); |
| 611 writer.SetBase64Encoded("q", q); | 610 writer.SetBase64Encoded("q", q); |
| 612 writer.SetBase64Encoded("dp", dp); | 611 writer.SetBase64Encoded("dp", dp); |
| 613 writer.SetBase64Encoded("dq", dq); | 612 writer.SetBase64Encoded("dq", dq); |
| 614 writer.SetBase64Encoded("qi", qi); | 613 writer.SetBase64Encoded("qi", qi); |
| 615 writer.ToBytes(jwk_key_data); | 614 writer.ToBytes(jwk_key_data); |
| 616 } | 615 } |
| 617 | 616 |
| 618 JwkRsaInfo::JwkRsaInfo() : is_private_key(false) { | 617 JwkRsaInfo::JwkRsaInfo() : is_private_key(false) { |
| 619 } | 618 } |
| 620 | 619 |
| 621 JwkRsaInfo::~JwkRsaInfo() { | 620 JwkRsaInfo::~JwkRsaInfo() { |
| 622 } | 621 } |
| 623 | 622 |
| 624 Status ReadRsaKeyJwk(const CryptoData& key_data, | 623 Status ReadRsaKeyJwk(const CryptoData& key_data, |
| 625 const std::string& expected_algorithm, | 624 const std::string& expected_algorithm, |
| 626 bool expected_extractable, | 625 bool expected_extractable, |
| 627 blink::WebCryptoKeyUsageMask expected_usage_mask, | 626 blink::WebCryptoKeyUsageMask expected_usages, |
| 628 JwkRsaInfo* result) { | 627 JwkRsaInfo* result) { |
| 629 if (!key_data.byte_length()) | 628 if (!key_data.byte_length()) |
| 630 return Status::ErrorImportEmptyKeyData(); | 629 return Status::ErrorImportEmptyKeyData(); |
| 631 | 630 |
| 632 scoped_ptr<base::DictionaryValue> dict; | 631 scoped_ptr<base::DictionaryValue> dict; |
| 633 std::string kty; | 632 std::string kty; |
| 634 Status status = ParseJwkCommon( | 633 Status status = ParseJwkCommon( |
| 635 key_data, expected_extractable, expected_usage_mask, &kty, &dict); | 634 key_data, expected_extractable, expected_usages, &kty, &dict); |
| 636 if (status.IsError()) | 635 if (status.IsError()) |
| 637 return status; | 636 return status; |
| 638 | 637 |
| 639 status = VerifyAlg(dict.get(), expected_algorithm); | 638 status = VerifyAlg(dict.get(), expected_algorithm); |
| 640 if (status.IsError()) | 639 if (status.IsError()) |
| 641 return status; | 640 return status; |
| 642 | 641 |
| 643 if (kty != "RSA") | 642 if (kty != "RSA") |
| 644 return Status::ErrorJwkUnexpectedKty("RSA"); | 643 return Status::ErrorJwkUnexpectedKty("RSA"); |
| 645 | 644 |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 726 | 725 |
| 727 std::string Base64EncodeUrlSafe(const std::vector<uint8_t>& input) { | 726 std::string Base64EncodeUrlSafe(const std::vector<uint8_t>& input) { |
| 728 const base::StringPiece string_piece( | 727 const base::StringPiece string_piece( |
| 729 reinterpret_cast<const char*>(vector_as_array(&input)), input.size()); | 728 reinterpret_cast<const char*>(vector_as_array(&input)), input.size()); |
| 730 return Base64EncodeUrlSafe(string_piece); | 729 return Base64EncodeUrlSafe(string_piece); |
| 731 } | 730 } |
| 732 | 731 |
| 733 } // namespace webcrypto | 732 } // namespace webcrypto |
| 734 | 733 |
| 735 } // namespace content | 734 } // namespace content |
| OLD | NEW |