alonbl / gnupg-pkcs11-scd

PKCS#11 GnuPG SCD
http://gnupg-pkcs11.sourceforge.net/
Other
68 stars 17 forks source link

Support for SSH authentication #27

Closed invidian closed 3 years ago

invidian commented 3 years ago

It seems that right now when you add enable-ssh-support to ~/.gnupg/gpg-agent.conf and the right keygrip to .gnupg/sshcontrol, listing SSH keys sort of works:

$ ssh-add -L
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDsRFFnVTl5kuLYKLgAWTg7KR9aDdDuxkvJgKnQklm/hfnGQy+1bz5mqXNUtPQKnxqBmYDljTTPzCce67C+GnUi5VsVBhsc9TrKJBFLpBN0Tkvi7mMPyP2ULjQ/jwm99MBKDs66dkBOCDPGHtMNesKM49QeIAuz8aRdxLMTe0X3EP5qbftDCpK7VJoG52ecCzssxnc4ec6hYjGHF7n211cZSFto19X4Idl/YSmdfksa64GbLrRZ7QKP9GPxI4zjWbxsAJMAJsoBRChFzT7VzKXQlay4jjfiDxIIlY+HKwISijR1LJISHQa5uCNkgEmeljAE8Ts31gjejhj8/UoPMyNr (none)

Debug logs:

gnupg-pkcs11-scd[956916]: chan_0 <- SERIALNO
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: pkcs11h_token_enumTokenIds entry method=1, p_token_id_list=0x7ffe01aac1c0
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: _pkcs11h_session_getSlotList entry provider=0x557b79910d60, token_present=1, pSlotList=0x7ffe01aac088, pulCount=0x7ffe01aac090
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: _pkcs11h_session_getSlotList return rv=0-'CKR_OK' *pulCount=1
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: _pkcs11h_token_getTokenId entry p_token_id=0x557b7997cfe8
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: _pkcs11h_token_newTokenId entry p_token_id=0x7ffe01aac020
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: _pkcs11h_token_newTokenId return rv=0-'CKR_OK', *p_token_id=0x557b7997d900
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: _pkcs11h_token_getTokenId return rv=0-'CKR_OK', *p_token_id=0x557b7997d900
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: pkcs11h_token_enumTokenIds return rv=0-'CKR_OK', *p_token_id_list=0x7ffe01aac1c0
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: pkcs11h_token_serializeTokenId entry sz=(nil), *max=0000000000000000, token_id=0x557b7997d900
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: pkcs11h_token_serializeTokenId return rv=0-'CKR_OK', *max=0000000000000062, sz='(null)'
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: pkcs11h_token_serializeTokenId entry sz=0x7f419c009120, *max=0000000000000062, token_id=0x557b7997d900
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: pkcs11h_token_serializeTokenId return rv=0-'CKR_OK', *max=0000000000000062, sz='piv_II/PKCS\x2315\x20emulated/498c934e2cd3f42b/Mateusz\x20Gozdek\x27s\x20Authenticati\x2E\x2E\x2E'
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: pkcs11h_token_freeTokenIdList entry token_id_list=0x557b7997cfe0
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: pkcs11h_token_freeTokenId entry certificate_id=0x557b7997d900
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: pkcs11h_token_freeTokenId return
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: pkcs11h_token_freeTokenIdList return
gnupg-pkcs11-scd[956916]: chan_0 -> S SERIALNO D2760001240111503131B68474111111 0
gnupg-pkcs11-scd[956916]: chan_0 -> OK
gnupg-pkcs11-scd[956916]: chan_0 <- GETINFO card_list
gnupg-pkcs11-scd[956916]: chan_0 -> ERR 79 Invalid data <Unspecified source>
gnupg-pkcs11-scd[956916]: chan_0 <- RESTART
gnupg-pkcs11-scd[956916]: chan_0 -> OK

However, SSH authentication does not work:

$ ssh -o ControlMaster=ask -o PreferredAuthentications=publickey localhost echo -n
sign_and_send_pubkey: signing failed for RSA "(none)" from agent: agent refused operation
invidian@localhost: Permission denied (publickey,password).

Debug logs:

