[Cryptech-Commits] [sw/libhal] 01/01: Export/import "raw" keys for external storage.

git at cryptech.is git at cryptech.is
Wed Nov 6 21:34:13 UTC 2019


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

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

commit 323bc8ade3eae73174961bbf604257a1b099fe55
Author: Paul Selkirk <paul at psgd.org>
AuthorDate: Wed Nov 6 14:34:00 2019 -0500

    Export/import "raw" keys for external storage.
    
    Exported keys are wrapped with the MKM KEK, not a transit KEK, and can
    only be imported back to the same HSM.
    
    The idea is to support operators who have more keys than will fit on the
    HSM, so they will cycle keys into and out of the HSM as needed.
    
    NOTE that hashsig is, as always, special. The hashsig key has an internal
    index that is updated on every signature. To prevent a hashsig key from
    being re-imported with an old index (which would compromise the security
    of the key), the hashsig key is disabled on export, and must be deleted
    from the HSM before being re-imported.
---
 cryptech/libhal.py |  20 +++++++++++
 hal.h              |  13 +++++++
 hal_internal.h     |  14 +++++++-
 hashsig.c          |  35 ++++++++++++++++++
 rpc_api.c          |  20 +++++++++++
 rpc_client.c       |  66 ++++++++++++++++++++++++++++++++--
 rpc_pkey.c         | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 rpc_server.c       |  60 +++++++++++++++++++++++++++++++
 utils/pkey.c       | 104 +++++++++++++++++++++++++++++++++--------------------
 9 files changed, 394 insertions(+), 42 deletions(-)

diff --git a/cryptech/libhal.py b/cryptech/libhal.py
index 647dbd6..1899102 100644
--- a/cryptech/libhal.py
+++ b/cryptech/libhal.py
@@ -191,6 +191,8 @@ RPCFunc.define('''
     RPC_FUNC_PKEY_EXPORT,
     RPC_FUNC_PKEY_IMPORT,
     RPC_FUNC_PKEY_GENERATE_HASHSIG,
+    RPC_FUNC_PKEY_EXPORT_RAW,
+    RPC_FUNC_PKEY_IMPORT_RAW,
 ''')
 
 class HALDigestAlgorithm(Enum): pass
@@ -434,6 +436,12 @@ class PKey(Handle):
     def import_pkey(self, pkcs8, kek, flags = 0):
         return self.hsm.pkey_import(kekek = self, pkcs8 = pkcs8, kek = kek, flags = flags)
 
+    def export_raw_pkey(self, pkey):
+        return self.hsm.pkey_export_raw(pkey = pkey, der_max = 5480)
+
+    def import_raw_pkey(self, der, flags = 0):
+        return self.hsm.pkey_import_raw(der = der, flags = flags)
+
 class ContextManagedUnpacker(xdrlib.Unpacker):
 
     def __enter__(self):
@@ -710,3 +718,15 @@ class HSM(object):
             pkey = PKey(self, r.unpack_uint(), UUID(bytes = r.unpack_bytes()))
             logger.debug("Imported pkey %s", pkey.uuid)
             return pkey
+
+    def pkey_export_raw(self, pkey, der_max = 2560):
+        with self.rpc(RPC_FUNC_PKEY_EXPORT_RAW, pkey, der_max) as r:
+            der = r.unpack_bytes(), r.unpack_bytes()
+            logger.debug("Exported raw pkey %s", pkey.uuid)
+            return der
+
+    def pkey_import_raw(self, der, flags = 0, client = 0, session = 0):
+        with self.rpc(RPC_FUNC_PKEY_IMPORT_RAW, session, der, flags, client = client) as r:
+            pkey = PKey(self, r.unpack_uint(), UUID(bytes = r.unpack_bytes()))
+            logger.debug("Imported raw pkey %s", pkey.uuid)
+            return pkey
diff --git a/hal.h b/hal.h
index 43ea6a0..1a08690 100644
--- a/hal.h
+++ b/hal.h
@@ -893,6 +893,9 @@ extern hal_error_t hal_rpc_pkey_export(const hal_pkey_handle_t pkey,
                                        uint8_t *pkcs8, size_t *pkcs8_len, const size_t pkcs8_max,
                                        uint8_t *kek,   size_t *kek_len,   const size_t kek_max);
 
