From a7d0e918321708c1af78f4ea11593842c3872f47 Mon Sep 17 00:00:00 2001 From: Aido Date: Tue, 10 Oct 2023 12:09:22 +0100 Subject: [PATCH] Implement cx_bn_gf2_n_mul() --- CMakeLists.txt | 2 +- src/bolos/cx_bn.c | 18 +++++++++ src/bolos/cx_mpi.c | 13 ++++++ src/bolos/cxlib.h | 5 +++ src/emulate_lnsp_1.0.c | 3 ++ src/emulate_unified_sdk.c | 7 ++++ tests/syscalls/CMakeLists.txt | 3 +- tests/syscalls/test_bn.c | 75 +++++++++++++++++++++++++++++++++++ 8 files changed, 124 insertions(+), 2 deletions(-) create mode 100644 tests/syscalls/test_bn.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 26e82329..3045800a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,7 +85,7 @@ else() openssl URL https://www.openssl.org/source/openssl-1.1.1k.tar.gz URL_HASH SHA256=892a0875b9872acd04a9fde79b1f943075d5ea162415de3047c327df33fbaee5 - CONFIGURE_COMMAND ./Configure "CC=${CMAKE_C_COMPILER}" "CFLAGS=${OPENSSL_CFLAGS}" no-afalgeng no-aria no-asan no-asm no-async no-autoalginit no-autoerrinit no-autoload-config no-bf no-buildtest-c++ no-camellia no-capieng no-cast no-chacha no-cmac no-cms no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-ct no-deprecated no-des no-devcryptoeng no-dgram no-dh no-dsa no-dso no-dtls no-ec2m no-ecdh no-egd no-engine no-err no-external-tests no-filenames no-fuzz-afl no-fuzz-libfuzzer no-gost no-heartbeats no-hw no-idea no-makedepend no-md2 no-md4 no-mdc2 no-msan no-multiblock no-nextprotoneg no-ocb no-ocsp no-pinshared no-poly1305 no-posix-io no-psk no-rc2 no-rc4 no-rc5 no-rdrand no-rfc3779 no-scrypt no-sctp no-seed no-shared no-siphash no-sm2 no-sm3 no-sm4 no-sock no-srp no-srtp no-sse2 no-ssl no-ssl3-method no-ssl-trace no-stdio no-tests no-threads no-tls no-ts no-ubsan no-ui-console no-unit-test no-whirlpool no-zlib no-zlib-dynamic linux-armv4 --prefix=${INSTALL_DIR} + CONFIGURE_COMMAND ./Configure "CC=${CMAKE_C_COMPILER}" "CFLAGS=${OPENSSL_CFLAGS}" no-afalgeng no-aria no-asan no-asm no-async no-autoalginit no-autoerrinit no-autoload-config no-bf no-buildtest-c++ no-camellia no-capieng no-cast no-chacha no-cmac no-cms no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-ct no-deprecated no-des no-devcryptoeng no-dgram no-dh no-dsa no-dso no-dtls no-ecdh no-egd no-engine no-err no-external-tests no-filenames no-fuzz-afl no-fuzz-libfuzzer no-gost no-heartbeats no-hw no-idea no-makedepend no-md2 no-md4 no-mdc2 no-msan no-multiblock no-nextprotoneg no-ocb no-ocsp no-pinshared no-poly1305 no-posix-io no-psk no-rc2 no-rc4 no-rc5 no-rdrand no-rfc3779 no-scrypt no-sctp no-seed no-shared no-siphash no-sm2 no-sm3 no-sm4 no-sock no-srp no-srtp no-sse2 no-ssl no-ssl3-method no-ssl-trace no-stdio no-tests no-threads no-tls no-ts no-ubsan no-ui-console no-unit-test no-whirlpool no-zlib no-zlib-dynamic linux-armv4 --prefix=${INSTALL_DIR} BUILD_COMMAND make INSTALL_COMMAND make install_sw BUILD_IN_SOURCE 1 diff --git a/src/bolos/cx_bn.c b/src/bolos/cx_bn.c index 63d93a9a..99205844 100644 --- a/src/bolos/cx_bn.c +++ b/src/bolos/cx_bn.c @@ -481,3 +481,21 @@ cx_err_t sys_cx_bn_next_prime(const cx_bn_t bn_x) end: return error; } + +cx_err_t sys_cx_bn_gf2_n_mul(cx_bn_t bn_r, const cx_bn_t bn_a, + const cx_bn_t bn_b, const cx_bn_t bn_n, + const cx_bn_t bn_h) +{ + cx_err_t error = CX_OK; // By default, until some error occurs + cx_mpi_t *r, *a, *b, *n, *h; + + // Convert bn to mpi + CX_CHECK(cx_bn_rab_to_mpi(bn_r, &r, bn_a, &a, bn_b, &b)); + CX_CHECK(cx_bn_ab_to_mpi(bn_n, &n, bn_h, &h)); + + // Perform a Galois field multiplication operation reduced by n + CX_CHECK(cx_mpi_gf2_n_mul(r, a, b, n, h)); + +end: + return error; +} diff --git a/src/bolos/cx_mpi.c b/src/bolos/cx_mpi.c index dbec1376..cf600af3 100644 --- a/src/bolos/cx_mpi.c +++ b/src/bolos/cx_mpi.c @@ -1167,6 +1167,19 @@ cx_err_t cx_mpi_next_prime(cx_mpi_t *x) return error; } +cx_err_t cx_mpi_gf2_n_mul(cx_mpi_t *r, const cx_mpi_t *a, const cx_mpi_t *b, + const cx_mpi_t *n, + const cx_mpi_t *h __attribute__((unused))) +{ + cx_err_t error = CX_OK; // By default, until some error occurs + + if (!BN_GF2m_mod_mul(r, a, b, n, local_bn_ctx)) { + error = CX_INTERNAL_ERROR; + } + + return error; +} + #define MAX_BYTE_LEN 128 void cx_mpi_reverse(cx_mpi_t *x, uint32_t nbytes) { diff --git a/src/bolos/cxlib.h b/src/bolos/cxlib.h index 59fe2144..747d2272 100644 --- a/src/bolos/cxlib.h +++ b/src/bolos/cxlib.h @@ -134,6 +134,8 @@ cx_err_t cx_mpi_mod_pow(cx_mpi_t *r, const cx_mpi_t *a, const cx_mpi_t *e, const cx_mpi_t *n); cx_err_t cx_mpi_is_prime(cx_mpi_t *x, bool *prime); cx_err_t cx_mpi_next_prime(cx_mpi_t *x); +cx_err_t cx_mpi_gf2_n_mul(cx_mpi_t *r, const cx_mpi_t *a, const cx_mpi_t *b, + const cx_mpi_t *n, const cx_mpi_t *h); void cx_mpi_reverse(cx_mpi_t *x, uint32_t nbytes); void cx_mpi_swap(cx_mpi_t *a, cx_mpi_t *b, const int c); @@ -196,6 +198,9 @@ cx_err_t sys_cx_bn_mod_pow2(cx_bn_t bn_r, const cx_bn_t bn_a, const uint8_t *e, uint32_t len_e, const cx_bn_t bn_n); cx_err_t sys_cx_bn_is_prime(const cx_bn_t bn_x, bool *prime); cx_err_t sys_cx_bn_next_prime(const cx_bn_t bn_x); +cx_err_t sys_cx_bn_gf2_n_mul(cx_bn_t bn_r, const cx_bn_t bn_a, + const cx_bn_t bn_b, const cx_bn_t bn_n, + const cx_bn_t bn_h); // cx_ecdomain.c int cx_nid_from_curve(cx_curve_t curve); diff --git a/src/emulate_lnsp_1.0.c b/src/emulate_lnsp_1.0.c index 744862c0..daead103 100644 --- a/src/emulate_lnsp_1.0.c +++ b/src/emulate_lnsp_1.0.c @@ -266,6 +266,9 @@ int emulate_nanosp_1_0(unsigned long syscall, unsigned long *parameters, SYSCALL1(cx_bn_next_prime, "(%u)", uint32_t, a); + SYSCALL5(cx_bn_gf2_n_mul, "(%u, %u, %u, %u, %u)", uint32_t, r, uint32_t, a, + uint32_t, b, uint32_t, n, uint32_t, h); + // SYSCALLs that may exists on other SDK versions, but with a different ID: SYSCALL0i(os_perso_isonboarded, os_perso_isonboarded_2_0); diff --git a/src/emulate_unified_sdk.c b/src/emulate_unified_sdk.c index 5fd52597..416734a9 100644 --- a/src/emulate_unified_sdk.c +++ b/src/emulate_unified_sdk.c @@ -524,6 +524,13 @@ int emulate_syscall_cx(unsigned long syscall, unsigned long *parameters, SYSCALL1(cx_bn_next_prime, "(%u)", uint32_t, a); + SYSCALL5(cx_bn_gf2_n_mul, "(%u, %u, %u, %u, %u)", + uint32_t, r, + uint32_t, a, + uint32_t, b, + uint32_t, n, + uint32_t, h); + SYSCALL10(cx_bls12381_key_gen, "(%u, %p, %u, %p, %u, %p, %u, %p, %p, %u)", uint8_t, mode, uint8_t *, secret, diff --git a/tests/syscalls/CMakeLists.txt b/tests/syscalls/CMakeLists.txt index 700745a3..546e591c 100644 --- a/tests/syscalls/CMakeLists.txt +++ b/tests/syscalls/CMakeLists.txt @@ -8,6 +8,7 @@ add_executable(test_aes test_aes.c nist_cavp.c utils.c) add_executable(test_bip32 test_bip32.c utils.c) add_executable(test_blake2 test_blake2.c nist_cavp.c utils.c) add_executable(test_bls test_bls.c utils.c) +add_executable(test_bn test_bn.c) add_executable(test_crc16 test_crc16.c) add_executable(test_ecdh test_ecdh.c utils.c) add_executable(test_ecdsa test_ecdsa.c utils.c) @@ -26,6 +27,6 @@ add_executable(test_sha2 test_sha2.c nist_cavp.c utils.c) add_executable(test_sha3 test_sha3.c nist_cavp.c utils.c) add_executable(test_slip21 test_slip21.c) -foreach(target hello test_aes test_bip32 test_blake2 test_bls test_crc16 test_ec test_ecpoint test_ecdh test_ecdsa test_eddsa test_endorsement test_hmac test_math test_os_global_pin_is_validated test_rfc6979 test_ripemd test_sha2 test_sha3 test_slip21 test_eip2333) +foreach(target hello test_aes test_bip32 test_blake2 test_bls test_bn test_crc16 test_ec test_ecpoint test_ecdh test_ecdsa test_eddsa test_endorsement test_hmac test_math test_os_global_pin_is_validated test_rfc6979 test_ripemd test_sha2 test_sha3 test_slip21 test_eip2333) add_test(NAME ${target} COMMAND qemu-arm-static ${target} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) endforeach() diff --git a/tests/syscalls/test_bn.c b/tests/syscalls/test_bn.c new file mode 100644 index 00000000..4d8631b5 --- /dev/null +++ b/tests/syscalls/test_bn.c @@ -0,0 +1,75 @@ +#include +#include +#include +// must come after setjmp.h +#include + +#include "bolos/cxlib.h" + +#define GF2_8_MPI_BYTES 1 + +static void test_cx_bn_gf2_n_mul(void **state __attribute__((unused))) +{ + cx_err_t error = CX_OK; + + cx_bn_t a, // multiplicand + b, // multiplier + m, // modulus + r, // result + r2; // Montgomery constant + + // A(x) + const uint8_t multiplicand[1] = { 0x1B }; // 27 + // B(x) + const uint8_t multiplier[1] = { 0x3D }; // 61 + + // The irreducible polynomial N(x) = x^8 + x^4 + x^3 + x + 1 + const uint8_t N[2] = { 0x01, 0x1B }; // 283 + + // 2nd Montgomery constant: R2 = x^(2*t*8) mod N(x) + // t = 1 since the number of bytes of R is 1. + const uint8_t R2[1] = { 0x56 }; + + // Expected result of N(x) = A(x )* B(x) + const uint32_t re = 0x49; // result expected = 71 + int diff; + + CX_CHECK(sys_cx_bn_lock(GF2_8_MPI_BYTES, 0)); + CX_CHECK(sys_cx_bn_alloc(&r, GF2_8_MPI_BYTES)); + CX_CHECK(sys_cx_bn_alloc_init(&a, GF2_8_MPI_BYTES, multiplicand, + sizeof(multiplicand))); + CX_CHECK(sys_cx_bn_alloc_init(&b, GF2_8_MPI_BYTES, multiplier, + sizeof(multiplier))); + CX_CHECK(sys_cx_bn_alloc_init(&m, GF2_8_MPI_BYTES, N, sizeof(N))); + CX_CHECK(sys_cx_bn_alloc_init(&r2, GF2_8_MPI_BYTES, R2, sizeof(R2))); + + // Perform the Galois Field GF(2m) multiplication operation + CX_CHECK(sys_cx_bn_gf2_n_mul(r, a, b, m, r2)); + + // Compare result to expected result + CX_CHECK(sys_cx_bn_cmp_u32(r, re, &diff)); + + CX_CHECK(sys_cx_bn_destroy(&r)); + CX_CHECK(sys_cx_bn_destroy(&a)); + CX_CHECK(sys_cx_bn_destroy(&b)); + CX_CHECK(sys_cx_bn_destroy(&m)); + CX_CHECK(sys_cx_bn_destroy(&r2)); + +end: + if (sys_cx_bn_is_locked()) { + sys_cx_bn_unlock(); + } + + // Assert that there are no errors + assert_int_equal(error, CX_OK); + + // Assert that the result is correct + assert_int_equal(diff, 0); +} + +int main(void) +{ + const struct CMUnitTest tests[] = { cmocka_unit_test(test_cx_bn_gf2_n_mul) }; + + return cmocka_run_group_tests(tests, NULL, NULL); +}