Skip to content

Commit deabcf7

Browse files
committed
fixup! implement a subset of "Modern Algorithms in the Web Cryptography API"
1 parent 1a52547 commit deabcf7

5 files changed

Lines changed: 144 additions & 101 deletions

File tree

src/workerd/api/crypto/chacha20.c++

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ class ChaCha20Poly1305Key final: public CryptoKey::Impl {
136136
}
137137

138138
kj::StringPtr jsgGetMemoryName() const override {
139-
return "ChaCha20Poly1305Key"_kjc;
139+
return "ChaCha20Poly1305Key";
140140
}
141141
size_t jsgGetMemorySelfSize() const override {
142142
return sizeof(ChaCha20Poly1305Key);

src/workerd/api/crypto/crypto.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -727,6 +727,28 @@ class SubtleCrypto: public jsg::Object {
727727
plainText: ArrayBuffer | ArrayBufferView)
728728
: Promise<ArrayBuffer>;
729729
exportKey(format: string, key: CryptoKey) : Promise<ArrayBuffer | JsonWebKey>;
730+
encapsulateKey(encapsulationAlgorithm: string | SubtleCryptoImportKeyAlgorithm,
731+
encapsulationKey: CryptoKey,
732+
sharedKeyAlgorithm: string | SubtleCryptoImportKeyAlgorithm,
733+
extractable: boolean,
734+
keyUsages: string[])
735+
: Promise<SubtleCryptoEncapsulatedKey>;
736+
encapsulateBits(encapsulationAlgorithm: string | SubtleCryptoImportKeyAlgorithm,
737+
encapsulationKey: CryptoKey)
738+
: Promise<SubtleCryptoEncapsulatedBits>;
739+
decapsulateKey(decapsulationAlgorithm: string | SubtleCryptoImportKeyAlgorithm,
740+
decapsulationKey: CryptoKey,
741+
ciphertext: ArrayBuffer | ArrayBufferView,
742+
sharedKeyAlgorithm: string | SubtleCryptoImportKeyAlgorithm,
743+
extractable: boolean,
744+
keyUsages: string[])
745+
: Promise<CryptoKey>;
746+
decapsulateBits(decapsulationAlgorithm: string | SubtleCryptoImportKeyAlgorithm,
747+
decapsulationKey: CryptoKey,
748+
ciphertext: ArrayBuffer | ArrayBufferView)
749+
: Promise<ArrayBuffer>;
750+
getPublicKey(key: CryptoKey, keyUsages: string[])
751+
: Promise<CryptoKey>;
730752
});
731753
}
732754
};

src/workerd/api/crypto/mldsa.c++

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,8 @@ std::pair<const uint8_t*, size_t> getContext(
153153
auto ctxData = ctx.getHandle(js).asArrayPtr();
154154
return {ctxData.begin(), ctxData.size()};
155155
}
156+
// BoringSSL treats (nullptr, 0) as an empty context, equivalent to a zero-length byte string
157+
// per FIPS 204 §5.2.
156158
return {nullptr, 0};
157159
}
158160

