[Cryptech-Commits] [user/sra/libhal] 05/15: Add test harness: no useful tests yet, just the framework. Add human-readable error strings for hal_error_t codes.

git at cryptech.is git at cryptech.is
Mon May 25 21:04:20 UTC 2015


This is an automated email from the git hooks/post-receive script.

sra at hactrn.net pushed a commit to branch master
in repository user/sra/libhal.

commit f50805b30323155755393ac6639aaae1067452c1
Author: Rob Austein <sra at hactrn.net>
Date:   Thu May 21 13:47:12 2015 -0400

    Add test harness: no useful tests yet, just the framework.
    Add human-readable error strings for hal_error_t codes.
---
 Makefile.in               |  15 ++++-
 aes_keywrap.c             |   2 +
 configure                 |   5 +-
 configure.ac              |   2 +-
 cryptech.h                |  43 ++++++++------
 errorstrings.c            |  25 +++++++++
 tests/Makefile.in         |  24 ++++++++
 tests/test-aes-key-wrap.c | 140 ++++++++++++++++++++++++++++++++++++++++++++++
 8 files changed, 234 insertions(+), 22 deletions(-)

diff --git a/Makefile.in b/Makefile.in
index b984151..bc60029 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -2,7 +2,7 @@
 
 INC		= cryptech.h
 LIB		= libcryptech.a
-OBJ		= ${IO_OBJ} csprng.o hash.o aes_keywrap.o
+OBJ		= ${IO_OBJ} csprng.o hash.o aes_keywrap.o errorstrings.o
 
 IO_OBJ		= ${IO_OBJ_ at FPGA_BUS@}
 IO_OBJ_EIM	= hal_io_eim.o novena-eim.o
@@ -24,6 +24,9 @@ ${OBJ}: ${INC}
 ${LIB}: ${OBJ}
 	ar rcs $@ $^
 
+test: all
+	cd tests; ${MAKE} -k $@
+
 install: ${LIB} ${INC}
 	install ${LIB} ${libdir}
 	install ${INC} ${includedir}
@@ -34,3 +37,13 @@ uninstall:
 
 clean:
 	rm -f ${OBJ} ${LIB}
+	cd tests; ${MAKE} $@
+
+distclean: clean
+	cd tests; ${MAKE} $@
+	rm -f config.log config.status TAGS Makefile
+
+tags: TAGS
+
+TAGS: *.[ch]
+	etags $^
diff --git a/aes_keywrap.c b/aes_keywrap.c
index b8f505f..cc62676 100644
--- a/aes_keywrap.c
+++ b/aes_keywrap.c
@@ -53,6 +53,8 @@ static hal_error_t load_kek(const uint8_t *K, const size_t K_len, const kek_acti
   case bitsToBytes(256):
     config[3] |=  AES_CONFIG_KEYLEN;
     break;
+  case bitsToBytes(192):
+    return HAL_ERROR_UNSUPPORTED_KEY;
   default:
     return HAL_ERROR_BAD_ARGUMENTS;
   }
diff --git a/configure b/configure
index 9c91f97..de3ba04 100755
--- a/configure
+++ b/configure
@@ -1699,14 +1699,12 @@ case $CC in #(
   *) :
      ;;
 esac
-
 case $CFLAGS in #(
   "") :
     CFLAGS="-g -Wall -fPIC" ;; #(
   *) :
      ;;
 esac
-
 case $LDFLAGS in #(
   "") :
     LDFLAGS="-g" ;; #(
@@ -1723,7 +1721,7 @@ $as_echo "$as_me: C compiler flags: $CFLAGS" >&6;}
 { $as_echo "$as_me:${as_lineno-$LINENO}: Linker flags: $LDFLAGS" >&5
 $as_echo "$as_me: Linker flags: $LDFLAGS" >&6;}
 
