/*
 * RELIC is an Efficient LIbrary for Cryptography
 * Copyright (c) 2009 RELIC Authors
 *
 * This file is part of RELIC. RELIC is legal property of its developers,
 * whose names are not listed here. Please refer to the COPYRIGHT file
 * for contact information.
 *
 * RELIC is free software; you can redistribute it and/or modify it under the
 * terms of the version 2.1 (or later) of the GNU Lesser General Public License
 * as published by the Free Software Foundation; or version 2.0 of the Apache
 * License as published by the Apache Software Foundation. See the LICENSE files
 * for more details.
 *
 * RELIC is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the LICENSE files for more details.
 *
 * You should have received a copy of the GNU Lesser General Public or the
 * Apache License along with RELIC. If not, see <https://www.gnu.org/licenses/>
 * or <https://www.apache.org/licenses/>.
 */

/**
 * @file
 *
 * Implementation of the prime elliptic curve parameters.
 *
 * @ingroup ep
 */

#include "relic_core.h"
#include "relic_epx.h"

/*============================================================================*/
/* Private definitions                                                        */
/*============================================================================*/

/*
 * A note on the MAP_U values below.
 *
 * These values were generated using the methods recommended in
 * draft-irtf-cfrg-hash-to-curve-06, Appendix E. In particular,
 * for any curve with j-invariant 0 or 1728 (i.e., a = 0 or b = 0),
 * the MAP_U value is the output of the find_z_svdw function.
 * For all other curves, the MAP_U value was calculated using the
 * find_z_sswu function.
 *
 * Note that for the BLS12-381 curve (B12_P381) when using an
 * isogeny map (defined(EP_CTMAP)), the MAP_U value is from the
 * find_z_sswu function for the isogenous curve. Similarly, when
 * specifying isogeny maps for other curves one should specify
 * the MAP_U value for the isogenous curve.
 */

#if defined(EP_PLAIN) && FP_PRIME == 160
/**
 * Parameters for the SECG P-160 prime elliptic curve.
 */
/** @{ */
#define SECG_P160_A		"-3"
#define SECG_P160_B		"1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45"
#define SECG_P160_X		"4A96B5688EF573284664698968C38BB913CBFC82"
#define SECG_P160_Y		"23A628553168947D59DCC912042351377AC5FB32"
#define SECG_P160_R		"100000000000000000001F4C8F927AED3CA752257"
#define SECG_P160_H		"1"
#define SECG_P160_MAPU	"3"
/** @} */
#endif

#if defined(EP_ENDOM) && FP_PRIME == 160
/**
 * Parameters for the SECG K-160 prime elliptic curve.
 */
/** @{ */
#define SECG_K160_A		"0"
#define SECG_K160_B		"7"
#define SECG_K160_X		"3B4C382CE37AA192A4019E763036F4F5DD4D7EBB"
#define SECG_K160_Y		"938CF935318FDCED6BC28286531733C3F03C4FEE"
#define SECG_K160_R		"100000000000000000001B8FA16DFAB9ACA16B6B3"
#define SECG_K160_H		"1"
#define SECG_K160_MAPU	"-1"
/** @} */
#endif

#if defined(EP_PLAIN) && FP_PRIME == 192
/**
 * Parameters for the NIST P-192 prime elliptic curve.
 */
/** @{ */
#define NIST_P192_A		"-3"
#define NIST_P192_B		"64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1"
#define NIST_P192_X		"188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012"
#define NIST_P192_Y		"07192B95FFC8DA78631011ED6B24CDD573F977A11E794811"
#define NIST_P192_R		"FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831"
#define NIST_P192_H		"1"
#define NIST_P192_MAPU	"-5"
/** @} */
#endif

#if defined(EP_ENDOM) && FP_PRIME == 192
/**
 * Parameters for the SECG K-192 prime elliptic curve.
 */
/** @{ */
#define SECG_K192_A		"0"
#define SECG_K192_B		"3"
#define SECG_K192_X		"DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D"
#define SECG_K192_Y		"9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D"
#define SECG_K192_R		"FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D"
#define SECG_K192_H		"1"
#define SECG_K192_MAPU	"1"
/** @} */
#endif

#if defined(EP_PLAIN) && FP_PRIME == 221
/**
 * Parameters for the Curve22103 prime elliptic curve.
 */
/** @{ */
#define CURVE_22103_A	"155555555555555555555555555555555555555555555552174084FF"
#define CURVE_22103_B	"1425ED097B425ED097B425ED097B425ED097B425ED0BBA9428427967"
#define CURVE_22103_X	"CB476FE081B61F56A60B1D1B34FB7207D072EF25DADF377731049B0"
#define CURVE_22103_Y	"36429404D97E1E217BAD2E5601F6551F95D8FE9481BD454D1F3E7B6"
#define CURVE_22103_R	"3FFFFFFFFFFFFFFFFFFFFFFFFFFF5CD04695A145C3067CF4AAE2025"
#define CURVE_22103_H	"8"
#define CURVE_22103_MAPU "F"
/** @} */
#endif

#if defined(EP_PLAIN) && FP_PRIME == 224
/**
 * Parameters for the NIST P-224 prime elliptic curve.
 */
/** @{ */
#define NIST_P224_A		"-3"
#define NIST_P224_B		"B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4"
#define NIST_P224_X		"B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21"
#define NIST_P224_Y		"BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34"
#define NIST_P224_R		"FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D"
#define NIST_P224_H		"1"
#define NIST_P224_MAPU	"1F"
/** @} */
#endif

#if defined(EP_ENDOM) && FP_PRIME == 224
/**
 * Parameters for the SECG K-224 prime elliptic curve.
 */
/** @{ */
#define SECG_K224_A		"0"
#define SECG_K224_B		"5"
#define SECG_K224_X		"A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C"
#define SECG_K224_Y		"7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5"
#define SECG_K224_R		"10000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7"
#define SECG_K224_H		"1"
#define SECG_K224_BETA	"FE0E87005B4E83761908C5131D552A850B3F58B749C37CF5B84D6768"
#define SECG_K224_LAMB	"60DCD2104C4CBC0BE6EEEFC2BDD610739EC34E317F9B33046C9E4788"
#define SECG_K224_MAPU	"-1"
/** @} */
#endif

#if defined(EP_PLAIN) && FP_PRIME == 226
/**
 * Parameters for the Curve4417 prime elliptic curve.
 */
/** @{ */
#define CURVE_4417_A	"4648D10B419379D50F4BA01869D9AE363285E01FE66920878EE075B0"
#define CURVE_4417_B	"4C4DCEDFAC09383A0311B98EE9637415B9134B4115FDB760C1A3D419"
#define CURVE_4417_X	"FF9D7EDD97D523012FFAACA32B7C90F1A8E026F21972C789A8484A2B"
#define CURVE_4417_Y	"3E9036ADC1A41FCE2F2CA08E2D1BE4F6D97E30CA7761DB1F3E2F2CE96"
#define CURVE_4417_R	"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFC4A75594D4923FC93D42713CDAF"
#define CURVE_4417_H	"4"
#define CURVE_4417_MAPU "-E"
/** @} */
#endif

#if defined(EP_PLAIN) && FP_PRIME == 251
/**
 * Parameters for the Curve1174 prime elliptic curve.
 */
/** @{ */
#define CURVE_1174_A	"486BE25B34C8080922B969257EEB54C404F914A29067A5560BB9AEE0BC67A6D"
#define CURVE_1174_B	"E347A25BF875DD2F1F12D8A10334D417CC15E77893A99F4BF278CA563072E6"
#define CURVE_1174_X	"3BE821D63D2CD5AFE0504F452E5CF47A60A10446928CEAECFD5294F89B45051"
#define CURVE_1174_Y	"66FE4E7B8B6FE152F743393029A61BFB839747C8FB00F7B27A6841C07532A0"
#define CURVE_1174_R	"1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF77965C4DFD307348944D45FD166C971"
#define CURVE_1174_H	"4"
#define CURVE_1174_MAPU "-A"
/** @} */
#endif

#if defined(EP_PLAIN) && FP_PRIME == 255
/**
 * Parameters for the Curve25519 prime elliptic curve.
 */
/** @{ */
#define CURVE_25519_A	"2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA984914A144"
#define CURVE_25519_B	"7B425ED097B425ED097B425ED097B425ED097B425ED097B4260B5E9C7710C864"
#define CURVE_25519_X	"7266F864F799E0D8194DFA071F95AA4D1F29D1DF42D553B4950B0FDD9C5D5711"
#define CURVE_25519_Y	"72FB43CD5568B3B691204CA8E6A2930633716B80FE7DADAF91E072344991E1F1"
#define CURVE_25519_R	"1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED"
#define CURVE_25519_H	"8"
#define CURVE_25519_MAPU "8"
/** @} */
#endif

#if defined(EP_PLAIN) && FP_PRIME == 256
/**
 * Parameters for the NIST P-256 prime elliptic curve.
 */
/** @{ */
#define NIST_P256_A		"-3"
#define NIST_P256_B		"5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B"
#define NIST_P256_X		"6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"
#define NIST_P256_Y		"4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5"
#define NIST_P256_R		"FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551"
#define NIST_P256_H		"1"
#define NIST_P256_MAPU "-A"
/** @} */
#endif

#if defined(EP_PLAIN) && FP_PRIME == 256
/**
 * Parameters for the Brainpool P256r1 prime elliptic curve.
 */
/** @{ */
#define BSI_P256_A		"7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9"
#define BSI_P256_B		"26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6"
#define BSI_P256_X		"8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262"
#define BSI_P256_Y		"547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997"
#define BSI_P256_R		"A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7"
#define BSI_P256_H		"1"
#define BSI_P256_MAPU	"-2"
/** @} */
#endif

