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 May 19, 2024
1 parent 62dd047 commit 1a15fad
Show file tree
Hide file tree
Showing 2 changed files with 95 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 */
69 changes: 69 additions & 0 deletions src/cx_wrappers.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,72 @@ 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;
uint32_t degree, nbits_a, nbits_b;

// Calculate the degree of the modulus polynomial
CX_CHECK(cx_bn_cnt_bits(bn_n, &degree));
degree--;

CX_CHECK(cx_bn_cnt_bits(bn_a, &nbits_a));
CX_CHECK(cx_bn_cnt_bits(bn_b, &nbits_b));

// Ensure both operands are in field
if (degree < 1 || nbits_a > degree || nbits_b > degree) {
error = CX_INVALID_PARAMETER;
goto end;
}

// Preliminaries
cx_bn_t bn_tempa, bn_tempb, bn_tempx;
uint32_t bit_indexb = 0;
size_t nbytes;
bool bit_set = 0;

CX_CHECK(cx_bn_nbytes(bn_n, &nbytes));
CX_CHECK(cx_bn_alloc(&bn_tempa, nbytes));
CX_CHECK(cx_bn_alloc(&bn_tempb, nbytes));
CX_CHECK(cx_bn_alloc(&bn_tempx, nbytes));

CX_CHECK(cx_bn_copy(bn_tempa, bn_a));
CX_CHECK(cx_bn_copy(bn_tempb, bn_b));
CX_CHECK(cx_bn_set_u32(bn_r, (uint32_t) 0));

// Main loop for multiplication
if (nbits_a) {
while (nbits_b > bit_indexb) {
CX_CHECK(cx_bn_tst_bit(bn_tempb, bit_indexb, &bit_set));
if (bit_set) {
CX_CHECK(cx_bn_copy(bn_tempx, bn_r));
CX_CHECK(cx_bn_xor(bn_r, bn_tempa, bn_tempx));
}

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

if (bit_set) {
CX_CHECK(cx_bn_copy(bn_tempx, bn_tempa));
CX_CHECK(cx_bn_xor(bn_tempa, bn_n, bn_tempx));
}

bit_indexb++;
}
}

// Clean up
CX_CHECK(cx_bn_destroy(&bn_tempa));
CX_CHECK(cx_bn_destroy(&bn_tempb));
CX_CHECK(cx_bn_destroy(&bn_tempx));

end:
return error;
}

0 comments on commit 1a15fad

Please sign in to comment.