--- /dev/null
+#include "tlse.h"
+
+#define mp_init(a) ltc_mp.init(a)
+#define mp_init_multi ltc_init_multi
+#define mp_clear(a) ltc_mp.deinit(a)
+#define mp_clear_multi ltc_deinit_multi
+#define mp_count_bits(a) ltc_mp.count_bits(a)
+#define mp_read_radix(a, b, c) ltc_mp.read_radix(a, b, c)
+#define mp_unsigned_bin_size(a) ltc_mp.unsigned_size(a)
+#define mp_to_unsigned_bin(a, b) ltc_mp.unsigned_write(a, b)
+#define mp_read_unsigned_bin(a, b, c) ltc_mp.unsigned_read(a, b, c)
+#define mp_exptmod(a, b, c, d) ltc_mp.exptmod(a, b, c, d)
+#define mp_add(a, b, c) ltc_mp.add(a, b, c)
+#define mp_mul(a, b, c) ltc_mp.mul(a, b, c)
+#define mp_cmp(a, b) ltc_mp.compare(a, b)
+#define mp_cmp_d(a, b) ltc_mp.compare_d(a, b)
+#define mp_sqr(a, b) ltc_mp.sqr(a, b)
+#define mp_mod(a, b, c) ltc_mp.mpdiv(a, b, NULL, c)
+#define mp_sub(a, b, c) ltc_mp.sub(a, b, c)
+#define mp_set(a, b) ltc_mp.set_int(a, b)
+
+struct DHKey ffdhe2048 = {
+ 0x0100,
+ NULL,
+ NULL,
+ (void *)
+ "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF97D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD65612433F51F5F066ED0856365553DED1AF3B557135E7F57C935984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE73530ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FBB96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB190B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F619172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD733BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA886B423861285C97FFFFFFFFFFFFFFFF",
+ (void *)
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002"
+};
+
+struct DHKey ffdhe3072 = {
+ 0x0101,
+ NULL,
+ NULL,
+ (void *)
+ "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF97D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD65612433F51F5F066ED0856365553DED1AF3B557135E7F57C935984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE73530ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FBB96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB190B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F619172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD733BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C023861B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91CAEFE130985139270B4130C93BC437944F4FD4452E2D74DD364F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0DABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF3C1B20EE3FD59D7C25E41D2B66C62E37FFFFFFFFFFFFFFFF",
+ (void *)
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002"
+};
+
+struct DHKey ffdhe4096 = {
+ 0x0102,
+ NULL,
+ NULL,
+ (void *)
+ "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF97D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD65612433F51F5F066ED0856365553DED1AF3B557135E7F57C935984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE73530ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FBB96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB190B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F619172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD733BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C023861B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91CAEFE130985139270B4130C93BC437944F4FD4452E2D74DD364F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0DABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF3C1B20EE3FD59D7C25E41D2B669E1EF16E6F52C3164DF4FB7930E9E4E58857B6AC7D5F42D69F6D187763CF1D5503400487F55BA57E31CC7A7135C886EFB4318AED6A1E012D9E6832A907600A918130C46DC778F971AD0038092999A333CB8B7A1A1DB93D7140003C2A4ECEA9F98D0ACC0A8291CDCEC97DCF8EC9B55A7F88A46B4DB5A851F44182E1C68A007E5E655F6AFFFFFFFFFFFFFFFF",
+ (void *)
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002"
+};
+
+struct DHKey ffdhe6144 = {
+ 0x0103,
+ NULL,
+ NULL,
+ (void *)
+ "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF97D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD65612433F51F5F066ED0856365553DED1AF3B557135E7F57C935984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE73530ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FBB96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB190B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F619172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD733BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C023861B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91CAEFE130985139270B4130C93BC437944F4FD4452E2D74DD364F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0DABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF3C1B20EE3FD59D7C25E41D2B669E1EF16E6F52C3164DF4FB7930E9E4E58857B6AC7D5F42D69F6D187763CF1D5503400487F55BA57E31CC7A7135C886EFB4318AED6A1E012D9E6832A907600A918130C46DC778F971AD0038092999A333CB8B7A1A1DB93D7140003C2A4ECEA9F98D0ACC0A8291CDCEC97DCF8EC9B55A7F88A46B4DB5A851F44182E1C68A007E5E0DD9020BFD64B645036C7A4E677D2C38532A3A23BA4442CAF53EA63BB454329B7624C8917BDD64B1C0FD4CB38E8C334C701C3ACDAD0657FCCFEC719B1F5C3E4E46041F388147FB4CFDB477A52471F7A9A96910B855322EDB6340D8A00EF092350511E30ABEC1FFF9E3A26E7FB29F8C183023C3587E38DA0077D9B4763E4E4B94B2BBC194C6651E77CAF992EEAAC0232A281BF6B3A739C1226116820AE8DB5847A67CBEF9C9091B462D538CD72B03746AE77F5E62292C311562A846505DC82DB854338AE49F5235C95B91178CCF2DD5CACEF403EC9D1810C6272B045B3B71F9DC6B80D63FDD4A8E9ADB1E6962A69526D43161C1A41D570D7938DAD4A40E329CD0E40E65FFFFFFFFFFFFFFFF",
+ (void *)
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002"
+};
+
+struct DHKey ffdhe8192 = {
+ 0x0104,
+ NULL,
+ NULL,
+ (void *)
+ "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF97D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD65612433F51F5F066ED0856365553DED1AF3B557135E7F57C935984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE73530ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FBB96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB190B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F619172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD733BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C023861B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91CAEFE130985139270B4130C93BC437944F4FD4452E2D74DD364F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0DABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF3C1B20EE3FD59D7C25E41D2B669E1EF16E6F52C3164DF4FB7930E9E4E58857B6AC7D5F42D69F6D187763CF1D5503400487F55BA57E31CC7A7135C886EFB4318AED6A1E012D9E6832A907600A918130C46DC778F971AD0038092999A333CB8B7A1A1DB93D7140003C2A4ECEA9F98D0ACC0A8291CDCEC97DCF8EC9B55A7F88A46B4DB5A851F44182E1C68A007E5E0DD9020BFD64B645036C7A4E677D2C38532A3A23BA4442CAF53EA63BB454329B7624C8917BDD64B1C0FD4CB38E8C334C701C3ACDAD0657FCCFEC719B1F5C3E4E46041F388147FB4CFDB477A52471F7A9A96910B855322EDB6340D8A00EF092350511E30ABEC1FFF9E3A26E7FB29F8C183023C3587E38DA0077D9B4763E4E4B94B2BBC194C6651E77CAF992EEAAC0232A281BF6B3A739C1226116820AE8DB5847A67CBEF9C9091B462D538CD72B03746AE77F5E62292C311562A846505DC82DB854338AE49F5235C95B91178CCF2DD5CACEF403EC9D1810C6272B045B3B71F9DC6B80D63FDD4A8E9ADB1E6962A69526D43161C1A41D570D7938DAD4A40E329CCFF46AAA36AD004CF600C8381E425A31D951AE64FDB23FCEC9509D43687FEB69EDD1CC5E0B8CC3BDF64B10EF86B63142A3AB8829555B2F747C932665CB2C0F1CC01BD70229388839D2AF05E454504AC78B7582822846C0BA35C35F5C59160CC046FD8251541FC68C9C86B022BB7099876A460E7451A8A93109703FEE1C217E6C3826E52C51AA691E0E423CFC99E9E31650C1217B624816CDAD9A95F9D5B8019488D9C0A0A1FE3075A577E23183F81D4A3F2FA4571EFC8CE0BA8A4FE8B6855DFE72B0A66EDED2FBABFBE58A30FAFABE1C5D71A87E2F741EF8C1FE86FEA6BBFDE530677F0D97D11D49F7A8443D0822E506A9F4614E011E2A94838FF88CD68C8BB7C5C6424CFFFFFFFFFFFFFFFF",
+ (void *)
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002"
+};
+
+struct ECCCurveParameters secp192r1 = {
+ 24,
+ 19,
+ "secp192r1",
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", /* P */
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", /* A */
+ "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1", /* B */
+ "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012", /* Gx */
+ "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811", /* Gy */
+ "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831" /* order (n) */
+ , { 0 }
+};
+
+
+struct ECCCurveParameters secp224r1 = {
+ 28,
+ 21,
+ "secp224r1",
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", /* P */
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE", /* A */
+ "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", /* B */
+ "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21", /* Gx */
+ "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", /* Gy */
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D" /* order (n) */
+ , { 0 }
+};
+
+struct ECCCurveParameters secp224k1 = {
+ 28,
+ 20,
+ "secp224k1",
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D", /* P */
+ "00000000000000000000000000000000000000000000000000000000", /* A */
+ "00000000000000000000000000000000000000000000000000000005", /* B */
+ "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C", /* Gx */
+ "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5", /* Gy */
+ /* order (n) */
+ "0000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7",
+ { 0 }
+};
+
+struct ECCCurveParameters secp256r1 = {
+ 32,
+ 23,
+ "secp256r1",
+ "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", /* P */
+ "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", /* A */
+ "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", /* B */
+ "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", /* Gx */
+ "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", /* Gy */
+ "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
+ { 0 }
+};
+
+struct ECCCurveParameters secp256k1 = {
+ 32,
+ 22,
+ "secp256k1",
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", /* P */
+ "0000000000000000000000000000000000000000000000000000000000000000", /* A */
+ "0000000000000000000000000000000000000000000000000000000000000007", /* B */
+ "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", /* Gx */
+ "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", /* Gy */
+ /* order (n) */
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141",
+ { 0 }
+};
+
+struct ECCCurveParameters secp384r1 = {
+ 48,
+ 24,
+ "secp384r1",
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF",
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC",
+ "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF",
+ "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7",
+ "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F",
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
+ { 0 }
+};
+
+struct ECCCurveParameters secp521r1 = {
+ 66,
+ 25,
+ "secp521r1",
+ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
+ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC",
+ "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
+ "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",
+ "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650",
+ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
+ { 0 }
+
+};
+
+/* dummy */
+struct ECCCurveParameters curve25519 = {
+ 32,
+ 29,
+ "x25519",
+ "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED",
+ "0000000000000000000000000000000000000000000000000000000000076D06",
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "0000000000000000000000000000000000000000000000000000000000000009",
+ "20AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9",
+ "1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED",
+ { 0 }
+};
+
+struct ECCCurveParameters *const tls_ecc_default_curve = &secp256r1;
+
+static void init_curve(struct ECCCurveParameters *curve) {
+ curve->dp.size = curve->size;
+ curve->dp.name = (char *) curve->name;
+ curve->dp.B = (char *) curve->B;
+ curve->dp.prime = (char *) curve->P;
+ curve->dp.Gx = (char *) curve->Gx;
+ curve->dp.Gy = (char *) curve->Gy;
+ curve->dp.order = (char *) curve->order;
+}
+
+void tls_ecc_init_curves() {
+ init_curve(&secp192r1);
+ init_curve(&secp224r1);
+ init_curve(&secp224k1);
+ init_curve(&secp256r1);
+ init_curve(&secp256k1);
+ init_curve(&secp384r1);
+ init_curve(&secp521r1);
+}
+
+#if 1
+static int l_dh_shared_secret(struct DHKey *private_key, struct DHKey *public_key,
+ unsigned char *out,
+ unsigned long *outlen) {
+ void *tmp;
+ unsigned long x;
+ int err;
+
+ if ((!private_key) || (!public_key) || (!out) || (!outlen))
+ return TLS_GENERIC_ERROR;
+
+ /* compute y^x mod p */
+ if ((err = mp_init(&tmp)) != CRYPT_OK)
+ return err;
+
+ if ((err =
+ mp_exptmod(public_key->y, private_key->x, private_key->p,
+ tmp)) != CRYPT_OK) {
+ mp_clear(tmp);
+ return err;
+ }
+
+ x = (unsigned long) mp_unsigned_bin_size(tmp);
+ if (*outlen < x) {
+ err = CRYPT_BUFFER_OVERFLOW;
+ mp_clear(tmp);
+ return err;
+ }
+
+ if ((err = mp_to_unsigned_bin(tmp, out)) != CRYPT_OK) {
+ mp_clear(tmp);
+ return err;
+ }
+ *outlen = x;
+ mp_clear(tmp);
+ return 0;
+}
+#endif
+
+unsigned char *tls_decrypt_dhe(struct TLSContext *context, const unsigned char
+ *buffer, unsigned int len, unsigned int *size, int clear_key) {
+ *size = 0;
+ if ((!len) || (!context) || (!context->dhe)) {
+ DEBUG_PRINT("No private DHE key set\n");
+ return NULL;
+ }
+
+ unsigned long out_size = len;
+ void *Yc = NULL;
+
+ if (mp_init(&Yc)) {
+ DEBUG_PRINT("ERROR CREATING Yc\n");
+ return NULL;
+ }
+ if (mp_read_unsigned_bin(Yc, (unsigned char *) buffer, len)) {
+ DEBUG_PRINT("ERROR LOADING DHE Yc\n");
+ mp_clear(Yc);
+ return NULL;
+ }
+
+ unsigned char *out = malloc(len);
+ struct DHKey client_key;
+ memset(&client_key, 0, sizeof client_key);
+
+ client_key.p = context->dhe->p;
+ client_key.g = context->dhe->g;
+ client_key.y = Yc;
+
+ /* TODO use dh_shared_secret from tomcrypt */
+ int err = l_dh_shared_secret(context->dhe, &client_key, out, &out_size);
+ /* don't delete p and g */
+ client_key.p = NULL;
+ client_key.g = NULL;
+ tls_dh_clear_key(&client_key);
+ /* not needing the dhe key anymore */
+
+ if (clear_key) {
+ tls_dhe_free(context);
+ }
+
+ if (err) {
+ DEBUG_PRINT("DHE DECRYPT ERROR %i\n", err);
+ free(out);
+ return NULL;
+ }
+ DEBUG_PRINT("OUT_SIZE: %lu\n", out_size);
+ DEBUG_DUMP_HEX_LABEL("DHE", out, out_size);
+ *size = (unsigned int) out_size;
+ return out;
+}
+
+unsigned char *tls_decrypt_ecc_dhe(struct TLSContext *context, const unsigned
+ char *buffer, unsigned int len, unsigned int *size, int
+ clear_key) {
+ *size = 0;
+ if (!len || !context || !context->ecc_dhe) {
+ DEBUG_PRINT("No private ECC DHE key set\n");
+ return NULL;
+ }
+
+ const struct ECCCurveParameters *curve;
+ if (context->curve) {
+ curve = context->curve;
+ } else {
+ curve = tls_ecc_default_curve;
+ }
+
+ ltc_ecc_set_type *dp = (ltc_ecc_set_type *) & curve->dp;
+
+ ecc_key client_key;
+ memset(&client_key, 0, sizeof(client_key));
+ if (ecc_ansi_x963_import_ex(buffer, len, &client_key, dp)) {
+ DEBUG_PRINT("Error importing ECC DHE key\n");
+ return NULL;
+ }
+ unsigned char *out = malloc(len);
+ unsigned long out_size = len;
+
+ int err = ecc_shared_secret(context->ecc_dhe, &client_key, out,
+ &out_size);
+ ecc_free(&client_key);
+ if (clear_key) {
+ tls_ecc_dhe_free(context);
+ }
+ if (err) {
+ DEBUG_PRINT("ECC DHE DECRYPT ERROR %i\n", err);
+ free(out);
+ return NULL;
+ }
+ DEBUG_PRINT("OUT_SIZE: %lu\n", out_size);
+ DEBUG_DUMP_HEX_LABEL("ECC DHE", out, out_size);
+ *size = (unsigned int) out_size;
+ return out;
+}
+
+const struct ECCCurveParameters *tls_set_curve(struct TLSContext *context, const struct
+ ECCCurveParameters *curve) {
+ if (!context->is_server)
+ return NULL;
+ const struct ECCCurveParameters *old_curve = context->curve;
+ context->curve = curve;
+ return old_curve;
+}
+
+void tls_dhe_free(struct TLSContext *context) {
+ if (context->dhe) {
+ tls_dh_clear_key(context->dhe);
+ free(context->dhe);
+ context->dhe = NULL;
+ }
+}
+
+void tls_dhe_create(struct TLSContext *context) {
+ tls_dhe_free(context);
+ context->dhe = malloc(sizeof(struct DHKey));
+ if (context->dhe)
+ memset(context->dhe, 0, sizeof(struct DHKey));
+}
+
+void tls_ecc_dhe_free(struct TLSContext *context) {
+ if (context->ecc_dhe) {
+ ecc_free(context->ecc_dhe);
+ free(context->ecc_dhe);
+ context->ecc_dhe = NULL;
+ }
+}
+
+void tls_ecc_dhe_create(struct TLSContext *context) {
+ tls_ecc_dhe_free(context);
+ context->ecc_dhe = malloc(sizeof(ecc_key));
+ memset(context->ecc_dhe, 0, sizeof(ecc_key));
+}
+
+int tls_set_default_dhe_pg(struct TLSContext *context,
+ const char *p_hex_str, const char *g_hex_str) {
+ if (!context || context->is_child || !context->is_server || !p_hex_str
+ || !g_hex_str)
+ return 0;
+
+ free(context->default_dhe_p);
+ free(context->default_dhe_g);
+
+ context->default_dhe_p = NULL;
+ context->default_dhe_g = NULL;
+
+ int p_len = strlen(p_hex_str);
+ int g_len = strlen(g_hex_str);
+ if (p_len <= 0 || g_len <= 0) {
+ return 0;
+ }
+ context->default_dhe_p = malloc(p_len + 1);
+ if (!context->default_dhe_p) {
+ return 0;
+ }
+ context->default_dhe_g = malloc(g_len + 1);
+ if (!context->default_dhe_g) {
+ return 0;
+ }
+
+ memcpy(context->default_dhe_p, p_hex_str, p_len);
+ context->default_dhe_p[p_len] = 0;
+
+ memcpy(context->default_dhe_g, g_hex_str, g_len);
+ context->default_dhe_g[g_len] = 0;
+ return 1;
+}
+
+int tls_dh_export_Y(unsigned char *Ybuf, unsigned long *Ylen,
+ struct DHKey *key) {
+ unsigned long len;
+
+ if (Ybuf == NULL || Ylen == NULL || key == NULL) {
+ return TLS_GENERIC_ERROR;
+ }
+
+ len = mp_unsigned_bin_size(key->y);
+ if (len > *Ylen) {
+ return TLS_GENERIC_ERROR;
+ }
+
+ *Ylen = len;
+ return 0;
+}
+
+int tls_dh_export_pqY(unsigned char *pbuf, unsigned long *plen,
+ unsigned char *gbuf, unsigned long *glen,
+ unsigned char *Ybuf, unsigned long *Ylen,
+ struct DHKey *key) {
+ unsigned long len;
+ int err;
+
+ if (pbuf == NULL || plen == NULL || gbuf == NULL || glen == NULL ||
+ Ybuf == NULL || Ylen == NULL || key == NULL) {
+ return TLS_GENERIC_ERROR;
+ }
+
+ len = mp_unsigned_bin_size(key->y);
+ if (len > *Ylen) {
+ return TLS_GENERIC_ERROR;
+ }
+
+ if ((err = mp_to_unsigned_bin(key->y, Ybuf)) != CRYPT_OK) {
+ return err;
+ }
+
+ *Ylen = len;
+
+ len = mp_unsigned_bin_size(key->p);
+ if (len > *plen) {
+ return TLS_GENERIC_ERROR;
+ }
+
+ if ((err = mp_to_unsigned_bin(key->p, pbuf)) != CRYPT_OK) {
+ return err;
+ }
+
+ *plen = len;
+
+ len = mp_unsigned_bin_size(key->g);
+ if (len > *glen) {
+ return TLS_GENERIC_ERROR;
+ }
+
+ if ((err = mp_to_unsigned_bin(key->g, gbuf)) != CRYPT_OK)
+ return err;
+
+ *glen = len;
+
+ return 0;
+}
+
+void tls_dh_clear_key(struct DHKey *key) {
+ mp_clear_multi(key->g, key->p, key->x, key->y, NULL);
+ key->g = NULL;
+ key->p = NULL;
+ key->x = NULL;
+ key->y = NULL;
+}
+
+int tls_dh_make_key(int keysize, struct DHKey *key, const char *pbuf,
+ const char *gbuf, int pbuf_len, int gbuf_len)
+{
+ unsigned char *buf;
+ int err;
+ if (!key) {
+ return TLS_GENERIC_ERROR;
+ }
+
+ static prng_state prng;
+ int wprng = find_prng("sprng");
+ if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+ return err;
+ }
+
+ buf = malloc(keysize);
+ if (!buf) {
+ return TLS_NO_MEMORY;
+ }
+
+ if (rng_make_prng(keysize, wprng, &prng, NULL) != CRYPT_OK) {
+ free(buf);
+ return TLS_GENERIC_ERROR;
+ }
+
+ if (prng_descriptor[wprng].read(buf, keysize, &prng) != (unsigned long)
+ keysize) {
+ free(buf);
+ return TLS_GENERIC_ERROR;
+ }
+
+ if ((err = mp_init_multi(&key->g, &key->p, &key->x, &key->y, NULL)) !=
+ CRYPT_OK) {
+ free(buf);
+
+ return TLS_GENERIC_ERROR;
+ }
+
+ if (gbuf_len <= 0) {
+ if ((err = mp_read_radix(key->g, gbuf, 16)) != CRYPT_OK) {
+ free(buf);
+ tls_dh_clear_key(key);
+ return TLS_GENERIC_ERROR;
+ }
+ } else {
+ if ((err = mp_read_unsigned_bin(key->g, (unsigned char *) gbuf,
+ gbuf_len)) != CRYPT_OK) {
+ free(buf);
+ tls_dh_clear_key(key);
+ return TLS_GENERIC_ERROR;
+ }
+ }
+
+ if (pbuf_len <= 0) {
+ if ((err = mp_read_radix(key->p, pbuf, 16)) != CRYPT_OK) {
+ free(buf);
+ tls_dh_clear_key(key);
+ return TLS_GENERIC_ERROR;
+ }
+ } else {
+ if ((err = mp_read_unsigned_bin(key->p, (unsigned char *) pbuf,
+ pbuf_len)) != CRYPT_OK) {
+ free(buf);
+ tls_dh_clear_key(key);
+ return TLS_GENERIC_ERROR;
+ }
+ }
+
+ if ((err = mp_read_unsigned_bin(key->x, buf, keysize)) != CRYPT_OK) {
+ free(buf);
+ tls_dh_clear_key(key);
+ return TLS_GENERIC_ERROR;
+ }
+
+ if ((err = mp_exptmod(key->g, key->x, key->p, key->y)) != CRYPT_OK) {
+ free(buf);
+ tls_dh_clear_key(key);
+ return TLS_GENERIC_ERROR;
+ }
+
+ free(buf);
+ return 0;
+}