diff --git a/zkey/keystore.c b/zkey/keystore.c index 9589d82d..771bc08d 100644 --- a/zkey/keystore.c +++ b/zkey/keystore.c @@ -3,7 +3,7 @@ * * Keystore handling functions * - * Copyright IBM Corp. 2018, 2020 + * Copyright IBM Corp. 2018, 2024 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. @@ -360,6 +360,8 @@ static int _keystore_valid_key_type(const char *key_type) return 1; if (strcasecmp(key_type, KEY_TYPE_EP11_AES) == 0) return 1; + if (strcasecmp(key_type, KEY_TYPE_PVSECRET_AES) == 0) + return 1; return 0; } diff --git a/zkey/pkey.c b/zkey/pkey.c index 821978bd..53c0a550 100644 --- a/zkey/pkey.c +++ b/zkey/pkey.c @@ -1,7 +1,7 @@ /* * zkey - Generate, re-encipher, and validate secure keys * - * Copyright IBM Corp. 2018 + * Copyright IBM Corp. 2018, 2024 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. @@ -26,6 +26,7 @@ #include "lib/util_panic.h" #include "pkey.h" +#include "pvsecrets.h" #include "utils.h" #ifndef AF_ALG @@ -1719,6 +1720,38 @@ bool is_ep11_key_session_bound(const u8 *key, size_t key_size) } } +/** + * Check if the specified key is a PVSECRET-AES key token. + * + * @param[in] key the secure key token + * @param[in] key_size the size of the secure key + * + * @returns true if the key is a PVSECRET token type + */ +bool is_pvsecret_aes_key(const u8 *key, size_t key_size) +{ + struct pvsecrettoken *pvsecret = (struct pvsecrettoken *)key; + + if (key == NULL || key_size < PVSECRET_KEY_SIZE) + return false; + + if (pvsecret->hdr.type != TOKEN_TYPE_NON_CCA) + return false; + if (pvsecret->hdr.version != TOKEN_VERSION_PVSECRET) + return false; + + switch (pvsecret->secret_type) { + case UV_SECRET_TYPE_AES_128: + case UV_SECRET_TYPE_AES_192: + case UV_SECRET_TYPE_AES_256: + case UV_SECRET_TYPE_AES_XTS_128: + case UV_SECRET_TYPE_AES_XTS_256: + return true; + default: + return false; + } +} + /** * Check if the specified key is an XTS type key * @@ -1729,6 +1762,8 @@ bool is_ep11_key_session_bound(const u8 *key, size_t key_size) */ bool is_xts_key(const u8 *key, size_t key_size) { + struct pvsecrettoken *pvsecret = (struct pvsecrettoken *)key; + if (is_cca_aes_data_key(key, key_size)) { if (key_size == 2 * AESDATA_KEY_SIZE && is_cca_aes_data_key(key + AESDATA_KEY_SIZE, @@ -1749,11 +1784,41 @@ bool is_xts_key(const u8 *key, size_t key_size) is_ep11_aes_key_with_header(key + EP11_AES_KEY_SIZE, key_size - EP11_AES_KEY_SIZE)) return true; + } else if (is_pvsecret_aes_key(key, key_size)) { + switch (pvsecret->secret_type) { + case UV_SECRET_TYPE_AES_XTS_128: + case UV_SECRET_TYPE_AES_XTS_256: + return true; + default: + return false; + } } return false; } +/** + * Check if the specified key is a secure key type (i.e. requires a crypto card) + * + * @param[in] key the secure key token + * @param[in] key_size the size of the secure key + * + * @returns true if the key is a secure key type + */ +bool is_secure_key(const u8 *key, size_t key_size) +{ + if (is_cca_aes_data_key(key, key_size)) + return true; + if (is_cca_aes_cipher_key(key, key_size)) + return true; + if (is_ep11_aes_key(key, key_size)) + return true; + if (is_ep11_aes_key_with_header(key, key_size)) + return true; + + return false; +} + /** * Gets the size in bits of the effective key of the specified secure key * @@ -1771,6 +1836,7 @@ int get_key_bit_size(const u8 *key, size_t key_size, size_t *bitsize) struct aescipherkeytoken *cipherkey = (struct aescipherkeytoken *)key; struct ep11keytoken *ep11key = (struct ep11keytoken *)key; struct ep11kblob_header *hdr = (struct ep11kblob_header *)key; + struct pvsecrettoken *pvsecret = (struct pvsecrettoken *)key; util_assert(bitsize != NULL, "Internal error: bitsize is NULL"); @@ -1805,6 +1871,26 @@ int get_key_bit_size(const u8 *key, size_t key_size, size_t *bitsize) (key + EP11_AES_KEY_SIZE); *bitsize += hdr->bitlen; } + } else if (is_pvsecret_aes_key(key, key_size)) { + switch (pvsecret->secret_type) { + case UV_SECRET_TYPE_AES_128: + *bitsize = 128; + break; + case UV_SECRET_TYPE_AES_192: + *bitsize = 192; + break; + case UV_SECRET_TYPE_AES_256: + *bitsize = 256; + break; + case UV_SECRET_TYPE_AES_XTS_128: + *bitsize = 128 * 2; + break; + case UV_SECRET_TYPE_AES_XTS_256: + *bitsize = 256 * 2; + break; + default: + return -EINVAL; + } } else { return -EINVAL; } @@ -1830,9 +1916,31 @@ const char *get_key_type(const u8 *key, size_t key_size) return KEY_TYPE_EP11_AES; if (is_ep11_aes_key_with_header(key, key_size)) return KEY_TYPE_EP11_AES; + if (is_pvsecret_aes_key(key, key_size)) + return KEY_TYPE_PVSECRET_AES; + return NULL; } +/** + * Returns true if the key type is a secure key type + * + * @param[in] key_type the type of the key + * + * @returns true if the key type is a secure key type, false otherwise + */ +bool is_secure_key_type(const char *key_type) +{ + if (strcasecmp(key_type, KEY_TYPE_CCA_AESCIPHER) == 0) + return true; + if (strcasecmp(key_type, KEY_TYPE_CCA_AESDATA) == 0) + return true; + if (strcasecmp(key_type, KEY_TYPE_EP11_AES) == 0) + return true; + + return false; +} + /** * Returns the minimum card level for a specific key type * diff --git a/zkey/pkey.h b/zkey/pkey.h index 3b57c5f0..ce3bd8bd 100644 --- 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 IBM Corp. 2017, 2018 + * Copyright IBM Corp. 2017, 2024 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. @@ -41,6 +41,8 @@ struct tokenheader { #define TOKEN_VERSION_EP11_AES 0x03 #define TOKEN_VERSION_EP11_AES_WITH_HEADER 0x06 #define TOKEN_VERSION_EP11_ECC_WITH_HEADER 0x07 +/* 0x08 is reserved for internal use */ +#define TOKEN_VERSION_PVSECRET 0x09 struct aesdatakeytoken { u8 type; /* TOKEN_TYPE_INTERNAL (0x01) for internal key token */ @@ -116,6 +118,15 @@ struct ep11keytoken { u8 padding[64]; } __packed; +#define UV_SECRET_ID_LEN 32 + +struct pvsecrettoken { + struct tokenheader hdr; + u16 secret_type; /* the secret type as the UV told us */ + u16 secret_len; /* length in bytes of the secret */ + u8 secretid[UV_SECRET_ID_LEN]; /* the secret id for this secret */ +} __packed; + #define ZERO_SESSION \ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" @@ -124,21 +135,26 @@ struct ep11keytoken { #define EP11_KEY_SIZE sizeof(struct ep11keytoken) #define EP11_AES_KEY_SIZE (sizeof(struct ep11kblob_header) + \ sizeof(struct ep11keytoken)) +#define PVSECRET_KEY_SIZE sizeof(struct pvsecrettoken) /* MAX/MIN from zt_common.h produces warnings for variable length arrays */ #define _MIN(a, b) ((a) < (b) ? (a) : (b)) #define _MAX(a, b) ((a) > (b) ? (a) : (b)) #define MAX_SECURE_KEY_SIZE _MAX( \ - _MAX(EP11_KEY_SIZE, \ - EP11_AES_KEY_SIZE), \ - _MAX(AESDATA_KEY_SIZE, \ - AESCIPHER_KEY_SIZE)) + _MAX( \ + _MAX(EP11_KEY_SIZE, \ + EP11_AES_KEY_SIZE), \ + _MAX(AESDATA_KEY_SIZE, \ + AESCIPHER_KEY_SIZE)), \ + PVSECRET_KEY_SIZE) #define MIN_SECURE_KEY_SIZE _MIN( \ - _MIN(EP11_KEY_SIZE, \ - EP11_AES_KEY_SIZE), \ - _MIN(AESDATA_KEY_SIZE, \ - AESCIPHER_KEY_SIZE)) + _MIN( \ + _MIN(EP11_KEY_SIZE, \ + EP11_AES_KEY_SIZE), \ + _MIN(AESDATA_KEY_SIZE, \ + AESCIPHER_KEY_SIZE)), \ + PVSECRET_KEY_SIZE) struct pkey_seckey { u8 seckey[AESDATA_KEY_SIZE]; /* the secure key blob */ @@ -285,6 +301,7 @@ struct pkey_apqns4keytype { #define KEY_TYPE_CCA_AESDATA "CCA-AESDATA" #define KEY_TYPE_CCA_AESCIPHER "CCA-AESCIPHER" #define KEY_TYPE_EP11_AES "EP11-AES" +#define KEY_TYPE_PVSECRET_AES "PVSECRET-AES" #define DEFAULT_KEYBITS 256 #define PAES_BLOCK_SIZE 16 @@ -342,9 +359,12 @@ bool is_cca_aes_cipher_key(const u8 *key, size_t key_size); bool is_ep11_aes_key(const u8 *key, size_t key_size); bool is_ep11_aes_key_with_header(const u8 *key, size_t key_size); bool is_ep11_key_session_bound(const u8 *key, size_t key_size); +bool is_pvsecret_aes_key(const u8 *key, size_t key_size); bool is_xts_key(const u8 *key, size_t key_size); +bool is_secure_key(const u8 *key, size_t key_size); int get_key_bit_size(const u8 *key, size_t key_size, size_t *bitsize); const char *get_key_type(const u8 *key, size_t key_size); +bool is_secure_key_type(const char *key_type); int get_min_card_level_for_keytype(const char *key_type); const struct fw_version *get_min_fw_version_for_keytype(const char *key_type); enum card_type get_card_type_for_keytype(const char *key_type); diff --git a/zkey/pvsecrets.h b/zkey/pvsecrets.h index 6acebfdd..ad844035 100644 --- a/zkey/pvsecrets.h +++ b/zkey/pvsecrets.h @@ -15,6 +15,8 @@ #include "lib/zt_common.h" +#include "pkey.h" + /* * Definitions for the /dev/uv kernel module interface */ @@ -60,8 +62,6 @@ struct uvio_ioctl_cb { #define UV_SECRET_TYPE_EDDSA_ED25519 0x14 #define UV_SECRET_TYPE_EDDSA_ED448 0x15 -#define UV_SECRET_ID_LEN 32 - #define UVIO_LIST_SECRETS_MAX_LEN 0x8000 struct uvio_list_secret_entry {