format of curve25519 key

This commit is contained in:
Jacob Barthelmeh
2015-03-05 15:38:07 -07:00
parent 450ccea7ee
commit 7ef362d4ba
3 changed files with 120 additions and 72 deletions

View File

@@ -38,8 +38,6 @@
#include <wolfcrypt/src/misc.c> #include <wolfcrypt/src/misc.c>
#endif #endif
#define MONTGOMERY_X_LE 65
const ecc25519_set_type ecc25519_sets[] = { const ecc25519_set_type ecc25519_sets[] = {
{ {
32, 32,
@@ -102,7 +100,7 @@ int wc_ecc25519_make_key(RNG* rng, int keysize, ecc25519_key* key)
unsigned char n[ECC25519_KEYSIZE]; unsigned char n[ECC25519_KEYSIZE];
unsigned char p[ECC25519_KEYSIZE]; unsigned char p[ECC25519_KEYSIZE];
int i; int i;
int err; int ret;
if (key == NULL || rng == NULL) if (key == NULL || rng == NULL)
return ECC_BAD_ARG_E; 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; return ECC_BAD_ARG_E;
/* get random number from RNG */ /* get random number from RNG */
err = wc_RNG_GenerateBlock(rng, n, keysize); ret = wc_RNG_GenerateBlock(rng, n, keysize);
if (err != 0) if (ret != 0)
return err; return ret;
for (i = 0; i < keysize; ++i) key->k.point[i] = n[i]; for (i = 0; i < keysize; ++i) key->k.point[i] = n[i];
key->k.point[ 0] &= 248; 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; key->k.point[31] |= 64;
/*compute public key*/ /*compute public key*/
err = curve25519(p, key->k.point, basepoint); ret = curve25519(p, key->k.point, basepoint);
/* store keys in big endian format */ /* store keys in big endian format */
for (i = 0; i < keysize; ++i) n[i] = key->k.point[i]; 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(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 k[ECC25519_KEYSIZE];
unsigned char p[ECC25519_KEYSIZE]; unsigned char p[ECC25519_KEYSIZE];
int err = 0; unsigned char o[ECC25519_KEYSIZE];
int ret = 0;
int i; int i;
/* sanity check */ /* 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) if (public_key->p.point[0] > 0x7F)
return ECC_BAD_ARG_E; return ECC_BAD_ARG_E;
if (*outlen < ECC25519_KEYSIZE)
return BUFFER_E;
XMEMSET(p, 0, sizeof(p)); XMEMSET(p, 0, sizeof(p));
XMEMSET(k, 0, sizeof(k)); XMEMSET(k, 0, sizeof(k));
XMEMSET(out, 0, ECC25519_KEYSIZE); 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]; k[i] = private_key->k.point[ECC25519_KEYSIZE - i - 1];
} }
err = curve25519(out , k, p); ret = curve25519(o , k, p);
*outlen = ECC25519_KEYSIZE; *outlen = ECC25519_KEYSIZE;
for (i = 0; i < ECC25519_KEYSIZE; ++i) {
out[i] = o[ECC25519_KEYSIZE - i -1];
}
ForceZero(p, sizeof(p)); ForceZero(p, sizeof(p));
ForceZero(k, sizeof(k)); ForceZero(k, sizeof(k));
ForceZero(o, sizeof(o));
return err; return ret;
} }
/* curve25519 uses a serialized string for key representation */ /* curve25519 uses a serialized string for key representation */
int wc_ecc25519_export_public(ecc25519_key* key, byte* out, word32* outLen) int wc_ecc25519_export_public(ecc25519_key* key, byte* out, word32* outLen)
{ {
word32 keySz; word32 keySz;
byte offset;
if (key == NULL || out == NULL) if (key == NULL || out == NULL || outLen == NULL)
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
/* check size of outgoing key */ /* check size of outgoing key */
keySz = wc_ecc25519_size(key); keySz = wc_ecc25519_size(key);
offset = 2;
/* copy in public key and leave room for length and type byte */ /* copy in public key */
XMEMCPY(out + offset, key->p.point, keySz); XMEMCPY(out, key->p.point, keySz);
*outLen = keySz + offset; *outLen = keySz;
/* length and type */
out[0] = *outLen;
out[1] = key->f;
return 0; return 0;
} }
@@ -206,7 +201,6 @@ 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) int wc_ecc25519_import_public(const byte* in, word32 inLen, ecc25519_key* key)
{ {
word32 keySz; word32 keySz;
byte offset;
/* sanity check */ /* sanity check */
if (key == NULL || in == NULL) if (key == NULL || in == NULL)
@@ -214,13 +208,10 @@ int wc_ecc25519_import_public(const byte* in, word32 inLen, ecc25519_key* key)
/* check size of incoming keys */ /* check size of incoming keys */
keySz = wc_ecc25519_size(key); keySz = wc_ecc25519_size(key);
offset = 2; if (inLen != keySz)
/* check that it is correct size plus length and type */
if ((inLen != keySz + offset) || (in[1] != MONTGOMERY_X_LE))
return ECC_BAD_ARG_E; return ECC_BAD_ARG_E;
XMEMCPY(key->p.point, in + offset, inLen); XMEMCPY(key->p.point, in, inLen);
key->dp = &ecc25519_sets[0]; 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; return ECC_BAD_ARG_E;
keySz = wc_ecc25519_size(key); keySz = wc_ecc25519_size(key);
if (*outLen < keySz) {
*outLen = keySz; *outLen = keySz;
return BUFFER_E; XMEMSET(out, 0, keySz);
} XMEMCPY(out, key->k.point, keySz);
*outLen = keySz;
XMEMSET(out, 0, *outLen);
XMEMCPY(out, key->k.point, *outLen);
return 0; 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, int wc_ecc25519_import_private_raw(const byte* priv, word32 privSz,
const byte* pub, word32 pubSz, ecc25519_key* key) 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; word32 keySz;
/* sanity check */ /* sanity check */
if (key == NULL || priv == NULL || pub ==NULL) if (key == NULL || priv == NULL || pub == NULL)
return ECC_BAD_ARG_E; return ECC_BAD_ARG_E;
/* check size of incoming keys */ /* check size of incoming keys */
@@ -283,7 +270,6 @@ int wc_ecc25519_init(ecc25519_key* key)
return ECC_BAD_ARG_E; return ECC_BAD_ARG_E;
/* currently the format for curve25519 */ /* currently the format for curve25519 */
key->f = MONTGOMERY_X_LE;
key->dp = &ecc25519_sets[0]; key->dp = &ecc25519_sets[0];
keySz = key->dp->size; 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) void wc_ecc25519_free(ecc25519_key* key)
{ {
if (key == NULL) 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) int wc_ecc25519_size(ecc25519_key* key)
{ {
if (key == NULL) return 0; if (key == NULL) return 0;

View File

@@ -5162,6 +5162,50 @@ int ecc25519_test(void)
byte exportBuf[1024]; byte exportBuf[1024];
ecc25519_key userA, userB, pubKey; 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) if (wc_InitRng(&rng) != 0)
return -1001; return -1001;
@@ -5171,43 +5215,65 @@ int ecc25519_test(void)
/* make curve25519 keys */ /* make curve25519 keys */
if (wc_ecc25519_make_key(&rng, 32, &userA) != 0) if (wc_ecc25519_make_key(&rng, 32, &userA) != 0)
return -1014;
if (wc_ecc25519_make_key(&rng, 32, &userB) != 0)
return -1002; return -1002;
/* find shared secret key */ if (wc_ecc25519_make_key(&rng, 32, &userB) != 0)
x = sizeof(sharedA);
if (wc_ecc25519_shared_secret(&userA, &userB, sharedA, &x) != 0)
return -1015;
y = sizeof(sharedB);
if (wc_ecc25519_shared_secret(&userB, &userA, sharedB, &y) != 0)
return -1003; return -1003;
/* find shared secret key */
if (wc_ecc25519_shared_secret(&userA, &userB, sharedA, &x) != 0)
return -1004;
if (wc_ecc25519_shared_secret(&userB, &userA, sharedB, &y) != 0)
return -1005;
/* compare shared secret keys to test they are the same */ /* compare shared secret keys to test they are the same */
if (y != x) if (y != x)
return -1004;
if (memcmp(sharedA, sharedB, x))
return -1005;
/* 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 -1006;
if (wc_ecc25519_import_public(exportBuf, x, &pubKey) != 0) if (memcmp(sharedA, sharedB, x))
return -1007; return -1007;
/* test shared key after importing a public key */ /* export a public key and import it for another user */
y = sizeof(sharedB); if (wc_ecc25519_export_public(&userA, exportBuf, &x) != 0)
if (wc_ecc25519_shared_secret(&userB, &pubKey, sharedB, &y) != 0)
return -1008; return -1008;
if (memcmp(sharedA, sharedB, y)) if (wc_ecc25519_import_public(exportBuf, x, &pubKey) != 0)
return -1009;
/* test shared key after importing a public key */
XMEMSET(sharedB, 0, sizeof(sharedB));
if (wc_ecc25519_shared_secret(&userB, &pubKey, sharedB, &y) != 0)
return -1010; return -1010;
if (memcmp(sharedA, sharedB, y))
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 */ /* clean up keys when done */
wc_ecc25519_free(&pubKey); wc_ecc25519_free(&pubKey);
wc_ecc25519_free(&userB); wc_ecc25519_free(&userB);

View File

@@ -49,13 +49,11 @@ typedef struct {
/* An ECC25519 Key */ /* An ECC25519 Key */
typedef struct { typedef struct {
int type; /* Public or Private */
int idx; /* Index into the ecc_sets[] for the parameters of int idx; /* Index into the ecc_sets[] for the parameters of
this curve if -1, this key is using user supplied this curve if -1, this key is using user supplied
curve in dp */ curve in dp */
const ecc25519_set_type* dp; /* domain parameters, either points to const ecc25519_set_type* dp; /* domain parameters, either points to
curves (idx >= 0) or user supplied */ curves (idx >= 0) or user supplied */
byte f; /* format of key */
ECPoint p; /* public key */ ECPoint p; /* public key */
ECPoint k; /* private key */ ECPoint k; /* private key */
} ecc25519_key; } ecc25519_key;