1 /* $NetBSD: ssh-pkcs11-client.c,v 1.16 2020/02/27 00:24:40 christos Exp $ */ 2 /* $OpenBSD: ssh-pkcs11-client.c,v 1.16 2020/01/25 00:03:36 djm Exp $ */ 3 /* 4 * Copyright (c) 2010 Markus Friedl. All rights reserved. 5 * Copyright (c) 2014 Pedro Martelletto. All rights reserved. 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 #include "includes.h" 20 __RCSID("$NetBSD: ssh-pkcs11-client.c,v 1.16 2020/02/27 00:24:40 christos Exp $"); 21 22 #include <sys/types.h> 23 #include <sys/time.h> 24 #include <sys/socket.h> 25 26 #include <stdarg.h> 27 #include <string.h> 28 #include <unistd.h> 29 #include <errno.h> 30 31 #include <openssl/ecdsa.h> 32 #include <openssl/rsa.h> 33 34 #include "pathnames.h" 35 #include "xmalloc.h" 36 #include "sshbuf.h" 37 #include "log.h" 38 #include "misc.h" 39 #include "sshkey.h" 40 #include "authfd.h" 41 #include "atomicio.h" 42 #include "ssh-pkcs11.h" 43 #include "ssherr.h" 44 45 /* borrows code from sftp-server and ssh-agent */ 46 47 static int fd = -1; 48 static pid_t pid = -1; 49 50 static void 51 send_msg(struct sshbuf *m) 52 { 53 u_char buf[4]; 54 size_t mlen = sshbuf_len(m); 55 int r; 56 57 POKE_U32(buf, mlen); 58 if (atomicio(vwrite, fd, buf, 4) != 4 || 59 atomicio(vwrite, fd, sshbuf_mutable_ptr(m), 60 sshbuf_len(m)) != sshbuf_len(m)) 61 error("write to helper failed"); 62 if ((r = sshbuf_consume(m, mlen)) != 0) 63 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 64 } 65 66 static int 67 recv_msg(struct sshbuf *m) 68 { 69 u_int l, len; 70 u_char c, buf[1024]; 71 int r; 72 73 if ((len = atomicio(read, fd, buf, 4)) != 4) { 74 error("read from helper failed: %u", len); 75 return (0); /* XXX */ 76 } 77 len = PEEK_U32(buf); 78 if (len > 256 * 1024) 79 fatal("response too long: %u", len); 80 /* read len bytes into m */ 81 sshbuf_reset(m); 82 while (len > 0) { 83 l = len; 84 if (l > sizeof(buf)) 85 l = sizeof(buf); 86 if (atomicio(read, fd, buf, l) != l) { 87 error("response from helper failed."); 88 return (0); /* XXX */ 89 } 90 if ((r = sshbuf_put(m, buf, l)) != 0) 91 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 92 len -= l; 93 } 94 if ((r = sshbuf_get_u8(m, &c)) != 0) 95 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 96 return c; 97 } 98 99 int 100 pkcs11_init(int interactive) 101 { 102 return (0); 103 } 104 105 void 106 pkcs11_terminate(void) 107 { 108 if (fd >= 0) 109 close(fd); 110 } 111 112 static int 113 rsa_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, int padding) 114 { 115 struct sshkey *key = NULL; 116 struct sshbuf *msg = NULL; 117 u_char *blob = NULL, *signature = NULL; 118 size_t blen, slen = 0; 119 int r, ret = -1; 120 121 if (padding != RSA_PKCS1_PADDING) 122 goto fail; 123 key = sshkey_new(KEY_UNSPEC); 124 if (key == NULL) { 125 error("%s: sshkey_new failed", __func__); 126 goto fail; 127 } 128 key->type = KEY_RSA; 129 RSA_up_ref(rsa); 130 key->rsa = rsa; 131 if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) { 132 error("%s: sshkey_to_blob: %s", __func__, ssh_err(r)); 133 goto fail; 134 } 135 if ((msg = sshbuf_new()) == NULL) 136 fatal("%s: sshbuf_new failed", __func__); 137 if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_SIGN_REQUEST)) != 0 || 138 (r = sshbuf_put_string(msg, blob, blen)) != 0 || 139 (r = sshbuf_put_string(msg, from, flen)) != 0 || 140 (r = sshbuf_put_u32(msg, 0)) != 0) 141 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 142 send_msg(msg); 143 sshbuf_reset(msg); 144 145 if (recv_msg(msg) == SSH2_AGENT_SIGN_RESPONSE) { 146 if ((r = sshbuf_get_string(msg, &signature, &slen)) != 0) 147 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 148 if (slen <= (size_t)RSA_size(rsa)) { 149 memcpy(to, signature, slen); 150 ret = slen; 151 } 152 free(signature); 153 } 154 fail: 155 free(blob); 156 sshkey_free(key); 157 sshbuf_free(msg); 158 return (ret); 159 } 160 161 static ECDSA_SIG * 162 ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv, 163 const BIGNUM *rp, EC_KEY *ec) 164 { 165 struct sshkey *key = NULL; 166 struct sshbuf *msg = NULL; 167 ECDSA_SIG *ret = NULL; 168 const u_char *cp; 169 u_char *blob = NULL, *signature = NULL; 170 size_t blen, slen = 0; 171 int r, nid; 172 173 nid = sshkey_ecdsa_key_to_nid(ec); 174 if (nid < 0) { 175 error("%s: couldn't get curve nid", __func__); 176 goto fail; 177 } 178 179 key = sshkey_new(KEY_UNSPEC); 180 if (key == NULL) { 181 error("%s: sshkey_new failed", __func__); 182 goto fail; 183 } 184 key->ecdsa = ec; 185 key->ecdsa_nid = nid; 186 key->type = KEY_ECDSA; 187 EC_KEY_up_ref(ec); 188 189 if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) { 190 error("%s: sshkey_to_blob: %s", __func__, ssh_err(r)); 191 goto fail; 192 } 193 if ((msg = sshbuf_new()) == NULL) 194 fatal("%s: sshbuf_new failed", __func__); 195 if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_SIGN_REQUEST)) != 0 || 196 (r = sshbuf_put_string(msg, blob, blen)) != 0 || 197 (r = sshbuf_put_string(msg, dgst, dgst_len)) != 0 || 198 (r = sshbuf_put_u32(msg, 0)) != 0) 199 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 200 send_msg(msg); 201 sshbuf_reset(msg); 202 203 if (recv_msg(msg) == SSH2_AGENT_SIGN_RESPONSE) { 204 if ((r = sshbuf_get_string(msg, &signature, &slen)) != 0) 205 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 206 cp = signature; 207 ret = d2i_ECDSA_SIG(NULL, &cp, slen); 208 free(signature); 209 } 210 211 fail: 212 free(blob); 213 sshkey_free(key); 214 sshbuf_free(msg); 215 return (ret); 216 } 217 218 static RSA_METHOD *helper_rsa; 219 static EC_KEY_METHOD *helper_ecdsa; 220 221 /* redirect private key crypto operations to the ssh-pkcs11-helper */ 222 static void 223 wrap_key(struct sshkey *k) 224 { 225 if (k->type == KEY_RSA) 226 RSA_set_method(k->rsa, helper_rsa); 227 else if (k->type == KEY_ECDSA) 228 EC_KEY_set_method(k->ecdsa, helper_ecdsa); 229 else 230 fatal("%s: unknown key type", __func__); 231 } 232 233 static int 234 pkcs11_start_helper_methods(void) 235 { 236 if (helper_ecdsa != NULL) 237 return (0); 238 239 int (*orig_sign)(int, const unsigned char *, int, unsigned char *, 240 unsigned int *, const BIGNUM *, const BIGNUM *, EC_KEY *) = NULL; 241 if (helper_ecdsa != NULL) 242 return (0); 243 helper_ecdsa = EC_KEY_METHOD_new(EC_KEY_OpenSSL()); 244 if (helper_ecdsa == NULL) 245 return (-1); 246 EC_KEY_METHOD_get_sign(helper_ecdsa, &orig_sign, NULL, NULL); 247 EC_KEY_METHOD_set_sign(helper_ecdsa, orig_sign, NULL, ecdsa_do_sign); 248 249 if ((helper_rsa = RSA_meth_dup(RSA_get_default_method())) == NULL) 250 fatal("%s: RSA_meth_dup failed", __func__); 251 if (!RSA_meth_set1_name(helper_rsa, "ssh-pkcs11-helper") || 252 !RSA_meth_set_priv_enc(helper_rsa, rsa_encrypt)) 253 fatal("%s: failed to prepare method", __func__); 254 255 return (0); 256 } 257 258 static int 259 pkcs11_start_helper(void) 260 { 261 int pair[2]; 262 const char *helper, *verbosity = NULL; 263 264 if (log_level_get() >= SYSLOG_LEVEL_DEBUG1) 265 verbosity = "-vvv"; 266 267 if (pkcs11_start_helper_methods() == -1) { 268 error("pkcs11_start_helper_methods failed"); 269 return (-1); 270 } 271 272 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) { 273 error("socketpair: %s", strerror(errno)); 274 return (-1); 275 } 276 if ((pid = fork()) == -1) { 277 error("fork: %s", strerror(errno)); 278 return (-1); 279 } else if (pid == 0) { 280 if ((dup2(pair[1], STDIN_FILENO) == -1) || 281 (dup2(pair[1], STDOUT_FILENO) == -1)) { 282 fprintf(stderr, "dup2: %s\n", strerror(errno)); 283 _exit(1); 284 } 285 close(pair[0]); 286 close(pair[1]); 287 helper = getenv("SSH_PKCS11_HELPER"); 288 if (helper == NULL || strlen(helper) == 0) 289 helper = _PATH_SSH_PKCS11_HELPER; 290 debug("%s: starting %s %s", __func__, helper, 291 verbosity == NULL ? "" : verbosity); 292 execlp(helper, helper, verbosity, (char *)NULL); 293 fprintf(stderr, "exec: %s: %s\n", helper, strerror(errno)); 294 _exit(1); 295 } 296 close(pair[1]); 297 fd = pair[0]; 298 return (0); 299 } 300 301 int 302 pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp, 303 char ***labelsp) 304 { 305 struct sshkey *k; 306 int r, type; 307 u_char *blob; 308 char *label; 309 size_t blen; 310 u_int nkeys, i; 311 struct sshbuf *msg; 312 313 if (fd < 0 && pkcs11_start_helper() < 0) 314 return (-1); 315 316 if ((msg = sshbuf_new()) == NULL) 317 fatal("%s: sshbuf_new failed", __func__); 318 if ((r = sshbuf_put_u8(msg, SSH_AGENTC_ADD_SMARTCARD_KEY)) != 0 || 319 (r = sshbuf_put_cstring(msg, name)) != 0 || 320 (r = sshbuf_put_cstring(msg, pin)) != 0) 321 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 322 send_msg(msg); 323 sshbuf_reset(msg); 324 325 type = recv_msg(msg); 326 if (type == SSH2_AGENT_IDENTITIES_ANSWER) { 327 if ((r = sshbuf_get_u32(msg, &nkeys)) != 0) 328 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 329 *keysp = xcalloc(nkeys, sizeof(struct sshkey *)); 330 if (labelsp) 331 *labelsp = xcalloc(nkeys, sizeof(char *)); 332 for (i = 0; i < nkeys; i++) { 333 /* XXX clean up properly instead of fatal() */ 334 if ((r = sshbuf_get_string(msg, &blob, &blen)) != 0 || 335 (r = sshbuf_get_cstring(msg, &label, NULL)) != 0) 336 fatal("%s: buffer error: %s", 337 __func__, ssh_err(r)); 338 if ((r = sshkey_from_blob(blob, blen, &k)) != 0) 339 fatal("%s: bad key: %s", __func__, ssh_err(r)); 340 wrap_key(k); 341 (*keysp)[i] = k; 342 if (labelsp) 343 (*labelsp)[i] = label; 344 else 345 free(label); 346 free(blob); 347 } 348 } else if (type == SSH2_AGENT_FAILURE) { 349 if ((r = sshbuf_get_u32(msg, &nkeys)) != 0) 350 nkeys = -1; 351 } else { 352 nkeys = -1; 353 } 354 sshbuf_free(msg); 355 return (nkeys); 356 } 357 358 int 359 pkcs11_del_provider(char *name) 360 { 361 int r, ret = -1; 362 struct sshbuf *msg; 363 364 if ((msg = sshbuf_new()) == NULL) 365 fatal("%s: sshbuf_new failed", __func__); 366 if ((r = sshbuf_put_u8(msg, SSH_AGENTC_REMOVE_SMARTCARD_KEY)) != 0 || 367 (r = sshbuf_put_cstring(msg, name)) != 0 || 368 (r = sshbuf_put_cstring(msg, "")) != 0) 369 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 370 send_msg(msg); 371 sshbuf_reset(msg); 372 373 if (recv_msg(msg) == SSH_AGENT_SUCCESS) 374 ret = 0; 375 sshbuf_free(msg); 376 return (ret); 377 } 378