summaryrefslogtreecommitdiffhomepage
path: root/libtomcrypt/src/pk/ecc
diff options
context:
space:
mode:
authorMatt Johnston <matt@ucc.asn.au>2007-01-11 02:41:05 +0000
committerMatt Johnston <matt@ucc.asn.au>2007-01-11 02:41:05 +0000
commita938f4cfe140e8561d9dbf108b896492a662a893 (patch)
treef2a74322f959ff6a505ba5e87274ebe3d17d5e74 /libtomcrypt/src/pk/ecc
parent692d737a821c5e401c227d936b8f0d76b955650f (diff)
parent28ad393b008b34bc3cdbaa192440b8cc615329f0 (diff)
propagate from branch 'au.asn.ucc.matt.ltc.dropbear' (head 2af22fb4e878750b88f80f90d439b316d229796f)
to branch 'au.asn.ucc.matt.dropbear' (head 02c413252c90e9de8e03d91e9939dde3029f5c0a) --HG-- extra : convert_revision : 52ccb0ad0587a62bc64aecb939adbb76546aac16
Diffstat (limited to 'libtomcrypt/src/pk/ecc')
-rw-r--r--libtomcrypt/src/pk/ecc/ecc.c1055
-rw-r--r--libtomcrypt/src/pk/ecc/ecc_ansi_x963_export.c72
-rw-r--r--libtomcrypt/src/pk/ecc/ecc_ansi_x963_import.c104
-rw-r--r--libtomcrypt/src/pk/ecc/ecc_decrypt_key.c150
-rw-r--r--libtomcrypt/src/pk/ecc/ecc_encrypt_key.c136
-rw-r--r--libtomcrypt/src/pk/ecc/ecc_export.c82
-rw-r--r--libtomcrypt/src/pk/ecc/ecc_free.c40
-rw-r--r--libtomcrypt/src/pk/ecc/ecc_get_size.c44
-rw-r--r--libtomcrypt/src/pk/ecc/ecc_import.c172
-rw-r--r--libtomcrypt/src/pk/ecc/ecc_make_key.c125
-rw-r--r--libtomcrypt/src/pk/ecc/ecc_shared_secret.c95
-rw-r--r--libtomcrypt/src/pk/ecc/ecc_sign_hash.c114
-rw-r--r--libtomcrypt/src/pk/ecc/ecc_sizes.c48
-rw-r--r--libtomcrypt/src/pk/ecc/ecc_sys.c462
-rw-r--r--libtomcrypt/src/pk/ecc/ecc_test.c95
-rw-r--r--libtomcrypt/src/pk/ecc/ecc_verify_hash.c165
-rw-r--r--libtomcrypt/src/pk/ecc/ltc_ecc_is_valid_idx.c46
-rw-r--r--libtomcrypt/src/pk/ecc/ltc_ecc_map.c76
-rw-r--r--libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c207
-rw-r--r--libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c222
-rw-r--r--libtomcrypt/src/pk/ecc/ltc_ecc_mulmod_timing.c167
-rw-r--r--libtomcrypt/src/pk/ecc/ltc_ecc_points.c60
-rw-r--r--libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c196
-rw-r--r--libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c147
24 files changed, 2636 insertions, 1444 deletions
diff --git a/libtomcrypt/src/pk/ecc/ecc.c b/libtomcrypt/src/pk/ecc/ecc.c
index 469d56d..90bbed4 100644
--- a/libtomcrypt/src/pk/ecc/ecc.c
+++ b/libtomcrypt/src/pk/ecc/ecc.c
@@ -6,7 +6,7 @@
* The library is free for all purposes without any express
* guarantee it works.
*
- * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.org
+ * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
*/
/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
@@ -23,125 +23,94 @@
#ifdef MECC
-/* size of our temp buffers for exported keys */
-#define ECC_BUF_SIZE 256
-
-/* max private key size */
-#define ECC_MAXSIZE 66
-
/* This holds the key settings. ***MUST*** be organized by size from smallest to largest. */
-static const struct {
- int size;
- char *name, *prime, *B, *order, *Gx, *Gy;
-} sets[] = {
+const ltc_ecc_set_type ltc_ecc_sets[] = {
+#ifdef ECC112
+{
+ 14,
+ "SECP112R1",
+ "DB7C2ABF62E35E668076BEAD208B",
+ "659EF8BA043916EEDE8911702B22",
+ "DB7C2ABF62E35E7628DFAC6561C5",
+ "09487239995A5EE76B55F9C2F098",
+ "A89CE5AF8724C0A23E0E0FF77500"
+},
+#endif
+#ifdef ECC128
+{
+ 16,
+ "SECP128R1",
+ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF",
+ "E87579C11079F43DD824993C2CEE5ED3",
+ "FFFFFFFE0000000075A30D1B9038A115",
+ "161FF7528B899B2D0C28607CA52C5B86",
+ "CF5AC8395BAFEB13C02DA292DDED7A83",
+},
+#endif
+#ifdef ECC160
+{
+ 20,
+ "SECP160R1",
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF",
+ "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45",
+ "0100000000000000000001F4C8F927AED3CA752257",
+ "4A96B5688EF573284664698968C38BB913CBFC82",
+ "23A628553168947D59DCC912042351377AC5FB32",
+},
+#endif
#ifdef ECC192
{
- 24,
- "ECC-192",
- /* prime */
- "/////////////////////l//////////",
-
- /* B */
- "P2456UMSWESFf+chSYGmIVwutkp1Hhcn",
-
- /* order */
- "////////////////cTxuDXHhoR6qqYWn",
-
- /* Gx */
- "68se3h0maFPylo3hGw680FJ/2ls2/n0I",
-
- /* Gy */
- "1nahbV/8sdXZ417jQoJDrNFvTw4UUKWH"
+ 24,
+ "ECC-192",
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
+ "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1",
+ "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831",
+ "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012",
+ "7192B95FFC8DA78631011ED6B24CDD573F977A11E794811",
},
#endif
#ifdef ECC224
{
- 28,
- "ECC-224",
-
- /* prime */
- "3/////////////////////0000000000000001",
-
- /* B */
- "2q1Gg530Ipg/L1CbPGHB2trx/OkYSBEKCZLV+q",
-
- /* order */
- "3//////////////////nQYuBZmFXFTAKLSN2ez",
-
- /* Gx */
- "2t3WozQxI/Vp8JaBbA0y7JLi8H8ZGoWDOHN1qX",
-
-
- /* Gy */
- "2zDsE8jVSZ+qmYt+RDGtMWMWT7P4JLWPc507uq",
+ 28,
+ "ECC-224",
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001",
+ "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4",
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D",
+ "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21",
+ "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34",
},
#endif
#ifdef ECC256
{
- 32,
- "ECC-256",
- /* Prime */
- "F////y000010000000000000000////////////////",
-
- /* B */
- "5h6DTYgEfFdi+kzLNQOXhnb7GQmp5EmzZlEF3udqc1B",
-
- /* Order */
- "F////y00000//////////+yvlgjfnUUXFEvoiByOoLH",
-
- /* Gx */
- "6iNqVBXB497+BpcvMEaGF9t0ts1BUipeFIXEKNOcCAM",
-
- /* Gy */
- "4/ZGkB+6d+RZkVhIdmFdXOhpZDNQp5UpiksG6Wtlr7r"
+ 32,
+ "ECC-256",
+ "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
+ "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
+ "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
+ "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
+ "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
},
#endif
#ifdef ECC384
{
- 48,
- "ECC-384",
- /* prime */
- "//////////////////////////////////////////x/////00000000003/"
- "////",
-
- /* B */
- "ip4lf+8+v+IOZWLhu/Wj6HWTd6x+WK4I0nG8Zr0JXrh6LZcDYYxHdIg5oEtJ"
- "x2hl",
-
- /* Order */
- "////////////////////////////////nsDDWVGtBTzO6WsoIB2dUkpi6MhC"
- "nIbp",
-
- /* Gx and Gy */
- "geVA8hwB1JUEiSSUyo2jT6uTEsABfvkOMVT1u89KAZXL0l9TlrKfR3fKNZXo"
- "TWgt",
-
- "DXVUIfOcB6zTdfY/afBSAVZq7RqecXHywTen4xNmkC0AOB7E7Nw1dNf37NoG"
- "wWvV"
+ 48,
+ "ECC-384",
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF",
+ "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF",
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
+ "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7",
+ "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F",
},
#endif
#ifdef ECC521
{
- 65,
- "ECC-521",
- /* prime */
- "V///////////////////////////////////////////////////////////"
- "///////////////////////////",
-
- /* B */
- "56LFhbXZXoQ7vAQ8Q2sXK3kejfoMvcp5VEuj8cHZl49uLOPEL7iVfDx5bB0l"
- "JknlmSrSz+8FImqyUz57zHhK3y0",
-
- /* Order */
- "V//////////////////////////////////////////+b66XuE/BvPhVym1I"
- "FS9fT0xjScuYPn7hhjljnwHE6G9",
-
- /* Gx and Gy */
- "CQ5ZWQt10JfpPu+osOZbRH2d6I1EGK/jI7uAAzWQqqzkg5BNdVlvrae/Xt19"
- "wB/gDupIBF1XMf2c/b+VZ72vRrc",
-
- "HWvAMfucZl015oANxGiVHlPcFL4ILURH6WNhxqN9pvcB9VkSfbUz2P0nL2v0"
- "J+j1s4rF726edB2G8Y+b7QVqMPG",
+ 66,
+ "ECC-521",
+ "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
+ "51953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
+ "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
+ "C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",
+ "11839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650",
},
#endif
{
@@ -150,887 +119,9 @@ static const struct {
}
};
-static int is_valid_idx(int n)
-{
- int x;
-
- for (x = 0; sets[x].size != 0; x++);
- if ((n < 0) || (n >= x)) {
- return 0;
- }
- return 1;
-}
-
-static ecc_point *new_point(void)
-{
- ecc_point *p;
- p = XMALLOC(sizeof(ecc_point));
- if (p == NULL) {
- return NULL;
- }
- if (mp_init_multi(&p->x, &p->y, &p->z, NULL) != MP_OKAY) {
- XFREE(p);
- return NULL;
- }
- return p;
-}
-
-static void del_point(ecc_point *p)
-{
- /* prevents free'ing null arguments */
- if (p != NULL) {
- mp_clear_multi(&p->x, &p->y, &p->z, NULL);
- XFREE(p);
- }
-}
-
-static int ecc_map(ecc_point *P, mp_int *modulus, mp_digit mp)
-{
- mp_int t1, t2;
- int err;
-
- if ((err = mp_init_multi(&t1, &t2, NULL)) != CRYPT_OK) {
- return CRYPT_MEM;
- }
-
- /* first map z back to normal */
- if ((err = mp_montgomery_reduce(&P->z, modulus, mp)) != MP_OKAY) { goto error; }
-
- /* get 1/z */
- if ((err = mp_invmod(&P->z, modulus, &t1)) != MP_OKAY) { goto error; }
-
- /* get 1/z^2 and 1/z^3 */
- if ((err = mp_sqr(&t1, &t2)) != MP_OKAY) { goto error; }
- if ((err = mp_mod(&t2, modulus, &t2)) != MP_OKAY) { goto error; }
- if ((err = mp_mul(&t1, &t2, &t1)) != MP_OKAY) { goto error; }
- if ((err = mp_mod(&t1, modulus, &t1)) != MP_OKAY) { goto error; }
-
- /* multiply against x/y */
- if ((err = mp_mul(&P->x, &t2, &P->x)) != MP_OKAY) { goto error; }
- if ((err = mp_montgomery_reduce(&P->x, modulus, mp)) != MP_OKAY) { goto error; }
- if ((err = mp_mul(&P->y, &t1, &P->y)) != MP_OKAY) { goto error; }
- if ((err = mp_montgomery_reduce(&P->y, modulus, mp)) != MP_OKAY) { goto error; }
- mp_set(&P->z, 1);
-
- err = CRYPT_OK;
- goto done;
-error:
- err = mpi_to_ltc_error(err);
-done:
- mp_clear_multi(&t1, &t2, NULL);
- return err;
-
-}
-
-/* double a point R = 2P, R can be P*/
-static int dbl_point(ecc_point *P, ecc_point *R, mp_int *modulus, mp_digit mp)
-{
- mp_int t1, t2;
- int err;
-
- if ((err = mp_init_multi(&t1, &t2, NULL)) != MP_OKAY) {
- return mpi_to_ltc_error(err);
- }
-
- if ((err = mp_copy(&P->x, &R->x)) != MP_OKAY) { goto error; }
- if ((err = mp_copy(&P->y, &R->y)) != MP_OKAY) { goto error; }
- if ((err = mp_copy(&P->z, &R->z)) != MP_OKAY) { goto error; }
-
- /* t1 = Z * Z */
- if ((err = mp_sqr(&R->z, &t1)) != MP_OKAY) { goto error; }
- if ((err = mp_montgomery_reduce(&t1, modulus, mp)) != MP_OKAY) { goto error; }
- /* Z = Y * Z */
- if ((err = mp_mul(&R->z, &R->y, &R->z)) != MP_OKAY) { goto error; }
- if ((err = mp_montgomery_reduce(&R->z, modulus, mp)) != MP_OKAY) { goto error; }
- /* Z = 2Z */
- if ((err = mp_mul_2(&R->z, &R->z)) != MP_OKAY) { goto error; }
- if (mp_cmp(&R->z, modulus) != MP_LT) {
- if ((err = mp_sub(&R->z, modulus, &R->z)) != MP_OKAY) { goto error; }
- }
-
- /* T2 = X - T1 */
- if ((err = mp_sub(&R->x, &t1, &t2)) != MP_OKAY) { goto error; }
- if (mp_cmp_d(&t2, 0) == MP_LT) {
- if ((err = mp_add(&t2, modulus, &t2)) != MP_OKAY) { goto error; }
- }
- /* T1 = X + T1 */
- if ((err = mp_add(&t1, &R->x, &t1)) != MP_OKAY) { goto error; }
- if (mp_cmp(&t1, modulus) != MP_LT) {
- if ((err = mp_sub(&t1, modulus, &t1)) != MP_OKAY) { goto error; }
- }
- /* T2 = T1 * T2 */
- if ((err = mp_mul(&t1, &t2, &t2)) != MP_OKAY) { goto error; }
- if ((err = mp_montgomery_reduce(&t2, modulus, mp)) != MP_OKAY) { goto error; }
- /* T1 = 2T2 */
- if ((err = mp_mul_2(&t2, &t1)) != MP_OKAY) { goto error; }
- if (mp_cmp(&t1, modulus) != MP_LT) {
- if ((err = mp_sub(&t1, modulus, &t1)) != MP_OKAY) { goto error; }
- }
- /* T1 = T1 + T2 */
- if ((err = mp_add(&t1, &t2, &t1)) != MP_OKAY) { goto error; }
- if (mp_cmp(&t1, modulus) != MP_LT) {
- if ((err = mp_sub(&t1, modulus, &t1)) != MP_OKAY) { goto error; }
- }
-
- /* Y = 2Y */
- if ((err = mp_mul_2(&R->y, &R->y)) != MP_OKAY) { goto error; }
- if (mp_cmp(&R->y, modulus) != MP_LT) {
- if ((err = mp_sub(&R->y, modulus, &R->y)) != MP_OKAY) { goto error; }
- }
- /* Y = Y * Y */
- if ((err = mp_sqr(&R->y, &R->y)) != MP_OKAY) { goto error; }
- if ((err = mp_montgomery_reduce(&R->y, modulus, mp)) != MP_OKAY) { goto error; }
- /* T2 = Y * Y */
- if ((err = mp_sqr(&R->y, &t2)) != MP_OKAY) { goto error; }
- if ((err = mp_montgomery_reduce(&t2, modulus, mp)) != MP_OKAY) { goto error; }
- /* T2 = T2/2 */
- if (mp_isodd(&t2)) {
- if ((err = mp_add(&t2, modulus, &t2)) != MP_OKAY) { goto error; }
- }
- if ((err = mp_div_2(&t2, &t2)) != MP_OKAY) { goto error; }
- /* Y = Y * X */
- if ((err = mp_mul(&R->y, &R->x, &R->y)) != MP_OKAY) { goto error; }
- if ((err = mp_montgomery_reduce(&R->y, modulus, mp)) != MP_OKAY) { goto error; }
-
- /* X = T1 * T1 */
- if ((err = mp_sqr(&t1, &R->x)) != MP_OKAY) { goto error; }
- if ((err = mp_montgomery_reduce(&R->x, modulus, mp)) != MP_OKAY) { goto error; }
- /* X = X - Y */
- if ((err = mp_sub(&R->x, &R->y, &R->x)) != MP_OKAY) { goto error; }
- if (mp_cmp_d(&R->x, 0) == MP_LT) {
- if ((err = mp_add(&R->x, modulus, &R->x)) != MP_OKAY) { goto error; }
- }
- /* X = X - Y */
- if ((err = mp_sub(&R->x, &R->y, &R->x)) != MP_OKAY) { goto error; }
- if (mp_cmp_d(&R->x, 0) == MP_LT) {
- if ((err = mp_add(&R->x, modulus, &R->x)) != MP_OKAY) { goto error; }
- }
-
- /* Y = Y - X */
- if ((err = mp_sub(&R->y, &R->x, &R->y)) != MP_OKAY) { goto error; }
- if (mp_cmp_d(&R->y, 0) == MP_LT) {
- if ((err = mp_add(&R->y, modulus, &R->y)) != MP_OKAY) { goto error; }
- }
- /* Y = Y * T1 */
- if ((err = mp_mul(&R->y, &t1, &R->y)) != MP_OKAY) { goto error; }
- if ((err = mp_montgomery_reduce(&R->y, modulus, mp)) != MP_OKAY) { goto error; }
- /* Y = Y - T2 */
- if ((err = mp_sub(&R->y, &t2, &R->y)) != MP_OKAY) { goto error; }
- if (mp_cmp_d(&R->y, 0) == MP_LT) {
- if ((err = mp_add(&R->y, modulus, &R->y)) != MP_OKAY) { goto error; }
- }
-
- err = CRYPT_OK;
- goto done;
-error:
- err = mpi_to_ltc_error(err);
-done:
- mp_clear_multi(&t1, &t2, NULL);
- return err;
-}
-
-/* add two different points over Z/pZ, R = P + Q, note R can equal either P or Q */
-static int add_point(ecc_point *P, ecc_point *Q, ecc_point *R, mp_int *modulus, mp_digit mp)
-{
- mp_int t1, t2, x, y, z;
- int err;
-
- if ((err = mp_init_multi(&t1, &t2, &x, &y, &z, NULL)) != MP_OKAY) {
- return mpi_to_ltc_error(err);
- }
-
- if ((err = mp_copy(&P->x, &x)) != MP_OKAY) { goto error; }
- if ((err = mp_copy(&P->y, &y)) != MP_OKAY) { goto error; }
- if ((err = mp_copy(&P->z, &z)) != MP_OKAY) { goto error; }
-
- /* T1 = Z' * Z' */
- if ((err = mp_sqr(&Q->z, &t1)) != MP_OKAY) { goto error; }
- if ((err = mp_montgomery_reduce(&t1, modulus, mp)) != MP_OKAY) { goto error; }
- /* X = X * T1 */
- if ((err = mp_mul(&t1, &x, &x)) != MP_OKAY) { goto error; }
- if ((err = mp_montgomery_reduce(&x, modulus, mp)) != MP_OKAY) { goto error; }
- /* T1 = Z' * T1 */
- if ((err = mp_mul(&Q->z, &t1, &t1)) != MP_OKAY) { goto error; }
- if ((err = mp_montgomery_reduce(&t1, modulus, mp)) != MP_OKAY) { goto error; }
- /* Y = Y * T1 */
- if ((err = mp_mul(&t1, &y, &y)) != MP_OKAY) { goto error; }
- if ((err = mp_montgomery_reduce(&y, modulus, mp)) != MP_OKAY) { goto error; }
-
- /* T1 = Z*Z */
- if ((err = mp_sqr(&z, &t1)) != MP_OKAY) { goto error; }
- if ((err = mp_montgomery_reduce(&t1, modulus, mp)) != MP_OKAY) { goto error; }
- /* T2 = X' * T1 */
- if ((err = mp_mul(&Q->x, &t1, &t2)) != MP_OKAY) { goto error; }
- if ((err = mp_montgomery_reduce(&t2, modulus, mp)) != MP_OKAY) { goto error; }
- /* T1 = Z * T1 */
- if ((err = mp_mul(&z, &t1, &t1)) != MP_OKAY) { goto error; }
- if ((err = mp_montgomery_reduce(&t1, modulus, mp)) != MP_OKAY) { goto error; }
- /* T1 = Y' * T1 */
- if ((err = mp_mul(&Q->y, &t1, &t1)) != MP_OKAY) { goto error; }
- if ((err = mp_montgomery_reduce(&t1, modulus, mp)) != MP_OKAY) { goto error; }
-
- /* Y = Y - T1 */
- if ((err = mp_sub(&y, &t1, &y)) != MP_OKAY) { goto error; }
- if (mp_cmp_d(&y, 0) == MP_LT) {
- if ((err = mp_add(&y, modulus, &y)) != MP_OKAY) { goto error; }
- }
- /* T1 = 2T1 */
- if ((err = mp_mul_2(&t1, &t1)) != MP_OKAY) { goto error; }
- if (mp_cmp(&t1, modulus) != MP_LT) {
- if ((err = mp_sub(&t1, modulus, &t1)) != MP_OKAY) { goto error; }
- }
- /* T1 = Y + T1 */
- if ((err = mp_add(&t1, &y, &t1)) != MP_OKAY) { goto error; }
- if (mp_cmp(&t1, modulus) != MP_LT) {
- if ((err = mp_sub(&t1, modulus, &t1)) != MP_OKAY) { goto error; }
- }
- /* X = X - T2 */
- if ((err = mp_sub(&x, &t2, &x)) != MP_OKAY) { goto error; }
- if (mp_cmp_d(&x, 0) == MP_LT) {
- if ((err = mp_add(&x, modulus, &x)) != MP_OKAY) { goto error; }
- }
- /* T2 = 2T2 */
- if ((err = mp_mul_2(&t2, &t2)) != MP_OKAY) { goto error; }
- if (mp_cmp(&t2, modulus) != MP_LT) {
- if ((err = mp_sub(&t2, modulus, &t2)) != MP_OKAY) { goto error; }
- }
- /* T2 = X + T2 */
- if ((err = mp_add(&t2, &x, &t2)) != MP_OKAY) { goto error; }
- if (mp_cmp(&t2, modulus) != MP_LT) {
- if ((err = mp_sub(&t2, modulus, &t2)) != MP_OKAY) { goto error; }
- }
-
- /* if Z' != 1 */
- if (mp_cmp_d(&Q->z, 1) != MP_EQ) {
- /* Z = Z * Z' */
- if ((err = mp_mul(&z, &Q->z, &z)) != MP_OKAY) { goto error; }
- if ((err = mp_montgomery_reduce(&z, modulus, mp)) != MP_OKAY) { goto error; }
- }
- /* Z = Z * X */
- if ((err = mp_mul(&z, &x, &z)) != MP_OKAY) { goto error; }
- if ((err = mp_montgomery_reduce(&z, modulus, mp)) != MP_OKAY) { goto error; }
-
- /* T1 = T1 * X */
- if ((err = mp_mul(&t1, &x, &t1)) != MP_OKAY) { goto error; }
- if ((err = mp_montgomery_reduce(&t1, modulus, mp)) != MP_OKAY) { goto error; }
- /* X = X * X */
- if ((err = mp_sqr(&x, &x)) != MP_OKAY) { goto error; }
- if ((err = mp_montgomery_reduce(&x, modulus, mp)) != MP_OKAY) { goto error; }
- /* T2 = T2 * x */
- if ((err = mp_mul(&t2, &x, &t2)) != MP_OKAY) { goto error; }
- if ((err = mp_montgomery_reduce(&t2, modulus, mp)) != MP_OKAY) { goto error; }
- /* T1 = T1 * X */
- if ((err = mp_mul(&t1, &x, &t1)) != MP_OKAY) { goto error; }
- if ((err = mp_montgomery_reduce(&t1, modulus, mp)) != MP_OKAY) { goto error; }
-
- /* X = Y*Y */
- if ((err = mp_sqr(&y, &x)) != MP_OKAY) { goto error; }
- if ((err = mp_montgomery_reduce(&x, modulus, mp)) != MP_OKAY) { goto error; }
- /* X = X - T2 */
- if ((err = mp_sub(&x, &t2, &x)) != MP_OKAY) { goto error; }
- if (mp_cmp_d(&x, 0) == MP_LT) {
- if ((err = mp_add(&x, modulus, &x)) != MP_OKAY) { goto error; }
- }
-
- /* T2 = T2 - X */
- if ((err = mp_sub(&t2, &x, &t2)) != MP_OKAY) { goto error; }
- if (mp_cmp_d(&t2, 0) == MP_LT) {
- if ((err = mp_add(&t2, modulus, &t2)) != MP_OKAY) { goto error; }
- }
- /* T2 = T2 - X */
- if ((err = mp_sub(&t2, &x, &t2)) != MP_OKAY) { goto error; }
- if (mp_cmp_d(&t2, 0) == MP_LT) {
- if ((err = mp_add(&t2, modulus, &t2)) != MP_OKAY) { goto error; }
- }
- /* T2 = T2 * Y */
- if ((err = mp_mul(&t2, &y, &t2)) != MP_OKAY) { goto error; }
- if ((err = mp_montgomery_reduce(&t2, modulus, mp)) != MP_OKAY) { goto error; }
- /* Y = T2 - T1 */
- if ((err = mp_sub(&t2, &t1, &y)) != MP_OKAY) { goto error; }
- if (mp_cmp_d(&y, 0) == MP_LT) {
- if ((err = mp_add(&y, modulus, &y)) != MP_OKAY) { goto error; }
- }
- /* Y = Y/2 */
- if (mp_isodd(&y)) {
- if ((err = mp_add(&y, modulus, &y)) != MP_OKAY) { goto error; }
- }
- if ((err = mp_div_2(&y, &y)) != MP_OKAY) { goto error; }
-
- if ((err = mp_copy(&x, &R->x)) != MP_OKAY) { goto error; }
- if ((err = mp_copy(&y, &R->y)) != MP_OKAY) { goto error; }
- if ((err = mp_copy(&z, &R->z)) != MP_OKAY) { goto error; }
-
- err = CRYPT_OK;
- goto done;
-error:
- err = mpi_to_ltc_error(err);
-done:
- mp_clear_multi(&t1, &t2, &x, &y, &z, NULL);
- return err;
-}
-
-/* size of sliding window, don't change this! */
-#define WINSIZE 4
-
-/* perform R = kG where k == integer and G == ecc_point */
-static int ecc_mulmod(mp_int *k, ecc_point *G, ecc_point *R, mp_int *modulus, int map)
-{
- ecc_point *tG, *M[8];
- int i, j, err;
- mp_int mu;
- mp_digit buf, mp;
- int first, bitbuf, bitcpy, bitcnt, mode, digidx;
-
- /* init montgomery reduction */
- if ((err = mp_montgomery_setup(modulus, &mp)) != MP_OKAY) {
- return CRYPT_INVALID_ARG;
- }
- if ((err = mp_init(&mu)) != MP_OKAY) {
- return CRYPT_MEM;
- }
- if ((err = mp_montgomery_calc_normalization(&mu, modulus)) != MP_OKAY) {
- mp_clear(&mu);
- return CRYPT_INVALID_ARG;
- }
-
- /* alloc ram for window temps */
- for (i = 0; i < 8; i++) {
- M[i] = new_point();
- if (M[i] == NULL) {
- for (j = 0; j < i; j++) {
- del_point(M[j]);
- }
- mp_clear(&mu);
- return CRYPT_MEM;
- }
- }
-
- /* make a copy of G incase R==G */
- tG = new_point();
- if (tG == NULL) { err = CRYPT_MEM; goto done; }
-
- /* tG = G and convert to montgomery */
- if ((err = mp_mulmod(&G->x, &mu, modulus, &tG->x)) != MP_OKAY) { goto error; }
- if ((err = mp_mulmod(&G->y, &mu, modulus, &tG->y)) != MP_OKAY) { goto error; }
- if ((err = mp_mulmod(&G->z, &mu, modulus, &tG->z)) != MP_OKAY) { goto error; }
- mp_clear(&mu);
-
- /* calc the M tab, which holds kG for k==8..15 */
- /* M[0] == 8G */
- if ((err = dbl_point(tG, M[0], modulus, mp)) != CRYPT_OK) { goto done; }
- if ((err = dbl_point(M[0], M[0], modulus, mp)) != CRYPT_OK) { goto done; }
- if ((err = dbl_point(M[0], M[0], modulus, mp)) != CRYPT_OK) { goto done; }
-
- /* now find (8+k)G for k=1..7 */
- for (j = 9; j < 16; j++) {
- if ((err = add_point(M[j-9], tG, M[j-8], modulus, mp)) != CRYPT_OK) { goto done; }
- }
-
- /* setup sliding window */
- mode = 0;
- bitcnt = 1;
- buf = 0;
- digidx = k->used - 1;
- bitcpy = bitbuf = 0;
- first = 1;
-
- /* perform ops */
- for (;;) {
- /* grab next digit as required */
- if (--bitcnt == 0) {
- if (digidx == -1) {
- break;
- }
- buf = k->dp[digidx--];
- bitcnt = (int) DIGIT_BIT;
- }
-
- /* grab the next msb from the ltiplicand */
- i = (buf >> (DIGIT_BIT - 1)) & 1;
- buf <<= 1;
-
- /* skip leading zero bits */
- if (mode == 0 && i == 0) {
- continue;
- }
-
- /* if the bit is zero and mode == 1 then we double */
- if (mode == 1 && i == 0) {
- if ((err = dbl_point(R, R, modulus, mp)) != CRYPT_OK) { goto done; }
- continue;
- }
-
- /* else we add it to the window */
- bitbuf |= (i << (WINSIZE - ++bitcpy));
- mode = 2;
-
- if (bitcpy == WINSIZE) {
- /* if this is the first window we do a simple copy */
- if (first == 1) {
- /* R = kG [k = first window] */
- if ((err = mp_copy(&M[bitbuf-8]->x, &R->x)) != MP_OKAY) { goto error; }
- if ((err = mp_copy(&M[bitbuf-8]->y, &R->y)) != MP_OKAY) { goto error; }
- if ((err = mp_copy(&M[bitbuf-8]->z, &R->z)) != MP_OKAY) { goto error; }
- first = 0;
- } else {
- /* normal window */
- /* ok window is filled so double as required and add */
- /* double first */
- for (j = 0; j < WINSIZE; j++) {
- if ((err = dbl_point(R, R, modulus, mp)) != CRYPT_OK) { goto done; }
- }
-
- /* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranteed */
- if ((err = add_point(R, M[bitbuf-8], R, modulus, mp)) != CRYPT_OK) { goto done; }
- }
- /* empty window and reset */
- bitcpy = bitbuf = 0;
- mode = 1;
- }
- }
-
- /* if bits remain then double/add */
- if (mode == 2 && bitcpy > 0) {
- /* double then add */
- for (j = 0; j < bitcpy; j++) {
- /* only double if we have had at least one add first */
- if (first == 0) {
- if ((err = dbl_point(R, R, modulus, mp)) != CRYPT_OK) { goto done; }
- }
-
- bitbuf <<= 1;
- if ((bitbuf & (1 << WINSIZE)) != 0) {
- if (first == 1){
- /* first add, so copy */
- if ((err = mp_copy(&tG->x, &R->x)) != MP_OKAY) { goto error; }
- if ((err = mp_copy(&tG->y, &R->y)) != MP_OKAY) { goto error; }
- if ((err = mp_copy(&tG->z, &R->z)) != MP_OKAY) { goto error; }
- first = 0;
- } else {
- /* then add */
- if ((err = add_point(R, tG, R, modulus, mp)) != CRYPT_OK) { goto done; }
- }
- }
- }
- }
-
- /* map R back from projective space */
- if (map) {
- err = ecc_map(R, modulus, mp);
- } else {
- err = CRYPT_OK;
- }
-
- goto done;
-error:
- err = mpi_to_ltc_error(err);
-done:
- del_point(tG);
- for (i = 0; i < 8; i++) {
- del_point(M[i]);
- }
- return err;
-}
-
-#undef WINSIZE
-
-/**
- Perform on the ECC system
- @return CRYPT_OK if successful
-*/
-int ecc_test(void)
-{
- mp_int modulus, order;
- ecc_point *G, *GG;
- int i, err, primality;
-
- if ((err = mp_init_multi(&modulus, &order, NULL)) != MP_OKAY) {
- return mpi_to_ltc_error(err);
- }
-
- G = new_point();
- GG = new_point();
- if (G == NULL || GG == NULL) {
- mp_clear_multi(&modulus, &order, NULL);
- del_point(G);
- del_point(GG);
- return CRYPT_MEM;
- }
-
- for (i = 0; sets[i].size; i++) {
- #if 0
- printf("Testing %d\n", sets[i].size);
- #endif
- if ((err = mp_read_radix(&modulus, (char *)sets[i].prime, 64)) != MP_OKAY) { goto error; }
- if ((err = mp_read_radix(&order, (char *)sets[i].order, 64)) != MP_OKAY) { goto error; }
-
- /* is prime actually prime? */
- if ((err = is_prime(&modulus, &primality)) != CRYPT_OK) { goto done; }
- if (primality == 0) {
- err = CRYPT_FAIL_TESTVECTOR;
- goto done;
- }
-
- /* is order prime ? */
- if ((err = is_prime(&order, &primality)) != CRYPT_OK) { goto done; }
- if (primality == 0) {
- err = CRYPT_FAIL_TESTVECTOR;
- goto done;
- }
-
- if ((err = mp_read_radix(&G->x, (char *)sets[i].Gx, 64)) != MP_OKAY) { goto error; }
- if ((err = mp_read_radix(&G->y, (char *)sets[i].Gy, 64)) != MP_OKAY) { goto error; }
- mp_set(&G->z, 1);
-
- /* then we should have G == (order + 1)G */
- if ((err = mp_add_d(&order, 1, &order)) != MP_OKAY) { goto error; }
- if ((err = ecc_mulmod(&order, G, GG, &modulus, 1)) != CRYPT_OK) { goto done; }
- if (mp_cmp(&G->x, &GG->x) != 0 || mp_cmp(&G->y, &GG->y) != 0) {
- err = CRYPT_FAIL_TESTVECTOR;
- goto done;
- }
- }
- err = CRYPT_OK;
- goto done;
-error:
- err = mpi_to_ltc_error(err);
-done:
- del_point(GG);
- del_point(G);
- mp_clear_multi(&order, &modulus, NULL);
- return err;
-}
-
-void ecc_sizes(int *low, int *high)
-{
- int i;
- LTC_ARGCHK(low != NULL);
- LTC_ARGCHK(high != NULL);
-
- *low = INT_MAX;
- *high = 0;
- for (i = 0; sets[i].size != 0; i++) {
- if (sets[i].size < *low) {
- *low = sets[i].size;
- }
- if (sets[i].size > *high) {
- *high = sets[i].size;
- }
- }
-}
-
-/**
- Make a new ECC key
- @param prng An active PRNG state
- @param wprng The index of the PRNG you wish to use
- @param keysize The keysize for the new key (in octets from 20 to 65 bytes)
- @param key [out] Destination of the newly created key
- @return CRYPT_OK if successful, upon error all allocated memory will be freed
-*/
-int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key)
-{
- int x, err;
- ecc_point *base;
- mp_int prime;
- unsigned char *buf;
-
- LTC_ARGCHK(key != NULL);
-
- /* good prng? */
- if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
- return err;
- }
-
- /* find key size */
- for (x = 0; (keysize > sets[x].size) && (sets[x].size != 0); x++);
- keysize = sets[x].size;
-
- if (keysize > ECC_MAXSIZE || sets[x].size == 0) {
- return CRYPT_INVALID_KEYSIZE;
- }
- key->idx = x;
-
- /* allocate ram */
- base = NULL;
- buf = XMALLOC(ECC_MAXSIZE);
- if (buf == NULL) {
- return CRYPT_MEM;
- }
-
- /* make up random string */
- if (prng_descriptor[wprng].read(buf, (unsigned long)keysize, prng) != (unsigned long)keysize) {
- err = CRYPT_ERROR_READPRNG;
- goto LBL_ERR2;
- }
-
- /* setup the key variables */
- if ((err = mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, &prime, NULL)) != MP_OKAY) {
- err = mpi_to_ltc_error(err);
- goto LBL_ERR;
- }
- base = new_point();
- if (base == NULL) {
- mp_clear_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, &prime, NULL);
- err = CRYPT_MEM;
- goto LBL_ERR;
- }
-
- /* read in the specs for this key */
- if ((err = mp_read_radix(&prime, (char *)sets[key->idx].prime, 64)) != MP_OKAY) { goto error; }
- if ((err = mp_read_radix(&base->x, (char *)sets[key->idx].Gx, 64)) != MP_OKAY) { goto error; }
- if ((err = mp_read_radix(&base->y, (char *)sets[key->idx].Gy, 64)) != MP_OKAY) { goto error; }
- mp_set(&base->z, 1);
- if ((err = mp_read_unsigned_bin(&key->k, (unsigned char *)buf, keysize)) != MP_OKAY) { goto error; }
-
- /* make the public key */
- if ((err = ecc_mulmod(&key->k, base, &key->pubkey, &prime, 1)) != CRYPT_OK) { goto LBL_ERR; }
- key->type = PK_PRIVATE;
-
- /* shrink key */
- if ((err = mp_shrink(&key->k)) != MP_OKAY) { goto error; }
- if ((err = mp_shrink(&key->pubkey.x)) != MP_OKAY) { goto error; }
- if ((err = mp_shrink(&key->pubkey.y)) != MP_OKAY) { goto error; }
- if ((err = mp_shrink(&key->pubkey.z)) != MP_OKAY) { goto error; }
-
- /* free up ram */
- err = CRYPT_OK;
- goto LBL_ERR;
-error:
- err = mpi_to_ltc_error(err);
-LBL_ERR:
- del_point(base);
- mp_clear(&prime);
-LBL_ERR2:
-#ifdef LTC_CLEAN_STACK
- zeromem(buf, ECC_MAXSIZE);
-#endif
-
- XFREE(buf);
-
- return err;
-}
-
-/**
- Free an ECC key from memory
- @param key The key you wish to free
-*/
-void ecc_free(ecc_key *key)
-{
- LTC_ARGCHK(key != NULL);
- mp_clear_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL);
-}
-
-/**
- Export an ECC key as a binary packet
- @param out [out] Destination for the key
- @param outlen [in/out] Max size and resulting size of the exported key
- @param type The type of key you want to export (PK_PRIVATE or PK_PUBLIC)
- @param key The key to export
- @return CRYPT_OK if successful
-*/
-int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key)
-{
- int err;
- unsigned char flags[1];
- unsigned long key_size;
-
- LTC_ARGCHK(out != NULL);
- LTC_ARGCHK(outlen != NULL);
- LTC_ARGCHK(key != NULL);
-
- /* type valid? */
- if (key->type != PK_PRIVATE && type == PK_PRIVATE) {
- return CRYPT_PK_TYPE_MISMATCH;
- }
-
- if (is_valid_idx(key->idx) == 0) {
- return CRYPT_INVALID_ARG;
- }
-
- /* we store the NIST byte size */
- key_size = sets[key->idx].size;
-
- if (type == PK_PRIVATE) {
- flags[0] = 1;
- err = der_encode_sequence_multi(out, outlen,
- LTC_ASN1_BIT_STRING, 1UL, flags,
- LTC_ASN1_SHORT_INTEGER, 1UL, &key_size,
- LTC_ASN1_INTEGER, 1UL, &key->pubkey.x,
- LTC_ASN1_INTEGER, 1UL, &key->pubkey.y,
- LTC_ASN1_INTEGER, 1UL, &key->k,
- LTC_ASN1_EOL, 0UL, NULL);
- } else {
- flags[0] = 0;
- err = der_encode_sequence_multi(out, outlen,
- LTC_ASN1_BIT_STRING, 1UL, flags,
- LTC_ASN1_SHORT_INTEGER, 1UL, &key_size,
- LTC_ASN1_INTEGER, 1UL, &key->pubkey.x,
- LTC_ASN1_INTEGER, 1UL, &key->pubkey.y,
- LTC_ASN1_EOL, 0UL, NULL);
- }
-
- return err;
-}
-
-/**
- Import an ECC key from a binary packet
- @param in The packet to import
- @param inlen The length of the packet
- @param key [out] The destination of the import
- @return CRYPT_OK if successful, upon error all allocated memory will be freed
-*/
-int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key)
-{
- unsigned long key_size;
- unsigned char flags[1];
- int err;
-
- LTC_ARGCHK(in != NULL);
- LTC_ARGCHK(key != NULL);
-
- /* init key */
- if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL) != MP_OKAY) {
- return CRYPT_MEM;
- }
-
- /* find out what type of key it is */
- if ((err = der_decode_sequence_multi(in, inlen,
- LTC_ASN1_BIT_STRING, 1UL, &flags,
- LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
- goto error;
- }
-
-
- if (flags[0] == 1) {
- /* private key */
- key->type = PK_PRIVATE;
- if ((err = der_decode_sequence_multi(in, inlen,
- LTC_ASN1_BIT_STRING, 1UL, flags,
- LTC_ASN1_SHORT_INTEGER, 1UL, &key_size,
- LTC_ASN1_INTEGER, 1UL, &key->pubkey.x,
- LTC_ASN1_INTEGER, 1UL, &key->pubkey.y,
- LTC_ASN1_INTEGER, 1UL, &key->k,
- LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
- goto error;
- }
- } else {
- /* public key */
- /* private key */
- key->type = PK_PUBLIC;
- if ((err = der_decode_sequence_multi(in, inlen,
- LTC_ASN1_BIT_STRING, 1UL, flags,
- LTC_ASN1_SHORT_INTEGER, 1UL, &key_size,
- LTC_ASN1_INTEGER, 1UL, &key->pubkey.x,
- LTC_ASN1_INTEGER, 1UL, &key->pubkey.y,
- LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
- goto error;
- }
- }
-
- /* find the idx */
- for (key->idx = 0; sets[key->idx].size && (unsigned long)sets[key->idx].size != key_size; ++key->idx);
- if (sets[key->idx].size == 0) {
- err = CRYPT_INVALID_PACKET;
- goto error;
- }
-
- /* set z */
- mp_set(&key->pubkey.z, 1);
-
- /* we're good */
- return CRYPT_OK;
-error:
- mp_clear_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL);
- return err;
-}
-
-/**
- Create an ECC shared secret between two keys
- @param private_key The private ECC key
- @param public_key The public key
- @param out [out] Destination of the shared secret (Conforms to EC-DH from ANSI X9.63)
- @param outlen [in/out] The max size and resulting size of the shared secret
- @return CRYPT_OK if successful
-*/
-int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key,
- unsigned char *out, unsigned long *outlen)
-{
- unsigned long x;
- ecc_point *result;
- mp_int prime;
- int err;
-
- LTC_ARGCHK(private_key != NULL);
- LTC_ARGCHK(public_key != NULL);
- LTC_ARGCHK(out != NULL);
- LTC_ARGCHK(outlen != NULL);
-
- /* type valid? */
- if (private_key->type != PK_PRIVATE) {
- return CRYPT_PK_NOT_PRIVATE;
- }
-
- if (is_valid_idx(private_key->idx) == 0) {
- return CRYPT_INVALID_ARG;
- }
-
- if (private_key->idx != public_key->idx) {
- return CRYPT_PK_TYPE_MISMATCH;
- }
-
- /* make new point */
- result = new_point();
- if (result == NULL) {
- return CRYPT_MEM;
- }
-
- if ((err = mp_init(&prime)) != MP_OKAY) {
- del_point(result);
- return mpi_to_ltc_error(err);
- }
-
- if ((err = mp_read_radix(&prime, (char *)sets[private_key->idx].prime, 64)) != MP_OKAY) { goto error; }
- if ((err = ecc_mulmod(&private_key->k, &public_key->pubkey, result, &prime, 1)) != CRYPT_OK) { goto done1; }
-
- x = (unsigned long)mp_unsigned_bin_size(&prime);
- if (*outlen < x) {
- err = CRYPT_BUFFER_OVERFLOW;
- goto done1;
- }
- zeromem(out, x);
- if ((err = mp_to_unsigned_bin(&result->x, out + (x - mp_unsigned_bin_size(&result->x)))) != MP_OKAY) { goto error; }
-
- err = CRYPT_OK;
- *outlen = x;
- goto done1;
-error:
- err = mpi_to_ltc_error(err);
-done1:
- mp_clear(&prime);
- del_point(result);
- return err;
-}
-
-/**
- Get the size of an ECC key
- @param key The key to get the size of
- @return The size (octets) of the key or INT_MAX on error
-*/
-int ecc_get_size(ecc_key *key)
-{
- LTC_ARGCHK(key != NULL);
- if (is_valid_idx(key->idx))
- return sets[key->idx].size;
- else
- return INT_MAX; /* large value known to cause it to fail when passed to ecc_make_key() */
-}
-
-#include "ecc_sys.c"
-
#endif
-
-
/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc.c,v $ */
-/* $Revision: 1.20 $ */
-/* $Date: 2005/06/14 20:42:28 $ */
+/* $Revision: 1.38 $ */
+/* $Date: 2006/11/07 23:14:28 $ */
+
diff --git a/libtomcrypt/src/pk/ecc/ecc_ansi_x963_export.c b/libtomcrypt/src/pk/ecc/ecc_ansi_x963_export.c
new file mode 100644
index 0000000..2a32912
--- /dev/null
+++ b/libtomcrypt/src/pk/ecc/ecc_ansi_x963_export.c
@@ -0,0 +1,72 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "tomcrypt.h"
+
+/**
+ @file ecc_ansi_x963_export.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef MECC
+
+/** ECC X9.63 (Sec. 4.3.6) uncompressed export
+ @param key Key to export
+ @param out [out] destination of export
+ @param outlen [in/out] Length of destination and final output size
+ Return CRYPT_OK on success
+*/
+int ecc_ansi_x963_export(ecc_key *key, unsigned char *out, unsigned long *outlen)
+{
+ unsigned char buf[ECC_BUF_SIZE];
+ unsigned long numlen;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ if (ltc_ecc_is_valid_idx(key->idx) == 0) {
+ return CRYPT_INVALID_ARG;
+ }
+ numlen = key->dp->size;
+
+ if (*outlen < (1 + 2*numlen)) {
+ *outlen = 1 + 2*numlen;
+ return CRYPT_BUFFER_OVERFLOW;
+ }
+
+ /* store byte 0x04 */
+ out[0] = 0x04;
+
+ /* pad and store x */
+ zeromem(buf, sizeof(buf));
+ mp_to_unsigned_bin(key->pubkey.x, buf + (numlen - mp_unsigned_bin_size(key->pubkey.x)));
+ XMEMCPY(out+1, buf, numlen);
+
+ /* pad and store y */
+ zeromem(buf, sizeof(buf));
+ mp_to_unsigned_bin(key->pubkey.y, buf + (numlen - mp_unsigned_bin_size(key->pubkey.y)));
+ XMEMCPY(out+1+numlen, buf, numlen);
+
+ *outlen = 1 + 2*numlen;
+ return CRYPT_OK;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_ansi_x963_export.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/04 02:50:11 $ */
diff --git a/libtomcrypt/src/pk/ecc/ecc_ansi_x963_import.c b/libtomcrypt/src/pk/ecc/ecc_ansi_x963_import.c
new file mode 100644
index 0000000..e92f5f4
--- /dev/null
+++ b/libtomcrypt/src/pk/ecc/ecc_ansi_x963_import.c
@@ -0,0 +1,104 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "tomcrypt.h"
+
+/**
+ @file ecc_ansi_x963_import.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef MECC
+
+/** Import an ANSI X9.63 format public key
+ @param in The input data to read
+ @param inlen The length of the input data
+ @param key [out] destination to store imported key \
+*/
+int ecc_ansi_x963_import(const unsigned char *in, unsigned long inlen, ecc_key *key)
+{
+ return ecc_ansi_x963_import_ex(in, inlen, key, NULL);
+}
+
+int ecc_ansi_x963_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, ltc_ecc_set_type *dp)
+{
+ int x, err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* must be odd */
+ if ((inlen & 1) == 0) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* init key */
+ if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL) != CRYPT_OK) {
+ return CRYPT_MEM;
+ }
+
+ /* check for 4, 6 or 7 */
+ if (in[0] != 4 && in[0] != 6 && in[0] != 7) {
+ err = CRYPT_INVALID_PACKET;
+ goto error;
+ }
+
+ /* read data */
+ if ((err = mp_read_unsigned_bin(key->pubkey.x, (unsigned char *)in+1, (inlen-1)>>1)) != CRYPT_OK) {
+ goto error;
+ }
+
+ if ((err = mp_read_unsigned_bin(key->pubkey.y, (unsigned char *)in+1+((inlen-1)>>1), (inlen-1)>>1)) != CRYPT_OK) {
+ goto error;
+ }
+ if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) { goto error; }
+
+ if (dp == NULL) {
+ /* determine the idx */
+ for (x = 0; ltc_ecc_sets[x].size != 0; x++) {
+ if ((unsigned)ltc_ecc_sets[x].size >= ((inlen-1)>>1)) {
+ break;
+ }
+ }
+ if (ltc_ecc_sets[x].size == 0) {
+ err = CRYPT_INVALID_PACKET;
+ goto error;
+ }
+ /* set the idx */
+ key->idx = x;
+ key->dp = &ltc_ecc_sets[x];
+ } else {
+ if (((inlen-1)>>1) != (unsigned long) dp->size) {
+ err = CRYPT_INVALID_PACKET;
+ goto error;
+ }
+ key->idx = -1;
+ key->dp = dp;
+ }
+ key->type = PK_PUBLIC;
+
+ /* we're done */
+ return CRYPT_OK;
+error:
+ mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL);
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_ansi_x963_import.c,v $ */
+/* $Revision: 1.9 $ */
+/* $Date: 2006/12/04 22:17:46 $ */
diff --git a/libtomcrypt/src/pk/ecc/ecc_decrypt_key.c b/libtomcrypt/src/pk/ecc/ecc_decrypt_key.c
new file mode 100644
index 0000000..bb56208
--- /dev/null
+++ b/libtomcrypt/src/pk/ecc/ecc_decrypt_key.c
@@ -0,0 +1,150 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "tomcrypt.h"
+
+/**
+ @file ecc_decrypt_key.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef MECC
+
+/**
+ Decrypt an ECC encrypted key
+ @param in The ciphertext
+ @param inlen The length of the ciphertext (octets)
+ @param out [out] The plaintext
+ @param outlen [in/out] The max size and resulting size of the plaintext
+ @param key The corresponding private ECC key
+ @return CRYPT_OK if successful
+*/
+int ecc_decrypt_key(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ ecc_key *key)
+{
+ unsigned char *ecc_shared, *skey, *pub_expt;
+ unsigned long x, y, hashOID[32];
+ int hash, err;
+ ecc_key pubkey;
+ ltc_asn1_list decode[3];
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* right key type? */
+ if (key->type != PK_PRIVATE) {
+ return CRYPT_PK_NOT_PRIVATE;
+ }
+
+ /* decode to find out hash */
+ LTC_SET_ASN1(decode, 0, LTC_ASN1_OBJECT_IDENTIFIER, hashOID, sizeof(hashOID)/sizeof(hashOID[0]));
+
+ if ((err = der_decode_sequence(in, inlen, decode, 1)) != CRYPT_OK) {
+ return err;
+ }
+
+ hash = find_hash_oid(hashOID, decode[0].size);
+ if (hash_is_valid(hash) != CRYPT_OK) {
+ return CRYPT_INVALID_PACKET;
+ }
+
+ /* we now have the hash! */
+
+ /* allocate memory */
+ pub_expt = XMALLOC(ECC_BUF_SIZE);
+ ecc_shared = XMALLOC(ECC_BUF_SIZE);
+ skey = XMALLOC(MAXBLOCKSIZE);
+ if (pub_expt == NULL || ecc_shared == NULL || skey == NULL) {
+ if (pub_expt != NULL) {
+ XFREE(pub_expt);
+ }
+ if (ecc_shared != NULL) {
+ XFREE(ecc_shared);
+ }
+ if (skey != NULL) {
+ XFREE(skey);
+ }
+ return CRYPT_MEM;
+ }
+ LTC_SET_ASN1(decode, 1, LTC_ASN1_OCTET_STRING, pub_expt, ECC_BUF_SIZE);
+ LTC_SET_ASN1(decode, 2, LTC_ASN1_OCTET_STRING, skey, MAXBLOCKSIZE);
+
+ /* read the structure in now */
+ if ((err = der_decode_sequence(in, inlen, decode, 3)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* import ECC key from packet */
+ if ((err = ecc_import(decode[1].data, decode[1].size, &pubkey)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* make shared key */
+ x = ECC_BUF_SIZE;
+ if ((err = ecc_shared_secret(key, &pubkey, ecc_shared, &x)) != CRYPT_OK) {
+ ecc_free(&pubkey);
+ goto LBL_ERR;
+ }
+ ecc_free(&pubkey);
+
+ y = MIN(ECC_BUF_SIZE, MAXBLOCKSIZE);
+ if ((err = hash_memory(hash, ecc_shared, x, ecc_shared, &y)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* ensure the hash of the shared secret is at least as big as the encrypt itself */
+ if (decode[2].size > y) {
+ err = CRYPT_INVALID_PACKET;
+ goto LBL_ERR;
+ }
+
+ /* avoid buffer overflow */
+ if (*outlen < decode[2].size) {
+ *outlen = decode[2].size;
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto LBL_ERR;
+ }
+
+ /* Decrypt the key */
+ for (x = 0; x < decode[2].size; x++) {
+ out[x] = skey[x] ^ ecc_shared[x];
+ }
+ *outlen = x;
+
+ err = CRYPT_OK;
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ zeromem(pub_expt, ECC_BUF_SIZE);
+ zeromem(ecc_shared, ECC_BUF_SIZE);
+ zeromem(skey, MAXBLOCKSIZE);
+#endif
+
+ XFREE(pub_expt);
+ XFREE(ecc_shared);
+ XFREE(skey);
+
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_decrypt_key.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/06/16 21:53:41 $ */
+
diff --git a/libtomcrypt/src/pk/ecc/ecc_encrypt_key.c b/libtomcrypt/src/pk/ecc/ecc_encrypt_key.c
new file mode 100644
index 0000000..dd9bab0
--- /dev/null
+++ b/libtomcrypt/src/pk/ecc/ecc_encrypt_key.c
@@ -0,0 +1,136 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "tomcrypt.h"
+
+/**
+ @file ecc_encrypt_key.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef MECC
+
+/**
+ Encrypt a symmetric key with ECC
+ @param in The symmetric key you want to encrypt
+ @param inlen The length of the key to encrypt (octets)
+ @param out [out] The destination for the ciphertext
+ @param outlen [in/out] The max size and resulting size of the ciphertext
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG you wish to use
+ @param hash The index of the hash you want to use
+ @param key The ECC key you want to encrypt to
+ @return CRYPT_OK if successful
+*/
+int ecc_encrypt_key(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ prng_state *prng, int wprng, int hash,
+ ecc_key *key)
+{
+ unsigned char *pub_expt, *ecc_shared, *skey;
+ ecc_key pubkey;
+ unsigned long x, y, pubkeysize;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* check that wprng/cipher/hash are not invalid */
+ if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+ return err;
+ }
+
+ if ((err = hash_is_valid(hash)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (inlen > hash_descriptor[hash].hashsize) {
+ return CRYPT_INVALID_HASH;
+ }
+
+ /* make a random key and export the public copy */
+ if ((err = ecc_make_key_ex(prng, wprng, &pubkey, key->dp)) != CRYPT_OK) {
+ return err;
+ }
+
+ pub_expt = XMALLOC(ECC_BUF_SIZE);
+ ecc_shared = XMALLOC(ECC_BUF_SIZE);
+ skey = XMALLOC(MAXBLOCKSIZE);
+ if (pub_expt == NULL || ecc_shared == NULL || skey == NULL) {
+ if (pub_expt != NULL) {
+ XFREE(pub_expt);
+ }
+ if (ecc_shared != NULL) {
+ XFREE(ecc_shared);
+ }
+ if (skey != NULL) {
+ XFREE(skey);
+ }
+ ecc_free(&pubkey);
+ return CRYPT_MEM;
+ }
+
+ pubkeysize = ECC_BUF_SIZE;
+ if ((err = ecc_export(pub_expt, &pubkeysize, PK_PUBLIC, &pubkey)) != CRYPT_OK) {
+ ecc_free(&pubkey);
+ goto LBL_ERR;
+ }
+
+ /* make random key */
+ x = ECC_BUF_SIZE;
+ if ((err = ecc_shared_secret(&pubkey, key, ecc_shared, &x)) != CRYPT_OK) {
+ ecc_free(&pubkey);
+ goto LBL_ERR;
+ }
+ ecc_free(&pubkey);
+ y = MAXBLOCKSIZE;
+ if ((err = hash_memory(hash, ecc_shared, x, skey, &y)) != CRYPT_OK) {
+ goto LBL_ERR;
+ }
+
+ /* Encrypt key */
+ for (x = 0; x < inlen; x++) {
+ skey[x] ^= in[x];
+ }
+
+ err = der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_OBJECT_IDENTIFIER, hash_descriptor[hash].OIDlen, hash_descriptor[hash].OID,
+ LTC_ASN1_OCTET_STRING, pubkeysize, pub_expt,
+ LTC_ASN1_OCTET_STRING, inlen, skey,
+ LTC_ASN1_EOL, 0UL, NULL);
+
+LBL_ERR:
+#ifdef LTC_CLEAN_STACK
+ /* clean up */
+ zeromem(pub_expt, ECC_BUF_SIZE);
+ zeromem(ecc_shared, ECC_BUF_SIZE);
+ zeromem(skey, MAXBLOCKSIZE);
+#endif
+
+ XFREE(skey);
+ XFREE(ecc_shared);
+ XFREE(pub_expt);
+
+ return err;
+}
+
+#endif
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_encrypt_key.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/11/21 00:10:18 $ */
+
diff --git a/libtomcrypt/src/pk/ecc/ecc_export.c b/libtomcrypt/src/pk/ecc/ecc_export.c
new file mode 100644
index 0000000..1919849
--- /dev/null
+++ b/libtomcrypt/src/pk/ecc/ecc_export.c
@@ -0,0 +1,82 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "tomcrypt.h"
+
+/**
+ @file ecc_export.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef MECC
+
+/**
+ Export an ECC key as a binary packet
+ @param out [out] Destination for the key
+ @param outlen [in/out] Max size and resulting size of the exported key
+ @param type The type of key you want to export (PK_PRIVATE or PK_PUBLIC)
+ @param key The key to export
+ @return CRYPT_OK if successful
+*/
+int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key)
+{
+ int err;
+ unsigned char flags[1];
+ unsigned long key_size;
+
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* type valid? */
+ if (key->type != PK_PRIVATE && type == PK_PRIVATE) {
+ return CRYPT_PK_TYPE_MISMATCH;
+ }
+
+ if (ltc_ecc_is_valid_idx(key->idx) == 0) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* we store the NIST byte size */
+ key_size = key->dp->size;
+
+ if (type == PK_PRIVATE) {
+ flags[0] = 1;
+ err = der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_BIT_STRING, 1UL, flags,
+ LTC_ASN1_SHORT_INTEGER, 1UL, &key_size,
+ LTC_ASN1_INTEGER, 1UL, key->pubkey.x,
+ LTC_ASN1_INTEGER, 1UL, key->pubkey.y,
+ LTC_ASN1_INTEGER, 1UL, key->k,
+ LTC_ASN1_EOL, 0UL, NULL);
+ } else {
+ flags[0] = 0;
+ err = der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_BIT_STRING, 1UL, flags,
+ LTC_ASN1_SHORT_INTEGER, 1UL, &key_size,
+ LTC_ASN1_INTEGER, 1UL, key->pubkey.x,
+ LTC_ASN1_INTEGER, 1UL, key->pubkey.y,
+ LTC_ASN1_EOL, 0UL, NULL);
+ }
+
+ return err;
+}
+
+#endif
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_export.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/11/21 00:10:18 $ */
+
diff --git a/libtomcrypt/src/pk/ecc/ecc_free.c b/libtomcrypt/src/pk/ecc/ecc_free.c
new file mode 100644
index 0000000..039178d
--- /dev/null
+++ b/libtomcrypt/src/pk/ecc/ecc_free.c
@@ -0,0 +1,40 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "tomcrypt.h"
+
+/**
+ @file ecc_free.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef MECC
+
+/**
+ Free an ECC key from memory
+ @param key The key you wish to free
+*/
+void ecc_free(ecc_key *key)
+{
+ LTC_ARGCHKVD(key != NULL);
+ mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL);
+}
+
+#endif
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_free.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/06/09 01:38:14 $ */
+
diff --git a/libtomcrypt/src/pk/ecc/ecc_get_size.c b/libtomcrypt/src/pk/ecc/ecc_get_size.c
new file mode 100644
index 0000000..9eafdeb
--- /dev/null
+++ b/libtomcrypt/src/pk/ecc/ecc_get_size.c
@@ -0,0 +1,44 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "tomcrypt.h"
+
+/**
+ @file ecc_get_size.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef MECC
+
+/**
+ Get the size of an ECC key
+ @param key The key to get the size of
+ @return The size (octets) of the key or INT_MAX on error
+*/
+int ecc_get_size(ecc_key *key)
+{
+ LTC_ARGCHK(key != NULL);
+ if (ltc_ecc_is_valid_idx(key->idx))
+ return key->dp->size;
+ else
+ return INT_MAX; /* large value known to cause it to fail when passed to ecc_make_key() */
+}
+
+#endif
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_get_size.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/11/21 00:10:18 $ */
+
diff --git a/libtomcrypt/src/pk/ecc/ecc_import.c b/libtomcrypt/src/pk/ecc/ecc_import.c
new file mode 100644
index 0000000..4adb28e
--- /dev/null
+++ b/libtomcrypt/src/pk/ecc/ecc_import.c
@@ -0,0 +1,172 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "tomcrypt.h"
+
+/**
+ @file ecc_import.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef MECC
+
+static int is_point(ecc_key *key)
+{
+ void *prime, *b, *t1, *t2;
+ int err;
+
+ if ((err = mp_init_multi(&prime, &b, &t1, &t2, NULL)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* load prime and b */
+ if ((err = mp_read_radix(prime, key->dp->prime, 16)) != CRYPT_OK) { goto error; }
+ if ((err = mp_read_radix(b, key->dp->B, 16)) != CRYPT_OK) { goto error; }
+
+ /* compute y^2 */
+ if ((err = mp_sqr(key->pubkey.y, t1)) != CRYPT_OK) { goto error; }
+
+ /* compute x^3 */
+ if ((err = mp_sqr(key->pubkey.x, t2)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mod(t2, prime, t2)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mul(key->pubkey.x, t2, t2)) != CRYPT_OK) { goto error; }
+
+ /* compute y^2 - x^3 */
+ if ((err = mp_sub(t1, t2, t1)) != CRYPT_OK) { goto error; }
+
+ /* compute y^2 - x^3 + 3x */
+ if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) { goto error; }
+ if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) { goto error; }
+ if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) { goto error; }
+ if ((err = mp_mod(t1, prime, t1)) != CRYPT_OK) { goto error; }
+ while (mp_cmp_d(t1, 0) == LTC_MP_LT) {
+ if ((err = mp_add(t1, prime, t1)) != CRYPT_OK) { goto error; }
+ }
+ while (mp_cmp(t1, prime) != LTC_MP_LT) {
+ if ((err = mp_sub(t1, prime, t1)) != CRYPT_OK) { goto error; }
+ }
+
+ /* compare to b */
+ if (mp_cmp(t1, b) != LTC_MP_EQ) {
+ err = CRYPT_INVALID_PACKET;
+ } else {
+ err = CRYPT_OK;
+ }
+
+error:
+ mp_clear_multi(prime, b, t1, t2, NULL);
+ return err;
+}
+
+/**
+ Import an ECC key from a binary packet
+ @param in The packet to import
+ @param inlen The length of the packet
+ @param key [out] The destination of the import
+ @return CRYPT_OK if successful, upon error all allocated memory will be freed
+*/
+int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key)
+{
+ return ecc_import_ex(in, inlen, key, NULL);
+}
+
+/**
+ Import an ECC key from a binary packet, using user supplied domain params rather than one of the NIST ones
+ @param in The packet to import
+ @param inlen The length of the packet
+ @param key [out] The destination of the import
+ @param dp pointer to user supplied params; must be the same as the params used when exporting
+ @return CRYPT_OK if successful, upon error all allocated memory will be freed
+*/
+int ecc_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, const ltc_ecc_set_type *dp)
+{
+ unsigned long key_size;
+ unsigned char flags[1];
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(ltc_mp.name != NULL);
+
+ /* init key */
+ if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL) != CRYPT_OK) {
+ return CRYPT_MEM;
+ }
+
+ /* find out what type of key it is */
+ if ((err = der_decode_sequence_multi(in, inlen,
+ LTC_ASN1_BIT_STRING, 1UL, &flags,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ goto done;
+ }
+
+
+ if (flags[0] == 1) {
+ /* private key */
+ key->type = PK_PRIVATE;
+ if ((err = der_decode_sequence_multi(in, inlen,
+ LTC_ASN1_BIT_STRING, 1UL, flags,
+ LTC_ASN1_SHORT_INTEGER, 1UL, &key_size,
+ LTC_ASN1_INTEGER, 1UL, key->pubkey.x,
+ LTC_ASN1_INTEGER, 1UL, key->pubkey.y,
+ LTC_ASN1_INTEGER, 1UL, key->k,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ goto done;
+ }
+ } else {
+ /* public key */
+ key->type = PK_PUBLIC;
+ if ((err = der_decode_sequence_multi(in, inlen,
+ LTC_ASN1_BIT_STRING, 1UL, flags,
+ LTC_ASN1_SHORT_INTEGER, 1UL, &key_size,
+ LTC_ASN1_INTEGER, 1UL, key->pubkey.x,
+ LTC_ASN1_INTEGER, 1UL, key->pubkey.y,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ goto done;
+ }
+ }
+
+ if (dp == NULL) {
+ /* find the idx */
+ for (key->idx = 0; ltc_ecc_sets[key->idx].size && (unsigned long)ltc_ecc_sets[key->idx].size != key_size; ++key->idx);
+ if (ltc_ecc_sets[key->idx].size == 0) {
+ err = CRYPT_INVALID_PACKET;
+ goto done;
+ }
+ key->dp = &ltc_ecc_sets[key->idx];
+ } else {
+ key->idx = -1;
+ key->dp = dp;
+ }
+ /* set z */
+ if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) { goto done; }
+
+ /* is it a point on the curve? */
+ if ((err = is_point(key)) != CRYPT_OK) {
+ goto done;
+ }
+
+ /* we're good */
+ return CRYPT_OK;
+done:
+ mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL);
+ return err;
+}
+#endif
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_import.c,v $ */
+/* $Revision: 1.11 $ */
+/* $Date: 2006/12/04 02:19:48 $ */
+
diff --git a/libtomcrypt/src/pk/ecc/ecc_make_key.c b/libtomcrypt/src/pk/ecc/ecc_make_key.c
new file mode 100644
index 0000000..796b674
--- /dev/null
+++ b/libtomcrypt/src/pk/ecc/ecc_make_key.c
@@ -0,0 +1,125 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "tomcrypt.h"
+
+/**
+ @file ecc_make_key.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef MECC
+
+/**
+ Make a new ECC key
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG you wish to use
+ @param keysize The keysize for the new key (in octets from 20 to 65 bytes)
+ @param key [out] Destination of the newly created key
+ @return CRYPT_OK if successful, upon error all allocated memory will be freed
+*/
+int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key)
+{
+ int x, err;
+
+ /* find key size */
+ for (x = 0; (keysize > ltc_ecc_sets[x].size) && (ltc_ecc_sets[x].size != 0); x++);
+ keysize = ltc_ecc_sets[x].size;
+
+ if (keysize > ECC_MAXSIZE || ltc_ecc_sets[x].size == 0) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+ err = ecc_make_key_ex(prng, wprng, key, &ltc_ecc_sets[x]);
+ key->idx = x;
+ return err;
+}
+
+int ecc_make_key_ex(prng_state *prng, int wprng, ecc_key *key, const ltc_ecc_set_type *dp)
+{
+ int err;
+ ecc_point *base;
+ void *prime;
+ unsigned char *buf;
+ int keysize;
+
+ LTC_ARGCHK(key != NULL);
+ LTC_ARGCHK(ltc_mp.name != NULL);
+ LTC_ARGCHK(dp != NULL);
+
+ /* good prng? */
+ if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+ return err;
+ }
+
+ key->idx = -1;
+ key->dp = dp;
+ keysize = dp->size;
+
+ /* allocate ram */
+ base = NULL;
+ buf = XMALLOC(ECC_MAXSIZE);
+ if (buf == NULL) {
+ return CRYPT_MEM;
+ }
+
+ /* make up random string */
+ if (prng_descriptor[wprng].read(buf, (unsigned long)keysize, prng) != (unsigned long)keysize) {
+ err = CRYPT_ERROR_READPRNG;
+ goto ERR_BUF;
+ }
+
+ /* setup the key variables */
+ if ((err = mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, &prime, NULL)) != CRYPT_OK) {
+ goto ERR_BUF;
+ }
+ base = ltc_ecc_new_point();
+ if (base == NULL) {
+ err = CRYPT_MEM;
+ goto errkey;
+ }
+
+ /* read in the specs for this key */
+ if ((err = mp_read_radix(prime, (char *)key->dp->prime, 16)) != CRYPT_OK) { goto errkey; }
+ if ((err = mp_read_radix(base->x, (char *)key->dp->Gx, 16)) != CRYPT_OK) { goto errkey; }
+ if ((err = mp_read_radix(base->y, (char *)key->dp->Gy, 16)) != CRYPT_OK) { goto errkey; }
+ if ((err = mp_set(base->z, 1)) != CRYPT_OK) { goto errkey; }
+ if ((err = mp_read_unsigned_bin(key->k, (unsigned char *)buf, keysize)) != CRYPT_OK) { goto errkey; }
+
+ /* make the public key */
+ if ((err = ltc_mp.ecc_ptmul(key->k, base, &key->pubkey, prime, 1)) != CRYPT_OK) { goto errkey; }
+ key->type = PK_PRIVATE;
+
+ /* free up ram */
+ err = CRYPT_OK;
+ goto cleanup;
+errkey:
+ mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL);
+cleanup:
+ ltc_ecc_del_point(base);
+ mp_clear(prime);
+ERR_BUF:
+#ifdef LTC_CLEAN_STACK
+ zeromem(buf, ECC_MAXSIZE);
+#endif
+ XFREE(buf);
+ return err;
+}
+
+#endif
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_make_key.c,v $ */
+/* $Revision: 1.9 $ */
+/* $Date: 2006/12/04 02:50:11 $ */
+
diff --git a/libtomcrypt/src/pk/ecc/ecc_shared_secret.c b/libtomcrypt/src/pk/ecc/ecc_shared_secret.c
new file mode 100644
index 0000000..ddef847
--- /dev/null
+++ b/libtomcrypt/src/pk/ecc/ecc_shared_secret.c
@@ -0,0 +1,95 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "tomcrypt.h"
+
+/**
+ @file ecc_shared_secret.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef MECC
+
+/**
+ Create an ECC shared secret between two keys
+ @param private_key The private ECC key
+ @param public_key The public key
+ @param out [out] Destination of the shared secret (Conforms to EC-DH from ANSI X9.63)
+ @param outlen [in/out] The max size and resulting size of the shared secret
+ @return CRYPT_OK if successful
+*/
+int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key,
+ unsigned char *out, unsigned long *outlen)
+{
+ unsigned long x;
+ ecc_point *result;
+ void *prime;
+ int err;
+
+ LTC_ARGCHK(private_key != NULL);
+ LTC_ARGCHK(public_key != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ /* type valid? */
+ if (private_key->type != PK_PRIVATE) {
+ return CRYPT_PK_NOT_PRIVATE;
+ }
+
+ if (ltc_ecc_is_valid_idx(private_key->idx) == 0 || ltc_ecc_is_valid_idx(public_key->idx) == 0) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ if (XSTRCMP(private_key->dp->name, public_key->dp->name) != 0) {
+ return CRYPT_PK_TYPE_MISMATCH;
+ }
+
+ /* make new point */
+ result = ltc_ecc_new_point();
+ if (result == NULL) {
+ return CRYPT_MEM;
+ }
+
+ if ((err = mp_init(&prime)) != CRYPT_OK) {
+ ltc_ecc_del_point(result);
+ return err;
+ }
+
+ if ((err = mp_read_radix(prime, (char *)private_key->dp->prime, 16)) != CRYPT_OK) { goto done; }
+ if ((err = ltc_mp.ecc_ptmul(private_key->k, &public_key->pubkey, result, prime, 1)) != CRYPT_OK) { goto done; }
+
+ x = (unsigned long)mp_unsigned_bin_size(prime);
+ if (*outlen < x) {
+ *outlen = x;
+ err = CRYPT_BUFFER_OVERFLOW;
+ goto done;
+ }
+ zeromem(out, x);
+ if ((err = mp_to_unsigned_bin(result->x, out + (x - mp_unsigned_bin_size(result->x)))) != CRYPT_OK) { goto done; }
+
+ err = CRYPT_OK;
+ *outlen = x;
+done:
+ mp_clear(prime);
+ ltc_ecc_del_point(result);
+ return err;
+}
+
+#endif
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_shared_secret.c,v $ */
+/* $Revision: 1.8 $ */
+/* $Date: 2006/12/04 02:19:48 $ */
+
diff --git a/libtomcrypt/src/pk/ecc/ecc_sign_hash.c b/libtomcrypt/src/pk/ecc/ecc_sign_hash.c
new file mode 100644
index 0000000..44f949e
--- /dev/null
+++ b/libtomcrypt/src/pk/ecc/ecc_sign_hash.c
@@ -0,0 +1,114 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "tomcrypt.h"
+
+/**
+ @file ecc_sign_hash.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef MECC
+
+/**
+ Sign a message digest
+ @param in The message digest to sign
+ @param inlen The length of the digest
+ @param out [out] The destination for the signature
+ @param outlen [in/out] The max size and resulting size of the signature
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG you wish to use
+ @param key A private ECC key
+ @return CRYPT_OK if successful
+*/
+int ecc_sign_hash(const unsigned char *in, unsigned long inlen,
+ unsigned char *out, unsigned long *outlen,
+ prng_state *prng, int wprng, ecc_key *key)
+{
+ ecc_key pubkey;
+ void *r, *s, *e, *p;
+ int err;
+
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* is this a private key? */
+ if (key->type != PK_PRIVATE) {
+ return CRYPT_PK_NOT_PRIVATE;
+ }
+
+ /* is the IDX valid ? */
+ if (ltc_ecc_is_valid_idx(key->idx) != 1) {
+ return CRYPT_PK_INVALID_TYPE;
+ }
+
+ if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* get the hash and load it as a bignum into 'e' */
+ /* init the bignums */
+ if ((err = mp_init_multi(&r, &s, &p, &e, NULL)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = mp_read_radix(p, (char *)key->dp->order, 16)) != CRYPT_OK) { goto errnokey; }
+ if ((err = mp_read_unsigned_bin(e, (unsigned char *)in, (int)inlen)) != CRYPT_OK) { goto errnokey; }
+
+ /* make up a key and export the public copy */
+ for (;;) {
+ if ((err = ecc_make_key_ex(prng, wprng, &pubkey, key->dp)) != CRYPT_OK) {
+ goto errnokey;
+ }
+
+ /* find r = x1 mod n */
+ if ((err = mp_mod(pubkey.pubkey.x, p, r)) != CRYPT_OK) { goto error; }
+
+ if (mp_iszero(r) == LTC_MP_YES) {
+ ecc_free(&pubkey);
+ } else {
+ /* find s = (e + xr)/k */
+ if ((err = mp_invmod(pubkey.k, p, pubkey.k)) != CRYPT_OK) { goto error; } /* k = 1/k */
+ if ((err = mp_mulmod(key->k, r, p, s)) != CRYPT_OK) { goto error; } /* s = xr */
+ if ((err = mp_add(e, s, s)) != CRYPT_OK) { goto error; } /* s = e + xr */
+ if ((err = mp_mod(s, p, s)) != CRYPT_OK) { goto error; } /* s = e + xr */
+ if ((err = mp_mulmod(s, pubkey.k, p, s)) != CRYPT_OK) { goto error; } /* s = (e + xr)/k */
+ ecc_free(&pubkey);
+ if (mp_iszero(s) == LTC_MP_NO) {
+ break;
+ }
+ }
+ }
+
+ /* store as SEQUENCE { r, s -- integer } */
+ err = der_encode_sequence_multi(out, outlen,
+ LTC_ASN1_INTEGER, 1UL, r,
+ LTC_ASN1_INTEGER, 1UL, s,
+ LTC_ASN1_EOL, 0UL, NULL);
+ goto errnokey;
+error:
+ ecc_free(&pubkey);
+errnokey:
+ mp_clear_multi(r, s, p, e, NULL);
+ return err;
+}
+
+#endif
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_sign_hash.c,v $ */
+/* $Revision: 1.9 $ */
+/* $Date: 2006/12/04 02:50:11 $ */
+
diff --git a/libtomcrypt/src/pk/ecc/ecc_sizes.c b/libtomcrypt/src/pk/ecc/ecc_sizes.c
new file mode 100644
index 0000000..f4b2d82
--- /dev/null
+++ b/libtomcrypt/src/pk/ecc/ecc_sizes.c
@@ -0,0 +1,48 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "tomcrypt.h"
+
+/**
+ @file ecc_sizes.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef MECC
+
+void ecc_sizes(int *low, int *high)
+{
+ int i;
+ LTC_ARGCHKVD(low != NULL);
+ LTC_ARGCHKVD(high != NULL);
+
+ *low = INT_MAX;
+ *high = 0;
+ for (i = 0; ltc_ecc_sets[i].size != 0; i++) {
+ if (ltc_ecc_sets[i].size < *low) {
+ *low = ltc_ecc_sets[i].size;
+ }
+ if (ltc_ecc_sets[i].size > *high) {
+ *high = ltc_ecc_sets[i].size;
+ }
+ }
+}
+
+#endif
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_sizes.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/06/09 01:38:14 $ */
+
diff --git a/libtomcrypt/src/pk/ecc/ecc_sys.c b/libtomcrypt/src/pk/ecc/ecc_sys.c
deleted file mode 100644
index 65ead31..0000000
--- a/libtomcrypt/src/pk/ecc/ecc_sys.c
+++ /dev/null
@@ -1,462 +0,0 @@
-/* LibTomCrypt, modular cryptographic library -- Tom St Denis
- *
- * LibTomCrypt is a library that provides various cryptographic
- * algorithms in a highly modular and flexible manner.
- *
- * The library is free for all purposes without any express
- * guarantee it works.
- *
- * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.org
- */
-
-/**
- @file ecc_sys.c
- ECC Crypto, Tom St Denis
-*/
-
-/**
- Encrypt a symmetric key with ECC
- @param in The symmetric key you want to encrypt
- @param inlen The length of the key to encrypt (octets)
- @param out [out] The destination for the ciphertext
- @param outlen [in/out] The max size and resulting size of the ciphertext
- @param prng An active PRNG state
- @param wprng The index of the PRNG you wish to use
- @param hash The index of the hash you want to use
- @param key The ECC key you want to encrypt to
- @return CRYPT_OK if successful
-*/
-int ecc_encrypt_key(const unsigned char *in, unsigned long inlen,
- unsigned char *out, unsigned long *outlen,
- prng_state *prng, int wprng, int hash,
- ecc_key *key)
-{
- unsigned char *pub_expt, *ecc_shared, *skey;
- ecc_key pubkey;
- unsigned long x, y, pubkeysize;
- int err;
-
- LTC_ARGCHK(in != NULL);
- LTC_ARGCHK(out != NULL);
- LTC_ARGCHK(outlen != NULL);
- LTC_ARGCHK(key != NULL);
-
- /* check that wprng/cipher/hash are not invalid */
- if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
- return err;
- }
-
- if ((err = hash_is_valid(hash)) != CRYPT_OK) {
- return err;
- }
-
- if (inlen > hash_descriptor[hash].hashsize) {
- return CRYPT_INVALID_HASH;
- }
-
- /* make a random key and export the public copy */
- if ((err = ecc_make_key(prng, wprng, ecc_get_size(key), &pubkey)) != CRYPT_OK) {
- return err;
- }
-
- pub_expt = XMALLOC(ECC_BUF_SIZE);
- ecc_shared = XMALLOC(ECC_BUF_SIZE);
- skey = XMALLOC(MAXBLOCKSIZE);
- if (pub_expt == NULL || ecc_shared == NULL || skey == NULL) {
- if (pub_expt != NULL) {
- XFREE(pub_expt);
- }
- if (ecc_shared != NULL) {
- XFREE(ecc_shared);
- }
- if (skey != NULL) {
- XFREE(skey);
- }
- ecc_free(&pubkey);
- return CRYPT_MEM;
- }
-
- pubkeysize = ECC_BUF_SIZE;
- if ((err = ecc_export(pub_expt, &pubkeysize, PK_PUBLIC, &pubkey)) != CRYPT_OK) {
- ecc_free(&pubkey);
- goto LBL_ERR;
- }
-
- /* make random key */
- x = ECC_BUF_SIZE;
- if ((err = ecc_shared_secret(&pubkey, key, ecc_shared, &x)) != CRYPT_OK) {
- ecc_free(&pubkey);
- goto LBL_ERR;
- }
- ecc_free(&pubkey);
- y = MAXBLOCKSIZE;
- if ((err = hash_memory(hash, ecc_shared, x, skey, &y)) != CRYPT_OK) {
- goto LBL_ERR;
- }
-
- /* Encrypt key */
- for (x = 0; x < inlen; x++) {
- skey[x] ^= in[x];
- }
-
- err = der_encode_sequence_multi(out, outlen,
- LTC_ASN1_OBJECT_IDENTIFIER, hash_descriptor[hash].OIDlen, hash_descriptor[hash].OID,
- LTC_ASN1_OCTET_STRING, pubkeysize, pub_expt,
- LTC_ASN1_OCTET_STRING, inlen, skey,
- LTC_ASN1_EOL, 0UL, NULL);
-
-LBL_ERR:
-#ifdef LTC_CLEAN_STACK
- /* clean up */
- zeromem(pub_expt, ECC_BUF_SIZE);
- zeromem(ecc_shared, ECC_BUF_SIZE);
- zeromem(skey, MAXBLOCKSIZE);
-#endif
-
- XFREE(skey);
- XFREE(ecc_shared);
- XFREE(pub_expt);
-
- return err;
-}
-
-/**
- Decrypt an ECC encrypted key
- @param in The ciphertext
- @param inlen The length of the ciphertext (octets)
- @param out [out] The plaintext
- @param outlen [in/out] The max size and resulting size of the plaintext
- @param key The corresponding private ECC key
- @return CRYPT_OK if successful
-*/
-int ecc_decrypt_key(const unsigned char *in, unsigned long inlen,
- unsigned char *out, unsigned long *outlen,
- ecc_key *key)
-{
- unsigned char *ecc_shared, *skey, *pub_expt;
- unsigned long x, y, hashOID[32];
- int hash, err;
- ecc_key pubkey;
- ltc_asn1_list decode[3];
-
- LTC_ARGCHK(in != NULL);
- LTC_ARGCHK(out != NULL);
- LTC_ARGCHK(outlen != NULL);
- LTC_ARGCHK(key != NULL);
-
- /* right key type? */
- if (key->type != PK_PRIVATE) {
- return CRYPT_PK_NOT_PRIVATE;
- }
-
- /* decode to find out hash */
- LTC_SET_ASN1(decode, 0, LTC_ASN1_OBJECT_IDENTIFIER, hashOID, sizeof(hashOID)/sizeof(hashOID[0]));
-
- if ((err = der_decode_sequence(in, inlen, decode, 1)) != CRYPT_OK) {
- return err;
- }
- for (hash = 0; hash_descriptor[hash].name != NULL &&
- (hash_descriptor[hash].OIDlen != decode[0].size ||
- memcmp(hash_descriptor[hash].OID, hashOID, sizeof(unsigned long)*decode[0].size)); hash++);
-
- if (hash_descriptor[hash].name == NULL) {
- return CRYPT_INVALID_PACKET;
- }
-
- /* we now have the hash! */
-
- /* allocate memory */
- pub_expt = XMALLOC(ECC_BUF_SIZE);
- ecc_shared = XMALLOC(ECC_BUF_SIZE);
- skey = XMALLOC(MAXBLOCKSIZE);
- if (pub_expt == NULL || ecc_shared == NULL || skey == NULL) {
- if (pub_expt != NULL) {
- XFREE(pub_expt);
- }
- if (ecc_shared != NULL) {
- XFREE(ecc_shared);
- }
- if (skey != NULL) {
- XFREE(skey);
- }
- return CRYPT_MEM;
- }
- LTC_SET_ASN1(decode, 1, LTC_ASN1_OCTET_STRING, pub_expt, ECC_BUF_SIZE);
- LTC_SET_ASN1(decode, 2, LTC_ASN1_OCTET_STRING, skey, MAXBLOCKSIZE);
-
- /* read the structure in now */
- if ((err = der_decode_sequence(in, inlen, decode, 3)) != CRYPT_OK) {
- goto LBL_ERR;
- }
-
- /* import ECC key from packet */
- if ((err = ecc_import(decode[1].data, decode[1].size, &pubkey)) != CRYPT_OK) {
- goto LBL_ERR;
- }
-
- /* make shared key */
- x = ECC_BUF_SIZE;
- if ((err = ecc_shared_secret(key, &pubkey, ecc_shared, &x)) != CRYPT_OK) {
- ecc_free(&pubkey);
- goto LBL_ERR;
- }
- ecc_free(&pubkey);
-
- y = MAXBLOCKSIZE;
- if ((err = hash_memory(hash, ecc_shared, x, ecc_shared, &y)) != CRYPT_OK) {
- goto LBL_ERR;
- }
-
- /* ensure the hash of the shared secret is at least as big as the encrypt itself */
- if (decode[2].size > y) {
- err = CRYPT_INVALID_PACKET;
- goto LBL_ERR;
- }
-
- /* avoid buffer overflow */
- if (*outlen < decode[2].size) {
- err = CRYPT_BUFFER_OVERFLOW;
- goto LBL_ERR;
- }
-
- /* Decrypt the key */
- for (x = 0; x < decode[2].size; x++) {
- out[x] = skey[x] ^ ecc_shared[x];
- }
- *outlen = x;
-
- err = CRYPT_OK;
-LBL_ERR:
-#ifdef LTC_CLEAN_STACK
- zeromem(pub_expt, ECC_BUF_SIZE);
- zeromem(ecc_shared, ECC_BUF_SIZE);
- zeromem(skey, MAXBLOCKSIZE);
-#endif
-
- XFREE(pub_expt);
- XFREE(ecc_shared);
- XFREE(skey);
-
- return err;
-}
-
-/**
- Sign a message digest
- @param in The message digest to sign
- @param inlen The length of the digest
- @param out [out] The destination for the signature
- @param outlen [in/out] The max size and resulting size of the signature
- @param prng An active PRNG state
- @param wprng The index of the PRNG you wish to use
- @param key A private ECC key
- @return CRYPT_OK if successful
-*/
-int ecc_sign_hash(const unsigned char *in, unsigned long inlen,
- unsigned char *out, unsigned long *outlen,
- prng_state *prng, int wprng, ecc_key *key)
-{
- ecc_key pubkey;
- mp_int r, s, e, p;
- int err;
-
- LTC_ARGCHK(in != NULL);
- LTC_ARGCHK(out != NULL);
- LTC_ARGCHK(outlen != NULL);
- LTC_ARGCHK(key != NULL);
-
- /* is this a private key? */
- if (key->type != PK_PRIVATE) {
- return CRYPT_PK_NOT_PRIVATE;
- }
-
- /* is the IDX valid ? */
- if (is_valid_idx(key->idx) != 1) {
- return CRYPT_PK_INVALID_TYPE;
- }
-
- if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
- return err;
- }
-
- /* get the hash and load it as a bignum into 'e' */
- /* init the bignums */
- if ((err = mp_init_multi(&r, &s, &p, &e, NULL)) != MP_OKAY) {
- ecc_free(&pubkey);
- err = mpi_to_ltc_error(err);
- goto LBL_ERR;
- }
- if ((err = mp_read_radix(&p, (char *)sets[key->idx].order, 64)) != MP_OKAY) { goto error; }
- if ((err = mp_read_unsigned_bin(&e, (unsigned char *)in, (int)inlen)) != MP_OKAY) { goto error; }
-
- /* make up a key and export the public copy */
- for (;;) {
- if ((err = ecc_make_key(prng, wprng, ecc_get_size(key), &pubkey)) != CRYPT_OK) {
- return err;
- }
-
- /* find r = x1 mod n */
- if ((err = mp_mod(&pubkey.pubkey.x, &p, &r)) != MP_OKAY) { goto error; }
-
- if (mp_iszero(&r)) {
- ecc_free(&pubkey);
- } else {
- /* find s = (e + xr)/k */
- if ((err = mp_invmod(&pubkey.k, &p, &pubkey.k)) != MP_OKAY) { goto error; } /* k = 1/k */
- if ((err = mp_mulmod(&key->k, &r, &p, &s)) != MP_OKAY) { goto error; } /* s = xr */
- if ((err = mp_addmod(&e, &s, &p, &s)) != MP_OKAY) { goto error; } /* s = e + xr */
- if ((err = mp_mulmod(&s, &pubkey.k, &p, &s)) != MP_OKAY) { goto error; } /* s = (e + xr)/k */
-
- if (mp_iszero(&s)) {
- ecc_free(&pubkey);
- } else {
- break;
- }
- }
- }
-
- /* store as SEQUENCE { r, s -- integer } */
- err = der_encode_sequence_multi(out, outlen,
- LTC_ASN1_INTEGER, 1UL, &r,
- LTC_ASN1_INTEGER, 1UL, &s,
- LTC_ASN1_EOL, 0UL, NULL);
- goto LBL_ERR;
-error:
- err = mpi_to_ltc_error(err);
-LBL_ERR:
- mp_clear_multi(&r, &s, &p, &e, NULL);
- ecc_free(&pubkey);
-
- return err;
-}
-
-/* verify
- *
- * w = s^-1 mod n
- * u1 = xw
- * u2 = rw
- * X = u1*G + u2*Q
- * v = X_x1 mod n
- * accept if v == r
- */
-
-/**
- Verify an ECC signature
- @param sig The signature to verify
- @param siglen The length of the signature (octets)
- @param hash The hash (message digest) that was signed
- @param hashlen The length of the hash (octets)
- @param stat Result of signature, 1==valid, 0==invalid
- @param key The corresponding public ECC key
- @return CRYPT_OK if successful (even if the signature is not valid)
-*/
-int ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
- const unsigned char *hash, unsigned long hashlen,
- int *stat, ecc_key *key)
-{
- ecc_point *mG, *mQ;
- mp_int r, s, v, w, u1, u2, e, p, m;
- mp_digit mp;
- int err;
-
- LTC_ARGCHK(sig != NULL);
- LTC_ARGCHK(hash != NULL);
- LTC_ARGCHK(stat != NULL);
- LTC_ARGCHK(key != NULL);
-
- /* default to invalid signature */
- *stat = 0;
-
- /* is the IDX valid ? */
- if (is_valid_idx(key->idx) != 1) {
- return CRYPT_PK_INVALID_TYPE;
- }
-
- /* allocate ints */
- if ((err = mp_init_multi(&r, &s, &v, &w, &u1, &u2, &p, &e, &m, NULL)) != MP_OKAY) {
- return CRYPT_MEM;
- }
-
- /* allocate points */
- mG = new_point();
- mQ = new_point();
- if (mQ == NULL || mG == NULL) {
- err = CRYPT_MEM;
- goto done;
- }
-
- /* parse header */
- if ((err = der_decode_sequence_multi(sig, siglen,
- LTC_ASN1_INTEGER, 1UL, &r,
- LTC_ASN1_INTEGER, 1UL, &s,
- LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
- goto done;
- }
-
- /* get the order */
- if ((err = mp_read_radix(&p, (char *)sets[key->idx].order, 64)) != MP_OKAY) { goto error; }
-
- /* get the modulus */
- if ((err = mp_read_radix(&m, (char *)sets[key->idx].prime, 64)) != MP_OKAY) { goto error; }
-
- /* check for zero */
- if (mp_iszero(&r) || mp_iszero(&s) || mp_cmp(&r, &p) != MP_LT || mp_cmp(&s, &p) != MP_LT) {
- err = CRYPT_INVALID_PACKET;
- goto done;
- }
-
- /* read hash */
- if ((err = mp_read_unsigned_bin(&e, (unsigned char *)hash, (int)hashlen)) != MP_OKAY) { goto error; }
-
- /* w = s^-1 mod n */
- if ((err = mp_invmod(&s, &p, &w)) != MP_OKAY) { goto error; }
-
- /* u1 = ew */
- if ((err = mp_mulmod(&e, &w, &p, &u1)) != MP_OKAY) { goto error; }
-
- /* u2 = rw */
- if ((err = mp_mulmod(&r, &w, &p, &u2)) != MP_OKAY) { goto error; }
-
- /* find mG = u1*G */
- if ((err = mp_read_radix(&mG->x, (char *)sets[key->idx].Gx, 64)) != MP_OKAY) { goto error; }
- if ((err = mp_read_radix(&mG->y, (char *)sets[key->idx].Gy, 64)) != MP_OKAY) { goto error; }
- mp_set(&mG->z, 1);
- if ((err = ecc_mulmod(&u1, mG, mG, &m, 0)) != CRYPT_OK) { goto done; }
-
- /* find mQ = u2*Q */
- if ((err = mp_copy(&key->pubkey.x, &mQ->x)) != MP_OKAY) { goto error; }
- if ((err = mp_copy(&key->pubkey.y, &mQ->y)) != MP_OKAY) { goto error; }
- if ((err = mp_copy(&key->pubkey.z, &mQ->z)) != MP_OKAY) { goto error; }
- if ((err = ecc_mulmod(&u2, mQ, mQ, &m, 0)) != CRYPT_OK) { goto done; }
-
- /* find the montgomery mp */
- if ((err = mp_montgomery_setup(&m, &mp)) != MP_OKAY) { goto error; }
- /* add them */
- if ((err = add_point(mQ, mG, mG, &m, mp)) != CRYPT_OK) { goto done; }
-
- /* reduce */
- if ((err = ecc_map(mG, &m, mp)) != CRYPT_OK) { goto done; }
-
- /* v = X_x1 mod n */
- if ((err = mp_mod(&mG->x, &p, &v)) != CRYPT_OK) { goto done; }
-
- /* does v == r */
- if (mp_cmp(&v, &r) == MP_EQ) {
- *stat = 1;
- }
-
- /* clear up and return */
- err = CRYPT_OK;
- goto done;
-error:
- err = mpi_to_ltc_error(err);
-done:
- del_point(mG);
- del_point(mQ);
- mp_clear_multi(&r, &s, &v, &w, &u1, &u2, &p, &e, &m, NULL);
- return err;
-}
-
-
-/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_sys.c,v $ */
-/* $Revision: 1.18 $ */
-/* $Date: 2005/06/14 20:47:55 $ */
diff --git a/libtomcrypt/src/pk/ecc/ecc_test.c b/libtomcrypt/src/pk/ecc/ecc_test.c
new file mode 100644
index 0000000..faa167c
--- /dev/null
+++ b/libtomcrypt/src/pk/ecc/ecc_test.c
@@ -0,0 +1,95 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "tomcrypt.h"
+
+/**
+ @file ecc_test.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef MECC
+
+/**
+ Perform on the ECC system
+ @return CRYPT_OK if successful
+*/
+int ecc_test(void)
+{
+ void *modulus, *order;
+ ecc_point *G, *GG;
+ int i, err, primality;
+
+ if ((err = mp_init_multi(&modulus, &order, NULL)) != CRYPT_OK) {
+ return err;
+ }
+
+ G = ltc_ecc_new_point();
+ GG = ltc_ecc_new_point();
+ if (G == NULL || GG == NULL) {
+ mp_clear_multi(modulus, order, NULL);
+ ltc_ecc_del_point(G);
+ ltc_ecc_del_point(GG);
+ return CRYPT_MEM;
+ }
+
+ for (i = 0; ltc_ecc_sets[i].size; i++) {
+ #if 0
+ printf("Testing %d\n", ltc_ecc_sets[i].size);
+ #endif
+ if ((err = mp_read_radix(modulus, (char *)ltc_ecc_sets[i].prime, 16)) != CRYPT_OK) { goto done; }
+ if ((err = mp_read_radix(order, (char *)ltc_ecc_sets[i].order, 16)) != CRYPT_OK) { goto done; }
+
+ /* is prime actually prime? */
+ if ((err = mp_prime_is_prime(modulus, 8, &primality)) != CRYPT_OK) { goto done; }
+ if (primality == 0) {
+ err = CRYPT_FAIL_TESTVECTOR;
+ goto done;
+ }
+
+ /* is order prime ? */
+ if ((err = mp_prime_is_prime(order, 8, &primality)) != CRYPT_OK) { goto done; }
+ if (primality == 0) {
+ err = CRYPT_FAIL_TESTVECTOR;
+ goto done;
+ }
+
+ if ((err = mp_read_radix(G->x, (char *)ltc_ecc_sets[i].Gx, 16)) != CRYPT_OK) { goto done; }
+ if ((err = mp_read_radix(G->y, (char *)ltc_ecc_sets[i].Gy, 16)) != CRYPT_OK) { goto done; }
+ mp_set(G->z, 1);
+
+ /* then we should have G == (order + 1)G */
+ if ((err = mp_add_d(order, 1, order)) != CRYPT_OK) { goto done; }
+ if ((err = ltc_mp.ecc_ptmul(order, G, GG, modulus, 1)) != CRYPT_OK) { goto done; }
+ if (mp_cmp(G->x, GG->x) != LTC_MP_EQ || mp_cmp(G->y, GG->y) != LTC_MP_EQ) {
+ err = CRYPT_FAIL_TESTVECTOR;
+ goto done;
+ }
+ }
+ err = CRYPT_OK;
+done:
+ ltc_ecc_del_point(GG);
+ ltc_ecc_del_point(G);
+ mp_clear_multi(order, modulus, NULL);
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_test.c,v $ */
+/* $Revision: 1.10 $ */
+/* $Date: 2006/12/04 02:19:48 $ */
+
diff --git a/libtomcrypt/src/pk/ecc/ecc_verify_hash.c b/libtomcrypt/src/pk/ecc/ecc_verify_hash.c
new file mode 100644
index 0000000..bd8a840
--- /dev/null
+++ b/libtomcrypt/src/pk/ecc/ecc_verify_hash.c
@@ -0,0 +1,165 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "tomcrypt.h"
+
+/**
+ @file ecc_verify_hash.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef MECC
+
+/* verify
+ *
+ * w = s^-1 mod n
+ * u1 = xw
+ * u2 = rw
+ * X = u1*G + u2*Q
+ * v = X_x1 mod n
+ * accept if v == r
+ */
+
+/**
+ Verify an ECC signature
+ @param sig The signature to verify
+ @param siglen The length of the signature (octets)
+ @param hash The hash (message digest) that was signed
+ @param hashlen The length of the hash (octets)
+ @param stat Result of signature, 1==valid, 0==invalid
+ @param key The corresponding public ECC key
+ @return CRYPT_OK if successful (even if the signature is not valid)
+*/
+int ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
+ const unsigned char *hash, unsigned long hashlen,
+ int *stat, ecc_key *key)
+{
+ ecc_point *mG, *mQ;
+ void *r, *s, *v, *w, *u1, *u2, *e, *p, *m;
+ void *mp;
+ int err;
+
+ LTC_ARGCHK(sig != NULL);
+ LTC_ARGCHK(hash != NULL);
+ LTC_ARGCHK(stat != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ /* default to invalid signature */
+ *stat = 0;
+ mp = NULL;
+
+ /* is the IDX valid ? */
+ if (ltc_ecc_is_valid_idx(key->idx) != 1) {
+ return CRYPT_PK_INVALID_TYPE;
+ }
+
+ /* allocate ints */
+ if ((err = mp_init_multi(&r, &s, &v, &w, &u1, &u2, &p, &e, &m, NULL)) != CRYPT_OK) {
+ return CRYPT_MEM;
+ }
+
+ /* allocate points */
+ mG = ltc_ecc_new_point();
+ mQ = ltc_ecc_new_point();
+ if (mQ == NULL || mG == NULL) {
+ err = CRYPT_MEM;
+ goto error;
+ }
+
+ /* parse header */
+ if ((err = der_decode_sequence_multi(sig, siglen,
+ LTC_ASN1_INTEGER, 1UL, r,
+ LTC_ASN1_INTEGER, 1UL, s,
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
+ goto error;
+ }
+
+ /* get the order */
+ if ((err = mp_read_radix(p, (char *)key->dp->order, 16)) != CRYPT_OK) { goto error; }
+
+ /* get the modulus */
+ if ((err = mp_read_radix(m, (char *)key->dp->prime, 16)) != CRYPT_OK) { goto error; }
+
+ /* check for zero */
+ if (mp_iszero(r) || mp_iszero(s) || mp_cmp(r, p) != LTC_MP_LT || mp_cmp(s, p) != LTC_MP_LT) {
+ err = CRYPT_INVALID_PACKET;
+ goto error;
+ }
+
+ /* read hash */
+ if ((err = mp_read_unsigned_bin(e, (unsigned char *)hash, (int)hashlen)) != CRYPT_OK) { goto error; }
+
+ /* w = s^-1 mod n */
+ if ((err = mp_invmod(s, p, w)) != CRYPT_OK) { goto error; }
+
+ /* u1 = ew */
+ if ((err = mp_mulmod(e, w, p, u1)) != CRYPT_OK) { goto error; }
+
+ /* u2 = rw */
+ if ((err = mp_mulmod(r, w, p, u2)) != CRYPT_OK) { goto error; }
+
+ /* find mG and mQ */
+ if ((err = mp_read_radix(mG->x, (char *)key->dp->Gx, 16)) != CRYPT_OK) { goto error; }
+ if ((err = mp_read_radix(mG->y, (char *)key->dp->Gy, 16)) != CRYPT_OK) { goto error; }
+ if ((err = mp_set(mG->z, 1)) != CRYPT_OK) { goto error; }
+
+ if ((err = mp_copy(key->pubkey.x, mQ->x)) != CRYPT_OK) { goto error; }
+ if ((err = mp_copy(key->pubkey.y, mQ->y)) != CRYPT_OK) { goto error; }
+ if ((err = mp_copy(key->pubkey.z, mQ->z)) != CRYPT_OK) { goto error; }
+
+ /* compute u1*mG + u2*mQ = mG */
+ if (ltc_mp.ecc_mul2add == NULL) {
+ if ((err = ltc_mp.ecc_ptmul(u1, mG, mG, m, 0)) != CRYPT_OK) { goto error; }
+ if ((err = ltc_mp.ecc_ptmul(u2, mQ, mQ, m, 0)) != CRYPT_OK) { goto error; }
+
+ /* find the montgomery mp */
+ if ((err = mp_montgomery_setup(m, &mp)) != CRYPT_OK) { goto error; }
+
+ /* add them */
+ if ((err = ltc_mp.ecc_ptadd(mQ, mG, mG, m, mp)) != CRYPT_OK) { goto error; }
+
+ /* reduce */
+ if ((err = ltc_mp.ecc_map(mG, m, mp)) != CRYPT_OK) { goto error; }
+ } else {
+ /* use Shamir's trick to compute u1*mG + u2*mQ using half of the doubles */
+ if ((err = ltc_mp.ecc_mul2add(mG, u1, mQ, u2, mG, m)) != CRYPT_OK) { goto error; }
+ }
+
+ /* v = X_x1 mod n */
+ if ((err = mp_mod(mG->x, p, v)) != CRYPT_OK) { goto error; }
+
+ /* does v == r */
+ if (mp_cmp(v, r) == LTC_MP_EQ) {
+ *stat = 1;
+ }
+
+ /* clear up and return */
+ err = CRYPT_OK;
+error:
+ ltc_ecc_del_point(mG);
+ ltc_ecc_del_point(mQ);
+ mp_clear_multi(r, s, v, w, u1, u2, p, e, m, NULL);
+ if (mp != NULL) {
+ mp_montgomery_free(mp);
+ }
+ return err;
+}
+
+#endif
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_verify_hash.c,v $ */
+/* $Revision: 1.12 $ */
+/* $Date: 2006/12/04 05:07:59 $ */
+
diff --git a/libtomcrypt/src/pk/ecc/ltc_ecc_is_valid_idx.c b/libtomcrypt/src/pk/ecc/ltc_ecc_is_valid_idx.c
new file mode 100644
index 0000000..cf81f24
--- /dev/null
+++ b/libtomcrypt/src/pk/ecc/ltc_ecc_is_valid_idx.c
@@ -0,0 +1,46 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "tomcrypt.h"
+
+/**
+ @file ltc_ecc_is_valid_idx.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef MECC
+
+/** Returns whether an ECC idx is valid or not
+ @param n The idx number to check
+ @return 1 if valid, 0 if not
+*/
+int ltc_ecc_is_valid_idx(int n)
+{
+ int x;
+
+ for (x = 0; ltc_ecc_sets[x].size != 0; x++);
+ /* -1 is a valid index --- indicating that the domain params were supplied by the user */
+ if ((n >= -1) || (n < x)) {
+ return 1;
+ }
+ return 0;
+}
+
+#endif
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_is_valid_idx.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/11/21 00:10:18 $ */
+
diff --git a/libtomcrypt/src/pk/ecc/ltc_ecc_map.c b/libtomcrypt/src/pk/ecc/ltc_ecc_map.c
new file mode 100644
index 0000000..eec28b3
--- /dev/null
+++ b/libtomcrypt/src/pk/ecc/ltc_ecc_map.c
@@ -0,0 +1,76 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "tomcrypt.h"
+
+/**
+ @file ltc_ecc_map.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef MECC
+
+/**
+ Map a projective jacbobian point back to affine space
+ @param P [in/out] The point to map
+ @param modulus The modulus of the field the ECC curve is in
+ @param mp The "b" value from montgomery_setup()
+ @return CRYPT_OK on success
+*/
+int ltc_ecc_map(ecc_point *P, void *modulus, void *mp)
+{
+ void *t1, *t2;
+ int err;
+
+ LTC_ARGCHK(P != NULL);
+ LTC_ARGCHK(modulus != NULL);
+ LTC_ARGCHK(mp != NULL);
+
+ if ((err = mp_init_multi(&t1, &t2, NULL)) != CRYPT_OK) {
+ return CRYPT_MEM;
+ }
+
+ /* first map z back to normal */
+ if ((err = mp_montgomery_reduce(P->z, modulus, mp)) != CRYPT_OK) { goto done; }
+
+ /* get 1/z */
+ if ((err = mp_invmod(P->z, modulus, t1)) != CRYPT_OK) { goto done; }
+
+ /* get 1/z^2 and 1/z^3 */
+ if ((err = mp_sqr(t1, t2)) != CRYPT_OK) { goto done; }
+ if ((err = mp_mod(t2, modulus, t2)) != CRYPT_OK) { goto done; }
+ if ((err = mp_mul(t1, t2, t1)) != CRYPT_OK) { goto done; }
+ if ((err = mp_mod(t1, modulus, t1)) != CRYPT_OK) { goto done; }
+
+ /* multiply against x/y */
+ if ((err = mp_mul(P->x, t2, P->x)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(P->x, modulus, mp)) != CRYPT_OK) { goto done; }
+ if ((err = mp_mul(P->y, t1, P->y)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(P->y, modulus, mp)) != CRYPT_OK) { goto done; }
+ if ((err = mp_set(P->z, 1)) != CRYPT_OK) { goto done; }
+
+ err = CRYPT_OK;
+done:
+ mp_clear_multi(t1, t2, NULL);
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_map.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/04 02:50:11 $ */
+
diff --git a/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c b/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c
new file mode 100644
index 0000000..ac1c24f
--- /dev/null
+++ b/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c
@@ -0,0 +1,207 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "tomcrypt.h"
+
+/**
+ @file ltc_ecc_mul2add.c
+ ECC Crypto, Shamir's Trick, Tom St Denis
+*/
+
+#ifdef MECC
+
+#ifdef LTC_ECC_SHAMIR
+
+/** Computes kA*A + kB*B = C using Shamir's Trick
+ @param A First point to multiply
+ @param kA What to multiple A by
+ @param B Second point to multiply
+ @param kB What to multiple B by
+ @param C [out] Destination point (can overlap with A or B
+ @param modulus Modulus for curve
+ @return CRYPT_OK on success
+*/
+int ltc_ecc_mul2add(ecc_point *A, void *kA,
+ ecc_point *B, void *kB,
+ ecc_point *C,
+ void *modulus)
+{
+ ecc_point *precomp[16];
+ unsigned bitbufA, bitbufB, lenA, lenB, len, x, y, nA, nB, nibble;
+ unsigned char *tA, *tB;
+ int err, first;
+ void *mp, *mu;
+
+ /* argchks */
+ LTC_ARGCHK(A != NULL);
+ LTC_ARGCHK(B != NULL);
+ LTC_ARGCHK(C != NULL);
+ LTC_ARGCHK(kA != NULL);
+ LTC_ARGCHK(kB != NULL);
+ LTC_ARGCHK(modulus != NULL);
+
+ /* allocate memory */
+ tA = XCALLOC(1, ECC_BUF_SIZE);
+ if (tA == NULL) {
+ return CRYPT_MEM;
+ }
+ tB = XCALLOC(1, ECC_BUF_SIZE);
+ if (tB == NULL) {
+ XFREE(tA);
+ return CRYPT_MEM;
+ }
+
+ /* get sizes */
+ lenA = mp_unsigned_bin_size(kA);
+ lenB = mp_unsigned_bin_size(kB);
+ len = MAX(lenA, lenB);
+
+ /* sanity check */
+ if ((lenA > ECC_BUF_SIZE) || (lenB > ECC_BUF_SIZE)) {
+ err = CRYPT_INVALID_ARG;
+ goto ERR_T;
+ }
+
+ /* extract and justify kA */
+ mp_to_unsigned_bin(kA, (len - lenA) + tA);
+
+ /* extract and justify kB */
+ mp_to_unsigned_bin(kB, (len - lenB) + tB);
+
+ /* allocate the table */
+ for (x = 0; x < 16; x++) {
+ precomp[x] = ltc_ecc_new_point();
+ if (precomp[x] == NULL) {
+ for (y = 0; y < x; ++y) {
+ ltc_ecc_del_point(precomp[y]);
+ }
+ err = CRYPT_MEM;
+ goto ERR_T;
+ }
+ }
+
+ /* init montgomery reduction */
+ if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) {
+ goto ERR_P;
+ }
+ if ((err = mp_init(&mu)) != CRYPT_OK) {
+ goto ERR_MP;
+ }
+ if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) {
+ goto ERR_MU;
+ }
+
+ /* copy ones ... */
+ if ((err = mp_mulmod(A->x, mu, modulus, precomp[1]->x)) != CRYPT_OK) { goto ERR_MU; }
+ if ((err = mp_mulmod(A->y, mu, modulus, precomp[1]->y)) != CRYPT_OK) { goto ERR_MU; }
+ if ((err = mp_mulmod(A->z, mu, modulus, precomp[1]->z)) != CRYPT_OK) { goto ERR_MU; }
+
+ if ((err = mp_mulmod(B->x, mu, modulus, precomp[1<<2]->x)) != CRYPT_OK) { goto ERR_MU; }
+ if ((err = mp_mulmod(B->y, mu, modulus, precomp[1<<2]->y)) != CRYPT_OK) { goto ERR_MU; }
+ if ((err = mp_mulmod(B->z, mu, modulus, precomp[1<<2]->z)) != CRYPT_OK) { goto ERR_MU; }
+
+ /* precomp [i,0](A + B) table */
+ if ((err = ltc_mp.ecc_ptdbl(precomp[1], precomp[2], modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
+ if ((err = ltc_mp.ecc_ptadd(precomp[1], precomp[2], precomp[3], modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
+
+ /* precomp [0,i](A + B) table */
+ if ((err = ltc_mp.ecc_ptdbl(precomp[1<<2], precomp[2<<2], modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
+ if ((err = ltc_mp.ecc_ptadd(precomp[1<<2], precomp[2<<2], precomp[3<<2], modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
+
+ /* precomp [i,j](A + B) table (i != 0, j != 0) */
+ for (x = 1; x < 4; x++) {
+ for (y = 1; y < 4; y++) {
+ if ((err = ltc_mp.ecc_ptadd(precomp[x], precomp[(y<<2)], precomp[x+(y<<2)], modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
+ }
+ }
+
+ nibble = 3;
+ first = 1;
+ bitbufA = tA[0];
+ bitbufB = tB[0];
+
+ /* for every byte of the multiplicands */
+ for (x = -1;; ) {
+ /* grab a nibble */
+ if (++nibble == 4) {
+ ++x; if (x == len) break;
+ bitbufA = tA[x];
+ bitbufB = tB[x];
+ nibble = 0;
+ }
+
+ /* extract two bits from both, shift/update */
+ nA = (bitbufA >> 6) & 0x03;
+ nB = (bitbufB >> 6) & 0x03;
+ bitbufA = (bitbufA << 2) & 0xFF;
+ bitbufB = (bitbufB << 2) & 0xFF;
+
+ /* if both zero, if first, continue */
+ if ((nA == 0) && (nB == 0) && (first == 1)) {
+ continue;
+ }
+
+ /* double twice, only if this isn't the first */
+ if (first == 0) {
+ /* double twice */
+ if ((err = ltc_mp.ecc_ptdbl(C, C, modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
+ if ((err = ltc_mp.ecc_ptdbl(C, C, modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
+ }
+
+ /* if not both zero */
+ if ((nA != 0) || (nB != 0)) {
+ if (first == 1) {
+ /* if first, copy from table */
+ first = 0;
+ if ((err = mp_copy(precomp[nA + (nB<<2)]->x, C->x)) != CRYPT_OK) { goto ERR_MU; }
+ if ((err = mp_copy(precomp[nA + (nB<<2)]->y, C->y)) != CRYPT_OK) { goto ERR_MU; }
+ if ((err = mp_copy(precomp[nA + (nB<<2)]->z, C->z)) != CRYPT_OK) { goto ERR_MU; }
+ } else {
+ /* if not first, add from table */
+ if ((err = ltc_mp.ecc_ptadd(C, precomp[nA + (nB<<2)], C, modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
+ }
+ }
+ }
+
+ /* reduce to affine */
+ err = ltc_ecc_map(C, modulus, mp);
+
+ /* clean up */
+ERR_MU:
+ mp_clear(mu);
+ERR_MP:
+ mp_montgomery_free(mp);
+ERR_P:
+ for (x = 0; x < 16; x++) {
+ ltc_ecc_del_point(precomp[x]);
+ }
+ERR_T:
+#ifdef LTC_CLEAN_STACK
+ zeromem(tA, ECC_BUF_SIZE);
+ zeromem(tB, ECC_BUF_SIZE);
+#endif
+ XFREE(tA);
+ XFREE(tB);
+
+ return err;
+}
+
+#endif
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c,v $ */
+/* $Revision: 1.6 $ */
+/* $Date: 2006/12/04 05:07:59 $ */
diff --git a/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c b/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c
new file mode 100644
index 0000000..0e4c92b
--- /dev/null
+++ b/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c
@@ -0,0 +1,222 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "tomcrypt.h"
+
+/**
+ @file ltc_ecc_mulmod.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef MECC
+#ifndef LTC_ECC_TIMING_RESISTANT
+
+/* size of sliding window, don't change this! */
+#define WINSIZE 4
+
+/**
+ Perform a point multiplication
+ @param k The scalar to multiply by
+ @param G The base point
+ @param R [out] Destination for kG
+ @param modulus The modulus of the field the ECC curve is in
+ @param map Boolean whether to map back to affine or not (1==map, 0 == leave in projective)
+ @return CRYPT_OK on success
+*/
+int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map)
+{
+ ecc_point *tG, *M[8];
+ int i, j, err;
+ void *mu, *mp;
+ unsigned long buf;
+ int first, bitbuf, bitcpy, bitcnt, mode, digidx;
+
+ LTC_ARGCHK(k != NULL);
+ LTC_ARGCHK(G != NULL);
+ LTC_ARGCHK(R != NULL);
+ LTC_ARGCHK(modulus != NULL);
+
+ /* init montgomery reduction */
+ if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = mp_init(&mu)) != CRYPT_OK) {
+ mp_montgomery_free(mp);
+ return err;
+ }
+ if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) {
+ mp_montgomery_free(mp);
+ mp_clear(mu);
+ return err;
+ }
+
+ /* alloc ram for window temps */
+ for (i = 0; i < 8; i++) {
+ M[i] = ltc_ecc_new_point();
+ if (M[i] == NULL) {
+ for (j = 0; j < i; j++) {
+ ltc_ecc_del_point(M[j]);
+ }
+ mp_montgomery_free(mp);
+ mp_clear(mu);
+ return CRYPT_MEM;
+ }
+ }
+
+ /* make a copy of G incase R==G */
+ tG = ltc_ecc_new_point();
+ if (tG == NULL) { err = CRYPT_MEM; goto done; }
+
+ /* tG = G and convert to montgomery */
+ if (mp_cmp_d(mu, 1) == LTC_MP_EQ) {
+ if ((err = mp_copy(G->x, tG->x)) != CRYPT_OK) { goto done; }
+ if ((err = mp_copy(G->y, tG->y)) != CRYPT_OK) { goto done; }
+ if ((err = mp_copy(G->z, tG->z)) != CRYPT_OK) { goto done; }
+ } else {
+ if ((err = mp_mulmod(G->x, mu, modulus, tG->x)) != CRYPT_OK) { goto done; }
+ if ((err = mp_mulmod(G->y, mu, modulus, tG->y)) != CRYPT_OK) { goto done; }
+ if ((err = mp_mulmod(G->z, mu, modulus, tG->z)) != CRYPT_OK) { goto done; }
+ }
+ mp_clear(mu);
+ mu = NULL;
+
+ /* calc the M tab, which holds kG for k==8..15 */
+ /* M[0] == 8G */
+ if ((err = ltc_mp.ecc_ptdbl(tG, M[0], modulus, mp)) != CRYPT_OK) { goto done; }
+ if ((err = ltc_mp.ecc_ptdbl(M[0], M[0], modulus, mp)) != CRYPT_OK) { goto done; }
+ if ((err = ltc_mp.ecc_ptdbl(M[0], M[0], modulus, mp)) != CRYPT_OK) { goto done; }
+
+ /* now find (8+k)G for k=1..7 */
+ for (j = 9; j < 16; j++) {
+ if ((err = ltc_mp.ecc_ptadd(M[j-9], tG, M[j-8], modulus, mp)) != CRYPT_OK) { goto done; }
+ }
+
+ /* setup sliding window */
+ mode = 0;
+ bitcnt = 1;
+ buf = 0;
+ digidx = mp_get_digit_count(k) - 1;
+ bitcpy = bitbuf = 0;
+ first = 1;
+
+ /* perform ops */
+ for (;;) {
+ /* grab next digit as required */
+ if (--bitcnt == 0) {
+ if (digidx == -1) {
+ break;
+ }
+ buf = mp_get_digit(k, digidx);
+ bitcnt = (int) ltc_mp.bits_per_digit;
+ --digidx;
+ }
+
+ /* grab the next msb from the ltiplicand */
+ i = (buf >> (ltc_mp.bits_per_digit - 1)) & 1;
+ buf <<= 1;
+
+ /* skip leading zero bits */
+ if (mode == 0 && i == 0) {
+ continue;
+ }
+
+ /* if the bit is zero and mode == 1 then we double */
+ if (mode == 1 && i == 0) {
+ if ((err = ltc_mp.ecc_ptdbl(R, R, modulus, mp)) != CRYPT_OK) { goto done; }
+ continue;
+ }
+
+ /* else we add it to the window */
+ bitbuf |= (i << (WINSIZE - ++bitcpy));
+ mode = 2;
+
+ if (bitcpy == WINSIZE) {
+ /* if this is the first window we do a simple copy */
+ if (first == 1) {
+ /* R = kG [k = first window] */
+ if ((err = mp_copy(M[bitbuf-8]->x, R->x)) != CRYPT_OK) { goto done; }
+ if ((err = mp_copy(M[bitbuf-8]->y, R->y)) != CRYPT_OK) { goto done; }
+ if ((err = mp_copy(M[bitbuf-8]->z, R->z)) != CRYPT_OK) { goto done; }
+ first = 0;
+ } else {
+ /* normal window */
+ /* ok window is filled so double as required and add */
+ /* double first */
+ for (j = 0; j < WINSIZE; j++) {
+ if ((err = ltc_mp.ecc_ptdbl(R, R, modulus, mp)) != CRYPT_OK) { goto done; }
+ }
+
+ /* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranteed */
+ if ((err = ltc_mp.ecc_ptadd(R, M[bitbuf-8], R, modulus, mp)) != CRYPT_OK) { goto done; }
+ }
+ /* empty window and reset */
+ bitcpy = bitbuf = 0;
+ mode = 1;
+ }
+ }
+
+ /* if bits remain then double/add */
+ if (mode == 2 && bitcpy > 0) {
+ /* double then add */
+ for (j = 0; j < bitcpy; j++) {
+ /* only double if we have had at least one add first */
+ if (first == 0) {
+ if ((err = ltc_mp.ecc_ptdbl(R, R, modulus, mp)) != CRYPT_OK) { goto done; }
+ }
+
+ bitbuf <<= 1;
+ if ((bitbuf & (1 << WINSIZE)) != 0) {
+ if (first == 1){
+ /* first add, so copy */
+ if ((err = mp_copy(tG->x, R->x)) != CRYPT_OK) { goto done; }
+ if ((err = mp_copy(tG->y, R->y)) != CRYPT_OK) { goto done; }
+ if ((err = mp_copy(tG->z, R->z)) != CRYPT_OK) { goto done; }
+ first = 0;
+ } else {
+ /* then add */
+ if ((err = ltc_mp.ecc_ptadd(R, tG, R, modulus, mp)) != CRYPT_OK) { goto done; }
+ }
+ }
+ }
+ }
+
+ /* map R back from projective space */
+ if (map) {
+ err = ltc_ecc_map(R, modulus, mp);
+ } else {
+ err = CRYPT_OK;
+ }
+done:
+ if (mu != NULL) {
+ mp_clear(mu);
+ }
+ mp_montgomery_free(mp);
+ ltc_ecc_del_point(tG);
+ for (i = 0; i < 8; i++) {
+ ltc_ecc_del_point(M[i]);
+ }
+ return err;
+}
+
+#endif
+
+#undef WINSIZE
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c,v $ */
+/* $Revision: 1.24 $ */
+/* $Date: 2006/12/04 05:07:59 $ */
diff --git a/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod_timing.c b/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod_timing.c
new file mode 100644
index 0000000..b94a50c
--- /dev/null
+++ b/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod_timing.c
@@ -0,0 +1,167 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "tomcrypt.h"
+
+/**
+ @file ltc_ecc_mulmod_timing.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef MECC
+
+#ifdef LTC_ECC_TIMING_RESISTANT
+
+/**
+ Perform a point multiplication (timing resistant)
+ @param k The scalar to multiply by
+ @param G The base point
+ @param R [out] Destination for kG
+ @param modulus The modulus of the field the ECC curve is in
+ @param map Boolean whether to map back to affine or not (1==map, 0 == leave in projective)
+ @return CRYPT_OK on success
+*/
+int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map)
+{
+ ecc_point *tG, *M[3];
+ int i, j, err;
+ void *mu, *mp;
+ unsigned long buf;
+ int first, bitbuf, bitcpy, bitcnt, mode, digidx;
+
+ LTC_ARGCHK(k != NULL);
+ LTC_ARGCHK(G != NULL);
+ LTC_ARGCHK(R != NULL);
+ LTC_ARGCHK(modulus != NULL);
+
+ /* init montgomery reduction */
+ if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) {
+ return err;
+ }
+ if ((err = mp_init(&mu)) != CRYPT_OK) {
+ mp_montgomery_free(mp);
+ return err;
+ }
+ if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) {
+ mp_clear(mu);
+ mp_montgomery_free(mp);
+ return err;
+ }
+
+ /* alloc ram for window temps */
+ for (i = 0; i < 3; i++) {
+ M[i] = ltc_ecc_new_point();
+ if (M[i] == NULL) {
+ for (j = 0; j < i; j++) {
+ ltc_ecc_del_point(M[j]);
+ }
+ mp_clear(mu);
+ mp_montgomery_free(mp);
+ return CRYPT_MEM;
+ }
+ }
+
+ /* make a copy of G incase R==G */
+ tG = ltc_ecc_new_point();
+ if (tG == NULL) { err = CRYPT_MEM; goto done; }
+
+ /* tG = G and convert to montgomery */
+ if ((err = mp_mulmod(G->x, mu, modulus, tG->x)) != CRYPT_OK) { goto done; }
+ if ((err = mp_mulmod(G->y, mu, modulus, tG->y)) != CRYPT_OK) { goto done; }
+ if ((err = mp_mulmod(G->z, mu, modulus, tG->z)) != CRYPT_OK) { goto done; }
+ mp_clear(mu);
+ mu = NULL;
+
+ /* calc the M tab */
+ /* M[0] == G */
+ if ((err = mp_copy(tG->x, M[0]->x)) != CRYPT_OK) { goto done; }
+ if ((err = mp_copy(tG->y, M[0]->y)) != CRYPT_OK) { goto done; }
+ if ((err = mp_copy(tG->z, M[0]->z)) != CRYPT_OK) { goto done; }
+ /* M[1] == 2G */
+ if ((err = ltc_mp.ecc_ptdbl(tG, M[1], modulus, mp)) != CRYPT_OK) { goto done; }
+
+ /* setup sliding window */
+ mode = 0;
+ bitcnt = 1;
+ buf = 0;
+ digidx = mp_get_digit_count(k) - 1;
+ bitcpy = bitbuf = 0;
+ first = 1;
+
+ /* perform ops */
+ for (;;) {
+ /* grab next digit as required */
+ if (--bitcnt == 0) {
+ if (digidx == -1) {
+ break;
+ }
+ buf = mp_get_digit(k, digidx);
+ bitcnt = (int) MP_DIGIT_BIT;
+ --digidx;
+ }
+
+ /* grab the next msb from the ltiplicand */
+ i = (buf >> (MP_DIGIT_BIT - 1)) & 1;
+ buf <<= 1;
+
+ if (mode == 0 && i == 0) {
+ /* dummy operations */
+ if ((err = ltc_mp.ecc_ptadd(M[0], M[1], M[2], modulus, mp)) != CRYPT_OK) { goto done; }
+ if ((err = ltc_mp.ecc_ptdbl(M[1], M[2], modulus, mp)) != CRYPT_OK) { goto done; }
+ continue;
+ }
+
+ if (mode == 0 && i == 1) {
+ mode = 1;
+ /* dummy operations */
+ if ((err = ltc_mp.ecc_ptadd(M[0], M[1], M[2], modulus, mp)) != CRYPT_OK) { goto done; }
+ if ((err = ltc_mp.ecc_ptdbl(M[1], M[2], modulus, mp)) != CRYPT_OK) { goto done; }
+ continue;
+ }
+
+ if ((err = ltc_mp.ecc_ptadd(M[0], M[1], M[i^1], modulus, mp)) != CRYPT_OK) { goto done; }
+ if ((err = ltc_mp.ecc_ptdbl(M[i], M[i], modulus, mp)) != CRYPT_OK) { goto done; }
+ }
+
+ /* copy result out */
+ if ((err = mp_copy(M[0]->x, R->x)) != CRYPT_OK) { goto done; }
+ if ((err = mp_copy(M[0]->y, R->y)) != CRYPT_OK) { goto done; }
+ if ((err = mp_copy(M[0]->z, R->z)) != CRYPT_OK) { goto done; }
+
+ /* map R back from projective space */
+ if (map) {
+ err = ltc_ecc_map(R, modulus, mp);
+ } else {
+ err = CRYPT_OK;
+ }
+done:
+ if (mu != NULL) {
+ mp_clear(mu);
+ }
+ mp_montgomery_free(mp);
+ ltc_ecc_del_point(tG);
+ for (i = 0; i < 3; i++) {
+ ltc_ecc_del_point(M[i]);
+ }
+ return err;
+}
+
+#endif
+#endif
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod_timing.c,v $ */
+/* $Revision: 1.11 $ */
+/* $Date: 2006/12/04 22:17:46 $ */
+
diff --git a/libtomcrypt/src/pk/ecc/ltc_ecc_points.c b/libtomcrypt/src/pk/ecc/ltc_ecc_points.c
new file mode 100644
index 0000000..39f1321
--- /dev/null
+++ b/libtomcrypt/src/pk/ecc/ltc_ecc_points.c
@@ -0,0 +1,60 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "tomcrypt.h"
+
+/**
+ @file ltc_ecc_points.c
+ ECC Crypto, Tom St Denis
+*/
+
+#ifdef MECC
+
+/**
+ Allocate a new ECC point
+ @return A newly allocated point or NULL on error
+*/
+ecc_point *ltc_ecc_new_point(void)
+{
+ ecc_point *p;
+ p = XCALLOC(1, sizeof(*p));
+ if (p == NULL) {
+ return NULL;
+ }
+ if (mp_init_multi(&p->x, &p->y, &p->z, NULL) != CRYPT_OK) {
+ XFREE(p);
+ return NULL;
+ }
+ return p;
+}
+
+/** Free an ECC point from memory
+ @param p The point to free
+*/
+void ltc_ecc_del_point(ecc_point *p)
+{
+ /* prevents free'ing null arguments */
+ if (p != NULL) {
+ mp_clear_multi(p->x, p->y, p->z, NULL); /* note: p->z may be NULL but that's ok with this function anyways */
+ XFREE(p);
+ }
+}
+
+#endif
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_points.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/04 02:19:48 $ */
+
diff --git a/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c b/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c
new file mode 100644
index 0000000..c8e359f
--- /dev/null
+++ b/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c
@@ -0,0 +1,196 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "tomcrypt.h"
+
+/**
+ @file ltc_ecc_projective_add_point.c
+ ECC Crypto, Tom St Denis
+*/
+
+#if defined(MECC) && (!defined(MECC_ACCEL) || defined(LTM_DESC))
+
+/**
+ Add two ECC points
+ @param P The point to add
+ @param Q The point to add
+ @param R [out] The destination of the double
+ @param modulus The modulus of the field the ECC curve is in
+ @param mp The "b" value from montgomery_setup()
+ @return CRYPT_OK on success
+*/
+int ltc_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, void *modulus, void *mp)
+{
+ void *t1, *t2, *x, *y, *z;
+ int err;
+
+ LTC_ARGCHK(P != NULL);
+ LTC_ARGCHK(Q != NULL);
+ LTC_ARGCHK(R != NULL);
+ LTC_ARGCHK(modulus != NULL);
+ LTC_ARGCHK(mp != NULL);
+
+ if ((err = mp_init_multi(&t1, &t2, &x, &y, &z, NULL)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* should we dbl instead? */
+ if ((err = mp_sub(modulus, Q->y, t1)) != CRYPT_OK) { goto done; }
+
+ if ( (mp_cmp(P->x, Q->x) == LTC_MP_EQ) &&
+ (Q->z != NULL && mp_cmp(P->z, Q->z) == LTC_MP_EQ) &&
+ (mp_cmp(P->y, Q->y) == LTC_MP_EQ || mp_cmp(P->y, t1) == LTC_MP_EQ)) {
+ mp_clear_multi(t1, t2, x, y, z, NULL);
+ return ltc_ecc_projective_dbl_point(P, R, modulus, mp);
+ }
+
+ if ((err = mp_copy(P->x, x)) != CRYPT_OK) { goto done; }
+ if ((err = mp_copy(P->y, y)) != CRYPT_OK) { goto done; }
+ if ((err = mp_copy(P->z, z)) != CRYPT_OK) { goto done; }
+
+ /* if Z is one then these are no-operations */
+ if (Q->z != NULL) {
+ /* T1 = Z' * Z' */
+ if ((err = mp_sqr(Q->z, t1)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* X = X * T1 */
+ if ((err = mp_mul(t1, x, x)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(x, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* T1 = Z' * T1 */
+ if ((err = mp_mul(Q->z, t1, t1)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* Y = Y * T1 */
+ if ((err = mp_mul(t1, y, y)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(y, modulus, mp)) != CRYPT_OK) { goto done; }
+ }
+
+ /* T1 = Z*Z */
+ if ((err = mp_sqr(z, t1)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* T2 = X' * T1 */
+ if ((err = mp_mul(Q->x, t1, t2)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* T1 = Z * T1 */
+ if ((err = mp_mul(z, t1, t1)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* T1 = Y' * T1 */
+ if ((err = mp_mul(Q->y, t1, t1)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; }
+
+ /* Y = Y - T1 */
+ if ((err = mp_sub(y, t1, y)) != CRYPT_OK) { goto done; }
+ if (mp_cmp_d(y, 0) == LTC_MP_LT) {
+ if ((err = mp_add(y, modulus, y)) != CRYPT_OK) { goto done; }
+ }
+ /* T1 = 2T1 */
+ if ((err = mp_add(t1, t1, t1)) != CRYPT_OK) { goto done; }
+ if (mp_cmp(t1, modulus) != LTC_MP_LT) {
+ if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; }
+ }
+ /* T1 = Y + T1 */
+ if ((err = mp_add(t1, y, t1)) != CRYPT_OK) { goto done; }
+ if (mp_cmp(t1, modulus) != LTC_MP_LT) {
+ if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; }
+ }
+ /* X = X - T2 */
+ if ((err = mp_sub(x, t2, x)) != CRYPT_OK) { goto done; }
+ if (mp_cmp_d(x, 0) == LTC_MP_LT) {
+ if ((err = mp_add(x, modulus, x)) != CRYPT_OK) { goto done; }
+ }
+ /* T2 = 2T2 */
+ if ((err = mp_add(t2, t2, t2)) != CRYPT_OK) { goto done; }
+ if (mp_cmp(t2, modulus) != LTC_MP_LT) {
+ if ((err = mp_sub(t2, modulus, t2)) != CRYPT_OK) { goto done; }
+ }
+ /* T2 = X + T2 */
+ if ((err = mp_add(t2, x, t2)) != CRYPT_OK) { goto done; }
+ if (mp_cmp(t2, modulus) != LTC_MP_LT) {
+ if ((err = mp_sub(t2, modulus, t2)) != CRYPT_OK) { goto done; }
+ }
+
+ /* if Z' != 1 */
+ if (Q->z != NULL) {
+ /* Z = Z * Z' */
+ if ((err = mp_mul(z, Q->z, z)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(z, modulus, mp)) != CRYPT_OK) { goto done; }
+ }
+
+ /* Z = Z * X */
+ if ((err = mp_mul(z, x, z)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(z, modulus, mp)) != CRYPT_OK) { goto done; }
+
+ /* T1 = T1 * X */
+ if ((err = mp_mul(t1, x, t1)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* X = X * X */
+ if ((err = mp_sqr(x, x)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(x, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* T2 = T2 * x */
+ if ((err = mp_mul(t2, x, t2)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* T1 = T1 * X */
+ if ((err = mp_mul(t1, x, t1)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; }
+
+ /* X = Y*Y */
+ if ((err = mp_sqr(y, x)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(x, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* X = X - T2 */
+ if ((err = mp_sub(x, t2, x)) != CRYPT_OK) { goto done; }
+ if (mp_cmp_d(x, 0) == LTC_MP_LT) {
+ if ((err = mp_add(x, modulus, x)) != CRYPT_OK) { goto done; }
+ }
+
+ /* T2 = T2 - X */
+ if ((err = mp_sub(t2, x, t2)) != CRYPT_OK) { goto done; }
+ if (mp_cmp_d(t2, 0) == LTC_MP_LT) {
+ if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK) { goto done; }
+ }
+ /* T2 = T2 - X */
+ if ((err = mp_sub(t2, x, t2)) != CRYPT_OK) { goto done; }
+ if (mp_cmp_d(t2, 0) == LTC_MP_LT) {
+ if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK) { goto done; }
+ }
+ /* T2 = T2 * Y */
+ if ((err = mp_mul(t2, y, t2)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* Y = T2 - T1 */
+ if ((err = mp_sub(t2, t1, y)) != CRYPT_OK) { goto done; }
+ if (mp_cmp_d(y, 0) == LTC_MP_LT) {
+ if ((err = mp_add(y, modulus, y)) != CRYPT_OK) { goto done; }
+ }
+ /* Y = Y/2 */
+ if (mp_isodd(y)) {
+ if ((err = mp_add(y, modulus, y)) != CRYPT_OK) { goto done; }
+ }
+ if ((err = mp_div_2(y, y)) != CRYPT_OK) { goto done; }
+
+ if ((err = mp_copy(x, R->x)) != CRYPT_OK) { goto done; }
+ if ((err = mp_copy(y, R->y)) != CRYPT_OK) { goto done; }
+ if ((err = mp_copy(z, R->z)) != CRYPT_OK) { goto done; }
+
+ err = CRYPT_OK;
+done:
+ mp_clear_multi(t1, t2, x, y, z, NULL);
+ return err;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c,v $ */
+/* $Revision: 1.13 $ */
+/* $Date: 2006/12/04 05:07:59 $ */
+
diff --git a/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c b/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c
new file mode 100644
index 0000000..f0b3e1d
--- /dev/null
+++ b/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c
@@ -0,0 +1,147 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
+ */
+
+/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
+ *
+ * All curves taken from NIST recommendation paper of July 1999
+ * Available at http://csrc.nist.gov/cryptval/dss.htm
+ */
+#include "tomcrypt.h"
+
+/**
+ @file ltc_ecc_projective_dbl_point.c
+ ECC Crypto, Tom St Denis
+*/
+
+#if defined(MECC) && (!defined(MECC_ACCEL) || defined(LTM_DESC))
+
+/**
+ Double an ECC point
+ @param P The point to double
+ @param R [out] The destination of the double
+ @param modulus The modulus of the field the ECC curve is in
+ @param mp The "b" value from montgomery_setup()
+ @return CRYPT_OK on success
+*/
+int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulus, void *mp)
+{
+ void *t1, *t2;
+ int err;
+
+ LTC_ARGCHK(P != NULL);
+ LTC_ARGCHK(R != NULL);
+ LTC_ARGCHK(modulus != NULL);
+ LTC_ARGCHK(mp != NULL);
+
+ if ((err = mp_init_multi(&t1, &t2, NULL)) != CRYPT_OK) {
+ return err;
+ }
+
+ if (P != R) {
+ if ((err = mp_copy(P->x, R->x)) != CRYPT_OK) { goto done; }
+ if ((err = mp_copy(P->y, R->y)) != CRYPT_OK) { goto done; }
+ if ((err = mp_copy(P->z, R->z)) != CRYPT_OK) { goto done; }
+ }
+
+ /* t1 = Z * Z */
+ if ((err = mp_sqr(R->z, t1)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* Z = Y * Z */
+ if ((err = mp_mul(R->z, R->y, R->z)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(R->z, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* Z = 2Z */
+ if ((err = mp_add(R->z, R->z, R->z)) != CRYPT_OK) { goto done; }
+ if (mp_cmp(R->z, modulus) != LTC_MP_LT) {
+ if ((err = mp_sub(R->z, modulus, R->z)) != CRYPT_OK) { goto done; }
+ }
+
+ /* T2 = X - T1 */
+ if ((err = mp_sub(R->x, t1, t2)) != CRYPT_OK) { goto done; }
+ if (mp_cmp_d(t2, 0) == LTC_MP_LT) {
+ if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK) { goto done; }
+ }
+ /* T1 = X + T1 */
+ if ((err = mp_add(t1, R->x, t1)) != CRYPT_OK) { goto done; }
+ if (mp_cmp(t1, modulus) != LTC_MP_LT) {
+ if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; }
+ }
+ /* T2 = T1 * T2 */
+ if ((err = mp_mul(t1, t2, t2)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* T1 = 2T2 */
+ if ((err = mp_add(t2, t2, t1)) != CRYPT_OK) { goto done; }
+ if (mp_cmp(t1, modulus) != LTC_MP_LT) {
+ if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; }
+ }
+ /* T1 = T1 + T2 */
+ if ((err = mp_add(t1, t2, t1)) != CRYPT_OK) { goto done; }
+ if (mp_cmp(t1, modulus) != LTC_MP_LT) {
+ if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; }
+ }
+
+ /* Y = 2Y */
+ if ((err = mp_add(R->y, R->y, R->y)) != CRYPT_OK) { goto done; }
+ if (mp_cmp(R->y, modulus) != LTC_MP_LT) {
+ if ((err = mp_sub(R->y, modulus, R->y)) != CRYPT_OK) { goto done; }
+ }
+ /* Y = Y * Y */
+ if ((err = mp_sqr(R->y, R->y)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(R->y, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* T2 = Y * Y */
+ if ((err = mp_sqr(R->y, t2)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* T2 = T2/2 */
+ if (mp_isodd(t2)) {
+ if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK) { goto done; }
+ }
+ if ((err = mp_div_2(t2, t2)) != CRYPT_OK) { goto done; }
+ /* Y = Y * X */
+ if ((err = mp_mul(R->y, R->x, R->y)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(R->y, modulus, mp)) != CRYPT_OK) { goto done; }
+
+ /* X = T1 * T1 */
+ if ((err = mp_sqr(t1, R->x)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(R->x, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* X = X - Y */
+ if ((err = mp_sub(R->x, R->y, R->x)) != CRYPT_OK) { goto done; }
+ if (mp_cmp_d(R->x, 0) == LTC_MP_LT) {
+ if ((err = mp_add(R->x, modulus, R->x)) != CRYPT_OK) { goto done; }
+ }
+ /* X = X - Y */
+ if ((err = mp_sub(R->x, R->y, R->x)) != CRYPT_OK) { goto done; }
+ if (mp_cmp_d(R->x, 0) == LTC_MP_LT) {
+ if ((err = mp_add(R->x, modulus, R->x)) != CRYPT_OK) { goto done; }
+ }
+
+ /* Y = Y - X */
+ if ((err = mp_sub(R->y, R->x, R->y)) != CRYPT_OK) { goto done; }
+ if (mp_cmp_d(R->y, 0) == LTC_MP_LT) {
+ if ((err = mp_add(R->y, modulus, R->y)) != CRYPT_OK) { goto done; }
+ }
+ /* Y = Y * T1 */
+ if ((err = mp_mul(R->y, t1, R->y)) != CRYPT_OK) { goto done; }
+ if ((err = mp_montgomery_reduce(R->y, modulus, mp)) != CRYPT_OK) { goto done; }
+ /* Y = Y - T2 */
+ if ((err = mp_sub(R->y, t2, R->y)) != CRYPT_OK) { goto done; }
+ if (mp_cmp_d(R->y, 0) == LTC_MP_LT) {
+ if ((err = mp_add(R->y, modulus, R->y)) != CRYPT_OK) { goto done; }
+ }
+
+ err = CRYPT_OK;
+done:
+ mp_clear_multi(t1, t2, NULL);
+ return err;
+}
+#endif
+/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c,v $ */
+/* $Revision: 1.8 $ */
+/* $Date: 2006/12/04 05:07:59 $ */
+