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

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