tools: mkeficapsule: Add support for pkcs11

With pkcs11 support it's now possible to specify keys
with URI format. To use this feature the filename must
begin "pkcs11:.." and have valid URI pointing to certificate
and private key in HSM.

The environment variable PKCS11_MODULE_PATH must point to the
right pkcs11 provider i.e. with softhsm:
export PKCS11_MODULE_PATH=<path>/libsofthsm2.so

Example command line:
tools/mkeficapsule --monotonic-count 1 \
 --private-key "pkcs11:token=EX;object=capsule;type=private;pin-source=pin.txt" \
 --certificate "pkcs11:token=EX;object=capsule;type=cert;pin-source=pin.txt" \
 --index 1 \
 --guid XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX \
 "capsule-payload" \
 "capsule.cap"

Signed-off-by: Wojciech Dubowik <Wojciech.Dubowik@mt.com>
Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
This commit is contained in:
Wojciech Dubowik
2026-02-20 10:15:11 +01:00
committed by Simon Glass
parent 4d17632b9a
commit 0c716a157b

View File

@@ -228,21 +228,54 @@ static int create_auth_data(struct auth_context *ctx)
gnutls_pkcs7_t pkcs7;
gnutls_datum_t data;
gnutls_datum_t signature;
gnutls_pkcs11_obj_t *obj_list;
unsigned int obj_list_size = 0;
const char *lib;
int ret;
bool pkcs11_cert = false;
bool pkcs11_key = false;
ret = read_bin_file(ctx->cert_file, &cert.data, &file_size);
if (ret < 0)
return -1;
if (file_size > UINT_MAX)
return -1;
cert.size = file_size;
if (!strncmp(ctx->cert_file, "pkcs11:", strlen("pkcs11:")))
pkcs11_cert = true;
ret = read_bin_file(ctx->key_file, &key.data, &file_size);
if (ret < 0)
return -1;
if (file_size > UINT_MAX)
return -1;
key.size = file_size;
if (!strncmp(ctx->key_file, "pkcs11:", strlen("pkcs11:")))
pkcs11_key = true;
if (pkcs11_cert || pkcs11_key) {
lib = getenv("PKCS11_MODULE_PATH");
if (!lib) {
fprintf(stdout,
"PKCS11_MODULE_PATH not set in the environment\n");
return -1;
}
gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_MANUAL, NULL);
gnutls_global_init();
ret = gnutls_pkcs11_add_provider(lib, "trusted");
if (ret < 0) {
fprintf(stdout, "Failed to add pkcs11 provider\n");
return -1;
}
}
if (!pkcs11_cert) {
ret = read_bin_file(ctx->cert_file, &cert.data, &file_size);
if (ret < 0)
return -1;
if (file_size > UINT_MAX)
return -1;
cert.size = file_size;
}
if (!pkcs11_key) {
ret = read_bin_file(ctx->key_file, &key.data, &file_size);
if (ret < 0)
return -1;
if (file_size > UINT_MAX)
return -1;
key.size = file_size;
}
/*
* For debugging,
@@ -265,22 +298,42 @@ static int create_auth_data(struct auth_context *ctx)
return -1;
}
/* load a private key */
ret = gnutls_privkey_import_x509_raw(pkey, &key, GNUTLS_X509_FMT_PEM,
0, 0);
if (ret < 0) {
fprintf(stderr,
"error in gnutls_privkey_import_x509_raw(): %s\n",
gnutls_strerror(ret));
return -1;
/* load x509 certificate */
if (pkcs11_cert) {
ret = gnutls_pkcs11_obj_list_import_url4(&obj_list, &obj_list_size,
ctx->cert_file, 0);
if (ret < 0 || obj_list_size == 0) {
fprintf(stdout, "Failed to import crt_file URI objects\n");
return -1;
}
gnutls_x509_crt_import_pkcs11(x509, obj_list[0]);
} else {
ret = gnutls_x509_crt_import(x509, &cert, GNUTLS_X509_FMT_PEM);
if (ret < 0) {
fprintf(stderr, "error in gnutls_x509_crt_import(): %s\n",
gnutls_strerror(ret));
return -1;
}
}
/* load x509 certificate */
ret = gnutls_x509_crt_import(x509, &cert, GNUTLS_X509_FMT_PEM);
if (ret < 0) {
fprintf(stderr, "error in gnutls_x509_crt_import(): %s\n",
gnutls_strerror(ret));
return -1;
/* load a private key */
if (pkcs11_key) {
ret = gnutls_privkey_import_pkcs11_url(pkey, ctx->key_file);
if (ret < 0) {
fprintf(stderr, "error in %d: %s\n", __LINE__,
gnutls_strerror(ret));
return -1;
}
} else {
ret = gnutls_privkey_import_x509_raw(pkey, &key, GNUTLS_X509_FMT_PEM,
0, 0);
if (ret < 0) {
fprintf(stderr,
"error in gnutls_privkey_import_x509_raw(): %s\n",
gnutls_strerror(ret));
return -1;
}
}
/* generate a PKCS #7 structure */
@@ -349,6 +402,11 @@ static int create_auth_data(struct auth_context *ctx)
* gnutls_free(signature.data);
*/
if (pkcs11_cert || pkcs11_key) {
gnutls_global_deinit();
gnutls_pkcs11_deinit();
}
return 0;
}