Browse Source

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]>
Steffen Jaeckel 3 years ago
parent
commit
9dec999564

+ 31 - 7
doc/crypt.tex

@@ -5909,25 +5909,49 @@ It has support for the following output formats:
 To sign and/or verify a message use the following functions:
 
 \index{ed25519\_sign}
+\index{ed25519ctx\_sign}
+\index{ed25519ph\_sign}
 \begin{verbatim}
-int ed25519_sign(const unsigned char  *msg, unsigned long msglen,
-                       unsigned char  *sig, unsigned long *siglen,
+int ed25519_sign(const  unsigned char *msg, unsigned long msglen,
+                        unsigned char *sig, unsigned long *siglen,
                  const curve25519_key *private_key);
+int ed25519ctx_sign(const  unsigned char *msg, unsigned long  msglen,
+                           unsigned char *sig, unsigned long *siglen,
+                    const  unsigned char *ctx, unsigned long  ctxlen,
+                    const curve25519_key *private_key);
+int ed25519ph_sign(const  unsigned char *msg, unsigned long  msglen,
+                          unsigned char *sig, unsigned long *siglen,
+                   const  unsigned char *ctx, unsigned long  ctxlen,
+                   const curve25519_key *private_key);
 \end{verbatim}
 
-This function will EdDSA sign the message stored in the array pointed to by \textit{msg} of length \textit{msglen} octets.  The signature
-will be stored in the array pointed to by \textit{sig} of length \textit{siglen} octets.
+These functions will EdDSA sign the message stored in the array pointed to by \textit{msg} of length \textit{msglen} octets.  The signature
+will be stored in the array pointed to by \textit{sig} of length \textit{siglen} octets.  The \texttt{ctx} and \texttt{ph} variants also
+allow passing a context \textit{ctx} of length \textit{ctxlen} octets.  This context is allowed to be max. 255 octets long.
 
 \index{ed25519\_verify}
+\index{ed25519ctx\_verify}
+\index{ed25519ph\_verify}
 \begin{verbatim}
 int ed25519_verify(const  unsigned char *msg, unsigned long msglen,
                    const  unsigned char *sig, unsigned long siglen,
-                   int *stat, const curve25519_key *public_key);
+                                    int *stat,
+                   const curve25519_key *public_key);
+int ed25519ctx_verify(const  unsigned char *msg, unsigned long msglen,
+                      const  unsigned char *sig, unsigned long siglen,
+                      const  unsigned char *ctx, unsigned long ctxlen,
+                                       int *stat,
+                      const curve25519_key *public_key);
+int ed25519ph_verify(const  unsigned char *msg, unsigned long msglen,
+                     const  unsigned char *sig, unsigned long siglen,
+                     const  unsigned char *ctx, unsigned long ctxlen,
+                                      int *stat,
+                     const curve25519_key *public_key);
 \end{verbatim}
 
-This function will verify the EdDSA signature in the array pointed to by \textit{sig} of length \textit{siglen} octets, against the message
+These functions will verify the EdDSA signature in the array pointed to by \textit{sig} of length \textit{siglen} octets, against the message
 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:
-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.
+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.
 
 
 \chapter{Digital Signature Algorithm}

+ 16 - 11
src/headers/tomcrypt_pk.h

@@ -355,25 +355,30 @@ int ed25519_import_pkcs8(const unsigned char *in, unsigned long inlen,
                                   const void *pwd, unsigned long pwdlen,
                               curve25519_key *key);
 
