Skip to content

Commit 9dec999

Browse files
committed
re-factor some parts of the Ed25519ctx and Ed25519ph implementation
* The RFC doesn't limit the context to be a string. It talks about `octets` which means it could be any binary data. * Move the context-preprocessing function out of tweetnacl.c * Fix potential segfaults when Ed25519 signature verification fails and `LTC_CLEAN_STACK` is enabled. * Fix all the warnings. * Update documentation. Signed-off-by: Steffen Jaeckel <[email protected]>
1 parent b761cc0 commit 9dec999

File tree

8 files changed

+195
-146
lines changed

8 files changed

+195
-146
lines changed

doc/crypt.tex

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5909,25 +5909,49 @@ \subsection{EdDSA Cryptographic Operations}
59095909
To sign and/or verify a message use the following functions:
59105910

59115911
\index{ed25519\_sign}
5912+
\index{ed25519ctx\_sign}
5913+
\index{ed25519ph\_sign}
59125914
\begin{verbatim}
5913-
int ed25519_sign(const unsigned char *msg, unsigned long msglen,
5914-
unsigned char *sig, unsigned long *siglen,
5915+
int ed25519_sign(const unsigned char *msg, unsigned long msglen,
5916+
unsigned char *sig, unsigned long *siglen,
59155917
const curve25519_key *private_key);
5918+
int ed25519ctx_sign(const unsigned char *msg, unsigned long msglen,
5919+
unsigned char *sig, unsigned long *siglen,
5920+
const unsigned char *ctx, unsigned long ctxlen,
5921+
const curve25519_key *private_key);
5922+
int ed25519ph_sign(const unsigned char *msg, unsigned long msglen,
5923+
unsigned char *sig, unsigned long *siglen,
5924+
const unsigned char *ctx, unsigned long ctxlen,
5925+
const curve25519_key *private_key);
59165926
\end{verbatim}
59175927

5918-
This function will EdDSA sign the message stored in the array pointed to by \textit{msg} of length \textit{msglen} octets. The signature
5919-
will be stored in the array pointed to by \textit{sig} of length \textit{siglen} octets.
5928+
These functions will EdDSA sign the message stored in the array pointed to by \textit{msg} of length \textit{msglen} octets. The signature
5929+
will be stored in the array pointed to by \textit{sig} of length \textit{siglen} octets. The \texttt{ctx} and \texttt{ph} variants also
5930+
allow passing a context \textit{ctx} of length \textit{ctxlen} octets. This context is allowed to be max. 255 octets long.
59205931

59215932
\index{ed25519\_verify}
5933+
\index{ed25519ctx\_verify}
5934+
\index{ed25519ph\_verify}
59225935
\begin{verbatim}
59235936
int ed25519_verify(const unsigned char *msg, unsigned long msglen,
59245937
const unsigned char *sig, unsigned long siglen,
5925-
int *stat, const curve25519_key *public_key);
5938+
int *stat,
5939+
const curve25519_key *public_key);
5940+
int ed25519ctx_verify(const unsigned char *msg, unsigned long msglen,
5941+
const unsigned char *sig, unsigned long siglen,
5942+
const unsigned char *ctx, unsigned long ctxlen,
5943+
int *stat,
5944+
const curve25519_key *public_key);
5945+
int ed25519ph_verify(const unsigned char *msg, unsigned long msglen,
5946+
const unsigned char *sig, unsigned long siglen,
5947+
const unsigned char *ctx, unsigned long ctxlen,
5948+
int *stat,
5949+
const curve25519_key *public_key);
59265950
\end{verbatim}
59275951

5928-
This function will verify the EdDSA signature in the array pointed to by \textit{sig} of length \textit{siglen} octets, against the message
5952+
These functions will verify the EdDSA signature in the array pointed to by \textit{sig} of length \textit{siglen} octets, against the message
59295953
pointed to by the array \textit{msg} of length \textit{msglen}. It will store a non--zero value in \textit{stat} if the signature is valid. Note:
5930-
the function will not return an error if the signature is invalid. It will return an error, if the actual signature payload is an invalid format.
5954+
the function will not return an error if the signature is invalid. It will only return an error if the actual signature payload is an invalid format.
59315955

59325956

