1
0

libluksmeta.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514
  1. /* vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80: */
  2. /*
  3. * Copyright (c) 2016 Red Hat, Inc.
  4. * Author: Nathaniel McCallum <npmccallum@redhat.com>
  5. *
  6. * This program is free software: you can redistribute it and/or modify it
  7. * under the terms of the GNU Lesser General Public License as published by
  8. * the Free Software Foundation, either version 2.1 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "crc32c.h"
  20. #include "luksmeta.h"
  21. #include <sys/types.h>
  22. #include <sys/stat.h>
  23. #include <errno.h>
  24. #include <fcntl.h>
  25. #include <stdbool.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include <unistd.h>
  29. #define ALIGN(s, up) (((s) + (up ? 4095 : 0)) & ~4095ULL)
  30. #define LUKS_NSLOTS 8
  31. #define LM_VERSION 1
  32. static const uint8_t LM_MAGIC[] = { 'L', 'U', 'K', 'S', 'M', 'E', 'T', 'A' };
  33. typedef struct __attribute__((packed)) {
  34. luksmeta_uuid_t uuid;
  35. uint32_t offset; /* Bytes from the start of the hole */
  36. uint32_t length; /* Bytes */
  37. uint32_t crc32c;
  38. uint32_t _reserved; /* Reserved */
  39. } lm_slot_t;
  40. typedef struct __attribute__((packed)) {
  41. uint8_t magic[sizeof(LM_MAGIC)];
  42. uint32_t version;
  43. uint32_t crc32c;
  44. lm_slot_t slots[LUKS_NSLOTS];
  45. } lm_t;
  46. static bool
  47. uuid_is_zero(const luksmeta_uuid_t uuid)
  48. {
  49. for (size_t i = 0; i < sizeof(luksmeta_uuid_t); i++) {
  50. if (uuid[i] != 0)
  51. return false;
  52. }
  53. return true;
  54. }
  55. static inline uint32_t
  56. checksum(lm_t lm)
  57. {
  58. lm.crc32c = 0;
  59. return crc32c(0, &lm, sizeof(lm_t));
  60. }
  61. static inline bool
  62. overlap(const lm_t *lm, uint32_t start, size_t end, uint32_t hard_limit)
  63. {
  64. /* Make sure the data fits the available area in the gap. */
  65. if (end > hard_limit)
  66. return true;
  67. for (int i = 0; i < LUKS_NSLOTS; i++) {
  68. const lm_slot_t *s = &lm->slots[i];
  69. uint32_t e = s->offset + s->length;
  70. if (start <= s->offset && s->offset < end)
  71. return true;
  72. if (start < e && e <= end)
  73. return true;
  74. }
  75. return false;
  76. }
  77. static inline uint32_t
  78. find_gap(const lm_t *lm, uint32_t length, size_t size)
  79. {
  80. size = ALIGN(size, true);
  81. /* Make sure the data is not larger than the total available
  82. * area in the gap. */
  83. if (length < size)
  84. return 0;
  85. for (uint32_t off = ALIGN(1, true); off < length; off += ALIGN(1, true)) {
  86. if (!overlap(lm, off, off + size, lm->slots[0].offset + length))
  87. return off;
  88. }
  89. return 0;
  90. }
  91. static int
  92. find_unused_slot(struct crypt_device *cd, const lm_t *lm)
  93. {
  94. for (int slot = 0; slot < LUKS_NSLOTS; slot++) {
  95. if (crypt_keyslot_status(cd, slot) == CRYPT_SLOT_INACTIVE &&
  96. uuid_is_zero(lm->slots[slot].uuid))
  97. return slot;
  98. }
  99. return -1;
  100. }
  101. static inline ssize_t
  102. readall(int fd, void *data, size_t size)
  103. {
  104. uint8_t *tmp = data;
  105. for (ssize_t r, t = 0; t < (ssize_t) size; t += r) {
  106. r = read(fd, &tmp[t], size - t);
  107. if (r < 0 && errno != EAGAIN)
  108. return -errno;
  109. if (r == 0)
  110. return -ENOENT;
  111. }
  112. return size;
  113. }
  114. static inline ssize_t
  115. writeall(int fd, const void *buf, size_t size)
  116. {
  117. const uint8_t *tmp = buf;
  118. for (ssize_t r, t = 0; t < (ssize_t) size; t += r) {
  119. r = write(fd, &tmp[t], size - t);
  120. if (r < 0) {
  121. if (errno != EAGAIN)
  122. return -errno;
  123. r = 0;
  124. }
  125. }
  126. return size;
  127. }
  128. /**
  129. * Opens the device with the specified flags.
  130. *
  131. * The length parameter is set to the amount of space in the gap between the
  132. * end of the last slot and the start of the encrypted data.
  133. *
  134. * The function returns either the file descriptor positioned to the start of
  135. * the hole or a negative errno.
  136. */
  137. static int
  138. open_hole(struct crypt_device *cd, int flags, uint32_t *length)
  139. {
  140. const char *name = NULL;
  141. const char *type = NULL;
  142. uint64_t hole = 0;
  143. uint64_t data = 0;
  144. int fd = 0;
  145. int r = 0;
  146. type = crypt_get_type(cd);
  147. if (!type || strcmp(CRYPT_LUKS1, type) != 0)
  148. return -ENOTSUP;
  149. data = crypt_get_data_offset(cd) * 512;
  150. if (data < 4096)
  151. return -ENOSPC;
  152. for (int slot = 0; slot < LUKS_NSLOTS; slot++) {
  153. uint64_t off = 0;
  154. uint64_t len = 0;
  155. r = crypt_keyslot_area(cd, slot, &off, &len);
  156. if (r < 0)
  157. return r;
  158. if (hole < off + len)
  159. hole = ALIGN(off + len, true);
  160. }
  161. if (hole == 0)
  162. return -ENOTSUP;
  163. if (hole >= data)
  164. return -ENOSPC;
  165. name = crypt_get_device_name(cd);
  166. if (!name)
  167. return -ENOTSUP;
  168. fd = open(name, flags);
  169. if (fd < 0)
  170. return -errno;
  171. if (lseek(fd, hole, SEEK_SET) == -1) {
  172. close(fd);
  173. return -errno;
  174. }
  175. *length = ALIGN(data - hole, false);
  176. return fd;
  177. }
  178. static int
  179. read_header(struct crypt_device *cd, int flags, uint32_t *length, lm_t *lm)
  180. {
  181. uint32_t maxlen;
  182. int fd = -1;
  183. int r = 0;
  184. fd = open_hole(cd, flags, length);
  185. if (fd < 0)
  186. return fd;
  187. r = *length >= sizeof(lm_t) ? 0 : -ENOENT;
  188. if (r < 0)
  189. goto error;
  190. r = readall(fd, lm, sizeof(lm_t));
  191. if (r < 0)
  192. goto error;
  193. r = memcmp(LM_MAGIC, lm->magic, sizeof(LM_MAGIC)) == 0 ? 0 : -ENOENT;
  194. if (r < 0)
  195. goto error;
  196. r = lm->version == htobe32(LM_VERSION) ? 0 : -ENOTSUP;
  197. if (r < 0)
  198. goto error;
  199. lm->crc32c = be32toh(lm->crc32c);
  200. r = checksum(*lm) == lm->crc32c ? 0 : -EINVAL;
  201. if (r < 0)
  202. goto error;
  203. lm->version = be32toh(lm->version);
  204. maxlen = *length - ALIGN(sizeof(lm_t), true);
  205. for (int slot = 0; slot < LUKS_NSLOTS; slot++) {
  206. lm_slot_t *s = &lm->slots[slot];
  207. s->offset = be32toh(s->offset);
  208. s->length = be32toh(s->length);
  209. s->crc32c = be32toh(s->crc32c);
  210. if (!uuid_is_zero(s->uuid)) {
  211. r = s->offset > sizeof(lm_t) ? 0 : -EINVAL;
  212. if (r < 0)
  213. goto error;
  214. r = s->length <= maxlen ? 0 : -EINVAL;
  215. if (r < 0)
  216. goto error;
  217. }
  218. }
  219. return fd;
  220. error:
  221. close(fd);
  222. return r;
  223. }
  224. static int
  225. write_header(int fd, lm_t lm)
  226. {
  227. for (int slot = 0; slot < LUKS_NSLOTS; slot++) {
  228. lm.slots[slot].offset = htobe32(lm.slots[slot].offset);
  229. lm.slots[slot].length = htobe32(lm.slots[slot].length);
  230. lm.slots[slot].crc32c = htobe32(lm.slots[slot].crc32c);
  231. }
  232. memcpy(lm.magic, LM_MAGIC, sizeof(LM_MAGIC));
  233. lm.version = htobe32(LM_VERSION);
  234. lm.crc32c = htobe32(checksum(lm));
  235. return writeall(fd, &lm, sizeof(lm));
  236. }
  237. int
  238. luksmeta_test(struct crypt_device *cd)
  239. {
  240. int fd = -1;
  241. fd = read_header(cd, O_RDONLY, &(uint32_t) {0}, &(lm_t) {});
  242. if (fd >= 0) {
  243. close(fd);
  244. return 0;
  245. }
  246. return fd;
  247. }
  248. int
  249. luksmeta_nuke(struct crypt_device *cd)
  250. {
  251. uint8_t zero[ALIGN(1, true)] = {};
  252. uint32_t length = 0;
  253. int fd = -1;
  254. int r = 0;
  255. fd = open_hole(cd, O_RDWR | O_SYNC, &length);
  256. if (fd < 0)
  257. return fd;
  258. for (size_t i = 0; r >= 0 && i < length; i += sizeof(zero))
  259. r = writeall(fd, zero, sizeof(zero));
  260. close(fd);
  261. return r < 0 ? r : 0;
  262. }
  263. int
  264. luksmeta_init(struct crypt_device *cd)
  265. {
  266. uint32_t length = 0;
  267. int fd = -1;
  268. int r = 0;
  269. r = luksmeta_test(cd);
  270. if (r == 0)
  271. return -EALREADY;
  272. else if (r != -ENOENT && r != -EINVAL)
  273. return r;
  274. fd = open_hole(cd, O_RDWR | O_SYNC, &length);
  275. if (fd < 0)
  276. return fd;
  277. if (length < ALIGN(sizeof(lm_t), true)) {
  278. close(fd);
  279. return -ENOSPC;
  280. }
  281. r = write_header(fd, (lm_t) {});
  282. close(fd);
  283. return r > 0 ? 0 : r;
  284. }
  285. int
  286. luksmeta_load(struct crypt_device *cd, int slot,
  287. luksmeta_uuid_t uuid, void *buf, size_t size)
  288. {
  289. uint32_t length = 0;
  290. lm_slot_t *s = NULL;
  291. lm_t lm = {};
  292. int fd = -1;
  293. int r = 0;
  294. if (slot < 0 || slot >= LUKS_NSLOTS)
  295. return -EBADSLT;
  296. s = &lm.slots[slot];
  297. fd = read_header(cd, O_RDONLY, &length, &lm);
  298. if (fd < 0)
  299. return fd;
  300. r = uuid_is_zero(s->uuid) ? -ENODATA : 0;
  301. if (r < 0)
  302. goto error;
  303. if (buf) {
  304. r = size >= s->length ? 0 : -E2BIG;
  305. if (r < 0)
  306. goto error;
  307. r = lseek(fd, s->offset - sizeof(lm), SEEK_CUR) == -1 ? -errno : 0;
  308. if (r < 0)
  309. goto error;
  310. r = readall(fd, buf, s->length);
  311. if (r < 0)
  312. goto error;
  313. r = crc32c(0, buf, s->length) == s->crc32c ? 0 : -EINVAL;
  314. if (r < 0)
  315. goto error;
  316. }
  317. memcpy(uuid, s->uuid, sizeof(luksmeta_uuid_t));
  318. close(fd);
  319. return s->length;
  320. error:
  321. close(fd);
  322. return r;
  323. }
  324. int
  325. luksmeta_save(struct crypt_device *cd, int slot,
  326. const luksmeta_uuid_t uuid, const void *buf, size_t size)
  327. {
  328. uint32_t length = 0;
  329. lm_slot_t *s = NULL;
  330. lm_t lm = {};
  331. int fd = -1;
  332. int r = 0;
  333. off_t off;
  334. if (uuid_is_zero(uuid))
  335. return -EKEYREJECTED;
  336. fd = read_header(cd, O_RDWR | O_SYNC, &length, &lm);
  337. if (fd < 0)
  338. return fd;
  339. if (slot == CRYPT_ANY_SLOT)
  340. slot = find_unused_slot(cd, &lm);
  341. r = slot >= 0 && slot < LUKS_NSLOTS ? 0 : -EBADSLT;
  342. if (r < 0)
  343. goto error;
  344. s = &lm.slots[slot];
  345. r = uuid_is_zero(s->uuid) ? 0 : -EALREADY;
  346. if (r < 0)
  347. goto error;
  348. s->offset = find_gap(&lm, length, size);
  349. r = s->offset >= ALIGN(sizeof(lm), true) ? 0 : -ENOSPC;
  350. if (r < 0)
  351. goto error;
  352. memcpy(s->uuid, uuid, sizeof(luksmeta_uuid_t));
  353. s->length = size;
  354. s->crc32c = crc32c(0, buf, size);
  355. off = s->offset - sizeof(lm);
  356. r = lseek(fd, off, SEEK_CUR) == -1 ? -errno : 0;
  357. if (r < 0)
  358. goto error;
  359. r = writeall(fd, buf, size);
  360. if (r < 0)
  361. goto error;
  362. off = s->offset + s->length;
  363. r = lseek(fd, -off, SEEK_CUR) == -1 ? -errno : 0;
  364. if (r < 0)
  365. goto error;
  366. r = write_header(fd, lm);
  367. error:
  368. close(fd);
  369. return r < 0 ? r : slot;
  370. }
  371. int
  372. luksmeta_wipe(struct crypt_device *cd, int slot, const luksmeta_uuid_t uuid)
  373. {
  374. uint8_t *zero = NULL;
  375. uint32_t length = 0;
  376. lm_slot_t *s = NULL;
  377. lm_t lm = {};
  378. int fd = -1;
  379. int r = 0;
  380. off_t off;
  381. if (slot < 0 || slot >= LUKS_NSLOTS)
  382. return -EBADSLT;
  383. s = &lm.slots[slot];
  384. fd = read_header(cd, O_RDWR | O_SYNC, &length, &lm);
  385. if (fd < 0)
  386. return fd;
  387. r = uuid_is_zero(s->uuid) ? -EALREADY : 0;
  388. if (r < 0)
  389. goto error;
  390. if (uuid && memcmp(uuid, s->uuid, sizeof(luksmeta_uuid_t)) != 0) {
  391. r = -EKEYREJECTED;
  392. goto error;
  393. }
  394. off = s->offset - sizeof(lm_t);
  395. r = lseek(fd, off, SEEK_CUR) == -1 ? -errno : 0;
  396. if (r < 0)
  397. goto error;
  398. r = (zero = calloc(1, s->length)) ? 0 : -errno;
  399. if (r < 0)
  400. goto error;
  401. r = writeall(fd, zero, s->length);
  402. free(zero);
  403. if (r < 0)
  404. goto error;
  405. off = s->offset + s->length;
  406. r = lseek(fd, -off, SEEK_CUR) == -1 ? -errno : 0;
  407. if (r < 0)
  408. goto error;
  409. memset(s, 0, sizeof(lm_slot_t));
  410. r = write_header(fd, lm);
  411. error:
  412. close(fd);
  413. return r < 0 ? r : 0;
  414. }