Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for SSH authentication #27

Closed
invidian opened this issue Mar 15, 2021 · 6 comments · Fixed by #28
Closed

Support for SSH authentication #27

invidian opened this issue Mar 15, 2021 · 6 comments · Fixed by #28

Comments

@invidian
Copy link
Contributor

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
Copy link
Contributor Author

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
Copy link
Contributor Author

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
Copy link
Owner

alonbl commented Mar 19, 2021

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
Copy link
Contributor Author

Sure, I'll have a look. Thanks!

@alonbl
Copy link
Owner

alonbl commented Mar 19, 2021

and please make the _cmd_pksign_type static.

invidian added a commit to invidian/gnupg-pkcs11-scd that referenced this issue Mar 19, 2021
This commit adds PKAUTH command support to gnupg-pkcs11-scd, so
gpg-agent with "enable-ssh-support" setting defined can act as a SSH
Agent when PKCS11 is used as a GPG backend.

Auth operation is almost the same as sign operation, except it looks
like SSH always sends data with hash algorithm signature appended at the
beginning, but the data is of different size than the signature
detection code expects, so it always fallback to default behavior, which
is to append SHA1 signature.

As having 2 different signature prefixes is incorrect, we need to
use the different default value from the sign action, which is to not
append anything in case of auth operation.

Closes alonbl#27

Signed-off-by: Mateusz Gozdek <mgozdekof@gmail.com>
@invidian
Copy link
Contributor Author

Created #28.

invidian added a commit to invidian/gnupg-pkcs11-scd that referenced this issue Mar 19, 2021
This commit adds PKAUTH command support to gnupg-pkcs11-scd, so
gpg-agent with "enable-ssh-support" setting defined can act as a SSH
Agent when PKCS11 is used as a GPG backend.

Auth operation is almost the same as sign operation, except it looks
like SSH always sends data with hash algorithm signature appended at the
beginning, but the data is of different size than the signature
detection code expects, so it always fallback to default behavior, which
is to append SHA1 signature.

As having 2 different signature prefixes is incorrect, we need to
use the different default value from the sign action, which is to not
append anything in case of auth operation.

Closes alonbl#27

Signed-off-by: Mateusz Gozdek <mgozdekof@gmail.com>
invidian added a commit to invidian/gnupg-pkcs11-scd that referenced this issue Mar 19, 2021
This commit adds PKAUTH command support to gnupg-pkcs11-scd, so
gpg-agent with "enable-ssh-support" setting defined can act as a SSH
Agent when PKCS11 is used as a GPG backend.

Auth operation is almost the same as sign operation, except it looks
like SSH always sends data with hash algorithm signature appended at the
beginning, but the data is of different size than the signature
detection code expects, so it always fallback to default behavior, which
is to append SHA1 signature.

As having 2 different signature prefixes is incorrect, we need to
use the different default value from the sign action, which is to not
append anything in case of auth operation.

Closes alonbl#27

Signed-off-by: Mateusz Gozdek <mgozdekof@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants