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

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