krl.c 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454
  1. /*
  2. * Copyright (c) 2012 Damien Miller <djm@mindrot.org>
  3. *
  4. * Permission to use, copy, modify, and distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. /* $OpenBSD: krl.c,v 1.51 2020/08/27 01:06:18 djm Exp $ */
  17. #include "includes.h"
  18. #include <sys/types.h>
  19. #include <openbsd-compat/sys-tree.h>
  20. #include <openbsd-compat/sys-queue.h>
  21. #include <errno.h>
  22. #include <fcntl.h>
  23. #include <limits.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <time.h>
  27. #include <unistd.h>
  28. #include "sshbuf.h"
  29. #include "ssherr.h"
  30. #include "sshkey.h"
  31. #include "authfile.h"
  32. #include "misc.h"
  33. #include "log.h"
  34. #include "digest.h"
  35. #include "bitmap.h"
  36. #include "utf8.h"
  37. #include "krl.h"
  38. /* #define DEBUG_KRL */
  39. #ifdef DEBUG_KRL
  40. # define KRL_DBG(x) debug3 x
  41. #else
  42. # define KRL_DBG(x)
  43. #endif
  44. /*
  45. * Trees of revoked serial numbers, key IDs and keys. This allows
  46. * quick searching, querying and producing lists in canonical order.
  47. */
  48. /* Tree of serial numbers. XXX make smarter: really need a real sparse bitmap */
  49. struct revoked_serial {
  50. u_int64_t lo, hi;
  51. RB_ENTRY(revoked_serial) tree_entry;
  52. };
  53. static int serial_cmp(struct revoked_serial *a, struct revoked_serial *b);
  54. RB_HEAD(revoked_serial_tree, revoked_serial);
  55. RB_GENERATE_STATIC(revoked_serial_tree, revoked_serial, tree_entry, serial_cmp);
  56. /* Tree of key IDs */
  57. struct revoked_key_id {
  58. char *key_id;
  59. RB_ENTRY(revoked_key_id) tree_entry;
  60. };
  61. static int key_id_cmp(struct revoked_key_id *a, struct revoked_key_id *b);
  62. RB_HEAD(revoked_key_id_tree, revoked_key_id);
  63. RB_GENERATE_STATIC(revoked_key_id_tree, revoked_key_id, tree_entry, key_id_cmp);
  64. /* Tree of blobs (used for keys and fingerprints) */
  65. struct revoked_blob {
  66. u_char *blob;
  67. size_t len;
  68. RB_ENTRY(revoked_blob) tree_entry;
  69. };
  70. static int blob_cmp(struct revoked_blob *a, struct revoked_blob *b);
  71. RB_HEAD(revoked_blob_tree, revoked_blob);
  72. RB_GENERATE_STATIC(revoked_blob_tree, revoked_blob, tree_entry, blob_cmp);
  73. /* Tracks revoked certs for a single CA */
  74. struct revoked_certs {
  75. struct sshkey *ca_key;
  76. struct revoked_serial_tree revoked_serials;
  77. struct revoked_key_id_tree revoked_key_ids;
  78. TAILQ_ENTRY(revoked_certs) entry;
  79. };
  80. TAILQ_HEAD(revoked_certs_list, revoked_certs);
  81. struct ssh_krl {
  82. u_int64_t krl_version;
  83. u_int64_t generated_date;
  84. u_int64_t flags;
  85. char *comment;
  86. struct revoked_blob_tree revoked_keys;
  87. struct revoked_blob_tree revoked_sha1s;
  88. struct revoked_blob_tree revoked_sha256s;
  89. struct revoked_certs_list revoked_certs;
  90. };
  91. /* Return equal if a and b overlap */
  92. static int
  93. serial_cmp(struct revoked_serial *a, struct revoked_serial *b)
  94. {
  95. if (a->hi >= b->lo && a->lo <= b->hi)
  96. return 0;
  97. return a->lo < b->lo ? -1 : 1;
  98. }
  99. static int
  100. key_id_cmp(struct revoked_key_id *a, struct revoked_key_id *b)
  101. {
  102. return strcmp(a->key_id, b->key_id);
  103. }
  104. static int
  105. blob_cmp(struct revoked_blob *a, struct revoked_blob *b)
  106. {
  107. int r;
  108. if (a->len != b->len) {
  109. if ((r = memcmp(a->blob, b->blob, MINIMUM(a->len, b->len))) != 0)
  110. return r;
  111. return a->len > b->len ? 1 : -1;
  112. } else
  113. return memcmp(a->blob, b->blob, a->len);
  114. }
  115. struct ssh_krl *
  116. ssh_krl_init(void)
  117. {
  118. struct ssh_krl *krl;
  119. if ((krl = calloc(1, sizeof(*krl))) == NULL)
  120. return NULL;
  121. RB_INIT(&krl->revoked_keys);
  122. RB_INIT(&krl->revoked_sha1s);
  123. RB_INIT(&krl->revoked_sha256s);
  124. TAILQ_INIT(&krl->revoked_certs);
  125. return krl;
  126. }
  127. static void
  128. revoked_certs_free(struct revoked_certs *rc)
  129. {
  130. struct revoked_serial *rs, *trs;
  131. struct revoked_key_id *rki, *trki;
  132. RB_FOREACH_SAFE(rs, revoked_serial_tree, &rc->revoked_serials, trs) {
  133. RB_REMOVE(revoked_serial_tree, &rc->revoked_serials, rs);
  134. free(rs);
  135. }
  136. RB_FOREACH_SAFE(rki, revoked_key_id_tree, &rc->revoked_key_ids, trki) {
  137. RB_REMOVE(revoked_key_id_tree, &rc->revoked_key_ids, rki);
  138. free(rki->key_id);
  139. free(rki);
  140. }
  141. sshkey_free(rc->ca_key);
  142. }
  143. void
  144. ssh_krl_free(struct ssh_krl *krl)
  145. {
  146. struct revoked_blob *rb, *trb;
  147. struct revoked_certs *rc, *trc;
  148. if (krl == NULL)
  149. return;
  150. free(krl->comment);
  151. RB_FOREACH_SAFE(rb, revoked_blob_tree, &krl->revoked_keys, trb) {
  152. RB_REMOVE(revoked_blob_tree, &krl->revoked_keys, rb);
  153. free(rb->blob);
  154. free(rb);
  155. }
  156. RB_FOREACH_SAFE(rb, revoked_blob_tree, &krl->revoked_sha1s, trb) {
  157. RB_REMOVE(revoked_blob_tree, &krl->revoked_sha1s, rb);
  158. free(rb->blob);
  159. free(rb);
  160. }
  161. RB_FOREACH_SAFE(rb, revoked_blob_tree, &krl->revoked_sha256s, trb) {
  162. RB_REMOVE(revoked_blob_tree, &krl->revoked_sha256s, rb);
  163. free(rb->blob);
  164. free(rb);
  165. }
  166. TAILQ_FOREACH_SAFE(rc, &krl->revoked_certs, entry, trc) {
  167. TAILQ_REMOVE(&krl->revoked_certs, rc, entry);
  168. revoked_certs_free(rc);
  169. }
  170. }
  171. void
  172. ssh_krl_set_version(struct ssh_krl *krl, u_int64_t version)
  173. {
  174. krl->krl_version = version;
  175. }
  176. int
  177. ssh_krl_set_comment(struct ssh_krl *krl, const char *comment)
  178. {
  179. free(krl->comment);
  180. if ((krl->comment = strdup(comment)) == NULL)
  181. return SSH_ERR_ALLOC_FAIL;
  182. return 0;
  183. }
  184. /*
  185. * Find the revoked_certs struct for a CA key. If allow_create is set then
  186. * create a new one in the tree if one did not exist already.
  187. */
  188. static int
  189. revoked_certs_for_ca_key(struct ssh_krl *krl, const struct sshkey *ca_key,
  190. struct revoked_certs **rcp, int allow_create)
  191. {
  192. struct revoked_certs *rc;
  193. int r;
  194. *rcp = NULL;
  195. TAILQ_FOREACH(rc, &krl->revoked_certs, entry) {
  196. if ((ca_key == NULL && rc->ca_key == NULL) ||
  197. sshkey_equal(rc->ca_key, ca_key)) {
  198. *rcp = rc;
  199. return 0;
  200. }
  201. }
  202. if (!allow_create)
  203. return 0;
  204. /* If this CA doesn't exist in the list then add it now */
  205. if ((rc = calloc(1, sizeof(*rc))) == NULL)
  206. return SSH_ERR_ALLOC_FAIL;
  207. if (ca_key == NULL)
  208. rc->ca_key = NULL;
  209. else if ((r = sshkey_from_private(ca_key, &rc->ca_key)) != 0) {
  210. free(rc);
  211. return r;
  212. }
  213. RB_INIT(&rc->revoked_serials);
  214. RB_INIT(&rc->revoked_key_ids);
  215. TAILQ_INSERT_TAIL(&krl->revoked_certs, rc, entry);
  216. KRL_DBG(("%s: new CA %s", __func__,
  217. ca_key == NULL ? "*" : sshkey_type(ca_key)));
  218. *rcp = rc;
  219. return 0;
  220. }
  221. static int
  222. insert_serial_range(struct revoked_serial_tree *rt, u_int64_t lo, u_int64_t hi)
  223. {
  224. struct revoked_serial rs, *ers, *crs, *irs;
  225. KRL_DBG(("%s: insert %llu:%llu", __func__, lo, hi));
  226. memset(&rs, 0, sizeof(rs));
  227. rs.lo = lo;
  228. rs.hi = hi;
  229. ers = RB_NFIND(revoked_serial_tree, rt, &rs);
  230. if (ers == NULL || serial_cmp(ers, &rs) != 0) {
  231. /* No entry matches. Just insert */
  232. if ((irs = malloc(sizeof(rs))) == NULL)
  233. return SSH_ERR_ALLOC_FAIL;
  234. memcpy(irs, &rs, sizeof(*irs));
  235. ers = RB_INSERT(revoked_serial_tree, rt, irs);
  236. if (ers != NULL) {
  237. KRL_DBG(("%s: bad: ers != NULL", __func__));
  238. /* Shouldn't happen */
  239. free(irs);
  240. return SSH_ERR_INTERNAL_ERROR;
  241. }
  242. ers = irs;
  243. } else {
  244. KRL_DBG(("%s: overlap found %llu:%llu", __func__,
  245. ers->lo, ers->hi));
  246. /*
  247. * The inserted entry overlaps an existing one. Grow the
  248. * existing entry.
  249. */
  250. if (ers->lo > lo)
  251. ers->lo = lo;
  252. if (ers->hi < hi)
  253. ers->hi = hi;
  254. }
  255. /*
  256. * The inserted or revised range might overlap or abut adjacent ones;
  257. * coalesce as necessary.
  258. */
  259. /* Check predecessors */
  260. while ((crs = RB_PREV(revoked_serial_tree, rt, ers)) != NULL) {
  261. KRL_DBG(("%s: pred %llu:%llu", __func__, crs->lo, crs->hi));
  262. if (ers->lo != 0 && crs->hi < ers->lo - 1)
  263. break;
  264. /* This entry overlaps. */
  265. if (crs->lo < ers->lo) {
  266. ers->lo = crs->lo;
  267. KRL_DBG(("%s: pred extend %llu:%llu", __func__,
  268. ers->lo, ers->hi));
  269. }
  270. RB_REMOVE(revoked_serial_tree, rt, crs);
  271. free(crs);
  272. }
  273. /* Check successors */
  274. while ((crs = RB_NEXT(revoked_serial_tree, rt, ers)) != NULL) {
  275. KRL_DBG(("%s: succ %llu:%llu", __func__, crs->lo, crs->hi));
  276. if (ers->hi != (u_int64_t)-1 && crs->lo > ers->hi + 1)
  277. break;
  278. /* This entry overlaps. */
  279. if (crs->hi > ers->hi) {
  280. ers->hi = crs->hi;
  281. KRL_DBG(("%s: succ extend %llu:%llu", __func__,
  282. ers->lo, ers->hi));
  283. }
  284. RB_REMOVE(revoked_serial_tree, rt, crs);
  285. free(crs);
  286. }
  287. KRL_DBG(("%s: done, final %llu:%llu", __func__, ers->lo, ers->hi));
  288. return 0;
  289. }
  290. int
  291. ssh_krl_revoke_cert_by_serial(struct ssh_krl *krl, const struct sshkey *ca_key,
  292. u_int64_t serial)
  293. {
  294. return ssh_krl_revoke_cert_by_serial_range(krl, ca_key, serial, serial);
  295. }
  296. int
  297. ssh_krl_revoke_cert_by_serial_range(struct ssh_krl *krl,
  298. const struct sshkey *ca_key, u_int64_t lo, u_int64_t hi)
  299. {
  300. struct revoked_certs *rc;
  301. int r;
  302. if (lo > hi || lo == 0)
  303. return SSH_ERR_INVALID_ARGUMENT;
  304. if ((r = revoked_certs_for_ca_key(krl, ca_key, &rc, 1)) != 0)
  305. return r;
  306. return insert_serial_range(&rc->revoked_serials, lo, hi);
  307. }
  308. int
  309. ssh_krl_revoke_cert_by_key_id(struct ssh_krl *krl, const struct sshkey *ca_key,
  310. const char *key_id)
  311. {
  312. struct revoked_key_id *rki, *erki;
  313. struct revoked_certs *rc;
  314. int r;
  315. if ((r = revoked_certs_for_ca_key(krl, ca_key, &rc, 1)) != 0)
  316. return r;
  317. KRL_DBG(("%s: revoke %s", __func__, key_id));
  318. if ((rki = calloc(1, sizeof(*rki))) == NULL ||
  319. (rki->key_id = strdup(key_id)) == NULL) {
  320. free(rki);
  321. return SSH_ERR_ALLOC_FAIL;
  322. }
  323. erki = RB_INSERT(revoked_key_id_tree, &rc->revoked_key_ids, rki);
  324. if (erki != NULL) {
  325. free(rki->key_id);
  326. free(rki);
  327. }
  328. return 0;
  329. }
  330. /* Convert "key" to a public key blob without any certificate information */
  331. static int
  332. plain_key_blob(const struct sshkey *key, u_char **blob, size_t *blen)
  333. {
  334. struct sshkey *kcopy;
  335. int r;
  336. if ((r = sshkey_from_private(key, &kcopy)) != 0)
  337. return r;
  338. if (sshkey_is_cert(kcopy)) {
  339. if ((r = sshkey_drop_cert(kcopy)) != 0) {
  340. sshkey_free(kcopy);
  341. return r;
  342. }
  343. }
  344. r = sshkey_to_blob(kcopy, blob, blen);
  345. sshkey_free(kcopy);
  346. return r;
  347. }
  348. /* Revoke a key blob. Ownership of blob is transferred to the tree */
  349. static int
  350. revoke_blob(struct revoked_blob_tree *rbt, u_char *blob, size_t len)
  351. {
  352. struct revoked_blob *rb, *erb;
  353. if ((rb = calloc(1, sizeof(*rb))) == NULL)
  354. return SSH_ERR_ALLOC_FAIL;
  355. rb->blob = blob;
  356. rb->len = len;
  357. erb = RB_INSERT(revoked_blob_tree, rbt, rb);
  358. if (erb != NULL) {
  359. free(rb->blob);
  360. free(rb);
  361. }
  362. return 0;
  363. }
  364. int
  365. ssh_krl_revoke_key_explicit(struct ssh_krl *krl, const struct sshkey *key)
  366. {
  367. u_char *blob;
  368. size_t len;
  369. int r;
  370. debug3("%s: revoke type %s", __func__, sshkey_type(key));
  371. if ((r = plain_key_blob(key, &blob, &len)) != 0)
  372. return r;
  373. return revoke_blob(&krl->revoked_keys, blob, len);
  374. }
  375. static int
  376. revoke_by_hash(struct revoked_blob_tree *target, const u_char *p, size_t len)
  377. {
  378. u_char *blob;
  379. int r;
  380. /* need to copy hash, as revoke_blob steals ownership */
  381. if ((blob = malloc(len)) == NULL)
  382. return SSH_ERR_SYSTEM_ERROR;
  383. memcpy(blob, p, len);
  384. if ((r = revoke_blob(target, blob, len)) != 0) {
  385. free(blob);
  386. return r;
  387. }
  388. return 0;
  389. }
  390. int
  391. ssh_krl_revoke_key_sha1(struct ssh_krl *krl, const u_char *p, size_t len)
  392. {
  393. debug3("%s: revoke by sha1", __func__);
  394. if (len != 20)
  395. return SSH_ERR_INVALID_FORMAT;
  396. return revoke_by_hash(&krl->revoked_sha1s, p, len);
  397. }
  398. int
  399. ssh_krl_revoke_key_sha256(struct ssh_krl *krl, const u_char *p, size_t len)
  400. {
  401. debug3("%s: revoke by sha256", __func__);
  402. if (len != 32)
  403. return SSH_ERR_INVALID_FORMAT;
  404. return revoke_by_hash(&krl->revoked_sha256s, p, len);
  405. }
  406. int
  407. ssh_krl_revoke_key(struct ssh_krl *krl, const struct sshkey *key)
  408. {
  409. /* XXX replace with SHA256? */
  410. if (!sshkey_is_cert(key))
  411. return ssh_krl_revoke_key_explicit(krl, key);
  412. if (key->cert->serial == 0) {
  413. return ssh_krl_revoke_cert_by_key_id(krl,
  414. key->cert->signature_key,
  415. key->cert->key_id);
  416. } else {
  417. return ssh_krl_revoke_cert_by_serial(krl,
  418. key->cert->signature_key,
  419. key->cert->serial);
  420. }
  421. }
  422. /*
  423. * Select the most compact section type to emit next in a KRL based on
  424. * the current section type, the run length of contiguous revoked serial
  425. * numbers and the gaps from the last and to the next revoked serial.
  426. * Applies a mostly-accurate bit cost model to select the section type
  427. * that will minimise the size of the resultant KRL.
  428. */
  429. static int
  430. choose_next_state(int current_state, u_int64_t contig, int final,
  431. u_int64_t last_gap, u_int64_t next_gap, int *force_new_section)
  432. {
  433. int new_state;
  434. u_int64_t cost, cost_list, cost_range, cost_bitmap, cost_bitmap_restart;
  435. /*
  436. * Avoid unsigned overflows.
  437. * The limits are high enough to avoid confusing the calculations.
  438. */
  439. contig = MINIMUM(contig, 1ULL<<31);
  440. last_gap = MINIMUM(last_gap, 1ULL<<31);
  441. next_gap = MINIMUM(next_gap, 1ULL<<31);
  442. /*
  443. * Calculate the cost to switch from the current state to candidates.
  444. * NB. range sections only ever contain a single range, so their
  445. * switching cost is independent of the current_state.
  446. */
  447. cost_list = cost_bitmap = cost_bitmap_restart = 0;
  448. cost_range = 8;
  449. switch (current_state) {
  450. case KRL_SECTION_CERT_SERIAL_LIST:
  451. cost_bitmap_restart = cost_bitmap = 8 + 64;
  452. break;
  453. case KRL_SECTION_CERT_SERIAL_BITMAP:
  454. cost_list = 8;
  455. cost_bitmap_restart = 8 + 64;
  456. break;
  457. case KRL_SECTION_CERT_SERIAL_RANGE:
  458. case 0:
  459. cost_bitmap_restart = cost_bitmap = 8 + 64;
  460. cost_list = 8;
  461. }
  462. /* Estimate base cost in bits of each section type */
  463. cost_list += 64 * contig + (final ? 0 : 8+64);
  464. cost_range += (2 * 64) + (final ? 0 : 8+64);
  465. cost_bitmap += last_gap + contig + (final ? 0 : MINIMUM(next_gap, 8+64));
  466. cost_bitmap_restart += contig + (final ? 0 : MINIMUM(next_gap, 8+64));
  467. /* Convert to byte costs for actual comparison */
  468. cost_list = (cost_list + 7) / 8;
  469. cost_bitmap = (cost_bitmap + 7) / 8;
  470. cost_bitmap_restart = (cost_bitmap_restart + 7) / 8;
  471. cost_range = (cost_range + 7) / 8;
  472. /* Now pick the best choice */
  473. *force_new_section = 0;
  474. new_state = KRL_SECTION_CERT_SERIAL_BITMAP;
  475. cost = cost_bitmap;
  476. if (cost_range < cost) {
  477. new_state = KRL_SECTION_CERT_SERIAL_RANGE;
  478. cost = cost_range;
  479. }
  480. if (cost_list < cost) {
  481. new_state = KRL_SECTION_CERT_SERIAL_LIST;
  482. cost = cost_list;
  483. }
  484. if (cost_bitmap_restart < cost) {
  485. new_state = KRL_SECTION_CERT_SERIAL_BITMAP;
  486. *force_new_section = 1;
  487. cost = cost_bitmap_restart;
  488. }
  489. KRL_DBG(("%s: contig %llu last_gap %llu next_gap %llu final %d, costs:"
  490. "list %llu range %llu bitmap %llu new bitmap %llu, "
  491. "selected 0x%02x%s", __func__, (long long unsigned)contig,
  492. (long long unsigned)last_gap, (long long unsigned)next_gap, final,
  493. (long long unsigned)cost_list, (long long unsigned)cost_range,
  494. (long long unsigned)cost_bitmap,
  495. (long long unsigned)cost_bitmap_restart, new_state,
  496. *force_new_section ? " restart" : ""));
  497. return new_state;
  498. }
  499. static int
  500. put_bitmap(struct sshbuf *buf, struct bitmap *bitmap)
  501. {
  502. size_t len;
  503. u_char *blob;
  504. int r;
  505. len = bitmap_nbytes(bitmap);
  506. if ((blob = malloc(len)) == NULL)
  507. return SSH_ERR_ALLOC_FAIL;
  508. if (bitmap_to_string(bitmap, blob, len) != 0) {
  509. free(blob);
  510. return SSH_ERR_INTERNAL_ERROR;
  511. }
  512. r = sshbuf_put_bignum2_bytes(buf, blob, len);
  513. free(blob);
  514. return r;
  515. }
  516. /* Generate a KRL_SECTION_CERTIFICATES KRL section */
  517. static int
  518. revoked_certs_generate(struct revoked_certs *rc, struct sshbuf *buf)
  519. {
  520. int final, force_new_sect, r = SSH_ERR_INTERNAL_ERROR;
  521. u_int64_t i, contig, gap, last = 0, bitmap_start = 0;
  522. struct revoked_serial *rs, *nrs;
  523. struct revoked_key_id *rki;
  524. int next_state, state = 0;
  525. struct sshbuf *sect;
  526. struct bitmap *bitmap = NULL;
  527. if ((sect = sshbuf_new()) == NULL)
  528. return SSH_ERR_ALLOC_FAIL;
  529. /* Store the header: optional CA scope key, reserved */
  530. if (rc->ca_key == NULL) {
  531. if ((r = sshbuf_put_string(buf, NULL, 0)) != 0)
  532. goto out;
  533. } else {
  534. if ((r = sshkey_puts(rc->ca_key, buf)) != 0)
  535. goto out;
  536. }
  537. if ((r = sshbuf_put_string(buf, NULL, 0)) != 0)
  538. goto out;
  539. /* Store the revoked serials. */
  540. for (rs = RB_MIN(revoked_serial_tree, &rc->revoked_serials);
  541. rs != NULL;
  542. rs = RB_NEXT(revoked_serial_tree, &rc->revoked_serials, rs)) {
  543. KRL_DBG(("%s: serial %llu:%llu state 0x%02x", __func__,
  544. (long long unsigned)rs->lo, (long long unsigned)rs->hi,
  545. state));
  546. /* Check contiguous length and gap to next section (if any) */
  547. nrs = RB_NEXT(revoked_serial_tree, &rc->revoked_serials, rs);
  548. final = nrs == NULL;
  549. gap = nrs == NULL ? 0 : nrs->lo - rs->hi;
  550. contig = 1 + (rs->hi - rs->lo);
  551. /* Choose next state based on these */
  552. next_state = choose_next_state(state, contig, final,
  553. state == 0 ? 0 : rs->lo - last, gap, &force_new_sect);
  554. /*
  555. * If the current section is a range section or has a different
  556. * type to the next section, then finish it off now.
  557. */
  558. if (state != 0 && (force_new_sect || next_state != state ||
  559. state == KRL_SECTION_CERT_SERIAL_RANGE)) {
  560. KRL_DBG(("%s: finish state 0x%02x", __func__, state));
  561. switch (state) {
  562. case KRL_SECTION_CERT_SERIAL_LIST:
  563. case KRL_SECTION_CERT_SERIAL_RANGE:
  564. break;
  565. case KRL_SECTION_CERT_SERIAL_BITMAP:
  566. if ((r = put_bitmap(sect, bitmap)) != 0)
  567. goto out;
  568. bitmap_free(bitmap);
  569. bitmap = NULL;
  570. break;
  571. }
  572. if ((r = sshbuf_put_u8(buf, state)) != 0 ||
  573. (r = sshbuf_put_stringb(buf, sect)) != 0)
  574. goto out;
  575. sshbuf_reset(sect);
  576. }
  577. /* If we are starting a new section then prepare it now */
  578. if (next_state != state || force_new_sect) {
  579. KRL_DBG(("%s: start state 0x%02x", __func__,
  580. next_state));
  581. state = next_state;
  582. sshbuf_reset(sect);
  583. switch (state) {
  584. case KRL_SECTION_CERT_SERIAL_LIST:
  585. case KRL_SECTION_CERT_SERIAL_RANGE:
  586. break;
  587. case KRL_SECTION_CERT_SERIAL_BITMAP:
  588. if ((bitmap = bitmap_new()) == NULL) {
  589. r = SSH_ERR_ALLOC_FAIL;
  590. goto out;
  591. }
  592. bitmap_start = rs->lo;
  593. if ((r = sshbuf_put_u64(sect,
  594. bitmap_start)) != 0)
  595. goto out;
  596. break;
  597. }
  598. }
  599. /* Perform section-specific processing */
  600. switch (state) {
  601. case KRL_SECTION_CERT_SERIAL_LIST:
  602. for (i = 0; i < contig; i++) {
  603. if ((r = sshbuf_put_u64(sect, rs->lo + i)) != 0)
  604. goto out;
  605. }
  606. break;
  607. case KRL_SECTION_CERT_SERIAL_RANGE:
  608. if ((r = sshbuf_put_u64(sect, rs->lo)) != 0 ||
  609. (r = sshbuf_put_u64(sect, rs->hi)) != 0)
  610. goto out;
  611. break;
  612. case KRL_SECTION_CERT_SERIAL_BITMAP:
  613. if (rs->lo - bitmap_start > INT_MAX) {
  614. error("%s: insane bitmap gap", __func__);
  615. goto out;
  616. }
  617. for (i = 0; i < contig; i++) {
  618. if (bitmap_set_bit(bitmap,
  619. rs->lo + i - bitmap_start) != 0) {
  620. r = SSH_ERR_ALLOC_FAIL;
  621. goto out;
  622. }
  623. }
  624. break;
  625. }
  626. last = rs->hi;
  627. }
  628. /* Flush the remaining section, if any */
  629. if (state != 0) {
  630. KRL_DBG(("%s: serial final flush for state 0x%02x",
  631. __func__, state));
  632. switch (state) {
  633. case KRL_SECTION_CERT_SERIAL_LIST:
  634. case KRL_SECTION_CERT_SERIAL_RANGE:
  635. break;
  636. case KRL_SECTION_CERT_SERIAL_BITMAP:
  637. if ((r = put_bitmap(sect, bitmap)) != 0)
  638. goto out;
  639. bitmap_free(bitmap);
  640. bitmap = NULL;
  641. break;
  642. }
  643. if ((r = sshbuf_put_u8(buf, state)) != 0 ||
  644. (r = sshbuf_put_stringb(buf, sect)) != 0)
  645. goto out;
  646. }
  647. KRL_DBG(("%s: serial done ", __func__));
  648. /* Now output a section for any revocations by key ID */
  649. sshbuf_reset(sect);
  650. RB_FOREACH(rki, revoked_key_id_tree, &rc->revoked_key_ids) {
  651. KRL_DBG(("%s: key ID %s", __func__, rki->key_id));
  652. if ((r = sshbuf_put_cstring(sect, rki->key_id)) != 0)
  653. goto out;
  654. }
  655. if (sshbuf_len(sect) != 0) {
  656. if ((r = sshbuf_put_u8(buf, KRL_SECTION_CERT_KEY_ID)) != 0 ||
  657. (r = sshbuf_put_stringb(buf, sect)) != 0)
  658. goto out;
  659. }
  660. r = 0;
  661. out:
  662. bitmap_free(bitmap);
  663. sshbuf_free(sect);
  664. return r;
  665. }
  666. int
  667. ssh_krl_to_blob(struct ssh_krl *krl, struct sshbuf *buf,
  668. struct sshkey **sign_keys, u_int nsign_keys)
  669. {
  670. int r = SSH_ERR_INTERNAL_ERROR;
  671. struct revoked_certs *rc;
  672. struct revoked_blob *rb;
  673. struct sshbuf *sect;
  674. u_char *sblob = NULL;
  675. size_t slen, i;
  676. if (krl->generated_date == 0)
  677. krl->generated_date = time(NULL);
  678. if ((sect = sshbuf_new()) == NULL)
  679. return SSH_ERR_ALLOC_FAIL;
  680. /* Store the header */
  681. if ((r = sshbuf_put(buf, KRL_MAGIC, sizeof(KRL_MAGIC) - 1)) != 0 ||
  682. (r = sshbuf_put_u32(buf, KRL_FORMAT_VERSION)) != 0 ||
  683. (r = sshbuf_put_u64(buf, krl->krl_version)) != 0 ||
  684. (r = sshbuf_put_u64(buf, krl->generated_date)) != 0 ||
  685. (r = sshbuf_put_u64(buf, krl->flags)) != 0 ||
  686. (r = sshbuf_put_string(buf, NULL, 0)) != 0 ||
  687. (r = sshbuf_put_cstring(buf, krl->comment)) != 0)
  688. goto out;
  689. /* Store sections for revoked certificates */
  690. TAILQ_FOREACH(rc, &krl->revoked_certs, entry) {
  691. sshbuf_reset(sect);
  692. if ((r = revoked_certs_generate(rc, sect)) != 0)
  693. goto out;
  694. if ((r = sshbuf_put_u8(buf, KRL_SECTION_CERTIFICATES)) != 0 ||
  695. (r = sshbuf_put_stringb(buf, sect)) != 0)
  696. goto out;
  697. }
  698. /* Finally, output sections for revocations by public key/hash */
  699. sshbuf_reset(sect);
  700. RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_keys) {
  701. KRL_DBG(("%s: key len %zu ", __func__, rb->len));
  702. if ((r = sshbuf_put_string(sect, rb->blob, rb->len)) != 0)
  703. goto out;
  704. }
  705. if (sshbuf_len(sect) != 0) {
  706. if ((r = sshbuf_put_u8(buf, KRL_SECTION_EXPLICIT_KEY)) != 0 ||
  707. (r = sshbuf_put_stringb(buf, sect)) != 0)
  708. goto out;
  709. }
  710. sshbuf_reset(sect);
  711. RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_sha1s) {
  712. KRL_DBG(("%s: hash len %zu ", __func__, rb->len));
  713. if ((r = sshbuf_put_string(sect, rb->blob, rb->len)) != 0)
  714. goto out;
  715. }
  716. if (sshbuf_len(sect) != 0) {
  717. if ((r = sshbuf_put_u8(buf,
  718. KRL_SECTION_FINGERPRINT_SHA1)) != 0 ||
  719. (r = sshbuf_put_stringb(buf, sect)) != 0)
  720. goto out;
  721. }
  722. sshbuf_reset(sect);
  723. RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_sha256s) {
  724. KRL_DBG(("%s: hash len %zu ", __func__, rb->len));
  725. if ((r = sshbuf_put_string(sect, rb->blob, rb->len)) != 0)
  726. goto out;
  727. }
  728. if (sshbuf_len(sect) != 0) {
  729. if ((r = sshbuf_put_u8(buf,
  730. KRL_SECTION_FINGERPRINT_SHA256)) != 0 ||
  731. (r = sshbuf_put_stringb(buf, sect)) != 0)
  732. goto out;
  733. }
  734. for (i = 0; i < nsign_keys; i++) {
  735. KRL_DBG(("%s: signature key %s", __func__,
  736. sshkey_ssh_name(sign_keys[i])));
  737. if ((r = sshbuf_put_u8(buf, KRL_SECTION_SIGNATURE)) != 0 ||
  738. (r = sshkey_puts(sign_keys[i], buf)) != 0)
  739. goto out;
  740. /* XXX support sk-* keys */
  741. if ((r = sshkey_sign(sign_keys[i], &sblob, &slen,
  742. sshbuf_ptr(buf), sshbuf_len(buf), NULL, NULL,
  743. NULL, 0)) != 0)
  744. goto out;
  745. KRL_DBG(("%s: signature sig len %zu", __func__, slen));
  746. if ((r = sshbuf_put_string(buf, sblob, slen)) != 0)
  747. goto out;
  748. }
  749. r = 0;
  750. out:
  751. free(sblob);
  752. sshbuf_free(sect);
  753. return r;
  754. }
  755. static void
  756. format_timestamp(u_int64_t timestamp, char *ts, size_t nts)
  757. {
  758. time_t t;
  759. struct tm *tm;
  760. t = timestamp;
  761. tm = localtime(&t);
  762. if (tm == NULL)
  763. strlcpy(ts, "<INVALID>", nts);
  764. else {
  765. *ts = '\0';
  766. strftime(ts, nts, "%Y%m%dT%H%M%S", tm);
  767. }
  768. }
  769. static int
  770. parse_revoked_certs(struct sshbuf *buf, struct ssh_krl *krl)
  771. {
  772. int r = SSH_ERR_INTERNAL_ERROR;
  773. u_char type;
  774. const u_char *blob;
  775. size_t blen, nbits;
  776. struct sshbuf *subsect = NULL;
  777. u_int64_t serial, serial_lo, serial_hi;
  778. struct bitmap *bitmap = NULL;
  779. char *key_id = NULL;
  780. struct sshkey *ca_key = NULL;
  781. if ((subsect = sshbuf_new()) == NULL)
  782. return SSH_ERR_ALLOC_FAIL;
  783. /* Header: key, reserved */
  784. if ((r = sshbuf_get_string_direct(buf, &blob, &blen)) != 0 ||
  785. (r = sshbuf_skip_string(buf)) != 0)
  786. goto out;
  787. if (blen != 0 && (r = sshkey_from_blob(blob, blen, &ca_key)) != 0)
  788. goto out;
  789. while (sshbuf_len(buf) > 0) {
  790. sshbuf_free(subsect);
  791. subsect = NULL;
  792. if ((r = sshbuf_get_u8(buf, &type)) != 0 ||
  793. (r = sshbuf_froms(buf, &subsect)) != 0)
  794. goto out;
  795. KRL_DBG(("%s: subsection type 0x%02x", __func__, type));
  796. /* sshbuf_dump(subsect, stderr); */
  797. switch (type) {
  798. case KRL_SECTION_CERT_SERIAL_LIST:
  799. while (sshbuf_len(subsect) > 0) {
  800. if ((r = sshbuf_get_u64(subsect, &serial)) != 0)
  801. goto out;
  802. if ((r = ssh_krl_revoke_cert_by_serial(krl,
  803. ca_key, serial)) != 0)
  804. goto out;
  805. }
  806. break;
  807. case KRL_SECTION_CERT_SERIAL_RANGE:
  808. if ((r = sshbuf_get_u64(subsect, &serial_lo)) != 0 ||
  809. (r = sshbuf_get_u64(subsect, &serial_hi)) != 0)
  810. goto out;
  811. if ((r = ssh_krl_revoke_cert_by_serial_range(krl,
  812. ca_key, serial_lo, serial_hi)) != 0)
  813. goto out;
  814. break;
  815. case KRL_SECTION_CERT_SERIAL_BITMAP:
  816. if ((bitmap = bitmap_new()) == NULL) {
  817. r = SSH_ERR_ALLOC_FAIL;
  818. goto out;
  819. }
  820. if ((r = sshbuf_get_u64(subsect, &serial_lo)) != 0 ||
  821. (r = sshbuf_get_bignum2_bytes_direct(subsect,
  822. &blob, &blen)) != 0)
  823. goto out;
  824. if (bitmap_from_string(bitmap, blob, blen) != 0) {
  825. r = SSH_ERR_INVALID_FORMAT;
  826. goto out;
  827. }
  828. nbits = bitmap_nbits(bitmap);
  829. for (serial = 0; serial < (u_int64_t)nbits; serial++) {
  830. if (serial > 0 && serial_lo + serial == 0) {
  831. error("%s: bitmap wraps u64", __func__);
  832. r = SSH_ERR_INVALID_FORMAT;
  833. goto out;
  834. }
  835. if (!bitmap_test_bit(bitmap, serial))
  836. continue;
  837. if ((r = ssh_krl_revoke_cert_by_serial(krl,
  838. ca_key, serial_lo + serial)) != 0)
  839. goto out;
  840. }
  841. bitmap_free(bitmap);
  842. bitmap = NULL;
  843. break;
  844. case KRL_SECTION_CERT_KEY_ID:
  845. while (sshbuf_len(subsect) > 0) {
  846. if ((r = sshbuf_get_cstring(subsect,
  847. &key_id, NULL)) != 0)
  848. goto out;
  849. if ((r = ssh_krl_revoke_cert_by_key_id(krl,
  850. ca_key, key_id)) != 0)
  851. goto out;
  852. free(key_id);
  853. key_id = NULL;
  854. }
  855. break;
  856. default:
  857. error("Unsupported KRL certificate section %u", type);
  858. r = SSH_ERR_INVALID_FORMAT;
  859. goto out;
  860. }
  861. if (sshbuf_len(subsect) > 0) {
  862. error("KRL certificate section contains unparsed data");
  863. r = SSH_ERR_INVALID_FORMAT;
  864. goto out;
  865. }
  866. }
  867. r = 0;
  868. out:
  869. if (bitmap != NULL)
  870. bitmap_free(bitmap);
  871. free(key_id);
  872. sshkey_free(ca_key);
  873. sshbuf_free(subsect);
  874. return r;
  875. }
  876. static int
  877. blob_section(struct sshbuf *sect, struct revoked_blob_tree *target_tree,
  878. size_t expected_len)
  879. {
  880. u_char *rdata = NULL;
  881. size_t rlen = 0;
  882. int r;
  883. while (sshbuf_len(sect) > 0) {
  884. if ((r = sshbuf_get_string(sect, &rdata, &rlen)) != 0)
  885. return r;
  886. if (expected_len != 0 && rlen != expected_len) {
  887. error("%s: bad length", __func__);
  888. free(rdata);
  889. return SSH_ERR_INVALID_FORMAT;
  890. }
  891. if ((r = revoke_blob(target_tree, rdata, rlen)) != 0) {
  892. free(rdata);
  893. return r;
  894. }
  895. }
  896. return 0;
  897. }
  898. /* Attempt to parse a KRL, checking its signature (if any) with sign_ca_keys. */
  899. int
  900. ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp,
  901. const struct sshkey **sign_ca_keys, size_t nsign_ca_keys)
  902. {
  903. struct sshbuf *copy = NULL, *sect = NULL;
  904. struct ssh_krl *krl = NULL;
  905. char timestamp[64];
  906. int r = SSH_ERR_INTERNAL_ERROR, sig_seen;
  907. struct sshkey *key = NULL, **ca_used = NULL, **tmp_ca_used;
  908. u_char type;
  909. const u_char *blob;
  910. size_t i, j, sig_off, sects_off, blen, nca_used;
  911. u_int format_version;
  912. nca_used = 0;
  913. *krlp = NULL;
  914. if (sshbuf_len(buf) < sizeof(KRL_MAGIC) - 1 ||
  915. memcmp(sshbuf_ptr(buf), KRL_MAGIC, sizeof(KRL_MAGIC) - 1) != 0) {
  916. debug3("%s: not a KRL", __func__);
  917. return SSH_ERR_KRL_BAD_MAGIC;
  918. }
  919. /* Take a copy of the KRL buffer so we can verify its signature later */
  920. if ((copy = sshbuf_fromb(buf)) == NULL) {
  921. r = SSH_ERR_ALLOC_FAIL;
  922. goto out;
  923. }
  924. if ((r = sshbuf_consume(copy, sizeof(KRL_MAGIC) - 1)) != 0)
  925. goto out;
  926. if ((krl = ssh_krl_init()) == NULL) {
  927. error("%s: alloc failed", __func__);
  928. goto out;
  929. }
  930. if ((r = sshbuf_get_u32(copy, &format_version)) != 0)
  931. goto out;
  932. if (format_version != KRL_FORMAT_VERSION) {
  933. r = SSH_ERR_INVALID_FORMAT;
  934. goto out;
  935. }
  936. if ((r = sshbuf_get_u64(copy, &krl->krl_version)) != 0 ||
  937. (r = sshbuf_get_u64(copy, &krl->generated_date)) != 0 ||
  938. (r = sshbuf_get_u64(copy, &krl->flags)) != 0 ||
  939. (r = sshbuf_skip_string(copy)) != 0 ||
  940. (r = sshbuf_get_cstring(copy, &krl->comment, NULL)) != 0)
  941. goto out;
  942. format_timestamp(krl->generated_date, timestamp, sizeof(timestamp));
  943. debug("KRL version %llu generated at %s%s%s",
  944. (long long unsigned)krl->krl_version, timestamp,
  945. *krl->comment ? ": " : "", krl->comment);
  946. /*
  947. * 1st pass: verify signatures, if any. This is done to avoid
  948. * detailed parsing of data whose provenance is unverified.
  949. */
  950. sig_seen = 0;
  951. if (sshbuf_len(buf) < sshbuf_len(copy)) {
  952. /* Shouldn't happen */
  953. r = SSH_ERR_INTERNAL_ERROR;
  954. goto out;
  955. }
  956. sects_off = sshbuf_len(buf) - sshbuf_len(copy);
  957. while (sshbuf_len(copy) > 0) {
  958. if ((r = sshbuf_get_u8(copy, &type)) != 0 ||
  959. (r = sshbuf_get_string_direct(copy, &blob, &blen)) != 0)
  960. goto out;
  961. KRL_DBG(("%s: first pass, section 0x%02x", __func__, type));
  962. if (type != KRL_SECTION_SIGNATURE) {
  963. if (sig_seen) {
  964. error("KRL contains non-signature section "
  965. "after signature");
  966. r = SSH_ERR_INVALID_FORMAT;
  967. goto out;
  968. }
  969. /* Not interested for now. */
  970. continue;
  971. }
  972. sig_seen = 1;
  973. /* First string component is the signing key */
  974. if ((r = sshkey_from_blob(blob, blen, &key)) != 0) {
  975. r = SSH_ERR_INVALID_FORMAT;
  976. goto out;
  977. }
  978. if (sshbuf_len(buf) < sshbuf_len(copy)) {
  979. /* Shouldn't happen */
  980. r = SSH_ERR_INTERNAL_ERROR;
  981. goto out;
  982. }
  983. sig_off = sshbuf_len(buf) - sshbuf_len(copy);
  984. /* Second string component is the signature itself */
  985. if ((r = sshbuf_get_string_direct(copy, &blob, &blen)) != 0) {
  986. r = SSH_ERR_INVALID_FORMAT;
  987. goto out;
  988. }
  989. /* Check signature over entire KRL up to this point */
  990. if ((r = sshkey_verify(key, blob, blen,
  991. sshbuf_ptr(buf), sig_off, NULL, 0, NULL)) != 0)
  992. goto out;
  993. /* Check if this key has already signed this KRL */
  994. for (i = 0; i < nca_used; i++) {
  995. if (sshkey_equal(ca_used[i], key)) {
  996. error("KRL signed more than once with "
  997. "the same key");
  998. r = SSH_ERR_INVALID_FORMAT;
  999. goto out;
  1000. }
  1001. }
  1002. /* Record keys used to sign the KRL */
  1003. tmp_ca_used = recallocarray(ca_used, nca_used, nca_used + 1,
  1004. sizeof(*ca_used));
  1005. if (tmp_ca_used == NULL) {
  1006. r = SSH_ERR_ALLOC_FAIL;
  1007. goto out;
  1008. }
  1009. ca_used = tmp_ca_used;
  1010. ca_used[nca_used++] = key;
  1011. key = NULL;
  1012. }
  1013. if (sshbuf_len(copy) != 0) {
  1014. /* Shouldn't happen */
  1015. r = SSH_ERR_INTERNAL_ERROR;
  1016. goto out;
  1017. }
  1018. /*
  1019. * 2nd pass: parse and load the KRL, skipping the header to the point
  1020. * where the section start.
  1021. */
  1022. sshbuf_free(copy);
  1023. if ((copy = sshbuf_fromb(buf)) == NULL) {
  1024. r = SSH_ERR_ALLOC_FAIL;
  1025. goto out;
  1026. }
  1027. if ((r = sshbuf_consume(copy, sects_off)) != 0)
  1028. goto out;
  1029. while (sshbuf_len(copy) > 0) {
  1030. sshbuf_free(sect);
  1031. sect = NULL;
  1032. if ((r = sshbuf_get_u8(copy, &type)) != 0 ||
  1033. (r = sshbuf_froms(copy, &sect)) != 0)
  1034. goto out;
  1035. KRL_DBG(("%s: second pass, section 0x%02x", __func__, type));
  1036. switch (type) {
  1037. case KRL_SECTION_CERTIFICATES:
  1038. if ((r = parse_revoked_certs(sect, krl)) != 0)
  1039. goto out;
  1040. break;
  1041. case KRL_SECTION_EXPLICIT_KEY:
  1042. if ((r = blob_section(sect,
  1043. &krl->revoked_keys, 0)) != 0)
  1044. goto out;
  1045. break;
  1046. case KRL_SECTION_FINGERPRINT_SHA1:
  1047. if ((r = blob_section(sect,
  1048. &krl->revoked_sha1s, 20)) != 0)
  1049. goto out;
  1050. break;
  1051. case KRL_SECTION_FINGERPRINT_SHA256:
  1052. if ((r = blob_section(sect,
  1053. &krl->revoked_sha256s, 32)) != 0)
  1054. goto out;
  1055. break;
  1056. case KRL_SECTION_SIGNATURE:
  1057. /* Handled above, but still need to stay in synch */
  1058. sshbuf_free(sect);
  1059. sect = NULL;
  1060. if ((r = sshbuf_skip_string(copy)) != 0)
  1061. goto out;
  1062. break;
  1063. default:
  1064. error("Unsupported KRL section %u", type);
  1065. r = SSH_ERR_INVALID_FORMAT;
  1066. goto out;
  1067. }
  1068. if (sect != NULL && sshbuf_len(sect) > 0) {
  1069. error("KRL section contains unparsed data");
  1070. r = SSH_ERR_INVALID_FORMAT;
  1071. goto out;
  1072. }
  1073. }
  1074. /* Check that the key(s) used to sign the KRL weren't revoked */
  1075. sig_seen = 0;
  1076. for (i = 0; i < nca_used; i++) {
  1077. if (ssh_krl_check_key(krl, ca_used[i]) == 0)
  1078. sig_seen = 1;
  1079. else {
  1080. sshkey_free(ca_used[i]);
  1081. ca_used[i] = NULL;
  1082. }
  1083. }
  1084. if (nca_used && !sig_seen) {
  1085. error("All keys used to sign KRL were revoked");
  1086. r = SSH_ERR_KEY_REVOKED;
  1087. goto out;
  1088. }
  1089. /* If we have CA keys, then verify that one was used to sign the KRL */
  1090. if (sig_seen && nsign_ca_keys != 0) {
  1091. sig_seen = 0;
  1092. for (i = 0; !sig_seen && i < nsign_ca_keys; i++) {
  1093. for (j = 0; j < nca_used; j++) {
  1094. if (ca_used[j] == NULL)
  1095. continue;
  1096. if (sshkey_equal(ca_used[j], sign_ca_keys[i])) {
  1097. sig_seen = 1;
  1098. break;
  1099. }
  1100. }
  1101. }
  1102. if (!sig_seen) {
  1103. r = SSH_ERR_SIGNATURE_INVALID;
  1104. error("KRL not signed with any trusted key");
  1105. goto out;
  1106. }
  1107. }
  1108. *krlp = krl;
  1109. r = 0;
  1110. out:
  1111. if (r != 0)
  1112. ssh_krl_free(krl);
  1113. for (i = 0; i < nca_used; i++)
  1114. sshkey_free(ca_used[i]);
  1115. free(ca_used);
  1116. sshkey_free(key);
  1117. sshbuf_free(copy);
  1118. sshbuf_free(sect);
  1119. return r;
  1120. }
  1121. /* Checks certificate serial number and key ID revocation */
  1122. static int
  1123. is_cert_revoked(const struct sshkey *key, struct revoked_certs *rc)
  1124. {
  1125. struct revoked_serial rs, *ers;
  1126. struct revoked_key_id rki, *erki;
  1127. /* Check revocation by cert key ID */
  1128. memset(&rki, 0, sizeof(rki));
  1129. rki.key_id = key->cert->key_id;
  1130. erki = RB_FIND(revoked_key_id_tree, &rc->revoked_key_ids, &rki);
  1131. if (erki != NULL) {
  1132. KRL_DBG(("%s: revoked by key ID", __func__));
  1133. return SSH_ERR_KEY_REVOKED;
  1134. }
  1135. /*
  1136. * Zero serials numbers are ignored (it's the default when the
  1137. * CA doesn't specify one).
  1138. */
  1139. if (key->cert->serial == 0)
  1140. return 0;
  1141. memset(&rs, 0, sizeof(rs));
  1142. rs.lo = rs.hi = key->cert->serial;
  1143. ers = RB_FIND(revoked_serial_tree, &rc->revoked_serials, &rs);
  1144. if (ers != NULL) {
  1145. KRL_DBG(("%s: revoked serial %llu matched %llu:%llu", __func__,
  1146. key->cert->serial, ers->lo, ers->hi));
  1147. return SSH_ERR_KEY_REVOKED;
  1148. }
  1149. return 0;
  1150. }
  1151. /* Checks whether a given key/cert is revoked. Does not check its CA */
  1152. static int
  1153. is_key_revoked(struct ssh_krl *krl, const struct sshkey *key)
  1154. {
  1155. struct revoked_blob rb, *erb;
  1156. struct revoked_certs *rc;
  1157. int r;
  1158. /* Check explicitly revoked hashes first */
  1159. memset(&rb, 0, sizeof(rb));
  1160. if ((r = sshkey_fingerprint_raw(key, SSH_DIGEST_SHA1,
  1161. &rb.blob, &rb.len)) != 0)
  1162. return r;
  1163. erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha1s, &rb);
  1164. free(rb.blob);
  1165. if (erb != NULL) {
  1166. KRL_DBG(("%s: revoked by key SHA1", __func__));
  1167. return SSH_ERR_KEY_REVOKED;
  1168. }
  1169. memset(&rb, 0, sizeof(rb));
  1170. if ((r = sshkey_fingerprint_raw(key, SSH_DIGEST_SHA256,
  1171. &rb.blob, &rb.len)) != 0)
  1172. return r;
  1173. erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha256s, &rb);
  1174. free(rb.blob);
  1175. if (erb != NULL) {
  1176. KRL_DBG(("%s: revoked by key SHA256", __func__));
  1177. return SSH_ERR_KEY_REVOKED;
  1178. }
  1179. /* Next, explicit keys */
  1180. memset(&rb, 0, sizeof(rb));
  1181. if ((r = plain_key_blob(key, &rb.blob, &rb.len)) != 0)
  1182. return r;
  1183. erb = RB_FIND(revoked_blob_tree, &krl->revoked_keys, &rb);
  1184. free(rb.blob);
  1185. if (erb != NULL) {
  1186. KRL_DBG(("%s: revoked by explicit key", __func__));
  1187. return SSH_ERR_KEY_REVOKED;
  1188. }
  1189. if (!sshkey_is_cert(key))
  1190. return 0;
  1191. /* Check cert revocation for the specified CA */
  1192. if ((r = revoked_certs_for_ca_key(krl, key->cert->signature_key,
  1193. &rc, 0)) != 0)
  1194. return r;
  1195. if (rc != NULL) {
  1196. if ((r = is_cert_revoked(key, rc)) != 0)
  1197. return r;
  1198. }
  1199. /* Check cert revocation for the wildcard CA */
  1200. if ((r = revoked_certs_for_ca_key(krl, NULL, &rc, 0)) != 0)
  1201. return r;
  1202. if (rc != NULL) {
  1203. if ((r = is_cert_revoked(key, rc)) != 0)
  1204. return r;
  1205. }
  1206. KRL_DBG(("%s: %llu no match", __func__, key->cert->serial));
  1207. return 0;
  1208. }
  1209. int
  1210. ssh_krl_check_key(struct ssh_krl *krl, const struct sshkey *key)
  1211. {
  1212. int r;
  1213. KRL_DBG(("%s: checking key", __func__));
  1214. if ((r = is_key_revoked(krl, key)) != 0)
  1215. return r;
  1216. if (sshkey_is_cert(key)) {
  1217. debug2("%s: checking CA key", __func__);
  1218. if ((r = is_key_revoked(krl, key->cert->signature_key)) != 0)
  1219. return r;
  1220. }
  1221. KRL_DBG(("%s: key okay", __func__));
  1222. return 0;
  1223. }
  1224. int
  1225. ssh_krl_file_contains_key(const char *path, const struct sshkey *key)
  1226. {
  1227. struct sshbuf *krlbuf = NULL;
  1228. struct ssh_krl *krl = NULL;
  1229. int oerrno = 0, r;
  1230. if (path == NULL)
  1231. return 0;
  1232. if ((r = sshbuf_load_file(path, &krlbuf)) != 0) {
  1233. oerrno = errno;
  1234. goto out;
  1235. }
  1236. if ((r = ssh_krl_from_blob(krlbuf, &krl, NULL, 0)) != 0)
  1237. goto out;
  1238. debug2("%s: checking KRL %s", __func__, path);
  1239. r = ssh_krl_check_key(krl, key);
  1240. out:
  1241. sshbuf_free(krlbuf);
  1242. ssh_krl_free(krl);
  1243. if (r != 0)
  1244. errno = oerrno;
  1245. return r;
  1246. }
  1247. int
  1248. krl_dump(struct ssh_krl *krl, FILE *f)
  1249. {
  1250. struct sshkey *key = NULL;
  1251. struct revoked_blob *rb;
  1252. struct revoked_certs *rc;
  1253. struct revoked_serial *rs;
  1254. struct revoked_key_id *rki;
  1255. int r, ret = 0;
  1256. char *fp, timestamp[64];
  1257. /* Try to print in a KRL spec-compatible format */
  1258. format_timestamp(krl->generated_date, timestamp, sizeof(timestamp));
  1259. fprintf(f, "# KRL version %llu\n",
  1260. (unsigned long long)krl->krl_version);
  1261. fprintf(f, "# Generated at %s\n", timestamp);
  1262. if (krl->comment != NULL && *krl->comment != '\0') {
  1263. r = INT_MAX;
  1264. asmprintf(&fp, INT_MAX, &r, "%s", krl->comment);
  1265. fprintf(f, "# Comment: %s\n", fp);
  1266. free(fp);
  1267. }
  1268. fputc('\n', f);
  1269. RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_keys) {
  1270. if ((r = sshkey_from_blob(rb->blob, rb->len, &key)) != 0) {
  1271. ret = SSH_ERR_INVALID_FORMAT;
  1272. error("Parse key in KRL: %s", ssh_err(r));
  1273. continue;
  1274. }
  1275. if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT,
  1276. SSH_FP_DEFAULT)) == NULL) {
  1277. ret = SSH_ERR_INVALID_FORMAT;
  1278. error("sshkey_fingerprint failed");
  1279. continue;
  1280. }
  1281. fprintf(f, "hash: SHA256:%s # %s\n", fp, sshkey_ssh_name(key));
  1282. free(fp);
  1283. free(key);
  1284. }
  1285. RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_sha256s) {
  1286. fp = tohex(rb->blob, rb->len);
  1287. fprintf(f, "hash: SHA256:%s\n", fp);
  1288. free(fp);
  1289. }
  1290. RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_sha1s) {
  1291. /*
  1292. * There is not KRL spec keyword for raw SHA1 hashes, so
  1293. * print them as comments.
  1294. */
  1295. fp = tohex(rb->blob, rb->len);
  1296. fprintf(f, "# hash SHA1:%s\n", fp);
  1297. free(fp);
  1298. }
  1299. TAILQ_FOREACH(rc, &krl->revoked_certs, entry) {
  1300. fputc('\n', f);
  1301. if (rc->ca_key == NULL)
  1302. fprintf(f, "# Wildcard CA\n");
  1303. else {
  1304. if ((fp = sshkey_fingerprint(rc->ca_key,
  1305. SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL) {
  1306. ret = SSH_ERR_INVALID_FORMAT;
  1307. error("sshkey_fingerprint failed");
  1308. continue;
  1309. }
  1310. fprintf(f, "# CA key %s %s\n",
  1311. sshkey_ssh_name(rc->ca_key), fp);
  1312. free(fp);
  1313. }
  1314. RB_FOREACH(rs, revoked_serial_tree, &rc->revoked_serials) {
  1315. if (rs->lo == rs->hi) {
  1316. fprintf(f, "serial: %llu\n",
  1317. (unsigned long long)rs->lo);
  1318. } else {
  1319. fprintf(f, "serial: %llu-%llu\n",
  1320. (unsigned long long)rs->lo,
  1321. (unsigned long long)rs->hi);
  1322. }
  1323. }
  1324. RB_FOREACH(rki, revoked_key_id_tree, &rc->revoked_key_ids) {
  1325. /*
  1326. * We don't want key IDs with embedded newlines to
  1327. * mess up the display.
  1328. */
  1329. r = INT_MAX;
  1330. asmprintf(&fp, INT_MAX, &r, "%s", rki->key_id);
  1331. fprintf(f, "id: %s\n", fp);
  1332. free(fp);
  1333. }
  1334. }
  1335. return ret;
  1336. }