#define PKEY_KEYTYPE_ECC_P521          7
 #define PKEY_KEYTYPE_ECC_ED25519       8
 #define PKEY_KEYTYPE_ECC_ED448         9
+#define PKEY_KEYTYPE_AES_XTS_128       10
+#define PKEY_KEYTYPE_AES_XTS_256       11
+#define PKEY_KEYTYPE_HMAC_512          12
+#define PKEY_KEYTYPE_HMAC_1024         13
 
 /* the newer ioctls use a pkey_key_type enum for type information */
 enum pkey_key_type {
 
 #define MAXAPQNSINLIST 64      /* max 64 apqns within a apqn list */
 #define AES_WK_VP_SIZE 32      /* Size of WK VP block appended to a prot key */
 
-/* inside view of a protected key token (only type 0x00 version 0x01) */
+/* inside view of a generic protected key token */
+struct protkeytoken {
+       u8  type;     /* 0x00 for PAES specific key tokens */
+       u8  res0[3];
+       u8  version;  /* should be 0x01 for protected key token */
+       u8  res1[3];
+       u32 keytype;  /* key type, one of the PKEY_KEYTYPE values */
+       u32 len;      /* bytes actually stored in protkey[] */
+       u8  protkey[]; /* the protected key blob */
+} __packed;
+
+/* inside view of a protected AES key token */
 struct protaeskeytoken {
        u8  type;     /* 0x00 for PAES specific key tokens */
        u8  res0[3];
-       u8  version;  /* should be 0x01 for protected AES key token */
+       u8  version;  /* should be 0x01 for protected key token */
        u8  res1[3];
        u32 keytype;  /* key type, one of the PKEY_KEYTYPE values */
        u32 len;      /* bytes actually stored in protkey[] */
 
                        case PKEY_KEYTYPE_ECC_P521:
                        case PKEY_KEYTYPE_ECC_ED25519:
                        case PKEY_KEYTYPE_ECC_ED448:
+                       case PKEY_KEYTYPE_AES_XTS_128:
+                       case PKEY_KEYTYPE_AES_XTS_256:
+                       case PKEY_KEYTYPE_HMAC_512:
+                       case PKEY_KEYTYPE_HMAC_1024:
                                return true;
                        default:
                                return false;
        static cpacf_mask_t pckmo_functions;
 
        int keysize, rc = -EINVAL;
-       u8 paramblock[112];
+       u8 paramblock[160];
        u32 pkeytype;
        long fc;
 
                pkeytype = PKEY_KEYTYPE_ECC;
                fc = CPACF_PCKMO_ENC_ECC_ED448_KEY;
                break;
+       case PKEY_KEYTYPE_AES_XTS_128:
+               /* 2x16 byte keys, 32 byte aes wkvp, total 64 bytes */
+               keysize = 32;
+               pkeytype = PKEY_KEYTYPE_AES_XTS_128;
+               fc = CPACF_PCKMO_ENC_AES_XTS_128_DOUBLE_KEY;
+               break;
+       case PKEY_KEYTYPE_AES_XTS_256:
+               /* 2x32 byte keys, 32 byte aes wkvp, total 96 bytes */
+               keysize = 64;
+               pkeytype = PKEY_KEYTYPE_AES_XTS_256;
+               fc = CPACF_PCKMO_ENC_AES_XTS_256_DOUBLE_KEY;
+               break;
+       case PKEY_KEYTYPE_HMAC_512:
+               /* 64 byte key, 32 byte aes wkvp, total 96 bytes */
+               keysize = 64;
+               pkeytype = PKEY_KEYTYPE_HMAC_512;
+               fc = CPACF_PCKMO_ENC_HMAC_512_KEY;
+               break;
+       case PKEY_KEYTYPE_HMAC_1024:
+               /* 128 byte key, 32 byte aes wkvp, total 160 bytes */
+               keysize = 128;
+               pkeytype = PKEY_KEYTYPE_HMAC_1024;
+               fc = CPACF_PCKMO_ENC_HMAC_1024_KEY;
+               break;
        default:
                PKEY_DBF_ERR("%s unknown/unsupported keytype %u\n",
                             __func__, keytype);
 
        switch (hdr->version) {
        case TOKVER_PROTECTED_KEY: {
-               struct protaeskeytoken *t;
+               struct protkeytoken *t = (struct protkeytoken *)key;
 
-               if (keylen != sizeof(struct protaeskeytoken))
+               if (keylen < sizeof(*t))
                        goto out;
-               t = (struct protaeskeytoken *)key;
-               rc = pckmo_verify_protkey(t->protkey, t->len, t->keytype);
-               if (rc)
+               switch (t->keytype) {
+               case PKEY_KEYTYPE_AES_128:
+               case PKEY_KEYTYPE_AES_192:
+               case PKEY_KEYTYPE_AES_256:
+                       if (keylen != sizeof(struct protaeskeytoken))
+                               goto out;
+                       rc = pckmo_verify_protkey(t->protkey, t->len,
+                                                 t->keytype);
+                       if (rc)
+                               goto out;
+                       break;
+               case PKEY_KEYTYPE_AES_XTS_128:
+                       if (t->len != 64 || keylen != sizeof(*t) + t->len)
+                               goto out;
+                       break;
+               case PKEY_KEYTYPE_AES_XTS_256:
+               case PKEY_KEYTYPE_HMAC_512:
+                       if (t->len != 96 || keylen != sizeof(*t) + t->len)
+                               goto out;
+                       break;
+               case PKEY_KEYTYPE_HMAC_1024:
+                       if (t->len != 160 || keylen != sizeof(*t) + t->len)
+                               goto out;
+                       break;
+               default:
+                       PKEY_DBF_ERR("%s protected key token: unknown keytype %u\n",
+                                    __func__, t->keytype);
                        goto out;
+               }
                memcpy(protkey, t->protkey, t->len);
                *protkeylen = t->len;
                *protkeytype = t->keytype;
                case PKEY_KEYTYPE_ECC_ED448:
                        keysize = 64;
                        break;
+               case PKEY_KEYTYPE_AES_XTS_128:
+                       keysize = 32;
+                       break;
+               case PKEY_KEYTYPE_AES_XTS_256:
+                       keysize = 64;
+                       break;
+               case PKEY_KEYTYPE_HMAC_512:
+                       keysize = 64;
+                       break;
+               case PKEY_KEYTYPE_HMAC_1024:
+                       keysize = 128;
+                       break;
                default:
                        break;
                }
 static int pckmo_gen_protkey(u32 keytype, u32 subtype,
                             u8 *protkey, u32 *protkeylen, u32 *protkeytype)
 {
-       u8 clrkey[32];
+       u8 clrkey[128];
        int keysize;
        int rc;
 
-       keysize = pkey_keytype_aes_to_size(keytype);
-       if (!keysize) {
-               PKEY_DBF_ERR("%s unknown/unsupported keytype %d\n", __func__,
-                            keytype);
+       switch (keytype) {
+       case PKEY_KEYTYPE_AES_128:
+       case PKEY_KEYTYPE_AES_192:
+       case PKEY_KEYTYPE_AES_256:
+               keysize = pkey_keytype_aes_to_size(keytype);
+               break;
+       case PKEY_KEYTYPE_AES_XTS_128:
+               keysize = 32;
+               break;
+       case PKEY_KEYTYPE_AES_XTS_256:
+       case PKEY_KEYTYPE_HMAC_512:
+               keysize = 64;
+               break;
+       case PKEY_KEYTYPE_HMAC_1024:
+               keysize = 128;
+               break;
+       default:
+               PKEY_DBF_ERR("%s unknown/unsupported keytype %d\n",
+                            __func__, keytype);
                return -EINVAL;
        }
        if (subtype != PKEY_TYPE_PROTKEY) {
 
        return sizeof(protkeytoken);
 }
 
+/*
+ * Sysfs attribute read function for the AES XTS prot key binary attributes.
+ * The implementation can not deal with partial reads, because a new random
+ * protected key blob is generated with each read. In case of partial reads
+ * (i.e. off != 0 or count < key blob size) -EINVAL is returned.
+ */
+static ssize_t pkey_protkey_aes_xts_attr_read(u32 keytype, char *buf,
+                                             loff_t off, size_t count)
+{
+       struct protkeytoken *t = (struct protkeytoken *)buf;
+       u32 protlen, prottype;
+       int rc;
+
+       switch (keytype) {
+       case PKEY_KEYTYPE_AES_XTS_128:
+               protlen = 64;
+               break;
+       case PKEY_KEYTYPE_AES_XTS_256:
+               protlen = 96;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (off != 0 || count < sizeof(*t) + protlen)
+               return -EINVAL;
+
+       memset(t, 0, sizeof(*t) + protlen);
+       t->type = TOKTYPE_NON_CCA;
+       t->version = TOKVER_PROTECTED_KEY;
+       t->keytype = keytype;
+
+       rc = sys_pkey_handler_gen_key(keytype, PKEY_TYPE_PROTKEY, 0, 0,
+                                     t->protkey, &protlen, &prottype);
+       if (rc)
+               return rc;
+
+       t->len = protlen;
+
+       return sizeof(*t) + protlen;
+}
+
+/*
+ * Sysfs attribute read function for the HMAC prot key binary attributes.
+ * The implementation can not deal with partial reads, because a new random
+ * protected key blob is generated with each read. In case of partial reads
+ * (i.e. off != 0 or count < key blob size) -EINVAL is returned.
+ */
+static ssize_t pkey_protkey_hmac_attr_read(u32 keytype, char *buf,
+                                          loff_t off, size_t count)
+{
+       struct protkeytoken *t = (struct protkeytoken *)buf;
+       u32 protlen, prottype;
+       int rc;
+
+       switch (keytype) {
+       case PKEY_KEYTYPE_HMAC_512:
+               protlen = 96;
+               break;
+       case PKEY_KEYTYPE_HMAC_1024:
+               protlen = 160;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (off != 0 || count < sizeof(*t) + protlen)
+               return -EINVAL;
+
+       memset(t, 0, sizeof(*t) + protlen);
+       t->type = TOKTYPE_NON_CCA;
+       t->version = TOKVER_PROTECTED_KEY;
+       t->keytype = keytype;
+
+       rc = sys_pkey_handler_gen_key(keytype, PKEY_TYPE_PROTKEY, 0, 0,
+                                     t->protkey, &protlen, &prottype);
+       if (rc)
+               return rc;
+
+       t->len = protlen;
+
+       return sizeof(*t) + protlen;
+}
+
 static ssize_t protkey_aes_128_read(struct file *filp,
                                    struct kobject *kobj,
                                    struct bin_attribute *attr,
                                          off, count);
 }
 
+static ssize_t protkey_aes_xts_128_read(struct file *filp,
+                                       struct kobject *kobj,
+                                       struct bin_attribute *attr,
+                                       char *buf, loff_t off,
+                                       size_t count)
+{
+       return pkey_protkey_aes_xts_attr_read(PKEY_KEYTYPE_AES_XTS_128,
+                                             buf, off, count);
+}
+
+static ssize_t protkey_aes_xts_256_read(struct file *filp,
+                                       struct kobject *kobj,
+                                       struct bin_attribute *attr,
+                                       char *buf, loff_t off,
+                                       size_t count)
+{
+       return pkey_protkey_aes_xts_attr_read(PKEY_KEYTYPE_AES_XTS_256,
+                                             buf, off, count);
+}
+
+static ssize_t protkey_hmac_512_read(struct file *filp,
+                                    struct kobject *kobj,
+                                    struct bin_attribute *attr,
+                                    char *buf, loff_t off,
+                                    size_t count)
+{
+       return pkey_protkey_hmac_attr_read(PKEY_KEYTYPE_HMAC_512,
+                                          buf, off, count);
+}
+
+static ssize_t protkey_hmac_1024_read(struct file *filp,
+                                     struct kobject *kobj,
+                                     struct bin_attribute *attr,
+                                     char *buf, loff_t off,
+                                     size_t count)
+{
+       return pkey_protkey_hmac_attr_read(PKEY_KEYTYPE_HMAC_1024,
+                                          buf, off, count);
+}
+
 static BIN_ATTR_RO(protkey_aes_128, sizeof(struct protaeskeytoken));
 static BIN_ATTR_RO(protkey_aes_192, sizeof(struct protaeskeytoken));
 static BIN_ATTR_RO(protkey_aes_256, sizeof(struct protaeskeytoken));
 static BIN_ATTR_RO(protkey_aes_128_xts, 2 * sizeof(struct protaeskeytoken));
 static BIN_ATTR_RO(protkey_aes_256_xts, 2 * sizeof(struct protaeskeytoken));
+static BIN_ATTR_RO(protkey_aes_xts_128, sizeof(struct protkeytoken) + 64);
+static BIN_ATTR_RO(protkey_aes_xts_256, sizeof(struct protkeytoken) + 96);
+static BIN_ATTR_RO(protkey_hmac_512, sizeof(struct protkeytoken) + 96);
+static BIN_ATTR_RO(protkey_hmac_1024, sizeof(struct protkeytoken) + 160);
 
 static struct bin_attribute *protkey_attrs[] = {
        &bin_attr_protkey_aes_128,
        &bin_attr_protkey_aes_256,
        &bin_attr_protkey_aes_128_xts,
        &bin_attr_protkey_aes_256_xts,
+       &bin_attr_protkey_aes_xts_128,
+       &bin_attr_protkey_aes_xts_256,
+       &bin_attr_protkey_hmac_512,
+       &bin_attr_protkey_hmac_1024,
        NULL
 };