zkey: Remove the use of AF_ALG for calculating key verification patterns

Instead of using AF_ALG to calculate key verification patterns, transform
the key blob into a protected key and calculate the key verification
patterns with CAPCF calls.

The 'zkey-cryptsetup convert' command also calculates key verification
patterns from clear keys. Support this, too.

Reviewed-by: Finn Callies <fcallies@linux.ibm.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
Ingo Franzki
2026-06-08 13:15:30 +02:00
committed by Jan Höppner
parent 44d6020774
commit 7fffdcfe8c
8 changed files with 1098 additions and 221 deletions

View File

@@ -102,6 +102,9 @@
_x > _y ? _x : _y; \
})
#ifdef __SIZEOF_INT128__
typedef unsigned __int128 u128 __aligned(16);
#endif
typedef unsigned long long u64;
typedef signed long long s64;
typedef unsigned int u32;

View File

@@ -98,7 +98,7 @@ zkey-cryptsetup-skip-openssl:
all: $(BUILD_TARGETS) $(SUB_DIRS)
zkey.o: check-dep-zkey zkey.c pkey.h cca.h ep11.h misc.h
pkey.o: pkey.c pkey.h cca.h ep11.h utils.h
pkey.o: pkey.c pkey.h cca.h ep11.h utils.h cpacf.h
cca.o: cca.c cca.h pkey.h ep11.h utils.h
ep11.o: ep11.c ep11.h pkey.h cca.h utils.h
utils.o: utils.h pkey.h cca.h ep11.h
@@ -109,14 +109,15 @@ zkey-cryptsetup.o: check-dep-zkey-cryptsetup zkey-cryptsetup.c pkey.h cca.h \
ep11.h misc.h utils.h
kms.o: kms.c kms.h kms-plugin.h utils.h pkey.h
pvsecrets.o: pvsecrets.h
cpacf.o: cpacf.c cpacf.h pkey.h
zkey: LDLIBS = -ldl -lcrypto
zkey: zkey.o pkey.o cca.o ep11.o properties.o keystore.o utils.o kms.o \
pvsecrets.o $(libs)
pvsecrets.o cpacf.o $(libs)
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@
zkey-cryptsetup: LDLIBS = -ldl -lcryptsetup -ljson-c -lcrypto
zkey-cryptsetup: zkey-cryptsetup.o pkey.o cca.o ep11.o utils.o $(libs)
zkey-cryptsetup: zkey-cryptsetup.o pkey.o cca.o ep11.o utils.o cpacf.o $(libs)
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@
install-common:

603
zkey/cpacf.c Normal file
View File

