gnutls_tpm2.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  1. /*
  2. * OpenConnect (SSL + DTLS) VPN client
  3. *
  4. * Copyright © 2018 David Woodhouse.
  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 "gnutls.h"
  20. #include <gnutls/gnutls.h>
  21. #include <errno.h>
  22. #include <string.h>
  23. #ifdef HAVE_TSS2
  24. #include <libtasn1.h>
  25. /*
  26. * TPMKey ::= SEQUENCE {
  27. * type OBJECT IDENTIFIER,
  28. * emptyAuth [0] EXPLICIT BOOLEAN OPTIONAL,
  29. * parent INTEGER,
  30. * pubkey OCTET STRING,
  31. * privkey OCTET STRING
  32. * }
  33. */
  34. const asn1_static_node tpmkey_asn1_tab[] = {
  35. { "TPMKey", 536875024, NULL },
  36. { NULL, 1073741836, NULL },
  37. { "TPMKey", 536870917, NULL },
  38. { "type", 1073741836, NULL },
  39. { "emptyAuth", 1610637316, NULL },
  40. { NULL, 2056, "0"},
  41. { "parent", 1073741827, NULL },
  42. { "pubkey", 1073741831, NULL },
  43. { "privkey", 7, NULL },
  44. { NULL, 0, NULL }
  45. };
  46. const asn1_static_node tpmkey_asn1_tab_old[] = {
  47. { "TPMKey", 536875024, NULL },
  48. { NULL, 1073741836, NULL },
  49. { "TPMKey", 536870917, NULL },
  50. { "type", 1073741836, NULL },
  51. { "emptyAuth", 1610637316, NULL },
  52. { NULL, 2056, "0"},
  53. { "parent", 1610637315, NULL },
  54. { NULL, 2056, "1"},
  55. { "pubkey", 1610637319, NULL },
  56. { NULL, 2056, "2"},
  57. { "privkey", 7, NULL },
  58. { NULL, 0, NULL }
  59. };
  60. static const char OID_legacy_loadableKey[] = "2.23.133.10.2";
  61. static const char OID_loadableKey[] = "2.23.133.10.1.3";
  62. #if GNUTLS_VERSION_NUMBER < 0x030600
  63. static int tpm2_rsa_sign_fn(gnutls_privkey_t key, void *_certinfo,
  64. const gnutls_datum_t *data, gnutls_datum_t *sig)
  65. {
  66. return tpm2_rsa_sign_hash_fn(key, GNUTLS_SIGN_UNKNOWN, _certinfo, 0, data, sig);
  67. }
  68. static int tpm2_ec_sign_fn(gnutls_privkey_t key, void *_certinfo,
  69. const gnutls_datum_t *data, gnutls_datum_t *sig)
  70. {
  71. struct cert_info *certinfo = _certinfo;
  72. struct openconnect_info *vpninfo = certinfo->vpninfo;
  73. gnutls_sign_algorithm_t algo;
  74. switch (data->size) {
  75. case SHA1_SIZE: algo = GNUTLS_SIGN_ECDSA_SHA1; break;
  76. case SHA256_SIZE: algo = GNUTLS_SIGN_ECDSA_SHA256; break;
  77. case SHA384_SIZE: algo = GNUTLS_SIGN_ECDSA_SHA384; break;
  78. case SHA512_SIZE: algo = GNUTLS_SIGN_ECDSA_SHA512; break;
  79. default:
  80. vpn_progress(vpninfo, PRG_ERR,
  81. _("Unknown TPM2 EC digest size %d\n"),
  82. data->size);
  83. return GNUTLS_E_PK_SIGN_FAILED;
  84. }
  85. return tpm2_ec_sign_hash_fn(key, algo, certinfo, 0, data, sig);
  86. }
  87. #endif
  88. #if GNUTLS_VERSION_NUMBER >= 0x030600
  89. static int rsa_key_info(gnutls_privkey_t key, unsigned int flags, void *_certinfo)
  90. {
  91. struct cert_info *certinfo = _certinfo;
  92. struct openconnect_info *vpninfo = certinfo->vpninfo;
  93. if (flags & GNUTLS_PRIVKEY_INFO_PK_ALGO)
  94. return GNUTLS_PK_RSA;
  95. if (flags & GNUTLS_PRIVKEY_INFO_SIGN_ALGO)
  96. return GNUTLS_SIGN_RSA_RAW;
  97. int bits = tpm2_rsa_key_bits(vpninfo, certinfo);
  98. if (flags & GNUTLS_PRIVKEY_INFO_PK_ALGO_BITS)
  99. return bits;
  100. if (flags & GNUTLS_PRIVKEY_INFO_HAVE_SIGN_ALGO) {
  101. gnutls_sign_algorithm_t algo = GNUTLS_FLAGS_TO_SIGN_ALGO(flags);
  102. switch (algo) {
  103. case GNUTLS_SIGN_RSA_RAW:
  104. case GNUTLS_SIGN_RSA_SHA1:
  105. case GNUTLS_SIGN_RSA_SHA256:
  106. case GNUTLS_SIGN_RSA_SHA384:
  107. case GNUTLS_SIGN_RSA_SHA512:
  108. return 1;
  109. /* Only support RSA-PSS for a given hash if the key is large
  110. * enough, since RFC8446 mandates that the salt length MUST
  111. * equal the digest output length. So we need 2N + 2 bytes. */
  112. case GNUTLS_SIGN_RSA_PSS_SHA256:
  113. case GNUTLS_SIGN_RSA_PSS_RSAE_SHA256:
  114. if (bits >= (SHA256_SIZE * 16) + 16)
  115. return 1;
  116. /* Fall through */
  117. case GNUTLS_SIGN_RSA_PSS_SHA384:
  118. case GNUTLS_SIGN_RSA_PSS_RSAE_SHA384:
  119. if (bits >= (SHA384_SIZE * 16) + 16)
  120. return 1;
  121. /* Fall through */
  122. case GNUTLS_SIGN_RSA_PSS_SHA512:
  123. case GNUTLS_SIGN_RSA_PSS_RSAE_SHA512:
  124. if (bits >= (SHA512_SIZE * 16) + 16)
  125. return 1;
  126. /* Fall through */
  127. default:
  128. vpn_progress(vpninfo, PRG_DEBUG,
  129. _("Not supporting EC sign algo %s\n"),
  130. gnutls_sign_get_name(algo));
  131. return 0;
  132. }
  133. }
  134. return -1;
  135. }
  136. #endif
  137. #if GNUTLS_VERSION_NUMBER >= 0x030400
  138. static int ec_key_info(gnutls_privkey_t key, unsigned int flags, void *_certinfo)
  139. {
  140. if (flags & GNUTLS_PRIVKEY_INFO_PK_ALGO)
  141. return GNUTLS_PK_EC;
  142. #ifdef GNUTLS_PRIVKEY_INFO_HAVE_SIGN_ALGO
  143. if (flags & GNUTLS_PRIVKEY_INFO_HAVE_SIGN_ALGO) {
  144. struct cert_info *certinfo = _certinfo;
  145. struct openconnect_info *vpninfo = certinfo->vpninfo;
  146. uint16_t tpm2_curve = tpm2_key_curve(vpninfo, certinfo);
  147. gnutls_sign_algorithm_t algo = GNUTLS_FLAGS_TO_SIGN_ALGO(flags);
  148. switch (algo) {
  149. case GNUTLS_SIGN_ECDSA_SHA1:
  150. case GNUTLS_SIGN_ECDSA_SHA256:
  151. return 1;
  152. case GNUTLS_SIGN_ECDSA_SECP256R1_SHA256:
  153. return tpm2_curve == 0x0003; /* TPM2_ECC_NIST_P256 */
  154. case GNUTLS_SIGN_ECDSA_SECP384R1_SHA384:
  155. return tpm2_curve == 0x0004; /* TPM2_ECC_NIST_P384 */
  156. case GNUTLS_SIGN_ECDSA_SECP521R1_SHA512:
  157. return tpm2_curve == 0x0005; /* TPM2_ECC_NIST_P521 */
  158. default:
  159. vpn_progress(vpninfo, PRG_DEBUG,
  160. _("Not supporting EC sign algo %s\n"),
  161. gnutls_sign_get_name(algo));
  162. return 0;
  163. }
  164. }
  165. #endif
  166. if (flags & GNUTLS_PRIVKEY_INFO_SIGN_ALGO)
  167. return GNUTLS_SIGN_ECDSA_SHA256;
  168. return -1;
  169. }
  170. #endif
  171. static int decode_data(ASN1_TYPE n, gnutls_datum_t *r)
  172. {
  173. ASN1_DATA_NODE d;
  174. int len, lenlen;
  175. if (!n)
  176. return -EINVAL;
  177. if (asn1_read_node_value(n, &d) != ASN1_SUCCESS)
  178. return -EINVAL;
  179. len = asn1_get_length_der(d.value, d.value_len, &lenlen);
  180. if (len < 0)
  181. return -EINVAL;
  182. r->data = (unsigned char *)d.value + lenlen;
  183. r->size = len;
  184. return 0;
  185. }
  186. int load_tpm2_key(struct openconnect_info *vpninfo, struct cert_info *certinfo,
  187. gnutls_datum_t *fdata, gnutls_privkey_t *pkey, gnutls_datum_t *pkey_sig)
  188. {
  189. gnutls_datum_t asn1, pubdata, privdata;
  190. ASN1_TYPE tpmkey_def = ASN1_TYPE_EMPTY, tpmkey = ASN1_TYPE_EMPTY;
  191. const char *oid = NULL;
  192. char value_buf[16];
  193. int value_buflen;
  194. int emptyauth = 0;
  195. unsigned int parent;
  196. int err, ret = -EINVAL;
  197. const asn1_static_node *asn1tab;
  198. err = gnutls_pem_base64_decode_alloc("TSS2 PRIVATE KEY", fdata, &asn1);
  199. if (!err) {
  200. asn1tab = tpmkey_asn1_tab;
  201. oid = OID_loadableKey;
  202. } else {
  203. if (gnutls_pem_base64_decode_alloc("TSS2 KEY BLOB", fdata, &asn1)) {
  204. /* Report the first error */
  205. vpn_progress(vpninfo, PRG_ERR,
  206. _("Error decoding TSS2 key blob: %s\n"),
  207. gnutls_strerror(err));
  208. return -EINVAL;
  209. }
  210. asn1tab = tpmkey_asn1_tab_old;
  211. oid = OID_legacy_loadableKey;
  212. }
  213. err = asn1_array2tree(asn1tab, &tpmkey_def, NULL);
  214. if (err != ASN1_SUCCESS) {
  215. vpn_progress(vpninfo, PRG_ERR,
  216. _("Failed to create ASN.1 type for TPM2: %s\n"),
  217. asn1_strerror(err));
  218. goto out_asn1;
  219. }
  220. asn1_create_element(tpmkey_def, "TPMKey.TPMKey", &tpmkey);
  221. err = asn1_der_decoding(&tpmkey, asn1.data, asn1.size, NULL);
  222. if (err != ASN1_SUCCESS) {
  223. vpn_progress(vpninfo, PRG_ERR,
  224. _("Failed to decode TPM2 key ASN.1: %s\n"),
  225. asn1_strerror(err));
  226. goto out_tpmkey;
  227. }
  228. value_buflen = sizeof(value_buf);
  229. if (asn1_read_value(tpmkey, "type", value_buf, &value_buflen)) {
  230. vpn_progress(vpninfo, PRG_ERR,
  231. _("Failed to parse TPM2 key type OID: %s\n"),
  232. asn1_strerror(err));
  233. goto out_tpmkey;
  234. }
  235. if (strncmp(value_buf, oid, value_buflen)) {
  236. vpn_progress(vpninfo, PRG_ERR,
  237. _("TPM2 key has unknown type OID %s not %s\n"),
  238. value_buf, oid);
  239. goto out_tpmkey;
  240. }
  241. value_buflen = sizeof(value_buf);
  242. if (!asn1_read_value(tpmkey, "emptyAuth", value_buf, &value_buflen) &&
  243. !strcmp(value_buf, "TRUE"))
  244. emptyauth = 1;
  245. memset(value_buf, 0, 5);
  246. value_buflen = 5;
  247. err = asn1_read_value(tpmkey, "parent", value_buf, &value_buflen);
  248. if (err == ASN1_ELEMENT_NOT_FOUND)
  249. parent = 0x40000001; // RH_OWNER
  250. else if (err != ASN1_SUCCESS) {
  251. badparent:
  252. vpn_progress(vpninfo, PRG_ERR,
  253. _("Failed to parse TPM2 key parent: %s\n"),
  254. asn1_strerror(err));
  255. goto out_tpmkey;
  256. } else {
  257. int i = 0;
  258. parent = 0;
  259. if (value_buflen == 5) {
  260. if (value_buf[0])
  261. goto badparent;
  262. /* Skip the leading zero */
  263. i++;
  264. }
  265. for ( ; i < value_buflen; i++) {
  266. parent <<= 8;
  267. parent |= value_buf[i];
  268. }
  269. }
  270. if (decode_data(asn1_find_node(tpmkey, "pubkey"), &pubdata) < 0) {
  271. vpn_progress(vpninfo, PRG_ERR,
  272. _("Failed to parse TPM2 pubkey element\n"));
  273. goto out_tpmkey;
  274. }
  275. if (decode_data(asn1_find_node(tpmkey, "privkey"), &privdata) < 0) {
  276. vpn_progress(vpninfo, PRG_ERR,
  277. _("Failed to parse TPM2 privkey element\n"));
  278. goto out_tpmkey;
  279. }
  280. vpn_progress(vpninfo, PRG_DEBUG,
  281. _("Parsed TPM2 key with parent %x, emptyauth %d\n"),
  282. parent, emptyauth);
  283. /* Now we've extracted what we need from the ASN.1, invoke the
  284. * actual TPM2 code (whichever implementation we end up with */
  285. ret = install_tpm2_key(vpninfo, certinfo, pkey, pkey_sig, parent, emptyauth,
  286. asn1tab == tpmkey_asn1_tab_old, &privdata, &pubdata);
  287. if (ret < 0)
  288. goto out_tpmkey;
  289. gnutls_privkey_init(pkey);
  290. switch(ret) {
  291. case GNUTLS_PK_RSA:
  292. #if GNUTLS_VERSION_NUMBER >= 0x030600
  293. gnutls_privkey_import_ext4(*pkey, certinfo, NULL, tpm2_rsa_sign_hash_fn, NULL, NULL, rsa_key_info, 0);
  294. #else
  295. gnutls_privkey_import_ext(*pkey, GNUTLS_PK_RSA, certinfo, tpm2_rsa_sign_fn, NULL, 0);
  296. #endif
  297. break;
  298. case GNUTLS_PK_ECC:
  299. #if GNUTLS_VERSION_NUMBER >= 0x030600
  300. gnutls_privkey_import_ext4(*pkey, certinfo, NULL, tpm2_ec_sign_hash_fn, NULL, NULL, ec_key_info, 0);
  301. #elif GNUTLS_VERSION_NUMBER >= 0x030400
  302. gnutls_privkey_import_ext3(*pkey, certinfo, tpm2_ec_sign_fn, NULL, NULL, ec_key_info, 0);
  303. #else
  304. gnutls_privkey_import_ext(*pkey, GNUTLS_PK_EC, certinfo, tpm2_ec_sign_fn, NULL, 0);
  305. #endif
  306. break;
  307. }
  308. ret = 0;
  309. out_tpmkey:
  310. asn1_delete_structure(&tpmkey);
  311. asn1_delete_structure(&tpmkey_def);
  312. out_asn1:
  313. free(asn1.data);
  314. return ret;
  315. }
  316. #if GNUTLS_VERSION_NUMBER < 0x030600
  317. static void append_bignum(struct oc_text_buf *sig_der, const gnutls_datum_t *d)
  318. {
  319. unsigned char derlen[2];
  320. buf_append_bytes(sig_der, "\x02", 1); // INTEGER
  321. derlen[0] = d->size;
  322. /* If it might be interpreted as negative, prepend a zero */
  323. if (d->data[0] >= 0x80) {
  324. derlen[0]++;
  325. derlen[1] = 0;
  326. buf_append_bytes(sig_der, derlen, 2);
  327. } else {
  328. buf_append_bytes(sig_der, derlen, 1);
  329. }
  330. buf_append_bytes(sig_der, d->data, d->size);
  331. }
  332. int oc_gnutls_encode_rs_value(gnutls_datum_t *sig, const gnutls_datum_t *sig_r,
  333. const gnutls_datum_t *sig_s)
  334. {
  335. struct oc_text_buf *sig_der = NULL;
  336. /*
  337. * Create the DER-encoded SEQUENCE containing R and S:
  338. *
  339. * DSASignatureValue ::= SEQUENCE {
  340. * r INTEGER,
  341. * s INTEGER
  342. * }
  343. */
  344. sig_der = buf_alloc();
  345. buf_append_bytes(sig_der, "\x30\x80", 2); // SEQUENCE, indeterminate length
  346. append_bignum(sig_der, sig_r);
  347. append_bignum(sig_der, sig_s);
  348. /* If the length actually fits in one byte (which it should), do
  349. * it that way. Else, leave it indeterminate and add two
  350. * end-of-contents octets to mark the end of the SEQUENCE. */
  351. if (!buf_error(sig_der) && sig_der->pos <= 0x80)
  352. sig_der->data[1] = sig_der->pos - 2;
  353. else {
  354. buf_append_bytes(sig_der, "\0\0", 2);
  355. if (buf_error(sig_der))
  356. goto out;
  357. }
  358. sig->data = (void *)sig_der->data;
  359. sig->size = sig_der->pos;
  360. sig_der->data = NULL;
  361. out:
  362. return buf_free(sig_der);
  363. }
  364. #endif /* GnuTLS < 3.6.0 */
  365. /* EMSA-PKCS1-v1_5 padding in accordance with RFC3447 §9.2 */
  366. #define PKCS1_PAD_OVERHEAD 11
  367. static int oc_pkcs1_pad(struct openconnect_info *vpninfo,
  368. unsigned char *buf, int size, const gnutls_datum_t *data)
  369. {
  370. if (data->size + PKCS1_PAD_OVERHEAD > size) {
  371. vpn_progress(vpninfo, PRG_ERR,
  372. _("TPM2 digest too large: %d > %d\n"),
  373. data->size, size - PKCS1_PAD_OVERHEAD);
  374. return GNUTLS_E_PK_SIGN_FAILED;
  375. }
  376. buf[0] = 0;
  377. buf[1] = 1;
  378. memset(buf + 2, 0xff, size - data->size - 3);
  379. buf[size - data->size - 1] = 0;
  380. memcpy(buf + size - data->size, data->data, data->size);
  381. return 0;
  382. }
  383. #if GNUTLS_VERSION_NUMBER >= 0x030600
  384. /* EMSA-PSS encoding in accordance with RFC3447 §9.1 */
  385. static int oc_pss_mgf1_pad(struct openconnect_info *vpninfo, gnutls_digest_algorithm_t dig,
  386. unsigned char *emBuf, int emLen, const gnutls_datum_t *mHash, int keybits)
  387. {
  388. gnutls_hash_hd_t hashctx = NULL;
  389. int err = GNUTLS_E_PK_SIGN_FAILED;
  390. /* The emBits for EMSA-PSS encoding is actually one *fewer* bit than
  391. * the RSA modulus. As RFC3447 §8.1.1 points out, "the octet length
  392. * of EM will be one less than k if modBits - 1 is divisible by 8
  393. * and equal to k otherwise". Where k is the input emLen, which we
  394. * thus need to adjust before using it as emLen for the following
  395. * operations. Not that it matters much since I don't think the TPM
  396. * can cope with RSA keys whose modulus isn't a multiple of 8 bits
  397. * anyway. */
  398. int msbits = (keybits - 1) & 7;
  399. if (!msbits) {
  400. *(emBuf++) = 0;
  401. emLen--;
  402. }
  403. /* GnuTLS gives us a predigested mHash from which we create M' and
  404. * continue the process. Can we infer all the PSS parameters from
  405. * the digest size, including the salt size? Or does GnuTLS need
  406. * a gnutls_privkey_import_ext5() which lets us have the params too?
  407. * Better still, could GnuTLS just do this all for us and we only
  408. * do a raw signature — really raw, unlike GNUTLS_SIGN_RSA_RAW
  409. * which AIUI is actually padded. */
  410. /* Actually, RFC8446 §4.2.3 mandates that the salt length MUST be
  411. * equal to the length of the output of the digest algorithm. So
  412. * truncating is it *wrong*.
  413. *
  414. * • https://gitlab.com/gnutls/gnutls/-/issues/1258
  415. * • https://github.com/openssl/openssl/issues/16167
  416. */
  417. int sLen = mHash->size;
  418. if (sLen + mHash->size > emLen - 2) {
  419. vpn_progress(vpninfo, PRG_ERR,
  420. _("PSS encoding failed; hash size %d too large for RSA key %d\n"),
  421. mHash->size, emLen);
  422. return GNUTLS_E_PK_SIGN_FAILED;
  423. }
  424. /*
  425. * We don't truncate salt since RFC8446 forbids it for TLSv1.3 and
  426. * that's all we are using it for.
  427. *
  428. * if (sLen + mHash->size > emLen - 2)
  429. * sLen = emLen - 2 - mHash->size;
  430. */
  431. char salt[SHA512_SIZE];
  432. if (sLen) {
  433. err = gnutls_rnd(GNUTLS_RND_NONCE, salt, sLen);
  434. if (err)
  435. goto out;
  436. }
  437. /* Hash M' (8 zeroes || mHash || salt) into its place in EM */
  438. if ((err = gnutls_hash_init(&hashctx, dig)) ||
  439. (err = gnutls_hash(hashctx, "\0\0\0\0\0\0\0\0", 8)) ||
  440. (err = gnutls_hash(hashctx, mHash->data, mHash->size)) ||
  441. (sLen && (err = gnutls_hash(hashctx, salt, sLen))))
  442. goto out;
  443. int maskedDBLen = emLen - mHash->size - 1;
  444. gnutls_hash_output(hashctx, emBuf + maskedDBLen);
  445. emBuf[emLen - 1] = 0xbc;
  446. /* Although gnutls_hash_output() is supposed to reset the context,
  447. * it doesn't actually seem to work at least for SHA384; the later
  448. * gnutls_hash_copy() ends up wrong somehow, and gives incorrect
  449. * output. Unless we completely destroy the context and make a
  450. * new one. https://gitlab.com/gnutls/gnutls/-/issues/1257 */
  451. gnutls_hash_deinit(hashctx, NULL);
  452. err = gnutls_hash_init(&hashctx, dig);
  453. if (err) {
  454. hashctx = NULL;
  455. goto out;
  456. }
  457. /* Now the MGF1 function as defined in RFC3447 Appendix B, although
  458. * it's somewhat easier to read in NIST SP 800-56B §7.2.2.2.
  459. *
  460. * We repeatedly hash (M' || C) where C is an incrementing 32-bit
  461. * counter, so hash M' first and then use gnutls_hash_copy() each
  462. * time to add C to the copy. */
  463. err = gnutls_hash(hashctx, emBuf + maskedDBLen, mHash->size);
  464. if (err)
  465. goto out;
  466. int mgflen = 0, mgf_count = 0;
  467. while (mgflen < maskedDBLen) {
  468. gnutls_hash_hd_t ctx2 = gnutls_hash_copy(hashctx);
  469. if (!ctx2) {
  470. err = GNUTLS_E_PK_SIGN_FAILED;
  471. goto out;
  472. }
  473. uint32_t be_count = htonl(mgf_count++);
  474. err = gnutls_hash(ctx2, &be_count, sizeof(be_count));
  475. if (err) {
  476. gnutls_hash_deinit(ctx2, NULL);
  477. goto out;
  478. }
  479. if (mgflen + mHash->size <= maskedDBLen) {
  480. gnutls_hash_deinit(ctx2, emBuf + mgflen);
  481. mgflen += mHash->size;
  482. } else {
  483. char md[SHA512_SIZE];
  484. gnutls_hash_deinit(ctx2, md);
  485. memcpy(emBuf + mgflen, md, maskedDBLen - mgflen);
  486. mgflen = maskedDBLen;
  487. }
  488. }
  489. /* Back to EMSA-PSS-ENCODE step 10. The MGF result was directly placed
  490. * into emBuf, so now XOR with DB, which is (zeroes || 0x01 || salt) */
  491. int dst = maskedDBLen - 1;
  492. while (sLen--)
  493. emBuf[dst--] ^= salt[sLen];
  494. emBuf[dst] ^= 0x01;
  495. /* Now mask out the high bits. In the case where msbits is zero, we
  496. * skipped the entire first byte so do nothing. */
  497. if (msbits)
  498. emBuf[0] &= 0xFF >> (8 - msbits);
  499. err = 0;
  500. out:
  501. if (hashctx)
  502. gnutls_hash_deinit(hashctx, NULL);
  503. return err;
  504. }
  505. #endif
  506. int oc_pad_rsasig(struct openconnect_info *vpninfo, gnutls_sign_algorithm_t algo,
  507. unsigned char *buf, int size, const gnutls_datum_t *data, int keybits)
  508. {
  509. switch(algo) {
  510. case GNUTLS_SIGN_UNKNOWN:
  511. case GNUTLS_SIGN_RSA_SHA1:
  512. case GNUTLS_SIGN_RSA_SHA256:
  513. case GNUTLS_SIGN_RSA_SHA384:
  514. case GNUTLS_SIGN_RSA_SHA512:
  515. return oc_pkcs1_pad(vpninfo, buf, size, data);
  516. #if GNUTLS_VERSION_NUMBER >= 0x030600
  517. /* Really PKCS#1.5 padding, yes. */
  518. case GNUTLS_SIGN_RSA_RAW:
  519. return oc_pkcs1_pad(vpninfo, buf, size, data);
  520. case GNUTLS_SIGN_RSA_PSS_SHA256:
  521. case GNUTLS_SIGN_RSA_PSS_RSAE_SHA256:
  522. if (data->size != SHA256_SIZE)
  523. return GNUTLS_E_PK_SIGN_FAILED;
  524. return oc_pss_mgf1_pad(vpninfo, GNUTLS_DIG_SHA256, buf, size, data, keybits);
  525. case GNUTLS_SIGN_RSA_PSS_SHA384:
  526. case GNUTLS_SIGN_RSA_PSS_RSAE_SHA384:
  527. if (data->size != SHA384_SIZE)
  528. return GNUTLS_E_PK_SIGN_FAILED;
  529. return oc_pss_mgf1_pad(vpninfo, GNUTLS_DIG_SHA384, buf, size, data, keybits);
  530. case GNUTLS_SIGN_RSA_PSS_SHA512:
  531. case GNUTLS_SIGN_RSA_PSS_RSAE_SHA512:
  532. if (data->size != SHA512_SIZE)
  533. return GNUTLS_E_PK_SIGN_FAILED;
  534. return oc_pss_mgf1_pad(vpninfo, GNUTLS_DIG_SHA512, buf, size, data, keybits);
  535. #endif /* 3.6.0+ */
  536. default:
  537. vpn_progress(vpninfo, PRG_ERR,
  538. _("TPMv2 RSA sign called for unknown algorithm %s\n"),
  539. gnutls_sign_get_name(algo));
  540. return GNUTLS_E_PK_SIGN_FAILED;
  541. }
  542. }
  543. #endif /* HAVE_TSS2 */