gnupg-pkcs11-scd[956916]: chan_0 <- SERIALNO
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: pkcs11h_token_enumTokenIds entry method=1, p_token_id_list=0x7ffe01aac1c0
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: _pkcs11h_session_getSlotList entry provider=0x557b79910d60, token_present=1, pSlotList=0x7ffe01aac088, pulCount=0x7ffe01aac090
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: _pkcs11h_session_getSlotList return rv=0-'CKR_OK' *pulCount=1
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: _pkcs11h_token_getTokenId entry p_token_id=0x557b7997d8c8
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: _pkcs11h_token_newTokenId entry p_token_id=0x7ffe01aac020
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: _pkcs11h_token_newTokenId return rv=0-'CKR_OK', *p_token_id=0x557b7997d900
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: _pkcs11h_token_getTokenId return rv=0-'CKR_OK', *p_token_id=0x557b7997d900
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: pkcs11h_token_enumTokenIds return rv=0-'CKR_OK', *p_token_id_list=0x7ffe01aac1c0
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: pkcs11h_token_serializeTokenId entry sz=(nil), *max=0000000000000000, token_id=0x557b7997d900
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: pkcs11h_token_serializeTokenId return rv=0-'CKR_OK', *max=0000000000000062, sz='(null)'
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: pkcs11h_token_serializeTokenId entry sz=0x7f419c009120, *max=0000000000000062, token_id=0x557b7997d900
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: pkcs11h_token_serializeTokenId return rv=0-'CKR_OK', *max=0000000000000062, sz='piv_II/PKCS\x2315\x20emulated/498c934e2cd3f42b/Mateusz\x20Gozdek\x27s\x20Authenticati\x2E\x2E\x2E'
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: pkcs11h_token_freeTokenIdList entry token_id_list=0x557b7997d8c0
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: pkcs11h_token_freeTokenId entry certificate_id=0x557b7997d900
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: pkcs11h_token_freeTokenId return
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: pkcs11h_token_freeTokenIdList return
gnupg-pkcs11-scd[956916]: chan_0 -> S SERIALNO D2760001240111503131B68474111111 0
gnupg-pkcs11-scd[956916]: chan_0 -> OK
gnupg-pkcs11-scd[956916]: chan_0 <- GETINFO card_list
gnupg-pkcs11-scd[956916]: chan_0 -> ERR 79 Invalid data <Unspecified source>
gnupg-pkcs11-scd[956916]: chan_0 <- SERIALNO --demand=D2760001240111503131B68474111111
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: pkcs11h_token_enumTokenIds entry method=1, p_token_id_list=0x7ffe01aac1c0
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: _pkcs11h_session_getSlotList entry provider=0x557b79910d60, token_present=1, pSlotList=0x7ffe01aac088, pulCount=0x7ffe01aac090
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: _pkcs11h_session_getSlotList return rv=0-'CKR_OK' *pulCount=1
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: _pkcs11h_token_getTokenId entry p_token_id=0x557b7997cfe8
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: _pkcs11h_token_newTokenId entry p_token_id=0x7ffe01aac020
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: _pkcs11h_token_newTokenId return rv=0-'CKR_OK', *p_token_id=0x557b7997d900
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: _pkcs11h_token_getTokenId return rv=0-'CKR_OK', *p_token_id=0x557b7997d900
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: pkcs11h_token_enumTokenIds return rv=0-'CKR_OK', *p_token_id_list=0x7ffe01aac1c0
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: pkcs11h_token_serializeTokenId entry sz=(nil), *max=0000000000000000, token_id=0x557b7997d900
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: pkcs11h_token_serializeTokenId return rv=0-'CKR_OK', *max=0000000000000062, sz='(null)'
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: pkcs11h_token_serializeTokenId entry sz=0x7f419c009120, *max=0000000000000062, token_id=0x557b7997d900
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: pkcs11h_token_serializeTokenId return rv=0-'CKR_OK', *max=0000000000000062, sz='piv_II/PKCS\x2315\x20emulated/498c934e2cd3f42b/Mateusz\x20Gozdek\x27s\x20Authenticati\x2E\x2E\x2E'
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: pkcs11h_token_freeTokenIdList entry token_id_list=0x557b7997cfe0
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: pkcs11h_token_freeTokenId entry certificate_id=0x557b7997d900
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: pkcs11h_token_freeTokenId return
gnupg-pkcs11-scd[956916.2890780032]: PKCS#11: pkcs11h_token_freeTokenIdList return
gnupg-pkcs11-scd[956916]: chan_0 -> S SERIALNO D2760001240111503131B68474111111 0
gnupg-pkcs11-scd[956916]: chan_0 -> OK
gnupg-pkcs11-scd[956916]: chan_0 <- SETDATA 3051300D0609608648016503040203050004405D4778142FFEB2E6E215544214A79E155D4BAFC9FECCB9CA5804B5777C9A00DE39205FCF88CEC767B740919F574DA6B35FF98A5EDC5EB4CA9989ACB377A47E2F
gnupg-pkcs11-scd[956916]: chan_0 -> OK
gnupg-pkcs11-scd[956916]: chan_0 <- PKAUTH piv_II/PKCS\x2315\x20emulated/498c934e2cd3f42b/Mateusz\x20Gozdek\x27s\x20Authenticati\x2E\x2E\x2E/01
gnupg-pkcs11-scd[956916]: chan_0 -> ERR 536870992 Unspecific Assuan server fault <User defined source 1> - no handler registered
gnupg-pkcs11-scd[956916]: chan_0 <- RESTART
gnupg-pkcs11-scd[956916]: chan_0 -> OK

