add support for curve 25519 and Ed25519 in OpenSSH

refactor curve25519 and Ed25519 code
fix warning in PEM_xxx_mem_xxx functions
pull/113/head
Ludovic FLAMENT 2015-08-01 18:28:18 +02:00
parent e363848ecc
commit 409126a97c
15 changed files with 888 additions and 204 deletions

View File

@ -733,6 +733,11 @@ AC_ARG_ENABLE([curve25519],
)
if test "$ENABLED_OPENSSH" = "yes"
then
ENABLED_CURVE25519="yes"
fi
if test "$ENABLED_CURVE25519" = "small"
then
AM_CFLAGS="$AM_CFLAGS -DCURVED25519_SMALL"
@ -758,6 +763,11 @@ AC_ARG_ENABLE([ed25519],
)
if test "$ENABLED_OPENSSH" = "yes"
then
ENABLED_ED25519="yes"
fi
if test "$ENABLED_ED25519" = "small"
then
AM_CFLAGS="$AM_CFLAGS -DCURVED25519_SMALL"

View File

@ -0,0 +1,3 @@
/* ec25519.h */
#include <wolfssl/openssl/ec25519.h>

View File

@ -0,0 +1,3 @@
/* ed25519.h */
#include <wolfssl/openssl/ed25519.h>

View File

@ -13,6 +13,8 @@ nobase_include_HEADERS+= \
cyassl/openssl/ecdsa.h \
cyassl/openssl/ecdh.h \
cyassl/openssl/ec.h \
cyassl/openssl/ec25519.h \
cyassl/openssl/ed25519.h \
cyassl/openssl/engine.h \
cyassl/openssl/err.h \
cyassl/openssl/evp.h \

323
src/ssl.c
View File