@@ -185,6 +187,12 @@ class MlDsaKey final: public CryptoKey::Impl {
185187
publicKey(kj::mv(publicKey)),
186188
publicKeyBytes(kj::mv(publicKeyBytes)) {}
187189

190+
~MlDsaKey() noexcept(false) {
191+
KJ_IF_SOME(s, seed) {
192+
OPENSSL_cleanse(s.begin(), s.size());
193+
}
194+
}
195+
188196
jsg::JsArrayBuffer sign(jsg::Lock& js,
189197
SubtleCrypto::SignAlgorithm&& algorithm,
190198
kj::ArrayPtr<const kj::byte> data) const override {
@@ -275,6 +283,12 @@ class MlDsaKey final: public CryptoKey::Impl {
275283
size_t jsgGetMemorySelfSize() const override {
276284
return sizeof(MlDsaKey<P>);
277285
}
286+
void jsgGetMemoryInfo(jsg::MemoryTracker& tracker) const override {
287+
tracker.trackFieldWithSize("publicKeyBytes", publicKeyBytes.size());
288+
KJ_IF_SOME(s, seed) {
289+
tracker.trackFieldWithSize("seed", s.size());
290+
}
291+
}
278292

279293
kj::Own<CryptoKey::Impl> getPublicKey(jsg::Lock& js, CryptoKeyUsageSet usages) const override {
280294
JSG_REQUIRE(
@@ -598,31 +612,31 @@ class MlDsaKey final: public CryptoKey::Impl {
598612
auto oid = getOid<P>();
599613

600614
// Manually build the SPKI
601-
bssl::ScopedCBB cbb2;
602-
CBB spki2, algId2, oidCbb, bitString;
603-
JSG_REQUIRE(CBB_init(cbb2.get(), P::PUBLIC_KEY_BYTES + 64), InternalDOMOperationError,
615+
bssl::ScopedCBB cbb;
616+
CBB spki, algId, oidCbb, bitString;
617+
JSG_REQUIRE(CBB_init(cbb.get(), P::PUBLIC_KEY_BYTES + 64), InternalDOMOperationError,
604618
"Failed to init SPKI CBB.");
605-
JSG_REQUIRE(CBB_add_asn1(cbb2.get(), &spki2, CBS_ASN1_SEQUENCE), InternalDOMOperationError,
619+
JSG_REQUIRE(CBB_add_asn1(cbb.get(), &spki, CBS_ASN1_SEQUENCE), InternalDOMOperationError,
606620
"Failed to add SPKI SEQUENCE.");
607-
JSG_REQUIRE(CBB_add_asn1(&spki2, &algId2, CBS_ASN1_SEQUENCE), InternalDOMOperationError,
621+
JSG_REQUIRE(CBB_add_asn1(&spki, &algId, CBS_ASN1_SEQUENCE), InternalDOMOperationError,
608622
"Failed to add AlgorithmIdentifier SEQUENCE.");
609-
JSG_REQUIRE(CBB_add_asn1(&algId2, &oidCbb, CBS_ASN1_OBJECT), InternalDOMOperationError,
623+
JSG_REQUIRE(CBB_add_asn1(&algId, &oidCbb, CBS_ASN1_OBJECT), InternalDOMOperationError,
610624
"Failed to add OID.");
611625
JSG_REQUIRE(CBB_add_bytes(&oidCbb, oid.begin(), oid.size()), InternalDOMOperationError,
612626
"Failed to add OID bytes.");
613627
JSG_REQUIRE(
614-
CBB_flush(&algId2), InternalDOMOperationError, "Failed to flush AlgorithmIdentifier.");
615-
JSG_REQUIRE(CBB_add_asn1(&spki2, &bitString, CBS_ASN1_BITSTRING), InternalDOMOperationError,
628+
CBB_flush(&algId), InternalDOMOperationError, "Failed to flush AlgorithmIdentifier.");
629+
JSG_REQUIRE(CBB_add_asn1(&spki, &bitString, CBS_ASN1_BITSTRING), InternalDOMOperationError,
616630
"Failed to add BIT STRING.");
617631
JSG_REQUIRE(
618632
CBB_add_u8(&bitString, 0), InternalDOMOperationError, "Failed to add unused bits byte.");
619633
JSG_REQUIRE(CBB_add_bytes(&bitString, publicKeyBytes.begin(), publicKeyBytes.size()),
620634
InternalDOMOperationError, "Failed to add public key bytes.");
621-
JSG_REQUIRE(CBB_flush(cbb2.get()), InternalDOMOperationError, "Failed to flush SPKI.");
635+
JSG_REQUIRE(CBB_flush(cbb.get()), InternalDOMOperationError, "Failed to flush SPKI.");
622636

623637
uint8_t* der = nullptr;
624638
size_t derLen;
625-
JSG_REQUIRE(CBB_finish(cbb2.get(), &der, &derLen), InternalDOMOperationError,
639+
JSG_REQUIRE(CBB_finish(cbb.get(), &der, &derLen), InternalDOMOperationError,
626640
"Failed to finish SPKI encoding.");
627641
KJ_DEFER(OPENSSL_free(der));
628642

src/workerd/api/crypto/mlkem.c++

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,12 @@ class MlKemKey final: public CryptoKey::Impl {
122122
publicKey(kj::mv(publicKey)),
123123
publicKeyBytes(kj::mv(publicKeyBytes)) {}
124124

125+
~MlKemKey() noexcept(false) {
126+
KJ_IF_SOME(s, seed) {
127+
OPENSSL_cleanse(s.begin(), s.size());
128+
}
129+
}
130+
125131
std::pair<jsg::JsArrayBuffer, jsg::JsArrayBuffer> encapsulate(jsg::Lock& js) const override {
126132
JSG_REQUIRE(
127133
keyType == KeyType::PUBLIC, DOMInvalidAccessError, "Encapsulation requires a public key.");
@@ -209,6 +215,12 @@ class MlKemKey final: public CryptoKey::Impl {
209215
size_t jsgGetMemorySelfSize() const override {
210216
return sizeof(MlKemKey<P>);
211217
}
218+
void jsgGetMemoryInfo(jsg::MemoryTracker& tracker) const override {
219+
tracker.trackFieldWithSize("publicKeyBytes", publicKeyBytes.size());
220+
KJ_IF_SOME(s, seed) {
221+
tracker.trackFieldWithSize("seed", s.size());
222+
}
223+
}
212224

213225
kj::Own<CryptoKey::Impl> getPublicKey(jsg::Lock& js, CryptoKeyUsageSet usages) const override {
214226
JSG_REQUIRE(

0 commit comments

Comments
 (0)