blob: f6709333cf4b807a3353e0ef39d2cd9db5d8ce52 [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"
eroman5a6f5022016-02-29 11:04:0010#include "components/webcrypto/algorithm_dispatch.h"
11#include "components/webcrypto/crypto_data.h"
12#include "components/webcrypto/status.h"
jam7ffe5e2e2016-08-12 01:05:0113#include "third_party/WebKit/public/platform/Platform.h"
eroman5a6f5022016-02-29 11:04:0014#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
jam7ffe5e2e2016-08-12 01:05:0115#include "third_party/WebKit/public/web/WebKit.h"
eroman5a6f5022016-02-29 11:04:0016
17namespace webcrypto {
18
19namespace {
20
21// This mock is used to initialize blink.
Nico Weber43ddd7a32017-08-15 19:19:2722class InitOnce : public blink::Platform {
eroman5a6f5022016-02-29 11:04:0023 public:
24 InitOnce() {
eroman5a6f5022016-02-29 11:04:0025 base::CommandLine::Init(0, nullptr);
Blink Reformat1c4d759e2017-04-09 16:34:5426 blink::Platform::Initialize(this);
eroman5a6f5022016-02-29 11:04:0027 }
jam7ffe5e2e2016-08-12 01:05:0128 ~InitOnce() override {}
eroman5a6f5022016-02-29 11:04:0029};
30
31base::LazyInstance<InitOnce>::Leaky g_once = LAZY_INSTANCE_INITIALIZER;
32
33void EnsureInitialized() {
34 g_once.Get();
35}
36
37blink::WebCryptoAlgorithm CreateRsaHashedImportAlgorithm(
38 blink::WebCryptoAlgorithmId id,
39 blink::WebCryptoAlgorithmId hash_id) {
Blink Reformat1c4d759e2017-04-09 16:34:5440 DCHECK(blink::WebCryptoAlgorithm::IsHash(hash_id));
41 return blink::WebCryptoAlgorithm::AdoptParamsAndCreate(
eroman5a6f5022016-02-29 11:04:0042 id,
43 new blink::WebCryptoRsaHashedImportParams(
Blink Reformat1c4d759e2017-04-09 16:34:5444 blink::WebCryptoAlgorithm::AdoptParamsAndCreate(hash_id, nullptr)));
eroman5a6f5022016-02-29 11:04:0045}
46
47blink::WebCryptoAlgorithm CreateEcImportAlgorithm(
48 blink::WebCryptoAlgorithmId id,
49 blink::WebCryptoNamedCurve named_curve) {
Blink Reformat1c4d759e2017-04-09 16:34:5450 return blink::WebCryptoAlgorithm::AdoptParamsAndCreate(
eroman5a6f5022016-02-29 11:04:0051 id, new blink::WebCryptoEcKeyImportParams(named_curve));
52}
53
54} // namespace
55
56blink::WebCryptoKeyUsageMask GetCompatibleKeyUsages(
57 blink::WebCryptoKeyFormat format) {
58 // SPKI format implies import of a public key, whereas PKCS8 implies import
59 // of a private key. Pick usages that are compatible with a signature
60 // algorithm.
Blink Reformat1c4d759e2017-04-09 16:34:5461 return format == blink::kWebCryptoKeyFormatSpki
62 ? blink::kWebCryptoKeyUsageVerify
63 : blink::kWebCryptoKeyUsageSign;
eroman5a6f5022016-02-29 11:04:0064}
65
66void ImportEcKeyFromDerFuzzData(const uint8_t* data,
67 size_t size,
68 blink::WebCryptoKeyFormat format) {
Blink Reformat1c4d759e2017-04-09 16:34:5469 DCHECK(format == blink::kWebCryptoKeyFormatSpki ||
70 format == blink::kWebCryptoKeyFormatPkcs8);
eroman5a6f5022016-02-29 11:04:0071 EnsureInitialized();
72
73 // There are 3 possible EC named curves. Fix this parameter. It shouldn't
74 // matter based on the current implementation for PKCS8 or SPKI. But it
75 // will have an impact when parsing JWK format.
Blink Reformat1c4d759e2017-04-09 16:34:5476 blink::WebCryptoNamedCurve curve = blink::kWebCryptoNamedCurveP384;
eroman5a6f5022016-02-29 11:04:0077
78 // Always use ECDSA as the algorithm. Shouldn't make much difference for
79 // non-JWK formats.
Blink Reformat1c4d759e2017-04-09 16:34:5480 blink::WebCryptoAlgorithmId algorithm_id = blink::kWebCryptoAlgorithmIdEcdsa;
eroman5a6f5022016-02-29 11:04:0081
82 // Use key usages that are compatible with the chosen algorithm and key type.
83 blink::WebCryptoKeyUsageMask usages = GetCompatibleKeyUsages(format);
84
85 blink::WebCryptoKey key;
86 webcrypto::Status status = webcrypto::ImportKey(
kulshin776109842016-07-14 01:08:1687 format, webcrypto::CryptoData(data, base::checked_cast<uint32_t>(size)),
eroman5a6f5022016-02-29 11:04:0088 CreateEcImportAlgorithm(algorithm_id, curve), true, usages, &key);
89
90 // These errors imply a bad setup of parameters, and means ImportKey() may not
91 // be testing the actual parsing.
92 DCHECK_NE(status.error_details(),
93 Status::ErrorUnsupportedImportKeyFormat().error_details());
94 DCHECK_NE(status.error_details(),
95 Status::ErrorCreateKeyBadUsages().error_details());
96}
97
eromancfcb6c92016-08-12 00:33:4698void ImportEcKeyFromRawFuzzData(const uint8_t* data, size_t size) {
99 EnsureInitialized();
100
101 // There are 3 possible EC named curves. Consume the first byte to decide on
102 // the curve.
103 uint8_t curve_index = 0;
104 if (size > 0) {
105 curve_index = data[0];
106 data++;
107 size--;
108 }
109
110 blink::WebCryptoNamedCurve curve;
111
112 switch (curve_index % 3) {
113 case 0:
Blink Reformat1c4d759e2017-04-09 16:34:54114 curve = blink::kWebCryptoNamedCurveP256;
eromancfcb6c92016-08-12 00:33:46115 break;
116 case 1:
Blink Reformat1c4d759e2017-04-09 16:34:54117 curve = blink::kWebCryptoNamedCurveP384;
eromancfcb6c92016-08-12 00:33:46118 break;
119 default:
Blink Reformat1c4d759e2017-04-09 16:34:54120 curve = blink::kWebCryptoNamedCurveP521;
eromancfcb6c92016-08-12 00:33:46121 break;
122 }
123
124 // Always use ECDSA as the algorithm. Shouldn't make an difference for import.
Blink Reformat1c4d759e2017-04-09 16:34:54125 blink::WebCryptoAlgorithmId algorithm_id = blink::kWebCryptoAlgorithmIdEcdsa;
eromancfcb6c92016-08-12 00:33:46126
127 // Use key usages that are compatible with the chosen algorithm and key type.
Blink Reformat1c4d759e2017-04-09 16:34:54128 blink::WebCryptoKeyUsageMask usages = blink::kWebCryptoKeyUsageVerify;
eromancfcb6c92016-08-12 00:33:46129
130 blink::WebCryptoKey key;
131 webcrypto::Status status = webcrypto::ImportKey(
Blink Reformat1c4d759e2017-04-09 16:34:54132 blink::kWebCryptoKeyFormatRaw,
eromancfcb6c92016-08-12 00:33:46133 webcrypto::CryptoData(data, base::checked_cast<uint32_t>(size)),
134 CreateEcImportAlgorithm(algorithm_id, curve), true, usages, &key);
135
136 // These errors imply a bad setup of parameters, and means ImportKey() may not
137 // be testing the actual parsing.
138 DCHECK_NE(status.error_details(),
139 Status::ErrorUnsupportedImportKeyFormat().error_details());
140 DCHECK_NE(status.error_details(),
141 Status::ErrorCreateKeyBadUsages().error_details());
142}
143
eroman5a6f5022016-02-29 11:04:00144void ImportRsaKeyFromDerFuzzData(const uint8_t* data,
145 size_t size,
146 blink::WebCryptoKeyFormat format) {
Blink Reformat1c4d759e2017-04-09 16:34:54147 DCHECK(format == blink::kWebCryptoKeyFormatSpki ||
148 format == blink::kWebCryptoKeyFormatPkcs8);
eroman5a6f5022016-02-29 11:04:00149 EnsureInitialized();
150
151 // There are several possible hash functions. Fix this parameter. It shouldn't
152 // matter based on the current implementation for PKCS8 or SPKI. But it
153 // will have an impact when parsing JWK format.
Blink Reformat1c4d759e2017-04-09 16:34:54154 blink::WebCryptoAlgorithmId hash_id = blink::kWebCryptoAlgorithmIdSha256;
eroman5a6f5022016-02-29 11:04:00155
156 // Always use RSA-SSA PKCS#1 as the algorithm. Shouldn't make much difference
157 // for non-JWK formats.
158 blink::WebCryptoAlgorithmId algorithm_id =
Blink Reformat1c4d759e2017-04-09 16:34:54159 blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5;
eroman5a6f5022016-02-29 11:04:00160
161 // Use key usages that are compatible with the chosen algorithm and key type.
162 blink::WebCryptoKeyUsageMask usages = GetCompatibleKeyUsages(format);
163
164 blink::WebCryptoKey key;
165 webcrypto::Status status = webcrypto::ImportKey(
kulshin776109842016-07-14 01:08:16166 format, webcrypto::CryptoData(data, base::checked_cast<uint32_t>(size)),
eroman5a6f5022016-02-29 11:04:00167 CreateRsaHashedImportAlgorithm(algorithm_id, hash_id), true, usages,
168 &key);
169
170 // These errors imply a bad setup of parameters, and means ImportKey() may not
171 // be testing the actual parsing.
172 DCHECK_NE(status.error_details(),
173 Status::ErrorUnsupportedImportKeyFormat().error_details());
174 DCHECK_NE(status.error_details(),
175 Status::ErrorCreateKeyBadUsages().error_details());
176}
177
178} // namespace webcrypto