Skip to content

Commit 4448a29

Browse files
committed
upstream: Make it possible to load certs from PKCS#11 tokens
Adds a protocol extension to allow grafting certificates supplied by ssh-add to keys loaded from PKCS#11 tokens in the agent. feedback/ok markus@ OpenBSD-Commit-ID: bb5433cd28ede2bc910996eb3c0b53e20f86037f
1 parent 881d9c6 commit 4448a29

8 files changed

+299
-70
lines changed

PROTOCOL.agent

+32-1
Original file line numberDiff line numberDiff line change
@@ -81,4 +81,35 @@ the constraint is:
8181

8282
This option is only valid for XMSS keys.
8383

84-
$OpenBSD: PROTOCOL.agent,v 1.20 2023/10/03 23:56:10 djm Exp $
84+
3. associated-certs-v00@openssh.com key constraint extension
85+
86+
The key constraint extension allows certificates to be associated
87+
with private keys as they are loaded from a PKCS#11 token.
88+
89+
byte SSH_AGENT_CONSTRAIN_EXTENSION (0xff)
90+
string associated-certs-v00@openssh.com
91+
bool certs_only
92+
string certsblob
93+
94+
Where "certsblob" constists of one or more certificates encoded as public
95+
key blobs:
96+
97+
string[] certificates
98+
99+
This extension is only valid for SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED
100+
requests. When an agent receives this extension, it will attempt to match
101+
each certificate in the request with a corresponding private key loaded
102+
from the requested PKCS#11 token. When a matching key is found, the
103+
agent will graft the certificate contents to the token-hosted private key
104+
and store the result for subsequent use by regular agent operations.
105+
106+
If the "certs_only" flag is set, then this extension will cause ONLY
107+
the resultant certificates to be loaded to the agent. The default
108+
behaviour is to load the PKCS#11-hosted private key as well as the
109+
resultant certificate.
110+
111+
A SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED will return SSH_AGENT_SUCCESS
112+
if any key (plain private or certificate) was successfully loaded, or
113+
SSH_AGENT_FAILURE if no key was loaded.
114+
115+
$OpenBSD: PROTOCOL.agent,v 1.21 2023/12/18 14:46:56 djm Exp $

authfd.c

+32-8
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: authfd.c,v 1.133 2023/03/09 21:06:24 jcs Exp $ */
1+
/* $OpenBSD: authfd.c,v 1.134 2023/12/18 14:46:56 djm Exp $ */
22
/*
33
* Author: Tatu Ylonen <ylo@cs.hut.fi>
44
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -504,9 +504,10 @@ encode_dest_constraint(struct sshbuf *m, const struct dest_constraint *dc)
504504
}
505505

506506
static int
507-
encode_constraints(struct sshbuf *m, u_int life, u_int confirm, u_int maxsign,
508-
const char *provider, struct dest_constraint **dest_constraints,
509-
size_t ndest_constraints)
507+
encode_constraints(struct sshbuf *m, u_int life, u_int confirm,
508+
u_int maxsign, const char *provider,
509+
struct dest_constraint **dest_constraints, size_t ndest_constraints,
510+
int cert_only, struct sshkey **certs, size_t ncerts)
510511
{
511512
int r;
512513
struct sshbuf *b = NULL;
@@ -550,6 +551,27 @@ encode_constraints(struct sshbuf *m, u_int life, u_int confirm, u_int maxsign,
550551
"restrict-destination-v00@openssh.com")) != 0 ||
551552
(r = sshbuf_put_stringb(m, b)) != 0)
552553
goto out;
554+
sshbuf_free(b);
555+
b = NULL;
556+
}
557+
if (ncerts != 0) {
558+
if ((b = sshbuf_new()) == NULL) {
559+
r = SSH_ERR_ALLOC_FAIL;
560+
goto out;
561+
}
562+
for (i = 0; i < ncerts; i++) {
563+
if ((r = sshkey_puts(certs[i], b)) != 0)
564+
goto out;
565+
}
566+
if ((r = sshbuf_put_u8(m,
567+
SSH_AGENT_CONSTRAIN_EXTENSION)) != 0 ||
568+
(r = sshbuf_put_cstring(m,
569+
"associated-certs-v00@openssh.com")) != 0 ||
570+
(r = sshbuf_put_u8(m, cert_only != 0)) != 0 ||
571+
(r = sshbuf_put_stringb(m, b)) != 0)
572+
goto out;
573+
sshbuf_free(b);
574+
b = NULL;
553575
}
554576
r = 0;
555577
out:
@@ -607,7 +629,7 @@ ssh_add_identity_constrained(int sock, struct sshkey *key,
607629
}
608630
if (constrained &&
609631
(r = encode_constraints(msg, life, confirm, maxsign,
610-
provider, dest_constraints, ndest_constraints)) != 0)
632+
provider, dest_constraints, ndest_constraints, 0, NULL, 0)) != 0)
611633
goto out;
612634
if ((r = ssh_request_reply_decode(sock, msg)) != 0)
613635
goto out;
@@ -662,10 +684,11 @@ ssh_remove_identity(int sock, const struct sshkey *key)
662684
int
663685
ssh_update_card(int sock, int add, const char *reader_id, const char *pin,
664686
u_int life, u_int confirm,
665-
struct dest_constraint **dest_constraints, size_t ndest_constraints)
687+
struct dest_constraint **dest_constraints, size_t ndest_constraints,
688+
int cert_only, struct sshkey **certs, size_t ncerts)
666689
{
667690
struct sshbuf *msg;
668-
int r, constrained = (life || confirm || dest_constraints);
691+
int r, constrained = (life || confirm || dest_constraints || certs);
669692
u_char type;
670693

671694
if (add) {
@@ -683,7 +706,8 @@ ssh_update_card(int sock, int add, const char *reader_id, const char *pin,
683706
goto out;
684707
if (constrained &&
685708
(r = encode_constraints(msg, life, confirm, 0, NULL,
686-
dest_constraints, ndest_constraints)) != 0)
709+
dest_constraints, ndest_constraints,
710+
cert_only, certs, ncerts)) != 0)
687711
goto out;
688712
if ((r = ssh_request_reply_decode(sock, msg)) != 0)
689713
goto out;

authfd.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: authfd.h,v 1.51 2021/12/19 22:10:24 djm Exp $ */
1+
/* $OpenBSD: authfd.h,v 1.52 2023/12/18 14:46:56 djm Exp $ */
22

