1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
|
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/webcrypto/fuzzer_support.h"
#include "base/command_line.h"
#include "base/containers/span.h"
#include "base/no_destructor.h"
#include "base/task/single_thread_task_executor.h"
#include "components/webcrypto/algorithm_dispatch.h"
#include "components/webcrypto/status.h"
#include "mojo/core/embedder/embedder.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_crypto_algorithm_params.h"
#include "third_party/blink/public/web/blink.h"
namespace webcrypto {
namespace {
// This mock is used to initialize blink.
class InitOnce : public blink::Platform {
public:
InitOnce() {
base::CommandLine::Init(0, nullptr);
mojo::core::Init();
blink::Platform::CreateMainThreadAndInitialize(this);
}
~InitOnce() override {}
private:
base::SingleThreadTaskExecutor main_thread_task_executor_;
};
void EnsureInitialized() {
static base::NoDestructor<InitOnce> init_once;
}
blink::WebCryptoAlgorithm CreateRsaHashedImportAlgorithm(
blink::WebCryptoAlgorithmId id,
blink::WebCryptoAlgorithmId hash_id) {
DCHECK(blink::WebCryptoAlgorithm::IsHash(hash_id));
return blink::WebCryptoAlgorithm::AdoptParamsAndCreate(
id,
new blink::WebCryptoRsaHashedImportParams(
blink::WebCryptoAlgorithm::AdoptParamsAndCreate(hash_id, nullptr)));
}
blink::WebCryptoAlgorithm CreateEcImportAlgorithm(
blink::WebCryptoAlgorithmId id,
blink::WebCryptoNamedCurve named_curve) {
return blink::WebCryptoAlgorithm::AdoptParamsAndCreate(
id, new blink::WebCryptoEcKeyImportParams(named_curve));
}
} // namespace
blink::WebCryptoKeyUsageMask GetCompatibleKeyUsages(
blink::WebCryptoKeyFormat format) {
// SPKI format implies import of a public key, whereas PKCS8 implies import
// of a private key. Pick usages that are compatible with a signature
// algorithm.
return format == blink::kWebCryptoKeyFormatSpki
? blink::kWebCryptoKeyUsageVerify
: blink::kWebCryptoKeyUsageSign;
}
void ImportEcKeyFromDerFuzzData(const uint8_t* data,
size_t size,
blink::WebCryptoKeyFormat format) {
DCHECK(format == blink::kWebCryptoKeyFormatSpki ||
format == blink::kWebCryptoKeyFormatPkcs8);
EnsureInitialized();
// There are 3 possible EC named curves. Fix this parameter. It shouldn't
// matter based on the current implementation for PKCS8 or SPKI. But it
// will have an impact when parsing JWK format.
blink::WebCryptoNamedCurve curve = blink::kWebCryptoNamedCurveP384;
// Always use ECDSA as the algorithm. Shouldn't make much difference for
// non-JWK formats.
blink::WebCryptoAlgorithmId algorithm_id = blink::kWebCryptoAlgorithmIdEcdsa;
// Use key usages that are compatible with the chosen algorithm and key type.
blink::WebCryptoKeyUsageMask usages = GetCompatibleKeyUsages(format);
blink::WebCryptoKey key;
webcrypto::Status status = webcrypto::ImportKey(
format, base::make_span(data, size),
CreateEcImportAlgorithm(algorithm_id, curve), true, usages, &key);
// These errors imply a bad setup of parameters, and means ImportKey() may not
// be testing the actual parsing.
DCHECK_NE(status.error_details(),
Status::ErrorUnsupportedImportKeyFormat().error_details());
DCHECK_NE(status.error_details(),
Status::ErrorCreateKeyBadUsages().error_details());
}
void ImportEcKeyFromRawFuzzData(const uint8_t* data, size_t size) {
EnsureInitialized();
// There are 3 possible EC named curves. Consume the first byte to decide on
// the curve.
uint8_t curve_index = 0;
if (size > 0) {
curve_index = data[0];
data++;
size--;
}
blink::WebCryptoNamedCurve curve;
switch (curve_index % 3) {
case 0:
curve = blink::kWebCryptoNamedCurveP256;
break;
case 1:
curve = blink::kWebCryptoNamedCurveP384;
break;
default:
curve = blink::kWebCryptoNamedCurveP521;
break;
}
// Always use ECDSA as the algorithm. Shouldn't make an difference for import.
blink::WebCryptoAlgorithmId algorithm_id = blink::kWebCryptoAlgorithmIdEcdsa;
// Use key usages that are compatible with the chosen algorithm and key type.
blink::WebCryptoKeyUsageMask usages = blink::kWebCryptoKeyUsageVerify;
blink::WebCryptoKey key;
webcrypto::Status status = webcrypto::ImportKey(
blink::kWebCryptoKeyFormatRaw, base::make_span(data, size),
CreateEcImportAlgorithm(algorithm_id, curve), true, usages, &key);
// These errors imply a bad setup of parameters, and means ImportKey() may not
// be testing the actual parsing.
DCHECK_NE(status.error_details(),
Status::ErrorUnsupportedImportKeyFormat().error_details());
DCHECK_NE(status.error_details(),
Status::ErrorCreateKeyBadUsages().error_details());
}
void ImportRsaKeyFromDerFuzzData(const uint8_t* data,
size_t size,
blink::WebCryptoKeyFormat format) {
DCHECK(format == blink::kWebCryptoKeyFormatSpki ||
format == blink::kWebCryptoKeyFormatPkcs8);
EnsureInitialized();
// There are several possible hash functions. Fix this parameter. It shouldn't
// matter based on the current implementation for PKCS8 or SPKI. But it
// will have an impact when parsing JWK format.
blink::WebCryptoAlgorithmId hash_id = blink::kWebCryptoAlgorithmIdSha256;
// Always use RSA-SSA PKCS#1 as the algorithm. Shouldn't make much difference
// for non-JWK formats.
blink::WebCryptoAlgorithmId algorithm_id =
blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5;
// Use key usages that are compatible with the chosen algorithm and key type.
blink::WebCryptoKeyUsageMask usages = GetCompatibleKeyUsages(format);
blink::WebCryptoKey key;
webcrypto::Status status = webcrypto::ImportKey(
format, base::make_span(data, size),
CreateRsaHashedImportAlgorithm(algorithm_id, hash_id), true, usages,
&key);
// These errors imply a bad setup of parameters, and means ImportKey() may not
// be testing the actual parsing.
DCHECK_NE(status.error_details(),
Status::ErrorUnsupportedImportKeyFormat().error_details());
DCHECK_NE(status.error_details(),
Status::ErrorCreateKeyBadUsages().error_details());
}
} // namespace webcrypto
|