Преглед изворни кода

Merge branch 'master' of github.com:wolfssl/wolfssl

toddouska пре 9 година
родитељ
комит
d3c8ff3488

+ 10 - 0
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"

+ 3 - 0
cyassl/openssl/ec25519.h

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

+ 3 - 0
cyassl/openssl/ed25519.h

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

+ 2 - 0
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 \

+ 10 - 1
mplabx/wolfssl.X/nbproject/configurations.xml

@@ -50,6 +50,15 @@
         <itemPath>../../wolfcrypt/src/tfm.c</itemPath>
         <itemPath>../../wolfcrypt/src/wc_port.c</itemPath>
         <itemPath>../../wolfcrypt/src/port/pic32/pic32mz-hash.c</itemPath>
+        <itemPath>../../wolfcrypt/src/hash.c</itemPath>
+        <itemPath>../../wolfcrypt/src/chacha20_poly1305.c</itemPath>
+        <itemPath>../../wolfcrypt/src/curve25519.c</itemPath>
+        <itemPath>../../wolfcrypt/src/ed25519.c</itemPath>
+        <itemPath>../../wolfcrypt/src/fe_low_mem.c</itemPath>
+        <itemPath>../../wolfcrypt/src/fe_operations.c</itemPath>
+        <itemPath>../../wolfcrypt/src/ge_low_mem.c</itemPath>
+        <itemPath>../../wolfcrypt/src/ge_operations.c</itemPath>
+        <itemPath>../../wolfcrypt/src/wc_encrypt.c</itemPath>
       </logicalFolder>
       <logicalFolder name="f1" displayName="wolfssl" projectFiles="true">
         <itemPath>../../src/crl.c</itemPath>
@@ -85,7 +94,7 @@
         <targetPluginBoard></targetPluginBoard>
         <platformTool>PKOBSKDEPlatformTool</platformTool>
         <languageToolchain>XC32</languageToolchain>
-        <languageToolchainVersion></languageToolchainVersion>
+        <languageToolchainVersion>1.33</languageToolchainVersion>
         <platform>4</platform>
       </toolsSet>
       <compileType>

+ 318 - 5
src/ssl.c

@@ -50,6 +50,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 */
@@ -59,6 +61,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
@@ -12635,8 +12639,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) {
@@ -13496,7 +13499,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;
@@ -14867,7 +14870,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;
@@ -15040,7 +15043,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;
@@ -16330,3 +16333,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 */
+

+ 220 - 92
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;
-
-  if (key == NULL || rng == NULL)
-      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;
-
-  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;
-
-  /* compute public key */
-  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];
-  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;
-}
+    unsigned char basepoint[CURVE25519_KEYSIZE] = {9};
+    int  ret;
+
+    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;
+
+    /* random number for private key */
+    ret = wc_RNG_GenerateBlock(rng, key->k.point, keysize);
+    if (ret != 0)
+        return ret;
+
+    /* 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(key->p.point, key->k.point, basepoint);
+    if (ret != 0) {
+        ForceZero(key->k.point, keysize);
+        ForceZero(key->p.point, 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);
+    ret = curve25519(o, private_key->k.point, public_key->p.point);
+    if (ret != 0) {
+        ForceZero(o, CURVE25519_KEYSIZE);
+        return ret;
+    }
 
-    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];
+    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);
 
-    ret     = curve25519(o , k, p);
     *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 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)
+{
+    return wc_curve25519_export_key_raw_ex(key, priv, privSz,
+                                           pub, pubSz, EC25519_BIG_ENDIAN);
+}
+
+/* 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;
+
+    /* export private part */
+    ret = wc_curve25519_export_private_raw_ex(key, priv, privSz, endian);
+    if (ret != 0)
+        return ret;
+
+    /* export public part */
+    return wc_curve25519_export_public_ex(key, pub, pubSz, endian);
+}
+
 
-/* curve25519 private key import.
-   Public key to match private key needs to be imported too */
+/* 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)
+                                     const byte* pub, word32 pubSz,
+                                     curve25519_key* key)
 {
-    int ret = 0;
-    word32 keySz;
+    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 || pub == NULL)
-        return ECC_BAD_ARG_E;
+    if (key == NULL || priv == NULL)
+        return BAD_FUNC_ARG;
 
     /* check size of incoming keys */
