mirror of
https://github.com/oven-sh/bun
synced 2026-02-10 10:58:56 +00:00
Pass test-crypto-keygen-* tests (#19040)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com> Co-authored-by: Dave Caruso <me@paperdave.net>
This commit is contained in:
@@ -108,6 +108,11 @@
|
||||
#include "ZigGeneratedClasses.h"
|
||||
#include "JSX509Certificate.h"
|
||||
#include "ncrypto.h"
|
||||
#include "JSKeyObject.h"
|
||||
#include "JSSecretKeyObject.h"
|
||||
#include "JSPublicKeyObject.h"
|
||||
#include "JSPrivateKeyObject.h"
|
||||
#include "CryptoKeyType.h"
|
||||
|
||||
#if USE(CG)
|
||||
#include <CoreGraphics/CoreGraphics.h>
|
||||
@@ -131,6 +136,7 @@
|
||||
namespace WebCore {
|
||||
|
||||
using namespace JSC;
|
||||
using namespace Bun;
|
||||
|
||||
DEFINE_ALLOCATOR_WITH_HEAP_IDENTIFIER(SerializedScriptValue);
|
||||
|
||||
@@ -236,6 +242,7 @@ enum SerializationTag {
|
||||
Bun__BlobTag = 254,
|
||||
// bun types start at 254 and decrease with each addition
|
||||
Bun__X509CertificateTag = 253,
|
||||
Bun__KeyObjectTag = 252,
|
||||
|
||||
ErrorTag = 255
|
||||
};
|
||||
@@ -1825,9 +1832,18 @@ private:
|
||||
serializedKey, SerializationContext::Default, dummySharedBuffers, m_forStorage);
|
||||
rawKeySerializer.write(key);
|
||||
Vector<uint8_t> wrappedKey;
|
||||
if (!wrapCryptoKey(m_lexicalGlobalObject, serializedKey, wrappedKey))
|
||||
return false;
|
||||
write(wrappedKey);
|
||||
|
||||
// Wrapping isn't required
|
||||
// https://github.com/WebKit/WebKit/blob/c0902fc4dd3abf5d2d5e008eb0b008aeae837953/Source/WebCore/crypto/SerializedCryptoKeyWrap.h#L35-L40
|
||||
//
|
||||
// and doesn't do anything currently, so we skip it.
|
||||
// https://github.com/WebKit/WebKit/blob/c0902fc4dd3abf5d2d5e008eb0b008aeae837953/Source/WebCore/crypto/gcrypt/SerializedCryptoKeyWrapGCrypt.cpp#L49
|
||||
// https://github.com/WebKit/WebKit/blob/c0902fc4dd3abf5d2d5e008eb0b008aeae837953/Source/WebCore/crypto/openssl/SerializedCryptoKeyWrapOpenSSL.cpp#L51
|
||||
//
|
||||
// if (!wrapCryptoKey(m_lexicalGlobalObject, serializedKey, wrappedKey))
|
||||
// return false;
|
||||
|
||||
write(serializedKey);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
@@ -1959,6 +1975,57 @@ private:
|
||||
return true;
|
||||
}
|
||||
|
||||
if (auto* keyObject = jsDynamicCast<Bun::JSKeyObject*>(obj)) {
|
||||
write(Bun__KeyObjectTag);
|
||||
|
||||
auto& handle = keyObject->handle();
|
||||
|
||||
write(static_cast<uint8_t>(handle.type()));
|
||||
|
||||
switch (handle.type()) {
|
||||
case CryptoKeyType::Secret: {
|
||||
write(handle.symmetricKey());
|
||||
return true;
|
||||
}
|
||||
case CryptoKeyType::Public: {
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
auto* pkey = handle.asymmetricKey().get();
|
||||
|
||||
BIO* bio = BIO_new(BIO_s_mem());
|
||||
|
||||
PEM_write_bio_PUBKEY(bio, pkey);
|
||||
|
||||
const uint8_t* pemData = nullptr;
|
||||
uint64_t pemSize = 0;
|
||||
BIO_mem_contents(bio, &pemData, reinterpret_cast<size_t*>(&pemSize));
|
||||
|
||||
write(pemSize);
|
||||
write(pemData, pemSize);
|
||||
BIO_free(bio);
|
||||
|
||||
return true;
|
||||
}
|
||||
case CryptoKeyType::Private: {
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
auto* pkey = handle.asymmetricKey().get();
|
||||
|
||||
BIO* bio = BIO_new(BIO_s_mem());
|
||||
|
||||
PEM_write_bio_PrivateKey(bio, pkey, nullptr, nullptr, 0, nullptr, nullptr);
|
||||
|
||||
const uint8_t* pemData = nullptr;
|
||||
uint64_t pemSize = 0;
|
||||
BIO_mem_contents(bio, &pemData, reinterpret_cast<size_t*>(&pemSize));
|
||||
|
||||
write(pemSize);
|
||||
write(pemData, pemSize);
|
||||
BIO_free(bio);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
// Any other types are expected to serialize as null.
|
||||
@@ -3820,6 +3887,29 @@ private:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool read(CryptoKeyType& result)
|
||||
{
|
||||
uint8_t type;
|
||||
if (!read(type))
|
||||
return false;
|
||||
if (type > cryptoKeyTypeMaximumValue) {
|
||||
return false;
|
||||
}
|
||||
result = static_cast<CryptoKeyType>(type);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool read(BIO** bio, uint64_t length)
|
||||
{
|
||||
if (m_ptr + length > m_end)
|
||||
return false;
|
||||
*bio = BIO_new_mem_buf(m_ptr, length);
|
||||
if (!*bio)
|
||||
return false;
|
||||
m_ptr += length;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool readHMACKey(bool extractable, CryptoKeyUsageBitmap usages, RefPtr<CryptoKey>& result)
|
||||
{
|
||||
Vector<uint8_t> keyData;
|
||||
@@ -4434,6 +4524,66 @@ private:
|
||||
return cert_obj;
|
||||
}
|
||||
|
||||
JSValue readKeyObject()
|
||||
{
|
||||
VM& vm = m_globalObject->vm();
|
||||
auto* globalObject = defaultGlobalObject(m_globalObject);
|
||||
|
||||
CryptoKeyType keyType;
|
||||
if (!read(keyType)) {
|
||||
fail();
|
||||
return JSValue();
|
||||
}
|
||||
|
||||
switch (keyType) {
|
||||
case CryptoKeyType::Secret: {
|
||||
Vector<uint8_t> keyData;
|
||||
if (!read(keyData)) {
|
||||
fail();
|
||||
return JSValue();
|
||||
}
|
||||
|
||||
KeyObject keyObject = KeyObject::create(WTFMove(keyData));
|
||||
Structure* structure = globalObject->m_JSSecretKeyObjectClassStructure.get(m_globalObject);
|
||||
return JSSecretKeyObject::create(vm, structure, m_globalObject, WTFMove(keyObject));
|
||||
}
|
||||
case CryptoKeyType::Public:
|
||||
case CryptoKeyType::Private: {
|
||||
uint64_t pemSize = 0;
|
||||
if (!read(pemSize)) {
|
||||
fail();
|
||||
return JSValue();
|
||||
}
|
||||
|
||||
BIO* bio = nullptr;
|
||||
if (!read(&bio, pemSize)) {
|
||||
fail();
|
||||
return JSValue();
|
||||
}
|
||||
|
||||
if (keyType == CryptoKeyType::Public) {
|
||||
EVP_PKEY* pkey = PEM_read_bio_PUBKEY(bio, nullptr, nullptr, nullptr);
|
||||
if (!pkey) {
|
||||
fail();
|
||||
return JSValue();
|
||||
}
|
||||
auto keyObject = KeyObject::create(CryptoKeyType::Public, ncrypto::EVPKeyPointer(pkey));
|
||||
Structure* structure = globalObject->m_JSPublicKeyObjectClassStructure.get(m_globalObject);
|
||||
return JSPublicKeyObject::create(vm, structure, m_globalObject, WTFMove(keyObject));
|
||||
}
|
||||
|
||||
EVP_PKEY* pkey = PEM_read_bio_PrivateKey(bio, nullptr, nullptr, nullptr);
|
||||
if (!pkey) {
|
||||
fail();
|
||||
return JSValue();
|
||||
}
|
||||
auto keyObject = KeyObject::create(CryptoKeyType::Private, ncrypto::EVPKeyPointer(pkey));
|
||||
Structure* structure = globalObject->m_JSPrivateKeyObjectClassStructure.get(m_globalObject);
|
||||
return JSPrivateKeyObject::create(vm, structure, m_globalObject, WTFMove(keyObject));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JSValue readDOMException()
|
||||
{
|
||||
CachedStringRef message;
|
||||
@@ -4927,16 +5077,19 @@ private:
|
||||
}
|
||||
#if ENABLE(WEB_CRYPTO)
|
||||
case CryptoKeyTag: {
|
||||
Vector<uint8_t> wrappedKey;
|
||||
if (!read(wrappedKey)) {
|
||||
fail();
|
||||
return JSValue();
|
||||
}
|
||||
Vector<uint8_t> serializedKey;
|
||||
if (!unwrapCryptoKey(m_lexicalGlobalObject, wrappedKey, serializedKey)) {
|
||||
if (!read(serializedKey)) {
|
||||
fail();
|
||||
return JSValue();
|
||||
}
|
||||
|
||||
// See CryptoKey serialization for why we don't wrap
|
||||
//
|
||||
// Vector<uint8_t> serializedKey;
|
||||
// if (!unwrapCryptoKey(m_lexicalGlobalObject, wrappedKey, serializedKey)) {
|
||||
// fail();
|
||||
// return JSValue();
|
||||
// }
|
||||
JSValue cryptoKey;
|
||||
// Vector<RefPtr<MessagePort>> dummyMessagePorts;
|
||||
// CloneDeserializer rawKeyDeserializer(m_lexicalGlobalObject, m_globalObject, dummyMessagePorts, nullptr, {}, serializedKey);
|
||||
@@ -4992,6 +5145,9 @@ private:
|
||||
case Bun__X509CertificateTag:
|
||||
return readX509Certificate();
|
||||
|
||||
case Bun__KeyObjectTag:
|
||||
return readKeyObject();
|
||||
|
||||
default:
|
||||
m_ptr--; // Push the tag back
|
||||
return JSValue();
|
||||
@@ -5021,8 +5177,8 @@ private:
|
||||
Vector<String> m_blobURLs;
|
||||
Vector<String> m_blobFilePaths;
|
||||
ArrayBufferContentsArray* m_sharedBuffers;
|
||||
// Vector<std::optional<ImageBitmapBacking>> m_backingStores;
|
||||
// Vector<RefPtr<ImageBitmap>> m_imageBitmaps;
|
||||
// Vector<std::optional<ImageBitmapBacking>> m_backingStores;
|
||||
// Vector<RefPtr<ImageBitmap>> m_imageBitmaps;
|
||||
#if ENABLE(OFFSCREEN_CANVAS_IN_WORKERS)
|
||||
Vector<std::unique_ptr<DetachedOffscreenCanvas>> m_detachedOffscreenCanvases;
|
||||
Vector<RefPtr<OffscreenCanvas>> m_offscreenCanvases;
|
||||
|
||||
Reference in New Issue
Block a user