forked from wolfSSL/wolfssl
format of curve25519 key
This commit is contained in:
@ -38,8 +38,6 @@
|
||||
#include <wolfcrypt/src/misc.c>
|
||||
#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;
|
||||
keySz = wc_ecc25519_size(key);
|
||||
if (inLen != keySz)
|
||||
return ECC_BAD_ARG_E;
|
||||
|
||||
/* check that it is correct size plus length and type */
|
||||
if ((inLen != keySz + offset) || (in[1] != MONTGOMERY_X_LE))
|
||||
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;
|
||||
|
@ -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,43 +5215,65 @@ int ecc25519_test(void)
|
||||
|
||||
/* make curve25519 keys */
|
||||
if (wc_ecc25519_make_key(&rng, 32, &userA) != 0)
|
||||
return -1014;
|
||||
|
||||
if (wc_ecc25519_make_key(&rng, 32, &userB) != 0)
|
||||
return -1002;
|
||||
|
||||
/* find shared secret key */
|
||||
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)
|
||||
if (wc_ecc25519_make_key(&rng, 32, &userB) != 0)
|
||||
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 */
|
||||
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;
|
||||
|
||||
if (wc_ecc25519_import_public(exportBuf, x, &pubKey) != 0)
|
||||
if (memcmp(sharedA, sharedB, x))
|
||||
return -1007;
|
||||
|
||||
/* test shared key after importing a public key */
|
||||
y = sizeof(sharedB);
|
||||
if (wc_ecc25519_shared_secret(&userB, &pubKey, sharedB, &y) != 0)
|
||||
/* export a public key and import it for another user */
|
||||
if (wc_ecc25519_export_public(&userA, exportBuf, &x) != 0)
|
||||
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;
|
||||
|
||||
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 */
|
||||
wc_ecc25519_free(&pubKey);
|
||||
wc_ecc25519_free(&userB);
|
||||
|
@ -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;
|
||||
|
Reference in New Issue
Block a user