/* Return the parameters of the curve NAME. */ gcry_err_code_t _gcry_ecc_get_param (const char *name, gcry_mpi_t *pkey) { gpg_err_code_t err; unsigned int nbits; elliptic_curve_t E; mpi_ec_t ctx; gcry_mpi_t g_x, g_y; err = generate_curve (0, name, &E, &nbits); if (err) return err; g_x = mpi_new (0); g_y = mpi_new (0); ctx = _gcry_mpi_ec_init (E.p, E.a); if (_gcry_mpi_ec_get_affine (g_x, g_y, &E.G, ctx)) log_fatal ("ecc get param: Failed to get affine coordinates\n"); _gcry_mpi_ec_free (ctx); point_free (&E.G); pkey[0] = E.p; pkey[1] = E.a; pkey[2] = E.b; pkey[3] = ec2os (g_x, g_y, E.p); pkey[4] = E.n; pkey[5] = NULL; return 0; }
/* Extended version of ecc_generate which is called directly by pubkey.c. If CURVE is not NULL, that name will be used to select the domain parameters. NBITS is not used in this case. */ gcry_err_code_t _gcry_ecc_generate (int algo, unsigned int nbits, const char *curve, gcry_mpi_t *skey, gcry_mpi_t **retfactors) { gpg_err_code_t err; ECC_secret_key sk; gcry_mpi_t g_x, g_y, q_x, q_y; (void)algo; /* Make an empty list of factors. */ *retfactors = gcry_calloc ( 1, sizeof **retfactors ); if (!*retfactors) return gpg_err_code_from_syserror (); g_x = mpi_new (0); g_y = mpi_new (0); q_x = mpi_new (0); q_y = mpi_new (0); err = generate_key (&sk, nbits, curve, g_x, g_y, q_x, q_y); if (err) { gcry_free (*retfactors); *retfactors = NULL; return err; } skey[0] = sk.E.p; skey[1] = sk.E.a; skey[2] = sk.E.b; /* The function ec2os releases g_x and g_y. */ skey[3] = ec2os (g_x, g_y, sk.E.p); skey[4] = sk.E.n; /* The function ec2os releases g_x and g_y. */ skey[5] = ec2os (q_x, q_y, sk.E.p); skey[6] = sk.d; point_free (&sk.E.G); point_free (&sk.Q); return 0; }
/* PSEC-KEM key encapsulation mechanism Return: TRUE if succeed; otherwise FALSE */ u8 PSEC_KEM_KEM( PSEC_KEM_PUB_KEY *publicKey, /* PSEC_KEM public key */ PSEC_KEM_KEY_ENCAPSULATION *keyEncapsulation, /* returned keyEncapsulation */ PSEC_KEM_KEY_MATERIAL *keyMaterial, /* returned key material */ EC_PARAM *E, PSEC_KEM_EC_ENCODING_FORMAT format ) { mpz_t s, u, res, v; u8 *s_raw, *u_raw, *t_raw, *mgf_arg_1, *mgf_arg_2, *res_raw, *v_raw, *PEH_raw; u8 *EG_raw; s32 i; u32 hoLen, uoLen, EGoLen, PEHoLen, qoLen; EC_POINT h_tilde, g_tilde; mpz_init(s); mpz_init(u); mpz_init(res); mpz_init(v); hoLen = (publicKey->hLen) >> 3; uoLen = (u32)ceil(E->pLen/8.0) + 16; keyMaterial->KoLen = (publicKey->outputKeyLen) >> 3; qoLen = (u32)ceil(E->qLen/8.0); if (format == COMPRESSED) { EGoLen = 1 + qoLen; PEHoLen = 1 + qoLen; } else { EGoLen = 1 + 2*qoLen; PEHoLen = 1 + 2*qoLen; } if ((publicKey->pk).inf_id == EC_O) PEHoLen = 1; if ((E->P).inf_id == EC_O) EGoLen = 1; #ifdef DEBUG printf("hoLen = %u\n", hoLen); printf("uoLen = %u\n", uoLen); printf("keyMaterial->KoLen = %u\n", keyMaterial->KoLen); printf("EGoLen = %u\n", EGoLen); printf("PEHoLen = %u\n", PEHoLen); #endif EC_initPoint ( &h_tilde ); EC_initPoint ( &g_tilde); s_raw = (BYTE *) malloc (hoLen); u_raw = (BYTE *) malloc (uoLen); t_raw = (BYTE *) malloc (uoLen + keyMaterial->KoLen); mgf_arg_1 = (u8 *) malloc (4 + hoLen); mgf_arg_2 = (u8 *) malloc (4 + EGoLen + PEHoLen); res_raw = (u8 *) malloc (hoLen); v_raw = (u8 *) malloc (hoLen); PEH_raw = (u8 *) malloc (PEHoLen); EG_raw = (u8 *) malloc (EGoLen); /* generate s */ GenerateBytes(s_raw, hoLen, global_prng); BYTE2WORD (s, s_raw, hoLen); #ifdef DEBUG printf("s = 0x%s\n", mpz_get_str(NULL, 16, s)); printf("\n"); fflush(stdout); #endif /* compute t = MGF1(0 || s) */ U32TO8_BIG(mgf_arg_1, 0L); memcpy(mgf_arg_1+4, s_raw, hoLen); MGF1( t_raw, 8 * (uoLen + keyMaterial->KoLen), mgf_arg_1, 4 + hoLen); #ifdef DEBUG printf("t = "); printAsHex(t_raw, uoLen+keyMaterial->KoLen); printf("\n"); fflush(stdout); #endif /* parse t as t = u || K */ memcpy( u_raw, t_raw, uoLen ); BYTE2WORD( u, u_raw, uoLen ); memcpy( keyMaterial->K_raw, t_raw+uoLen, keyMaterial->KoLen ); #ifdef DEBUG printf("u = 0x%s\n", mpz_get_str(NULL, 16, u)); printf("keyMaterial = "); printAsHex(keyMaterial->K_raw, keyMaterial->KoLen); printf("\n"); fflush(stdout); #endif /* compute h_tilde = u * publicKey->pk */ EC_Mult( &h_tilde, u, &(publicKey->pk), E ); ec2os (PEH_raw, &h_tilde, E, format); #ifdef DEBUG printf("h_tilde.x = 0x%s\n", mpz_get_str(NULL, 16, h_tilde.x)); printf("h_tilde.y = 0x%s\n", mpz_get_str(NULL, 16, h_tilde.y)); printf("PEH = "); printAsHex(PEH_raw, PEHoLen); printf("\n"); fflush(stdout); #endif /* compute g_tilde = u * E->P */ EC_Mult( &g_tilde, u, &(E->P), E ); #ifdef DEBUG printf("g_tilde.x = 0x%s\n", mpz_get_str(NULL, 16, g_tilde.x)); printf("g_tilde.y = 0x%s\n", mpz_get_str(NULL, 16, g_tilde.y)); printf("g_tilde.inf_id = %u\n", g_tilde.inf_id); #endif /* convert g_tilde's EC point to an octet string according to P1363 E.2.3.2 */ ec2os( EG_raw, &g_tilde, E, format); #ifdef DEBUG printf("EG = "); printAsHex(EG_raw, EGoLen); printf("\n"); fflush(stdout); #endif /* compute res = MGF1( 1 || EG || PEH ) */ U32TO8_BIG ( mgf_arg_2, 1L ); memcpy( mgf_arg_2 + 4, EG_raw, EGoLen ); memcpy( mgf_arg_2 + 4 + EGoLen, PEH_raw, PEHoLen ); MGF1( res_raw, publicKey->hLen, mgf_arg_2, 4 + EGoLen + PEHoLen); BYTE2WORD( res, res_raw, hoLen); #ifdef DEBUG printf("res = 0x%s\n", mpz_get_str(NULL, 16, res)); printf("\n"); fflush(stdout); #endif /* compute v = s \xor res */ mpz_xor(v, s, res); WORD2BYTE(v_raw, v, hoLen); #ifdef DEBUG printf("v = 0x%s\n", mpz_get_str(NULL, 16, v)); printf("\n"); fflush(stdout); #endif /* output C0 = EG || v */ memcpy( keyEncapsulation->C0, EG_raw, EGoLen); memcpy( keyEncapsulation->C0 + EGoLen, v_raw, hoLen); #ifdef DEBUG printf("C0 = "); printAsHex(keyEncapsulation->C0, keyEncapsulation->C0oLen); printf("\n"); fflush(stdout); #endif /* clean up */ mpz_clear(s); mpz_clear(u); mpz_clear(res); mpz_clear(v); memset(s_raw, 0, hoLen); memset(u_raw, 0, uoLen); memset(t_raw, 0, uoLen + keyMaterial->KoLen); memset(mgf_arg_1, 0, 4+hoLen); memset(mgf_arg_2, 0, 4 + EGoLen + PEHoLen); memset(res_raw, 0, hoLen); memset(v_raw, 0, hoLen); memset(PEH_raw, 0, PEHoLen); memset(EG_raw, 0, EGoLen); free(s_raw); free(u_raw); free(t_raw); free(mgf_arg_1); free(mgf_arg_2); free(res_raw); free(v_raw); free(PEH_raw); free(EG_raw); EC_clearPoint ( &h_tilde ); EC_clearPoint ( &g_tilde ); return TRUE; }