| 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 |