18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0+ */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *  Copyright IBM Corp. 2019
48c2ecf20Sopenharmony_ci *  Author(s): Harald Freudenberger <freude@linux.ibm.com>
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci *  Collection of EP11 misc functions used by zcrypt and pkey
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#ifndef _ZCRYPT_EP11MISC_H_
108c2ecf20Sopenharmony_ci#define _ZCRYPT_EP11MISC_H_
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include <asm/zcrypt.h>
138c2ecf20Sopenharmony_ci#include <asm/pkey.h>
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci#define EP11_API_V 4  /* highest known and supported EP11 API version */
168c2ecf20Sopenharmony_ci#define EP11_STRUCT_MAGIC 0x1234
178c2ecf20Sopenharmony_ci#define EP11_BLOB_PKEY_EXTRACTABLE 0x00200000
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci/*
208c2ecf20Sopenharmony_ci * Internal used values for the version field of the key header.
218c2ecf20Sopenharmony_ci * Should match to the enum pkey_key_type in pkey.h.
228c2ecf20Sopenharmony_ci */
238c2ecf20Sopenharmony_ci#define TOKVER_EP11_AES  0x03  /* EP11 AES key blob (old style) */
248c2ecf20Sopenharmony_ci#define TOKVER_EP11_AES_WITH_HEADER 0x06 /* EP11 AES key blob with header */
258c2ecf20Sopenharmony_ci#define TOKVER_EP11_ECC_WITH_HEADER 0x07 /* EP11 ECC key blob with header */
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci/* inside view of an EP11 secure key blob */
288c2ecf20Sopenharmony_cistruct ep11keyblob {
298c2ecf20Sopenharmony_ci	union {
308c2ecf20Sopenharmony_ci		u8 session[32];
318c2ecf20Sopenharmony_ci		/* only used for PKEY_TYPE_EP11: */
328c2ecf20Sopenharmony_ci		struct ep11kblob_header head;
338c2ecf20Sopenharmony_ci	};
348c2ecf20Sopenharmony_ci	u8  wkvp[16];  /* wrapping key verification pattern */
358c2ecf20Sopenharmony_ci	u64 attr;      /* boolean key attributes */
368c2ecf20Sopenharmony_ci	u64 mode;      /* mode bits */
378c2ecf20Sopenharmony_ci	u16 version;   /* 0x1234, EP11_STRUCT_MAGIC */
388c2ecf20Sopenharmony_ci	u8  iv[14];
398c2ecf20Sopenharmony_ci	u8  encrypted_key_data[144];
408c2ecf20Sopenharmony_ci	u8  mac[32];
418c2ecf20Sopenharmony_ci} __packed;
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci/* check ep11 key magic to find out if this is an ep11 key blob */
448c2ecf20Sopenharmony_cistatic inline bool is_ep11_keyblob(const u8 *key)
458c2ecf20Sopenharmony_ci{
468c2ecf20Sopenharmony_ci	struct ep11keyblob *kb = (struct ep11keyblob *) key;
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	return (kb->version == EP11_STRUCT_MAGIC);
498c2ecf20Sopenharmony_ci}
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci/*
528c2ecf20Sopenharmony_ci * Simple check if the key blob is a valid EP11 AES key blob with header.
538c2ecf20Sopenharmony_ci * If checkcpacfexport is enabled, the key is also checked for the
548c2ecf20Sopenharmony_ci * attributes needed to export this key for CPACF use.
558c2ecf20Sopenharmony_ci * Returns 0 on success or errno value on failure.
568c2ecf20Sopenharmony_ci */
578c2ecf20Sopenharmony_ciint ep11_check_aes_key_with_hdr(debug_info_t *dbg, int dbflvl,
588c2ecf20Sopenharmony_ci				const u8 *key, size_t keylen, int checkcpacfexp);
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci/*
618c2ecf20Sopenharmony_ci * Simple check if the key blob is a valid EP11 ECC key blob with header.
628c2ecf20Sopenharmony_ci * If checkcpacfexport is enabled, the key is also checked for the
638c2ecf20Sopenharmony_ci * attributes needed to export this key for CPACF use.
648c2ecf20Sopenharmony_ci * Returns 0 on success or errno value on failure.
658c2ecf20Sopenharmony_ci */
668c2ecf20Sopenharmony_ciint ep11_check_ecc_key_with_hdr(debug_info_t *dbg, int dbflvl,
678c2ecf20Sopenharmony_ci				const u8 *key, size_t keylen, int checkcpacfexp);
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci/*
708c2ecf20Sopenharmony_ci * Simple check if the key blob is a valid EP11 AES key blob with
718c2ecf20Sopenharmony_ci * the header in the session field (old style EP11 AES key).
728c2ecf20Sopenharmony_ci * If checkcpacfexport is enabled, the key is also checked for the
738c2ecf20Sopenharmony_ci * attributes needed to export this key for CPACF use.
748c2ecf20Sopenharmony_ci * Returns 0 on success or errno value on failure.
758c2ecf20Sopenharmony_ci */
768c2ecf20Sopenharmony_ciint ep11_check_aes_key(debug_info_t *dbg, int dbflvl,
778c2ecf20Sopenharmony_ci		       const u8 *key, size_t keylen, int checkcpacfexp);
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci/* EP11 card info struct */
808c2ecf20Sopenharmony_cistruct ep11_card_info {
818c2ecf20Sopenharmony_ci	u32  API_ord_nr;    /* API ordinal number */
828c2ecf20Sopenharmony_ci	u16  FW_version;    /* Firmware major and minor version */
838c2ecf20Sopenharmony_ci	char serial[16];    /* serial number string (16 ascii, no 0x00 !) */
848c2ecf20Sopenharmony_ci	u64  op_mode;	    /* card operational mode(s) */
858c2ecf20Sopenharmony_ci};
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci/* EP11 domain info struct */
888c2ecf20Sopenharmony_cistruct ep11_domain_info {
898c2ecf20Sopenharmony_ci	char cur_wk_state;  /* '0' invalid, '1' valid */
908c2ecf20Sopenharmony_ci	char new_wk_state;  /* '0' empty, '1' uncommitted, '2' committed */
918c2ecf20Sopenharmony_ci	u8   cur_wkvp[32];  /* current wrapping key verification pattern */
928c2ecf20Sopenharmony_ci	u8   new_wkvp[32];  /* new wrapping key verification pattern */
938c2ecf20Sopenharmony_ci	u64  op_mode;	    /* domain operational mode(s) */
948c2ecf20Sopenharmony_ci};
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci/*
978c2ecf20Sopenharmony_ci * Provide information about an EP11 card.
988c2ecf20Sopenharmony_ci */
998c2ecf20Sopenharmony_ciint ep11_get_card_info(u16 card, struct ep11_card_info *info, int verify);
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci/*
1028c2ecf20Sopenharmony_ci * Provide information about a domain within an EP11 card.
1038c2ecf20Sopenharmony_ci */
1048c2ecf20Sopenharmony_ciint ep11_get_domain_info(u16 card, u16 domain, struct ep11_domain_info *info);
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci/*
1078c2ecf20Sopenharmony_ci * Generate (random) EP11 AES secure key.
1088c2ecf20Sopenharmony_ci */
1098c2ecf20Sopenharmony_ciint ep11_genaeskey(u16 card, u16 domain, u32 keybitsize, u32 keygenflags,
1108c2ecf20Sopenharmony_ci		   u8 *keybuf, size_t *keybufsize);
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci/*
1138c2ecf20Sopenharmony_ci * Generate EP11 AES secure key with given clear key value.
1148c2ecf20Sopenharmony_ci */
1158c2ecf20Sopenharmony_ciint ep11_clr2keyblob(u16 cardnr, u16 domain, u32 keybitsize, u32 keygenflags,
1168c2ecf20Sopenharmony_ci		     const u8 *clrkey, u8 *keybuf, size_t *keybufsize);
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci/*
1198c2ecf20Sopenharmony_ci * Build a list of ep11 apqns meeting the following constrains:
1208c2ecf20Sopenharmony_ci * - apqn is online and is in fact an EP11 apqn
1218c2ecf20Sopenharmony_ci * - if cardnr is not FFFF only apqns with this cardnr
1228c2ecf20Sopenharmony_ci * - if domain is not FFFF only apqns with this domainnr
1238c2ecf20Sopenharmony_ci * - if minhwtype > 0 only apqns with hwtype >= minhwtype
1248c2ecf20Sopenharmony_ci * - if minapi > 0 only apqns with API_ord_nr >= minapi
1258c2ecf20Sopenharmony_ci * - if wkvp != NULL only apqns where the wkvp (EP11_WKVPLEN bytes) matches
1268c2ecf20Sopenharmony_ci *   to the first EP11_WKVPLEN bytes of the wkvp of the current wrapping
1278c2ecf20Sopenharmony_ci *   key for this domain. When a wkvp is given there will aways be a re-fetch
1288c2ecf20Sopenharmony_ci *   of the domain info for the potential apqn - so this triggers an request
1298c2ecf20Sopenharmony_ci *   reply to each apqn eligible.
1308c2ecf20Sopenharmony_ci * The array of apqn entries is allocated with kmalloc and returned in *apqns;
1318c2ecf20Sopenharmony_ci * the number of apqns stored into the list is returned in *nr_apqns. One apqn
1328c2ecf20Sopenharmony_ci * entry is simple a 32 bit value with 16 bit cardnr and 16 bit domain nr and
1338c2ecf20Sopenharmony_ci * may be casted to struct pkey_apqn. The return value is either 0 for success
1348c2ecf20Sopenharmony_ci * or a negative errno value. If no apqn meeting the criterias is found,
1358c2ecf20Sopenharmony_ci * -ENODEV is returned.
1368c2ecf20Sopenharmony_ci */
1378c2ecf20Sopenharmony_ciint ep11_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
1388c2ecf20Sopenharmony_ci		   int minhwtype, int minapi, const u8 *wkvp);
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci/*
1418c2ecf20Sopenharmony_ci * Derive proteced key from EP11 key blob (AES and ECC keys).
1428c2ecf20Sopenharmony_ci */
1438c2ecf20Sopenharmony_ciint ep11_kblob2protkey(u16 card, u16 dom, const u8 *key, size_t keylen,
1448c2ecf20Sopenharmony_ci		       u8 *protkey, u32 *protkeylen, u32 *protkeytype);
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_civoid zcrypt_ep11misc_exit(void);
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci#endif /* _ZCRYPT_EP11MISC_H_ */
149