Blame SOURCES/0014-authtok-add-label-to-Smartcard-token.patch

bac598
From 8b6be52e95e953ae0431676de0b8c8be7a3262bc Mon Sep 17 00:00:00 2001
bac598
From: Sumit Bose <sbose@redhat.com>
bac598
Date: Fri, 13 Nov 2020 18:05:14 +0100
bac598
Subject: [PATCH 14/16] authtok: add label to Smartcard token
bac598
bac598
The key-id might not be sufficient to identify a certificate on a
bac598
Smartcard since it is possible that multiple certificates will use the
bac598
same key.
bac598
bac598
This patch adds the certificate label to the Smartcard authtok item to
bac598
resolve the ambiguity if the key-id is used for multiple certificates.
bac598
bac598
Resolves: https://github.com/SSSD/sssd/issues/5400
bac598
bac598
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
bac598
---
bac598
 src/p11_child/p11_child.h         |  3 +-
bac598
 src/p11_child/p11_child_common.c  | 12 +++--
bac598
 src/p11_child/p11_child_openssl.c | 16 +++++--
bac598
 src/providers/krb5/krb5_child.c   | 14 +++++-
bac598
 src/responder/pam/pamsrv_cmd.c    |  5 +-
bac598
 src/responder/pam/pamsrv_p11.c    |  8 +++-
bac598
 src/sss_client/pam_sss.c          |  3 ++
bac598
 src/tests/cmocka/test_authtok.c   | 36 +++++++++------
bac598
 src/tests/cmocka/test_pam_srv.c   | 65 ++++++++++++++------------
bac598
 src/util/authtok-utils.c          | 30 ++++++++++--
bac598
 src/util/authtok-utils.h          | 11 ++++-
bac598
 src/util/authtok.c                | 77 +++++++++++++++++++++++++------
bac598
 src/util/authtok.h                | 14 +++++-
bac598
 13 files changed, 214 insertions(+), 80 deletions(-)
bac598
bac598
diff --git a/src/p11_child/p11_child.h b/src/p11_child/p11_child.h
bac598
index 0b53e70c5..9c0cefe05 100644
bac598
--- a/src/p11_child/p11_child.h
bac598
+++ b/src/p11_child/p11_child.h
bac598
@@ -68,7 +68,8 @@ bool do_verification_b64(struct p11_ctx *p11_ctx, const char *cert_b64);
bac598
 errno_t do_card(TALLOC_CTX *mem_ctx, struct p11_ctx *p11_ctx,
bac598
                 enum op_mode mode, const char *pin,
bac598
                 const char *module_name_in, const char *token_name_in,
bac598
-                const char *key_id_in, const char *uri, char **_multi);
bac598
+                const char *key_id_in, const char *label,
bac598
+                const char *uri, char **_multi);
bac598
 
bac598
 errno_t parse_cert_verify_opts(TALLOC_CTX *mem_ctx, const char *verify_opts,
bac598
                                struct cert_verify_opts **cert_verify_opts);
bac598
diff --git a/src/p11_child/p11_child_common.c b/src/p11_child/p11_child_common.c
bac598
index 236d7dac4..f17de1a9e 100644
bac598
--- a/src/p11_child/p11_child_common.c
bac598
+++ b/src/p11_child/p11_child_common.c
bac598
@@ -60,7 +60,8 @@ static int do_work(TALLOC_CTX *mem_ctx, enum op_mode mode, const char *ca_db,
bac598
                    bool wait_for_card,
bac598
                    const char *cert_b64, const char *pin,
bac598
                    const char *module_name, const char *token_name,
bac598
-                   const char *key_id, const char *uri, char **multi)
bac598
+                   const char *key_id, const char *label, const char *uri,
bac598
+                   char **multi)
bac598
 {
bac598
     int ret;
bac598
     struct p11_ctx *p11_ctx;
bac598
@@ -91,7 +92,7 @@ static int do_work(TALLOC_CTX *mem_ctx, enum op_mode mode, const char *ca_db,
bac598
         }
bac598
     } else {
bac598
         ret = do_card(mem_ctx, p11_ctx, mode, pin,
bac598
-                      module_name, token_name, key_id, uri, multi);
bac598
+                      module_name, token_name, key_id, label, uri, multi);
bac598
     }
bac598
 
bac598
 done:
bac598
@@ -158,6 +159,7 @@ int main(int argc, const char *argv[])
bac598
     char *module_name = NULL;
bac598
     char *token_name = NULL;
bac598
     char *key_id = NULL;
bac598
+    char *label = NULL;
bac598
     char *cert_b64 = NULL;
bac598
     bool wait_for_card = false;
bac598
     char *uri = NULL;
bac598
@@ -194,6 +196,8 @@ int main(int argc, const char *argv[])
bac598
          _("Token name for authentication"), NULL},
bac598
         {"key_id", 0, POPT_ARG_STRING, &key_id, 0,
bac598
          _("Key ID for authentication"), NULL},
bac598
+        {"label", 0, POPT_ARG_STRING, &label, 0,
bac598
+         _("Label for authentication"), NULL},
bac598
         {"certificate", 0, POPT_ARG_STRING, &cert_b64, 0,
bac598
          _("certificate to verify, base64 encoded"), NULL},
bac598
         {"uri", 0, POPT_ARG_STRING, &uri, 0,
bac598
@@ -340,6 +344,7 @@ int main(int argc, const char *argv[])
bac598
     }
bac598
     talloc_steal(main_ctx, debug_prg_name);
bac598
 
