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

Side by Side Diff: components/webcrypto/algorithm_dispatch.cc

Issue 2163053002: [webcrypto] Check for empty key usages *after* key creation rather than before, to match the spec's… (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 4 years, 4 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
« no previous file with comments | « no previous file | components/webcrypto/algorithm_implementation.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "components/webcrypto/algorithm_dispatch.h" 5 #include "components/webcrypto/algorithm_dispatch.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "components/webcrypto/algorithm_implementation.h" 8 #include "components/webcrypto/algorithm_implementation.h"
9 #include "components/webcrypto/algorithm_implementations.h" 9 #include "components/webcrypto/algorithm_implementations.h"
10 #include "components/webcrypto/algorithm_registry.h" 10 #include "components/webcrypto/algorithm_registry.h"
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 GenerateKeyResult* result) { 96 GenerateKeyResult* result) {
97 const AlgorithmImplementation* impl = NULL; 97 const AlgorithmImplementation* impl = NULL;
98 Status status = GetAlgorithmImplementation(algorithm.id(), &impl); 98 Status status = GetAlgorithmImplementation(algorithm.id(), &impl);
99 if (status.IsError()) 99 if (status.IsError())
100 return status; 100 return status;
101 101
102 status = impl->GenerateKey(algorithm, extractable, usages, result); 102 status = impl->GenerateKey(algorithm, extractable, usages, result);
103 if (status.IsError()) 103 if (status.IsError())
104 return status; 104 return status;
105 105
106 // The Web Crypto spec says to reject secret and private keys generated with
107 // empty usages:
108 //
109 // https://w3c.github.io/webcrypto/Overview.html#dfn-SubtleCrypto-method-gener ateKey
110 //
111 // (14.3.6.8):
112 // If result is a CryptoKey object:
113 // If the [[type]] internal slot of result is "secret" or "private"
114 // and usages is empty, then throw a SyntaxError.
115 //
116 // (14.3.6.9)
117 // If result is a CryptoKeyPair object:
118 // If the [[usages]] internal slot of the privateKey attribute of
119 // result is the empty sequence, then throw a SyntaxError.
106 const blink::WebCryptoKey* key = NULL; 120 const blink::WebCryptoKey* key = NULL;
107 if (result->type() == GenerateKeyResult::TYPE_SECRET_KEY) 121 if (result->type() == GenerateKeyResult::TYPE_SECRET_KEY)
108 key = &result->secret_key(); 122 key = &result->secret_key();
109 if (result->type() == GenerateKeyResult::TYPE_PUBLIC_PRIVATE_KEY_PAIR) 123 if (result->type() == GenerateKeyResult::TYPE_PUBLIC_PRIVATE_KEY_PAIR)
110 key = &result->private_key(); 124 key = &result->private_key();
111 if (key == NULL) 125 if (key == NULL)
112 return Status::ErrorUnexpected(); 126 return Status::ErrorUnexpected();
113 127
114 // This should only fail if an algorithm is implemented incorrectly and
115 // does not do its own check of the usages.
116 if (key->usages() == 0) { 128 if (key->usages() == 0) {
117 DCHECK(false) << "Key usages for generateKey() must not be empty";
118 return Status::ErrorCreateKeyEmptyUsages(); 129 return Status::ErrorCreateKeyEmptyUsages();
119 } 130 }
120 return status; 131
132 return Status::Success();
121 } 133 }
122 134
123 Status ImportKey(blink::WebCryptoKeyFormat format, 135 Status ImportKey(blink::WebCryptoKeyFormat format,
124 const CryptoData& key_data, 136 const CryptoData& key_data,
125 const blink::WebCryptoAlgorithm& algorithm, 137 const blink::WebCryptoAlgorithm& algorithm,
126 bool extractable, 138 bool extractable,
127 blink::WebCryptoKeyUsageMask usages, 139 blink::WebCryptoKeyUsageMask usages,
128 blink::WebCryptoKey* key) { 140 blink::WebCryptoKey* key) {
129 const AlgorithmImplementation* impl = NULL; 141 const AlgorithmImplementation* impl = NULL;
130 Status status = GetAlgorithmImplementation(algorithm.id(), &impl); 142 Status status = GetAlgorithmImplementation(algorithm.id(), &impl);
131 if (status.IsError()) 143 if (status.IsError())
132 return status; 144 return status;
133 145
134 status = impl->VerifyKeyUsagesBeforeImportKey(format, usages); 146 status =
147 impl->ImportKey(format, key_data, algorithm, extractable, usages, key);
135 if (status.IsError()) 148 if (status.IsError())
136 return status; 149 return status;
137 150
138 return impl->ImportKey(format, key_data, algorithm, extractable, usages, key); 151 // The Web Crypto spec says to reject secret and private keys imported with
152 // empty usages:
153 //
154 // https://w3c.github.io/webcrypto/Overview.html#dfn-SubtleCrypto-method-impor tKey
155 //
156 // 14.3.9.9: If the [[type]] internal slot of result is "secret" or "private"
157 // and usages is empty, then throw a SyntaxError.
158 if (key->usages() == 0 && (key->type() == blink::WebCryptoKeyTypeSecret ||
159 key->type() == blink::WebCryptoKeyTypePrivate)) {
160 return Status::ErrorCreateKeyEmptyUsages();
161 }
162
163 return Status::Success();
139 } 164 }
140 165
141 Status ExportKey(blink::WebCryptoKeyFormat format, 166 Status ExportKey(blink::WebCryptoKeyFormat format,
142 const blink::WebCryptoKey& key, 167 const blink::WebCryptoKey& key,
143 std::vector<uint8_t>* buffer) { 168 std::vector<uint8_t>* buffer) {
144 if (!key.extractable()) 169 if (!key.extractable())
145 return Status::ErrorKeyNotExtractable(); 170 return Status::ErrorKeyNotExtractable();
146 return ExportKeyDontCheckExtractability(format, key, buffer); 171 return ExportKeyDontCheckExtractability(format, key, buffer);
147 } 172 }
148 173
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
203 const blink::WebCryptoAlgorithm& wrapping_algorithm, 228 const blink::WebCryptoAlgorithm& wrapping_algorithm,
204 const blink::WebCryptoAlgorithm& algorithm, 229 const blink::WebCryptoAlgorithm& algorithm,
205 bool extractable, 230 bool extractable,
206 blink::WebCryptoKeyUsageMask usages, 231 blink::WebCryptoKeyUsageMask usages,
207 blink::WebCryptoKey* key) { 232 blink::WebCryptoKey* key) {
208 if (!wrapping_key.keyUsageAllows(blink::WebCryptoKeyUsageUnwrapKey)) 233 if (!wrapping_key.keyUsageAllows(blink::WebCryptoKeyUsageUnwrapKey))
209 return Status::ErrorUnexpected(); 234 return Status::ErrorUnexpected();
210 if (wrapping_algorithm.id() != wrapping_key.algorithm().id()) 235 if (wrapping_algorithm.id() != wrapping_key.algorithm().id())
211 return Status::ErrorUnexpected(); 236 return Status::ErrorUnexpected();
212 237
213 // Fail fast if the import is doomed to fail. 238 std::vector<uint8_t> buffer;
214 const AlgorithmImplementation* import_impl = NULL; 239 Status status = DecryptDontCheckKeyUsage(wrapping_algorithm, wrapping_key,
215 Status status = GetAlgorithmImplementation(algorithm.id(), &import_impl); 240 wrapped_key_data, &buffer);
216 if (status.IsError()) 241 if (status.IsError())
217 return status; 242 return status;
218 243
219 status = import_impl->VerifyKeyUsagesBeforeImportKey(format, usages);
220 if (status.IsError())
221 return status;
222
223 std::vector<uint8_t> buffer;
224 status = DecryptDontCheckKeyUsage(wrapping_algorithm, wrapping_key,
225 wrapped_key_data, &buffer);
226 if (status.IsError())
227 return status;
228
229 // NOTE that returning the details of ImportKey() failures may leak 244 // NOTE that returning the details of ImportKey() failures may leak
230 // information about the plaintext of the encrypted key (for instance the JWK 245 // information about the plaintext of the encrypted key (for instance the JWK
231 // key_ops). As long as the ImportKey error messages don't describe actual 246 // key_ops). As long as the ImportKey error messages don't describe actual
232 // key bytes however this should be OK. For more discussion see 247 // key bytes however this should be OK. For more discussion see
233 // http://crbug.com/372040 248 // http://crbug.com/372040
234 return ImportKey(format, CryptoData(buffer), algorithm, extractable, usages, 249 return ImportKey(format, CryptoData(buffer), algorithm, extractable, usages,
235 key); 250 key);
236 } 251 }
237 252
238 Status DeriveBits(const blink::WebCryptoAlgorithm& algorithm, 253 Status DeriveBits(const blink::WebCryptoAlgorithm& algorithm,
(...skipping 30 matching lines...) Expand all
269 284
270 if (import_algorithm.id() != key_length_algorithm.id()) 285 if (import_algorithm.id() != key_length_algorithm.id())
271 return Status::ErrorUnexpected(); 286 return Status::ErrorUnexpected();
272 287
273 const AlgorithmImplementation* import_impl = NULL; 288 const AlgorithmImplementation* import_impl = NULL;
274 Status status = 289 Status status =
275 GetAlgorithmImplementation(import_algorithm.id(), &import_impl); 290 GetAlgorithmImplementation(import_algorithm.id(), &import_impl);
276 if (status.IsError()) 291 if (status.IsError())
277 return status; 292 return status;
278 293
279 // Fail fast if the requested key usages are incorect.
280 status = import_impl->VerifyKeyUsagesBeforeImportKey(
281 blink::WebCryptoKeyFormatRaw, usages);
282 if (status.IsError())
283 return status;
284
285 // Determine how many bits long the derived key should be. 294 // Determine how many bits long the derived key should be.
286 unsigned int length_bits = 0; 295 unsigned int length_bits = 0;
287 bool has_length_bits = false; 296 bool has_length_bits = false;
288 status = import_impl->GetKeyLength(key_length_algorithm, &has_length_bits, 297 status = import_impl->GetKeyLength(key_length_algorithm, &has_length_bits,
289 &length_bits); 298 &length_bits);
290 if (status.IsError()) 299 if (status.IsError())
291 return status; 300 return status;
292 301
293 // Derive the key bytes. 302 // Derive the key bytes.
294 const AlgorithmImplementation* derive_impl = NULL; 303 const AlgorithmImplementation* derive_impl = NULL;
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 Status status = GetAlgorithmImplementation(algorithm.id(), &impl); 343 Status status = GetAlgorithmImplementation(algorithm.id(), &impl);
335 if (status.IsError()) 344 if (status.IsError())
336 return false; 345 return false;
337 346
338 status = impl->DeserializeKeyForClone(algorithm, type, extractable, usages, 347 status = impl->DeserializeKeyForClone(algorithm, type, extractable, usages,
339 key_data, key); 348 key_data, key);
340 return status.IsSuccess(); 349 return status.IsSuccess();
341 } 350 }
342 351
343 } // namespace webcrypto 352 } // namespace webcrypto
OLDNEW
« no previous file with comments | « no previous file | components/webcrypto/algorithm_implementation.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698