-    keySz = wc_curve25519_size(key);
-    if (privSz != keySz || pubSz != keySz)
-       return ECC_BAD_ARG_E;
+    if ((int)privSz != wc_curve25519_size(key))
+        return ECC_BAD_ARG_E;
 
-    XMEMCPY(key->k.point, priv, privSz);
-    XMEMCPY(key->p.point, pub, pubSz);
+    if (endian == EC25519_BIG_ENDIAN) {
+        int i;
 
-    return ret;
-}
+        /* 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;
 }

+ 184 - 92
wolfcrypt/src/ed25519.c

@@ -39,14 +39,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;
 
@@ -57,16 +55,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;
 }
@@ -76,43 +83,56 @@ 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);
+    if (ret != 0)
+        return ret;
+
+    /* 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
@@ -122,13 +142,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;
 }
@@ -144,11 +175,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;
 
@@ -156,14 +186,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 */
@@ -171,24 +198,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;
 }
@@ -223,19 +267,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;
 }
@@ -249,37 +291,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;
     }
 
@@ -294,77 +334,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;
+
+    if (*outLen < ED25519_KEY_SIZE) {
+        *outLen = ED25519_KEY_SIZE;
+        return BUFFER_E;
+    }
+
+    *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;
 
-    keySz = wc_ed25519_size(key);
-    if (*outLen < keySz) {
-        *outLen = keySz;
+    if (*outLen < ED25519_PRV_KEY_SIZE) {
+        *outLen = ED25519_PRV_KEY_SIZE;
         return BUFFER_E;
     }
-    *outLen = keySz;
-    XMEMCPY(out, key->k, keySz);
+
+    *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;
+}
 
-/* is the compressed key size in bytes */
+/* 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 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 keySz;
+    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 */

+ 16 - 5
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);

+ 29 - 0
wolfcrypt/test/test.c

@@ -5565,9 +5565,11 @@ int curve25519_test(void)
         return -1003;
 
     /* find shared secret key */
+    x = sizeof(sharedA);
     if (wc_curve25519_shared_secret(&userA, &userB, sharedA, &x) != 0)
         return -1004;
 
+    y = sizeof(sharedB);
     if (wc_curve25519_shared_secret(&userB, &userA, sharedB, &y) != 0)
         return -1005;
 
@@ -5579,6 +5581,7 @@ int curve25519_test(void)
         return -1007;
 
     /* export a public key and import it for another user */
+    x = sizeof(exportBuf);
     if (wc_curve25519_export_public(&userA, exportBuf, &x) != 0)
         return -1008;
 
@@ -5587,6 +5590,7 @@ int curve25519_test(void)
 
     /* test shared key after importing a public key */
     XMEMSET(sharedB, 0, sizeof(sharedB));
+    y = sizeof(sharedB);
     if (wc_curve25519_shared_secret(&userB, &pubKey, sharedB, &y) != 0)
         return -1010;
 
@@ -5604,6 +5608,7 @@ int curve25519_test(void)
 
     /* test against known test vector */
     XMEMSET(sharedB, 0, sizeof(sharedB));
+    y = sizeof(sharedB);
     if (wc_curve25519_shared_secret(&userA, &userB, sharedB, &y) != 0)
         return -1014;
 
@@ -5612,12 +5617,36 @@ int curve25519_test(void)
 
     /* test swaping roles of keys and generating same shared key */
     XMEMSET(sharedB, 0, sizeof(sharedB));
+    y = sizeof(sharedB);
     if (wc_curve25519_shared_secret(&userB, &userA, sharedB, &y) != 0)
         return -1016;
 
     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;
+
+    x = sizeof(sharedA);
+    if (wc_curve25519_shared_secret(&userA, &userB, sharedA, &x) != 0)
+        return -1020;
+
+    y = sizeof(sharedB);
+    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);

+ 23 - 0
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 */

+ 26 - 0
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 */

+ 2 - 0
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 \

+ 3 - 3
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);
 

+ 41 - 2
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);

+ 17 - 4
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

+ 1 - 0
wolfssl/wolfcrypt/settings.h

@@ -178,6 +178,7 @@
     #define USE_FAST_MATH
     #define TFM_TIMING_RESISTANT
     #define NEED_AES_TABLES
+    #define WOLFSSL_HAVE_MIN
 #endif
 
 #ifdef WOLFSSL_MICROCHIP_PIC32MZ