+extern hal_error_t hal_rpc_pkey_export_raw(const hal_pkey_handle_t pkey,
+                                           uint8_t *pkcs8, size_t *pkcs8_len, const size_t pkcs8_max);
+
 extern hal_error_t hal_rpc_pkey_import(const hal_client_handle_t client,
                                        const hal_session_handle_t session,
                                        hal_pkey_handle_t *pkey,
@@ -902,6 +905,13 @@ extern hal_error_t hal_rpc_pkey_import(const hal_client_handle_t client,
                                        const uint8_t * const kek,   const size_t kek_len,
                                        const hal_key_flags_t flags);
 
+extern hal_error_t hal_rpc_pkey_import_raw(const hal_client_handle_t client,
+                                           const hal_session_handle_t session,
+                                           hal_pkey_handle_t *pkey,
+                                           hal_uuid_t *name,
+                                           const uint8_t * const pkcs8, const size_t pkcs8_len,
+                                           const hal_key_flags_t flags);
+
 extern hal_error_t hal_rpc_client_init(void);
 
 extern hal_error_t hal_rpc_client_close(void);
@@ -1005,6 +1015,9 @@ extern hal_error_t hal_hashsig_ks_init(void);
 extern hal_error_t hal_hashsig_export(const hal_uuid_t * const name,
                                       uint8_t *der, size_t *der_len, const size_t der_max);
 
+extern hal_error_t hal_hashsig_export_raw(const hal_uuid_t * const name,
+                                          uint8_t *der, size_t *der_len, const size_t der_max);
+
 extern hal_error_t hal_hashsig_import(const uint8_t *der, const size_t der_len,
                                       const hal_key_flags_t flags);
 
diff --git a/hal_internal.h b/hal_internal.h
index 15f4c79..1885595 100644
--- a/hal_internal.h
+++ b/hal_internal.h
@@ -380,6 +380,16 @@ typedef struct {
                         const uint8_t * const kek, const size_t kek_len,
                         const hal_key_flags_t flags);
 
+  hal_error_t (*export_raw)(const hal_pkey_handle_t pkey_handle,
+                            uint8_t *der, size_t *der_len, const size_t der_max);
+
+  hal_error_t (*import_raw)(const hal_client_handle_t client,
+                            const hal_session_handle_t session,
+                            hal_pkey_handle_t *pkey,
+                            hal_uuid_t *name,
+                            const uint8_t * const der, const size_t der_len,
+                            const hal_key_flags_t flags);
+
 } hal_rpc_pkey_dispatch_t;
 
 
@@ -662,9 +672,11 @@ typedef enum {
     RPC_FUNC_PKEY_EXPORT,
     RPC_FUNC_PKEY_IMPORT,
     RPC_FUNC_PKEY_GENERATE_HASHSIG,
+    RPC_FUNC_PKEY_EXPORT_RAW,
+    RPC_FUNC_PKEY_IMPORT_RAW,
 } rpc_func_num_t;
 