bac598
+    /* We do not require the label, but it is recommended */
bac598
     if (mode == OP_AUTH && (module_name == NULL || token_name == NULL
bac598
                                 || key_id == NULL)) {
bac598
         DEBUG(SSSDBG_FATAL_FAILURE,
bac598
@@ -369,7 +374,8 @@ int main(int argc, const char *argv[])
bac598
     }
bac598
 
bac598
     ret = do_work(main_ctx, mode, ca_db, cert_verify_opts, wait_for_card,
bac598
-                  cert_b64, pin, module_name, token_name, key_id, uri, &multi);
bac598
+                  cert_b64, pin, module_name, token_name, key_id, label, uri,
bac598
+                  &multi);
bac598
     if (ret != 0) {
bac598
         DEBUG(SSSDBG_OP_FAILURE, "do_work failed.\n");
bac598
         goto fail;
bac598
diff --git a/src/p11_child/p11_child_openssl.c b/src/p11_child/p11_child_openssl.c
bac598
index 04b3e1467..d81a1a9ea 100644
bac598
--- a/src/p11_child/p11_child_openssl.c
bac598
+++ b/src/p11_child/p11_child_openssl.c
bac598
@@ -1587,7 +1587,8 @@ static errno_t wait_for_card(CK_FUNCTION_LIST *module, CK_SLOT_ID *slot_id)
bac598
 errno_t do_card(TALLOC_CTX *mem_ctx, struct p11_ctx *p11_ctx,
bac598
                 enum op_mode mode, const char *pin,
bac598
                 const char *module_name_in, const char *token_name_in,
bac598
-                const char *key_id_in, const char *uri_str, char **_multi)
bac598
+                const char *key_id_in, const char *label_in,
bac598
+                const char *uri_str, char **_multi)
bac598
 {
bac598
     int ret;
bac598
     size_t c;
bac598
@@ -1845,11 +1846,13 @@ errno_t do_card(TALLOC_CTX *mem_ctx, struct p11_ctx *p11_ctx,
bac598
     DLIST_FOR_EACH(item, all_cert_list) {
bac598
         /* Check if we found the certificates we needed for authentication or
bac598
          * the requested ones for pre-auth. For authentication all attributes
bac598
-         * must be given and match, for pre-auth only the given ones must
bac598
-         * match. */
bac598
-        DEBUG(SSSDBG_TRACE_ALL, "%s %s %s %s %s %s.\n",
bac598
+         * except the label must be given and match. The label is optional for
bac598
+         * authentication but if given it must match as well. For pre-auth
bac598
+         * only the given ones must match. */
bac598
+        DEBUG(SSSDBG_TRACE_ALL, "%s %s %s %s %s %s %s.\n",
bac598
               module_name_in, module_file_name, token_name_in, token_name,
bac598
-              key_id_in, item->id);
bac598
+              key_id_in, label_in == NULL ? "- no label given-" : label_in,
bac598
+              item->id);
bac598
 
bac598
         if ((mode == OP_AUTH
bac598
                 && module_name_in != NULL
bac598
@@ -1857,6 +1860,9 @@ errno_t do_card(TALLOC_CTX *mem_ctx, struct p11_ctx *p11_ctx,
bac598
                 && key_id_in != NULL
bac598
                 && item->id != NULL
bac598
                 && strcmp(key_id_in, item->id) == 0
bac598
+                && (label_in == NULL
bac598
+                    || (label_in != NULL && item->label != NULL
bac598
+                        && strcmp(label_in, item->label) == 0))
bac598
                 && strcmp(token_name_in, token_name) == 0
bac598
                 && strcmp(module_name_in, module_file_name) == 0)
bac598
             || (mode == OP_PREAUTH
bac598
diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c
bac598
index 6e2bf6d75..cab7b27a2 100644
bac598
--- a/src/providers/krb5/krb5_child.c
bac598
+++ b/src/providers/krb5/krb5_child.c
bac598
@@ -714,7 +714,7 @@ static krb5_error_code answer_pkinit(krb5_context ctx,
bac598
         kerr = sss_authtok_get_sc(kr->pd->authtok, &pin, NULL,
bac598
                                  &token_name, NULL,
bac598
                                  &module_name, NULL,
bac598
-                                 NULL, NULL);
bac598
+                                 NULL, NULL, NULL, NULL);
bac598
         if (kerr != EOK) {
bac598
             DEBUG(SSSDBG_OP_FAILURE,
bac598
                   "sss_authtok_get_sc failed.\n");
bac598
@@ -1226,11 +1226,12 @@ static errno_t get_pkinit_identity(TALLOC_CTX *mem_ctx,
bac598
     const char *token_name;
bac598
     const char *module_name;
bac598
     const char *key_id;
bac598
+    const char *label;
bac598
 
bac598
     ret = sss_authtok_get_sc(authtok, NULL, NULL,
bac598
                              &token_name, NULL,
bac598
                              &module_name, NULL,
bac598
-                             &key_id, NULL);
bac598
+                             &key_id, NULL, &label, NULL);
bac598
     if (ret != EOK) {
bac598
         DEBUG(SSSDBG_OP_FAILURE, "sss_authtok_get_sc failed.\n");
bac598
         return ret;
bac598
@@ -1267,6 +1268,15 @@ static errno_t get_pkinit_identity(TALLOC_CTX *mem_ctx,
bac598
         }
bac598
     }
bac598
 
bac598
+    if (label != NULL && *label != '\0') {
bac598
+        identity = talloc_asprintf_append(identity, ":certlabel=%s", label);
bac598
+        if (identity == NULL) {
bac598
+            DEBUG(SSSDBG_OP_FAILURE,
bac598
+                  "talloc_asprintf_append failed.\n");
bac598
+            return ENOMEM;
bac598
+        }
bac598
+    }
bac598
+
bac598
     *_identity = identity;
bac598
 
bac598
     DEBUG(SSSDBG_TRACE_ALL, "Using pkinit identity [%s].\n", identity);
bac598
diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c
bac598
index 9ea488be4..d3f092b2b 100644
bac598
--- a/src/responder/pam/pamsrv_cmd.c
bac598
+++ b/src/responder/pam/pamsrv_cmd.c
bac598
@@ -1258,7 +1258,7 @@ static errno_t pam_forwarder_parse_data(struct cli_ctx *cctx, struct pam_data *p
bac598
                     || sss_authtok_get_type(pd->authtok)
bac598
                                                == SSS_AUTHTOK_TYPE_SC_KEYPAD)) {
bac598
             ret = sss_authtok_get_sc(pd->authtok, NULL, NULL, NULL, NULL, NULL,
bac598
-                                     NULL, &key_id, NULL);
bac598
+                                     NULL, &key_id, NULL, NULL, NULL);
bac598
             if (ret != EOK) {
bac598
                 DEBUG(SSSDBG_OP_FAILURE, "sss_authtok_get_sc failed.\n");
bac598
                 goto done;
bac598
@@ -2274,7 +2274,8 @@ static void pam_dom_forwarder(struct pam_auth_req *preq)
bac598
                                  SSS_AUTHTOK_TYPE_SC_PIN, NULL, 0,
bac598
                                  sss_cai_get_token_name(preq->current_cert), 0,
bac598
                                  sss_cai_get_module_name(preq->current_cert), 0,
bac598
-                                 sss_cai_get_key_id(preq->current_cert), 0);
bac598
+                                 sss_cai_get_key_id(preq->current_cert), 0,
bac598
+                                 sss_cai_get_label(preq->current_cert), 0);
bac598
                         if (ret != EOK) {
bac598
                             DEBUG(SSSDBG_OP_FAILURE,
bac598
                                   "sss_authtok_set_sc failed, Smartcard "
bac598
diff --git a/src/responder/pam/pamsrv_p11.c b/src/responder/pam/pamsrv_p11.c
bac598
index abc987804..23f94927a 100644
bac598
--- a/src/responder/pam/pamsrv_p11.c
bac598
+++ b/src/responder/pam/pamsrv_p11.c
bac598
@@ -727,6 +727,7 @@ struct tevent_req *pam_check_cert_send(TALLOC_CTX *mem_ctx,
bac598
     const char *module_name = NULL;
bac598
     const char *token_name = NULL;
bac598
     const char *key_id = NULL;
bac598
+    const char *label = NULL;
bac598
 
bac598
     req = tevent_req_create(mem_ctx, &state, struct pam_check_cert_state);
bac598
     if (req == NULL) {
bac598
@@ -766,7 +767,8 @@ struct tevent_req *pam_check_cert_send(TALLOC_CTX *mem_ctx,
bac598
     if (sss_authtok_get_type(pd->authtok) == SSS_AUTHTOK_TYPE_SC_PIN
bac598
             || sss_authtok_get_type(pd->authtok) == SSS_AUTHTOK_TYPE_SC_KEYPAD) {
bac598
         ret = sss_authtok_get_sc(pd->authtok, NULL, NULL, &token_name, NULL,
bac598
-                                 &module_name, NULL, &key_id, NULL);
bac598
+                                 &module_name, NULL, &key_id, NULL,
bac598
+                                 &label, NULL);
bac598
         if (ret != EOK) {
bac598
             DEBUG(SSSDBG_OP_FAILURE, "sss_authtok_get_sc failed.\n");
bac598
             goto done;
bac598
@@ -784,6 +786,10 @@ struct tevent_req *pam_check_cert_send(TALLOC_CTX *mem_ctx,
bac598
             extra_args[arg_c++] = key_id;
bac598
             extra_args[arg_c++] = "--key_id";
bac598
         }
bac598
+        if (label != NULL && *label != '\0') {
bac598
+            extra_args[arg_c++] = label;
bac598
+            extra_args[arg_c++] = "--label";
bac598
+        }
bac598
     }
bac598
 
bac598
     if (pd->cmd == SSS_PAM_AUTHENTICATE) {
bac598
diff --git a/src/sss_client/pam_sss.c b/src/sss_client/pam_sss.c
bac598
index 04dfdb55d..cffbfa770 100644
bac598
--- a/src/sss_client/pam_sss.c
bac598
+++ b/src/sss_client/pam_sss.c
bac598
@@ -126,6 +126,7 @@ struct cert_auth_info {
bac598
     char *token_name;
bac598
     char *module_name;
bac598
     char *key_id;
bac598
+    char *label;
bac598
     char *prompt_str;
bac598
     char *pam_cert_user;
bac598
     char *choice_list_id;
bac598
@@ -1962,6 +1963,7 @@ static int prompt_sc_pin(pam_handle_t *pamh, struct pam_items *pi)
bac598
         ret = sss_auth_pack_sc_blob(answer, 0, cai->token_name, 0,
bac598
                                     cai->module_name, 0,
bac598
                                     cai->key_id, 0,
bac598
+                                    cai->label, 0,
bac598
                                     NULL, 0, &needed_size);
bac598
         if (ret != EAGAIN) {
bac598
             D(("sss_auth_pack_sc_blob failed."));
bac598
@@ -1979,6 +1981,7 @@ static int prompt_sc_pin(pam_handle_t *pamh, struct pam_items *pi)
bac598
         ret = sss_auth_pack_sc_blob(answer, 0, cai->token_name, 0,
bac598
                                     cai->module_name, 0,
bac598
                                     cai->key_id, 0,
bac598
+                                    cai->label, 0,
bac598
                                     (uint8_t *) pi->pam_authtok, needed_size,
bac598
                                     &needed_size);
bac598
         if (ret != EOK) {
bac598
diff --git a/src/tests/cmocka/test_authtok.c b/src/tests/cmocka/test_authtok.c
bac598
index a8f5bdee7..a31014eb6 100644
bac598
--- a/src/tests/cmocka/test_authtok.c
bac598
+++ b/src/tests/cmocka/test_authtok.c
bac598
@@ -451,25 +451,27 @@ void test_sss_authtok_sc_blobs(void **state)
bac598
     size_t module_name_len;
bac598
     const char *key_id;
bac598
     size_t key_id_len;
bac598
+    const char *label;
bac598
+    size_t label_len;
bac598
 
bac598
     ts = talloc_get_type_abort(*state, struct test_state);
bac598
 
bac598
     ret = sss_auth_pack_sc_blob("abc", 0, "defg", 0, "hijkl", 0, "mnopqr", 0,
bac598
-                                NULL, 0, &needed_size);
bac598
+                                "stuvw", 0, NULL, 0, &needed_size);
bac598
     assert_int_equal(ret, EAGAIN);
bac598
 
bac598
     buf = talloc_size(ts, needed_size);
bac598
     assert_non_null(buf);
bac598
 
bac598
     ret = sss_auth_pack_sc_blob("abc", 0, "defg", 0, "hijkl", 0, "mnopqr", 0,
bac598
-                                buf, needed_size, &needed_size);
bac598
+                                "stuvw", 0, buf, needed_size, &needed_size);
bac598
     assert_int_equal(ret, EOK);
bac598
 
bac598
 #if __BYTE_ORDER == __LITTLE_ENDIAN
bac598
-    assert_memory_equal(buf, "\4\0\0\0\5\0\0\0\6\0\0\0\7\0\0\0abc\0defg\0hijkl\0mnopqr\0",
bac598
+    assert_memory_equal(buf, "\4\0\0\0\5\0\0\0\6\0\0\0\7\0\0\0\6\0\0\0abc\0defg\0hijkl\0mnopqr\0stuvw\0",
bac598
                         needed_size);
bac598
 #else
bac598
-    assert_memory_equal(buf, "\0\0\0\4\0\0\0\5\0\0\0\6\0\0\0\7abc\0defg\0hijkl\0mnopqr\0",
bac598
+    assert_memory_equal(buf, "\0\0\0\4\0\0\0\5\0\0\0\6\0\0\0\7\0\0\0\6abc\0defg\0hijkl\0mnopqr\0stuvw\0",
bac598
                         needed_size);
bac598
 #endif
bac598
 
bac598
@@ -485,7 +487,8 @@ void test_sss_authtok_sc_blobs(void **state)
bac598
     ret = sss_authtok_get_sc(ts->authtoken, &pin, &pin_len,
bac598
                              &token_name, &token_name_len,
bac598
                              &module_name, &module_name_len,
bac598
-                             &key_id, &key_id_len);
bac598
+                             &key_id, &key_id_len,
bac598
+                             &label, &label_len);
bac598
     assert_int_equal(ret, EOK);
bac598
     assert_int_equal(pin_len, 3);
bac598
     assert_string_equal(pin, "abc");
bac598
@@ -495,11 +498,14 @@ void test_sss_authtok_sc_blobs(void **state)
bac598
     assert_string_equal(module_name, "hijkl");
bac598
     assert_int_equal(key_id_len, 6);
bac598
     assert_string_equal(key_id, "mnopqr");
bac598
+    assert_int_equal(label_len, 5);
bac598
+    assert_string_equal(label, "stuvw");
bac598
 
bac598
     ret = sss_authtok_get_sc(ts->authtoken, NULL, NULL,
bac598
                              &token_name, &token_name_len,
bac598
                              &module_name, &module_name_len,
bac598
-                             &key_id, &key_id_len);
bac598
+                             &key_id, &key_id_len,
bac598
+                             &label, &label_len);
bac598
     assert_int_equal(ret, EOK);
bac598
     assert_int_equal(token_name_len, 4);
bac598
     assert_string_equal(token_name, "defg");
bac598
@@ -507,15 +513,19 @@ void test_sss_authtok_sc_blobs(void **state)
bac598
     assert_string_equal(module_name, "hijkl");
bac598
     assert_int_equal(key_id_len, 6);
bac598
     assert_string_equal(key_id, "mnopqr");
bac598
+    assert_int_equal(label_len, 5);
bac598
+    assert_string_equal(label, "stuvw");
bac598
 
bac598
     ret = sss_authtok_get_sc(ts->authtoken, NULL, NULL,
bac598
                              &token_name, NULL,
bac598
                              &module_name, NULL,
bac598
-                             &key_id, NULL);
bac598
+                             &key_id, NULL,
bac598
+                             &label, NULL);
bac598
     assert_int_equal(ret, EOK);
bac598
     assert_string_equal(token_name, "defg");
bac598
     assert_string_equal(module_name, "hijkl");
bac598
     assert_string_equal(key_id, "mnopqr");
bac598
+    assert_string_equal(label, "stuvw");
bac598
 
bac598
     sss_authtok_set_empty(ts->authtoken);
bac598
     talloc_free(buf);
bac598
@@ -608,14 +618,14 @@ void test_sss_authtok_sc_pin(void **state)
bac598
     assert_int_equal(sss_authtok_get_type(ts->authtoken),
bac598
                      SSS_AUTHTOK_TYPE_SC_PIN);
bac598
     size = sss_authtok_get_size(ts->authtoken);
bac598
-    assert_int_equal(size, 28);
bac598
+    assert_int_equal(size, 33);
bac598
 #if __BYTE_ORDER == __LITTLE_ENDIAN
bac598
     assert_memory_equal(sss_authtok_get_data(ts->authtoken),
bac598
-                        "\11\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0" "12345678\0\0\0\0",
bac598
+                        "\11\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0" "12345678\0\0\0\0\0",
bac598
                         size);
bac598
 #else
bac598
     assert_memory_equal(sss_authtok_get_data(ts->authtoken),
bac598
-                        "\0\0\0\11\0\0\0\1\0\0\0\1\0\0\0\1" "12345678\0\0\0\0",
bac598
+                        "\0\0\0\11\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1" "12345678\0\0\0\0\0",
bac598
                         size);
bac598
 #endif
bac598
 
bac598
@@ -624,14 +634,14 @@ void test_sss_authtok_sc_pin(void **state)
bac598
     assert_int_equal(sss_authtok_get_type(ts->authtoken),
bac598
                      SSS_AUTHTOK_TYPE_SC_PIN);
bac598
     size = sss_authtok_get_size(ts->authtoken);
bac598
-    assert_int_equal(size, 25);
bac598
+    assert_int_equal(size, 30);
bac598
 #if __BYTE_ORDER == __LITTLE_ENDIAN
bac598
     assert_memory_equal(sss_authtok_get_data(ts->authtoken),
bac598
-                        "\6\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0" "12345\0\0\0\0",
bac598
+                        "\6\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0" "12345\0\0\0\0\0",
bac598
                         size);
bac598
 #else
bac598
     assert_memory_equal(sss_authtok_get_data(ts->authtoken),
bac598
-                        "\0\0\0\6\0\0\0\1\0\0\0\1\0\0\0\1" "12345\0\0\0\0",
bac598
+                        "\0\0\0\6\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1" "12345\0\0\0\0\0",
bac598
                         size);
bac598
 #endif
bac598
 
bac598
diff --git a/src/tests/cmocka/test_pam_srv.c b/src/tests/cmocka/test_pam_srv.c
bac598
index 326deaf1f..cb05042de 100644
bac598
--- a/src/tests/cmocka/test_pam_srv.c
bac598
+++ b/src/tests/cmocka/test_pam_srv.c
bac598
@@ -536,7 +536,7 @@ static void mock_input_pam(TALLOC_CTX *mem_ctx,
bac598
 static void mock_input_pam_cert(TALLOC_CTX *mem_ctx, const char *name,
bac598
                                 const char *pin, const char *token_name,
bac598
                                 const char *module_name, const char *key_id,
bac598
-                                const char *service,
bac598
+                                const char *label, const char *service,
bac598
                                 acct_cb_t acct_cb, const char *cert)
bac598
 {
bac598
     size_t buf_size;
bac598
@@ -556,14 +556,14 @@ static void mock_input_pam_cert(TALLOC_CTX *mem_ctx, const char *name,
bac598
 
bac598
     if (pin != NULL) {
bac598
         ret = sss_auth_pack_sc_blob(pin, 0, token_name, 0, module_name, 0,
bac598
-                                    key_id, 0, NULL, 0, &needed_size);
bac598
+                                    key_id, 0, label, 0, NULL, 0, &needed_size);
bac598
         assert_int_equal(ret, EAGAIN);
bac598
 
bac598
         pi.pam_authtok = malloc(needed_size);
bac598
         assert_non_null(pi.pam_authtok);
bac598
 
bac598
         ret = sss_auth_pack_sc_blob(pin, 0, token_name, 0, module_name, 0,
bac598
-                                    key_id, 0,
bac598
+                                    key_id, 0, label, 0,
bac598
                                     (uint8_t *)pi.pam_authtok, needed_size,
bac598
                                     &needed_size);
bac598
         assert_int_equal(ret, EOK);
bac598
@@ -1766,7 +1766,7 @@ void test_pam_preauth_no_logon_name(void **state)
bac598
     int ret;
bac598
 
bac598
     mock_input_pam_cert(pam_test_ctx, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
bac598
-                        NULL);
bac598
+                        NULL, NULL);
bac598
 
bac598
     will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH);
bac598
     will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
bac598
@@ -1862,7 +1862,7 @@ void test_pam_preauth_cert_nocert(void **state)
bac598
     unsetenv("SOFTHSM2_CONF");
bac598
 
bac598
     mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL, NULL, NULL, NULL,
bac598
-                        NULL, NULL);
bac598
+                        NULL, NULL, NULL);
bac598
 
bac598
     will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH);
bac598
     will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
bac598
@@ -2004,7 +2004,7 @@ void test_pam_preauth_cert_nomatch(void **state)
bac598
     set_cert_auth_param(pam_test_ctx->pctx, CA_DB);
bac598
 
bac598
     mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL, NULL, NULL, NULL,
bac598
-                        test_lookup_by_cert_cb, NULL);
bac598
+                        NULL, test_lookup_by_cert_cb, NULL);
bac598
 
bac598
     will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH);
bac598
     will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
bac598
@@ -2026,7 +2026,7 @@ void test_pam_preauth_cert_match(void **state)
bac598
     set_cert_auth_param(pam_test_ctx->pctx, CA_DB);
bac598
 
bac598
     mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL, NULL, NULL, NULL,
bac598
-                        test_lookup_by_cert_cb, SSSD_TEST_CERT_0001);
bac598
+                        NULL, test_lookup_by_cert_cb, SSSD_TEST_CERT_0001);
bac598
 
bac598
     will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH);
bac598
     will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
bac598
@@ -2048,7 +2048,7 @@ void test_pam_preauth_cert_match_gdm_smartcard(void **state)
bac598
 
bac598
     set_cert_auth_param(pam_test_ctx->pctx, CA_DB);
bac598
 
bac598
-    mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL, NULL, NULL,
bac598
+    mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL, NULL, NULL, NULL,
bac598
                         "gdm-smartcard", test_lookup_by_cert_cb,
bac598
                         SSSD_TEST_CERT_0001);
bac598
 
bac598
@@ -2072,7 +2072,7 @@ void test_pam_preauth_cert_match_wrong_user(void **state)
bac598
     set_cert_auth_param(pam_test_ctx->pctx, CA_DB);
bac598
 
bac598
     mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL, NULL, NULL, NULL,
bac598
-                        test_lookup_by_cert_wrong_user_cb,
bac598
+                        NULL, test_lookup_by_cert_wrong_user_cb,
bac598
                         SSSD_TEST_CERT_0001);
bac598
 
bac598
     will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH);
