blob: 15623285012b64f919da0a125255282d81d249e6 [file] [log] [blame]
eroman5a6f5022016-02-29 11:04:001// Copyright 2016 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "components/webcrypto/fuzzer_support.h"
6
7#include "base/command_line.h"
8#include "base/lazy_instance.h"
kulshin776109842016-07-14 01:08:169#include "base/numerics/safe_conversions.h"
Alex Clarke636e7052019-05-30 10:49:3710#include "base/task/single_thread_task_executor.h"
eroman5a6f5022016-02-29 11:04:0011#include "components/webcrypto/algorithm_dispatch.h"
12#include "components/webcrypto/crypto_data.h"
13#include "components/webcrypto/status.h"
Ken Rockot9b26bc52018-07-04 19:57:4914#include "mojo/core/embedder/embedder.h"
Blink Reformata30d4232018-04-07 15:31:0615#include "third_party/blink/public/platform/platform.h"
16#include "third_party/blink/public/platform/web_crypto_algorithm_params.h"
17#include "third_party/blink/public/web/blink.h"
eroman5a6f5022016-02-29 11:04:0018
19namespace webcrypto {
20
21namespace {
22
23// This mock is used to initialize blink.
Nico Weber43ddd7a32017-08-15 19:19:2724class InitOnce : public blink::Platform {
eroman5a6f5022016-02-29 11:04:0025 public:
26 InitOnce() {
eroman5a6f5022016-02-29 11:04:0027 base::CommandLine::Init(0, nullptr);
Ken Rockot9b26bc52018-07-04 19:57:4928 mojo::core::Init();
Eric Romana73a1682018-08-09 03:28:2229 blink::Platform::CreateMainThreadAndInitialize(this);
eroman5a6f5022016-02-29 11:04:0030 }
jam7ffe5e2e2016-08-12 01:05:0131 ~InitOnce() override {}
Eric Roman9457c5e2017-09-12 21:53:1632
33 private:
Alex Clarke636e7052019-05-30 10:49:3734 base::SingleThreadTaskExecutor main_thread_task_executor_;
eroman5a6f5022016-02-29 11:04:0035};
36
37base::LazyInstance<InitOnce>::Leaky g_once = LAZY_INSTANCE_INITIALIZER;
38
39void EnsureInitialized() {
40 g_once.Get();
41}
42
43blink::WebCryptoAlgorithm CreateRsaHashedImportAlgorithm(
44 blink::WebCryptoAlgorithmId id,
45 blink::WebCryptoAlgorithmId hash_id) {
Blink Reformat1c4d759e2017-04-09 16:34:5446 DCHECK(blink::WebCryptoAlgorithm::IsHash(hash_id));
47 return blink::WebCryptoAlgorithm::AdoptParamsAndCreate(
eroman5a6f5022016-02-29 11:04:0048 id,
49 new blink::WebCryptoRsaHashedImportParams(
Blink Reformat1c4d759e2017-04-09 16:34:5450 blink::WebCryptoAlgorithm::AdoptParamsAndCreate(hash_id, nullptr)));
eroman5a6f5022016-02-29 11:04:0051}
52
53blink::WebCryptoAlgorithm CreateEcImportAlgorithm(
54 blink::WebCryptoAlgorithmId id,
55 blink::WebCryptoNamedCurve named_curve) {
Blink Reformat1c4d759e2017-04-09 16:34:5456 return blink::WebCryptoAlgorithm::AdoptParamsAndCreate(
eroman5a6f5022016-02-29 11:04:0057 id, new blink::WebCryptoEcKeyImportParams(named_curve));
58}
59
60} // namespace
61
62blink::WebCryptoKeyUsageMask GetCompatibleKeyUsages(
63 blink::WebCryptoKeyFormat format) {
64 // SPKI format implies import of a public key, whereas PKCS8 implies import
65 // of a private key. Pick usages that are compatible with a signature
66 // algorithm.
Blink Reformat1c4d759e2017-04-09 16:34:5467 return format == blink::kWebCryptoKeyFormatSpki
68 ? blink::kWebCryptoKeyUsageVerify
69 : blink::kWebCryptoKeyUsageSign;
eroman5a6f5022016-02-29 11:04:0070}
71
72void ImportEcKeyFromDerFuzzData(const uint8_t* data,
73 size_t size,
74 blink::WebCryptoKeyFormat format) {
Blink Reformat1c4d759e2017-04-09 16:34:5475 DCHECK(format == blink::kWebCryptoKeyFormatSpki ||
76 format == blink::kWebCryptoKeyFormatPkcs8);
eroman5a6f5022016-02-29 11:04:0077 EnsureInitialized();
78
79 // There are 3 possible EC named curves. Fix this parameter. It shouldn't
80 // matter based on the current implementation for PKCS8 or SPKI. But it
81 // will have an impact when parsing JWK format.
Blink Reformat1c4d759e2017-04-09 16:34:5482 blink::WebCryptoNamedCurve curve = blink::kWebCryptoNamedCurveP384;
eroman5a6f5022016-02-29 11:04:0083
84 // Always use ECDSA as the algorithm. Shouldn't make much difference for
85 // non-JWK formats.
Blink Reformat1c4d759e2017-04-09 16:34:5486 blink::WebCryptoAlgorithmId algorithm_id = blink::kWebCryptoAlgorithmIdEcdsa;
eroman5a6f5022016-02-29 11:04:0087
88 // Use key usages that are compatible with the chosen algorithm and key type.
89 blink::WebCryptoKeyUsageMask usages = GetCompatibleKeyUsages(format);
90
91 blink::WebCryptoKey key;
92 webcrypto::Status status = webcrypto::ImportKey(
kulshin776109842016-07-14 01:08:1693 format, webcrypto::CryptoData(data, base::checked_cast<uint32_t>(size)),
eroman5a6f5022016-02-29 11:04:0094 CreateEcImportAlgorithm(algorithm_id, curve), true, usages, &key);
95
96 // These errors imply a bad setup of parameters, and means ImportKey() may not
97 // be testing the actual parsing.
98 DCHECK_NE(status.error_details(),
99 Status::ErrorUnsupportedImportKeyFormat().error_details());
100 DCHECK_NE(status.error_details(),
101 Status::ErrorCreateKeyBadUsages().error_details());
102}
103
eromancfcb6c92016-08-12 00:33:46104void ImportEcKeyFromRawFuzzData(const uint8_t* data, size_t size) {
105 EnsureInitialized();
106
107 // There are 3 possible EC named curves. Consume the first byte to decide on
108 // the curve.
109 uint8_t curve_index = 0;
110 if (size > 0) {
111 curve_index = data[0];
112 data++;
113 size--;
114 }
115
116 blink::WebCryptoNamedCurve curve;
117
118 switch (curve_index % 3) {
119 case 0:
Blink Reformat1c4d759e2017-04-09 16:34:54120 curve = blink::kWebCryptoNamedCurveP256;
eromancfcb6c92016-08-12 00:33:46121 break;
122 case 1:
Blink Reformat1c4d759e2017-04-09 16:34:54123 curve = blink::kWebCryptoNamedCurveP384;
eromancfcb6c92016-08-12 00:33:46124 break;
125 default:
Blink Reformat1c4d759e2017-04-09 16:34:54126 curve = blink::kWebCryptoNamedCurveP521;
eromancfcb6c92016-08-12 00:33:46127 break;
128 }
129
130 // Always use ECDSA as the algorithm. Shouldn't make an difference for import.
Blink Reformat1c4d759e2017-04-09 16:34:54131 blink::WebCryptoAlgorithmId algorithm_id = blink::kWebCryptoAlgorithmIdEcdsa;
eromancfcb6c92016-08-12 00:33:46132
133 // Use key usages that are compatible with the chosen algorithm and key type.
Blink Reformat1c4d759e2017-04-09 16:34:54134 blink::WebCryptoKeyUsageMask usages = blink::kWebCryptoKeyUsageVerify;
eromancfcb6c92016-08-12 00:33:46135
136 blink::WebCryptoKey key;
137 webcrypto::Status status = webcrypto::ImportKey(
Blink Reformat1c4d759e2017-04-09 16:34:54138 blink::kWebCryptoKeyFormatRaw,
eromancfcb6c92016-08-12 00:33:46139 webcrypto::CryptoData(data, base::checked_cast<uint32_t>(size)),
140 CreateEcImportAlgorithm(algorithm_id, curve), true, usages, &key);
141
142 // These errors imply a bad setup of parameters, and means ImportKey() may not
143 // be testing the actual parsing.
144 DCHECK_NE(status.error_details(),
145 Status::ErrorUnsupportedImportKeyFormat().error_details());
146 DCHECK_NE(status.error_details(),
147 Status::ErrorCreateKeyBadUsages().error_details());
148}
149
eroman5a6f5022016-02-29 11:04:00150void ImportRsaKeyFromDerFuzzData(const uint8_t* data,
151 size_t size,
152 blink::WebCryptoKeyFormat format) {
Blink Reformat1c4d759e2017-04-09 16:34:54153 DCHECK(format == blink::kWebCryptoKeyFormatSpki ||
154 format == blink::kWebCryptoKeyFormatPkcs8);
eroman5a6f5022016-02-29 11:04:00155 EnsureInitialized();
156
157 // There are several possible hash functions. Fix this parameter. It shouldn't
158 // matter based on the current implementation for PKCS8 or SPKI. But it
159 // will have an impact when parsing JWK format.
Blink Reformat1c4d759e2017-04-09 16:34:54160 blink::WebCryptoAlgorithmId hash_id = blink::kWebCryptoAlgorithmIdSha256;
eroman5a6f5022016-02-29 11:04:00161
162 // Always use RSA-SSA PKCS#1 as the algorithm. Shouldn't make much difference
163 // for non-JWK formats.
164 blink::WebCryptoAlgorithmId algorithm_id =
Blink Reformat1c4d759e2017-04-09 16:34:54165 blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5;
eroman5a6f5022016-02-29 11:04:00166
167 // Use key usages that are compatible with the chosen algorithm and key type.
168 blink::WebCryptoKeyUsageMask usages = GetCompatibleKeyUsages(format);
169
170 blink::WebCryptoKey key;
171 webcrypto::Status status = webcrypto::ImportKey(
kulshin776109842016-07-14 01:08:16172 format, webcrypto::CryptoData(data, base::checked_cast<uint32_t>(size)),
eroman5a6f5022016-02-29 11:04:00173 CreateRsaHashedImportAlgorithm(algorithm_id, hash_id), true, usages,
174 &key);
175
176 // These errors imply a bad setup of parameters, and means ImportKey() may not
177 // be testing the actual parsing.
178 DCHECK_NE(status.error_details(),
179 Status::ErrorUnsupportedImportKeyFormat().error_details());
180 DCHECK_NE(status.error_details(),
181 Status::ErrorCreateKeyBadUsages().error_details());
182}
183
184} // namespace webcrypto