mirror of
https://github.com/cesanta/mongoose.git
synced 2026-10-27 12:26:24 +00:00
2262 lines
70 KiB
C
2262 lines
70 KiB
C
// P-256 for Cortex-M4/M7/M33, https://github.com/Emill/P256-Cortex-M4
|
|
// commit ecd3ec2
|
|
// Enabled by MG_P256=MG_P256_LENNGREN. Provides mg_p256_*(), see tls_p256.h
|
|
//
|
|
// Copyright (c) 2017-2021 Emil Lenngren
|
|
// Copyright (c) 2021 Shortcut Labs AB
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
// in the Software without restriction, including without limitation the rights
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in all
|
|
// copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
// SOFTWARE.
|
|
//
|
|
// Mongoose changes: the library's C code, header, config and GCC assembly are
|
|
// merged into one file, the assembly is a top-level __asm__ without .end.
|
|
// Trimmed with unifdef to keygen, ECDH, sign and verify. Uses the no-FPU field
|
|
// multiplication and the constant RAM access pattern table lookup (safe with a
|
|
// data cache). Internal C functions are static, casts added in slide_257().
|
|
// mg_p256_*() wrappers are at the end
|
|
|
|
#include "tls_p256.h"
|
|
#include "util.h"
|
|
|
|
#if MG_P256 == MG_P256_LENNGREN && \
|
|
(MG_TLS == MG_TLS_BUILTIN || defined(MG_OTA_PUBLIC_KEY))
|
|
|
|
typedef const uint32_t (*constarr)[8];
|
|
|
|
struct FGInteger {
|
|
// To get the value this struct represents,
|
|
// interpret signed_value as a two's complement 288-bit little endian integer,
|
|
// and negate if flip_sign is -1
|
|
int flip_sign; // 0 or -1
|
|
uint32_t signed_value[9]; // of 288 bits, 257 are useful (top 31 bits are sign-extended from bit 256)
|
|
};
|
|
|
|
struct SignPrecomp { // p256_sign_step1() result
|
|
uint32_t r[8];
|
|
uint32_t k_inv[8];
|
|
};
|
|
|
|
struct XYInteger {
|
|
// To get the value this struct represents,
|
|
// interpret signed_value as an unsigned 288-bit little endian integer,
|
|
// and negate if flip_sign is -1
|
|
int flip_sign; // 0 or -1
|
|
uint32_t value[8]; // unsigned value, 0 <= value < P256_order
|
|
};
|
|
|
|
int P256_divsteps2_31(int delta, uint32_t f, uint32_t g, uint32_t res_matrix[4]);
|
|
void P256_matrix_mul_fg_9(uint32_t a, uint32_t b, const struct FGInteger fg[2], struct FGInteger *res);
|
|
void P256_matrix_mul_mod_n(uint32_t a, uint32_t b, const struct XYInteger xy[2], struct XYInteger *res);
|
|
|
|
void P256_to_montgomery(uint32_t aR[8], const uint32_t a[8]);
|
|
void P256_from_montgomery(uint32_t a[8], const uint32_t aR[8]);
|
|
bool P256_check_range_p(const uint32_t a[8]);
|
|
|
|
bool P256_check_range_n(const uint32_t a[8]);
|
|
void P256_mul_mod_n(uint32_t res[8], const uint32_t a[8], const uint32_t b[8]);
|
|
void P256_add_mod_n(uint32_t res[8], const uint32_t a[8], const uint32_t b[8]);
|
|
void P256_reduce_mod_n_32bytes(uint32_t res[8], const uint32_t a[8]);
|
|
|
|
void P256_select_point(uint32_t (*output)[8], uint32_t* table, uint32_t num_coordinates, uint32_t index);
|
|
|
|
void P256_jacobian_to_affine(uint32_t affine_mont_x[8], uint32_t affine_mont_y[8], const uint32_t jacobian_mont[3][8]);
|
|
bool P256_point_is_on_curve(const uint32_t x_mont[8], const uint32_t y_mont[8]);
|
|
void P256_double_j(uint32_t jacobian_point_out[3][8], const uint32_t jacobian_point_in[3][8]);
|
|
void P256_add_sub_j(uint32_t jacobian_point1[3][8], const uint32_t (*point2)[8], bool is_sub, bool p2_is_affine);
|
|
bool P256_verify_last_step(const uint32_t r[8], const uint32_t jacobian_point[3][8]);
|
|
|
|
void P256_negate_mod_p_if(uint32_t out[8], const uint32_t in[8], uint32_t should_negate);
|
|
void P256_negate_mod_n_if(uint32_t out[8], const uint32_t in[8], uint32_t should_negate);
|
|
|
|
extern uint32_t P256_order[9];
|
|
|
|
static const uint32_t one_montgomery[8] = {1, 0, 0, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffffe, 0};
|
|
|
|
// This table contains 1G, 3G, 5G, ... 15G in affine coordinates in montgomery form
|
|
static const uint32_t p256_basepoint_precomp[8][2][8] = {
|
|
{{0x18a9143c, 0x79e730d4, 0x5fedb601, 0x75ba95fc, 0x77622510, 0x79fb732b, 0xa53755c6, 0x18905f76},
|
|
{0xce95560a, 0xddf25357, 0xba19e45c, 0x8b4ab8e4, 0xdd21f325, 0xd2e88688, 0x25885d85, 0x8571ff18}},
|
|
{{0x4eebc127, 0xffac3f90, 0x87d81fb, 0xb027f84a, 0x87cbbc98, 0x66ad77dd, 0xb6ff747e, 0x26936a3f},
|
|
{0xc983a7eb, 0xb04c5c1f, 0x861fe1a, 0x583e47ad, 0x1a2ee98e, 0x78820831, 0xe587cc07, 0xd5f06a29}},
|
|
{{0xc45c61f5, 0xbe1b8aae, 0x94b9537d, 0x90ec649a, 0xd076c20c, 0x941cb5aa, 0x890523c8, 0xc9079605},
|
|
{0xe7ba4f10, 0xeb309b4a, 0xe5eb882b, 0x73c568ef, 0x7e7a1f68, 0x3540a987, 0x2dd1e916, 0x73a076bb}},
|
|
{{0xa0173b4f, 0x746354e, 0xd23c00f7, 0x2bd20213, 0xc23bb08, 0xf43eaab5, 0xc3123e03, 0x13ba5119},
|
|
{0x3f5b9d4d, 0x2847d030, 0x5da67bdd, 0x6742f2f2, 0x77c94195, 0xef933bdc, 0x6e240867, 0xeaedd915}},
|
|
{{0x264e20e8, 0x75c96e8f, 0x59a7a841, 0xabe6bfed, 0x44c8eb00, 0x2cc09c04, 0xf0c4e16b, 0xe05b3080},
|
|
{0xa45f3314, 0x1eb7777a, 0xce5d45e3, 0x56af7bed, 0x88b12f1a, 0x2b6e019a, 0xfd835f9b, 0x86659cd}},
|
|
{{0x6245e404, 0xea7d260a, 0x6e7fdfe0, 0x9de40795, 0x8dac1ab5, 0x1ff3a415, 0x649c9073, 0x3e7090f1},
|
|
{0x2b944e88, 0x1a768561, 0xe57f61c8, 0x250f939e, 0x1ead643d, 0xc0daa89, 0xe125b88e, 0x68930023}},
|
|
{{0x4b2ed709, 0xccc42563, 0x856fd30d, 0xe356769, 0x559e9811, 0xbcbcd43f, 0x5395b759, 0x738477ac},
|
|
{0xc00ee17f, 0x35752b90, 0x742ed2e3, 0x68748390, 0xbd1f5bc1, 0x7cd06422, 0xc9e7b797, 0xfbc08769}},
|
|
{{0xbc60055b, 0x72bcd8b7, 0x56e27e4b, 0x3cc23ee, 0xe4819370, 0xee337424, 0xad3da09, 0xe2aa0e43},
|
|
{0x6383c45d, 0x40b8524f, 0x42a41b25, 0xd7663554, 0x778a4797, 0x64efa6de, 0x7079adf4, 0x2042170a}}
|
|
};
|
|
|
|
// This contains two tables, 8 points each in affine coordinates in montgomery form
|
|
// The first table contains these points:
|
|
// (2^192 - 2^128 - 2^64 - 1)G
|
|
// (2^192 - 2^128 - 2^64 + 1)G
|
|
// (2^192 - 2^128 + 2^64 - 1)G
|
|
// (2^192 - 2^128 + 2^64 + 1)G
|
|
// (2^192 + 2^128 - 2^64 - 1)G
|
|
// (2^192 + 2^128 - 2^64 + 1)G
|
|
// (2^192 + 2^128 + 2^64 - 1)G
|
|
// (2^192 + 2^128 + 2^64 + 1)G
|
|
// The second table contains the same points multiplied by 2^32
|
|
static const uint32_t p256_basepoint_precomp2[2][8][2][8] =
|
|
{
|
|
{
|
|
{{0x670844e0, 0x52d8a7c9, 0xef68a29d, 0xe33bdc, 0x4bdb7361, 0xf3d2848, 0x91c5304d, 0x5222c821},
|
|
{0xdf73fc25, 0xea6d2944, 0x255c81b, 0xa04c0f55, 0xefe488a8, 0x29acdc97, 0x80a560de, 0xbe2e158f}},
|
|
{{0x2b13e673, 0xfc8511ee, 0xd103ed24, 0xffc58dee, 0xea7e99b8, 0x1022523a, 0x4afc8a17, 0x8f43ea39},
|
|
{0xc5f33d0b, 0x8f4e2dbc, 0xd0aa1681, 0x3bc099fa, 0x79ff9df1, 0xffbb7b41, 0xd58b57c4, 0x180de09d}},
|
|
{{0x8bd1cda5, 0x56430752, 0x8e05eda5, 0x1807577f, 0x956896e9, 0x99c699b, 0xf1f0efb5, 0x83d6093d},
|
|
{0xed97061c, 0xef5af17e, 0x30d4c3c, 0x35b977b8, 0x49229439, 0x81fa75a2, 0xa0b6d35d, 0xf5a22070}},
|
|
{{0x74f81cf1, 0x814c5365, 0x120065b, 0xe30baff7, 0x15132621, 0x80ae1256, 0x36a80788, 0x16d2b8cb},
|
|
{0xecc50bca, 0x33d14697, 0x17aedd21, 0x19a9dfb0, 0xedc3f766, 0x523fbcc7, 0xb2cf5afd, 0x9c4de6dd}},
|
|
{{0xcf0d9f6d, 0x5305a9e6, 0x81a9b021, 0x5839172f, 0x75c687cf, 0xcca7a4dd, 0x844be22f, 0x36d59b3e},
|
|
{0x111a53e9, 0xcace7e62, 0xf063f3a1, 0x91c843d4, 0xda812da, 0xbf77e5f0, 0x437f3176, 0xe64af9c}},
|
|
{{0xcf07517d, 0xdbd568bb, 0xba6830b9, 0x2f1afba2, 0xe6c4c2a6, 0x15b6807c, 0xe4966aef, 0x91c7eabc},
|
|
{0xd6b2b6e6, 0x716dea1b, 0x19f85b4b, 0x248c43d1, 0x4a315e2a, 0x16dcfd60, 0xc72b3d0b, 0x15fdd303}},
|
|
{{0x42b7dfd5, 0xe40bf9f4, 0x2d934f2a, 0x673689f3, 0x30a6f50b, 0x8314beb4, 0x976ec64e, 0xd17af2bc},
|
|
{0x1ee7ddf1, 0x39f66c4f, 0x68ea373c, 0x7f68e18b, 0x53d0b186, 0x5166c1f2, 0x7be58f14, 0x95dda601}},
|
|
{{0x42913074, 0xd5ae356, 0x48a542b1, 0x55491b27, 0xb310732a, 0x469ca665, 0x5f1a4cc1, 0x29591d52},
|
|
{0xb84f983f, 0xe76f5b6b, 0x9f5f84e1, 0xbe7eef41, 0x80baa189, 0x1200d496, 0x18ef332c, 0x6376551f}}
|
|
},
|
|
{
|
|
{{0x7c4e54f5, 0xb9e5cbc0, 0xe1410e34, 0xc53a1a17, 0xec454425, 0x3e199130, 0x1700902e, 0xb029c97e},
|
|
{0x786423b6, 0x2de66e11, 0xb41a95be, 0x262dc914, 0x451b683, 0x51766abd, 0x85bb6fb1, 0x55ad5f34}},
|
|
{{0x9066cb79, 0x74f4f1c, 0x30c8b94e, 0x1ab31bd6, 0xd74275b3, 0x6d3f012f, 0x9ddcce40, 0xa214d0b1},
|
|
{0xd165050a, 0x24aedf74, 0xe0e5dc3e, 0x95f17ece, 0xd9224456, 0x6ada9cda, 0x2dd60eea, 0x1fadb2d1}},
|
|
{{0xe20cfb9b, 0xa3d83091, 0xba76e0cb, 0xae79c975, 0xc8858a6e, 0xa5f2a588, 0x874a3168, 0xe897a5f4},
|
|
{0x7d48f096, 0xf6c1ef40, 0xc35b132c, 0x1f9c516b, 0x53c479fd, 0xe1040f91, 0x9df06743, 0x60e881f}},
|
|
{{0x52a90e51, 0x9e0ad72, 0x38c50a96, 0xb7e66ea3, 0x7d997770, 0xab32ad05, 0x445671cb, 0xceaffe2},
|
|
{0x5d37cc99, 0xdfbe753c, 0xe0fea2d5, 0x95d068cc, 0x4dd77cb6, 0x1e37cdda, 0x55530688, 0x88c5a4bb}},
|
|
{{0xc7744f1, 0x3413f033, 0xbc816702, 0x23c05c89, 0x1192b5ac, 0x2322ee9a, 0x373180bb, 0xc1636a0},
|
|
{0xbdde0207, 0xfe2f3d4, 0xc23578d8, 0xe1a093a, 0xc888ead, 0x6e5f0d1, 0x52a2b660, 0x9ca285a5}},
|
|
{{0xce923964, 0xdae76995, 0xa34c7993, 0xcc96493a, 0xea73d9e7, 0xd19b5144, 0x311e6e34, 0x4a5c263},
|
|
{0xd9a2a443, 0x7db5b32b, 0x2cfd960c, 0x3754bd33, 0xa430f15, 0xc5bcc98, 0xd9a94574, 0x5651201f}},
|
|
{{0xfc0418fe, 0xebdd8921, 0x34e20036, 0x37015b39, 0xdf03a353, 0xcf4fcd8f, 0xf12cab16, 0xdc2de6e1},
|
|
{0xd071df14, 0x9c17cc1a, 0x63415530, 0xd7c5e6a3, 0x68f3fb1e, 0xb5301660, 0x18269301, 0xb5f70bc9}},
|
|
{{0x79ec1a0f, 0x2d8daefd, 0xceb39c97, 0x3bbcd6fd, 0x58f61a95, 0xf5575ffc, 0xadf7b420, 0xdbd986c4},
|
|
{0x15f39eb7, 0x81aa8814, 0xb98d976c, 0x6ee2fcf5, 0xcf2f717d, 0x5465475d, 0x6860bbd0, 0x8e24d3c4}}
|
|
}
|
|
};
|
|
|
|
// Takes the leftmost 256 bits in hash (treated as big endian),
|
|
// and converts to little endian integer z.
|
|
static void hash_to_z(uint32_t z[8], const uint8_t* hash, uint32_t hashlen) {
|
|
if (hashlen > 32) {
|
|
hashlen = 32;
|
|
}
|
|
for (uint32_t i = 0; i < hashlen; i++) {
|
|
((uint8_t*)z)[i] = hash[hashlen - 1 - i];
|
|
}
|
|
for (uint32_t i = hashlen; i < 32; i++) {
|
|
((uint8_t*)z)[i] = 0;
|
|
}
|
|
}
|
|
|
|
// Creates a representation of a (little endian integer),
|
|
// so that r[0] + 2*r[1] + 2^2*r[2] + 2^3*r[3] + ... = a,
|
|
// where each r[i] is -15, -13, ..., 11, 13, 15 or 0.
|
|
// Only around 1/5.5 of the r[i] will be non-zero.
|
|
static void slide_257(signed char r[257], const uint8_t a[32]) {
|
|
for (int i = 0; i < 256; ++i) {
|
|
r[i] = 1 & (a[i >> 3] >> (i & 7));
|
|
}
|
|
r[256] = 0;
|
|
|
|
for (int i = 0; i < 256; i++) {
|
|
if (r[i] != 0) {
|
|
for (int b = 1; b <= 4 && i + b < 256; b++) {
|
|
if (r[i + b] != 0) {
|
|
if (r[i] + (r[i + b] << b) <= 15) {
|
|
r[i] = (signed char) (r[i] + (r[i + b] << b)); r[i + b] = 0;
|
|
} else if (r[i] - (r[i + b] << b) >= -15) {
|
|
r[i] = (signed char) (r[i] - (r[i + b] << b));
|
|
for (;;) {
|
|
r[i + b] = 0;
|
|
b++;
|
|
if (!r[i + b]) {
|
|
r[i + b] = 1;
|
|
b--; // Will be added back after loop footer b++
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void P256_mod_n_inv(uint32_t out[8], const uint32_t in[8]) {
|
|
// This function follows the algorithm in section 12.1 of https://gcd.cr.yp.to/safegcd-20190413.pdf.
|
|
// It has been altered in the following ways:
|
|
// 1. Due to 32-bit cpu, we use 24 * 31 iterations instead of 12 * 62.
|
|
// 2. P-256 modulus instead of 2^255-19.
|
|
// 744 iterations are still enough and slightly more than the required 741 (floor((49*256+57)/17)).
|
|
// 3. Step 5 has been corrected to go back to step 2 instead of step 3.
|
|
// 4. The order of the matrix multiplications in step 6 has been changed to (T24*(T23*(T22*(...*(T1*[0, 1]))))),
|
|
// where [0, 1] is a column vector to make it possible to be able to extract the "top-right corner", v, of T24*T23*...*T1.
|
|
// The result v will then be contained in the first element of the resulting column vector.
|
|
|
|
struct {
|
|
struct FGInteger fg[2]; // f and g
|
|
struct XYInteger xy[2]; // x and y
|
|
} state[2]; // "current" and "next"
|
|
|
|
state[0].fg[0].flip_sign = 0; // non-negative f
|
|
memcpy(&state[0].fg[0].signed_value, P256_order, 36); // f
|
|
state[0].fg[1].flip_sign = 0; // non-negative g
|
|
memcpy(&state[0].fg[1].signed_value, in, 32); // g
|
|
state[0].fg[1].signed_value[8] = 0; // upper bits of g are 0
|
|
memset(&state[0].xy, 0, sizeof(state[0].xy));
|
|
// We later need a factor 2^-744. The montgomery multiplication gives 2^(24*-32)=2^-768, so multiply the init value (1) by 2^24 here.
|
|
state[0].xy[1].value[0] = 1U << 24;
|
|
|
|
int delta = 1;
|
|
for (int i = 0; i < 24; i++) {
|
|
// Scaled translation matrix Ti
|
|
uint32_t matrix[4]; // element range: [-2^30, 2^31] (negative numbers are stored in two's complement form)
|
|
|
|
// Decode f and g into two's complement representation and use the lowest 32 bits in the P256_divsteps2_31 calculation
|
|
uint32_t negate_f = state[i % 2].fg[0].flip_sign;
|
|
uint32_t negate_g = state[i % 2].fg[1].flip_sign;
|
|
delta = P256_divsteps2_31(delta, (state[i % 2].fg[0].signed_value[0] ^ negate_f) - negate_f, (state[i % 2].fg[1].signed_value[0] ^ negate_g) - negate_g, matrix);
|
|
|
|
// "Jump step", calculates the new f and g values that applies after 31 divstep2 iterations
|
|
P256_matrix_mul_fg_9(matrix[0], matrix[1], state[i % 2].fg, &state[(i + 1) % 2].fg[0]);
|
|
P256_matrix_mul_fg_9(matrix[2], matrix[3], state[i % 2].fg, &state[(i + 1) % 2].fg[1]);
|
|
|
|
// Iterate the result vector
|
|
// Due to montgomery multiplication inside this function, each step also adds a 2^-32 factor
|
|
P256_matrix_mul_mod_n(matrix[0], matrix[1], state[i % 2].xy, &state[(i + 1) % 2].xy[0]);
|
|
P256_matrix_mul_mod_n(matrix[2], matrix[3], state[i % 2].xy, &state[(i + 1) % 2].xy[1]);
|
|
}
|
|
// Calculates val^-1 = sgn(f) * v * 2^-744, where v is the "top-right corner" of the resulting T24*T23*...*T1 matrix.
|
|
// In this implementation, at this point x contains v * 2^-744.
|
|
P256_negate_mod_n_if(out, &state[0].xy[0].value[0], (state[0].xy[0].flip_sign ^ state[0].fg[0].flip_sign ^ state[0].fg[0].signed_value[8]) & 1);
|
|
}
|
|
|
|
// Constant time abs
|
|
static inline uint32_t abs_int(int8_t a) {
|
|
uint32_t a_u = (uint32_t)(int32_t)a;
|
|
uint32_t mask = a_u >> 31;
|
|
mask |= mask << 1;
|
|
mask |= mask << 2;
|
|
uint32_t result = (-a) & mask;
|
|
result |= a & (mask ^ 0xf);
|
|
return result;
|
|
}
|
|
|
|
// Calculates scalar*P in constant time (except for the scalars 2 and n-2, for which the results take a few extra cycles to compute)
|
|
static void scalarmult_variable_base(uint32_t output_mont_x[8], uint32_t output_mont_y[8], const uint32_t input_mont_x[8], const uint32_t input_mont_y[8], const uint32_t scalar[8]) {
|
|
// Based on https://eprint.iacr.org/2014/130.pdf, Algorithm 1.
|
|
|
|
uint32_t scalar2[8];
|
|
int8_t e[64];
|
|
|
|
// The algorithm used requires the scalar to be odd. If even, negate the scalar modulo p to make it odd, and later negate the end result.
|
|
bool even = (scalar[0] & 1) ^ 1;
|
|
P256_negate_mod_n_if(scalar2, scalar, even);
|
|
|
|
// Rewrite the scalar as e[0] + 2^4*e[1] + 2^8*e[2] + ... + 2^252*e[63], where each e[i] is an odd number and -15 <= e[i] <= 15.
|
|
e[0] = scalar2[0] & 0xf;
|
|
for (int i = 1; i < 64; i++) {
|
|
// Extract 4 bits
|
|
e[i] = (scalar2[i / 8] >> ((i % 8) * 4)) & 0xf;
|
|
// If even, subtract 2^4 from e[i - 1] and add 1 to e[i]
|
|
e[i - 1] -= (int8_t) (((e[i] & 1) ^ 1) << 4);
|
|
e[i] |= 1;
|
|
}
|
|
|
|
// Create a table of P, 3P, 5P, ... 15P.
|
|
uint32_t table[8][3][8];
|
|
memcpy(table[0][0], input_mont_x, 32);
|
|
memcpy(table[0][1], input_mont_y, 32);
|
|
memcpy(table[0][2], one_montgomery, 32);
|
|
P256_double_j(table[7], (constarr)table[0]);
|
|
for (int i = 1; i < 8; i++) {
|
|
memcpy(table[i], table[7], 96);
|
|
P256_add_sub_j(table[i], (constarr)table[i - 1], 0, 0);
|
|
}
|
|
|
|
// Calculate the result as (((((((((e[63]*G)*2^4)+e[62])*2^4)+e[61])*2^4)...)+e[1])*2^4)+e[0] = (2^252*e[63] + 2^248*e[62] + ... + e[0])*G.
|
|
|
|
uint32_t current_point[3][8];
|
|
|
|
// e[63] is never negative
|
|
P256_select_point(current_point, (uint32_t*)table, 3, e[63] >> 1);
|
|
|
|
for (uint32_t i = 63; i --> 0;) {
|
|
for (int j = 3; j >= 0; j--) {
|
|
P256_double_j(current_point, (constarr)current_point);
|
|
}
|
|
uint32_t selected_point[3][8];
|
|
P256_select_point(selected_point, (uint32_t*)table, 3, abs_int(e[i]) >> 1);
|
|
P256_negate_mod_p_if(selected_point[1], selected_point[1], (uint8_t)e[i] >> 7);
|
|
|
|
// There is (only) one odd input scalar that leads to an exception when i == 0: n-2,
|
|
// in that case current_point will be equal to selected_point and hence a doubling
|
|
// will occur instead. We don't bother fixing the same constant time for that case since
|
|
// the probability of that random value to be generated is around 1/2^255 and an
|
|
// attacker could easily test this case anyway.
|
|
P256_add_sub_j(current_point, (constarr)selected_point, false, false);
|
|
}
|
|
P256_jacobian_to_affine(output_mont_x, output_mont_y, (constarr)current_point);
|
|
|
|
// If the scalar was initially even, we now negate the result to get the correct result, since -(scalar*G) = (-scalar*G).
|
|
// This is done by negating y, since -(x,y) = (x,-y).
|
|
P256_negate_mod_p_if(output_mont_y, output_mont_y, even);
|
|
}
|
|
|
|
#define get_bit(arr, i) ((arr[(i) / 32] >> ((i) % 32)) & 1)
|
|
|
|
// Calculates scalar*G in constant time
|
|
static void scalarmult_fixed_base(uint32_t output_mont_x[8], uint32_t output_mont_y[8], const uint32_t scalar[8]) {
|
|
uint32_t scalar2[8];
|
|
|
|
// Just as with the algorithm used in variable base scalar multiplication, this algorithm requires the scalar to be odd.
|
|
bool even = (scalar[0] & 1) ^ 1;
|
|
P256_negate_mod_n_if(scalar2, scalar, even);
|
|
|
|
// This algorithm conceptually rewrites the odd scalar as s[0] + 2^1*s[1] + 2^2*s[2] + ... + 2^255*s[255], where each s[i] is -1 or 1.
|
|
// By initially setting s[i] to the corresponding bit S[i] in the original odd scalar S, we go from lsb to msb, and whenever a value s[i] is 0,
|
|
// increase s[i] by 1 and decrease s[i-1] by 2.
|
|
// This will result in that s[i] = S[i+1] == 1 ? 1 : -1 for i < 255, and s[255] = 1.
|
|
|
|
// We then form the scalars abs(s[j] + s[j+64]*2^64 + s[j+128]*2^128 + s[j+192]*2^192)*(2^32 * floor(j / 32)) for different 0 <= j < 64.
|
|
// Each scalar times G has already been precomputed in p256_basepoint_precomp2.
|
|
// That way we only need 31 point doublings and 63 point additions.
|
|
|
|
uint32_t current_point[3][8];
|
|
uint32_t selected_point[2][8];
|
|
|
|
for (uint32_t i = 32; i --> 0;) {
|
|
{
|
|
uint32_t mask = get_bit(scalar2, i + 32 + 1) | (get_bit(scalar2, i + 64 + 32 + 1) << 1) | (get_bit(scalar2, i + 2 * 64 + 32 + 1) << 2);
|
|
if (i == 31) {
|
|
P256_select_point(current_point, (uint32_t*)p256_basepoint_precomp2[1], 2, mask);
|
|
memcpy(current_point[2], one_montgomery, 32);
|
|
} else {
|
|
P256_double_j(current_point, (constarr)current_point);
|
|
|
|
uint32_t sign = get_bit(scalar2, i + 3 * 64 + 32 + 1) - 1; // positive: 0, negative: -1
|
|
mask = (mask ^ sign) & 7;
|
|
P256_select_point(selected_point, (uint32_t*)p256_basepoint_precomp2[1], 2, mask);
|
|
P256_negate_mod_p_if(selected_point[1], selected_point[1], sign & 1);
|
|
P256_add_sub_j(current_point, (constarr)selected_point, false, true);
|
|
}
|
|
}
|
|
{
|
|
uint32_t mask = get_bit(scalar2, i + 1) | (get_bit(scalar2, i + 64 + 1) << 1) | (get_bit(scalar2, i + 2 * 64 + 1) << 2);
|
|
uint32_t sign = get_bit(scalar2, i + 3 * 64 + 1) - 1; // positive: 0, negative: -1
|
|
mask = (mask ^ sign) & 7;
|
|
P256_select_point(selected_point, (uint32_t*)p256_basepoint_precomp2[0], 2, mask);
|
|
P256_negate_mod_p_if(selected_point[1], selected_point[1], sign & 1);
|
|
P256_add_sub_j(current_point, (constarr)selected_point, false, true);
|
|
}
|
|
}
|
|
P256_jacobian_to_affine(output_mont_x, output_mont_y, (constarr)current_point);
|
|
|
|
// Negate final result if the scalar was initially even.
|
|
P256_negate_mod_p_if(output_mont_y, output_mont_y, even);
|
|
}
|
|
|
|
static void p256_convert_endianness(void* output, const void* input, size_t byte_len) {
|
|
for (size_t i = 0; i < byte_len / 2; i++) {
|
|
uint8_t t = ((uint8_t*)input)[byte_len - 1 - i];
|
|
((uint8_t*)output)[byte_len - 1 - i] = ((uint8_t*)input)[i];
|
|
((uint8_t*)output)[i] = t;
|
|
}
|
|
}
|
|
|
|
static bool p256_verify(const uint32_t public_key_x[8], const uint32_t public_key_y[8], const uint8_t* hash, uint32_t hashlen_in_bytes, const uint32_t r[8], const uint32_t s[8]) {
|
|
if (!P256_check_range_n(r) || !P256_check_range_n(s)) {
|
|
return false;
|
|
}
|
|
|
|
if (!P256_check_range_p(public_key_x) || !P256_check_range_p(public_key_y)) {
|
|
return false;
|
|
}
|
|
|
|
uint32_t pk_table[8][3][8];
|
|
P256_to_montgomery(pk_table[0][0], public_key_x);
|
|
P256_to_montgomery(pk_table[0][1], public_key_y);
|
|
memcpy(pk_table[0][2], one_montgomery, 32);
|
|
|
|
if (!P256_point_is_on_curve(pk_table[0][0], pk_table[0][1])) {
|
|
return false;
|
|
}
|
|
|
|
// Create a table of P, 3P, 5P, ..., 15P, where P is the public key.
|
|
P256_double_j(pk_table[7], (constarr)pk_table[0]);
|
|
for (int i = 1; i < 8; i++) {
|
|
memcpy(pk_table[i], pk_table[7], 96);
|
|
P256_add_sub_j(pk_table[i], (constarr)pk_table[i - 1], 0, 0);
|
|
}
|
|
|
|
uint32_t z[8], w[8], u1[8], u2[8];
|
|
|
|
hash_to_z(z, hash, hashlen_in_bytes);
|
|
|
|
P256_mod_n_inv(w, s);
|
|
|
|
P256_mul_mod_n(u1, z, w);
|
|
P256_mul_mod_n(u2, r, w);
|
|
|
|
// Each value in these arrays will be an odd integer v, so that -15 <= v <= 15.
|
|
// Around 1/5.5 of them will be non-zero.
|
|
signed char slide_bp[257], slide_pk[257];
|
|
slide_257(slide_bp, (uint8_t*)u1);
|
|
slide_257(slide_pk, (uint8_t*)u2);
|
|
|
|
uint32_t cp[3][8] = {0};
|
|
|
|
for (int i = 256; i >= 0; i--) {
|
|
P256_double_j(cp, (constarr)cp);
|
|
if (slide_bp[i] > 0) {
|
|
P256_add_sub_j(cp, p256_basepoint_precomp[slide_bp[i]/2], 0, 1);
|
|
} else if (slide_bp[i] < 0) {
|
|
P256_add_sub_j(cp, p256_basepoint_precomp[(-slide_bp[i])/2], 1, 1);
|
|
}
|
|
if (slide_pk[i] > 0) {
|
|
P256_add_sub_j(cp, (constarr)pk_table[slide_pk[i]/2], 0, 0);
|
|
} else if (slide_pk[i] < 0) {
|
|
P256_add_sub_j(cp, (constarr)pk_table[(-slide_pk[i])/2], 1, 0);
|
|
}
|
|
}
|
|
|
|
return P256_verify_last_step(r, (constarr)cp);
|
|
}
|
|
|
|
static bool p256_sign_step1(struct SignPrecomp *result, const uint32_t k[8]) {
|
|
do {
|
|
uint32_t point_res[2][8];
|
|
if (!P256_check_range_n(k)) {
|
|
break;
|
|
}
|
|
scalarmult_fixed_base(point_res[0], point_res[1], k);
|
|
P256_mod_n_inv(result->k_inv, k);
|
|
P256_from_montgomery(result->r, point_res[0]);
|
|
P256_reduce_mod_n_32bytes(result->r, result->r);
|
|
|
|
uint32_t r_sum = 0;
|
|
for (int i = 0; i < 8; i++) {
|
|
r_sum |= result->r[i];
|
|
}
|
|
if (r_sum == 0) {
|
|
break;
|
|
}
|
|
return true;
|
|
} while (false);
|
|
|
|
memset(result, 0, sizeof(struct SignPrecomp));
|
|
return false;
|
|
}
|
|
|
|
static bool p256_sign_step2(uint32_t r[8], uint32_t s[8], const uint8_t* hash, uint32_t hashlen_in_bytes, const uint32_t private_key[8], struct SignPrecomp *sign_precomp) {
|
|
do {
|
|
if (!P256_check_range_n(sign_precomp->k_inv) || !P256_check_range_n(sign_precomp->r)) { // just make sure user did not input an obviously invalid precomp
|
|
break;
|
|
}
|
|
uint32_t *const z = r;
|
|
hash_to_z(z, hash, hashlen_in_bytes);
|
|
P256_mul_mod_n(s, sign_precomp->r, private_key);
|
|
P256_add_mod_n(s, z, s);
|
|
P256_mul_mod_n(s, sign_precomp->k_inv, s);
|
|
|
|
memcpy(r, sign_precomp->r, 32);
|
|
|
|
uint32_t s_sum = 0;
|
|
for (int i = 0; i < 8; i++) {
|
|
s_sum |= s[i];
|
|
}
|
|
if (s_sum == 0) {
|
|
break;
|
|
}
|
|
memset(sign_precomp, 0, sizeof(*sign_precomp));
|
|
return true;
|
|
} while (false);
|
|
|
|
memset(r, 0, 32);
|
|
memset(s, 0, 32);
|
|
return false;
|
|
}
|
|
|
|
static bool p256_sign(uint32_t r[8], uint32_t s[8], const uint8_t* hash, uint32_t hashlen_in_bytes, const uint32_t private_key[8], const uint32_t k[8]) {
|
|
struct SignPrecomp t;
|
|
if (!p256_sign_step1(&t, k)) {
|
|
memset(r, 0, 32);
|
|
memset(s, 0, 32);
|
|
return false;
|
|
}
|
|
return p256_sign_step2(r, s, hash, hashlen_in_bytes, private_key, &t);
|
|
}
|
|
|
|
static bool p256_scalarmult_base(uint32_t result_x[8], uint32_t result_y[8], const uint32_t scalar[8]) {
|
|
if (!P256_check_range_n(scalar)) {
|
|
return false;
|
|
}
|
|
scalarmult_fixed_base(result_x, result_y, scalar);
|
|
P256_from_montgomery(result_x, result_x);
|
|
P256_from_montgomery(result_y, result_y);
|
|
return true;
|
|
|
|
}
|
|
|
|
static bool p256_keygen(uint32_t public_key_x[8], uint32_t public_key_y[8], const uint32_t private_key[8]) {
|
|
return p256_scalarmult_base(public_key_x, public_key_y, private_key);
|
|
}
|
|
|
|
|
|
static bool p256_scalarmult_generic_no_scalar_check(uint32_t output_mont_x[8], uint32_t output_mont_y[8], const uint32_t scalar[8], const uint32_t in_x[8], const uint32_t in_y[8]) {
|
|
if (!P256_check_range_p(in_x) || !P256_check_range_p(in_y)) {
|
|
return false;
|
|
}
|
|
|
|
P256_to_montgomery(output_mont_x, in_x);
|
|
P256_to_montgomery(output_mont_y, in_y);
|
|
|
|
if (!P256_point_is_on_curve(output_mont_x, output_mont_y)) {
|
|
return false;
|
|
}
|
|
|
|
scalarmult_variable_base(output_mont_x, output_mont_y, output_mont_x, output_mont_y, scalar);
|
|
return true;
|
|
}
|
|
|
|
static bool p256_ecdh_calc_shared_secret(uint8_t shared_secret[32], const uint32_t private_key[8], const uint32_t others_public_key_x[8], const uint32_t others_public_key_y[8]) {
|
|
uint32_t result_x[8], result_y[8];
|
|
if (!p256_scalarmult_generic_no_scalar_check(result_x, result_y, private_key, others_public_key_x, others_public_key_y)) {
|
|
return false;
|
|
}
|
|
P256_from_montgomery(result_x, result_x);
|
|
p256_convert_endianness(shared_secret, result_x, 32);
|
|
return true;
|
|
}
|
|
|
|
// Assembler, from p256-cortex-m4-asm-gcc.S, converted to a top-level asm
|
|
// block so it can live in the amalgamated mongoose.c
|
|
__asm__(
|
|
".pushsection .text.mg_p256,\"ax\",%progbits\n"
|
|
"\t.syntax unified\n"
|
|
"\t.thumb\n"
|
|
"\t.align 2\n"
|
|
"\t.type P256_select_point, %function\n"
|
|
"P256_select_point:\n"
|
|
"\t.global P256_select_point\n"
|
|
"\tpush {r0,r2,r3,r4-r11,lr}\n"
|
|
"\tsubs r2,#1\n"
|
|
"\tlsls r2,#5\n"
|
|
"0:\n"
|
|
"\trsbs r3,#0\n"
|
|
"\tsbcs r3,r3,r3\n"
|
|
"\tmvns r3,r3\n"
|
|
"\tldm r1!,{r6-r12,lr}\n"
|
|
"\tands r6,r3\n"
|
|
"\tands r7,r3\n"
|
|
"\tand r8,r3\n"
|
|
"\tand r9,r3\n"
|
|
"\tand r10,r3\n"
|
|
"\tand r11,r3\n"
|
|
"\tand r12,r3\n"
|
|
"\tand lr,r3\n"
|
|
"\tadds r1,r2\n"
|
|
"\tmovs r3,#1\n"
|
|
"1:\n"
|
|
"\tldr r0,[sp,#8]\n"
|
|
"\teors r0,r3\n"
|
|
"\tmrs r0,apsr\n"
|
|
"\tlsrs r0,#30\n"
|
|
"\tldm r1!,{r4,r5}\n"
|
|
"\tumlal r6,r2,r0,r4\n"
|
|
"\tumlal r7,r3,r0,r5\n"
|
|
"\tldm r1!,{r4,r5}\n"
|
|
"\tumlal r8,r2,r0,r4\n"
|
|
"\tumlal r9,r3,r0,r5\n"
|
|
"\tldm r1!,{r4,r5}\n"
|
|
"\tumlal r10,r2,r0,r4\n"
|
|
"\tumlal r11,r3,r0,r5\n"
|
|
"\tldm r1!,{r4,r5}\n"
|
|
"\tumlal r12,r2,r0,r4\n"
|
|
"\tumlal lr,r3,r0,r5\n"
|
|
"\tadds r1,r2\n"
|
|
"\tadds r3,#1\n"
|
|
"\tcmp r3,#8\n"
|
|
"\tbne 1b\n"
|
|
"\tldm sp,{r0,r4}\n"
|
|
"\tstm r0!,{r6-r12,lr}\n"
|
|
"\tstr r0,[sp]\n"
|
|
"\tsub r1,r1,r2, lsl #3\n"
|
|
"\tsubs r1,#224\n"
|
|
"\tsubs r4,#1\n"
|
|
"\tstr r4,[sp,#4]\n"
|
|
"\tldr r3,[sp,#8]\n"
|
|
"\tbne 0b\n"
|
|
"\tadd sp,#12\n"
|
|
"\tpop {r4-r11,pc}\n"
|
|
"\t.size P256_select_point, .-P256_select_point\n"
|
|
"\t.type mul288x288, %function\n"
|
|
"mul288x288:\n"
|
|
"\tpush {r4-r11,lr}\n"
|
|
"\tmov r4,r0\n"
|
|
"\tmov r5,r2\n"
|
|
"\tmov r6,r1\n"
|
|
"\tmovs r1,#72\n"
|
|
"\tbl setzero\n"
|
|
"\tldm r5,{r0-r2,r8-r12,lr}\n"
|
|
"\tmovs r7,#9\n"
|
|
"0:\n"
|
|
"\tldm r6!,{r5}\n"
|
|
"\tpush {r6,r7}\n"
|
|
"\tmovs r3,#0\n"
|
|
"\tldm r4,{r6,r7}\n"
|
|
"\tumaal r6,r3,r5,r0\n"
|
|
"\tumaal r7,r3,r5,r1\n"
|
|
"\tstm r4!,{r6,r7}\n"
|
|
"\tldm r4,{r6,r7}\n"
|
|
"\tumaal r6,r3,r5,r2\n"
|
|
"\tumaal r7,r3,r5,r8\n"
|
|
"\tstm r4!,{r6,r7}\n"
|
|
"\tldm r4,{r6,r7}\n"
|
|
"\tumaal r6,r3,r5,r9\n"
|
|
"\tumaal r7,r3,r5,r10\n"
|
|
"\tstm r4!,{r6,r7}\n"
|
|
"\tldm r4,{r6,r7}\n"
|
|
"\tumaal r6,r3,r5,r11\n"
|
|
"\tumaal r7,r3,r5,r12\n"
|
|
"\tstm r4!,{r6,r7}\n"
|
|
"\tldm r4,{r6}\n"
|
|
"\tumaal r3,r6,r5,lr\n"
|
|
"\tstm r4!,{r3,r6}\n"
|
|
"\tsubs r4,r4,#36\n"
|
|
"\tpop {r6,r7}\n"
|
|
"\tsubs r7,r7,#1\n"
|
|
"\tbne 0b\n"
|
|
"\tpop {r4-r11,pc}\n"
|
|
"\t.size mul288x288, .-mul288x288\n"
|
|
"\t.type setzero, %function\n"
|
|
"setzero:\n"
|
|
"\tmovs r2,#0\n"
|
|
"\tmovs r3,#0\n"
|
|
"0:\n"
|
|
"\tstm r0!,{r2,r3}\n"
|
|
"\tsubs r1,r1,#8\n"
|
|
"\tbne 0b\n"
|
|
"\tbx lr\n"
|
|
"\t.size setzero, .-setzero\n"
|
|
"\t.type P256_mulmod, %function\n"
|
|
"P256_mulmod:\n"
|
|
"\tpush {r2,lr}\n"
|
|
"\tsub sp,#28\n"
|
|
"\tldm r2,{r2,r3,r4,r5}\n"
|
|
"\tldm r1!,{r0,r10,lr}\n"
|
|
"\tumull r6,r11,r2,r0\n"
|
|
"\tumull r7,r12,r3,r0\n"
|
|
"\tumaal r7,r11,r2,r10\n"
|
|
"\tpush {r6,r7}\n"
|
|
"\tumull r8,r6,r4,r0\n"
|
|
"\tumaal r8,r11,r3,r10\n"
|
|
"\tumull r9,r7,r5,r0\n"
|
|
"\tumaal r9,r11,r4,r10\n"
|
|
"\tumaal r11,r7,r5,r10\n"
|
|
"\tumaal r8,r12,r2,lr\n"
|
|
"\tumaal r9,r12,r3,lr\n"
|
|
"\tumaal r11,r12,r4,lr\n"
|
|
"\tumaal r12,r7,r5,lr\n"
|
|
"\tldm r1!,{r0,r10,lr}\n"
|
|
"\tumaal r9,r6,r2,r0\n"
|
|
"\tumaal r11,r6,r3,r0\n"
|
|
"\tumaal r12,r6,r4,r0\n"
|
|
"\tumaal r6,r7,r5,r0\n"
|
|
"\tstrd r8,r9,[sp,#8]\n"
|
|
"\tmov r9,#0\n"
|
|
"\tumaal r11,r9,r2,r10\n"
|
|
"\tumaal r12,r9,r3,r10\n"
|
|
"\tumaal r6,r9,r4,r10\n"
|
|
"\tumaal r7,r9,r5,r10\n"
|
|
"\tmov r10,#0\n"
|
|
"\tumaal r12,r10,r2,lr\n"
|
|
"\tumaal r6,r10,r3,lr\n"
|
|
"\tumaal r7,r10,r4,lr\n"
|
|
"\tumaal r9,r10,r5,lr\n"
|
|
"\tldr r8,[r1],#4\n"
|
|
"\tmov lr,#0\n"
|
|
"\tumaal lr,r6,r2,r8\n"
|
|
"\tumaal r7,r6,r3,r8\n"
|
|
"\tumaal r9,r6,r4,r8\n"
|
|
"\tumaal r10,r6,r5,r8\n"
|
|
"\tldr r8,[r1],#-28\n"
|
|
"\tmov r0,#0\n"
|
|
"\tumaal r7,r0,r2,r8\n"
|
|
"\tumaal r9,r0,r3,r8\n"
|
|
"\tumaal r10,r0,r4,r8\n"
|
|
"\tumaal r6,r0,r5,r8\n"
|
|
"\tpush {r0}\n"
|
|
"\tldr r2,[sp,#40]\n"
|
|
"\tadds r2,r2,#16\n"
|
|
"\tldm r2,{r2,r3,r4,r5}\n"
|
|
"\tldr r8,[r1],#4\n"
|
|
"\tmov r0,#0\n"
|
|
"\tumaal r11,r0,r2,r8\n"
|
|
"\tstr r11,[sp,#16+4]\n"
|
|
"\tumaal r12,r0,r3,r8\n"
|
|
"\tumaal lr,r0,r4,r8\n"
|
|
"\tumaal r0,r7,r5,r8\n"
|
|
"\tldr r8,[r1],#4\n"
|
|
"\tmov r11,#0\n"
|
|
"\tumaal r12,r11,r2,r8\n"
|
|
"\tstr r12,[sp,#20+4]\n"
|
|
"\tumaal lr,r11,r3,r8\n"
|
|
"\tumaal r0,r11,r4,r8\n"
|
|
"\tumaal r11,r7,r5,r8\n"
|
|
"\tldr r8,[r1],#4\n"
|
|
"\tmov r12,#0\n"
|
|
"\tumaal lr,r12,r2,r8\n"
|
|
"\tstr lr,[sp,#24+4]\n"
|
|
"\tumaal r0,r12,r3,r8\n"
|
|
"\tumaal r11,r12,r4,r8\n"
|
|
"\tumaal r10,r12,r5,r8\n"
|
|
"\tldr r8,[r1],#4\n"
|
|
"\tmov lr,#0\n"
|
|
"\tumaal r0,lr,r2,r8\n"
|
|
"\tstr r0,[sp,#28+4]\n"
|
|
"\tumaal r11,lr,r3,r8\n"
|
|
"\tumaal r10,lr,r4,r8\n"
|
|
"\tumaal r6,lr,r5,r8\n"
|
|
"\tldm r1!,{r0,r8}\n"
|
|
"\tumaal r11,r9,r2,r0\n"
|
|
"\tstr r11,[sp,#32+4]\n"
|
|
"\tumaal r9,r10,r3,r0\n"
|
|
"\tumaal r10,r6,r4,r0\n"
|
|
"\tpop {r11}\n"
|
|
"\tumaal r11,r6,r5,r0\n"
|
|
"\tumaal r9,r7,r2,r8\n"
|
|
"\tumaal r10,r7,r3,r8\n"
|
|
"\tumaal r11,r7,r4,r8\n"
|
|
"\tumaal r6,r7,r5,r8\n"
|
|
"\tldm r1!,{r0,r8}\n"
|
|
"\tumaal r10,r12,r2,r0\n"
|
|
"\tumaal r11,r12,r3,r0\n"
|
|
"\tumaal r6,r12,r4,r0\n"
|
|
"\tumaal r7,r12,r5,r0\n"
|
|
"\tumaal r11,lr,r2,r8\n"
|
|
"\tumaal lr,r6,r3,r8\n"
|
|
"\tumaal r6,r7,r4,r8\n"
|
|
"\tumaal r7,r12,r5,r8\n"
|
|
"\tpush {r6,r7,r12}\n"
|
|
"\tadd r7,sp,#12\n"
|
|
"\tldm r7,{r0-r8}\n"
|
|
"\tmov r12,#0\n"
|
|
"\tadds r3,r0\n"
|
|
"\tadcs r4,r4,r1\n"
|
|
"\tadcs r5,r5,r2\n"
|
|
"\tadcs r6,r6,r0\n"
|
|
"\tadcs r7,r7,r1\n"
|
|
"\tadcs r8,r8,r0\n"
|
|
"\tadcs r9,r9,r1\n"
|
|
"\tadcs r10,r10,#0\n"
|
|
"\tadcs r11,r11,#0\n"
|
|
"\tadcs r12,r12,#0\n"
|
|
"\tadds r6,r3\n"
|
|
"\tadcs r7,r7,r4\n"
|
|
"\tadcs r8,r8,r2\n"
|
|
"\tadcs r9,r9,r3\n"
|
|
"\tadcs r10,r10,r2\n"
|
|
"\tadcs r11,r11,r3\n"
|
|
"\tadcs r12,r12,#0\n"
|
|
"\tsubs r7,r0\n"
|
|
"\tsbcs r8,r8,r1\n"
|
|
"\tsbcs r9,r9,r2\n"
|
|
"\tsbcs r10,r10,r3\n"
|
|
"\tsbcs r11,r11,#0\n"
|
|
"\tsbcs r12,r12,#0\n"
|
|
"\tpop {r1-r3}\n"
|
|
"\tadds r0,lr,r12\n"
|
|
"\tadcs r1,r1,#0\n"
|
|
"\tmov r12,#0\n"
|
|
"\tadcs r12,r12,#0\n"
|
|
"\tadcs r8,r8,r5\n"
|
|
"\tadcs r9,r9,r6\n"
|
|
"\tadcs r10,r10,r4\n"
|
|
"\tadcs r11,r11,r5\n"
|
|
"\tadcs r0,r0,r4\n"
|
|
"\tadcs r1,r1,r5\n"
|
|
"\tadcs r2,r2,r12\n"
|
|
"\tadcs r3,r3,#0\n"
|
|
"\tmov r12,#0\n"
|
|
"\tadcs r12,r12,#0\n"
|
|
"\tadcs r10,r10,r7\n"
|
|
"\tadcs r11,r11,#0\n"
|
|
"\tadcs r0,r0,r6\n"
|
|
"\tadcs r1,r1,r7\n"
|
|
"\tadcs r2,r2,r6\n"
|
|
"\tadcs r3,r3,r7\n"
|
|
"\tadcs r12,r12,#0\n"
|
|
"\tsubs r11,r4\n"
|
|
"\tsbcs r0,r0,r5\n"
|
|
"\tsbcs r1,r1,r6\n"
|
|
"\tsbcs r2,r2,r7\n"
|
|
"\tsbcs r3,r3,#0\n"
|
|
"\tsbcs r12,r12,#0\n"
|
|
"\tsubs r8,r8,#0xffffffff\n"
|
|
"\tsbcs r9,r9,#0xffffffff\n"
|
|
"\tsbcs r10,r10,#0xffffffff\n"
|
|
"\tsbcs r11,r11,#0\n"
|
|
"\tsbcs r4,r0,#0\n"
|
|
"\tsbcs r5,r1,#0\n"
|
|
"\tsbcs r6,r2,#1\n"
|
|
"\tsbcs r7,r3,#0xffffffff\n"
|
|
"\tsbc r12,r12,#0\n"
|
|
"\tadds r0,r8,r12\n"
|
|
"\tadcs r1,r9,r12\n"
|
|
"\tadcs r2,r10,r12\n"
|
|
"\tadcs r3,r11,#0\n"
|
|
"\tadcs r4,r4,#0\n"
|
|
"\tadcs r5,r5,#0\n"
|
|
"\tadcs r6,r6,r12, lsr #31\n"
|
|
"\tadcs r7,r7,r12\n"
|
|
"\tadd sp,sp,#40\n"
|
|
"\tpop {pc}\n"
|
|
"\t.size P256_mulmod, .-P256_mulmod\n"
|
|
"\t.type P256_sqrmod, %function\n"
|
|
"P256_sqrmod:\n"
|
|
"\tpush {lr}\n"
|
|
"\tumull r9,r10,r0,r0\n"
|
|
"\tumull r11,r12,r0,r1\n"
|
|
"\tadds r11,r11,r11\n"
|
|
"\tmov lr,#0\n"
|
|
"\tumaal r10,r11,lr,lr\n"
|
|
"\tpush {r9,r10}\n"
|
|
"\tmov r9,#0\n"
|
|
"\tumaal r9,r12,r0,r2\n"
|
|
"\tadcs r9,r9,r9\n"
|
|
"\tumaal r9,r11,r1,r1\n"
|
|
"\tpush {r9}\n"
|
|
"\tumull r9,r10,r0,r3\n"
|
|
"\tumaal r9,r12,r1,r2\n"
|
|
"\tadcs r9,r9,r9\n"
|
|
"\tumaal r9,r11,lr,lr\n"
|
|
"\tpush {r9}\n"
|
|
"\tmov r9,#0\n"
|
|
"\tumaal r9,r10,r0,r4\n"
|
|
"\tumaal r9,r12,r1,r3\n"
|
|
"\tadcs r9,r9,r9\n"
|
|
"\tumaal r9,r11,r2,r2\n"
|
|
"\tpush {r9}\n"
|
|
"\tumull r9,r8,r0,r5\n"
|
|
"\tumaal r9,r10,r1,r4\n"
|
|
"\tumaal r9,r12,r2,r3\n"
|
|
"\tadcs r9,r9,r9\n"
|
|
"\tumaal r9,r11,lr,lr\n"
|
|
"\tpush {r9}\n"
|
|
"\tmov r9,#0\n"
|
|
"\tumaal r9,r8,r1,r5\n"
|
|
"\tumaal r9,r12,r2,r4\n"
|
|
"\tumaal r9,r10,r0,r6\n"
|
|
"\tadcs r9,r9,r9\n"
|
|
"\tumaal r9,r11,r3,r3\n"
|
|
"\tpush {r9}\n"
|
|
"\tumull r9,r0,r0,r7\n"
|
|
"\tumaal r9,r10,r1,r6\n"
|
|
"\tumaal r9,r12,r2,r5\n"
|
|
"\tumaal r9,r8,r3,r4\n"
|
|
"\tadcs r9,r9,r9\n"
|
|
"\tumaal r9,r11,lr,lr\n"
|
|
"\tumaal r0,r8,r1,r7\n"
|
|
"\tumaal r0,r10,r2,r6\n"
|
|
"\tumaal r0,r12,r3,r5\n"
|
|
"\tadcs r0,r0,r0\n"
|
|
"\tumaal r11,r0,r4,r4\n"
|
|
"\tumaal r12,r8,r2,r7\n"
|
|
"\tumaal r12,r10,r3,r6\n"
|
|
"\tmovs r2,#0\n"
|
|
"\tumaal r12,r2,r4,r5\n"
|
|
"\tadcs r1,r12,r12\n"
|
|
"\tumaal r0,r1,lr,lr\n"
|
|
"\tumaal r2,r8,r3,r7\n"
|
|
"\tumaal r2,r10,r4,r6\n"
|
|
"\tadcs r2,r2,r2\n"
|
|
"\tumaal r1,r2,r5,r5\n"
|
|
"\tmovs r3,#0\n"
|
|
"\tumaal r3,r8,r4,r7\n"
|
|
"\tumaal r3,r10,r5,r6\n"
|
|
"\tadcs r3,r3,r3\n"
|
|
"\tumaal r2,r3,lr,lr\n"
|
|
"\tumaal r8,r10,r5,r7\n"
|
|
"\tadcs r8,r8,r8\n"
|
|
"\tumaal r3,r8,r6,r6\n"
|
|
"\tumull r4,r5,lr,lr\n"
|
|
"\tumaal r4,r10,r6,r7\n"
|
|
"\tadcs r4,r4,r4\n"
|
|
"\tumaal r4,r8,lr,lr\n"
|
|
"\tadcs r10,r10,r10\n"
|
|
"\tumaal r8,r10,r7,r7\n"
|
|
"\tadcs r10,r10,lr\n"
|
|
"\tpush {r4,r8,r10}\n"
|
|
"\tadd r4,sp,#12\n"
|
|
"\tldm r4,{r4-r8,r10,r12}\n"
|
|
"\tX0 .req r10\n"
|
|
"\tX1 .req r12\n"
|
|
"\tX2 .req r8\n"
|
|
"\tX3 .req r7\n"
|
|
"\tX4 .req r6\n"
|
|
"\tX5 .req r5\n"
|
|
"\tX6 .req r4\n"
|
|
"\tX7 .req r9\n"
|
|
"\tX8 .req r11\n"
|
|
"\tX9 .req r0\n"
|
|
"\tX10 .req r1\n"
|
|
"\tX11 .req r2\n"
|
|
"\tX12 .req r3\n"
|
|
"\tX13 .req r7\n"
|
|
"\tX14 .req r8\n"
|
|
"\tX15 .req r12\n"
|
|
"\tadcs X3,X3,X0\n"
|
|
"\tadcs X4,X4,X1\n"
|
|
"\tadcs X5,X5,X2\n"
|
|
"\tadcs X6,X6,X0\n"
|
|
"\tadcs X7,X7,X1\n"
|
|
"\tadcs X8,X8,X0\n"
|
|
"\tadcs X9,X9,X1\n"
|
|
"\tadcs X10,X10,#0\n"
|
|
"\tadcs X11,X11,#0\n"
|
|
"\tadcs lr,lr,#0\n"
|
|
"\tadds X6,X3\n"
|
|
"\tadcs X7,X7,X4\n"
|
|
"\tadcs X8,X8,X2\n"
|
|
"\tadcs X9,X9,X3\n"
|
|
"\tadcs X10,X10,X2\n"
|
|
"\tadcs X11,X11,X3\n"
|
|
"\tadcs lr,lr,#0\n"
|
|
"\tsubs X7,X0\n"
|
|
"\tsbcs X8,X8,X1\n"
|
|
"\tsbcs X9,X9,X2\n"
|
|
"\tsbcs X10,X10,X3\n"
|
|
"\tsbcs X11,X11,#0\n"
|
|
"\tsbcs lr,lr,#0\n"
|
|
"\tpop {X13,X14,X15}\n"
|
|
"\tadds X0,X12,lr\n"
|
|
"\tadcs X13,X13,#0\n"
|
|
"\tmov lr,#0\n"
|
|
"\tadcs lr,lr,#0\n"
|
|
"\tadcs X8,X8,X5\n"
|
|
"\tadcs X9,X9,X6\n"
|
|
"\tadcs X10,X10,X4\n"
|
|
"\tadcs X11,X11,X5\n"
|
|
"\tadcs X0,X0,X4\n"
|
|
"\tadcs X13,X13,X5\n"
|
|
"\tadcs X14,X14,lr\n"
|
|
"\tadcs X15,X15,#0\n"
|
|
"\tmov lr,#0\n"
|
|
"\tadcs lr,lr,#0\n"
|
|
"\tadcs X10,X10,X7\n"
|
|
"\tadcs X11,X11,#0\n"
|
|
"\tadcs X0,X0,X6\n"
|
|
"\tadcs X13,X13,X7\n"
|
|
"\tadcs X14,X14,X6\n"
|
|
"\tadcs X15,X15,X7\n"
|
|
"\tadcs lr,lr,#0\n"
|
|
"\tsubs X11,X4\n"
|
|
"\tsbcs X0,X0,X5\n"
|
|
"\tsbcs X13,X13,X6\n"
|
|
"\tsbcs X14,X14,X7\n"
|
|
"\tsbcs X15,X15,#0\n"
|
|
"\tsbcs lr,lr,#0\n"
|
|
"\tsubs r11,r11,#0xffffffff\n"
|
|
"\tsbcs r9,r0,#0xffffffff\n"
|
|
"\tsbcs r4,r1,#0xffffffff\n"
|
|
"\tsbcs r3,r2,#0\n"
|
|
"\tsbcs r6,r10,#0\n"
|
|
"\tsbcs r5,r7,#0\n"
|
|
"\tsbcs r10,r8,#1\n"
|
|
"\tsbcs r8,r12,#0xffffffff\n"
|
|
"\tsbcs r7,lr,#0\n"
|
|
"\tadds r0,r11,r7\n"
|
|
"\tadcs r1,r9,r7\n"
|
|
"\tadcs r2,r4,r7\n"
|
|
"\tadcs r3,r3,#0\n"
|
|
"\tadcs r4,r6,#0\n"
|
|
"\tadcs r5,r5,#0\n"
|
|
"\tadcs r6,r10,r7, lsr #31\n"
|
|
"\tadcs r7,r8,r7\n"
|
|
"\tadd sp,#28\n"
|
|
"\tpop {pc}\n"
|
|
"\t.size P256_sqrmod, .-P256_sqrmod\n"
|
|
"\t.type P256_submod, %function\n"
|
|
"P256_submod:\n"
|
|
"\tldm r1,{r3-r10}\n"
|
|
"\tldm r2!,{r0,r1,r11,r12}\n"
|
|
"\tsubs r3,r0\n"
|
|
"\tsbcs r4,r4,r1\n"
|
|
"\tsbcs r5,r5,r11\n"
|
|
"\tsbcs r6,r6,r12\n"
|
|
"\tldm r2,{r0,r1,r11,r12}\n"
|
|
"\tsbcs r7,r7,r0\n"
|
|
"\tsbcs r8,r8,r1\n"
|
|
"\tsbcs r9,r9,r11\n"
|
|
"\tsbcs r10,r10,r12\n"
|
|
"\tsbcs r11,r11,r11\n"
|
|
"\tadds r0,r3,r11\n"
|
|
"\tadcs r1,r4,r11\n"
|
|
"\tadcs r2,r5,r11\n"
|
|
"\tadcs r3,r6,#0\n"
|
|
"\tadcs r4,r7,#0\n"
|
|
"\tadcs r5,r8,#0\n"
|
|
"\tadcs r6,r9,r11, lsr #31\n"
|
|
"\tadcs r7,r10,r11\n"
|
|
"\tbx lr\n"
|
|
"\t.size P256_submod, .-P256_submod\n"
|
|
"\t.type P256_addmod, %function\n"
|
|
"P256_addmod:\n"
|
|
"\tldm r2,{r2-r9}\n"
|
|
"\tldm r1!,{r0,r10,r11,r12}\n"
|
|
"\tadds r2,r0\n"
|
|
"\tadcs r3,r3,r10\n"
|
|
"\tadcs r4,r4,r11\n"
|
|
"\tadcs r5,r5,r12\n"
|
|
"\tldm r1,{r0,r1,r11,r12}\n"
|
|
"\tadcs r6,r6,r0\n"
|
|
"\tadcs r7,r7,r1\n"
|
|
"\tadcs r8,r8,r11\n"
|
|
"\tadcs r9,r9,r12\n"
|
|
"\tmovs r10,#0\n"
|
|
"\tadcs r10,r10,r10\n"
|
|
"\tsubs r2,#0xffffffff\n"
|
|
"\tsbcs r3,r3,#0xffffffff\n"
|
|
"\tsbcs r4,r4,#0xffffffff\n"
|
|
"\tsbcs r5,r5,#0\n"
|
|
"\tsbcs r6,r6,#0\n"
|
|
"\tsbcs r7,r7,#0\n"
|
|
"\tsbcs r8,r8,#1\n"
|
|
"\tsbcs r9,r9,#0xffffffff\n"
|
|
"\tsbcs r10,r10,#0\n"
|
|
"\tadds r0,r2,r10\n"
|
|
"\tadcs r1,r3,r10\n"
|
|
"\tadcs r2,r4,r10\n"
|
|
"\tadcs r3,r5,#0\n"
|
|
"\tadcs r4,r6,#0\n"
|
|
"\tadcs r5,r7,#0\n"
|
|
"\tadcs r6,r8,r10, lsr #31\n"
|
|
"\tadcs r7,r9,r10\n"
|
|
"\tbx lr\n"
|
|
"\t.size P256_addmod, .-P256_addmod\n"
|
|
"\t.type P256_sqrmod_many, %function\n"
|
|
"P256_sqrmod_many:\n"
|
|
"\tpush {r8,lr}\n"
|
|
"0:\n"
|
|
"\tbl P256_sqrmod\n"
|
|
"\tldr r8,[sp,#0]\n"
|
|
"\tsubs r8,r8,#1\n"
|
|
"\tstr r8,[sp,#0]\n"
|
|
"\tbne 0b\n"
|
|
"\tpop {r8,pc}\n"
|
|
"\t.size P256_sqrmod_many, .-P256_sqrmod_many\n"
|
|
"\t.type P256_sqrmod_many_and_mulmod, %function\n"
|
|
"P256_sqrmod_many_and_mulmod:\n"
|
|
"\tpush {r9,lr}\n"
|
|
"\tbl P256_sqrmod_many\n"
|
|
"\tpush {r0-r7}\n"
|
|
"\tmov r1,sp\n"
|
|
"\tldr r2,[sp,#32]\n"
|
|
"\tbl P256_mulmod\n"
|
|
"\tadd sp,#36\n"
|
|
"\tpop {pc}\n"
|
|
"\t.size P256_sqrmod_many_and_mulmod, .-P256_sqrmod_many_and_mulmod\n"
|
|
"\t.type P256_modinv_sqrt, %function\n"
|
|
"P256_modinv_sqrt:\n"
|
|
"\tpush {r0-r8,lr}\n"
|
|
"\tmov r8,#1\n"
|
|
"\tmov r9,sp\n"
|
|
"\tbl P256_sqrmod_many_and_mulmod\n"
|
|
"\tpush {r0-r7}\n"
|
|
"\tbl P256_sqrmod\n"
|
|
"\tbl P256_sqrmod\n"
|
|
"\tpush {r0-r7}\n"
|
|
"\tmov r1,sp\n"
|
|
"\tadd r2,sp,#32\n"
|
|
"\tbl P256_mulmod\n"
|
|
"\tadd r8,sp,#32\n"
|
|
"\tstm r8,{r0-r7}\n"
|
|
"\tmov r8,#8-4\n"
|
|
"\tadd r9,sp,#32\n"
|
|
"\tbl P256_sqrmod_many_and_mulmod\n"
|
|
"\tpush {r0-r7}\n"
|
|
"\tmov r8,#16-8\n"
|
|
"\tmov r9,sp\n"
|
|
"\tbl P256_sqrmod_many_and_mulmod\n"
|
|
"\tpush {r0-r7}\n"
|
|
"\tmov r8,#16\n"
|
|
"\tmov r9,sp\n"
|
|
"\tbl P256_sqrmod_many_and_mulmod\n"
|
|
"\tpush {r0-r7}\n"
|
|
"\tmov r8,#32\n"
|
|
"\tadd r9,sp,#5*32\n"
|
|
"\tbl P256_sqrmod_many_and_mulmod\n"
|
|
"\tldr r8,[sp,#6*32]\n"
|
|
"\tcmp r8,#0\n"
|
|
"\tbne 0f\n"
|
|
"\tmov r8,#192-64\n"
|
|
"\tmov r9,sp\n"
|
|
"\tbl P256_sqrmod_many_and_mulmod\n"
|
|
"\tmov r8,#224-192\n"
|
|
"\tmov r9,sp\n"
|
|
"\tbl P256_sqrmod_many_and_mulmod\n"
|
|
"\tmov r8,#240-224\n"
|
|
"\tadd r9,sp,#32\n"
|
|
"\tbl P256_sqrmod_many_and_mulmod\n"
|
|
"\tmov r8,#248-240\n"
|
|
"\tadd r9,sp,#64\n"
|
|
"\tbl P256_sqrmod_many_and_mulmod\n"
|
|
"\tmov r8,#252-248\n"
|
|
"\tadd r9,sp,#128\n"
|
|
"\tbl P256_sqrmod_many_and_mulmod\n"
|
|
"\tmov r8,#256-252\n"
|
|
"\tadd r9,sp,#96\n"
|
|
"\tbl P256_sqrmod_many_and_mulmod\n"
|
|
"\tstm sp,{r0-r7}\n"
|
|
"\tmov r1,sp\n"
|
|
"\tadd r2,sp,#5*32\n"
|
|
"\tbl P256_mulmod\n"
|
|
"\tb 1f\n"
|
|
"0:\n"
|
|
"\tmov r8,#160-64\n"
|
|
"\tadd r9,sp,#5*32\n"
|
|
"\tbl P256_sqrmod_many_and_mulmod\n"
|
|
"\tmov r8,#254-160\n"
|
|
"\tbl P256_sqrmod_many\n"
|
|
"1:\n"
|
|
"\tadd sp,#6*32+4\n"
|
|
"\tpop {pc}\n"
|
|
"\t.size P256_modinv_sqrt, .-P256_modinv_sqrt\n"
|
|
"\t.type P256_times2, %function\n"
|
|
"P256_times2:\n"
|
|
"\tadds r0,r0\n"
|
|
"\tadcs r1,r1,r1\n"
|
|
"\tadcs r2,r2,r2\n"
|
|
"\tadcs r3,r3,r3\n"
|
|
"\tadcs r4,r4,r4\n"
|
|
"\tadcs r5,r5,r5\n"
|
|
"\tadcs r6,r6,r6\n"
|
|
"\tadcs r7,r7,r7\n"
|
|
"\tmov r8,#0\n"
|
|
"\tadcs r8,r8,r8\n"
|
|
"\tsubs r0,#0xffffffff\n"
|
|
"\tsbcs r1,r1,#0xffffffff\n"
|
|
"\tsbcs r2,r2,#0xffffffff\n"
|
|
"\tsbcs r3,r3,#0\n"
|
|
"\tsbcs r4,r4,#0\n"
|
|
"\tsbcs r5,r5,#0\n"
|
|
"\tsbcs r6,r6,#1\n"
|
|
"\tsbcs r7,r7,#0xffffffff\n"
|
|
"\tsbcs r8,r8,#0\n"
|
|
"\tadds r0,r8\n"
|
|
"\tadcs r1,r1,r8\n"
|
|
"\tadcs r2,r2,r8\n"
|
|
"\tadcs r3,r3,#0\n"
|
|
"\tadcs r4,r4,#0\n"
|
|
"\tadcs r5,r5,#0\n"
|
|
"\tadcs r6,r6,r8, lsr #31\n"
|
|
"\tadcs r7,r7,r8\n"
|
|
"\tbx lr\n"
|
|
"\t.size P256_times2, .-P256_times2\n"
|
|
"\t.align 2\n"
|
|
"R2_mod_p:\n"
|
|
"\t.word 3\n"
|
|
"\t.word 0\n"
|
|
"\t.word 0xffffffff\n"
|
|
"\t.word 0xfffffffb\n"
|
|
"\t.word 0xfffffffe\n"
|
|
"\t.word 0xffffffff\n"
|
|
"\t.word 0xfffffffd\n"
|
|
"\t.word 4\n"
|
|
"\t.type P256_to_montgomery, %function\n"
|
|
"P256_to_montgomery:\n"
|
|
"\t.global P256_to_montgomery\n"
|
|
"\tpush {r0,r4-r11,lr}\n"
|
|
"\tadr r2,R2_mod_p\n"
|
|
"\tbl P256_mulmod\n"
|
|
"\tpop {r8}\n"
|
|
"\tstm r8,{r0-r7}\n"
|
|
"\tpop {r4-r11,pc}\n"
|
|
"\t.size P256_to_montgomery, .-P256_to_montgomery\n"
|
|
"\t.type P256_from_montgomery, %function\n"
|
|
"P256_from_montgomery:\n"
|
|
"\t.global P256_from_montgomery\n"
|
|
"\tpush {r0,r4-r11,lr}\n"
|
|
"\tmovs r2,#0\n"
|
|
"\tmovs r3,#0\n"
|
|
"\tpush {r2-r3}\n"
|
|
"\tpush {r2-r3}\n"
|
|
"\tpush {r2-r3}\n"
|
|
"\tmovs r2,#1\n"
|
|
"\tpush {r2-r3}\n"
|
|
"\tmov r2,sp\n"
|
|
"\tbl P256_mulmod\n"
|
|
"\tadd sp,#32\n"
|
|
"\tpop {r8}\n"
|
|
"\tstm r8,{r0-r7}\n"
|
|
"\tpop {r4-r11,pc}\n"
|
|
"\t.size P256_from_montgomery, .-P256_from_montgomery\n"
|
|
"\t.type P256_check_range_p, %function\n"
|
|
"P256_check_range_p:\n"
|
|
"\t.global P256_check_range_p\n"
|
|
"\tpush {r4-r8,lr}\n"
|
|
"\tldm r0,{r1-r8}\n"
|
|
"\tmovs r0,#0xffffffff\n"
|
|
"\tsubs r1,r0\n"
|
|
"\tsbcs r2,r2,r0\n"
|
|
"\tsbcs r3,r3,r0\n"
|
|
"\tsbcs r4,r4,#0\n"
|
|
"\tsbcs r5,r5,#0\n"
|
|
"\tsbcs r6,r6,#0\n"
|
|
"\tsbcs r7,r7,#1\n"
|
|
"\tsbcs r8,r8,r0\n"
|
|
"\tsbcs r0,r0,r0\n"
|
|
"\tlsrs r0,#31\n"
|
|
"\tpop {r4-r8,pc}\n"
|
|
"\t.size P256_check_range_p, .-P256_check_range_p\n"
|
|
"\t.align 2\n"
|
|
"P256_order_mu:\n"
|
|
"\t.word 0xeedf9bfe\n"
|
|
"\t.word 0x012ffd85\n"
|
|
"\t.word 0xdf1a6c21\n"
|
|
"\t.word 0x43190552\n"
|
|
"\t.word 0xffffffff\n"
|
|
"\t.word 0xfffffffe\n"
|
|
"\t.word 0xffffffff\n"
|
|
"\t.word 0x0\n"
|
|
"\t.word 0x1\n"
|
|
"\t.type P256_reduce_mod_n_once, %function\n"
|
|
"P256_reduce_mod_n_once:\n"
|
|
"\tpush {lr}\n"
|
|
"\tadr r10,P256_order\n"
|
|
"\tldm r10,{r10,r11,r12,lr}\n"
|
|
"\tsubs r0,r10\n"
|
|
"\tsbcs r1,r1,r11\n"
|
|
"\tsbcs r2,r2,r12\n"
|
|
"\tsbcs r3,r3,lr\n"
|
|
"\tsbcs r4,r4,#0xffffffff\n"
|
|
"\tsbcs r5,r5,#0xffffffff\n"
|
|
"\tsbcs r6,r6,#0\n"
|
|
"\tsbcs r7,r7,#0xffffffff\n"
|
|
"\tsbcs r8,r8,#0\n"
|
|
"\tsbc r9,r9,r9\n"
|
|
"\tand r10,r9\n"
|
|
"\tand r11,r9\n"
|
|
"\tand r12,r9\n"
|
|
"\tand lr,r9\n"
|
|
"\tadds r0,r10\n"
|
|
"\tadcs r1,r1,r11\n"
|
|
"\tadcs r2,r2,r12\n"
|
|
"\tadcs r3,r3,lr\n"
|
|
"\tadcs r4,r4,r9\n"
|
|
"\tadcs r5,r5,r9\n"
|
|
"\tadcs r6,r6,#0\n"
|
|
"\tadcs r7,r7,r9\n"
|
|
"\tadcs r8,r8,#0\n"
|
|
"\tpop {pc}\n"
|
|
"\t.size P256_reduce_mod_n_once, .-P256_reduce_mod_n_once\n"
|
|
"\t.type P256_reduce_mod_n_64bytes, %function\n"
|
|
"P256_reduce_mod_n_64bytes:\n"
|
|
"\tpush {r0,r4-r11,lr}\n"
|
|
"\tsub sp,sp,#108\n"
|
|
"\tmov r10,r1\n"
|
|
"\tadd r0,sp,#36\n"
|
|
"\tadds r1,r1,#28\n"
|
|
"\tadr r2,P256_order_mu\n"
|
|
"\tbl mul288x288\n"
|
|
"\tmov r0,sp\n"
|
|
"\tadd r1,sp,#72\n"
|
|
"\tadr r2,P256_order\n"
|
|
"\tbl mul288x288\n"
|
|
"\tldm r10,{r0-r8}\n"
|
|
"\tpop {r9-r12}\n"
|
|
"\tsubs r0,r0,r9\n"
|
|
"\tsbcs r1,r1,r10\n"
|
|
"\tsbcs r2,r2,r11\n"
|
|
"\tsbcs r3,r3,r12\n"
|
|
"\tpop {r9-r12,lr}\n"
|
|
"\tsbcs r4,r4,r9\n"
|
|
"\tsbcs r5,r5,r10\n"
|
|
"\tsbcs r6,r6,r11\n"
|
|
"\tsbcs r7,r7,r12\n"
|
|
"\tsbcs r8,r8,lr\n"
|
|
"\tbl P256_reduce_mod_n_once\n"
|
|
"\tbl P256_reduce_mod_n_once\n"
|
|
"\tadd sp,sp,#72\n"
|
|
"\tpop {r9}\n"
|
|
"\tstm r9,{r0-r7}\n"
|
|
"\tpop {r4-r11,pc}\n"
|
|
"\t.size P256_reduce_mod_n_64bytes, .-P256_reduce_mod_n_64bytes\n"
|
|
"\t.type P256_reduce_mod_n_32bytes, %function\n"
|
|
"P256_reduce_mod_n_32bytes:\n"
|
|
"\t.global P256_reduce_mod_n_32bytes\n"
|
|
"\tpush {r0,r4-r11,lr}\n"
|
|
"\tldm r1,{r0-r7}\n"
|
|
"\tmov r8,#0\n"
|
|
"\tbl P256_reduce_mod_n_once\n"
|
|
"\tpop {r8}\n"
|
|
"\tstm r8,{r0-r7}\n"
|
|
"\tpop {r4-r11,pc}\n"
|
|
"\t.size P256_reduce_mod_n_32bytes, .-P256_reduce_mod_n_32bytes\n"
|
|
"\t.type P256_add_mod_n, %function\n"
|
|
"P256_add_mod_n:\n"
|
|
"\t.global P256_add_mod_n\n"
|
|
"\tpush {r0,r4-r11,lr}\n"
|
|
"\tmov r12,r1\n"
|
|
"\tldm r2,{r4-r11}\n"
|
|
"\tldm r12!,{r0-r3}\n"
|
|
"\tadds r0,r4\n"
|
|
"\tadcs r1,r1,r5\n"
|
|
"\tadcs r2,r2,r6\n"
|
|
"\tadcs r3,r3,r7\n"
|
|
"\tldm r12,{r4-r7}\n"
|
|
"\tadcs r4,r4,r8\n"
|
|
"\tadcs r5,r5,r9\n"
|
|
"\tadcs r6,r6,r10\n"
|
|
"\tadcs r7,r7,r11\n"
|
|
"\tmovs r8,#0\n"
|
|
"\tadcs r8,r8,r8\n"
|
|
"\tbl P256_reduce_mod_n_once\n"
|
|
"\tbl P256_reduce_mod_n_once\n"
|
|
"\tpop {r8}\n"
|
|
"\tstm r8,{r0-r7}\n"
|
|
"\tpop {r4-r11,pc}\n"
|
|
"\t.size P256_add_mod_n, .-P256_add_mod_n\n"
|
|
"\t.type P256_mul_mod_n, %function\n"
|
|
"P256_mul_mod_n:\n"
|
|
"\t.global P256_mul_mod_n\n"
|
|
"\tmovs r3,#0\n"
|
|
"\tpush {r3-r10,lr}\n"
|
|
"\tmov r4,r0\n"
|
|
"\tldm r1,{r1,r3,r5-r10}\n"
|
|
"\tpush {r1,r3,r5-r10}\n"
|
|
"\tmovs r1,#0\n"
|
|
"\tpush {r1}\n"
|
|
"\tldm r2,{r1,r3,r5-r10}\n"
|
|
"\tpush {r1,r3,r5-r10}\n"
|
|
"\tsub sp,#72\n"
|
|
"\tmov r0,sp\n"
|
|
"\tadd r1,sp,#72\n"
|
|
"\tadd r2,sp,#108\n"
|
|
"\tbl mul288x288\n"
|
|
"\tmov r0,r4\n"
|
|
"\tmov r1,sp\n"
|
|
"\tbl P256_reduce_mod_n_64bytes\n"
|
|
"\tadd sp,#144\n"
|
|
"\tpop {r4-r10,pc}\n"
|
|
"\t.size P256_mul_mod_n, .-P256_mul_mod_n\n"
|
|
"\t.type P256_divsteps2_31, %function\n"
|
|
"P256_divsteps2_31:\n"
|
|
"\t.global P256_divsteps2_31\n"
|
|
"\tpush {r3,r4-r8,lr}\n"
|
|
"\tmovs r4,#1\n"
|
|
"\tmovs r5,#0\n"
|
|
"\tmovs r6,#0\n"
|
|
"\tmovs r7,#1\n"
|
|
"\tmov lr,#31\n"
|
|
"0:\n"
|
|
"\tsubs r3,r0,#1\n"
|
|
"\tlsl r12,r2,#31\n"
|
|
"\tbic r3,r12,r3\n"
|
|
"\tasrs r3,r3,#31\n"
|
|
"\tlsr r8,r3,#31\n"
|
|
"\teors r0,r0,r3\n"
|
|
"\tsubs r0,r0,r3\n"
|
|
"\tmul r12,r1,r3\n"
|
|
"\tbics r1,r1,r3\n"
|
|
"\tumlal r1,r12,r2,r8\n"
|
|
"\tumaal r2,r12,r2,r3\n"
|
|
"\tmul r12,r4,r3\n"
|
|
"\tbics r4,r4,r3\n"
|
|
"\tumlal r4,r12,r6,r8\n"
|
|
"\tumaal r6,r12,r6,r3\n"
|
|
"\tmul r12,r5,r3\n"
|
|
"\tbics r5,r5,r3\n"
|
|
"\tumlal r5,r12,r7,r8\n"
|
|
"\tumaal r7,r12,r7,r3\n"
|
|
"\tands r12,r2,#1\n"
|
|
"\tadds r0,r0,#1\n"
|
|
"\tmul r3,r12,r1\n"
|
|
"\tadds r2,r2,r3\n"
|
|
"\tlsrs r2,r2,#1\n"
|
|
"\tumlal r6,r8,r12,r4\n"
|
|
"\tumlal r7,r8,r12,r5\n"
|
|
"\tadds r4,r4,r4\n"
|
|
"\tadds r5,r5,r5\n"
|
|
"\tsubs lr,lr,#1\n"
|
|
"\tbne 0b\n"
|
|
"\tpop {r3}\n"
|
|
"\tstm r3!,{r4-r7}\n"
|
|
"\tpop {r4-r8,pc}\n"
|
|
"\t.size P256_divsteps2_31, .-P256_divsteps2_31\n"
|
|
"\t.type P256_matrix_mul_fg_9, %function\n"
|
|
"P256_matrix_mul_fg_9:\n"
|
|
"\t.global P256_matrix_mul_fg_9\n"
|
|
"\tpush {r4-r11,lr}\n"
|
|
"\tand r4,r0,r0,lsl #1\n"
|
|
"\tasrs r4,r4,#31\n"
|
|
"\teors r0,r0,r4\n"
|
|
"\tsubs r0,r0,r4\n"
|
|
"\tand r5,r1,r1,lsl #1\n"
|
|
"\tasrs r5,r5,#31\n"
|
|
"\teors r1,r1,r5\n"
|
|
"\tsubs r1,r1,r5\n"
|
|
"\tldm r2!,{r6}\n"
|
|
"\tldr r7,[r2,#36]\n"
|
|
"\teors r4,r4,r6\n"
|
|
"\teors r5,r5,r7\n"
|
|
"\teors r4,r4,r5\n"
|
|
"\tstm r3!,{r5}\n"
|
|
"\tpush {r1,r2,r3}\n"
|
|
"\tldm r2!,{r1,r3,r5-r11}\n"
|
|
"\teors r1,r1,r4\n"
|
|
"\teors r3,r3,r4\n"
|
|
"\teors r5,r5,r4\n"
|
|
"\teors r6,r6,r4\n"
|
|
"\teors r7,r7,r4\n"
|
|
"\teor r8,r8,r4\n"
|
|
"\teor r9,r9,r4\n"
|
|
"\teor r10,r10,r4\n"
|
|
"\tsubs r1,r1,r4\n"
|
|
"\tsbcs r3,r3,r4\n"
|
|
"\tsbcs r5,r5,r4\n"
|
|
"\tsbcs r6,r6,r4\n"
|
|
"\tsbcs r7,r7,r4\n"
|
|
"\tsbcs r8,r8,r4\n"
|
|
"\tsbcs r9,r9,r4\n"
|
|
"\tsbcs r10,r10,r4\n"
|
|
"\teor r4,r4,r11\n"
|
|
"\tumull r1,lr,r0,r1\n"
|
|
"\tmovs r2,#0\n"
|
|
"\tumull r11,r12,r2,r2\n"
|
|
"\tumaal r2,lr,r0,r3\n"
|
|
"\tumaal r11,lr,r0,r5\n"
|
|
"\tumull r3,r5,r12,r12\n"
|
|
"\tumaal r3,lr,r0,r6\n"
|
|
"\tumaal r5,lr,r0,r7\n"
|
|
"\tumull r6,r7,r12,r12\n"
|
|
"\tumaal r6,lr,r0,r8\n"
|
|
"\tumaal r7,lr,r0,r9\n"
|
|
"\tumaal r12,lr,r0,r10\n"
|
|
"\tmla lr,r0,r4,lr\n"
|
|
"\tpop {r0,r4}\n"
|
|
"\tadds r4,r4,#40\n"
|
|
"\tldm r4!,{r8,r9}\n"
|
|
"\tmov r10,#0\n"
|
|
"\tumaal r1,r10,r0,r8\n"
|
|
"\tumaal r2,r10,r0,r9\n"
|
|
"\tadds r1,r1,r1\n"
|
|
"\tadcs r2,r2,r2\n"
|
|
"\tldm r4!,{r1,r8,r9}\n"
|
|
"\tumaal r10,r11,r0,r1\n"
|
|
"\tumaal r11,r3,r0,r8\n"
|
|
"\tumaal r3,r5,r0,r9\n"
|
|
"\tadcs r10,r10,r10\n"
|
|
"\tadcs r11,r11,r11\n"
|
|
"\tadcs r3,r3,r3\n"
|
|
"\tldm r4,{r1,r4,r8,r9}\n"
|
|
"\tumaal r5,r6,r0,r1\n"
|
|
"\tumaal r6,r7,r0,r4\n"
|
|
"\tumaal r7,r12,r0,r8\n"
|
|
"\tumaal r12,lr,r0,r9\n"
|
|
"\tadcs r5,r5,r5\n"
|
|
"\tadcs r6,r6,r6\n"
|
|
"\tadcs r7,r7,r7\n"
|
|
"\tadcs r12,r12,r12\n"
|
|
"\tsbcs lr,lr,lr\n"
|
|
"\tmvn lr,lr\n"
|
|
"\tpop {r1}\n"
|
|
"\tstm r1!,{r2,r10,r11}\n"
|
|
"\tstm r1!,{r3,r5,r6,r7,r12,lr}\n"
|
|
"\tpop {r4-r11,pc}\n"
|
|
"\t.size P256_matrix_mul_fg_9, .-P256_matrix_mul_fg_9\n"
|
|
"\t.align 2\n"
|
|
"\t.type P256_matrix_mul_mod_n, %function\n"
|
|
"P256_matrix_mul_mod_n:\n"
|
|
"\t.global P256_matrix_mul_mod_n\n"
|
|
"\tpush {r4-r11,lr}\n"
|
|
"\tand r4,r0,r0,lsl #1\n"
|
|
"\tasrs r4,r4,#31\n"
|
|
"\teors r0,r0,r4\n"
|
|
"\tsubs r0,r0,r4\n"
|
|
"\tand r5,r1,r1,lsl #1\n"
|
|
"\tasrs r5,r5,#31\n"
|
|
"\teors r1,r1,r5\n"
|
|
"\tsubs r1,r1,r5\n"
|
|
"\tldm r2!,{r6}\n"
|
|
"\tldr r7,[r2,#32]\n"
|
|
"\teors r4,r4,r6\n"
|
|
"\teors r5,r5,r7\n"
|
|
"\teors r4,r4,r5\n"
|
|
"\tstm r3!,{r5}\n"
|
|
"\tpush {r1,r2,r3}\n"
|
|
"\tldm r2,{r1-r3,r5-r9}\n"
|
|
"\teors r1,r1,r4\n"
|
|
"\teors r2,r2,r4\n"
|
|
"\teors r3,r3,r4\n"
|
|
"\teors r5,r5,r4\n"
|
|
"\teors r6,r6,r4\n"
|
|
"\teors r7,r7,r4\n"
|
|
"\teor r8,r8,r4\n"
|
|
"\teor r9,r9,r4\n"
|
|
"\tsubs r1,r1,r4\n"
|
|
"\tsbcs r2,r2,r4\n"
|
|
"\tsbcs r3,r3,r4\n"
|
|
"\tsbcs r5,r5,r4\n"
|
|
"\tsbcs r6,r6,r4\n"
|
|
"\tsbcs r7,r7,r4\n"
|
|
"\tsbcs r8,r8,r4\n"
|
|
"\tsbcs r9,r9,r4\n"
|
|
"\tsbcs r4,r4,r4\n"
|
|
"\tlsrs lr,r4,#31\n"
|
|
"\tmov r12,#0\n"
|
|
"\tldrd r10,r11,P256_order_local\n"
|
|
"\tumaal r1,r12,lr,r10\n"
|
|
"\tumaal r2,r12,lr,r11\n"
|
|
"\tldrd r10,r11,P256_order_local+8\n"
|
|
"\tumaal r3,r12,lr,r10\n"
|
|
"\tumaal r5,r12,lr,r11\n"
|
|
"\tumaal r6,r12,lr,r4\n"
|
|
"\tumaal r7,r12,lr,r4\n"
|
|
"\tmov r10,#0\n"
|
|
"\tumaal r8,r12,lr,r10\n"
|
|
"\tumaal r9,r12,lr,r4\n"
|
|
"\tumull r11,lr,r10,r10\n"
|
|
"\tumull r10,lr,r0,r1\n"
|
|
"\tumull r1,r12,r11,r11\n"
|
|
"\tumaal r11,lr,r0,r2\n"
|
|
"\tumaal r1,lr,r0,r3\n"
|
|
"\tumull r2,r3,r12,r12\n"
|
|
"\tumaal r2,lr,r0,r5\n"
|
|
"\tumaal r3,lr,r0,r6\n"
|
|
"\tumull r4,r5,r12,r12\n"
|
|
"\tumaal r4,lr,r0,r7\n"
|
|
"\tumaal r5,lr,r0,r8\n"
|
|
"\tumaal r12,lr,r0,r9\n"
|
|
"\tpop {r0,r6}\n"
|
|
"\tadds r6,r6,#36\n"
|
|
"\tldm r6!,{r8,r9}\n"
|
|
"\tmovs r7,#0\n"
|
|
"\tumaal r10,r7,r0,r8\n"
|
|
"\tumaal r11,r7,r0,r9\n"
|
|
"\tldm r6!,{r8,r9}\n"
|
|
"\tumaal r1,r7,r0,r8\n"
|
|
"\tumaal r2,r7,r0,r9\n"
|
|
"\tldm r6!,{r8,r9}\n"
|
|
"\tumaal r3,r7,r0,r8\n"
|
|
"\tumaal r4,r7,r0,r9\n"
|
|
"\tldm r6!,{r8,r9}\n"
|
|
"\tumaal r5,r7,r0,r8\n"
|
|
"\tumaal r12,r7,r0,r9\n"
|
|
"\tadd lr,lr,r7\n"
|
|
"\tldr r0,=0xee00bc4f\n"
|
|
"\tmul r0,r10,r0\n"
|
|
"\tmovs r6,#0\n"
|
|
"\tldrd r8,r9,P256_order_local\n"
|
|
"\tumaal r10,r6,r0,r8\n"
|
|
"\tumaal r11,r6,r0,r9\n"
|
|
"\tsubs r11,r11,r8\n"
|
|
"\tldrd r8,r10,P256_order_local+8\n"
|
|
"\tumaal r1,r6,r0,r8\n"
|
|
"\tsbcs r1,r1,r9\n"
|
|
"\tumaal r2,r6,r0,r10\n"
|
|
"\tmov r9,#-1\n"
|
|
"\tumaal r3,r6,r0,r9\n"
|
|
"\tumaal r4,r6,r0,r9\n"
|
|
"\tmovs r7,#0\n"
|
|
"\tumaal r5,r6,r0,r7\n"
|
|
"\tumaal r12,r6,r0,r9\n"
|
|
"\tumaal lr,r6,r7,r7\n"
|
|
"\tsbcs r2,r2,r8\n"
|
|
"\tsbcs r3,r3,r10\n"
|
|
"\tsbcs r4,r4,r9\n"
|
|
"\tsbcs r5,r5,r9\n"
|
|
"\tsbcs r12,r12,r7\n"
|
|
"\tsbcs lr,lr,r9\n"
|
|
"\tsbcs r6,r6,r7\n"
|
|
"\tldrd r0,r9,P256_order_local\n"
|
|
"\tlsrs r6,r6,#31\n"
|
|
"\tumaal r7,r11,r6,r0\n"
|
|
"\tumaal r1,r11,r6,r9\n"
|
|
"\tumaal r2,r11,r6,r8\n"
|
|
"\tumaal r3,r11,r6,r10\n"
|
|
"\trsbs r0,r6,#0\n"
|
|
"\tumaal r4,r11,r6,r0\n"
|
|
"\tumaal r5,r11,r6,r0\n"
|
|
"\tmov r8,#0\n"
|
|
"\tumaal r11,r12,r6,r8\n"
|
|
"\tumaal r12,lr,r6,r0\n"
|
|
"\tpop {r6}\n"
|
|
"\tstm r6!,{r7}\n"
|
|
"\tstm r6!,{r1,r2,r3,r4,r5,r11,r12}\n"
|
|
"\tpop {r4-r11,pc}\n"
|
|
"\t.ltorg\n"
|
|
"\t.size P256_matrix_mul_mod_n, .-P256_matrix_mul_mod_n\n"
|
|
"\t.align 2\n"
|
|
"P256_order_local:\n"
|
|
"\t.type P256_order, %object\n"
|
|
"P256_order:\n"
|
|
"\t.global P256_order\n"
|
|
"\t.word 0xFC632551\n"
|
|
"\t.word 0xF3B9CAC2\n"
|
|
"\t.word 0xA7179E84\n"
|
|
"\t.word 0xBCE6FAAD\n"
|
|
"\t.word 0xFFFFFFFF\n"
|
|
"\t.word 0xFFFFFFFF\n"
|
|
"\t.word 0\n"
|
|
"\t.word 0xFFFFFFFF\n"
|
|
"\t.word 0\n"
|
|
"\t.size P256_order, .-P256_order\n"
|
|
"\t.type P256_check_range_n, %function\n"
|
|
"P256_check_range_n:\n"
|
|
"\t.global P256_check_range_n\n"
|
|
"\tpush {r4-r11,lr}\n"
|
|
"\tldm r0,{r1-r8}\n"
|
|
"\torrs r0,r1,r2\n"
|
|
"\torrs r0,r3\n"
|
|
"\torrs r0,r4\n"
|
|
"\torrs r0,r5\n"
|
|
"\torrs r0,r6\n"
|
|
"\torrs r0,r7\n"
|
|
"\torrs r0,r8\n"
|
|
"\tbeq 0f\n"
|
|
"\tadr r0,P256_order\n"
|
|
"\tldm r0!,{r9-r12}\n"
|
|
"\tsubs r1,r9\n"
|
|
"\tsbcs r2,r2,r10\n"
|
|
"\tsbcs r3,r3,r11\n"
|
|
"\tsbcs r4,r4,r12\n"
|
|
"\tldm r0,{r0-r3}\n"
|
|
"\tsbcs r5,r5,r0\n"
|
|
"\tsbcs r6,r6,r1\n"
|
|
"\tsbcs r7,r7,r2\n"
|
|
"\tsbcs r8,r8,r3\n"
|
|
"\tsbcs r0,r0,r0\n"
|
|
"\tlsrs r0,#31\n"
|
|
"0:\n"
|
|
"\tpop {r4-r11,pc}\n"
|
|
"\t.size P256_check_range_n, .-P256_check_range_n\n"
|
|
"\t.align 2\n"
|
|
"b_mont:\n"
|
|
"\t.word 0x29c4bddf\n"
|
|
"\t.word 0xd89cdf62\n"
|
|
"\t.word 0x78843090\n"
|
|
"\t.word 0xacf005cd\n"
|
|
"\t.word 0xf7212ed6\n"
|
|
"\t.word 0xe5a220ab\n"
|
|
"\t.word 0x04874834\n"
|
|
"\t.word 0xdc30061d\n"
|
|
"three_mont:\n"
|
|
"\t.word 0x3\n"
|
|
"\t.word 0x0\n"
|
|
"\t.word 0x0\n"
|
|
"\t.word 0xfffffffd\n"
|
|
"\t.word 0xffffffff\n"
|
|
"\t.word 0xffffffff\n"
|
|
"\t.word 0xfffffffc\n"
|
|
"\t.word 0x2\n"
|
|
"\t.type P256_point_is_on_curve, %function\n"
|
|
"P256_point_is_on_curve:\n"
|
|
"\t.global P256_point_is_on_curve\n"
|
|
"\tpush {r0,r4-r11,lr}\n"
|
|
"\tldm r1,{r0-r7}\n"
|
|
"\tbl P256_sqrmod\n"
|
|
"\tpush {r0-r7}\n"
|
|
"\tldr r0,[sp,#32]\n"
|
|
"\tldm r0,{r0-r7}\n"
|
|
"\tbl P256_sqrmod\n"
|
|
"\tpush {r0-r7}\n"
|
|
"\tmov r1,sp\n"
|
|
"\tadr r2,three_mont\n"
|
|
"\tbl P256_submod\n"
|
|
"\tstm sp,{r0-r7}\n"
|
|
"\tldr r1,[sp,#64]\n"
|
|
"\tmov r2,sp\n"
|
|
"\tbl P256_mulmod\n"
|
|
"\tstm sp,{r0-r7}\n"
|
|
"\tadd r1,sp,#32\n"
|
|
"\tmov r2,sp\n"
|
|
"\tbl P256_submod\n"
|
|
"\tadr r8,b_mont\n"
|
|
"\tldm r8!,{r9-r12}\n"
|
|
"\teors r0,r9\n"
|
|
"\tittt eq\n"
|
|
"\teorseq r1,r10\n"
|
|
"\teorseq r2,r11\n"
|
|
"\teorseq r3,r12\n"
|
|
"\tldm r8,{r9-r12}\n"
|
|
"\titttt eq\n"
|
|
"\teorseq r4,r9\n"
|
|
"\teorseq r5,r10\n"
|
|
"\teorseq r6,r11\n"
|
|
"\teorseq r7,r12\n"
|
|
"\tmov r0,#0\n"
|
|
"\tit eq\n"
|
|
"\tmoveq r0,#1\n"
|
|
"\tadd sp,#68\n"
|
|
"\tpop {r4-r11,pc}\n"
|
|
"\t.size P256_point_is_on_curve, .-P256_point_is_on_curve\n"
|
|
"\t.align 2\n"
|
|
"P256_p:\n"
|
|
"\t.word 0xffffffff\n"
|
|
"\t.word 0xffffffff\n"
|
|
"\t.word 0xffffffff\n"
|
|
"\t.word 0\n"
|
|
"\t.word 0\n"
|
|
"\t.word 0\n"
|
|
"\t.word 1\n"
|
|
"\t.word 0xffffffff\n"
|
|
"\t.type P256_jacobian_to_affine, %function\n"
|
|
"P256_jacobian_to_affine:\n"
|
|
"\t.global P256_jacobian_to_affine\n"
|
|
"\tpush {r0,r1,r2,r4-r11,lr}\n"
|
|
"\tadds r2,#64\n"
|
|
"\tldm r2,{r0-r7}\n"
|
|
"\tmov r8,#0\n"
|
|
"\tbl P256_modinv_sqrt\n"
|
|
"\tpush {r0-r7}\n"
|
|
"\tbl P256_sqrmod\n"
|
|
"\tpush {r0-r7}\n"
|
|
"\tadd r1,sp,#32\n"
|
|
"\tmov r2,sp\n"
|
|
"\tbl P256_mulmod\n"
|
|
"\tadd r8,sp,#32\n"
|
|
"\tstm r8,{r0-r7}\n"
|
|
"\tmov r1,sp\n"
|
|
"\tldr r2,[sp,#72]\n"
|
|
"\tbl P256_mulmod\n"
|
|
"\tldr r8,[sp,#64]\n"
|
|
"\tstm r8,{r0-r7}\n"
|
|
"\tldr r2,[sp,#72]\n"
|
|
"\tadd r1,sp,#32\n"
|
|
"\tadds r2,r2,#32\n"
|
|
"\tbl P256_mulmod\n"
|
|
"\tldr r8,[sp,#68]\n"
|
|
"\tstm r8,{r0-r7}\n"
|
|
"\tadd sp,#76\n"
|
|
"\tpop {r4-r11,pc}\n"
|
|
"\t.size P256_jacobian_to_affine, .-P256_jacobian_to_affine\n"
|
|
"\t.type P256_double_j, %function\n"
|
|
"P256_double_j:\n"
|
|
"\t.global P256_double_j\n"
|
|
"\tpush {r0,r1,r4-r11,lr}\n"
|
|
"\tadds r1,#64\n"
|
|
"\tldm r1,{r0-r7}\n"
|
|
"\tbl P256_sqrmod\n"
|
|
"\tpush {r0-r7}\n"
|
|
"\tldr r1,[sp,#36]\n"
|
|
"\tadds r1,#32\n"
|
|
"\tadd r2,r1,#32\n"
|
|
"\tbl P256_mulmod\n"
|
|
"\tldr r8,[sp,#32]\n"
|
|
"\tadd r8,#64\n"
|
|
"\tstm r8,{r0-r7}\n"
|
|
"\tldr r1,[sp,#36]\n"
|
|
"\tmov r2,sp\n"
|
|
"\tbl P256_addmod\n"
|
|
"\tpush {r0-r7}\n"
|
|
"\tldr r1,[sp,#68]\n"
|
|
"\tadd r2,sp,#32\n"
|
|
"\tbl P256_submod\n"
|
|
"\tadd r8,sp,#32\n"
|
|
"\tstm r8,{r0-r7}\n"
|
|
"\tadd r1,sp,#32\n"
|
|
"\tmov r2,sp\n"
|
|
"\tbl P256_mulmod\n"
|
|
"\tadd r8,sp,#32\n"
|
|
"\tstm r8,{r0-r7}\n"
|
|
"\tlsl r8,r0,#31\n"
|
|
"\tadds r0,r0,r8, asr #31\n"
|
|
"\tadcs r1,r1,r8, asr #31\n"
|
|
"\tadcs r2,r2,r8, asr #31\n"
|
|
"\tadcs r3,r3,#0\n"
|
|
"\tadcs r4,r4,#0\n"
|
|
"\tadcs r5,r5,#0\n"
|
|
"\tadcs r6,r6,r8, lsr #31\n"
|
|
"\tadcs r7,r7,r8, asr #31\n"
|
|
"\trrxs r7,r7\n"
|
|
"\trrxs r6,r6\n"
|
|
"\trrxs r5,r5\n"
|
|
"\trrxs r4,r4\n"
|
|
"\trrxs r3,r3\n"
|
|
"\trrxs r2,r2\n"
|
|
"\trrxs r1,r1\n"
|
|
"\trrx r0,r0\n"
|
|
"\tstm sp,{r0-r7}\n"
|
|
"\tadd r1,sp,#32\n"
|
|
"\tmov r2,sp\n"
|
|
"\tbl P256_addmod\n"
|
|
"\tadd r8,sp,#32\n"
|
|
"\tstm r8,{r0-r7}\n"
|
|
"\tbl P256_sqrmod\n"
|
|
"\tstm sp,{r0-r7}\n"
|
|
"\tldr r0,[sp,#68]\n"
|
|
"\tadds r0,#32\n"
|
|
"\tldm r0,{r0-r7}\n"
|
|
"\tbl P256_sqrmod\n"
|
|
"\tldr r8,[sp,#64]\n"
|
|
"\tadd r8,#32\n"
|
|
"\tstm r8,{r0-r7}\n"
|
|
"\tbl P256_sqrmod\n"
|
|
"\tpush {r0-r7}\n"
|
|
"\tldrd r0,r1,[sp,#96]\n"
|
|
"\tadd r2,r0,#32\n"
|
|
"\tbl P256_mulmod\n"
|
|
"\tldr r8,[sp,#96]\n"
|
|
"\tadd r8,#32\n"
|
|
"\tstm r8,{r0-r7}\n"
|
|
"\tbl P256_times2\n"
|
|
"\tldr r8,[sp,#96]\n"
|
|
"\tstm r8,{r0-r7}\n"
|
|
"\tadd r1,sp,#32\n"
|
|
"\tmov r2,r8\n"
|
|
"\tbl P256_submod\n"
|
|
"\tldr r8,[sp,#96]\n"
|
|
"\tstm r8,{r0-r7}\n"
|
|
"\tmov r2,r8\n"
|
|
"\tadd r1,r2,#32\n"
|
|
"\tbl P256_submod\n"
|
|
"\tadd r8,sp,#32\n"
|
|
"\tstm r8,{r0-r7}\n"
|
|
"\tadd r1,sp,#64\n"
|
|
"\tadd r2,sp,#32\n"
|
|
"\tbl P256_mulmod\n"
|
|
"\tadd r8,sp,#64\n"
|
|
"\tstm r8,{r0-r7}\n"
|
|
"\tadd r1,sp,#64\n"
|
|
"\tmov r2,sp\n"
|
|
"\tbl P256_submod\n"
|
|
"\tldr r8,[sp,#96]\n"
|
|
"\tadd r8,#32\n"
|
|
"\tstm r8,{r0-r7}\n"
|
|
"\tadd sp,#104\n"
|
|
"\tpop {r4-r11,pc}\n"
|
|
"\t.size P256_double_j, .-P256_double_j\n"
|
|
"\t.type add_sub_helper, %function\n"
|
|
"add_sub_helper:\n"
|
|
"\tpush {lr}\n"
|
|
"\tldm r1!,{r5-r12}\n"
|
|
"\tstm r0!,{r5-r12}\n"
|
|
"\tldm r1!,{r5-r12}\n"
|
|
"\tcbz r2,0f\n"
|
|
"\tmov lr,#0\n"
|
|
"\trsbs r4,r2,#0\n"
|
|
"\tsubs r5,r4,r5\n"
|
|
"\tsbcs r6,r4,r6\n"
|
|
"\tsbcs r7,r4,r7\n"
|
|
"\tsbcs r8,lr,r8\n"
|
|
"\tsbcs r9,lr,r9\n"
|
|
"\tsbcs r10,lr,r10\n"
|
|
"\tsbcs r11,r2,r11\n"
|
|
"\tsbcs r12,r4,r12\n"
|
|
"0:\n"
|
|
"\tstm r0!,{r5-r12}\n"
|
|
"\tcbnz r3,1f\n"
|
|
"\tldm r1,{r5-r12}\n"
|
|
"\tstm r0,{r5-r12}\n"
|
|
"\tb 2f\n"
|
|
"1:\n"
|
|
"\tmovs r4,#0\n"
|
|
"\tumull r5,r10,r4,r4\n"
|
|
"\tmvns r6,r4\n"
|
|
"\tmvns r7,r4\n"
|
|
"\tmov r8,#0xffffffff\n"
|
|
"\tmov r9,#0xfffffffe\n"
|
|
"\tstm r0,{r3-r10}\n"
|
|
"2:\n"
|
|
"\tpop {pc}\n"
|
|
"\t.size add_sub_helper, .-add_sub_helper\n"
|
|
"\t.type P256_add_sub_j, %function\n"
|
|
"P256_add_sub_j:\n"
|
|
"\t.global P256_add_sub_j\n"
|
|
"\tpush {r0-r11,lr}\n"
|
|
"\tadd r4,r0,#64\n"
|
|
"\tldm r4,{r4-r11}\n"
|
|
"\torrs r4,r5\n"
|
|
"\torrs r4,r6\n"
|
|
"\torrs r4,r7\n"
|
|
"\torrs r4,r8\n"
|
|
"\torrs r4,r9\n"
|
|
"\torrs r4,r10\n"
|
|
"\torrs r4,r11\n"
|
|
"\tbne 2f\n"
|
|
"\tbl add_sub_helper\n"
|
|
"\tadd sp,#16\n"
|
|
"\tpop {r4-r11,pc}\n"
|
|
"2:\n"
|
|
"\tcbnz r3,100f\n"
|
|
"\tadds r1,#64\n"
|
|
"\tldm r1,{r0-r7}\n"
|
|
"\tbl P256_sqrmod\n"
|
|
"\tpush {r0-r7}\n"
|
|
"\tldr r1,[sp,#32]\n"
|
|
"\tmov r2,sp\n"
|
|
"\tbl P256_mulmod\n"
|
|
"\tldr r8,[sp,#32]\n"
|
|
"\tstm r8,{r0-r7}\n"
|
|
"\tldr r1,[sp,#36]\n"
|
|
"\tadds r1,#64\n"
|
|
"\tmov r2,sp\n"
|
|
"\tbl P256_mulmod\n"
|
|
"\tstm sp,{r0-r7}\n"
|
|
"\tldr r1,[sp,#32]\n"
|
|
"\tadds r1,#32\n"
|
|
"\tmov r2,sp\n"
|
|
"\tbl P256_mulmod\n"
|
|
"\tldr r8,[sp,#32]\n"
|
|
"\tadd r8,#32\n"
|
|
"\tstm r8,{r0-r7}\n"
|
|
"\tb 101f\n"
|
|
"100:\n"
|
|
"\tsub sp,#32\n"
|
|
"101:\n"
|
|
"\tldr r1,[sp,#32]\n"
|
|
"\tadds r1,#64\n"
|
|
"\tldm r1,{r0-r7}\n"
|
|
"\tbl P256_sqrmod\n"
|
|
"\tpush {r0-r7}\n"
|
|
"\tldr r1,[sp,#68]\n"
|
|
"\tmov r2,sp\n"
|
|
"\tbl P256_mulmod\n"
|
|
"\tadd r8,sp,#32\n"
|
|
"\tstm r8,{r0-r7}\n"
|
|
"\tldr r1,[sp,#64]\n"
|
|
"\tadds r1,#64\n"
|
|
"\tmov r2,sp\n"
|
|
"\tbl P256_mulmod\n"
|
|
"\tstm sp,{r0-r7}\n"
|
|
"\tldr r1,[sp,#68]\n"
|
|
"\tadds r1,#32\n"
|
|
"\tmov r2,sp\n"
|
|
"\tbl P256_mulmod\n"
|
|
"\tstm sp,{r0-r7}\n"
|
|
"\tldr r1,[sp,#64]\n"
|
|
"\tadd r2,sp,#32\n"
|
|
"\tbl P256_submod\n"
|
|
"\tldr r8,[sp,#64]\n"
|
|
"\tstm r8,{r0-r7}\n"
|
|
"\tbl P256_sqrmod\n"
|
|
"\tpush {r0-r7}\n"
|
|
"\tldr r2,[sp,#96]\n"
|
|
"\tadd r1,r2,#64\n"
|
|
"\tbl P256_mulmod\n"
|
|
"\tldr r8,[sp,#96]\n"
|
|
"\tadd r8,#64\n"
|
|
"\tstm r8,{r0-r7}\n"
|
|
"\tldr r1,[sp,#108]\n"
|
|
"\tcbnz r1,102f\n"
|
|
"\tldr r1,[sp,#100]\n"
|
|
"\tadds r1,#64\n"
|
|
"\tmov r2,r8\n"
|
|
"\tbl P256_mulmod\n"
|
|
"\tldr r8,[sp,#96]\n"
|
|
"\tadd r8,#64\n"
|
|
"\tstm r8,{r0-r7}\n"
|
|
"102:\n"
|
|
"\tldr r1,[sp,#96]\n"
|
|
"\tmov r2,sp\n"
|
|
"\tbl P256_mulmod\n"
|
|
"\tldr r8,[sp,#96]\n"
|
|
"\tstm r8,{r0-r7}\n"
|
|
"\torrs r1,r0\n"
|
|
"\torrs r1,r2\n"
|
|
"\torrs r1,r3\n"
|
|
"\torrs r1,r4\n"
|
|
"\torrs r1,r5\n"
|
|
"\torrs r1,r6\n"
|
|
"\torrs r0,r1,r7\n"
|
|
"3:\n"
|
|
"\tpush {r0}\n"
|
|
"\tldr r1,[sp,#100]\n"
|
|
"\tadds r1,#32\n"
|
|
"\tadd r2,sp,#36\n"
|
|
"\tldr r3,[sp,#108]\n"
|
|
"\tcbz r3,4f\n"
|
|
"\tbl P256_addmod\n"
|
|
"\tb 5f\n"
|
|
"4:\n"
|
|
"\tbl P256_submod\n"
|
|
"5:\n"
|
|
"\tldr r8,[sp,#100]\n"
|
|
"\tadd r8,#32\n"
|
|
"\tstm r8,{r0-r7}\n"
|
|
"\tpop {r8}\n"
|
|
"\torrs r1,r0\n"
|
|
"\torrs r1,r2\n"
|
|
"\torrs r1,r3\n"
|
|
"\torrs r1,r4\n"
|
|
"\torrs r1,r5\n"
|
|
"\torrs r1,r6\n"
|
|
"\torrs r1,r7\n"
|
|
"\torrs r1,r8\n"
|
|
"\tbne 6f\n"
|
|
"\tadd sp,#96\n"
|
|
"\tldm sp,{r0-r3}\n"
|
|
"\tbl add_sub_helper\n"
|
|
"\tldr r0,[sp,#0]\n"
|
|
"\tmov r1,r0\n"
|
|
"\tadd sp,#16\n"
|
|
"\tbl P256_double_j\n"
|
|
"\tpop {r4-r11,pc}\n"
|
|
"6:\n"
|
|
"\tadd r1,sp,#64\n"
|
|
"\tmov r2,sp\n"
|
|
"\tbl P256_mulmod\n"
|
|
"\tadd r8,sp,#64\n"
|
|
"\tstm r8,{r0-r7}\n"
|
|
"\tldr r0,[sp,#96]\n"
|
|
"\tadds r0,#32\n"
|
|
"\tldm r0,{r0-r7}\n"
|
|
"\tbl P256_sqrmod\n"
|
|
"\tstm sp,{r0-r7}\n"
|
|
"\tadd r1,sp,#32\n"
|
|
"\tldr r2,[sp,#96]\n"
|
|
"\tbl P256_mulmod\n"
|
|
"\tadd r8,sp,#32\n"
|
|
"\tstm r8,{r0-r7}\n"
|
|
"\tmov r1,sp\n"
|
|
"\tldr r2,[sp,#96]\n"
|
|
"\tbl P256_submod\n"
|
|
"\tldr r8,[sp,#96]\n"
|
|
"\tstm r8,{r0-r7}\n"
|
|
"\tadd r0,sp,#64\n"
|
|
"\tldm r0,{r0-r7}\n"
|
|
"\tbl P256_times2\n"
|
|
"\tstm sp,{r0-r7}\n"
|
|
"\tldr r1,[sp,#96]\n"
|
|
"\tmov r2,sp\n"
|
|
"\tbl P256_submod\n"
|
|
"\tldr r8,[sp,#96]\n"
|
|
"\tstm r8,{r0-r7}\n"
|
|
"\tadd r1,sp,#64\n"
|
|
"\tldr r2,[sp,#96]\n"
|
|
"\tbl P256_submod\n"
|
|
"\tstm sp,{r0-r7}\n"
|
|
"\tldr r1,[sp,#96]\n"
|
|
"\tadds r1,#32\n"
|
|
"\tmov r2,sp\n"
|
|
"\tbl P256_mulmod\n"
|
|
"\tstm sp,{r0-r7}\n"
|
|
"\tldr r0,[sp,#104]\n"
|
|
"\tmov r1,sp\n"
|
|
"\tadd r2,sp,#32\n"
|
|
"\tcbz r0,7f\n"
|
|
"\tbl P256_addmod\n"
|
|
"\tb 8f\n"
|
|
"7:\n"
|
|
"\tbl P256_submod\n"
|
|
"8:\n"
|
|
"\tldr r8,[sp,#96]\n"
|
|
"\tadd r8,#32\n"
|
|
"\tstm r8,{r0-r7}\n"
|
|
"\tadd sp,#112\n"
|
|
"\tpop {r4-r11,pc}\n"
|
|
"\t.size P256_add_sub_j, .-P256_add_sub_j\n"
|
|
"\t.type P256_verify_last_step, %function\n"
|
|
"P256_verify_last_step:\n"
|
|
"\t.global P256_verify_last_step\n"
|
|
"\tpush {r0,r1,r4-r11,lr}\n"
|
|
"\tsub sp,#32\n"
|
|
"\tadd r1,#64\n"
|
|
"\tldm r1,{r0-r7}\n"
|
|
"\tbl P256_sqrmod\n"
|
|
"\tpush {r0-r7}\n"
|
|
"\torrs r0,r1\n"
|
|
"\torrs r0,r2\n"
|
|
"\torrs r0,r3\n"
|
|
"\torrs r0,r4\n"
|
|
"\torrs r0,r5\n"
|
|
"\torrs r0,r6\n"
|
|
"\torrs r0,r7\n"
|
|
"\tbeq 0f\n"
|
|
"\tldr r1,[sp,#64]\n"
|
|
"2:\n"
|
|
"\tadd r0,sp,#32\n"
|
|
"\tbl P256_to_montgomery\n"
|
|
"\tadd r1,sp,#32\n"
|
|
"\tmov r2,sp\n"
|
|
"\tbl P256_mulmod\n"
|
|
"\tldr r8,[sp,#68]\n"
|
|
"\tldm r8!,{r9-r12}\n"
|
|
"\teors r0,r9\n"
|
|
"\tittt eq\n"
|
|
"\teorseq r1,r10\n"
|
|
"\teorseq r2,r11\n"
|
|
"\teorseq r3,r12\n"
|
|
"\tldm r8!,{r9-r12}\n"
|
|
"\titttt eq\n"
|
|
"\teorseq r4,r9\n"
|
|
"\teorseq r5,r10\n"
|
|
"\teorseq r6,r11\n"
|
|
"\teorseq r7,r12\n"
|
|
"\tmov r0,#1\n"
|
|
"\tbeq 1f\n"
|
|
"\tadr r0,P256_order\n"
|
|
"\tldm r0,{r8-r11}\n"
|
|
"\tldr r0,[sp,#64]\n"
|
|
"\tcbz r0,0f\n"
|
|
"\tldm r0,{r0-r7}\n"
|
|
"\tadds r0,r8\n"
|
|
"\tadcs r1,r1,r9\n"
|
|
"\tadcs r2,r2,r10\n"
|
|
"\tadcs r3,r3,r11\n"
|
|
"\tadcs r4,r4,#0xffffffff\n"
|
|
"\tadcs r5,r5,#0xffffffff\n"
|
|
"\tadcs r6,r6,#0\n"
|
|
"\tadcs r7,r7,#0xffffffff\n"
|
|
"\tbcs 0f\n"
|
|
"\tsubs r8,r0,#0xffffffff\n"
|
|
"\tsbcs r8,r1,#0xffffffff\n"
|
|
"\tsbcs r8,r2,#0xffffffff\n"
|
|
"\tsbcs r8,r3,#0\n"
|
|
"\tsbcs r8,r4,#0\n"
|
|
"\tsbcs r8,r5,#0\n"
|
|
"\tsbcs r8,r6,#1\n"
|
|
"\tsbcs r8,r7,#0xffffffff\n"
|
|
"\tbcs 0f\n"
|
|
"\tadd r8,sp,#32\n"
|
|
"\tstm r8,{r0-r7}\n"
|
|
"\tmovs r2,#0\n"
|
|
"\tstr r2,[sp,#64]\n"
|
|
"\tmov r1,r8\n"
|
|
"\tb 2b\n"
|
|
"0:\n"
|
|
"\tmovs r0,#0\n"
|
|
"1:\n"
|
|
"\tadd sp,#72\n"
|
|
"\tpop {r4-r11,pc}\n"
|
|
"\t.size P256_verify_last_step, .-P256_verify_last_step\n"
|
|
"\t.type P256_negate_mod_m_if, %function\n"
|
|
"P256_negate_mod_m_if:\n"
|
|
"\tpush {r4-r8,lr}\n"
|
|
"\trsb r8,r2,#1\n"
|
|
"\tmovs r6,#8\n"
|
|
"\tsubs r7,r7\n"
|
|
"0:\n"
|
|
"\tldm r1!,{r4,r12}\n"
|
|
"\tldm r3!,{r5,lr}\n"
|
|
"\tsbcs r5,r5,r4\n"
|
|
"\tumull r4,r7,r8,r4\n"
|
|
"\tumaal r4,r7,r2,r5\n"
|
|
"\tsbcs lr,lr,r12\n"
|
|
"\tumull r12,r7,r8,r12\n"
|
|
"\tumaal r12,r7,r2,lr\n"
|
|
"\tstm r0!,{r4,r12}\n"
|
|
"\tsub r6,#2\n"
|
|
"\tcbz r6,1f\n"
|
|
"\tb 0b\n"
|
|
"1:\n"
|
|
"\tpop {r4-r8,pc}\n"
|
|
"\t.size P256_negate_mod_m_if, .-P256_negate_mod_m_if\n"
|
|
"\t.type P256_negate_mod_n_if, %function\n"
|
|
"P256_negate_mod_n_if:\n"
|
|
"\t.global P256_negate_mod_n_if\n"
|
|
"\tldr r3,=P256_order\n"
|
|
"\tb P256_negate_mod_m_if\n"
|
|
"\t.size P256_negate_mod_n_if, .-P256_negate_mod_n_if\n"
|
|
"\t.type P256_negate_mod_p_if, %function\n"
|
|
"P256_negate_mod_p_if:\n"
|
|
"\t.global P256_negate_mod_p_if\n"
|
|
"\tadr r3,P256_p\n"
|
|
"\tb P256_negate_mod_m_if\n"
|
|
"\t.size P256_negate_mod_p_if, .-P256_negate_mod_p_if\n"
|
|
"\t.align 2\n"
|
|
".popsection\n"); // No .end here: it would drop the C code that follows
|
|
|
|
// mg_p256_*() wrappers, see tls_p256.h. The API uses big endian byte strings,
|
|
// this library uses little endian 32-bit words, so convert both ways
|
|
|
|
int mg_p256_make_key(uint8_t public_key[64], uint8_t private_key[32]) {
|
|
uint32_t x[8], y[8], d[8];
|
|
int tries, ok = 0;
|
|
for (tries = 0; tries < 64 && !ok; tries++) {
|
|
if (!mg_random(d, sizeof(d))) break;
|
|
ok = p256_keygen(x, y, d);
|
|
}
|
|
if (ok) {
|
|
p256_convert_endianness(public_key, x, 32);
|
|
p256_convert_endianness(public_key + 32, y, 32);
|
|
p256_convert_endianness(private_key, d, 32);
|
|
}
|
|
mg_bzero((unsigned char *) d, sizeof(d));
|
|
return ok;
|
|
}
|
|
|
|
int mg_p256_compute_public_key(const uint8_t private_key[32],
|
|
uint8_t public_key[64]) {
|
|
uint32_t x[8], y[8], d[8];
|
|
int ok;
|
|
p256_convert_endianness(d, private_key, 32);
|
|
ok = p256_keygen(x, y, d); // False if the key is out of range
|
|
if (ok) {
|
|
p256_convert_endianness(public_key, x, 32);
|
|
p256_convert_endianness(public_key + 32, y, 32);
|
|
}
|
|
mg_bzero((unsigned char *) d, sizeof(d));
|
|
return ok;
|
|
}
|
|
|
|
int mg_p256_shared_secret(const uint8_t public_key[64],
|
|
const uint8_t private_key[32], uint8_t secret[32]) {
|
|
uint32_t x[8], y[8], d[8];
|
|
int ok;
|
|
p256_convert_endianness(x, public_key, 32);
|
|
p256_convert_endianness(y, public_key + 32, 32);
|
|
p256_convert_endianness(d, private_key, 32);
|
|
ok = p256_ecdh_calc_shared_secret(secret, d, x, y); // Validates the point
|
|
mg_bzero((unsigned char *) d, sizeof(d));
|
|
return ok;
|
|
}
|
|
|
|
int mg_p256_sign_with_k(const uint8_t private_key[32], const uint8_t *hash,
|
|
size_t hash_size, const uint8_t k[32],
|
|
uint8_t signature[64]) {
|
|
uint32_t r[8], s[8], d[8], kw[8];
|
|
int ok;
|
|
p256_convert_endianness(d, private_key, 32);
|
|
p256_convert_endianness(kw, k, 32);
|
|
ok = p256_sign(r, s, hash, (uint32_t) hash_size, d, kw); // False if k is
|
|
// out of range
|
|
if (ok) {
|
|
p256_convert_endianness(signature, r, 32);
|
|
p256_convert_endianness(signature + 32, s, 32);
|
|
}
|
|
mg_bzero((unsigned char *) d, sizeof(d));
|
|
mg_bzero((unsigned char *) kw, sizeof(kw));
|
|
return ok;
|
|
}
|
|
|
|
int mg_p256_verify(const uint8_t public_key[64], const uint8_t *hash,
|
|
size_t hash_size, const uint8_t signature[64]) {
|
|
uint32_t x[8], y[8], r[8], s[8];
|
|
p256_convert_endianness(x, public_key, 32);
|
|
p256_convert_endianness(y, public_key + 32, 32);
|
|
p256_convert_endianness(r, signature, 32);
|
|
p256_convert_endianness(s, signature + 32, 32);
|
|
return p256_verify(x, y, hash, (uint32_t) hash_size, r, s); // Checks point
|
|
}
|
|
#undef get_bit
|
|
#endif // MG_P256 == MG_P256_LENNGREN
|