33
/*
44
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -56,7 +56,8 @@ int ssh_remove_identity(int sock, const struct sshkey *key);
5656
int ssh_update_card(int sock, int add, const char *reader_id,
5757
const char *pin, u_int life, u_int confirm,
5858
struct dest_constraint **dest_constraints,
59-
size_t ndest_constraints);
59+
size_t ndest_constraints,
60+
int cert_only, struct sshkey **certs, size_t ncerts);
6061
int ssh_remove_all_identities(int sock, int version);
6162

6263
int ssh_agent_sign(int sock, const struct sshkey *key,

ssh-add.1

+11-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.\" $OpenBSD: ssh-add.1,v 1.84 2022/02/04 02:49:17 dtucker Exp $
1+
.\" $OpenBSD: ssh-add.1,v 1.85 2023/12/18 14:46:56 djm Exp $
22
.\"
33
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
44
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -35,15 +35,15 @@
3535
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3636
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737
.\"
38-
.Dd $Mdocdate: February 4 2022 $
38+
.Dd $Mdocdate: December 18 2023 $
3939
.Dt SSH-ADD 1
4040
.Os
4141
.Sh NAME
4242
.Nm ssh-add
4343
.Nd adds private key identities to the OpenSSH authentication agent
4444
.Sh SYNOPSIS
4545
.Nm ssh-add
46-
.Op Fl cDdKkLlqvXx
46+
.Op Fl cCDdKkLlqvXx
4747
.Op Fl E Ar fingerprint_hash
4848
.Op Fl H Ar hostkey_file
4949
.Op Fl h Ar destination_constraint
@@ -52,6 +52,8 @@
5252
.Op Ar
5353
.Nm ssh-add
5454
.Fl s Ar pkcs11
55+
.Op Fl vC
56+
.Op Ar certificate ...
5557
.Nm ssh-add
5658
.Fl e Ar pkcs11
5759
.Nm ssh-add
@@ -100,6 +102,9 @@ Confirmation is performed by
100102
Successful confirmation is signaled by a zero exit status from
101103
.Xr ssh-askpass 1 ,
102104
rather than text entered into the requester.
105+
.It Fl C
106+
When loading keys into or deleting keys from the agent, process
107+
certificates only and skip plain keys.
103108
.It Fl D
104109
Deletes all identities from the agent.
105110
.It Fl d
@@ -228,6 +233,9 @@ internal USB HID support.
228233
.It Fl s Ar pkcs11
229234
Add keys provided by the PKCS#11 shared library
230235
.Ar pkcs11 .
236+
Certificate files may optionally be listed as command-line arguments.
237+
If these are present, then they will be loaded into the agent using any
238+
corresponding private keys loaded from the PKCS#11 token.
231239
.It Fl T Ar pubkey ...
232240
Tests whether the private keys that correspond to the specified
233241
.Ar pubkey

0 commit comments

Comments
 (0)