bac598
@@ -2104,7 +2104,7 @@ void test_pam_preauth_cert_no_logon_name(void **state)
bac598
      * request will be done with the username found by the certificate
bac598
      * lookup. */
bac598
     mock_input_pam_cert(pam_test_ctx, NULL, NULL, NULL, NULL, NULL, NULL,
bac598
-                        test_lookup_by_cert_cb, SSSD_TEST_CERT_0001);
bac598
+                        NULL, test_lookup_by_cert_cb, SSSD_TEST_CERT_0001);
bac598
     mock_account_recv_simple();
bac598
     mock_parse_inp("pamuser", NULL, EOK);
bac598
     mock_parse_inp("pamuser", NULL, EOK);
bac598
@@ -2134,7 +2134,7 @@ void test_pam_preauth_cert_no_logon_name_with_hint(void **state)
bac598
      * during pre-auth and there is no need for an extra mocked response as in
bac598
      * test_pam_preauth_cert_no_logon_name. */
bac598
     mock_input_pam_cert(pam_test_ctx, NULL, NULL, NULL, NULL, NULL, NULL,
bac598
-                        test_lookup_by_cert_cb, SSSD_TEST_CERT_0001);
bac598
+                        NULL, test_lookup_by_cert_cb, SSSD_TEST_CERT_0001);
bac598
 
