tests/pkcs11/pkcs11-rsa-pss-privkey-test
tests/pkcs11/tls-neg-pkcs11-key
tests/pkcs11/tls-neg-pkcs11-no-key
+tests/pkcs11-provider/pkcs11-provider-cipher
+tests/pkcs11-provider/pkcs11-provider-hmac
+tests/pkcs11-provider/pkcs11-provider-pk
+tests/pkcs11-provider/pkcs11-provider-sig
tests/pkcs12-decode/Makefile
tests/pkcs12-decode/Makefile.in
tests/pkcs12_encode
indirect_tests += rsaes-pkcs1-v1_5
rsaes_pkcs1_v1_5_SOURCES = rsaes-pkcs1-v1_5.c
rsaes_pkcs1_v1_5_LDADD = $(COMMON_GNUTLS_LDADD)
+
+dist_check_SCRIPTS += pkcs11-provider/test-pkcs11-provider.sh
+indirect_tests += pkcs11-provider/pkcs11-provider-pk \
+ pkcs11-provider/pkcs11-provider-sig \
+ pkcs11-provider/pkcs11-provider-cipher \
+ pkcs11-provider/pkcs11-provider-hmac
+pkcs11_provider_pk_SOURCES = pkcs11-provider/pkcs11-provider-pk.c
+pkcs11_provider_sig_SOURCES = pkcs11-provider/pkcs11-provider-sig.c
+pkcs11_provider_cipher_SOURCES = pkcs11-provider/pkcs11-provider-cipher.c
+pkcs11_provider_hmac_SOURCES = pkcs11-provider/pkcs11-provider-hmac.c
+pkcs11_provider_pk_LDADD = $(LDADD)
+pkcs11_provider_sig_LDADD = $(LDADD)
+pkcs11_provider_cipher_LDADD = $(LDADD)
+pkcs11_provider_hmac_LDADD = $(LDADD)
endif
dist_check_SCRIPTS += gnutls-cli-self-signed.sh gnutls-cli-invalid-crl.sh gnutls-cli-rawpk.sh
--- /dev/null
+/*
+ * Copyright (C) 2025 Red Hat, Inc.
+ *
+ * Author: Zoltan Fridrich
+ *
+ * This file is part of GnuTLS.
+ *
+ * GnuTLS is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuTLS 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
+ * 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/>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/crypto.h>
+
+static int test_cipher(const char *alg_str, int alg)
+{
+ int ret;
+ gnutls_cipher_hd_t ch;
+ gnutls_datum_t key, iv;
+ uint8_t key16[64], iv16[32], ptext[128], data[128];
+
+ key.data = key16;
+ key.size = gnutls_cipher_get_key_size(alg);
+ assert(key.size <= sizeof(key16));
+
+ iv.data = iv16;
+ iv.size = gnutls_cipher_get_iv_size(alg);
+ assert(iv.size <= sizeof(iv16));
+
+ memset(iv.data, 0xff, iv.size);
+ memset(key.data, 0xfe, key.size);
+ memset(ptext, 0xfa, sizeof(ptext));
+ memset(data, 0xfa, sizeof(data));
+
+ printf("Testing %s encrypt-decrypt\n", alg_str);
+
+ ret = gnutls_cipher_init(&ch, alg, &key, &iv);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_cipher_init: %s\n",
+ gnutls_strerror(ret));
+ return ret;
+ }
+
+ ret = gnutls_cipher_encrypt(ch, data, sizeof(data));
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_cipher_encrypt: %s\n",
+ gnutls_strerror(ret));
+ return ret;
+ }
+
+ ret = gnutls_cipher_decrypt(ch, data, sizeof(data));
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_cipher_decrypt: %s\n",
+ gnutls_strerror(ret));
+ return ret;
+ }
+
+ if (memcmp(data, ptext, sizeof(ptext)) != 0) {
+ fprintf(stderr, "Decrypted data don't match original\n");
+ return -1;
+ }
+
+ printf("ok\n");
+
+ gnutls_cipher_deinit(ch);
+ return 0;
+}
+
+static int test_aead(const char *alg_str, int alg)
+{
+ int ret;
+ gnutls_aead_cipher_hd_t ch;
+ gnutls_datum_t key, iv;
+ size_t out_len, ctext_len, tag_len;
+ uint8_t key16[64], iv16[32], auth[32], ptext[128];
+ uint8_t ctext[128 + 32] = { 0 };
+ uint8_t out[128] = { 0 };
+
+ key.data = key16;
+ key.size = gnutls_cipher_get_key_size(alg);
+ assert(key.size <= sizeof(key16));
+
+ iv.data = iv16;
+ iv.size = gnutls_cipher_get_iv_size(alg);
+ assert(iv.size <= sizeof(iv16));
+
+ tag_len = gnutls_cipher_get_tag_size(alg);
+
+ memset(iv.data, 0xff, iv.size);
+ memset(key.data, 0xfe, key.size);
+ memset(ptext, 0xfa, sizeof(ptext));
+ memset(auth, 0xfb, sizeof(auth));
+
+ printf("Testing %s AEAD encrypt-decrypt\n", alg_str);
+
+ ret = gnutls_aead_cipher_init(&ch, alg, &key);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_aead_cipher_init: %s\n",
+ gnutls_strerror(ret));
+ return ret;
+ }
+
+ ctext_len = sizeof(ctext);
+ ret = gnutls_aead_cipher_encrypt(ch, iv.data, iv.size, auth,
+ sizeof(auth), tag_len, ptext,
+ sizeof(ptext), ctext, &ctext_len);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_aead_cipher_encrypt: %s\n",
+ gnutls_strerror(ret));
+ return ret;
+ }
+
+ if (ctext_len != sizeof(ptext) + tag_len) {
+ fprintf(stderr, "output ciphertext length mismatch\n");
+ return -1;
+ }
+
+ out_len = sizeof(out);
+ ret = gnutls_aead_cipher_decrypt(ch, iv.data, iv.size, auth,
+ sizeof(auth), tag_len, ctext,
+ ctext_len, out, &out_len);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_aead_cipher_decrypt\n");
+ return ret;
+ }
+
+ if (out_len != sizeof(ptext) ||
+ memcmp(out, ptext, sizeof(ptext)) != 0) {
+ fprintf(stderr, "mismatch of decrypted data\n");
+ return -1;
+ }
+
+ printf("ok\n");
+
+ gnutls_aead_cipher_deinit(ch);
+ return 0;
+}
+
+int main(void)
+{
+ int ret;
+
+ gnutls_global_init();
+
+ ret = test_cipher("aes128-cbc", GNUTLS_CIPHER_AES_128_CBC);
+ if (ret < 0)
+ goto cleanup;
+ ret = test_cipher("aes192-cbc", GNUTLS_CIPHER_AES_192_CBC);
+ if (ret < 0)
+ goto cleanup;
+ ret = test_cipher("aes256-cbc", GNUTLS_CIPHER_AES_256_CBC);
+ if (ret < 0)
+ goto cleanup;
+ ret = test_aead("aes128-gcm", GNUTLS_CIPHER_AES_128_GCM);
+ if (ret < 0)
+ goto cleanup;
+ ret = test_aead("aes192-gcm", GNUTLS_CIPHER_AES_192_GCM);
+ if (ret < 0)
+ goto cleanup;
+ ret = test_aead("aes256-gcm", GNUTLS_CIPHER_AES_256_GCM);
+ if (ret < 0)
+ goto cleanup;
+
+cleanup:
+ gnutls_global_deinit();
+ return ret;
+}
--- /dev/null
+/*
+ * Copyright (C) 2025 Red Hat, Inc.
+ *
+ * Author: Zoltan Fridrich
+ *
+ * This file is part of GnuTLS.
+ *
+ * GnuTLS is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuTLS 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
+ * 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/>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/crypto.h>
+
+static int test_mac(gnutls_mac_algorithm_t alg, const char *key,
+ size_t key_size, const char *ptext, size_t ptext_size,
+ const char *exp_digest)
+{
+ int ret = 0;
+ size_t digest_size = 0;
+ uint8_t *digest = NULL;
+ gnutls_hmac_hd_t hd = NULL;
+
+ digest_size = gnutls_hmac_get_len(alg);
+ digest = gnutls_malloc(digest_size);
+ assert(digest != NULL);
+
+ printf("Testing mac %s\n", gnutls_mac_get_name(alg));
+
+ ret = gnutls_hmac_init(&hd, alg, key, key_size);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_hmac_init: %s\n", gnutls_strerror(ret));
+ goto cleanup;
+ }
+
+ ret = gnutls_hmac(hd, ptext, ptext_size / 2);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_hmac: %s\n", gnutls_strerror(ret));
+ goto cleanup;
+ }
+
+ ret = gnutls_hmac(hd, ptext + (ptext_size / 2),
+ ptext_size - (ptext_size / 2));
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_hmac: %s\n", gnutls_strerror(ret));
+ goto cleanup;
+ }
+
+ gnutls_hmac_output(hd, digest);
+
+ if (memcmp(digest, exp_digest, digest_size) != 0) {
+ fprintf(stderr, "hmac: digest data don't match\n");
+ ret = -1;
+ goto cleanup;
+ }
+
+ ret = gnutls_hmac_fast(alg, key, key_size, ptext, ptext_size, digest);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_hmac_fast: %s\n", gnutls_strerror(ret));
+ goto cleanup;
+ }
+
+ if (memcmp(digest, exp_digest, digest_size) != 0) {
+ fprintf(stderr, "hmac_fast: digest data don't match\n");
+ ret = -1;
+ goto cleanup;
+ }
+
+ printf("ok\n");
+
+cleanup:
+ gnutls_hmac_deinit(hd, NULL);
+ gnutls_free(digest);
+ return ret;
+}
+
+static int test_hash(gnutls_digest_algorithm_t alg, const char *alg_str,
+ const char *text, size_t text_size, const char *exp_digest)
+{
+ int ret = 0;
+ size_t digest_size = 0;
+ uint8_t *digest = NULL;
+ gnutls_hash_hd_t hd = NULL;
+
+ digest_size = gnutls_hash_get_len(alg);
+ digest = gnutls_malloc(digest_size);
+ assert(digest != NULL);
+
+ printf("Testing hash %s\n", alg_str);
+
+ ret = gnutls_hash_init(&hd, alg);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_hash_init: %s\n", gnutls_strerror(ret));
+ goto cleanup;
+ }
+
+ ret = gnutls_hash(hd, text, text_size / 2);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_hash: %s\n", gnutls_strerror(ret));
+ goto cleanup;
+ }
+
+ ret = gnutls_hash(hd, text + (text_size / 2),
+ text_size - (text_size / 2));
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_hash: %s\n", gnutls_strerror(ret));
+ goto cleanup;
+ }
+
+ gnutls_hash_output(hd, digest);
+
+ if (memcmp(digest, exp_digest, digest_size) != 0) {
+ fprintf(stderr, "hash: digest data don't match\n");
+ ret = -1;
+ goto cleanup;
+ }
+
+ ret = gnutls_hash_fast(alg, text, text_size, digest);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_hash_fast: %s\n", gnutls_strerror(ret));
+ goto cleanup;
+ }
+
+ if (memcmp(digest, exp_digest, digest_size) != 0) {
+ fprintf(stderr, "hash_fast: digest data don't match\n");
+ ret = -1;
+ goto cleanup;
+ }
+
+ printf("ok\n");
+
+cleanup:
+ gnutls_hash_deinit(hd, NULL);
+ gnutls_free(digest);
+ return ret;
+}
+
+/*
+static int test_hkdf(gnutls_mac_algorithm_t mac, const char *ikm_hex,
+ const char *salt_hex, const char *info_hex, size_t length,
+ const char *prk_hex, const char *okm_hex)
+{
+ int ret = 0;
+ uint8_t buf[1024];
+ gnutls_datum_t hex, ikm, salt, info, prk, okm;
+
+ printf("Testing HKDF %s\n", gnutls_mac_get_name(mac));
+
+ hex.data = (void *)ikm_hex;
+ hex.size = strlen(ikm_hex);
+ ret = gnutls_hex_decode2(&hex, &ikm);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_hex_decode2: %s\n",
+ gnutls_strerror(ret));
+ return ret;
+ }
+
+ hex.data = (void *)salt_hex;
+ hex.size = strlen(salt_hex);
+ ret = gnutls_hex_decode2(&hex, &salt);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_hex_decode2: %s\n",
+ gnutls_strerror(ret));
+ gnutls_free(ikm.data);
+ return ret;
+ }
+
+ ret = gnutls_hkdf_extract(mac, &ikm, &salt, buf);
+ gnutls_free(ikm.data);
+ gnutls_free(salt.data);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_hkdf_extract: %s\n",
+ gnutls_strerror(ret));
+ return ret;
+ }
+
+ prk.data = buf;
+ prk.size = strlen(prk_hex) / 2;
+ ret = gnutls_hex_encode2(&prk, &hex);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_hex_encode2: %s\n",
+ gnutls_strerror(ret));
+ return ret;
+ }
+
+ if (strcmp((char *)hex.data, prk_hex) != 0) {
+ fprintf(stderr, "HKDF: prk doesn't match: %s != %s\n",
+ (char *)hex.data, prk_hex);
+ gnutls_free(hex.data);
+ return -1;
+ }
+
+ gnutls_free(hex.data);
+
+ hex.data = (void *)info_hex;
+ hex.size = strlen(info_hex);
+ ret = gnutls_hex_decode2(&hex, &info);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_hex_decode2: %s\n",
+ gnutls_strerror(ret));
+ return ret;
+ }
+ ret = gnutls_hkdf_expand(mac, &prk, &info, buf, length);
+ gnutls_free(info.data);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_hkdf_expand: %s\n",
+ gnutls_strerror(ret));
+ return ret;
+ }
+
+ okm.data = buf;
+ okm.size = strlen(okm_hex) / 2;
+ ret = gnutls_hex_encode2(&okm, &hex);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_hex_encode2: %s\n",
+ gnutls_strerror(ret));
+ return ret;
+ }
+
+ if (strcmp((char *)hex.data, okm_hex) != 0) {
+ fprintf(stderr, "HKDF: okm doesn't match: %s != %s\n",
+ (char *)hex.data, okm_hex);
+ gnutls_free(hex.data);
+ return -1;
+ }
+
+ gnutls_free(hex.data);
+ return 0;
+}
+
+static int test_pbkdf2(gnutls_mac_algorithm_t mac, const char *ikm_hex,
+ const char *salt_hex, unsigned iter_count, size_t length,
+ const char *okm_hex)
+{
+ int ret = 0;
+ uint8_t buf[1024];
+ gnutls_datum_t hex, ikm, salt, okm;
+
+ printf("Testing PBKDF2 %s\n", gnutls_mac_get_name(mac));
+
+ hex.data = (void *)ikm_hex;
+ hex.size = strlen(ikm_hex);
+ ret = gnutls_hex_decode2(&hex, &ikm);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_hex_decode2: %s\n",
+ gnutls_strerror(ret));
+ return ret;
+ }
+
+ hex.data = (void *)salt_hex;
+ hex.size = strlen(salt_hex);
+ ret = gnutls_hex_decode2(&hex, &salt);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_hex_decode2: %s\n",
+ gnutls_strerror(ret));
+ gnutls_free(ikm.data);
+ return ret;
+ }
+
+ ret = gnutls_pbkdf2(mac, &ikm, &salt, iter_count, buf, length);
+ gnutls_free(ikm.data);
+ gnutls_free(salt.data);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_pbkdf2: %s\n", gnutls_strerror(ret));
+ return ret;
+ }
+
+ okm.data = buf;
+ okm.size = length;
+ ret = gnutls_hex_encode2(&okm, &hex);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_hex_encode2: %s\n",
+ gnutls_strerror(ret));
+ return ret;
+ }
+
+ if (strcmp((char *)hex.data, okm_hex) != 0) {
+ fprintf(stderr, "PBKDF2: okm doesn't match: %s != %s\n",
+ (char *)hex.data, okm_hex);
+ gnutls_free(hex.data);
+ return -1;
+ }
+
+ gnutls_free(hex.data);
+ return 0;
+}
+*/
+
+static int test_macs(void)
+{
+ return test_mac(GNUTLS_MAC_SHA1, "keykeykeykeykeykeyke", 20, "abcdefgh",
+ 8,
+ "\x30\x7d\xac\x31\x1e\x38\xfa\x70\x92\x30"
+ "\xdd\x27\x97\x27\x32\x45\x4b\x39\x74\x39") < 0 ||
+ test_mac(GNUTLS_MAC_SHA224, "keykeykeykeykeykeykeykeykeyk", 28,
+ "abcdefgh", 8,
+ "\x91\xa1\x39\x7d\x2b\xf7\xcd\xdd\x45\x57"
+ "\x64\x04\x6f\x65\x89\x96\xd5\x1c\x43\x2b"
+ "\xe1\x59\x10\xe8\xf4\x65\x1e\x46") < 0 ||
+ test_mac(GNUTLS_MAC_SHA256, "keykeykeykeykeykeykeykeykeykeyke",
+ 32, "abcdefgh", 8,
+ "\xde\xa4\xbf\x53\x29\x54\x17\xb2\xdb\xb6"
+ "\x75\x14\x31\x12\x49\x75\xb1\xea\x5f\x59"
+ "\x5b\x13\x52\x6a\x31\x21\xf4\x93\x93\x38"
+ "\xfc\x82") < 0 ||
+ test_mac(GNUTLS_MAC_SHA384,
+ "keykeykeykeykeykeykeykeykeykeykeykeykeykeykeykey", 48,
+ "abcdefgh", 8,
+ "\x3a\x83\xdb\x7e\x5d\xdc\x03\x24\x23\x00"
+ "\x0a\x9e\x8a\x81\x4f\x5b\x52\xb9\x49\x9e"
+ "\xb1\xf0\x73\xc2\x5c\x9f\xb9\x38\xc4\x99"
+ "\x13\x80\x22\x6f\x08\xda\x0b\xc0\x56\x40"
+ "\xf4\x09\x26\x60\xb8\xd5\xec\x74") < 0 ||
+ test_mac(
+ GNUTLS_MAC_SHA512,
+ "keykeykeykeykeykeykeykeykeykeykeykeykeykeykeykeykeykeykeykeykeyk",
+ 64, "abcdefgh", 8,
+ "\xc9\x59\x6c\xd2\x87\x90\x75\xd2\xff\x6a"
+ "\x55\x57\x0b\x52\xff\xf9\x0b\x44\xe1\x8d"
+ "\x3f\xec\x5d\xc4\x10\x77\x25\x3b\x60\x6c"
+ "\x14\x0d\x8c\x8d\x29\x08\xbd\x8c\xcf\x7e"
+ "\x5a\x18\x90\xc0\x6f\x86\xf4\xd0\xe6\x33"
+ "\xc2\x93\x59\xbf\x8d\x11\x5a\x2d\xa1\x73"
+ "\xee\x7c\x82\x67") < 0 ||
+ test_mac(GNUTLS_MAC_AES_CMAC_128, "keykeykeykeykeyk", 16,
+ "abcdefgh", 8,
+ "\xbe\x1a\xf8\xa3\xd3\x6e\x0d\xbb\x33\x34"
+ "\xf8\xc5\xe5\xe0\x11\x35") < 0 ||
+ test_mac(GNUTLS_MAC_AES_CMAC_256,
+ "keykeykeykeykeykeykeykeykeykeyke", 32, "abcdefgh", 8,
+ "\x3d\x9c\xe6\xe1\x51\x6f\x17\x86\xb4\x19"
+ "\x4a\x3d\x30\xa8\x08\xf9") < 0;
+}
+
+static int test_hashes(void)
+{
+ return test_hash(GNUTLS_DIG_SHA1, "sha1", "abcdefgh", 8,
+ "\x42\x5a\xf1\x2a\x07\x43\x50\x2b\x32\x2e"
+ "\x93\xa0\x15\xbc\xf8\x68\xe3\x24\xd5\x6a") < 0 ||
+ test_hash(GNUTLS_DIG_SHA224, "sha224", "abcdefgh", 8,
+ "\x17\xeb\x7d\x40\xf0\x35\x6f\x85\x98\xe8"
+ "\x9e\xaf\xad\x5f\x6c\x75\x9b\x1f\x82\x29"
+ "\x75\xd9\xc9\xb7\x37\xc8\xa5\x17") < 0 ||
+ test_hash(GNUTLS_DIG_SHA256, "sha256", "abcdefgh", 8,
+ "\x9c\x56\xcc\x51\xb3\x74\xc3\xba\x18\x92"
+ "\x10\xd5\xb6\xd4\xbf\x57\x79\x0d\x35\x1c"
+ "\x96\xc4\x7c\x02\x19\x0e\xcf\x1e\x43\x06"
+ "\x35\xab") < 0 ||
+ test_hash(GNUTLS_DIG_SHA384, "sha384", "abcdefgh", 8,
+ "\x90\x00\xcd\x7c\xad\xa5\x9d\x1d\x2e\xb8"
+ "\x29\x12\xf7\xf2\x4e\x5e\x69\xcc\x55\x17"
+ "\xf6\x82\x83\xb0\x05\xfa\x27\xc2\x85\xb6"
+ "\x1e\x05\xed\xf1\xad\x1a\x8a\x9b\xde\xd6"
+ "\xfd\x29\xeb\x87\xd7\x5a\xd8\x06") < 0 ||
+ test_hash(GNUTLS_DIG_SHA512, "sha512", "abcdefgh", 8,
+ "\xa3\xa8\xc8\x1b\xc9\x7c\x25\x60\x01\x0d"
+ "\x73\x89\xbc\x88\xaa\xc9\x74\xa1\x04\xe0"
+ "\xe2\x38\x12\x20\xc6\xe0\x84\xc4\xdc\xcd"
+ "\x1d\x2d\x17\xd4\xf8\x6d\xb3\x1c\x2a\x85"
+ "\x1d\xc8\x0e\x66\x81\xd7\x47\x33\xc5\x5d"
+ "\xcd\x03\xdd\x96\xf6\x06\x2c\xdd\xa1\x2a"
+ "\x29\x1a\xe6\xce") < 0;
+ /*
+ test_hash(GNUTLS_DIG_SHA3_224, "sha3-224",
+ "abcdefgh", 8,
+ "\x48\xbf\x2e\x86\x40\xcf\xfe\x77\xb6\x7c"
+ "\x61\x82\xa6\xa4\x7f\x8b\x5a\xf7\x3f\x60"
+ "\xbd\x20\x4e\xf3\x48\x37\x1d\x03") < 0 ||
+ test_hash(GNUTLS_DIG_SHA3_256, "sha3-256",
+ "abcdefgh", 8,
+ "\x3e\x20\x20\x72\x5a\x38\xa4\x8e\xb3\xbb"
+ "\xf7\x57\x67\xf0\x3a\x22\xc6\xb3\xf4\x1f"
+ "\x45\x9c\x83\x13\x09\xb0\x64\x33\xec\x64"
+ "\x97\x79") < 0 ||
+ test_hash(GNUTLS_DIG_SHA3_384, "sha3-384",
+ "abcdefgh", 8,
+ "\xf4\xd9\xfc\x5e\x9f\x44\xeb\x87\xfe\x96"
+ "\x8f\xc8\xe4\xe4\x69\x1e\xb1\xda\xb6\xd8"
+ "\x21\xfb\x77\x55\x0b\x52\x7f\x71\xcc\xfb"
+ "\x1b\xa0\x43\x85\x1b\xb0\x54\xf2\x81\x36"
+ "\x4c\x44\xd8\x54\x19\x04\xdb\x5a") < 0 ||
+ test_hash(GNUTLS_DIG_SHA3_512, "sha3-512",
+ "abcdefgh", 8,
+ "\xc9\xf2\x5e\xee\x75\xab\x4c\xf9\xa8\xcf"
+ "\xd4\x4f\x49\x92\xb2\x82\x07\x9b\x64\xd9"
+ "\x46\x47\xed\xbd\x88\xe8\x18\xe4\x4f\x70"
+ "\x1e\xde\xb4\x50\x81\x8f\x72\x72\xcb\xa7"
+ "\xa2\x02\x05\xb3\x67\x1c\xe1\x99\x1c\xe9"
+ "\xa6\xd2\xdf\x8d\xba\xd6\xe0\xbb\x3e\x50"
+ "\x49\x3d\x7f\xa7") < 0;
+ */
+}
+
+/*
+static int test_kdfs(void)
+{
+ return test_hkdf(GNUTLS_MAC_SHA256,
+ "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+ "000102030405060708090a0b0c", "f0f1f2f3f4f5f6f7f8f9",
+ 42,
+ "077709362c2e32df0ddc3f0dc47bba6390b6c73bb"
+ "50f9c3122ec844ad7c2b3e5",
+ "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf"
+ "1a5a4c5db02d56ecc4c5bf34007208d5b887185865") < 0 ||
+ test_pbkdf2(GNUTLS_MAC_SHA1, "70617373776f7264", "73616c74",
+ 4096, 20,
+ "4b007901b765489abead49d926f721d065a429c1") < 0;
+}
+*/
+
+int main(void)
+{
+ int ret;
+
+ gnutls_global_init();
+
+ ret = test_macs();
+ if (ret < 0)
+ goto cleanup;
+ ret = test_hashes();
+ if (ret < 0)
+ goto cleanup;
+ /*
+ ret = test_kdfs();
+ if (ret < 0)
+ goto cleanup;
+ */
+
+cleanup:
+ gnutls_global_deinit();
+ return ret;
+}
--- /dev/null
+/*
+ * Copyright (C) 2025 Red Hat, Inc.
+ *
+ * Author: Zoltan Fridrich
+ *
+ * This file is part of GnuTLS.
+ *
+ * GnuTLS is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuTLS 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
+ * 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/>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <gnutls/abstract.h>
+
+/* sha1 hash of "hello" string */
+const gnutls_datum_t hash_data = {
+ (void *)"\xaa\xf4\xc6\x1d\xdc\xc5\xe8\xa2\xda\xbe"
+ "\xde\x0f\x3b\x48\x2c\xd9\xae\xa9\x43\x4d",
+ 20
+};
+
+const gnutls_datum_t raw_data = { (void *)"hello there", 11 };
+
+static int test_encrypt_decrypt(gnutls_pubkey_t *pubkey,
+ gnutls_privkey_t *privkey)
+{
+ int ret;
+ gnutls_datum_t out = { NULL, 0 };
+ gnutls_datum_t out2 = { NULL, 0 };
+
+ ret = gnutls_pubkey_encrypt_data(*pubkey, 0, &hash_data, &out);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_pubkey_encrypt_data: %s\n",
+ gnutls_strerror(ret));
+ return ret;
+ }
+
+ ret = gnutls_privkey_decrypt_data(*privkey, 0, &out, &out2);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_privkey_decrypt_data: %s\n",
+ gnutls_strerror(ret));
+ return ret;
+ }
+
+ if (out2.size != hash_data.size) {
+ fprintf(stderr, "Decrypted data don't match original (1)\n");
+ return -1;
+ }
+
+ if (memcmp(out2.data, hash_data.data, hash_data.size) != 0) {
+ fprintf(stderr, "Decrypted data don't match original (2)\n");
+ return -1;
+ }
+
+ /* try again with fixed length API */
+ memset(out2.data, 'A', out2.size);
+ ret = gnutls_privkey_decrypt_data2(*privkey, 0, &out, out2.data,
+ out2.size);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_privkey_decrypt_data: %s\n",
+ gnutls_strerror(ret));
+ return ret;
+ }
+
+ if (memcmp(out2.data, hash_data.data, hash_data.size) != 0) {
+ fprintf(stderr, "Decrypted data don't match original (2b)\n");
+ return -1;
+ }
+
+ gnutls_free(out.data);
+ gnutls_free(out2.data);
+
+ ret = gnutls_pubkey_encrypt_data(*pubkey, 0, &raw_data, &out);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_pubkey_encrypt_data: %s\n",
+ gnutls_strerror(ret));
+ return ret;
+ }
+
+ ret = gnutls_privkey_decrypt_data(*privkey, 0, &out, &out2);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_privkey_decrypt_data: %s\n",
+ gnutls_strerror(ret));
+ return ret;
+ }
+
+ if (out2.size != raw_data.size) {
+ fprintf(stderr, "Decrypted data don't match original (3)\n");
+ return -1;
+ }
+
+ if (memcmp(out2.data, raw_data.data, raw_data.size) != 0) {
+ fprintf(stderr, "Decrypted data don't match original (4)\n");
+ return -1;
+ }
+
+ /* try again with fixed length API */
+ memset(out2.data, 'A', out2.size);
+ ret = gnutls_privkey_decrypt_data2(*privkey, 0, &out, out2.data,
+ out2.size);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_privkey_decrypt_data: %s\n",
+ gnutls_strerror(ret));
+ return ret;
+ }
+
+ if (memcmp(out2.data, raw_data.data, raw_data.size) != 0) {
+ fprintf(stderr, "Decrypted data don't match original (4b)\n");
+ return -1;
+ }
+
+ printf("ok\n");
+
+ gnutls_free(out.data);
+ gnutls_free(out2.data);
+
+ return 0;
+}
+
+static int generate_rsa_keys(gnutls_pubkey_t *pubkey, gnutls_privkey_t *privkey)
+{
+ int ret = 0;
+
+ ret = gnutls_pubkey_init(pubkey);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_pubkey_init: %s\n",
+ gnutls_strerror(ret));
+ return ret;
+ }
+
+ ret = gnutls_privkey_init(privkey);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_privkey_init: %s\n",
+ gnutls_strerror(ret));
+ return ret;
+ }
+
+ ret = gnutls_privkey_generate(*privkey, GNUTLS_PK_RSA, 2048, 0);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_privkey_generate: %s\n",
+ gnutls_strerror(ret));
+ return ret;
+ }
+
+ ret = gnutls_pubkey_import_privkey(*pubkey, *privkey,
+ GNUTLS_KEY_DATA_ENCIPHERMENT, 0);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_pubkey_import_privkey: %s\n",
+ gnutls_strerror(ret));
+ return ret;
+ }
+
+ return ret;
+}
+
+static int test_rsa(void)
+{
+ int ret = 0;
+ gnutls_pubkey_t pubkey = NULL;
+ gnutls_privkey_t privkey = NULL;
+
+ ret = generate_rsa_keys(&pubkey, &privkey);
+ if (ret < 0) {
+ fprintf(stderr, "Failed to generate RSA keys\n");
+ return ret;
+ }
+
+ printf("Testing RSA encrypt-decrypt\n");
+ ret = test_encrypt_decrypt(&pubkey, &privkey);
+
+ gnutls_privkey_deinit(privkey);
+ gnutls_pubkey_deinit(pubkey);
+ return ret;
+}
+
+static int test_rsa_oaep(void)
+{
+ int ret = 0;
+ gnutls_pubkey_t pubkey = NULL;
+ gnutls_privkey_t privkey = NULL;
+ gnutls_x509_spki_t spki;
+ const gnutls_datum_t label = { (void *)"label", 5 };
+
+ ret = gnutls_x509_spki_init(&spki);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_x509_spki_init: %s\n",
+ gnutls_strerror(ret));
+ return ret;
+ }
+
+ ret = gnutls_x509_spki_set_rsa_oaep_params(spki, GNUTLS_DIG_SHA512,
+ &label);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_x509_spki_set_rsa_oaep_params: %s\n",
+ gnutls_strerror(ret));
+ return ret;
+ }
+
+ ret = generate_rsa_keys(&pubkey, &privkey);
+ if (ret < 0) {
+ fprintf(stderr, "Failed to generate RSA keys\n");
+ return ret;
+ }
+
+ ret = gnutls_privkey_set_spki(privkey, spki, 0);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_privkey_set_spki: %s\n",
+ gnutls_strerror(ret));
+ return ret;
+ }
+
+ ret = gnutls_pubkey_set_spki(pubkey, spki, 0);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_pubkey_set_spki: %s\n",
+ gnutls_strerror(ret));
+ return ret;
+ }
+
+ printf("Testing RSA OAEP encrypt-decrypt\n");
+ ret = test_encrypt_decrypt(&pubkey, &privkey);
+
+ gnutls_x509_spki_deinit(spki);
+ gnutls_privkey_deinit(privkey);
+ gnutls_pubkey_deinit(pubkey);
+ return ret;
+}
+
+static int test_ec_keygen(gnutls_ecc_curve_t curve)
+{
+ int ret;
+ gnutls_privkey_t privkey;
+
+ printf("Testing ECDSA key generation\n");
+
+ ret = gnutls_privkey_init(&privkey);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_privkey_init: %s\n",
+ gnutls_strerror(ret));
+ return ret;
+ }
+
+ ret = gnutls_privkey_generate(privkey, GNUTLS_PK_EC,
+ GNUTLS_CURVE_TO_BITS(curve), 0);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_privkey_generate: %s\n",
+ gnutls_strerror(ret));
+ return ret;
+ }
+
+ printf("ok\n");
+
+ gnutls_privkey_deinit(privkey);
+ return 0;
+}
+
+int main(void)
+{
+ int ret;
+
+ gnutls_global_init();
+
+ ret = test_rsa();
+ if (ret < 0)
+ goto cleanup;
+
+ ret = test_rsa_oaep();
+ if (ret < 0)
+ goto cleanup;
+
+ ret = test_ec_keygen(GNUTLS_ECC_CURVE_SECP256R1);
+ if (ret < 0)
+ goto cleanup;
+
+cleanup:
+ gnutls_global_deinit();
+ return ret;
+}
--- /dev/null
+/*
+ * Copyright (C) 2025 Red Hat, Inc.
+ *
+ * Author: Zoltan Fridrich
+ *
+ * This file is part of GnuTLS.
+ *
+ * GnuTLS is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuTLS 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
+ * 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/>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <gnutls/abstract.h>
+#include "common-key-tests.h"
+
+/* sha1 hash of "hello" string */
+const gnutls_datum_t sha1_hash_data = {
+ (void *)"\xaa\xf4\xc6\x1d\xdc\xc5\xe8\xa2\xda\xbe"
+ "\xde\x0f\x3b\x48\x2c\xd9\xae\xa9\x43\x4d",
+ 20
+};
+
+const gnutls_datum_t sha256_hash_data = {
+ (void *)"\x2c\xf2\x4d\xba\x5f\xb0\xa3\x0e\x26\xe8\x3b\x2a\xc5\xb9\xe2\x9e"
+ "\x1b\x16\x1e\x5c\x1f\xa7\x42\x5e\x73\x04\x33\x62\x93\x8b\x98\x24",
+ 32
+};
+
+const gnutls_datum_t sha256_invalid_hash_data = {
+ (void *)"\x2c\xf2\x4d\xba\x5f\xb1\xa3\x0e\x26\xe8\x3b\x2a\xc5\xb9\xe2\x9e"
+ "\x1b\x16\x1e\x5c\x1f\xa3\x42\x5e\x73\x04\x33\x62\x93\x8b\x98\x24",
+ 32
+};
+
+const gnutls_datum_t sha1_invalid_hash_data = {
+ (void *)"\xaa\xf4\xc6\x1d\xdc\xca\xe8\xa2\xda\xbe"
+ "\xde\x0f\x3b\x48\x2c\xb9\xae\xa9\x43\x4d",
+ 20
+};
+
+const gnutls_datum_t raw_data = { (void *)"hello", 5 };
+
+#define tests common_key_tests
+
+int main(void)
+{
+ gnutls_x509_privkey_t key;
+ gnutls_x509_crt_t crt;
+ gnutls_pubkey_t pubkey;
+ gnutls_privkey_t privkey;
+ gnutls_sign_algorithm_t sign_algo;
+ gnutls_datum_t signature;
+ gnutls_datum_t signature2;
+ int ret;
+ size_t i;
+ const gnutls_datum_t *hash_data;
+ const gnutls_datum_t *invalid_hash_data;
+
+ gnutls_global_init();
+
+ for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
+ if (tests[i].pk != GNUTLS_PK_RSA &&
+ tests[i].pk != GNUTLS_PK_RSA_PSS &&
+ tests[i].pk != GNUTLS_PK_ECDSA)
+ continue;
+
+ printf("testing: %s - %s\n", tests[i].name,
+ gnutls_sign_algorithm_get_name(tests[i].sigalgo));
+
+ if (tests[i].digest == GNUTLS_DIG_SHA1) {
+ hash_data = &sha1_hash_data;
+ invalid_hash_data = &sha1_invalid_hash_data;
+ } else {
+ hash_data = &sha256_hash_data;
+ invalid_hash_data = &sha256_invalid_hash_data;
+ }
+
+ ret = gnutls_x509_privkey_init(&key);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_x509_privkey_init: %s\n",
+ gnutls_strerror(ret));
+ return EXIT_FAILURE;
+ }
+
+ ret = gnutls_x509_privkey_import(key, &tests[i].key,
+ GNUTLS_X509_FMT_PEM);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_x509_privkey_import: %s\n",
+ gnutls_strerror(ret));
+ return EXIT_FAILURE;
+ }
+
+ ret = gnutls_pubkey_init(&pubkey);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_privkey_init: %s\n",
+ gnutls_strerror(ret));
+ return EXIT_FAILURE;
+ }
+
+ ret = gnutls_privkey_init(&privkey);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_pubkey_init: %s\n",
+ gnutls_strerror(ret));
+ return EXIT_FAILURE;
+ }
+
+ ret = gnutls_privkey_import_x509(privkey, key, 0);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_privkey_import_x509: %s\n",
+ gnutls_strerror(ret));
+ return EXIT_FAILURE;
+ }
+
+ ret = gnutls_privkey_sign_hash(privkey, tests[i].digest,
+ tests[i].sign_flags, hash_data,
+ &signature2);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_privkey_sign_hash: %s\n",
+ gnutls_strerror(ret));
+ return EXIT_FAILURE;
+ }
+
+ ret = gnutls_privkey_sign_data(privkey, tests[i].digest,
+ tests[i].sign_flags, &raw_data,
+ &signature);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_x509_privkey_sign_hash: %s\n",
+ gnutls_strerror(ret));
+ return EXIT_FAILURE;
+ }
+
+ ret = gnutls_x509_crt_init(&crt);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_x509_crt_init: %s\n",
+ gnutls_strerror(ret));
+ return EXIT_FAILURE;
+ }
+
+ ret = gnutls_x509_crt_import(crt, &tests[i].cert,
+ GNUTLS_X509_FMT_PEM);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_x509_crt_import: %s\n",
+ gnutls_strerror(ret));
+ return EXIT_FAILURE;
+ }
+
+ ret = gnutls_pubkey_import_x509(pubkey, crt, 0);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_x509_pubkey_import: %s\n",
+ gnutls_strerror(ret));
+ return EXIT_FAILURE;
+ }
+
+ ret = gnutls_pubkey_verify_hash2(
+ pubkey, tests[i].sigalgo,
+ GNUTLS_VERIFY_ALLOW_SIGN_WITH_SHA1, hash_data,
+ &signature);
+ if (ret < 0) {
+ fprintf(stderr, "gnutls_x509_pubkey_verify_hash2: %s\n",
+ gnutls_strerror(ret));
+ return EXIT_FAILURE;
+ }
+
+ ret = gnutls_pubkey_verify_hash2(
+ pubkey, tests[i].sigalgo,
+ GNUTLS_VERIFY_ALLOW_SIGN_WITH_SHA1, hash_data,
+ &signature2);
+ if (ret < 0) {
+ fprintf(stderr,
+ "gnutls_x509_pubkey_verify_hash-1 (hashed data): %s\n",
+ gnutls_strerror(ret));
+ return EXIT_FAILURE;
+ }
+
+ /* should fail */
+ ret = gnutls_pubkey_verify_hash2(
+ pubkey, tests[i].sigalgo,
+ GNUTLS_VERIFY_ALLOW_SIGN_WITH_SHA1, invalid_hash_data,
+ &signature2);
+ if (ret != GNUTLS_E_PK_SIG_VERIFY_FAILED) {
+ fprintf(stderr,
+ "gnutls_x509_pubkey_verify_hash-2 (hashed data): %s\n",
+ gnutls_strerror(ret));
+ return EXIT_FAILURE;
+ }
+
+ sign_algo = gnutls_pk_to_sign(
+ gnutls_pubkey_get_pk_algorithm(pubkey, NULL),
+ tests[i].digest);
+
+ ret = gnutls_pubkey_verify_hash2(
+ pubkey, sign_algo, GNUTLS_VERIFY_ALLOW_SIGN_WITH_SHA1,
+ hash_data, &signature2);
+ if (ret < 0) {
+ fprintf(stderr,
+ "gnutls_x509_pubkey_verify_hash2-1 (hashed data): %s\n",
+ gnutls_strerror(ret));
+ return EXIT_FAILURE;
+ }
+
+ /* should fail */
+ ret = gnutls_pubkey_verify_hash2(
+ pubkey, sign_algo, GNUTLS_VERIFY_ALLOW_SIGN_WITH_SHA1,
+ invalid_hash_data, &signature2);
+ if (ret != GNUTLS_E_PK_SIG_VERIFY_FAILED) {
+ fprintf(stderr,
+ "gnutls_x509_pubkey_verify_hash2-2 (hashed data): %s\n",
+ gnutls_strerror(ret));
+ return EXIT_FAILURE;
+ }
+
+ /* test the raw interface */
+ gnutls_free(signature.data);
+
+ if (gnutls_pubkey_get_pk_algorithm(pubkey, NULL) ==
+ GNUTLS_PK_RSA) {
+ ret = gnutls_privkey_sign_hash(
+ privkey, tests[i].digest,
+ GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA, hash_data,
+ &signature);
+ if (ret < 0) {
+ fprintf(stderr,
+ "gnutls_privkey_sign_hash: %s\n",
+ gnutls_strerror(ret));
+ return EXIT_FAILURE;
+ }
+
+ sign_algo = gnutls_pk_to_sign(
+ gnutls_pubkey_get_pk_algorithm(pubkey, NULL),
+ tests[i].digest);
+
+ ret = gnutls_pubkey_verify_hash2(
+ pubkey, sign_algo,
+ GNUTLS_PUBKEY_VERIFY_FLAG_TLS1_RSA, hash_data,
+ &signature);
+ if (ret < 0) {
+ fprintf(stderr,
+ "gnutls_pubkey_verify_hash-3 (raw hashed data): %s\n",
+ gnutls_strerror(ret));
+ return EXIT_FAILURE;
+ }
+
+ gnutls_free(signature.data);
+ /* test the legacy API */
+ ret = gnutls_privkey_sign_raw_data(
+ privkey, 0, hash_data, &signature);
+ if (ret < 0) {
+ fprintf(stderr,
+ "gnutls_privkey_sign_raw_data: %s\n",
+ gnutls_strerror(ret));
+ return EXIT_FAILURE;
+ }
+
+ ret = gnutls_pubkey_verify_hash2(
+ pubkey, sign_algo,
+ GNUTLS_PUBKEY_VERIFY_FLAG_TLS1_RSA, hash_data,
+ &signature);
+ if (ret < 0) {
+ fprintf(stderr,
+ "gnutls_pubkey_verify_hash-4 (legacy raw hashed data): %s\n",
+ gnutls_strerror(ret));
+ return EXIT_FAILURE;
+ }
+ }
+ gnutls_free(signature.data);
+ gnutls_free(signature2.data);
+ gnutls_x509_privkey_deinit(key);
+ gnutls_x509_crt_deinit(crt);
+ gnutls_privkey_deinit(privkey);
+ gnutls_pubkey_deinit(pubkey);
+ }
+
+ gnutls_global_deinit();
+}
--- /dev/null
+#!/bin/sh
+
+# Copyright (C) 2025 Red Hat, Inc.
+#
+# Author: Zoltan Fridrich <zfridric@redhat.com>
+#
+# This file is part of GnuTLS.
+#
+# GnuTLS is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3 of the License, or (at
+# your option) any later version.
+#
+# GnuTLS 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
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GnuTLS. If not, see <https://www.gnu.org/licenses/>.
+
+: ${testdir=$abs_top_builddir/tests/pkcs11-provider}
+
+if test "${GNUTLS_FORCE_FIPS_MODE}" != 1; then
+ exit 77
+fi
+
+if [ -z "$(which pkcs11-tool 2>/dev/null)" ]; then
+ echo "Need pkcs11-tool from opensc package to run this test."
+ exit 77
+fi
+
+MODULE="/lib64/pkcs11/libkryoptic_pkcs11.so"
+if [ ! -f "$MODULE" ]; then
+ echo "Need Kryoptic module to run this test."
+ exit 77
+fi
+
+LABEL="Kryoptic Token"
+PIN="12345"
+PRIORITY_FILE="${testdir}/gnutls.$$.conf"
+KRYOPTIC_DB="${testdir}/kryoptic.$$.sql"
+export KRYOPTIC_CONF="${testdir}/kryoptic.$$.conf"
+export GNUTLS_SYSTEM_PRIORITY_FAIL_ON_INVALID=1
+export GNUTLS_SYSTEM_PRIORITY_FILE="${PRIORITY_FILE}"
+export GNUTLS_DEBUG_LEVEL=6
+
+cat >"${PRIORITY_FILE}" <<_EOF_
+[overrides]
+allow-rsa-pkcs1-encrypt = true
+
+[provider]
+path = ${MODULE}
+pin = ${PIN}
+_EOF_
+
+cat >"${KRYOPTIC_CONF}" <<_EOF_
+[ec_point_encoding]
+encoding = "Bytes"
+
+[[slots]]
+slot = 22
+dbtype = "sqlite"
+dbargs = "${KRYOPTIC_DB}"
+_EOF_
+
+echo "Initializing token"
+
+# init token
+pkcs11-tool --module "${MODULE}" --init-token --label "${LABEL}" --so-pin "${PIN}" >/dev/null
+if test $? != 0; then
+ echo "failed to initialize token"
+ exit 1
+fi
+# set user pin
+pkcs11-tool --module "${MODULE}" --so-pin "${PIN}" --login --login-type so --init-pin --pin "${PIN}" >/dev/null
+if test $? != 0; then
+ echo "failed to set user pin"
+ exit 1
+fi
+
+echo "Testing public key algorithms"
+"${testdir}/pkcs11-provider-pk"
+rc=$?
+if test "${rc}" = "0"; then
+ echo "test passed"
+else
+ echo "test failed"
+ rm -f ${PRIORITY_FILE} ${KRYOPTIC_CONF} ${KRYOPTIC_DB}
+ exit ${rc}
+fi
+
+echo "Testing signatures"
+"${testdir}/pkcs11-provider-sig"
+rc=$?
+if test "${rc}" = "0"; then
+ echo "test passed"
+else
+ echo "test failed"
+ rm -f ${PRIORITY_FILE} ${KRYOPTIC_CONF} ${KRYOPTIC_DB}
+ exit ${rc}
+fi
+
+echo "Testing ciphers"
+"${testdir}/pkcs11-provider-cipher"
+rc=$?
+if test "${rc}" = "0"; then
+ echo "test passed"
+else
+ echo "test failed"
+ rm -f ${PRIORITY_FILE} ${KRYOPTIC_CONF} ${KRYOPTIC_DB}
+ exit ${rc}
+fi
+
+echo "Testing hmacs"
+"${testdir}/pkcs11-provider-hmac"
+rc=$?
+if test "${rc}" = "0"; then
+ echo "test passed"
+else
+ echo "test failed"
+ rm -f ${PRIORITY_FILE} ${KRYOPTIC_CONF} ${KRYOPTIC_DB}
+ exit ${rc}
+fi
+
+rm -f ${PRIORITY_FILE} ${KRYOPTIC_CONF} ${KRYOPTIC_DB}
+exit ${rc}