ssh-pkcs11-helper.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. /* $OpenBSD: ssh-pkcs11-helper.c,v 1.23 2020/03/06 18:26:21 markus Exp $ */
  2. /*
  3. * Copyright (c) 2010 Markus Friedl. All rights reserved.
  4. *
  5. * Permission to use, copy, modify, and distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  10. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  11. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  12. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  14. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  15. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16. */
  17. #include "includes.h"
  18. #include <sys/types.h>
  19. #ifdef HAVE_SYS_TIME_H
  20. # include <sys/time.h>
  21. #endif
  22. #include "openbsd-compat/sys-queue.h"
  23. #include <stdlib.h>
  24. #include <errno.h>
  25. #ifdef HAVE_POLL_H
  26. #include <poll.h>
  27. #endif
  28. #include <stdarg.h>
  29. #include <string.h>
  30. #include <unistd.h>
  31. #include "xmalloc.h"
  32. #include "sshbuf.h"
  33. #include "log.h"
  34. #include "misc.h"
  35. #include "sshkey.h"
  36. #include "authfd.h"
  37. #include "ssh-pkcs11.h"
  38. #include "ssherr.h"
  39. #ifdef ENABLE_PKCS11
  40. #ifdef WITH_OPENSSL
  41. /* borrows code from sftp-server and ssh-agent */
  42. struct pkcs11_keyinfo {
  43. struct sshkey *key;
  44. char *providername, *label;
  45. TAILQ_ENTRY(pkcs11_keyinfo) next;
  46. };
  47. TAILQ_HEAD(, pkcs11_keyinfo) pkcs11_keylist;
  48. #define MAX_MSG_LENGTH 10240 /*XXX*/
  49. /* input and output queue */
  50. struct sshbuf *iqueue;
  51. struct sshbuf *oqueue;
  52. static void
  53. add_key(struct sshkey *k, char *name, char *label)
  54. {
  55. struct pkcs11_keyinfo *ki;
  56. ki = xcalloc(1, sizeof(*ki));
  57. ki->providername = xstrdup(name);
  58. ki->key = k;
  59. ki->label = xstrdup(label);
  60. TAILQ_INSERT_TAIL(&pkcs11_keylist, ki, next);
  61. }
  62. static void
  63. del_keys_by_name(char *name)
  64. {
  65. struct pkcs11_keyinfo *ki, *nxt;
  66. for (ki = TAILQ_FIRST(&pkcs11_keylist); ki; ki = nxt) {
  67. nxt = TAILQ_NEXT(ki, next);
  68. if (!strcmp(ki->providername, name)) {
  69. TAILQ_REMOVE(&pkcs11_keylist, ki, next);
  70. free(ki->providername);
  71. free(ki->label);
  72. sshkey_free(ki->key);
  73. free(ki);
  74. }
  75. }
  76. }
  77. /* lookup matching 'private' key */
  78. static struct sshkey *
  79. lookup_key(struct sshkey *k)
  80. {
  81. struct pkcs11_keyinfo *ki;
  82. TAILQ_FOREACH(ki, &pkcs11_keylist, next) {
  83. debug("check %p %s %s", ki, ki->providername, ki->label);
  84. if (sshkey_equal(k, ki->key))
  85. return (ki->key);
  86. }
  87. return (NULL);
  88. }
  89. static void
  90. send_msg(struct sshbuf *m)
  91. {
  92. int r;
  93. if ((r = sshbuf_put_stringb(oqueue, m)) != 0)
  94. fatal("%s: buffer error: %s", __func__, ssh_err(r));
  95. }
  96. static void
  97. process_add(void)
  98. {
  99. char *name, *pin;
  100. struct sshkey **keys = NULL;
  101. int r, i, nkeys;
  102. u_char *blob;
  103. size_t blen;
  104. struct sshbuf *msg;
  105. char **labels = NULL;
  106. if ((msg = sshbuf_new()) == NULL)
  107. fatal("%s: sshbuf_new failed", __func__);
  108. if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
  109. (r = sshbuf_get_cstring(iqueue, &pin, NULL)) != 0)
  110. fatal("%s: buffer error: %s", __func__, ssh_err(r));
  111. if ((nkeys = pkcs11_add_provider(name, pin, &keys, &labels)) > 0) {
  112. if ((r = sshbuf_put_u8(msg,
  113. SSH2_AGENT_IDENTITIES_ANSWER)) != 0 ||
  114. (r = sshbuf_put_u32(msg, nkeys)) != 0)
  115. fatal("%s: buffer error: %s", __func__, ssh_err(r));
  116. for (i = 0; i < nkeys; i++) {
  117. if ((r = sshkey_to_blob(keys[i], &blob, &blen)) != 0) {
  118. debug("%s: sshkey_to_blob: %s",
  119. __func__, ssh_err(r));
  120. continue;
  121. }
  122. if ((r = sshbuf_put_string(msg, blob, blen)) != 0 ||
  123. (r = sshbuf_put_cstring(msg, labels[i])) != 0)
  124. fatal("%s: buffer error: %s",
  125. __func__, ssh_err(r));
  126. free(blob);
  127. add_key(keys[i], name, labels[i]);
  128. free(labels[i]);
  129. }
  130. } else {
  131. if ((r = sshbuf_put_u8(msg, SSH_AGENT_FAILURE)) != 0)
  132. fatal("%s: buffer error: %s", __func__, ssh_err(r));
  133. if ((r = sshbuf_put_u32(msg, -nkeys)) != 0)
  134. fatal("%s: buffer error: %s", __func__, ssh_err(r));
  135. }
  136. free(labels);
  137. free(keys); /* keys themselves are transferred to pkcs11_keylist */
  138. free(pin);
  139. free(name);
  140. send_msg(msg);
  141. sshbuf_free(msg);
  142. }
  143. static void
  144. process_del(void)
  145. {
  146. char *name, *pin;
  147. struct sshbuf *msg;
  148. int r;
  149. if ((msg = sshbuf_new()) == NULL)
  150. fatal("%s: sshbuf_new failed", __func__);
  151. if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
  152. (r = sshbuf_get_cstring(iqueue, &pin, NULL)) != 0)
  153. fatal("%s: buffer error: %s", __func__, ssh_err(r));
  154. del_keys_by_name(name);
  155. if ((r = sshbuf_put_u8(msg, pkcs11_del_provider(name) == 0 ?
  156. SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE)) != 0)
  157. fatal("%s: buffer error: %s", __func__, ssh_err(r));
  158. free(pin);
  159. free(name);
  160. send_msg(msg);
  161. sshbuf_free(msg);
  162. }
  163. static void
  164. process_sign(void)
  165. {
  166. u_char *blob, *data, *signature = NULL;
  167. size_t blen, dlen, slen = 0;
  168. int r, ok = -1;
  169. struct sshkey *key, *found;
  170. struct sshbuf *msg;
  171. /* XXX support SHA2 signature flags */
  172. if ((r = sshbuf_get_string(iqueue, &blob, &blen)) != 0 ||
  173. (r = sshbuf_get_string(iqueue, &data, &dlen)) != 0 ||
  174. (r = sshbuf_get_u32(iqueue, NULL)) != 0)
  175. fatal("%s: buffer error: %s", __func__, ssh_err(r));
  176. if ((r = sshkey_from_blob(blob, blen, &key)) != 0)
  177. error("%s: sshkey_from_blob: %s", __func__, ssh_err(r));
  178. else {
  179. if ((found = lookup_key(key)) != NULL) {
  180. #ifdef WITH_OPENSSL
  181. int ret;
  182. if (key->type == KEY_RSA) {
  183. slen = RSA_size(key->rsa);
  184. signature = xmalloc(slen);
  185. ret = RSA_private_encrypt(dlen, data, signature,
  186. found->rsa, RSA_PKCS1_PADDING);
  187. if (ret != -1) {
  188. slen = ret;
  189. ok = 0;
  190. }
  191. #ifdef OPENSSL_HAS_ECC
  192. } else if (key->type == KEY_ECDSA) {
  193. u_int xslen = ECDSA_size(key->ecdsa);
  194. signature = xmalloc(xslen);
  195. /* "The parameter type is ignored." */
  196. ret = ECDSA_sign(-1, data, dlen, signature,
  197. &xslen, found->ecdsa);
  198. if (ret != 0)
  199. ok = 0;
  200. else
  201. error("%s: ECDSA_sign"
  202. " returns %d", __func__, ret);
  203. slen = xslen;
  204. #endif /* OPENSSL_HAS_ECC */
  205. } else
  206. error("%s: don't know how to sign with key "
  207. "type %d", __func__, (int)key->type);
  208. #endif /* WITH_OPENSSL */
  209. }
  210. sshkey_free(key);
  211. }
  212. if ((msg = sshbuf_new()) == NULL)
  213. fatal("%s: sshbuf_new failed", __func__);
  214. if (ok == 0) {
  215. if ((r = sshbuf_put_u8(msg, SSH2_AGENT_SIGN_RESPONSE)) != 0 ||
  216. (r = sshbuf_put_string(msg, signature, slen)) != 0)
  217. fatal("%s: buffer error: %s", __func__, ssh_err(r));
  218. } else {
  219. if ((r = sshbuf_put_u8(msg, SSH2_AGENT_FAILURE)) != 0)
  220. fatal("%s: buffer error: %s", __func__, ssh_err(r));
  221. }
  222. free(data);
  223. free(blob);
  224. free(signature);
  225. send_msg(msg);
  226. sshbuf_free(msg);
  227. }
  228. static void
  229. process(void)
  230. {
  231. u_int msg_len;
  232. u_int buf_len;
  233. u_int consumed;
  234. u_char type;
  235. const u_char *cp;
  236. int r;
  237. buf_len = sshbuf_len(iqueue);
  238. if (buf_len < 5)
  239. return; /* Incomplete message. */
  240. cp = sshbuf_ptr(iqueue);
  241. msg_len = get_u32(cp);
  242. if (msg_len > MAX_MSG_LENGTH) {
  243. error("bad message len %d", msg_len);
  244. cleanup_exit(11);
  245. }
  246. if (buf_len < msg_len + 4)
  247. return;
  248. if ((r = sshbuf_consume(iqueue, 4)) != 0 ||
  249. (r = sshbuf_get_u8(iqueue, &type)) != 0)
  250. fatal("%s: buffer error: %s", __func__, ssh_err(r));
  251. buf_len -= 4;
  252. switch (type) {
  253. case SSH_AGENTC_ADD_SMARTCARD_KEY:
  254. debug("process_add");
  255. process_add();
  256. break;
  257. case SSH_AGENTC_REMOVE_SMARTCARD_KEY:
  258. debug("process_del");
  259. process_del();
  260. break;
  261. case SSH2_AGENTC_SIGN_REQUEST:
  262. debug("process_sign");
  263. process_sign();
  264. break;
  265. default:
  266. error("Unknown message %d", type);
  267. break;
  268. }
  269. /* discard the remaining bytes from the current packet */
  270. if (buf_len < sshbuf_len(iqueue)) {
  271. error("iqueue grew unexpectedly");
  272. cleanup_exit(255);
  273. }
  274. consumed = buf_len - sshbuf_len(iqueue);
  275. if (msg_len < consumed) {
  276. error("msg_len %d < consumed %d", msg_len, consumed);
  277. cleanup_exit(255);
  278. }
  279. if (msg_len > consumed) {
  280. if ((r = sshbuf_consume(iqueue, msg_len - consumed)) != 0)
  281. fatal("%s: buffer error: %s", __func__, ssh_err(r));
  282. }
  283. }
  284. void
  285. cleanup_exit(int i)
  286. {
  287. /* XXX */
  288. _exit(i);
  289. }
  290. int
  291. main(int argc, char **argv)
  292. {
  293. int r, ch, in, out, log_stderr = 0;
  294. ssize_t len;
  295. SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
  296. LogLevel log_level = SYSLOG_LEVEL_ERROR;
  297. char buf[4*4096];
  298. extern char *__progname;
  299. struct pollfd pfd[2];
  300. __progname = ssh_get_progname(argv[0]);
  301. seed_rng();
  302. TAILQ_INIT(&pkcs11_keylist);
  303. log_init(__progname, log_level, log_facility, log_stderr);
  304. while ((ch = getopt(argc, argv, "v")) != -1) {
  305. switch (ch) {
  306. case 'v':
  307. log_stderr = 1;
  308. if (log_level == SYSLOG_LEVEL_ERROR)
  309. log_level = SYSLOG_LEVEL_DEBUG1;
  310. else if (log_level < SYSLOG_LEVEL_DEBUG3)
  311. log_level++;
  312. break;
  313. default:
  314. fprintf(stderr, "usage: %s [-v]\n", __progname);
  315. exit(1);
  316. }
  317. }
  318. log_init(__progname, log_level, log_facility, log_stderr);
  319. pkcs11_init(0);
  320. in = STDIN_FILENO;
  321. out = STDOUT_FILENO;
  322. if ((iqueue = sshbuf_new()) == NULL)
  323. fatal("%s: sshbuf_new failed", __func__);
  324. if ((oqueue = sshbuf_new()) == NULL)
  325. fatal("%s: sshbuf_new failed", __func__);
  326. while (1) {
  327. memset(pfd, 0, sizeof(pfd));
  328. pfd[0].fd = in;
  329. pfd[1].fd = out;
  330. /*
  331. * Ensure that we can read a full buffer and handle
  332. * the worst-case length packet it can generate,
  333. * otherwise apply backpressure by stopping reads.
  334. */
  335. if ((r = sshbuf_check_reserve(iqueue, sizeof(buf))) == 0 &&
  336. (r = sshbuf_check_reserve(oqueue, MAX_MSG_LENGTH)) == 0)
  337. pfd[0].events = POLLIN;
  338. else if (r != SSH_ERR_NO_BUFFER_SPACE)
  339. fatal("%s: buffer error: %s", __func__, ssh_err(r));
  340. if (sshbuf_len(oqueue) > 0)
  341. pfd[1].events = POLLOUT;
  342. if ((r = poll(pfd, 2, -1 /* INFTIM */)) <= 0) {
  343. if (r == 0 || errno == EINTR)
  344. continue;
  345. fatal("poll: %s", strerror(errno));
  346. }
  347. /* copy stdin to iqueue */
  348. if ((pfd[0].revents & (POLLIN|POLLERR)) != 0) {
  349. len = read(in, buf, sizeof buf);
  350. if (len == 0) {
  351. debug("read eof");
  352. cleanup_exit(0);
  353. } else if (len < 0) {
  354. error("read: %s", strerror(errno));
  355. cleanup_exit(1);
  356. } else if ((r = sshbuf_put(iqueue, buf, len)) != 0) {
  357. fatal("%s: buffer error: %s",
  358. __func__, ssh_err(r));
  359. }
  360. }
  361. /* send oqueue to stdout */
  362. if ((pfd[1].revents & (POLLOUT|POLLHUP)) != 0) {
  363. len = write(out, sshbuf_ptr(oqueue),
  364. sshbuf_len(oqueue));
  365. if (len < 0) {
  366. error("write: %s", strerror(errno));
  367. cleanup_exit(1);
  368. } else if ((r = sshbuf_consume(oqueue, len)) != 0) {
  369. fatal("%s: buffer error: %s",
  370. __func__, ssh_err(r));
  371. }
  372. }
  373. /*
  374. * Process requests from client if we can fit the results
  375. * into the output buffer, otherwise stop processing input
  376. * and let the output queue drain.
  377. */
  378. if ((r = sshbuf_check_reserve(oqueue, MAX_MSG_LENGTH)) == 0)
  379. process();
  380. else if (r != SSH_ERR_NO_BUFFER_SPACE)
  381. fatal("%s: buffer error: %s", __func__, ssh_err(r));
  382. }
  383. }
  384. #else /* WITH_OPENSSL */
  385. void
  386. cleanup_exit(int i)
  387. {
  388. _exit(i);
  389. }
  390. int
  391. main(int argc, char **argv)
  392. {
  393. fprintf(stderr, "PKCS#11 code is not enabled\n");
  394. return 1;
  395. }
  396. #endif /* WITH_OPENSSL */
  397. #else /* ENABLE_PKCS11 */
  398. int
  399. main(int argc, char **argv)
  400. {
  401. extern char *__progname;
  402. __progname = ssh_get_progname(argv[0]);
  403. log_init(__progname, SYSLOG_LEVEL_ERROR, SYSLOG_FACILITY_AUTH, 0);
  404. fatal("PKCS#11 support disabled at compile time");
  405. }
  406. #endif /* ENABLE_PKCS11 */