[Cryptech-Commits] [sw/libhal] 01/01: Add support for Joachim's keywrap core.

git at cryptech.is git at cryptech.is
Wed Aug 15 21:30:37 UTC 2018


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

paul at psgd.org pushed a commit to branch js_keywrap
in repository sw/libhal.

commit 255ebc59bf1000af6715217679bc82d5bc4d536b
Author: Paul Selkirk <paul at psgd.org>
AuthorDate: Wed Aug 15 17:30:14 2018 -0400

    Add support for Joachim's keywrap core.
---
 aes_keywrap.c       | 178 +++++++++++++++++++++++++++++++++++++++++++---------
 hal.h               |   5 ++
 hal_io_fmc.c        |   6 +-
 verilog_constants.h |  26 ++++++++
 4 files changed, 182 insertions(+), 33 deletions(-)

diff --git a/aes_keywrap.c b/aes_keywrap.c
index 144ad68..77146e6 100644
--- a/aes_keywrap.c
+++ b/aes_keywrap.c
@@ -4,7 +4,7 @@
  * Implementation of RFC 5649 over Cryptech AES core.
  *
  * Authors: Rob Austein
- * Copyright (c) 2015-2017, NORDUnet A/S
+ * Copyright (c) 2015-2018, NORDUnet A/S
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -49,8 +49,22 @@
 #include "hal.h"
 #include "hal_internal.h"
 
+/*
+ * Enable use of the experimental keywrap core, if present.
+ */
+
+static int use_keywrap_core = 0;
+
+int hal_aes_use_keywrap_core(int onoff)
+{
+  use_keywrap_core = (onoff && hal_core_find(KEYWRAP_NAME, NULL) != NULL);
+  return use_keywrap_core;
+}
+
+
 /*
  * How long the ciphertext will be for a given plaintext length.
+ * This rounds up the length to a multiple of 8, and adds 8 for the IV.
  */
 
 size_t hal_aes_keywrap_ciphertext_length(const size_t plaintext_length)
@@ -62,6 +76,8 @@ size_t hal_aes_keywrap_ciphertext_length(const size_t plaintext_length)
 /*
  * Check the KEK, then load it into the AES core.
  * Note that our AES core only supports 128 and 256 bit keys.
+ *
+ * This should work without modification for the experimental keywrap core.
  */
 
 typedef enum { KEK_encrypting, KEK_decrypting } kek_action_t;
@@ -113,6 +129,68 @@ static hal_error_t load_kek(const hal_core_t *core, const uint8_t *K, const size
 }
 
 