-int ed25519_sign(const unsigned char  *msg, unsigned long msglen,
-                       unsigned char  *sig, unsigned long *siglen,
+int ed25519_sign(const  unsigned char *msg, unsigned long msglen,
+                        unsigned char *sig, unsigned long *siglen,
                  const curve25519_key *private_key);
-int ed25519ctx_sign(const unsigned char *msg, unsigned long msglen,
-                    unsigned char *sig, unsigned long *siglen,
-                    const char* ctx, const curve25519_key *private_key);
-int ed25519ph_sign(const unsigned char *msg, unsigned long msglen,
-                   unsigned char *sig, unsigned long *siglen,
-                   const char *ctx, const curve25519_key *private_key);
+int ed25519ctx_sign(const  unsigned char *msg, unsigned long  msglen,
+                           unsigned char *sig, unsigned long *siglen,
+                    const  unsigned char *ctx, unsigned long  ctxlen,
+                    const curve25519_key *private_key);
+int ed25519ph_sign(const  unsigned char *msg, unsigned long  msglen,
+                          unsigned char *sig, unsigned long *siglen,
+                   const  unsigned char *ctx, unsigned long  ctxlen,
+                   const curve25519_key *private_key);
 int ed25519_verify(const  unsigned char *msg, unsigned long msglen,
                    const  unsigned char *sig, unsigned long siglen,
-                   int *stat, const curve25519_key *public_key);
+                                    int *stat,
+                   const curve25519_key *public_key);
 int ed25519ctx_verify(const  unsigned char *msg, unsigned long msglen,
                       const  unsigned char *sig, unsigned long siglen,
-                      int *stat, const char* ctx,
+                      const  unsigned char *ctx, unsigned long ctxlen,
+                                       int *stat,
                       const curve25519_key *public_key);
 int ed25519ph_verify(const  unsigned char *msg, unsigned long msglen,
                      const  unsigned char *sig, unsigned long siglen,
-                     int *stat, const char* ctx,
+                     const  unsigned char *ctx, unsigned long ctxlen,
+                                      int *stat,
                      const curve25519_key *public_key);
 
 /** X25519 Key-Exchange API */

+ 3 - 4
src/headers/tomcrypt_private.h

@@ -9,8 +9,6 @@
 
 #define LTC_PAD_MASK       (0xF000U)
 
-#define ED25519_CONTEXT_PREFIX "SigEd25519 no Ed25519 collisions"
-
 /*
  * Internal Enums
  */
@@ -346,8 +344,6 @@ int tweetnacl_crypto_sk_to_pk(unsigned char *pk, const unsigned char *sk);
 int tweetnacl_crypto_scalarmult(unsigned char *q, const unsigned char *n, const unsigned char *p);
 int tweetnacl_crypto_scalarmult_base(unsigned char *q,const unsigned char *n);
 int tweetnacl_crypto_ph(unsigned char *out, const unsigned char *msg, unsigned long msglen);
-int tweetnacl_crypto_ctx(unsigned char *out, unsigned long *outlen,
-                       unsigned char flag, const char *pr, const char* ctx);
 
 typedef int (*sk_to_pk)(unsigned char *pk ,const unsigned char *sk);
 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,
 int ec25519_export(       unsigned char *out, unsigned long *outlen,
                                     int  which,
                    const curve25519_key *key);
+int ec25519_crypto_ctx(      unsigned char *out, unsigned long *outlen,
+                             unsigned char flag,
+                       const unsigned char *ctx, unsigned long  ctxlen);
 #endif /* LTC_CURVE25519 */
 
 #ifdef LTC_DER

+ 40 - 0
src/pk/ec25519/ec25519_crypto_ctx.c

@@ -0,0 +1,40 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+#include "tomcrypt_private.h"
+
+/**
+  @file ec25519_crypto_ctx.c
+  curve25519 crypto context helper
+*/
+
+#ifdef LTC_CURVE25519
+
+int ec25519_crypto_ctx(unsigned char *out, unsigned long *outlen, unsigned char flag, const unsigned char *ctx, unsigned long ctxlen)
+{
+  unsigned char *buf = out;
+
+  const char *prefix = "SigEd25519 no Ed25519 collisions";
+  const unsigned long prefix_len = XSTRLEN(prefix);
+  const unsigned char ctxlen8 = (unsigned char)ctxlen;
+
+  if (ctxlen > 255u) return CRYPT_INPUT_TOO_LONG;
+  if (*outlen < prefix_len + 2u + ctxlen) return CRYPT_BUFFER_OVERFLOW;
+
+  XMEMCPY(buf, prefix, prefix_len);
+  buf += prefix_len;
+  XMEMCPY(buf, &flag, 1);
+  buf++;
+  XMEMCPY(buf, &ctxlen8, 1);
+  buf++;
+
+  if (ctxlen > 0u) {
+    XMEMCPY(buf, ctx, ctxlen);
+    buf += ctxlen;
+  }
+
+  *outlen = buf-out;
+
+  return CRYPT_OK;
+}
+
+#endif

+ 1 - 36
src/pk/ec25519/tweetnacl.c

