openssl-pkcs11.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729
  1. /*
  2. * OpenConnect (SSL + DTLS) VPN client
  3. *
  4. * Copyright © 2008-2015 Intel Corporation.
  5. *
  6. * Author: David Woodhouse <dwmw2@infradead.org>
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public License
  10. * version 2.1, as published by the Free Software Foundation.
  11. *
  12. * This program is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. */
  17. #include <config.h>
  18. #include "openconnect-internal.h"
  19. #include <openssl/rand.h>
  20. #include <sys/types.h>
  21. #include <errno.h>
  22. #include <string.h>
  23. #include <ctype.h>
  24. #ifdef HAVE_LIBP11 /* And p11-kit */
  25. #include <libp11.h>
  26. #include <p11-kit/pkcs11.h>
  27. static PKCS11_CTX *pkcs11_ctx(struct openconnect_info *vpninfo)
  28. {
  29. PKCS11_CTX *ctx;
  30. if (!vpninfo->pkcs11_ctx) {
  31. ERR_load_PKCS11_strings();
  32. ctx = PKCS11_CTX_new();
  33. if (!ctx) {
  34. vpn_progress(vpninfo, PRG_ERR,
  35. _("Failed to establish libp11 PKCS#11 context:\n"));
  36. openconnect_report_ssl_errors(vpninfo);
  37. return NULL;
  38. }
  39. if (PKCS11_CTX_load(ctx, DEFAULT_PKCS11_MODULE) < 0) {
  40. vpn_progress(vpninfo, PRG_ERR,
  41. _("Failed to load PKCS#11 provider module (%s):\n"),
  42. DEFAULT_PKCS11_MODULE);
  43. openconnect_report_ssl_errors(vpninfo);
  44. PKCS11_CTX_free(ctx);
  45. return NULL;
  46. }
  47. vpninfo->pkcs11_ctx = ctx;
  48. }
  49. return vpninfo->pkcs11_ctx;
  50. }
  51. static int parse_uri_attr(const char *attr, int attrlen, unsigned char **field,
  52. size_t *field_len)
  53. {
  54. size_t outlen = 0;
  55. unsigned char *out;
  56. int ret = 0;
  57. out = malloc(attrlen + 1);
  58. if (!out)
  59. return -ENOMEM;
  60. while (!ret && attrlen) {
  61. if (*attr == '%') {
  62. if (attrlen < 3) {
  63. ret = -EINVAL;
  64. } else {
  65. out[outlen++] = unhex(attr+1);
  66. attrlen -= 3;
  67. attr += 3;
  68. }
  69. } else {
  70. out[outlen++] = *(attr++);
  71. attrlen--;
  72. }
  73. }
  74. if (ret)
  75. free(out);
  76. else {
  77. if (field_len)
  78. *field_len = outlen;
  79. out[outlen] = 0;
  80. *field = out;
  81. }
  82. return ret;
  83. }
  84. static int parse_pkcs11_uri(const char *uri, PKCS11_TOKEN **p_tok,
  85. unsigned char **id, size_t *id_len,
  86. char **label, char **pin)
  87. {
  88. PKCS11_TOKEN *tok;
  89. char *newlabel = NULL;
  90. const char *end, *p;
  91. int ret = 0;
  92. tok = calloc(1, sizeof(*tok));
  93. if (!tok) {
  94. fprintf(stderr, "Could not allocate memory for token info\n");
  95. return -ENOMEM;
  96. }
  97. *id = NULL;
  98. /* We are only ever invoked if the string starts with 'pkcs11:' */
  99. end = uri + 6;
  100. while (!ret && end[0] && end[1]) {
  101. p = end + 1;
  102. end = strchr(p, ';');
  103. if (!end)
  104. end = p + strlen(p);
  105. if (!strncmp(p, "model=", 6)) {
  106. p += 6;
  107. ret = parse_uri_attr(p, end - p, (void *)&tok->model, NULL);
  108. } else if (!strncmp(p, "manufacturer=", 13)) {
  109. p += 13;
  110. ret = parse_uri_attr(p, end - p, (void *)&tok->manufacturer, NULL);
  111. } else if (!strncmp(p, "token=", 6)) {
  112. p += 6;
  113. ret = parse_uri_attr(p, end - p, (void *)&tok->label, NULL);
  114. } else if (!strncmp(p, "serial=", 7)) {
  115. p += 7;
  116. ret = parse_uri_attr(p, end - p, (void *)&tok->serialnr, NULL);
  117. } else if (!strncmp(p, "object=", 7)) {
  118. p += 7;
  119. ret = parse_uri_attr(p, end - p, (void *)&newlabel, NULL);
  120. } else if (!strncmp(p, "id=", 3)) {
  121. p += 3;
  122. ret = parse_uri_attr(p, end - p, (void *)id, id_len);
  123. } else if (!strncmp(p, "type=", 5) || !strncmp(p, "object-type=", 12)) {
  124. p = strchr(p, '=') + 1;
  125. if ((end - p == 4 && !strncmp(p, "cert", 4)) ||
  126. (end - p == 7 && !strncmp(p, "private", 7))) {
  127. /* Actually, just ignore it */
  128. } else
  129. ret = -EINVAL;
  130. /* Ignore object type for now. */
  131. } else if (!strncmp(p, "pin-value=", 10)) {
  132. /* XXX We could do better than this but it'll cover all sane
  133. use cases. */
  134. char *pinvalue = NULL;
  135. p += 10;
  136. ret = parse_uri_attr(p, end - p, (void *)&pinvalue, NULL);
  137. if (pinvalue) {
  138. free(*pin);
  139. *pin = pinvalue;
  140. }
  141. } else {
  142. ret = -EINVAL;
  143. }
  144. }
  145. if (!ret) {
  146. *label = newlabel;
  147. *p_tok = tok;
  148. } else {
  149. free(tok);
  150. tok = NULL;
  151. free(newlabel);
  152. free(*id);
  153. *id = NULL;
  154. }
  155. return ret;
  156. }
  157. static int request_pin(struct openconnect_info *vpninfo, struct cert_info *certinfo,
  158. struct pin_cache *cache, int retrying)
  159. {
  160. struct oc_auth_form f;
  161. struct oc_form_opt o;
  162. char message[1024];
  163. int ret;
  164. if (!vpninfo || !vpninfo->process_auth_form)
  165. return -EINVAL;
  166. if (certinfo->password) {
  167. cache->pin = certinfo->password;
  168. certinfo->password = NULL;
  169. return 0;
  170. }
  171. memset(&f, 0, sizeof(f));
  172. f.auth_id = (char *)certinfo_string(certinfo, "pkcs11_pin", "secondary_pkcs11_pin");
  173. f.opts = &o;
  174. message[sizeof(message)-1] = 0;
  175. snprintf(message, sizeof(message) - 1, _("PIN required for %s"), cache->token);
  176. f.message = message;
  177. if (retrying)
  178. f.error = (char *)_("Wrong PIN");
  179. o.next = NULL;
  180. o.type = OC_FORM_OPT_PASSWORD;
  181. o.name = (char *)"pkcs11_pin";
  182. o.label = (char *)_("Enter PIN:");
  183. o._value = NULL;
  184. ret = process_auth_form(vpninfo, &f);
  185. if (ret || !o._value)
  186. return -EIO;
  187. cache->pin = o._value;
  188. return 0;
  189. }
  190. static int slot_login(struct openconnect_info *vpninfo, struct cert_info *certinfo,
  191. PKCS11_CTX *ctx, PKCS11_SLOT *slot)
  192. {
  193. PKCS11_TOKEN *token = slot->token;
  194. struct pin_cache *cache = vpninfo->pin_cache;
  195. int ret, retrying = 0;
  196. retry:
  197. ERR_clear_error();
  198. if (!token->secureLogin) {
  199. if (!cache) {
  200. for (cache = vpninfo->pin_cache; cache; cache = cache->next)
  201. if (!strcmp(slot->description, cache->token))
  202. break;
  203. }
  204. if (!cache) {
  205. cache = malloc(sizeof(*cache));
  206. if (!cache)
  207. return -ENOMEM;
  208. cache->pin = NULL;
  209. cache->next = vpninfo->pin_cache;
  210. cache->token = strdup(slot->description);
  211. if (!cache->token) {
  212. free(cache);
  213. return -ENOMEM;
  214. }
  215. vpninfo->pin_cache = cache;
  216. }
  217. if (!cache->pin) {
  218. ret = request_pin(vpninfo, certinfo, cache, retrying);
  219. if (ret)
  220. return ret;
  221. }
  222. }
  223. ret = PKCS11_login(slot, 0, cache ? cache->pin : NULL);
  224. if (ret) {
  225. unsigned long err = ERR_peek_error();
  226. #if OPENSSL_VERSION_NUMBER < 0x30000000L
  227. if (ERR_GET_LIB(err) == ERR_LIB_PKCS11 &&
  228. ERR_GET_FUNC(err) == PKCS11_F_PKCS11_LOGIN)
  229. #else
  230. if (ERR_GET_LIB(err) == ERR_LIB_PKCS11)
  231. #endif
  232. err = ERR_GET_REASON(err);
  233. else
  234. err = CKR_OK; /* Anything we don't explicitly match */
  235. switch (ERR_GET_REASON(err)) {
  236. case CKR_PIN_INCORRECT:
  237. /* They'll be told about it in the next UI prompt */
  238. if (cache) {
  239. free(cache->pin);
  240. cache->pin = NULL;
  241. }
  242. retrying = 1;
  243. goto retry;
  244. case CKR_PIN_LOCKED:
  245. vpn_progress(vpninfo, PRG_ERR, _("PIN locked\n"));
  246. break;
  247. case CKR_PIN_EXPIRED:
  248. vpn_progress(vpninfo, PRG_ERR, _("PIN expired\n"));
  249. break;
  250. case CKR_USER_ANOTHER_ALREADY_LOGGED_IN:
  251. vpn_progress(vpninfo, PRG_ERR, _("Another user already logged in\n"));
  252. break;
  253. default:
  254. vpn_progress(vpninfo, PRG_ERR,
  255. _("Unknown error logging in to PKCS#11 token\n"));
  256. openconnect_report_ssl_errors(vpninfo);
  257. }
  258. ERR_clear_error();
  259. return -EPERM;
  260. }
  261. vpn_progress(vpninfo, PRG_TRACE,
  262. _("Logged in to PKCS#11 slot '%s'\n"),
  263. slot->description);
  264. return 0;
  265. }
  266. static PKCS11_CERT *slot_find_cert(struct openconnect_info *vpninfo, PKCS11_CTX *ctx,
  267. PKCS11_SLOT *slot, const char *cert_label,
  268. unsigned char *cert_id, size_t cert_id_len)
  269. {
  270. PKCS11_CERT *cert_list = NULL, *cert = NULL;
  271. unsigned int cert_count;
  272. if (PKCS11_enumerate_certs(slot->token, &cert_list, &cert_count) < 0) {
  273. vpn_progress(vpninfo, PRG_ERR,
  274. _("Failed to enumerate certs in PKCS#11 slot '%s'\n"),
  275. slot->description);
  276. return NULL;
  277. }
  278. vpn_progress(vpninfo, PRG_TRACE,
  279. _("Found %d certs in slot '%s'\n"),
  280. cert_count, slot->description);
  281. for (cert = cert_list; cert < &cert_list[cert_count]; cert++) {
  282. if (cert_label && strcmp(cert_label, cert->label))
  283. continue;
  284. if (cert_id && (cert_id_len != cert->id_len ||
  285. memcmp(cert_id, cert->id, cert_id_len)))
  286. continue;
  287. return cert;
  288. }
  289. return NULL;
  290. }
  291. int load_pkcs11_certificate(struct openconnect_info *vpninfo, struct cert_info *certinfo, X509 **certp)
  292. {
  293. PKCS11_CTX *ctx;
  294. PKCS11_TOKEN *match_tok = NULL;
  295. PKCS11_CERT *cert = NULL;
  296. char *cert_label = NULL;
  297. unsigned char *cert_id = NULL;
  298. size_t cert_id_len = 0;
  299. PKCS11_SLOT *slot_list = NULL, *slot, *login_slot = NULL;
  300. unsigned int slot_count, matching_slots = 0;
  301. int ret = 0;
  302. ctx = pkcs11_ctx(vpninfo);
  303. if (!ctx)
  304. return -EIO;
  305. if (parse_pkcs11_uri(certinfo->cert, &match_tok, &cert_id,
  306. &cert_id_len, &cert_label, &certinfo->password) < 0) {
  307. vpn_progress(vpninfo, PRG_ERR,
  308. _("Failed to parse PKCS#11 URI '%s'\n"),
  309. certinfo->cert);
  310. return -EINVAL;
  311. }
  312. if (PKCS11_enumerate_slots(ctx, &slot_list, &slot_count) < 0) {
  313. vpn_progress(vpninfo, PRG_ERR,
  314. _("Failed to enumerate PKCS#11 slots\n"));
  315. openconnect_report_ssl_errors(vpninfo);
  316. ret = -EIO;
  317. goto out;
  318. }
  319. for (slot = slot_list; slot < &slot_list[slot_count] && slot != login_slot; slot++) {
  320. if (!slot->token)
  321. continue;
  322. if (match_tok->label &&
  323. strcmp(match_tok->label, slot->token->label))
  324. continue;
  325. if (match_tok->manufacturer &&
  326. strcmp(match_tok->manufacturer, slot->token->manufacturer))
  327. continue;
  328. if (match_tok->model &&
  329. strcmp(match_tok->model, slot->token->model))
  330. continue;
  331. if (match_tok->serialnr &&
  332. strcmp(match_tok->serialnr, slot->token->serialnr))
  333. continue;
  334. cert = slot_find_cert(vpninfo, ctx, slot, cert_label, cert_id, cert_id_len);
  335. if (cert)
  336. goto got_cert;
  337. login_slot = slot;
  338. matching_slots++;
  339. }
  340. /* If there was precisely one matching slot, and we still didn't find the cert,
  341. try logging in to it. */
  342. if (matching_slots == 1 && (login_slot->token->loginRequired || login_slot->token->userPinSet)) {
  343. slot = login_slot;
  344. vpn_progress(vpninfo, PRG_INFO,
  345. _("Logging in to PKCS#11 slot '%s'\n"),
  346. slot->description);
  347. if (!slot_login(vpninfo, certinfo, ctx, slot)) {
  348. cert = slot_find_cert(vpninfo, ctx, slot, cert_label, cert_id, cert_id_len);
  349. if (cert)
  350. goto got_cert;
  351. }
  352. }
  353. ret = -EINVAL;
  354. vpn_progress(vpninfo, PRG_ERR,
  355. _("Failed to find PKCS#11 cert '%s'\n"),
  356. certinfo->cert);
  357. got_cert:
  358. if (cert) {
  359. /* This happens if the cert is too large for the fixed buffer
  360. in libp11 :( */
  361. if (!cert->x509) {
  362. vpn_progress(vpninfo, PRG_ERR,
  363. _("Certificate X.509 content not fetched by libp11\n"));
  364. ret = -EIO;
  365. goto out;
  366. }
  367. vpn_progress(vpninfo, PRG_DEBUG,
  368. certinfo_string(certinfo, _("Using PKCS#11 certificate %s\n"),
  369. _("Using secondary PKCS#11 certificate %s\n")),
  370. certinfo->cert);
  371. *certp = cert->x509;
  372. /* If the key is in PKCS#11 too (which is likely), then keep the slot around.
  373. We might want to know which slot the certificate was found in, so we can
  374. log into it to find the key. */
  375. if (!strncmp(certinfo->key, "pkcs11:", 7)) {
  376. vpninfo->pkcs11_slot_list = slot_list;
  377. vpninfo->pkcs11_slot_count = slot_count;
  378. vpninfo->pkcs11_cert_slot = slot;
  379. slot_list = NULL;
  380. }
  381. /* Also remember the ID of the cert, in case it helps us find the matching key */
  382. vpninfo->pkcs11_cert_id = malloc(cert->id_len);
  383. if (vpninfo->pkcs11_cert_id) {
  384. vpninfo->pkcs11_cert_id_len = cert->id_len;
  385. memcpy(vpninfo->pkcs11_cert_id, cert->id, cert->id_len);
  386. }
  387. }
  388. out:
  389. if (match_tok) {
  390. free(match_tok->model);
  391. free(match_tok->manufacturer);
  392. free(match_tok->serialnr);
  393. free(match_tok->label);
  394. free(match_tok);
  395. }
  396. free(cert_id);
  397. free(cert_label);
  398. if (slot_list)
  399. PKCS11_release_all_slots(ctx, slot_list, slot_count);
  400. return ret;
  401. }
  402. static PKCS11_KEY *slot_find_key(struct openconnect_info *vpninfo, PKCS11_CTX *ctx,
  403. PKCS11_SLOT *slot, const char *key_label,
  404. unsigned char *key_id, size_t key_id_len)
  405. {
  406. PKCS11_KEY *key_list = NULL, *key = NULL;
  407. unsigned int key_count;
  408. if (PKCS11_enumerate_keys(slot->token, &key_list, &key_count) < 0) {
  409. vpn_progress(vpninfo, PRG_ERR,
  410. _("Failed to enumerate keys in PKCS#11 slot '%s'\n"),
  411. slot->description);
  412. return NULL;
  413. }
  414. vpn_progress(vpninfo, PRG_TRACE,
  415. _("Found %d keys in slot '%s'\n"),
  416. key_count, slot->description);
  417. for (key = key_list; key < &key_list[key_count]; key++) {
  418. if (key_label && strcmp(key_label, key->label))
  419. continue;
  420. if (key_id && (key_id_len != key->id_len ||
  421. memcmp(key_id, key->id, key_id_len)))
  422. continue;
  423. return key;
  424. }
  425. return NULL;
  426. }
  427. #ifndef OPENSSL_NO_EC
  428. #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
  429. #define EVP_PKEY_id(k) ((k)->type)
  430. #endif
  431. static int validate_ecdsa_key(struct openconnect_info *vpninfo, struct cert_info *certinfo,
  432. EC_KEY *priv_ec)
  433. {
  434. EVP_PKEY *pub_pkey;
  435. EC_KEY *pub_ec;
  436. unsigned char rdata[SHA1_SIZE];
  437. unsigned int siglen = ECDSA_size(priv_ec);
  438. unsigned char *sig;
  439. int ret = -EINVAL;
  440. pub_pkey = X509_get_pubkey(vpninfo->cert_x509);
  441. if (!pub_pkey) {
  442. vpn_progress(vpninfo, PRG_ERR,
  443. certinfo_string(certinfo, _("Certificate has no public key\n"),
  444. _("Secondary certificate has no public key\n")));
  445. goto out;
  446. }
  447. pub_ec = EVP_PKEY_get1_EC_KEY(pub_pkey);
  448. if (!pub_ec) {
  449. vpn_progress(vpninfo, PRG_ERR,
  450. certinfo_string(certinfo, _("Certificate does not match private key\n"),
  451. _("Secondary certificate does not match private key\n")));
  452. goto out_pkey;
  453. }
  454. vpn_progress(vpninfo, PRG_TRACE, _("Checking EC key matches cert\n"));
  455. sig = malloc(siglen);
  456. if (!sig) {
  457. vpn_progress(vpninfo, PRG_ERR,
  458. _("Failed to allocate signature buffer\n"));
  459. ret = -ENOMEM;
  460. goto out_pubec;
  461. }
  462. if (!RAND_bytes(rdata, sizeof(rdata))) {
  463. /* Actually, who cares? */
  464. }
  465. if (!ECDSA_sign(NID_sha1, rdata, sizeof(rdata),
  466. sig, &siglen, priv_ec)) {
  467. vpn_progress(vpninfo, PRG_ERR,
  468. _("Failed to sign dummy data to validate EC key\n"));
  469. openconnect_report_ssl_errors(vpninfo);
  470. goto out_sig;
  471. }
  472. if (!ECDSA_verify(NID_sha1, rdata, sizeof(rdata), sig, siglen, pub_ec)) {
  473. vpn_progress(vpninfo, PRG_ERR,
  474. certinfo_string(certinfo, _("Certificate does not match private key\n"),
  475. _("Secondary certificate does not match private key\n")));
  476. goto out_sig;
  477. }
  478. /* Finally, copy the public EC_POINT data now that we know it really did match */
  479. EC_KEY_set_public_key(priv_ec, EC_KEY_get0_public_key(pub_ec));
  480. ret = 0;
  481. out_sig:
  482. free(sig);
  483. out_pubec:
  484. EC_KEY_free(pub_ec);
  485. out_pkey:
  486. EVP_PKEY_free(pub_pkey);
  487. out:
  488. return ret;
  489. }
  490. #endif
  491. int load_pkcs11_key(struct openconnect_info *vpninfo, struct cert_info *certinfo, EVP_PKEY **keyp)
  492. {
  493. PKCS11_CTX *ctx;
  494. PKCS11_TOKEN *match_tok = NULL;
  495. PKCS11_KEY *key = NULL;
  496. EVP_PKEY *pkey = NULL;
  497. char *key_label = NULL;
  498. unsigned char *key_id = NULL;
  499. size_t key_id_len = 0;
  500. PKCS11_SLOT *slot_list = NULL, *slot, *login_slot = NULL;
  501. unsigned int slot_count, matching_slots = 0;
  502. int ret = 0;
  503. ctx = pkcs11_ctx(vpninfo);
  504. if (!ctx)
  505. return -EIO;
  506. if (parse_pkcs11_uri(certinfo->key, &match_tok, &key_id,
  507. &key_id_len, &key_label, &certinfo->password) < 0) {
  508. vpn_progress(vpninfo, PRG_ERR,
  509. _("Failed to parse PKCS#11 URI '%s'\n"),
  510. certinfo->key);
  511. return -EINVAL;
  512. }
  513. if (vpninfo->pkcs11_slot_list) {
  514. slot_list = vpninfo->pkcs11_slot_list;
  515. slot_count = vpninfo->pkcs11_slot_count;
  516. } else if (PKCS11_enumerate_slots(ctx, &slot_list, &slot_count) < 0) {
  517. vpn_progress(vpninfo, PRG_ERR,
  518. _("Failed to enumerate PKCS#11 slots\n"));
  519. openconnect_report_ssl_errors(vpninfo);
  520. ret = -EIO;
  521. goto out;
  522. }
  523. for (slot = slot_list; slot < &slot_list[slot_count] && slot != login_slot; slot++) {
  524. if (!slot->token)
  525. continue;
  526. if (match_tok->label &&
  527. strcmp(match_tok->label, slot->token->label))
  528. continue;
  529. if (match_tok->manufacturer &&
  530. strcmp(match_tok->manufacturer, slot->token->manufacturer))
  531. continue;
  532. if (match_tok->model &&
  533. strcmp(match_tok->model, slot->token->model))
  534. continue;
  535. if (match_tok->serialnr &&
  536. strcmp(match_tok->serialnr, slot->token->serialnr))
  537. continue;
  538. key = slot_find_key(vpninfo, ctx, slot, key_label, key_id, key_id_len);
  539. if (key)
  540. goto got_key;
  541. login_slot = slot;
  542. matching_slots++;
  543. }
  544. /* If there was precisely one matching slot, or if we know which slot
  545. the cert was found in and the key wasn't separately specified, then
  546. try that slot. */
  547. if (matching_slots != 1 && vpninfo->pkcs11_cert_slot &&
  548. certinfo->key == certinfo->cert) {
  549. /* Use the slot the cert was found in, if one specifier was given for both */
  550. matching_slots = 1;
  551. login_slot = vpninfo->pkcs11_cert_slot;
  552. vpninfo->pkcs11_cert_slot = NULL;
  553. }
  554. if (matching_slots == 1 && (login_slot->token->loginRequired || login_slot->token->userPinSet)) {
  555. slot = login_slot;
  556. vpn_progress(vpninfo, PRG_INFO,
  557. _("Logging in to PKCS#11 slot '%s'\n"),
  558. slot->description);
  559. if (!slot_login(vpninfo, certinfo, ctx, slot)) {
  560. key = slot_find_key(vpninfo, ctx, slot, key_label, key_id, key_id_len);
  561. if (key)
  562. goto got_key;
  563. /* We still haven't found it. If we weren't explicitly given a URI for
  564. the key and we're inferring the location of the key from the cert,
  565. then drop the label and try matching the CKA_ID of the cert. */
  566. if (certinfo->cert == certinfo->key && vpninfo->pkcs11_cert_id &&
  567. (key_label || !key_id)) {
  568. key = slot_find_key(vpninfo, ctx, slot, NULL, vpninfo->pkcs11_cert_id,
  569. vpninfo->pkcs11_cert_id_len);
  570. if (key)
  571. goto got_key;
  572. }
  573. }
  574. }
  575. ret = -EINVAL;
  576. vpn_progress(vpninfo, PRG_ERR,
  577. _("Failed to find PKCS#11 key '%s'\n"),
  578. certinfo->key);
  579. got_key:
  580. if (key) {
  581. vpn_progress(vpninfo, PRG_DEBUG,
  582. certinfo_string(certinfo, _("Using PKCS#11 key %s\n"),
  583. _("Using secondary PKCS#11 key %s\n")),
  584. certinfo->key);
  585. pkey = PKCS11_get_private_key(key);
  586. if (!pkey) {
  587. vpn_progress(vpninfo, PRG_ERR,
  588. certinfo_string(certinfo, _("Failed to instantiate private key from PKCS#11\n"),
  589. _("Failed to instantiate secondary private key from PKCS#11\n")));
  590. openconnect_report_ssl_errors(vpninfo);
  591. ret = -EIO;
  592. goto out;
  593. }
  594. #ifndef OPENSSL_NO_EC
  595. /*
  596. * If an EC EVP_PKEY has no public key, OpenSSL will crash
  597. * when trying to check it matches the certificate:
  598. * https://github.com/openssl/openssl/issues/1532
  599. *
  600. * Work around this by detecting this condition, manually
  601. * checking that the certificate *does* match by performing
  602. * a signature and validating it against the cert, then
  603. * copying the EC_POINT public key information from the cert.
  604. */
  605. if (EVP_PKEY_id(pkey) == EVP_PKEY_EC) {
  606. EC_KEY *priv_ec = EVP_PKEY_get1_EC_KEY(pkey);
  607. ret = 0;
  608. if (!EC_KEY_get0_public_key(priv_ec))
  609. ret = validate_ecdsa_key(vpninfo, certinfo, priv_ec);
  610. EC_KEY_free(priv_ec);
  611. if (ret)
  612. goto out;
  613. }
  614. #endif
  615. *keyp = pkey;
  616. /* We have to keep the entire slot list around, because the EVP_PKEY
  617. depends on the one we're using, and we have no way to free the
  618. others. */
  619. vpninfo->pkcs11_slot_list = slot_list;
  620. vpninfo->pkcs11_slot_count = slot_count;
  621. slot_list = NULL;
  622. }
  623. out:
  624. if (match_tok) {
  625. free(match_tok->model);
  626. free(match_tok->manufacturer);
  627. free(match_tok->serialnr);
  628. free(match_tok->label);
  629. free(match_tok);
  630. }
  631. free(key_id);
  632. free(key_label);
  633. if (slot_list)
  634. PKCS11_release_all_slots(ctx, slot_list, slot_count);
  635. return ret;
  636. }
  637. #else
  638. int load_pkcs11_key(struct openconnect_info *vpninfo, struct cert_info *certinfo, EVP_PKEY **keyp)
  639. {
  640. vpn_progress(vpninfo, PRG_ERR,
  641. _("This version of OpenConnect was built without PKCS#11 support\n"));
  642. return -EINVAL;
  643. }
  644. int load_pkcs11_certificate(struct openconnect_info *vpninfo, struct cert_info *certinfo, X509 **certp)
  645. {
  646. vpn_progress(vpninfo, PRG_ERR,
  647. _("This version of OpenConnect was built without PKCS#11 support\n"));
  648. return -EINVAL;
  649. }
  650. #endif