bac598
     will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH);
bac598
     will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
bac598
@@ -2155,7 +2155,7 @@ void test_pam_preauth_cert_no_logon_name_double_cert(void **state)
bac598
 
bac598
     set_cert_auth_param(pam_test_ctx->pctx, CA_DB);
bac598
 
bac598
-    mock_input_pam_cert(pam_test_ctx, NULL, NULL, NULL, NULL, NULL, NULL,
bac598
+    mock_input_pam_cert(pam_test_ctx, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
bac598
                         test_lookup_by_cert_double_cb, SSSD_TEST_CERT_0001);
bac598
 
bac598
     will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH);
bac598
@@ -2178,7 +2178,7 @@ void test_pam_preauth_cert_no_logon_name_double_cert_with_hint(void **state)
bac598
     set_cert_auth_param(pam_test_ctx->pctx, CA_DB);
bac598
     pam_test_ctx->rctx->domains->user_name_hint = true;
bac598
 
bac598
-    mock_input_pam_cert(pam_test_ctx, NULL, NULL, NULL, NULL, NULL, NULL,
bac598
+    mock_input_pam_cert(pam_test_ctx, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
bac598
                         test_lookup_by_cert_double_cb, SSSD_TEST_CERT_0001);
bac598
 
bac598
     will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH);
bac598
@@ -2201,7 +2201,7 @@ void test_pam_preauth_no_cert_no_logon_name(void **state)
bac598
     set_cert_auth_param(pam_test_ctx->pctx, "/no/path");
bac598
 
bac598
     mock_input_pam_cert(pam_test_ctx, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
bac598
-                        NULL);
bac598
+                        NULL, NULL);
bac598
 
bac598
     will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH);
bac598
     will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
bac598
@@ -2223,7 +2223,7 @@ void test_pam_preauth_cert_no_logon_name_no_match(void **state)
bac598
     set_cert_auth_param(pam_test_ctx->pctx, CA_DB);
bac598
 
bac598
     mock_input_pam_cert(pam_test_ctx, NULL, NULL, NULL, NULL, NULL, NULL,
bac598
-                        test_lookup_by_cert_cb, NULL);
bac598
+                        NULL, test_lookup_by_cert_cb, NULL);
bac598
 
bac598
     will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH);
bac598
     will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
bac598
@@ -2252,7 +2252,8 @@ void test_pam_cert_auth(void **state)
bac598
      * in the cache and no second request to the backend is needed. */
