OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 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_util.h" | 5 #include "content/renderer/webcrypto/webcrypto_util.h" |
6 | 6 |
7 #include "base/base64.h" | 7 #include "base/base64.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/strings/stringprintf.h" |
9 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" | 10 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" |
10 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" | 11 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" |
11 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" | 12 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" |
12 | 13 |
13 namespace content { | 14 namespace content { |
14 | 15 |
15 namespace webcrypto { | 16 namespace webcrypto { |
16 | 17 |
17 bool Status::IsError() const { return type_ == TYPE_ERROR; } | 18 bool Status::IsError() const { return type_ == TYPE_ERROR; } |
18 | 19 |
(...skipping 21 matching lines...) Expand all Loading... |
40 const std::string& expected_type) { | 41 const std::string& expected_type) { |
41 return Status("The JWK property \"" + property + "\" must be a " + | 42 return Status("The JWK property \"" + property + "\" must be a " + |
42 expected_type); | 43 expected_type); |
43 } | 44 } |
44 | 45 |
45 Status Status::ErrorJwkBase64Decode(const std::string& property) { | 46 Status Status::ErrorJwkBase64Decode(const std::string& property) { |
46 return Status("The JWK property \"" + property + | 47 return Status("The JWK property \"" + property + |
47 "\" could not be base64 decoded"); | 48 "\" could not be base64 decoded"); |
48 } | 49 } |
49 | 50 |
50 Status Status::ErrorJwkExtractableInconsistent() { | 51 Status Status::ErrorJwkExtInconsistent() { |
51 return Status( | 52 return Status( |
52 "The \"extractable\" property of the JWK dictionary is " | 53 "The \"ext\" property of the JWK dictionary is inconsistent what that " |
53 "inconsistent what that specified by the Web Crypto call"); | 54 "specified by the Web Crypto call"); |
54 } | 55 } |
55 | 56 |
56 Status Status::ErrorJwkUnrecognizedAlgorithm() { | 57 Status Status::ErrorJwkUnrecognizedAlgorithm() { |
57 return Status("The JWK \"alg\" property was not recognized"); | 58 return Status("The JWK \"alg\" property was not recognized"); |
58 } | 59 } |
59 | 60 |
60 Status Status::ErrorJwkAlgorithmInconsistent() { | 61 Status Status::ErrorJwkAlgorithmInconsistent() { |
61 return Status( | 62 return Status( |
62 "The JWK \"alg\" property was inconsistent with that specified " | 63 "The JWK \"alg\" property was inconsistent with that specified " |
63 "by the Web Crypto call"); | 64 "by the Web Crypto call"); |
64 } | 65 } |
65 | 66 |
66 Status Status::ErrorJwkAlgorithmMissing() { | 67 Status Status::ErrorJwkAlgorithmMissing() { |
67 return Status( | 68 return Status( |
68 "The JWK optional \"alg\" property is missing or not a string, " | 69 "The JWK optional \"alg\" property is missing or not a string, " |
69 "and one wasn't specified by the Web Crypto call"); | 70 "and one wasn't specified by the Web Crypto call"); |
70 } | 71 } |
71 | 72 |
72 Status Status::ErrorJwkUnrecognizedUsage() { | 73 Status Status::ErrorJwkUnrecognizedUse() { |
73 return Status("The JWK \"use\" property could not be parsed"); | 74 return Status("The JWK \"use\" property could not be parsed"); |
74 } | 75 } |
75 | 76 |
76 Status Status::ErrorJwkUsageInconsistent() { | 77 Status Status::ErrorJwkUnrecognizedKeyop() { |
| 78 return Status("The JWK \"key_ops\" property could not be parsed"); |
| 79 } |
| 80 |
| 81 Status Status::ErrorJwkUseInconsistent() { |
77 return Status( | 82 return Status( |
78 "The JWK \"use\" property was inconsistent with that specified " | 83 "The JWK \"use\" property was inconsistent with that specified " |
79 "by the Web Crypto call. The JWK usage must be a superset of " | 84 "by the Web Crypto call. The JWK usage must be a superset of " |
80 "those requested"); | 85 "those requested"); |
81 } | 86 } |
82 | 87 |
| 88 Status Status::ErrorJwkKeyopsInconsistent() { |
| 89 return Status( |
| 90 "The JWK \"key_ops\" property was inconsistent with that " |
| 91 "specified by the Web Crypto call. The JWK usage must be a " |
| 92 "superset of those requested"); |
| 93 } |
| 94 |
| 95 Status Status::ErrorJwkUseAndKeyopsInconsistent() { |
| 96 return Status( |
| 97 "The JWK \"use\" and \"key_ops\" properties were both found " |
| 98 "but are inconsistent with each other."); |
| 99 } |
| 100 |
83 Status Status::ErrorJwkRsaPrivateKeyUnsupported() { | 101 Status Status::ErrorJwkRsaPrivateKeyUnsupported() { |
84 return Status( | 102 return Status( |
85 "JWK RSA key contained \"d\" property: Private key import is " | 103 "JWK RSA key contained \"d\" property: Private key import is " |
86 "not yet supported"); | 104 "not yet supported"); |
87 } | 105 } |
88 | 106 |
89 Status Status::ErrorJwkUnrecognizedKty() { | 107 Status Status::ErrorJwkUnrecognizedKty() { |
90 return Status("The JWK \"kty\" property was unrecognized"); | 108 return Status("The JWK \"kty\" property was unrecognized"); |
91 } | 109 } |
92 | 110 |
93 Status Status::ErrorJwkIncorrectKeyLength() { | 111 Status Status::ErrorJwkIncorrectKeyLength() { |
94 return Status( | 112 return Status( |
95 "The JWK \"k\" property did not include the right length " | 113 "The JWK \"k\" property did not include the right length " |
96 "of key data for the given algorithm."); | 114 "of key data for the given algorithm."); |
97 } | 115 } |
98 | 116 |
| 117 Status Status::ErrorJwkUnsupportedHmacHash() { |
| 118 return Status("JWK does not support HMAC with this inner hash."); |
| 119 } |
| 120 |
99 Status Status::ErrorImportEmptyKeyData() { | 121 Status Status::ErrorImportEmptyKeyData() { |
100 return Status("No key data was provided"); | 122 return Status("No key data was provided"); |
101 } | 123 } |
102 | 124 |
103 Status Status::ErrorUnexpectedKeyType() { | 125 Status Status::ErrorUnexpectedKeyType() { |
104 return Status("The key is not of the expected type"); | 126 return Status("The key is not of the expected type"); |
105 } | 127 } |
106 | 128 |
107 Status Status::ErrorIncorrectSizeAesCbcIv() { | 129 Status Status::ErrorIncorrectSizeAesCbcIv() { |
108 return Status("The \"iv\" has an unexpected length -- must be 16 bytes"); | 130 return Status("The \"iv\" has an unexpected length -- must be 16 bytes"); |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
212 // transformation including adding padding if required, and then call a base64 | 234 // transformation including adding padding if required, and then call a base64 |
213 // decoder. | 235 // decoder. |
214 bool Base64DecodeUrlSafe(const std::string& input, std::string* output) { | 236 bool Base64DecodeUrlSafe(const std::string& input, std::string* output) { |
215 std::string base64EncodedText(input); | 237 std::string base64EncodedText(input); |
216 std::replace(base64EncodedText.begin(), base64EncodedText.end(), '-', '+'); | 238 std::replace(base64EncodedText.begin(), base64EncodedText.end(), '-', '+'); |
217 std::replace(base64EncodedText.begin(), base64EncodedText.end(), '_', '/'); | 239 std::replace(base64EncodedText.begin(), base64EncodedText.end(), '_', '/'); |
218 base64EncodedText.append((4 - base64EncodedText.size() % 4) % 4, '='); | 240 base64EncodedText.append((4 - base64EncodedText.size() % 4) % 4, '='); |
219 return base::Base64Decode(base64EncodedText, output); | 241 return base::Base64Decode(base64EncodedText, output); |
220 } | 242 } |
221 | 243 |
| 244 // Produces an unpadded 'base64url' encoding of the input data, using the |
| 245 // inverse of the process above. |
| 246 void Base64EncodeUrlSafe(const base::StringPiece& input, std::string* output) { |
| 247 base::Base64Encode(input, output); |
| 248 std::replace(output->begin(), output->end(), '+', '-'); |
| 249 std::replace(output->begin(), output->end(), '/', '_'); |
| 250 output->erase(std::remove(output->begin(), output->end(), '='), |
| 251 output->end()); |
| 252 } |
| 253 |
| 254 // Composes a Web Crypto usage mask from an array of JWK key_ops values. |
| 255 Status GetUsagesFromJwkKeyOps(base::ListValue* jwk_key_ops_value, |
| 256 blink::WebCryptoKeyUsageMask* jwk_key_ops_mask) { |
| 257 for (size_t i = 0; i < jwk_key_ops_value->GetSize(); ++i) { |
| 258 std::string key_op; |
| 259 if (!jwk_key_ops_value->GetString(i, &key_op)) |
| 260 return Status::ErrorJwkPropertyWrongType( |
| 261 base::StringPrintf("key_ops[%d]", static_cast<int>(i)), "string"); |
| 262 if (key_op == "encrypt") |
| 263 *jwk_key_ops_mask |= blink::WebCryptoKeyUsageEncrypt; |
| 264 else if (key_op == "decrypt") |
| 265 *jwk_key_ops_mask |= blink::WebCryptoKeyUsageDecrypt; |
| 266 else if (key_op == "sign") |
| 267 *jwk_key_ops_mask |= blink::WebCryptoKeyUsageSign; |
| 268 else if (key_op == "verify") |
| 269 *jwk_key_ops_mask |= blink::WebCryptoKeyUsageVerify; |
| 270 else if (key_op == "wrapKey") |
| 271 *jwk_key_ops_mask |= blink::WebCryptoKeyUsageWrapKey; |
| 272 else if (key_op == "unwrapKey") |
| 273 *jwk_key_ops_mask |= blink::WebCryptoKeyUsageUnwrapKey; |
| 274 else if (key_op == "deriveKey") |
| 275 *jwk_key_ops_mask |= blink::WebCryptoKeyUsageDeriveKey; |
| 276 else |
| 277 return Status::ErrorJwkUnrecognizedKeyop(); |
| 278 // TODO(padolph): Add 'deriveBits' once supported by Blink. |
| 279 } |
| 280 return Status::Success(); |
| 281 } |
| 282 |
222 bool IsHashAlgorithm(blink::WebCryptoAlgorithmId alg_id) { | 283 bool IsHashAlgorithm(blink::WebCryptoAlgorithmId alg_id) { |
223 return alg_id == blink::WebCryptoAlgorithmIdSha1 || | 284 return alg_id == blink::WebCryptoAlgorithmIdSha1 || |
224 alg_id == blink::WebCryptoAlgorithmIdSha224 || | 285 alg_id == blink::WebCryptoAlgorithmIdSha224 || |
225 alg_id == blink::WebCryptoAlgorithmIdSha256 || | 286 alg_id == blink::WebCryptoAlgorithmIdSha256 || |
226 alg_id == blink::WebCryptoAlgorithmIdSha384 || | 287 alg_id == blink::WebCryptoAlgorithmIdSha384 || |
227 alg_id == blink::WebCryptoAlgorithmIdSha512; | 288 alg_id == blink::WebCryptoAlgorithmIdSha512; |
228 } | 289 } |
229 | 290 |
230 blink::WebCryptoAlgorithm GetInnerHashAlgorithm( | 291 blink::WebCryptoAlgorithm GetInnerHashAlgorithm( |
231 const blink::WebCryptoAlgorithm& algorithm) { | 292 const blink::WebCryptoAlgorithm& algorithm) { |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
311 new blink::WebCryptoAesKeyAlgorithmParams(keylen_bytes * 8)); | 372 new blink::WebCryptoAesKeyAlgorithmParams(keylen_bytes * 8)); |
312 return true; | 373 return true; |
313 default: | 374 default: |
314 return false; | 375 return false; |
315 } | 376 } |
316 } | 377 } |
317 | 378 |
318 } // namespace webcrypto | 379 } // namespace webcrypto |
319 | 380 |
320 } // namespace content | 381 } // namespace content |
OLD | NEW |