#if defined(EP_ENDOM) && FP_PRIME == 256
/**
 * Parameters for the SECG K-256 prime elliptic curve.
 */
/** @{ */
#define SECG_K256_A		"0"
#define SECG_K256_B		"7"
#define SECG_K256_X		"79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"
#define SECG_K256_Y		"483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8"
#define SECG_K256_R		"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"
#define SECG_K256_H		"1"
#define SECG_K256_BETA	"7AE96A2B657C07106E64479EAC3434E99CF0497512F58995C1396C28719501EE"
#define SECG_K256_LAMB	"5363AD4CC05C30E0A5261C028812645A122E22EA20816678DF02967C1B23BD72"
#define SECG_K256_MAPU "1"
/** @} */
#endif

#if defined(EP_PLAIN) && FP_PRIME == 382
/**
 * Parameters for the Curve67254 prime elliptic curve.
 */
/** @{ */
#define CURVE_67254_A	"2E32419A32377AF8E7F03148A106D112C8C2E26D31A89F46B743DEED322C7ADC3024AFE4B5AFD8DB7180281586549F4A"
#define CURVE_67254_B	"22F6EF3BE72A67FDC236D7173727CD2AF6D02A195753C44BDF451369B02EA0F963D9A775CAE6DC3AE9CCABB7F183C1AD"
#define CURVE_67254_X	"141946416199FDDA96EC1F1AC80058AA3F0CE96B1BCD023E97BAE542FE3404B4738DB9B81A13698339387672ECA360C0"
#define CURVE_67254_Y	"D51BF79D968F4A076022E750F821058E2B5073697B639EDD355EBF8AD32352B1EFA9478DE7EB5662EF0D26EF6EEA795"
#define CURVE_67254_R	"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD5FB21F21E95EEE17C5E69281B102D2773E27E13FD3C9719"
#define CURVE_67254_H	"4"
#define CURVE_67254_MAPU "-9"
/** @} */
#endif

#if defined(EP_PLAIN) && FP_PRIME == 383
/**
 * Parameters for the Curve383187 prime elliptic curve.
 */
/** @{ */
#define CURVE_383187_A	"2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA68FEBE08D"
#define CURVE_383187_B	"4BDA12F684BDA12F684BDA12F684BDA12F684BDA12F684BDA12F684BDA12F684BDA12F684BDA12F684F0D6EE62EDBCA"
#define CURVE_383187_X	"4D089F05073F52D26988EF5B2378E120A85DEDD8A1EFACEA0008B13951B3CDA06D5C0B44C5C1B8AC6DC3E5E1F2BF015D"
#define CURVE_383187_Y	"55AB95F2C81569A8E2EADF7C823B133547094AF055BDB287DF4B89F07F1E187D6FCF17FAFA89375C092463FD3D750C55"
#define CURVE_383187_R	"1000000000000000000000000000000000000000000000000E85A85287A1488ACD41AE84B2B7030446F72088B00A0E21"
#define CURVE_383187_H	"8"
#define CURVE_383187_MAPU "2"
/** @} */
#endif

#if defined(EP_PLAIN) && FP_PRIME == 384
/**
 * Parameters for the NIST P-384 prime elliptic curve.
 */
/** @{ */
#define NIST_P384_A		"-3"
#define NIST_P384_B		"B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF"
#define NIST_P384_X		"AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7"
#define NIST_P384_Y		"3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F"
#define NIST_P384_R		"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973"
#define NIST_P384_H		"1"
#define NIST_P384_MAPU	"-C"
/** @} */
#endif

#if defined(EP_PLAIN) && FP_PRIME == 511
/**
 * Parameters for the Curve511187 prime elliptic curve.
 */
/** @{ */
#define CURVE_511187_A	"2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA94D474F50C"
#define CURVE_511187_B	"425ED097B425ED097B425ED097B425ED097B425ED097B425ED097B425ED097B425ED097B425ED097B425ED097B425ED097B425ED097B425ED0BEFAE0163491C0"
#define CURVE_511187_X	"739DCA287463592D2CB963D1C98E0229385B245EEE4380AE1AC2E2953C806C7DC2C3D7C05F3DBB2C0D32B06ED49E8F2F2E3D7289AD62A1CDEB3EAE7D762FBF78"
#define CURVE_511187_Y	"4515C654CEF9B490BDD32C5DC3930C3E287752AF10D0438213A2873B4A71BA95DD90EE5B3A0D0A1ACD6DBEECC0AB188B748EDF0D31BF92E434867B5948DE59C9"
#define CURVE_511187_R	"100000000000000000000000000000000000000000000000000000000000000017B5FEFF30C7F5677AB2AEEBD13779A2AC125042A6AA10BFA54C15BAB76BAF1B"
#define CURVE_511187_H	"8"
#define CURVE_511187_MAPU "-18"
/** @} */
#endif

#if defined(EP_PLAIN) && FP_PRIME == 521
/**
 * Parameters for the NIST P-192 prime elliptic curve.
 */
/** @{ */
#define NIST_P521_A		"-3"
#define NIST_P521_B		"51953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00"
#define NIST_P521_X		"C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66"
#define NIST_P521_Y		"11839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650"
#define NIST_P521_R		"1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409"
#define NIST_P521_H		"1"
#define NIST_P521_MAPU	"-4"
/** @} */
#endif

#if defined(EP_ENDOM) && FP_PRIME == 158
/**
 * Parameters for a 158-bit pairing-friendly prime curve.
 */
/** @{ */
#define BN_P158_A		"0"
#define BN_P158_B		"11"
#define BN_P158_X		"240000006ED000007FE9C000419FEC800CA035C6"
#define BN_P158_Y		"4"
#define BN_P158_R		"240000006ED000007FE96000419F59800C9FFD81"
#define BN_P158_H		"1"
#define BN_P158_BETA	"240000006E8800007F434000411F93C00C7F3B08"
#define BN_P158_LAMB	"240000006E4000007E9D800040A064000C5EB323"
#define BN_P158_MAPU	"1"
/** @} */
#endif

#if defined(EP_ENDOM) && FP_PRIME == 254
/**
 * Parameters for a 254-bit pairing-friendly prime curve.
 */
/** @{ */
#define BN_P254_A		"0"
#define BN_P254_B		"2"
#define BN_P254_X		"2523648240000001BA344D80000000086121000000000013A700000000000012"
#define BN_P254_Y		"1"
#define BN_P254_R		"2523648240000001BA344D8000000007FF9F800000000010A10000000000000D"
#define BN_P254_H		"1"
#define BN_P254_MAPU	"-1"
/** @} */
#endif

#if defined(EP_ENDOM) && FP_PRIME == 255
/**
 * Parameters for a 255-bit crve with high 2-adicity.
 */
/** @{ */
#define TWEEDLEDUM_A	"0"
#define TWEEDLEDUM_B	"5"
#define TWEEDLEDUM_X	"14733B283272574E23931F358A0354B7BCD5C765CC1FCEACC3B3D1A0C495C9E"
#define TWEEDLEDUM_Y	"D27E5D5B7C3AFAED0754EA62B947B23546EBF597530A7369EDC466E456761D8"
#define TWEEDLEDUM_R	"40000000000000000000000000000000038AA127696286C9842CAFD400000001"
#define TWEEDLEDUM_H	"1"
#define TWEEDLEDUM_BETA	"1508415AB5E97C949BEBC9146EF83D9A7881FB239BA41A268598ABB3A410C9C8"
#define TWEEDLEDUM_LAMB	"36C66D3A1E049A5887AD8B5FF9731FFE69CF8DE720E52EC14394C2BD148FA4FD"
#define TWEEDLEDUM_MAPU	"-1"
/** @} */
#endif

#if defined(EP_ENDOM) && FP_PRIME == 256
/**
 * Parameters for a 256-bit pairing-friendly prime curve.
 */
/** @{ */
#define BN_P256_A		"0"
#define BN_P256_B		"11"
#define BN_P256_X		"B64000000000FF2F2200000085FD5480B0001F44B6B88BF142BC818F95E3E6AE"
#define BN_P256_Y		"4"
#define BN_P256_R		"B64000000000FF2F2200000085FD547FD8001F44B6B7F4B7C2BC818F7B6BEF99"
#define BN_P256_H		"1"
#define BN_P256_MAPU	"1"
/** @} */
#endif

#if defined(EP_ENDOM) && FP_PRIME == 256
/**
 * Parameters for a 256-bit pairing-friendly prime curve standardized in China.
 */
/** @{ */
#define SM9_P256_A		"0"
#define SM9_P256_B		"5"
#define SM9_P256_X		"93DE051D62BF718FF5ED0704487D01D6E1E4086909DC3280E8C4E4817C66DDDD"
#define SM9_P256_Y		"21FE8DDA4F21E607631065125C395BBC1C1C00CBFA6024350C464CD70A3EA616"
#define SM9_P256_R		"B640000002A3A6F1D603AB4FF58EC74449F2934B18EA8BEEE56EE19CD69ECF25"
#define SM9_P256_H		"1"
#define SM9_P256_MAPU	"-1"
/** @} */
#endif