bac598
     mock_input_pam_cert(pam_test_ctx, "pamuser", "123456", "SSSD Test Token",
bac598
                         TEST_MODULE_NAME,
bac598
-                        "C554C9F82C2A9D58B70921C143304153A8A42F17", NULL,
bac598
+                        "C554C9F82C2A9D58B70921C143304153A8A42F17",
bac598
+                        "SSSD test cert 0001", NULL,
bac598
                         test_lookup_by_cert_cb, SSSD_TEST_CERT_0001);
bac598
 
bac598
     will_return(__wrap_sss_packet_get_cmd, SSS_PAM_AUTHENTICATE);
bac598
@@ -2289,7 +2290,8 @@ void test_pam_ecc_cert_auth(void **state)
bac598
     mock_input_pam_cert(pam_test_ctx, "pamuser", "123456",
bac598
                         "SSSD Test ECC Token",
bac598
                         TEST_MODULE_NAME,
bac598
-                        "190E513C9A3DFAACDE5D2D0592F0FDFF559C10CB", NULL,
bac598
+                        "190E513C9A3DFAACDE5D2D0592F0FDFF559C10CB",
bac598
+                        "SSSD test ECC cert 0001", NULL,
bac598
                         test_lookup_by_cert_cb, SSSD_TEST_ECC_CERT_0001);
bac598
 
bac598
     will_return(__wrap_sss_packet_get_cmd, SSS_PAM_AUTHENTICATE);
bac598
@@ -2324,7 +2326,8 @@ void test_pam_cert_auth_no_logon_name(void **state)
bac598
      * in the cache and no second request to the backend is needed. */
bac598
     mock_input_pam_cert(pam_test_ctx, NULL, "123456", "SSSD Test Token",
bac598
                         TEST_MODULE_NAME,
bac598
-                        "C554C9F82C2A9D58B70921C143304153A8A42F17", NULL,
bac598
+                        "C554C9F82C2A9D58B70921C143304153A8A42F17",
bac598
+                        "SSSD test cert 0001", NULL,
bac598
                         test_lookup_by_cert_cb, SSSD_TEST_CERT_0001);
bac598
 
bac598
     mock_account_recv_simple();
bac598
@@ -2360,7 +2363,7 @@ void test_pam_cert_auth_no_logon_name_no_key_id(void **state)
bac598
      * to the user entry the lookup by certificate will already find the user
bac598
      * in the cache and no second request to the backend is needed. */
bac598
     mock_input_pam_cert(pam_test_ctx, NULL, "123456", "SSSD Test Token",
bac598
-                        TEST_MODULE_NAME, NULL, NULL,
bac598
+                        TEST_MODULE_NAME, NULL, NULL, NULL,
bac598
                         NULL, NULL);
bac598
 
bac598
     will_return(__wrap_sss_packet_get_cmd, SSS_PAM_AUTHENTICATE);
bac598
@@ -2387,7 +2390,8 @@ void test_pam_cert_auth_double_cert(void **state)
bac598
 
bac598
     mock_input_pam_cert(pam_test_ctx, "pamuser", "123456", "SSSD Test Token",
bac598
                         TEST_MODULE_NAME,
bac598
-                        "C554C9F82C2A9D58B70921C143304153A8A42F17", NULL,
bac598
+                        "C554C9F82C2A9D58B70921C143304153A8A42F17",
bac598
+                        "SSSD test cert 0001", NULL,
bac598
                         test_lookup_by_cert_double_cb, SSSD_TEST_CERT_0001);
bac598
 
bac598
     will_return(__wrap_sss_packet_get_cmd, SSS_PAM_AUTHENTICATE);
bac598
@@ -2416,7 +2420,7 @@ void test_pam_cert_preauth_2certs_one_mapping(void **state)
bac598
     ret = test_lookup_by_cert_cb(discard_const(SSSD_TEST_CERT_0001));
bac598
     assert_int_equal(ret, EOK);
bac598
     mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL, NULL, NULL, NULL,
bac598
-                        test_lookup_by_cert_cb, NULL);
bac598
+                        NULL, test_lookup_by_cert_cb, NULL);
bac598
 
bac598
     will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH);
bac598
     will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
bac598
@@ -2439,7 +2443,7 @@ void test_pam_cert_preauth_2certs_two_mappings(void **state)
bac598
     putenv(discard_const("SOFTHSM2_CONF=" ABS_BUILD_DIR "/src/tests/test_CA/softhsm2_two.conf"));
bac598
 
bac598
     mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL, NULL, NULL, NULL,
bac598
-                        test_lookup_by_cert_cb_2nd_cert_same_user,
bac598
+                        NULL, test_lookup_by_cert_cb_2nd_cert_same_user,
bac598
                         SSSD_TEST_CERT_0001);
bac598
 
bac598
     will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH);
bac598
@@ -2464,7 +2468,8 @@ void test_pam_cert_auth_2certs_one_mapping(void **state)
bac598
 
bac598
     mock_input_pam_cert(pam_test_ctx, "pamuser", "123456", "SSSD Test Token",
bac598
                         TEST_MODULE_NAME,
bac598
-                        "C554C9F82C2A9D58B70921C143304153A8A42F17", NULL,
bac598
+                        "C554C9F82C2A9D58B70921C143304153A8A42F17",
bac598
+                        "SSSD test cert 0001", NULL,
bac598
                         test_lookup_by_cert_double_cb, SSSD_TEST_CERT_0001);
bac598
 
bac598
     will_return(__wrap_sss_packet_get_cmd, SSS_PAM_AUTHENTICATE);
bac598
@@ -2498,7 +2503,7 @@ void test_pam_cert_preauth_uri_token1(void **state)
bac598
     putenv(discard_const("SOFTHSM2_CONF=" ABS_BUILD_DIR "/src/tests/test_CA/softhsm2_2tokens.conf"));
bac598
 
bac598
     mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL, NULL, NULL, NULL,
bac598
-                        test_lookup_by_cert_cb, SSSD_TEST_CERT_0001);
bac598
+                        NULL, test_lookup_by_cert_cb, SSSD_TEST_CERT_0001);
bac598
 
bac598
     will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH);
bac598
     will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
bac598
@@ -2528,7 +2533,7 @@ void test_pam_cert_preauth_uri_token2(void **state)
bac598
     putenv(discard_const("SOFTHSM2_CONF=" ABS_BUILD_DIR "/src/tests/test_CA/softhsm2_2tokens.conf"));
bac598
 
bac598
     mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL, NULL, NULL, NULL,
bac598
-                        test_lookup_by_cert_cb, SSSD_TEST_CERT_0002);
bac598
+                        NULL, test_lookup_by_cert_cb, SSSD_TEST_CERT_0002);
bac598
 
bac598
     will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH);
bac598
     will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
bac598
@@ -2567,7 +2572,7 @@ void test_pam_preauth_expired_crl_file(void **state)
bac598
     set_cert_auth_param(pam_test_ctx->pctx, CA_DB);
bac598
 
bac598
     mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL, NULL, NULL, NULL,
bac598
-                        NULL, NULL);
bac598
+                        NULL, NULL, NULL);
bac598
 
bac598
     will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH);
bac598
     will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
bac598
@@ -2599,7 +2604,7 @@ void test_pam_preauth_expired_crl_file_soft(void **state)
bac598
     set_cert_auth_param(pam_test_ctx->pctx, CA_DB);
bac598
 
bac598
     mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL, NULL, NULL, NULL,
bac598
-                        test_lookup_by_cert_cb, SSSD_TEST_CERT_0001);
bac598
+                        NULL, test_lookup_by_cert_cb, SSSD_TEST_CERT_0001);
bac598
 
bac598
     will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH);
bac598
     will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
bac598
@@ -2632,7 +2637,7 @@ void test_pam_preauth_ocsp(void **state)
bac598
     putenv(discard_const("SOFTHSM2_CONF=" ABS_BUILD_DIR "/src/tests/test_CA/softhsm2_ocsp.conf"));
bac598
 
bac598
     mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL, NULL, NULL, NULL,
bac598
-                        NULL, NULL);
bac598
+                        NULL, NULL, NULL);
bac598
 
bac598
     will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH);
bac598
     will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