-#define RPC_VERSION 0x01010100          /* 1.1.1.0 */
+#define RPC_VERSION 0x01010200          /* 1.1.2.0 */
 
 /*
  * RPC client locality. These have to be defines rather than an enum,
diff --git a/hashsig.c b/hashsig.c
index f55558d..cd00224 100644
--- a/hashsig.c
+++ b/hashsig.c
@@ -2100,6 +2100,41 @@ err_out:
     return err;
 }
 
+hal_error_t hal_hashsig_export_raw(const hal_uuid_t * const name, uint8_t *der, size_t *der_len, const size_t der_max)
+{
+    hal_error_t err;
+    hal_hashsig_key_t keybuf, *tmp_key = &keybuf, *hss_key;
+
+    if ((err = hal_hashsig_private_key_from_der(&hss_key, &keybuf, sizeof(keybuf), der, *der_len)) != HAL_OK)
+        goto err_out;
+    if (hss_key == tmp_key) {
+        err = HAL_ERROR_KEY_NOT_FOUND;         /* or IMPOSSIBLE? */
+        goto err_out;
+    }
+
+    /* adjust exported q */
+    hss_key->q_start = hss_key->lms_keys[0].q;
+
+    /* store updated hss_key
+     * toggle HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE to disable further use
+     */
+    hal_pkey_slot_t slot = {
+        .type = HAL_KEY_TYPE_HASHSIG_PRIVATE,
+        .name = *name,
+        .flags = HAL_KEY_FLAG_TOKEN | HAL_KEY_FLAG_EXPORTABLE
+    };
+    if ((err = hal_hashsig_private_key_to_der(hss_key, der, der_len, der_max)) != HAL_OK ||
+        (err = hal_ks_rewrite_der(hal_ks_token, &slot, der, *der_len)) != HAL_OK)
+        goto err_out;
+
+    /* return with updated der */
+
+err_out:
+    memset(&keybuf, 0, sizeof(keybuf));
+    hss_key = NULL;
+    return err;
+}
+
 hal_error_t hal_hashsig_import(const uint8_t *der, const size_t der_len,
                                const hal_key_flags_t flags)
 {
diff --git a/rpc_api.c b/rpc_api.c
index 97c8e99..155cb30 100644
--- a/rpc_api.c
+++ b/rpc_api.c
@@ -432,6 +432,26 @@ hal_error_t hal_rpc_pkey_import(const hal_client_handle_t client,
   return hal_rpc_pkey_dispatch->import(client, session, pkey, name, kekek, pkcs8, pkcs8_len, kek, kek_len, flags);
 }
 
+hal_error_t hal_rpc_pkey_export_raw(const hal_pkey_handle_t pkey,
+                                    uint8_t *der, size_t *der_len, const size_t der_max)
+{
+  if (der == NULL || der_len == NULL)
+    return HAL_ERROR_BAD_ARGUMENTS;
+  return hal_rpc_pkey_dispatch->export_raw(pkey, der, der_len, der_max);
+}
+
+hal_error_t hal_rpc_pkey_import_raw(const hal_client_handle_t client,
+                                    const hal_session_handle_t session,
+                                    hal_pkey_handle_t *pkey,
+                                    hal_uuid_t *name,
+                                    const uint8_t * const der, const size_t der_len,
+                                    const hal_key_flags_t flags)
+{
+  if (pkey == NULL || name == NULL || der == NULL)
+    return HAL_ERROR_BAD_ARGUMENTS;
+  return hal_rpc_pkey_dispatch->import_raw(client, session, pkey, name, der, der_len, flags);
+}
+
 /*
  * Local variables:
  * indent-tabs-mode: nil
diff --git a/rpc_client.c b/rpc_client.c
index c9ac9b7..face70f 100644
--- a/rpc_client.c
+++ b/rpc_client.c
@@ -1018,6 +1018,64 @@ static hal_error_t pkey_remote_import(const hal_client_handle_t client,
   return rpc_ret;
 }
 
+static hal_error_t pkey_remote_export_raw(const hal_pkey_handle_t pkey,
+                                          uint8_t *der, size_t *der_len, const size_t der_max)
+{
+  uint8_t outbuf[nargs(4)], *optr = outbuf, *olimit = outbuf + sizeof(outbuf);
+  uint8_t inbuf[nargs(3) + pad(der_max)];
+  const uint8_t *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf);
+  hal_client_handle_t dummy_client = {0};
+  hal_error_t rpc_ret;
+
+  check(hal_xdr_encode_int(&optr, olimit, RPC_FUNC_PKEY_EXPORT_RAW));
+  check(hal_xdr_encode_int(&optr, olimit, dummy_client.handle));
+  check(hal_xdr_encode_int(&optr, olimit, pkey.handle));
+  check(hal_xdr_encode_int(&optr, olimit, der_max));
+  check(hal_rpc_send(outbuf, optr - outbuf));
+
+  check(read_matching_packet(RPC_FUNC_PKEY_EXPORT_RAW, inbuf, sizeof(inbuf), &iptr, &ilimit));
+
+  check(hal_xdr_decode_int(&iptr, ilimit, &rpc_ret));
+  if (rpc_ret == HAL_OK) {
+    check(hal_xdr_decode_variable_opaque(&iptr, ilimit, der, der_len, der_max));
+  }
+  return rpc_ret;
+}
+
+static hal_error_t pkey_remote_import_raw(const hal_client_handle_t client,
+                                          const hal_session_handle_t session,
+                                          hal_pkey_handle_t *pkey,
+                                          hal_uuid_t *name,
+                                          const uint8_t * const der, const size_t der_len,
+                                          const hal_key_flags_t flags)
+{
+  uint8_t outbuf[nargs(5) + pad(der_len)], *optr = outbuf, *olimit = outbuf + sizeof(outbuf);
+  uint8_t inbuf[nargs(5) + pad(sizeof(name->uuid))];
+  const uint8_t *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf);
+  size_t name_len;
+  hal_error_t rpc_ret;
+
+  check(hal_xdr_encode_int(&optr, olimit, RPC_FUNC_PKEY_IMPORT_RAW));
+  check(hal_xdr_encode_int(&optr, olimit, client.handle));
+  check(hal_xdr_encode_int(&optr, olimit, session.handle));
+  check(hal_xdr_encode_variable_opaque(&optr, olimit, der, der_len));
+  check(hal_xdr_encode_int(&optr, olimit, flags));
+  check(hal_rpc_send(outbuf, optr - outbuf));
+
+  check(read_matching_packet(RPC_FUNC_PKEY_IMPORT_RAW, inbuf, sizeof(inbuf), &iptr, &ilimit));
+
+  check(hal_xdr_decode_int(&iptr, ilimit, &rpc_ret));
+
+  if (rpc_ret == HAL_OK) {
+    check(hal_xdr_decode_int(&iptr, ilimit, &pkey->handle));
+    check(hal_xdr_decode_variable_opaque(&iptr, ilimit, name->uuid, &name_len, sizeof(name->uuid)));
+    if (name_len != sizeof(name->uuid))
+      return HAL_ERROR_KEY_NAME_TOO_LONG;
+  }
+
+  return rpc_ret;
+}
+
 #if RPC_CLIENT == RPC_CLIENT_MIXED
 
 /*
@@ -1149,7 +1207,9 @@ const hal_rpc_pkey_dispatch_t hal_rpc_remote_pkey_dispatch = {
   .set_attributes               = pkey_remote_set_attributes,
   .get_attributes               = pkey_remote_get_attributes,
   .export                       = pkey_remote_export,
-  .import                       = pkey_remote_import
+  .import                       = pkey_remote_import,
+  .export_raw                   = pkey_remote_export_raw,
+  .import_raw                   = pkey_remote_import_raw
 };
 
 #if RPC_CLIENT == RPC_CLIENT_MIXED
@@ -1172,7 +1232,9 @@ const hal_rpc_pkey_dispatch_t hal_rpc_mixed_pkey_dispatch = {
   .set_attributes               = pkey_remote_set_attributes,
   .get_attributes               = pkey_remote_get_attributes,
   .export                       = pkey_remote_export,
-  .import                       = pkey_remote_import
+  .import                       = pkey_remote_import,
+  .export_raw                   = pkey_remote_export_raw,
+  .import_raw                   = pkey_remote_import_raw
 };
 #endif /* RPC_CLIENT == RPC_CLIENT_MIXED */
 
diff --git a/rpc_pkey.c b/rpc_pkey.c
index b44eb54..67732ad 100644
--- a/rpc_pkey.c
+++ b/rpc_pkey.c
@@ -1474,6 +1474,106 @@ static hal_error_t pkey_local_import(const hal_client_handle_t client,
   return err;
 }
 
+static hal_error_t pkey_local_export_raw(const hal_pkey_handle_t pkey_handle,
+                                         uint8_t *pkcs8, size_t *pkcs8_len, const size_t pkcs8_max)
+{
+  hal_assert(pkcs8 != NULL && pkcs8_len != NULL);
+
+  uint8_t kek[KEK_LENGTH];
+  size_t kek_len;
+  hal_error_t err;
+  size_t len;
+
+  hal_pkey_slot_t * const pkey = find_handle(pkey_handle);
+
+  if (pkey == NULL)
+    return HAL_ERROR_KEY_NOT_FOUND;
+
+  if ((pkey->flags & HAL_KEY_FLAG_EXPORTABLE) == 0)
+    return HAL_ERROR_FORBIDDEN;
+
+  if (pkcs8_max < HAL_KS_WRAPPED_KEYSIZE)
+    return HAL_ERROR_RESULT_TOO_LONG;
+
+  if ((err = ks_fetch_from_flags(pkey, pkcs8, &len, pkcs8_max)) != HAL_OK)
+    goto fail;
+
+  /* if hashsig, update internal parameters and disable further use */
+  if (pkey->type == HAL_KEY_TYPE_HASHSIG_PRIVATE) {
+    if ((err = hal_hashsig_export_raw(&pkey->name, pkcs8, &len, pkcs8_max)) != HAL_OK)
+      goto fail;
+    pkey->flags &= ~HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE;
+  }
+
+  if ((err = hal_mkm_get_kek(kek, &kek_len, sizeof(kek))) != HAL_OK)
+    goto fail;
+
+  *pkcs8_len = pkcs8_max;
+  if ((err = hal_aes_keywrap(NULL, kek, KEK_LENGTH, pkcs8, len, pkcs8, pkcs8_len)) != HAL_OK)
+    goto fail;
+
+  if ((err = hal_asn1_encode_pkcs8_encryptedprivatekeyinfo(hal_asn1_oid_aesKeyWrap,
+                                                           hal_asn1_oid_aesKeyWrap_len,
+                                                           pkcs8, *pkcs8_len,
+                                                           pkcs8, pkcs8_len, pkcs8_max)) != HAL_OK)
+    goto fail;
+
+  return HAL_OK;
+
+ fail:
+  memset(pkcs8, 0, pkcs8_max);
+  memset(kek, 0, sizeof(kek));
+  *pkcs8_len = 0;
+  return err;
+}
+
+static hal_error_t pkey_local_import_raw(const hal_client_handle_t client,
+                                         const hal_session_handle_t session,
+                                         hal_pkey_handle_t *pkey,
+                                         hal_uuid_t *name,
+                                         const uint8_t * const pkcs8, const size_t pkcs8_len,
+                                         const hal_key_flags_t flags)
+{
+  hal_assert(pkey != NULL && name != NULL && pkcs8 != NULL);
+
+  uint8_t kek[KEK_LENGTH], der[HAL_KS_WRAPPED_KEYSIZE];
+  size_t der_len, oid_len, data_len, kek_len;
+  const uint8_t *oid, *data;
+  hal_error_t err;
+
+  if ((err = hal_asn1_decode_pkcs8_encryptedprivatekeyinfo(&oid, &oid_len, &data, &data_len,
+                                                           pkcs8, pkcs8_len)) != HAL_OK)
+    goto fail;
+
+  if (oid_len != hal_asn1_oid_aesKeyWrap_len ||
+      memcmp(oid, hal_asn1_oid_aesKeyWrap, oid_len) != 0 ||
+      data_len > sizeof(der)) {
+    err = HAL_ERROR_ASN1_PARSE_FAILED;
+    goto fail;
+  }
+
+  if ((err = hal_mkm_get_kek(kek, &kek_len, sizeof(kek))) != HAL_OK)
+    goto fail;
+
+  der_len = sizeof(der);
+  if ((err = hal_aes_keyunwrap(NULL, kek, kek_len, data, data_len, der, &der_len)) != HAL_OK)
+    goto fail;
+
+  hal_key_type_t type;
+  hal_curve_name_t curve;
+  if ((err = hal_asn1_guess_key_type(&type, &curve, der, der_len)) == HAL_OK &&
+      type == HAL_KEY_TYPE_HASHSIG_PRIVATE &&
+      (err = hal_hashsig_import(der, der_len, flags)) != HAL_OK)
+    goto fail;
+
+  err = hal_rpc_pkey_load(client, session, pkey, name, der, der_len, flags);
+
+ fail:
+  memset(kek, 0, sizeof(kek));
+  memset(der, 0, sizeof(der));
+  return err;
+}
+
 const hal_rpc_pkey_dispatch_t hal_rpc_local_pkey_dispatch = {
   .load                 = pkey_local_load,
   .open                 = pkey_local_open,
@@ -1493,7 +1593,9 @@ const hal_rpc_pkey_dispatch_t hal_rpc_local_pkey_dispatch = {
   .set_attributes       = pkey_local_set_attributes,
   .get_attributes       = pkey_local_get_attributes,
   .export               = pkey_local_export,
-  .import               = pkey_local_import
+  .import               = pkey_local_import,
+  .export_raw           = pkey_local_export_raw,
+  .import_raw           = pkey_local_import_raw
 };
 
 /*
diff --git a/rpc_server.c b/rpc_server.c
index 9598413..aa7e936 100644
--- a/rpc_server.c
+++ b/rpc_server.c
@@ -776,6 +776,60 @@ static hal_error_t pkey_import(const uint8_t **iptr, const uint8_t * const ilimi
     return err;
 }
 
+static hal_error_t pkey_export_raw(const uint8_t **iptr, const uint8_t * const ilimit,
+                                   uint8_t **optr, const uint8_t * const olimit)
+{
+    hal_client_handle_t client;
+    hal_pkey_handle_t pkey;
+    size_t   der_len;
+    uint32_t der_max;
+    uint8_t *optr_orig = *optr;
+    hal_error_t err;
+
+    check(hal_xdr_decode_int(iptr, ilimit, &client.handle));
+    check(hal_xdr_decode_int(iptr, ilimit, &pkey.handle));
+    check(hal_xdr_decode_int(iptr, ilimit, &der_max));
+
+    if (nargs(1) + pad(der_max) > (uint32_t)(olimit - *optr))
+        return HAL_ERROR_RPC_PACKET_OVERFLOW;
+
+    uint8_t der[der_max];
+
+    check(hal_rpc_pkey_export_raw(pkey, der, &der_len, sizeof(der)));
+
+    if ((err = hal_xdr_encode_variable_opaque(optr, olimit, der, der_len)) != HAL_OK)
+        *optr = optr_orig;
+
+    return err;
+}
+
+static hal_error_t pkey_import_raw(const uint8_t **iptr, const uint8_t * const ilimit,
+                                   uint8_t **optr, const uint8_t * const olimit)
+{
+    hal_client_handle_t client;
+    hal_session_handle_t session;
+    hal_pkey_handle_t pkey;
+    hal_uuid_t name;
+    const uint8_t *der;
+    size_t der_len;
+    uint8_t *optr_orig = *optr;
+    hal_key_flags_t flags;
+    hal_error_t err;
+
+    check(hal_xdr_decode_int(iptr, ilimit, &client.handle));
+    check(hal_xdr_decode_int(iptr, ilimit, &session.handle));
+    check(hal_xdr_decode_variable_opaque_ptr(iptr, ilimit, &der, &der_len));
+    check(hal_xdr_decode_int(iptr, ilimit, &flags));
+
+    check(hal_rpc_pkey_import_raw(client, session, &pkey, &name, der, der_len, flags));
+
+    if ((err = hal_xdr_encode_int(optr, olimit, pkey.handle)) != HAL_OK ||
+        (err = hal_xdr_encode_variable_opaque(optr, olimit, name.uuid, sizeof(name.uuid))) != HAL_OK)
+        *optr = optr_orig;
+
+    return err;
+}
+
 
 hal_error_t hal_rpc_server_dispatch(const uint8_t * const ibuf, const size_t ilen,
                                     uint8_t * const obuf, size_t * const olen)
@@ -890,6 +944,12 @@ hal_error_t hal_rpc_server_dispatch(const uint8_t * const ibuf, const size_t ile
     case RPC_FUNC_PKEY_IMPORT:
         handler = pkey_import;
         break;
+    case RPC_FUNC_PKEY_EXPORT_RAW:
+        handler = pkey_export_raw;
+        break;
+    case RPC_FUNC_PKEY_IMPORT_RAW:
+        handler = pkey_import_raw;
+        break;
     }
 
     if (handler)
diff --git a/utils/pkey.c b/utils/pkey.c
index 76c1bf7..efd360d 100644
--- a/utils/pkey.c
+++ b/utils/pkey.c
@@ -62,8 +62,8 @@
  * list [-t type]
  * sign [-h (hash)] [-k keyname] [-m msgfile] [-s sigfile] [-n iterations]
  * verify [-h (hash)] [-k keyname] [-m msgfile] [-s sigfile]
- * export [-k keyname] [-K kekekfile] [-o outfile]
- * import [-K kekekfile] [-i infile] [-x (exportable)] [-v (volatile keystore)]
+ * export [-k keyname] [-r (raw) | -K kekekfile] [-o outfile]
+ * import [-r (raw) | -K kekekfile] [-i infile] [-x (exportable)] [-v (volatile keystore)]
  * delete [-k keyname] ...
  */
 
@@ -166,7 +166,7 @@ static int file_write(const char * const fn, const void * const buf, const size_
     if (fclose(fp) != 0)
         lose("Error closing %s: %s\n", fn, strerror(errno));
 
-    if (secret && chmod(fn, S_IRUSR) != 0)
+    if (secret && chmod(fn, S_IRUSR|S_IWUSR) != 0)
         lose("Error chmod'ing %s: %s\n", fn, strerror(errno));
 
     return 0;
@@ -799,6 +799,8 @@ done:
                                      m, mlen, sig, &sig_len, sizeof(sig))) != HAL_OK) {
             if (i > 0 && err == HAL_ERROR_HASHSIG_KEY_EXHAUSTED)
                 break;
+            else if (n == 1)
+                lose("Error signing: %s\n", hal_error_string(err));
             else
                 lose("Error signing (%d): %s\n", i, hal_error_string(err));
         }
