From 7ef362d4bad348dceaa885ee63c1c646b20ba077 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Thu, 5 Mar 2015 15:38:07 -0700 Subject: [PATCH] format of curve25519 key --- wolfcrypt/src/ecc25519.c | 78 ++++++++++++------------------ wolfcrypt/test/test.c | 94 ++++++++++++++++++++++++++++++------ wolfssl/wolfcrypt/ecc25519.h | 2 - 3 files changed, 111 insertions(+), 63 deletions(-) diff --git a/wolfcrypt/src/ecc25519.c b/wolfcrypt/src/ecc25519.c index 2ce42c6a7ed..253b01ae927 100644 --- a/wolfcrypt/src/ecc25519.c +++ b/wolfcrypt/src/ecc25519.c @@ -38,8 +38,6 @@ #include #endif -#define MONTGOMERY_X_LE 65 - const ecc25519_set_type ecc25519_sets[] = { { 32, @@ -102,7 +100,7 @@ int wc_ecc25519_make_key(RNG* rng, int keysize, ecc25519_key* key) unsigned char n[ECC25519_KEYSIZE]; unsigned char p[ECC25519_KEYSIZE]; int i; - int err; + int ret; if (key == NULL || rng == NULL) return ECC_BAD_ARG_E; @@ -112,9 +110,9 @@ int wc_ecc25519_make_key(RNG* rng, int keysize, ecc25519_key* key) return ECC_BAD_ARG_E; /* get random number from RNG */ - err = wc_RNG_GenerateBlock(rng, n, keysize); - if (err != 0) - return err; + ret = wc_RNG_GenerateBlock(rng, n, keysize); + if (ret != 0) + return ret; for (i = 0; i < keysize; ++i) key->k.point[i] = n[i]; key->k.point[ 0] &= 248; @@ -122,7 +120,7 @@ int wc_ecc25519_make_key(RNG* rng, int keysize, ecc25519_key* key) key->k.point[31] |= 64; /*compute public key*/ - err = curve25519(p, key->k.point, basepoint); + ret = curve25519(p, key->k.point, basepoint); /* store keys in big endian format */ for (i = 0; i < keysize; ++i) n[i] = key->k.point[i]; @@ -132,8 +130,9 @@ int wc_ecc25519_make_key(RNG* rng, int keysize, ecc25519_key* key) } ForceZero(n, keysize); + ForceZero(p, keysize); - return err; + return ret; } @@ -142,7 +141,8 @@ int wc_ecc25519_shared_secret(ecc25519_key* private_key, ecc25519_key* public_ke { unsigned char k[ECC25519_KEYSIZE]; unsigned char p[ECC25519_KEYSIZE]; - int err = 0; + unsigned char o[ECC25519_KEYSIZE]; + int ret = 0; int i; /* sanity check */ @@ -154,9 +154,6 @@ int wc_ecc25519_shared_secret(ecc25519_key* private_key, ecc25519_key* public_ke if (public_key->p.point[0] > 0x7F) return ECC_BAD_ARG_E; - if (*outlen < ECC25519_KEYSIZE) - return BUFFER_E; - XMEMSET(p, 0, sizeof(p)); XMEMSET(k, 0, sizeof(k)); XMEMSET(out, 0, ECC25519_KEYSIZE); @@ -166,37 +163,35 @@ int wc_ecc25519_shared_secret(ecc25519_key* private_key, ecc25519_key* public_ke k[i] = private_key->k.point[ECC25519_KEYSIZE - i - 1]; } - err = curve25519(out , k, p); + ret = curve25519(o , k, p); *outlen = ECC25519_KEYSIZE; + for (i = 0; i < ECC25519_KEYSIZE; ++i) { + out[i] = o[ECC25519_KEYSIZE - i -1]; + } + ForceZero(p, sizeof(p)); ForceZero(k, sizeof(k)); + ForceZero(o, sizeof(o)); - return err; + return ret; } - /* curve25519 uses a serialized string for key representation */ int wc_ecc25519_export_public(ecc25519_key* key, byte* out, word32* outLen) { word32 keySz; - byte offset; - if (key == NULL || out == NULL) + if (key == NULL || out == NULL || outLen == NULL) return BAD_FUNC_ARG; /* check size of outgoing key */ keySz = wc_ecc25519_size(key); - offset = 2; - /* copy in public key and leave room for length and type byte */ - XMEMCPY(out + offset, key->p.point, keySz); - *outLen = keySz + offset; - - /* length and type */ - out[0] = *outLen; - out[1] = key->f; + /* copy in public key */ + XMEMCPY(out, key->p.point, keySz); + *outLen = keySz; return 0; } @@ -206,21 +201,17 @@ int wc_ecc25519_export_public(ecc25519_key* key, byte* out, word32* outLen) int wc_ecc25519_import_public(const byte* in, word32 inLen, ecc25519_key* key) { word32 keySz; - byte offset; /* sanity check */ if (key == NULL || in == NULL) return ECC_BAD_ARG_E; /* check size of incoming keys */ - keySz = wc_ecc25519_size(key); - offset = 2; - - /* check that it is correct size plus length and type */ - if ((inLen != keySz + offset) || (in[1] != MONTGOMERY_X_LE)) - return ECC_BAD_ARG_E; + keySz = wc_ecc25519_size(key); + if (inLen != keySz) + return ECC_BAD_ARG_E; - XMEMCPY(key->p.point, in + offset, inLen); + XMEMCPY(key->p.point, in, inLen); key->dp = &ecc25519_sets[0]; @@ -239,20 +230,16 @@ int wc_ecc25519_export_private_raw(ecc25519_key* key, byte* out, word32* outLen) return ECC_BAD_ARG_E; keySz = wc_ecc25519_size(key); - - if (*outLen < keySz) { - *outLen = keySz; - return BUFFER_E; - } *outLen = keySz; - XMEMSET(out, 0, *outLen); - XMEMCPY(out, key->k.point, *outLen); + XMEMSET(out, 0, keySz); + XMEMCPY(out, key->k.point, keySz); return 0; } -/* curve25519 private key import,public key in serialized format, private raw */ +/* curve25519 private key import. + Public key to match private key needs to be imported too */ int wc_ecc25519_import_private_raw(const byte* priv, word32 privSz, const byte* pub, word32 pubSz, ecc25519_key* key) { @@ -260,7 +247,7 @@ int wc_ecc25519_import_private_raw(const byte* priv, word32 privSz, word32 keySz; /* sanity check */ - if (key == NULL || priv == NULL || pub ==NULL) + if (key == NULL || priv == NULL || pub == NULL) return ECC_BAD_ARG_E; /* check size of incoming keys */ @@ -283,7 +270,6 @@ int wc_ecc25519_init(ecc25519_key* key) return ECC_BAD_ARG_E; /* currently the format for curve25519 */ - key->f = MONTGOMERY_X_LE; key->dp = &ecc25519_sets[0]; keySz = key->dp->size; @@ -294,9 +280,7 @@ int wc_ecc25519_init(ecc25519_key* key) } -/** - Clean the memory of a key -*/ +/* Clean the memory of a key */ void wc_ecc25519_free(ecc25519_key* key) { if (key == NULL) @@ -308,7 +292,7 @@ void wc_ecc25519_free(ecc25519_key* key) } -/* key size */ +/* get key size */ int wc_ecc25519_size(ecc25519_key* key) { if (key == NULL) return 0; diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index b3788034c12..200c07f18a4 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -5162,6 +5162,50 @@ int ecc25519_test(void) byte exportBuf[1024]; ecc25519_key userA, userB, pubKey; + /* test vectors from + https://tools.ietf.org/html/draft-josefsson-tls-curve25519-03 + */ + + /* secret key for party a */ + byte sa[] = { + 0x5A,0xC9,0x9F,0x33,0x63,0x2E,0x5A,0x76, + 0x8D,0xE7,0xE8,0x1B,0xF8,0x54,0xC2,0x7C, + 0x46,0xE3,0xFB,0xF2,0xAB,0xBA,0xCD,0x29, + 0xEC,0x4A,0xFF,0x51,0x73,0x69,0xC6,0x60 + }; + + /* public key for party a */ + byte pa[] = { + 0x05,0x7E,0x23,0xEA,0x9F,0x1C,0xBE,0x8A, + 0x27,0x16,0x8F,0x6E,0x69,0x6A,0x79,0x1D, + 0xE6,0x1D,0xD3,0xAF,0x7A,0xCD,0x4E,0xEA, + 0xCC,0x6E,0x7B,0xA5,0x14,0xFD,0xA8,0x63 + }; + + /* secret key for party b */ + byte sb[] = { + 0x47,0xDC,0x3D,0x21,0x41,0x74,0x82,0x0E, + 0x11,0x54,0xB4,0x9B,0xC6,0xCD,0xB2,0xAB, + 0xD4,0x5E,0xE9,0x58,0x17,0x05,0x5D,0x25, + 0x5A,0xA3,0x58,0x31,0xB7,0x0D,0x32,0x60 + }; + + /* public key for party b */ + byte pb[] = { + 0x6E,0xB8,0x9D,0xA9,0x19,0x89,0xAE,0x37, + 0xC7,0xEA,0xC7,0x61,0x8D,0x9E,0x5C,0x49, + 0x51,0xDB,0xA1,0xD7,0x3C,0x28,0x5A,0xE1, + 0xCD,0x26,0xA8,0x55,0x02,0x0E,0xEF,0x04 + }; + + /* expected shared key */ + byte ss[] = { + 0x61,0x45,0x0C,0xD9,0x8E,0x36,0x01,0x6B, + 0x58,0x77,0x6A,0x89,0x7A,0x9F,0x0A,0xEF, + 0x73,0x8B,0x99,0xF0,0x94,0x68,0xB8,0xD6, + 0xB8,0x51,0x11,0x84,0xD5,0x34,0x94,0xAB + }; + if (wc_InitRng(&rng) != 0) return -1001; @@ -5171,42 +5215,64 @@ int ecc25519_test(void) /* make curve25519 keys */ if (wc_ecc25519_make_key(&rng, 32, &userA) != 0) - return -1014; + return -1002; if (wc_ecc25519_make_key(&rng, 32, &userB) != 0) - return -1002; + return -1003; /* find shared secret key */ - x = sizeof(sharedA); if (wc_ecc25519_shared_secret(&userA, &userB, sharedA, &x) != 0) - return -1015; + return -1004; - y = sizeof(sharedB); if (wc_ecc25519_shared_secret(&userB, &userA, sharedB, &y) != 0) - return -1003; + return -1005; /* compare shared secret keys to test they are the same */ if (y != x) - return -1004; + return -1006; if (memcmp(sharedA, sharedB, x)) - return -1005; + return -1007; /* export a public key and import it for another user */ - x = sizeof(exportBuf); if (wc_ecc25519_export_public(&userA, exportBuf, &x) != 0) - return -1006; + return -1008; if (wc_ecc25519_import_public(exportBuf, x, &pubKey) != 0) - return -1007; + return -1009; /* test shared key after importing a public key */ - y = sizeof(sharedB); + XMEMSET(sharedB, 0, sizeof(sharedB)); if (wc_ecc25519_shared_secret(&userB, &pubKey, sharedB, &y) != 0) - return -1008; + return -1010; if (memcmp(sharedA, sharedB, y)) - return -1010; + return -1011; + + /* import RFC test vectors and compare shared key */ + if (wc_ecc25519_import_private_raw(sa, sizeof(sa), pa, sizeof(pa), &userA) + != 0) + return -1012; + + if (wc_ecc25519_import_private_raw(sb, sizeof(sb), pb, sizeof(pb), &userB) + != 0) + return -1013; + + /* test against known test vector */ + XMEMSET(sharedB, 0, sizeof(sharedB)); + if (wc_ecc25519_shared_secret(&userA, &userB, sharedB, &y) != 0) + return -1014; + + if (memcmp(ss, sharedB, y)) + return -1015; + + /* test swaping roles of keys and generating same shared key */ + XMEMSET(sharedB, 0, sizeof(sharedB)); + if (wc_ecc25519_shared_secret(&userB, &userA, sharedB, &y) != 0) + return -1016; + + if (memcmp(ss, sharedB, y)) + return -1017; /* clean up keys when done */ wc_ecc25519_free(&pubKey); diff --git a/wolfssl/wolfcrypt/ecc25519.h b/wolfssl/wolfcrypt/ecc25519.h index 9a910b40f1c..8d26a35dd5f 100644 --- a/wolfssl/wolfcrypt/ecc25519.h +++ b/wolfssl/wolfcrypt/ecc25519.h @@ -49,13 +49,11 @@ typedef struct { /* An ECC25519 Key */ typedef struct { - int type; /* Public or Private */ int idx; /* Index into the ecc_sets[] for the parameters of this curve if -1, this key is using user supplied curve in dp */ const ecc25519_set_type* dp; /* domain parameters, either points to curves (idx >= 0) or user supplied */ - byte f; /* format of key */ ECPoint p; /* public key */ ECPoint k; /* private key */ } ecc25519_key;