@@ -504,40 +504,5 @@ int tweetnacl_crypto_sign_open(int *stat, u8 *m,u64 *mlen,const u8 *sm,u64 smlen
 
 int tweetnacl_crypto_ph(u8 *out,const u8 *msg,size_t msglen)
 {
-  hash_state md;
-
-  sha512_init(&md);
-
-  if(sha512_process(&md, msg, msglen) != CRYPT_OK)
-    return CRYPT_INVALID_ARG;
-
-  if(sha512_done(&md, out) != CRYPT_OK)
-    return CRYPT_INVALID_ARG;
-
-  return CRYPT_OK;
-}
-
-int tweetnacl_crypto_ctx(u8 *out,size_t *outlen,u8 flag,const char *pr, const char *ctx)
-{
-  u8 *buf = out;
-  const int ctx_prefix_len = strlen(pr);
-  const int ctxlen = ctx ? strlen(ctx) : 0;
-
-  if(ctxlen > 255) return CRYPT_INPUT_TOO_LONG;
-
-  XMEMCPY(buf, pr, ctx_prefix_len);
-  buf += ctx_prefix_len;
-  XMEMCPY(buf, &flag, 1);
-  buf++;
-  XMEMCPY(buf, &ctxlen, 1);
-  buf++;
-
-  if(ctxlen > 0) {
-    XMEMCPY(buf, ctx, ctxlen);
-    buf += ctxlen;
-  }
-
-  *outlen = buf-out;
-
-  return CRYPT_OK;
+  return tweetnacl_crypto_hash(out, msg, msglen);
 }

+ 26 - 26
src/pk/ed25519/ed25519_sign.c

@@ -9,9 +9,9 @@
 
 #ifdef LTC_CURVE25519
 
-static int ed25519_sign_private(const unsigned char *msg, unsigned long msglen,
-                       unsigned char *sig, unsigned long *siglen,
-                          const char* ctx, unsigned long ctxlen,
+static int s_ed25519_sign(const unsigned char  *msg, unsigned long  msglen,
+                                unsigned char  *sig, unsigned long *siglen,
+                          const unsigned char  *ctx, unsigned long  ctxlen,
                           const curve25519_key *private_key)
 {
    unsigned char *s;
@@ -61,21 +61,21 @@ static int ed25519_sign_private(const unsigned char *msg, unsigned long msglen,
    @param private_key     The private Ed25519 key in the pair
    @return CRYPT_OK if successful
 */
-int ed25519ctx_sign(const unsigned char *msg, unsigned long msglen,
-                          unsigned char *sig, unsigned long *siglen,
-                    const char* ctx, const curve25519_key *private_key)
+int ed25519ctx_sign(const  unsigned char *msg, unsigned long  msglen,
+                           unsigned char *sig, unsigned long *siglen,
+                    const  unsigned char *ctx, unsigned long  ctxlen,
+                    const curve25519_key *private_key)
 {
+   int err;
    unsigned char ctx_prefix[512] = {0};
-   unsigned long ctx_prefix_size = 0;
+   unsigned long ctx_prefix_size = sizeof(ctx_prefix);
 
    LTC_ARGCHK(ctx != NULL);
 
-   if(tweetnacl_crypto_ctx(ctx_prefix, &ctx_prefix_size, 0,
-                           ED25519_CONTEXT_PREFIX, ctx) != CRYPT_OK)
-      return CRYPT_INVALID_ARG;
+   if ((err = ec25519_crypto_ctx(ctx_prefix, &ctx_prefix_size, 0, ctx, ctxlen)) != CRYPT_OK)
+      return err;
 
-   return ed25519_sign_private(msg, msglen, sig, siglen, ctx_prefix,
-                               ctx_prefix_size, private_key);
+   return s_ed25519_sign(msg, msglen, sig, siglen, ctx_prefix, ctx_prefix_size, private_key);
 }
 
 /**
@@ -88,26 +88,26 @@ int ed25519ctx_sign(const unsigned char *msg, unsigned long msglen,
    @param private_key     The private Ed25519 key in the pair
    @return CRYPT_OK if successful
 */
-int ed25519ph_sign(const unsigned char *msg, unsigned long msglen,
-                         unsigned char *sig, unsigned long *siglen,
-                   const char *ctx, const curve25519_key *private_key)
+int ed25519ph_sign(const  unsigned char *msg, unsigned long  msglen,
+                          unsigned char *sig, unsigned long *siglen,
+                   const  unsigned char *ctx, unsigned long  ctxlen,
+                   const curve25519_key *private_key)
 {
+   int err;
    unsigned char ctx_prefix[512] = {0};
    unsigned char msg_hash[64] = {0};
-   unsigned long ctx_prefix_size = 0;
+   unsigned long ctx_prefix_size = sizeof(ctx_prefix);
 
-   if (tweetnacl_crypto_ctx(ctx_prefix, &ctx_prefix_size, 1,
-                            ED25519_CONTEXT_PREFIX, ctx) != CRYPT_OK)
-      return CRYPT_INVALID_ARG;
+   if ((err = ec25519_crypto_ctx(ctx_prefix, &ctx_prefix_size, 1, ctx, ctxlen)) != CRYPT_OK)
+      return err;
 
-   if (tweetnacl_crypto_ph(msg_hash, msg, msglen) != CRYPT_OK)
-      return CRYPT_INVALID_ARG;
+   if ((err = tweetnacl_crypto_ph(msg_hash, msg, msglen)) != CRYPT_OK)
+      return err;
 
    msg = msg_hash;
    msglen = 64;
 
-   return ed25519_sign_private(msg, msglen, sig, siglen, ctx_prefix,
-                               ctx_prefix_size, private_key);
+   return s_ed25519_sign(msg, msglen, sig, siglen, ctx_prefix, ctx_prefix_size, private_key);
 }
 
 /**
@@ -119,11 +119,11 @@ int ed25519ph_sign(const unsigned char *msg, unsigned long msglen,
    @param private_key     The private Ed25519 key in the pair
    @return CRYPT_OK if successful
 */
-int ed25519_sign(const unsigned char *msg, unsigned long msglen,
-                       unsigned char *sig, unsigned long *siglen,
+int ed25519_sign(const  unsigned char *msg, unsigned long msglen,
+                        unsigned char *sig, unsigned long *siglen,
                  const curve25519_key *private_key)
 {
-   return ed25519_sign_private(msg, msglen, sig, siglen, 0, 0, private_key);
+   return s_ed25519_sign(msg, msglen, sig, siglen, NULL, 0, private_key);
 }
 
 #endif

+ 41 - 39
src/pk/ed25519/ed25519_verify.c

@@ -9,12 +9,11 @@
 
 #ifdef LTC_CURVE25519
 
-static int ed25519_verify_private(
-                   const unsigned char *msg, unsigned long msglen,
-                   const unsigned char *sig, unsigned long siglen,
-                   int *stat,
-                   const char *ctx, unsigned long ctxlen,
-                   const curve25519_key *public_key)
+static int s_ed25519_verify(const  unsigned char *msg, unsigned long msglen,
+                            const  unsigned char *sig, unsigned long siglen,
+                            const  unsigned char *ctx, unsigned long ctxlen,
+                                             int *stat,
+                            const curve25519_key *public_key)
 {
    unsigned char* m;
    unsigned long long mlen;
@@ -46,7 +45,7 @@ static int ed25519_verify_private(
                                     public_key->pub);
 
 #ifdef LTC_CLEAN_STACK
-   zeromem(m, mlen);
+   zeromem(m, msglen + siglen);
 #endif
    XFREE(m);
 
@@ -54,82 +53,85 @@ static int ed25519_verify_private(
 }
 
 /**
-   Verify an Ed25519 signature.
+   Verify an Ed25519ctx signature.
+   @param msg             [in] The data to be verified
+   @param msglen          [in] The size of the data to be verified
    @param sig             [in] The signature to be verified
    @param siglen          [in] The size of the signature to be verified
+   @param ctx             [in] The context
+   @param ctxlen          [in] The size of the context
    @param stat            [out] The result of the signature verification, 1==valid, 0==invalid
-   @param ctx             [in] The context is a constant null terminated string
    @param public_key      [in] The public Ed25519 key in the pair
    @return CRYPT_OK if successful
 */
-int ed25519ctx_verify(const unsigned char *msg, unsigned long msglen,
-                      const unsigned char *sig, unsigned long siglen,
-                      int *stat, const char *ctx,
+int ed25519ctx_verify(const  unsigned char *msg, unsigned long msglen,
+                      const  unsigned char *sig, unsigned long siglen,
+                      const  unsigned char *ctx, unsigned long ctxlen,
+                                       int *stat,
                       const curve25519_key *public_key)
 {
    unsigned char ctx_prefix[512] = {0};
-   unsigned long ctx_prefix_size = 0;
+   unsigned long ctx_prefix_size = sizeof(ctx_prefix);
 
    LTC_ARGCHK(ctx != NULL);
 
-   if(tweetnacl_crypto_ctx(ctx_prefix, &ctx_prefix_size, 0,
-                           ED25519_CONTEXT_PREFIX, ctx) != CRYPT_OK)
+   if (ec25519_crypto_ctx(ctx_prefix, &ctx_prefix_size, 0, ctx, ctxlen) != CRYPT_OK)
       return CRYPT_INVALID_ARG;
 
-   return ed25519_verify_private(msg, msglen, sig, siglen, stat,
-                                 ctx_prefix, ctx_prefix_size, public_key);
+   return s_ed25519_verify(msg, msglen, sig, siglen, ctx_prefix, ctx_prefix_size, stat, public_key);
 }
 
 /**
-   Verify an Ed25519 signature.
-   @param msg             [in] The data to be signed
-   @param msglen          [in] The size of the data to be signed
+   Verify an Ed25519ph signature.
+   @param msg             [in] The data to be verified
+   @param msglen          [in] The size of the data to be verified
    @param sig             [in] The signature to be verified
    @param siglen          [in] The size of the signature to be verified
+   @param ctx             [in] The context
+   @param ctxlen          [in] The size of the context
    @param stat            [out] The result of the signature verification, 1==valid, 0==invalid
-   @param ctx             [in] The context is a constant null terminated string
    @param public_key      [in] The public Ed25519 key in the pair
    @return CRYPT_OK if successful
 */
-int ed25519ph_verify(const unsigned char *msg, unsigned long msglen,
-                     const unsigned char *sig, unsigned long siglen,
-                     int *stat, const char *ctx,
+int ed25519ph_verify(const  unsigned char *msg, unsigned long msglen,
+                     const  unsigned char *sig, unsigned long siglen,
+                     const  unsigned char *ctx, unsigned long ctxlen,
+                                      int *stat,
                      const curve25519_key *public_key)
 {
+   int err;
    unsigned char ctx_prefix[512] = {0};
    unsigned char msg_hash[64] = {0};
-   unsigned long ctx_prefix_size = 0;
+   unsigned long ctx_prefix_size = sizeof(ctx_prefix);
 
-   if(tweetnacl_crypto_ctx(ctx_prefix, &ctx_prefix_size, 1,
-                           ED25519_CONTEXT_PREFIX, ctx) != CRYPT_OK)
-      return CRYPT_INVALID_ARG;
+   if ((err = ec25519_crypto_ctx(ctx_prefix, &ctx_prefix_size, 1, ctx, ctxlen)) != CRYPT_OK)
+      return err;
 
-   if (tweetnacl_crypto_ph(msg_hash, msg, msglen) != CRYPT_OK)
-      return CRYPT_INVALID_ARG;
+   if ((err = tweetnacl_crypto_ph(msg_hash, msg, msglen)) != CRYPT_OK)
+      return err;
 
    msg = msg_hash;
    msglen = 64;
 
-   return ed25519_verify_private(msg, msglen, sig, siglen, stat,
-                                 ctx_prefix, ctx_prefix_size, public_key);
+   return s_ed25519_verify(msg, msglen, sig, siglen, ctx_prefix, ctx_prefix_size, stat, public_key);
 }
 
 /**
    Verify an Ed25519 signature.
-   @param msg             [in] The data to be signed
-   @param msglen          [in] The size of the data to be signed
+   @param msg             [in] The data to be verified
+   @param msglen          [in] The size of the data to be verified
    @param sig             [in] The signature to be verified
    @param siglen          [in] The size of the signature to be verified
    @param stat            [out] The result of the signature verification, 1==valid, 0==invalid
    @param public_key      [in] The public Ed25519 key in the pair
    @return CRYPT_OK if successful
 */
-int ed25519_verify(const unsigned char *msg, unsigned long msglen,
-                   const unsigned char *sig, unsigned long siglen,
-                   int *stat, const curve25519_key *public_key)
+int ed25519_verify(const  unsigned char *msg, unsigned long msglen,
+                   const  unsigned char *sig, unsigned long siglen,
+                                    int *stat,
+                   const curve25519_key *public_key)
 {
-   return ed25519_verify_private(msg, msglen, sig, siglen,
-                                 stat, 0, 0, public_key);
+   return s_ed25519_verify(msg, msglen, sig, siglen, NULL, 0, stat, public_key);
 }
 
 #endif

+ 37 - 23
tests/ed25519_test.c

@@ -9,9 +9,10 @@
 
 #ifdef LTC_CURVE25519
 
-static void xor_shuffle(char *buf, int size, int change)
+static void xor_shuffle(unsigned char *buf, unsigned long size, unsigned char change)
 {
-   for(int i = 0; i < size; i++)
+   unsigned long i;
+   for(i = 0; i < size; i++)
       buf[i] ^= change;
 }
 
@@ -108,7 +109,9 @@ static int s_rfc_8032_7_1_test(void)
          "",
          /* SIGNATURE */
          "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e06522490155"
-         "5fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b"
+         "5fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b",
+         /* CONTEXT */
+         NULL
       },
       {
          /* SECRET KEY */
@@ -119,7 +122,9 @@ static int s_rfc_8032_7_1_test(void)
          "72",
          /* SIGNATURE */
          "92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da"
-         "085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00"
+         "085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00",
+         /* CONTEXT */
+         NULL
       },
       {
          /* SECRET KEY */
@@ -130,7 +135,9 @@ static int s_rfc_8032_7_1_test(void)
          "af82",
          /* SIGNATURE */
          "6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac"
-         "18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40a"
+         "18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40a",
+         /* CONTEXT */
+         NULL
       },
       {
          /* SECRET KEY */
@@ -172,7 +179,9 @@ static int s_rfc_8032_7_1_test(void)
          "0618983f8741c5ef68d3a101e8a3b8cac60c905c15fc910840b94c00a0b9d0",
          /* SIGNATURE */
          "0aab4c900501b3e24d7cdf4663326a3a87df5e4843b2cbdb67cbf6e460fec350"
-         "aa5371b1508f9f4528ecea23c436d94b5e8fcd4f681e30a6ac00a9704a188a03"
+         "aa5371b1508f9f4528ecea23c436d94b5e8fcd4f681e30a6ac00a9704a188a03",
+         /* CONTEXT */
+         NULL
       },
       {
          /* SECRET KEY */
@@ -184,7 +193,9 @@ static int s_rfc_8032_7_1_test(void)
          "2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f",
          /* SIGNATURE */
          "dc2a4459e7369633a52b1bf277839a00201009a3efbf3ecb69bea2186c26b589"
-         "09351fc9ac90b3ecfdfbc7c66431e0303dca179c138ac17ad9bef1177331a704"
+         "09351fc9ac90b3ecfdfbc7c66431e0303dca179c138ac17ad9bef1177331a704",
+         /* CONTEXT */
+         NULL
       }
    };
    unsigned int n;
@@ -209,10 +220,10 @@ static int s_rfc_8032_7_1_test(void)
       DO(ed25519_verify(msg, mlen, sig, siglen, &ret, &key));
       DO(do_compare_testvector(&ret, sizeof(ret), &should, sizeof(should), "Ed25519 RFC8032 7.1 - verify w/ privkey", n));
 
-      xor_shuffle(sig, siglen, 0x8);
+      xor_shuffle(sig, siglen, 0x8u);
       DO( ed25519_verify(msg, mlen, sig, siglen, &ret, &key));
       ENSUREX(ret != 1, "ed25519_verify is expected to fail on the modified signature");
-      xor_shuffle(msg, mlen, 0xf);
+      xor_shuffle(msg, mlen, 0xfu);
       DO( ed25519_verify(msg, mlen, sig, siglen, &ret, &key));
       ENSUREX(ret != 1, "ed25519_verify is expected to fail on the modified message");
 
@@ -305,26 +316,26 @@ static int s_rfc_8032_7_2_test(void)
       DO(base16_decode(rfc_8032_7_2[n].message, XSTRLEN(rfc_8032_7_2[n].message), msg, &mlen));
       siglen = sizeof(sig);
       DO(base16_decode(rfc_8032_7_2[n].signature, XSTRLEN(rfc_8032_7_2[n].signature), sig, &siglen));
+      ctxlen = sizeof(ctx);
       DO(base16_decode(rfc_8032_7_2[n].context, XSTRLEN(rfc_8032_7_2[n].context), ctx, &ctxlen));
-      ctx[ctxlen] = 0;
       buflen = sizeof(buf);
 
       DO(ed25519_import_raw(sec, slen, PK_PRIVATE, &key));
-      DO(ed25519ctx_sign(msg, mlen, buf, &buflen, ctx, &key));
+      DO(ed25519ctx_sign(msg, mlen, buf, &buflen, ctx, ctxlen, &key));
       DO(do_compare_testvector(buf, buflen, sig, siglen, "Ed25519 RFC8032 7.2 - sign", n));
-      DO(ed25519ctx_verify(msg, mlen, buf, buflen, &ret, ctx, &key));
+      DO(ed25519ctx_verify(msg, mlen, buf, buflen, ctx, ctxlen, &ret, &key));
       ENSUREX(ret == should, "Ed25519 RFC8032 7.2 - verify w/ privkey");
 
       DO(ed25519_import_raw(pub, plen, PK_PUBLIC, &key2));
-      DO(ed25519ctx_verify(msg, mlen, sig, siglen, &ret, ctx, &key2));
+      DO(ed25519ctx_verify(msg, mlen, sig, siglen, ctx, ctxlen, &ret, &key2));
       ENSUREX(ret == should, "Ed25519 RFC8032 7.2 - verify w/ pubkey");
 
-      xor_shuffle(buf, buflen, 0x4);
-      DO( ed25519ctx_verify(msg, mlen, buf, buflen, &ret, ctx, &key));
-      ENSUREX(ret != 1, "ed25519_verify is expected to fail on the modified signature");
-      xor_shuffle(msg, mlen, 0x8);
-      DO( ed25519ctx_verify(msg, mlen, buf, buflen, &ret, ctx, &key));
-      ENSUREX(ret != 1, "ed25519_verify is expected to fail on the modified message");
+      xor_shuffle(buf, buflen, 0x4u);
+      DO(ed25519ctx_verify(msg, mlen, buf, buflen, ctx, ctxlen, &ret, &key));
+      ENSUREX(ret != 1, "ed25519ctx_verify is expected to fail on the modified signature");
+      xor_shuffle(msg, mlen, 0x8u);
+      DO(ed25519ctx_verify(msg, mlen, buf, buflen, ctx, ctxlen, &ret, &key));
+      ENSUREX(ret != 1, "ed25519ctx_verify is expected to fail on the modified message");
 
       zeromem(&key, sizeof(key));
       zeromem(&key2, sizeof(key2));
@@ -346,15 +357,18 @@ static int s_rfc_8032_7_3_test(void)
          /* SIGNATURE */
          "98a70222f0b8121aa9d30f813d683f809e462b469c7ff87639499bb94e6dae41"
          "31f85042463c2a355a2003d062adf5aaa10b8c61e636062aaad11c2a26083406",
+         /* CONTEXT */
+         NULL
       },
    };
 
-   unsigned long mlen, slen, plen, siglen, buflen, ctxlen;
+   unsigned long mlen, slen, plen, siglen, buflen;
    unsigned char msg[1024], sec[32], pub[32], sig[64], buf[64];
-   curve25519_key key, key2;
+   curve25519_key key;
    int ret;
    const int should = 1;
 
+   buflen = sizeof(buf);
    slen = sizeof(sec);
    DO(base16_decode(rfc_8032_7_3[0].secret_key, XSTRLEN(rfc_8032_7_3[0].secret_key), sec, &slen));
    plen = sizeof(pub);
@@ -365,9 +379,9 @@ static int s_rfc_8032_7_3_test(void)
    DO(base16_decode(rfc_8032_7_3[0].signature, XSTRLEN(rfc_8032_7_3[0].signature), sig, &siglen));
 
    DO(ed25519_import_raw(sec, slen, PK_PRIVATE, &key));
-   DO(ed25519ph_sign(msg, mlen, buf, &buflen, 0, &key));
+   DO(ed25519ph_sign(msg, mlen, buf, &buflen, NULL, 0, &key));
    DO(do_compare_testvector(buf, buflen, sig, siglen, "Ed25519 RFC8032 7.3 - sign", 0));
-   DO(ed25519ph_verify(msg, mlen, buf, buflen, &ret, 0, &key));
+   DO(ed25519ph_verify(msg, mlen, buf, buflen, NULL, 0, &ret, &key));
    ENSUREX(ret == should, "Ed25519 RFC8032 7.3 - verify w/ privkey");
 
    return CRYPT_OK;