119261079SEd Maste /* $OpenBSD: ssh-pkcs11-client.c,v 1.17 2020/10/18 11:32:02 djm Exp $ */ 2b15c8340SDag-Erling Smørgrav /* 3b15c8340SDag-Erling Smørgrav * Copyright (c) 2010 Markus Friedl. All rights reserved. 419261079SEd Maste * Copyright (c) 2014 Pedro Martelletto. All rights reserved. 5b15c8340SDag-Erling Smørgrav * 6b15c8340SDag-Erling Smørgrav * Permission to use, copy, modify, and distribute this software for any 7b15c8340SDag-Erling Smørgrav * purpose with or without fee is hereby granted, provided that the above 8b15c8340SDag-Erling Smørgrav * copyright notice and this permission notice appear in all copies. 9b15c8340SDag-Erling Smørgrav * 10b15c8340SDag-Erling Smørgrav * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11b15c8340SDag-Erling Smørgrav * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12b15c8340SDag-Erling Smørgrav * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13b15c8340SDag-Erling Smørgrav * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14b15c8340SDag-Erling Smørgrav * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15b15c8340SDag-Erling Smørgrav * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16b15c8340SDag-Erling Smørgrav * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17b15c8340SDag-Erling Smørgrav */ 18b15c8340SDag-Erling Smørgrav 19b15c8340SDag-Erling Smørgrav #include "includes.h" 20b15c8340SDag-Erling Smørgrav 21b15c8340SDag-Erling Smørgrav #ifdef ENABLE_PKCS11 22b15c8340SDag-Erling Smørgrav 23b15c8340SDag-Erling Smørgrav #include <sys/types.h> 24b15c8340SDag-Erling Smørgrav #ifdef HAVE_SYS_TIME_H 25b15c8340SDag-Erling Smørgrav # include <sys/time.h> 26b15c8340SDag-Erling Smørgrav #endif 27b15c8340SDag-Erling Smørgrav #include <sys/socket.h> 28b15c8340SDag-Erling Smørgrav 29b15c8340SDag-Erling Smørgrav #include <stdarg.h> 30b15c8340SDag-Erling Smørgrav #include <string.h> 31b15c8340SDag-Erling Smørgrav #include <unistd.h> 32b15c8340SDag-Erling Smørgrav #include <errno.h> 33b15c8340SDag-Erling Smørgrav 3419261079SEd Maste #include <openssl/ecdsa.h> 35a0ee8cc6SDag-Erling Smørgrav #include <openssl/rsa.h> 36a0ee8cc6SDag-Erling Smørgrav 372a01feabSEd Maste #include "openbsd-compat/openssl-compat.h" 382a01feabSEd Maste 39b15c8340SDag-Erling Smørgrav #include "pathnames.h" 40b15c8340SDag-Erling Smørgrav #include "xmalloc.h" 41190cef3dSDag-Erling Smørgrav #include "sshbuf.h" 42b15c8340SDag-Erling Smørgrav #include "log.h" 43b15c8340SDag-Erling Smørgrav #include "misc.h" 44190cef3dSDag-Erling Smørgrav #include "sshkey.h" 45b15c8340SDag-Erling Smørgrav #include "authfd.h" 46b15c8340SDag-Erling Smørgrav #include "atomicio.h" 47b15c8340SDag-Erling Smørgrav #include "ssh-pkcs11.h" 48190cef3dSDag-Erling Smørgrav #include "ssherr.h" 49b15c8340SDag-Erling Smørgrav 50b15c8340SDag-Erling Smørgrav /* borrows code from sftp-server and ssh-agent */ 51b15c8340SDag-Erling Smørgrav 5219261079SEd Maste static int fd = -1; 5319261079SEd Maste static pid_t pid = -1; 54b15c8340SDag-Erling Smørgrav 55b15c8340SDag-Erling Smørgrav static void 56190cef3dSDag-Erling Smørgrav send_msg(struct sshbuf *m) 57b15c8340SDag-Erling Smørgrav { 58b15c8340SDag-Erling Smørgrav u_char buf[4]; 59190cef3dSDag-Erling Smørgrav size_t mlen = sshbuf_len(m); 60190cef3dSDag-Erling Smørgrav int r; 61b15c8340SDag-Erling Smørgrav 62190cef3dSDag-Erling Smørgrav POKE_U32(buf, mlen); 63b15c8340SDag-Erling Smørgrav if (atomicio(vwrite, fd, buf, 4) != 4 || 64190cef3dSDag-Erling Smørgrav atomicio(vwrite, fd, sshbuf_mutable_ptr(m), 65190cef3dSDag-Erling Smørgrav sshbuf_len(m)) != sshbuf_len(m)) 66b15c8340SDag-Erling Smørgrav error("write to helper failed"); 67190cef3dSDag-Erling Smørgrav if ((r = sshbuf_consume(m, mlen)) != 0) 6819261079SEd Maste fatal_fr(r, "consume"); 69b15c8340SDag-Erling Smørgrav } 70b15c8340SDag-Erling Smørgrav 71b15c8340SDag-Erling Smørgrav static int 72190cef3dSDag-Erling Smørgrav recv_msg(struct sshbuf *m) 73b15c8340SDag-Erling Smørgrav { 74b15c8340SDag-Erling Smørgrav u_int l, len; 75190cef3dSDag-Erling Smørgrav u_char c, buf[1024]; 76190cef3dSDag-Erling Smørgrav int r; 77b15c8340SDag-Erling Smørgrav 78b15c8340SDag-Erling Smørgrav if ((len = atomicio(read, fd, buf, 4)) != 4) { 79b15c8340SDag-Erling Smørgrav error("read from helper failed: %u", len); 80b15c8340SDag-Erling Smørgrav return (0); /* XXX */ 81b15c8340SDag-Erling Smørgrav } 82190cef3dSDag-Erling Smørgrav len = PEEK_U32(buf); 83b15c8340SDag-Erling Smørgrav if (len > 256 * 1024) 84b15c8340SDag-Erling Smørgrav fatal("response too long: %u", len); 85b15c8340SDag-Erling Smørgrav /* read len bytes into m */ 86190cef3dSDag-Erling Smørgrav sshbuf_reset(m); 87b15c8340SDag-Erling Smørgrav while (len > 0) { 88b15c8340SDag-Erling Smørgrav l = len; 89b15c8340SDag-Erling Smørgrav if (l > sizeof(buf)) 90b15c8340SDag-Erling Smørgrav l = sizeof(buf); 91b15c8340SDag-Erling Smørgrav if (atomicio(read, fd, buf, l) != l) { 92b15c8340SDag-Erling Smørgrav error("response from helper failed."); 93b15c8340SDag-Erling Smørgrav return (0); /* XXX */ 94b15c8340SDag-Erling Smørgrav } 95190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put(m, buf, l)) != 0) 9619261079SEd Maste fatal_fr(r, "sshbuf_put"); 97b15c8340SDag-Erling Smørgrav len -= l; 98b15c8340SDag-Erling Smørgrav } 99190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_u8(m, &c)) != 0) 10019261079SEd Maste fatal_fr(r, "parse type"); 101190cef3dSDag-Erling Smørgrav return c; 102b15c8340SDag-Erling Smørgrav } 103b15c8340SDag-Erling Smørgrav 104b15c8340SDag-Erling Smørgrav int 105b15c8340SDag-Erling Smørgrav pkcs11_init(int interactive) 106b15c8340SDag-Erling Smørgrav { 107b15c8340SDag-Erling Smørgrav return (0); 108b15c8340SDag-Erling Smørgrav } 109b15c8340SDag-Erling Smørgrav 110b15c8340SDag-Erling Smørgrav void 111b15c8340SDag-Erling Smørgrav pkcs11_terminate(void) 112b15c8340SDag-Erling Smørgrav { 11347dd1d1bSDag-Erling Smørgrav if (fd >= 0) 114b15c8340SDag-Erling Smørgrav close(fd); 115b15c8340SDag-Erling Smørgrav } 116b15c8340SDag-Erling Smørgrav 117b15c8340SDag-Erling Smørgrav static int 11819261079SEd Maste rsa_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, int padding) 119b15c8340SDag-Erling Smørgrav { 12019261079SEd Maste struct sshkey *key = NULL; 12119261079SEd Maste struct sshbuf *msg = NULL; 12219261079SEd Maste u_char *blob = NULL, *signature = NULL; 123190cef3dSDag-Erling Smørgrav size_t blen, slen = 0; 124190cef3dSDag-Erling Smørgrav int r, ret = -1; 125b15c8340SDag-Erling Smørgrav 126b15c8340SDag-Erling Smørgrav if (padding != RSA_PKCS1_PADDING) 12719261079SEd Maste goto fail; 12819261079SEd Maste key = sshkey_new(KEY_UNSPEC); 12919261079SEd Maste if (key == NULL) { 13019261079SEd Maste error_f("sshkey_new failed"); 13119261079SEd Maste goto fail; 13219261079SEd Maste } 13319261079SEd Maste key->type = KEY_RSA; 13419261079SEd Maste RSA_up_ref(rsa); 13519261079SEd Maste key->rsa = rsa; 13619261079SEd Maste if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) { 13719261079SEd Maste error_fr(r, "encode key"); 13819261079SEd Maste goto fail; 139190cef3dSDag-Erling Smørgrav } 140190cef3dSDag-Erling Smørgrav if ((msg = sshbuf_new()) == NULL) 14119261079SEd Maste fatal_f("sshbuf_new failed"); 142190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_SIGN_REQUEST)) != 0 || 143190cef3dSDag-Erling Smørgrav (r = sshbuf_put_string(msg, blob, blen)) != 0 || 144190cef3dSDag-Erling Smørgrav (r = sshbuf_put_string(msg, from, flen)) != 0 || 145190cef3dSDag-Erling Smørgrav (r = sshbuf_put_u32(msg, 0)) != 0) 14619261079SEd Maste fatal_fr(r, "compose"); 147190cef3dSDag-Erling Smørgrav send_msg(msg); 148190cef3dSDag-Erling Smørgrav sshbuf_reset(msg); 149b15c8340SDag-Erling Smørgrav 150190cef3dSDag-Erling Smørgrav if (recv_msg(msg) == SSH2_AGENT_SIGN_RESPONSE) { 151190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_string(msg, &signature, &slen)) != 0) 15219261079SEd Maste fatal_fr(r, "parse"); 153190cef3dSDag-Erling Smørgrav if (slen <= (size_t)RSA_size(rsa)) { 154b15c8340SDag-Erling Smørgrav memcpy(to, signature, slen); 155b15c8340SDag-Erling Smørgrav ret = slen; 156b15c8340SDag-Erling Smørgrav } 157e4a9863fSDag-Erling Smørgrav free(signature); 158b15c8340SDag-Erling Smørgrav } 15919261079SEd Maste fail: 16019261079SEd Maste free(blob); 16119261079SEd Maste sshkey_free(key); 162190cef3dSDag-Erling Smørgrav sshbuf_free(msg); 163b15c8340SDag-Erling Smørgrav return (ret); 164b15c8340SDag-Erling Smørgrav } 165b15c8340SDag-Erling Smørgrav 166*1323ec57SEd Maste #if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) 16719261079SEd Maste static ECDSA_SIG * 16819261079SEd Maste ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv, 16919261079SEd Maste const BIGNUM *rp, EC_KEY *ec) 170b15c8340SDag-Erling Smørgrav { 17119261079SEd Maste struct sshkey *key = NULL; 17219261079SEd Maste struct sshbuf *msg = NULL; 17319261079SEd Maste ECDSA_SIG *ret = NULL; 17419261079SEd Maste const u_char *cp; 17519261079SEd Maste u_char *blob = NULL, *signature = NULL; 17619261079SEd Maste size_t blen, slen = 0; 17719261079SEd Maste int r, nid; 17819261079SEd Maste 17919261079SEd Maste nid = sshkey_ecdsa_key_to_nid(ec); 18019261079SEd Maste if (nid < 0) { 18119261079SEd Maste error_f("couldn't get curve nid"); 18219261079SEd Maste goto fail; 18319261079SEd Maste } 18419261079SEd Maste 18519261079SEd Maste key = sshkey_new(KEY_UNSPEC); 18619261079SEd Maste if (key == NULL) { 18719261079SEd Maste error_f("sshkey_new failed"); 18819261079SEd Maste goto fail; 18919261079SEd Maste } 19019261079SEd Maste key->ecdsa = ec; 19119261079SEd Maste key->ecdsa_nid = nid; 19219261079SEd Maste key->type = KEY_ECDSA; 19319261079SEd Maste EC_KEY_up_ref(ec); 19419261079SEd Maste 19519261079SEd Maste if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) { 19619261079SEd Maste error_fr(r, "encode key"); 19719261079SEd Maste goto fail; 19819261079SEd Maste } 19919261079SEd Maste if ((msg = sshbuf_new()) == NULL) 20019261079SEd Maste fatal_f("sshbuf_new failed"); 20119261079SEd Maste if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_SIGN_REQUEST)) != 0 || 20219261079SEd Maste (r = sshbuf_put_string(msg, blob, blen)) != 0 || 20319261079SEd Maste (r = sshbuf_put_string(msg, dgst, dgst_len)) != 0 || 20419261079SEd Maste (r = sshbuf_put_u32(msg, 0)) != 0) 20519261079SEd Maste fatal_fr(r, "compose"); 20619261079SEd Maste send_msg(msg); 20719261079SEd Maste sshbuf_reset(msg); 20819261079SEd Maste 20919261079SEd Maste if (recv_msg(msg) == SSH2_AGENT_SIGN_RESPONSE) { 21019261079SEd Maste if ((r = sshbuf_get_string(msg, &signature, &slen)) != 0) 21119261079SEd Maste fatal_fr(r, "parse"); 21219261079SEd Maste cp = signature; 21319261079SEd Maste ret = d2i_ECDSA_SIG(NULL, &cp, slen); 21419261079SEd Maste free(signature); 21519261079SEd Maste } 21619261079SEd Maste 21719261079SEd Maste fail: 21819261079SEd Maste free(blob); 21919261079SEd Maste sshkey_free(key); 22019261079SEd Maste sshbuf_free(msg); 22119261079SEd Maste return (ret); 22219261079SEd Maste } 223*1323ec57SEd Maste #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ 22419261079SEd Maste 2252a01feabSEd Maste static RSA_METHOD *helper_rsa; 226*1323ec57SEd Maste #if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) 22719261079SEd Maste static EC_KEY_METHOD *helper_ecdsa; 228*1323ec57SEd Maste #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ 22919261079SEd Maste 23019261079SEd Maste /* redirect private key crypto operations to the ssh-pkcs11-helper */ 23119261079SEd Maste static void 23219261079SEd Maste wrap_key(struct sshkey *k) 23319261079SEd Maste { 23419261079SEd Maste if (k->type == KEY_RSA) 23519261079SEd Maste RSA_set_method(k->rsa, helper_rsa); 236*1323ec57SEd Maste #if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) 23719261079SEd Maste else if (k->type == KEY_ECDSA) 23819261079SEd Maste EC_KEY_set_method(k->ecdsa, helper_ecdsa); 239*1323ec57SEd Maste #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ 24019261079SEd Maste else 24119261079SEd Maste fatal_f("unknown key type"); 24219261079SEd Maste } 24319261079SEd Maste 24419261079SEd Maste static int 24519261079SEd Maste pkcs11_start_helper_methods(void) 24619261079SEd Maste { 24719261079SEd Maste if (helper_rsa != NULL) 24819261079SEd Maste return (0); 24919261079SEd Maste 250*1323ec57SEd Maste #if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) 25119261079SEd Maste int (*orig_sign)(int, const unsigned char *, int, unsigned char *, 25219261079SEd Maste unsigned int *, const BIGNUM *, const BIGNUM *, EC_KEY *) = NULL; 25319261079SEd Maste if (helper_ecdsa != NULL) 25419261079SEd Maste return (0); 25519261079SEd Maste helper_ecdsa = EC_KEY_METHOD_new(EC_KEY_OpenSSL()); 25619261079SEd Maste if (helper_ecdsa == NULL) 25719261079SEd Maste return (-1); 25819261079SEd Maste EC_KEY_METHOD_get_sign(helper_ecdsa, &orig_sign, NULL, NULL); 25919261079SEd Maste EC_KEY_METHOD_set_sign(helper_ecdsa, orig_sign, NULL, ecdsa_do_sign); 260*1323ec57SEd Maste #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ 261b15c8340SDag-Erling Smørgrav 2622a01feabSEd Maste if ((helper_rsa = RSA_meth_dup(RSA_get_default_method())) == NULL) 26319261079SEd Maste fatal_f("RSA_meth_dup failed"); 2642a01feabSEd Maste if (!RSA_meth_set1_name(helper_rsa, "ssh-pkcs11-helper") || 26519261079SEd Maste !RSA_meth_set_priv_enc(helper_rsa, rsa_encrypt)) 26619261079SEd Maste fatal_f("failed to prepare method"); 26719261079SEd Maste 268b15c8340SDag-Erling Smørgrav return (0); 269b15c8340SDag-Erling Smørgrav } 270b15c8340SDag-Erling Smørgrav 271b15c8340SDag-Erling Smørgrav static int 272b15c8340SDag-Erling Smørgrav pkcs11_start_helper(void) 273b15c8340SDag-Erling Smørgrav { 274b15c8340SDag-Erling Smørgrav int pair[2]; 27519261079SEd Maste char *helper, *verbosity = NULL; 27619261079SEd Maste 27719261079SEd Maste if (log_level_get() >= SYSLOG_LEVEL_DEBUG1) 27819261079SEd Maste verbosity = "-vvv"; 27919261079SEd Maste 28019261079SEd Maste if (pkcs11_start_helper_methods() == -1) { 28119261079SEd Maste error("pkcs11_start_helper_methods failed"); 28219261079SEd Maste return (-1); 28319261079SEd Maste } 284b15c8340SDag-Erling Smørgrav 285b15c8340SDag-Erling Smørgrav if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) { 286b15c8340SDag-Erling Smørgrav error("socketpair: %s", strerror(errno)); 287b15c8340SDag-Erling Smørgrav return (-1); 288b15c8340SDag-Erling Smørgrav } 289b15c8340SDag-Erling Smørgrav if ((pid = fork()) == -1) { 290b15c8340SDag-Erling Smørgrav error("fork: %s", strerror(errno)); 291b15c8340SDag-Erling Smørgrav return (-1); 292b15c8340SDag-Erling Smørgrav } else if (pid == 0) { 293b15c8340SDag-Erling Smørgrav if ((dup2(pair[1], STDIN_FILENO) == -1) || 294b15c8340SDag-Erling Smørgrav (dup2(pair[1], STDOUT_FILENO) == -1)) { 295b15c8340SDag-Erling Smørgrav fprintf(stderr, "dup2: %s\n", strerror(errno)); 296b15c8340SDag-Erling Smørgrav _exit(1); 297b15c8340SDag-Erling Smørgrav } 298b15c8340SDag-Erling Smørgrav close(pair[0]); 299b15c8340SDag-Erling Smørgrav close(pair[1]); 30019261079SEd Maste helper = getenv("SSH_PKCS11_HELPER"); 30119261079SEd Maste if (helper == NULL || strlen(helper) == 0) 30219261079SEd Maste helper = _PATH_SSH_PKCS11_HELPER; 30319261079SEd Maste debug_f("starting %s %s", helper, 30419261079SEd Maste verbosity == NULL ? "" : verbosity); 30519261079SEd Maste execlp(helper, helper, verbosity, (char *)NULL); 30619261079SEd Maste fprintf(stderr, "exec: %s: %s\n", helper, strerror(errno)); 307b15c8340SDag-Erling Smørgrav _exit(1); 308b15c8340SDag-Erling Smørgrav } 309b15c8340SDag-Erling Smørgrav close(pair[1]); 310b15c8340SDag-Erling Smørgrav fd = pair[0]; 311b15c8340SDag-Erling Smørgrav return (0); 312b15c8340SDag-Erling Smørgrav } 313b15c8340SDag-Erling Smørgrav 314b15c8340SDag-Erling Smørgrav int 31519261079SEd Maste pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp, 31619261079SEd Maste char ***labelsp) 317b15c8340SDag-Erling Smørgrav { 3184f52dfbbSDag-Erling Smørgrav struct sshkey *k; 31919261079SEd Maste int r, type; 320b15c8340SDag-Erling Smørgrav u_char *blob; 32119261079SEd Maste char *label; 322190cef3dSDag-Erling Smørgrav size_t blen; 323190cef3dSDag-Erling Smørgrav u_int nkeys, i; 324190cef3dSDag-Erling Smørgrav struct sshbuf *msg; 325b15c8340SDag-Erling Smørgrav 326b15c8340SDag-Erling Smørgrav if (fd < 0 && pkcs11_start_helper() < 0) 327b15c8340SDag-Erling Smørgrav return (-1); 328b15c8340SDag-Erling Smørgrav 329190cef3dSDag-Erling Smørgrav if ((msg = sshbuf_new()) == NULL) 33019261079SEd Maste fatal_f("sshbuf_new failed"); 331190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put_u8(msg, SSH_AGENTC_ADD_SMARTCARD_KEY)) != 0 || 332190cef3dSDag-Erling Smørgrav (r = sshbuf_put_cstring(msg, name)) != 0 || 333190cef3dSDag-Erling Smørgrav (r = sshbuf_put_cstring(msg, pin)) != 0) 33419261079SEd Maste fatal_fr(r, "compose"); 335190cef3dSDag-Erling Smørgrav send_msg(msg); 336190cef3dSDag-Erling Smørgrav sshbuf_reset(msg); 337b15c8340SDag-Erling Smørgrav 33819261079SEd Maste type = recv_msg(msg); 33919261079SEd Maste if (type == SSH2_AGENT_IDENTITIES_ANSWER) { 340190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_u32(msg, &nkeys)) != 0) 34119261079SEd Maste fatal_fr(r, "parse nkeys"); 342190cef3dSDag-Erling Smørgrav *keysp = xcalloc(nkeys, sizeof(struct sshkey *)); 34319261079SEd Maste if (labelsp) 34419261079SEd Maste *labelsp = xcalloc(nkeys, sizeof(char *)); 345b15c8340SDag-Erling Smørgrav for (i = 0; i < nkeys; i++) { 346190cef3dSDag-Erling Smørgrav /* XXX clean up properly instead of fatal() */ 347190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_string(msg, &blob, &blen)) != 0 || 34819261079SEd Maste (r = sshbuf_get_cstring(msg, &label, NULL)) != 0) 34919261079SEd Maste fatal_fr(r, "parse key"); 350190cef3dSDag-Erling Smørgrav if ((r = sshkey_from_blob(blob, blen, &k)) != 0) 35119261079SEd Maste fatal_fr(r, "decode key"); 35219261079SEd Maste wrap_key(k); 353b15c8340SDag-Erling Smørgrav (*keysp)[i] = k; 35419261079SEd Maste if (labelsp) 35519261079SEd Maste (*labelsp)[i] = label; 35619261079SEd Maste else 35719261079SEd Maste free(label); 358e4a9863fSDag-Erling Smørgrav free(blob); 359b15c8340SDag-Erling Smørgrav } 36019261079SEd Maste } else if (type == SSH2_AGENT_FAILURE) { 36119261079SEd Maste if ((r = sshbuf_get_u32(msg, &nkeys)) != 0) 36219261079SEd Maste nkeys = -1; 363b15c8340SDag-Erling Smørgrav } else { 364b15c8340SDag-Erling Smørgrav nkeys = -1; 365b15c8340SDag-Erling Smørgrav } 366190cef3dSDag-Erling Smørgrav sshbuf_free(msg); 367b15c8340SDag-Erling Smørgrav return (nkeys); 368b15c8340SDag-Erling Smørgrav } 369b15c8340SDag-Erling Smørgrav 370b15c8340SDag-Erling Smørgrav int 371b15c8340SDag-Erling Smørgrav pkcs11_del_provider(char *name) 372b15c8340SDag-Erling Smørgrav { 373190cef3dSDag-Erling Smørgrav int r, ret = -1; 374190cef3dSDag-Erling Smørgrav struct sshbuf *msg; 375b15c8340SDag-Erling Smørgrav 376190cef3dSDag-Erling Smørgrav if ((msg = sshbuf_new()) == NULL) 37719261079SEd Maste fatal_f("sshbuf_new failed"); 378190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put_u8(msg, SSH_AGENTC_REMOVE_SMARTCARD_KEY)) != 0 || 379190cef3dSDag-Erling Smørgrav (r = sshbuf_put_cstring(msg, name)) != 0 || 380190cef3dSDag-Erling Smørgrav (r = sshbuf_put_cstring(msg, "")) != 0) 38119261079SEd Maste fatal_fr(r, "compose"); 382190cef3dSDag-Erling Smørgrav send_msg(msg); 383190cef3dSDag-Erling Smørgrav sshbuf_reset(msg); 384b15c8340SDag-Erling Smørgrav 385190cef3dSDag-Erling Smørgrav if (recv_msg(msg) == SSH_AGENT_SUCCESS) 386b15c8340SDag-Erling Smørgrav ret = 0; 387190cef3dSDag-Erling Smørgrav sshbuf_free(msg); 388b15c8340SDag-Erling Smørgrav return (ret); 389b15c8340SDag-Erling Smørgrav } 390b15c8340SDag-Erling Smørgrav 391b15c8340SDag-Erling Smørgrav #endif /* ENABLE_PKCS11 */ 392