#if defined(EP_ENDOM) && FP_PRIME == 381
/**
* Parameters for a 381-bit pairing-friendly prime curve.
*/
/** @{ */
#define B12_P381_A		"0"
#define B12_P381_B		"4"
#define B12_P381_X		"17F1D3A73197D7942695638C4FA9AC0FC3688C4F9774B905A14E3A3F171BAC586C55E83FF97A1AEFFB3AF00ADB22C6BB"
#define B12_P381_Y		"08B3F481E3AAA0F1A09E30ED741D8AE4FCF5E095D5D00AF600DB18CB2C04B3EDD03CC744A2888AE40CAA232946C5E7E1"
#define B12_P381_R		"73EDA753299D7D483339D80809A1D80553BDA402FFFE5BFEFFFFFFFF00000001"
#define B12_P381_H		"396C8C005555E1568C00AAAB0000AAAB"
#if defined(EP_CTMAP)
#define B12_P381_ISO_A  "144698A3B8E9433D693A02C96D4982B0EA985383EE66A8D8E8981AEFD881AC98936F8DA0E0F97F5CF428082D584C1D"
#define B12_P381_ISO_B  "12E2908D11688030018B12E8753EEE3B2016C1F0F24F4070A0B9C14FCEF35EF55A23215A316CEAA5D1CC48E98E172BE0"
#define B12_P381_ISO_XN "11A05F2B1E833340B809101DD99815856B303E88A2D7005FF2627B56CDB4E2C85610C2D5F2E62D6EAEAC1662734649B7;17294ED3E943AB2F0588BAB22147A81C7C17E75B2F6A8417F565E33C70D1E86B4838F2A6F318C356E834EEF1B3CB83BB;D54005DB97678EC1D1048C5D10A9A1BCE032473295983E56878E501EC68E25C958C3E3D2A09729FE0179F9DAC9EDCB0;1778E7166FCC6DB74E0609D307E55412D7F5E4656A8DBF25F1B33289F1B330835336E25CE3107193C5B388641D9B6861;E99726A3199F4436642B4B3E4118E5499DB995A1257FB3F086EEB65982FAC18985A286F301E77C451154CE9AC8895D9;1630C3250D7313FF01D1201BF7A74AB5DB3CB17DD952799B9ED3AB9097E68F90A0870D2DCAE73D19CD13C1C66F652983;D6ED6553FE44D296A3726C38AE652BFB11586264F0F8CE19008E218F9C86B2A8DA25128C1052ECADDD7F225A139ED84;17B81E7701ABDBE2E8743884D1117E53356DE5AB275B4DB1A682C62EF0F2753339B7C8F8C8F475AF9CCB5618E3F0C88E;80D3CF1F9A78FC47B90B33563BE990DC43B756CE79F5574A2C596C928C5D1DE4FA295F296B74E956D71986A8497E317;169B1F8E1BCFA7C42E0C37515D138F22DD2ECB803A0C5C99676314BAF4BB1B7FA3190B2EDC0327797F241067BE390C9E;10321DA079CE07E272D8EC09D2565B0DFA7DCCDDE6787F96D50AF36003B14866F69B771F8C285DECCA67DF3F1605FB7B;6E08C248E260E70BD1E962381EDEE3D31D79D7E22C837BC23C0BF1BC24C6B68C24B1B80B64D391FA9C8BA2E8BA2D229"
#define B12_P381_ISO_XD "8CA8D548CFF19AE18B2E62F4BD3FA6F01D5EF4BA35B48BA9C9588617FC8AC62B558D681BE343DF8993CF9FA40D21B1C;12561A5DEB559C4348B4711298E536367041E8CA0CF0800C0126C2588C48BF5713DAA8846CB026E9E5C8276EC82B3BFF;B2962FE57A3225E8137E629BFF2991F6F89416F5A718CD1FCA64E00B11ACEACD6A3D0967C94FEDCFCC239BA5CB83E19;3425581A58AE2FEC83AAFEF7C40EB545B08243F16B1655154CCA8ABC28D6FD04976D5243EECF5C4130DE8938DC62CD8;13A8E162022914A80A6F1D5F43E7A07DFFDFC759A12062BB8D6B44E833B306DA9BD29BA81F35781D539D395B3532A21E;E7355F8E4E667B955390F7F0506C6E9395735E9CE9CAD4D0A43BCEF24B8982F7400D24BC4228F11C02DF9A29F6304A5;772CAACF16936190F3E0C63E0596721570F5799AF53A1894E2E073062AEDE9CEA73B3538F0DE06CEC2574496EE84A3A;14A7AC2A9D64A8B230B3F5B074CF01996E7F63C21BCA68A81996E1CDF9822C580FA5B9489D11E2D311F7D99BBDCC5A5E;A10ECF6ADA54F825E920B3DAFC7A3CCE07F8D1D7161366B74100DA67F39883503826692ABBA43704776EC3A79A1D641;95FC13AB9E92AD4476D6E3EB3A56680F682B4EE96F7D03776DF533978F31C1593174E4B4B7865002D6384D168ECDD0A;1"
#define B12_P381_ISO_YN "90D97C81BA24EE0259D1F094980DCFA11AD138E48A869522B52AF6C956543D3CD0C7AEE9B3BA3C2BE9845719707BB33;134996A104EE5811D51036D776FB46831223E96C254F383D0F906343EB67AD34D6C56711962FA8BFE097E75A2E41C696;CC786BAA966E66F4A384C86A3B49942552E2D658A31CE2C344BE4B91400DA7D26D521628B00523B8DFE240C72DE1F6;1F86376E8981C217898751AD8746757D42AA7B90EEB791C09E4A3EC03251CF9DE405ABA9EC61DECA6355C77B0E5F4CB;8CC03FDEFE0FF135CAF4FE2A21529C4195536FBE3CE50B879833FD221351ADC2EE7F8DC099040A841B6DAECF2E8FEDB;16603FCA40634B6A2211E11DB8F0A6A074A7D0D4AFADB7BD76505C3D3AD5544E203F6326C95A807299B23AB13633A5F0;4AB0B9BCFAC1BBCB2C977D027796B3CE75BB8CA2BE184CB5231413C4D634F3747A87AC2460F415EC961F8855FE9D6F2;987C8D5333AB86FDE9926BD2CA6C674170A05BFE3BDD81FFD038DA6C26C842642F64550FEDFE935A15E4CA31870FB29;9FC4018BD96684BE88C9E221E4DA1BB8F3ABD16679DC26C1E8B6E6A1F20CABE69D65201C78607A360370E577BDBA587;E1BBA7A1186BDB5223ABDE7ADA14A23C42A0CA7915AF6FE06985E7ED1E4D43B9B3F7055DD4EBA6F2BAFAAEBCA731C30;19713E47937CD1BE0DFD0B8F1D43FB93CD2FCBCB6CAF493FD1183E416389E61031BF3A5CCE3FBAFCE813711AD011C132;18B46A908F36F6DEB918C143FED2EDCC523559B8AAF0C2462E6BFE7F911F643249D9CDF41B44D606CE07C8A4D0074D8E;B182CAC101B9399D155096004F53F447AA7B12A3426B08EC02710E807B4633F06C851C1919211F20D4C04F00B971EF8;245A394AD1ECA9B72FC00AE7BE315DC757B3B080D4C158013E6632D3C40659CC6CF90AD1C232A6442D9D3F5DB980133;5C129645E44CF1102A159F748C4A3FC5E673D81D7E86568D9AB0F5D396A7CE46BA1049B6579AFB7866B1E715475224B;15E6BE4E990F03CE4EA50B3B42DF2EB5CB181D8F84965A3957ADD4FA95AF01B2B665027EFEC01C7704B456BE69C8B604"
#define B12_P381_ISO_YD "16112C4C3A9C98B252181140FAD0EAE9601A6DE578980BE6EEC3232B5BE72E7A07F3688EF60C206D01479253B03663C1;1962D75C2381201E1A0CBD6C43C348B885C84FF731C4D59CA4A10356F453E01F78A4260763529E3532F6102C2E49A03D;58DF3306640DA276FAAAE7D6E8EB15778C4855551AE7F310C35A5DD279CD2ECA6757CD636F96F891E2538B53DBF67F2;16B7D288798E5395F20D23BF89EDB4D1D115C5DBDDBCD30E123DA489E726AF41727364F2C28297ADA8D26D98445F5416;BE0E079545F43E4B00CC912F8228DDCC6D19C9F0F69BBB0542EDA0FC9DEC916A20B15DC0FD2EDEDDA39142311A5001D;8D9E5297186DB2D9FB266EAAC783182B70152C65550D881C5ECD87B6F0F5A6449F38DB9DFA9CCE202C6477FAAF9B7AC;166007C08A99DB2FC3BA8734ACE9824B5EECFDFA8D0CF8EF5DD365BC400A0051D5FA9C01A58B1FB93D1A1399126A775C;16A3EF08BE3EA7EA03BCDDFABBA6FF6EE5A4375EFA1F4FD7FEB34FD206357132B920F5B00801DEE460EE415A15812ED9;1866C8ED336C61231A1BE54FD1D74CC4F9FB0CE4C6AF5920ABC5750C4BF39B4852CFE2F7BB9248836B233D9D55535D4A;167A55CDA70A6E1CEA820597D94A84903216F763E13D87BB5308592E7EA7D4FBC7385EA3D529B35E346EF48BB8913F55;4D2F259EEA405BD48F010A01AD2911D9C6DD039BB61A6290E591B36E636A5C871A5C29F4F83060400F8B49CBA8F6AA8;ACCBB67481D033FF5852C1E48C50C477F94FF8AEFCE42D28C0F9A88CEA7913516F968986F7EBBEA9684B529E2561092;AD6B9514C767FE3C3613144B45F1496543346D98ADF02267D5CEEF9A00D9B8693000763E3B90AC11E99B138573345CC;2660400EB2E4F3B628BDD0D53CD76F2BF565B94E72927C1CB748DF27942480E420517BD8714CC80D1FADC1326ED06F7;E0FA1D816DDC03E6B24255E0D7819C171C40F65E273B853324EFCD6356CAA205CA2F570F13497804415473A1D634B8F;1"
#define B12_P381_MAPU	"B"
#else /* !defined(EP_CTMAP) */
#define B12_P381_MAPU	"-3"
#endif /* EP_CTMAP */
/** @} */
#endif

