From 90c7e64dcde336a04de995a08b3ab4d9106a52b9 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 23 Oct 2023 16:32:17 -0400 Subject: [PATCH] Implement support for CKA_ALWAYS_AUTHENTICATE Fixes #42 Signed-off-by: Simo Sorce --- src/asymmetric_cipher.c | 10 ++++++++++ src/objects.c | 34 +++++++++++++++++++++++++++++++++- src/objects.h | 1 + src/session.c | 31 ++++++++++++++++++++++++++++--- src/session.h | 4 ++++ src/signature.c | 10 ++++++++++ 6 files changed, 86 insertions(+), 4 deletions(-) diff --git a/src/asymmetric_cipher.c b/src/asymmetric_cipher.c index a4f33083..bd8e3bc8 100644 --- a/src/asymmetric_cipher.c +++ b/src/asymmetric_cipher.c @@ -245,6 +245,7 @@ static int p11prov_rsaenc_decrypt(void *ctx, unsigned char *out, size_t *outlen, CK_OBJECT_HANDLE handle; CK_ULONG out_size = *outlen; int result = RET_OSSL_ERR; + bool always_auth = false; CK_RV ret; P11PROV_debug("decrypt (ctx=%p)", ctx); @@ -296,6 +297,15 @@ static int p11prov_rsaenc_decrypt(void *ctx, unsigned char *out, size_t *outlen, goto endsess; } + always_auth = + p11prov_obj_get_bool(encctx->key, CKA_ALWAYS_AUTHENTICATE, false); + if (always_auth) { + ret = p11prov_context_specific_login(session, NULL, NULL, NULL); + if (ret != CKR_OK) { + goto endsess; + } + } + ret = p11prov_Decrypt(encctx->provctx, sess, (void *)in, inlen, out, &out_size); if (ret != CKR_OK) { diff --git a/src/objects.c b/src/objects.c index cb92843d..11318ccd 100644 --- a/src/objects.c +++ b/src/objects.c @@ -498,6 +498,35 @@ CK_ATTRIBUTE *p11prov_obj_get_attr(P11PROV_OBJ *obj, CK_ATTRIBUTE_TYPE type) return NULL; } +bool p11prov_obj_get_bool(P11PROV_OBJ *obj, CK_ATTRIBUTE_TYPE type, bool def) +{ + CK_ATTRIBUTE *attr = NULL; + + if (!obj) { + return def; + } + + for (int i = 0; i < obj->numattrs; i++) { + if (obj->attrs[i].type == type) { + attr = &obj->attrs[i]; + } + } + + if (!attr || !attr->pValue) { + return def; + } + + if (attr->ulValueLen == sizeof(CK_BBOOL)) { + if (*((CK_BBOOL *)attr->pValue) == CK_FALSE) { + return false; + } else { + return true; + } + } + + return def; +} + CK_KEY_TYPE p11prov_obj_get_key_type(P11PROV_OBJ *obj) { if (obj) { @@ -566,8 +595,9 @@ P11PROV_CTX *p11prov_obj_get_prov_ctx(P11PROV_OBJ *obj) /* CKA_ID * CKA_LABEL + * CKA_ALWAYS_AUTHENTICATE * CKA_ALLOWED_MECHANISMS see p11prov_obj_from_handle() */ -#define BASE_KEY_ATTRS_NUM 3 +#define BASE_KEY_ATTRS_NUM 4 #define RSA_ATTRS_NUM (BASE_KEY_ATTRS_NUM + 2) static int fetch_rsa_key(P11PROV_CTX *ctx, P11PROV_SESSION *session, @@ -588,6 +618,7 @@ static int fetch_rsa_key(P11PROV_CTX *ctx, P11PROV_SESSION *session, FA_SET_BUF_ALLOC(attrs, num, CKA_PUBLIC_EXPONENT, true); FA_SET_BUF_ALLOC(attrs, num, CKA_ID, false); FA_SET_BUF_ALLOC(attrs, num, CKA_LABEL, false); + FA_SET_BUF_ALLOC(attrs, num, CKA_ALWAYS_AUTHENTICATE, false); ret = p11prov_fetch_attributes(ctx, session, object, attrs, num); if (ret != CKR_OK) { /* free any allocated memory */ @@ -745,6 +776,7 @@ static CK_RV fetch_ec_key(P11PROV_CTX *ctx, P11PROV_SESSION *session, } FA_SET_BUF_ALLOC(attrs, num, CKA_ID, false); FA_SET_BUF_ALLOC(attrs, num, CKA_LABEL, false); + FA_SET_BUF_ALLOC(attrs, num, CKA_ALWAYS_AUTHENTICATE, false); ret = p11prov_fetch_attributes(ctx, session, object, attrs, num); if (ret != CKR_OK) { /* free any allocated memory */ diff --git a/src/objects.h b/src/objects.h index dcf958b3..97ace2f6 100644 --- a/src/objects.h +++ b/src/objects.h @@ -21,6 +21,7 @@ CK_SLOT_ID p11prov_obj_get_slotid(P11PROV_OBJ *obj); CK_OBJECT_HANDLE p11prov_obj_get_handle(P11PROV_OBJ *obj); CK_OBJECT_CLASS p11prov_obj_get_class(P11PROV_OBJ *obj); CK_ATTRIBUTE *p11prov_obj_get_attr(P11PROV_OBJ *obj, CK_ATTRIBUTE_TYPE type); +bool p11prov_obj_get_bool(P11PROV_OBJ *obj, CK_ATTRIBUTE_TYPE type, bool def); CK_KEY_TYPE p11prov_obj_get_key_type(P11PROV_OBJ *obj); CK_ULONG p11prov_obj_get_key_bit_size(P11PROV_OBJ *obj); CK_ULONG p11prov_obj_get_key_size(P11PROV_OBJ *obj); diff --git a/src/session.c b/src/session.c index 9f16e278..421462c4 100644 --- a/src/session.c +++ b/src/session.c @@ -390,7 +390,7 @@ CK_SLOT_ID p11prov_session_slotid(P11PROV_SESSION *session) /* returns a locked login_session if _session is not NULL */ static CK_RV token_login(P11PROV_SESSION *session, P11PROV_URI *uri, OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg, - struct p11prov_slot *slot) + struct p11prov_slot *slot, CK_USER_TYPE user_type) { char cb_pin[MAX_PIN_LENGTH + 1] = { 0 }; size_t cb_pin_len = 0; @@ -452,7 +452,7 @@ static CK_RV token_login(P11PROV_SESSION *session, P11PROV_URI *uri, P11PROV_debug("Attempt Login on session %lu", session->session); /* Supports only USER login sessions for now */ - ret = p11prov_Login(session->provctx, session->session, CKU_USER, pin, + ret = p11prov_Login(session->provctx, session->session, user_type, pin, pinlen); if (ret == CKR_USER_ALREADY_LOGGED_IN) { ret = CKR_OK; @@ -481,6 +481,31 @@ static CK_RV token_login(P11PROV_SESSION *session, P11PROV_URI *uri, return ret; } +CK_RV p11prov_context_specific_login(P11PROV_SESSION *session, P11PROV_URI *uri, + OSSL_PASSPHRASE_CALLBACK *pw_cb, + void *pw_cbarg) +{ + P11PROV_SLOTS_CTX *sctx = NULL; + P11PROV_SLOT *slot = NULL; + CK_RV ret; + + ret = p11prov_take_slots(session->provctx, &sctx); + if (ret != CKR_OK) { + return CKR_GENERAL_ERROR; + } + + slot = p11prov_get_slot_by_id(sctx, p11prov_session_slotid(session)); + if (!slot) { + ret = CKR_GENERAL_ERROR; + } + + ret = + token_login(session, uri, pw_cb, pw_cbarg, slot, CKU_CONTEXT_SPECIFIC); + + p11prov_return_slots(sctx); + return ret; +} + static CK_RV check_slot(P11PROV_CTX *ctx, P11PROV_SLOT *slot, P11PROV_URI *uri, CK_MECHANISM_TYPE mechtype, bool rw) { @@ -689,7 +714,7 @@ static CK_RV slot_login(P11PROV_SLOT *slot, P11PROV_URI *uri, /* we seem to already have a valid logged in session */ ret = CKR_OK; } else { - ret = token_login(session, uri, pw_cb, pw_cbarg, slot); + ret = token_login(session, uri, pw_cb, pw_cbarg, slot, CKU_USER); } done: diff --git a/src/session.h b/src/session.h index 23efaa04..37b13602 100644 --- a/src/session.h +++ b/src/session.h @@ -21,6 +21,10 @@ CK_RV p11prov_take_login_session(P11PROV_CTX *provctx, CK_SLOT_ID slotid, P11PROV_SESSION **_session); void p11prov_return_session(P11PROV_SESSION *session); +CK_RV p11prov_context_specific_login(P11PROV_SESSION *session, P11PROV_URI *uri, + OSSL_PASSPHRASE_CALLBACK *pw_cb, + void *pw_cbarg); + typedef CK_RV (*p11prov_session_callback_t)(void *cbarg); void p11prov_session_set_callback(P11PROV_SESSION *session, p11prov_session_callback_t cb, void *cbarg); diff --git a/src/signature.c b/src/signature.c index 0100426b..bbbeb41f 100644 --- a/src/signature.c +++ b/src/signature.c @@ -775,6 +775,7 @@ static CK_RV p11prov_sig_operate_init(P11PROV_SIG_CTX *sigctx, bool digest_op, CK_SESSION_HANDLE sess; CK_SLOT_ID slotid; bool reqlogin = false; + bool always_auth = false; CK_RV ret; P11PROV_debug("called (sigctx=%p, digest_op=%s)", sigctx, @@ -838,6 +839,15 @@ static CK_RV p11prov_sig_operate_init(P11PROV_SIG_CTX *sigctx, bool digest_op, "Failed to open session on slot %lu", slotid); } + if (reqlogin) { + always_auth = + p11prov_obj_get_bool(sigctx->key, CKA_ALWAYS_AUTHENTICATE, false); + } + + if (always_auth) { + ret = p11prov_context_specific_login(session, NULL, NULL, NULL); + } + done: if (ret != CKR_OK) { p11prov_return_session(session);