You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
159 lines
4.9 KiB
159 lines
4.9 KiB
/******************************************************************************
|
|
*
|
|
* Copyright 2017 Xaptum, Inc.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#include "./ecp_FP256BN.h"
|
|
#include "./big_256_56.h"
|
|
|
|
#include "internal-utilities/rand_pool.h"
|
|
|
|
size_t ecp_FP256BN_length(void)
|
|
{
|
|
return ECP_FP256BN_LENGTH;
|
|
}
|
|
|
|
void ecp_FP256BN_set_to_generator(ECP_FP256BN *point)
|
|
{
|
|
BIG_256_56 gx, gy;
|
|
BIG_256_56_rcopy(gx, CURVE_Gx_FP256BN);
|
|
BIG_256_56_rcopy(gy, CURVE_Gy_FP256BN);
|
|
(void)ECP_FP256BN_set(point, gx, gy); // we know this will succeed, b/c the coords are for the generator
|
|
}
|
|
|
|
void ecp_FP256BN_serialize(uint8_t *buffer_out,
|
|
ECP_FP256BN *point)
|
|
{
|
|
octet as_oct = {.len = 0,
|
|
.max = ECP_FP256BN_LENGTH,
|
|
.val = (char*)buffer_out};
|
|
|
|
ECP_FP256BN_toOctet(&as_oct, point);
|
|
}
|
|
|
|
int ecp_FP256BN_deserialize(ECP_FP256BN *point_out,
|
|
uint8_t *buffer)
|
|
{
|
|
// 1) Check that serialized point was properly formatted.
|
|
if (0x4 != buffer[0])
|
|
return -2;
|
|
|
|
// 2) Get the x,y coordinates.
|
|
BIG_256_56 wx, wy;
|
|
BIG_256_56_fromBytes(wx, (char*)&(buffer[1]));
|
|
BIG_256_56_fromBytes(wy, (char*)&(buffer[MODBYTES_256_56+1]));
|
|
|
|
// 3) Check the coordinates are valid Fp points
|
|
// (i.e. that they are less-than modulus)
|
|
// (step 2 in X9.62 Sec 5.2.2)
|
|
BIG_256_56 q;
|
|
BIG_256_56_rcopy(q, Modulus_FP256BN);
|
|
if (1 == BIG_256_56_comp(wx, q))
|
|
return -1;
|
|
if (1 == BIG_256_56_comp(wy, q))
|
|
return -1;
|
|
|
|
// 4) Check that point is on curve (ECP_FP256BN_set does this implicitly).
|
|
// (step 3 in X9.62 Sec 5.2.2)
|
|
if (!ECP_FP256BN_set(point_out, wx, wy)) {
|
|
return -1;
|
|
}
|
|
|
|
// 5) Check that point is not the identity.
|
|
// (step 1 in X9.62 Sec 5.2.2)
|
|
if (ECP_FP256BN_isinf(point_out)) {
|
|
return -1;
|
|
}
|
|
|
|
// 6) Check that point is in the proper subgroup
|
|
// (step 4 in X9.62 Sec 5.2.2)
|
|
// (order*point == inf is equivalent to cofactor*point != inf).
|
|
ECP_FP256BN point_copy;
|
|
ECP_FP256BN_copy(&point_copy, point_out);
|
|
|
|
BIG_256_56 cof;
|
|
BIG_256_56_rcopy(cof, CURVE_Cof_FP256BN);
|
|
ECP_FP256BN_mul(&point_copy, cof);
|
|
|
|
if (ECP_FP256BN_isinf(&point_copy)) {
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int32_t ecp_FP256BN_fromhash(ECP_FP256BN *point_out, const uint8_t *message, uint32_t message_length)
|
|
{
|
|
// Following the Appendix of Chen and Li, 2013
|
|
|
|
BIG_256_56 curve_order;
|
|
BIG_256_56_rcopy(curve_order, CURVE_Order_FP256BN);
|
|
|
|
for (int32_t i=0; i < 232; i++) {
|
|
BIG_256_56 x;
|
|
big_256_56_from_two_message_hash(&x, (uint8_t*)&i, sizeof(i), message, message_length);
|
|
BIG_256_56_mod(x, curve_order);
|
|
// Check if generated point is on curve:
|
|
// (the 0 indicates we want the y-coord with lsb=0)
|
|
if (ECP_FP256BN_setx(point_out, x, 0)) {
|
|
// If on curve, and cofactor != 1, multiply by cofactor to get on correct subgroup.
|
|
BIG_256_56 cofactor;
|
|
BIG_256_56_rcopy(cofactor, CURVE_Cof_FP256BN);
|
|
if (!BIG_256_56_isunity(cofactor)) {
|
|
ECP_FP256BN_mul(point_out, cofactor);
|
|
}
|
|
return i;
|
|
}
|
|
}
|
|
|
|
// If we reach here, we ran out of tries, so return error.
|
|
return -1;
|
|
}
|
|
|
|
void ecp_FP256BN_random_mod_order(BIG_256_56 *big_out,
|
|
void (*get_random)(void *buf, size_t buflen))
|
|
{
|
|
// 1) Get the order of the group
|
|
BIG_256_56 curve_order;
|
|
BIG_256_56_rcopy(curve_order, CURVE_Order_FP256BN);
|
|
|
|
// 2) Initialize our randomness
|
|
struct ecdaa_rand_pool rand_pool;
|
|
size_t needed_random_bytes = (size_t)(1 + 2*BIG_256_56_nbits(curve_order) / 8);
|
|
ecdaa_rand_pool_init(&rand_pool, needed_random_bytes, get_random);
|
|
|
|
// 3) Generate a random BIG bit-by-bit,
|
|
// then reduce it modulo the group order.
|
|
// Adapted from AMCL big.c.in::BIG_256_56_randomnum() function
|
|
int i,j=0;
|
|
uint8_t r=0;
|
|
DBIG_256_56 d;
|
|
BIG_256_56_dzero(d);
|
|
/* generate random DBIG */
|
|
for (i=0; i<2*BIG_256_56_nbits(curve_order); i++)
|
|
{
|
|
if (j==0) r=get_random_byte(&rand_pool);
|
|
else r>>=1;
|
|
int b=r&1;
|
|
BIG_256_56_dshl(d,1);
|
|
d[0]+=b;
|
|
j++;
|
|
j&=7;
|
|
}
|
|
/* reduce modulo a BIG. Removes bias */
|
|
BIG_256_56_dmod(*big_out,d,curve_order);
|
|
}
|
|
|
|
|