@@ -0,0 +1,603 @@
/*
* zkey - Generate, re-encipher, and validate secure keys
*
* 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.
*/
#include <errno.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/auxv.h>
#include <openssl/crypto.h>
#include "lib/util_libc.h"
#include "cpacf.h"
#include "pkey.h"
#define MASK64(n) (1ULL << (63 - (n) % 64))
#define OFF64(n) ((n) / 64)
/*
* Checks if the specified MSA level is available.
*
* @param[in] msa the MSA level to query
*
* @returns true if available, false otherwise
*/
static bool cpacf_msa(int msa)
{
bool ret;
unsigned long hwcap, facility_list_nmemb;
u64 *facility_list = NULL, tmp;
hwcap = getauxval(AT_HWCAP);
if ((hwcap & HWCAP_S390_STFLE) == 0)
return false;
facility_list_nmemb = stfle(&tmp, 1);
if (facility_list_nmemb > UINT8_MAX)
return false;
facility_list = util_zalloc(facility_list_nmemb * sizeof(u64));
stfle(facility_list, facility_list_nmemb);
ret = (facility_list_nmemb >= (unsigned long)OFF64(msa) + 1 &&
(facility_list[OFF64(msa)] & MASK64(msa)) != 0);
free(facility_list);
return ret;
}
/*
* Checks if the KMC instruction and the specified KMC function code is
* supported.
*
* @param[in] fc the function code to query
*
* @returns true if supported, false otherwise
*/
static bool cpacf_query_kmc(int fc)
{
u64 status_word[2] = { 0 };
if (!cpacf_msa(MSA))
return false;
cpacf_kmc(CPACF_KM_QUERY, &status_word, NULL, NULL, 0, NULL);
return (status_word[OFF64(fc)] & MASK64(fc)) != 0;
}
/*
* Checks if the KM instruction and the specified KM function code is
* supported.
*
* @param[in] fc the function code to query
*
* @returns true if supported, false otherwise
*/
static bool cpacf_query_km(int fc)
{
u64 status_word[2] = { 0 };
if (!cpacf_msa(MSA))
return false;
cpacf_km(CPACF_KMC_QUERY, &status_word, NULL, NULL, 0, NULL);
return (status_word[OFF64(fc)] & MASK64(fc)) != 0;
}
/*
* Checks if the KMAC instruction and the specified KMAC function code is
* supported.
*
* @param[in] fc the function code to query
*
* @returns true if supported, false otherwise
*/
static bool cpacf_query_kmac(int fc)
{
u64 status_word[2] = { 0 };
if (!cpacf_msa(MSA))
return false;
cpacf_kmac(CPACF_KMAC_QUERY, &status_word, NULL, 0);
return (status_word[OFF64(fc)] & MASK64(fc)) != 0;
}
/*
* Checks if the PCC instruction and the specified PCC function code is
* supported.
*
* @param[in] fc the function code to query
*
* @returns true if supported, false otherwise
*/
static bool cpacf_query_pcc(int fc)
{
u64 status_word[2] = { 0 };
if (!cpacf_msa(MSA4))
return false;
cpacf_pcc(CPACF_PCC_QUERY, &status_word);
return (status_word[OFF64(fc)] & MASK64(fc)) != 0;
}
/*
* Performs a one-shot AES-ECB encryption using a clear or protected key.
*
* @param[in] key the clear or protected key
* @param[in] key_size the size of the clear or protected key
* @param[in] in the clear data to encrypt
* @param[in] out the output buffer to write the encrypted data to
* @param[in] size the size of the data to encrypt, and also the size
* of the output buffer.
* @param[in] pkey_type the type of the protected key (PKEY_KEYTYPE_nnn)
* or 0 if it is a clear key.
*
* @returns 0 on success, a negative errno in case of an error
*/
int cpacf_aes_cbc_enc(const u8 *key, size_t key_size,
const u8 *in, u8 *out, size_t size,
int pkey_type)
{
union {
struct cpacf_kmc_aes_128_param aes_128;
struct cpacf_kmc_aes_192_param aes_192;
struct cpacf_kmc_aes_256_param aes_256;
struct cpacf_kmc_enc_aes_128_param aes_128_enc;
struct cpacf_kmc_enc_aes_192_param aes_192_enc;
struct cpacf_kmc_enc_aes_256_param aes_256_enc;
} kmc_param = { 0 };
int fc, cc, rc = 0;
switch (pkey_type) {
case 0:
/* clear key */
switch (key_size) {
case 16:
fc = CPACF_KMC_AES_128;
memcpy(kmc_param.aes_128.key, key,
sizeof(kmc_param.aes_128.key));
break;
case 24:
fc = CPACF_KMC_AES_192;
memcpy(kmc_param.aes_192.key, key,
sizeof(kmc_param.aes_192.key));
break;
case 32:
fc = CPACF_KMC_AES_256;
memcpy(kmc_param.aes_256.key, key,
sizeof(kmc_param.aes_256.key));
break;
default:
rc = -EINVAL;
goto out;
}
break;
case PKEY_KEYTYPE_AES_128:
fc = CPACF_KMC_ENCRYPTED_AES_128;
if (key_size != sizeof(kmc_param.aes_128_enc.protkey)) {
rc = -EINVAL;
goto out;
}
memcpy(kmc_param.aes_128_enc.protkey, key,
sizeof(kmc_param.aes_128_enc.protkey));
break;
case PKEY_KEYTYPE_AES_192:
fc = CPACF_KMC_ENCRYPTED_AES_192;
if (key_size != sizeof(kmc_param.aes_192_enc.protkey)) {
rc = -EINVAL;
goto out;
}
memcpy(kmc_param.aes_192_enc.protkey, key,
sizeof(kmc_param.aes_192_enc.protkey));
break;
case PKEY_KEYTYPE_AES_256:
fc = CPACF_KMC_ENCRYPTED_AES_256;
if (key_size != sizeof(kmc_param.aes_256_enc.protkey)) {
rc = -EINVAL;
goto out;
}
memcpy(kmc_param.aes_256_enc.protkey, key,
sizeof(kmc_param.aes_256_enc.protkey));
break;
default:
rc = -EINVAL;
goto out;
}
if (!cpacf_query_kmc(fc)) {
rc = -ENODEV;
goto out;
}
cc = cpacf_kmc(fc, &kmc_param, out, in, size, NULL);
if (cc == 1) /* WKVP mismatch */
rc = -EAGAIN;
else if (cc != 0)
rc = -EIO;
out:
OPENSSL_cleanse(&kmc_param, sizeof(kmc_param));
return rc;
}
/*
* Performs a one-shot AES-XTS encryption using a clear or protected key.
*
* @param[in] key the clear or protected key
* @param[in] key_size the size of the clear or protected key
* @param[in] in the clear data to encrypt
* @param[in] out the output buffer to write the encrypted data to
* @param[in] size the size of the data to encrypt, and also the size
* of the output buffer.
* @param[in] pkey_type the type of the protected key (PKEY_KEYTYPE_nnn)
* or 0 if it is a clear key.
*
* @returns 0 on success, a negative errno in case of an error
*/
int cpacf_aes_xts_enc(const u8 *key, size_t key_size,
const u8 *in, u8 *out, size_t size,
int pkey_type)
{
union {
struct cpacf_pcc_xts_aes_128_param aes_xts_128;
struct cpacf_pcc_xts_aes_256_param aes_xts_256;
struct cpacf_pcc_enc_xts_aes_128_param aes_xts_enc_128;
struct cpacf_pcc_enc_xts_aes_256_param aes_xts_enc_256;
} pcc_param = { 0 };
union {
struct cpacf_km_xts_aes_128_param aes_xts_128;
struct cpacf_km_xts_aes_256_param aes_xts_256;
struct cpacf_km_enc_xts_aes_128_param aes_xts_enc_128;
struct cpacf_km_enc_xts_aes_256_param aes_xts_enc_256;
} km_param = { 0 };
int pcc_fc, km_fc, cc, rc = 0;
switch (pkey_type) {
case 0:
/* clear key */
switch (key_size) {
case 32:
pcc_fc = CPACF_PCC_XTS_AES_128;
memcpy(pcc_param.aes_xts_128.key,
key + sizeof(pcc_param.aes_xts_128.key),
sizeof(pcc_param.aes_xts_128.key));
break;
case 64:
pcc_fc = CPACF_PCC_XTS_AES_256;
memcpy(pcc_param.aes_xts_256.key,
key + sizeof(pcc_param.aes_xts_256.key),
sizeof(pcc_param.aes_xts_256.key));
break;
default:
rc = -EINVAL;
goto out;
}
break;
case PKEY_KEYTYPE_AES_128:
pcc_fc = CPACF_PCC_XTS_ENCRYPTED_AES_128;
if (key_size != 2 * sizeof(pcc_param.aes_xts_enc_128.protkey)) {
rc = -EINVAL;
goto out;
}
memcpy(pcc_param.aes_xts_enc_128.protkey,
key + sizeof(pcc_param.aes_xts_enc_128.protkey),
sizeof(pcc_param.aes_xts_enc_128.protkey));
break;
case PKEY_KEYTYPE_AES_256:
pcc_fc = CPACF_PCC_XTS_ENCRYPTED_AES_256;
if (key_size != 2 * sizeof(pcc_param.aes_xts_enc_256.protkey)) {
rc = -EINVAL;
goto out;
}
memcpy(pcc_param.aes_xts_enc_256.protkey,
key + sizeof(pcc_param.aes_xts_enc_256.protkey),
sizeof(pcc_param.aes_xts_enc_256.protkey));
break;
default:
rc = -EINVAL;
goto out;
}
if (!cpacf_query_pcc(pcc_fc)) {
rc = -ENODEV;
goto out;
}
cc = cpacf_pcc(pcc_fc, &pcc_param);
if (cc == 1) /* WKVP mismatch */
rc = -EAGAIN;
else if (cc != 0)
rc = -EIO;
if (rc != 0)
goto out;
switch (pkey_type) {
case 0:
/* clear key */
switch (key_size) {
case 32:
km_fc = CPACF_KM_XTS_AES_128;
memcpy(km_param.aes_xts_128.key, key,
sizeof(km_param.aes_xts_128.key));
memcpy(km_param.aes_xts_128.xtsparam,
pcc_param.aes_xts_128.xtsparams,
sizeof(km_param.aes_xts_128.xtsparam));
break;
case 64:
km_fc = CPACF_KM_XTS_AES_256;
memcpy(km_param.aes_xts_256.key, key,
sizeof(km_param.aes_xts_256.key));
memcpy(km_param.aes_xts_256.xtsparam,
pcc_param.aes_xts_256.xtsparams,
sizeof(km_param.aes_xts_256.xtsparam));
break;
default:
rc = -EINVAL;
goto out;
}
break;
case PKEY_KEYTYPE_AES_128:
km_fc = CPACF_KM_XTS_ENCRYPTED_AES_128;
memcpy(km_param.aes_xts_enc_128.protkey, key,
sizeof(km_param.aes_xts_enc_128.protkey));
memcpy(km_param.aes_xts_enc_128.xtsparam,
pcc_param.aes_xts_enc_128.xtsparams,
sizeof(km_param.aes_xts_enc_128.xtsparam));
break;
case PKEY_KEYTYPE_AES_256:
km_fc = CPACF_KM_XTS_ENCRYPTED_AES_256;
memcpy(km_param.aes_xts_enc_256.protkey, key,
sizeof(km_param.aes_xts_enc_256.protkey));
memcpy(km_param.aes_xts_enc_256.xtsparam,
pcc_param.aes_xts_enc_256.xtsparams,
sizeof(km_param.aes_xts_enc_256.xtsparam));
break;
default:
rc = -EINVAL;
goto out;
}
if (!cpacf_query_km(km_fc)) {
rc = -ENODEV;
goto out;
}
cc = cpacf_km(km_fc, &km_param, out, in, size, NULL);
if (cc == 1) /* WKVP mismatch */
rc = -EAGAIN;
else if (cc != 0)
rc = -EIO;
out:
OPENSSL_cleanse(&pcc_param, sizeof(pcc_param));
OPENSSL_cleanse(&km_param, sizeof(km_param));
return rc;
}
/*
* Performs a one-shot AES-XTS encryption using a Full-XTS protected key
*
* @param[in] key the protected key
* @param[in] key_size the size of the protected key
* @param[in] in the clear data to encrypt
* @param[in] out the output buffer to write the encrypted data to
* @param[in] size the size of the data to encrypt, and also the size
* of the output buffer.
* @param[in] pkey_type the type of the protected key (PKEY_KEYTYPE_nnn).
*
* @returns 0 on success, a negative errno in case of an error
*/
int cpacf_aes_xts_full_enc(const u8 *key, size_t key_size,
const u8 *in, u8 *out, size_t size,
int pkey_type)
{
union {
struct cpacf_km_xts_full_aes_128_param aes_128;
struct cpacf_km_xts_full_aes_256_param aes_256;
} km_param = { 0 };
int fc, cc, rc = 0;
switch (pkey_type) {
case PKEY_KEYTYPE_AES_XTS_128:
fc = CPACF_KM_FXTS_ENCRYPTED_AES_128;
if (key_size != sizeof(km_param.aes_128.protkey) +
sizeof(km_param.aes_128.wkvp)) {
rc = -EINVAL;
goto out;
}
memcpy(km_param.aes_128.protkey, key,
sizeof(km_param.aes_128.protkey));
km_param.aes_128.nap[0] = 0x01;
memcpy(km_param.aes_128.wkvp,
key + sizeof(km_param.aes_128.protkey),
sizeof(km_param.aes_128.wkvp));
break;
case PKEY_KEYTYPE_AES_XTS_256:
fc = CPACF_KM_FXTS_ENCRYPTED_AES_256;
if (key_size != sizeof(km_param.aes_256.protkey) +
sizeof(km_param.aes_256.wkvp)) {
rc = -EINVAL;
goto out;
}
memcpy(km_param.aes_256.protkey, key,
sizeof(km_param.aes_256.protkey));
km_param.aes_256.nap[0] = 0x01;
memcpy(km_param.aes_256.wkvp,
key + sizeof(km_param.aes_256.protkey),
sizeof(km_param.aes_256.wkvp));
break;
default:
rc = -EINVAL;
goto out;
}
if (!cpacf_query_km(fc)) {
rc = -ENODEV;
goto out;
}
cc = cpacf_km(fc, &km_param, out, in, size, NULL);
if (cc == 1) /* WKVP mismatch */
rc = -EAGAIN;
else if (cc != 0)
rc = -EIO;
out:
OPENSSL_cleanse(&km_param, sizeof(km_param));
return rc;
}
/*
* Performs a one-shot SHA-HMAC operation using a clear or protected key.
*
* @param[in] key the clear or protected key
* @param[in] key_size the size of the clear or protected key
* @param[in] in the clear data to mac
* @param[in] in_size the size of the data to mac
* @param[in] mac the output buffer to write the mac to
* @param[in] mac_size the size of the mac buffer
* @param[in] pkey_type the type of the protected key (PKEY_KEYTYPE_nnn)
* or 0 if it is a clear key.
*
* @returns 0 on success, a negative errno in case of an error
*/
int cpacf_hmac_sha(const u8 *key, size_t key_size,
const u8 *in, size_t in_size,
u8 *mac, size_t mac_size,
int pkey_type)
{
union {
struct cpacf_kmac_hmac_224_256_param hmac_256;
struct cpacf_kmac_hmac_384_512_param hmac_512;
struct cpacf_kmac_enc_hmac_224_256_param hmac_256_enc;
struct cpacf_kmac_enc_hmac_384_512_param hmac_512_enc;
} kmac_param = { 0 };
int fc, cc, rc = 0;
switch (pkey_type) {
case 0:
/* clear key */
switch (key_size) {
case 64:
fc = CPACF_KMAC_HMAC_SHA_256;
memcpy(kmac_param.hmac_256.key, key,
sizeof(kmac_param.hmac_256.key));
kmac_param.hmac_256.imbl = in_size * 8;
break;
case 128:
fc = CPACF_KMAC_HMAC_SHA_512;
memcpy(kmac_param.hmac_512.key, key,
sizeof(kmac_param.hmac_512.key));
kmac_param.hmac_512.imbl = in_size * 8;
break;
default:
rc = -EINVAL;
goto out;
}
break;
case PKEY_KEYTYPE_HMAC_512:
fc = CPACF_KMAC_HMAC_ENCRYPTED_SHA_256;
if (key_size != sizeof(kmac_param.hmac_256_enc.protkey)) {
rc = -EINVAL;
goto out;
}
memcpy(kmac_param.hmac_256_enc.protkey, key,
sizeof(kmac_param.hmac_256_enc.protkey));
kmac_param.hmac_256_enc.imbl = in_size * 8;
break;
case PKEY_KEYTYPE_HMAC_1024:
fc = CPACF_KMAC_HMAC_ENCRYPTED_SHA_512;
if (key_size != sizeof(kmac_param.hmac_512_enc.protkey)) {
rc = -EINVAL;
goto out;
}
memcpy(kmac_param.hmac_512_enc.protkey, key,
sizeof(kmac_param.hmac_512_enc.protkey));
kmac_param.hmac_512_enc.imbl = in_size * 8;
break;
default:
rc = -EINVAL;
goto out;
}
if (!cpacf_query_kmac(fc)) {
rc = -ENODEV;
goto out;
}
cc = cpacf_kmac(fc, &kmac_param, in, in_size);
if (cc == 1) /* WKVP mismatch */
rc = -EAGAIN;
else if (cc != 0)
rc = -EIO;
if (rc != 0)
goto out;
switch (pkey_type) {
case 0:
/* clear key */
switch (key_size) {
case 64:
memcpy(mac, kmac_param.hmac_256.h,
MIN(mac_size, sizeof(kmac_param.hmac_256.h)));
break;
case 128:
memcpy(mac, kmac_param.hmac_512.h,
MIN(mac_size, sizeof(kmac_param.hmac_512.h)));
break;
default:
rc = -EINVAL;
goto out;
}
break;
case PKEY_KEYTYPE_HMAC_512:
memcpy(mac, kmac_param.hmac_256_enc.h,
MIN(mac_size, sizeof(kmac_param.hmac_256_enc.h)));
break;
case PKEY_KEYTYPE_HMAC_1024:
memcpy(mac, kmac_param.hmac_512_enc.h,
MIN(mac_size, sizeof(kmac_param.hmac_512_enc.h)));
break;
default:
rc = -EINVAL;
goto out;
}
out:
OPENSSL_cleanse(&kmac_param, sizeof(kmac_param));
return rc;
}

