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

Side by Side Diff: content/renderer/webcrypto/webcrypto_impl.cc

Issue 25906002: [webcrypto] Add JWK import for HMAC and AES-CBC key. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: re-upload Created 7 years, 2 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 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_impl.h" 5 #include "content/renderer/webcrypto/webcrypto_impl.h"
6 6
7 #include <algorithm>
8 #include <map>
9 #include "base/base64.h"
10 #include "base/json/json_reader.h"
11 #include "base/logging.h"
7 #include "base/memory/scoped_ptr.h" 12 #include "base/memory/scoped_ptr.h"
13 #include "base/strings/string_piece.h"
14 #include "base/values.h"
8 #include "third_party/WebKit/public/platform/WebArrayBuffer.h" 15 #include "third_party/WebKit/public/platform/WebArrayBuffer.h"
9 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" 16 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h"
17 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
10 #include "third_party/WebKit/public/platform/WebCryptoKey.h" 18 #include "third_party/WebKit/public/platform/WebCryptoKey.h"
11 19
12 namespace content { 20 namespace content {
13 21
22 namespace {
23
24 // FIXME! Need WebKit::WebCryptoAlgorithmIdNone
eroman 2013/10/22 21:49:38 There are other ways of accomplishing this that I
Ryan Sleevi 2013/10/24 01:45:58 There are other formats that may have embedded alg
eroman 2013/10/24 02:35:04 I will make the necessary changes to Blink side.
padolph 2013/10/28 20:35:07 This is addressed by your recent Blink checkin. Th
25 const WebKit::WebCryptoAlgorithmId WebCryptoAlgorithmIdNone =
26 (WebKit::WebCryptoAlgorithmId)99;
27
28 // TODO(padolph) Similar Create*Algorithm() methods are in
eroman 2013/10/22 21:49:38 What do you think about a renderer/webcrypto/webcr
padolph 2013/10/28 20:35:07 Done. Should the stuff in webcrypto_util.[h|cc] b
29 // webcrypto_impl_unittest.cc. Find a common place to put these.
30
31 WebKit::WebCryptoAlgorithm CreateAlgorithm(WebKit::WebCryptoAlgorithmId id) {
32 return WebKit::WebCryptoAlgorithm::adoptParamsAndCreate(id, NULL);
33 }
34
35 WebKit::WebCryptoAlgorithm CreateAlgorithmWithInnerHash(
36 WebKit::WebCryptoAlgorithmId algorithm_id,
37 unsigned short hash_key_length) {
38 WebKit::WebCryptoAlgorithmId hashId;
eroman 2013/10/22 21:49:38 use hacker_style_variable_naming for chromium code
padolph 2013/10/28 20:35:07 Done.
39 switch (hash_key_length) {
40 case 160:
41 hashId = WebKit::WebCryptoAlgorithmIdSha1;
42 break;
43 case 224:
44 hashId = WebKit::WebCryptoAlgorithmIdSha224;
45 break;
46 case 256:
47 hashId = WebKit::WebCryptoAlgorithmIdSha256;
48 break;
49 case 384:
50 hashId = WebKit::WebCryptoAlgorithmIdSha384;
51 break;
52 case 512:
53 hashId = WebKit::WebCryptoAlgorithmIdSha384;
54 break;
55 }
56 return WebKit::WebCryptoAlgorithm::adoptParamsAndCreate(
eroman 2013/10/22 21:49:38 Please add a default case to the switch above (per
padolph 2013/10/28 20:35:07 Done.
57 algorithm_id,
58 new WebKit::WebCryptoHmacParams(CreateAlgorithm(hashId)));
59 }
60
61 WebKit::WebCryptoAlgorithm CreateHmacAlgorithm(unsigned short hash_key_length) {
62 return CreateAlgorithmWithInnerHash(
63 WebKit::WebCryptoAlgorithmIdHmac,
64 hash_key_length);
65 }
66
67 WebKit::WebCryptoAlgorithm CreateRsaSsaAlgorithm(
68 unsigned short hash_key_length) {
69 return CreateAlgorithmWithInnerHash(
70 WebKit::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
71 hash_key_length);
72 }
73
74 WebKit::WebCryptoAlgorithm CreateRsaOaepAlgorithm(
75 unsigned short hash_key_length) {
76 return CreateAlgorithmWithInnerHash(
77 WebKit::WebCryptoAlgorithmIdRsaOaep,
78 hash_key_length);
79 }
80
81 WebKit::WebCryptoAlgorithm CreateAesAlgorithm(
82 WebKit::WebCryptoAlgorithmId aes_alg_id,
83 unsigned short length) {
84 return WebKit::WebCryptoAlgorithm::adoptParamsAndCreate(
85 aes_alg_id,
86 new WebKit::WebCryptoAesKeyGenParams(length));
87 }
88
89 WebKit::WebCryptoAlgorithm CreateAesCbcAlgorithm(unsigned short length) {
90 return CreateAesAlgorithm(WebKit::WebCryptoAlgorithmIdAesCbc, length);
91 }
92
93 WebKit::WebCryptoAlgorithm CreateAesGcmAlgorithm(unsigned short length) {
94 return CreateAesAlgorithm(WebKit::WebCryptoAlgorithmIdAesGcm, length);
95 }
96
97 bool Base64DecodeUrlSafe(const std::string& input, std::string* output) {
eroman 2013/10/22 21:49:38 Please provide a comment pointing to the definitio
padolph 2013/10/28 20:35:07 Will do. 'base64url' encoding is relatively common
98 std::string base64EncodedText(input);
99 std::replace(base64EncodedText.begin(), base64EncodedText.end(), '-', '+');
eroman 2013/10/22 21:49:38 Are these transformations enumerated int he JOSE s
padolph 2013/10/28 20:35:07 Yes, in RFC4648 Section 5.
100 std::replace(base64EncodedText.begin(), base64EncodedText.end(), '_', '/');
101 base64EncodedText.append((4 - base64EncodedText.size() % 4) % 4, '=');
102 return base::Base64Decode(base64EncodedText, output);
103 }
104
105 // Identifiers for all JWK "alg" (algorithm) values handled by this code. The
eroman 2013/10/22 21:49:38 There is enough JWK stuff, that I suggest moving t
padolph 2013/10/28 20:35:07 Most of this code went away with the function tabl
106 // "enum trick" is used to force int type, so a user type is not required in
eroman 2013/10/22 21:49:38 Not sure I know what the "enum trick" refers to. Y
padolph 2013/10/28 20:35:07 This code went away with the function table refact
107 // web_crypto_impl.h
108 enum {
109 kJwkAlgorithmHs256,
110 kJwkAlgorithmHs384,
111 kJwkAlgorithmHs512,
112 kJwkAlgorithmRs256,
113 kJwkAlgorithmRs384,
114 kJwkAlgorithmRs512,
115 kJwkAlgorithmRsa1_5,
116 kJwkAlgorithmRsaOaep,
117 kJwkAlgorithmA128Kw,
118 kJwkAlgorithmA256Kw,
119 kJwkAlgorithmA128Gcm,
120 kJwkAlgorithmA256Gcm,
121 kJwkAlgorithmA128Cbc,
122 kJwkAlgorithmA256Cbc,
123 kJwkAlgorithmA384Cbc,
124 kJwkAlgorithmA512Cbc
125 };
126
127 WebKit::WebCryptoAlgorithmId JwkAlgIdToWebCryptoAlgId(int jwk_algorithm_id) {
eroman 2013/10/22 21:49:38 This function appears to be unused
padolph 2013/10/28 20:35:07 Done.
128 switch (jwk_algorithm_id) {
129 case kJwkAlgorithmHs256:
130 case kJwkAlgorithmHs384:
131 case kJwkAlgorithmHs512:
132 return WebKit::WebCryptoAlgorithmIdHmac;
133 case kJwkAlgorithmRs256:
134 case kJwkAlgorithmRs384:
135 case kJwkAlgorithmRs512:
136 return WebKit::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5;
137 case kJwkAlgorithmRsa1_5:
138 return WebKit::WebCryptoAlgorithmIdRsaEsPkcs1v1_5;
139 case kJwkAlgorithmRsaOaep:
140 return WebKit::WebCryptoAlgorithmIdRsaOaep;
141 case kJwkAlgorithmA128Kw:
142 case kJwkAlgorithmA256Kw:
143 // TODO(padolph) Support AES keywrap algorithm, required for JWK but not
144 // present in the Web Crypto spec.
145 return WebCryptoAlgorithmIdNone;
146 case kJwkAlgorithmA128Gcm:
147 case kJwkAlgorithmA256Gcm:
148 return WebKit::WebCryptoAlgorithmIdAesGcm;
149 case kJwkAlgorithmA128Cbc:
150 case kJwkAlgorithmA256Cbc:
151 case kJwkAlgorithmA384Cbc:
152 case kJwkAlgorithmA512Cbc:
153 return WebKit::WebCryptoAlgorithmIdAesCbc;
154 default:
155 DCHECK(false);
156 return WebCryptoAlgorithmIdNone;
157 }
158 }
159
160 unsigned short JwkAlgIdToKeyLengthBits(int jwk_algorithm_id) {
161 switch (jwk_algorithm_id) {
162 case kJwkAlgorithmA128Kw:
163 case kJwkAlgorithmA128Gcm:
164 case kJwkAlgorithmA128Cbc:
165 return 128;
166 case kJwkAlgorithmHs256:
167 case kJwkAlgorithmA256Kw:
168 case kJwkAlgorithmRs256:
169 case kJwkAlgorithmA256Gcm:
170 case kJwkAlgorithmA256Cbc:
171 return 256;
172 case kJwkAlgorithmHs384:
173 case kJwkAlgorithmRs384:
174 case kJwkAlgorithmA384Cbc:
175 return 384;
176 case kJwkAlgorithmHs512:
177 case kJwkAlgorithmRs512:
178 case kJwkAlgorithmA512Cbc:
179 return 512;
180 default:
181 return 0;
182 }
183 }
184
185 WebKit::WebCryptoAlgorithm CreateWebCryptoAlgorithmFromJwkAlgorithmId(
eroman 2013/10/22 21:49:38 I think things would be more readable to have a si
padolph 2013/10/28 20:35:07 Done. But since the creation functions have differ
186 int jwk_algorithm_id) {
187 const unsigned short key_length_bits =
188 JwkAlgIdToKeyLengthBits(jwk_algorithm_id);
189 DCHECK(key_length_bits);
190 switch(jwk_algorithm_id) {
191 case kJwkAlgorithmHs256:
192 case kJwkAlgorithmHs384:
193 case kJwkAlgorithmHs512:
194 return CreateHmacAlgorithm(key_length_bits);
195 case kJwkAlgorithmRs256:
196 case kJwkAlgorithmRs384:
197 case kJwkAlgorithmRs512:
198 return CreateRsaSsaAlgorithm(key_length_bits);
199 case kJwkAlgorithmRsa1_5:
200 return CreateAlgorithm(WebKit::WebCryptoAlgorithmIdRsaEsPkcs1v1_5);
201 case kJwkAlgorithmRsaOaep:
202 return CreateRsaOaepAlgorithm(key_length_bits);
203 case kJwkAlgorithmA128Kw:
204 case kJwkAlgorithmA256Kw:
205 // TODO(padolph) Support AES keywrap algorithm, required for JWK but not
206 // present in the Web Crypto spec.
207 return CreateAlgorithm(WebCryptoAlgorithmIdNone);
208 case kJwkAlgorithmA128Gcm:
209 case kJwkAlgorithmA256Gcm:
210 return CreateAesGcmAlgorithm(key_length_bits);
211 case kJwkAlgorithmA128Cbc:
212 case kJwkAlgorithmA256Cbc:
213 case kJwkAlgorithmA384Cbc:
214 case kJwkAlgorithmA512Cbc:
215 return CreateAesCbcAlgorithm(key_length_bits);
216 default:
217 DCHECK(false);
eroman 2013/10/22 21:49:38 NOTREACHED()
padolph 2013/10/28 20:35:07 This code is now gone.
218 return CreateAlgorithm(WebCryptoAlgorithmIdNone);
219 }
220 }
221
222 typedef std::map<std::string, int> StringIntMap;
223
224 void InitJwkAlgorithmMap(StringIntMap& jwk_algorithm_map)
eroman 2013/10/22 21:49:38 Chromium style (unlike Blink style) does not like
padolph 2013/10/28 20:35:07 This code is now gone.
225 {
226 // Note: A*CBC are not yet present in the JOSE JWA spec
227 // http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-16
228 jwk_algorithm_map["HS256" ] = kJwkAlgorithmHs256;
eroman 2013/10/22 21:49:38 style nit: remove the space padding (i personally
padolph 2013/10/28 20:35:07 Done.
229 jwk_algorithm_map["HS384" ] = kJwkAlgorithmHs384;
230 jwk_algorithm_map["HS512" ] = kJwkAlgorithmHs512;
231 jwk_algorithm_map["RS256" ] = kJwkAlgorithmRs256;
232 jwk_algorithm_map["RS384" ] = kJwkAlgorithmRs384;
233 jwk_algorithm_map["RS512" ] = kJwkAlgorithmRs512;
234 jwk_algorithm_map["RSA1_5" ] = kJwkAlgorithmRsa1_5;
235 jwk_algorithm_map["RSA-OAEP"] = kJwkAlgorithmRsaOaep;
236 jwk_algorithm_map["A128KW" ] = kJwkAlgorithmA128Kw;
237 jwk_algorithm_map["A256KW" ] = kJwkAlgorithmA256Kw;
238 jwk_algorithm_map["A128GCM" ] = kJwkAlgorithmA128Gcm;
239 jwk_algorithm_map["A256GCM" ] = kJwkAlgorithmA256Gcm;
240 jwk_algorithm_map["A128CBC" ] = kJwkAlgorithmA128Cbc;
241 jwk_algorithm_map["A256CBC" ] = kJwkAlgorithmA256Cbc;
242 jwk_algorithm_map["A384CBC" ] = kJwkAlgorithmA384Cbc;
243 jwk_algorithm_map["A512CBC" ] = kJwkAlgorithmA512Cbc;
244 }
245
246 // forward
247 bool operator!=(const WebKit::WebCryptoAlgorithm& lhs,
248 const WebKit::WebCryptoAlgorithm& rhs);
249
250 // TODO(padolph) Verify this logic is sufficient to judge algorithm
251 // "consistency" for JWK import, and for all supported algorithms.
252 bool operator==(const WebKit::WebCryptoAlgorithm& lhs,
eroman 2013/10/22 21:49:38 Chromium style guide doesn't like operator overloa
Ryan Sleevi 2013/10/24 01:45:58 Should WebKit::WebCryptoAlgorithm have an Equals()
eroman 2013/10/24 02:35:04 It isn't obvious what equality means, so I think t
padolph 2013/10/28 20:35:07 Function name changed. But I am also very confused
253 const WebKit::WebCryptoAlgorithm& rhs) {
254 if (lhs.id() != rhs.id())
255 return false;
256 if (lhs.id() == WebKit::WebCryptoAlgorithmIdHmac ||
257 lhs.id() == WebKit::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 ||
258 lhs.id() == WebKit::WebCryptoAlgorithmIdRsaOaep) {
259 if (lhs.hmacParams()->hash() != rhs.hmacParams()->hash())
260 return false;
261 }
262 return true;
eroman 2013/10/22 21:49:38 For the sake of future proofing, I would rather ha
padolph 2013/10/28 20:35:07 Done.
263 }
264
265 bool operator!=(const WebKit::WebCryptoAlgorithm& lhs,
266 const WebKit::WebCryptoAlgorithm& rhs) {
267 return !(lhs == rhs);
268 }
269
270 } // namespace
271
14 WebCryptoImpl::WebCryptoImpl() { 272 WebCryptoImpl::WebCryptoImpl() {
15 Init(); 273 Init();
274 InitJwkAlgorithmMap(jwk_algorithm_map_);
eroman 2013/10/22 21:49:38 I would prefer lazy initialization, since JWK may
Ryan Sleevi 2013/10/24 01:45:58 Don't use a function-level static. They're forbidd
eroman 2013/10/24 02:35:04 My mistake! I got muddled with Blink style vs Chro
padolph 2013/10/28 20:35:07 LazyInstance used.
16 } 275 }
17 276
18 void WebCryptoImpl::encrypt( 277 void WebCryptoImpl::encrypt(
19 const WebKit::WebCryptoAlgorithm& algorithm, 278 const WebKit::WebCryptoAlgorithm& algorithm,
20 const WebKit::WebCryptoKey& key, 279 const WebKit::WebCryptoKey& key,
21 const unsigned char* data, 280 const unsigned char* data,
22 unsigned data_size, 281 unsigned data_size,
23 WebKit::WebCryptoResult result) { 282 WebKit::WebCryptoResult result) {
24 WebKit::WebArrayBuffer buffer; 283 WebKit::WebArrayBuffer buffer;
25 if (!EncryptInternal(algorithm, key, data, data_size, &buffer)) { 284 if (!EncryptInternal(algorithm, key, data, data_size, &buffer)) {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 WebKit::WebCryptoKeyFormat format, 336 WebKit::WebCryptoKeyFormat format,
78 const unsigned char* key_data, 337 const unsigned char* key_data,
79 unsigned key_data_size, 338 unsigned key_data_size,
80 const WebKit::WebCryptoAlgorithm& algorithm, 339 const WebKit::WebCryptoAlgorithm& algorithm,
81 bool extractable, 340 bool extractable,
82 WebKit::WebCryptoKeyUsageMask usage_mask, 341 WebKit::WebCryptoKeyUsageMask usage_mask,
83 WebKit::WebCryptoResult result) { 342 WebKit::WebCryptoResult result) {
84 WebKit::WebCryptoKeyType type; 343 WebKit::WebCryptoKeyType type;
85 scoped_ptr<WebKit::WebCryptoKeyHandle> handle; 344 scoped_ptr<WebKit::WebCryptoKeyHandle> handle;
86 345
87 if (!ImportKeyInternal(format, 346 if (format == WebKit::WebCryptoKeyFormatJwk) {
88 key_data, 347 if (!ImportKeyJwk(key_data,
89 key_data_size, 348 key_data_size,
90 algorithm, 349 extractable,
91 usage_mask, 350 algorithm,
92 &handle, 351 usage_mask,
93 &type)) { 352 &handle,
94 result.completeWithError(); 353 &type)) {
95 return; 354 result.completeWithError();
355 }
356 } else {
357 if (!ImportKeyInternal(format,
358 key_data,
359 key_data_size,
360 algorithm,
361 usage_mask,
362 &handle,
363 &type)) {
364 result.completeWithError();
365 }
96 } 366 }
97 367
98 WebKit::WebCryptoKey key( 368 WebKit::WebCryptoKey key(WebKit::WebCryptoKey::create(
99 WebKit::WebCryptoKey::create( 369 handle.release(), type, extractable, algorithm, usage_mask));
100 handle.release(), type, extractable, algorithm, usage_mask));
101 370
102 result.completeWithKey(key); 371 result.completeWithKey(key);
103 } 372 }
104 373
105 void WebCryptoImpl::sign( 374 void WebCryptoImpl::sign(
106 const WebKit::WebCryptoAlgorithm& algorithm, 375 const WebKit::WebCryptoAlgorithm& algorithm,
107 const WebKit::WebCryptoKey& key, 376 const WebKit::WebCryptoKey& key,
108 const unsigned char* data, 377 const unsigned char* data,
109 unsigned data_size, 378 unsigned data_size,
110 WebKit::WebCryptoResult result) { 379 WebKit::WebCryptoResult result) {
(...skipping 20 matching lines...) Expand all
131 signature_size, 400 signature_size,
132 data, 401 data,
133 data_size, 402 data_size,
134 &signature_match)) { 403 &signature_match)) {
135 result.completeWithError(); 404 result.completeWithError();
136 } else { 405 } else {
137 result.completeWithBoolean(signature_match); 406 result.completeWithBoolean(signature_match);
138 } 407 }
139 } 408 }
140 409
410 bool WebCryptoImpl::ImportKeyJwk(
411 const unsigned char* key_data,
412 unsigned key_data_size,
413 bool extractable,
414 const WebKit::WebCryptoAlgorithm& algorithm,
415 WebKit::WebCryptoKeyUsageMask usage_mask,
416 scoped_ptr<WebKit::WebCryptoKeyHandle>* handle,
417 WebKit::WebCryptoKeyType* type) {
418
419 // JSON Web Key Format (JWK)
eroman 2013/10/22 21:49:38 This is a good comment block, thanks!
420 // http://tools.ietf.org/html/draft-ietf-jose-json-web-key-16
421 // TODO(padolph) Not all possible values are handled by this code right now
422 //
423 // A JWK is a simple JSON dictionary with the following entries
424 // - "kty" (Key Type) Parameter, REQUIRED
425 // - <kty-specific parameters, see below>, REQUIRED
426 // - "use" (Key Use) Parameter, OPTIONAL
427 // - "alg" (Algorithm) Parameter, OPTIONAL
428 // - "extractable" (Key Exportability), OPTIONAL [NOTE: not yet part of JOSE]
429 // (all other entries are ignored)
430 //
431 // Input key_data contains the JWK. To build a Web Crypto Key, the JWK values
432 // are parsed out and used as follows:
433 // Web Crypto Key type <-- (deduced)
434 // Web Crypto Key extractable <-- extractable
435 // Web Crypto Key algorithm <-- alg
436 // Web Crypto Key keyUsage <-- usage
437 // Web Crypto Key keying material <-- kty-specific parameters
438 //
439 // Values for each entry are case-sensitive and defined in
440 // http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-16.
441 // Note that not all values specified by JOSE are handled by this code. Only
442 // handled values are listed.
443 // - kty (Key Type)
444 // +-------+--------------------------------------------------------------+
445 // | "RSA" | RSA [RFC3447] |
446 // | "oct" | Octet sequence (used to represent symmetric keys) |
447 // +-------+--------------------------------------------------------------+
448 // - use (Key Use)
449 // +-------+--------------------------------------------------------------+
450 // | "enc" | encrypt and decrypt operations |
451 // | "sig" | sign and verify (MAC) operations |
452 // | "wrap"| key wrap and unwrap [not yet part of JOSE] |
453 // +-------+--------------------------------------------------------------+
454 // - extractable (Key Exportability)
455 // +-------+--------------------------------------------------------------+
456 // | true | Key may be exported from the trusted environment |
457 // | false | Key cannot exit the trusted environment |
458 // +-------+--------------------------------------------------------------+
459 // - alg (Algorithm)
460 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-16
461 // +--------------+-------------------------------------------------------+
462 // | Digital Signature or MAC Algorithm |
463 // +--------------+-------------------------------------------------------+
464 // | "HS256" | HMAC using SHA-256 hash algorithm |
465 // | "HS384" | HMAC using SHA-384 hash algorithm |
466 // | "HS512" | HMAC using SHA-512 hash algorithm |
467 // | "RS256" | RSASSA using SHA-256 hash algorithm |
468 // | "RS384" | RSASSA using SHA-384 hash algorithm |
469 // | "RS512" | RSASSA using SHA-512 hash algorithm |
470 // +--------------+-------------------------------------------------------|
471 // | Key Management Algorithm |
472 // +--------------+-------------------------------------------------------+
473 // | "RSA1_5" | RSAES-PKCS1-V1_5 [RFC3447] |
474 // | "RSA-OAEP" | RSAES using Optimal Asymmetric Encryption Padding |
475 // | | (OAEP) [RFC3447], with the default parameters |
476 // | | specified by RFC3447 in Section A.2.1 |
477 // | "A128KW" | Advanced Encryption Standard (AES) Key Wrap Algorithm |
478 // | | [RFC3394] using 128 bit keys |
479 // | "A256KW" | AES Key Wrap Algorithm using 256 bit keys |
480 // | "A128GCM" | AES in Galois/Counter Mode (GCM) [NIST.800-38D] using |
481 // | | 128 bit keys |
482 // | "A256GCM" | AES GCM using 256 bit keys |
483 // | "A128CBC" | AES in Cipher Block Chaining Mode (CBC) with PKCS #5 |
484 // | | padding [NIST.800-38A] [not yet part of JOSE] |
485 // | "A256CBC" | AES CBC using 256 bit keys [not yet part of JOSE] |
486 // | "A384CBC" | AES CBC using 384 bit keys [not yet part of JOSE] |
487 // | "A512CBC" | AES CBC using 512 bit keys [not yet part of JOSE] |
488 // +--------------+-------------------------------------------------------+
489 //
490 // kty-specific parameters
491 // The value of kty determines the type and content of the keying material
492 // carried in the JWK to be imported. Currently only two possibilities are
493 // supported: a raw key or an RSA public key. RSA private keys are not
494 // supported because typical applications seldom need to import a private key,
495 // and the large number of JWK parameters required to describe one.
496 // - kty == "oct" (symmetric or other raw key)
497 // +-------+--------------------------------------------------------------+
498 // | "k" | Contains the value of the symmetric (or other single-valued) |
499 // | | key. It is represented as the base64url encoding of the |
500 // | | octet sequence containing the key value. |
501 // +-------+--------------------------------------------------------------+
502 // - kty == "RSA" (RSA public key)
503 // +-------+--------------------------------------------------------------+
504 // | "n" | Contains the modulus value for the RSA public key. It is |
505 // | | represented as the base64url encoding of the value's |
506 // | | unsigned big endian representation as an octet sequence. |
507 // +-------+--------------------------------------------------------------+
508 // | "e" | Contains the exponent value for the RSA public key. It is |
509 // | | represented as the base64url encoding of the value's |
510 // | | unsigned big endian representation as an octet sequence. |
511 // +-------+--------------------------------------------------------------+
512 //
513 // Conflict resolution
514 // The type, algorithm, extractable, and usage_mask input parameters may be
515 // different from similar values inside the JWK. The Web Crypto spec says that
516 // if a JWK value is present, but is inconsistent with the input value, it is
517 // an error and the operation must fail.
518
519 const char* const foo = reinterpret_cast<const char *>(key_data);
eroman 2013/10/22 21:49:38 Please use a variable name other than "foo".
padolph 2013/10/28 20:35:07 Done.
520 base::StringPiece json_string(foo, key_data_size);
521 scoped_ptr<base::Value> value(base::JSONReader::Read(json_string));
522 // Note, bare pointer dict_value is ok since it points into scoped value.
523 base::DictionaryValue* dict_value = NULL;
524 if (!value.get() || !value->GetAsDictionary(&dict_value) || !dict_value)
525 return false;
526
527 // JWK "kty". Exit early if this required JWK parameter is missing.
528 std::string jwk_kty_value;
529 if (!dict_value->GetString("kty", &jwk_kty_value))
530 return false;
531
532 // JWK "extractable" --> extractable parameter
533 bool jwk_extractable_value;
534 if (dict_value->GetBoolean("extractable", &jwk_extractable_value)) {
535 // collision check
536 if (jwk_extractable_value != extractable)
537 return false;
538 }
539
540 // JWK "alg" --> algorithm parameter
541 std::string jwk_alg_value;
542 if (dict_value->GetString("alg", &jwk_alg_value)) {
543 const StringIntMap::iterator pos = jwk_algorithm_map_.find(jwk_alg_value);
eroman 2013/10/22 21:49:38 const_iterator?
padolph 2013/10/28 20:35:07 Done.
544 if (pos == jwk_algorithm_map_.end())
545 return false;
546 const int jwk_algorithm_id = pos->second;
547 WebKit::WebCryptoAlgorithm webcrypto_algorithm_from_jwk =
548 CreateWebCryptoAlgorithmFromJwkAlgorithmId(jwk_algorithm_id);
549 // collision check
550 if (webcrypto_algorithm_from_jwk != algorithm)
551 return false;
552 }
553
554 // JWK "use" --> usage_mask parameter
555 std::string jwk_use_value;
556 if (dict_value->GetString("use", &jwk_use_value)) {
557 unsigned jwk_usage_mask;
558 if (jwk_use_value == "enc") {
559 jwk_usage_mask =
560 WebKit::WebCryptoKeyUsageEncrypt | WebKit::WebCryptoKeyUsageDecrypt;
561 } else if (jwk_use_value == "sig") {
562 jwk_usage_mask =
563 WebKit::WebCryptoKeyUsageSign | WebKit::WebCryptoKeyUsageVerify;
564 } else if (jwk_use_value == "wrap") {
565 jwk_usage_mask =
566 WebKit::WebCryptoKeyUsageWrapKey | WebKit::WebCryptoKeyUsageUnwrapKey;
567 } else {
568 return false;
569 }
570 // collision check
571 if (!(jwk_usage_mask & usage_mask))
eroman 2013/10/22 21:49:38 Do they need to match exactly?
Ryan Sleevi 2013/10/24 01:45:58 No. The spec merely says that if they conflict in
eroman 2013/10/24 02:35:04 Thanks Ryan! My understanding then is that we wan
padolph 2013/10/28 20:35:07 Yea, after thinking about it more, subset makes mo
572 return false;
573 }
574
575 // JWK keying material --> ImportKeyInternal()
576 if (jwk_kty_value == "oct") {
577 // collision check
578 if (*type != WebKit::WebCryptoKeyTypeSecret)
579 return false;
580 std::string jwk_k_value_url64;
581 if (!dict_value->GetString("k", &jwk_k_value_url64))
582 return false;
583 std::string jwk_k_value;
584 if (!Base64DecodeUrlSafe(jwk_k_value_url64, &jwk_k_value))
585 return false;
586 const std::vector<uint8> data(jwk_k_value.begin(), jwk_k_value.end());
eroman 2013/10/22 21:49:38 Rather than copying into a std::vector<>, I believ
padolph 2013/10/28 20:35:07 Done.
587 if (!ImportKeyInternal(WebKit::WebCryptoKeyFormatRaw,
588 &data[0],
eroman 2013/10/22 21:49:38 Is data guaranteed to have at least 1 element?
padolph 2013/10/28 20:35:07 No. I added a check for that plus a unit test. Tha
589 data.size(),
590 algorithm,
591 usage_mask,
592 handle,
593 type)) {
594 return false;
595 }
596 } else if (jwk_kty_value == "RSA") {
597 // Only an RSA public key is currently handled.
598 // collision check
599 if (*type != WebKit::WebCryptoKeyTypePublic)
600 return false;
601 // TODO(padolph): JWK import RSA public key
602 return false;
603 } else {
604 return false;
605 }
606
607 return true;
608 }
609
141 } // namespace content 610 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/webcrypto/webcrypto_impl.h ('k') | content/renderer/webcrypto/webcrypto_impl_openssl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698