[Cryptech-Commits] [sw/libhal] 03/03: Clean up and document cryptech_backup.

git at cryptech.is git at cryptech.is
Fri Apr 14 21:13:23 UTC 2017


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

sra at hactrn.net pushed a commit to branch ksng
in repository sw/libhal.

commit 91ce93471aa8e9824a8ad298dfb11d05814937c7
Author: Rob Austein <sra at hactrn.net>
AuthorDate: Fri Apr 14 16:10:12 2017 -0400

    Clean up and document cryptech_backup.
---
 cryptech_backup | 113 ++++++++++++++++++++++++++++++++++++++------------------
 1 file changed, 78 insertions(+), 35 deletions(-)

diff --git a/cryptech_backup b/cryptech_backup
index 18441a3..f14f119 100755
--- a/cryptech_backup
+++ b/cryptech_backup
@@ -1,18 +1,38 @@
 #!/usr/bin/env python
 
-#    KEY SOURCE                            KEY BACKUP
+"""
+Securely back up private keys from one Cryptech HSM to another.
+
+This works by having the destination HSM (the one importing keys)
+create an RSA keypair (the "KEKEK"), the public key of which can then
+be imported into the source HSM (the one exporting keys) and used to
+encrypt AES key encryption keys (KEKs) which in turn can be used to
+wrap the private keys being transfered.  Transfers are encoded in
+JSON; the underlying ASN.1 formats are SubjectPublicKeyInfo (KEKEK
+public key) and PKCS #8 EncryptedPrivateKeyInfo (everything else).
+
+NOTE WELL: while this process makes it POSSIBLE to back up keys
+securely, it is not sufficient by itself: the operator MUST make
+sure only to export keys using a KEKEK known to have been generated by
+the target HSM.  See the unit tests in the source repository for
+an example of how to fake this in a few lines of Python.
+
+YOU HAVE BEEN WARNED.  Be careful out there.
+"""
+
+# Diagram of the trivial protocol we're using:
+#
+#    SOURCE HSM                            DESTINATION HSM
 #
 #                                          Generate and export KEKEK:
 #                                               hal_rpc_pkey_generate_rsa()
 #                                               hal_rpc_pkey_get_public_key()
 #
-#   Load KEKEK public   <----------------  Export KEKEK public
-#
-#       hal_rpc_pkey_load()
-#       hal_rpc_pkey_export()
+#   Load KEKEK public        <---------    Export KEKEK public
+#        hal_rpc_pkey_load()
+#        hal_rpc_pkey_export()
 #
 #   Export PKCS #8 and KEK   ---------->   Load PKCS #8 and KEK, import key
-#
 #                                               hal_rpc_pkey_import()
 
 import sys
@@ -27,42 +47,63 @@ from cryptech.libhal import *
 def main():
 
     parser = argparse.ArgumentParser(
-        formatter_class = argparse.ArgumentDefaultsHelpFormatter,
+        formatter_class = argparse.RawDescriptionHelpFormatter,
         description = __doc__)
     subparsers = parser.add_subparsers(
         title = "Commands (use \"--help\" after command name for help with individual commands)",
         metavar = "")
+    setup_parser  = defcmd(subparsers, cmd_setup)
+    export_parser = defcmd(subparsers, cmd_export)
+    import_parser = defcmd(subparsers, cmd_import)
+    setup_mutex_group = setup_parser.add_mutually_exclusive_group()
+
+
     parser.add_argument(
         "-p", "--pin",
-        help = "wheel PIN")
-
-    subparser = defcmd(subparsers, cmd_setup)
-    group = subparser.add_mutually_exclusive_group()
-    group.add_argument(
-        "-n", "--new", action = "store_true",
-        help = "force creation of new KEKEK")
-    group.add_argument(
+        help    = "wheel PIN")
+
+
+    setup_mutex_group.add_argument(
+        "-n", "--new",
+        action  = "store_true",
+        help    = "force creation of new KEKEK")
+
+    setup_mutex_group.add_argument(
         "-u", "--uuid",
-        help = "UUID of existing KEKEK to use")
-    subparser.add_argument(
-        "-k", "--keylen", type = int, default = 2048,
-        help = "length of new KEKEK if we need to create one")
-    subparser.add_argument(
-        "-o", "--output", type = argparse.FileType("w"), default = "-",
-        help = "output file")
-
-    subparser = defcmd(subparsers, cmd_export)
-    subparser.add_argument(
-        "-i", "--input", type = argparse.FileType("r"), default = "-",
-        help = "input file")
-    subparser.add_argument(
-        "-o", "--output", type = argparse.FileType("w"), default = "-",
-        help = "output file")
-
-    subparser = defcmd(subparsers, cmd_import)
-    subparser.add_argument(
-        "-i", "--input", type = argparse.FileType("r"), default = "-",
-        help = "input file")
+        help    = "UUID of existing KEKEK to use")
+
+    setup_parser.add_argument(
+        "-k", "--keylen",
+        type    = int,
+        default = 2048,
+        help    = "length of new KEKEK if we need to create one")
+
+    setup_parser.add_argument(
+        "-o", "--output",
+        type    = argparse.FileType("w"),
+        default = "-",
+        help    = "output file")
+
+
+    export_parser.add_argument(
+        "-i", "--input",
+        type    = argparse.FileType("r"),
+        default = "-",
+        help    = "input file")
+
+    export_parser.add_argument(
+        "-o", "--output",
+        type    = argparse.FileType("w"),
+        default = "-",
+        help    = "output file")
+
+
+    import_parser.add_argument(
+        "-i", "--input",
+        type    = argparse.FileType("r"),
+        default = "-",
+        help    = "input file")
+
 
     args = parser.parse_args()
 
@@ -138,6 +179,7 @@ def cmd_setup(args, hsm):
 
     result.update(comment = "KEKEK public key")
     json.dump(result, args.output, indent = 4, sort_keys = True)
+    args.output.write("\n")
 
 
 def key_flag_names(flags):
@@ -195,6 +237,7 @@ def cmd_export(args, hsm):
     db.update(comment = "Cryptech Alpha encrypted key backup",
               keys    = result)
     json.dump(db, args.output, indent = 4, sort_keys = True)
+    args.output.write("\n")
 
 
 def cmd_import(args, hsm):



More information about the Commits mailing list