Skip to content

Commit 77e8b29

Browse files
committed
tmp
1 parent d83c274 commit 77e8b29

File tree

10 files changed

+157
-4
lines changed

10 files changed

+157
-4
lines changed

Libraries/LibCrypto/PK/EC.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ class ECPublicKey {
3636
{
3737
}
3838

39+
UnsignedBigInteger const& x() const { return m_x; }
40+
UnsignedBigInteger const& y() const { return m_y; }
3941
size_t scalar_size() const { return m_scalar_size; }
4042

4143
ErrorOr<ByteBuffer> x_bytes() const

Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8141,6 +8141,7 @@ WebIDL::ExceptionOr<GC::Ref<JS::Object>> HMAC::export_key(Bindings::KeyFormat fo
81418141
// 2. Let bits be the raw bits of the key represented by [[handle]] internal slot of key.
81428142
// 3. Let data be an octet string containing bits.
81438143
auto data = key->handle().get<ByteBuffer>();
8144+
dbgln("DATA {}", data.bytes());
81448145

81458146
// 4. If format is "raw":
81468147
GC::Ptr<JS::Object> result;

Libraries/LibWeb/Crypto/CryptoBindings.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ JS::ThrowCompletionOr<JsonWebKey> JsonWebKey::parse(JS::Realm& realm, ReadonlyBy
8585

8686
#undef JWK_PARSE_STRING_PROPERTY
8787

88-
JS::ThrowCompletionOr<GC::Ref<JS::Object>> JsonWebKey::to_object(JS::Realm& realm)
88+
JS::ThrowCompletionOr<GC::Ref<JS::Object>> JsonWebKey::to_object(JS::Realm& realm) const
8989
{
9090
auto& vm = realm.vm();
9191
auto object = JS::Object::create(realm, realm.intrinsics().object_prototype());

Libraries/LibWeb/Crypto/CryptoBindings.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ struct JsonWebKey {
4343
Optional<Vector<RsaOtherPrimesInfo>> oth;
4444
Optional<String> k;
4545

46-
JS::ThrowCompletionOr<GC::Ref<JS::Object>> to_object(JS::Realm&);
46+
JS::ThrowCompletionOr<GC::Ref<JS::Object>> to_object(JS::Realm&) const;
4747

4848
static JS::ThrowCompletionOr<JsonWebKey> parse(JS::Realm& realm, ReadonlyBytes data);
4949
};

Libraries/LibWeb/Crypto/CryptoKey.cpp

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ JS_DEFINE_NATIVE_FUNCTION(CryptoKeyPair::private_key_getter)
134134
return TRY(Bindings::throw_dom_exception_if_needed(vm, [&] { return impl->private_key(); }));
135135
}
136136

137+
// https://w3c.github.io/webcrypto/#cryptokey-interface-serializable
137138
WebIDL::ExceptionOr<void> CryptoKey::serialization_steps(HTML::SerializationRecord& serialized, bool for_storage, HTML::SerializationMemory& memory)
138139
{
139140
auto& vm = this->vm();
@@ -144,19 +145,58 @@ WebIDL::ExceptionOr<void> CryptoKey::serialization_steps(HTML::SerializationReco
144145
// 2. Set serialized.[[Extractable]] to the [[extractable]] internal slot of value.
145146
HTML::serialize_primitive_type(serialized, m_extractable);
146147

148+
dbgln("PRE SERIALIZE ALGORITHM");
147149
// 3. Set serialized.[[Algorithm]] to the sub-serialization of the [[algorithm]] internal slot of value.
148150
auto serialized_algorithm = TRY(HTML::structured_serialize_internal(vm, m_algorithm, for_storage, memory));
149151
serialized.extend(move(serialized_algorithm));
152+
dbgln("POST SERIALIZE ALGORITHM");
150153

151154
// 4. Set serialized.[[Usages]] to the sub-serialization of the [[usages]] internal slot of value.
152155
auto serialized_usages = TRY(HTML::structured_serialize_internal(vm, m_usages, for_storage, memory));
153156
serialized.extend(move(serialized_usages));
154157

155-
// FIXME: 5. Set serialized.[[Handle]] to the [[handle]] internal slot of value.
158+
// 5. Set serialized.[[Handle]] to the [[handle]] internal slot of value.
159+
TRY(m_key_data.visit(
160+
[&](ByteBuffer const& data) -> WebIDL::ExceptionOr<void> {
161+
TRY(HTML::serialize_string(vm, serialized, "bytes"_string));
162+
TRY(HTML::serialize_bytes(vm, serialized, data));
163+
return {};
164+
},
165+
[&](Bindings::JsonWebKey const& jwk) -> WebIDL::ExceptionOr<void> {
166+
TRY(HTML::serialize_string(vm, serialized, "jwk"_string));
167+
auto serialized_jwk = TRY(HTML::structured_serialize_internal(vm, TRY(jwk.to_object(realm())), for_storage, memory));
168+
serialized.extend(move(serialized_jwk));
169+
return {};
170+
},
171+
[&](::Crypto::PK::RSAPublicKey const& public_key) -> WebIDL::ExceptionOr<void> {
172+
TRY(HTML::serialize_string(vm, serialized, "rsa-pub"_string));
173+
auto bytes = TRY_OR_THROW_OOM(vm, public_key.export_as_der());
174+
TRY(HTML::serialize_bytes(vm, serialized, bytes));
175+
return {};
176+
},
177+
[&](::Crypto::PK::RSAPrivateKey const& private_key) -> WebIDL::ExceptionOr<void> {
178+
TRY(HTML::serialize_string(vm, serialized, "rsa-priv"_string));
179+
auto bytes = TRY_OR_THROW_OOM(vm, private_key.export_as_der());
180+
TRY(HTML::serialize_bytes(vm, serialized, bytes));
181+
return {};
182+
},
183+
[&](::Crypto::PK::ECPublicKey const& public_key) -> WebIDL::ExceptionOr<void> {
184+
TRY(HTML::serialize_string(vm, serialized, "ec-pub"_string));
185+
auto bytes = TRY_OR_THROW_OOM(vm, public_key.to_uncompressed());
186+
TRY(HTML::serialize_bytes(vm, serialized, bytes));
187+
return {};
188+
},
189+
[&](::Crypto::PK::ECPrivateKey const& private_key) -> WebIDL::ExceptionOr<void> {
190+
TRY(HTML::serialize_string(vm, serialized, "ec-priv"_string));
191+
auto bytes = TRY_OR_THROW_OOM(vm, private_key.export_as_der());
192+
TRY(HTML::serialize_bytes(vm, serialized, bytes));
193+
return {};
194+
}));
156195

157196
return {};
158197
}
159198

199+
// https://w3c.github.io/webcrypto/#cryptokey-interface-serializable
160200
WebIDL::ExceptionOr<void> CryptoKey::deserialization_steps(ReadonlySpan<u32> const& serialized, size_t& position, HTML::DeserializationMemory& memory)
161201
{
162202
auto& vm = this->vm();
@@ -169,18 +209,44 @@ WebIDL::ExceptionOr<void> CryptoKey::deserialization_steps(ReadonlySpan<u32> con
169209
m_extractable = HTML::deserialize_primitive_type<bool>(serialized, position);
170210

171211
// 3. Initialize the [[algorithm]] internal slot of value to the sub-deserialization of serialized.[[Algorithm]].
212+
dbgln("PRE DESERIALIZE ALGORITHM");
172213
auto deserialized_record = TRY(HTML::structured_deserialize_internal(vm, serialized, realm, memory, position));
173214
if (deserialized_record.value.has_value())
174215
m_algorithm = deserialized_record.value.release_value().as_object();
175216
position = deserialized_record.position;
217+
dbgln("POST DESERIALIZE ALGORITHM: {}", m_algorithm);
176218

177219
// 4. Initialize the [[usages]] internal slot of value to the sub-deserialization of serialized.[[Usages]].
178220
deserialized_record = TRY(HTML::structured_deserialize_internal(vm, serialized, realm, memory, position));
179221
if (deserialized_record.value.has_value())
180222
m_usages = deserialized_record.value.release_value().as_object();
181223
position = deserialized_record.position;
182224

183-
// FIXME: 5. Initialize the [[handle]] internal slot of value to serialized.[[Handle]].
225+
// 5. Initialize the [[handle]] internal slot of value to serialized.[[Handle]].
226+
auto deserialized_key_data_type = TRY(HTML::deserialize_string(vm, serialized, position));
227+
if (deserialized_key_data_type == "bytes") {
228+
m_key_data = TRY(HTML::deserialize_bytes(vm, serialized, position));
229+
} else if (deserialized_key_data_type == "jwk") {
230+
VERIFY_NOT_REACHED();
231+
} else if (deserialized_key_data_type == "rsa-pub") {
232+
auto bytes = TRY(HTML::deserialize_bytes(vm, serialized, position));
233+
auto key_pair = MUST(::Crypto::PK::RSA::parse_rsa_key(bytes, false, {}));
234+
m_key_data = key_pair.public_key;
235+
} else if (deserialized_key_data_type == "rsa-priv") {
236+
auto bytes = TRY(HTML::deserialize_bytes(vm, serialized, position));
237+
auto key_pair = MUST(::Crypto::PK::RSA::parse_rsa_key(bytes, true, {}));
238+
m_key_data = key_pair.private_key;
239+
} else if (deserialized_key_data_type == "ec-pub") {
240+
auto bytes = TRY(HTML::deserialize_bytes(vm, serialized, position));
241+
auto key_pair = MUST(::Crypto::PK::EC::parse_ec_key(bytes, false, {}));
242+
m_key_data = key_pair.public_key;
243+
} else if (deserialized_key_data_type == "ec-priv") {
244+
auto bytes = TRY(HTML::deserialize_bytes(vm, serialized, position));
245+
auto key_pair = MUST(::Crypto::PK::EC::parse_ec_key(bytes, true, {}));
246+
m_key_data = key_pair.private_key;
247+
} else {
248+
VERIFY_NOT_REACHED();
249+
}
184250

185251
return {};
186252
}

Libraries/LibWeb/Crypto/SubtleCrypto.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,7 @@ GC::Ref<WebIDL::Promise> SubtleCrypto::export_key(Bindings::KeyFormat format, GC
448448
// 5. If the name member of the [[algorithm]] internal slot of key does not identify a registered algorithm that supports the export key operation,
449449
// then throw a NotSupportedError.
450450
// Note: Handled by the base AlgorithmMethods implementation
451+
dbgln("EXPORT: {}", key->algorithm()->class_name());
451452
auto& algorithm = as<KeyAlgorithm>(*key->algorithm());
452453
// FIXME: Stash the AlgorithmMethods on the KeyAlgorithm
453454
auto normalized_algorithm_or_error = normalize_an_algorithm(realm, algorithm.name(), "exportKey"_string);

Libraries/LibWeb/HTML/StructuredSerialize.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,7 @@ class Serializer {
320320

321321
// 19. Otherwise, if value is a platform object that is a serializable object:
322322
else if (value.is_object() && is<Bindings::Serializable>(value.as_object())) {
323+
dbgln("SERIALIZE {}", value.as_object().class_name());
323324
auto& serializable = dynamic_cast<Bindings::Serializable&>(value.as_object());
324325

325326
// FIXME: 1. If value has a [[Detached]] internal slot whose value is true, then throw a "DataCloneError" DOMException.
@@ -349,6 +350,8 @@ class Serializer {
349350

350351
// 24. Otherwise:
351352
else {
353+
dbgln("OTHERWISE {}",value.as_object().class_name() );
354+
352355
// 1. Set serialized to { [[Type]]: "Object", [[Properties]]: a new empty List }.
353356
serialize_enum(m_serialized, ValueTag::Object);
354357

@@ -530,6 +533,11 @@ WebIDL::ExceptionOr<void> serialize_reg_exp_object(JS::VM& vm, SerializationReco
530533
return {};
531534
}
532535

536+
WebIDL::ExceptionOr<void> serialize_unsigned_big_integer(JS::VM& vm, Vector<u32>& vector, ::Crypto::UnsignedBigInteger const& bigint)
537+
{
538+
return serialize_string(vm, vector, TRY_OR_THROW_OOM(vm, bigint.to_base(10)));
539+
}
540+
533541
WebIDL::ExceptionOr<void> serialize_bytes(JS::VM& vm, Vector<u32>& vector, ReadonlyBytes bytes)
534542
{
535543
// Append size of the buffer to the serialized structure.
@@ -716,6 +724,7 @@ class Deserializer {
716724
WebIDL::ExceptionOr<JS::Value> deserialize()
717725
{
718726
auto tag = deserialize_primitive_type<ValueTag>(m_serialized, m_position);
727+
dbgln("DESERIALIZE TAG: {}", static_cast<u32>(tag));
719728

720729
// 2. If memory[serialized] exists, then return memory[serialized].
721730
if (tag == ValueTag::ObjectReference) {

Libraries/LibWeb/HTML/StructuredSerialize.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <LibWeb/Forward.h>
1717
#include <LibWeb/HTML/StructuredSerializeTypes.h>
1818
#include <LibWeb/WebIDL/ExceptionOr.h>
19+
#include <LibCrypto/BigInt/UnsignedBigInteger.h>
1920

2021
// Structured serialize is an entirely different format from IPC because:
2122
// - It contains representation of type information
@@ -91,6 +92,7 @@ void serialize_enum(SerializationRecord& serialized, T value)
9192
serialize_primitive_type<UnderlyingType<T>>(serialized, to_underlying(value));
9293
}
9394

95+
WebIDL::ExceptionOr<void> serialize_unsigned_big_integer(JS::VM& vm, Vector<u32>& vector, ::Crypto::UnsignedBigInteger const& bigint);
9496
WebIDL::ExceptionOr<void> serialize_bytes(JS::VM& vm, Vector<u32>& vector, ReadonlyBytes bytes);
9597
WebIDL::ExceptionOr<void> serialize_string(JS::VM& vm, Vector<u32>& vector, StringView);
9698
WebIDL::ExceptionOr<void> serialize_string(JS::VM& vm, Vector<u32>& vector, String const& string);
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
AES-GCM kty: true
2+
AES-GCM key_ops: false
3+
AES-GCM alg: false
4+
AES-GCM ext: true
5+
AES-GCM k: false
6+
Caught error while running async test: OperationError: unclear key size
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<!DOCTYPE html>
2+
<script src="../include.js"></script>
3+
<script>
4+
async function prepareDatabase() {
5+
const req = window.indexedDB.open("TestDatabase");
6+
7+
return new Promise((resolve, reject) => {
8+
req.onerror = () => {
9+
reject(req.error);
10+
};
11+
req.onupgradeneeded = () => {
12+
req.result.createObjectStore("TestObjectStore");
13+
};
14+
req.onsuccess = () => {
15+
resolve(req.result);
16+
};
17+
})
18+
}
19+
20+
async function awaitRequest(request) {
21+
return new Promise((resolve, reject) => {
22+
request.onerror = () => {
23+
reject(request.error);
24+
};
25+
request.onsuccess = () => {
26+
resolve(request.result);
27+
};
28+
});
29+
}
30+
31+
asyncTest(async (done) => {
32+
for (const [algo, usages] of [
33+
[{name: "AES-GCM", length: 256}, ["encrypt", "decrypt"]],
34+
[{name: "AES-CBC", length: 256}, ["encrypt", "decrypt"]],
35+
[{name: "AES-KW", length: 256}, ["wrapKey", "unwrapKey"]],
36+
[{name: "HMAC", hash: {name: "SHA-256"}}, ["sign", "verify"]],
37+
[{name: "RSASSA-PKCS1-v1_5", hash: {name: "SHA-256"}}, ["sign", "verify"]],
38+
[{name: "ECDSA", namedCurve: "P-256"}, ["sign", "verify"]],
39+
[{name: "Ed25519"}, ["sign", "verify"]],
40+
]) {
41+
const originalKey = await crypto.subtle.generateKey(algo, true, usages);
42+
43+
const db = await prepareDatabase()
44+
45+
const tx = db.transaction("TestObjectStore", "readwrite");
46+
const store = tx.objectStore("TestObjectStore");
47+
await awaitRequest(store.put(originalKey, "testKey"));
48+
49+
const serializedKey = await awaitRequest(store.get("testKey"));
50+
51+
const originalKeyJwk = await crypto.subtle.exportKey("jwk", originalKey);
52+
53+
try {
54+
const serializedKeyJwk = await crypto.subtle.exportKey("jwk", serializedKey);
55+
56+
for (const key of Object.keys(originalKeyJwk)) {
57+
println(`${algo.name} ${key}: ${originalKeyJwk[key] === serializedKeyJwk[key]}`);
58+
}
59+
} catch (e) {
60+
println(`${algo.name}: ${e}`);
61+
}
62+
}
63+
64+
done();
65+
});
66+
</script>

0 commit comments

Comments
 (0)