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