summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authortb <>2025-09-14 17:03:28 +0000
committertb <>2025-09-14 17:03:28 +0000
commitda62f2d5a634074faef81fcd126a41abdc3b0ae2 (patch)
treed584fa4a5a8b8066a65435afa668bc2bb962fff2 /src
parent4c3431c42271c25d676afc9be6b449390cc67152 (diff)
downloadopenbsd-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.go141
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
501type 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
513func (wt *wycheproofTestMLKEM) String() string {
514 return wycheproofFormatTestCase(wt.TCID, wt.Comment, wt.Flags, wt.Result)
515}
516
517type wycheproofTestGroupMLKEM struct {
518 Type string `json:"type"`
519 ParameterSet string `json:"parameterSet"`
520 Tests []*wycheproofTestMLKEM `json:"tests"`
521}
522
500type wycheproofTestPrimality struct { 523type 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
2347func 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
2407func 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
2424func (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
2324func runPrimalityTest(wt *wycheproofTestPrimality) bool { 2461func 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":