Would it be difficult to get this to work? Do you have some pointer how this could be done?

My motivation was to simplify the setup a bit, to be able to not use ssh-agent at all. I was hoping GPG could handle entering PIN and unplugged smart card better than ssh-agent with PKCS#11.

invidian commented 3 years ago

After quick look at the code, it seems that for first error, we would have to implement card_list command in cmd_getinfo function, which I guess should be fairly simple.

For 2nd one, we would need to implement PKAUTH command.

I also found https://sourceforge.net/p/gnupg-pkcs11/mailman/message/393565/ and https://sourceforge.net/p/gnupg-pkcs11/mailman/message/393567/. I wonder if anything changed since then. It seems using cmd_pksign for PKAUTH sort of works, but not completely.

invidian commented 3 years ago

After quick look at the code, it seems that for first error, we would have to implement card_list command in cmd_getinfo function, which I guess should be fairly simple.

It seems this is optional for functioning.

For 2nd one, we would need to implement PKAUTH command.

I also found https://sourceforge.net/p/gnupg-pkcs11/mailman/message/393565/ and https://sourceforge.net/p/gnupg-pkcs11/mailman/message/393567/. I wonder if anything changed since then. It seems using cmd_pksign for PKAUTH sort of works, but not completely.

Once I changed argument for _get_certificate_by_name from OPENPGP_SIGN to OPENPGP_AUTH, everything works fine.

Final patch:

From 530880802537664531ef1682c431e41e7ddcb647 Mon Sep 17 00:00:00 2001
From: Mateusz Gozdek <mgozdekof@gmail.com>
Date: Mon, 15 Mar 2021 12:34:49 +0100
Subject: [PATCH] test auth

Signed-off-by: Mateusz Gozdek <mgozdekof@gmail.com>
---
 gnupg-pkcs11-scd/command.c  | 41 ++++++++++++++++++++++++-------------
 gnupg-pkcs11-scd/command.h  |  1 +
 gnupg-pkcs11-scd/scdaemon.c |  2 +-
 3 files changed, 29 insertions(+), 15 deletions(-)

diff --git gnupg-pkcs11-scd/command.c gnupg-pkcs11-scd/command.c
index 331a005..ebc9ffb 100644
--- gnupg-pkcs11-scd/command.c
+++ gnupg-pkcs11-scd/command.c
@@ -52,6 +52,17 @@
 #define OPENPGP_ENCR 2
 #define OPENPGP_AUTH 3

