forked from wolfSSL/wolfssl
add support for curve 25519 and Ed25519 in OpenSSH
refactor curve25519 and Ed25519 code fix warning in PEM_xxx_mem_xxx functions
This commit is contained in:
10
configure.ac
10
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"
|
if test "$ENABLED_CURVE25519" = "small"
|
||||||
then
|
then
|
||||||
AM_CFLAGS="$AM_CFLAGS -DCURVED25519_SMALL"
|
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"
|
if test "$ENABLED_ED25519" = "small"
|
||||||
then
|
then
|
||||||
AM_CFLAGS="$AM_CFLAGS -DCURVED25519_SMALL"
|
AM_CFLAGS="$AM_CFLAGS -DCURVED25519_SMALL"
|
||||||
|
3
cyassl/openssl/ec25519.h
Normal file
3
cyassl/openssl/ec25519.h
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
/* ec25519.h */
|
||||||
|
|
||||||
|
#include <wolfssl/openssl/ec25519.h>
|
3
cyassl/openssl/ed25519.h
Normal file
3
cyassl/openssl/ed25519.h
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
/* ed25519.h */
|
||||||
|
|
||||||
|
#include <wolfssl/openssl/ed25519.h>
|
@ -13,6 +13,8 @@ nobase_include_HEADERS+= \
|
|||||||
cyassl/openssl/ecdsa.h \
|
cyassl/openssl/ecdsa.h \
|
||||||
cyassl/openssl/ecdh.h \
|
cyassl/openssl/ecdh.h \
|
||||||
cyassl/openssl/ec.h \
|
cyassl/openssl/ec.h \
|
||||||
|
cyassl/openssl/ec25519.h \
|
||||||
|
cyassl/openssl/ed25519.h \
|
||||||
cyassl/openssl/engine.h \
|
cyassl/openssl/engine.h \
|
||||||
cyassl/openssl/err.h \
|
cyassl/openssl/err.h \
|
||||||
cyassl/openssl/evp.h \
|
cyassl/openssl/evp.h \
|
||||||
|
323
src/ssl.c
323
src/ssl.c
@ -48,6 +48,8 @@
|
|||||||
#include <wolfssl/openssl/rsa.h>
|
#include <wolfssl/openssl/rsa.h>
|
||||||
#include <wolfssl/openssl/pem.h>
|
#include <wolfssl/openssl/pem.h>
|
||||||
#include <wolfssl/openssl/ec.h>
|
#include <wolfssl/openssl/ec.h>
|
||||||
|
#include <wolfssl/openssl/ec25519.h>
|
||||||
|
#include <wolfssl/openssl/ed25519.h>
|
||||||
#include <wolfssl/openssl/ecdsa.h>
|
#include <wolfssl/openssl/ecdsa.h>
|
||||||
#include <wolfssl/openssl/ecdh.h>
|
#include <wolfssl/openssl/ecdh.h>
|
||||||
/* openssl headers end, wolfssl internal headers next */
|
/* openssl headers end, wolfssl internal headers next */
|
||||||
@ -57,6 +59,8 @@
|
|||||||
#include <wolfssl/wolfcrypt/md4.h>
|
#include <wolfssl/wolfcrypt/md4.h>
|
||||||
#include <wolfssl/wolfcrypt/md5.h>
|
#include <wolfssl/wolfcrypt/md5.h>
|
||||||
#include <wolfssl/wolfcrypt/arc4.h>
|
#include <wolfssl/wolfcrypt/arc4.h>
|
||||||
|
#include <wolfssl/wolfcrypt/curve25519.h>
|
||||||
|
#include <wolfssl/wolfcrypt/ed25519.h>
|
||||||
#ifdef WOLFSSL_SHA512
|
#ifdef WOLFSSL_SHA512
|
||||||
#include <wolfssl/wolfcrypt/sha512.h>
|
#include <wolfssl/wolfcrypt/sha512.h>
|
||||||
#endif
|
#endif
|
||||||
@ -12632,8 +12636,7 @@ int wolfSSL_DSA_generate_key(WOLFSSL_DSA* dsa)
|
|||||||
return SSL_FAILURE;
|
return SSL_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dsa->inSet == 0)
|
if (dsa->inSet == 0) {
|
||||||
{
|
|
||||||
WOLFSSL_MSG("No DSA internal set, do it");
|
WOLFSSL_MSG("No DSA internal set, do it");
|
||||||
|
|
||||||
if (SetDsaInternal(dsa) != SSL_SUCCESS) {
|
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,
|
int wolfSSL_PEM_write_mem_RSAPrivateKey(RSA* rsa, const EVP_CIPHER* cipher,
|
||||||
unsigned char* passwd, int passwdSz,
|
unsigned char* passwd, int passwdSz,
|
||||||
byte **pem, int *plen)
|
unsigned char **pem, int *plen)
|
||||||
{
|
{
|
||||||
byte *der, *tmp, *cipherInfo = NULL;
|
byte *der, *tmp, *cipherInfo = NULL;
|
||||||
int der_max_len = 0, derSz = 0;
|
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,
|
int wolfSSL_PEM_write_mem_ECPrivateKey(WOLFSSL_EC_KEY* ecc,
|
||||||
const EVP_CIPHER* cipher,
|
const EVP_CIPHER* cipher,
|
||||||
unsigned char* passwd, int passwdSz,
|
unsigned char* passwd, int passwdSz,
|
||||||
byte **pem, int *plen)
|
unsigned char **pem, int *plen)
|
||||||
{
|
{
|
||||||
byte *der, *tmp, *cipherInfo = NULL;
|
byte *der, *tmp, *cipherInfo = NULL;
|
||||||
int der_max_len = 0, derSz = 0;
|
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,
|
int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa,
|
||||||
const EVP_CIPHER* cipher,
|
const EVP_CIPHER* cipher,
|
||||||
unsigned char* passwd, int passwdSz,
|
unsigned char* passwd, int passwdSz,
|
||||||
byte **pem, int *plen)
|
unsigned char **pem, int *plen)
|
||||||
{
|
{
|
||||||
byte *der, *tmp, *cipherInfo = NULL;
|
byte *der, *tmp, *cipherInfo = NULL;
|
||||||
int der_max_len = 0, derSz = 0;
|
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;
|
return sess->sessionID;
|
||||||
}
|
}
|
||||||
#endif /* OPENSSL_EXTRA and HAVE_STUNNEL */
|
#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 */
|
||||||
|
|
||||||
|
@ -46,94 +46,96 @@ const curve25519_set_type curve25519_sets[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int wc_curve25519_make_key(RNG* rng, int keysize, curve25519_key* key)
|
int wc_curve25519_make_key(RNG* rng, int keysize, curve25519_key* key)
|
||||||
{
|
{
|
||||||
unsigned char basepoint[CURVE25519_KEYSIZE] = {9};
|
unsigned char basepoint[CURVE25519_KEYSIZE] = {9};
|
||||||
unsigned char n[CURVE25519_KEYSIZE];
|
int ret;
|
||||||
unsigned char p[CURVE25519_KEYSIZE];
|
|
||||||
int i;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (key == NULL || rng == NULL)
|
if (key == NULL || rng == NULL)
|
||||||
return ECC_BAD_ARG_E;
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
/* currently only a key size of 32 bytes is used */
|
/* currently only a key size of 32 bytes is used */
|
||||||
if (keysize != CURVE25519_KEYSIZE)
|
if (keysize != CURVE25519_KEYSIZE)
|
||||||
return ECC_BAD_ARG_E;
|
return ECC_BAD_ARG_E;
|
||||||
|
|
||||||
/* get random number from RNG */
|
/* random number for private key */
|
||||||
ret = wc_RNG_GenerateBlock(rng, n, keysize);
|
ret = wc_RNG_GenerateBlock(rng, key->k.point, keysize);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
for (i = 0; i < keysize; ++i) key->k.point[i] = n[i];
|
/* Clamp the private key */
|
||||||
key->k.point[ 0] &= 248;
|
key->k.point[0] &= 248;
|
||||||
key->k.point[31] &= 127;
|
key->k.point[CURVE25519_KEYSIZE-1] &= 63; /* same &=127 because |=64 after */
|
||||||
key->k.point[31] |= 64;
|
key->k.point[CURVE25519_KEYSIZE-1] |= 64;
|
||||||
|
|
||||||
/* compute public key */
|
/* compute public key */
|
||||||
ret = curve25519(p, key->k.point, basepoint);
|
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 */
|
return ret;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int wc_curve25519_shared_secret(curve25519_key* private_key,
|
int wc_curve25519_shared_secret(curve25519_key* private_key,
|
||||||
curve25519_key* public_key,
|
curve25519_key* public_key,
|
||||||
byte* out, word32* outlen)
|
byte* out, word32* outlen)
|
||||||
{
|
{
|
||||||
unsigned char k[CURVE25519_KEYSIZE];
|
return wc_curve25519_shared_secret_ex(private_key, public_key,
|
||||||
unsigned char p[CURVE25519_KEYSIZE];
|
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];
|
unsigned char o[CURVE25519_KEYSIZE];
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int i;
|
|
||||||
|
|
||||||
/* sanity check */
|
/* sanity check */
|
||||||
if (private_key == NULL || public_key == NULL || out == NULL ||
|
if (private_key == NULL || public_key == NULL ||
|
||||||
outlen == NULL)
|
out == NULL || outlen == NULL || *outlen < CURVE25519_KEYSIZE)
|
||||||
return BAD_FUNC_ARG;
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
/* avoid implementation fingerprinting */
|
/* avoid implementation fingerprinting */
|
||||||
if (public_key->p.point[0] > 0x7F)
|
if (public_key->p.point[CURVE25519_KEYSIZE-1] > 0x7F)
|
||||||
return ECC_BAD_ARG_E;
|
return ECC_BAD_ARG_E;
|
||||||
|
|
||||||
XMEMSET(p, 0, sizeof(p));
|
ret = curve25519(o, private_key->k.point, public_key->p.point);
|
||||||
XMEMSET(k, 0, sizeof(k));
|
if (ret != 0) {
|
||||||
XMEMSET(out, 0, CURVE25519_KEYSIZE);
|
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];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
*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));
|
ForceZero(o, sizeof(o));
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* export curve25519 public key (Big endian)
|
||||||
/* curve25519 uses a serialized string for key representation */
|
* return 0 on success */
|
||||||
int wc_curve25519_export_public(curve25519_key* key, byte* out, word32* outLen)
|
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;
|
word32 keySz;
|
||||||
|
|
||||||
@ -143,30 +145,59 @@ int wc_curve25519_export_public(curve25519_key* key, byte* out, word32* outLen)
|
|||||||
/* check size of outgoing key */
|
/* check size of outgoing key */
|
||||||
keySz = wc_curve25519_size(key);
|
keySz = wc_curve25519_size(key);
|
||||||
|
|
||||||
/* copy in public key */
|
/* check and set outgoing key size */
|
||||||
XMEMCPY(out, key->p.point, keySz);
|
if (*outLen < keySz) {
|
||||||
|
*outLen = keySz;
|
||||||
|
return ECC_BAD_ARG_E;
|
||||||
|
}
|
||||||
*outLen = keySz;
|
*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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* import curve25519 public key
|
/* import curve25519 public key (Big endian)
|
||||||
return 0 on success */
|
* return 0 on success */
|
||||||
int wc_curve25519_import_public(const byte* in, word32 inLen,
|
int wc_curve25519_import_public(const byte* in, word32 inLen,
|
||||||
curve25519_key* key)
|
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;
|
word32 keySz;
|
||||||
|
|
||||||
/* sanity check */
|
/* sanity check */
|
||||||
if (key == NULL || in == NULL)
|
if (key == NULL || in == NULL)
|
||||||
return ECC_BAD_ARG_E;
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
/* check size of incoming keys */
|
/* check size of incoming keys */
|
||||||
keySz = wc_curve25519_size(key);
|
keySz = wc_curve25519_size(key);
|
||||||
if (inLen != keySz)
|
if (inLen != keySz)
|
||||||
return ECC_BAD_ARG_E;
|
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];
|
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
|
/* export curve25519 private key only raw (Big endian)
|
||||||
return 0 on success */
|
* outLen is in/out size
|
||||||
|
* return 0 on success */
|
||||||
int wc_curve25519_export_private_raw(curve25519_key* key, byte* out,
|
int wc_curve25519_export_private_raw(curve25519_key* key, byte* out,
|
||||||
word32* outLen)
|
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;
|
word32 keySz;
|
||||||
|
|
||||||
/* sanity check */
|
/* sanity check */
|
||||||
if (key == NULL || out == NULL || outLen == NULL)
|
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);
|
keySz = wc_curve25519_size(key);
|
||||||
|
if (*outLen < keySz) {
|
||||||
|
*outLen = keySz;
|
||||||
|
return ECC_BAD_ARG_E;
|
||||||
|
}
|
||||||
*outLen = keySz;
|
*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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* curve25519 key pair export (Big or Little endian)
|
||||||
/* curve25519 private key import.
|
* return 0 on success */
|
||||||
Public key to match private key needs to be imported too */
|
int wc_curve25519_export_key_raw(curve25519_key* key,
|
||||||
int wc_curve25519_import_private_raw(const byte* priv, word32 privSz,
|
byte* priv, word32 *privSz,
|
||||||
const byte* pub, word32 pubSz, curve25519_key* key)
|
byte* pub, word32 *pubSz)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
return wc_curve25519_export_key_raw_ex(key, priv, privSz,
|
||||||
word32 keySz;
|
pub, pubSz, EC25519_BIG_ENDIAN);
|
||||||
|
}
|
||||||
|
|
||||||
/* sanity check */
|
/* curve25519 key pair export (Big or Little endian)
|
||||||
if (key == NULL || priv == NULL || pub == NULL)
|
* return 0 on success */
|
||||||
return ECC_BAD_ARG_E;
|
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 */
|
/* export private part */
|
||||||
keySz = wc_curve25519_size(key);
|
ret = wc_curve25519_export_private_raw_ex(key, priv, privSz, endian);
|
||||||
if (privSz != keySz || pubSz != keySz)
|
if (ret != 0)
|
||||||
return ECC_BAD_ARG_E;
|
return ret;
|
||||||
|
|
||||||
XMEMCPY(key->k.point, priv, privSz);
|
/* export public part */
|
||||||
XMEMCPY(key->p.point, pub, pubSz);
|
return wc_curve25519_export_public_ex(key, pub, pubSz, endian);
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 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)
|
int wc_curve25519_init(curve25519_key* key)
|
||||||
{
|
{
|
||||||
word32 keySz;
|
|
||||||
|
|
||||||
if (key == NULL)
|
if (key == NULL)
|
||||||
return ECC_BAD_ARG_E;
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
/* currently the format for curve25519 */
|
/* currently the format for curve25519 */
|
||||||
key->dp = &curve25519_sets[0];
|
key->dp = &curve25519_sets[0];
|
||||||
keySz = key->dp->size;
|
|
||||||
|
|
||||||
XMEMSET(key->k.point, 0, keySz);
|
XMEMSET(key->k.point, 0, key->dp->size);
|
||||||
XMEMSET(key->p.point, 0, keySz);
|
XMEMSET(key->p.point, 0, key->dp->size);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -251,7 +378,8 @@ void wc_curve25519_free(curve25519_key* key)
|
|||||||
/* get key size */
|
/* get key size */
|
||||||
int wc_curve25519_size(curve25519_key* key)
|
int wc_curve25519_size(curve25519_key* key)
|
||||||
{
|
{
|
||||||
if (key == NULL) return 0;
|
if (key == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
return key->dp->size;
|
return key->dp->size;
|
||||||
}
|
}
|
||||||
|
@ -38,14 +38,12 @@
|
|||||||
#include <wolfcrypt/src/misc.c>
|
#include <wolfcrypt/src/misc.c>
|
||||||
#endif
|
#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)
|
int wc_ed25519_make_key(RNG* rng, int keySz, ed25519_key* key)
|
||||||
{
|
{
|
||||||
byte az[64];
|
byte az[ED25519_PRV_KEY_SIZE];
|
||||||
int ret;
|
int ret;
|
||||||
ge_p3 A;
|
ge_p3 A;
|
||||||
|
|
||||||
@ -56,16 +54,25 @@ int wc_ed25519_make_key(RNG* rng, int keySz, ed25519_key* key)
|
|||||||
if (keySz != ED25519_KEY_SIZE)
|
if (keySz != ED25519_KEY_SIZE)
|
||||||
return BAD_FUNC_ARG;
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
ret = 0;
|
ret = wc_RNG_GenerateBlock(rng, key->k, ED25519_KEY_SIZE);
|
||||||
ret |= wc_RNG_GenerateBlock(rng, key->k, 32);
|
if (ret != 0)
|
||||||
ret |= wc_Sha512Hash(key->k, 32, az);
|
return ret;
|
||||||
az[0] &= 248;
|
ret = wc_Sha512Hash(key->k, ED25519_KEY_SIZE, az);
|
||||||
az[31] &= 63;
|
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;
|
az[31] |= 64;
|
||||||
|
|
||||||
ge_scalarmult_base(&A, az);
|
ge_scalarmult_base(&A, az);
|
||||||
ge_p3_tobytes(key->p, &A);
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -75,43 +82,54 @@ int wc_ed25519_make_key(RNG* rng, int keySz, ed25519_key* key)
|
|||||||
in contains the message to sign
|
in contains the message to sign
|
||||||
inlen is the length of the message to sign
|
inlen is the length of the message to sign
|
||||||
out is the buffer to write the signature
|
out is the buffer to write the signature
|
||||||
outlen [in/out] input size of out buf
|
outLen [in/out] input size of out buf
|
||||||
output gets set as the final length of out
|
output gets set as the final length of out
|
||||||
key is the ed25519 key to use when signing
|
key is the ed25519 key to use when signing
|
||||||
return 0 on success
|
return 0 on success
|
||||||
*/
|
*/
|
||||||
int wc_ed25519_sign_msg(const byte* in, word32 inlen, byte* out,
|
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;
|
ge_p3 R;
|
||||||
byte nonce[SHA512_DIGEST_SIZE];
|
byte nonce[SHA512_DIGEST_SIZE];
|
||||||
byte hram[SHA512_DIGEST_SIZE];
|
byte hram[SHA512_DIGEST_SIZE];
|
||||||
byte az[64];
|
byte az[ED25519_PRV_KEY_SIZE];
|
||||||
word32 sigSz;
|
|
||||||
Sha512 sha;
|
Sha512 sha;
|
||||||
int ret = 0;
|
int ret;
|
||||||
|
|
||||||
/* sanity check on arguments */
|
/* 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;
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
/* check and set up out length */
|
/* check and set up out length */
|
||||||
ret = 0;
|
if (*outLen < ED25519_SIG_SIZE) {
|
||||||
sigSz = wc_ed25519_sig_size(key);
|
*outLen = ED25519_SIG_SIZE;
|
||||||
if (*outlen < sigSz)
|
return BUFFER_E;
|
||||||
return BAD_FUNC_ARG;
|
}
|
||||||
*outlen = sigSz;
|
*outLen = ED25519_SIG_SIZE;
|
||||||
|
|
||||||
/* step 1: create nonce to use where nonce is r in
|
/* step 1: create nonce to use where nonce is r in
|
||||||
r = H(h_b, ... ,h_2b-1,M) */
|
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[0] &= 248;
|
||||||
az[31] &= 63;
|
az[31] &= 63; /* same than az[31] &= 127 because of az[31] |= 64 */
|
||||||
az[31] |= 64;
|
az[31] |= 64;
|
||||||
ret |= wc_InitSha512(&sha);
|
|
||||||
ret |= wc_Sha512Update(&sha, az + 32, 32);
|
ret = wc_InitSha512(&sha);
|
||||||
ret |= wc_Sha512Update(&sha, in, inlen);
|
if (ret != 0)
|
||||||
ret |= wc_Sha512Final(&sha, nonce);
|
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);
|
sc_reduce(nonce);
|
||||||
|
|
||||||
/* step 2: computing R = rB where rB is the scalar multiplication of
|
/* 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
|
/* step 3: hash R + public key + message getting H(R,A,M) then
|
||||||
creating S = (r + H(R,A,M)a) mod l */
|
creating S = (r + H(R,A,M)a) mod l */
|
||||||
ret |= wc_InitSha512(&sha);
|
ret = wc_InitSha512(&sha);
|
||||||
ret |= wc_Sha512Update(&sha, out, 32);
|
if (ret != 0)
|
||||||
ret |= wc_Sha512Update(&sha, key->p, 32);
|
return ret;
|
||||||
ret |= wc_Sha512Update(&sha, in, inlen);
|
ret = wc_Sha512Update(&sha, out, ED25519_SIG_SIZE/2);
|
||||||
ret |= wc_Sha512Final(&sha, hram);
|
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_reduce(hram);
|
||||||
sc_muladd(out + 32, hram, az, nonce);
|
sc_muladd(out + (ED25519_SIG_SIZE/2), hram, az, nonce);
|
||||||
|
|
||||||
return ret;
|
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,
|
int wc_ed25519_verify_msg(byte* sig, word32 siglen, const byte* msg,
|
||||||
word32 msglen, int* stat, ed25519_key* key)
|
word32 msglen, int* stat, ed25519_key* key)
|
||||||
{
|
{
|
||||||
byte rcheck[32];
|
byte rcheck[ED25519_KEY_SIZE];
|
||||||
byte h[SHA512_DIGEST_SIZE];
|
byte h[SHA512_DIGEST_SIZE];
|
||||||
ge_p3 A;
|
ge_p3 A;
|
||||||
ge_p2 R;
|
ge_p2 R;
|
||||||
word32 sigSz;
|
|
||||||
int ret;
|
int ret;
|
||||||
Sha512 sha;
|
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)
|
if (sig == NULL || msg == NULL || stat == NULL || key == NULL)
|
||||||
return BAD_FUNC_ARG;
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
ret = 0;
|
/* set verification failed by default */
|
||||||
*stat = 0;
|
*stat = 0;
|
||||||
sigSz = wc_ed25519_size(key);
|
|
||||||
|
|
||||||
/* check on basics needed to verify signature */
|
/* check on basics needed to verify signature */
|
||||||
if (siglen < sigSz)
|
if (siglen < ED25519_SIG_SIZE || (sig[ED25519_SIG_SIZE-1] & 224))
|
||||||
return BAD_FUNC_ARG;
|
|
||||||
if (sig[63] & 224)
|
|
||||||
return BAD_FUNC_ARG;
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
/* uncompress A (public key), test if valid, and negate it */
|
/* 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;
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
/* find H(R,A,M) and store it as h */
|
/* find H(R,A,M) and store it as h */
|
||||||
ret |= wc_InitSha512(&sha);
|
ret = wc_InitSha512(&sha);
|
||||||
ret |= wc_Sha512Update(&sha, sig, 32);
|
if (ret != 0)
|
||||||
ret |= wc_Sha512Update(&sha, key->p, 32);
|
return ret;
|
||||||
ret |= wc_Sha512Update(&sha, msg, msglen);
|
ret = wc_Sha512Update(&sha, sig, ED25519_SIG_SIZE/2);
|
||||||
ret |= wc_Sha512Final(&sha, h);
|
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);
|
sc_reduce(h);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Uses a fast single-signature verification SB = R + H(R,A,M)A becomes
|
Uses a fast single-signature verification SB = R + H(R,A,M)A becomes
|
||||||
SB - H(R,A,M)A saving decompression of R
|
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);
|
ge_tobytes(rcheck, &R);
|
||||||
|
|
||||||
/* comparison of R created to R in sig */
|
/* 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;
|
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)
|
int wc_ed25519_export_public(ed25519_key* key, byte* out, word32* outLen)
|
||||||
{
|
{
|
||||||
word32 keySz;
|
|
||||||
|
|
||||||
/* sanity check on arguments */
|
/* sanity check on arguments */
|
||||||
if (key == NULL || out == NULL || outLen == NULL)
|
if (key == NULL || out == NULL || outLen == NULL)
|
||||||
return BAD_FUNC_ARG;
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
keySz = wc_ed25519_size(key);
|
if (*outLen < ED25519_PUB_KEY_SIZE) {
|
||||||
if (*outLen < keySz) {
|
*outLen = ED25519_PUB_KEY_SIZE;
|
||||||
*outLen = keySz;
|
|
||||||
return BUFFER_E;
|
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;
|
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)
|
int wc_ed25519_import_public(const byte* in, word32 inLen, ed25519_key* key)
|
||||||
{
|
{
|
||||||
word32 keySz;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* sanity check on arguments */
|
/* sanity check on arguments */
|
||||||
if (in == NULL || key == NULL)
|
if (in == NULL || key == NULL)
|
||||||
return BAD_FUNC_ARG;
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
keySz = wc_ed25519_size(key);
|
if (inLen < ED25519_PUB_KEY_SIZE)
|
||||||
|
|
||||||
if (inLen < keySz)
|
|
||||||
return BAD_FUNC_ARG;
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
/* compressed prefix according to draft
|
/* compressed prefix according to draft
|
||||||
http://www.ietf.org/id/draft-koch-eddsa-for-openpgp-02.txt */
|
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 */
|
/* 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* importing uncompressed public key */
|
/* 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 */
|
/* 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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if not specified compressed or uncompressed check key size
|
/* if not specified compressed or uncompressed check key size
|
||||||
if key size is equal to compressed key size copy in key */
|
if key size is equal to compressed key size copy in key */
|
||||||
if (inLen == keySz) {
|
if (inLen == ED25519_PUB_KEY_SIZE) {
|
||||||
XMEMCPY(key->p, in, keySz);
|
XMEMCPY(key->p, in, ED25519_PUB_KEY_SIZE);
|
||||||
return 0;
|
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,
|
int wc_ed25519_import_private_key(const byte* priv, word32 privSz,
|
||||||
const byte* pub, word32 pubSz, ed25519_key* key)
|
const byte* pub, word32 pubSz, ed25519_key* key)
|
||||||
{
|
{
|
||||||
word32 keySz;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* sanity check on arguments */
|
/* sanity check on arguments */
|
||||||
if (priv == NULL || pub == NULL || key == NULL)
|
if (priv == NULL || pub == NULL || key == NULL)
|
||||||
return BAD_FUNC_ARG;
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
keySz = wc_ed25519_size(key);
|
|
||||||
|
|
||||||
/* key size check */
|
/* key size check */
|
||||||
if (privSz < keySz || pubSz < keySz)
|
if (privSz < ED25519_KEY_SIZE || pubSz < ED25519_PUB_KEY_SIZE)
|
||||||
return BAD_FUNC_ARG;
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
XMEMCPY(key->k, priv, keySz);
|
/* import public key */
|
||||||
ret = wc_ed25519_import_public(pub, pubSz, 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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
outLen should contain the size of out buffer when input. outLen is than set
|
export private key only (secret part so 32 bytes)
|
||||||
to the final output length.
|
outLen should contain the size of out buffer when input. outLen is than set
|
||||||
returns 0 on success
|
to the final output length.
|
||||||
|
returns 0 on success
|
||||||
*/
|
*/
|
||||||
int wc_ed25519_export_private_only(ed25519_key* key, byte* out, word32* outLen)
|
int wc_ed25519_export_private_only(ed25519_key* key, byte* out, word32* outLen)
|
||||||
{
|
{
|
||||||
word32 keySz;
|
|
||||||
|
|
||||||
/* sanity checks on arguments */
|
/* sanity checks on arguments */
|
||||||
if (key == NULL || out == NULL || outLen == NULL)
|
if (key == NULL || out == NULL || outLen == NULL)
|
||||||
return BAD_FUNC_ARG;
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
keySz = wc_ed25519_size(key);
|
if (*outLen < ED25519_KEY_SIZE) {
|
||||||
if (*outLen < keySz) {
|
*outLen = ED25519_KEY_SIZE;
|
||||||
*outLen = keySz;
|
|
||||||
return BUFFER_E;
|
return BUFFER_E;
|
||||||
}
|
}
|
||||||
*outLen = keySz;
|
|
||||||
XMEMCPY(out, key->k, keySz);
|
*outLen = ED25519_KEY_SIZE;
|
||||||
|
XMEMCPY(out, key->k, ED25519_KEY_SIZE);
|
||||||
|
|
||||||
return 0;
|
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)
|
int wc_ed25519_size(ed25519_key* key)
|
||||||
{
|
{
|
||||||
word32 keySz;
|
|
||||||
|
|
||||||
if (key == NULL)
|
if (key == NULL)
|
||||||
return BAD_FUNC_ARG;
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
keySz = ED25519_KEY_SIZE;
|
return ED25519_KEY_SIZE;
|
||||||
|
|
||||||
return keySz;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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 */
|
/* returns the size of signature in bytes */
|
||||||
int wc_ed25519_sig_size(ed25519_key* key)
|
int wc_ed25519_sig_size(ed25519_key* key)
|
||||||
{
|
{
|
||||||
word32 sigSz;
|
|
||||||
|
|
||||||
if (key == NULL)
|
if (key == NULL)
|
||||||
return BAD_FUNC_ARG;
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
sigSz = ED25519_SIG_SIZE;
|
return ED25519_SIG_SIZE;
|
||||||
|
|
||||||
return sigSz;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* HAVE_ED25519 */
|
#endif /* HAVE_ED25519 */
|
||||||
|
@ -107,8 +107,9 @@ void fe_0(fe h)
|
|||||||
|
|
||||||
int curve25519(byte* q, byte* n, byte* p)
|
int curve25519(byte* q, byte* n, byte* p)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
unsigned char e[32];
|
unsigned char e[32];
|
||||||
unsigned int i;
|
#endif
|
||||||
fe x1;
|
fe x1;
|
||||||
fe x2;
|
fe x2;
|
||||||
fe z2;
|
fe z2;
|
||||||
@ -120,10 +121,16 @@ int curve25519(byte* q, byte* n, byte* p)
|
|||||||
unsigned int swap;
|
unsigned int swap;
|
||||||
unsigned int b;
|
unsigned int b;
|
||||||
|
|
||||||
for (i = 0;i < 32;++i) e[i] = n[i];
|
/* Clamp already done during key generation and import */
|
||||||
e[0] &= 248;
|
#if 0
|
||||||
e[31] &= 127;
|
{
|
||||||
e[31] |= 64;
|
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_frombytes(x1,p);
|
||||||
fe_1(x2);
|
fe_1(x2);
|
||||||
@ -133,7 +140,11 @@ int curve25519(byte* q, byte* n, byte* p)
|
|||||||
|
|
||||||
swap = 0;
|
swap = 0;
|
||||||
for (pos = 254;pos >= 0;--pos) {
|
for (pos = 254;pos >= 0;--pos) {
|
||||||
|
#if 0
|
||||||
b = e[pos / 8] >> (pos & 7);
|
b = e[pos / 8] >> (pos & 7);
|
||||||
|
#else
|
||||||
|
b = n[pos / 8] >> (pos & 7);
|
||||||
|
#endif
|
||||||
b &= 1;
|
b &= 1;
|
||||||
swap ^= b;
|
swap ^= b;
|
||||||
fe_cswap(x2,x3,swap);
|
fe_cswap(x2,x3,swap);
|
||||||
|
@ -5510,6 +5510,27 @@ int curve25519_test(void)
|
|||||||
if (XMEMCMP(ss, sharedB, y))
|
if (XMEMCMP(ss, sharedB, y))
|
||||||
return -1017;
|
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 */
|
/* clean up keys when done */
|
||||||
wc_curve25519_free(&pubKey);
|
wc_curve25519_free(&pubKey);
|
||||||
wc_curve25519_free(&userB);
|
wc_curve25519_free(&userB);
|
||||||
|
23
wolfssl/openssl/ec25519.h
Normal file
23
wolfssl/openssl/ec25519.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/* ec25519.h */
|
||||||
|
|
||||||
|
#ifndef WOLFSSL_EC25519_H_
|
||||||
|
#define WOLFSSL_EC25519_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
WOLFSSL_API
|
||||||
|
int wolfSSL_EC25519_generate_key(unsigned char *priv, unsigned int *privSz,
|
||||||
|
unsigned char *pub, unsigned int *pubSz);
|
||||||
|
|
||||||
|
WOLFSSL_API
|
||||||
|
int wolfSSL_EC25519_shared_key(unsigned char *shared, unsigned int *sharedSz,
|
||||||
|
const unsigned char *priv, unsigned int privSz,
|
||||||
|
const unsigned char *pub, unsigned int pubSz);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* header */
|
26
wolfssl/openssl/ed25519.h
Normal file
26
wolfssl/openssl/ed25519.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/* ed25519.h */
|
||||||
|
|
||||||
|
#ifndef WOLFSSL_ED25519_H_
|
||||||
|
#define WOLFSSL_ED25519_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
WOLFSSL_API
|
||||||
|
int wolfSSL_ED25519_generate_key(unsigned char *priv, unsigned int *privSz,
|
||||||
|
unsigned char *pub, unsigned int *pubSz);
|
||||||
|
WOLFSSL_API
|
||||||
|
int wolfSSL_ED25519_sign(const unsigned char *msg, unsigned int msgSz,
|
||||||
|
const unsigned char *priv, unsigned int privSz,
|
||||||
|
unsigned char *sig, unsigned int *sigSz);
|
||||||
|
WOLFSSL_API
|
||||||
|
int wolfSSL_ED25519_verify(const unsigned char *msg, unsigned int msgSz,
|
||||||
|
const unsigned char *pub, unsigned int pubSz,
|
||||||
|
const unsigned char *sig, unsigned int sigSz);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* header */
|
@ -13,6 +13,8 @@ nobase_include_HEADERS+= \
|
|||||||
wolfssl/openssl/ecdsa.h \
|
wolfssl/openssl/ecdsa.h \
|
||||||
wolfssl/openssl/ecdh.h \
|
wolfssl/openssl/ecdh.h \
|
||||||
wolfssl/openssl/ec.h \
|
wolfssl/openssl/ec.h \
|
||||||
|
wolfssl/openssl/ec25519.h \
|
||||||
|
wolfssl/openssl/ed25519.h \
|
||||||
wolfssl/openssl/engine.h \
|
wolfssl/openssl/engine.h \
|
||||||
wolfssl/openssl/err.h \
|
wolfssl/openssl/err.h \
|
||||||
wolfssl/openssl/evp.h \
|
wolfssl/openssl/evp.h \
|
||||||
|
@ -28,7 +28,7 @@ int wolfSSL_PEM_write_RSAPrivateKey(FILE *fp, WOLFSSL_RSA *rsa,
|
|||||||
WOLFSSL_API
|
WOLFSSL_API
|
||||||
int wolfSSL_PEM_write_mem_RSAPrivateKey(RSA* rsa, const EVP_CIPHER* cipher,
|
int wolfSSL_PEM_write_mem_RSAPrivateKey(RSA* rsa, const EVP_CIPHER* cipher,
|
||||||
unsigned char* passwd, int len,
|
unsigned char* passwd, int len,
|
||||||
byte **pem, int *plen);
|
unsigned char **pem, int *plen);
|
||||||
WOLFSSL_API
|
WOLFSSL_API
|
||||||
WOLFSSL_RSA *wolfSSL_PEM_read_RSAPublicKey(FILE *fp, WOLFSSL_RSA **x,
|
WOLFSSL_RSA *wolfSSL_PEM_read_RSAPublicKey(FILE *fp, WOLFSSL_RSA **x,
|
||||||
pem_password_cb *cb, void *u);
|
pem_password_cb *cb, void *u);
|
||||||
@ -54,7 +54,7 @@ WOLFSSL_API
|
|||||||
int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa,
|
int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa,
|
||||||
const EVP_CIPHER* cipher,
|
const EVP_CIPHER* cipher,
|
||||||
unsigned char* passwd, int len,
|
unsigned char* passwd, int len,
|
||||||
byte **pem, int *plen);
|
unsigned char **pem, int *plen);
|
||||||
WOLFSSL_API
|
WOLFSSL_API
|
||||||
int wolfSSL_PEM_write_DSA_PUBKEY(FILE *fp, WOLFSSL_DSA *x);
|
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,
|
int wolfSSL_PEM_write_mem_ECPrivateKey(WOLFSSL_EC_KEY* key,
|
||||||
const EVP_CIPHER* cipher,
|
const EVP_CIPHER* cipher,
|
||||||
unsigned char* passwd, int len,
|
unsigned char* passwd, int len,
|
||||||
byte **pem, int *plen);
|
unsigned char **pem, int *plen);
|
||||||
WOLFSSL_API
|
WOLFSSL_API
|
||||||
int wolfSSL_PEM_write_EC_PUBKEY(FILE *fp, WOLFSSL_EC_KEY *key);
|
int wolfSSL_PEM_write_EC_PUBKEY(FILE *fp, WOLFSSL_EC_KEY *key);
|
||||||
|
|
||||||
|
@ -42,7 +42,8 @@ typedef struct {
|
|||||||
} curve25519_set_type;
|
} curve25519_set_type;
|
||||||
|
|
||||||
|
|
||||||
/* ECC point */
|
/* ECC point, the internal structure is Little endian
|
||||||
|
* the mathematical functions used the endianess */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
byte point[CURVE25519_KEYSIZE];
|
byte point[CURVE25519_KEYSIZE];
|
||||||
}ECPoint;
|
}ECPoint;
|
||||||
@ -58,6 +59,11 @@ typedef struct {
|
|||||||
ECPoint k; /* private key */
|
ECPoint k; /* private key */
|
||||||
} curve25519_key;
|
} curve25519_key;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
EC25519_LITTLE_ENDIAN=0,
|
||||||
|
EC25519_BIG_ENDIAN=1
|
||||||
|
};
|
||||||
|
|
||||||
WOLFSSL_API
|
WOLFSSL_API
|
||||||
int wc_curve25519_make_key(RNG* rng, int keysize, curve25519_key* key);
|
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,
|
curve25519_key* public_key,
|
||||||
byte* out, word32* outlen);
|
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
|
WOLFSSL_API
|
||||||
int wc_curve25519_init(curve25519_key* key);
|
int wc_curve25519_init(curve25519_key* key);
|
||||||
|
|
||||||
@ -74,21 +85,49 @@ void wc_curve25519_free(curve25519_key* key);
|
|||||||
|
|
||||||
|
|
||||||
/* raw key helpers */
|
/* 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
|
WOLFSSL_API
|
||||||
int wc_curve25519_import_private_raw(const byte* priv, word32 privSz,
|
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);
|
||||||
WOLFSSL_API
|
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,
|
int wc_curve25519_export_private_raw(curve25519_key* key, byte* out,
|
||||||
word32* outLen);
|
word32* outLen);
|
||||||
|
WOLFSSL_API
|
||||||
|
int wc_curve25519_export_private_raw_ex(curve25519_key* key, byte* out,
|
||||||
|
word32* outLen, int endian);
|
||||||
|
|
||||||
WOLFSSL_API
|
WOLFSSL_API
|
||||||
int wc_curve25519_import_public(const byte* in, word32 inLen,
|
int wc_curve25519_import_public(const byte* in, word32 inLen,
|
||||||
curve25519_key* key);
|
curve25519_key* key);
|
||||||
|
WOLFSSL_API
|
||||||
|
int wc_curve25519_import_public_ex(const byte* in, word32 inLen,
|
||||||
|
curve25519_key* key, int endian);
|
||||||
|
|
||||||
WOLFSSL_API
|
WOLFSSL_API
|
||||||
int wc_curve25519_export_public(curve25519_key* key, byte* out, word32* outLen);
|
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 */
|
/* size helper */
|
||||||
WOLFSSL_API
|
WOLFSSL_API
|
||||||
int wc_curve25519_size(curve25519_key* key);
|
int wc_curve25519_size(curve25519_key* key);
|
||||||
|
@ -46,14 +46,17 @@
|
|||||||
"-121665/121666", value of d
|
"-121665/121666", value of d
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define ED25519_KEY_SIZE 32
|
#define ED25519_KEY_SIZE 32 /* private key only */
|
||||||
#define ED25519_SIG_SIZE 64
|
#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 */
|
/* An ED25519 Key */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
byte p[32]; /* compressed public key */
|
byte p[ED25519_PUB_KEY_SIZE]; /* compressed public key */
|
||||||
byte k[64]; /* private key : 32 secret -- 32 public */
|
byte k[ED25519_PRV_KEY_SIZE]; /* private key : 32 secret -- 32 public */
|
||||||
} ed25519_key;
|
} ed25519_key;
|
||||||
|
|
||||||
|
|
||||||
@ -78,11 +81,21 @@ WOLFSSL_API
|
|||||||
int wc_ed25519_export_public(ed25519_key*, byte* out, word32* outLen);
|
int wc_ed25519_export_public(ed25519_key*, byte* out, word32* outLen);
|
||||||
WOLFSSL_API
|
WOLFSSL_API
|
||||||
int wc_ed25519_export_private_only(ed25519_key* key, byte* out, word32* outLen);
|
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 */
|
/* size helper */
|
||||||
WOLFSSL_API
|
WOLFSSL_API
|
||||||
int wc_ed25519_size(ed25519_key* key);
|
int wc_ed25519_size(ed25519_key* key);
|
||||||
WOLFSSL_API
|
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);
|
int wc_ed25519_sig_size(ed25519_key* key);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
Reference in New Issue
Block a user