324
zkey/cpacf.h Normal file
View File

@@ -0,0 +1,324 @@
/*
* zkey - Generate, re-encipher, and validate secure keys
*
* 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, 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.
*/
#ifndef CPACF_H
#define CPACF_H
#include "lib/zt_common.h"
int cpacf_aes_cbc_enc(const u8 *key, size_t key_size,
const u8 *in, u8 *out, size_t size,
int pkey_type);
int cpacf_aes_xts_enc(const u8 *key, size_t key_size,
const u8 *in, u8 *out, size_t size,
int pkey_type);
int cpacf_aes_xts_full_enc(const u8 *key, size_t key_size,
const u8 *in, u8 *out, size_t size,
int pkey_type);
int cpacf_hmac_sha(const u8 *key, size_t key_size,
const u8 *in, size_t in_size,
u8 *mac, size_t mac_size,
int pkey_type);
#define MSA 17 /* message-security-assist */
#define MSA4 77 /* message-security-assist extension 4 */
/* STFLE (store facility list extended) */
static inline unsigned long stfle(u64 flist[], u8 nmemb)
{
register unsigned long r0 __asm__("0") = (unsigned long)nmemb - 1;
__asm__ volatile(
".insn s,%[opc]<<16,0(%[flist])"
: "+d" (r0)
: [flist] "a" (flist), [opc] "i" (0xb2b0)
: "memory", "cc"
);
return r0 + 1;
}
/* KM */
/* Function codes */
#define CPACF_KM_QUERY 0
#define CPACF_KM_XTS_AES_128 50
#define CPACF_KM_XTS_AES_256 52
#define CPACF_KM_XTS_ENCRYPTED_AES_128 58
#define CPACF_KM_XTS_ENCRYPTED_AES_256 60
#define CPACF_KM_FXTS_ENCRYPTED_AES_128 90
#define CPACF_KM_FXTS_ENCRYPTED_AES_256 92
struct cpacf_km_xts_aes_128_param {
u8 key[16];
u8 xtsparam[16];
};
struct cpacf_km_xts_aes_256_param {
u8 key[32];
u8 xtsparam[16];
};
struct cpacf_km_enc_xts_aes_128_param {
u8 protkey[48]; /* WKa(K)|WKaVP */
u8 xtsparam[16];
};
struct cpacf_km_enc_xts_aes_256_param {
u8 protkey[64]; /* WKa(K)|WKaVP */
u8 xtsparam[16];
};
struct cpacf_km_xts_full_aes_128_param {
u8 protkey[32]; /* WKa(K) */
u8 tweak[16];
u8 nap[16];
u8 wkvp[32]; /* WKaVP */
};
struct cpacf_km_xts_full_aes_256_param {
u8 protkey[64]; /* WKa(K) */
u8 tweak[16];
u8 nap[16];
u8 wkvp[32]; /* WKaVP */
};
static inline int cpacf_km(unsigned long fc, void *param, u8 *out,
const u8 *in, unsigned long inlen,
unsigned long *bytes_processed)
{
register unsigned long r0 __asm__("0") = (unsigned long)fc;
register unsigned long r1 __asm__("1") = (unsigned long)param;
register unsigned long r2 __asm__("2") = (unsigned long)in;
register unsigned long r3 __asm__("3") = (unsigned long)inlen;
register unsigned long r4 __asm__("4") = (unsigned long)out;
u8 cc;
__asm__ volatile(
"0: .insn rre,%[opc] << 16,%[out],%[in]\n"
" brc 1,0b\n" /* handle partial completion */
" ipm %[cc]\n"
" srl %[cc],28\n"
: [in] "+a" (r2), [inlen] "+d" (r3), [out] "+a" (r4),
[cc] "=d" (cc)
: [fc] "d" (r0), [param] "a" (r1), [opc] "i" (0xb92e)
: "cc", "memory"
);
if (bytes_processed != NULL)
*bytes_processed = fc ? inlen - r3 : r3;
return cc;
}
/* KMC */
/* Function codes */
#define CPACF_KMC_QUERY 0
#define CPACF_KMC_AES_128 18
#define CPACF_KMC_AES_192 19
#define CPACF_KMC_AES_256 20
#define CPACF_KMC_ENCRYPTED_AES_128 26
#define CPACF_KMC_ENCRYPTED_AES_192 27
#define CPACF_KMC_ENCRYPTED_AES_256 28
struct cpacf_kmc_aes_128_param {
u8 cv[16];
u8 key[16];
};
struct cpacf_kmc_aes_192_param {
u8 cv[16];
u8 key[24];
};
struct cpacf_kmc_aes_256_param {
u8 cv[16];
u8 key[32];
};
struct cpacf_kmc_enc_aes_128_param {
u8 cv[16];
u8 protkey[48]; /* WKa(K)|WKaVP */
};
struct cpacf_kmc_enc_aes_192_param {
u8 cv[16];
u8 protkey[56]; /* WKa(K)|WKaVP */
};
struct cpacf_kmc_enc_aes_256_param {
u8 cv[16];
u8 protkey[64]; /* WKa(K)|WKaVP */
};
static inline int cpacf_kmc(unsigned long fc, void *param, u8 *out,
const u8 *in, long inlen,
unsigned long *bytes_processed)
{
register unsigned long r0 __asm__("0") = (unsigned long)fc;
register unsigned long r1 __asm__("1") = (unsigned long)param;
register unsigned long r2 __asm__("2") = (unsigned long)in;
register unsigned long r3 __asm__("3") = (unsigned long)inlen;
register unsigned long r4 __asm__("4") = (unsigned long)out;
u8 cc;
__asm__ volatile(
"0: .insn rre,%[opc] << 16,%[out],%[in]\n"
" brc 1,0b\n" /* handle partial completion */
" ipm %[cc]\n"
" srl %[cc],28\n"
: [in] "+a" (r2), [inlen] "+d" (r3), [out] "+a" (r4),
[cc] "=d" (cc)
: [fc] "d" (r0), [param] "a" (r1), [opc] "i" (0xb92f)
: "cc", "memory"
);
if (bytes_processed != NULL)
*bytes_processed = fc ? inlen - r3 : r3;
return cc;
}
/* KMAC */
/* Function codes */
#define CPACF_KMAC_QUERY 0
#define CPACF_KMAC_HMAC_SHA_256 113
#define CPACF_KMAC_HMAC_SHA_512 115
#define CPACF_KMAC_HMAC_ENCRYPTED_SHA_256 121
#define CPACF_KMAC_HMAC_ENCRYPTED_SHA_512 123
/* Flags */
#define CPACF_KMAC_IKP 0x8000
#define CPACF_KMAC_IIMP 0x4000
#define CPACF_KMAC_CCUP 0x2000
struct cpacf_kmac_hmac_224_256_param {
u32 h[8];
u64 imbl;
unsigned char key[64];
};
struct cpacf_kmac_hmac_384_512_param {
u64 h[8];
#ifdef __SIZEOF_INT128__
u128 imbl;
#else
u64 imblhi;
u64 imbl;
#endif
unsigned char key[128];
};
struct cpacf_kmac_enc_hmac_224_256_param {
u32 h[8];
u64 imbl;
unsigned char protkey[96]; /* WKa(K)|WKaVP */
};
struct cpacf_kmac_enc_hmac_384_512_param {
u64 h[8];
#ifdef __SIZEOF_INT128__
u128 imbl;
#else
u64 imblhi;
u64 imbl;
#endif
unsigned char protkey[160]; /* WKa(K)|WKaVP */
};
static inline int cpacf_kmac(unsigned long fc, void *param, const u8 *in,
unsigned long inlen)
{
register unsigned long r0 __asm__("0") = (unsigned long)fc;
register unsigned long r1 __asm__("1") = (unsigned long)param;
register unsigned long r2 __asm__("2") = (unsigned long)in;
register unsigned long r3 __asm__("3") = (unsigned long)inlen;
u8 cc;
__asm__ volatile(
"0: .insn rre,%[opc] << 16,0,%[in]\n"
" brc 1,0b\n" /* handle partial completion */
" ipm %[cc]\n"
" srl %[cc],28\n"
: [in] "+a" (r2), [inlen] "+d" (r3), [cc] "=d" (cc)
: [fc] "d" (r0), [param] "a" (r1), [opc] "i" (0xb91e)
: "cc", "memory"
);
return cc;
}
/* PCC */
/* Function codes */
#define CPACF_PCC_QUERY 0
#define CPACF_PCC_XTS_AES_128 50
#define CPACF_PCC_XTS_AES_256 52
#define CPACF_PCC_XTS_ENCRYPTED_AES_128 58
#define CPACF_PCC_XTS_ENCRYPTED_AES_256 60
struct cpacf_pcc_xts_aes_128_param {
u8 key[16];
u8 i[16];
u8 j[16];
u8 t[16];
u8 xtsparams[16];
};
struct cpacf_pcc_xts_aes_256_param {
u8 key[32];
u8 i[16];
u8 j[16];
u8 t[16];
u8 xtsparams[16];
};
struct cpacf_pcc_enc_xts_aes_128_param {
u8 protkey[48]; /* WKa(K)|WKaVP */
u8 i[16];
u8 j[16];
u8 t[16];
u8 xtsparams[16];
};
struct cpacf_pcc_enc_xts_aes_256_param {
u8 protkey[64]; /* WKa(K)|WKaVP */
u8 i[16];
u8 j[16];
u8 t[16];
u8 xtsparams[16];
};
/* PCC (perform cryptographic computation) */
static inline int cpacf_pcc(unsigned long fc, void *param)
{
register unsigned long r0 __asm__("0") = (unsigned long)fc;
register unsigned long r1 __asm__("1") = (unsigned long)param;
u8 cc;
__asm__ volatile(
"0: .insn rre,%[opc] << 16,0,0\n" /* PCC opcode */
" brc 1,0b\n" /* handle partial completion */
" ipm %[cc]\n"
" srl %[cc],28\n"
: [cc] "=d" (cc)
: [fc] "d" (r0), [param] "a" (r1), [opc] "i" (0xb92c)
: "cc", "memory"
);
return cc;
}
#endif