@ -48,6 +48,8 @@
#include <wolfssl/openssl/rsa.h>
#include <wolfssl/openssl/pem.h>
#include <wolfssl/openssl/ec.h>
#include <wolfssl/openssl/ec25519.h>
#include <wolfssl/openssl/ed25519.h>
#include <wolfssl/openssl/ecdsa.h>
#include <wolfssl/openssl/ecdh.h>
/* openssl headers end, wolfssl internal headers next */
@ -57,6 +59,8 @@
#include <wolfssl/wolfcrypt/md4.h>
#include <wolfssl/wolfcrypt/md5.h>
#include <wolfssl/wolfcrypt/arc4.h>
#include <wolfssl/wolfcrypt/curve25519.h>
#include <wolfssl/wolfcrypt/ed25519.h>
#ifdef WOLFSSL_SHA512
#include <wolfssl/wolfcrypt/sha512.h>
#endif
@ -12632,8 +12636,7 @@ int wolfSSL_DSA_generate_key(WOLFSSL_DSA* dsa)
return SSL_FAILURE;
}
if (dsa->inSet == 0)
{
if (dsa->inSet == 0) {
WOLFSSL_MSG("No DSA internal set, do it");
if (SetDsaInternal(dsa) != SSL_SUCCESS) {
@ -13493,7 +13496,7 @@ static int EncryptDerKey(byte *der, int *derSz, const EVP_CIPHER* cipher,
*/
int wolfSSL_PEM_write_mem_RSAPrivateKey(RSA* rsa, const EVP_CIPHER* cipher,
unsigned char* passwd, int passwdSz,
byte **pem, int *plen)
unsigned char **pem, int *plen)
{
byte *der, *tmp, *cipherInfo = NULL;
int der_max_len = 0, derSz = 0;
@ -14864,7 +14867,7 @@ int wolfSSL_PEM_write_bio_ECPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EC_KEY* ecc,
int wolfSSL_PEM_write_mem_ECPrivateKey(WOLFSSL_EC_KEY* ecc,
const EVP_CIPHER* cipher,
unsigned char* passwd, int passwdSz,
byte **pem, int *plen)
unsigned char **pem, int *plen)
{
byte *der, *tmp, *cipherInfo = NULL;
int der_max_len = 0, derSz = 0;
@ -15037,7 +15040,7 @@ int wolfSSL_PEM_write_bio_DSAPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_DSA* dsa,
int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa,
const EVP_CIPHER* cipher,
unsigned char* passwd, int passwdSz,
byte **pem, int *plen)
unsigned char **pem, int *plen)
{
byte *der, *tmp, *cipherInfo = NULL;
int der_max_len = 0, derSz = 0;
@ -16327,3 +16330,313 @@ const byte* wolfSSL_SESSION_get_id(WOLFSSL_SESSION* sess, unsigned int* idLen)
return sess->sessionID;
}
#endif /* OPENSSL_EXTRA and HAVE_STUNNEL */
#if defined(OPENSSL_EXTRA) && defined(HAVE_CURVE25519)
/* return 1 if success, 0 if error
* output keys are little endian format
*/
int wolfSSL_EC25519_generate_key(unsigned char *priv, unsigned int *privSz,
unsigned char *pub, unsigned int *pubSz)
{
#ifndef WOLFSSL_KEY_GEN
WOLFSSL_MSG("No Key Gen built in");
return SSL_FAILURE;
#else /* WOLFSSL_KEY_GEN */
int ret = SSL_FAILURE;
int initTmpRng = 0;
RNG *rng = NULL;
#ifdef WOLFSSL_SMALL_STACK
RNG *tmpRNG = NULL;
#else
RNG tmpRNG[1];
#endif
WOLFSSL_ENTER("wolfSSL_EC25519_generate_key");
if (priv == NULL || privSz == NULL || *privSz < CURVE25519_KEYSIZE ||
pub == NULL || pubSz == NULL || *pubSz < CURVE25519_KEYSIZE) {
WOLFSSL_MSG("Bad arguments");
return SSL_FAILURE;
}
#ifdef WOLFSSL_SMALL_STACK
tmpRNG = (RNG*)XMALLOC(sizeof(RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (tmpRNG == NULL)
return SSL_FAILURE;
#endif
if (wc_InitRng(tmpRNG) == 0) {
rng = tmpRNG;
initTmpRng = 1;
}
else {
WOLFSSL_MSG("Bad RNG Init, trying global");
if (initGlobalRNG == 0)
WOLFSSL_MSG("Global RNG no Init");
else
rng = &globalRNG;
}
if (rng) {
curve25519_key key;
if (wc_curve25519_init(&key) != MP_OKAY)
WOLFSSL_MSG("wc_curve25519_init failed");
else if (wc_curve25519_make_key(rng, CURVE25519_KEYSIZE, &key)!=MP_OKAY)
WOLFSSL_MSG("wc_curve25519_make_key failed");
/* export key pair */
else if (wc_curve25519_export_key_raw_ex(&key, priv, privSz, pub,
pubSz, EC25519_LITTLE_ENDIAN)
!= MP_OKAY)
WOLFSSL_MSG("wc_curve25519_export_key_raw_ex failed");
else
ret = SSL_SUCCESS;
wc_curve25519_free(&key);
}
if (initTmpRng)
wc_FreeRng(tmpRNG);
#ifdef WOLFSSL_SMALL_STACK
XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ret;
#endif /* WOLFSSL_KEY_GEN */
}
/* return 1 if success, 0 if error
* input and output keys are little endian format
*/
int wolfSSL_EC25519_shared_key(unsigned char *shared, unsigned int *sharedSz,
const unsigned char *priv, unsigned int privSz,
const unsigned char *pub, unsigned int pubSz)
{
#ifndef WOLFSSL_KEY_GEN
WOLFSSL_MSG("No Key Gen built in");
return SSL_FAILURE;
#else /* WOLFSSL_KEY_GEN */
int ret = SSL_FAILURE;
curve25519_key privkey, pubkey;
WOLFSSL_ENTER("wolfSSL_EC25519_shared_key");
if (shared == NULL || sharedSz == NULL || *sharedSz < CURVE25519_KEYSIZE ||
priv == NULL || privSz < CURVE25519_KEYSIZE ||
pub == NULL || pubSz < CURVE25519_KEYSIZE) {
WOLFSSL_MSG("Bad arguments");
return SSL_FAILURE;
}
/* import private key */
if (wc_curve25519_init(&privkey) != MP_OKAY) {
WOLFSSL_MSG("wc_curve25519_init privkey failed");
return ret;
}
if (wc_curve25519_import_private_ex(priv, privSz, &privkey,
EC25519_LITTLE_ENDIAN) != MP_OKAY) {
WOLFSSL_MSG("wc_curve25519_import_private_ex failed");
wc_curve25519_free(&privkey);
return ret;
}
/* import public key */
if (wc_curve25519_init(&pubkey) != MP_OKAY) {
WOLFSSL_MSG("wc_curve25519_init pubkey failed");
wc_curve25519_free(&privkey);
return ret;
}
if (wc_curve25519_import_public_ex(pub, pubSz, &pubkey,
EC25519_LITTLE_ENDIAN) != MP_OKAY) {
WOLFSSL_MSG("wc_curve25519_import_public_ex failed");
wc_curve25519_free(&privkey);
wc_curve25519_free(&pubkey);
return ret;
}
if (wc_curve25519_shared_secret_ex(&privkey, &pubkey,
shared, sharedSz,
EC25519_LITTLE_ENDIAN) != MP_OKAY)
WOLFSSL_MSG("wc_curve25519_shared_secret_ex failed");
else
ret = SSL_SUCCESS;
wc_curve25519_free(&privkey);
wc_curve25519_free(&pubkey);
return ret;
#endif /* WOLFSSL_KEY_GEN */
}
#endif /* OPENSSL_EXTRA && HAVE_CURVE25519 */
#if defined(OPENSSL_EXTRA) && defined(HAVE_ED25519)
/* return 1 if success, 0 if error
* output keys are little endian format
*/
int wolfSSL_ED25519_generate_key(unsigned char *priv, unsigned int *privSz,
unsigned char *pub, unsigned int *pubSz)
{
#ifndef WOLFSSL_KEY_GEN
WOLFSSL_MSG("No Key Gen built in");
return SSL_FAILURE;
#else /* WOLFSSL_KEY_GEN */
int ret = SSL_FAILURE;
int initTmpRng = 0;
RNG *rng = NULL;
#ifdef WOLFSSL_SMALL_STACK
RNG *tmpRNG = NULL;
#else
RNG tmpRNG[1];
#endif
WOLFSSL_ENTER("wolfSSL_ED25519_generate_key");
if (priv == NULL || privSz == NULL || *privSz < ED25519_PRV_KEY_SIZE ||
pub == NULL || pubSz == NULL || *pubSz < ED25519_PUB_KEY_SIZE) {
WOLFSSL_MSG("Bad arguments");
return SSL_FAILURE;
}
#ifdef WOLFSSL_SMALL_STACK
tmpRNG = (RNG*)XMALLOC(sizeof(RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (tmpRNG == NULL)
return SSL_FATAL_ERROR;
#endif
if (wc_InitRng(tmpRNG) == 0) {
rng = tmpRNG;
initTmpRng = 1;
}
else {
WOLFSSL_MSG("Bad RNG Init, trying global");
if (initGlobalRNG == 0)
WOLFSSL_MSG("Global RNG no Init");
else
rng = &globalRNG;
}
if (rng) {
ed25519_key key;
if (wc_ed25519_init(&key) != MP_OKAY)
WOLFSSL_MSG("wc_ed25519_init failed");
else if (wc_ed25519_make_key(rng, ED25519_KEY_SIZE, &key)!=MP_OKAY)
WOLFSSL_MSG("wc_ed25519_make_key failed");
/* export private key */
else if (wc_ed25519_export_key(&key, priv, privSz, pub, pubSz)!=MP_OKAY)
WOLFSSL_MSG("wc_ed25519_export_key failed");
else
ret = SSL_SUCCESS;
wc_ed25519_free(&key);
}
if (initTmpRng)
wc_FreeRng(tmpRNG);
#ifdef WOLFSSL_SMALL_STACK
XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ret;
#endif /* WOLFSSL_KEY_GEN */
}
/* return 1 if success, 0 if error
* input and output keys are little endian format
* priv is a buffer containing private and public part of key
*/
int wolfSSL_ED25519_sign(const unsigned char *msg, unsigned int msgSz,
const unsigned char *priv, unsigned int privSz,
unsigned char *sig, unsigned int *sigSz)
{
#ifndef WOLFSSL_KEY_GEN
WOLFSSL_MSG("No Key Gen built in");
return SSL_FAILURE;
#else /* WOLFSSL_KEY_GEN */
ed25519_key key;
int ret = SSL_FAILURE;
WOLFSSL_ENTER("wolfSSL_ED25519_sign");
if (priv == NULL || privSz != ED25519_PRV_KEY_SIZE ||
msg == NULL || sig == NULL || *sigSz < ED25519_SIG_SIZE) {
WOLFSSL_MSG("Bad arguments");
return SSL_FAILURE;
}
/* import key */
if (wc_ed25519_init(&key) != MP_OKAY) {
WOLFSSL_MSG("wc_curve25519_init failed");
return ret;
}
if (wc_ed25519_import_private_key(priv, privSz/2,
priv+(privSz/2), ED25519_PUB_KEY_SIZE,
&key) != MP_OKAY){
WOLFSSL_MSG("wc_ed25519_import_private failed");
wc_ed25519_free(&key);
return ret;
}
if (wc_ed25519_sign_msg(msg, msgSz, sig, sigSz, &key) != MP_OKAY)
WOLFSSL_MSG("wc_curve25519_shared_secret_ex failed");
else
ret = SSL_SUCCESS;
wc_ed25519_free(&key);
return ret;
#endif /* WOLFSSL_KEY_GEN */
}
/* return 1 if success, 0 if error
* input and output keys are little endian format
* pub is a buffer containing public part of key
*/
int wolfSSL_ED25519_verify(const unsigned char *msg, unsigned int msgSz,
const unsigned char *pub, unsigned int pubSz,
const unsigned char *sig, unsigned int sigSz)
{
#ifndef WOLFSSL_KEY_GEN
WOLFSSL_MSG("No Key Gen built in");
return SSL_FAILURE;
#else /* WOLFSSL_KEY_GEN */
ed25519_key key;
int ret = SSL_FAILURE, check = 0;
WOLFSSL_ENTER("wolfSSL_ED25519_verify");
if (pub == NULL || pubSz != ED25519_PUB_KEY_SIZE ||
msg == NULL || sig == NULL || sigSz != ED25519_SIG_SIZE) {
WOLFSSL_MSG("Bad arguments");
return SSL_FAILURE;
}
/* import key */
if (wc_ed25519_init(&key) != MP_OKAY) {
WOLFSSL_MSG("wc_curve25519_init failed");
return ret;
}
if (wc_ed25519_import_public(pub, pubSz, &key) != MP_OKAY){
WOLFSSL_MSG("wc_ed25519_import_public failed");
wc_ed25519_free(&key);
return ret;
}
if ((ret = wc_ed25519_verify_msg((byte*)sig, sigSz, msg, msgSz,
&check, &key)) != MP_OKAY) {
WOLFSSL_MSG("wc_ed25519_verify_msg failed");
fprintf(stderr, "err code = %d, sigSz=%d, msgSz=%d\n", ret, sigSz, msgSz);
}
else if (!check)
WOLFSSL_MSG("wc_ed25519_verify_msg failed (signature invalid)");
else
ret = SSL_SUCCESS;
wc_ed25519_free(&key);
return ret;
#endif /* WOLFSSL_KEY_GEN */
}
#endif /* OPENSSL_EXTRA && HAVE_ED25519 */

View File

@ -46,94 +46,96 @@ const curve25519_set_type curve25519_sets[] = {
};
int wc_curve25519_make_key(RNG* rng, int keysize, curve25519_key* key)
{
unsigned char basepoint[CURVE25519_KEYSIZE] = {9};
unsigned char n[CURVE25519_KEYSIZE];
unsigned char p[CURVE25519_KEYSIZE];
int i;
int ret;
unsigned char basepoint[CURVE25519_KEYSIZE] = {9};
int ret;
if (key == NULL || rng == NULL)
return ECC_BAD_ARG_E;
if (key == NULL || rng == NULL)
return BAD_FUNC_ARG;
/* currently only a key size of 32 bytes is used */
if (keysize != CURVE25519_KEYSIZE)
return ECC_BAD_ARG_E;
/* currently only a key size of 32 bytes is used */
if (keysize != CURVE25519_KEYSIZE)
return ECC_BAD_ARG_E;
/* get random number from RNG */
ret = wc_RNG_GenerateBlock(rng, n, keysize);
if (ret != 0)
return ret;
/* random number for private key */
ret = wc_RNG_GenerateBlock(rng, key->k.point, keysize);
if (ret != 0)
return ret;
for (i = 0; i < keysize; ++i) key->k.point[i] = n[i];
key->k.point[ 0] &= 248;
key->k.point[31] &= 127;
key->k.point[31] |= 64;
/* Clamp the private key */
key->k.point[0] &= 248;
key->k.point[CURVE25519_KEYSIZE-1] &= 63; /* same &=127 because |=64 after */
key->k.point[CURVE25519_KEYSIZE-1] |= 64;
/* compute public key */
ret = curve25519(p, key->k.point, basepoint);
/* compute public key */
ret = curve25519(key->p.point, key->k.point, basepoint);
if (ret != 0) {
ForceZero(key->k.point, keysize);
ForceZero(key->p.point, keysize);
return ret;
}
/* store keys in big endian format */
for (i = 0; i < keysize; ++i) n[i] = key->k.point[i];
for (i = 0; i < keysize; ++i) {
key->p.point[keysize - i - 1] = p[i];
key->k.point[keysize - i - 1] = n[i];
}
ForceZero(n, keysize);
ForceZero(p, keysize);
return ret;
return ret;
}
int wc_curve25519_shared_secret(curve25519_key* private_key,
curve25519_key* public_key,
byte* out, word32* outlen)
{
unsigned char k[CURVE25519_KEYSIZE];
unsigned char p[CURVE25519_KEYSIZE];
return wc_curve25519_shared_secret_ex(private_key, public_key,
out, outlen, EC25519_BIG_ENDIAN);
}
int wc_curve25519_shared_secret_ex(curve25519_key* private_key,
curve25519_key* public_key,
byte* out, word32* outlen, int endian)
{
unsigned char o[CURVE25519_KEYSIZE];
int ret = 0;
int i;
/* sanity check */
if (private_key == NULL || public_key == NULL || out == NULL ||
outlen == NULL)
if (private_key == NULL || public_key == NULL ||
out == NULL || outlen == NULL || *outlen < CURVE25519_KEYSIZE)
return BAD_FUNC_ARG;
/* avoid implementation fingerprinting */
if (public_key->p.point[0] > 0x7F)
if (public_key->p.point[CURVE25519_KEYSIZE-1] > 0x7F)
return ECC_BAD_ARG_E;
XMEMSET(p, 0, sizeof(p));
XMEMSET(k, 0, sizeof(k));
XMEMSET(out, 0, CURVE25519_KEYSIZE);
for (i = 0; i < CURVE25519_KEYSIZE; ++i) {
p[i] = public_key->p.point [CURVE25519_KEYSIZE - i - 1];
k[i] = private_key->k.point[CURVE25519_KEYSIZE - i - 1];
ret = curve25519(o, private_key->k.point, public_key->p.point);
if (ret != 0) {
ForceZero(o, CURVE25519_KEYSIZE);
return ret;
}
ret = curve25519(o , k, p);
if (endian == EC25519_BIG_ENDIAN) {
int i;
/* put shared secret key in Big Endian format */
for (i = 0; i < CURVE25519_KEYSIZE; i++)
out[i] = o[CURVE25519_KEYSIZE - i -1];
}
else /* put shared secret key in Little Endian format */
XMEMCPY(out, o, CURVE25519_KEYSIZE);
*outlen = CURVE25519_KEYSIZE;
for (i = 0; i < CURVE25519_KEYSIZE; ++i) {
out[i] = o[CURVE25519_KEYSIZE - i -1];
}
ForceZero(p, sizeof(p));
ForceZero(k, sizeof(k));
ForceZero(o, sizeof(o));
return ret;
}
/* curve25519 uses a serialized string for key representation */
/* export curve25519 public key (Big endian)
* return 0 on success */
int wc_curve25519_export_public(curve25519_key* key, byte* out, word32* outLen)
{
return wc_curve25519_export_public_ex(key, out, outLen, EC25519_BIG_ENDIAN);
}
/* export curve25519 public key (Big or Little endian)
* return 0 on success */
int wc_curve25519_export_public_ex(curve25519_key* key, byte* out,
word32* outLen, int endian)
{
word32 keySz;
@ -143,30 +145,59 @@ int wc_curve25519_export_public(curve25519_key* key, byte* out, word32* outLen)
/* check size of outgoing key */
keySz = wc_curve25519_size(key);
/* copy in public key */
XMEMCPY(out, key->p.point, keySz);
/* check and set outgoing key size */
if (*outLen < keySz) {
*outLen = keySz;
return ECC_BAD_ARG_E;
}
*outLen = keySz;
if (endian == EC25519_BIG_ENDIAN) {
int i;
/* read keys in Big Endian format */
for (i = 0; i < CURVE25519_KEYSIZE; i++)
out[i] = key->p.point[CURVE25519_KEYSIZE - i - 1];
}
else
XMEMCPY(out, key->p.point, keySz);
return 0;
}
/* import curve25519 public key
return 0 on success */
/* import curve25519 public key (Big endian)
* return 0 on success */
int wc_curve25519_import_public(const byte* in, word32 inLen,
curve25519_key* key)
{
return wc_curve25519_import_public_ex(in, inLen, key, EC25519_BIG_ENDIAN);
}
/* import curve25519 public key (Big or Little endian)
* return 0 on success */
int wc_curve25519_import_public_ex(const byte* in, word32 inLen,
curve25519_key* key, int endian)
{
word32 keySz;
/* sanity check */
if (key == NULL || in == NULL)
return ECC_BAD_ARG_E;
return BAD_FUNC_ARG;
/* check size of incoming keys */
keySz = wc_curve25519_size(key);
if (inLen != keySz)
return ECC_BAD_ARG_E;
XMEMCPY(key->p.point, in, inLen);
if (endian == EC25519_BIG_ENDIAN) {
int i;
/* read keys in Big Endian format */
for (i = 0; i < CURVE25519_KEYSIZE; i++)
key->p.point[i] = in[CURVE25519_KEYSIZE - i - 1];
}
else
XMEMCPY(key->p.point, in, inLen);
key->dp = &curve25519_sets[0];
@ -174,63 +205,159 @@ int wc_curve25519_import_public(const byte* in, word32 inLen,
}
/* export curve25519 private key only raw, outLen is in/out size
return 0 on success */
/* export curve25519 private key only raw (Big endian)
* outLen is in/out size
* return 0 on success */
int wc_curve25519_export_private_raw(curve25519_key* key, byte* out,
word32* outLen)
{
return wc_curve25519_export_private_raw_ex(key, out, outLen,
EC25519_BIG_ENDIAN);
}
/* export curve25519 private key only raw (Big or Little endian)
* outLen is in/out size
* return 0 on success */
int wc_curve25519_export_private_raw_ex(curve25519_key* key, byte* out,
word32* outLen, int endian)
{
word32 keySz;
/* sanity check */
if (key == NULL || out == NULL || outLen == NULL)
return ECC_BAD_ARG_E;
return BAD_FUNC_ARG;
/* check size of outgoing buffer */
keySz = wc_curve25519_size(key);
if (*outLen < keySz) {
*outLen = keySz;
return ECC_BAD_ARG_E;
}
*outLen = keySz;
XMEMSET(out, 0, keySz);
XMEMCPY(out, key->k.point, keySz);
if (endian == EC25519_BIG_ENDIAN) {
int i;
/* put the key in Big Endian format */
for (i = 0; i < CURVE25519_KEYSIZE; i++)
out[i] = key->k.point[CURVE25519_KEYSIZE - i - 1];
}
else
XMEMCPY(out, key->k.point, keySz);
return 0;
}
/* curve25519 private key import.
Public key to match private key needs to be imported too */
int wc_curve25519_import_private_raw(const byte* priv, word32 privSz,
const byte* pub, word32 pubSz, curve25519_key* key)
/* curve25519 key pair export (Big or Little endian)
* return 0 on success */
int wc_curve25519_export_key_raw(curve25519_key* key,
byte* priv, word32 *privSz,
byte* pub, word32 *pubSz)
{
int ret = 0;
word32 keySz;
return wc_curve25519_export_key_raw_ex(key, priv, privSz,
pub, pubSz, EC25519_BIG_ENDIAN);
}
/* sanity check */
if (key == NULL || priv == NULL || pub == NULL)
return ECC_BAD_ARG_E;
/* curve25519 key pair export (Big or Little endian)
* return 0 on success */
int wc_curve25519_export_key_raw_ex(curve25519_key* key,
byte* priv, word32 *privSz,
byte* pub, word32 *pubSz,
int endian)
{
int ret;
/* check size of incoming keys */
keySz = wc_curve25519_size(key);
if (privSz != keySz || pubSz != keySz)
return ECC_BAD_ARG_E;
/* export private part */
ret = wc_curve25519_export_private_raw_ex(key, priv, privSz, endian);
if (ret != 0)
return ret;
XMEMCPY(key->k.point, priv, privSz);
XMEMCPY(key->p.point, pub, pubSz);
return ret;
/* export public part */
return wc_curve25519_export_public_ex(key, pub, pubSz, endian);
}
/* curve25519 private key import (Big endian)
* Public key to match private key needs to be imported too
* return 0 on success */
int wc_curve25519_import_private_raw(const byte* priv, word32 privSz,
const byte* pub, word32 pubSz,
curve25519_key* key)
{
return wc_curve25519_import_private_raw_ex(priv, privSz, pub, pubSz,
key, EC25519_BIG_ENDIAN);
}
/* curve25519 private key import (Big or Little endian)
* Public key to match private key needs to be imported too
* return 0 on success */
int wc_curve25519_import_private_raw_ex(const byte* priv, word32 privSz,
const byte* pub, word32 pubSz,
curve25519_key* key, int endian)
{
int ret;
/* import private part */
ret = wc_curve25519_import_private_ex(priv, privSz, key, endian);
if (ret != 0)
return ret;
/* import public part */
return wc_curve25519_import_public_ex(pub, pubSz, key, endian);
}
/* curve25519 private key import only. (Big endian)
* return 0 on success */
int wc_curve25519_import_private(const byte* priv, word32 privSz,
curve25519_key* key)
{
return wc_curve25519_import_private_ex(priv, privSz,
key, EC25519_BIG_ENDIAN);
}
/* curve25519 private key import only. (Big or Little endian)
* return 0 on success */
int wc_curve25519_import_private_ex(const byte* priv, word32 privSz,
curve25519_key* key, int endian)
{
/* sanity check */
if (key == NULL || priv == NULL)
return BAD_FUNC_ARG;
/* check size of incoming keys */
if ((int)privSz != wc_curve25519_size(key))
return ECC_BAD_ARG_E;
if (endian == EC25519_BIG_ENDIAN) {
int i;
/* read the key in Big Endian format */
for (i = 0; i < CURVE25519_KEYSIZE; i++)
key->k.point[i] = priv[CURVE25519_KEYSIZE - i - 1];
}
else
XMEMCPY(key->k.point, priv, privSz);
key->dp = &curve25519_sets[0];
/* Clamp the key */
key->k.point[0] &= 248;
key->k.point[privSz-1] &= 63; /* same &=127 because |=64 after */
key->k.point[privSz-1] |= 64;
return 0;
}
int wc_curve25519_init(curve25519_key* key)
{
word32 keySz;
if (key == NULL)
return ECC_BAD_ARG_E;
return BAD_FUNC_ARG;
/* currently the format for curve25519 */
key->dp = &curve25519_sets[0];
keySz = key->dp->size;
XMEMSET(key->k.point, 0, keySz);
XMEMSET(key->p.point, 0, keySz);
XMEMSET(key->k.point, 0, key->dp->size);
XMEMSET(key->p.point, 0, key->dp->size);
return 0;
}
@ -251,7 +378,8 @@ void wc_curve25519_free(curve25519_key* key)
/* get key size */
int wc_curve25519_size(curve25519_key* key)
{
if (key == NULL) return 0;
if (key == NULL)
return 0;
return key->dp->size;
}

View File

@ -38,14 +38,12 @@
#include <wolfcrypt/src/misc.c>
#endif
/*
generate an ed25519 key pair.
returns 0 on success
/* generate an ed25519 key pair.
* returns 0 on success
*/
int wc_ed25519_make_key(RNG* rng, int keySz, ed25519_key* key)
{
byte az[64];
byte az[ED25519_PRV_KEY_SIZE];
int ret;
ge_p3 A;
@ -56,16 +54,25 @@ int wc_ed25519_make_key(RNG* rng, int keySz, ed25519_key* key)
if (keySz != ED25519_KEY_SIZE)
return BAD_FUNC_ARG;
ret = 0;
ret |= wc_RNG_GenerateBlock(rng, key->k, 32);
ret |= wc_Sha512Hash(key->k, 32, az);
az[0] &= 248;
az[31] &= 63;
ret = wc_RNG_GenerateBlock(rng, key->k, ED25519_KEY_SIZE);
if (ret != 0)
return ret;
ret = wc_Sha512Hash(key->k, ED25519_KEY_SIZE, az);
if (ret != 0) {
ForceZero(key->k, ED25519_KEY_SIZE);
return ret;
}
/* apply clamp */
az[0] &= 248;
az[31] &= 63; /* same than az[31] &= 127 because of az[31] |= 64 */
az[31] |= 64;
ge_scalarmult_base(&A, az);
ge_p3_tobytes(key->p, &A);
XMEMMOVE(key->k + 32, key->p, 32);
/* put public key after private key, on the same buffer */
XMEMMOVE(key->k + ED25519_KEY_SIZE, key->p, ED25519_PUB_KEY_SIZE);
return ret;
}
@ -75,43 +82,54 @@ int wc_ed25519_make_key(RNG* rng, int keySz, ed25519_key* key)
in contains the message to sign
inlen is the length of the message to sign
out is the buffer to write the signature
outlen [in/out] input size of out buf
output gets set as the final length of out
outLen [in/out] input size of out buf
output gets set as the final length of out
key is the ed25519 key to use when signing
return 0 on success
*/
int wc_ed25519_sign_msg(const byte* in, word32 inlen, byte* out,
word32 *outlen, ed25519_key* key)
word32 *outLen, ed25519_key* key)
{
ge_p3 R;
byte nonce[SHA512_DIGEST_SIZE];
byte hram[SHA512_DIGEST_SIZE];
byte az[64];
word32 sigSz;
byte az[ED25519_PRV_KEY_SIZE];
Sha512 sha;
int ret = 0;
int ret;
/* sanity check on arguments */
if (in == NULL || out == NULL || outlen == NULL || key == NULL)
if (in == NULL || out == NULL || outLen == NULL || key == NULL)
return BAD_FUNC_ARG;
/* check and set up out length */
ret = 0;
sigSz = wc_ed25519_sig_size(key);
if (*outlen < sigSz)
return BAD_FUNC_ARG;
*outlen = sigSz;
if (*outLen < ED25519_SIG_SIZE) {
*outLen = ED25519_SIG_SIZE;
return BUFFER_E;
}
*outLen = ED25519_SIG_SIZE;
/* step 1: create nonce to use where nonce is r in
r = H(h_b, ... ,h_2b-1,M) */
ret |= wc_Sha512Hash(key->k,32,az);
ret = wc_Sha512Hash(key->k, ED25519_KEY_SIZE, az);
/* apply clamp */
az[0] &= 248;
az[31] &= 63;
az[31] &= 63; /* same than az[31] &= 127 because of az[31] |= 64 */
az[31] |= 64;
ret |= wc_InitSha512(&sha);
ret |= wc_Sha512Update(&sha, az + 32, 32);
ret |= wc_Sha512Update(&sha, in, inlen);
ret |= wc_Sha512Final(&sha, nonce);
ret = wc_InitSha512(&sha);
if (ret != 0)
return ret;
ret = wc_Sha512Update(&sha, az + ED25519_KEY_SIZE, ED25519_KEY_SIZE);
if (ret != 0)
return ret;
ret = wc_Sha512Update(&sha, in, inlen);
if (ret != 0)
return ret;
ret = wc_Sha512Final(&sha, nonce);
if (ret != 0)
return ret;
sc_reduce(nonce);
/* step 2: computing R = rB where rB is the scalar multiplication of
@ -121,13 +139,24 @@ int wc_ed25519_sign_msg(const byte* in, word32 inlen, byte* out,
/* step 3: hash R + public key + message getting H(R,A,M) then
creating S = (r + H(R,A,M)a) mod l */
ret |= wc_InitSha512(&sha);
ret |= wc_Sha512Update(&sha, out, 32);
ret |= wc_Sha512Update(&sha, key->p, 32);
ret |= wc_Sha512Update(&sha, in, inlen);
ret |= wc_Sha512Final(&sha, hram);
ret = wc_InitSha512(&sha);
if (ret != 0)
return ret;
ret = wc_Sha512Update(&sha, out, ED25519_SIG_SIZE/2);
if (ret != 0)
return ret;
ret = wc_Sha512Update(&sha, key->p, ED25519_PUB_KEY_SIZE);
if (ret != 0)
return ret;
ret = wc_Sha512Update(&sha, in, inlen);
if (ret != 0)
return ret;
ret = wc_Sha512Final(&sha, hram);
if (ret != 0)
return ret;
sc_reduce(hram);
sc_muladd(out + 32, hram, az, nonce);
sc_muladd(out + (ED25519_SIG_SIZE/2), hram, az, nonce);
return ret;
}
@ -143,11 +172,10 @@ int wc_ed25519_sign_msg(const byte* in, word32 inlen, byte* out,
int wc_ed25519_verify_msg(byte* sig, word32 siglen, const byte* msg,
word32 msglen, int* stat, ed25519_key* key)
{
byte rcheck[32];
byte rcheck[ED25519_KEY_SIZE];
byte h[SHA512_DIGEST_SIZE];
ge_p3 A;
ge_p2 R;
word32 sigSz;
int ret;
Sha512 sha;
@ -155,14 +183,11 @@ int wc_ed25519_verify_msg(byte* sig, word32 siglen, const byte* msg,
if (sig == NULL || msg == NULL || stat == NULL || key == NULL)
return BAD_FUNC_ARG;
ret = 0;
/* set verification failed by default */
*stat = 0;
sigSz = wc_ed25519_size(key);
/* check on basics needed to verify signature */
if (siglen < sigSz)
return BAD_FUNC_ARG;
if (sig[63] & 224)
if (siglen < ED25519_SIG_SIZE || (sig[ED25519_SIG_SIZE-1] & 224))
return BAD_FUNC_ARG;
/* uncompress A (public key), test if valid, and negate it */
@ -170,24 +195,41 @@ int wc_ed25519_verify_msg(byte* sig, word32 siglen, const byte* msg,
return BAD_FUNC_ARG;
/* find H(R,A,M) and store it as h */
ret |= wc_InitSha512(&sha);
ret |= wc_Sha512Update(&sha, sig, 32);
ret |= wc_Sha512Update(&sha, key->p, 32);
ret |= wc_Sha512Update(&sha, msg, msglen);
ret |= wc_Sha512Final(&sha, h);
ret = wc_InitSha512(&sha);
if (ret != 0)
return ret;
ret = wc_Sha512Update(&sha, sig, ED25519_SIG_SIZE/2);
if (ret != 0)
return ret;
ret = wc_Sha512Update(&sha, key->p, ED25519_PUB_KEY_SIZE);
if (ret != 0)
return ret;
ret = wc_Sha512Update(&sha, msg, msglen);
if (ret != 0)
return ret;
ret = wc_Sha512Final(&sha, h);
if (ret != 0)
return ret;
sc_reduce(h);
/*
Uses a fast single-signature verification SB = R + H(R,A,M)A becomes
SB - H(R,A,M)A saving decompression of R
*/
ret |= ge_double_scalarmult_vartime(&R, h, &A, sig + 32);
ret = ge_double_scalarmult_vartime(&R, h, &A, sig + (ED25519_SIG_SIZE/2));
if (ret != 0)
return ret;
ge_tobytes(rcheck, &R);
/* comparison of R created to R in sig */
ret |= ConstantCompare(rcheck, sig, 32);
ret = ConstantCompare(rcheck, sig, ED25519_SIG_SIZE/2);
if (ret != 0)
return ret;
*stat = (ret == 0)? 1: 0;
/* set the verification status */
*stat = 1;
return ret;
}
@ -222,19 +264,17 @@ void wc_ed25519_free(ed25519_key* key)
*/
int wc_ed25519_export_public(ed25519_key* key, byte* out, word32* outLen)
{
word32 keySz;
/* sanity check on arguments */
if (key == NULL || out == NULL || outLen == NULL)
return BAD_FUNC_ARG;
keySz = wc_ed25519_size(key);
if (*outLen < keySz) {
*outLen = keySz;
if (*outLen < ED25519_PUB_KEY_SIZE) {
*outLen = ED25519_PUB_KEY_SIZE;
return BUFFER_E;
}
*outLen = keySz;
XMEMCPY(out, key->p, keySz);
*outLen = ED25519_PUB_KEY_SIZE;
XMEMCPY(out, key->p, ED25519_PUB_KEY_SIZE);
return 0;
}
@ -248,37 +288,35 @@ int wc_ed25519_export_public(ed25519_key* key, byte* out, word32* outLen)
*/
int wc_ed25519_import_public(const byte* in, word32 inLen, ed25519_key* key)
{
word32 keySz;
int ret;
/* sanity check on arguments */
if (in == NULL || key == NULL)
return BAD_FUNC_ARG;
keySz = wc_ed25519_size(key);
if (inLen < keySz)
if (inLen < ED25519_PUB_KEY_SIZE)
return BAD_FUNC_ARG;
/* compressed prefix according to draft
http://www.ietf.org/id/draft-koch-eddsa-for-openpgp-02.txt */
if (in[0] == 0x40) {
if (in[0] == 0x40 && inLen > ED25519_PUB_KEY_SIZE) {
/* key is stored in compressed format so just copy in */
XMEMCPY(key->p, (in + 1), keySz);
XMEMCPY(key->p, (in + 1), ED25519_PUB_KEY_SIZE);
return 0;
}
/* importing uncompressed public key */
if (in[0] == 0x04) {
if (in[0] == 0x04 && inLen > 2*ED25519_PUB_KEY_SIZE) {
/* pass in (x,y) and store compressed key */
ret = ge_compress_key(key->p, (in+1), (in+1+keySz), keySz);
ret = ge_compress_key(key->p, in+1,
in+1+ED25519_PUB_KEY_SIZE, ED25519_PUB_KEY_SIZE);
return ret;
}
/* if not specified compressed or uncompressed check key size
if key size is equal to compressed key size copy in key */
if (inLen == keySz) {
XMEMCPY(key->p, in, keySz);
if (inLen == ED25519_PUB_KEY_SIZE) {
XMEMCPY(key->p, in, ED25519_PUB_KEY_SIZE);
return 0;
}
@ -293,77 +331,129 @@ int wc_ed25519_import_public(const byte* in, word32 inLen, ed25519_key* key)
int wc_ed25519_import_private_key(const byte* priv, word32 privSz,
const byte* pub, word32 pubSz, ed25519_key* key)
{
word32 keySz;
int ret;
/* sanity check on arguments */
if (priv == NULL || pub == NULL || key == NULL)
return BAD_FUNC_ARG;
keySz = wc_ed25519_size(key);
/* key size check */
if (privSz < keySz || pubSz < keySz)
if (privSz < ED25519_KEY_SIZE || pubSz < ED25519_PUB_KEY_SIZE)
return BAD_FUNC_ARG;
XMEMCPY(key->k, priv, keySz);
/* import public key */
ret = wc_ed25519_import_public(pub, pubSz, key);
XMEMCPY((key->k + keySz), key->p, keySz);
if (ret != 0)
return ret;
/* make the private key (priv + pub) */
XMEMCPY(key->k, priv, ED25519_KEY_SIZE);
XMEMCPY(key->k + ED25519_KEY_SIZE, key->p, ED25519_PUB_KEY_SIZE);
return ret;
}
/*
outLen should contain the size of out buffer when input. outLen is than set
to the final output length.
returns 0 on success
export private key only (secret part so 32 bytes)
outLen should contain the size of out buffer when input. outLen is than set
to the final output length.
returns 0 on success
*/
int wc_ed25519_export_private_only(ed25519_key* key, byte* out, word32* outLen)
{
word32 keySz;
/* sanity checks on arguments */
if (key == NULL || out == NULL || outLen == NULL)
return BAD_FUNC_ARG;
keySz = wc_ed25519_size(key);
if (*outLen < keySz) {
*outLen = keySz;
if (*outLen < ED25519_KEY_SIZE) {
*outLen = ED25519_KEY_SIZE;
return BUFFER_E;
}
*outLen = keySz;
XMEMCPY(out, key->k, keySz);
*outLen = ED25519_KEY_SIZE;
XMEMCPY(out, key->k, ED25519_KEY_SIZE);
return 0;
}
/*
export private key, including public part
outLen should contain the size of out buffer when input. outLen is than set
to the final output length.
returns 0 on success
*/
int wc_ed25519_export_private(ed25519_key* key, byte* out, word32* outLen)
{
/* sanity checks on arguments */
if (key == NULL || out == NULL || outLen == NULL)
return BAD_FUNC_ARG;
/* is the compressed key size in bytes */
if (*outLen < ED25519_PRV_KEY_SIZE) {
*outLen = ED25519_PRV_KEY_SIZE;
return BUFFER_E;
}
*outLen = ED25519_PRV_KEY_SIZE;
XMEMCPY(out, key->k, ED25519_PRV_KEY_SIZE);
return 0;
}
/* export full private key and public key
return 0 on success
*/
int wc_ed25519_export_key(ed25519_key* key,
byte* priv, word32 *privSz,
byte* pub, word32 *pubSz)
{
int ret;
/* export 'full' private part */
ret = wc_ed25519_export_private(key, priv, privSz);
if (ret != 0)
return ret;
/* export public part */
ret = wc_ed25519_export_public(key, pub, pubSz);
return ret;
}
/* returns the private key size (secret only) in bytes */
int wc_ed25519_size(ed25519_key* key)
{
word32 keySz;
if (key == NULL)
return BAD_FUNC_ARG;
keySz = ED25519_KEY_SIZE;
return keySz;
return ED25519_KEY_SIZE;
}
/* returns the private key size (secret + public) in bytes */
int wc_ed25519_priv_size(ed25519_key* key)
{
if (key == NULL)
return BAD_FUNC_ARG;
return ED25519_PRV_KEY_SIZE;
}
/* returns the compressed key size in bytes (public key) */
int wc_ed25519_pub_size(ed25519_key* key)
{
if (key == NULL)
return BAD_FUNC_ARG;
return ED25519_PUB_KEY_SIZE;
}
/* returns the size of signature in bytes */
int wc_ed25519_sig_size(ed25519_key* key)
{
word32 sigSz;
if (key == NULL)
return BAD_FUNC_ARG;
sigSz = ED25519_SIG_SIZE;
return sigSz;
return ED25519_SIG_SIZE;
}
#endif /* HAVE_ED25519 */

View File

@ -107,8 +107,9 @@ void fe_0(fe h)
int curve25519(byte* q, byte* n, byte* p)
{
#if 0
unsigned char e[32];
unsigned int i;
#endif
fe x1;
fe x2;
fe z2;
@ -120,10 +121,16 @@ int curve25519(byte* q, byte* n, byte* p)
unsigned int swap;
unsigned int b;
for (i = 0;i < 32;++i) e[i] = n[i];
e[0] &= 248;
e[31] &= 127;
e[31] |= 64;
/* Clamp already done during key generation and import */
#if 0
{
unsigned int i;
for (i = 0;i < 32;++i) e[i] = n[i];
e[0] &= 248;
e[31] &= 127;
e[31] |= 64;
}
#endif
fe_frombytes(x1,p);
fe_1(x2);
@ -133,7 +140,11 @@ int curve25519(byte* q, byte* n, byte* p)
swap = 0;
for (pos = 254;pos >= 0;--pos) {
#if 0
b = e[pos / 8] >> (pos & 7);
#else
b = n[pos / 8] >> (pos & 7);
#endif
b &= 1;
swap ^= b;
fe_cswap(x2,x3,swap);

View File

@ -5510,6 +5510,27 @@ int curve25519_test(void)
if (XMEMCMP(ss, sharedB, y))
return -1017;
/* test with 1 generated key and 1 from known test vector */
if (wc_curve25519_import_private_raw(sa, sizeof(sa), pa, sizeof(pa), &userA)
!= 0)
return -1018;
if (wc_curve25519_make_key(&rng, 32, &userB) != 0)
return -1019;
if (wc_curve25519_shared_secret(&userA, &userB, sharedA, &x) != 0)
return -1020;
if (wc_curve25519_shared_secret(&userB, &userA, sharedB, &y) != 0)
return -1021;
/* compare shared secret keys to test they are the same */
if (y != x)
return -1022;
if (XMEMCMP(sharedA, sharedB, x))
return -1023;
/* clean up keys when done */
wc_curve25519_free(&pubKey);
wc_curve25519_free(&userB);

View File

@ -0,0 +1,23 @@
/* ec25519.h */
#ifndef WOLFSSL_EC25519_H_
#define WOLFSSL_EC25519_H_
#ifdef __cplusplus
extern "C" {
#endif
WOLFSSL_API
int wolfSSL_EC25519_generate_key(unsigned char *priv, unsigned int *privSz,
unsigned char *pub, unsigned int *pubSz);
WOLFSSL_API
int wolfSSL_EC25519_shared_key(unsigned char *shared, unsigned int *sharedSz,
const unsigned char *priv, unsigned int privSz,
const unsigned char *pub, unsigned int pubSz);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* header */

View File

@ -0,0 +1,26 @@
/* ed25519.h */
#ifndef WOLFSSL_ED25519_H_
#define WOLFSSL_ED25519_H_
#ifdef __cplusplus
extern "C" {
#endif
WOLFSSL_API
int wolfSSL_ED25519_generate_key(unsigned char *priv, unsigned int *privSz,
unsigned char *pub, unsigned int *pubSz);
WOLFSSL_API
int wolfSSL_ED25519_sign(const unsigned char *msg, unsigned int msgSz,
const unsigned char *priv, unsigned int privSz,
unsigned char *sig, unsigned int *sigSz);
WOLFSSL_API
int wolfSSL_ED25519_verify(const unsigned char *msg, unsigned int msgSz,
const unsigned char *pub, unsigned int pubSz,
const unsigned char *sig, unsigned int sigSz);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* header */

View File

@ -13,6 +13,8 @@ nobase_include_HEADERS+= \
wolfssl/openssl/ecdsa.h \
wolfssl/openssl/ecdh.h \
wolfssl/openssl/ec.h \
wolfssl/openssl/ec25519.h \
wolfssl/openssl/ed25519.h \
wolfssl/openssl/engine.h \
wolfssl/openssl/err.h \
wolfssl/openssl/evp.h \

View File

@ -28,7 +28,7 @@ int wolfSSL_PEM_write_RSAPrivateKey(FILE *fp, WOLFSSL_RSA *rsa,
WOLFSSL_API
int wolfSSL_PEM_write_mem_RSAPrivateKey(RSA* rsa, const EVP_CIPHER* cipher,
unsigned char* passwd, int len,
byte **pem, int *plen);
unsigned char **pem, int *plen);
WOLFSSL_API
WOLFSSL_RSA *wolfSSL_PEM_read_RSAPublicKey(FILE *fp, WOLFSSL_RSA **x,
pem_password_cb *cb, void *u);
@ -54,7 +54,7 @@ WOLFSSL_API
int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa,
const EVP_CIPHER* cipher,
unsigned char* passwd, int len,
byte **pem, int *plen);
unsigned char **pem, int *plen);
WOLFSSL_API
int wolfSSL_PEM_write_DSA_PUBKEY(FILE *fp, WOLFSSL_DSA *x);
@ -73,7 +73,7 @@ WOLFSSL_API
int wolfSSL_PEM_write_mem_ECPrivateKey(WOLFSSL_EC_KEY* key,
const EVP_CIPHER* cipher,
unsigned char* passwd, int len,
byte **pem, int *plen);
unsigned char **pem, int *plen);
WOLFSSL_API
int wolfSSL_PEM_write_EC_PUBKEY(FILE *fp, WOLFSSL_EC_KEY *key);

View File

@ -42,7 +42,8 @@ typedef struct {
} curve25519_set_type;
/* ECC point */
/* ECC point, the internal structure is Little endian
* the mathematical functions used the endianess */
typedef struct {
byte point[CURVE25519_KEYSIZE];
}ECPoint;
@ -58,6 +59,11 @@ typedef struct {
ECPoint k; /* private key */
} curve25519_key;
enum {
EC25519_LITTLE_ENDIAN=0,
EC25519_BIG_ENDIAN=1
};
WOLFSSL_API
int wc_curve25519_make_key(RNG* rng, int keysize, curve25519_key* key);
@ -66,6 +72,11 @@ int wc_curve25519_shared_secret(curve25519_key* private_key,
curve25519_key* public_key,
byte* out, word32* outlen);
WOLFSSL_API
int wc_curve25519_shared_secret_ex(curve25519_key* private_key,
curve25519_key* public_key,
byte* out, word32* outlen, int endian);
WOLFSSL_API
int wc_curve25519_init(curve25519_key* key);
@ -74,21 +85,49 @@ void wc_curve25519_free(curve25519_key* key);
/* raw key helpers */
WOLFSSL_API
int wc_curve25519_import_private(const byte* priv, word32 privSz,
curve25519_key* key);
WOLFSSL_API
int wc_curve25519_import_private_ex(const byte* priv, word32 privSz,
curve25519_key* key, int endian);
WOLFSSL_API
int wc_curve25519_import_private_raw(const byte* priv, word32 privSz,
const byte* pub, word32 pubSz, curve25519_key* key);
WOLFSSL_API
int wc_curve25519_import_private_raw_ex(const byte* priv, word32 privSz,
const byte* pub, word32 pubSz,
curve25519_key* key, int endian);
WOLFSSL_API
int wc_curve25519_export_private_raw(curve25519_key* key, byte* out,
word32* outLen);
WOLFSSL_API
int wc_curve25519_export_private_raw_ex(curve25519_key* key, byte* out,
word32* outLen, int endian);
WOLFSSL_API
int wc_curve25519_import_public(const byte* in, word32 inLen,
curve25519_key* key);
WOLFSSL_API
int wc_curve25519_import_public_ex(const byte* in, word32 inLen,
curve25519_key* key, int endian);
WOLFSSL_API
int wc_curve25519_export_public(curve25519_key* key, byte* out, word32* outLen);
WOLFSSL_API
int wc_curve25519_export_public_ex(curve25519_key* key, byte* out,
word32* outLen, int endian);
WOLFSSL_API
int wc_curve25519_export_key_raw(curve25519_key* key,
byte* priv, word32 *privSz,
byte* pub, word32 *pubSz);
WOLFSSL_API
int wc_curve25519_export_key_raw_ex(curve25519_key* key,
byte* priv, word32 *privSz,
byte* pub, word32 *pubSz,
int endian);
/* size helper */
WOLFSSL_API
int wc_curve25519_size(curve25519_key* key);

View File

@ -46,14 +46,17 @@
"-121665/121666", value of d
*/
#define ED25519_KEY_SIZE 32
#define ED25519_SIG_SIZE 64
#define ED25519_KEY_SIZE 32 /* private key only */
#define ED25519_SIG_SIZE 64
#define ED25519_PUB_KEY_SIZE 32 /* compressed */
/* both private and public key */
#define ED25519_PRV_KEY_SIZE (ED25519_PUB_KEY_SIZE+ED25519_KEY_SIZE)
/* An ED25519 Key */
typedef struct {
byte p[32]; /* compressed public key */
byte k[64]; /* private key : 32 secret -- 32 public */
byte p[ED25519_PUB_KEY_SIZE]; /* compressed public key */
byte k[ED25519_PRV_KEY_SIZE]; /* private key : 32 secret -- 32 public */
} ed25519_key;
@ -78,11 +81,21 @@ WOLFSSL_API
int wc_ed25519_export_public(ed25519_key*, byte* out, word32* outLen);
WOLFSSL_API
int wc_ed25519_export_private_only(ed25519_key* key, byte* out, word32* outLen);
WOLFSSL_API
int wc_ed25519_export_private(ed25519_key* key, byte* out, word32* outLen);
WOLFSSL_API
int wc_ed25519_export_key(ed25519_key* key,
byte* priv, word32 *privSz,
byte* pub, word32 *pubSz);
/* size helper */
WOLFSSL_API
int wc_ed25519_size(ed25519_key* key);
WOLFSSL_API
int wc_ed25519_priv_size(ed25519_key* key);
WOLFSSL_API
int wc_ed25519_pub_size(ed25519_key* key);
WOLFSSL_API
int wc_ed25519_sig_size(ed25519_key* key);
#ifdef __cplusplus