diff options
author | 2022-10-23 20:25:18 -0700 | |
---|---|---|
committer | 2022-10-23 20:25:18 -0700 | |
commit | 76652ac3cad64dbc2fd54e976ce4bad0a37caa03 (patch) | |
tree | 179865bc417dc6bf2f224dd310b77b931ee45c73 /src/bun.js/bindings/webcrypto/CryptoAlgorithmECDSA.cpp | |
parent | 14cec299f5170b8ed35eed28e53b88724b8cc04f (diff) | |
download | bun-76652ac3cad64dbc2fd54e976ce4bad0a37caa03.tar.gz bun-76652ac3cad64dbc2fd54e976ce4bad0a37caa03.tar.zst bun-76652ac3cad64dbc2fd54e976ce4bad0a37caa03.zip |
Add Web Crypto API (#1384)
* Add Web Crypto API
* Duplicate symbols
* Update c_cpp_properties.json
Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
Diffstat (limited to 'src/bun.js/bindings/webcrypto/CryptoAlgorithmECDSA.cpp')
-rw-r--r-- | src/bun.js/bindings/webcrypto/CryptoAlgorithmECDSA.cpp | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/src/bun.js/bindings/webcrypto/CryptoAlgorithmECDSA.cpp b/src/bun.js/bindings/webcrypto/CryptoAlgorithmECDSA.cpp new file mode 100644 index 000000000..dbc000620 --- /dev/null +++ b/src/bun.js/bindings/webcrypto/CryptoAlgorithmECDSA.cpp @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2017 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "CryptoAlgorithmECDSA.h" + +#if ENABLE(WEB_CRYPTO) + +#include "CryptoAlgorithmEcKeyParams.h" +#include "CryptoAlgorithmEcdsaParams.h" +#include "CryptoKeyEC.h" +#include <JavaScriptCore/JSCJSValueInlines.h> +#include <wtf/CrossThreadCopier.h> + +namespace WebCore { + +namespace CryptoAlgorithmECDSAInternal { +static constexpr auto ALG256 = "ES256"_s; +static constexpr auto ALG384 = "ES384"_s; +static constexpr auto ALG512 = "ES512"_s; +static constexpr auto P256 = "P-256"_s; +static constexpr auto P384 = "P-384"_s; +static constexpr auto P521 = "P-521"_s; +} + +Ref<CryptoAlgorithm> CryptoAlgorithmECDSA::create() +{ + return adoptRef(*new CryptoAlgorithmECDSA); +} + +CryptoAlgorithmIdentifier CryptoAlgorithmECDSA::identifier() const +{ + return s_identifier; +} + +void CryptoAlgorithmECDSA::sign(const CryptoAlgorithmParameters& parameters, Ref<CryptoKey>&& key, Vector<uint8_t>&& data, VectorCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue) +{ + if (key->type() != CryptoKeyType::Private) { + exceptionCallback(InvalidAccessError); + return; + } + + dispatchOperationInWorkQueue(workQueue, context, WTFMove(callback), WTFMove(exceptionCallback), + [parameters = crossThreadCopy(downcast<CryptoAlgorithmEcdsaParams>(parameters)), key = WTFMove(key), data = WTFMove(data)] { + return platformSign(parameters, downcast<CryptoKeyEC>(key.get()), data); + }); +} + +void CryptoAlgorithmECDSA::verify(const CryptoAlgorithmParameters& parameters, Ref<CryptoKey>&& key, Vector<uint8_t>&& signature, Vector<uint8_t>&& data, BoolCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue) +{ + if (key->type() != CryptoKeyType::Public) { + exceptionCallback(InvalidAccessError); + return; + } + + dispatchOperationInWorkQueue(workQueue, context, WTFMove(callback), WTFMove(exceptionCallback), + [parameters = crossThreadCopy(downcast<CryptoAlgorithmEcdsaParams>(parameters)), key = WTFMove(key), signature = WTFMove(signature), data = WTFMove(data)] { + return platformVerify(parameters, downcast<CryptoKeyEC>(key.get()), signature, data); + }); +} + +void CryptoAlgorithmECDSA::generateKey(const CryptoAlgorithmParameters& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyOrKeyPairCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext&) +{ + const auto& ecParameters = downcast<CryptoAlgorithmEcKeyParams>(parameters); + + if (usages & (CryptoKeyUsageEncrypt | CryptoKeyUsageDecrypt | CryptoKeyUsageDeriveKey | CryptoKeyUsageDeriveBits | CryptoKeyUsageWrapKey | CryptoKeyUsageUnwrapKey)) { + exceptionCallback(SyntaxError); + return; + } + + auto result = CryptoKeyEC::generatePair(CryptoAlgorithmIdentifier::ECDSA, ecParameters.namedCurve, extractable, usages); + if (result.hasException()) { + exceptionCallback(result.releaseException().code()); + return; + } + + auto pair = result.releaseReturnValue(); + pair.publicKey->setUsagesBitmap(pair.publicKey->usagesBitmap() & CryptoKeyUsageVerify); + pair.privateKey->setUsagesBitmap(pair.privateKey->usagesBitmap() & CryptoKeyUsageSign); + callback(WTFMove(pair)); +} + +void CryptoAlgorithmECDSA::importKey(CryptoKeyFormat format, KeyData&& data, const CryptoAlgorithmParameters& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyCallback&& callback, ExceptionCallback&& exceptionCallback) +{ + using namespace CryptoAlgorithmECDSAInternal; + const auto& ecParameters = downcast<CryptoAlgorithmEcKeyParams>(parameters); + + RefPtr<CryptoKeyEC> result; + switch (format) { + case CryptoKeyFormat::Jwk: { + JsonWebKey key = WTFMove(std::get<JsonWebKey>(data)); + + if (usages && ((!key.d.isNull() && (usages ^ CryptoKeyUsageSign)) || (key.d.isNull() && (usages ^ CryptoKeyUsageVerify)))) { + exceptionCallback(SyntaxError); + return; + } + if (usages && !key.use.isNull() && key.use != "sig"_s) { + exceptionCallback(DataError); + return; + } + + bool isMatched = false; + if (key.crv == P256) + isMatched = key.alg.isNull() || key.alg == ALG256; + if (key.crv == P384) + isMatched = key.alg.isNull() || key.alg == ALG384; + if (key.crv == P521) + isMatched = key.alg.isNull() || key.alg == ALG512; + if (!isMatched) { + exceptionCallback(DataError); + return; + } + + result = CryptoKeyEC::importJwk(ecParameters.identifier, ecParameters.namedCurve, WTFMove(key), extractable, usages); + break; + } + case CryptoKeyFormat::Raw: + if (usages && (usages ^ CryptoKeyUsageVerify)) { + exceptionCallback(SyntaxError); + return; + } + result = CryptoKeyEC::importRaw(ecParameters.identifier, ecParameters.namedCurve, WTFMove(std::get<Vector<uint8_t>>(data)), extractable, usages); + break; + case CryptoKeyFormat::Spki: + if (usages && (usages ^ CryptoKeyUsageVerify)) { + exceptionCallback(SyntaxError); + return; + } + result = CryptoKeyEC::importSpki(ecParameters.identifier, ecParameters.namedCurve, WTFMove(std::get<Vector<uint8_t>>(data)), extractable, usages); + break; + case CryptoKeyFormat::Pkcs8: + if (usages && (usages ^ CryptoKeyUsageSign)) { + exceptionCallback(SyntaxError); + return; + } + result = CryptoKeyEC::importPkcs8(ecParameters.identifier, ecParameters.namedCurve, WTFMove(std::get<Vector<uint8_t>>(data)), extractable, usages); + break; + } + if (!result) { + exceptionCallback(DataError); + return; + } + + callback(*result); +} + +void CryptoAlgorithmECDSA::exportKey(CryptoKeyFormat format, Ref<CryptoKey>&& key, KeyDataCallback&& callback, ExceptionCallback&& exceptionCallback) +{ + const auto& ecKey = downcast<CryptoKeyEC>(key.get()); + + if (!ecKey.keySizeInBits()) { + exceptionCallback(OperationError); + return; + } + + KeyData result; + switch (format) { + case CryptoKeyFormat::Jwk: { + auto jwk = ecKey.exportJwk(); + if (jwk.hasException()) { + exceptionCallback(jwk.releaseException().code()); + return; + } + result = jwk.releaseReturnValue(); + break; + } + case CryptoKeyFormat::Raw: { + auto raw = ecKey.exportRaw(); + if (raw.hasException()) { + exceptionCallback(raw.releaseException().code()); + return; + } + result = raw.releaseReturnValue(); + break; + } + case CryptoKeyFormat::Spki: { + auto spki = ecKey.exportSpki(); + if (spki.hasException()) { + exceptionCallback(spki.releaseException().code()); + return; + } + result = spki.releaseReturnValue(); + break; + } + case CryptoKeyFormat::Pkcs8: { + auto pkcs8 = ecKey.exportPkcs8(); + if (pkcs8.hasException()) { + exceptionCallback(pkcs8.releaseException().code()); + return; + } + result = pkcs8.releaseReturnValue(); + break; + } + } + + callback(format, WTFMove(result)); +} + +} // namespace WebCore + +#endif // ENABLE(WEB_CRYPTO) |