@@ -923,14 +925,15 @@ fail:
 
 static int pkey_export(int argc, char *argv[])
 {
-    char usage[] = "Usage: export [-k keyname] [-K kekekfile] [-o outfile]";
+    char usage[] = "Usage: export [-k keyname] [-r | -K kekekfile] [-o outfile]";
 
     hal_pkey_handle_t kekek_handle = {HAL_HANDLE_NONE};
     char *kekek_fn = NULL;
     char *out_fn = NULL;
+    int raw = 0;
 
     int opt;
-    while ((opt = getopt(argc, argv, "-k:K:o:")) != -1) {
+    while ((opt = getopt(argc, argv, "-k:K:o:r")) != -1) {
         switch (opt) {
         case 1:
             /* found the next command */
@@ -947,6 +950,9 @@ static int pkey_export(int argc, char *argv[])
         case 'o':
             out_fn = optarg;
             break;
+        case 'r':
+            raw = 1;
+            break;
         default:
             puts(usage);
             return -1;
@@ -960,7 +966,7 @@ done:
         return -1;
     }
 
-    if (kekek_fn == NULL) {
+    if (!raw && kekek_fn == NULL) {
         printf("export: missing kekek\n");
         puts(usage);
         return -1;
@@ -975,34 +981,43 @@ done:
             out_fn = key_name;
         }
 
-        if (pkey_load(kekek_fn, &kekek_handle) != 0)
+        if (!raw && pkey_load(kekek_fn, &kekek_handle) != 0)
             goto fail;
 
         uint8_t der[HAL_KS_WRAPPED_KEYSIZE]; size_t der_len;
         uint8_t kek[HAL_KS_WRAPPED_KEYSIZE]; size_t kek_len;
 
-        if ((err = hal_rpc_pkey_export(key_handle, kekek_handle,
-                                       der, &der_len, sizeof(der),
-                                       kek, &kek_len, sizeof(kek))) != HAL_OK)
-            lose("Error exporting private key: %s\n", hal_error_string(err));
+        if (!raw) {
+            if ((err = hal_rpc_pkey_export(key_handle, kekek_handle,
+                                           der, &der_len, sizeof(der),
+                                           kek, &kek_len, sizeof(kek))) != HAL_OK)
+                lose("Error exporting private key: %s\n", hal_error_string(err));
+        }
+        else {
+            if ((err = hal_rpc_pkey_export_raw(key_handle,
+                                           der, &der_len, sizeof(der))) != HAL_OK)
+                lose("Error exporting private key: %s\n", hal_error_string(err));
+        }
 
         char fn[strlen(out_fn) + 5];
         strcpy(fn, out_fn); strcat(fn, ".der");
         if (file_write(fn, der, der_len, 1) != 0)
             goto fail;
 
-        strcpy(fn, out_fn); strcat(fn, ".kek");
-        if (file_write(fn, kek, kek_len, 1) != 0)
-            goto fail;
+        if (!raw) {
+            strcpy(fn, out_fn); strcat(fn, ".kek");
+            if (file_write(fn, kek, kek_len, 1) != 0)
+                goto fail;
 
-        if ((err = hal_rpc_pkey_delete(kekek_handle)) != HAL_OK)
-            lose("Could not delete key: %s\n", hal_error_string(err));
+            if ((err = hal_rpc_pkey_delete(kekek_handle)) != HAL_OK)
+                lose("Could not delete key: %s\n", hal_error_string(err));
+        }
     }
 
     return 0;
 
 fail:
-    if (kekek_handle.handle != HAL_HANDLE_NONE)
+    if (!raw && kekek_handle.handle != HAL_HANDLE_NONE)
         (void)hal_rpc_pkey_delete(kekek_handle);
 
     return -1;
@@ -1010,14 +1025,15 @@ fail:
 
 static int pkey_import(int argc, char *argv[])
 {
-    char usage[] = "Usage: import [-K kekekfile] [-i infile] [-x (exportable)] [-v (volatile keystore)]";
+    char usage[] = "Usage: import [-r | -K kekekfile] [-i infile] [-x (exportable)] [-v (volatile keystore)]";
 
     hal_pkey_handle_t kekek_handle = {HAL_HANDLE_NONE};
     char *kekek_fn = NULL;
     char *in_fn = NULL;
+    int raw = 0;
 
     int opt;
-    while ((opt = getopt(argc, argv, "-K:i:xv")) != -1) {
+    while ((opt = getopt(argc, argv, "-K:i:xvr")) != -1) {
         switch (opt) {
         case 1:
             /* found the next command */
@@ -1036,6 +1052,9 @@ static int pkey_import(int argc, char *argv[])
         case 'v':
             flags &= ~HAL_KEY_FLAG_TOKEN;
             break;
+        case 'r':
+            raw = 1;
+            break;
         default:
             puts(usage);
             return -1;
@@ -1043,7 +1062,7 @@ static int pkey_import(int argc, char *argv[])
     }
 done:
 
-    if (kekek_fn == NULL) {
+    if (!raw && kekek_fn == NULL) {
         printf("export: missing kekek\n");
         puts(usage);
         return -1;
@@ -1055,10 +1074,11 @@ done:
         return -1;
     }
 
-    if (pkey_load(kekek_fn, &kekek_handle) != 0)
+    if (!raw && pkey_load(kekek_fn, &kekek_handle) != 0)
         goto fail;
 
     {
+        hal_error_t err;
         char fn[strlen(in_fn) + 5];
         strcpy(fn, in_fn); strcat(fn, ".der");
         size_t der_len = file_size(fn);
@@ -1068,36 +1088,44 @@ done:
         if (file_read(fn, der, &der_len, sizeof(der)) != 0)
             goto fail;
 
-        strcpy(fn, in_fn); strcat(fn, ".kek");
-        size_t kek_len = file_size(fn);
-        if (kek_len == SIZE_MAX)
-            goto fail;
-        uint8_t kek[kek_len]; 
-        if (file_read(fn, kek, &kek_len, sizeof(kek)) != 0)
-            goto fail;
+        if (!raw) {
+            strcpy(fn, in_fn); strcat(fn, ".kek");
+            size_t kek_len = file_size(fn);
+            if (kek_len == SIZE_MAX)
+                goto fail;
+            uint8_t kek[kek_len]; 
+            if (file_read(fn, kek, &kek_len, sizeof(kek)) != 0)
+                goto fail;
 
-        hal_error_t err;
-        if ((err = hal_rpc_pkey_import(client, session,
-                                       &key_handle, &key_uuid,
-                                       kekek_handle,
-                                       der, der_len,
-                                       kek, kek_len,
-                                       flags)) != HAL_OK)
-            lose("Error importing private key: %s\n", hal_error_string(err));
+            if ((err = hal_rpc_pkey_import(client, session,
+                                           &key_handle, &key_uuid,
+                                           kekek_handle,
+                                           der, der_len,
+                                           kek, kek_len,
+                                           flags)) != HAL_OK)
+                lose("Error importing private key: %s\n", hal_error_string(err));
+        }
+        else {
+            if ((err = hal_rpc_pkey_import_raw(client, session,
+                                               &key_handle, &key_uuid,
+                                               der, der_len,
+                                               flags)) != HAL_OK)
+                lose("Error importing private key: %s\n", hal_error_string(err));
+        }            
 
         char name_str[HAL_UUID_TEXT_SIZE];
         if ((err = hal_uuid_format(&key_uuid, name_str, sizeof(name_str))) != HAL_OK)
             lose("Error formatting private key name: %s\n", hal_error_string(err));
         printf("New private key name: %s\n", name_str);
 
-        if ((err = hal_rpc_pkey_delete(kekek_handle)) != HAL_OK)
+        if (!raw && (err = hal_rpc_pkey_delete(kekek_handle)) != HAL_OK)
             lose("Could not delete key: %s\n", hal_error_string(err));
     }
 
     return 0;
 
 fail:
-    if (kekek_handle.handle != HAL_HANDLE_NONE)
+    if (!raw && kekek_handle.handle != HAL_HANDLE_NONE)
         (void)hal_rpc_pkey_delete(kekek_handle);
 
     return -1;



More information about the Commits mailing list