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