/****************************************************************************** * * 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); }