| Index: content/child/webcrypto/jwk.cc
|
| diff --git a/content/child/webcrypto/jwk.cc b/content/child/webcrypto/jwk.cc
|
| index 67eb5242fbf0e73e41a55928ddcf348bde264937..4bc15e2b788aa898ee618bbf31cb0bfba7cf3230 100644
|
| --- a/content/child/webcrypto/jwk.cc
|
| +++ b/content/child/webcrypto/jwk.cc
|
| @@ -322,27 +322,23 @@ Status GetJwkBytes(base::DictionaryValue* dict,
|
| return Status::Success();
|
| }
|
|
|
| -// Extracts the optional string property with key |path| from |dict| and saves
|
| -// the base64url-decoded bytes to |*result|. If the property exist and is not a
|
| -// string, or could not be base64url-decoded, returns an error. In the case
|
| -// where the property does not exist, |result| is guaranteed to be empty.
|
| -Status GetOptionalJwkBytes(base::DictionaryValue* dict,
|
| - const std::string& path,
|
| - std::string* result,
|
| - bool* property_exists) {
|
| - std::string base64_string;
|
| - Status status =
|
| - GetOptionalJwkString(dict, path, &base64_string, property_exists);
|
| +// Extracts the required base64url property, which is interpreted as being a
|
| +// big-endian unsigned integer.
|
| +Status GetJwkBigInteger(base::DictionaryValue* dict,
|
| + const std::string& path,
|
| + std::string* result) {
|
| + Status status = GetJwkBytes(dict, path, result);
|
| if (status.IsError())
|
| return status;
|
|
|
| - if (!*property_exists) {
|
| - result->clear();
|
| - return Status::Success();
|
| - }
|
| + if (result->empty())
|
| + return Status::ErrorJwkEmptyBigInteger(path);
|
|
|
| - if (!Base64DecodeUrlSafe(base64_string, result))
|
| - return Status::ErrorJwkBase64Decode(path);
|
| + // The JWA spec says that "The octet sequence MUST utilize the minimum number
|
| + // of octets to represent the value." This means there shouldn't be any
|
| + // leading zeros.
|
| + if (result->size() > 1 && (*result)[0] == 0)
|
| + return Status::ErrorJwkBigIntegerHasLeadingZero(path);
|
|
|
| return Status::Success();
|
| }
|
| @@ -650,10 +646,10 @@ Status ReadRsaKeyJwk(const CryptoData& key_data,
|
| // (private exponent) entry.
|
| // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18,
|
| // section 6.3.
|
| - status = GetJwkBytes(dict.get(), "n", &result->n);
|
| + status = GetJwkBigInteger(dict.get(), "n", &result->n);
|
| if (status.IsError())
|
| return status;
|
| - status = GetJwkBytes(dict.get(), "e", &result->e);
|
| + status = GetJwkBigInteger(dict.get(), "e", &result->e);
|
| if (status.IsError())
|
| return status;
|
|
|
| @@ -661,43 +657,33 @@ Status ReadRsaKeyJwk(const CryptoData& key_data,
|
| if (!result->is_private_key)
|
| return Status::Success();
|
|
|
| - status = GetJwkBytes(dict.get(), "d", &result->d);
|
| + status = GetJwkBigInteger(dict.get(), "d", &result->d);
|
| if (status.IsError())
|
| return status;
|
|
|
| - // The "p", "q", "dp", "dq", and "qi" properties are optional. Treat these
|
| - // properties the same if they are unspecified, as if they were specified-but
|
| - // empty, since ImportRsaPrivateKey() doesn't do validation checks anyway.
|
| + // The "p", "q", "dp", "dq", and "qi" properties are optional in the JWA
|
| + // spec. However they are required by Chromium's WebCrypto implementation.
|
|
|
| - bool has_p;
|
| - status = GetOptionalJwkBytes(dict.get(), "p", &result->p, &has_p);
|
| + status = GetJwkBigInteger(dict.get(), "p", &result->p);
|
| if (status.IsError())
|
| return status;
|
|
|
| - bool has_q;
|
| - status = GetOptionalJwkBytes(dict.get(), "q", &result->q, &has_q);
|
| + status = GetJwkBigInteger(dict.get(), "q", &result->q);
|
| if (status.IsError())
|
| return status;
|
|
|
| - bool has_dp;
|
| - status = GetOptionalJwkBytes(dict.get(), "dp", &result->dp, &has_dp);
|
| + status = GetJwkBigInteger(dict.get(), "dp", &result->dp);
|
| if (status.IsError())
|
| return status;
|
|
|
| - bool has_dq;
|
| - status = GetOptionalJwkBytes(dict.get(), "dq", &result->dq, &has_dq);
|
| + status = GetJwkBigInteger(dict.get(), "dq", &result->dq);
|
| if (status.IsError())
|
| return status;
|
|
|
| - bool has_qi;
|
| - status = GetOptionalJwkBytes(dict.get(), "qi", &result->qi, &has_qi);
|
| + status = GetJwkBigInteger(dict.get(), "qi", &result->qi);
|
| if (status.IsError())
|
| return status;
|
|
|
| - int num_optional_properties = has_p + has_q + has_dp + has_dq + has_qi;
|
| - if (num_optional_properties != 0 && num_optional_properties != 5)
|
| - return Status::ErrorJwkIncompleteOptionalRsaPrivateKey();
|
| -
|
| return Status::Success();
|
| }
|
|
|
|
|