Skip to content

Commit

Permalink
Implement cx_bn_gf2_n_mul
Browse files Browse the repository at this point in the history
Workaround that implements cx_bn_gf2_n_mul() in the SDK until it is hopefully added as a syscall like all other Ledger devices
Fixes LedgerHQ#64
  • Loading branch information
aido committed Feb 29, 2024
1 parent 62dd047 commit f468f15
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 0 deletions.
26 changes: 26 additions & 0 deletions include/ox_bn.h
Original file line number Diff line number Diff line change
Expand Up @@ -1075,4 +1075,30 @@ SYSCALL cx_err_t cx_bn_next_prime(cx_bn_t n);
*/
SYSCALL cx_err_t cx_bn_rng(cx_bn_t r, const cx_bn_t n);

/**
* @brief Performs a multiplication over GF(2^n).
*
* @param[out] bn_r BN index for the result.
*
* @param[in] bn_a BN index of the first operand.
*
* @param[in] bn_b BN index of the second operand.
*
* @param[in] bn_n BN index of the modulus.
* The modulus must be an irreducible polynomial over GF(2)
* of degree n.
*
* @param[in] bn_h BN index of the second montgomery constant.
*
* @return Error code:
* - CX_OK on success
* - CX_NOT_LOCKED
* - CX_INVALID_PARAMETER
* - CX_MEMORY_FULL
*/
WARN_UNUSED_RESULT cx_err_t 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);
#endif /* CX_BN_H */
89 changes: 89 additions & 0 deletions src/cx_wrappers.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,92 @@ uint32_t cx_crc32(const void *buf, size_t len)
{
return cx_crc32_update(CX_CRC32_INIT, buf, len);
}

// At some point this could/should be migrated to the OS
// Meanwhile, it's implemented here
cx_err_t 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 __attribute__((unused))) {
cx_err_t error = CX_OK;
cx_bn_t bn_x, bn_y, bn_temp;
int cmp_x, cmp_y;
uint32_t degree = 0;
size_t nbytes;
bool bit_set = 0;

// Preliminaries
CX_CHECK(cx_bn_nbytes(bn_n, &nbytes));
CX_CHECK(cx_bn_alloc(&bn_x, nbytes));
CX_CHECK(cx_bn_alloc(&bn_y, nbytes));
CX_CHECK(cx_bn_alloc(&bn_temp, nbytes));
CX_CHECK(cx_bn_copy(bn_x, bn_a));
CX_CHECK(cx_bn_copy(bn_y, bn_b));

// Calculate the degree of the modulus polynomial
CX_CHECK(cx_bn_copy(bn_temp, bn_n));
do {
CX_CHECK(cx_bn_cmp_u32(bn_temp, (uint32_t) 0, &cmp_x));
CX_CHECK(cx_bn_shr(bn_temp, 1));
} while (cmp_x != 0 && ++degree);

// After loop degree is offset by 1
degree--;
if (degree < 1) {
error = CX_INVALID_PARAMETER;
goto end;
}

// Ensure both operands are in field
CX_CHECK(cx_bn_shr(bn_x, degree));
CX_CHECK(cx_bn_shr(bn_y, degree));
// Maybe change cx_bn_cmp_u32 to cx_bn_cnt_bits
CX_CHECK(cx_bn_cmp_u32(bn_x, (uint32_t) 0, &cmp_x));
CX_CHECK(cx_bn_cmp_u32(bn_y, (uint32_t) 0, &cmp_y));

if (cmp_x != 0 || cmp_y != 0) {
error = CX_INVALID_PARAMETER;
goto end;
}

// Check if both operands are non-zero
CX_CHECK(cx_bn_copy(bn_x, bn_a));
CX_CHECK(cx_bn_copy(bn_y, bn_b));
// Maybe cx_bn_cmp_u32 change to cx_bn_cnt_bits
CX_CHECK(cx_bn_cmp_u32(bn_x, (uint32_t) 0, &cmp_x));
CX_CHECK(cx_bn_cmp_u32(bn_y, (uint32_t) 0, &cmp_y));

CX_CHECK(cx_bn_set_u32(bn_r, (uint32_t) 0));

// Main loop for multiplication
while (cmp_x != 0 && cmp_y != 0) {
CX_CHECK(cx_bn_tst_bit(bn_y, 0, &bit_set));
if (bit_set) {
CX_CHECK(cx_bn_copy(bn_temp, bn_r));
CX_CHECK(cx_bn_xor(bn_r, bn_x, bn_temp));
}

CX_CHECK(cx_bn_shl(bn_x, 1));
CX_CHECK(cx_bn_tst_bit(bn_x, degree, &bit_set));

if (bit_set) {
CX_CHECK(cx_bn_copy(bn_temp, bn_x));
CX_CHECK(cx_bn_xor(bn_x, bn_n, bn_temp));
}

CX_CHECK(cx_bn_shr(bn_y, 1));

// Maybe change cx_bn_cmp_u32 to cx_bn_cnt_bits
CX_CHECK(cx_bn_cmp_u32(bn_x, (uint32_t) 0, &cmp_x));
CX_CHECK(cx_bn_cmp_u32(bn_y, (uint32_t) 0, &cmp_y));
}

// Clean up
CX_CHECK(cx_bn_destroy(&bn_x));
CX_CHECK(cx_bn_destroy(&bn_y));
CX_CHECK(cx_bn_destroy(&bn_temp));

end:
return error;
}

0 comments on commit f468f15

Please sign in to comment.