bac598
@@ -2674,7 +2679,7 @@ void test_pam_preauth_ocsp_no_ocsp(void **state)
bac598
     putenv(discard_const("SOFTHSM2_CONF=" ABS_BUILD_DIR "/src/tests/test_CA/softhsm2_ocsp.conf"));
bac598
 
bac598
     mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL, NULL, NULL, NULL,
bac598
-                        test_lookup_by_cert_cb, SSSD_TEST_CERT_0005);
bac598
+                        NULL, test_lookup_by_cert_cb, SSSD_TEST_CERT_0005);
bac598
 
bac598
     will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH);
bac598
     will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
bac598
@@ -2708,7 +2713,7 @@ void test_pam_preauth_ocsp_soft_ocsp(void **state)
bac598
     putenv(discard_const("SOFTHSM2_CONF=" ABS_BUILD_DIR "/src/tests/test_CA/softhsm2_ocsp.conf"));
bac598
 
bac598
     mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL, NULL, NULL, NULL,
bac598
-                        test_lookup_by_cert_cb, SSSD_TEST_CERT_0005);
bac598
+                        NULL, test_lookup_by_cert_cb, SSSD_TEST_CERT_0005);
bac598
 
bac598
     will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH);
bac598
     will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
bac598
diff --git a/src/util/authtok-utils.c b/src/util/authtok-utils.c
bac598
index e50f86741..e76bd17c5 100644
bac598
--- a/src/util/authtok-utils.c
bac598
+++ b/src/util/authtok-utils.c
bac598
@@ -77,6 +77,7 @@ errno_t sss_auth_pack_sc_blob(const char *pin, size_t pin_len,
bac598
                               const char *token_name, size_t token_name_len,
bac598
                               const char *module_name, size_t module_name_len,
bac598
                               const char *key_id, size_t key_id_len,
bac598
+                              const char *label, size_t label_len,
bac598
                               uint8_t *buf, size_t buf_len,
bac598
                               size_t *_sc_blob_len)
