From 559dfe369bef8852bed62c42ab3e34d4593aed37 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 6 Sep 2023 17:52:02 -0400 Subject: [PATCH] Implement special parameter to define Key Usage This allows an application finer control on what usage will be allowed for the key. Fixes #285 Signed-off-by: Simo Sorce --- src/keymgmt.c | 172 +++++++++++++++++++++++++++++++++++++++++-------- src/provider.h | 1 + 2 files changed, 146 insertions(+), 27 deletions(-) diff --git a/src/keymgmt.c b/src/keymgmt.c index d1ccb18a..d12704da 100644 --- a/src/keymgmt.c +++ b/src/keymgmt.c @@ -108,6 +108,7 @@ struct key_generator { CK_KEY_TYPE type; P11PROV_URI *uri; + char *key_usage; CK_MECHANISM mechanism; @@ -220,6 +221,14 @@ static int p11prov_common_gen_set_params(void *genctx, } } + p = OSSL_PARAM_locate_const(params, P11PROV_PARAM_KEY_USAGE); + if (p) { + ret = OSSL_PARAM_get_utf8_string(p, &ctx->key_usage, 0); + if (ret != RET_OSSL_OK) { + return ret; + } + } + switch (ctx->type) { case CKK_RSA: p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_BITS); @@ -334,6 +343,112 @@ static CK_RV common_gen_callback(void *cbarg) return CKR_OK; } +/* Common attributes that may currently be added to the template + * CKA_ID + * CKA_LABEL + */ +#define COMMON_TMPL_SIZE 2 + +const CK_BBOOL val_true = CK_TRUE; +const CK_BBOOL val_false = CK_FALSE; +#define DISCARD_CONST(x) (void *)(x) + +static void set_bool_val(CK_ATTRIBUTE *attr, bool val) +{ + if (val) { + attr->pValue = DISCARD_CONST(&val_true); + } else { + attr->pValue = DISCARD_CONST(&val_false); + } +} + +static void common_key_usage_set_attrs(CK_ATTRIBUTE *template, int tsize, + bool enc, bool sig, bool der, bool wrap) +{ + for (int i = 0; i < tsize; i++) { + switch (template[i].type) { + case CKA_ENCRYPT: + case CKA_DECRYPT: + set_bool_val(&template[i], enc); + break; + case CKA_VERIFY: + case CKA_VERIFY_RECOVER: + case CKA_SIGN: + case CKA_SIGN_RECOVER: + set_bool_val(&template[i], sig); + break; + case CKA_DERIVE: + set_bool_val(&template[i], der); + break; + case CKA_WRAP: + case CKA_UNWRAP: + set_bool_val(&template[i], wrap); + break; + default: + break; + } + } +} + +/* + * Takes a Key Usage string, which must be a space separated list of tokens. + * The tokens are the Key usage flag names as defined in ISO/IEC 9594-8 (X.509) + * Only the following tokens are recognized: + * - dataEncipherment + * - digitalSignature + * - keyAgreement + * - keyEncipherment + * uses: Table 25 from pkcs#11 3.1 spec for mappings for public keys + * and an analogous mapping for private keys + */ +static CK_RV common_key_usage_to_tmpl(struct key_generator *ctx, + CK_ATTRIBUTE *pubtmpl, + CK_ATTRIBUTE *privtmpl, int pubtsize, + int privtsize) +{ + const char *str = NULL; + size_t len = 0; + bool enc = false; + bool sig = false; + bool der = false; + bool wrap = false; + + if (!ctx->key_usage) { + /* leave defaults as set by templates */ + return CKR_OK; + } + + str = ctx->key_usage; + len = strlen(ctx->key_usage); + while (str) { + const char *tok = str; + size_t toklen = len; + const char *p = strchr(str, ' '); + if (p) { + toklen = p - str; + len -= toklen + 1; + p += 1; + } + str = p; + if (strncmp(tok, "dataEncipherment", toklen) == 0) { + enc = true; + } else if (strncmp(tok, "digitalSignature", toklen) == 0) { + sig = true; + } else if (strncmp(tok, "keyAgreement", toklen) == 0) { + der = true; + } else if (strncmp(tok, "keyEncipherment", toklen) == 0) { + wrap = true; + } else { + return CKR_ARGUMENTS_BAD; + } + } + + common_key_usage_set_attrs(pubtmpl, pubtsize, enc, sig, der, wrap); + common_key_usage_set_attrs(privtmpl, privtsize, enc, sig, der, wrap); + + return CKR_OK; +} + static void *p11prov_common_gen(struct key_generator *ctx, CK_ATTRIBUTE *pubkey_template, CK_ATTRIBUTE *privkey_template, int pubtsize, @@ -351,6 +466,13 @@ static void *p11prov_common_gen(struct key_generator *ctx, CK_ATTRIBUTE label = { 0 }; CK_RV ret; + ret = common_key_usage_to_tmpl(ctx, pubkey_template, privkey_template, + pubtsize, privtsize); + if (ret != CKR_OK) { + P11PROV_raise(ctx->provctx, ret, "Failed to map Key Usage"); + return NULL; + } + if (ctx->uri) { cka_id = p11prov_uri_get_id(ctx->uri); label = p11prov_uri_get_label(ctx->uri); @@ -483,29 +605,27 @@ static void *p11prov_rsa_gen_init(void *provctx, int selection, static void *p11prov_rsa_gen(void *genctx, OSSL_CALLBACK *cb_fn, void *cb_arg) { struct key_generator *ctx = (struct key_generator *)genctx; - CK_BBOOL val_true = CK_TRUE; - /* CK_BBOOL val_false = CK_FALSE; */ /* always leave space for CKA_ID and CKA_LABEL */ #define RSA_PUBKEY_TMPL_SIZE 6 - CK_ATTRIBUTE pubkey_template[RSA_PUBKEY_TMPL_SIZE + 2] = { - { CKA_ENCRYPT, &val_true, sizeof(val_true) }, - { CKA_VERIFY, &val_true, sizeof(val_true) }, - { CKA_WRAP, &val_true, sizeof(val_true) }, - { CKA_TOKEN, &val_true, sizeof(CK_BBOOL) }, + CK_ATTRIBUTE pubkey_template[RSA_PUBKEY_TMPL_SIZE + COMMON_TMPL_SIZE] = { + { CKA_ENCRYPT, DISCARD_CONST(&val_true), sizeof(CK_BBOOL) }, + { CKA_VERIFY, DISCARD_CONST(&val_true), sizeof(CK_BBOOL) }, + { CKA_WRAP, DISCARD_CONST(&val_true), sizeof(CK_BBOOL) }, + { CKA_TOKEN, DISCARD_CONST(&val_true), sizeof(CK_BBOOL) }, { CKA_MODULUS_BITS, &ctx->data.rsa.modulus_bits, sizeof(ctx->data.rsa.modulus_bits) }, { CKA_PUBLIC_EXPONENT, &ctx->data.rsa.exponent, ctx->data.rsa.exponent_size }, }; #define RSA_PRIVKEY_TMPL_SIZE 6 - CK_ATTRIBUTE privkey_template[RSA_PRIVKEY_TMPL_SIZE + 2] = { - { CKA_TOKEN, &val_true, sizeof(CK_BBOOL) }, - { CKA_PRIVATE, &val_true, sizeof(CK_BBOOL) }, - { CKA_SENSITIVE, &val_true, sizeof(CK_BBOOL) }, - { CKA_DECRYPT, &val_true, sizeof(CK_BBOOL) }, - { CKA_SIGN, &val_true, sizeof(CK_BBOOL) }, - { CKA_UNWRAP, &val_true, sizeof(CK_BBOOL) }, + CK_ATTRIBUTE privkey_template[RSA_PRIVKEY_TMPL_SIZE + COMMON_TMPL_SIZE] = { + { CKA_TOKEN, DISCARD_CONST(&val_true), sizeof(CK_BBOOL) }, + { CKA_PRIVATE, DISCARD_CONST(&val_true), sizeof(CK_BBOOL) }, + { CKA_SENSITIVE, DISCARD_CONST(&val_true), sizeof(CK_BBOOL) }, + { CKA_DECRYPT, DISCARD_CONST(&val_true), sizeof(CK_BBOOL) }, + { CKA_SIGN, DISCARD_CONST(&val_true), sizeof(CK_BBOOL) }, + { CKA_UNWRAP, DISCARD_CONST(&val_true), sizeof(CK_BBOOL) }, /* TODO? * CKA_SUBJECT * CKA_COPYABLE = true ? @@ -1019,26 +1139,24 @@ static void *p11prov_ec_gen_init(void *provctx, int selection, static void *p11prov_ec_gen(void *genctx, OSSL_CALLBACK *cb_fn, void *cb_arg) { struct key_generator *ctx = (struct key_generator *)genctx; - CK_BBOOL val_true = CK_TRUE; - /* CK_BBOOL val_false = CK_FALSE; */ /* always leave space for CKA_ID and CKA_LABEL */ #define EC_PUBKEY_TMPL_SIZE 5 - CK_ATTRIBUTE pubkey_template[EC_PUBKEY_TMPL_SIZE + 2] = { - { CKA_TOKEN, &val_true, sizeof(CK_BBOOL) }, - { CKA_DERIVE, &val_true, sizeof(val_true) }, - { CKA_VERIFY, &val_true, sizeof(val_true) }, - { CKA_WRAP, &val_true, sizeof(val_true) }, + CK_ATTRIBUTE pubkey_template[EC_PUBKEY_TMPL_SIZE + COMMON_TMPL_SIZE] = { + { CKA_TOKEN, DISCARD_CONST(&val_true), sizeof(CK_BBOOL) }, + { CKA_DERIVE, DISCARD_CONST(&val_true), sizeof(CK_BBOOL) }, + { CKA_VERIFY, DISCARD_CONST(&val_true), sizeof(CK_BBOOL) }, + { CKA_WRAP, DISCARD_CONST(&val_true), sizeof(CK_BBOOL) }, { CKA_EC_PARAMS, (CK_BYTE *)ctx->data.ec.ec_params, ctx->data.ec.ec_params_size }, }; #define EC_PRIVKEY_TMPL_SIZE 6 - CK_ATTRIBUTE privkey_template[EC_PRIVKEY_TMPL_SIZE + 2] = { - { CKA_TOKEN, &val_true, sizeof(CK_BBOOL) }, - { CKA_PRIVATE, &val_true, sizeof(CK_BBOOL) }, - { CKA_SENSITIVE, &val_true, sizeof(CK_BBOOL) }, - { CKA_SIGN, &val_true, sizeof(CK_BBOOL) }, - { CKA_UNWRAP, &val_true, sizeof(CK_BBOOL) }, + CK_ATTRIBUTE privkey_template[EC_PRIVKEY_TMPL_SIZE + COMMON_TMPL_SIZE] = { + { CKA_TOKEN, DISCARD_CONST(&val_true), sizeof(CK_BBOOL) }, + { CKA_PRIVATE, DISCARD_CONST(&val_true), sizeof(CK_BBOOL) }, + { CKA_SENSITIVE, DISCARD_CONST(&val_true), sizeof(CK_BBOOL) }, + { CKA_SIGN, DISCARD_CONST(&val_true), sizeof(CK_BBOOL) }, + { CKA_UNWRAP, DISCARD_CONST(&val_true), sizeof(CK_BBOOL) }, /* TODO? * CKA_SUBJECT * CKA_COPYABLE = true ? diff --git a/src/provider.h b/src/provider.h index 38f3df4f..6d092c24 100644 --- a/src/provider.h +++ b/src/provider.h @@ -58,6 +58,7 @@ #define P11PROV_DESCS_RAND "PKCS11 Random Generator" #define P11PROV_PARAM_URI "pkcs11_uri" +#define P11PROV_PARAM_KEY_USAGE "pkcs11_key_usage" #define P11PROV_PARAM_SLOT_ID "pkcs11_slot_id" typedef struct p11prov_ctx P11PROV_CTX;