#if defined(EP_ENDOM) && FP_PRIME == 382
/**
 * Parameters for a 382-bit pairing-friendly prime curve.
 */
/** @{ */
#define BN_P382_A		"0"
#define BN_P382_B		"2"
#define BN_P382_X		"24009015183F94892D996CC179C6D1666F82CEFBE47879BBA6E58DBE43002A0609480097801382BE004E000000000012"
#define BN_P382_Y		"1"
#define BN_P382_R		"24009015183F94892D996CC179C6D1666F82CEFBE47879BB46E4CDA2E2E2281D08DC008E80108252004200000000000D"
#define BN_P382_H		"1"
#define BN_P382_MAPU	"2"
/** @} */
#endif

#if defined(EP_ENDOM) && FP_PRIME == 383
/**
 * Parameters for a 383-bit pairing-friendly prime curve.
 */
/** @{ */
#define B12_P383_A		"0"
#define B12_P383_B		"4"
#define B12_P383_X		"4ECB5D037AAE9F176171C5D83FC0D6C7AB9195D3D1442B4809F4A6F577722D5DADC9737D5D368545441992AB647A89BE"
#define B12_P383_Y		"DD3BFDE4A26B777CEDA2A8F1C4C4E6192C586D8227CC05A34705CCC5A32288C0944408D54909F31BF5C664E81778B03"
#define B12_P383_R		"1002001800C00B809C04401C81698B381DE05F095A120D3973B2099EBFEBC0001"
#define B12_P383_H		"555AAAC000AABBFFB550556155169EAB"
#define B12_P383_MAPU	"5"
/** @} */
#endif

#if defined(EP_ENDOM) && FP_PRIME == 446
/**
 * Parameters for a 446-bit pairing-friendly prime curve at the new 128-bit security level.
 */
/** @{ */
#define BN_P446_A		"0"
#define BN_P446_B		"101"
#define BN_P446_X		"2400000000000000002400000002D00000000D800000021C0000001800000000870000000B0400000057C00000015C000000132000000066"
#define BN_P446_Y		"10"
#define BN_P446_R		"2400000000000000002400000002D00000000D800000021C00000017A0000000870000000AD400000054C000000156000000126000000061"
#define BN_P446_H		"1"
#define BN_P446_MAPU	"1"
#endif

#if defined(EP_ENDOM) && FP_PRIME == 446
/**
 * Parameters for a 446-bit pairing-friendly prime curve at the new 128-bit security level.
 */
/** @{ */
#define B12_P446_A		"0"
#define B12_P446_B		"1"
#define B12_P446_X		"297792B2D03DE39D64FACA6D49FCF7A8850144CA24FC5D815C082A3AA87D1A16929E56228C136123BA51421AE89CACD5B4789A38CE39035A"
#define B12_P446_Y		"DC40DDCBAB2823A7870B5C688AA04FEE40369D913E4F2F0947A152FE1C27A79B7F787E9C35B869C3846FAC4F12A70D0FE22D2E244268CC"
#define B12_P446_R		"511B70539F27995B34995830FA4D04C98CCC4C050BC7BB9B0E8D8CA34610428001400040001"
#define B12_P446_H		"C02082602B0055D560AB0AD5AAAAC0002AAAC"
#define B12_P446_MAPU	"2"
#endif

#if defined(EP_ENDOM) && FP_PRIME == 455
/**
 * Parameters for a 455-bit pairing-friendly prime curve at the new 128-bit security level.
 */
/** @{ */
#define B12_P455_A		"0"
#define B12_P455_B		"A"
#define B12_P455_X		"03018DF4C2336D178E6EA61540353ABA01923E3890B3295848906DFC90E0C43008E4751FFC913DC1FF3DF33D11DB57BADA7A9297195ACFB2FA"
#define B12_P455_Y		"19A8A9C4C3AC2FFB4C6B380D17B8282E029615052EAA6416C16C8F36F251D87C272657F0702CC58C4E072628D7BAD3C0E9B3A8AEBFC6B2357C"
#define B12_P455_R		"10000080000380002E0000F10004F00025E000750001D1000A00000400001C00007FFFFC00001"
#define B12_P455_H		"555556AAAAB15555B54AAB6A9557FFAABFFAAB"
#define B12_P455_MAPU	"-1"
#endif

#if defined(EP_ENDOM) && FP_PRIME == 508
/**
 * Parameters for a 508-bit pairing-friendly prime curve at the 192-bit security level.
 */
/** @{ */
#define KSS_P508_A		"0"
#define KSS_P508_B		"2"
#define KSS_P508_X		"3ADD59EAC7B6A0ABC781139CE46388AB3426C6619C27187CB1F2B48AC92E04608AFBD25DA121EDB06015CB5D2BCF369C03C163605BBA21FAF7D550960553784"
#define KSS_P508_Y		"8773227730CBE52483BF6AAAA9E4FE2870B463FA14D92C31D0F99C6B6EE13106A0E8C87AD7631F8ECCE0DD6189B4C2232C644E4B857F325923FC8A80A947FFA"
#define KSS_P508_R		"BF33E1C9934E7868ECE51D291E5644DA8A2F179CEE74854EE6819B240F20CE4E7D19F4CDABA6EAEA5B0E3000000001"
#define KSS_P508_H		"10565283D505534A492ADC6AAABB051B1D"
#define KSS_P508_BETA	"926C960A5EC3B3A6C6B9CEF2CB923D3240E4780BC1AE423EE39586AD923B1C949768022369DD2CE502E7FCA0670B3A996AC44B48B523DAA7390CCB1F6D9012F"
#define KSS_P508_LAMB	"1001740B431D14BFD17F4BD000300173FFFFFFFEFFFFFFFED"
#define KSS_P508_MAPU	"1"
/** @} */
#endif

#if defined(EP_ENDOM) && FP_PRIME == 509
/**
 * Parameters for a 477-bit pairing-friendly prime curve at the 192-bit security level.
 */
/** @{ */
#define B24_P509_A		"0"
#define B24_P509_B		"1"
#define B24_P509_X		"3A1ADC72F714991991F491FA07B2429302EE6CB4FD3A8663BA38F36F81984232A749B91C286A4579F7736D120DC572C42719E75C7F58AC1426DB4827CF4A46A"
#define B24_P509_Y		"101264A0ACB6129DE3CEB5FF829968E5030855FAD666E88506531D46050023ACB15843C4EA8F8AB478F618D263D4B6271D5972803F2046DDD7C7DBC2F6232FFD"
#define B24_P509_R		"100000FFFF870FF91CE195DB5B6F3EBD1E08C94C9E193B724ED58B907FF7C311A80D7CABC647746AE3ECB627C943998457FE001"
#define B24_P509_H		"155555AAAA805FFFAAC0154AAC"
#define B24_P509_MAPU	"2"
/** @} */
#endif

#if defined(EP_ENDOM) && FP_PRIME == 511
/**
 * Parameters for the 511-bit jacobi quartic curve.
 */
/** @{ */
#define OT8_P511_A		"1"
#define OT8_P511_B		"0"
#define OT8_P511_X		"17D8A9281052D5C14B26B88FBDA0DE7001F384C09F7425270874BD187725FF7D68887EC3539658E3C60F6FFADCED61F47267CCDAF5B850DF4A441105AE49CE6"
#define OT8_P511_Y		"9CB933777C7E567A2040EC255073F2C271F632E6E81490D85377DD77659416965584F5F44DFB146E33393CE36D908F79A4ED5B4B411D78572E6CA972F66DEC8"
#define OT8_P511_R		"100000000002AC000000002AD56000000131304C0000032F6D0B1000000000001"
#define OT8_P511_H		"40000000000AB000000000AB5580000044C4C130000564BDB42C401C8E400000"
#define OT8_P511_BETA	"20000000000AB0000000018FC7800000816148500019C9EF620CC291655380BA94133E310D1CC71ED0A7EBD9B2AB859C0F60AC90F7A2E5A1140C3FCBF1DD5400"
#define OT8_P511_LAMB	"100000000002AC000000002AD55FFFFFF131304BFFFEAD2F6D0B0FF8DC7000001"
#define OT8_P511_MAPU	"1"
/** @} */
#endif

#if defined(EP_ENDOM) && FP_PRIME == 544
/**
 * Parameters for the 544-bit Cocks-Pinch curve.
 */
/** @{ */
#define GMT8_P544_A		"2"
#define GMT8_P544_B		"0"
#define GMT8_P544_X		"251670DB162D336F28505AE026E94316A074EFF8A26AD412D22C58A9CD154E4643CFC40DE884D3D54B95455267566445CB284DF1E413E11CB190BB760CD5665B12456771"
#define GMT8_P544_Y		"A18EC01733AE4D3AA2B087933D739A4987D839A136695CEE9D7C5B0E24EC62754B70DCD5EFE918C626728C2C31BD9616BC2F724015BCC2CF4DD139897799DA9D198B26CF"
#define GMT8_P544_R		"FF0060739E18D7594A978B0AB6AE4CE3DBFD52A9D00197603FFFDF0000000101"
#define GMT8_P544_H		"BC5A106E29D336CBF340F2BB98248FFC0719523D3233C6B3909C882E2BD2251BD3B22F14"
#define GMT8_P544_BETA	"AEB8BAFC09BEB98DE5FB37D9FC56F9EAC4F908F09D88B1CD8622513C94499803C18F54E6B4FB9180292A2FD4C8AFD2AF43F54BCF308198872F3A6B591394AED0EBF7961A"
#define GMT8_P544_LAMB	"FF801041EF80043901FFFEF800000010"
#define GMT8_P544_MAPU	"5"
#endif
/** @} */

