diff -Nru libica-3.6.0/ChangeLog libica-3.6.1/ChangeLog --- libica-3.6.0/ChangeLog 2019-08-29 19:33:33.000000000 +0000 +++ libica-3.6.1/ChangeLog 2019-11-13 16:19:13.000000000 +0000 @@ -1,3 +1,5 @@ +v3.6.1 + - [PATCH] Fix x25519 and x448 handling of non-canonical values v3.6.0 - [FEATURE] Add MSA9 CPACF support for Ed25519, Ed448, X25519 and X448 v3.5.0 diff -Nru libica-3.6.0/configure.ac libica-3.6.1/configure.ac --- libica-3.6.0/configure.ac 2019-08-29 19:33:33.000000000 +0000 +++ libica-3.6.1/configure.ac 2019-11-13 16:19:13.000000000 +0000 @@ -1,4 +1,4 @@ -AC_INIT([libica], [3.6.0], [steuer@linux.vnet.ibm.com],, [https://github.com/opencryptoki/libica]) +AC_INIT([libica], [3.6.1], [https://github.com/opencryptoki/libica/issues],, [https://github.com/opencryptoki/libica]) # save cmdline flags cmdline_CFLAGS="$CFLAGS" diff -Nru libica-3.6.0/debian/changelog libica-3.6.1/debian/changelog --- libica-3.6.0/debian/changelog 2019-08-30 09:47:15.000000000 +0000 +++ libica-3.6.1/debian/changelog 2019-11-29 14:57:43.000000000 +0000 @@ -1,3 +1,9 @@ +libica (3.6.1-0ubuntu1) focal; urgency=medium + + * New upstream release LP: #1852550 + + -- Dimitri John Ledkov Fri, 29 Nov 2019 14:57:43 +0000 + libica (3.6.0-0ubuntu1) eoan; urgency=medium * New upstream release LP: #1836866 diff -Nru libica-3.6.0/debian/patches/pthread-missing.patch libica-3.6.1/debian/patches/pthread-missing.patch --- libica-3.6.0/debian/patches/pthread-missing.patch 2019-04-30 10:58:10.000000000 +0000 +++ libica-3.6.1/debian/patches/pthread-missing.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -Description: lots of pthread symbols used but not found in linked libraries -Author: Dimitri John Ledkov - - ---- libica-3.5.0.orig/src/Makefile.am -+++ libica-3.5.0/src/Makefile.am -@@ -11,7 +11,7 @@ libica_la_CFLAGS = ${AM_CFLAGS} -I${srcd - libica_la_CCASFLAGS = ${AM_CFLAGS} - libica_la_LIBADD = @LIBS@ -lrt -lcrypto - libica_la_LDFLAGS = -Wl,--version-script=${srcdir}/../libica.map \ -- -version-number ${VERSION} -+ -version-number ${VERSION} -pthread - libica_la_SOURCES = ica_api.c init.c icastats_shared.c s390_rsa.c \ - s390_crypto.c s390_ecc.c s390_prng.c s390_sha.c \ - s390_drbg.c s390_drbg_sha512.c test_vec.c fips.c \ diff -Nru libica-3.6.0/debian/patches/series libica-3.6.1/debian/patches/series --- libica-3.6.0/debian/patches/series 2019-04-30 10:58:10.000000000 +0000 +++ libica-3.6.1/debian/patches/series 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -pthread-missing.patch diff -Nru libica-3.6.0/libica.spec libica-3.6.1/libica.spec --- libica-3.6.0/libica.spec 2019-08-29 19:33:33.000000000 +0000 +++ libica-3.6.1/libica.spec 2019-11-13 16:19:13.000000000 +0000 @@ -1,5 +1,5 @@ Name: libica -Version: 3.6.0 +Version: 3.6.1 Release: 1%{?dist} Summary: Interface library to the ICA device driver @@ -62,6 +62,8 @@ %{_includedir}/ica_api.h %changelog +* Wed Nov 13 2019 Patrick Steuer +- Version v3.6.1 * Wed Aug 28 2019 Patrick Steuer - Version v3.6.0 * Tue Apr 23 2019 Patrick Steuer diff -Nru libica-3.6.0/src/ica_api.c libica-3.6.1/src/ica_api.c --- libica-3.6.0/src/ica_api.c 2019-08-29 19:33:33.000000000 +0000 +++ libica-3.6.1/src/ica_api.c 2019-11-13 16:19:13.000000000 +0000 @@ -1479,6 +1479,7 @@ if (priv != NULL) { memcpy(ctx->priv, priv, 32); ctx->priv_init = 1; + memset(ctx->pub, 0, 32); ctx->pub_init = 0; } @@ -1500,6 +1501,7 @@ if (priv != NULL) { memcpy(ctx->priv, priv, 56); ctx->priv_init = 1; + memset(ctx->pub, 0, 56); ctx->pub_init = 0; } @@ -1521,6 +1523,7 @@ if (priv != NULL) { memcpy(ctx->sign_param.priv, priv, 32); ctx->priv_init = 1; + memset(ctx->verify_param.pub, 0, 32); ctx->pub_init = 0; } @@ -1543,6 +1546,7 @@ memset(ctx->sign_param.priv, 0, sizeof(ctx->sign_param.priv)); memcpy(ctx->sign_param.priv + 64 - 57, priv, 57); ctx->priv_init = 1; + memset(ctx->verify_param.pub, 0, 57); ctx->pub_init = 0; } @@ -1579,8 +1583,10 @@ return -1; rc = x25519_derive_pub(ctx->pub, ctx->priv); - if (rc) + if (rc) { + memset(ctx->pub, 0, 32); return -1; + } ctx->pub_init = 1; } @@ -1612,8 +1618,10 @@ return -1; rc = x448_derive_pub(ctx->pub, ctx->priv); - if (rc) + if (rc) { + memset(ctx->pub, 0, 56); return -1; + } ctx->pub_init = 1; } @@ -1647,8 +1655,10 @@ rc = ed25519_derive_pub(ctx->verify_param.pub, ctx->sign_param.priv); - if (rc) + if (rc) { + memset(ctx->verify_param.pub, 0, 32); return -1; + } ctx->pub_init = 1; } @@ -1683,8 +1693,10 @@ rc = ed448_derive_pub(ctx->verify_param.pub + 64 - 57, ctx->sign_param.priv + 64 - 57); - if (rc) + if (rc) { + memset(ctx->verify_param.pub, 0, 57); return -1; + } ctx->pub_init = 1; } @@ -1740,8 +1752,10 @@ rc = s390_kdsa(S390_CRYPTO_EDDSA_SIGN_ED25519, &ctx->sign_param, msg, msglen); - if (rc) + if (rc) { + memset(ctx->sign_param.sig, 0, sizeof(ctx->sign_param.sig)); return -1; + } s390_flip_endian_32(sig, ctx->sign_param.sig); s390_flip_endian_32(sig + 32, ctx->sign_param.sig + 32); @@ -1762,8 +1776,10 @@ rc = s390_kdsa(S390_CRYPTO_EDDSA_SIGN_ED448, &ctx->sign_param, msg, msglen); - if (rc) + if (rc) { + memset(ctx->sign_param.sig, 0, sizeof(ctx->sign_param.sig)); return -1; + } s390_flip_endian_64(ctx->sign_param.sig, ctx->sign_param.sig); s390_flip_endian_64(ctx->sign_param.sig + 64, @@ -1791,8 +1807,10 @@ rc = ed25519_derive_pub(ctx->verify_param.pub, ctx->sign_param.priv); - if (rc) + if (rc) { + memset(ctx->verify_param.pub, 0, 32); return -1; + } ctx->pub_init = 1; } @@ -1802,13 +1820,11 @@ rc = s390_kdsa(S390_CRYPTO_EDDSA_VERIFY_ED25519, &ctx->verify_param, msg, msglen); - if (rc) - return -1; memset(ctx->verify_param.sig, 0, sizeof(ctx->verify_param.sig)); stats_increment(ICA_STATS_ED25519_VERIFY, ALGO_HW, ENCRYPT); - return 0; + return rc == 0 ? 0 : -1; } int ica_ed448_verify(ICA_ED448_CTX *ctx, const unsigned char sig[114], @@ -1826,8 +1842,10 @@ rc = ed448_derive_pub(ctx->verify_param.pub + 64 - 57, ctx->sign_param.priv + 64 - 57); - if (rc) + if (rc) { + memset(ctx->verify_param.pub, 0, 57); return -1; + } ctx->pub_init = 1; } @@ -1841,12 +1859,12 @@ rc = s390_kdsa(S390_CRYPTO_EDDSA_VERIFY_ED448, &ctx->verify_param, msg, msglen); if (rc || sig[113] != 0) /* XXX kdsa doesnt check last byte */ - return -1; + rc = -1; memset(ctx->verify_param.sig, 0, sizeof(ctx->verify_param.sig)); stats_increment(ICA_STATS_ED448_VERIFY, ALGO_HW, ENCRYPT); - return 0; + return rc == 0 ? 0 : -1; } int ica_x25519_ctx_del(ICA_X25519_CTX **ctx) @@ -1899,11 +1917,10 @@ return -1; memset(ctx, 0, sizeof(*ctx)); + ctx->pub_init = 0; rng_gen(ctx->priv, 32); - ctx->priv_init = 1; - ctx->pub_init = 0; return 0; } @@ -1913,11 +1930,10 @@ return -1; memset(ctx, 0, sizeof(*ctx)); + ctx->pub_init = 0; rng_gen(ctx->priv, 56); - ctx->priv_init = 1; - ctx->pub_init = 0; return 0; } @@ -1927,11 +1943,10 @@ return -1; memset(ctx, 0, sizeof(*ctx)); + ctx->pub_init = 0; rng_gen(ctx->sign_param.priv, sizeof(ctx->sign_param.priv)); - ctx->priv_init = 1; - ctx->pub_init = 0; return 0; } @@ -1941,12 +1956,11 @@ return -1; memset(ctx, 0, sizeof(*ctx)); + ctx->pub_init = 0; rng_gen(ctx->sign_param.priv + 64 - 57, sizeof(ctx->sign_param.priv) - (64 - 57)); - ctx->priv_init = 1; - ctx->pub_init = 0; return 0; } diff -Nru libica-3.6.0/src/Makefile.am libica-3.6.1/src/Makefile.am --- libica-3.6.0/src/Makefile.am 2019-08-29 19:33:33.000000000 +0000 +++ libica-3.6.1/src/Makefile.am 2019-11-13 16:19:13.000000000 +0000 @@ -1,4 +1,4 @@ -VERSION = 3:6:0 +VERSION = 3:6:1 AM_CFLAGS = @FLAGS@ @@ -7,7 +7,7 @@ lib_LTLIBRARIES = libica.la libica_la_CFLAGS = ${AM_CFLAGS} -I${srcdir}/include -I${srcdir}/../include \ - -fvisibility=hidden + -fvisibility=hidden -pthread libica_la_CCASFLAGS = ${AM_CFLAGS} libica_la_LIBADD = @LIBS@ -lrt -lcrypto libica_la_LDFLAGS = -Wl,--version-script=${srcdir}/../libica.map \ diff -Nru libica-3.6.0/src/s390_ecc.c libica-3.6.1/src/s390_ecc.c --- libica-3.6.0/src/s390_ecc.c 2019-08-29 19:33:33.000000000 +0000 +++ libica-3.6.1/src/s390_ecc.c 2019-11-13 16:19:13.000000000 +0000 @@ -557,6 +557,91 @@ return rc; } +/* + * mask must be 0xFF or 0x00. + * "constant time" is per len. + * + * if (mask) { + * unsigned char tmp[len]; + * + * memcpy(tmp, a, len); + * memcpy(a, b); + * memcpy(b, tmp); + * } + */ +static inline void constant_time_cond_swap_buff(unsigned char mask, + unsigned char *a, + unsigned char *b, + size_t len) +{ + size_t i; + unsigned char tmp; + + for (i = 0; i < len; i++) { + tmp = a[i] ^ b[i]; + tmp &= mask; + a[i] ^= tmp; + b[i] ^= tmp; + } +} + + +static void s390_x25519_mod_p(unsigned char u[32]) +{ + unsigned char u_red[32]; + unsigned int c = 0; + int i; + + memcpy(u_red, u, sizeof(u_red)); + + c += (unsigned int)u_red[31] + 19; + u_red[31] = (unsigned char)c; + c >>= 8; + + for (i = 30; i >= 0; i--) { + c += (unsigned int)u_red[i]; + u_red[i] = (unsigned char)c; + c >>= 8; + } + + c = (u_red[0] & 0x80) >> 7; + u_red[0] &= 0x7f; + constant_time_cond_swap_buff(0 - (unsigned char)c, + u, u_red, sizeof(u_red)); +} + +static void s390_x448_mod_p(unsigned char u[56]) +{ + unsigned char u_red[56]; + unsigned int c = 0; + int i; + + memcpy(u_red, u, sizeof(u_red)); + + c += (unsigned int)u_red[55] + 1; + u_red[55] = (unsigned char)c; + c >>= 8; + + for (i = 54; i >= 28; i--) { + c += (unsigned int)u_red[i]; + u_red[i] = (unsigned char)c; + c >>= 8; + } + + c += (unsigned int)u_red[27] + 1; + u_red[27] = (unsigned char)c; + c >>= 8; + + for (i = 26; i >= 0; i--) { + c += (unsigned int)u_red[i]; + u_red[i] = (unsigned char)c; + c >>= 8; + } + + constant_time_cond_swap_buff(0 - (unsigned char)c, + u, u_red, sizeof(u_red)); +} + int scalar_mulx_cpacf(unsigned char *res_u, const unsigned char *scalar, const unsigned char *u, @@ -598,6 +683,9 @@ s390_flip_endian_32(param.X25519.u, param.X25519.u); s390_flip_endian_32(param.X25519.scalar, param.X25519.scalar); + /* reduce non-canonical values */ + s390_x25519_mod_p(param.X25519.u); + fc = s390_pcc_functions[SCALAR_MULTIPLY_X25519].hw_fc; rc = s390_pcc(fc, ¶m) ? EIO : 0; @@ -619,6 +707,9 @@ s390_flip_endian_64(param.X448.u, param.X448.u); s390_flip_endian_64(param.X448.scalar, param.X448.scalar); + /* reduce non-canonical values */ + s390_x448_mod_p(param.X448.u + 8); + fc = s390_pcc_functions[SCALAR_MULTIPLY_X448].hw_fc; rc = s390_pcc(fc, ¶m) ? EIO : 0; diff -Nru libica-3.6.0/test/ecdh1_test.sh libica-3.6.1/test/ecdh1_test.sh --- libica-3.6.0/test/ecdh1_test.sh 2019-08-29 19:33:33.000000000 +0000 +++ libica-3.6.1/test/ecdh1_test.sh 2019-11-13 16:19:13.000000000 +0000 @@ -1,2 +1,7 @@ #!/bin/sh -ICAPATH=1 ./ecdh_test + +if lszcrypt | grep "CEX.C.*online" &> /dev/null; then + ICAPATH=1 ./ecdh_test +else + exit 77 +fi diff -Nru libica-3.6.0/test/ecdh2_test.sh libica-3.6.1/test/ecdh2_test.sh --- libica-3.6.0/test/ecdh2_test.sh 2019-08-29 19:33:33.000000000 +0000 +++ libica-3.6.1/test/ecdh2_test.sh 2019-11-13 16:19:13.000000000 +0000 @@ -1,2 +1,7 @@ #!/bin/sh -ICAPATH=2 ./ecdh_test + +if lszcrypt | grep "CEX.C.*online" &> /dev/null; then + ICAPATH=2 ./ecdh_test +else + exit 77 +fi diff -Nru libica-3.6.0/test/ecdsa1_test.sh libica-3.6.1/test/ecdsa1_test.sh --- libica-3.6.0/test/ecdsa1_test.sh 2019-08-29 19:33:33.000000000 +0000 +++ libica-3.6.1/test/ecdsa1_test.sh 2019-11-13 16:19:13.000000000 +0000 @@ -1,2 +1,7 @@ #!/bin/sh -ICAPATH=1 ./ecdsa_test + +if lszcrypt | grep "CEX.C.*online" &> /dev/null; then + ICAPATH=1 ./ecdsa_test +else + exit 77 +fi diff -Nru libica-3.6.0/test/ecdsa2_test.sh libica-3.6.1/test/ecdsa2_test.sh --- libica-3.6.0/test/ecdsa2_test.sh 2019-08-29 19:33:33.000000000 +0000 +++ libica-3.6.1/test/ecdsa2_test.sh 2019-11-13 16:19:13.000000000 +0000 @@ -1,2 +1,7 @@ #!/bin/sh -ICAPATH=2 ./ecdsa_test + +if lszcrypt | grep "CEX.C.*online" &> /dev/null; then + ICAPATH=2 ./ecdsa_test +else + exit 77 +fi diff -Nru libica-3.6.0/test/ec_keygen1_test.sh libica-3.6.1/test/ec_keygen1_test.sh --- libica-3.6.0/test/ec_keygen1_test.sh 2019-08-29 19:33:33.000000000 +0000 +++ libica-3.6.1/test/ec_keygen1_test.sh 2019-11-13 16:19:13.000000000 +0000 @@ -1,2 +1,7 @@ #!/bin/sh -ICAPATH=1 ./ec_keygen_test + +if lszcrypt | grep "CEX.C.*online" &> /dev/null; then + ICAPATH=1 ./ec_keygen_test +else + exit 77 +fi diff -Nru libica-3.6.0/test/ec_keygen2_test.sh libica-3.6.1/test/ec_keygen2_test.sh --- libica-3.6.0/test/ec_keygen2_test.sh 2019-08-29 19:33:33.000000000 +0000 +++ libica-3.6.1/test/ec_keygen2_test.sh 2019-11-13 16:19:13.000000000 +0000 @@ -1,2 +1,7 @@ #!/bin/sh -ICAPATH=2 ./ec_keygen_test + +if lszcrypt | grep "CEX.C.*online" &> /dev/null; then + ICAPATH=2 ./ec_keygen_test +else + exit 77 +fi diff -Nru libica-3.6.0/test/eddsa_test.c libica-3.6.1/test/eddsa_test.c --- libica-3.6.0/test/eddsa_test.c 2019-08-29 19:33:33.000000000 +0000 +++ libica-3.6.1/test/eddsa_test.c 2019-11-13 16:19:13.000000000 +0000 @@ -14,9 +14,9 @@ #include "testcase.h" #include "eddsa_test.h" -#define THREADS 1024 -#define ITERATIONS 100 /*XXX*/ -#define MSGLEN (3600-1) /*XXX (16384*100UL)*/ +#define THREADS 256 +#define ITERATIONS 1000 +#define MSGLEN (16384*2ULL) static void check_functionlist(void); @@ -265,14 +265,15 @@ if (msg == NULL) EXIT_ERR("malloc failed."); - fd = fopen("/dev/urandom", "r"); - if (fd == NULL) - EXIT_ERR("fopen failed."); - - if (fread(msg, msglen, 1, fd) != 1) - EXIT_ERR("fread failed."); - - fclose(fd); + if (msglen > 0) { + fd = fopen("/dev/urandom", "r"); + if (fd == NULL) + EXIT_ERR("fopen failed."); + + if (fread(msg, msglen, 1, fd) != 1) + EXIT_ERR("fread failed."); + fclose(fd); + } if (ica_ed25519_ctx_new(&ctx)) EXIT_ERR("ica_ed448_ctx_new failed."); @@ -347,14 +348,16 @@ if (msg == NULL) EXIT_ERR("malloc failed."); - fd = fopen("/dev/urandom", "r"); - if (fd == NULL) - EXIT_ERR("fopen failed."); + if (msglen > 0) { + fd = fopen("/dev/urandom", "r"); + if (fd == NULL) + EXIT_ERR("fopen failed."); - if (fread(msg, msglen, 1, fd) != 1) - EXIT_ERR("fread failed."); + if (fread(msg, msglen, 1, fd) != 1) + EXIT_ERR("fread failed."); - fclose(fd); + fclose(fd); + } if (ica_ed448_ctx_new(&ctx)) EXIT_ERR("ica_ed448_ctx_new failed."); @@ -535,7 +538,7 @@ gettimeofday(&stop, NULL); delta = delta_usec(&start, &stop); ops = ops_per_sec(ITERATIONS, delta); - printf("ica_ed25519_sign(%d bytes)\t%.2Lf ops/sec\n", MSGLEN, ops); + printf("ica_ed25519_sign(%llu bytes)\t%.2Lf ops/sec\n", MSGLEN, ops); gettimeofday(&start, NULL); for (i = 0; i < ITERATIONS; i++) { @@ -545,7 +548,7 @@ gettimeofday(&stop, NULL); delta = delta_usec(&start, &stop); ops = ops_per_sec(ITERATIONS, delta); - printf("ica_ed25519_verify(%d bytes)\t%.2Lf ops/sec\n", MSGLEN, ops); + printf("ica_ed25519_verify(%llu bytes)\t%.2Lf ops/sec\n", MSGLEN, ops); if (ica_ed25519_ctx_del(&ctx)) EXIT_ERR("ica_ed25519_ctx_del failed."); @@ -581,7 +584,7 @@ gettimeofday(&stop, NULL); delta = delta_usec(&start, &stop); ops = ops_per_sec(ITERATIONS, delta); - printf("ica_ed448_sign(%d bytes)\t%.2Lf ops/sec\n", MSGLEN, ops); + printf("ica_ed448_sign(%llu bytes)\t%.2Lf ops/sec\n", MSGLEN, ops); gettimeofday(&start, NULL); for (i = 0; i < ITERATIONS; i++) { @@ -591,7 +594,7 @@ gettimeofday(&stop, NULL); delta = delta_usec(&start, &stop); ops = ops_per_sec(ITERATIONS, delta); - printf("ica_ed448_verify(%d bytes)\t%.2Lf ops/sec\n", MSGLEN, ops); + printf("ica_ed448_verify(%llu bytes)\t%.2Lf ops/sec\n", MSGLEN, ops); if (ica_ed448_ctx_del(&ctx)) EXIT_ERR("ica_ed448_ctx_del failed."); diff -Nru libica-3.6.0/test/x_test.c libica-3.6.1/test/x_test.c --- libica-3.6.0/test/x_test.c 2019-08-29 19:33:33.000000000 +0000 +++ libica-3.6.1/test/x_test.c 2019-11-13 16:19:13.000000000 +0000 @@ -15,10 +15,18 @@ #include "ica_api.h" #include "testcase.h" -#define ITERATIONS 100 /*XXX*/ +#define ITERATIONS 1000 + +struct kat { + const unsigned char *priv; + const unsigned char *peer_pub; + const unsigned char *shared_secret; +}; static void check_functionlist(void); +static void x25519_kat(void); +static void x448_kat(void); static void x25519_pc(void); static void x448_pc(void); @@ -30,6 +38,12 @@ check_functionlist(); + VV_(printf("\n=== X25519 KAT ===\n")); + x25519_kat(); + + VV_(printf("\n=== X448 KAT ===\n")); + x448_kat(); + VV_(printf("\n=== X25519 PC ===\n")); for (i = 0; i < ITERATIONS; i++) x25519_pc(); @@ -135,6 +149,12 @@ if (memcmp(key1, key2, keylen) != 0) EXIT_ERR("x25519 shared secrets do not match."); + + (void)ica_x25519_ctx_del(&ctx1); + (void)ica_x25519_ctx_del(&ctx2); + EVP_PKEY_free(pkey1); + EVP_PKEY_free(pkey2); + EVP_PKEY_CTX_free(pctx); #endif } @@ -196,5 +216,196 @@ if (memcmp(key1, key2, keylen) != 0) EXIT_ERR("x448 shared secrets do not match."); + + (void)ica_x448_ctx_del(&ctx1); + (void)ica_x448_ctx_del(&ctx2); + EVP_PKEY_free(pkey1); + EVP_PKEY_free(pkey2); + EVP_PKEY_CTX_free(pctx); #endif } + +static void x25519_kat(void) +{ + struct kat vec[] = { + { + /* some wycheproof test vectors */ + .priv = (const unsigned char[]) { + 0x28, 0x87, 0x96, 0xbc, 0x5a, 0xff, 0x4b, 0x81, 0xa3, 0x75, 0x01, 0x75, + 0x7b, 0xc0, 0x75, 0x3a, 0x3c, 0x21, 0x96, 0x47, 0x90, 0xd3, 0x86, 0x99, + 0x30, 0x8d, 0xeb, 0xc1, 0x7a, 0x6e, 0xaf, 0x8d + }, + .peer_pub = (const unsigned char[]) { + 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f + }, + .shared_secret = (const unsigned char[]) { + 0xb4, 0xe0, 0xdd, 0x76, 0xda, 0x7b, 0x07, 0x17, 0x28, 0xb6, 0x1f, 0x85, + 0x67, 0x71, 0xaa, 0x35, 0x6e, 0x57, 0xed, 0xa7, 0x8a, 0x5b, 0x16, 0x55, + 0xcc, 0x38, 0x20, 0xfb, 0x5f, 0x85, 0x4c, 0x5c + }, + }, + { + .priv = (const unsigned char[]) { + 0x60, 0x88, 0x7b, 0x3d, 0xc7, 0x24, 0x43, 0x02, 0x6e, 0xbe, 0xdb, 0xbb, + 0xb7, 0x06, 0x65, 0xf4, 0x2b, 0x87, 0xad, 0xd1, 0x44, 0x0e, 0x77, 0x68, + 0xfb, 0xd7, 0xe8, 0xe2, 0xce, 0x5f, 0x63, 0x9d + }, + .peer_pub = (const unsigned char[]) { + 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }, + .shared_secret = (const unsigned char[]) { + 0x38, 0xd6, 0x30, 0x4c, 0x4a, 0x7e, 0x6d, 0x9f, 0x79, 0x59, 0x33, 0x4f, + 0xb5, 0x24, 0x5b, 0xd2, 0xc7, 0x54, 0x52, 0x5d, 0x4c, 0x91, 0xdb, 0x95, + 0x02, 0x06, 0x92, 0x62, 0x34, 0xc1, 0xf6, 0x33 + }, + }, + { + .priv = (const unsigned char[]) { + 0xa0, 0xa4, 0xf1, 0x30, 0xb9, 0x8a, 0x5b, 0xe4, 0xb1, 0xce, 0xdb, 0x7c, + 0xb8, 0x55, 0x84, 0xa3, 0x52, 0x0e, 0x14, 0x2d, 0x47, 0x4d, 0xc9, 0xcc, + 0xb9, 0x09, 0xa0, 0x73, 0xa9, 0x76, 0xbf, 0x63 + }, + .peer_pub = (const unsigned char[]) { + 0x0a, 0xb4, 0xe7, 0x63, 0x80, 0xd8, 0x4d, 0xde, 0x4f, 0x68, 0x33, 0xc5, + 0x8f, 0x2a, 0x9f, 0xb8, 0xf8, 0x3b, 0xb0, 0x16, 0x9b, 0x17, 0x2b, 0xe4, + 0xb6, 0xe0, 0x59, 0x28, 0x87, 0x74, 0x1a, 0x36 + }, + .shared_secret = (const unsigned char[]) { + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + }, + { + .priv = (const unsigned char[]) { + 0xa0, 0xa4, 0xf1, 0x30, 0xb9, 0x8a, 0x5b, 0xe4, 0xb1, 0xce, 0xdb, 0x7c, + 0xb8, 0x55, 0x84, 0xa3, 0x52, 0x0e, 0x14, 0x2d, 0x47, 0x4d, 0xc9, 0xcc, + 0xb9, 0x09, 0xa0, 0x73, 0xa9, 0x76, 0xbf, 0x63 + }, + .peer_pub = (const unsigned char[]) { + 0x89, 0xe1, 0x0d, 0x57, 0x01, 0xb4, 0x33, 0x7d, 0x2d, 0x03, 0x21, 0x81, + 0x53, 0x8b, 0x10, 0x64, 0xbd, 0x40, 0x84, 0x40, 0x1c, 0xec, 0xa1, 0xfd, + 0x12, 0x66, 0x3a, 0x19, 0x59, 0x38, 0x80, 0x00 + }, + .shared_secret = (const unsigned char[]) { + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + }, + { + .priv = (const unsigned char[]) { + 0xa0, 0xa4, 0xf1, 0x30, 0xb9, 0x8a, 0x5b, 0xe4, 0xb1, 0xce, 0xdb, 0x7c, + 0xb8, 0x55, 0x84, 0xa3, 0x52, 0x0e, 0x14, 0x2d, 0x47, 0x4d, 0xc9, 0xcc, + 0xb9, 0x09, 0xa0, 0x73, 0xa9, 0x76, 0xbf, 0x63 + }, + .peer_pub = (const unsigned char[]) { + 0x2b, 0x55, 0xd3, 0xaa, 0x4a, 0x8f, 0x80, 0xc8, 0xc0, 0xb2, 0xae, 0x5f, + 0x93, 0x3e, 0x85, 0xaf, 0x49, 0xbe, 0xac, 0x36, 0xc2, 0xfa, 0x73, 0x94, + 0xba, 0xb7, 0x6c, 0x89, 0x33, 0xf8, 0xf8, 0x1d + }, + .shared_secret = (const unsigned char[]) { + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + }, + }; + ICA_X25519_CTX *ctx = NULL; + unsigned char shared_secret[32]; + size_t i = 0; + + if (ica_x25519_ctx_new(&ctx)) + EXIT_ERR("ica_x448_ctx_new failed."); + + for (i = 0; i < sizeof(vec) / sizeof(vec[0]); i++) { + if (ica_x25519_key_set(ctx, vec[i].priv, NULL) != 0) + EXIT_ERR("ica_x25519_key_set failed."); + + if (ica_x25519_derive(ctx, + shared_secret, vec[i].peer_pub) != 0) + EXIT_ERR("ica_x25519_derive failed."); + + if (memcmp(shared_secret, vec[i].shared_secret, 32) != 0) + EXIT_ERR("x25519 shared secrets do not match."); + } + + (void)ica_x25519_ctx_del(&ctx); +} + +static void x448_kat(void) +{ + struct kat vec[] = { + { + /* openssl test vectors */ + .priv = (const unsigned char[]) { + 0x9a, 0x8f, 0x49, 0x25, 0xd1, 0x51, 0x9f, 0x57, 0x75, 0xcf, 0x46, 0xb0, + 0x4b, 0x58, 0x00, 0xd4, 0xee, 0x9e, 0xe8, 0xba, 0xe8, 0xbc, 0x55, 0x65, + 0xd4, 0x98, 0xc2, 0x8d, 0xd9, 0xc9, 0xba, 0xf5, 0x74, 0xa9, 0x41, 0x97, + 0x44, 0x89, 0x73, 0x91, 0x00, 0x63, 0x82, 0xa6, 0xf1, 0x27, 0xab, 0x1d, + 0x9a, 0xc2, 0xd8, 0xc0, 0xa5, 0x98, 0x72, 0x6b + }, + .peer_pub = (const unsigned char[]) { + 0x3e, 0xb7, 0xa8, 0x29, 0xb0, 0xcd, 0x20, 0xf5, 0xbc, 0xfc, 0x0b, 0x59, + 0x9b, 0x6f, 0xec, 0xcf, 0x6d, 0xa4, 0x62, 0x71, 0x07, 0xbd, 0xb0, 0xd4, + 0xf3, 0x45, 0xb4, 0x30, 0x27, 0xd8, 0xb9, 0x72, 0xfc, 0x3e, 0x34, 0xfb, + 0x42, 0x32, 0xa1, 0x3c, 0xa7, 0x06, 0xdc, 0xb5, 0x7a, 0xec, 0x3d, 0xae, + 0x07, 0xbd, 0xc1, 0xc6, 0x7b, 0xf3, 0x36, 0x09 + }, + .shared_secret = (const unsigned char[]) { + 0x07, 0xff, 0xf4, 0x18, 0x1a, 0xc6, 0xcc, 0x95, 0xec, 0x1c, 0x16, 0xa9, + 0x4a, 0x0f, 0x74, 0xd1, 0x2d, 0xa2, 0x32, 0xce, 0x40, 0xa7, 0x75, 0x52, + 0x28, 0x1d, 0x28, 0x2b, 0xb6, 0x0c, 0x0b, 0x56, 0xfd, 0x24, 0x64, 0xc3, + 0x35, 0x54, 0x39, 0x36, 0x52, 0x1c, 0x24, 0x40, 0x30, 0x85, 0xd5, 0x9a, + 0x44, 0x9a, 0x50, 0x37, 0x51, 0x4a, 0x87, 0x9d + } + }, + { + .priv = (const unsigned char[]) { + 0x9a, 0x8f, 0x49, 0x25, 0xd1, 0x51, 0x9f, 0x57, 0x75, 0xcf, 0x46, 0xb0, + 0x4b, 0x58, 0x00, 0xd4, 0xee, 0x9e, 0xe8, 0xba, 0xe8, 0xbc, 0x55, 0x65, + 0xd4, 0x98, 0xc2, 0x8d, 0xd9, 0xc9, 0xba, 0xf5, 0x74, 0xa9, 0x41, 0x97, + 0x44, 0x89, 0x73, 0x91, 0x00, 0x63, 0x82, 0xa6, 0xf1, 0x27, 0xab, 0x1d, + 0x9a, 0xc2, 0xd8, 0xc0, 0xa5, 0x98, 0x72, 0x6b + }, + .peer_pub = (const unsigned char[]) { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }, + .shared_secret = (const unsigned char[]) { + 0x66, 0xe2, 0xe6, 0x82, 0xb1, 0xf8, 0xe6, 0x8c, 0x80, 0x9f, 0x1b, 0xb3, + 0xe4, 0x06, 0xbd, 0x82, 0x69, 0x21, 0xd9, 0xc1, 0xa5, 0xbf, 0xbf, 0xcb, + 0xab, 0x7a, 0xe7, 0x2f, 0xee, 0xce, 0xe6, 0x36, 0x60, 0xea, 0xbd, 0x54, + 0x93, 0x4f, 0x33, 0x82, 0x06, 0x1d, 0x17, 0x60, 0x7f, 0x58, 0x1a, 0x90, + 0xbd, 0xac, 0x91, 0x7a, 0x06, 0x49, 0x59, 0xfb + } + } + }; + ICA_X448_CTX *ctx = NULL; + unsigned char shared_secret[56]; + size_t i = 0; + + if (ica_x448_ctx_new(&ctx)) + EXIT_ERR("ica_x448_ctx_new failed."); + + for (i = 0; i < sizeof(vec) / sizeof(vec[0]); i++) { + if (ica_x448_key_set(ctx, vec[i].priv, NULL) != 0) + EXIT_ERR("ica_x448_key_set failed."); + + if (ica_x448_derive(ctx, + shared_secret, vec[i].peer_pub) != 0) + EXIT_ERR("ica_x448_derive failed."); + + if (memcmp(shared_secret, vec[i].shared_secret, 56) != 0) + EXIT_ERR("x448 shared secrets do not match."); + } + + (void)ica_x448_ctx_del(&ctx); +}