Support Ed25519 sign/verify algorithms ctx and ph

This commit is contained in:
Sean Parkinson
2019-04-30 10:23:03 +10:00
parent fdabe614f8
commit 9d736898cc
3 changed files with 383 additions and 26 deletions

View File

@ -45,6 +45,12 @@
#include <wolfssl/wolfcrypt/port/nxp/ksdk_port.h>
#endif
#if defined(HAVE_ED25519_SIGN) || defined(HAVE_ED25519_VERIFY)
#define ED25519CTX_SIZE 32
static const byte ed25519Ctx[ED25519CTX_SIZE] =
"SigEd25519 no Ed25519 collisions";
#endif
int wc_ed25519_make_public(ed25519_key* key, unsigned char* pubKey,
word32 pubKeySz)
@ -118,15 +124,19 @@ int wc_ed25519_make_key(WC_RNG* rng, int keySz, ed25519_key* key)
#ifdef HAVE_ED25519_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
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
type one of Ed25519, Ed25519ctx or Ed25519ph
context extra signing data
contextLen length of extra signing data
return 0 on success
*/
int wc_ed25519_sign_msg(const byte* in, word32 inlen, byte* out,
word32 *outLen, ed25519_key* key)
static int ed25519_sign_msg(const byte* in, word32 inLen, byte* out,
word32 *outLen, ed25519_key* key, byte type,
const byte* context, byte contextLen)
{
#ifdef FREESCALE_LTC_ECC
byte tempBuf[ED25519_PRV_KEY_SIZE];
@ -140,8 +150,10 @@ int wc_ed25519_sign_msg(const byte* in, word32 inlen, byte* out,
int ret;
/* sanity check on arguments */
if (in == NULL || out == NULL || outLen == NULL || key == NULL)
if (in == NULL || out == NULL || outLen == NULL || key == NULL ||
(context == NULL && contextLen != 0)) {
return BAD_FUNC_ARG;
}
if (!key->pubKeySet)
return BAD_FUNC_ARG;
@ -166,9 +178,19 @@ int wc_ed25519_sign_msg(const byte* in, word32 inlen, byte* out,
ret = wc_InitSha512(&sha);
if (ret != 0)
return ret;
if (type == Ed25519ctx || type == Ed25519ph) {
ret = wc_Sha512Update(&sha, ed25519Ctx, ED25519CTX_SIZE);
if (ret == 0)
ret = wc_Sha512Update(&sha, &type, sizeof(type));
if (ret == 0)
ret = wc_Sha512Update(&sha, &contextLen, sizeof(contextLen));
if (ret == 0 && context != NULL)
ret = wc_Sha512Update(&sha, context, contextLen);
}
if (ret == 0)
ret = wc_Sha512Update(&sha, az + ED25519_KEY_SIZE, ED25519_KEY_SIZE);
if (ret == 0)
ret = wc_Sha512Update(&sha, in, inlen);
ret = wc_Sha512Update(&sha, in, inLen);
if (ret == 0)
ret = wc_Sha512Final(&sha, nonce);
wc_Sha512Free(&sha);
@ -180,7 +202,8 @@ int wc_ed25519_sign_msg(const byte* in, word32 inlen, byte* out,
ltcPoint.X = &tempBuf[0];
ltcPoint.Y = &tempBuf[32];
LTC_PKHA_sc_reduce(nonce);
LTC_PKHA_Ed25519_PointMul(LTC_PKHA_Ed25519_BasePoint(), nonce, ED25519_KEY_SIZE, &ltcPoint, kLTC_Ed25519 /* result on Ed25519 */);
LTC_PKHA_Ed25519_PointMul(LTC_PKHA_Ed25519_BasePoint(), nonce,
ED25519_KEY_SIZE, &ltcPoint, kLTC_Ed25519 /* result on Ed25519 */);
LTC_PKHA_Ed25519_Compress(&ltcPoint, out);
#else
sc_reduce(nonce);
@ -196,11 +219,21 @@ int wc_ed25519_sign_msg(const byte* in, word32 inlen, byte* out,
ret = wc_InitSha512(&sha);
if (ret != 0)
return ret;
if (type == Ed25519ctx || type == Ed25519ph) {
ret = wc_Sha512Update(&sha, ed25519Ctx, ED25519CTX_SIZE);
if (ret == 0)
ret = wc_Sha512Update(&sha, &type, sizeof(type));
if (ret == 0)
ret = wc_Sha512Update(&sha, &contextLen, sizeof(contextLen));
if (ret == 0 && context != NULL)
ret = wc_Sha512Update(&sha, context, contextLen);
}
if (ret == 0)
ret = wc_Sha512Update(&sha, out, ED25519_SIG_SIZE/2);
if (ret == 0)
ret = wc_Sha512Update(&sha, key->p, ED25519_PUB_KEY_SIZE);
if (ret == 0)
ret = wc_Sha512Update(&sha, in, inlen);
ret = wc_Sha512Update(&sha, in, inLen);
if (ret == 0)
ret = wc_Sha512Final(&sha, hram);
wc_Sha512Free(&sha);
@ -218,20 +251,100 @@ int wc_ed25519_sign_msg(const byte* in, word32 inlen, byte* out,
return ret;
}
/*
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
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)
{
return ed25519_sign_msg(in, inLen, out, outLen, key, Ed25519, NULL, 0);
}
/*
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
key is the ed25519 key to use when signing
context extra signing data
contextLen length of extra signing data
return 0 on success
*/
int wc_ed25519ctx_sign_msg(const byte* in, word32 inLen, byte* out,
word32 *outLen, ed25519_key* key,
const byte* context, byte contextLen)
{
return ed25519_sign_msg(in, inLen, out, outLen, key, Ed25519ctx, context,
contextLen);
}
/*
hash contains the SHA-512 hash of the message to sign
hashLen is the length of the SHA-512 hash 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
key is the ed25519 key to use when signing
context extra signing data
contextLen length of extra signing data
return 0 on success
*/
int wc_ed25519ph_sign_hash(const byte* hash, word32 hashLen, byte* out,
word32 *outLen, ed25519_key* key,
const byte* context, byte contextLen)
{
return ed25519_sign_msg(hash, hashLen, out, outLen, key, Ed25519ph, context,
contextLen);
}
/*
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
key is the ed25519 key to use when signing
context extra signing data
contextLen length of extra signing data
return 0 on success
*/
int wc_ed25519ph_sign_msg(const byte* in, word32 inLen, byte* out,
word32 *outLen, ed25519_key* key,
const byte* context, byte contextLen)
{
int ret;
byte hash[WC_SHA512_DIGEST_SIZE];
ret = wc_Sha512Hash(in, inLen, hash);
if (ret != 0)
return ret;
return wc_ed25519ph_sign_hash(hash, sizeof(hash), out, outLen, key, context,
contextLen);
}
#endif /* HAVE_ED25519_SIGN */
#ifdef HAVE_ED25519_VERIFY
/*
sig is array of bytes containing the signature
siglen is the length of sig byte array
sigLen is the length of sig byte array
msg the array of bytes containing the message
msglen length of msg array
msgLen length of msg array
res will be 1 on successful verify and 0 on unsuccessful
key Ed25519 public key
return 0 and res of 1 on success
*/
int wc_ed25519_verify_msg(const byte* sig, word32 siglen, const byte* msg,
word32 msglen, int* res, ed25519_key* key)
static int ed25519_verify_msg(const byte* sig, word32 sigLen, const byte* msg,
word32 msgLen, int* res, ed25519_key* key,
byte type, const byte* context, byte contextLen)
{
byte rcheck[ED25519_KEY_SIZE];
byte h[WC_SHA512_DIGEST_SIZE];
@ -243,14 +356,16 @@ int wc_ed25519_verify_msg(const byte* sig, word32 siglen, const byte* msg,
wc_Sha512 sha;
/* sanity check on arguments */
if (sig == NULL || msg == NULL || res == NULL || key == NULL)
if (sig == NULL || msg == NULL || res == NULL || key == NULL ||
(context == NULL && contextLen != 0)) {
return BAD_FUNC_ARG;
}
/* set verification failed by default */
*res = 0;
/* check on basics needed to verify signature */
if (siglen < ED25519_SIG_SIZE || (sig[ED25519_SIG_SIZE-1] & 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 */
@ -263,11 +378,21 @@ int wc_ed25519_verify_msg(const byte* sig, word32 siglen, const byte* msg,
ret = wc_InitSha512(&sha);
if (ret != 0)
return ret;
if (type == Ed25519ctx || type == Ed25519ph) {
ret = wc_Sha512Update(&sha, ed25519Ctx, ED25519CTX_SIZE);
if (ret == 0)
ret = wc_Sha512Update(&sha, &type, sizeof(type));
if (ret == 0)
ret = wc_Sha512Update(&sha, &contextLen, sizeof(contextLen));
if (ret == 0 && context != NULL)
ret = wc_Sha512Update(&sha, context, contextLen);
}
if (ret == 0)
ret = wc_Sha512Update(&sha, sig, ED25519_SIG_SIZE/2);
if (ret == 0)
ret = wc_Sha512Update(&sha, key->p, ED25519_PUB_KEY_SIZE);
if (ret == 0)
ret = wc_Sha512Update(&sha, msg, msglen);
ret = wc_Sha512Update(&sha, msg, msgLen);
if (ret == 0)
ret = wc_Sha512Final(&sha, h);
wc_Sha512Free(&sha);
@ -302,6 +427,85 @@ int wc_ed25519_verify_msg(const byte* sig, word32 siglen, const byte* msg,
return ret;
}
/*
sig is array of bytes containing the signature
sigLen is the length of sig byte array
msg the array of bytes containing the message
msgLen length of msg array
res will be 1 on successful verify and 0 on unsuccessful
key Ed25519 public key
return 0 and res of 1 on success
*/
int wc_ed25519_verify_msg(const byte* sig, word32 sigLen, const byte* msg,
word32 msgLen, int* res, ed25519_key* key)
{
return ed25519_verify_msg(sig, sigLen, msg, msgLen, res, key, Ed25519, NULL,
0);
}
/*
sig is array of bytes containing the signature
sigLen is the length of sig byte array
msg the array of bytes containing the message
msgLen length of msg array
res will be 1 on successful verify and 0 on unsuccessful
key Ed25519 public key
context extra sigining data
contextLen length of extra sigining data
return 0 and res of 1 on success
*/
int wc_ed25519ctx_verify_msg(const byte* sig, word32 sigLen, const byte* msg,
word32 msgLen, int* res, ed25519_key* key,
const byte* context, byte contextLen)
{
return ed25519_verify_msg(sig, sigLen, msg, msgLen, res, key, Ed25519ctx,
context, contextLen);
}
/*
sig is array of bytes containing the signature
sigLen is the length of sig byte array
hash the array of bytes containing the SHA-512 hash of the message
hashLen length of hash array
res will be 1 on successful verify and 0 on unsuccessful
key Ed25519 public key
context extra sigining data
contextLen length of extra sigining data
return 0 and res of 1 on success
*/
int wc_ed25519ph_verify_hash(const byte* sig, word32 sigLen, const byte* hash,
word32 hashLen, int* res, ed25519_key* key,
const byte* context, byte contextLen)
{
return ed25519_verify_msg(sig, sigLen, hash, hashLen, res, key, Ed25519ph,
context, contextLen);
}
/*
sig is array of bytes containing the signature
sigLen is the length of sig byte array
msg the array of bytes containing the message
msgLen length of msg array
res will be 1 on successful verify and 0 on unsuccessful
key Ed25519 public key
context extra sigining data
contextLen length of extra sigining data
return 0 and res of 1 on success
*/
int wc_ed25519ph_verify_msg(const byte* sig, word32 sigLen, const byte* msg,
word32 msgLen, int* res, ed25519_key* key,
const byte* context, byte contextLen)
{
int ret;
byte hash[WC_SHA512_DIGEST_SIZE];
ret = wc_Sha512Hash(msg, msgLen, hash);
if (ret != 0)
return ret;
return wc_ed25519ph_verify_hash(sig, sigLen, hash, sizeof(hash), res, key,
context, contextLen);
}
#endif /* HAVE_ED25519_VERIFY */

View File

@ -18531,6 +18531,20 @@ int ed25519_test(void)
static const byte* sKeys[] = {sKey1, sKey2, sKey3, sKey4, sKey5, sKey6};
static const byte sKeyCtx1[] = {
0x03,0x05,0x33,0x4e,0x38,0x1a,0xf7,0x8f,
0x14,0x1c,0xb6,0x66,0xf6,0x19,0x9f,0x57,
0xbc,0x34,0x95,0x33,0x5a,0x25,0x6a,0x95,
0xbd,0x2a,0x55,0xbf,0x54,0x66,0x63,0xf6
};
static const byte sKeyPh1[] = {
0x83,0x3f,0xe6,0x24,0x09,0x23,0x7b,0x9d,
0x62,0xec,0x77,0x58,0x75,0x20,0x91,0x1e,
0x9a,0x75,0x9c,0xec,0x1d,0x19,0x75,0x5b,
0x7d,0xa9,0x01,0xb9,0x6d,0xca,0x3d,0x42
};
static const byte pKey1[] = {
0xd7,0x5a,0x98,0x01,0x82,0xb1,0x0a,0xb7,
0xd5,0x4b,0xfe,0xd3,0xc9,0x64,0x07,0x3a,
@ -18584,6 +18598,22 @@ int ed25519_test(void)
static const byte pKeySz[] = {sizeof(pKey1), sizeof(pKey2), sizeof(pKey3),
sizeof(pKey4), sizeof(pKey5), sizeof(pKey6)};
static const byte pKeyCtx1[] = {
0xdf,0xc9,0x42,0x5e,0x4f,0x96,0x8f,0x7f,
0x0c,0x29,0xf0,0x25,0x9c,0xf5,0xf9,0xae,
0xd6,0x85,0x1c,0x2b,0xb4,0xad,0x8b,0xfb,
0x86,0x0c,0xfe,0xe0,0xab,0x24,0x82,0x92
};
static const byte pKeyPh1[] = {
0xec,0x17,0x2b,0x93,0xad,0x5e,0x56,0x3b,
0xf4,0x93,0x2c,0x70,0xe1,0x24,0x50,0x34,
0xc3,0x54,0x67,0xef,0x2e,0xfd,0x4d,0x64,
0xeb,0xf8,0x19,0x68,0x34,0x67,0xe2,0xbf
};
static const byte sig1[] = {
0xe5,0x56,0x43,0x00,0xc3,0x60,0xac,0x72,
0x90,0x86,0xe2,0xcc,0x80,0x6e,0x82,0x8a,
@ -18654,6 +18684,28 @@ int ed25519_test(void)
static const byte* sigs[] = {sig1, sig2, sig3, sig4, sig5, sig6};
static const byte sigCtx1[] = {
0x55,0xa4,0xcc,0x2f,0x70,0xa5,0x4e,0x04,
0x28,0x8c,0x5f,0x4c,0xd1,0xe4,0x5a,0x7b,
0xb5,0x20,0xb3,0x62,0x92,0x91,0x18,0x76,
0xca,0xda,0x73,0x23,0x19,0x8d,0xd8,0x7a,
0x8b,0x36,0x95,0x0b,0x95,0x13,0x00,0x22,
0x90,0x7a,0x7f,0xb7,0xc4,0xe9,0xb2,0xd5,
0xf6,0xcc,0xa6,0x85,0xa5,0x87,0xb4,0xb2,
0x1f,0x4b,0x88,0x8e,0x4e,0x7e,0xdb,0x0d
};
static const byte sigPh1[] = {
0x98,0xa7,0x02,0x22,0xf0,0xb8,0x12,0x1a,
0xa9,0xd3,0x0f,0x81,0x3d,0x68,0x3f,0x80,
0x9e,0x46,0x2b,0x46,0x9c,0x7f,0xf8,0x76,
0x39,0x49,0x9b,0xb9,0x4e,0x6d,0xae,0x41,
0x31,0xf8,0x50,0x42,0x46,0x3c,0x2a,0x35,
0x5a,0x20,0x03,0xd0,0x62,0xad,0xf5,0xaa,
0xa1,0x0b,0x8c,0x61,0xe6,0x36,0x06,0x2a,
0xaa,0xd1,0x1c,0x2a,0x26,0x08,0x34,0x06
};
static const byte msg1[] = {0x0 };
static const byte msg2[] = {0x72};
static const byte msg3[] = {0xAF,0x82};
@ -18798,6 +18850,19 @@ int ed25519_test(void)
0 /*sizeof(msg1)*/,
sizeof(msg4)
};
static const byte msgCtx1[] = {
0xf7,0x26,0x93,0x6d,0x19,0xc8,0x00,0x49,
0x4e,0x3f,0xda,0xff,0x20,0xb2,0x76,0xa8
};
static const byte msgPh1[] = {
0x61,0x62,0x63
};
static const byte contextCtx1[] = {
0x66,0x6f,0x6f
};
#ifndef NO_ASN
static byte privateEd25519[] = {
0x30,0x2e,0x02,0x01,0x00,0x30,0x05,0x06,
@ -18916,6 +18981,64 @@ int ed25519_test(void)
#endif /* HAVE_ED25519_VERIFY */
}
outlen = sizeof(out);
XMEMSET(out, 0, sizeof(out));
if (wc_ed25519_import_private_key(sKeyCtx1, ED25519_KEY_SIZE, pKeyCtx1,
sizeof(pKeyCtx1), &key) != 0)
return -9020;
if (wc_ed25519ctx_sign_msg(msgCtx1, sizeof(msgCtx1), out, &outlen, &key,
contextCtx1, sizeof(contextCtx1)) != 0)
return -9021;
if (XMEMCMP(out, sigCtx1, 64))
return -9022;
#if defined(HAVE_ED25519_VERIFY)
/* test verify on good msg */
if (wc_ed25519ctx_verify_msg(out, outlen, msgCtx1, sizeof(msgCtx1), &verify,
&key, contextCtx1, sizeof(contextCtx1)) != 0 ||
verify != 1)
return -9023;
/* test verify on bad msg */
out[outlen-1] = out[outlen-1] + 1;
if (wc_ed25519ctx_verify_msg(out, outlen, msgCtx1, sizeof(msgCtx1), &verify,
&key, contextCtx1, sizeof(contextCtx1)) == 0 ||
verify == 1)
return -9024;
#endif
outlen = sizeof(out);
XMEMSET(out, 0, sizeof(out));
if (wc_ed25519_import_private_key(sKeyPh1, ED25519_KEY_SIZE, pKeyPh1,
sizeof(pKeyPh1), &key) != 0)
return -9025;
if (wc_ed25519ph_sign_msg(msgPh1, sizeof(msgPh1), out, &outlen, &key, NULL,
0) != 0)
return -9026;
if (XMEMCMP(out, sigPh1, 64))
return -9027;
#if defined(HAVE_ED25519_VERIFY)
/* test verify on good msg */
if (wc_ed25519ph_verify_msg(out, outlen, msgPh1, sizeof(msgPh1), &verify,
&key, NULL, 0) != 0 ||
verify != 1)
return -9028;
/* test verify on bad msg */
out[outlen-1] = out[outlen-1] + 1;
if (wc_ed25519ph_verify_msg(out, outlen, msgPh1, sizeof(msgPh1), &verify,
&key, NULL, 0) == 0 ||
verify == 1)
return -9029;
#endif
#ifndef NO_ASN
/* Try ASN.1 encoded private-only key and public key. */
idx = 0;

View File

@ -63,6 +63,12 @@
#define ED25519_PRV_KEY_SIZE (ED25519_PUB_KEY_SIZE+ED25519_KEY_SIZE)
enum {
Ed25519 = -1,
Ed25519ctx = 0,
Ed25519ph = 1,
};
#ifndef WC_ED25519KEY_TYPE_DEFINED
typedef struct ed25519_key ed25519_key;
#define WC_ED25519KEY_TYPE_DEFINED
@ -90,11 +96,35 @@ int wc_ed25519_make_public(ed25519_key* key, unsigned char* pubKey,
WOLFSSL_API
int wc_ed25519_make_key(WC_RNG* rng, int keysize, ed25519_key* key);
WOLFSSL_API
int wc_ed25519_sign_msg(const byte* in, word32 inlen, byte* out,
word32 *outlen, ed25519_key* key);
int wc_ed25519_sign_msg(const byte* in, word32 inLen, byte* out,
word32 *outLen, ed25519_key* key);
WOLFSSL_API
int wc_ed25519_verify_msg(const byte* sig, word32 siglen, const byte* msg,
word32 msglen, int* stat, ed25519_key* key);
int wc_ed25519ctx_sign_msg(const byte* in, word32 inLen, byte* out,
word32 *outLen, ed25519_key* key,
const byte* context, byte contextLen);
WOLFSSL_API
int wc_ed25519ph_sign_hash(const byte* hash, word32 hashLen, byte* out,
word32 *outLen, ed25519_key* key,
const byte* context, byte contextLen);
WOLFSSL_API
int wc_ed25519ph_sign_msg(const byte* in, word32 inLen, byte* out,
word32 *outLen, ed25519_key* key, const byte* context,
byte contextLen);
WOLFSSL_API
int wc_ed25519_verify_msg(const byte* sig, word32 sigLen, const byte* msg,
word32 msgLen, int* stat, ed25519_key* key);
WOLFSSL_API
int wc_ed25519ctx_verify_msg(const byte* sig, word32 sigLen, const byte* msg,
word32 msgLen, int* stat, ed25519_key* key,
const byte* context, byte contextLen);
WOLFSSL_API
int wc_ed25519ph_verify_hash(const byte* sig, word32 sigLen, const byte* hash,
word32 hashLen, int* stat, ed25519_key* key,
const byte* context, byte contextLen);
WOLFSSL_API
int wc_ed25519ph_verify_msg(const byte* sig, word32 sigLen, const byte* msg,
word32 msgLen, int* stat, ed25519_key* key,
const byte* context, byte contextLen);
WOLFSSL_API
int wc_ed25519_init(ed25519_key* key);
WOLFSSL_API