+typedef enum {
+       INJECT_NONE=0,
+       INJECT_RMD160,
+       INJECT_MD5,
+       INJECT_SHA1,
+       INJECT_SHA224,
+       INJECT_SHA256,
+       INJECT_SHA384,
+       INJECT_SHA512
+} inject;
+
 /**
    @file
    Implementation of assuan commands. Currently, only one card is supported,
@@ -974,8 +985,7 @@ cleanup:
        return gpg_error (error);
 }

-/** Sign data (set by SETDATA) with certificate id in line. */
-gpg_error_t cmd_pksign (assuan_context_t ctx, char *line)
+gpg_error_t _cmd_pksign_type (assuan_context_t ctx, char *line, int typehint, inject injectDefault)
 {
        static const unsigned char rmd160_prefix[] = /* (1.3.36.3.2.1) */
                { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03,
@@ -1013,16 +1023,7 @@ gpg_error_t cmd_pksign (assuan_context_t ctx, char *line)
        unsigned char *sig = NULL;
        size_t sig_len;
        char hash[100] = "";
-       enum {
-               INJECT_NONE,
-               INJECT_RMD160,
-               INJECT_MD5,
-               INJECT_SHA1,
-               INJECT_SHA224,
-               INJECT_SHA256,
-               INJECT_SHA384,
-               INJECT_SHA512
-       } inject = INJECT_NONE;
+       inject inject;

        if (data->data == NULL) {
                error = GPG_ERR_INV_DATA;
@@ -1133,7 +1134,7 @@ gpg_error_t cmd_pksign (assuan_context_t ctx, char *line)
                         * unknown hash algorithm;
                         * gnupg's scdaemon forces to SHA1
                         */
-                       inject = INJECT_SHA1;
+                       inject = injectDefault;
                }
        }

@@ -1197,7 +1198,7 @@ gpg_error_t cmd_pksign (assuan_context_t ctx, char *line)
                (error = _get_certificate_by_name (
                        ctx,
                        line,
-                       OPENPGP_SIGN,
+                       typehint,
                        &cert_id,
                        NULL
                )) != GPG_ERR_NO_ERROR
@@ -1298,6 +1299,18 @@ cleanup:
        return gpg_error (error);
 }

+/** Sign data (set by SETDATA) with certificate id in line. */
+gpg_error_t cmd_pksign (assuan_context_t ctx, char *line)
+{
+  return _cmd_pksign_type(ctx, line, OPENPGP_SIGN, INJECT_SHA1);
+}
+
+/** Sign data (set by SETDATA) with certificate id in line. */
+gpg_error_t cmd_pkauth (assuan_context_t ctx, char *line)
+{
+    return _cmd_pksign_type(ctx, line, OPENPGP_AUTH, INJECT_NONE);
+}
+
 /** Decrypt data (set by SETDATA) with certificate id in line. */
 gpg_error_t cmd_pkdecrypt (assuan_context_t ctx, char *line)
 {
diff --git gnupg-pkcs11-scd/command.h gnupg-pkcs11-scd/command.h
index cd17663..7d25798 100644
--- gnupg-pkcs11-scd/command.h
+++ gnupg-pkcs11-scd/command.h
@@ -49,6 +49,7 @@ gpg_error_t cmd_readcert (assuan_context_t ctx, char *line);
 gpg_error_t cmd_readkey (assuan_context_t ctx, char *line);
 gpg_error_t cmd_setdata (assuan_context_t ctx, char *line);
 gpg_error_t cmd_pksign (assuan_context_t ctx, char *line);
+gpg_error_t cmd_pkauth (assuan_context_t ctx, char *line);
 gpg_error_t cmd_pkdecrypt (assuan_context_t ctx, char *line);
 gpg_error_t cmd_random (assuan_context_t ctx, char *line);
 gpg_error_t cmd_checkpin (assuan_context_t ctx, char *line);
diff --git gnupg-pkcs11-scd/scdaemon.c gnupg-pkcs11-scd/scdaemon.c
index 760ed63..6a026f3 100644
--- gnupg-pkcs11-scd/scdaemon.c
+++ gnupg-pkcs11-scd/scdaemon.c
@@ -125,7 +125,7 @@ register_commands (const assuan_context_t ctx)
                { "KEY-DATA",   NULL, NULL },
                { "SETDATA",    cmd_setdata, NULL },
                { "PKSIGN",     cmd_pksign, NULL },
-               { "PKAUTH",     NULL, NULL },
+               { "PKAUTH",     cmd_pkauth, NULL },
                { "PKDECRYPT",  cmd_pkdecrypt, NULL },
                { "INPUT",      NULL, NULL },
                { "OUTPUT",     NULL, NULL },
--
2.30.2

I'm curious if I missed something and if such patch would be accepted.

alonbl commented 3 years ago

Thanks, looks good!

Can you please create a proper pull request so I can merge it as-is?

Can you please try to drop the typedef and use enum directly?

invidian commented 3 years ago

Sure, I'll have a look. Thanks!

alonbl commented 3 years ago

and please make the _cmd_pksign_type static.

invidian commented 3 years ago

Created https://github.com/alonbl/gnupg-pkcs11-scd/pull/28.