-ac_config_files="$ac_config_files Makefile"
+ac_config_files="$ac_config_files Makefile tests/Makefile"
 
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
@@ -2431,6 +2429,7 @@ for ac_config_target in $ac_config_targets
 do
   case $ac_config_target in
     "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+    "tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;;
 
   *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
   esac
diff --git a/configure.ac b/configure.ac
index 07cd236..f7e4dd5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -29,5 +29,5 @@ AC_MSG_NOTICE([C compiler: $CC])
 AC_MSG_NOTICE([C compiler flags: $CFLAGS])
 AC_MSG_NOTICE([Linker flags: $LDFLAGS])
 
-AC_CONFIG_FILES([Makefile])
+AC_CONFIG_FILES([Makefile tests/Makefile])
 AC_OUTPUT
diff --git a/cryptech.h b/cryptech.h
index 8218aa2..3ceab95 100644
--- a/cryptech.h
+++ b/cryptech.h
@@ -425,30 +425,39 @@
 
 
 /*
- * C API error codes.
+ * C API error codes.  Defined in this form so we can keep the tokens
+ * and error strings together.  See errorstrings.c.
  */
 
-typedef enum {
-  HAL_OK,				/* All's well */
-  HAL_ERROR_MEMORY,			/* malloc() failure or similar */
-  HAL_ERROR_BAD_ARGUMENTS,		/* Bad arguments given */
-  HAL_ERROR_IO_SETUP_FAILED,		/* Could not set up I/O with FPGA */
-  HAL_ERROR_IO_TIMEOUT,			/* I/O with FPGA timed out */
-  HAL_ERROR_IO_UNEXPECTED,		/* Unexpected response from FPGA */
-  HAL_ERROR_IO_OS_ERROR,		/* Operating system error talking to FPGA */
-  HAL_ERROR_IO_BAD_COUNT,		/* Bad byte count */
-  HAL_ERROR_CSPRNG_BROKEN,		/* CSPRNG is returning nonsense (perhaps core not present?) */
-  HAL_ERROR_KEYWRAP_BAD_MAGIC,		/* Bad magic number while unwrapping key */
-  HAL_ERROR_KEYWRAP_BAD_LENGTH,		/* Length out of range while unwrapping key */
-  HAL_ERROR_KEYWRAP_BAD_PADDING,	/* Nonzero padding detected while unwrapping key */
-  N_HAL_ERRORS				/* Number of error codes (must be last) */
-} hal_error_t;
-
+#define HAL_ERROR_LIST \
+  DEFINE_HAL_ERROR(HAL_OK,				"No error")					\
+  DEFINE_HAL_ERROR(HAL_ERROR_BAD_ARGUMENTS,		"Bad arguments given")				\
+  DEFINE_HAL_ERROR(HAL_ERROR_UNSUPPORTED_KEY,		"Unsupported key type or key length")		\
+  DEFINE_HAL_ERROR(HAL_ERROR_IO_SETUP_FAILED,		"Could not set up I/O with FPGA")		\
+  DEFINE_HAL_ERROR(HAL_ERROR_IO_TIMEOUT,		"I/O with FPGA timed out")			\
+  DEFINE_HAL_ERROR(HAL_ERROR_IO_UNEXPECTED,		"Unexpected response from FPGA")		\
+  DEFINE_HAL_ERROR(HAL_ERROR_IO_OS_ERROR,		"Operating system error talking to FPGA")	\
+  DEFINE_HAL_ERROR(HAL_ERROR_IO_BAD_COUNT,		"Bad byte count")				\
+  DEFINE_HAL_ERROR(HAL_ERROR_CSPRNG_BROKEN,		"CSPRNG is returning nonsense")			\
+  DEFINE_HAL_ERROR(HAL_ERROR_KEYWRAP_BAD_MAGIC,		"Bad magic number while unwrapping key")	\
+  DEFINE_HAL_ERROR(HAL_ERROR_KEYWRAP_BAD_LENGTH,	"Length out of range while unwrapping key")	\
+  DEFINE_HAL_ERROR(HAL_ERROR_KEYWRAP_BAD_PADDING,	"Non-zero padding detected unwrapping key")	\
+  END_OF_HAL_ERROR_LIST
+
+/* Marker to forestall silly line continuation errors */
+#define END_OF_HAL_ERROR_LIST
+
+/* Define the error code enum here.  See errorstrings.c for the text strings. */
+#define DEFINE_HAL_ERROR(_code_,_text_)	 _code_,
+typedef enum { HAL_ERROR_LIST N_HAL_ERRORS } hal_error_t;
+#undef  DEFINE_HAL_ERROR
 
 /*
  * Public functions.
  */
 
