add test code
authorNIIBE Yutaka <gniibe@fsij.org>
Tue, 25 Mar 2014 05:30:51 +0000 (14:30 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Tue, 25 Mar 2014 05:30:51 +0000 (14:30 +0900)
ChangeLog
misc/t-eddsa.c [new file with mode: 0644]
src/ecc-edwards.c

index fd6c39f..5ad582c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,7 @@
 2014-03-25  Niibe Yutaka  <gniibe@fsij.org>
 
+       * misc/t-eddsa.c: New.
+
        * src/ecc-edwards.c (bnX_mul_C, mod_reduce_M): New.
        (eddsa_25519): New.
 
diff --git a/misc/t-eddsa.c b/misc/t-eddsa.c
new file mode 100644 (file)
index 0000000..3f81fbf
--- /dev/null
@@ -0,0 +1,418 @@
+/*
+ * t-eddsa.c - testing EdDSA
+ * Copyright (C) 2014 Free Software Initiative of Japan
+ * Author: NIIBE Yutaka <gniibe@fsij.org>
+ *
+ * Run following commands.  The file t-ed25519.inp is available in GNU
+ * libgcrypt source code under 'tests' directory.
+
+  gcc -Wall -c ecc-edwards.c
+  gcc -Wall -c -DBN256_NO_RANDOM -DBN256_C_IMPLEMENTATION bn.c
+  gcc -Wall -c mod.c
+  gcc -Wall -c -DBN256_C_IMPLEMENTATION mod25638.c
+  gcc -Wall -c sha512.c
+  gcc -Wall -c t-eddsa.c
+  gcc -o t-eddsa t-eddsa.o ecc-edwards.o bn.o mod.o mod25638.o sha512.o
+  ./t-eddsa < ./t-ed25519.inp
+
+ *
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "bn.h"
+#include "affine.h"
+#include "sha512.h"
+
+static void
+print_le_bn256 (const bn256 *X)
+{
+  int i;
+  const uint8_t *p = (const uint8_t *)X;
+
+  for (i = 0; i < 32; i++)
+    printf ("%02x", p[i]);
+  puts ("");
+}
+
+static void
+print_be_bn256 (const bn256 *X)
+{
+  int i;
+
+  for (i = 7; i >= 0; i--)
+    printf ("%08x", X->word[i]);
+  puts ("");
+}
+
+static void
+print_point (const ac *X)
+{
+  int i;
+
+  puts ("--");
+  for (i = 7; i >= 0; i--)
+    printf ("%08x", X->x->word[i]);
+  puts ("");
+  for (i = 7; i >= 0; i--)
+    printf ("%08x", X->y->word[i]);
+  puts ("");
+  puts ("--");
+}
+
+extern void eddsa_25519 (bn256 *r, bn256 *s,
+                        const uint8_t *input, size_t ilen, const bn256 *d);
+#define MAXLINE 4096
+
+static int lineno;
+static int test_no;
+static bn256 sk[1];
+static int pk_is_compressed;
+static ac pk[1];
+static unsigned char msg[MAXLINE];
+static size_t msglen;
+static bn512 sig[1];
+
+static const char *
+skip_white_space (const char *l)
+{
+  while (*l != '\n' && isspace (*l))
+    l++;
+
+  return l;
+}
+
+
+static int
+read_hex_4bit (char c)
+{
+  int r;
+
+  if (c >= '0' && c <= '9')
+    r = c - '0';
+  else if (c >= 'a' && c <= 'f')
+    r = c - 'a' + 10;
+  else if (c >= 'A' && c <= 'F')
+    r = c - 'A' + 10;
+  else
+    r = -1;
+  return r;
+}
+
+static int
+read_hex_8bit (const char **l_p)
+{
+  const char *l = *l_p;
+  int r, v;
+
+  r = read_hex_4bit (*l++);
+  if (r < 0)
+    return -1;
+  v = r*16;
+  r = read_hex_4bit (*l++);
+  if (r < 0)
+    return -1;
+  v += r;
+
+  *l_p = l;
+  return v;
+}
+
+static int
+read_msg (unsigned char *msg, const char *l, int len)
+{
+  int i, r;
+
+  for (i = 0; i < len; i++)
+    {
+      r = read_hex_8bit (&l);
+      if (r < 0)
+       return -1;
+      msg[i] = r;
+    }
+
+  return 0;
+}
+
+
+static int
+read_le_bn256 (bn256 *sk, const char *l)
+{
+  int i;
+  uint8_t *p = (uint8_t *)sk;
+
+  for (i = 0; i < sizeof (bn256); i++)
+    {
+      int r;
+
+      if (*l == '\n')
+       {
+         /* should support small input??? */
+         return -1;
+       }
+
+      r = read_hex_8bit (&l);
+      if (r < 0)
+       return -1;
+
+      p[i] = r;
+    }
+
+  return 0;
+}
+
+static int
+read_be_bn256 (bn256 *sk, const char *l)
+{
+  int i;
+  uint8_t *p = (uint8_t *)sk;
+
+  for (i = 0; i < sizeof (bn256); i++)
+    {
+      int r;
+
+      if (*l == '\n')
+       {
+         /* should support small input??? */
+         return -1;
+       }
+
+      r = read_hex_8bit (&l);
+      if (r < 0)
+       return -1;
+
+      p[31 - i] = r;
+    }
+
+  return 0;
+}
+
+
+static int
+read_pk (ac *pk, const char *l, int len)
+{
+  int r;
+
+  if (len == 64)               /* 64 chars == 32-byte */
+    {                          /* compressed form */
+      r = read_le_bn256 (pk->y, l);
+      if (r < 0)
+       return -1;
+      return 1;
+    }
+  else
+    {
+      r = read_hex_8bit (&l);
+      if (r < 0)
+       return -1;
+      if (r != 4)
+       return -1;
+
+      r = read_be_bn256 (pk->x, l);
+      if (r < 0)
+       return -1;
+      r = read_be_bn256 (pk->y, l+64);
+      if (r < 0)
+       return -1;
+
+      return 0;
+    }
+}
+
+static int
+read_le_bn512 (bn512 *sig, const char *l)
+{
+  int i;
+  uint8_t *p = (uint8_t *)sig;
+
+  for (i = 0; i < sizeof (bn512); i++)
+    {
+      int r;
+
+      if (*l == '\n')
+       {
+         /* should support small input??? */
+         return -1;
+       }
+
+      r = read_hex_8bit (&l);
+      if (r < 0)
+       return -1;
+
+      p[i] = r;
+    }
+
+  return 0;
+}
+
+static int
+read_testcase (void)
+{
+  ssize_t r;
+  size_t len = 0;
+  char *line = NULL;
+  int start = 0;
+  int err = 0;
+
+  test_no = 0;
+  memset (sk, 0, sizeof (bn256));
+  pk_is_compressed = 0;
+  memset (pk, 0, sizeof (ac));
+  msglen = 0;
+  memset (sig, 0, sizeof (bn512));
+
+  while (1)
+    {
+      lineno++;
+      r = getline (&line, &len, stdin);
+      if (r < 0)
+       {
+         /* EOF */
+         if (!start)
+           err = -1;
+         break;
+       }
+      len = r;        /* We don't need allocated size, but length.  */
+      if (len >= MAXLINE)
+       {
+         fprintf (stderr, "Line too long: %d: >= %d\n", lineno, MAXLINE);
+         err = -1;
+         break;
+       }
+
+      if (r == 1 && *line == '\n')
+       {
+         if (start)
+           break;              /* Done. */
+         else
+           continue; /* Ignore blank line before start.  */
+       }
+
+      if (r > 0 && *line == '#') /* Ignore comment line.  */
+       continue;
+
+      start = 1;
+      if (r > 4 && strncmp (line, "TST:", 4) == 0)
+       test_no = strtol (line+4, NULL, 10);
+      else if (r > 3 && strncmp (line, "SK:", 3) == 0)
+       {
+         const char *l = skip_white_space (line+3);
+         if (read_le_bn256 (sk, l) < 0)
+           {
+             fprintf (stderr, "read_le_bn256: %d\n", lineno);
+             err = -1;
+             break;
+           }
+       }
+      else if (r > 3 && strncmp (line, "PK:", 3) == 0)
+       {
+         const char *l = skip_white_space (line+3);
+         pk_is_compressed = read_pk (pk, l, line+len-1-l);
+         if (pk_is_compressed < 0)
+           {
+             fprintf (stderr, "read_pk: %d\n", lineno);
+             err = -1;
+             break;
+           }
+       }
+      else if (r > 4 && strncmp (line, "MSG:", 4) == 0)
+       {
+         const char *l = skip_white_space (line+4);
+         msglen = (line+len-1-l)/2;
+         if (read_msg (msg, l, msglen) < 0)
+           {
+             fprintf (stderr, "read_msg: %d\n", lineno);
+             err = -1;
+             break;
+           }
+       }
+      else if (r > 4 && strncmp (line, "SIG:", 4) == 0)
+       {
+         const char *l = skip_white_space (line+4);
+         if (read_le_bn512 (sig, l) < 0)
+           {
+             fprintf (stderr, "read_le_bn512: %d\n", lineno);
+             err = -1;
+             break;
+           }
+       }
+      else
+       {
+         fprintf (stderr, "Garbage line: %d", lineno);
+         err = -1;
+         break;
+       }
+    }
+
+  free (line);
+  return err;
+}
+
+
+int
+main (int argc, char *argv[])
+{
+  int r;
+  ac pk_calculated[1];
+  uint8_t hash[64];
+  bn256 a[1];
+  extern int compute_kG_25519 (ac *X, const bn256 *K);
+  extern int mod25519_is_neg (const bn256 *a);
+  extern void eddsa_25519 (bn256 *r, bn256 *s, const uint8_t *input,
+                          size_t ilen, const bn256 *d);
+
+  bn256 R[1], S[1];
+
+  while (1)
+    {
+      r = read_testcase ();
+      if (r < 0)
+       break;
+
+      sha512 ((uint8_t *)sk, sizeof (bn256), hash);
+      hash[0] &= 248;
+      hash[31] &= 127;
+      hash[31] |= 64;
+      memcpy (a, hash, sizeof (bn256)); /* Lower half of hash */
+
+      compute_kG_25519 (pk_calculated, a);
+      if (pk_is_compressed)
+       {
+         /* EdDSA encoding.  */
+         pk_calculated->y->word[7] ^= 
+           mod25519_is_neg (pk_calculated->x) * 0x80000000;
+         r = memcmp (pk->y, pk_calculated->y, sizeof (bn256));
+       }
+      else
+       {
+         r = memcmp (pk, pk_calculated, sizeof (ac));
+       }
+      if (r != 0)
+       {
+         printf ("ERR PK: %d\n", test_no);
+         print_be_bn256 (sk);
+         print_point (pk);
+         print_point (pk_calculated);
+         continue;
+       }
+
+      eddsa_25519 (R, S, msg, msglen, sk);
+      if (memcmp (sig, R, sizeof (bn256)) != 0
+         || memcmp (((const uint8_t *)sig)+32, S, sizeof (bn256)) != 0)
+       {
+         printf ("ERR SIG: %d\n", test_no);
+         print_le_bn256 (R);
+         print_le_bn256 (S);
+         print_le_bn256 ((const bn256 *)sig);
+         print_le_bn256 ((const bn256 *)(((const uint8_t *)sig)+32));
+         continue;
+       }
+
+      printf ("%d\n", test_no);
+    }
+  return 0;
+}
index 000c295..d5b86d2 100644 (file)
@@ -64,7 +64,7 @@ typedef struct
 #include "affine.h"
 
 
-static int
+int
 mod25519_is_neg (const bn256 *a)
 {
   return (a->word[0] & 1);