#if defined(EP_ENDOM) && FP_PRIME == 569
/**
 * Parameters for a 569-bit pairing-friendly prime curve.
 */
/** @{ */
#define K54_P569_A		"0"
#define K54_P569_B		"C"
#define K54_P569_X		"DE57C87B22B60745E50EC37662D936F2EEE89AB4BEA9D57A7A51458C12B7B2FDEEABEFF35F668015A5289952F19283A7FA557E83BE3969F3B11A9D60FB14BA64603C753360D236"
#define K54_P569_Y		"67F2F55258AE5E8CDEB1CBA4EBE0C6FDB2C1D56AFA41DEE078BFB87431D057A96104CC1EC77DB5DD0618993D1755CAB1D135938EAF099CE5A05A19947EE57E3DD61AC44B5358EA"
#define K54_P569_R		"A1112E622260091587703B03A3A18BB5D20524C35116FA9C56BF77006AF8B08F4B8EEB19A39E25CA4BFDA72A9C29E31D9AF44A4BA78A70A237BF1F3690D0A601"
#define K54_P569_H		"1C242734823F3D3"
#define K54_P569_BETA	"11B4A0273012B3534BEA4F2B96E641113A156E510AED07E600BE9DD709E2015B0F8E69E3F1A44690DA0652831007C27346D9F444F22DA68B20C46EDC4889EA0B49C773C72195876"
#define K54_P569_LAMB	"15FB59F1AFF4B536CBEBB5F1317A6D0332AAEF63DBEE47A528280DACBB244A601"
#define K54_P569_MAPU	"-1"
/** @} */
#endif

#if defined(EP_ENDOM) && FP_PRIME == 575
/**
 * Parameters for a 575-bit pairing-friendly prime curve.
 */
/** @{ */
#define B48_P575_A		"0"
#define B48_P575_B		"4"
#define B48_P575_X		"259F58760BBAF5EE9988E2DD032EAB1E69E0BF14C425A57DEA4159D76471A8CA1A95C3762F6AA220C6C93A33C1BFC7264F7B4B1EA9A81889B2E173882AD2A0163B73BC78F8A54AA2"
#define B48_P575_Y		"4E0AB4BE01EEA9C4A3EA81C84E2081B03934596D846AC24862A851F811CBE5078CD4AF03DECAD5571C4BB90F502155F462E23D3180562EED28C72882F3F538893BD643EDE63C4567"
#define B48_P575_R		"FFBFC68EB6176EFB58025E547BF4EBACB1315C184DC37EAAF67BBCCE069D07F425050E765ABB8B40D5E6D7AE8A2A5698B771DDBD6E109D56D59C3DFF00000001"
#define B48_P575_H		"5552A7FA0ADD830B"
#define B48_P575_BETA	"FFBBC37DA1869F31B9AAFAF31296EECB5167E1C9E9CE0B077E9903AE049FC122282856929B2DF0C32C0B39C487860D76077734153C1C276F79B75B1CB20A7935EB5F2611"
#define B48_P575_LAMB	"FFDFE14381A38FBBE3439A4861838B75D01E7A1E85BAE6AA2A63C200FFFFFFFF"
#define B48_P575_MAPU	"1"
/** @} */
#endif

#if defined(EP_ENDOM) && FP_PRIME == 638
/**
 * Parameters for a 638-bit pairing-friendly prime curve.
 */
/** @{ */
#define BN_P638_A		"0"
#define BN_P638_B		"5"
#define BN_P638_X		"17F382B46725AEFA6F38E6F87ACAA1ACA41757FC6F2C40DB6539EDEB8B95D519B1E99255DF031C67DE6C00E39547E6347E80E5F3D36CC5B4B42FC10D061BFA0A0A8C6CB6B561C487A1420E7B383DC742"
#define BN_P638_Y		"128AC488584B7C05EFD5436E559D741C978A5027926525B3DECB22D40E03FC7BD8D4235FD7E9DD2F3BFF3945D54C25E701624E27AFEF8F27F7DDEADEDAF3FE3AA0234D35290703FCE6254A7D75B6A304"
#define BN_P638_R		"23FFFFFDC000000D7FFFFFB8000001D3FFFFF942D000165E3FFF94870000D52FFFFDD0E00008DE55600086550021E555FFFFF54FFFF4EAC000000049800154D9FFFFFFFFFFFFEDA00000000000000061"
#define BN_P638_H		"1"
#define BN_P638_BETA	"47FFFFFCA000000D7FFFFFB8000001AFFFFFFCA480000D5BFFFFCA47FFFFFDBFFFFEE90000000018C000479CFFFFFFFFFFFFF9D0000000000000002E"
#define BN_P638_LAMB	"8FFFFFF94000001AFFFFFF700000035FFFFFF947E0001AC0FFFF947DFFFFFC0FFFFDCFC00000002580007D69FFFFFFFFFFFFF6A0000000000000003D"
#define BN_P638_MAPU	"-1"
/** @} */
#endif

#if defined(EP_ENDOM) && FP_PRIME == 638
/**
 * Parameters for a 638-bit pairing-friendly prime curve.
 */
/** @{ */
#define B12_P638_A		"0"
#define B12_P638_B		"4"
#define B12_P638_X		"160F63A3A3B297F113075ED79466138E85B025F7FE724B78E32D7AFC4D734BDD54F871092B8D1966D491C0F45A48A8BBA5586095DFFCC1410B7E26ED16BAF98C1117959134C24A17A7BE31E1AFBF844F"
#define B12_P638_Y		"2D340B33877480A9785E86ED2EDCAFC170B82568CB21B708B79FC6DA3748461FCD80697E486695F3CAE76FCB1781E784F6812F57BE05DFC850426650DED8B40A464B00A35718228EC8E02B52B59D876E"
#define B12_P638_R		"50F94035FF4000FFFFFFFFFFF9406BFDC0040000000000000035FB801DFFBFFFFFFFFFFFFFFF401BFF80000000000000000000FFC01"
#define B12_P638_H		"BFF8001555555555555555554D957EAAAAAAAAAAAAAAAAAAAABEB"
#define B12_P638_BETA	"1E5CD621BF4C01DFFDFFFFFFFCE57239EE275BF63000000000207C802254C4BE7FFFFFFFFFFF55FE959D1B8000000000000001BCCEB5801FFFFFFFFFFFFFFFFE2E801E"
#define B12_P638_LAMB	"50F94035FF4000FFFFFFFFFFF9406BFDC0040000000000000035F94035FF7FFFFFFFFFFFFFFF4033FF00000000000000000000FF801"
#define B12_P638_MAPU	"3"
/** @} */
#endif

#if defined(EP_SUPER) && FP_PRIME == 1536
/**
 * Parameters for a 1536-bit supersingular elliptic curve.
 */
/** @{ */
#define SS_P1536_A		"83093742908D4D529CEF06C72191A05D5E6073FE861E637D7747C5F154989D1DE125ACE7F997AD228B84EB0A0D0D719E34E83DBD68219BCE952167753C07B5DF0611625004D2959D9A5A42AB197DCF3FA8BB79D93C4F23D5437D6EA2C29D00A4D98BF0BD32E7FE4E8154DC52BCA7785F13D71C425551390B52972C085099A435EC00764313622A1C3A96FE4A97EF944DD3F62C726C5ABBBDF0B6C4E5D07763421DA034AE92B0EFFD8A8C98F08F182516C5159C215CDABF599329A51DD30571B0"
#define SS_P1536_B		"0"
#define SS_P1536_X		"3E230AF83F4F4D131622DFF03F35BD464BB9257B2BF87A6809AF0606DB21260C50BC5513DA44AB1E8B5333F2D164487E30DE6C39A1494831153E084A58A416BFA07009B16D12B883510E2DBE903E153FD64D75C02B1E33C93E3994BB8B3AD6810901518C3A0E9EA46F4D77DA416502ACD7A5E939EE25D3AE640AFB8AE5A650AF2748986C8C0DD9B755233F8AF25EC124711BE74F08FF3D01CED42493AAAF7E1D692A8339AD2A51F29B6E0D1B82A6648390CEC06811FA9F55FD337455BEC72A43"
#define SS_P1536_Y		"76F05A21A057DB46D591CED876EDCA9241A4A9618E13E091EE383BE3D8ECDA72C42449CB20CEA8C21B4A58B08F5871C6E101473933ABCD0BBB61C36F51BE5309138BA1040325EFE2D47B2216923BAC07BA64E6668C67D4647DA5916BF2305280A1BFFA1407ED68F0D28C2C2FC200BA7D1B7C5D71492CD39A2FC6BB7EF2D162B69984460A81D324DA69B0949DA2C7D0F79E39333EAF074F360243BAA824C762A039EBB3DEFF1ABDE3157482134BE93D73B4D8CB308C3ED0E72BA644DEFE22AAB9"
#define SS_P1536_R		"8000000000000000000000000000000000000000000000000000020000000001"
#define SS_P1536_H		"106126E85211A9AA539DE0D8E432340BABCC0E7FD0C3CC6FAEE8F87CA5F7725B54BBBE7DE38C3EBEE164AD00490346D95FD32BFC679AA8029708CEA26C981A77064FB3C8A6CDD411E36688D584793A96CAD10CE6351A0AC319F434764054488B5741CEF8BE9E019424732EB40A6EE109E4ADBD540FA43899E5484F37822EC07596F62045187571F182E85ACE872AE0376040E3510D06083B388463D1DD30571B4"
#define SS_P1536_MAPU	"1"
/** @} */
#endif

