SHA256
1
0
forked from pool/s390-tools
s390-tools/s390-tools-sles15sp1-0004-zkey-Externalize-secure-key-back-end-functions.patch

1544 lines
42 KiB
Diff

Subject: zkey: Externalize secure key back-end functions
From: Philipp Rudo <prudo@linux.ibm.com>
Summary: zkey: Add support of protected key crypto for dm-crypt.
Description: Support the usage of protected key crypto for dm-crypt disks in
plain format by providing a tool to manage a key repository
allowing to associate secure keys with disk partitions or logical
volumes.
Upstream-ID: 5872f8a21ba222f9c32f0155ce1ac0f36c12cf39
Problem-ID: SEC1800
Upstream-Description:
zkey: Externalize secure key back-end functions
To reduce the size of the zkey.c source file, all routines that
deal with secure keys are moved to a new source file pkey.c.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Hendrik Brueckner <brueckner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Philipp Rudo <prudo@linux.ibm.com>
---
zkey/Makefile | 3
zkey/pkey.c | 748 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
zkey/pkey.h | 44 +++
zkey/zkey.c | 581 +++------------------------------------------
4 files changed, 832 insertions(+), 544 deletions(-)
--- a/zkey/Makefile
+++ b/zkey/Makefile
@@ -25,9 +25,10 @@ all: check_dep zkey
libs = $(rootdir)/libutil/libutil.a
zkey.o: zkey.c pkey.h misc.h
+pkey.o: pkey.c pkey.h
properties.o: properties.c properties.h
-zkey: zkey.o properties.o $(libs)
+zkey: zkey.o pkey.o properties.o $(libs)
install: all
$(INSTALL) -d -m 755 $(DESTDIR)$(USRBINDIR)
--- /dev/null
+++ b/zkey/pkey.c
@@ -0,0 +1,748 @@
+/*
+ * zkey - Generate, re-encipher, and validate secure keys
+ *
+ * Copyright IBM Corp. 2018
+ *
+ * s390-tools is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include <dlfcn.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <string.h>
+#include <stdint.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "lib/util_base.h"
+#include "lib/util_libc.h"
+#include "lib/util_panic.h"
+
+#include "pkey.h"
+
+
+#define pr_verbose(verbose, fmt...) do { \
+ if (verbose) \
+ warnx(fmt); \
+ } while (0)
+
+#define DOUBLE_KEYSIZE_FOR_XTS(keysize, xts) ((xts) ? 2 * (keysize) : (keysize))
+#define HALF_KEYSIZE_FOR_XTS(keysize, xts) ((xts) ? (keysize) / 2 : (keysize))
+
+/*
+ * Definitions for the CCA library
+ */
+#define CCA_LIBRARY_NAME "libcsulcca.so"
+
+#define DEFAULT_KEYBITS 256
+
+/**
+ * Loads the CCA library and provides the entry point of the CSNBKTC function.
+ *
+ * @param[out] lib_csulcca on return this contains the address of the CCA
+ * library. dlclose() should be used to free this
+ * when no longer needed.
+ * @param[out] dll_CSNBKTC on return this contains the address of the
+ * CSNBKTC function.
+ * @param verbose if true, verbose messages are printed
+ *
+ * @returns 0 on success, -ELIBACC in case of library load errors
+ */
+int load_cca_library(void **lib_csulcca, t_CSNBKTC *dll_CSNBKTC, bool verbose)
+{
+ util_assert(lib_csulcca != NULL, "Internal error: lib_csulcca is NULL");
+ util_assert(dll_CSNBKTC != NULL, "Internal error: dll_CSNBKTC is NULL");
+
+ /* Load the CCA library */
+ *lib_csulcca = dlopen(CCA_LIBRARY_NAME, RTLD_GLOBAL | RTLD_NOW);
+ if (*lib_csulcca == NULL) {
+ warnx("%s\nEnsure that the IBM CCA Host Libraries and "
+ "Tools are installed properly", dlerror());
+ return -ELIBACC;
+ }
+
+ /* Get the Key Token Change function */
+ *dll_CSNBKTC = (t_CSNBKTC)dlsym(*lib_csulcca, "CSNBKTC");
+ if (*dll_CSNBKTC == NULL) {
+ warnx("%s\nEnsure that the IBM CCA Host Libraries and "
+ "Tools are installed properly", dlerror());
+ dlclose(*lib_csulcca);
+ *lib_csulcca = NULL;
+ return -ELIBACC;
+ }
+
+ pr_verbose(verbose, "CCA library '%s' has been loaded successfully",
+ CCA_LIBRARY_NAME);
+ return 0;
+}
+
+/**
+ * Opens the pkey device and returns its file descriptor.
+ *
+ * @param verbose if true, verbose messages are printed
+ *
+ * @returns the file descriptor or -1 to indicate an error
+ */
+int open_pkey_device(bool verbose)
+{
+ int pkey_fd;
+
+ pkey_fd = open(PKEYDEVICE, O_RDWR);
+ if (pkey_fd < 0) {
+ warnx("File '%s:' %s\nEnsure that the 'pkey' kernel module "
+ "is loaded", PKEYDEVICE, strerror(errno));
+ return -1;
+ }
+
+ pr_verbose(verbose, "Device '%s' has been opened successfully",
+ PKEYDEVICE);
+ return pkey_fd;
+}
+
+/**
+ * Read a secure key file and return the allocated buffer and size.
+ *
+ * @param[in] keyfile the name of the file to read
+ * @param[out] secure_key_size on return, the size of the secure key read
+ * @param[in] verbose if true, verbose messages are printed
+ *
+ * @return a buffer containing the secure key, or NULL in case of an error.
+ * The returned buffer must be freed by the caller.
+ */
+u8 *read_secure_key(const char *keyfile, size_t *secure_key_size,
+ bool verbose)
+{
+ size_t count, size;
+ struct stat sb;
+ char *msg;
+ FILE *fp;
+ u8 *buf;
+
+ util_assert(keyfile != NULL, "Internal error: keyfile is NULL");
+ util_assert(secure_key_size != NULL,
+ "Internal error: secure_key_size is NULL");
+
+ if (stat(keyfile, &sb)) {
+ warnx("File '%s': %s", keyfile, strerror(errno));
+ return NULL;
+ }
+ size = sb.st_size;
+
+ if (size != SECURE_KEY_SIZE && size != 2*SECURE_KEY_SIZE) {
+ warnx("File '%s' has an invalid size, %lu or %lu bytes "
+ "expected", keyfile, SECURE_KEY_SIZE,
+ 2 * SECURE_KEY_SIZE);
+ return NULL;
+ }
+
+ fp = fopen(keyfile, "r");
+ if (fp == NULL) {
+ warnx("File '%s': %s", keyfile, strerror(errno));
+ return NULL;
+ }
+
+ buf = util_malloc(size);
+ count = fread(buf, 1, size, fp);
+ if (count <= 0) {
+ msg = feof(fp) ? "File is too small" : strerror(errno);
+ warnx("File '%s': %s", keyfile, msg);
+ free(buf);
+ buf = NULL;
+ goto out;
+ }
+
+ *secure_key_size = size;
+
+ if (verbose) {
+ pr_verbose(verbose, "%lu bytes read from file '%s'", size,
+ keyfile);
+ util_hexdump_grp(stderr, NULL, buf, 4, size, 0);
+ }
+out:
+ fclose(fp);
+ return buf;
+}
+
+/**
+ * Write a secure key file
+ *
+ * @param[in] keyfile the name of the file to write
+ * @param[in] secure_key a buffer containing the secure key
+ * @param[in] secure_key_size the size of the secure key
+ * @param[in] verbose if true, verbose messages are printed
+ *
+ * @returns 0 in case of success, -EIO in case of an error
+ */
+int write_secure_key(const char *keyfile, const u8 *secure_key,
+ size_t secure_key_size, bool verbose)
+{
+ size_t count;
+ FILE *fp;
+
+ util_assert(keyfile != NULL, "Internal error: keyfile is NULL");
+ util_assert(secure_key != NULL, "Internal error: secure_key is NULL");
+ util_assert(secure_key_size > 0,
+ "Internal error: secure_key_size is zero");
+
+ fp = fopen(keyfile, "w");
+ if (fp == NULL) {
+ warnx("File '%s': %s", keyfile, strerror(errno));
+ return -EIO;
+ }
+
+ count = fwrite(secure_key, 1, secure_key_size, fp);
+ if (count <= 0) {
+ warnx("File '%s': %s", keyfile, strerror(errno));
+ fclose(fp);
+ return -EIO;
+ }
+
+ if (verbose) {
+ pr_verbose(verbose, "%lu bytes written to file '%s'",
+ secure_key_size, keyfile);
+ util_hexdump_grp(stderr, NULL, secure_key, 4,
+ secure_key_size, 0);
+ }
+ fclose(fp);
+ return 0;
+}
+
+/**
+ * Read a clear key file and return the allocated buffer and size
+ *
+ * @param[in] keyfile the name of the file to read
+ * @param[in] keybits the clear key size in bits. When keybits is 0, then
+ * the file size determines the keybits.
+ * @param[in] xts if true an XTS key is to be read
+ * @param[out] clear_key_size on return, the size of the clear key read
+ * @param[in] verbose if true, verbose messages are printed
+ *
+ * @return a buffer containing the clear key, or NULL in case of an error.
+ * The returned buffer must be freed by the caller.
+ */
+static u8 *read_clear_key(const char *keyfile, size_t keybits, bool xts,
+ size_t *clear_key_size, bool verbose)
+{
+ size_t count, size, expected_size;
+ struct stat sb;
+ char *msg;
+ FILE *fp;
+ u8 *buf;
+
+ util_assert(keyfile != NULL, "Internal error: keyfile is NULL");
+ util_assert(clear_key_size != NULL,
+ "Internal error: clear_key_size is NULL");
+
+ if (stat(keyfile, &sb)) {
+ warnx("File '%s': %s", keyfile, strerror(errno));
+ return NULL;
+ }
+ size = sb.st_size;
+
+ if (keybits != 0) {
+ expected_size = DOUBLE_KEYSIZE_FOR_XTS(keybits / 8, xts);
+ if (size != expected_size) {
+ warnx("File '%s' has an invalid size, "
+ "%lu bytes expected", keyfile, expected_size);
+ return NULL;
+ }
+ } else {
+ keybits = DOUBLE_KEYSIZE_FOR_XTS(size * 8, xts);
+ }
+
+ switch (keybits) {
+ case 128:
+ break;
+ case 192:
+ if (xts) {
+ warnx("File '%s' has an invalid size, "
+ "192 bit keys are not supported with XTS",
+ keyfile);
+ return NULL;
+ }
+ break;
+ case 256:
+ break;
+ default:
+ if (xts)
+ warnx("File '%s' has an invalid size, "
+ "32 or 64 bytes expected", keyfile);
+ else
+ warnx("File '%s' has an invalid size, 16, 24 "
+ "or 32 bytes expected", keyfile);
+ return NULL;
+ }
+
+ fp = fopen(keyfile, "r");
+ if (fp == NULL) {
+ warnx("File '%s': %s", keyfile, strerror(errno));
+ return NULL;
+ }
+
+ buf = util_malloc(size);
+ count = fread(buf, 1, size, fp);
+ if (count <= 0) {
+ msg = feof(fp) ? "File is too small" : strerror(errno);
+ warnx("File '%s': %s", keyfile, msg);
+ free(buf);
+ buf = NULL;
+ goto out;
+ }
+
+ *clear_key_size = size;
+
+ if (verbose) {
+ pr_verbose(verbose, "%lu bytes read from file '%s'", size,
+ keyfile);
+ util_hexdump_grp(stderr, NULL, buf, 4, size, 0);
+ }
+out:
+ fclose(fp);
+ return buf;
+}
+
+/**
+ * Generate a secure key by random
+ *
+ * @param[in] pkey_fd the pkey file descriptor
+ * @param[in] keyfile the file name of the secure key to generate
+ * @param[in] keybits the cryptographic size of the key in bits
+ * @param[in] xts if true an XTS key is generated
+ * @param[in] card the card number to use (or AUTOSELECT)
+ * @param[in] domain the domain number to use (or AUTOSELECT)
+ * @param[in] verbose if true, verbose messages are printed
+ *
+ * @returns 0 on success, a negative errno in case of an error
+ */
+int generate_secure_key_random(int pkey_fd, const char *keyfile,
+ size_t keybits, bool xts, u16 card, u16 domain,
+ bool verbose)
+{
+ struct pkey_genseck gensec;
+ size_t secure_key_size;
+ u8 *secure_key;
+ int rc;
+
+ util_assert(pkey_fd != -1, "Internal error: pkey_fd is -1");
+ util_assert(keyfile != NULL, "Internal error: keyfile is NULL");
+
+ if (keybits == 0)
+ keybits = DEFAULT_KEYBITS;
+
+ secure_key_size = DOUBLE_KEYSIZE_FOR_XTS(SECURE_KEY_SIZE, xts);
+ secure_key = util_malloc(secure_key_size);
+
+ pr_verbose(verbose, "Generate key on card %02x.%04x", card, domain);
+
+ gensec.cardnr = card;
+ gensec.domain = domain;
+ switch (keybits) {
+ case 128:
+ gensec.keytype = PKEY_KEYTYPE_AES_128;
+ break;
+ case 192:
+ if (xts) {
+ warnx("Invalid value for '--keybits'|'-c' "
+ "for XTS: '%lu'", keybits);
+ rc = -EINVAL;
+ goto out;
+ }
+ gensec.keytype = PKEY_KEYTYPE_AES_192;
+ break;
+ case 256:
+ gensec.keytype = PKEY_KEYTYPE_AES_256;
+ break;
+ default:
+ warnx("Invalid value for '--keybits'/'-c': '%lu'", keybits);
+ rc = -EINVAL;
+ goto out;
+ }
+
+ rc = ioctl(pkey_fd, PKEY_GENSECK, &gensec);
+ if (rc < 0) {
+ rc = -errno;
+ warnx("Failed to generate a secure key: %s", strerror(errno));
+ goto out;
+ }
+
+ memcpy(secure_key, &gensec.seckey, SECURE_KEY_SIZE);
+
+ if (xts) {
+ rc = ioctl(pkey_fd, PKEY_GENSECK, &gensec);
+ if (rc < 0) {
+ rc = -errno;
+ warnx("Failed to generate a secure key: %s",
+ strerror(errno));
+ goto out;
+ }
+
+ memcpy(secure_key + SECURE_KEY_SIZE, &gensec.seckey,
+ SECURE_KEY_SIZE);
+ }
+
+ pr_verbose(verbose, "Successfully generated a secure key");
+
+ rc = write_secure_key(keyfile, secure_key, secure_key_size, verbose);
+
+out:
+ free(secure_key);
+ return rc;
+}
+
+
+/*
+ * Generate a secure key from a clear key file
+ *
+ * @param[in] pkey_fd the pkey file descriptor
+ * @param[in] keyfile the file name of the secure key to generate
+ * @param[in] keybits the cryptographic size of the key in bits. When
+ * keybits is 0, then the clear key file size
+ * determines the keybits.
+ * @param[in] xts if true an XTS key is generated
+ * @param[in] clearkeyfile the file name of the clear key to read
+ * @param[in] card the card number to use (or AUTOSELECT)
+ * @param[in] domain the domain number to use (or AUTOSELECT)
+ * @param[in] verbose if true, verbose messages are printed
+ *
+ * @returns 0 on success, a negative errno in case of an error
+ */
+int generate_secure_key_clear(int pkey_fd, const char *keyfile,
+ size_t keybits, bool xts,
+ const char *clearkeyfile,
+ u16 card, u16 domain,
+ bool verbose)
+{
+ struct pkey_clr2seck clr2sec;
+ size_t secure_key_size;
+ size_t clear_key_size;
+ u8 *secure_key;
+ u8 *clear_key;
+ int rc;
+
+ util_assert(pkey_fd != -1, "Internal error: pkey_fd is -1");
+ util_assert(keyfile != NULL, "Internal error: keyfile is NULL");
+ util_assert(clearkeyfile != NULL,
+ "Internal error: clearkeyfile is NULL");
+
+ secure_key_size = DOUBLE_KEYSIZE_FOR_XTS(SECURE_KEY_SIZE, xts);
+ secure_key = util_malloc(secure_key_size);
+
+ clear_key = read_clear_key(clearkeyfile, keybits, xts, &clear_key_size,
+ verbose);
+ if (clear_key == NULL)
+ return -EINVAL;
+
+ pr_verbose(verbose, "Generate key on card %02x.%04x", card, domain);
+
+ clr2sec.cardnr = card;
+ clr2sec.domain = domain;
+ switch (HALF_KEYSIZE_FOR_XTS(clear_key_size * 8, xts)) {
+ case 128:
+ clr2sec.keytype = PKEY_KEYTYPE_AES_128;
+ break;
+ case 192:
+ clr2sec.keytype = PKEY_KEYTYPE_AES_192;
+ break;
+ case 256:
+ clr2sec.keytype = PKEY_KEYTYPE_AES_256;
+ break;
+ default:
+ warnx("Invalid clear key size: '%lu' bytes", clear_key_size);
+ rc = -EINVAL;
+ goto out;
+ }
+
+ memcpy(&clr2sec.clrkey, clear_key,
+ HALF_KEYSIZE_FOR_XTS(clear_key_size, xts));
+
+ rc = ioctl(pkey_fd, PKEY_CLR2SECK, &clr2sec);
+ if (rc < 0) {
+ rc = -errno;
+ warnx("Failed to generate a secure key from a "
+ "clear key: %s", strerror(errno));
+ goto out;
+ }
+
+ memcpy(secure_key, &clr2sec.seckey, SECURE_KEY_SIZE);
+
+ if (xts) {
+ memcpy(&clr2sec.clrkey, clear_key + clear_key_size / 2,
+ clear_key_size / 2);
+
+ rc = ioctl(pkey_fd, PKEY_CLR2SECK, &clr2sec);
+ if (rc < 0) {
+ rc = -errno;
+ warnx("Failed to generate a secure key from "
+ "a clear key: %s", strerror(errno));
+ goto out;
+ }
+
+ memcpy(secure_key+SECURE_KEY_SIZE, &clr2sec.seckey,
+ SECURE_KEY_SIZE);
+ }
+
+ pr_verbose(verbose,
+ "Successfully generated a secure key from a clear key");
+
+ rc = write_secure_key(keyfile, secure_key, secure_key_size, verbose);
+
+out:
+ memset(&clr2sec, 0, sizeof(clr2sec));
+ memset(clear_key, 0, clear_key_size);
+ free(clear_key);
+ free(secure_key);
+ return rc;
+}
+
+/**
+ * Prints CCA return and reason code information for certain known CCA
+ * error situations.
+ *
+ * @param return_code the CCA return code
+ * @param reason_code the CCA reason code
+ */
+static void print_CCA_error(int return_code, int reason_code)
+{
+ switch (return_code) {
+ case 8:
+ switch (reason_code) {
+ case 48:
+ warnx("The secure key has a CCA master key "
+ "verification pattern that is not valid");
+ break;
+ }
+ break;
+ case 12:
+ switch (reason_code) {
+ case 764:
+ warnx("The CCA master key is not loaded and "
+ "therefore a secure key cannot be enciphered");
+ break;
+ }
+ break;
+ }
+}
+
+/**
+ * Re-enciphers a secure key.
+ *
+ * @param[in] dll_CSNBKTC the address of the CCA CSNBKTC function
+ * @param[in] secure_key a buffer containing the secure key
+ * @param[in] secure_key_size the size of the secure key
+ * @param[in] method the re-enciphering method. METHOD_OLD_TO_CURRENT
+ * or METHOD_CURRENT_TO_NEW.
+ * @param[in] verbose if true, verbose messages are printed
+ *
+ * @returns 0 on success, -EIO in case of an error
+ */
+int key_token_change(t_CSNBKTC dll_CSNBKTC,
+ u8 *secure_key, unsigned int secure_key_size,
+ char *method, bool verbose)
+{
+ long exit_data_len = 0, rule_array_count;
+ unsigned char rule_array[2 * 80] = { 0, };
+ unsigned char exit_data[4] = { 0, };
+ long return_code, reason_code;
+
+ util_assert(dll_CSNBKTC != NULL, "Internal error: dll_CSNBKTC is NULL");
+ util_assert(secure_key != NULL, "Internal error: secure_key is NULL");
+ util_assert(secure_key_size > 0,
+ "Internal error: secure_key_size is 0");
+ util_assert(method != NULL, "Internal error: method is NULL");
+
+ memcpy(rule_array, method, 8);
+ memcpy(rule_array + 8, "AES ", 8);
+ rule_array_count = 2;
+
+ dll_CSNBKTC(&return_code, &reason_code,
+ &exit_data_len, exit_data,
+ &rule_array_count, rule_array,
+ secure_key);
+
+ pr_verbose(verbose, "CSNBKTC (Key Token Change) with '%s' returned: "
+ "return_code: %ld, reason_code: %ld", method, return_code,
+ reason_code);
+ if (return_code != 0) {
+ print_CCA_error(return_code, reason_code);
+ return -EIO;
+ }
+
+ if (secure_key_size == 2 * SECURE_KEY_SIZE) {
+ dll_CSNBKTC(&return_code, &reason_code,
+ &exit_data_len, exit_data,
+ &rule_array_count, rule_array,
+ secure_key + SECURE_KEY_SIZE);
+
+ pr_verbose(verbose, "CSNBKTC (Key Token Change) with '%s' "
+ "returned: return_code: %ld, reason_code: %ld",
+ method, return_code, reason_code);
+ if (return_code != 0) {
+ print_CCA_error(return_code, reason_code);
+ return -EIO;
+ }
+ }
+ return 0;
+}
+
+/**
+ * Validates an XTS secure key (the second part)
+ *
+ * @param[in] pkey_fd the pkey file descriptor
+ * @param[in] secure_key a buffer containing the secure key
+ * @param[in] secure_key_size the secure key size
+ * @param[in] part1_keysize the key size of the first key part
+ * @param[in] part1_attributes the attributes of the first key part
+ * @param[out] clear_key_bitsize on return , the cryptographic size of the
+ * clear key
+ * @param[in] verbose if true, verbose messages are printed
+ *
+ * @returns 0 on success, a negative errno in case of an error
+ */
+static int validate_secure_xts_key(int pkey_fd,
+ u8 *secure_key, size_t secure_key_size,
+ u16 part1_keysize, u32 part1_attributes,
+ size_t *clear_key_bitsize, bool verbose)
+{
+ struct secaeskeytoken *token = (struct secaeskeytoken *)secure_key;
+ struct pkey_verifykey verifykey;
+ struct secaeskeytoken *token2;
+ int rc;
+
+ util_assert(pkey_fd != -1, "Internal error: pkey_fd is -1");
+ util_assert(secure_key != NULL, "Internal error: secure_key is NULL");
+
+ /* XTS uses 2 secure key tokens concatenated to each other */
+ token2 = (struct secaeskeytoken *)(secure_key + SECURE_KEY_SIZE);
+
+ if (secure_key_size != 2 * SECURE_KEY_SIZE) {
+ pr_verbose(verbose, "Size of secure key is too small: "
+ "%lu expected %lu", secure_key_size,
+ 2 * SECURE_KEY_SIZE);
+ return -EINVAL;
+ }
+
+ if (token->bitsize != token2->bitsize) {
+ pr_verbose(verbose, "XTS secure key contains 2 clear keys of "
+ "different sizes");
+ return -EINVAL;
+ }
+ if (token->keysize != token2->keysize) {
+ pr_verbose(verbose, "XTS secure key contains 2 keys of "
+ "different sizes");
+ return -EINVAL;
+ }
+ if (memcmp(&token->mkvp, &token2->mkvp, sizeof(token->mkvp)) != 0) {
+ pr_verbose(verbose, "XTS secure key contains 2 keys using "
+ "different CCA master keys");
+ return -EINVAL;
+ }
+
+ memcpy(&verifykey.seckey, token2, sizeof(verifykey.seckey));
+
+ rc = ioctl(pkey_fd, PKEY_VERIFYKEY, &verifykey);
+ if (rc < 0) {
+ rc = -errno;
+ pr_verbose(verbose, "Failed to validate a secure key: %s",
+ strerror(-rc));
+ return rc;
+ }
+
+ if ((verifykey.attributes & PKEY_VERIFY_ATTR_AES) == 0) {
+ pr_verbose(verbose, "Secure key is not an AES key");
+ return -EINVAL;
+ }
+
+ if (verifykey.keysize != part1_keysize) {
+ pr_verbose(verbose, "XTS secure key contains 2 keys using "
+ "different key sizes");
+ return -EINVAL;
+ }
+
+ if (verifykey.attributes != part1_attributes) {
+ pr_verbose(verbose, "XTS secure key contains 2 keys using "
+ "different attributes");
+ return -EINVAL;
+ }
+
+ if (clear_key_bitsize)
+ *clear_key_bitsize += verifykey.keysize;
+
+ return 0;
+}
+
+/**
+ * Validates a secure key
+ *
+ * @param[in] pkey_fd the pkey file descriptor
+ * @param[in] secure_key a buffer containing the secure key
+ * @param[in] secure_key_size the secure key size
+ * @param[out] clear_key_bitsize on return , the cryptographic size of the
+ * clear key
+ * @param[out] is_old_mk in return set to 1 to indicate if the secure key
+ * is currently enciphered by the OLD CCA master key
+ * @param[in] verbose if true, verbose messages are printed
+ *
+ * @returns 0 on success, a negative errno in case of an error
+ */
+int validate_secure_key(int pkey_fd,
+ u8 *secure_key, size_t secure_key_size,
+ size_t *clear_key_bitsize, int *is_old_mk,
+ bool verbose)
+{
+ struct secaeskeytoken *token = (struct secaeskeytoken *)secure_key;
+ struct pkey_verifykey verifykey;
+ int rc;
+
+ util_assert(pkey_fd != -1, "Internal error: pkey_fd is -1");
+ util_assert(secure_key != NULL, "Internal error: secure_key is NULL");
+
+ if (secure_key_size < SECURE_KEY_SIZE) {
+ pr_verbose(verbose, "Size of secure key is too small: "
+ "%lu expected %lu", secure_key_size,
+ SECURE_KEY_SIZE);
+ return -EINVAL;
+ }
+
+ memcpy(&verifykey.seckey, token, sizeof(verifykey.seckey));
+
+ rc = ioctl(pkey_fd, PKEY_VERIFYKEY, &verifykey);
+ if (rc < 0) {
+ rc = -errno;
+ pr_verbose(verbose, "Failed to validate a secure key: %s",
+ strerror(-rc));
+ return rc;
+ }
+
+ if ((verifykey.attributes & PKEY_VERIFY_ATTR_AES) == 0) {
+ pr_verbose(verbose, "Secure key is not an AES key");
+ return -EINVAL;
+ }
+
+ if (clear_key_bitsize)
+ *clear_key_bitsize = verifykey.keysize;
+
+ /* XTS uses 2 secure key tokens concatenated to each other */
+ if (secure_key_size > SECURE_KEY_SIZE) {
+ rc = validate_secure_xts_key(pkey_fd,
+ secure_key, secure_key_size,
+ verifykey.keysize,
+ verifykey.attributes,
+ clear_key_bitsize,
+ verbose);
+ if (rc != 0)
+ return rc;
+ }
+
+ if (is_old_mk)
+ *is_old_mk = (verifykey.attributes &
+ PKEY_VERIFY_ATTR_OLD_MKVP) != 0;
+
+ pr_verbose(verbose, "Secure key validation completed successfully");
+
+ return 0;
+}
--- a/zkey/pkey.h
+++ b/zkey/pkey.h
@@ -4,7 +4,7 @@
* This header file defines the interface to the pkey kernel module.
* It defines a set of IOCTL commands with its associated structures.
*
- * Copyright 2017 IBM Corp.
+ * Copyright IBM Corp. 2017, 2018
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
@@ -82,4 +82,44 @@ struct pkey_verifykey {
#define PKEY_VERIFYKEY _IOWR(PKEY_IOCTL_MAGIC, 0x07, struct pkey_verifykey)
-#endif
\ No newline at end of file
+#define METHOD_OLD_TO_CURRENT "RTCMK "
+#define METHOD_CURRENT_TO_NEW "RTNMK "
+
+typedef void (*t_CSNBKTC)(long *return_code,
+ long *reason_code,
+ long *exit_data_length,
+ unsigned char *exit_data,
+ long *rule_array_count,
+ unsigned char *rule_array,
+ unsigned char *key_identifier);
+
+int load_cca_library(void **lib_csulcca, t_CSNBKTC *dll_CSNBKTC, bool verbose);
+
+int open_pkey_device(bool verbose);
+
+int generate_secure_key_random(int pkey_fd, const char *keyfile,
+ size_t keybits, bool xts, u16 card, u16 domain,
+ bool verbose);
+
+int generate_secure_key_clear(int pkey_fd, const char *keyfile,
+ size_t keybits, bool xts,
+ const char *clearkeyfile,
+ u16 card, u16 domain,
+ bool verbose);
+
+u8 *read_secure_key(const char *keyfile, size_t *secure_key_size,
+ bool verbose);
+
+int write_secure_key(const char *keyfile, const u8 *secure_key,
+ size_t secure_key_size, bool verbose);
+
+int validate_secure_key(int pkey_fd,
+ u8 *secure_key, size_t secure_key_size,
+ size_t *clear_key_bitsize, int *is_old_mk,
+ bool verbose);
+
+int key_token_change(t_CSNBKTC dll_CSNBKTC,
+ u8 *secure_key, unsigned int secure_key_size,
+ char *method, bool verbose);
+
+#endif
--- a/zkey/zkey.c
+++ b/zkey/zkey.c
@@ -188,9 +188,6 @@ static struct zkey_command zkey_commands
#define pr_verbose(fmt...) if (g.verbose) \
warnx(fmt)
-#define DOUBLE_KEYSIZE_FOR_XTS(keysize, xts) (xts) ? 2 * (keysize) : (keysize)
-#define HALF_KEYSIZE_FOR_XTS(keysize, xts) (xts) ? (keysize) / 2 : (keysize)
-
static void print_usage_command(const struct zkey_command *command)
{
char command_str[ZKEY_COMMAND_STR_LEN];
@@ -253,19 +250,6 @@ static void print_help(const struct zkey
}
/*
- * Definitions for the CCA library
- */
-#define CCA_LIBRARY_NAME "libcsulcca.so"
-
-typedef void (*t_CSNBKTC)(long *return_code,
- long *reason_code,
- long *exit_data_length,
- unsigned char *exit_data,
- long *rule_array_count,
- unsigned char *rule_array,
- unsigned char *key_identifier);
-
-/*
* Global variables for program options
*/
static struct zkey_globals {
@@ -283,212 +267,6 @@ static struct zkey_globals {
.pkey_fd = -1,
};
-#define DEFAULT_KEYBITS 256
-
-static int load_cca_library(void)
-{
- /* Load the CCA library */
- g.lib_csulcca = dlopen(CCA_LIBRARY_NAME, RTLD_GLOBAL | RTLD_NOW);
- if (g.lib_csulcca == NULL) {
- warnx("%s\nEnsure that the IBM CCA Host Libraries and "
- "Tools are installed properly", dlerror());
- return EXIT_FAILURE;
- }
-
- /* Get the Key Token Change function */
- g.dll_CSNBKTC = (t_CSNBKTC)dlsym(g.lib_csulcca, "CSNBKTC");
- if (g.dll_CSNBKTC == NULL) {
- warnx("%s\nEnsure that the IBM CCA Host Libraries and "
- "Tools are installed properly", dlerror());
- dlclose(g.lib_csulcca);
- g.lib_csulcca = NULL;
- return EXIT_FAILURE;
- }
-
- pr_verbose("CCA library '%s' has been loaded successfully",
- CCA_LIBRARY_NAME);
-
- return EXIT_SUCCESS;
-}
-
-static int open_pkey_device(void)
-{
- g.pkey_fd = open(PKEYDEVICE, O_RDWR);
- if (g.pkey_fd < 0) {
- warnx("File '%s:' %s\nEnsure that the 'pkey' kernel module "
- "is loaded", PKEYDEVICE, strerror(errno));
- return EXIT_FAILURE;
- }
-
- pr_verbose("Device '%s' has been opened successfully", PKEYDEVICE);
-
- return EXIT_SUCCESS;
-}
-
-/*
- * Read a secure key file and return the allocated buffer and size
- */
-static u8 *read_secure_key(const char *keyfile, size_t *secure_key_size)
-{
- size_t count, size;
- struct stat sb;
- char *msg;
- FILE *fp;
- u8 *buf;
-
- if (stat(keyfile, &sb)) {
- warnx("File '%s': %s", keyfile, strerror(errno));
- return NULL;
- }
- size = sb.st_size;
-
- if (size != SECURE_KEY_SIZE && size != 2*SECURE_KEY_SIZE) {
- warnx("File '%s' has an invalid size, %lu or %lu bytes "
- "expected", keyfile, SECURE_KEY_SIZE,
- 2 * SECURE_KEY_SIZE);
- return NULL;
- }
-
- fp = fopen(keyfile, "r");
- if (fp == NULL) {
- warnx("File '%s': %s", keyfile, strerror(errno));
- return NULL;
- }
-
- buf = util_malloc(size);
- count = fread(buf, 1, size, fp);
- if (count <= 0) {
- msg = feof(fp) ? "File is too small" : strerror(errno);
- warnx("File '%s': %s", keyfile, msg);
- free(buf);
- buf = NULL;
- goto out;
- }
-
- *secure_key_size = size;
-
- if (g.verbose) {
- pr_verbose("%lu bytes read from file '%s'", size, keyfile);
- util_hexdump_grp(stderr, NULL, buf, 4, size, 0);
- }
-out:
- fclose(fp);
- return buf;
-}
-
-/*
- * Write a secure key file
- */
-static int write_secure_key(const char *keyfile, const u8 *secure_key,
- size_t secure_key_size)
-{
- size_t count;
- FILE *fp;
-
- fp = fopen(keyfile, "w");
- if (fp == NULL) {
- warnx("File '%s': %s", keyfile, strerror(errno));
- return EXIT_FAILURE;
- }
-
- count = fwrite(secure_key, 1, secure_key_size, fp);
- if (count <= 0) {
- warnx("File '%s': %s", keyfile, strerror(errno));
- fclose(fp);
- return EXIT_FAILURE;
- }
-
- if (g.verbose) {
- pr_verbose("%lu bytes written to file '%s'",
- secure_key_size, keyfile);
- util_hexdump_grp(stderr, NULL, secure_key, 4,
- secure_key_size, 0);
- }
- fclose(fp);
- return EXIT_SUCCESS;
-}
-
-/*
- * Read a clear key file and return the allocated buffer and size
- *
- * When keybits is 0, then the file size determines the keybits.
- */
-static u8 *read_clear_key(const char *keyfile, size_t keybits,
- size_t *clear_key_size)
-{
- size_t count, size, expected_size;
- struct stat sb;
- char *msg;
- FILE *fp;
- u8 *buf;
-
- if (stat(keyfile, &sb)) {
- warnx("File '%s': %s", keyfile, strerror(errno));
- return NULL;
- }
- size = sb.st_size;
-
- if (keybits != 0) {
- expected_size = DOUBLE_KEYSIZE_FOR_XTS(keybits / 8, g.xts);
- if (size != expected_size) {
- warnx("File '%s' has an invalid size, "
- "%lu bytes expected", keyfile, expected_size);
- return NULL;
- }
- } else {
- keybits = DOUBLE_KEYSIZE_FOR_XTS(size * 8, g.xts);
- }
-
- switch (keybits) {
- case 128:
- break;
- case 192:
- if (g.xts) {
- warnx("File '%s' has an invalid size, "
- "192 bit keys are not supported with XTS",
- keyfile);
- return NULL;
- }
- break;
- case 256:
- break;
- default:
- if (g.xts)
- warnx("File '%s' has an invalid size, "
- "32 or 64 bytes expected", keyfile);
- else
- warnx("File '%s' has an invalid size, 16, 24 "
- "or 32 bytes expected", keyfile);
- return NULL;
- }
-
- fp = fopen(keyfile, "r");
- if (fp == NULL) {
- warnx("File '%s': %s", keyfile, strerror(errno));
- return NULL;
- }
-
- buf = util_malloc(size);
- count = fread(buf, 1, size ,fp);
- if (count <= 0) {
- msg = feof(fp) ? "File is too small" : strerror(errno);
- warnx("File '%s': %s", keyfile, msg);
- free(buf);
- buf = NULL;
- goto out;
- }
-
- *clear_key_size = size;
-
- if (g.verbose) {
- pr_verbose("%lu bytes read from file '%s'", size, keyfile);
- util_hexdump_grp(stderr, NULL, buf, 4, size, 0);
- }
-out:
- fclose(fp);
- return buf;
-}
-
/*
* Command handler for 'generate with clear key'
*
@@ -496,76 +274,15 @@ out:
*/
static int command_generate_clear(const char *keyfile)
{
- struct pkey_clr2seck clr2sec;
- size_t secure_key_size;
- size_t clear_key_size;
- u8 *secure_key;
- u8 *clear_key;
int rc;
- secure_key_size = DOUBLE_KEYSIZE_FOR_XTS(SECURE_KEY_SIZE, g.xts);
- secure_key = util_malloc(secure_key_size);
-
- clear_key = read_clear_key(g.clearkeyfile, g.keybits, &clear_key_size);
- if (clear_key == NULL)
- return EXIT_FAILURE;
-
- clr2sec.cardnr = AUTOSELECT;
- clr2sec.domain = AUTOSELECT;
- switch (HALF_KEYSIZE_FOR_XTS(clear_key_size * 8, g.xts)) {
- case 128:
- clr2sec.keytype = PKEY_KEYTYPE_AES_128;
- break;
- case 192:
- clr2sec.keytype = PKEY_KEYTYPE_AES_192;
- break;
- case 256:
- clr2sec.keytype = PKEY_KEYTYPE_AES_256;
- break;
- default:
- warnx("Invalid clear key size: '%lu' bytes", clear_key_size);
- rc = EXIT_FAILURE;
- goto out;
- }
-
- memcpy(&clr2sec.clrkey, clear_key,
- HALF_KEYSIZE_FOR_XTS(clear_key_size, g.xts));
-
- rc = ioctl(g.pkey_fd, PKEY_CLR2SECK, &clr2sec);
- if (rc < 0) {
- warnx("Failed to generate a secure key from a "
- "clear key: %s", strerror(errno));
+ rc = generate_secure_key_clear(g.pkey_fd, keyfile,
+ g.keybits, g.xts,
+ g.clearkeyfile,
+ AUTOSELECT, AUTOSELECT,
+ g.verbose);
+ if (rc != 0)
rc = EXIT_FAILURE;
- goto out;
- }
-
- memcpy(secure_key, &clr2sec.seckey, SECURE_KEY_SIZE);
-
- if (g.xts) {
- memcpy(&clr2sec.clrkey, clear_key + clear_key_size / 2,
- clear_key_size / 2);
-
- rc = ioctl(g.pkey_fd, PKEY_CLR2SECK, &clr2sec);
- if (rc < 0) {
- warnx("Failed to generate a secure key from "
- "a clear key: %s", strerror(errno));
- rc = EXIT_FAILURE;
- goto out;
- }
-
- memcpy(secure_key+SECURE_KEY_SIZE, &clr2sec.seckey,
- SECURE_KEY_SIZE);
- }
-
- pr_verbose("Successfully generated a secure key from a clear key");
-
- rc = write_secure_key(keyfile, secure_key, secure_key_size);
-
-out:
- memset(&clr2sec, 0, sizeof(clr2sec));
- memset(clear_key, 0, clear_key_size);
- free(clear_key);
- free(secure_key);
return rc;
}
@@ -576,69 +293,15 @@ out:
*/
static int command_generate_random(const char *keyfile)
{
- struct pkey_genseck gensec;
- size_t secure_key_size;
- u8 *secure_key;
int rc;
- if (g.keybits == 0)
- g.keybits = DEFAULT_KEYBITS;
-
- secure_key_size = DOUBLE_KEYSIZE_FOR_XTS(SECURE_KEY_SIZE, g.xts);
- secure_key = util_malloc(secure_key_size);
-
- gensec.cardnr = AUTOSELECT;
- gensec.domain = AUTOSELECT;
- switch (g.keybits) {
- case 128:
- gensec.keytype = PKEY_KEYTYPE_AES_128;
- break;
- case 192:
- if (g.xts) {
- warnx("Invalid value for '--keybits'|'-c' "
- "for XTS: '%lu'", g.keybits);
- rc = EXIT_FAILURE;
- goto out;
- }
- gensec.keytype = PKEY_KEYTYPE_AES_192;
- break;
- case 256:
- gensec.keytype = PKEY_KEYTYPE_AES_256;
- break;
- default:
- warnx("Invalid value for '--keybits'/'-c': '%lu'", g.keybits);
+ rc = generate_secure_key_random(g.pkey_fd, keyfile,
+ g.keybits, g.xts,
+ AUTOSELECT, AUTOSELECT,
+ g.verbose);
+ if (rc != 0)
rc = EXIT_FAILURE;
- goto out;
- }
-
- rc = ioctl(g.pkey_fd, PKEY_GENSECK, &gensec);
- if (rc < 0) {
- warnx("Failed to generate a secure key: %s", strerror(errno));
- rc = EXIT_FAILURE;
- goto out;
- }
-
- memcpy(secure_key, &gensec.seckey, SECURE_KEY_SIZE);
-
- if (g.xts) {
- rc = ioctl(g.pkey_fd, PKEY_GENSECK, &gensec);
- if (rc < 0) {
- warnx("Failed to generate a secure key: %s",
- strerror(errno));
- rc = EXIT_FAILURE;
- goto out;
- }
-
- memcpy(secure_key + SECURE_KEY_SIZE, &gensec.seckey,
- SECURE_KEY_SIZE);
- }
-
- pr_verbose("Successfully generated a secure key");
- rc = write_secure_key(keyfile, secure_key, secure_key_size);
-
-out:
- free(secure_key);
return rc;
}
@@ -653,182 +316,6 @@ static int command_generate(const char *
: command_generate_random(keyfile);
}
-static void print_CCA_error(int return_code, int reason_code)
-{
- switch (return_code) {
- case 8:
- switch (reason_code) {
- case 48:
- warnx("The secure key has a CCA master key "
- "verification pattern that is not valid");
- break;
- }
- break;
- case 12:
- switch (reason_code) {
- case 764:
- warnx("The CCA master key is not loaded and "
- "therefore a secure key cannot be enciphered");
- break;
- }
- break;
- }
-}
-
-static int key_token_change(u8 *secure_key, unsigned int secure_key_size,
- char *method)
-{
- long exit_data_len = 0, rule_array_count;
- unsigned char rule_array[2 * 80] = { 0, };
- unsigned char exit_data[4] = { 0, };
- long return_code, reason_code;
-
- memcpy(rule_array, method, 8);
- memcpy(rule_array + 8, "AES ", 8);
- rule_array_count = 2;
-
- g.dll_CSNBKTC(&return_code, &reason_code,
- &exit_data_len, exit_data,
- &rule_array_count, rule_array,
- secure_key);
-
- pr_verbose("CSNBKTC (Key Token Change) with '%s' returned: "
- "return_code: %ld, reason_code: %ld",
- method, return_code, reason_code);
- if (return_code != 0) {
- print_CCA_error(return_code, reason_code);
- return EXIT_FAILURE;
- }
-
- if (secure_key_size == 2 * SECURE_KEY_SIZE) {
- g.dll_CSNBKTC(&return_code, &reason_code,
- &exit_data_len, exit_data,
- &rule_array_count, rule_array,
- secure_key + SECURE_KEY_SIZE);
-
- pr_verbose("CSNBKTC (Key Token Change) with '%s' "
- "returned: return_code: %ld, reason_code: %ld",
- method, return_code, reason_code);
- if (return_code != 0) {
- print_CCA_error(return_code, reason_code);
- return EXIT_FAILURE;
- }
- }
- return EXIT_SUCCESS;
-}
-
-static int validate_secure_xts_key(u8 *secure_key, size_t secure_key_size,
- u16 part1_keysize, u32 part1_attributes,
- size_t *clear_key_bitsize)
-{
- struct secaeskeytoken *token = (struct secaeskeytoken *)secure_key;
- struct pkey_verifykey verifykey;
- struct secaeskeytoken *token2;
- int rc;
-
- /* XTS uses 2 secure key tokens concatenated to each other */
- token2 = (struct secaeskeytoken *)(secure_key + SECURE_KEY_SIZE);
-
- if (secure_key_size != 2 * SECURE_KEY_SIZE) {
- pr_verbose("Size of secure key is too small: %lu expected %lu",
- secure_key_size, 2 * SECURE_KEY_SIZE);
- return EXIT_FAILURE;
- }
-
- if (token->bitsize != token2->bitsize) {
- pr_verbose("XTS secure key contains 2 clear keys of "
- "different sizes");
- return EXIT_FAILURE;
- }
- if (token->keysize != token2->keysize) {
- pr_verbose("XTS secure key contains 2 keys of different "
- "sizes");
- return EXIT_FAILURE;
- }
- if (memcmp(&token->mkvp, &token2->mkvp, sizeof(token->mkvp)) != 0) {
- pr_verbose("XTS secure key contains 2 keys using different "
- "CCA master keys");
- return EXIT_FAILURE;
- }
-
- memcpy(&verifykey.seckey, token2, sizeof(verifykey.seckey));
-
- rc = ioctl(g.pkey_fd, PKEY_VERIFYKEY, &verifykey);
- if (rc < 0) {
- warnx("Failed to validate a secure key: %s", strerror(errno));
- return EXIT_FAILURE;
- }
-
- if ((verifykey.attributes & PKEY_VERIFY_ATTR_AES) == 0) {
- pr_verbose("Secure key is not an AES key");
- return EXIT_FAILURE;
- }
-
- if (verifykey.keysize != part1_keysize) {
- pr_verbose("XTS secure key contains 2 keys using different "
- "key sizes");
- return EXIT_FAILURE;
- }
-
- if (verifykey.attributes != part1_attributes) {
- pr_verbose("XTS secure key contains 2 keys using different "
- "attributes");
- return EXIT_FAILURE;
- }
-
- if (clear_key_bitsize)
- *clear_key_bitsize += verifykey.keysize;
-
- return EXIT_SUCCESS;
-}
-
-static int validate_secure_key(u8 *secure_key, size_t secure_key_size,
- size_t *clear_key_bitsize, int *is_old_mk)
-{
- struct secaeskeytoken *token = (struct secaeskeytoken *)secure_key;
- struct pkey_verifykey verifykey;
- int rc;
-
- if (secure_key_size < SECURE_KEY_SIZE) {
- pr_verbose("Size of secure key is too small: %lu expected %lu",
- secure_key_size, SECURE_KEY_SIZE);
- return EXIT_FAILURE;
- }
-
- memcpy(&verifykey.seckey, token, sizeof(verifykey.seckey));
-
- rc = ioctl(g.pkey_fd, PKEY_VERIFYKEY, &verifykey);
- if (rc < 0) {
- warnx("Failed to validate a secure key: %s", strerror(errno));
- return EXIT_FAILURE;
- }
-
- if ((verifykey.attributes & PKEY_VERIFY_ATTR_AES) == 0) {
- pr_verbose("Secure key is not an AES key");
- return EXIT_FAILURE;
- }
-
- if (clear_key_bitsize)
- *clear_key_bitsize = verifykey.keysize;
-
- /* XTS uses 2 secure key tokens concatenated to each other */
- if (secure_key_size > SECURE_KEY_SIZE) {
- rc = validate_secure_xts_key(secure_key, secure_key_size,
- verifykey.keysize,
- verifykey.attributes,
- clear_key_bitsize);
- if (rc != EXIT_SUCCESS)
- return rc;
- }
-
- if (is_old_mk)
- *is_old_mk = (verifykey.attributes &
- PKEY_VERIFY_ATTR_OLD_MKVP) != 0;
-
- pr_verbose("Secure key validation completed successfully");
-
- return EXIT_SUCCESS;
-}
/*
* Command handler for 'reencipher'.
@@ -842,14 +329,15 @@ static int command_reencipher(const char
u8 *secure_key;
/* Read the secure key to be re-enciphered */
- secure_key = read_secure_key(keyfile, &secure_key_size);
+ secure_key = read_secure_key(keyfile, &secure_key_size, g.verbose);
if (secure_key == NULL)
return EXIT_FAILURE;
- rc = validate_secure_key(secure_key, secure_key_size, NULL,
- &is_old_mk);
- if (rc != EXIT_SUCCESS) {
+ rc = validate_secure_key(g.pkey_fd, secure_key, secure_key_size, NULL,
+ &is_old_mk, g.verbose);
+ if (rc != 0) {
warnx("The secure key in file '%s' is not valid", keyfile);
+ rc = EXIT_FAILURE;
goto out;
}
@@ -884,10 +372,14 @@ static int command_reencipher(const char
pr_verbose("Secure key will be re-enciphered from OLD to the "
"CURRENT CCA master key");
- rc = key_token_change(secure_key, secure_key_size, "RTCMK ");
- if (rc != EXIT_SUCCESS) {
+ rc = key_token_change(g.dll_CSNBKTC,
+ secure_key, secure_key_size,
+ METHOD_OLD_TO_CURRENT,
+ g.verbose);
+ if (rc != 0) {
warnx("Re-encipher from OLD to CURRENT CCA "
"master key has failed");
+ rc = EXIT_FAILURE;
goto out;
}
}
@@ -895,10 +387,13 @@ static int command_reencipher(const char
pr_verbose("Secure key will be re-enciphered from CURRENT "
"to the NEW CCA master key");
- rc = key_token_change(secure_key, secure_key_size, "RTNMK ");
- if (rc != EXIT_SUCCESS) {
+ rc = key_token_change(g.dll_CSNBKTC,
+ secure_key, secure_key_size,
+ METHOD_CURRENT_TO_NEW, g.verbose);
+ if (rc != 0) {
warnx("Re-encipher from CURRENT to NEW CCA "
"master key has failed");
+ rc = EXIT_FAILURE;
goto out;
}
}
@@ -907,7 +402,9 @@ static int command_reencipher(const char
/* Write the migrated secure key */
rc = write_secure_key(g.outputfile ? g.outputfile : keyfile,
- secure_key, secure_key_size);
+ secure_key, secure_key_size, g.verbose);
+ if (rc != 0)
+ rc = EXIT_FAILURE;
out:
free(secure_key);
return rc;
@@ -927,14 +424,15 @@ static int command_validate(const char *
int rc;
/* Read the secure key to be re-enciphered */
- secure_key = read_secure_key(keyfile, &secure_key_size);
+ secure_key = read_secure_key(keyfile, &secure_key_size, g.verbose);
if (secure_key == NULL)
return EXIT_FAILURE;
- rc = validate_secure_key(secure_key, secure_key_size, &clear_key_size,
- &is_old_mk);
- if (rc != EXIT_SUCCESS) {
+ rc = validate_secure_key(g.pkey_fd, secure_key, secure_key_size,
+ &clear_key_size, &is_old_mk, g.verbose);
+ if (rc != 0) {
warnx("The secure key in file '%s' is not valid", keyfile);
+ rc = EXIT_FAILURE;
goto out;
}
@@ -1083,13 +581,14 @@ int main(int argc, char *argv[])
}
if (command->need_cca_library) {
- rc = load_cca_library();
- if (rc != EXIT_SUCCESS)
+ rc = load_cca_library(&g.lib_csulcca, &g.dll_CSNBKTC,
+ g.verbose);
+ if (rc != 0)
goto out;
}
if (command->need_pkey_device) {
- rc = open_pkey_device();
- if (rc != EXIT_SUCCESS)
+ g.pkey_fd = open_pkey_device(g.verbose);
+ if (g.pkey_fd == -1)
goto out;
}