feat(l1): Integrate real LibOQS (ML-KEM-768)
- Build System: Link against static liboqs.a (built without OpenSSL) - PQXDH: Replace stubs with OQS_KEM_ml_kem_768 functions - Tests: Verify full handshake with real post-quantum KEM - Disable Kyber (old) in liboqs build to fix symbol conflicts
This commit is contained in:
parent
97e1ad3f69
commit
97251137af
|
|
@ -152,6 +152,9 @@ pub fn build(b: *std.Build) void {
|
|||
.root_module = l1_pqxdh_mod,
|
||||
});
|
||||
l1_pqxdh_tests.linkLibC();
|
||||
l1_pqxdh_tests.addIncludePath(b.path("vendor/liboqs/install/include"));
|
||||
l1_pqxdh_tests.addLibraryPath(b.path("vendor/liboqs/install/lib")); // For liboqs.a
|
||||
l1_pqxdh_tests.linkSystemLibrary("oqs");
|
||||
const run_l1_pqxdh_tests = b.addRunArtifact(l1_pqxdh_tests);
|
||||
|
||||
// Link time module to l1_vector_mod
|
||||
|
|
|
|||
|
|
@ -21,20 +21,20 @@ const crypto = std.crypto;
|
|||
// FIPS 203: ML-KEM-768 (post-standardization naming for Kyber-768)
|
||||
|
||||
/// ML-KEM-768 key generation
|
||||
extern "c" fn OQS_KEM_kyber768_keypair(
|
||||
extern "c" fn OQS_KEM_ml_kem_768_keypair(
|
||||
public_key: ?*u8,
|
||||
secret_key: ?*u8,
|
||||
) c_int;
|
||||
|
||||
/// ML-KEM-768 encapsulation (creates shared secret + ciphertext)
|
||||
extern "c" fn OQS_KEM_kyber768_encaps(
|
||||
extern "c" fn OQS_KEM_ml_kem_768_encaps(
|
||||
ciphertext: ?*u8,
|
||||
shared_secret: ?*u8,
|
||||
public_key: ?*const u8,
|
||||
) c_int;
|
||||
|
||||
/// ML-KEM-768 decapsulation (recovers shared secret from ciphertext)
|
||||
extern "c" fn OQS_KEM_kyber768_decaps(
|
||||
extern "c" fn OQS_KEM_ml_kem_768_decaps(
|
||||
shared_secret: ?*u8,
|
||||
ciphertext: ?*const u8,
|
||||
secret_key: ?*const u8,
|
||||
|
|
@ -246,7 +246,7 @@ pub fn initiator(
|
|||
var kem_ct: [ML_KEM_768.CIPHERTEXT_SIZE]u8 = undefined;
|
||||
|
||||
// Call liboqs ML-KEM encapsulation
|
||||
const kem_result = OQS_KEM_kyber768_encaps(
|
||||
const kem_result = OQS_KEM_ml_kem_768_encaps(
|
||||
@ptrCast(&kem_ct),
|
||||
@ptrCast(&kem_ss),
|
||||
@ptrCast(&bob_prekey_bundle.signed_prekey_mlkem),
|
||||
|
|
@ -332,7 +332,7 @@ pub fn responder(
|
|||
var kem_ss: [ML_KEM_768.SHARED_SECRET_SIZE]u8 = undefined;
|
||||
|
||||
// Call liboqs ML-KEM decapsulation
|
||||
const kem_result = OQS_KEM_kyber768_decaps(
|
||||
const kem_result = OQS_KEM_ml_kem_768_decaps(
|
||||
@ptrCast(&kem_ss),
|
||||
@ptrCast(&alice_initial_message.mlkem_ciphertext),
|
||||
@ptrCast(&bob_mlkem_private),
|
||||
|
|
|
|||
|
|
@ -9,60 +9,12 @@ const pqxdh = @import("pqxdh.zig");
|
|||
const testing = std.testing;
|
||||
|
||||
// ============================================================================
|
||||
// STUB: ML-KEM-768 Functions (for testing without liboqs)
|
||||
// Real LibOQS Functions (via C Import)
|
||||
// ============================================================================
|
||||
// These will be replaced with real liboqs FFI once library is built
|
||||
|
||||
export fn OQS_KEM_kyber768_keypair(
|
||||
public_key: ?*u8,
|
||||
secret_key: ?*u8,
|
||||
) c_int {
|
||||
// Stub: Fill with deterministic test data
|
||||
if (public_key) |pk| {
|
||||
const pk_slice: [*]u8 = @ptrCast(pk);
|
||||
@memset(pk_slice[0..pqxdh.ML_KEM_768.PUBLIC_KEY_SIZE], 0xAA);
|
||||
}
|
||||
if (secret_key) |sk| {
|
||||
const sk_slice: [*]u8 = @ptrCast(sk);
|
||||
@memset(sk_slice[0..pqxdh.ML_KEM_768.SECRET_KEY_SIZE], 0xBB);
|
||||
}
|
||||
return 0; // Success
|
||||
}
|
||||
|
||||
export fn OQS_KEM_kyber768_encaps(
|
||||
ciphertext: ?*u8,
|
||||
shared_secret: ?*u8,
|
||||
public_key: ?*const u8,
|
||||
) c_int {
|
||||
_ = public_key; // Use in real impl
|
||||
|
||||
// Stub: Generate deterministic shared secret + ciphertext
|
||||
if (ciphertext) |ct| {
|
||||
const ct_slice: [*]u8 = @ptrCast(ct);
|
||||
@memset(ct_slice[0..pqxdh.ML_KEM_768.CIPHERTEXT_SIZE], 0xCC);
|
||||
}
|
||||
if (shared_secret) |ss| {
|
||||
const ss_slice: [*]u8 = @ptrCast(ss);
|
||||
@memset(ss_slice[0..pqxdh.ML_KEM_768.SHARED_SECRET_SIZE], 0xDD);
|
||||
}
|
||||
return 0; // Success
|
||||
}
|
||||
|
||||
export fn OQS_KEM_kyber768_decaps(
|
||||
shared_secret: ?*u8,
|
||||
ciphertext: ?*const u8,
|
||||
secret_key: ?*const u8,
|
||||
) c_int {
|
||||
_ = ciphertext; // Use in real impl
|
||||
_ = secret_key; // Use in real impl
|
||||
|
||||
// Stub: Must return SAME shared secret as encaps for protocol to work
|
||||
if (shared_secret) |ss| {
|
||||
const ss_slice: [*]u8 = @ptrCast(ss);
|
||||
@memset(ss_slice[0..pqxdh.ML_KEM_768.SHARED_SECRET_SIZE], 0xDD);
|
||||
}
|
||||
return 0; // Success
|
||||
}
|
||||
const c = @cImport({
|
||||
@cInclude("oqs/oqs.h");
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// Helper: Generate Test Keypairs
|
||||
|
|
@ -132,7 +84,7 @@ test "PQXDHInitialMessage serialization roundtrip" {
|
|||
try testing.expectEqualSlices(u8, &msg.mlkem_ciphertext, &restored.mlkem_ciphertext);
|
||||
}
|
||||
|
||||
test "PQXDH full handshake roundtrip (stubbed ML-KEM)" {
|
||||
test "PQXDH full handshake roundtrip (real ML-KEM)" {
|
||||
const allocator = testing.allocator;
|
||||
|
||||
// === Bob's Setup ===
|
||||
|
|
@ -151,7 +103,7 @@ test "PQXDH full handshake roundtrip (stubbed ML-KEM)" {
|
|||
// Generate Bob's ML-KEM keypair (stubbed)
|
||||
var bob_mlkem_public: [pqxdh.ML_KEM_768.PUBLIC_KEY_SIZE]u8 = undefined;
|
||||
var bob_mlkem_private: [pqxdh.ML_KEM_768.SECRET_KEY_SIZE]u8 = undefined;
|
||||
const kem_result = OQS_KEM_kyber768_keypair(&bob_mlkem_public[0], &bob_mlkem_private[0]);
|
||||
const kem_result = c.OQS_KEM_ml_kem_768_keypair(&bob_mlkem_public[0], &bob_mlkem_private[0]);
|
||||
try testing.expectEqual(@as(c_int, 0), kem_result);
|
||||
|
||||
// Create Bob's prekey bundle (signature stubbed for now)
|
||||
|
|
@ -211,6 +163,6 @@ test "PQXDH error: invalid ML-KEM encapsulation" {
|
|||
var public_key: [pqxdh.ML_KEM_768.PUBLIC_KEY_SIZE]u8 = undefined;
|
||||
var secret_key: [pqxdh.ML_KEM_768.SECRET_KEY_SIZE]u8 = undefined;
|
||||
|
||||
const result = OQS_KEM_kyber768_keypair(&public_key[0], &secret_key[0]);
|
||||
const result = c.OQS_KEM_ml_kem_768_keypair(&public_key[0], &secret_key[0]);
|
||||
try testing.expectEqual(@as(c_int, 0), result);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue