diff options
author | tb <> | 2025-09-14 17:03:28 +0000 |
---|---|---|
committer | tb <> | 2025-09-14 17:03:28 +0000 |
commit | da62f2d5a634074faef81fcd126a41abdc3b0ae2 (patch) | |
tree | d584fa4a5a8b8066a65435afa668bc2bb962fff2 /src | |
parent | 4c3431c42271c25d676afc9be6b449390cc67152 (diff) | |
download | openbsd-da62f2d5a634074faef81fcd126a41abdc3b0ae2.tar.gz openbsd-da62f2d5a634074faef81fcd126a41abdc3b0ae2.tar.bz2 openbsd-da62f2d5a634074faef81fcd126a41abdc3b0ae2.zip |
wycheproof: run ML-KEM test vectors against libcrypto
Diffstat (limited to 'src')
-rw-r--r-- | src/regress/lib/libcrypto/wycheproof/wycheproof.go | 141 |
1 files changed, 139 insertions, 2 deletions
diff --git a/src/regress/lib/libcrypto/wycheproof/wycheproof.go b/src/regress/lib/libcrypto/wycheproof/wycheproof.go index 3ba49bf3ca..349227fb36 100644 --- a/src/regress/lib/libcrypto/wycheproof/wycheproof.go +++ b/src/regress/lib/libcrypto/wycheproof/wycheproof.go | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: wycheproof.go,v 1.190 2025/09/09 03:22:49 tb Exp $ */ | 1 | /* $OpenBSD: wycheproof.go,v 1.191 2025/09/14 17:03:28 tb Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2018,2023 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2018,2023 Joel Sing <jsing@openbsd.org> |
4 | * Copyright (c) 2018,2019,2022-2025 Theo Buehler <tb@openbsd.org> | 4 | * Copyright (c) 2018,2019,2022-2025 Theo Buehler <tb@openbsd.org> |
@@ -36,6 +36,7 @@ package main | |||
36 | #include <openssl/evp.h> | 36 | #include <openssl/evp.h> |
37 | #include <openssl/kdf.h> | 37 | #include <openssl/kdf.h> |
38 | #include <openssl/hmac.h> | 38 | #include <openssl/hmac.h> |
39 | #include <openssl/mlkem.h> | ||
39 | #include <openssl/objects.h> | 40 | #include <openssl/objects.h> |
40 | #include <openssl/pem.h> | 41 | #include <openssl/pem.h> |
41 | #include <openssl/x509.h> | 42 | #include <openssl/x509.h> |
@@ -497,6 +498,28 @@ type wycheproofTestGroupKW struct { | |||
497 | Tests []*wycheproofTestKW `json:"tests"` | 498 | Tests []*wycheproofTestKW `json:"tests"` |
498 | } | 499 | } |
499 | 500 | ||
501 | type wycheproofTestMLKEM struct { | ||
502 | TCID int `json:"tcId"` | ||
503 | Comment string `json:"comment"` | ||
504 | Seed string `json:"seed"` | ||
505 | Ek string `json:"ek"` | ||
506 | M string `json:"m"` | ||
507 | C string `json:"c"` | ||
508 | K string `json:"K"` | ||
509 | Result string `json:"result"` | ||
510 | Flags []string `json:"flags"` | ||
511 | } | ||
512 | |||
513 | func (wt *wycheproofTestMLKEM) String() string { | ||
514 | return wycheproofFormatTestCase(wt.TCID, wt.Comment, wt.Flags, wt.Result) | ||
515 | } | ||
516 | |||
517 | type wycheproofTestGroupMLKEM struct { | ||
518 | Type string `json:"type"` | ||
519 | ParameterSet string `json:"parameterSet"` | ||
520 | Tests []*wycheproofTestMLKEM `json:"tests"` | ||
521 | } | ||
522 | |||
500 | type wycheproofTestPrimality struct { | 523 | type wycheproofTestPrimality struct { |
501 | TCID int `json:"tcId"` | 524 | TCID int `json:"tcId"` |
502 | Comment string `json:"comment"` | 525 | Comment string `json:"comment"` |
@@ -2321,6 +2344,120 @@ func (wtg *wycheproofTestGroupKW) run(algorithm string, variant testVariant) boo | |||
2321 | return success | 2344 | return success |
2322 | } | 2345 | } |
2323 | 2346 | ||
2347 | func runMLKEMTestGroup(rank C.int, wt *wycheproofTestMLKEM) bool { | ||
2348 | privKey := C.MLKEM_private_key_new(rank) | ||
2349 | defer C.MLKEM_private_key_free(privKey) | ||
2350 | if privKey == nil { | ||
2351 | log.Fatal("MLKEM_private_key_new failed") | ||
2352 | } | ||
2353 | pubKey := C.MLKEM_public_key_new(rank) | ||
2354 | defer C.MLKEM_public_key_free(pubKey) | ||
2355 | if pubKey == nil { | ||
2356 | log.Fatal("MLKEM_public_key_new failed") | ||
2357 | } | ||
2358 | |||
2359 | seed, seedLen := mustDecodeHexString(wt.Seed, "seed") | ||
2360 | ek, _ := mustDecodeHexString(wt.Ek, "ek") | ||
2361 | |||
2362 | if C.MLKEM_private_key_from_seed(privKey, (*C.uchar)(unsafe.Pointer(&seed[0])), C.size_t(seedLen)) != 1 { | ||
2363 | fmt.Printf("%s - MLKEM_private_key_from_seed failed\n", wt) | ||
2364 | return false | ||
2365 | } | ||
2366 | |||
2367 | if C.MLKEM_public_from_private(privKey, pubKey) != 1 { | ||
2368 | fmt.Printf("%s - MLKEM_public_from_private failed\n", wt) | ||
2369 | return false | ||
2370 | } | ||
2371 | |||
2372 | var marshalledPubKey *C.uchar | ||
2373 | var marshalledPubKeyLen C.size_t | ||
2374 | defer C.free(unsafe.Pointer(marshalledPubKey)) | ||
2375 | if C.MLKEM_marshal_public_key(pubKey, (**C.uchar)(unsafe.Pointer(&marshalledPubKey)), (*C.size_t)(unsafe.Pointer(&marshalledPubKeyLen))) != 1 { | ||
2376 | fmt.Printf("%s - MLKEM_marshal_private_key failed\n", wt) | ||
2377 | return false | ||
2378 | } | ||
2379 | gotEk := unsafe.Slice((*byte)(unsafe.Pointer(marshalledPubKey)), marshalledPubKeyLen) | ||
2380 | |||
2381 | if !bytes.Equal(ek, gotEk) { | ||
2382 | fmt.Printf("FAIL: %s marshalledPubKey mismatch\n", wt) | ||
2383 | return false | ||
2384 | } | ||
2385 | |||
2386 | c, cLen := mustDecodeHexString(wt.C, "c") | ||
2387 | |||
2388 | var sharedSecret *C.uchar | ||
2389 | var sharedSecretLen C.size_t | ||
2390 | defer C.free(unsafe.Pointer(sharedSecret)) | ||
2391 | if C.MLKEM_decap(privKey, (*C.uchar)(unsafe.Pointer(&c[0])), C.size_t(cLen), (**C.uchar)(unsafe.Pointer(&sharedSecret)), (*C.size_t)(unsafe.Pointer(&sharedSecretLen))) != 1 { | ||
2392 | fmt.Printf("%s - MLKEM_decap failed\n", wt) | ||
2393 | return false | ||
2394 | } | ||
2395 | gotK := unsafe.Slice((*byte)(unsafe.Pointer(sharedSecret)), sharedSecretLen) | ||
2396 | |||
2397 | k, _ := mustDecodeHexString(wt.K, "K") | ||
2398 | |||
2399 | if !bytes.Equal(k, gotK) { | ||
2400 | fmt.Printf("FAIL: %s sharedSecret mismatch\n", wt) | ||
2401 | return false | ||
2402 | } | ||
2403 | |||
2404 | return true | ||
2405 | } | ||
2406 | |||
2407 | func runMLKEMEncapsTestGroup(rank C.int, wt *wycheproofTestMLKEM) bool { | ||
2408 | pubKey := C.MLKEM_public_key_new(rank) | ||
2409 | defer C.MLKEM_public_key_free(pubKey) | ||
2410 | if pubKey == nil { | ||
2411 | log.Fatal("MLKEM_public_key_new failed") | ||
2412 | } | ||
2413 | |||
2414 | ek, ekLen := mustDecodeHexString(wt.C, "eK") | ||
2415 | |||
2416 | if C.MLKEM_parse_public_key(pubKey, (*C.uchar)(unsafe.Pointer(&ek[0])), (C.size_t)(ekLen)) != 0 || wt.Result != "invalid" { | ||
2417 | fmt.Printf("FAIL: %s MLKEM_parse_public_key succeeded\n", wt) | ||
2418 | return false | ||
2419 | } | ||
2420 | |||
2421 | return true | ||
2422 | } | ||
2423 | |||
2424 | func (wtg *wycheproofTestGroupMLKEM) run(algorithm string, variant testVariant) bool { | ||
2425 | var rank C.int | ||
2426 | |||
2427 | switch wtg.ParameterSet { | ||
2428 | case "ML-KEM-512": | ||
2429 | fmt.Printf("INFO: skipping %v test group of type %v for %s\n", algorithm, wtg.Type, wtg.ParameterSet) | ||
2430 | return true | ||
2431 | case "ML-KEM-768": | ||
2432 | rank = C.RANK768 | ||
2433 | case "ML-KEM-1024": | ||
2434 | rank = C.RANK1024 | ||
2435 | default: | ||
2436 | log.Fatalf("Unknown ML-KEM parameterSet %v", wtg.ParameterSet) | ||
2437 | } | ||
2438 | fmt.Printf("Running %v test group of type %v\n", algorithm, wtg.Type) | ||
2439 | |||
2440 | type MLKEMTestFunc func(C.int, *wycheproofTestMLKEM) bool | ||
2441 | var runTest MLKEMTestFunc | ||
2442 | |||
2443 | switch wtg.Type { | ||
2444 | case "MLKEMTest": | ||
2445 | runTest = runMLKEMTestGroup | ||
2446 | case "MLKEMEncapsTest": | ||
2447 | runTest = runMLKEMEncapsTestGroup | ||
2448 | default: | ||
2449 | log.Fatalf("Unknown ML-KEM test type %v", wtg.Type) | ||
2450 | } | ||
2451 | |||
2452 | success := true | ||
2453 | for _, wt := range wtg.Tests { | ||
2454 | if !runTest(rank, wt) { | ||
2455 | success = false | ||
2456 | } | ||
2457 | } | ||
2458 | return success | ||
2459 | } | ||
2460 | |||
2324 | func runPrimalityTest(wt *wycheproofTestPrimality) bool { | 2461 | func runPrimalityTest(wt *wycheproofTestPrimality) bool { |
2325 | bnValue := mustConvertBigIntToBigNum(wt.Value) | 2462 | bnValue := mustConvertBigIntToBigNum(wt.Value) |
2326 | defer C.BN_free(bnValue) | 2463 | defer C.BN_free(bnValue) |
@@ -2814,7 +2951,7 @@ func testGroupFromTestVector(wtv *wycheproofTestVectorsV1) (wycheproofTestGroupR | |||
2814 | case "ML-DSA-44", "ML-DSA-65", "ML-DSA-87": | 2951 | case "ML-DSA-44", "ML-DSA-65", "ML-DSA-87": |
2815 | return nil, Skip | 2952 | return nil, Skip |
2816 | case "ML-KEM": | 2953 | case "ML-KEM": |
2817 | return nil, Skip | 2954 | return &wycheproofTestGroupMLKEM{}, Normal |
2818 | case "MORUS640", "MORUS1280": | 2955 | case "MORUS640", "MORUS1280": |
2819 | return nil, Skip | 2956 | return nil, Skip |
2820 | case "PbeWithHmacSha1AndAes_128", "PbeWithHmacSha1AndAes_192", "PbeWithHmacSha1AndAes_256", "PbeWithHmacSha224AndAes_128", "PbeWithHmacSha224AndAes_192", "PbeWithHmacSha224AndAes_256", "PbeWithHmacSha256AndAes_128", "PbeWithHmacSha256AndAes_192", "PbeWithHmacSha256AndAes_256", "PbeWithHmacSha384AndAes_128", "PbeWithHmacSha384AndAes_192", "PbeWithHmacSha384AndAes_256", "PbeWithHmacSha512AndAes_128", "PbeWithHmacSha512AndAes_192", "PbeWithHmacSha512AndAes_256": | 2957 | case "PbeWithHmacSha1AndAes_128", "PbeWithHmacSha1AndAes_192", "PbeWithHmacSha1AndAes_256", "PbeWithHmacSha224AndAes_128", "PbeWithHmacSha224AndAes_192", "PbeWithHmacSha224AndAes_256", "PbeWithHmacSha256AndAes_128", "PbeWithHmacSha256AndAes_192", "PbeWithHmacSha256AndAes_256", "PbeWithHmacSha384AndAes_128", "PbeWithHmacSha384AndAes_192", "PbeWithHmacSha384AndAes_256", "PbeWithHmacSha512AndAes_128", "PbeWithHmacSha512AndAes_192", "PbeWithHmacSha512AndAes_256": |