/* * fieldset_deserialize * * Reconstitutes a field-set from a library. */ static int fieldset_deserialize (void *vctx, name_t *np, void *fh, unsigned int count) { scopectx_t scope = parser_scope_get(expr_parse_ctx(vctx)); namectx_t namectx = scope_namectx(scope); namereflist_t *frefs = name_extraspace(np); uint16_t n; size_t len; namedef_t ndef; char namebuf[NAME_SIZE]; if (count != sizeof(n)) return 0; if (file_readbuf(fh, &n, count, &len) <= 0) return 0; if (len != count) return 0; if (n == 0) return 1; memset(&ndef, 0, sizeof(ndef)); ndef.name = namebuf; while (n > 0) { name_t *fnp; unsigned int fcnt; if (!name_deserialize(fh, namebuf, &len, &ndef.lt, &ndef.flags, &fcnt)) return 0; if (ndef.lt != LEXTYPE_NAME_FIELD) return 0; ndef.namelen = len; fnp = name_declare(scope, &ndef, 0, 0, 0, 0); if (fnp == 0) return 0; if (!field_deserialize(vctx, fnp, fh, fcnt)) return 0; namereflist_instail(frefs, nameref_alloc(namectx, fnp)); n -= 1; } return 1; } /* fieldset_deserialize */
int goldilocks_verify ( const uint8_t signature[GOLDI_SIGNATURE_BYTES], const uint8_t *message, uint64_t message_len, const struct goldilocks_public_key_t *pubkey ) { if (!goldilocks_check_init()) { return GOLDI_EUNINIT; } struct field_t pk; word_t s[GOLDI_FIELD_WORDS]; mask_t succ = field_deserialize(&pk,pubkey->opaque); if (!succ) return GOLDI_EINVAL; succ = barrett_deserialize(s, &signature[GOLDI_FIELD_BYTES], &curve_prime_order); if (!succ) return GOLDI_EINVAL; word_t challenge[GOLDI_FIELD_WORDS]; goldilocks_derive_challenge(challenge, pubkey->opaque, signature, message, message_len); struct field_t eph; struct tw_extensible_t pk_text; /* deserialize [nonce]G */ succ = field_deserialize(&eph, signature); if (!succ) return GOLDI_EINVAL; succ = deserialize_and_twist_approx(&pk_text, &sqrt_d_minus_1, &pk); if (!succ) return GOLDI_EINVAL; linear_combo_var_fixed_vt( &pk_text, challenge, GOLDI_SCALAR_BITS, s, GOLDI_SCALAR_BITS, goldilocks_global.wnafs, WNAF_PRECMP_BITS ); untwist_and_double_and_serialize( &pk, &pk_text ); field_sub(&eph, &eph, &pk); field_bias(&eph, 2); succ = field_is_zero(&eph); return succ ? 0 : GOLDI_EINVAL; }
static mask_t mpz_to_field ( field_a_t out, const mpz_t in ) { uint8_t ser[FIELD_BYTES]; mpz_t modded; memset(ser,0,sizeof(ser)); mpz_init(modded); mpz_mod(modded, in, mp_field); mpz_export(ser, NULL, -1, 1, -1, 0, modded); mask_t succ = field_deserialize(out, ser); return succ; }
int goldilocks_private_to_public ( struct goldilocks_public_key_t *pubkey, const struct goldilocks_private_key_t *privkey ) { struct field_t pk; mask_t msucc = field_deserialize(&pk,&privkey->opaque[GOLDI_FIELD_BYTES]); if (msucc) { field_serialize(pubkey->opaque, &pk); return GOLDI_EOK; } else { return GOLDI_ECORRUPT; } }
int goldilocks_verify_precomputed ( const uint8_t signature[GOLDI_SIGNATURE_BYTES], const uint8_t *message, uint64_t message_len, const struct goldilocks_precomputed_public_key_t *pubkey ) { if (!goldilocks_check_init()) { return GOLDI_EUNINIT; } word_t s[GOLDI_FIELD_WORDS]; mask_t succ = barrett_deserialize(s, &signature[GOLDI_FIELD_BYTES], &curve_prime_order); if (!succ) return GOLDI_EINVAL; word_t challenge[GOLDI_FIELD_WORDS]; goldilocks_derive_challenge(challenge, pubkey->pub.opaque, signature, message, message_len); struct field_t eph, pk; struct tw_extensible_t pk_text; /* deserialize [nonce]G */ succ = field_deserialize(&eph, signature); if (!succ) return GOLDI_EINVAL; succ = linear_combo_combs_vt ( &pk_text, challenge, GOLDI_SCALAR_BITS, &pubkey->table, s, GOLDI_SCALAR_BITS, &goldilocks_global.fixed_base ); if (!succ) return GOLDI_EINVAL; untwist_and_double_and_serialize( &pk, &pk_text ); field_sub(&eph, &eph, &pk); field_bias(&eph, 2); succ = field_is_zero(&eph); return succ ? 0 : GOLDI_EINVAL; }
struct goldilocks_precomputed_public_key_t * goldilocks_precompute_public_key ( const struct goldilocks_public_key_t *pub ) { struct goldilocks_precomputed_public_key_t *precom; precom = (struct goldilocks_precomputed_public_key_t *) malloc(sizeof(*precom)); if (!precom) return NULL; struct tw_extensible_t pk_text; struct field_t pk; mask_t succ = field_deserialize(&pk, pub->opaque); if (!succ) { free(precom); return NULL; } succ = deserialize_and_twist_approx(&pk_text, &sqrt_d_minus_1, &pk); if (!succ) { free(precom); return NULL; } succ = precompute_fixed_base(&precom->table, &pk_text, COMB_N, COMB_T, COMB_S, NULL); if (!succ) { free(precom); return NULL; } memcpy(&precom->pub,pub,sizeof(*pub)); return precom; }
static int goldilocks_shared_secret_core ( uint8_t shared[GOLDI_SHARED_SECRET_BYTES], const struct goldilocks_private_key_t *my_privkey, const struct goldilocks_public_key_t *your_pubkey, const struct goldilocks_precomputed_public_key_t *pre ) { /* This function doesn't actually need anything in goldilocks_global, * so it doesn't check init. */ assert(GOLDI_SHARED_SECRET_BYTES == SHA512_OUTPUT_BYTES); word_t sk[GOLDI_FIELD_WORDS]; struct field_t pk; mask_t succ = field_deserialize(&pk,your_pubkey->opaque), msucc = -1; #ifdef EXPERIMENT_ECDH_STIR_IN_PUBKEYS struct field_t sum, prod; msucc &= field_deserialize(&sum,&my_privkey->opaque[GOLDI_FIELD_BYTES]); field_mul(&prod,&pk,&sum); field_add(&sum,&pk,&sum); #endif msucc &= barrett_deserialize(sk,my_privkey->opaque,&curve_prime_order); #if GOLDI_IMPLEMENT_PRECOMPUTED_KEYS if (pre) { struct tw_extensible_t tw; succ &= scalarmul_fixed_base(&tw, sk, GOLDI_SCALAR_BITS, &pre->table); untwist_and_double_and_serialize(&pk, &tw); } else { succ &= montgomery_ladder(&pk,&pk,sk,GOLDI_SCALAR_BITS,1); } #else (void)pre; succ &= montgomery_ladder(&pk,&pk,sk,GOLDI_SCALAR_BITS,1); #endif field_serialize(shared,&pk); /* obliterate records of our failure by adjusting with obliteration key */ struct sha512_ctx_t ctx; sha512_init(&ctx); #ifdef EXPERIMENT_ECDH_OBLITERATE_CT uint8_t oblit[GOLDI_DIVERSIFY_BYTES + GOLDI_SYMKEY_BYTES]; unsigned i; for (i=0; i<GOLDI_DIVERSIFY_BYTES; i++) { oblit[i] = "noshared"[i] & ~(succ&msucc); } for (i=0; i<GOLDI_SYMKEY_BYTES; i++) { oblit[GOLDI_DIVERSIFY_BYTES+i] = my_privkey->opaque[2*GOLDI_FIELD_BYTES+i] & ~(succ&msucc); } sha512_update(&ctx, oblit, sizeof(oblit)); #endif #ifdef EXPERIMENT_ECDH_STIR_IN_PUBKEYS /* stir in the sum and product of the pubkeys. */ uint8_t a_pk[GOLDI_FIELD_BYTES]; field_serialize(a_pk, &sum); sha512_update(&ctx, a_pk, GOLDI_FIELD_BYTES); field_serialize(a_pk, &prod); sha512_update(&ctx, a_pk, GOLDI_FIELD_BYTES); #endif /* stir in the shared key and finish */ sha512_update(&ctx, shared, GOLDI_FIELD_BYTES); sha512_final(&ctx, shared); return (GOLDI_ECORRUPT & ~msucc) | (GOLDI_EINVAL & msucc &~ succ) | (GOLDI_EOK & msucc & succ); }