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:
Dylan Conway
2025-04-19 00:25:30 -07:00
committed by GitHub
parent 218ee99155
commit 7e8e559fce
119 changed files with 7896 additions and 5731 deletions

View File

@@ -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;