Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1139)

Unified Diff: content/child/webcrypto/jwk.cc

Issue 200263002: Revert of [webcrypto] JWK: Updated import(ext, key_ops) and added export of symmetric keys (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@wcAesKw_nss1
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | content/child/webcrypto/shared_crypto.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/child/webcrypto/jwk.cc
diff --git a/content/child/webcrypto/jwk.cc b/content/child/webcrypto/jwk.cc
index 38ae18e82ab2ade8bf0c410d440decd4830dd9a2..513193021cd83fec9504c1b2e1b0061ca411bc6a 100644
--- a/content/child/webcrypto/jwk.cc
+++ b/content/child/webcrypto/jwk.cc
@@ -6,30 +6,21 @@
#include <functional>
#include <map>
#include "base/json/json_reader.h"
-#include "base/json/json_writer.h"
#include "base/lazy_instance.h"
-#include "base/strings/stringprintf.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_piece.h"
+#include "base/values.h"
#include "content/child/webcrypto/crypto_data.h"
#include "content/child/webcrypto/platform_crypto.h"
#include "content/child/webcrypto/shared_crypto.h"
#include "content/child/webcrypto/webcrypto_util.h"
-#include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
namespace content {
namespace webcrypto {
namespace {
-
-// Web Crypto equivalent usage mask for JWK 'use' = 'enc'.
-// TODO(padolph): Add 'deriveBits' once supported by Blink.
-const blink::WebCryptoKeyUsageMask kJwkEncUsage =
- blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt |
- blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey |
- blink::WebCryptoKeyUsageDeriveKey;
-// Web Crypto equivalent usage mask for JWK 'use' = 'sig'.
-const blink::WebCryptoKeyUsageMask kJwkSigUsage =
- blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify;
typedef blink::WebCryptoAlgorithm (*AlgorithmCreationFunc)();
@@ -47,7 +38,7 @@
unsigned int required_key_length_bits)
: creation_func_(algorithm_creation_func),
required_key_length_bytes_(required_key_length_bits / 8) {
- DCHECK_EQ(0u, required_key_length_bits % 8);
+ DCHECK((required_key_length_bits % 8) == 0);
}
bool CreateImportAlgorithm(blink::WebCryptoAlgorithm* algorithm) const {
@@ -79,9 +70,6 @@
// http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-20
// says HMAC with SHA-2 should have a key size at least as large as the
// hash output.
- alg_to_info_["HS1"] =
- JwkAlgorithmInfo(&BindAlgorithmId<CreateHmacImportAlgorithm,
- blink::WebCryptoAlgorithmIdSha1>);
alg_to_info_["HS256"] =
JwkAlgorithmInfo(&BindAlgorithmId<CreateHmacImportAlgorithm,
blink::WebCryptoAlgorithmIdSha256>);
@@ -106,21 +94,15 @@
alg_to_info_["RSA-OAEP"] =
JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaOaepImportAlgorithm,
blink::WebCryptoAlgorithmIdSha1>);
- alg_to_info_["A128KW"] = JwkAlgorithmInfo(
- &BindAlgorithmId<CreateAlgorithm, blink::WebCryptoAlgorithmIdAesKw>,
- 128);
- alg_to_info_["A192KW"] = JwkAlgorithmInfo(
- &BindAlgorithmId<CreateAlgorithm, blink::WebCryptoAlgorithmIdAesKw>,
- 192);
- alg_to_info_["A256KW"] = JwkAlgorithmInfo(
- &BindAlgorithmId<CreateAlgorithm, blink::WebCryptoAlgorithmIdAesKw>,
- 256);
+ // TODO(padolph): The Web Crypto spec does not enumerate AES-KW 128 yet
+ alg_to_info_["A128KW"] =
+ JwkAlgorithmInfo(&blink::WebCryptoAlgorithm::createNull, 128);
+ // TODO(padolph): The Web Crypto spec does not enumerate AES-KW 256 yet
+ alg_to_info_["A256KW"] =
+ JwkAlgorithmInfo(&blink::WebCryptoAlgorithm::createNull, 256);
alg_to_info_["A128GCM"] = JwkAlgorithmInfo(
&BindAlgorithmId<CreateAlgorithm, blink::WebCryptoAlgorithmIdAesGcm>,
128);
- alg_to_info_["A192GCM"] = JwkAlgorithmInfo(
- &BindAlgorithmId<CreateAlgorithm, blink::WebCryptoAlgorithmIdAesGcm>,
- 192);
alg_to_info_["A256GCM"] = JwkAlgorithmInfo(
&BindAlgorithmId<CreateAlgorithm, blink::WebCryptoAlgorithmIdAesGcm>,
256);
@@ -215,29 +197,9 @@
return Status::Success();
}
-// Extracts the optional array property with key |path| from |dict| and saves
-// the result to |*result| if it was found. If the property exists and is not an
-// array, returns an error. Otherwise returns success, and sets
-// |*property_exists| if it was found. Note that |*result| is owned by |dict|.
-Status GetOptionalJwkList(base::DictionaryValue* dict,
- const std::string& path,
- base::ListValue** result,
- bool* property_exists) {
- *property_exists = false;
- base::Value* value = NULL;
- if (!dict->Get(path, &value))
- return Status::Success();
-
- if (!value->GetAsList(result))
- return Status::ErrorJwkPropertyWrongType(path, "list");
-
- *property_exists = true;
- return Status::Success();
-}
-
// Extracts the required string property with key |path| from |dict| and saves
-// the base64url-decoded bytes to |*result|. If the property does not exist or
-// is not a string, or could not be base64url-decoded, returns an error.
+// the base64-decoded bytes to |*result|. If the property does not exist or is
+// not a string, or could not be base64-decoded, returns an error.
Status GetJwkBytes(base::DictionaryValue* dict,
const std::string& path,
std::string* result) {
@@ -272,115 +234,6 @@
return Status::Success();
}
-// Returns true if the set bits in b make up a subset of the set bits in a.
-bool ContainsKeyUsages(blink::WebCryptoKeyUsageMask a,
- blink::WebCryptoKeyUsageMask b) {
- return (a & b) == b;
-}
-
-// Writes a secret/symmetric key to a JWK dictionary.
-void WriteSecretKey(const blink::WebArrayBuffer& raw_key,
- base::DictionaryValue* jwk_dict) {
- DCHECK(jwk_dict);
- jwk_dict->SetString("kty", "oct");
- // For a secret/symmetric key, the only extra JWK field is 'k', containing the
- // base64url encoding of the raw key.
- DCHECK(!raw_key.isNull());
- DCHECK(raw_key.data());
- DCHECK(raw_key.byteLength());
- unsigned int key_length_bytes = raw_key.byteLength();
- const base::StringPiece key_str(static_cast<const char*>(raw_key.data()),
- key_length_bytes);
- jwk_dict->SetString("k", Base64EncodeUrlSafe(key_str));
-}
-
-// Writes a Web Crypto usage mask to a JWK dictionary.
-void WriteKeyOps(blink::WebCryptoKeyUsageMask key_usages,
- base::DictionaryValue* jwk_dict) {
- jwk_dict->Set("key_ops", CreateJwkKeyOpsFromWebCryptoUsages(key_usages));
-}
-
-// Writes a Web Crypto extractable value to a JWK dictionary.
-void WriteExt(bool extractable, base::DictionaryValue* jwk_dict) {
- jwk_dict->SetBoolean("ext", extractable);
-}
-
-// Writes a Web Crypto algorithm to a JWK dictionary.
-Status WriteAlg(const blink::WebCryptoKeyAlgorithm& algorithm,
- unsigned int raw_key_length_bytes,
- base::DictionaryValue* jwk_dict) {
- switch (algorithm.paramsType()) {
- case blink::WebCryptoKeyAlgorithmParamsTypeAes: {
- const char* aes_prefix = "";
- switch (raw_key_length_bytes) {
- case 16:
- aes_prefix = "A128";
- break;
- case 24:
- aes_prefix = "A192";
- break;
- case 32:
- aes_prefix = "A256";
- break;
- default:
- NOTREACHED(); // bad key length means algorithm was built improperly
- return Status::ErrorUnexpected();
- }
- const char* aes_suffix = "";
- switch (algorithm.id()) {
- case blink::WebCryptoAlgorithmIdAesCbc:
- aes_suffix = "CBC";
- break;
- case blink::WebCryptoAlgorithmIdAesCtr:
- aes_suffix = "CTR";
- break;
- case blink::WebCryptoAlgorithmIdAesGcm:
- aes_suffix = "GCM";
- break;
- case blink::WebCryptoAlgorithmIdAesKw:
- aes_suffix = "KW";
- break;
- default:
- return Status::ErrorUnsupported();
- }
- jwk_dict->SetString("alg",
- base::StringPrintf("%s%s", aes_prefix, aes_suffix));
- break;
- }
- case blink::WebCryptoKeyAlgorithmParamsTypeHmac: {
- DCHECK(algorithm.hmacParams());
- switch (algorithm.hmacParams()->hash().id()) {
- case blink::WebCryptoAlgorithmIdSha1:
- jwk_dict->SetString("alg", "HS1");
- break;
- case blink::WebCryptoAlgorithmIdSha224:
- jwk_dict->SetString("alg", "HS224");
- break;
- case blink::WebCryptoAlgorithmIdSha256:
- jwk_dict->SetString("alg", "HS256");
- break;
- case blink::WebCryptoAlgorithmIdSha384:
- jwk_dict->SetString("alg", "HS384");
- break;
- case blink::WebCryptoAlgorithmIdSha512:
- jwk_dict->SetString("alg", "HS512");
- break;
- default:
- NOTREACHED();
- return Status::ErrorUnexpected();
- }
- break;
- }
- case blink::WebCryptoKeyAlgorithmParamsTypeRsa:
- case blink::WebCryptoKeyAlgorithmParamsTypeRsaHashed:
- // TODO(padolph): Handle RSA key
- return Status::ErrorUnsupported();
- default:
- return Status::ErrorUnsupported();
- }
- return Status::Success();
-}
-
} // namespace
Status ImportKeyJwk(const CryptoData& key_data,
@@ -388,23 +241,22 @@
bool extractable,
blink::WebCryptoKeyUsageMask usage_mask,
blink::WebCryptoKey* key) {
- // TODO(padolph): Generalize this comment to include export, and move to top
- // of file.
// The goal of this method is to extract key material and meta data from the
// incoming JWK, combine them with the input parameters, and ultimately import
// a Web Crypto Key.
//
// JSON Web Key Format (JWK)
- // http://tools.ietf.org/html/draft-ietf-jose-json-web-key-21
+ // http://tools.ietf.org/html/draft-ietf-jose-json-web-key-16
+ // TODO(padolph): Not all possible values are handled by this code right now
//
// A JWK is a simple JSON dictionary with the following entries
// - "kty" (Key Type) Parameter, REQUIRED
// - <kty-specific parameters, see below>, REQUIRED
// - "use" (Key Use) Parameter, OPTIONAL
- // - "key_ops" (Key Operations) Parameter, OPTIONAL
// - "alg" (Algorithm) Parameter, OPTIONAL
- // - "ext" (Key Exportability), OPTIONAL
+ // - "extractable" (Key Exportability), OPTIONAL [NOTE: not yet part of JOSE,
+ // see https://www.w3.org/Bugs/Public/show_bug.cgi?id=23796]
// (all other entries are ignored)
//
// OPTIONAL here means that this code does not require the entry to be present
@@ -419,13 +271,13 @@
// values are parsed out and combined with the method input parameters to
// build a Web Crypto Key:
// Web Crypto Key type <-- (deduced)
- // Web Crypto Key extractable <-- JWK ext + input extractable
+ // Web Crypto Key extractable <-- JWK extractable + input extractable
// Web Crypto Key algorithm <-- JWK alg + input algorithm
- // Web Crypto Key keyUsage <-- JWK use, key_ops + input usage_mask
+ // Web Crypto Key keyUsage <-- JWK use + input usage_mask
// Web Crypto Key keying material <-- kty-specific parameters
//
// Values for each JWK entry are case-sensitive and defined in
- // http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18.
+ // http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-16.
// Note that not all values specified by JOSE are handled by this code. Only
// handled values are listed.
// - kty (Key Type)
@@ -433,50 +285,22 @@
// | "RSA" | RSA [RFC3447] |
// | "oct" | Octet sequence (used to represent symmetric keys) |
// +-------+--------------------------------------------------------------+
- //
- // - key_ops (Key Use Details)
- // The key_ops field is an array that contains one or more strings from
- // the table below, and describes the operations for which this key may be
- // used.
- // +-------+--------------------------------------------------------------+
- // | "encrypt" | encrypt operations |
- // | "decrypt" | decrypt operations |
- // | "sign" | sign (MAC) operations |
- // | "verify" | verify (MAC) operations |
- // | "wrapKey" | key wrap |
- // | "unwrapKey" | key unwrap |
- // | "deriveKey" | key derivation |
- // | "deriveBits" | key derivation TODO(padolph): not currently supported |
- // +-------+--------------------------------------------------------------+
- //
// - use (Key Use)
- // The use field contains a single entry from the table below.
- // +-------+--------------------------------------------------------------+
- // | "sig" | equivalent to key_ops of [sign, verify] |
- // | "enc" | equivalent to key_ops of [encrypt, decrypt, wrapKey, |
- // | | unwrapKey, deriveKey, deriveBits] |
- // +-------+--------------------------------------------------------------+
- //
- // NOTE: If both "use" and "key_ops" JWK members are present, the usages
- // specified by them MUST be consistent. In particular, the "use" value
- // "sig" corresponds to "sign" and/or "verify". The "use" value "enc"
- // corresponds to all other values defined above. If "key_ops" values
- // corresponding to both "sig" and "enc" "use" values are present, the "use"
- // member SHOULD NOT be present, and if present, its value MUST NOT be
- // either "sig" or "enc".
- //
- // - ext (Key Exportability)
+ // +-------+--------------------------------------------------------------+
+ // | "enc" | encrypt and decrypt operations |
+ // | "sig" | sign and verify (MAC) operations |
+ // | "wrap"| key wrap and unwrap [not yet part of JOSE] |
+ // +-------+--------------------------------------------------------------+
+ // - extractable (Key Exportability)
// +-------+--------------------------------------------------------------+
// | true | Key may be exported from the trusted environment |
// | false | Key cannot exit the trusted environment |
// +-------+--------------------------------------------------------------+
- //
// - alg (Algorithm)
- // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18
+ // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-16
// +--------------+-------------------------------------------------------+
// | Digital Signature or MAC Algorithm |
// +--------------+-------------------------------------------------------+
- // | "HS1" | HMAC using SHA-1 hash algorithm |
// | "HS256" | HMAC using SHA-256 hash algorithm |
// | "HS384" | HMAC using SHA-384 hash algorithm |
// | "HS512" | HMAC using SHA-512 hash algorithm |
@@ -492,16 +316,15 @@
// | | specified by RFC3447 in Section A.2.1 |
// | "A128KW" | Advanced Encryption Standard (AES) Key Wrap Algorithm |
// | | [RFC3394] using 128 bit keys |
- // | "A192KW" | AES Key Wrap Algorithm using 192 bit keys |
// | "A256KW" | AES Key Wrap Algorithm using 256 bit keys |
// | "A128GCM" | AES in Galois/Counter Mode (GCM) [NIST.800-38D] using |
// | | 128 bit keys |
- // | "A192GCM" | AES GCM using 192 bit keys |
// | "A256GCM" | AES GCM using 256 bit keys |
// | "A128CBC" | AES in Cipher Block Chaining Mode (CBC) with PKCS #5 |
- // | | padding [NIST.800-38A] |
- // | "A192CBC" | AES CBC using 192 bit keys |
- // | "A256CBC" | AES CBC using 256 bit keys |
+ // | | padding [NIST.800-38A] [not yet part of JOSE, see |
+ // | | https://www.w3.org/Bugs/Public/show_bug.cgi?id=23796 |
+ // | "A192CBC" | AES CBC using 192 bit keys [not yet part of JOSE] |
+ // | "A256CBC" | AES CBC using 256 bit keys [not yet part of JOSE] |
// +--------------+-------------------------------------------------------+
//
// kty-specific parameters
@@ -543,8 +366,8 @@
// algorithm.
//
// extractable
- // If the JWK ext field is true but the input parameter is false, make the
- // Web Crypto Key non-extractable. Conversely, if the JWK ext field is
+ // If the JWK extractable is true but the input parameter is false, make the
+ // Web Crypto Key non-extractable. Conversely, if the JWK extractable is
// false but the input parameter is true, it is an inconsistency. If both
// are true or both are false, use that value.
//
@@ -573,16 +396,18 @@
if (status.IsError())
return status;
- // JWK "ext" (optional) --> extractable parameter
+ // JWK "extractable" (optional) --> extractable parameter
{
- bool jwk_ext_value = false;
- bool has_jwk_ext;
- status =
- GetOptionalJwkBool(dict_value, "ext", &jwk_ext_value, &has_jwk_ext);
+ bool jwk_extractable_value = false;
+ bool has_jwk_extractable;
+ status = GetOptionalJwkBool(dict_value,
+ "extractable",
+ &jwk_extractable_value,
+ &has_jwk_extractable);
if (status.IsError())
return status;
- if (has_jwk_ext && !jwk_ext_value && extractable)
- return Status::ErrorJwkExtInconsistent();
+ if (has_jwk_extractable && !jwk_extractable_value && extractable)
+ return Status::ErrorJwkExtractableInconsistent();
}
// JWK "alg" (optional) --> algorithm parameter
@@ -635,24 +460,6 @@
}
DCHECK(!algorithm.isNull());
- // JWK "key_ops" (optional) --> usage_mask parameter
- base::ListValue* jwk_key_ops_value = NULL;
- bool has_jwk_key_ops;
- status = GetOptionalJwkList(
- dict_value, "key_ops", &jwk_key_ops_value, &has_jwk_key_ops);
- if (status.IsError())
- return status;
- blink::WebCryptoKeyUsageMask jwk_key_ops_mask = 0;
- if (has_jwk_key_ops) {
- status =
- GetWebCryptoUsagesFromJwkKeyOps(jwk_key_ops_value, &jwk_key_ops_mask);
- if (status.IsError())
- return status;
- // The input usage_mask must be a subset of jwk_key_ops_mask.
- if (!ContainsKeyUsages(jwk_key_ops_mask, usage_mask))
- return Status::ErrorJwkKeyopsInconsistent();
- }
-
// JWK "use" (optional) --> usage_mask parameter
std::string jwk_use_value;
bool has_jwk_use;
@@ -660,26 +467,29 @@
GetOptionalJwkString(dict_value, "use", &jwk_use_value, &has_jwk_use);
if (status.IsError())
return status;
- blink::WebCryptoKeyUsageMask jwk_use_mask = 0;
if (has_jwk_use) {
- if (jwk_use_value == "enc")
- jwk_use_mask = kJwkEncUsage;
- else if (jwk_use_value == "sig")
- jwk_use_mask = kJwkSigUsage;
- else
- return Status::ErrorJwkUnrecognizedUse();
- // The input usage_mask must be a subset of jwk_use_mask.
- if (!ContainsKeyUsages(jwk_use_mask, usage_mask))
- return Status::ErrorJwkUseInconsistent();
- }
-
- // If both 'key_ops' and 'use' are present, ensure they are consistent.
- if (has_jwk_key_ops && has_jwk_use &&
- !ContainsKeyUsages(jwk_use_mask, jwk_key_ops_mask))
- return Status::ErrorJwkUseAndKeyopsInconsistent();
+ blink::WebCryptoKeyUsageMask jwk_usage_mask = 0;
+ if (jwk_use_value == "enc") {
+ jwk_usage_mask =
+ blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt;
+ } else if (jwk_use_value == "sig") {
+ jwk_usage_mask =
+ blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify;
+ } else if (jwk_use_value == "wrap") {
+ jwk_usage_mask =
+ blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey;
+ } else {
+ return Status::ErrorJwkUnrecognizedUsage();
+ }
+ if ((jwk_usage_mask & usage_mask) != usage_mask) {
+ // A usage_mask must be a subset of jwk_usage_mask.
+ return Status::ErrorJwkUsageInconsistent();
+ }
+ }
// JWK keying material --> ImportKeyInternal()
if (jwk_kty_value == "oct") {
+
std::string jwk_k_value;
status = GetJwkBytes(dict_value, "k", &jwk_k_value);
if (status.IsError())
@@ -703,6 +513,7 @@
usage_mask,
key);
} else if (jwk_kty_value == "RSA") {
+
// An RSA public key must have an "n" (modulus) and an "e" (exponent) entry
// in the JWK, while an RSA private key must have those, plus at least a "d"
// (private exponent) entry.
@@ -738,35 +549,6 @@
return Status::Success();
}
-Status ExportKeyJwk(const blink::WebCryptoKey& key,
- blink::WebArrayBuffer* buffer) {
- base::DictionaryValue jwk_dict;
- Status status = Status::Error();
- blink::WebArrayBuffer exported_key;
-
- if (key.type() == blink::WebCryptoKeyTypeSecret) {
- status = ExportKey(blink::WebCryptoKeyFormatRaw, key, &exported_key);
- if (status.IsError())
- return status;
- WriteSecretKey(exported_key, &jwk_dict);
- } else {
- // TODO(padolph): Handle asymmetric keys, at least the public key.
- return Status::ErrorUnsupported();
- }
-
- WriteKeyOps(key.usages(), &jwk_dict);
- WriteExt(key.extractable(), &jwk_dict);
- status = WriteAlg(key.algorithm(), exported_key.byteLength(), &jwk_dict);
- if (status.IsError())
- return status;
-
- std::string json;
- base::JSONWriter::Write(&jwk_dict, &json);
- *buffer = CreateArrayBuffer(reinterpret_cast<const uint8*>(json.data()),
- json.size());
- return Status::Success();
-}
-
} // namespace webcrypto
} // namespace content
« no previous file with comments | « no previous file | content/child/webcrypto/shared_crypto.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698