Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Montgomery multiplication #446

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 133 additions & 0 deletions src/bolos/cx_bn.c
Original file line number Diff line number Diff line change
Expand Up @@ -499,3 +499,136 @@ cx_err_t sys_cx_bn_gf2_n_mul(cx_bn_t bn_r, const cx_bn_t bn_a,
end:
return error;
}

/* ========================================================================= */
/* === MONTGOMERY MODULAR ARITHMETIC === */
/* ========================================================================= */

#define _2POWB \
{ \
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00 \
} /*2^128*/
#define _2POWBm1 \
{ \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff \
} /* 2^128-1*/

cx_err_t sys_cx_mont_alloc(cx_bn_mont_ctx_t *ctx, size_t length)
{
cx_err_t error;

CX_CHECK(sys_cx_bn_alloc(&ctx->n, length));
CX_CHECK(sys_cx_bn_alloc(&ctx->h, length));

end:
return error;
}

cx_err_t sys_cx_mont_init(cx_bn_mont_ctx_t *ctx, const cx_bn_t n)
{
cx_err_t error;
size_t sizen;
uint8_t tu8_basis[] = _2POWB;
uint8_t tu8_basism1[] = _2POWBm1;
cx_bn_t basis, temp;

CX_CHECK(sys_cx_bn_nbytes(n, &sizen));
CX_CHECK(sys_cx_bn_alloc_init(&basis, sizen, tu8_basis,
(size_t)sizeof(tu8_basis)));
CX_CHECK(sys_cx_bn_alloc(&temp, sizen));

/* copy modulus*/
CX_CHECK(sys_cx_bn_copy((ctx->n), n));
/* -p^-1 mod 2^sizeword*/
CX_CHECK(sys_cx_bn_reduce(temp, n, basis));

CX_CHECK(sys_cx_bn_mod_pow(ctx->h, temp, tu8_basism1, sizeof(tu8_basism1),
basis)); /*1/P mod 2^n*/

/* 2^bitsizeof(n) mod n */
CX_CHECK(sys_cx_bn_xor(basis, basis, basis)); /* zero*/
CX_CHECK(sys_cx_bn_set_bit(
basis,
(sizen << 3) - 1)); /*2^(sizeofp)-1 to fit in memory before reduction*/
CX_CHECK(sys_cx_bn_mod_add(temp, basis, basis, n)); /* 2^(bitsize(p))*/
CX_CHECK(sys_cx_bn_mod_mul(ctx->h, temp, temp, n)); /* 2^(bitsize(p))^2*/

sys_cx_bn_destroy(&temp);
sys_cx_bn_destroy(&basis);

end:
return error;
}

cx_err_t sys_cx_mont_init2(cx_bn_mont_ctx_t *ctx, const cx_bn_t n,
const cx_bn_t h)
{
cx_err_t error = CX_OK; // By default, until some error occurs

CX_CHECK(sys_cx_bn_copy((ctx->n), n));
CX_CHECK(sys_cx_bn_copy((ctx->h), h));

end:
return error;
}

/* a horrible emulation of cx_mont_mul, not present in speculos, compute
* aR*bR=abR mod p*/
/* todo: integrate some decent Montgomery implementation (maybe OpenSSL
* BN_mod_mul_montgomery()) */
cx_err_t sys_cx_mont_mul(cx_bn_t r, const cx_bn_t a, const cx_bn_t b,
const cx_bn_mont_ctx_t *ctx)
{
cx_err_t error = CX_OK; // By default, until some error occurs
size_t field;

cx_bn_t temp;

CX_CHECK(sys_cx_bn_nbytes(ctx->n, &field));

CX_CHECK(sys_cx_bn_alloc(&temp, field));

CX_CHECK(sys_cx_bn_mod_invert_nprime(
temp, ctx->h,
ctx->n)); /* R^-1 (yes an inversion to emulate a mul, god forgive me)*/

CX_CHECK(sys_cx_bn_mod_mul(temp, a, temp, ctx->n));
CX_CHECK(sys_cx_bn_mod_mul(r, b, temp, ctx->n));

sys_cx_bn_destroy(&temp);

end:
return error;
}

cx_err_t sys_cx_mont_to_montgomery(cx_bn_t x, const cx_bn_t z,
const cx_bn_mont_ctx_t *ctx)
{
cx_err_t error = CX_OK; // By default, until some error occurs

CX_CHECK(sys_cx_bn_mod_mul(x, ctx->h, z, ctx->n));

end:
return error;
}

