diff --git a/zkey/keystore.c b/zkey/keystore.c index eda2339c..f02cc6f4 100644 --- a/zkey/keystore.c +++ b/zkey/keystore.c @@ -343,6 +343,8 @@ static int _keystore_valid_key_type(const char *key_type) return 1; if (strcasecmp(key_type, KEY_TYPE_CCA_AESCIPHER) == 0) return 1; + if (strcasecmp(key_type, KEY_TYPE_EP11_AES) == 0) + return 1; return 0; } diff --git a/zkey/pkey.c b/zkey/pkey.c index 591152da..837ebfec 100644 --- a/zkey/pkey.c +++ b/zkey/pkey.c @@ -691,6 +691,10 @@ static int build_apqn_list_for_key_type(int pkey_fd, enum pkey_key_type type, apqn_entries, verbose); return rc; + case -EINVAL: + /* This is usually due to an unsupported key type */ + rc = -ENOTSUP; + goto out; default: goto out; } @@ -799,6 +803,10 @@ static int build_apqn_list_for_key(int pkey_fd, u8 *key, u32 keylen, u32 flags, apqn_entries, verbose); return rc; + case -EINVAL: + /* This is usually due to an unsupported key type */ + rc = -ENOTSUP; + goto out; default: goto out; } @@ -850,6 +858,8 @@ static enum pkey_key_type key_type_to_pkey_type(const char *key_type) return PKEY_TYPE_CCA_DATA; if (strcasecmp(key_type, KEY_TYPE_CCA_AESCIPHER) == 0) return PKEY_TYPE_CCA_CIPHER; + if (strcasecmp(key_type, KEY_TYPE_EP11_AES) == 0) + return PKEY_TYPE_EP11; return 0; } @@ -868,6 +878,8 @@ static size_t key_size_for_type(enum pkey_key_type type) return AESDATA_KEY_SIZE; case PKEY_TYPE_CCA_CIPHER: return AESCIPHER_KEY_SIZE; + case PKEY_TYPE_EP11: + return EP11_KEY_SIZE; default: return 0; } @@ -1227,6 +1239,7 @@ int validate_secure_key(int pkey_fd, struct pkey_apqn *list = NULL; u32 i, list_entries = 0; bool xts, valid; + u32 flags; int rc; util_assert(pkey_fd != -1, "Internal error: pkey_fd is -1"); @@ -1234,11 +1247,15 @@ int validate_secure_key(int pkey_fd, xts = is_xts_key(secure_key, secure_key_size); + flags = PKEY_FLAGS_MATCH_CUR_MKVP; + if (is_cca_aes_data_key(secure_key, secure_key_size) || + is_cca_aes_cipher_key(secure_key, secure_key_size)) + flags |= PKEY_FLAGS_MATCH_ALT_MKVP; + rc = build_apqn_list_for_key(pkey_fd, secure_key, HALF_KEYSIZE_FOR_XTS(secure_key_size, xts), - PKEY_FLAGS_MATCH_CUR_MKVP | - PKEY_FLAGS_MATCH_ALT_MKVP, - apqns, &list, &list_entries, verbose); + flags, apqns, &list, &list_entries, + verbose); if (rc != 0) { pr_verbose(verbose, "Failed to build a list of APQNs that can " "validate this secure key: %s", strerror(-rc)); @@ -1451,6 +1468,7 @@ int get_master_key_verification_pattern(const u8 *key, size_t key_size, { struct aesdatakeytoken *datakey = (struct aesdatakeytoken *)key; struct aescipherkeytoken *cipherkey = (struct aescipherkeytoken *)key; + struct ep11keytoken *ep11key = (struct ep11keytoken *)key; util_assert(key != NULL, "Internal error: secure_key is NULL"); util_assert(mkvp != NULL, "Internal error: mkvp is NULL"); @@ -1460,6 +1478,8 @@ int get_master_key_verification_pattern(const u8 *key, size_t key_size, memcpy(mkvp, &datakey->mkvp, sizeof(datakey->mkvp)); else if (is_cca_aes_cipher_key(key, key_size)) memcpy(mkvp, &cipherkey->kvp, sizeof(cipherkey->kvp)); + else if (is_ep11_aes_key(key, key_size)) + memcpy(mkvp, &ep11key->wkvp, sizeof(ep11key->wkvp)); else return -EINVAL; @@ -1539,6 +1559,34 @@ bool is_cca_aes_cipher_key(const u8 *key, size_t key_size) return true; } +/** + * Check if the specified key is a EP11 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 an EP11 AES token type + */ +bool is_ep11_aes_key(const u8 *key, size_t key_size) +{ + struct ep11keytoken *ep11key = (struct ep11keytoken *)key; + + if (key == NULL || key_size < EP11_KEY_SIZE) + return false; + + if (ep11key->head.type != TOKEN_TYPE_NON_CCA) + return false; + if (ep11key->head.version != TOKEN_VERSION_EP11_AES) + return false; + if (ep11key->head.length > key_size) + return false; + + if (ep11key->version != 0x1234) + return false; + + return true; +} + /** * Check if the specified key is an XTS type key * @@ -1559,6 +1607,11 @@ bool is_xts_key(const u8 *key, size_t key_size) is_cca_aes_cipher_key(key + AESCIPHER_KEY_SIZE, key_size - AESCIPHER_KEY_SIZE)) return true; + } else if (is_ep11_aes_key(key, key_size)) { + if (key_size == 2 * EP11_KEY_SIZE && + is_ep11_aes_key(key + EP11_KEY_SIZE, + key_size - EP11_KEY_SIZE)) + return true; } return false; @@ -1579,6 +1632,7 @@ int get_key_bit_size(const u8 *key, size_t key_size, size_t *bitsize) { struct aesdatakeytoken *datakey = (struct aesdatakeytoken *)key; struct aescipherkeytoken *cipherkey = (struct aescipherkeytoken *)key; + struct ep11keytoken *ep11key = (struct ep11keytoken *)key; util_assert(bitsize != NULL, "Internal error: bitsize is NULL"); @@ -1600,6 +1654,12 @@ int get_key_bit_size(const u8 *key, size_t key_size, size_t *bitsize) if (cipherkey->pfv == 0x00) /* V0 payload */ *bitsize += cipherkey->pl - 384; } + } else if (is_ep11_aes_key(key, key_size)) { + *bitsize = ep11key->head.keybitlen; + if (key_size == 2 * AESDATA_KEY_SIZE) { + ep11key = (struct ep11keytoken *)(key + EP11_KEY_SIZE); + *bitsize += ep11key->head.keybitlen; + } } else { return -EINVAL; } @@ -1621,7 +1681,8 @@ const char *get_key_type(const u8 *key, size_t key_size) return KEY_TYPE_CCA_AESDATA; if (is_cca_aes_cipher_key(key, key_size)) return KEY_TYPE_CCA_AESCIPHER; - + if (is_ep11_aes_key(key, key_size)) + return KEY_TYPE_EP11_AES; return NULL; } @@ -1641,6 +1702,8 @@ int get_min_card_level_for_keytype(const char *key_type) return 3; if (strcasecmp(key_type, KEY_TYPE_CCA_AESCIPHER) == 0) return 6; + if (strcasecmp(key_type, KEY_TYPE_EP11_AES) == 0) + return 7; return -1; } @@ -1661,6 +1724,8 @@ enum card_type get_card_type_for_keytype(const char *key_type) return CARD_TYPE_CCA; if (strcasecmp(key_type, KEY_TYPE_CCA_AESCIPHER) == 0) return CARD_TYPE_CCA; + if (strcasecmp(key_type, KEY_TYPE_EP11_AES) == 0) + return CARD_TYPE_EP11; return CARD_TYPE_ANY; } diff --git a/zkey/pkey.h b/zkey/pkey.h index 71845c7f..ad1517c9 100644 --- a/zkey/pkey.h +++ b/zkey/pkey.h @@ -28,11 +28,17 @@ struct tokenheader { u8 res1[3]; } __packed; -#define TOKEN_TYPE_NON_CCA 0x00 -#define TOKEN_TYPE_CCA_INTERNAL 0x01 +#define TOKEN_TYPE_NON_CCA 0x00 +#define TOKEN_TYPE_CCA_INTERNAL 0x01 -#define TOKEN_VERSION_AESDATA 0x04 -#define TOKEN_VERSION_AESCIPHER 0x05 +/* CCA-Internal token versions */ +#define TOKEN_VERSION_AESDATA 0x04 +#define TOKEN_VERSION_AESCIPHER 0x05 + +/* Non-CCA token versions */ +#define TOKEN_VERSION_PROTECTED_KEY 0x01 +#define TOKEN_VERSION_CLEAR_KEY 0x02 +#define TOKEN_VERSION_EP11_AES 0x03 struct aesdatakeytoken { u8 type; /* TOKEN_TYPE_INTERNAL (0x01) for internal key token */ @@ -83,11 +89,36 @@ struct aescipherkeytoken { u8 varpart[80]; /* variable part */ } __packed; +struct ep11keytoken { + union { + u8 session[32]; + struct { + u8 type; /* TOKEN_TYPE_NON_CCA (0x00) */ + u8 res0; /* unused */ + u16 length; /* length of token */ + u8 version; /* TOKEN_VERSION_EP11_AES (0x03) */ + u8 res1; /* unused */ + u16 keybitlen; /* clear key bit len, 0 for unknown */ + } head; + }; + u8 wkvp[16]; /* wrapping key verification pattern */ + u64 attr; /* boolean key attributes */ + u64 mode; /* mode bits */ + u16 version; /* 0x1234, ep11 blob struct version */ + u8 iv[14]; + u8 encrypted_key_data[144]; + u8 mac[32]; + u8 padding[64]; +} __packed; + #define AESDATA_KEY_SIZE sizeof(struct aesdatakeytoken) #define AESCIPHER_KEY_SIZE sizeof(struct aescipherkeytoken) +#define EP11_KEY_SIZE sizeof(struct ep11keytoken) -#define MAX_SECURE_KEY_SIZE MAX(AESDATA_KEY_SIZE, AESCIPHER_KEY_SIZE) -#define MIN_SECURE_KEY_SIZE MIN(AESDATA_KEY_SIZE, AESCIPHER_KEY_SIZE) +#define MAX_SECURE_KEY_SIZE MAX(EP11_KEY_SIZE, \ + MAX(AESDATA_KEY_SIZE, AESCIPHER_KEY_SIZE)) +#define MIN_SECURE_KEY_SIZE MIN(EP11_KEY_SIZE, \ + MIN(AESDATA_KEY_SIZE, AESCIPHER_KEY_SIZE)) struct pkey_seckey { u8 seckey[AESDATA_KEY_SIZE]; /* the secure key blob */ @@ -139,6 +170,7 @@ struct pkey_verifykey { enum pkey_key_type { PKEY_TYPE_CCA_DATA = (u32) 1, PKEY_TYPE_CCA_CIPHER = (u32) 2, + PKEY_TYPE_EP11 = (u32) 3, }; enum pkey_key_size { @@ -229,6 +261,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 PAES_BLOCK_SIZE 16 #define ENC_ZERO_LEN (2 * PAES_BLOCK_SIZE) @@ -282,6 +315,7 @@ int get_master_key_verification_pattern(const u8 *key, size_t key_size, bool is_cca_aes_data_key(const u8 *key, size_t key_size); 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_xts_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); diff --git a/zkey/zkey.c b/zkey/zkey.c index 22f66ce9..39ee3789 100644 --- a/zkey/zkey.c +++ b/zkey/zkey.c @@ -227,9 +227,9 @@ static struct util_opt opt_vec[] = { .option = { "key-type", required_argument, NULL, 'K'}, .argument = "type", .desc = "The type of the key. Possible values are '" - KEY_TYPE_CCA_AESDATA"' and '"KEY_TYPE_CCA_AESCIPHER"'. " - "When this option is omitted, the default is '" - KEY_TYPE_CCA_AESDATA"'", + KEY_TYPE_CCA_AESDATA"', '"KEY_TYPE_CCA_AESCIPHER"' " + "and '"KEY_TYPE_EP11_AES"'. When this option is " + "omitted, the default is '"KEY_TYPE_CCA_AESDATA"'", .command = COMMAND_GENERATE, }, /***********************************************************/ @@ -452,9 +452,9 @@ static struct util_opt opt_vec[] = { .option = { "key-type", required_argument, NULL, 'K'}, .argument = "type", .desc = "The type of the key. Possible values are '" - KEY_TYPE_CCA_AESDATA"' and '"KEY_TYPE_CCA_AESCIPHER"'. " - "Use this option to list all keys with the specified " - "key type.", + KEY_TYPE_CCA_AESDATA"', '"KEY_TYPE_CCA_AESCIPHER"' " + "and '"KEY_TYPE_EP11_AES"'. Use this option to list " + "all keys with the specified key type.", .command = COMMAND_LIST, }, /***********************************************************/