+/*
+ * Use the experimental keywrap core to wrap/unwrap n 64-bit blocks of plaintext.
+ * The wrapped/unwrapped key is returned in the same buffer.
+ */
+
+static hal_error_t do_keywrap_core(const hal_core_t *core, uint8_t * const C, const size_t n)
+{
+#ifndef min
+#define min(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+  hal_error_t err;
+
+  hal_assert(core != NULL && C != NULL && n > 0);
+
+  /* The core is currently limited to 4 banks of 512 bytes, which is way too small. */
+  if (n == 0 || n > 4 * 64)
+    return HAL_ERROR_BAD_ARGUMENTS;
+
+  /* write the AIV to A */
+  if ((err = hal_io_write(core, KEYWRAP_ADDR_A0, C, 8)) != HAL_OK)
+    return err;
+
+  /* write the length to RLEN */
+  uint32_t nn = htonl(n);
+  if ((err = hal_io_write(core, KEYWRAP_ADDR_RLEN, (const uint8_t *)&nn, 4)) != HAL_OK)
+    return err;
+
+  /* write the data to R_DATA, with bank-switching as necessary */
+  for (size_t bank = 0; 64 * bank < n; ++bank) {
+    uint32_t bb = htonl(bank);
+    if ((err = hal_io_write(core, KEYWRAP_ADDR_R_BANK, (const uint8_t *)&bb, 4)) != HAL_OK)
+      return err;
+    /* R_DATA is 128 32-bit registers, so 64 64-bit blocks or 512 bytes. */
+    size_t len = min(n - 64 * bank, 64) * 8;
+    if ((err = hal_io_write(core, KEYWRAP_ADDR_R_DATA0, (C + 512 * bank + 8), len)) != HAL_OK)
+      return err;
+  }
+
+  /* start the wrap/unwrap operation, and wait for it to complete */
+  if ((err = hal_io_next(core)) != HAL_OK ||
+      (err = hal_io_wait_ready(core)) != HAL_OK)
+    return err;
+
+  /* read the A registers */
+  if ((err = hal_io_read(core, KEYWRAP_ADDR_A0, C, 8)) != HAL_OK)
+    return err;
+
+  /* read the data from R_DATA, with bank-switching as necessary */
+  for (size_t bank = 0; 64 * bank < n; ++bank) {
+    uint32_t bb = htonl(bank);
+    if ((err = hal_io_write(core, KEYWRAP_ADDR_R_BANK, (const uint8_t *)&bb, 4)) != HAL_OK)
+      return err;
+    size_t len = min(n - 64 * bank, 64) * 8;
+    if ((err = hal_io_read(core, KEYWRAP_ADDR_R_DATA0, (C + 512 * bank + 8), len)) != HAL_OK)
+      return err;
+  }
+
+  return HAL_OK;
+}
+
+
 /*
  * Process one block.  Since AES Key Wrap always deals with 64-bit
  * half blocks and since the bus is going to break this up into 32-bit
@@ -163,7 +241,7 @@ hal_error_t hal_aes_keywrap(hal_core_t *core,
                             size_t *C_len)
 {
   const size_t calculated_C_len = hal_aes_keywrap_ciphertext_length(m);
-  const int free_core = core == NULL;
+  const int free_core = (core == NULL);
   hal_error_t err;
   size_t n;
 
@@ -172,8 +250,22 @@ hal_error_t hal_aes_keywrap(hal_core_t *core,
   if (Q == NULL || C == NULL || C_len == NULL || *C_len < calculated_C_len)
     return HAL_ERROR_BAD_ARGUMENTS;
 
-  if (free_core && (err = hal_core_alloc(AES_CORE_NAME, &core, NULL)) != HAL_OK)
-    return err;
+  /* If we're passed a core, we should figure out which one it is.
+   * In practice, core is always NULL, so this is UNTESTED CODE.
+   */
+  if (core) {
+    const hal_core_info_t *info = hal_core_info(core);
+    if (memcmp(info->name, KEYWRAP_NAME, 8) == 0)
+      use_keywrap_core = 1;
+    else if (memcmp(info->name, AES_CORE_NAME, 8) != 0)
+      /* I have no idea what this is */
+      return HAL_ERROR_BAD_ARGUMENTS;
+  }
+  else {
+    const char *core_name = (use_keywrap_core ? KEYWRAP_NAME : AES_CORE_NAME);
+    if ((err = hal_core_alloc(core_name, &core, NULL)) != HAL_OK)
+      return err;
+  }
 
   if ((err = load_kek(core, K, K_len, KEK_encrypting)) != HAL_OK)
       goto out;