+extern const char *hal_error_string(const hal_error_t err);
+
 /*
  * Public I/O functions.
  */
diff --git a/errorstrings.c b/errorstrings.c
new file mode 100644
index 0000000..9686eab
--- /dev/null
+++ b/errorstrings.c
@@ -0,0 +1,25 @@
+/*
+ * Translate HAL error codes to strings.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+
+#include "cryptech.h"
+
+#define DEFINE_HAL_ERROR(_code_,_text_)	\
+  case _code_: return _text_;
+
+const char *hal_error_string(const hal_error_t code)
+{
+  switch (code) {
+    HAL_ERROR_LIST;
+  default:
+    return "Unknown HAL error code";
+  }
+}
+
+#undef DEFINE_HAL_ERROR
diff --git a/tests/Makefile.in b/tests/Makefile.in
new file mode 100644
index 0000000..f63e4fc
--- /dev/null
+++ b/tests/Makefile.in
@@ -0,0 +1,24 @@
+# @configure_input@
+
+INC		= ../cryptech.h
+LIB		= ../libcryptech.a
+BIN		= test-aes-key-wrap
+
+CC		= @CC@
+CFLAGS		= @CFLAGS@ -I..
+LDFLAGS		= @LDFLAGS@ ${LIB}
+
+all: ${BIN}
+
+*.o: ${INC}
+
+${BIN}: ${LIB}
+
+test: all
+	for i in ${BIN}; do ./$$i; done
+
+clean:
+	rm -f *.o ${BIN}
+
+distclean: clean
+	rm -f Makefile
diff --git a/tests/test-aes-key-wrap.c b/tests/test-aes-key-wrap.c
new file mode 100644
index 0000000..cc31011
--- /dev/null
+++ b/tests/test-aes-key-wrap.c
@@ -0,0 +1,140 @@
+/*
+ * Test code for AES Key Wrap.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+
+#include <cryptech.h>
+
+#ifndef TC_BUFSIZE
+#define TC_BUFSIZE      4096
+#endif
+
+/*
+ * Test cases from RFC 5649...which all use a 192-bit key, which our
+ * AES implementation doesn't support, to these will never pass.  Feh.
+ *
+ * Have to write our own, I guess, using our Python implementation or
+ * something.
+ */
+
+typedef struct {
+  const char *K;                /* Key-encryption-key */
+  const char *Q;                /* Plaintext */
+  const char *C;                /* Ciphertext */
+} test_case_t;
+
+static const test_case_t test_case[] = {
+
+  { "5840df6e29b02af1 ab493b705bf16ea1 ae8338f4dcc176a8",                       /* K */
+    "c37b7e6492584340 bed1220780894115 5068f738",                               /* Q */
+    "138bdeaa9b8fa7fc 61f97742e72248ee 5ae6ae5360d1ae6a 5f54f373fa543b6a"},     /* C */
+
+  { "5840df6e29b02af1 ab493b705bf16ea1 ae8338f4dcc176a8",                       /* K */
+    "466f7250617369",                                                           /* Q */
+    "afbeb0f07dfbf541 9200f2ccb50bb24f" }                                       /* C */
+
+};
+
+static int parse_hex(const char *hex, uint8_t *bin, size_t *len, const size_t max)
+{
+  static const char whitespace[] = " \t\r\n";
+  size_t i;
+
+  assert(hex != NULL && bin != NULL && len != NULL);
+
+  hex += strspn(hex, whitespace);
+
+  for (i = 0; *hex != '\0' && i < max; i++, hex += 2 + strspn(hex + 2, whitespace))
+    if (sscanf(hex, "%2hhx", &bin[i]) != 1)
+      return 0;
+
+  *len = i;
+
+  return *hex == '\0';
+}
+
+static const char *format_hex(const uint8_t *bin, const size_t len, char *hex, const size_t max)
+{
+  size_t i;
+
+  assert(bin != NULL && hex != NULL && len * 3 < max);
+
+  if (len == 0)
+    return "";
+
+  for (i = 0; i < len; i++)
+    sprintf(hex + 3 * i, "%02x:", bin[i]);
+
+  hex[len * 3 - 1] = '\0';
+  return hex;
+}
+
+static int run_test(const test_case_t * const tc)
+{
+  uint8_t K[TC_BUFSIZE], Q[TC_BUFSIZE], C[TC_BUFSIZE], q[TC_BUFSIZE], c[TC_BUFSIZE];
+  size_t K_len, Q_len, C_len, q_len = sizeof(q), c_len = sizeof(c);
+  char h1[TC_BUFSIZE * 3],  h2[TC_BUFSIZE * 3];
+  hal_error_t err;
+  int ok = 1;
+
+  assert(tc != NULL);
+
+  if (!parse_hex(tc->K, K, &K_len, sizeof(K)))
+    return printf("couldn't parse KEK %s\n", tc->K), 0;
+
+  if (!parse_hex(tc->Q, Q, &Q_len, sizeof(Q)))
+    return printf("couldn't parse plaintext %s\n", tc->Q), 0;
+
+  if (!parse_hex(tc->C, C, &C_len, sizeof(C)))
+    return printf("couldn't parse ciphertext %s\n", tc->C), 0;
+
+  if ((err = hal_aes_keywrap(K, K_len, Q, Q_len, c, &c_len)) != HAL_OK)
+    ok = printf("couldn't wrap %s: %s\n", tc->Q, hal_error_string(err)), 0;
+
+  if ((err = hal_aes_keyunwrap(K, K_len, C, C_len, q, &q_len)) != HAL_OK)
+    ok = printf("couldn't unwrap %s: %s\n", tc->C, hal_error_string(err)), 0;
+
+  if (C_len != c_len || memcmp(C, c, C_len) != 0)
+    ok = printf("ciphertext mismatch:\n  Want: %s\n  Got:  %s\n",
+		format_hex(C, C_len, h1, sizeof(h1)),
+		format_hex(c, c_len, h2, sizeof(h2))), 0;
+
+  if (Q_len != q_len || memcmp(Q, q, Q_len) != 0)
+    ok = printf("plaintext mismatch:\n  Want: %s\n  Got:  %s\n",
+		format_hex(Q, Q_len, h1, sizeof(h1)),
+		format_hex(q, q_len, h2, sizeof(h2))), 0;
+
+  return ok;
+}
+
+int main (int argc, char *argv[])
+{
+  int i, ok = 1;
+
+  for (i = 0; i < sizeof(test_case)/sizeof(*test_case); i++) {
+    printf("Running test case #%d...", i);
+    if (run_test(&test_case[i]))
+      printf("OK\n");
+    else
+      ok = 0;
+  }
+
+  return !ok;
+}
+
+/*
+ * "Any programmer who fails to comply with the standard naming, formatting,
+ *  or commenting conventions should be shot.  If it so happens that it is
+ *  inconvenient to shoot him, then he is to be politely requested to recode
+ *  his program in adherence to the above standard."
+ *                      -- Michael Spier, Digital Equipment Corporation
+ *
+ * Local variables:
+ * indent-tabs-mode: nil
+ * End:
+ */



More information about the Commits mailing list