/**
 * Assigns a set of ordinary elliptic curve parameters.
 *
 * @param[in] CURVE		- the curve parameters to assign.
 * @param[in] FIELD		- the finite field identifier.
 */
#define ASSIGN(CURVE, FIELD)												\
	fp_param_set(FIELD);													\
	RLC_GET(str, CURVE##_A, sizeof(CURVE##_A));								\
	fp_read_str(a, str, strlen(str), 16);									\
	RLC_GET(str, CURVE##_B, sizeof(CURVE##_B));								\
	fp_read_str(b, str, strlen(str), 16);									\
	RLC_GET(str, CURVE##_X, sizeof(CURVE##_X));								\
	fp_read_str(g->x, str, strlen(str), 16);								\
	RLC_GET(str, CURVE##_Y, sizeof(CURVE##_Y));								\
	fp_read_str(g->y, str, strlen(str), 16);								\
	RLC_GET(str, CURVE##_R, sizeof(CURVE##_R));								\
	bn_read_str(r, str, strlen(str), 16);									\
	RLC_GET(str, CURVE##_H, sizeof(CURVE##_H));								\
	bn_read_str(h, str, strlen(str), 16);									\
	RLC_GET(str, CURVE##_MAPU, sizeof(CURVE##_MAPU));						\
	fp_read_str(u, str, strlen(str), 16);									\

/**
 * Assigns a set of parameters for an elliptic curve with endomorphisms.
 *
 * @param[in] CURVE		- the curve parameters to assign.
 * @param[in] FIELD		- the finite field identifier.
 */
#define ASSIGNK(CURVE, FIELD)												\
	ASSIGN(CURVE, FIELD);													\
	RLC_GET(str, CURVE##_BETA, sizeof(CURVE##_BETA));						\
	fp_read_str(beta, str, strlen(str), 16);								\
	RLC_GET(str, CURVE##_LAMB, sizeof(CURVE##_LAMB));						\
	bn_read_str(lamb, str, strlen(str), 16);								\

#if defined(EP_CTMAP)

/**
 * Assigns the isogeny map parameters for hashing with SSWU map.
 *
 * @param[in] CURVE		- the curve parameters to assign.
 */
#define ASSIGNM(CURVE)														\
    ep_param_set_ctmap(CURVE##_ISO_A, CURVE##_ISO_B, CURVE##_ISO_XN,		\
			CURVE##_ISO_XD, CURVE##_ISO_YN, CURVE##_ISO_YD)					\

#endif /* EP_CTMAP */

/*============================================================================*/
/* Private definitions                                                        */
/*============================================================================*/

#if defined(EP_CTMAP)

/**
 * Reads a sequence of polynomial coefficients from semicolon separated string.
 *
 * @param[out] coeffs 		- the resulting coefficients.
 * @param[in] str			- the string to parse.
 */
static int ep_param_get_coeffs(fp_st *coeffs, const char *str) {
	if (str[0] == '\0') {
		/* need nonzero strlen */
		RLC_THROW(ERR_NO_VALID);
	}
	int degree = 0;
	unsigned offset = 0;
	for (; degree < RLC_EP_CTMAP_MAX; ++degree) {
		const char *end = strchr(str + offset, ';');
		if (end == NULL) {
			/* last one */
			fp_read_str(coeffs[degree], str + offset, strlen(str + offset), 16);
			break;
		}
		unsigned len = end - str - offset;
		fp_read_str(coeffs[degree], str + offset, len, 16);
		offset += len + 1; /* move to after ';' */
	}
	if (degree == RLC_EP_CTMAP_MAX) {
		/* ran out of space before converting all coeffs */
		RLC_THROW(ERR_NO_VALID);
	}
	return degree;
}

/**
 * Configures a constant-time hash-to-curve function based on an isogeny map.
 *
 * @param[in] a_str				- the string representing the 'a' coefficient.
 * @param[in] b_str				- the string representing the 'b' coefficient.
 * @param[in] xn_str			- the string representing the x numerator coefficients.
 * @param[in] xd_str			- the string representing the x denominator coefficients.
 * @param[in] yn_str			- the string representing the y numerator coefficients.
 * @param[in] yd_str			- the string representing the y denominator coefficients.
 */
/* declaring this function inline suppresses unused function warnings */
static inline void ep_param_set_ctmap(const char *a_str, const char *b_str,
									  const char *xn_str, const char *xd_str,
									  const char *yn_str, const char *yd_str) {
	/* coefficients of isogenous curve */
	fp_read_str(ep_curve_get_iso()->a, a_str, strlen(a_str), 16);
	fp_read_str(ep_curve_get_iso()->b, b_str, strlen(b_str), 16);

	/* isogeny map coeffs */
	iso_t coeffs = ep_curve_get_iso();
	coeffs->deg_xn = ep_param_get_coeffs(coeffs->xn, xn_str);
	coeffs->deg_xd = ep_param_get_coeffs(coeffs->xd, xd_str);
	coeffs->deg_yn = ep_param_get_coeffs(coeffs->yn, yn_str);
	coeffs->deg_yd = ep_param_get_coeffs(coeffs->yd, yd_str);
}

#endif /* EP_CTMAP */

/*============================================================================*/
/* Public definitions                                                         */
/*============================================================================*/

int ep_param_get(void) {
	return core_get()->ep_id;
}

void ep_param_set(int param) {
	int plain = 0, endom = 0, super = 0, pairf = 0, ctmap = 0;
	char str[2 * RLC_FP_BYTES + 2];
	fp_t a, b, beta, u;
	ep_t g;
	bn_t r, h, lamb;

	fp_null(a);
	fp_null(b);
	fp_null(beta);
	fp_null(u);
	bn_null(lamb);
	ep_null(g);
	bn_null(r);
	bn_null(h);

	RLC_TRY {
		fp_new(a);
		fp_new(b);
		fp_new(beta);
		fp_new(u);
		bn_new(lamb);
		ep_new(g);
		bn_new(r);
		bn_new(h);

		core_get()->ep_id = 0;

		switch (param) {
#if defined(EP_ENDOM) && FP_PRIME == 158
			case BN_P158:
				ASSIGN(BN_P158, BN_158);
				endom = 1;
				pairf = EP_BN;
				break;
#endif
#if defined(EP_PLAIN) && FP_PRIME == 160
			case SECG_P160:
				ASSIGN(SECG_P160, SECG_160);
				plain = 1;
				break;
#endif
#if defined(EP_ENDOM) && FP_PRIME == 160
			case SECG_K160:
				ASSIGN(SECG_K160, SECG_160D);
				endom = 1;
				break;
#endif
#if defined(EP_PLAIN) && FP_PRIME == 192
			case NIST_P192:
				ASSIGN(NIST_P192, NIST_192);
				plain = 1;
				break;
#endif
#if defined(EP_ENDOM) && FP_PRIME == 192
			case SECG_K192:
				ASSIGN(SECG_K192, SECG_192);
				endom = 1;
				break;
#endif
#if defined(EP_PLAIN) && FP_PRIME == 221
			case CURVE_22103:
				ASSIGN(CURVE_22103, PRIME_22103);
				plain = 1;
				break;
#endif
#if defined(EP_PLAIN) && FP_PRIME == 224
			case NIST_P224:
				ASSIGN(NIST_P224, NIST_224);
				plain = 1;
				break;
#endif
#if defined(EP_ENDOM) && FP_PRIME == 224
			case SECG_K224:
				ASSIGN(SECG_K224, SECG_224);
				endom = 1;
				break;
#endif
#if defined(EP_PLAIN) && FP_PRIME == 226
			case CURVE_4417:
				ASSIGN(CURVE_4417, PRIME_22605);
				plain = 1;
				break;
#endif
#if defined(EP_ENDOM) && FP_PRIME == 254
			case BN_P254:
				ASSIGN(BN_P254, BN_254);
				endom = 1;
				pairf = EP_BN;
				break;
#endif
#if defined(EP_PLAIN) && FP_PRIME == 251
			case CURVE_1174:
				ASSIGN(CURVE_1174, PRIME_25109);
				plain = 1;
				break;
#endif
#if defined(EP_PLAIN) && FP_PRIME == 255
			case CURVE_25519:
				ASSIGN(CURVE_25519, PRIME_25519);
				plain = 1;
				break;
#endif
#if defined(EP_ENDOM) && FP_PRIME == 255
			case TWEEDLEDUM:
				ASSIGNK(TWEEDLEDUM, PRIME_H2ADC);
				endom = 1;
				break;
#endif
#if defined(EP_PLAIN) && FP_PRIME == 256
			case NIST_P256:
				ASSIGN(NIST_P256, NIST_256);
				plain = 1;
				break;
			case BSI_P256:
				ASSIGN(BSI_P256, BSI_256);
				plain = 1;
				break;
#endif
#if defined(EP_ENDOM) && FP_PRIME == 256
			case SECG_K256:
				ASSIGN(SECG_K256, SECG_256);
				endom = 1;
				break;
			case SM9_P256:
				ASSIGN(SM9_P256, SM9_256);
				endom = 1;
				pairf = EP_BN;
				break;
			case BN_P256:
				ASSIGN(BN_P256, BN_256);
				endom = 1;
				pairf = EP_BN;
				break;
#endif
#if defined(EP_PLAIN) & FP_PRIME == 382
			case CURVE_67254:
				ASSIGN(CURVE_67254, PRIME_382105);
				plain = 1;
				break;
#endif
#if defined(EP_ENDOM) & FP_PRIME == 381
			case B12_P381:
				ASSIGN(B12_P381, B12_381);
				endom = 1;
#if defined(EP_CTMAP)
				ASSIGNM(B12_P381);
				ctmap = 1;
#endif /* EP_CTMAP */
				pairf = EP_B12;
				break;
#endif
#if defined(EP_ENDOM) & FP_PRIME == 382
			case BN_P382:
				ASSIGN(BN_P382, BN_382);
				endom = 1;
				pairf = EP_BN;
				break;
#endif
#if defined(EP_PLAIN) && FP_PRIME == 383
			case CURVE_383187:
				ASSIGN(CURVE_383187, PRIME_383187);
				plain = 1;
				break;
#endif
#if defined(EP_ENDOM) && FP_PRIME == 383
			case B12_P383:
				ASSIGN(B12_P383, B12_383);
				endom = 1;
				pairf = EP_B12;
				break;
#endif
#if defined(EP_PLAIN) && FP_PRIME == 384
			case NIST_P384:
				ASSIGN(NIST_P384, NIST_384);
				plain = 1;
				break;
#endif
#if defined(EP_ENDOM) && FP_PRIME == 446
			case BN_P446:
				ASSIGN(BN_P446, BN_446);
				endom = 1;
				pairf = EP_BN;
				break;
			case B12_P446:
				ASSIGN(B12_P446, B12_446);
				endom = 1;
				pairf = EP_B12;
				break;
#endif
#if defined(EP_ENDOM) && FP_PRIME == 455
			case B12_P455:
				ASSIGN(B12_P455, B12_455);
				endom = 1;
				pairf = EP_B12;
				break;
#endif
#if defined(EP_ENDOM) && FP_PRIME == 508
			case KSS_P508:
				ASSIGNK(KSS_P508, KSS_508);
				endom = 1;
				break;
#endif
#if defined(EP_ENDOM) && FP_PRIME == 509
			case B24_P509:
				ASSIGN(B24_P509, B24_509);
				endom = 1;
				pairf = EP_B24;
				break;
#endif
#if defined(EP_ENDOM) && FP_PRIME == 511
			case OT8_P511:
				ASSIGNK(OT8_P511, OT_511);
				endom = 1;
				break;
#endif
#if defined(EP_PLAIN) && FP_PRIME == 511
			case CURVE_511187:
				ASSIGN(CURVE_511187, PRIME_511187);
				plain = 1;
				break;
#endif
#if defined(EP_PLAIN) && FP_PRIME == 521
			case NIST_P521:
				ASSIGN(NIST_P521, NIST_521);
				plain = 1;
				break;
#endif
#if defined(EP_ENDOM) && FP_PRIME == 544
			case GMT8_P544:
				ASSIGN(GMT8_P544, GMT8_544);
				endom = 1;
				break;
#endif
#if defined(EP_ENDOM) && FP_PRIME == 569
			case K54_P569:
				ASSIGN(K54_P569, K54_569);
				endom = 1;
				pairf = EP_K54;
				break;
#endif
#if defined(EP_ENDOM) && FP_PRIME == 575
			case B48_P575:
				ASSIGNK(B48_P575, B48_575);
				endom = 1;
				pairf = EP_B48;
				break;
#endif
#if defined(EP_ENDOM) && FP_PRIME == 638
			case BN_P638:
				ASSIGN(BN_P638, BN_638);
				endom = 1;
				pairf = EP_BN;
				break;
			case B12_P638:
				ASSIGN(B12_P638, B12_638);
				endom = 1;
				pairf = EP_B12;
				break;
#endif
#if defined(EP_SUPER) && FP_PRIME == 1536
			case SS_P1536:
				ASSIGN(SS_P1536, SS_1536);
				super = 1;
				break;
#endif
			default:
				(void)str;
				RLC_THROW(ERR_NO_VALID);
				break;
		}

#if defined(EP_ENDOM)
		if (endom) {
			switch(pairf) {
				/* beta = (-1+sqrt(-3))/2, lambda = 36*u^3 + 18*u^2 + 6*u + 1 */
				case EP_BN:
					fp_set_dig(beta, 3);
					fp_neg(beta, beta);
					fp_srt(beta, beta);
					fp_sub_dig(beta, beta, 1);
					fp_hlv(beta, beta);
					fp_prime_get_par(lamb);
					bn_sqr(lamb, lamb);
					bn_sqr(lamb, lamb);
					bn_mul_dig(lamb, lamb, 36);
					bn_sub(lamb, r, lamb);
					if (bn_sign(lamb) == RLC_NEG) {
						bn_neg(lamb, lamb);
						bn_sub_dig(lamb, lamb, 1);
					}
					break;
				/* beta = (-1 + sqrt(-3))/2, lambda = z^2 - 1 */
				case EP_B12:
					fp_set_dig(beta, 3);
					fp_neg(beta, beta);
					fp_srt(beta, beta);
					fp_sub_dig(beta, beta, 1);
					fp_hlv(beta, beta);
					fp_prime_get_par(lamb);
					bn_sqr(lamb, lamb);
					bn_sub_dig(lamb, lamb, 1);
					break;
				case EP_B24:
				/* beta = (-1 + sqrt(-3))/2, lambda = z^4 - 1. */
					fp_set_dig(beta, 3);
					fp_neg(beta, beta);
					fp_srt(beta, beta);
					fp_sub_dig(beta, beta, 1);
					fp_hlv(beta, beta);
					fp_prime_get_par(lamb);
				 	bn_sqr(lamb, lamb);
					bn_sqr(lamb, lamb);
					bn_sub_dig(lamb, lamb, 1);
					break;
				default:
					if (bn_cmp_dig(h, 1) == RLC_EQ) {
						/* SECG curves with endomorphisms. */
						fp_set_dig(beta, 2);
						h->used = RLC_FP_DIGS;
						dv_copy(h->dp, fp_prime_get(), RLC_FP_DIGS);
						/* Borrow h but restore at the end. */
						bn_sub_dig(h, h, 1);
						bn_div_dig(h, h, 3);
						fp_exp(beta, beta, h);
						bn_set_dig(lamb, 3);
						bn_sub_dig(h, r, 1);
						bn_div_dig(h, h, 3);
						bn_mxp(lamb, lamb, h, r);
						/* Try another primitive root. */
						if (bn_cmp_dig(lamb, 1) == RLC_EQ) {
							bn_set_dig(lamb, 2);
							bn_mxp(lamb, lamb, h, r);
						}
						bn_set_dig(h, 1);
					}
					break;
			}
		}
#endif /* EP_ENDOM */

		/* Do not generate warnings when these are disabled. */
		(void)endom;
		(void)plain;
		(void)super;
		(void)pairf;
		(void)beta;
		(void)ctmap;

		fp_set_dig(g->z, 1);
		g->coord = BASIC;

#if defined(EP_PLAIN)
		if (plain) {
			ep_curve_set_plain(a, b, g, r, h, u, ctmap);
			core_get()->ep_id = param;
		}
#endif

#if defined(EP_ENDOM)
		if (endom) {
			ep_curve_set_endom(a, b, g, r, h, beta, lamb, u, ctmap);
			core_get()->ep_id = param;
			core_get()->ep_is_pairf = pairf;
		}
#endif

#if defined(EP_SUPER)
		if (super) {
			ep_curve_set_super(a, b, g, r, h, u, ctmap);
			core_get()->ep_id = param;
		}
#endif
	}
	RLC_CATCH_ANY {
		RLC_THROW(ERR_CAUGHT);
	}
	RLC_FINALLY {
		fp_free(a);
		fp_free(b);
		fp_free(beta);
		fp_free(u);
		bn_free(lamb);
		ep_free(g);
		bn_free(r);
		bn_free(h);
	}
}

int ep_param_set_any(void) {
	int r = ep_param_set_any_plain();
	if (r == RLC_ERR) {
		r = ep_param_set_any_endom();
		if (r == RLC_ERR) {
			r = ep_param_set_any_pairf();
			if (r == RLC_ERR) {
				return RLC_ERR;
			}
		}
	}
	return RLC_OK;
}

int ep_param_set_any_plain(void) {
	int r = RLC_OK;
#if defined(EP_PLAIN)
#if FP_PRIME == 160
	ep_param_set(SECG_P160);
#elif FP_PRIME == 192
	ep_param_set(NIST_P192);
#elif FP_PRIME == 221
	ep_param_set(CURVE_22103);
#elif FP_PRIME == 224
	ep_param_set(NIST_P224);
#elif FP_PRIME == 226
	ep_param_set(CURVE_4417);
#elif FP_PRIME == 251
	ep_param_set(CURVE_1174);
#elif FP_PRIME == 255
	ep_param_set(CURVE_25519);
#elif FP_PRIME == 256
	ep_param_set(NIST_P256);
#elif FP_PRIME == 382
	ep_param_set(CURVE_67254);
#elif FP_PRIME == 383
	ep_param_set(CURVE_383187);
#elif FP_PRIME == 384
	ep_param_set(NIST_P384);
#elif FP_PRIME == 521
	ep_param_set(NIST_P521);
#else
	r = RLC_ERR;
#endif
#else
	r = RLC_ERR;
#endif
	return r;
}

int ep_param_set_any_endom(void) {
	int r = RLC_OK;
#if defined(EP_ENDOM)
#if FP_PRIME == 158
	ep_param_set(BN_P158);
#elif FP_PRIME == 160
	ep_param_set(SECG_K160);
#elif FP_PRIME == 192
	ep_param_set(SECG_K192);
#elif FP_PRIME == 224
	ep_param_set(SECG_K224);
#elif FP_PRIME == 254
	ep_param_set(BN_P254);
#elif FP_PRIME == 255
	ep_param_set(TWEEDLEDUM);
#elif FP_PRIME == 256
	ep_param_set(SECG_K256);
#elif FP_PRIME == 381
	ep_param_set(B12_P381);
#elif FP_PRIME == 382
	ep_param_set(BN_P382);
#elif FP_PRIME == 383
	ep_param_set(B12_P383);
#elif FP_PRIME == 446
#ifdef FP_QNRES
	ep_param_set(B12_P446);
#else
	ep_param_set(BN_P446);
#endif
#elif FP_PRIME == 455
	ep_param_set(B12_P455);
#elif FP_PRIME == 508
	ep_param_set(KSS_P508);
#elif FP_PRIME == 509
	ep_param_set(B24_P509);
#elif FP_PRIME == 511
	ep_param_set(OT8_P511);
#elif FP_PRIME == 544
	ep_param_set(GMT8_P544);
#elif FP_PRIME == 638
#ifdef FP_QNRES
	ep_param_set(B12_P638);
#else
	ep_param_set(BN_P638);
#endif
#else
	r = RLC_ERR;
#endif
#else
	r = RLC_ERR;
#endif
	return r;
}

int ep_param_set_any_super(void) {
	int r = RLC_OK;
#if defined(EP_SUPER)
#if FP_PRIME == 1536
	ep_param_set(SS_P1536);
#elif FP_PRIME == 3072
	ep_param_set(SS_P3072);
#else
	r = RLC_ERR;
#endif
#else
	r = RLC_ERR;
#endif
	return r;
}

int ep_param_set_any_pairf(void) {
	int type = 0, degree = 0, r = RLC_OK;
#if defined(EP_ENDOM)
#if FP_PRIME == 158
	ep_param_set(BN_P158);
	type = RLC_EP_DTYPE;
	degree = 2;
#elif FP_PRIME == 254
	ep_param_set(BN_P254);
	type = RLC_EP_DTYPE;
	degree = 2;
#elif FP_PRIME == 256
	ep_param_set(BN_P256);
	type = RLC_EP_DTYPE;
	degree = 2;
#elif FP_PRIME == 381
	ep_param_set(B12_P381);
	type = RLC_EP_MTYPE;
	degree = 2;
#elif FP_PRIME == 382
	ep_param_set(BN_P382);
	type = RLC_EP_DTYPE;
	degree = 2;
#elif FP_PRIME == 383
	ep_param_set(B12_P383);
	type = RLC_EP_MTYPE;
	degree = 2;
#elif FP_PRIME == 446
#ifdef FP_QNRES
	ep_param_set(B12_P446);
	type = RLC_EP_MTYPE;
	degree = 2;
#else
	ep_param_set(BN_P446);
	type = RLC_EP_DTYPE;
	degree = 2;
#endif
#elif FP_PRIME == 455
	ep_param_set(B12_P455);
	type = RLC_EP_DTYPE;
	degree = 2;
#elif FP_PRIME == 508
	ep_param_set(KSS_P508);
	type = RLC_EP_DTYPE;
	degree = 3;
#elif FP_PRIME == 509
	ep_param_set(B24_P509);
	type = RLC_EP_DTYPE;
	degree = 4;
#elif FP_PRIME == 511
	ep_param_set(OT8_P511);
	type = RLC_EP_DTYPE;
	degree = 2;
#elif FP_PRIME == 544
	ep_param_set(GMT8_P544);
	type = RLC_EP_MTYPE;
	degree = 2;
#elif FP_PRIME == 569
	ep_param_set(K54_P569);
	type = RLC_EP_MTYPE;
	degree = 9;
#elif FP_PRIME == 575
	ep_param_set(B48_P575);
	type = RLC_EP_MTYPE;
	degree = 8;
#elif FP_PRIME == 638
#ifdef FP_QNRES
	ep_param_set(B12_P638);
	type = RLC_EP_MTYPE;
	degree = 2;
#else
	ep_param_set(BN_P638);
	type = RLC_EP_DTYPE;
	degree = 2;
#endif
#elif FP_PRIME == 1536
	ep_param_set(SS_P1536);
	degree = 0;
#elif FP_PRIME == 3072
	ep_param_set(SS_P3072);
	degree = 0;
#else
	r = RLC_ERR;
#endif
#else
	r = RLC_ERR;
#endif
#ifdef WITH_PP
	if (r == RLC_OK) {
		switch (degree) {
			case 0:
				ep2_curve_set_twist(0);
				/* Compute pairing generator. */
				pc_core_calc();
				break;
			case 2:
				ep2_curve_set_twist(type);
				break;
			case 4:
				ep4_curve_set_twist(type);
				break;
		}
	}
#else
	(void)type;
	(void)degree;
#endif
	return r;
}

void ep_param_print(void) {
	switch (ep_param_get()) {
		case SECG_P160:
			util_banner("Curve SECG-P160:", 0);
			break;
		case SECG_K160:
			util_banner("Curve SECG-K160:", 0);
			break;
		case NIST_P192:
			util_banner("Curve NIST-P192:", 0);
			break;
		case SECG_K192:
			util_banner("Curve SECG-K192:", 0);
			break;
		case NIST_P224:
			util_banner("Curve NIST-P224:", 0);
			break;
		case SECG_K224:
			util_banner("Curve SECG-K224:", 0);
			break;
		case NIST_P256:
			util_banner("Curve NIST-P256:", 0);
			break;
		case BSI_P256:
			util_banner("Curve BSI-P256:", 0);
			break;
		case SECG_K256:
			util_banner("Curve SECG-K256:", 0);
			break;
		case NIST_P384:
			util_banner("Curve NIST-P384:", 0);
			break;
		case NIST_P521:
			util_banner("Curve NIST-P521:", 0);
			break;
		case BN_P158:
			util_banner("Curve BN-P158:", 0);
			break;
		case BN_P254:
			util_banner("Curve BN-P254:", 0);
			break;
		case TWEEDLEDUM:
			util_banner("Curve Tweedledum:", 0);
			break;
		case BN_P256:
			util_banner("Curve BN-P256:", 0);
			break;
		case SM9_P256:
			util_banner("Curve SM9-P256:", 0);
			break;
		case B12_P381:
			util_banner("Curve B12-P381:", 0);
			break;
		case BN_P382:
			util_banner("Curve BN-P382:", 0);
			break;
		case B12_P383:
			util_banner("Curve B12-P383:", 0);
			break;
		case GMT8_P544:
			util_banner("Curve GMT8-P544:", 0);
			break;
		case BN_P446:
			util_banner("Curve BN-P446:", 0);
			break;
		case B12_P446:
			util_banner("Curve B12-P446:", 0);
			break;
		case B12_P455:
			util_banner("Curve B12-P455:", 0);
			break;
		case KSS_P508:
			util_banner("Curve KSS-P508:", 0);
			break;
		case B24_P509:
			util_banner("Curve B24-P509:", 0);
			break;
		case OT8_P511:
			util_banner("Curve OT8-P511:", 0);
			break;
		case K54_P569:
			util_banner("Curve K54-P569:", 0);
			break;
		case B48_P575:
			util_banner("Curve B48-P575:", 0);
			break;
		case BN_P638:
			util_banner("Curve BN-P638:", 0);
			break;
		case B12_P638:
			util_banner("Curve B12-P638:", 0);
			break;
		case SS_P1536:
			util_banner("Curve SS-P1536:", 0);
			break;
		case SS_P3072:
			util_banner("Curve SS-3072:", 0);
			break;
		case CURVE_1174:
			util_banner("Curve Curve1174:", 0);
			break;
		case CURVE_25519:
			util_banner("Curve Curve25519:", 0);
			break;
		case CURVE_383187:
			util_banner("Curve Curve383187:", 0);
			break;
		case CURVE_511187:
			util_banner("Curve Curve511187:", 0);
			break;
	}
}

int ep_param_level(void) {
	switch (ep_param_get()) {
		case BN_P158:
			return 78;
		case SECG_P160:
		case SECG_K160:
			return 80;
		case NIST_P192:
		case SECG_K192:
			return 96;
		case NIST_P224:
		case SECG_K224:
			return 112;
		case BN_P254:
		case BN_P256:
		case SM9_P256:
			return 112;
		case NIST_P256:
		case SECG_K256:
		case CURVE_25519:
		case TWEEDLEDUM:
			return 128;
		case B12_P381:
		case BN_P382:
		case B12_P383:
		case BN_P446:
		case B12_P446:
		case GMT8_544:
		case SS_P1536:
			return 128;
		case B12_P455:
			return 140;
		case NIST_P384:
		case B24_P509:
			return 192;
		case NIST_P521:
			return 256;
		case BN_P638:
		case B12_P638:
			return 160;
	}
	return 0;
}

int ep_param_embed(void) {
	switch (ep_param_get()) {
		case SS_P1536:
			return 2;
		case OT8_P511:
		case GMT8_P544:
			return 8;
		case BN_P158:
		case BN_P254:
		case BN_P256:
		case SM9_P256:
		case BN_P382:
		case BN_P446:
		case B12_P446:
		case BN_P638:
		case B12_P381:
		case B12_P383:
		case B12_P455:
		case B12_P638:
			return 12;
		case B24_P509:
			return 24;
		case B48_P575:
			return 48;
		case K54_P569:
			return 54;
	}
	return 0;
}