59335957
\chapter{Digital Signature Algorithm}

src/headers/tomcrypt_pk.h

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -355,25 +355,30 @@ int ed25519_import_pkcs8(const unsigned char *in, unsigned long inlen,
355355
const void *pwd, unsigned long pwdlen,
356356
curve25519_key *key);
357357

358-
int ed25519_sign(const unsigned char *msg, unsigned long msglen,
359-
unsigned char *sig, unsigned long *siglen,
358+
int ed25519_sign(const unsigned char *msg, unsigned long msglen,
359+
unsigned char *sig, unsigned long *siglen,
360360
const curve25519_key *private_key);
361-
int ed25519ctx_sign(const unsigned char *msg, unsigned long msglen,
362-
unsigned char *sig, unsigned long *siglen,
363-
const char* ctx, const curve25519_key *private_key);
364-
int ed25519ph_sign(const unsigned char *msg, unsigned long msglen,
365-
unsigned char *sig, unsigned long *siglen,
366-
const char *ctx, const curve25519_key *private_key);
361+
int ed25519ctx_sign(const unsigned char *msg, unsigned long msglen,
362+
unsigned char *sig, unsigned long *siglen,
363+
const unsigned char *ctx, unsigned long ctxlen,
364+
const curve25519_key *private_key);
365+
int ed25519ph_sign(const unsigned char *msg, unsigned long msglen,
366+
unsigned char *sig, unsigned long *siglen,
367+
const unsigned char *ctx, unsigned long ctxlen,
368+
const curve25519_key *private_key);
367369
int ed25519_verify(const unsigned char *msg, unsigned long msglen,
368370
const unsigned char *sig, unsigned long siglen,
369-
int *stat, const curve25519_key *public_key);
371+
int *stat,
372+
const curve25519_key *public_key);
370373
int ed25519ctx_verify(const unsigned char *msg, unsigned long msglen,
371374
const unsigned char *sig, unsigned long siglen,
372-
int *stat, const char* ctx,
375+
const unsigned char *ctx, unsigned long ctxlen,
376+
int *stat,
373377
const curve25519_key *public_key);
374378
int ed25519ph_verify(const unsigned char *msg, unsigned long msglen,
375379
const unsigned char *sig, unsigned long siglen,
376-
int *stat, const char* ctx,
380+
const unsigned char *ctx, unsigned long ctxlen,
381+
int *stat,
377382
const curve25519_key *public_key);
378383

379384
/** X25519 Key-Exchange API */

src/headers/tomcrypt_private.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99

1010
#define LTC_PAD_MASK (0xF000U)
1111

12-
#define ED25519_CONTEXT_PREFIX "SigEd25519 no Ed25519 collisions"
13-
1412
/*
1513
* Internal Enums
1614
*/
@@ -346,8 +344,6 @@ int tweetnacl_crypto_sk_to_pk(unsigned char *pk, const unsigned char *sk);
346344
int tweetnacl_crypto_scalarmult(unsigned char *q, const unsigned char *n, const unsigned char *p);
347345
int tweetnacl_crypto_scalarmult_base(unsigned char *q,const unsigned char *n);
348346
int tweetnacl_crypto_ph(unsigned char *out, const unsigned char *msg, unsigned long msglen);
349-
int tweetnacl_crypto_ctx(unsigned char *out, unsigned long *outlen,
350-
unsigned char flag, const char *pr, const char* ctx);
351347

