int
pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp)
{
	struct sshkey *k;
	int r;
	u_char *blob;
	size_t blen;
	u_int nkeys, i;
	struct sshbuf *msg;

	if (fd < 0 && pkcs11_start_helper() < 0)
		return (-1);

	if ((msg = sshbuf_new()) == NULL)
		fatal("%s: sshbuf_new failed", __func__);
	if ((r = sshbuf_put_u8(msg, SSH_AGENTC_ADD_SMARTCARD_KEY)) != 0 ||
	    (r = sshbuf_put_cstring(msg, name)) != 0 ||
	    (r = sshbuf_put_cstring(msg, pin)) != 0)
		fatal("%s: buffer error: %s", __func__, ssh_err(r));
	send_msg(msg);
	sshbuf_reset(msg);

	if (recv_msg(msg) == SSH2_AGENT_IDENTITIES_ANSWER) {
		if ((r = sshbuf_get_u32(msg, &nkeys)) != 0)
			fatal("%s: buffer error: %s", __func__, ssh_err(r));
		*keysp = xcalloc(nkeys, sizeof(struct sshkey *));
		for (i = 0; i < nkeys; i++) {
			/* XXX clean up properly instead of fatal() */
			if ((r = sshbuf_get_string(msg, &blob, &blen)) != 0 ||
			    (r = sshbuf_skip_string(msg)) != 0)
				fatal("%s: buffer error: %s",
				    __func__, ssh_err(r));
			if ((r = sshkey_from_blob(blob, blen, &k)) != 0)
				fatal("%s: bad key: %s", __func__, ssh_err(r));
			wrap_key(k->rsa);
			(*keysp)[i] = k;
			xfree(blob);
		}
	} else {
		nkeys = -1;
	}
	sshbuf_free(msg);
	return (nkeys);
}
int
pkcs11_add_provider(char *name, char *pin, Key ***keysp)
{
	Key *k;
	int i, nkeys;
	u_char *blob;
	u_int blen;
	Buffer msg;

	if (fd < 0 && pkcs11_start_helper() < 0)
		return (-1);

	buffer_init(&msg);
	buffer_put_char(&msg, SSH_AGENTC_ADD_SMARTCARD_KEY);
	buffer_put_cstring(&msg, name);
	buffer_put_cstring(&msg, pin);
	send_msg(&msg);
	buffer_clear(&msg);

	if (recv_msg(&msg) == SSH2_AGENT_IDENTITIES_ANSWER) {
		nkeys = buffer_get_int(&msg);
		*keysp = xcalloc(nkeys, sizeof(Key *));
		for (i = 0; i < nkeys; i++) {
			blob = buffer_get_string(&msg, &blen);
			free(buffer_get_string(&msg, NULL));
			k = key_from_blob(blob, blen);
			wrap_key(k->rsa);
			(*keysp)[i] = k;
			free(blob);
		}
	} else {
		nkeys = -1;
	}
	buffer_free(&msg);
	return (nkeys);
}