bac598
 {
bac598
@@ -88,7 +89,8 @@ errno_t sss_auth_pack_sc_blob(const char *pin, size_t pin_len,
bac598
             || (pin_len != 0 && pin == NULL)
bac598
             || (token_name_len != 0 && token_name == NULL)
bac598
             || (module_name_len != 0 && module_name == NULL)
bac598
-            || (key_id_len != 0 && key_id == NULL)) {
bac598
+            || (key_id_len != 0 && key_id == NULL)
bac598
+            || (label_len != 0 && label == NULL)) {
bac598
         return EINVAL;
bac598
     }
bac598
 
bac598
@@ -113,6 +115,11 @@ errno_t sss_auth_pack_sc_blob(const char *pin, size_t pin_len,
bac598
         key_id_len = 0;
bac598
     }
bac598
 
bac598
+    if (label == NULL) {
bac598
+        label = "";
bac598
+        label_len = 0;
bac598
+    }
bac598
+
bac598
     /* len should not include the trailing \0 */
bac598
     if (pin_len == 0 || pin[pin_len - 1] == '\0') {
bac598
         pin_len = strlen(pin);
bac598
@@ -130,8 +137,12 @@ errno_t sss_auth_pack_sc_blob(const char *pin, size_t pin_len,
bac598
         key_id_len = strlen(key_id);
bac598
     }
bac598
 
bac598
-    *_sc_blob_len = pin_len + token_name_len + module_name_len + key_id_len + 4
bac598
-                            + 4 * sizeof(uint32_t);
bac598
+    if (label_len == 0 || label[label_len - 1] == '\0') {
bac598
+        label_len = strlen(label);
bac598
+    }
bac598
+
bac598
+    *_sc_blob_len = pin_len + token_name_len + module_name_len + key_id_len
bac598
+                            + label_len + 5 + 5 * sizeof(uint32_t);
bac598
     if (buf == NULL || buf_len < *_sc_blob_len) {
bac598
         return EAGAIN;
bac598
     }
bac598
@@ -145,6 +156,8 @@ errno_t sss_auth_pack_sc_blob(const char *pin, size_t pin_len,
bac598
     SAFEALIGN_COPY_UINT32(buf + c, &tmp_uint32_t, &c);
bac598
     tmp_uint32_t = (uint32_t) key_id_len + 1;
bac598
     SAFEALIGN_COPY_UINT32(buf + c, &tmp_uint32_t, &c);
bac598
+    tmp_uint32_t = (uint32_t) label_len + 1;
bac598
+    SAFEALIGN_COPY_UINT32(buf + c, &tmp_uint32_t, &c);
bac598
 
bac598
     memcpy(buf + c, pin, pin_len);
bac598
     buf[c + pin_len] = '\0';
bac598
@@ -160,6 +173,10 @@ errno_t sss_auth_pack_sc_blob(const char *pin, size_t pin_len,
bac598
 
bac598
     memcpy(buf + c, key_id, key_id_len);
bac598
     buf[c + key_id_len] = '\0';
bac598
+    c += key_id_len +1;
bac598
+
bac598
+    memcpy(buf + c, label, label_len);
bac598
+    buf[c + label_len] = '\0';
bac598
 
bac598
     return 0;
bac598
 }
bac598
@@ -171,6 +188,7 @@ const char *sss_auth_get_pin_from_sc_blob(uint8_t *blob, size_t blob_len)
bac598
     uint32_t token_name_len;
bac598
     uint32_t module_name_len;
bac598
     uint32_t key_id_len;
bac598
+    uint32_t label_len;
bac598
 
bac598
     if (blob == NULL || blob_len == 0) {
bac598
         return NULL;
bac598
@@ -184,9 +202,11 @@ const char *sss_auth_get_pin_from_sc_blob(uint8_t *blob, size_t blob_len)
bac598
     SAFEALIGN_COPY_UINT32(&token_name_len, blob + c, &c);
bac598
     SAFEALIGN_COPY_UINT32(&module_name_len, blob + c, &c);
bac598
     SAFEALIGN_COPY_UINT32(&key_id_len, blob + c, &c);
bac598
+    SAFEALIGN_COPY_UINT32(&label_len, blob + c, &c);
bac598
 
bac598
-    if (blob_len != 4 * sizeof(uint32_t) + pin_len + token_name_len
bac598
-                                         + module_name_len + key_id_len) {
bac598
+    if (blob_len != 5 * sizeof(uint32_t) + pin_len + token_name_len
bac598
+                                         + module_name_len + key_id_len
bac598
+                                         + label_len) {
bac598
         return NULL;
bac598
     }
bac598
 
bac598
diff --git a/src/util/authtok-utils.h b/src/util/authtok-utils.h
bac598
index 714c8187e..f3b268f78 100644
bac598
--- a/src/util/authtok-utils.h
bac598
+++ b/src/util/authtok-utils.h
bac598
@@ -39,6 +39,9 @@
bac598
  * @param[in]  key_id      Key ID of the certificate
bac598
  * @param[in]  key_id_len  Length of the key id of the certificate, if 0
bac598
  *                         strlen() will be called internally
bac598
+ * @param[in]  label       Label of the certificate
bac598
+ * @param[in]  label_len   Length of the label of the certificate, if 0
bac598
+ *                         strlen() will be called internally
bac598
  * @param[in]  buf         memory buffer of size buf_len, may be NULL
bac598
  * @param[in]  buf_len     size of memory buffer buf
bac598
  *
bac598
@@ -53,6 +56,7 @@ errno_t sss_auth_pack_sc_blob(const char *pin, size_t pin_len,
bac598
                               const char *token_name, size_t token_name_len,
bac598
                               const char *module_name, size_t module_name_len,
bac598
                               const char *key_id, size_t key_id_len,
bac598
+                              const char *label, size_t label_len,
bac598
                               uint8_t *buf, size_t buf_len,
bac598
                               size_t *_sc_blob_len);
bac598
 /**
bac598
@@ -112,6 +116,10 @@ errno_t sss_auth_unpack_2fa_blob(TALLOC_CTX *mem_ctx,
bac598
  * @param[out] _token_name_len   Length of the token name
bac598
  * @param[out] _module_name      Name of PKCS#11 module, null terminated
bac598
  * @param[out] _module_name_len  Length of the module name
bac598
+ * @param[out] _key_id           Key ID of the certificate, null terminated
bac598
+ * @param[out] _key_id_len       Length of the key ID
bac598
+ * @param[out] _labe l           Label of the certificate, null terminated
bac598
+ * @param[out] _label_len        Length of the label
bac598
  *
bac598
  * @return     EOK       on success
bac598
  *             EINVAL    if input data is not consistent
bac598
@@ -122,7 +130,8 @@ errno_t sss_auth_unpack_sc_blob(TALLOC_CTX *mem_ctx,
bac598
                                  char **pin, size_t *_pin_len,
bac598
                                  char **token_name, size_t *_token_name_len,
bac598
                                  char **module_name, size_t *_module_name_len,
bac598
-                                 char **key_id, size_t *_key_id_len);
bac598
+                                 char **key_id, size_t *_key_id_len,
bac598
+                                 char **label, size_t *_label_len);
bac598
 
bac598
 /**
bac598
  * @brief Return a pointer to the PIN string in the memory buffer
bac598
diff --git a/src/util/authtok.c b/src/util/authtok.c
bac598
index f8b44d6d6..7254ed1da 100644
bac598
--- a/src/util/authtok.c
bac598
+++ b/src/util/authtok.c
bac598
@@ -503,7 +503,8 @@ errno_t sss_authtok_set_sc(struct sss_auth_token *tok,
bac598
                            const char *pin, size_t pin_len,
bac598
                            const char *token_name, size_t token_name_len,
bac598
                            const char *module_name, size_t module_name_len,
bac598
-                           const char *key_id, size_t key_id_len)
bac598
+                           const char *key_id, size_t key_id_len,
bac598
+                           const char *label, size_t label_len)
bac598
 {
bac598
     int ret;
bac598
     size_t needed_size;
bac598
@@ -518,7 +519,7 @@ errno_t sss_authtok_set_sc(struct sss_auth_token *tok,
bac598
 
bac598
     ret = sss_auth_pack_sc_blob(pin, pin_len, token_name, token_name_len,
bac598
                                 module_name, module_name_len,
bac598
-                                key_id, key_id_len, NULL, 0,
bac598
+                                key_id, key_id_len, label, label_len, NULL, 0,
bac598
                                 &needed_size);
bac598
     if (ret != EAGAIN) {
bac598
         DEBUG(SSSDBG_OP_FAILURE, "sss_auth_pack_sc_blob failed.\n");
bac598
@@ -533,7 +534,7 @@ errno_t sss_authtok_set_sc(struct sss_auth_token *tok,
bac598
 
bac598
     ret = sss_auth_pack_sc_blob(pin, pin_len, token_name, token_name_len,
bac598
                                 module_name, module_name_len,
bac598
-                                key_id, key_id_len, tok->data,
bac598
+                                key_id, key_id_len, label, label_len, tok->data,
bac598
                                 needed_size, &needed_size);
bac598
     if (ret != EOK) {
bac598
         DEBUG(SSSDBG_OP_FAILURE, "sss_auth_pack_sc_blob failed.\n");
bac598
@@ -560,6 +561,8 @@ errno_t sss_authtok_set_sc_from_blob(struct sss_auth_token *tok,
bac598
     size_t module_name_len;
bac598
     char *key_id = NULL;
bac598
     size_t key_id_len;
bac598
+    char *label = NULL;
bac598
+    size_t label_len;
bac598
     TALLOC_CTX *tmp_ctx;
bac598
 
bac598
     if (tok == NULL) {
bac598
@@ -579,7 +582,7 @@ errno_t sss_authtok_set_sc_from_blob(struct sss_auth_token *tok,
bac598
     ret = sss_auth_unpack_sc_blob(tmp_ctx, data, len, &pin, &pin_len,
bac598
                                   &token_name, &token_name_len,
bac598
                                   &module_name, &module_name_len,
bac598
-                                  &key_id, &key_id_len);
bac598
+                                  &key_id, &key_id_len, &label, &label_len);
bac598
     if (ret != EOK) {
bac598
         DEBUG(SSSDBG_OP_FAILURE, "sss_auth_unpack_sc_blob failed.\n");
bac598
         goto done;
bac598
@@ -588,7 +591,7 @@ errno_t sss_authtok_set_sc_from_blob(struct sss_auth_token *tok,
bac598
     ret = sss_authtok_set_sc(tok, SSS_AUTHTOK_TYPE_SC_PIN, pin, pin_len,
bac598
                              token_name, token_name_len,
bac598
                              module_name, module_name_len,
bac598
-                             key_id, key_id_len);
bac598
+                             key_id, key_id_len, label, label_len);
bac598
 
bac598
 done:
bac598
     talloc_free(tmp_ctx);
bac598
@@ -607,7 +610,7 @@ errno_t sss_authtok_set_sc_pin(struct sss_auth_token *tok, const char *pin,
bac598
     }
bac598
 
bac598
     return sss_authtok_set_sc(tok, SSS_AUTHTOK_TYPE_SC_PIN, pin, len,
bac598
-                              NULL, 0, NULL, 0, NULL, 0);
bac598
+                              NULL, 0, NULL, 0, NULL, 0, NULL, 0);
bac598
 }
bac598
 
bac598
 errno_t sss_authtok_get_sc_pin(struct sss_auth_token *tok, const char **_pin,
bac598
@@ -625,7 +628,8 @@ errno_t sss_authtok_get_sc_pin(struct sss_auth_token *tok, const char **_pin,
bac598
         return ENOENT;
bac598
     case SSS_AUTHTOK_TYPE_SC_PIN:
bac598
         ret = sss_authtok_get_sc(tok, &pin, &pin_len,
bac598
-                                 NULL, NULL, NULL, NULL, NULL, NULL);
bac598
+                                 NULL, NULL, NULL, NULL, NULL, NULL,
bac598
+                                 NULL, NULL);
bac598
         if (ret != EOK) {
bac598
             DEBUG(SSSDBG_OP_FAILURE, "sss_authtok_get_sc failed.\n");
bac598
             return ret;
bac598
@@ -663,13 +667,15 @@ errno_t sss_auth_unpack_sc_blob(TALLOC_CTX *mem_ctx,
bac598
                                  char **pin, size_t *_pin_len,
bac598
                                  char **token_name, size_t *_token_name_len,
bac598
                                  char **module_name, size_t *_module_name_len,
bac598
-                                 char **key_id, size_t *_key_id_len)
bac598
+                                 char **key_id, size_t *_key_id_len,
bac598
+                                 char **label, size_t *_label_len)
bac598
 {
bac598
     size_t c;
bac598
     uint32_t pin_len;
bac598
     uint32_t token_name_len;
bac598
     uint32_t module_name_len;
bac598
     uint32_t key_id_len;
bac598
+    uint32_t label_len;
bac598
 
bac598
     c = 0;
bac598
 
bac598
@@ -678,14 +684,16 @@ errno_t sss_auth_unpack_sc_blob(TALLOC_CTX *mem_ctx,
bac598
         token_name_len = 0;
bac598
         module_name_len = 0;
bac598
         key_id_len = 0;
bac598
+        label_len = 0;
bac598
     } else if (blob_len > 0
bac598
                 && strnlen((const char *) blob, blob_len) == blob_len - 1) {
bac598
         pin_len = blob_len;
bac598
         token_name_len = 0;
bac598
         module_name_len = 0;
bac598
         key_id_len = 0;
bac598
+        label_len = 0;
bac598
     } else {
bac598
-        if (blob_len < 4 * sizeof(uint32_t)) {
bac598
+        if (blob_len < 5 * sizeof(uint32_t)) {
bac598
             DEBUG(SSSDBG_CRIT_FAILURE, "Blob too small.\n");
bac598
             return EINVAL;
bac598
         }
bac598
@@ -694,9 +702,11 @@ errno_t sss_auth_unpack_sc_blob(TALLOC_CTX *mem_ctx,
bac598
         SAFEALIGN_COPY_UINT32(&token_name_len, blob + c, &c);
bac598
         SAFEALIGN_COPY_UINT32(&module_name_len, blob + c, &c);
bac598
         SAFEALIGN_COPY_UINT32(&key_id_len, blob + c, &c);
bac598
+        SAFEALIGN_COPY_UINT32(&label_len, blob + c, &c);
bac598
 
bac598
-        if (blob_len != 4 * sizeof(uint32_t) + pin_len + token_name_len
bac598
-                                             + module_name_len + key_id_len) {
bac598
+        if (blob_len != 5 * sizeof(uint32_t) + pin_len + token_name_len
bac598
+                                             + module_name_len + key_id_len
bac598
+                                             + label_len) {
bac598
             DEBUG(SSSDBG_CRIT_FAILURE, "Blob size mismatch.\n");
bac598
             return EINVAL;
bac598
         }
bac598
@@ -756,6 +766,25 @@ errno_t sss_auth_unpack_sc_blob(TALLOC_CTX *mem_ctx,
bac598
         *key_id = NULL;
bac598
     }
bac598
 
bac598
+    if (label_len != 0) {
bac598
+        *label = talloc_strndup(mem_ctx,
bac598
+                                      (const char *) blob + c + pin_len
bac598
+                                                              + token_name_len
bac598
+                                                              + module_name_len
bac598
+                                                              + key_id_len,
bac598
+                                      label_len);
bac598
+        if (*label == NULL) {
bac598
+            DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n");
bac598
+            talloc_free(*pin);
bac598
+            talloc_free(*token_name);
bac598
+            talloc_free(*module_name);
bac598
+            talloc_free(*key_id);
bac598
+            return ENOMEM;
bac598
+        }
bac598
+    } else {
bac598
+        *label = NULL;
bac598
+    }
bac598
+
bac598
     /* Re-calculate length for the case where \0 was missing in the blob */
bac598
     if (_pin_len != NULL) {
bac598
         *_pin_len = (*pin == NULL) ? 0 : strlen(*pin);
bac598
@@ -771,6 +800,10 @@ errno_t sss_auth_unpack_sc_blob(TALLOC_CTX *mem_ctx,
bac598
         *_key_id_len = (*key_id == NULL) ? 0 : strlen(*key_id);
bac598
     }
bac598
 
bac598
+    if (_label_len != NULL) {
bac598
+        *_label_len = (*label == NULL) ? 0 : strlen(*label);
bac598
+    }
bac598
+
bac598
     return EOK;
bac598
 }
bac598
 
bac598
@@ -778,13 +811,15 @@ errno_t sss_authtok_get_sc(struct sss_auth_token *tok,
bac598
                            const char **_pin, size_t *_pin_len,
bac598
                            const char **_token_name, size_t *_token_name_len,
bac598
                            const char **_module_name, size_t *_module_name_len,
bac598
-                           const char **_key_id, size_t *_key_id_len)
bac598
+                           const char **_key_id, size_t *_key_id_len,
bac598
+                           const char **_label, size_t *_label_len)
bac598
 {
bac598
     size_t c = 0;
bac598
     size_t pin_len;
bac598
     size_t token_name_len;
bac598
     size_t module_name_len;
bac598
     size_t key_id_len;
bac598
+    size_t label_len;
bac598
     uint32_t tmp_uint32_t;
bac598
 
bac598
     if (!tok) {
bac598
@@ -796,7 +831,7 @@ errno_t sss_authtok_get_sc(struct sss_auth_token *tok,
bac598
         return (tok->type == SSS_AUTHTOK_TYPE_EMPTY) ? ENOENT : EACCES;
bac598
     }
bac598
 
bac598
-    if (tok->length < 4 * sizeof(uint32_t)) {
bac598
+    if (tok->length < 5 * sizeof(uint32_t)) {
bac598
         DEBUG(SSSDBG_CRIT_FAILURE, "Blob too small.\n");
bac598
         return EINVAL;
bac598
     }
bac598
@@ -809,9 +844,12 @@ errno_t sss_authtok_get_sc(struct sss_auth_token *tok,
bac598
     module_name_len = tmp_uint32_t -1;
bac598
     SAFEALIGN_COPY_UINT32(&tmp_uint32_t, tok->data + c, &c);
bac598
     key_id_len = tmp_uint32_t -1;
bac598
+    SAFEALIGN_COPY_UINT32(&tmp_uint32_t, tok->data + c, &c);
bac598
+    label_len = tmp_uint32_t -1;
bac598
 
bac598
-    if (tok->length != 4 * sizeof(uint32_t) +  4 + pin_len + token_name_len
bac598
-                                         + module_name_len + key_id_len) {
bac598
+    if (tok->length != 5 * sizeof(uint32_t) +  5 + pin_len + token_name_len
bac598
+                                         + module_name_len + key_id_len
bac598
+                                         + label_len) {
bac598
         DEBUG(SSSDBG_CRIT_FAILURE, "Blob size mismatch.\n");
bac598
         return EINVAL;
bac598
     }
bac598
@@ -846,5 +884,14 @@ errno_t sss_authtok_get_sc(struct sss_auth_token *tok,
bac598
         *_key_id_len = key_id_len;
bac598
     }
bac598
 
bac598
+    if (_label != NULL) {
bac598
+        *_label = (const char *) tok->data + c + pin_len + 1
bac598
+                               + token_name_len + 1 + module_name_len + 1
bac598
+                               + key_id_len + 1;
bac598
+    }
bac598
+    if (_label_len != NULL) {
bac598
+        *_label_len = label_len;
bac598
+    }
bac598
+
bac598
     return EOK;
bac598
 }
bac598
diff --git a/src/util/authtok.h b/src/util/authtok.h
bac598
index f70c9da13..6fd3e9ef0 100644
bac598
--- a/src/util/authtok.h
bac598
+++ b/src/util/authtok.h
bac598
@@ -296,6 +296,10 @@ void sss_authtok_set_sc_keypad(struct sss_auth_token *tok);
bac598
  *                        terminated string containing the PKCS#11 key id
bac598
  * @param key_id_len      The length of the key id string, if set to 0 it will be
bac598
  *                        calculated
bac598
+ * @param label           A pointer to a const char *, that will point to a null
bac598
+ *                        terminated string containing the PKCS#11 label
bac598
+ * @param label_len       The length of the label string, if set to 0 it will be
bac598
+ *                        calculated
bac598
  *
bac598
  * @return       EOK on success
bac598
  *               EINVAL unexpected or inval input
bac598
@@ -306,7 +310,8 @@ errno_t sss_authtok_set_sc(struct sss_auth_token *tok,
bac598
                            const char *pin, size_t pin_len,
bac598
                            const char *token_name, size_t token_name_len,
bac598
                            const char *module_name, size_t module_name_len,
bac598
-                           const char *key_id, size_t key_id_len);
bac598
+                           const char *key_id, size_t key_id_len,
bac598
+                           const char *label, size_t label_len);
bac598
 /**
bac598
  * @brief Set a Smart Card authentication data, replacing any previous data
bac598
  *
bac598
@@ -342,6 +347,10 @@ errno_t sss_authtok_set_sc_from_blob(struct sss_auth_token *tok,
bac598
  *                              a null terminated string holding the PKCS#11
bac598
  *                              key id, may not be modified or freed
bac598
  * @param[out] _key_id_len      Length of the PKCS#11 key id
bac598
+ * @param[out] _label           A pointer to a const char *, that will point to
bac598
+ *                              a null terminated string holding the PKCS#11
bac598
+ *                              label, may not be modified or freed
bac598
+ * @param[out] _label_len       Length of the PKCS#11 label
bac598
  *
bac598
  * Any of the output pointers may be NULL if the caller does not need the
bac598
  * specific item.
bac598
@@ -356,7 +365,8 @@ errno_t sss_authtok_get_sc(struct sss_auth_token *tok,
bac598
                            const char **_pin, size_t *_pin_len,
bac598
                            const char **_token_name, size_t *_token_name_len,
bac598
                            const char **_module_name, size_t *_module_name_len,
bac598
-                           const char **_key_id, size_t *_key_id_len);
bac598
+                           const char **_key_id, size_t *_key_id_len,
bac598
+                           const char **_label, size_t *_label_len);
bac598
 
bac598
 
bac598
 /**
bac598
-- 
bac598
2.21.3
bac598