aboutsummaryrefslogtreecommitdiff
path: root/src/bun.js/bindings/webcrypto/CryptoKeyEC.cpp
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-10-23 20:25:18 -0700
committerGravatar GitHub <noreply@github.com> 2022-10-23 20:25:18 -0700
commit76652ac3cad64dbc2fd54e976ce4bad0a37caa03 (patch)
tree179865bc417dc6bf2f224dd310b77b931ee45c73 /src/bun.js/bindings/webcrypto/CryptoKeyEC.cpp
parent14cec299f5170b8ed35eed28e53b88724b8cc04f (diff)
downloadbun-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/CryptoKeyEC.cpp')
-rw-r--r--src/bun.js/bindings/webcrypto/CryptoKeyEC.cpp234
1 files changed, 234 insertions, 0 deletions
diff --git a/src/bun.js/bindings/webcrypto/CryptoKeyEC.cpp b/src/bun.js/bindings/webcrypto/CryptoKeyEC.cpp
new file mode 100644
index 000000000..d62a38b53
--- /dev/null
+++ b/src/bun.js/bindings/webcrypto/CryptoKeyEC.cpp
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2017-2019 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 "CryptoKeyEC.h"
+
+#if ENABLE(WEB_CRYPTO)
+
+#include "CryptoAlgorithmRegistry.h"
+#include "JsonWebKey.h"
+#include <wtf/text/Base64.h>
+
+namespace WebCore {
+
+static const ASCIILiteral P256 { "P-256"_s };
+static const ASCIILiteral P384 { "P-384"_s };
+static const ASCIILiteral P521 { "P-521"_s };
+
+static std::optional<CryptoKeyEC::NamedCurve> toNamedCurve(const String& curve)
+{
+ if (curve == P256)
+ return CryptoKeyEC::NamedCurve::P256;
+ if (curve == P384)
+ return CryptoKeyEC::NamedCurve::P384;
+ if (curve == P521)
+ return CryptoKeyEC::NamedCurve::P521;
+
+ return std::nullopt;
+}
+
+CryptoKeyEC::CryptoKeyEC(CryptoAlgorithmIdentifier identifier, NamedCurve curve, CryptoKeyType type, PlatformECKeyContainer&& platformKey, bool extractable, CryptoKeyUsageBitmap usages)
+ : CryptoKey(identifier, type, extractable, usages)
+ , m_platformKey(WTFMove(platformKey))
+ , m_curve(curve)
+{
+ // Only CryptoKeyEC objects for supported curves should be created.
+ ASSERT(platformSupportedCurve(curve));
+}
+
+ExceptionOr<CryptoKeyPair> CryptoKeyEC::generatePair(CryptoAlgorithmIdentifier identifier, const String& curve, bool extractable, CryptoKeyUsageBitmap usages)
+{
+ auto namedCurve = toNamedCurve(curve);
+ if (!namedCurve || !platformSupportedCurve(*namedCurve))
+ return Exception { NotSupportedError };
+
+ auto result = platformGeneratePair(identifier, *namedCurve, extractable, usages);
+ if (!result)
+ return Exception { OperationError };
+
+ return WTFMove(*result);
+}
+
+RefPtr<CryptoKeyEC> CryptoKeyEC::importRaw(CryptoAlgorithmIdentifier identifier, const String& curve, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap usages)
+{
+ auto namedCurve = toNamedCurve(curve);
+ if (!namedCurve || !platformSupportedCurve(*namedCurve))
+ return nullptr;
+
+ return platformImportRaw(identifier, *namedCurve, WTFMove(keyData), extractable, usages);
+}
+
+RefPtr<CryptoKeyEC> CryptoKeyEC::importJwk(CryptoAlgorithmIdentifier identifier, const String& curve, JsonWebKey&& keyData, bool extractable, CryptoKeyUsageBitmap usages)
+{
+ if (keyData.kty != "EC"_s)
+ return nullptr;
+ if (keyData.key_ops && ((keyData.usages & usages) != usages))
+ return nullptr;
+ if (keyData.ext && !keyData.ext.value() && extractable)
+ return nullptr;
+
+ if (keyData.crv.isNull() || curve != keyData.crv)
+ return nullptr;
+ auto namedCurve = toNamedCurve(keyData.crv);
+ if (!namedCurve || !platformSupportedCurve(*namedCurve))
+ return nullptr;
+
+ if (keyData.x.isNull() || keyData.y.isNull())
+ return nullptr;
+ auto x = base64URLDecode(keyData.x);
+ if (!x)
+ return nullptr;
+ auto y = base64URLDecode(keyData.y);
+ if (!y)
+ return nullptr;
+ if (keyData.d.isNull()) {
+ // import public key
+ return platformImportJWKPublic(identifier, *namedCurve, WTFMove(*x), WTFMove(*y), extractable, usages);
+ }
+
+ auto d = base64URLDecode(keyData.d);
+ if (!d)
+ return nullptr;
+ // import private key
+ return platformImportJWKPrivate(identifier, *namedCurve, WTFMove(*x), WTFMove(*y), WTFMove(*d), extractable, usages);
+}
+
+RefPtr<CryptoKeyEC> CryptoKeyEC::importSpki(CryptoAlgorithmIdentifier identifier, const String& curve, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap usages)
+{
+ auto namedCurve = toNamedCurve(curve);
+ if (!namedCurve || !platformSupportedCurve(*namedCurve))
+ return nullptr;
+
+ return platformImportSpki(identifier, *namedCurve, WTFMove(keyData), extractable, usages);
+}
+
+RefPtr<CryptoKeyEC> CryptoKeyEC::importPkcs8(CryptoAlgorithmIdentifier identifier, const String& curve, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap usages)
+{
+ auto namedCurve = toNamedCurve(curve);
+ if (!namedCurve || !platformSupportedCurve(*namedCurve))
+ return nullptr;
+
+ return platformImportPkcs8(identifier, *namedCurve, WTFMove(keyData), extractable, usages);
+}
+
+ExceptionOr<Vector<uint8_t>> CryptoKeyEC::exportRaw() const
+{
+ if (type() != CryptoKey::Type::Public)
+ return Exception { InvalidAccessError };
+
+ auto&& result = platformExportRaw();
+ if (result.isEmpty())
+ return Exception { OperationError };
+ return WTFMove(result);
+}
+
+ExceptionOr<JsonWebKey> CryptoKeyEC::exportJwk() const
+{
+ JsonWebKey result;
+ result.kty = "EC"_s;
+ switch (m_curve) {
+ case NamedCurve::P256:
+ result.crv = P256;
+ break;
+ case NamedCurve::P384:
+ result.crv = P384;
+ break;
+ case NamedCurve::P521:
+ result.crv = P521;
+ break;
+ }
+ result.key_ops = usages();
+ result.ext = extractable();
+ if (!platformAddFieldElements(result))
+ return Exception { OperationError };
+ return result;
+}
+
+ExceptionOr<Vector<uint8_t>> CryptoKeyEC::exportSpki() const
+{
+ if (type() != CryptoKey::Type::Public)
+ return Exception { InvalidAccessError };
+
+ auto&& result = platformExportSpki();
+ if (result.isEmpty())
+ return Exception { OperationError };
+ return WTFMove(result);
+}
+
+ExceptionOr<Vector<uint8_t>> CryptoKeyEC::exportPkcs8() const
+{
+ if (type() != CryptoKey::Type::Private)
+ return Exception { InvalidAccessError };
+
+ auto&& result = platformExportPkcs8();
+ if (result.isEmpty())
+ return Exception { OperationError };
+ return WTFMove(result);
+}
+
+String CryptoKeyEC::namedCurveString() const
+{
+ switch (m_curve) {
+ case NamedCurve::P256:
+ return String(P256);
+ case NamedCurve::P384:
+ return String(P384);
+ case NamedCurve::P521:
+ return String(P521);
+ }
+
+ ASSERT_NOT_REACHED();
+ return emptyString();
+}
+
+bool CryptoKeyEC::isValidECAlgorithm(CryptoAlgorithmIdentifier algorithm)
+{
+ return algorithm == CryptoAlgorithmIdentifier::ECDSA || algorithm == CryptoAlgorithmIdentifier::ECDH;
+}
+
+auto CryptoKeyEC::algorithm() const -> KeyAlgorithm
+{
+ CryptoEcKeyAlgorithm result;
+ result.name = CryptoAlgorithmRegistry::singleton().name(algorithmIdentifier());
+
+ switch (m_curve) {
+ case NamedCurve::P256:
+ result.namedCurve = P256;
+ break;
+ case NamedCurve::P384:
+ result.namedCurve = P384;
+ break;
+ case NamedCurve::P521:
+ result.namedCurve = P521;
+ break;
+ }
+
+ return result;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_CRYPTO)