@@ -195,21 +287,26 @@ hal_error_t hal_aes_keywrap(hal_core_t *core,
 
   n = calculated_C_len/8 - 1;
 
-  if (n == 1) {
-    if ((err = do_block(core, C, C + 8)) != HAL_OK)
-        goto out;
+  if (use_keywrap_core) {
+    err = do_keywrap_core(core, C, n);
   }
-
   else {
-    for (size_t j = 0; j <= 5; j++) {
-      for (size_t i = 1; i <= n; i++) {
-        uint32_t t = n * j + i;
-        if ((err = do_block(core, C, C + i * 8)) != HAL_OK)
+    if (n == 1) {
+      if ((err = do_block(core, C, C + 8)) != HAL_OK)
+        goto out;
+    }
+
+    else {
+      for (size_t j = 0; j <= 5; j++) {
+        for (size_t i = 1; i <= n; i++) {
+          uint32_t t = n * j + i;
+          if ((err = do_block(core, C, C + i * 8)) != HAL_OK)
             goto out;
-        C[7] ^= t & 0xFF; t >>= 8;
-        C[6] ^= t & 0xFF; t >>= 8;
-        C[5] ^= t & 0xFF; t >>= 8;
-        C[4] ^= t & 0xFF;
+          C[7] ^= t & 0xFF; t >>= 8;
+          C[6] ^= t & 0xFF; t >>= 8;
+          C[5] ^= t & 0xFF; t >>= 8;
+          C[4] ^= t & 0xFF;
+        }
       }
     }
   }
@@ -242,8 +339,22 @@ hal_error_t hal_aes_keyunwrap(hal_core_t *core,
   if (C == NULL || Q == NULL || C_len % 8 != 0 || C_len < 16 || Q_len == NULL || *Q_len < C_len)
     return HAL_ERROR_BAD_ARGUMENTS;
 
-  if (free_core && (err = hal_core_alloc(AES_CORE_NAME, &core, NULL)) != HAL_OK)
-    return err;
+  /* If we're passed a core, we should figure out which one it is.
+   * In practice, core is always NULL, so this is UNTESTED CODE.
+   */
+  if (core) {
+    const hal_core_info_t *info = hal_core_info(core);
+    if (memcmp(info->name, KEYWRAP_NAME, 8) == 0)
+      use_keywrap_core = 1;
+    else if (memcmp(info->name, AES_CORE_NAME, 8) != 0)
+      /* I have no idea what this is */
+      return HAL_ERROR_BAD_ARGUMENTS;
+  }
+  else {
+    const char *core_name = (use_keywrap_core ? KEYWRAP_NAME : AES_CORE_NAME);
+    if ((err = hal_core_alloc(core_name, &core, NULL)) != HAL_OK)
+      return err;
+  }
 
   if ((err = load_kek(core, K, K_len, KEK_decrypting)) != HAL_OK)
     goto out;
@@ -253,21 +364,26 @@ hal_error_t hal_aes_keyunwrap(hal_core_t *core,
   if (Q != C)
     memmove(Q, C, C_len);
 
-  if (n == 1) {
-    if ((err = do_block(core, Q, Q + 8)) != HAL_OK)
-      goto out;
+  if (use_keywrap_core) {
+    err = do_keywrap_core(core, Q, n);
   }
-
   else {
-    for (long j = 5; j >= 0; j--) {
-      for (size_t i = n; i >= 1; i--) {
-        uint32_t t = n * j + i;
-        Q[7] ^= t & 0xFF; t >>= 8;
-        Q[6] ^= t & 0xFF; t >>= 8;
-        Q[5] ^= t & 0xFF; t >>= 8;
-        Q[4] ^= t & 0xFF;
-        if ((err = do_block(core, Q, Q + i * 8)) != HAL_OK)
-          goto out;
+    if (n == 1) {
+      if ((err = do_block(core, Q, Q + 8)) != HAL_OK)
+        goto out;
+    }
+
+    else {
+      for (long j = 5; j >= 0; j--) {
+        for (size_t i = n; i >= 1; i--) {
+          uint32_t t = n * j + i;
+          Q[7] ^= t & 0xFF; t >>= 8;
+          Q[6] ^= t & 0xFF; t >>= 8;
+          Q[5] ^= t & 0xFF; t >>= 8;
+          Q[4] ^= t & 0xFF;
+          if ((err = do_block(core, Q, Q + i * 8)) != HAL_OK)
+            goto out;
+        }
       }
     }
   }
diff --git a/hal.h b/hal.h
index b544900..9986de7 100644
--- a/hal.h
+++ b/hal.h
@@ -109,6 +109,9 @@
 #define ECDSA384_NAME           "ecdsa384"
 #define ECDSA384_VERSION        "0.11"
 
+#define KEYWRAP_NAME            "key wrap"
+#define KEYWRAP_VERSION         "0.70"
+
 /*
  * C API error codes.  Defined in this form so we can keep the tokens
  * and error strings together.  See errorstrings.c.
@@ -363,6 +366,8 @@ extern const hal_hash_descriptor_t *hal_hmac_get_descriptor(const hal_hmac_state
  * AES key wrap functions.
  */
 
+extern int hal_aes_use_keywrap_core(int onoff);
+
 extern hal_error_t hal_aes_keywrap(hal_core_t *core,
                                    const uint8_t *kek, const size_t kek_length,
                                    const uint8_t *plaintext, const size_t plaintext_length,
diff --git a/hal_io_fmc.c b/hal_io_fmc.c
index 8a32921..07f9352 100644
--- a/hal_io_fmc.c
+++ b/hal_io_fmc.c
@@ -114,7 +114,8 @@ hal_error_t hal_io_write(const hal_core_t *core, hal_addr_t offset, const uint8_
   for (; len > 0; offset += 4, buf += 4, len -= 4) {
     uint32_t val;
     val = htonl(*(uint32_t *)buf);
-    fmc_write_32(offset, val);
+    if (fmc_write_32(offset, val) != 0)
+      return HAL_ERROR_IO_TIMEOUT;
   }
 
   return HAL_OK;
@@ -140,7 +141,8 @@ hal_error_t hal_io_read(const hal_core_t *core, hal_addr_t offset, uint8_t *buf,
   offset = fmc_offset(offset + hal_core_base(core));
   for (; rlen > 0; offset += 4, rbuf += 4, rlen -= 4) {
     uint32_t val;
-    fmc_read_32(offset, &val);
+    if (fmc_read_32(offset, &val) != 0)
+      return HAL_ERROR_IO_TIMEOUT;
     *(uint32_t *)rbuf = ntohl(val);
   }
 
diff --git a/verilog_constants.h b/verilog_constants.h
index 1b00b96..df808c4 100644
--- a/verilog_constants.h
+++ b/verilog_constants.h
@@ -40,6 +40,7 @@
 #ifndef _VERILOG_CONSTANTS_H_
 #define _VERILOG_CONSTANTS_H_
 
+
 /*
  * Common to all cores.
  */
@@ -298,6 +299,31 @@
 #define MKMIF_ADDR_EMEM_ADDR    (0x10)
 #define MKMIF_ADDR_EMEM_DATA    (0x20)
 
+/*
+ * AES Keywrap core
+ */
+
+#define KEYWRAP_ADDR_CONFIG     (0x0a)
+#define KEYWRAP_CONFIG_ENCDEC   (1)
+#define KEYWRAP_CONFIG_KEYLEN   (2)
+
+#define KEYWRAP_ADDR_RLEN       (0x0c)
+#define KEYWRAP_ADDR_R_BANK     (0x0d)
+#define KEYWRAP_ADDR_A0         (0x0e)
+#define KEYWRAP_ADDR_A1         (0x0f)
+
+#define KEYWRAP_ADDR_KEY0       (0x10)
+#define KEYWRAP_ADDR_KEY1       (0x11)
+#define KEYWRAP_ADDR_KEY2       (0x12)
+#define KEYWRAP_ADDR_KEY3       (0x13)
+#define KEYWRAP_ADDR_KEY4       (0x14)
+#define KEYWRAP_ADDR_KEY5       (0x15)
+#define KEYWRAP_ADDR_KEY6       (0x16)
+#define KEYWRAP_ADDR_KEY7       (0x17)
+
+#define KEYWRAP_ADDR_R_DATA0    (0x80)
+#define KEYWRAP_ADDR_R_DATA127  (0xff)
+
 #endif /* _VERILOG_CONSTANTS_H_ */
 
 /*



More information about the Commits mailing list