View File

@@ -17,7 +17,7 @@ plugin-utils.o: ../plugin-utils.c ../plugin-utils.h ../kms-plugin.h
properties.o: ../properties.c ../properties.h
$(CC) $(ALL_CPPFLAGS) $(ALL_CFLAGS) -fPIC -c $< -o $@
pkey.o: ../pkey.c ../pkey.h ../cca.h ../ep11.h ../utils.h
pkey.o: ../pkey.c ../pkey.h ../cca.h ../ep11.h ../utils.h ../cpacf.h
$(CC) $(ALL_CPPFLAGS) $(ALL_CFLAGS) -fPIC -c $< -o $@
cca.o: ../cca.c ../cca.h ../pkey.h ../ep11.h ../utils.h
@@ -29,12 +29,15 @@ ep11.o: ../ep11.c ../ep11.h ../pkey.h ../cca.h ../utils.h
utils.o: ../utils.c ../utils.h ../pkey.h ../cca.h ../ep11.h
$(CC) $(ALL_CPPFLAGS) $(ALL_CFLAGS) -fPIC -c $< -o $@
cpacf.o: ../cpacf.c ../cpacf.h ../pkey.h
$(CC) $(ALL_CPPFLAGS) $(ALL_CFLAGS) -fPIC -c $< -o $@
zkey-ekmfweb.so: ALL_CFLAGS += -fPIC
zkey-ekmfweb.so: LDLIBS = -L$(rootdir)/libekmfweb -lekmfweb -ldl -lcrypto
zkey-ekmfweb.so: ALL_LDFLAGS += -shared -Wl,--version-script=zkey-ekmfweb.map \
-Wl,-z,defs,-Bsymbolic -Wl,-soname,zkey-ekmfweb.so.$(VERM)
zkey-ekmfweb.so: zkey-ekmfweb.o plugin-utils.o properties.o pkey.o cca.o \
ep11.o utils.o $(libs)
ep11.o utils.o cpacf.o $(libs)
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@
install-libekmfweb.dep:

View File

@@ -18,7 +18,7 @@ plugin-utils.o: ../plugin-utils.c ../plugin-utils.h ../kms-plugin.h
properties.o: ../properties.c ../properties.h
$(CC) $(ALL_CPPFLAGS) $(ALL_CFLAGS) -fPIC -c $< -o $@
pkey.o: ../pkey.c ../pkey.h ../cca.h ../ep11.h ../utils.h ../kms-plugin.h
pkey.o: ../pkey.c ../pkey.h ../cca.h ../ep11.h ../utils.h ../cpacf.h
$(CC) $(ALL_CPPFLAGS) $(ALL_CFLAGS) -fPIC -c $< -o $@
cca.o: ../cca.c ../cca.h ../pkey.h ../ep11.h ../utils.h ../properties.h ../kms-plugin.h
@@ -30,12 +30,15 @@ ep11.o: ../ep11.c ../ep11.h ../pkey.h ../cca.h ../utils.h ../kms-plugin.h
utils.o: ../utils.c ../utils.h ../pkey.h ../cca.h ../ep11.h ../kms-plugin.h
$(CC) $(ALL_CPPFLAGS) $(ALL_CFLAGS) -fPIC -c $< -o $@
cpacf.o: ../cpacf.c ../cpacf.h ../pkey.h
$(CC) $(ALL_CPPFLAGS) $(ALL_CFLAGS) -fPIC -c $< -o $@
zkey-kmip.so: ALL_CFLAGS += -fPIC
zkey-kmip.so: LDLIBS = -L$(rootdir)/libkmipclient -lkmipclient -ldl -lcrypto
zkey-kmip.so: ALL_LDFLAGS += -shared -Wl,--version-script=zkey-kmip.map \
-Wl,-z,defs,-Bsymbolic -Wl,-soname,zkey-kmip.so.$(VERM)
zkey-kmip.so: zkey-kmip.o plugin-utils.o properties.o pkey.o cca.o ep11.o \
utils.o profiles.o $(libs)
utils.o profiles.o cpacf.o $(libs)
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@
install-libkmipclient.dep:

