/
githubmirror
/
libgcrypt
Обзор
Документация
Войти
/
githubmirror
/
libgcrypt
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
tests/t-kem.c
680 строк
19 KB
NIIBE Yutaka
tests:kem: Don't emit a message each time, but once.
07 апр 2026, 04:11
Не верифицирован
07 апр 2026, 04:11
460695d
Код
Авторство
О чём код?
/* t-kem.c - KEM regression tests * Copyright (C) 2023 Simon Josefsson <simon@josefsson.org> * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see <https://www.gnu.org/licenses/>. * SPDX-License-Identifier: LGPL-2.1-or-later */ #ifdef HAVE_CONFIG_H #include <config.h> #endif #include <stdio.h> #include <stdint.h> #include "stopwatch.h" #define PGM "t-kem" #define NEED_SHOW_NOTE #include "t-common.h" #define N_TESTS 10 static int in_fips_mode; static void test_kem_sntrup761 (int testno) { gcry_error_t err; uint8_t pubkey[GCRY_KEM_SNTRUP761_PUBKEY_LEN]; uint8_t seckey[GCRY_KEM_SNTRUP761_SECKEY_LEN]; uint8_t ciphertext[GCRY_KEM_SNTRUP761_ENCAPS_LEN]; uint8_t key1[GCRY_KEM_SNTRUP761_SHARED_LEN]; uint8_t key2[GCRY_KEM_SNTRUP761_SHARED_LEN]; err = gcry_kem_genkey (GCRY_KEM_SNTRUP761, pubkey, GCRY_KEM_SNTRUP761_PUBKEY_LEN, seckey, GCRY_KEM_SNTRUP761_SECKEY_LEN, NULL, 0); if (err) { fail ("gcry_kem_genkey %d: %s", testno, gpg_strerror (err)); return; } err = gcry_kem_encap (GCRY_KEM_SNTRUP761, pubkey, GCRY_KEM_SNTRUP761_PUBKEY_LEN, ciphertext, GCRY_KEM_SNTRUP761_ENCAPS_LEN, key1, GCRY_KEM_SNTRUP761_SHARED_LEN, NULL, 0); if (err) { fail ("gcry_kem_encap %d: %s", testno, gpg_strerror (err)); return; } err = gcry_kem_decap (GCRY_KEM_SNTRUP761, seckey, GCRY_KEM_SNTRUP761_SECKEY_LEN, ciphertext, GCRY_KEM_SNTRUP761_ENCAPS_LEN, key2, GCRY_KEM_SNTRUP761_SHARED_LEN, NULL, 0); if (err) { fail ("gcry_kem_decap %d: %s", testno, gpg_strerror (err)); return; } if (memcmp (key1, key2, GCRY_KEM_SNTRUP761_SHARED_LEN) != 0) { size_t i; fail ("sntrup761 test %d failed: mismatch\n", testno); fputs ("key1:", stderr); for (i = 0; i < GCRY_KEM_SNTRUP761_SHARED_LEN; i++) fprintf (stderr, " %02x", key1[i]); putc ('\n', stderr); fputs ("key2:", stderr); for (i = 0; i < GCRY_KEM_SNTRUP761_SHARED_LEN; i++) fprintf (stderr, " %02x", key2[i]); putc ('\n', stderr); } } static void test_kem_mceliece6688128f (int testno) { gcry_error_t err; uint8_t pubkey[GCRY_KEM_CM6688128F_PUBKEY_LEN]; uint8_t seckey[GCRY_KEM_CM6688128F_SECKEY_LEN]; uint8_t ciphertext[GCRY_KEM_CM6688128F_ENCAPS_LEN]; uint8_t key1[GCRY_KEM_CM6688128F_SHARED_LEN]; uint8_t key2[GCRY_KEM_CM6688128F_SHARED_LEN]; err = gcry_kem_genkey (GCRY_KEM_CM6688128F, pubkey, GCRY_KEM_CM6688128F_PUBKEY_LEN, seckey, GCRY_KEM_CM6688128F_SECKEY_LEN, NULL, 0); if (err) { fail ("gcry_kem_genkey %d: %s", testno, gpg_strerror (err)); return; } err = gcry_kem_encap (GCRY_KEM_CM6688128F, pubkey, GCRY_KEM_CM6688128F_PUBKEY_LEN, ciphertext, GCRY_KEM_CM6688128F_ENCAPS_LEN, key1, GCRY_KEM_CM6688128F_SHARED_LEN, NULL, 0); if (err) { fail ("gcry_kem_encap %d: %s", testno, gpg_strerror (err)); return; } err = gcry_kem_decap (GCRY_KEM_CM6688128F, seckey, GCRY_KEM_CM6688128F_SECKEY_LEN, ciphertext, GCRY_KEM_CM6688128F_ENCAPS_LEN, key2, GCRY_KEM_CM6688128F_SHARED_LEN, NULL, 0); if (err) { fail ("gcry_kem_decap %d: %s", testno, gpg_strerror (err)); return; } if (memcmp (key1, key2, GCRY_KEM_CM6688128F_SHARED_LEN) != 0) { size_t i; fail ("cm6688128f test %d failed: mismatch\n", testno); fputs ("key1:", stderr); for (i = 0; i < GCRY_KEM_CM6688128F_SHARED_LEN; i++) fprintf (stderr, " %02x", key1[i]); putc ('\n', stderr); fputs ("key2:", stderr); for (i = 0; i < GCRY_KEM_CM6688128F_SHARED_LEN; i++) fprintf (stderr, " %02x", key2[i]); putc ('\n', stderr); } } #ifdef USE_KYBER static void test_kem_mlkem512 (int testno) { gcry_error_t err; uint8_t pubkey[GCRY_KEM_MLKEM512_PUBKEY_LEN]; uint8_t seckey[GCRY_KEM_MLKEM512_SECKEY_LEN]; uint8_t ciphertext[GCRY_KEM_MLKEM512_ENCAPS_LEN]; uint8_t key1[GCRY_KEM_MLKEM512_SHARED_LEN]; uint8_t key2[GCRY_KEM_MLKEM512_SHARED_LEN]; err = gcry_kem_genkey (GCRY_KEM_MLKEM512, pubkey, GCRY_KEM_MLKEM512_PUBKEY_LEN, seckey, GCRY_KEM_MLKEM512_SECKEY_LEN, NULL, 0); if (err) { fail ("gcry_kem_genkey %d: %s", testno, gpg_strerror (err)); return; } err = gcry_kem_encap (GCRY_KEM_MLKEM512, pubkey, GCRY_KEM_MLKEM512_PUBKEY_LEN, ciphertext, GCRY_KEM_MLKEM512_ENCAPS_LEN, key1, GCRY_KEM_MLKEM512_SHARED_LEN, NULL, 0); if (err) { fail ("gcry_kem_encap %d: %s", testno, gpg_strerror (err)); return; } err = gcry_kem_decap (GCRY_KEM_MLKEM512, seckey, GCRY_KEM_MLKEM512_SECKEY_LEN, ciphertext, GCRY_KEM_MLKEM512_ENCAPS_LEN, key2, GCRY_KEM_MLKEM512_SHARED_LEN, NULL, 0); if (err) { fail ("gcry_kem_decap %d: %s", testno, gpg_strerror (err)); return; } if (memcmp (key1, key2, GCRY_KEM_MLKEM512_SHARED_LEN) != 0) { size_t i; fail ("mlkem512 test %d failed: mismatch\n", testno); fputs ("key1:", stderr); for (i = 0; i < GCRY_KEM_MLKEM512_SHARED_LEN; i++) fprintf (stderr, " %02x", key1[i]); putc ('\n', stderr); fputs ("key2:", stderr); for (i = 0; i < GCRY_KEM_MLKEM512_SHARED_LEN; i++) fprintf (stderr, " %02x", key2[i]); putc ('\n', stderr); } } static void test_kem_mlkem768 (int testno) { gcry_error_t err; uint8_t pubkey[GCRY_KEM_MLKEM768_PUBKEY_LEN]; uint8_t seckey[GCRY_KEM_MLKEM768_SECKEY_LEN]; uint8_t ciphertext[GCRY_KEM_MLKEM768_ENCAPS_LEN]; uint8_t key1[GCRY_KEM_MLKEM768_SHARED_LEN]; uint8_t key2[GCRY_KEM_MLKEM768_SHARED_LEN]; err = gcry_kem_genkey (GCRY_KEM_MLKEM768, pubkey, GCRY_KEM_MLKEM768_PUBKEY_LEN, seckey, GCRY_KEM_MLKEM768_SECKEY_LEN, NULL, 0); if (err) { fail ("gcry_kem_genkey %d: %s", testno, gpg_strerror (err)); return; } err = gcry_kem_encap (GCRY_KEM_MLKEM768, pubkey, GCRY_KEM_MLKEM768_PUBKEY_LEN, ciphertext, GCRY_KEM_MLKEM768_ENCAPS_LEN, key1, GCRY_KEM_MLKEM768_SHARED_LEN, NULL, 0); if (err) { fail ("gcry_kem_encap %d: %s", testno, gpg_strerror (err)); return; } err = gcry_kem_decap (GCRY_KEM_MLKEM768, seckey, GCRY_KEM_MLKEM768_SECKEY_LEN, ciphertext, GCRY_KEM_MLKEM768_ENCAPS_LEN, key2, GCRY_KEM_MLKEM768_SHARED_LEN, NULL, 0); if (err) { fail ("gcry_kem_decap %d: %s", testno, gpg_strerror (err)); return; } if (memcmp (key1, key2, GCRY_KEM_MLKEM768_SHARED_LEN) != 0) { size_t i; fail ("mlkem768 test %d failed: mismatch\n", testno); fputs ("key1:", stderr); for (i = 0; i < GCRY_KEM_MLKEM768_SHARED_LEN; i++) fprintf (stderr, " %02x", key1[i]); putc ('\n', stderr); fputs ("key2:", stderr); for (i = 0; i < GCRY_KEM_MLKEM768_SHARED_LEN; i++) fprintf (stderr, " %02x", key2[i]); putc ('\n', stderr); } } static void test_kem_mlkem1024 (int testno) { gcry_error_t err; uint8_t pubkey[GCRY_KEM_MLKEM1024_PUBKEY_LEN]; uint8_t seckey[GCRY_KEM_MLKEM1024_SECKEY_LEN]; uint8_t ciphertext[GCRY_KEM_MLKEM1024_ENCAPS_LEN]; uint8_t key1[GCRY_KEM_MLKEM1024_SHARED_LEN]; uint8_t key2[GCRY_KEM_MLKEM1024_SHARED_LEN]; err = gcry_kem_genkey (GCRY_KEM_MLKEM1024, pubkey, GCRY_KEM_MLKEM1024_PUBKEY_LEN, seckey, GCRY_KEM_MLKEM1024_SECKEY_LEN, NULL, 0); if (err) { fail ("gcry_kem_genkey %d: %s", testno, gpg_strerror (err)); return; } err = gcry_kem_encap (GCRY_KEM_MLKEM1024, pubkey, GCRY_KEM_MLKEM1024_PUBKEY_LEN, ciphertext, GCRY_KEM_MLKEM1024_ENCAPS_LEN, key1, GCRY_KEM_MLKEM1024_SHARED_LEN, NULL, 0); if (err) { fail ("gcry_kem_encap %d: %s", testno, gpg_strerror (err)); return; } err = gcry_kem_decap (GCRY_KEM_MLKEM1024, seckey, GCRY_KEM_MLKEM1024_SECKEY_LEN, ciphertext, GCRY_KEM_MLKEM1024_ENCAPS_LEN, key2, GCRY_KEM_MLKEM1024_SHARED_LEN, NULL, 0); if (err) { fail ("gcry_kem_decap %d: %s", testno, gpg_strerror (err)); return; } if (memcmp (key1, key2, GCRY_KEM_MLKEM1024_SHARED_LEN) != 0) { size_t i; fail ("mlkem1024 test %d failed: mismatch\n", testno); fputs ("key1:", stderr); for (i = 0; i < GCRY_KEM_MLKEM1024_SHARED_LEN; i++) fprintf (stderr, " %02x", key1[i]); putc ('\n', stderr); fputs ("key2:", stderr); for (i = 0; i < GCRY_KEM_MLKEM1024_SHARED_LEN; i++) fprintf (stderr, " %02x", key2[i]); putc ('\n', stderr); } } #endif static void test_kem_raw_x25519 (int testno) { gcry_error_t err; uint8_t pubkey[GCRY_KEM_ECC_X25519_PUBKEY_LEN]; uint8_t seckey[GCRY_KEM_ECC_X25519_SECKEY_LEN]; uint8_t ciphertext[GCRY_KEM_ECC_X25519_ENCAPS_LEN]; uint8_t key1[GCRY_KEM_RAW_X25519_SHARED_LEN]; uint8_t key2[GCRY_KEM_RAW_X25519_SHARED_LEN]; info (" Checking X25519.\n"); err = gcry_kem_genkey (GCRY_KEM_RAW_X25519, pubkey, GCRY_KEM_ECC_X25519_PUBKEY_LEN, seckey, GCRY_KEM_ECC_X25519_SECKEY_LEN, NULL, 0); if (in_fips_mode) { if (!err) fail ("gcry_kem_genkey is not expected to work in FIPS mode for test %d", testno); if (verbose > 1) info ("not executed in FIPS mode\n"); return; } if (err) { fail ("gcry_kem_genkey %d: %s", testno, gpg_strerror (err)); return; } err = gcry_kem_encap (GCRY_KEM_RAW_X25519, pubkey, GCRY_KEM_ECC_X25519_PUBKEY_LEN, ciphertext, GCRY_KEM_ECC_X25519_ENCAPS_LEN, key1, GCRY_KEM_RAW_X25519_SHARED_LEN, NULL, 0); if (err) { fail ("gcry_kem_encap %d: %s", testno, gpg_strerror (err)); return; } err = gcry_kem_decap (GCRY_KEM_RAW_X25519, seckey, GCRY_KEM_ECC_X25519_SECKEY_LEN, ciphertext, GCRY_KEM_ECC_X25519_ENCAPS_LEN, key2, GCRY_KEM_RAW_X25519_SHARED_LEN, NULL, 0); if (err) { fail ("gcry_kem_decap %d: %s", testno, gpg_strerror (err)); return; } if (memcmp (key1, key2, GCRY_KEM_RAW_X25519_SHARED_LEN) != 0) { size_t i; fail ("raw-x25519 test %d failed: mismatch\n", testno); fputs ("key1:", stderr); for (i = 0; i < GCRY_KEM_RAW_X25519_SHARED_LEN; i++) fprintf (stderr, " %02x", key1[i]); putc ('\n', stderr); fputs ("key2:", stderr); for (i = 0; i < GCRY_KEM_RAW_X25519_SHARED_LEN; i++) fprintf (stderr, " %02x", key2[i]); putc ('\n', stderr); } } static void test_kem_dhkem_x25519 (int testno) { gcry_error_t err; uint8_t pubkey[GCRY_KEM_DHKEM25519_PUBKEY_LEN]; uint8_t seckey[GCRY_KEM_DHKEM25519_SECKEY_LEN]; uint8_t ciphertext[GCRY_KEM_DHKEM25519_ENCAPS_LEN]; uint8_t key1[GCRY_KEM_DHKEM25519_SHARED_LEN]; uint8_t key2[GCRY_KEM_DHKEM25519_SHARED_LEN]; info (" Checking DHKEM25519.\n"); err = gcry_kem_genkey (GCRY_KEM_DHKEM25519, pubkey, GCRY_KEM_DHKEM25519_PUBKEY_LEN, seckey, GCRY_KEM_DHKEM25519_SECKEY_LEN, NULL, 0); if (in_fips_mode) { if (!err) fail ("gcry_kem_genkey is not expected to work in FIPS mode for test %d", testno); if (verbose > 1) info ("not executed in FIPS mode\n"); return; } if (err) { fail ("gcry_kem_genkey %d: %s", testno, gpg_strerror (err)); return; } err = gcry_kem_encap (GCRY_KEM_DHKEM25519, pubkey, GCRY_KEM_DHKEM25519_PUBKEY_LEN, ciphertext, GCRY_KEM_DHKEM25519_ENCAPS_LEN, key1, GCRY_KEM_DHKEM25519_SHARED_LEN, NULL, 0); if (err) { fail ("gcry_kem_encap %d: %s", testno, gpg_strerror (err)); return; } err = gcry_kem_decap (GCRY_KEM_DHKEM25519, seckey, GCRY_KEM_DHKEM25519_SECKEY_LEN, ciphertext, GCRY_KEM_DHKEM25519_ENCAPS_LEN, key2, GCRY_KEM_DHKEM25519_SHARED_LEN, pubkey, GCRY_KEM_DHKEM25519_PUBKEY_LEN); if (err) { fail ("gcry_kem_decap %d: %s", testno, gpg_strerror (err)); return; } if (memcmp (key1, key2, GCRY_KEM_DHKEM25519_SHARED_LEN) != 0) { size_t i; fail ("dhkem-x25519 test %d failed: mismatch\n", testno); fputs ("key1:", stderr); for (i = 0; i < GCRY_KEM_DHKEM25519_SHARED_LEN; i++) fprintf (stderr, " %02x", key1[i]); putc ('\n', stderr); fputs ("key2:", stderr); for (i = 0; i < GCRY_KEM_DHKEM25519_SHARED_LEN; i++) fprintf (stderr, " %02x", key2[i]); putc ('\n', stderr); } } #define SELECTED_ALGO_SNTRUP761 (1 << 0) #define SELECTED_ALGO_MLKEM512 (1 << 1) #define SELECTED_ALGO_MLKEM768 (1 << 2) #define SELECTED_ALGO_MLKEM1024 (1 << 3) #define SELECTED_ALGO_RAW_X25519 (1 << 4) #define SELECTED_ALGO_DHKEM25519 (1 << 5) #define SELECTED_ALGO_CM6688128F (1 << 6) static unsigned int selected_algo; static void check_kem (int n_loops) { int ntests; int testno; info ("Checking KEM.\n"); ntests = 0; if ((selected_algo & SELECTED_ALGO_SNTRUP761)) { info (" Checking SNTRUP761.\n"); for (testno = 0; testno < n_loops; testno++) test_kem_sntrup761 (testno); ntests += n_loops; } if ((selected_algo & SELECTED_ALGO_CM6688128F)) { info (" Checking CM6688128F.\n"); for (testno = 0; testno < n_loops; testno++) test_kem_mceliece6688128f (testno); ntests += n_loops; } #ifdef USE_KYBER if ((selected_algo & SELECTED_ALGO_MLKEM512)) { info (" Checking MLKEM512.\n"); for (testno = 0; testno < ntests + n_loops; testno++) test_kem_mlkem512 (testno); ntests += n_loops; } if ((selected_algo & SELECTED_ALGO_MLKEM768)) { info (" Checking MLKEM768.\n"); for (testno = 0; testno < ntests + n_loops; testno++) test_kem_mlkem768 (testno); ntests += n_loops; } if ((selected_algo & SELECTED_ALGO_MLKEM1024)) { info (" Checking MLKEM1024.\n"); for (testno = 0; testno < ntests + n_loops; testno++) test_kem_mlkem1024 (testno); ntests += n_loops; } #endif if ((selected_algo & SELECTED_ALGO_RAW_X25519)) { for (testno = 0; testno < ntests + n_loops; testno++) test_kem_raw_x25519 (testno); ntests += n_loops; } if ((selected_algo & SELECTED_ALGO_DHKEM25519)) { for (testno = 0; testno < ntests + n_loops; testno++) test_kem_dhkem_x25519 (testno); ntests += n_loops; } show_note ("%d tests done\n", ntests); } int main (int argc, char **argv) { int last_argc = -1; int n_loops = N_TESTS; if (argc) { argc--; argv++; } selected_algo = ~0; /* Default is all algos. */ while (argc && last_argc != argc) { last_argc = argc; if (!strcmp (*argv, "--")) { argc--; argv++; break; } else if (!strcmp (*argv, "--help")) { usage: fputs ("usage: " PGM " [options]\n" "Options:\n" " --verbose print timings etc.\n" " --debug flyswatter\n" " --loops N specify the loop count\n" " --sntrup761 select SNTRUP761 algo\n" " --cm6688128f select CM6688128F algo\n" #ifdef USE_KYBER " --mlkem512 select MLKEM512 algo\n" " --mlkem768 select MLKEM768 algo\n" " --mlkem1024 select MLKEM1024 algo\n" #endif " --dhkem25519 select DHKEM25519 algo\n", stdout); exit (0); } else if (!strcmp (*argv, "--verbose")) { verbose++; argc--; argv++; } else if (!strcmp (*argv, "--debug")) { verbose += 2; debug++; argc--; argv++; } else if (!strcmp (*argv, "--loops")) { argc--; argv++; if (!argc) goto usage; n_loops = atoi (*argv); argc--; argv++; } else if (!strcmp (*argv, "--sntrup761")) { selected_algo = SELECTED_ALGO_SNTRUP761; argc--; argv++; } else if (!strcmp (*argv, "--cm6688128f")) { selected_algo = SELECTED_ALGO_CM6688128F; argc--; argv++; } #ifdef USE_KYBER else if (!strcmp (*argv, "--mlkem512")) { selected_algo = SELECTED_ALGO_MLKEM512; argc--; argv++; } else if (!strcmp (*argv, "--mlkem768")) { selected_algo = SELECTED_ALGO_MLKEM768; argc--; argv++; } else if (!strcmp (*argv, "--mlkem1024")) { selected_algo = SELECTED_ALGO_MLKEM1024; argc--; argv++; } #endif else if (!strcmp (*argv, "--raw-x25519")) { selected_algo = SELECTED_ALGO_RAW_X25519; argc--; argv++; } else if (!strcmp (*argv, "--dhkem25519")) { selected_algo = SELECTED_ALGO_DHKEM25519; argc--; argv++; } else if (!strncmp (*argv, "--", 2)) die ("unknown option '%s'", *argv); } xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0)); if (!gcry_check_version (GCRYPT_VERSION)) die ("version mismatch\n"); if (debug) xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u, 0)); xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); if (gcry_fips_mode_active ()) in_fips_mode = 1; start_timer (); check_kem (n_loops); stop_timer (); info ("All tests completed in %s. Errors: %d\n", elapsed_time (1), error_count); return !!error_count; }