// int appears on lhs (1 / [ZR, G1, G2, GT]) status_t element_int_div(element_t c, integer_t a, element_t b) { GroupType type = b->type; EXIT_IF_NOT_SAME(c, b); LEAVE_IF( c->isInitialized != TRUE || b->isInitialized != TRUE, "uninitialized arguments."); LEAVE_IF( c->type != type, "result initialized but invalid type."); if(type == ZR) { if(bn_is_zero(b->bn)) return ELEMENT_DIV_ZERO; element_invert(c, b); if(bn_is_one(a)) return ELEMENT_OK; integer_t s; bn_inits(s); bn_mul(s, a, c->bn); bn_div_rem(s, c->bn, s, c->order); // if(bn_sign(c->bn) == BN_NEG) bn_add(c->bn, c->bn, c->order); bn_free(s); // bn_div(c->bn, a, b->bn); // bn_mod(c->bn, c->bn, c->order); } else if(type == G1 || type == G2 || type == GT) { if(bn_is_one(a)) { element_invert(c, b); } // TODO: other cases: a > 1 (ZR)? } return ELEMENT_OK; }
status_t element_mul(element_t c, element_t a, element_t b) { GroupType type = a->type; EXIT_IF_NOT_SAME(a, b); LEAVE_IF(a->isInitialized != TRUE || b->isInitialized != TRUE || c->isInitialized != TRUE, "uninitialized arguments."); LEAVE_IF( c->type != type, "result initialized but invalid type."); if(type == ZR) { bn_mul(c->bn, a->bn, b->bn); bn_mod(c->bn, c->bn, c->order); } else if(type == G1) { g1_add(c->g1, a->g1, b->g1); g1_norm(c->g1, c->g1); } else if(type == G2) { g2_add(c->g2, a->g2, b->g2); g2_norm(c->g2, c->g2); } else if(type == GT) { gt_mul(c->gt, a->gt, b->gt); } else { return ELEMENT_INVALID_TYPES; } return ELEMENT_OK; }
status_t element_pow_int(element_t c, element_t a, integer_t b) { GroupType type = a->type; // TODO: c (type) = a (type) ^ b (ZR) LEAVE_IF( c->isInitialized != TRUE || a->isInitialized != TRUE, "uninitialized argument."); EXIT_IF_NOT_SAME(c, a); LEAVE_IF(b == NULL, "uninitialized integer."); status_t result = ELEMENT_OK; LEAVE_IF( c->type != type, "result initialized but invalid type."); switch(type) { case ZR: bn_mxp(c->bn, a->bn, b, a->order); break; case G1: g1_mul(c->g1, a->g1, b); break; case G2: g2_mul(c->g2, a->g2, b); break; case GT: gt_exp(c->gt, a->gt, b); break; default: result = ELEMENT_INVALID_TYPES; break; } return result; }
status_t element_mul_int(element_t c, element_t a, integer_t b) { GroupType type = a->type; // TODO: c (type) = a (type) * b (ZR) LEAVE_IF(a->isInitialized != TRUE, "invalid argument."); LEAVE_IF(c->isInitialized != TRUE || c->type != type, "result not initialized or invalid type."); if(type == ZR) { bn_mul(c->bn, a->bn, b); bn_mod(c->bn, c->bn, c->order); } else if(type == G1) { g1_mul(c->g1, a->g1, b); } else if(type == G2) { g2_mul(c->g2, a->g2, b); } else if(type == GT) { gt_exp(c->gt, a->gt, b); } else { return ELEMENT_INVALID_TYPES; } return ELEMENT_OK; }
status_t element_pow_zr(element_t c, element_t a, element_t b) { GroupType type = a->type; // c (type) = a (type) ^ b (ZR) LEAVE_IF( c->isInitialized != TRUE || a->isInitialized != TRUE, "uninitialized argument."); EXIT_IF_NOT_SAME(c, a); LEAVE_IF(a->isInitialized != TRUE, "invalid argument."); LEAVE_IF(b->isInitialized != TRUE || b->type != ZR, "invalid type."); if(type == ZR) { bn_mxp(c->bn, a->bn, b->bn, a->order); } else if(type == G1) { g1_mul(c->g1, a->g1, b->bn); } else if(type == G2) { g2_mul(c->g2, a->g2, b->bn); } else if(type == GT) { gt_exp(c->gt, a->gt, b->bn); } else { return ELEMENT_INVALID_TYPES; } return ELEMENT_OK; }
status_t element_to_key(element_t e, uint8_t *data, int data_len, uint8_t label) { LEAVE_IF(e->isInitialized != TRUE, "uninitialized argument."); // adds an extra null byte by default - will use this last byte for the label int d_len = element_length(e), digest_len = SHA_LEN; uint8_t d[d_len + 1]; memset(d, 0, d_len); // write e to a tmp buf if(d_len > 0 && digest_len <= data_len) { element_to_bytes(d, d_len, e); d[d_len-1] = label; #ifdef DEBUG printf("%s: bytes form....\n", __FUNCTION__); print_as_hex(d, d_len); #endif // hash buf using md_map_sh256 and store data_len bytes in data uint8_t digest[digest_len + 1]; memset(digest, 0, digest_len); SHA_FUNC(digest, d, d_len); memcpy(data, digest, digest_len); #ifdef DEBUG printf("%s: digest: ", __FUNCTION__); print_as_hex(data, digest_len); #endif return ELEMENT_OK; } return ELEMENT_INVALID_ARG; }
status_t element_from_hash(element_t e, unsigned char *data, int len) { LEAVE_IF(e->isInitialized == FALSE, "uninitialized argument."); GroupType type = e->type; status_t result = ELEMENT_OK; int digest_len = SHA_LEN; unsigned char digest[digest_len + 1]; memset(digest, 0, digest_len); SHA_FUNC(digest, data, len); #ifdef DEBUG printf("%s: digest: ", __FUNCTION__); print_as_hex(digest, digest_len); #endif switch(type) { case ZR: bn_read_bin(e->bn, digest, digest_len); if(bn_cmp(e->bn, e->order) == CMP_GT) bn_mod(e->bn, e->bn, e->order); // bn_print(e->bn); break; case G1: g1_map(e->g1, digest, digest_len); break; case G2: g2_map(e->g2, digest, digest_len); break; default: result = ELEMENT_INVALID_TYPES; break; } return result; }
status_t element_div(element_t c, element_t a, element_t b) { GroupType type = a->type; EXIT_IF_NOT_SAME(a, b); LEAVE_IF(a->isInitialized != TRUE || b->isInitialized != TRUE || c->isInitialized != TRUE, "uninitialized arguments."); LEAVE_IF( c->type != type, "result initialized but invalid type."); if(type == ZR) { if(bn_is_zero(b->bn)) return ELEMENT_DIV_ZERO; // c = (1 / b) mod order element_invert(c, b); if(bn_is_one(a->bn)) return ELEMENT_OK; // bn_div(c->bn, a->bn, b->bn); // bn_mod(c->bn, c->bn, c->order); // remainder of ((a * c) / order) integer_t s; bn_inits(s); // c = (a * c) / order (remainder only) bn_mul(s, a->bn, c->bn); bn_div_rem(s, c->bn, s, a->order); // if(bn_sign(c->bn) == BN_NEG) bn_add(c->bn, c->bn, a->order); bn_free(s); } else if(type == G1) { g1_sub(c->g1, a->g1, b->g1); g1_norm(c->g1, c->g1); } else if(type == G2) { g2_sub(c->g2, a->g2, b->g2); g2_norm(c->g2, c->g2); } else if(type == GT) { gt_t t; gt_inits(t); gt_inv(t, b->gt); gt_mul(c->gt, a->gt, t); gt_free(t); } else { return ELEMENT_INVALID_TYPES; } return ELEMENT_OK; }
status_t element_set_si(element_t e, unsigned int x) { LEAVE_IF(e->isInitialized != TRUE, "uninitialized argument."); if(e->type == ZR) { bn_set_dig(e->bn, x); } return ELEMENT_OK; }
// int appears on rhs status_t element_div_int(element_t c, element_t a, integer_t b) { GroupType type = a->type; EXIT_IF_NOT_SAME(c, a); LEAVE_IF( c->isInitialized != TRUE || a->isInitialized != TRUE, "uninitialized arguments."); LEAVE_IF( c->type != type, "result initialized but invalid type."); if(type == ZR) { if(bn_is_zero(b)) return ELEMENT_DIV_ZERO; // if(bn_is_one(a->bn)) { // element_set_int(a, b); // return element_invert(c, a); // not going to work // } integer_t s; bn_inits(s); // compute c = (1 / b) mod order bn_gcd_ext(s, c->bn, NULL, b, a->order); if(bn_sign(c->bn) == BN_NEG) bn_add(c->bn, c->bn, a->order); if(bn_is_one(a->bn) && bn_sign(a->bn) == BN_POS) { bn_free(s); return ELEMENT_OK; } // remainder of ((a * c) / order) // c = (a * c) / order (remainder only) bn_mul(s, a->bn, c->bn); bn_div_rem(s, c->bn, s, a->order); // if(bn_sign(c->bn) == BN_NEG) bn_add(c->bn, c->bn, a->order); bn_free(s); // bn_div(c->bn, a->bn, b); // bn_mod(c->bn, c->bn, c->order); } else if(type == G1 || type == G2 || type == GT) { if(bn_is_one(b)) { return element_set(c, a); } // TODO: other cases: b > 1 (ZR)? } else { return ELEMENT_INVALID_TYPES; } return ELEMENT_OK; }
// copy x into e status_t element_set_int(element_t e, integer_t x) { LEAVE_IF(e->isInitialized != TRUE, "uninitialized argument."); if(e->type == ZR) { bn_copy(e->bn, x); return ELEMENT_OK; } return ELEMENT_INVALID_TYPES; }
status_t pairing_apply(element_t et, element_t e1, element_t e2) { LEAVE_IF(e1->isInitialized != TRUE || e2->isInitialized != TRUE || et->isInitialized != TRUE, "uninitialized arguments."); if(e1->type == G1 && e2->type == G2 && et->type == GT) { /* compute optimal ate pairing */ pp_map_oatep(et->gt, e1->g1, e2->g2); return ELEMENT_OK; } return ELEMENT_INVALID_ARG; }
/*! * Hash a null-terminated string to a byte array. * * @param input_buf The input buffer. * @param input_len The input buffer length (in bytes). * @param output_buf A pre-allocated output buffer of size hash_len. * @param hash_len Length of the output hash (in bytes). Should be approximately bit size of curve group order. * @param hash_prefix prefix for hash function. */ status_t hash_buffer_to_bytes(uint8_t *input_buf, int input_len, uint8_t *output_buf, int hash_len, uint8_t hash_prefix) { LEAVE_IF(input_buf == NULL || output_buf == NULL, "uninitialized argument."); int i, new_input_len = input_len + 2; // extra byte for prefix uint8_t first_block = 0; uint8_t new_input[new_input_len+1]; // printf("orig input => \n"); // print_as_hex(input_buf, input_len); memset(new_input, 0, new_input_len+1); new_input[0] = first_block; // block number (always 0 by default) new_input[1] = hash_prefix; // set hash prefix memcpy((uint8_t *)(new_input+2), input_buf, input_len); // copy input bytes // printf("new input => \n"); // print_as_hex(new_input, new_input_len); // prepare output buf memset(output_buf, 0, hash_len); if (hash_len <= SHA_LEN) { uint8_t md[SHA_LEN+1]; SHA_FUNC(md, new_input, new_input_len); memcpy(output_buf, md, hash_len); } else { // apply variable-size hash technique to get desired size // determine block count. int blocks = (int) ceil(((double) hash_len) / SHA_LEN); //debug("Num blocks needed: %d\n", blocks); uint8_t md[SHA_LEN+1]; uint8_t md2[(blocks * SHA_LEN)+1]; uint8_t *target_buf = md2; for(i = 0; i < blocks; i++) { /* compute digest = SHA-2( i || prefix || input_buf ) || ... || SHA-2( n-1 || prefix || input_buf ) */ target_buf += (i * SHA_LEN); new_input[0] = (uint8_t) i; //debug("input %d => ", i); //print_as_hex(new_input, new_input_len); SHA_FUNC(md, new_input, new_input_len); memcpy(target_buf, md, hash_len); //debug("block %d => ", i); //print_as_hex(md, SHA_LEN); memset(md, 0, SHA_LEN); } // copy back to caller memcpy(output_buf, md2, hash_len); } return ELEMENT_OK; }
int element_is_member(element_t e) { LEAVE_IF(e->isInitialized != TRUE, "uninitialized argument."); int result; if(e->type == ZR) { if(bn_cmp(e->bn, e->order) <= CMP_EQ) result = TRUE; else result = FALSE; } else if(e->type == G1) { g1_t r; g1_inits(r); g1_mul(r, e->g1, e->order); if(g1_is_infty(r) == 1) result = TRUE; else result = FALSE; g1_free(r); } else if(e->type == G2) { g2_t r; g2_inits(r); g2_mul(r, e->g2, e->order); if(g2_is_infty(r) == 1) result = TRUE; else result = FALSE; g2_free(r); } else if(e->type == GT) { gt_t r; gt_inits(r); gt_exp(r, e->gt, e->order); if(gt_is_unity(r) == 1) result = TRUE; else result = FALSE; gt_free(r); } else { result = ELEMENT_INVALID_ARG; } return result; }
// x = e (copies for ZR, maps x-coordinate for G1, and not defined for G2 or GT) status_t element_to_int(integer_t x, element_t e) { LEAVE_IF(x == NULL || e->isInitialized != TRUE, "uninitialized argument."); if(e->type == ZR) { bn_copy(x, e->bn); } else if(e->type == G1) { fp_prime_back(x, e->g1->x); } else { return ELEMENT_INVALID_TYPES; } return ELEMENT_OK; }
int element_cmp(element_t a, element_t b) { GroupType type = a->type; LEAVE_IF(a->isInitialized != TRUE || b->isInitialized != TRUE, "uninitialized argument."); EXIT_IF_NOT_SAME(a, b); switch(type) { case ZR: return bn_cmp(a->bn, b->bn); case G1: return g1_cmp(a->g1, b->g1); case G2: return g2_cmp(a->g2, b->g2); case GT: return gt_cmp(a->gt, b->gt); default: break; } return ELEMENT_INVALID_TYPES; }
status_t element_pp_pow_int(element_t o, element_pp_t e_pp, GroupType type, integer_t bn) { if(e_pp->isInitialized == FALSE) return ELEMENT_UNINITIALIZED; LEAVE_IF(bn == NULL, "uninitialized integer."); if(o->type == type) { if(type == G1) { g1_mul_fix(o->g1, e_pp->t1, bn); } else if(type == G2) { g2_mul_fix(o->g2, e_pp->t2, bn); } return ELEMENT_OK; } return ELEMENT_INVALID_ARG; }
status_t hash_buffer_to_bytes(uint8_t *input, int input_len, uint8_t *output, int output_len, uint8_t label) { LEAVE_IF(input == NULL || output == NULL, "uninitialized argument."); // adds an extra null byte by default - will use this last byte for the label int digest_len = SHA_LEN; if(digest_len <= output_len) { // hash buf using md_map_sh256 and store data_len bytes in data uint8_t digest[digest_len + 1]; memset(digest, 0, digest_len); SHA_FUNC(digest, input, input_len); memcpy(output, digest, digest_len); #ifdef DEBUG printf("%s: digest: ", __FUNCTION__); print_as_hex(output, digest_len); #endif return ELEMENT_OK; } return ELEMENT_INVALID_ARG; }
status_t element_from_bytes(element_t e, unsigned char *data, int data_len) { LEAVE_IF(e->isInitialized != TRUE, "uninitialized argument."); GroupType type = e->type; if(type == ZR) { bn_read_bin(e->bn, data, data_len); } else if(type == G1) { return g1_read_bin(e->g1, data, data_len); // x & y } else if(type == G2) { return g2_read_bin(e->g2, data, data_len); // x1, y1 & x2, y2 } else if(type == GT) { return gt_read_bin(e->gt, data, data_len); // x1-6 && y1-6 } else { return ELEMENT_INVALID_TYPES; } return ELEMENT_OK; }
// e = a status_t element_set(element_t e, element_t a) { GroupType type = a->type; LEAVE_IF(e->isInitialized != TRUE || a->isInitialized != TRUE, "uninitialized argument."); EXIT_IF_NOT_SAME(e, a); status_t result = ELEMENT_OK; switch(type) { case ZR: bn_copy(e->bn, a->bn); break; case G1: g1_copy(e->g1, a->g1); break; case G2: g2_copy(e->g2, a->g2); break; case GT: gt_copy(e->gt, a->gt); break; default: result = ELEMENT_INVALID_TYPES; break; } return result; }
status_t element_from_hash(element_t e, unsigned char *data, int len) { LEAVE_IF(e->isInitialized == FALSE, "uninitialized argument."); GroupType type = e->type; status_t result = ELEMENT_OK; int digest_len = SHA_LEN; unsigned char digest[digest_len + 1]; memset(digest, 0, digest_len); SHA_FUNC(digest, data, len); switch(type) { case ZR: bn_read_bin(e->bn, digest, digest_len); break; case G1: g1_map(e->g1, digest, digest_len); break; case G2: g2_map(e->g2, digest, digest_len); break; default: result = ELEMENT_INVALID_TYPES; break; } return result; }