View File

@@ -11,16 +11,16 @@
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <linux/if_alg.h>
#include <stdbool.h>
#include <string.h>
#include <stdint.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <openssl/sha.h>
#include <openssl/crypto.h>
#include "lib/util_base.h"
#include "lib/util_libc.h"
#include "lib/util_panic.h"
@@ -28,13 +28,7 @@
#include "pkey.h"
#include "pvsecrets.h"
#include "utils.h"
#ifndef AF_ALG
#define AF_ALG 38
#endif
#ifndef SOL_ALG
#define SOL_ALG 279
#endif
#include "cpacf.h"
#define pr_verbose(verbose, fmt...) do { \
if (verbose) \
@@ -48,6 +42,8 @@
#define INITIAL_APQN_ENTRIES 16
#define MAX_WKVP_RETRY_COUNT 1000
/**
* Opens the pkey device and returns its file descriptor.
*
@@ -1576,7 +1572,7 @@ out:
/**
* Generate a key verification pattern of a secure AES key by encrypting the all
* zero message with the secure key using the AF_ALG interface
* zero message with the secure key
*
* @param[in] pkey_fd the pkey file descriptor
* @param[in] key the secure key token
@@ -1595,31 +1591,19 @@ int generate_aes_key_verification_pattern(int pkey_fd,
const char *cipher,
bool verbose)
{
int tfmfd = -1, opfd = -1, rc = 0, retry_count = 0;
char null_msg[ENC_ZERO_LEN];
char enc_zero[ENC_ZERO_LEN];
struct af_alg_iv *alg_iv;
struct cmsghdr *header;
uint32_t *type;
ssize_t len;
u8 protkey[MAX(MAX_AES_PROTKEYSIZE * 2, MAX_XTSFULL_PROTKEYSIZE)];
size_t protkey_size = sizeof(protkey);
u8 null_msg[ENC_ZERO_LEN] = { 0 };
u8 enc_zero[ENC_ZERO_LEN];
bool securekey, xts;
int pkeytype = 0;
int count = 0;
size_t i;
int rc;
struct sockaddr_alg sa = {
.salg_family = AF_ALG,
.salg_type = "skcipher",
};
struct iovec iov = {
.iov_base = (void *)null_msg,
.iov_len = sizeof(null_msg),
};
int iv_msg_size = CMSG_SPACE(sizeof(*alg_iv) + PAES_BLOCK_SIZE);
char buffer[CMSG_SPACE(sizeof(*type)) + iv_msg_size];
struct msghdr msg = {
.msg_control = buffer,
.msg_controllen = sizeof(buffer),
.msg_iov = &iov,
.msg_iovlen = 1,
};
util_assert(pkey_fd != -1, "Internal error: pkey_fd is -1");
util_assert(key != NULL, "Internal error: key is NULL");
util_assert(vp != NULL, "Internal error: vp is NULL");
if (vp_len < VERIFICATION_PATTERN_LEN) {
rc = -EMSGSIZE;
@@ -1627,102 +1611,68 @@ int generate_aes_key_verification_pattern(int pkey_fd,
}
if (cipher != NULL) {
util_strlcpy((char *)sa.salg_name, cipher,
sizeof(sa.salg_name));
if (strcmp(cipher, "cbc(aes)") == 0) {
rc = cpacf_aes_cbc_enc(key, key_size,
null_msg, enc_zero,
sizeof(null_msg), 0);
} else if (strcmp(cipher, "xts(aes)") == 0) {
rc = cpacf_aes_xts_enc(key, key_size,
null_msg, enc_zero,
sizeof(null_msg), 0);
} else {
snprintf((char *)sa.salg_name, sizeof(sa.salg_name), "%s(paes)",
is_xts_key(key, key_size) ? "xts" : "cbc");
}
tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
if (tfmfd < 0) {
rc = -errno;
pr_verbose(verbose, "Failed to open an AF_ALG socket");
pr_verbose(verbose, "Invalid clear key cipher '%s'",
cipher);
rc = -EINVAL;
goto out;
}
} else {
securekey = is_secure_key(key, key_size);
xts = securekey ? is_xts_key(key, key_size) : false;
if (bind(tfmfd, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
rc = -errno;
pr_verbose(verbose, "Failed to bind the AF_ALG socket, "
"salg_name='%s' ", sa.salg_name);
do {
rc = pkey_kblob2protk(pkey_fd, (u8 *)key, key_size,
protkey, &protkey_size, &pkeytype,
verbose);
if (rc != 0)
goto out;
}
retry_setkey:
if (setsockopt(tfmfd, SOL_ALG, ALG_SET_KEY, key,
key_size) < 0) {
rc = -errno;
pr_verbose(verbose, "Failed to set the key: %s",
strerror(-rc));
/*
* After a master key change, it can happen that the setkey
* operation returns EINVAL or EAGAIN, although the key is
* valid. This is a temporary situation and the operation will
* succeed, once the firmware has completed some internal
* processing related with the master key change.
* Delay 1 second and retry up to 10 times.
*/
if ((rc == -EINVAL || rc == -EAGAIN) && retry_count < 10) {
pr_verbose(verbose, "Retrying after 1 second...");
retry_count++;
sleep(1);
goto retry_setkey;
}
goto out;
}
rc = 0;
opfd = accept(tfmfd, NULL, NULL);
if (opfd < 0) {
rc = -errno;
pr_verbose(verbose, "Failed to accept on the AF_ALG socket");
goto out;
}
memset(null_msg, 0, sizeof(null_msg));
memset(buffer, 0, sizeof(buffer));
header = CMSG_FIRSTHDR(&msg);
if (header == NULL) {
pr_verbose(verbose, "Failed to obtain control message header");
switch (pkeytype) {
case PKEY_KEYTYPE_AES_128:
case PKEY_KEYTYPE_AES_192:
case PKEY_KEYTYPE_AES_256:
if (xts)
rc = cpacf_aes_xts_enc(protkey,
protkey_size,
null_msg,
enc_zero,
sizeof(null_msg),
pkeytype);
else
rc = cpacf_aes_cbc_enc(protkey,
protkey_size,
null_msg,
enc_zero,
sizeof(null_msg),
pkeytype);
break;
case PKEY_KEYTYPE_AES_XTS_128:
case PKEY_KEYTYPE_AES_XTS_256:
rc = cpacf_aes_xts_full_enc(protkey,
protkey_size,
null_msg, enc_zero,
sizeof(null_msg),
pkeytype);
break;
default:
rc = -EINVAL;
goto out;
}
header->cmsg_level = SOL_ALG;
header->cmsg_type = ALG_SET_OP;
header->cmsg_len = CMSG_LEN(sizeof(*type));
type = (void *)CMSG_DATA(header);
*type = ALG_OP_ENCRYPT;
header = CMSG_NXTHDR(&msg, header);
if (header == NULL) {
pr_verbose(verbose, "Failed to obtain control message "
"header");
rc = -EINVAL;
goto out;
}
header->cmsg_level = SOL_ALG;
header->cmsg_type = ALG_SET_IV;
header->cmsg_len = iv_msg_size;
alg_iv = (void *)CMSG_DATA(header);
alg_iv->ivlen = PAES_BLOCK_SIZE;
memcpy(alg_iv->iv, null_msg, PAES_BLOCK_SIZE);
len = sendmsg(opfd, &msg, 0);
if (len != ENC_ZERO_LEN) {
pr_verbose(verbose, "Failed to send to the AF_ALG socket");
rc = -errno;
goto out;
} while (rc == -EAGAIN && count++ < MAX_WKVP_RETRY_COUNT);
}
len = read(opfd, enc_zero, sizeof(enc_zero));
if (len != ENC_ZERO_LEN) {
pr_verbose(verbose, "Failed to receive from the AF_ALG socket");
rc = -errno;
if (rc != 0)
goto out;
}
memset(vp, 0, vp_len);
for (i = 0; i < sizeof(enc_zero); i++)
@@ -1731,11 +1681,6 @@ retry_setkey:
pr_verbose(verbose, "Key verification pattern: %s", vp);
out:
if (opfd != -1)
close(opfd);
if (tfmfd != -1)
close(tfmfd);
if (rc != 0)
pr_verbose(verbose, "Failed to generate the key verification "
"pattern: %s", strerror(-rc));
@@ -1745,7 +1690,7 @@ out:
/**
* Generate a key verification pattern of a secure HMAC key by MACing the all
* zero message with the secure key using the AF_ALG interface
* zero message with the secure key
*
* @param[in] pkey_fd the pkey file descriptor
* @param[in] key the secure key token
@@ -1763,16 +1708,19 @@ int generate_hmac_key_verification_pattern(int pkey_fd,
const char *cipher,
bool verbose)
{
int tfmfd = -1, opfd = -1, rc = 0, retry_count = 0;
char null_msg[MAC_ZERO_LEN];
char mac_zero[MAC_ZERO_LEN];
size_t i, bitsize;
int len;
u8 protkey[MAX_HMAC_PROTKEYSIZE];
size_t protkey_size = sizeof(protkey);
u8 null_msg[MAC_ZERO_LEN] = { 0 };
u8 mac_zero[MAC_ZERO_LEN];
u8 clear_key[128] = { 0 };
size_t i, clear_key_size;
int pkeytype = 0;
int count = 0;
int rc;
struct sockaddr_alg sa = {
.salg_family = AF_ALG,
.salg_type = "hash",
};
util_assert(pkey_fd != -1, "Internal error: pkey_fd is -1");
util_assert(key != NULL, "Internal error: key is NULL");
util_assert(vp != NULL, "Internal error: vp is NULL");
if (vp_len < VERIFICATION_PATTERN_LEN) {
rc = -EMSGSIZE;
@@ -1780,79 +1728,66 @@ int generate_hmac_key_verification_pattern(int pkey_fd,
}
if (cipher != NULL) {
util_strlcpy((char *)sa.salg_name, cipher,
sizeof(sa.salg_name));
if (strcmp(cipher, "hmac(sha256)") == 0) {
if (key_size > 64) {
if (SHA256(key, key_size, clear_key) == NULL) {
pr_verbose(verbose,
"Failed to hash the key");
rc = -EIO;
goto out;
}
} else {
rc = get_key_bit_size(key, key_size, &bitsize);
if (rc != 0) {
pr_verbose(verbose, "Failed to get the key size");
memcpy(clear_key, key, key_size);
}
clear_key_size = 64;
} else if (strcmp(cipher, "hmac(sha512)") == 0) {
if (key_size > 128) {
if (SHA512(key, key_size, clear_key) == NULL) {
pr_verbose(verbose,
"Failed to hash the key");
rc = -EIO;
goto out;
}
snprintf((char *)sa.salg_name, sizeof(sa.salg_name),
"phmac(sha%lu)", bitsize / 2);
} else {
memcpy(clear_key, key, key_size);
}
tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
if (tfmfd < 0) {
rc = -errno;
pr_verbose(verbose, "Failed to open an AF_ALG socket");
clear_key_size = 128;
} else {
pr_verbose(verbose, "Invalid clear key cipher '%s'",
cipher);
rc = -EINVAL;
goto out;
}
if (bind(tfmfd, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
rc = -errno;
pr_verbose(verbose, "Failed to bind the AF_ALG socket, "
"salg_name='%s' ", sa.salg_name);
rc = cpacf_hmac_sha(clear_key, clear_key_size,
null_msg, sizeof(null_msg),
mac_zero, sizeof(mac_zero), 0);
} else {
do {
rc = pkey_kblob2protk(pkey_fd, (u8 *)key, key_size,
protkey, &protkey_size, &pkeytype,
verbose);
if (rc != 0)
goto out;
switch (pkeytype) {
case PKEY_KEYTYPE_HMAC_512:
case PKEY_KEYTYPE_HMAC_1024:
rc = cpacf_hmac_sha(protkey, protkey_size,
null_msg, sizeof(null_msg),
mac_zero, sizeof(mac_zero),
pkeytype);
break;
default:
rc = -EINVAL;
goto out;
}
retry_setkey:
if (setsockopt(tfmfd, SOL_ALG, ALG_SET_KEY, key,
key_size) < 0) {
rc = -errno;
pr_verbose(verbose, "Failed to set the key: %s",
strerror(-rc));
/*
* After a master key change, it can happen that the setkey
* operation returns EINVAL or EAGAIN, although the key is
* valid. This is a temporary situation and the operation will
* succeed, once the firmware has completed some internal
* processing related with the master key change.
* Delay 1 second and retry up to 10 times.
*/
if ((rc == -EINVAL || rc == -EAGAIN) && retry_count < 10) {
pr_verbose(verbose, "Retrying after 1 second...");
retry_count++;
sleep(1);
goto retry_setkey;
} while (rc == -EAGAIN && count++ < MAX_WKVP_RETRY_COUNT);
}
if (rc != 0)
goto out;
}
rc = 0;
opfd = accept(tfmfd, NULL, NULL);
if (opfd < 0) {
rc = -errno;
pr_verbose(verbose, "Failed to accept on the AF_ALG socket");
goto out;
}
memset(null_msg, 0, sizeof(null_msg));
len = send(opfd, &null_msg, sizeof(null_msg), 0);
if (len != MAC_ZERO_LEN) {
rc = -errno;
pr_verbose(verbose, "Failed to send to the AF_ALG socket");
goto out;
}
len = read(opfd, mac_zero, sizeof(mac_zero));
if (len < SHA_256_HASH_SIZE) {
rc = -errno;
pr_verbose(verbose, "Failed to receive from the AF_ALG socket");
goto out;
}
memset(vp, 0, vp_len);
for (i = 0; i < SHA_256_HASH_SIZE; i++)
@@ -1861,21 +1796,18 @@ retry_setkey:
pr_verbose(verbose, "Key verification pattern: %s", vp);
out:
if (opfd != -1)
close(opfd);
if (tfmfd != -1)
close(tfmfd);
if (rc != 0)
pr_verbose(verbose, "Failed to generate the key verification "
"pattern: %s", strerror(-rc));
OPENSSL_cleanse(clear_key, sizeof(clear_key));
return rc;
}
/**
* Generate a key verification pattern of a secure key by encrypting the all
* zero message with the secure key using the AF_ALG interface
* zero message with the secure key
*
* @param[in] pkey_fd the pkey file descriptor
* @param[in] key the secure key token

View File

@@ -170,6 +170,10 @@ struct pkey_clrkey {
#define PKEY_KEYTYPE_AES_128 1
#define PKEY_KEYTYPE_AES_192 2
#define PKEY_KEYTYPE_AES_256 3
#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
struct pkey_genseck {
u16 cardnr; /* in: card to use or FFFF for any */
@@ -310,6 +314,10 @@ struct pkey_kblob2pkey3 {
#define PKEY_KBLOB2PROTK3 _IOWR(PKEY_IOCTL_MAGIC, 0x1D, struct pkey_kblob2pkey3)
#define MAX_AES_PROTKEYSIZE 64
#define MAX_XTSFULL_PROTKEYSIZE 96
#define MAX_HMAC_PROTKEYSIZE 160
#define KEY_TYPE_CCA_AESDATA "CCA-AESDATA"
#define KEY_TYPE_CCA_AESCIPHER "CCA-AESCIPHER"
#define KEY_TYPE_EP11_AES "EP11-AES"