352348
typedef int (*sk_to_pk)(unsigned char *pk ,const unsigned char *sk);
353349
int ec25519_import_pkcs8(const unsigned char *in, unsigned long inlen,
@@ -357,6 +353,9 @@ int ec25519_import_pkcs8(const unsigned char *in, unsigned long inlen,
357353
int ec25519_export( unsigned char *out, unsigned long *outlen,
358354
int which,
359355
const curve25519_key *key);
356+
int ec25519_crypto_ctx( unsigned char *out, unsigned long *outlen,
357+
unsigned char flag,
358+
const unsigned char *ctx, unsigned long ctxlen);
360359
#endif /* LTC_CURVE25519 */
361360

362361
#ifdef LTC_DER

src/pk/ec25519/ec25519_crypto_ctx.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2+
/* SPDX-License-Identifier: Unlicense */
3+
#include "tomcrypt_private.h"
4+
5+
/**
6+
@file ec25519_crypto_ctx.c
7+
curve25519 crypto context helper
8+
*/
9+
10+
#ifdef LTC_CURVE25519
11+
12+
int ec25519_crypto_ctx(unsigned char *out, unsigned long *outlen, unsigned char flag, const unsigned char *ctx, unsigned long ctxlen)
13+
{
14+
unsigned char *buf = out;
15+
16+
const char *prefix = "SigEd25519 no Ed25519 collisions";
17+
const unsigned long prefix_len = XSTRLEN(prefix);
18+
const unsigned char ctxlen8 = (unsigned char)ctxlen;
19+
20+
if (ctxlen > 255u) return CRYPT_INPUT_TOO_LONG;
21+
if (*outlen < prefix_len + 2u + ctxlen) return CRYPT_BUFFER_OVERFLOW;
22+
23+
XMEMCPY(buf, prefix, prefix_len);
24+
buf += prefix_len;
25+
XMEMCPY(buf, &flag, 1);
26+
buf++;
27+
XMEMCPY(buf, &ctxlen8, 1);
28+
buf++;
29+
30+
if (ctxlen > 0u) {
31+
XMEMCPY(buf, ctx, ctxlen);
32+
buf += ctxlen;
33+
}
34+
35+
*outlen = buf-out;
36+
37+
return CRYPT_OK;
38+
}
39+
40+
#endif

src/pk/ec25519/tweetnacl.c

Lines changed: 1 addition & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -504,40 +504,5 @@ int tweetnacl_crypto_sign_open(int *stat, u8 *m,u64 *mlen,const u8 *sm,u64 smlen
504504

505505
int tweetnacl_crypto_ph(u8 *out,const u8 *msg,size_t msglen)
506506
{
507-
hash_state md;
508-
509-
sha512_init(&md);
510-
511-
if(sha512_process(&md, msg, msglen) != CRYPT_OK)
512-
return CRYPT_INVALID_ARG;
513-
514-
if(sha512_done(&md, out) != CRYPT_OK)
515-
return CRYPT_INVALID_ARG;
516-
517-
return CRYPT_OK;
518-
}
519-
520-
int tweetnacl_crypto_ctx(u8 *out,size_t *outlen,u8 flag,const char *pr, const char *ctx)
521-
{
522-
u8 *buf = out;
523-
const int ctx_prefix_len = strlen(pr);
524-
const int ctxlen = ctx ? strlen(ctx) : 0;
525-
526-
if(ctxlen > 255) return CRYPT_INPUT_TOO_LONG;
527-
528-
XMEMCPY(buf, pr, ctx_prefix_len);
529-
buf += ctx_prefix_len;
530-
XMEMCPY(buf, &flag, 1);
531-
buf++;
532-
XMEMCPY(buf, &ctxlen, 1);
533-
buf++;
534-
535-
if(ctxlen > 0) {
536-
XMEMCPY(buf, ctx, ctxlen);
537-
buf += ctxlen;
538-
}
539-
540-
*outlen = buf-out;
541-
542-
return CRYPT_OK;
507+
return tweetnacl_crypto_hash(out, msg, msglen);
543508
}

src/pk/ed25519/ed25519_sign.c

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99

1010
#ifdef LTC_CURVE25519
1111

12-
static int ed25519_sign_private(const unsigned char *msg, unsigned long msglen,
13-
unsigned char *sig, unsigned long *siglen,
14-
const char* ctx, unsigned long ctxlen,
12+
static int s_ed25519_sign(const unsigned char *msg, unsigned long msglen,
13+
unsigned char *sig, unsigned long *siglen,
14+
const unsigned char *ctx, unsigned long ctxlen,
1515
const curve25519_key *private_key)
1616
{
1717
unsigned char *s;
@@ -61,21 +61,21 @@ static int ed25519_sign_private(const unsigned char *msg, unsigned long msglen,
6161
@param private_key The private Ed25519 key in the pair
6262
@return CRYPT_OK if successful
6363
*/
64-
int ed25519ctx_sign(const unsigned char *msg, unsigned long msglen,
65-
unsigned char *sig, unsigned long *siglen,
66-
const char* ctx, const curve25519_key *private_key)
64+
int ed25519ctx_sign(const unsigned char *msg, unsigned long msglen,
65+
unsigned char *sig, unsigned long *siglen,
66+
const unsigned char *ctx, unsigned long ctxlen,
67+
const curve25519_key *private_key)
6768
{
69+
int err;
6870
unsigned char ctx_prefix[512] = {0};
69-
unsigned long ctx_prefix_size = 0;
71+
unsigned long ctx_prefix_size = sizeof(ctx_prefix);
7072

7173
LTC_ARGCHK(ctx != NULL);
7274

73-
if(tweetnacl_crypto_ctx(ctx_prefix, &ctx_prefix_size, 0,
74-
ED25519_CONTEXT_PREFIX, ctx) != CRYPT_OK)
75-
return CRYPT_INVALID_ARG;
75+
if ((err = ec25519_crypto_ctx(ctx_prefix, &ctx_prefix_size, 0, ctx, ctxlen)) != CRYPT_OK)
76+
return err;
7677

77-
return ed25519_sign_private(msg, msglen, sig, siglen, ctx_prefix,
78-
ctx_prefix_size, private_key);
78+
return s_ed25519_sign(msg, msglen, sig, siglen, ctx_prefix, ctx_prefix_size, private_key);
7979
}
8080

8181
/**
@@ -88,26 +88,26 @@ int ed25519ctx_sign(const unsigned char *msg, unsigned long msglen,
8888
@param private_key The private Ed25519 key in the pair
8989
@return CRYPT_OK if successful
9090
*/
91-
int ed25519ph_sign(const unsigned char *msg, unsigned long msglen,
92-
unsigned char *sig, unsigned long *siglen,
93-
const char *ctx, const curve25519_key *private_key)
91+
int ed25519ph_sign(const unsigned char *msg, unsigned long msglen,
92+
unsigned char *sig, unsigned long *siglen,
93+
const unsigned char *ctx, unsigned long ctxlen,
94+
const curve25519_key *private_key)
9495
{
96+
int err;
9597
unsigned char ctx_prefix[512] = {0};
9698
unsigned char msg_hash[64] = {0};
97-
unsigned long ctx_prefix_size = 0;
99+
unsigned long ctx_prefix_size = sizeof(ctx_prefix);
98100

99-
if (tweetnacl_crypto_ctx(ctx_prefix, &ctx_prefix_size, 1,
100-
ED25519_CONTEXT_PREFIX, ctx) != CRYPT_OK)
101-
return CRYPT_INVALID_ARG;
101+
if ((err = ec25519_crypto_ctx(ctx_prefix, &ctx_prefix_size, 1, ctx, ctxlen)) != CRYPT_OK)
102+
return err;
102103

103-
if (tweetnacl_crypto_ph(msg_hash, msg, msglen) != CRYPT_OK)
104-
return CRYPT_INVALID_ARG;
104+
if ((err = tweetnacl_crypto_ph(msg_hash, msg, msglen)) != CRYPT_OK)
105+
return err;
105106

106107
msg = msg_hash;
107108
msglen = 64;
108109

109-
return ed25519_sign_private(msg, msglen, sig, siglen, ctx_prefix,
110-
ctx_prefix_size, private_key);
110+
return s_ed25519_sign(msg, msglen, sig, siglen, ctx_prefix, ctx_prefix_size, private_key);
111111
}
112112

113113
/**
@@ -119,11 +119,11 @@ int ed25519ph_sign(const unsigned char *msg, unsigned long msglen,
119119
@param private_key The private Ed25519 key in the pair
120120
@return CRYPT_OK if successful
121121
*/
122-
int ed25519_sign(const unsigned char *msg, unsigned long msglen,
123-
unsigned char *sig, unsigned long *siglen,
122+
int ed25519_sign(const unsigned char *msg, unsigned long msglen,
123+
unsigned char *sig, unsigned long *siglen,
124124
const curve25519_key *private_key)
125125
{
126-
return ed25519_sign_private(msg, msglen, sig, siglen, 0, 0, private_key);
126+
return s_ed25519_sign(msg, msglen, sig, siglen, NULL, 0, private_key);
127127
}
128128

129129
#endif

0 commit comments

Comments
 (0)