aboutsummaryrefslogtreecommitdiff
path: root/utils/pkey-import.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/pkey-import.c')
-rw-r--r--utils/pkey-import.c168
1 files changed, 168 insertions, 0 deletions
diff --git a/utils/pkey-import.c b/utils/pkey-import.c
new file mode 100644
index 0000000..611448f
--- /dev/null
+++ b/utils/pkey-import.c
@@ -0,0 +1,168 @@
+/*
+ * pkey-import.c
+ * -------------
+ * Import a key.
+ *
+ * Copyright (c) 2018, NORDUnet A/S
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of the NORDUnet nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <getopt.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <hal.h>
+
+#define HAL_KS_WRAPPED_KEYSIZE ((2373 + 6 * 4096 / 8 + 6 * 4 + 15) & ~7)
+
+#define lose(...) do { printf(__VA_ARGS__); goto fail; } while (0)
+
+static int read_file(const char * const fn, uint8_t * const buf, size_t *buf_len, const size_t buf_max)
+{
+ int fd;
+ if ((fd = open(fn, O_RDONLY)) == -1)
+ lose("Error opening %s: %s\n", fn, strerror(errno));
+
+ size_t nread;
+ if ((nread = read(fd, buf, buf_max)) == -1)
+ lose("Error reading %s: %s\n", fn, strerror(errno));
+
+ *buf_len = nread;
+
+ if (close(fd) != 0)
+ lose("Error closing %s: %s\n", fn, strerror(errno));
+
+ return 0;
+
+fail:
+ return -1;
+}
+
+static int read_buf(const char * const name, const char * const ext, uint8_t * const buf, size_t *buf_len, const size_t buf_max)
+{
+ char fn[strlen(name) + strlen(ext) + 1];
+ strcpy(fn, name);
+ strcat(fn, ext);
+
+ return read_file(fn, buf, buf_len, buf_max);
+}
+
+#define lose_usage(...) do { printf(__VA_ARGS__); printf(usage, argv[0]); goto fail; } while (0)
+
+int main(int argc, char *argv[])
+{
+ hal_error_t err;
+ const hal_client_handle_t client = {HAL_HANDLE_NONE};
+ const hal_session_handle_t session = {HAL_HANDLE_NONE};
+ char *pin = "fnord";
+ char *kekek_fn = NULL;
+ char *key_fn = NULL;
+
+char usage[] = "\
+Usage: %s [-p pin] <-k kekek> keyfile\n\
+";
+
+ int opt;
+ while ((opt = getopt(argc, argv, "p:k:")) != -1) {
+ switch (opt) {
+ case 'p':
+ pin = optarg;
+ break;
+ case 'k':
+ kekek_fn = optarg;
+ break;
+ case 'h':
+ case '?':
+ printf(usage, argv[0]);
+ return 0;
+ }
+ }
+ key_fn = argv[optind];
+
+ if (kekek_fn == NULL)
+ lose_usage("Error: missing option -k\n");
+ if (key_fn == NULL)
+ lose_usage("Error: missing keyfile\n");
+
+ uint8_t kekek_der[HAL_KS_WRAPPED_KEYSIZE]; size_t kekek_der_len;
+
+ if (read_file(kekek_fn, kekek_der, &kekek_der_len, sizeof(kekek_der)) != 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 (read_buf(key_fn, ".der", der, &der_len, sizeof(der)) != 0 ||
+ read_buf(key_fn, ".kek", kek, &kek_len, sizeof(kek)) != 0)
+ goto fail;
+
+ if ((err = hal_rpc_client_init()) != HAL_OK)
+ lose("Error initializing RPC client: %s\n", hal_error_string(err));
+
+ if ((err = hal_rpc_login(client, HAL_USER_NORMAL, pin, strlen(pin))) != HAL_OK)
+ lose("Error logging into HSM: %s\n", hal_error_string(err));
+
+ hal_pkey_handle_t kekek = {HAL_HANDLE_NONE};
+ hal_uuid_t kekek_name;
+
+ if ((err = hal_rpc_pkey_load(client, session, &kekek, &kekek_name,
+ kekek_der, kekek_der_len,
+ HAL_KEY_FLAG_USAGE_KEYENCIPHERMENT)) != HAL_OK)
+ lose("Error loading import key: %s\n", hal_error_string(err));
+
+ hal_pkey_handle_t private_key = {HAL_HANDLE_NONE};
+ hal_uuid_t private_name;
+
+ if ((err = hal_rpc_pkey_import(client, session,
+ &private_key, &private_name,
+ kekek,
+ der, der_len,
+ kek, kek_len,
+ HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE | HAL_KEY_FLAG_TOKEN | HAL_KEY_FLAG_EXPORTABLE)) != 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(&private_name, 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_logout(client)) != HAL_OK)
+ lose("Error logging out of HSM: %s\n", hal_error_string(err));
+
+ if ((err = hal_rpc_client_close()) != HAL_OK)
+ lose("Error shutting down RPC client: %s\n", hal_error_string(err));
+
+ return 0;
+
+fail:
+ return -1;
+}