diff --git a/configure.ac b/configure.ac index 718675ae9..ab7614d31 100644 --- a/configure.ac +++ b/configure.ac @@ -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" diff --git a/cyassl/openssl/ec25519.h b/cyassl/openssl/ec25519.h new file mode 100644 index 000000000..6ee894506 --- /dev/null +++ b/cyassl/openssl/ec25519.h @@ -0,0 +1,3 @@ +/* ec25519.h */ + +#include diff --git a/cyassl/openssl/ed25519.h b/cyassl/openssl/ed25519.h new file mode 100644 index 000000000..240cbcaaf --- /dev/null +++ b/cyassl/openssl/ed25519.h @@ -0,0 +1,3 @@ +/* ed25519.h */ + +#include diff --git a/cyassl/openssl/include.am b/cyassl/openssl/include.am index 88950eeec..f5c3c56e9 100644 --- a/cyassl/openssl/include.am +++ b/cyassl/openssl/include.am @@ -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 \ diff --git a/src/ssl.c b/src/ssl.c index 5b7cc6f5e..5fe562526 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -48,6 +48,8 @@ #include #include #include + #include + #include #include #include /* openssl headers end, wolfssl internal headers next */ @@ -57,6 +59,8 @@ #include #include #include + #include + #include #ifdef WOLFSSL_SHA512 #include #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 */ + diff --git a/wolfcrypt/src/curve25519.c b/wolfcrypt/src/curve25519.c index b745a046c..2380e371e 100644 --- a/wolfcrypt/src/curve25519.c +++ b/wolfcrypt/src/curve25519.c @@ -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; } diff --git a/wolfcrypt/src/ed25519.c b/wolfcrypt/src/ed25519.c index ba0dcbe53..a66e76353 100644 --- a/wolfcrypt/src/ed25519.c +++ b/wolfcrypt/src/ed25519.c @@ -38,14 +38,12 @@ #include #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 */ diff --git a/wolfcrypt/src/fe_operations.c b/wolfcrypt/src/fe_operations.c index da07c951c..d78467e21 100644 --- a/wolfcrypt/src/fe_operations.c +++ b/wolfcrypt/src/fe_operations.c @@ -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); diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 26ee84d4c..61da86cdf 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -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); diff --git a/wolfssl/openssl/ec25519.h b/wolfssl/openssl/ec25519.h new file mode 100644 index 000000000..9ae255c6d --- /dev/null +++ b/wolfssl/openssl/ec25519.h @@ -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 */ diff --git a/wolfssl/openssl/ed25519.h b/wolfssl/openssl/ed25519.h new file mode 100644 index 000000000..8244555df --- /dev/null +++ b/wolfssl/openssl/ed25519.h @@ -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 */ diff --git a/wolfssl/openssl/include.am b/wolfssl/openssl/include.am index 9d415962f..21d99ef00 100644 --- a/wolfssl/openssl/include.am +++ b/wolfssl/openssl/include.am @@ -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 \ diff --git a/wolfssl/openssl/pem.h b/wolfssl/openssl/pem.h index 7da6074a9..f21525818 100644 --- a/wolfssl/openssl/pem.h +++ b/wolfssl/openssl/pem.h @@ -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); diff --git a/wolfssl/wolfcrypt/curve25519.h b/wolfssl/wolfcrypt/curve25519.h index 11715775f..ae795baca 100644 --- a/wolfssl/wolfcrypt/curve25519.h +++ b/wolfssl/wolfcrypt/curve25519.h @@ -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); diff --git a/wolfssl/wolfcrypt/ed25519.h b/wolfssl/wolfcrypt/ed25519.h index 6f9a19989..3a8e287b3 100644 --- a/wolfssl/wolfcrypt/ed25519.h +++ b/wolfssl/wolfcrypt/ed25519.h @@ -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