cx_err_t sys_cx_mont_from_montgomery(cx_bn_t z, const cx_bn_t x,
const cx_bn_mont_ctx_t *ctx)
{
cx_err_t error = CX_OK; // By default, until some error occurs
cx_bn_t temp;
size_t field;

CX_CHECK(sys_cx_bn_nbytes(ctx->h, &field));
CX_CHECK(sys_cx_bn_alloc(&temp, field));

CX_CHECK(sys_cx_bn_set_u32(temp, 1));
CX_CHECK(sys_cx_mont_mul(z, temp, x, ctx));

CX_CHECK(sys_cx_bn_destroy(&temp));

end:
return error;
}
16 changes: 16 additions & 0 deletions src/bolos/cxlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ typedef struct cx_mpi_ecpoint_s {

} cx_mpi_ecpoint_t;

// Montgomery context.
typedef struct {
cx_bn_t n; // Modulus
cx_bn_t h; // Second Montgomery constant
} cx_bn_mont_ctx_t;

//-----------------------------------------------------------------------------
// Prototypes
//-----------------------------------------------------------------------------
Expand Down Expand Up @@ -201,6 +207,16 @@ 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_err_t sys_cx_mont_alloc(cx_bn_mont_ctx_t *ctx, size_t length);
cx_err_t sys_cx_mont_init(cx_bn_mont_ctx_t *ctx, const cx_bn_t n);
cx_err_t sys_cx_mont_init2(cx_bn_mont_ctx_t *ctx, const cx_bn_t n,
const cx_bn_t h);
cx_err_t sys_cx_mont_to_montgomery(cx_bn_t x, const cx_bn_t z,
const cx_bn_mont_ctx_t *ctx);
cx_err_t sys_cx_mont_from_montgomery(cx_bn_t z, const cx_bn_t x,
const cx_bn_mont_ctx_t *ctx);
cx_err_t sys_cx_mont_mul(cx_bn_t r, const cx_bn_t a, const cx_bn_t b,
const cx_bn_mont_ctx_t *ctx);

// cx_ecdomain.c
int cx_nid_from_curve(cx_curve_t curve);
Expand Down
16 changes: 16 additions & 0 deletions src/emulate_lnsp_1.0.c
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,22 @@ int emulate_nanosp_1_0(unsigned long syscall, unsigned long *parameters,
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);

SYSCALL2(cx_mont_alloc, "(%p, %u)", void *, ctx, size_t, length);

SYSCALL2(cx_mont_init, "(%p, %u)", void *, ctx, uint32_t, n);

SYSCALL3(cx_mont_init2, "(%p, %u, %u)", void *, ctx, uint32_t, n, uint32_t,
h);

SYSCALL4(cx_mont_mul, "(%u, %u, %u, %p)", uint32_t, r, uint32_t, a,
uint32_t, b, void *, ctx);

SYSCALL3(cx_mont_to_montgomery, "(%u, %u, %p)", uint32_t, x, uint32_t, z,
void *, ctx);

SYSCALL3(cx_mont_from_montgomery, "(%u, %u, %p)", uint32_t, z, uint32_t, x,
void *, ctx);

// SYSCALLs that may exists on other SDK versions, but with a different ID:

SYSCALL0i(os_perso_isonboarded, os_perso_isonboarded_2_0);
Expand Down
30 changes: 30 additions & 0 deletions src/emulate_unified_sdk.c
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,36 @@ int emulate_syscall_cx(unsigned long syscall, unsigned long *parameters,
uint32_t, n,
uint32_t, h);

SYSCALL2(cx_mont_alloc, "(%p, %u)",
void *, ctx,
size_t, length);


SYSCALL2(cx_mont_init, "(%p, %u)",
void *, ctx,
uint32_t, n);

SYSCALL3(cx_mont_init2, "(%p, %u, %u)",
void *, ctx,
uint32_t, n,
uint32_t, h);

SYSCALL4(cx_mont_mul, "(%u, %u, %u, %p)",
uint32_t, r,
uint32_t, a,
uint32_t, b,
void *, ctx);

SYSCALL3(cx_mont_to_montgomery, "(%u, %u, %p)",
uint32_t, x,
uint32_t, z,
void *, ctx);

SYSCALL3(cx_mont_from_montgomery, "(%u, %u, %p)",
uint32_t, z,
uint32_t, x,
void *, ctx);

SYSCALL10(cx_bls12381_key_gen, "(%u, %p, %u, %p, %u, %p, %u, %p, %p, %u)",
uint8_t, mode,
uint8_t *, secret,
Expand Down
Loading