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 "content/child/webcrypto/webcrypto_util.h" | 5 #include "content/child/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 |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
212 // transformation including adding padding if required, and then call a base64 | 230 // transformation including adding padding if required, and then call a base64 |
213 // decoder. | 231 // decoder. |
214 bool Base64DecodeUrlSafe(const std::string& input, std::string* output) { | 232 bool Base64DecodeUrlSafe(const std::string& input, std::string* output) { |
215 std::string base64EncodedText(input); | 233 std::string base64EncodedText(input); |
216 std::replace(base64EncodedText.begin(), base64EncodedText.end(), '-', '+'); | 234 std::replace(base64EncodedText.begin(), base64EncodedText.end(), '-', '+'); |
217 std::replace(base64EncodedText.begin(), base64EncodedText.end(), '_', '/'); | 235 std::replace(base64EncodedText.begin(), base64EncodedText.end(), '_', '/'); |
218 base64EncodedText.append((4 - base64EncodedText.size() % 4) % 4, '='); | 236 base64EncodedText.append((4 - base64EncodedText.size() % 4) % 4, '='); |
219 return base::Base64Decode(base64EncodedText, output); | 237 return base::Base64Decode(base64EncodedText, output); |
220 } | 238 } |
221 | 239 |
| 240 // Returns an unpadded 'base64url' encoding of the input data, using the |
| 241 // inverse of the process above. |
| 242 std::string Base64EncodeUrlSafe(const base::StringPiece& input) { |
| 243 std::string output; |
| 244 base::Base64Encode(input, &output); |
| 245 std::replace(output.begin(), output.end(), '+', '-'); |
| 246 std::replace(output.begin(), output.end(), '/', '_'); |
| 247 output.erase(std::remove(output.begin(), output.end(), '='), output.end()); |
| 248 return output; |
| 249 } |
| 250 |
| 251 struct JwkToWebCryptoUsage { |
| 252 const char* const jwk_key_op; |
| 253 const blink::WebCryptoKeyUsage webcrypto_usage; |
| 254 }; |
| 255 |
| 256 const JwkToWebCryptoUsage kJwkWebCryptoUsageMap[] = { |
| 257 {"encrypt", blink::WebCryptoKeyUsageEncrypt}, |
| 258 {"decrypt", blink::WebCryptoKeyUsageDecrypt}, |
| 259 {"deriveKey", blink::WebCryptoKeyUsageDeriveKey}, |
| 260 // TODO(padolph): Add 'deriveBits' once supported by Blink. |
| 261 {"sign", blink::WebCryptoKeyUsageSign}, |
| 262 {"unwrapKey", blink::WebCryptoKeyUsageUnwrapKey}, |
| 263 {"verify", blink::WebCryptoKeyUsageVerify}, |
| 264 {"wrapKey", blink::WebCryptoKeyUsageWrapKey}}; |
| 265 |
| 266 // Modifies the input usage_mask by according to the key_op value. |
| 267 bool JwkKeyOpToWebCryptoUsage(const std::string& key_op, |
| 268 blink::WebCryptoKeyUsageMask* usage_mask) { |
| 269 for (size_t i = 0; i < arraysize(kJwkWebCryptoUsageMap); ++i) { |
| 270 if (kJwkWebCryptoUsageMap[i].jwk_key_op == key_op) { |
| 271 *usage_mask |= kJwkWebCryptoUsageMap[i].webcrypto_usage; |
| 272 return true; |
| 273 } |
| 274 } |
| 275 return false; |
| 276 } |
| 277 |
| 278 // Composes a Web Crypto usage mask from an array of JWK key_ops values. |
| 279 Status GetWebCryptoUsagesFromJwkKeyOps( |
| 280 const base::ListValue* jwk_key_ops_value, |
| 281 blink::WebCryptoKeyUsageMask* usage_mask) { |
| 282 *usage_mask = 0; |
| 283 for (size_t i = 0; i < jwk_key_ops_value->GetSize(); ++i) { |
| 284 std::string key_op; |
| 285 if (!jwk_key_ops_value->GetString(i, &key_op)) { |
| 286 return Status::ErrorJwkPropertyWrongType( |
| 287 base::StringPrintf("key_ops[%d]", static_cast<int>(i)), "string"); |
| 288 } |
| 289 if (!JwkKeyOpToWebCryptoUsage(key_op, usage_mask)) |
| 290 return Status::ErrorJwkUnrecognizedKeyop(); |
| 291 } |
| 292 return Status::Success(); |
| 293 } |
| 294 |
| 295 // Composes a JWK key_ops List from a Web Crypto usage mask. |
| 296 // Note: Caller must assume ownership of returned instance. |
| 297 base::ListValue* CreateJwkKeyOpsFromWebCryptoUsages( |
| 298 blink::WebCryptoKeyUsageMask usage_mask) { |
| 299 base::ListValue* jwk_key_ops = new base::ListValue(); |
| 300 for (size_t i = 0; i < arraysize(kJwkWebCryptoUsageMap); ++i) { |
| 301 if (usage_mask & kJwkWebCryptoUsageMap[i].webcrypto_usage) |
| 302 jwk_key_ops->AppendString(kJwkWebCryptoUsageMap[i].jwk_key_op); |
| 303 } |
| 304 return jwk_key_ops; |
| 305 } |
| 306 |
222 bool IsHashAlgorithm(blink::WebCryptoAlgorithmId alg_id) { | 307 bool IsHashAlgorithm(blink::WebCryptoAlgorithmId alg_id) { |
223 return alg_id == blink::WebCryptoAlgorithmIdSha1 || | 308 return alg_id == blink::WebCryptoAlgorithmIdSha1 || |
224 alg_id == blink::WebCryptoAlgorithmIdSha256 || | 309 alg_id == blink::WebCryptoAlgorithmIdSha256 || |
225 alg_id == blink::WebCryptoAlgorithmIdSha384 || | 310 alg_id == blink::WebCryptoAlgorithmIdSha384 || |
226 alg_id == blink::WebCryptoAlgorithmIdSha512; | 311 alg_id == blink::WebCryptoAlgorithmIdSha512; |
227 } | 312 } |
228 | 313 |
229 blink::WebCryptoAlgorithm GetInnerHashAlgorithm( | 314 blink::WebCryptoAlgorithm GetInnerHashAlgorithm( |
230 const blink::WebCryptoAlgorithm& algorithm) { | 315 const blink::WebCryptoAlgorithm& algorithm) { |
231 DCHECK(!algorithm.isNull()); | 316 DCHECK(!algorithm.isNull()); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
306 new blink::WebCryptoAesKeyAlgorithmParams(keylen_bytes * 8)); | 391 new blink::WebCryptoAesKeyAlgorithmParams(keylen_bytes * 8)); |
307 return true; | 392 return true; |
308 default: | 393 default: |
309 return false; | 394 return false; |
310 } | 395 } |
311 } | 396 } |
312 | 397 |
313 } // namespace webcrypto | 398 } // namespace webcrypto |
314 | 399 |
315 } // namespace content | 400 } // namespace content |
OLD | NEW |