libluksmeta.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  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)
  63. {
  64. for (int i = 0; i < LUKS_NSLOTS; i++) {
  65. const lm_slot_t *s = &lm->slots[i];
  66. uint32_t e = s->offset + s->length;
  67. if (start <= s->offset && s->offset < end)
  68. return true;
  69. if (start < e && e <= end)
  70. return true;
  71. }
  72. return false;
  73. }
  74. static inline uint32_t
  75. find_gap(const lm_t *lm, uint32_t length, size_t size)
  76. {
  77. size = ALIGN(size, true);
  78. for (uint32_t off = ALIGN(1, true); off < length; off += ALIGN(1, true)) {
  79. if (!overlap(lm, off, off + size))
  80. return off;
  81. }
  82. return 0;
  83. }
  84. static int
  85. find_unused_slot(struct crypt_device *cd, const lm_t *lm)
  86. {
  87. for (int slot = 0; slot < LUKS_NSLOTS; slot++) {
  88. if (crypt_keyslot_status(cd, slot) == CRYPT_SLOT_INACTIVE &&
  89. uuid_is_zero(lm->slots[slot].uuid))
  90. return slot;
  91. }
  92. return -1;
  93. }
  94. static inline ssize_t
  95. readall(int fd, void *data, size_t size)
  96. {
  97. uint8_t *tmp = data;
  98. for (ssize_t r, t = 0; t < (ssize_t) size; t += r) {
  99. r = read(fd, &tmp[t], size - t);
  100. if (r < 0 && errno != EAGAIN)
  101. return -errno;
  102. }
  103. return size;
  104. }
  105. static inline ssize_t
  106. writeall(int fd, const void *buf, size_t size)
  107. {
  108. const uint8_t *tmp = buf;
  109. for (ssize_t r, t = 0; t < (ssize_t) size; t += r) {
  110. r = write(fd, &tmp[t], size - t);
  111. if (r < 0) {
  112. if (errno != EAGAIN)
  113. return -errno;
  114. r = 0;
  115. }
  116. }
  117. return size;
  118. }
  119. /**
  120. * Opens the device with the specified flags.
  121. *
  122. * The length parameter is set to the amount of space in the gap between the
  123. * end of the last slot and the start of the encrypted data.
  124. *
  125. * The function returns either the file descriptor positioned to the start of
  126. * the hole or a negative errno.
  127. */
  128. static int
  129. open_hole(struct crypt_device *cd, int flags, uint32_t *length)
  130. {
  131. const char *name = NULL;
  132. const char *type = NULL;
  133. uint64_t hole = 0;
  134. uint64_t data = 0;
  135. int fd = 0;
  136. int r = 0;
  137. type = crypt_get_type(cd);
  138. if (!type || strcmp(CRYPT_LUKS1, type) != 0)
  139. return -ENOTSUP;
  140. data = crypt_get_data_offset(cd) * 512;
  141. if (data < 4096)
  142. return -ENOSPC;
  143. for (int slot = 0; slot < LUKS_NSLOTS; slot++) {
  144. uint64_t off = 0;
  145. uint64_t len = 0;
  146. r = crypt_keyslot_area(cd, slot, &off, &len);
  147. if (r < 0)
  148. return r;
  149. if (hole < off + len)
  150. hole = ALIGN(off + len, true);
  151. }
  152. if (hole == 0)
  153. return -ENOTSUP;
  154. if (hole >= data)
  155. return -ENOSPC;
  156. name = crypt_get_device_name(cd);
  157. if (!name)
  158. return -ENOTSUP;
  159. fd = open(name, flags);
  160. if (fd < 0)
  161. return -errno;
  162. if (lseek(fd, hole, SEEK_SET) == -1) {
  163. close(fd);
  164. return -errno;
  165. }
  166. *length = ALIGN(data - hole, false);
  167. return fd;
  168. }
  169. static int
  170. read_header(struct crypt_device *cd, int flags, uint32_t *length, lm_t *lm)
  171. {
  172. uint32_t maxlen;
  173. int fd = -1;
  174. int r = 0;
  175. fd = open_hole(cd, flags, length);
  176. if (fd < 0)
  177. return fd;
  178. r = *length >= sizeof(lm_t) ? 0 : -ENOENT;
  179. if (r < 0)
  180. goto error;
  181. r = readall(fd, lm, sizeof(lm_t));
  182. if (r < 0)
  183. goto error;
  184. r = memcmp(LM_MAGIC, lm->magic, sizeof(LM_MAGIC)) == 0 ? 0 : -ENOENT;
  185. if (r < 0)
  186. goto error;
  187. r = lm->version == htobe32(LM_VERSION) ? 0 : -ENOTSUP;
  188. if (r < 0)
  189. goto error;
  190. lm->crc32c = be32toh(lm->crc32c);
  191. r = checksum(*lm) == lm->crc32c ? 0 : -EINVAL;
  192. if (r < 0)
  193. goto error;
  194. lm->version = be32toh(lm->version);
  195. maxlen = *length - ALIGN(sizeof(lm_t), true);
  196. for (int slot = 0; slot < LUKS_NSLOTS; slot++) {
  197. lm_slot_t *s = &lm->slots[slot];
  198. s->offset = be32toh(s->offset);
  199. s->length = be32toh(s->length);
  200. s->crc32c = be32toh(s->crc32c);
  201. if (!uuid_is_zero(s->uuid)) {
  202. r = s->offset > sizeof(lm_t) ? 0 : -EINVAL;
  203. if (r < 0)
  204. goto error;
  205. r = s->length <= maxlen ? 0 : -EINVAL;
  206. if (r < 0)
  207. goto error;
  208. }
  209. }
  210. return fd;
  211. error:
  212. close(fd);
  213. return r;
  214. }
  215. static int
  216. write_header(int fd, lm_t lm)
  217. {
  218. for (int slot = 0; slot < LUKS_NSLOTS; slot++) {
  219. lm.slots[slot].offset = htobe32(lm.slots[slot].offset);
  220. lm.slots[slot].length = htobe32(lm.slots[slot].length);
  221. lm.slots[slot].crc32c = htobe32(lm.slots[slot].crc32c);
  222. }
  223. memcpy(lm.magic, LM_MAGIC, sizeof(LM_MAGIC));
  224. lm.version = htobe32(LM_VERSION);
  225. lm.crc32c = htobe32(checksum(lm));
  226. return writeall(fd, &lm, sizeof(lm));
  227. }
  228. int
  229. luksmeta_test(struct crypt_device *cd)
  230. {
  231. int fd = -1;
  232. fd = read_header(cd, O_RDONLY, &(uint32_t) {0}, &(lm_t) {});
  233. if (fd >= 0) {
  234. close(fd);
  235. return 0;
  236. }
  237. return fd;
  238. }
  239. int
  240. luksmeta_nuke(struct crypt_device *cd)
  241. {
  242. uint8_t zero[ALIGN(1, true)] = {};
  243. uint32_t length = 0;
  244. int fd = -1;
  245. int r = 0;
  246. fd = open_hole(cd, O_RDWR | O_SYNC, &length);
  247. if (fd < 0)
  248. return fd;
  249. for (size_t i = 0; r >= 0 && i < length; i += sizeof(zero))
  250. r = writeall(fd, zero, sizeof(zero));
  251. close(fd);
  252. return r < 0 ? r : 0;
  253. }
  254. int
  255. luksmeta_init(struct crypt_device *cd)
  256. {
  257. uint32_t length = 0;
  258. int fd = -1;
  259. int r = 0;
  260. r = luksmeta_test(cd);
  261. if (r == 0)
  262. return -EALREADY;
  263. else if (r != -ENOENT && r != -EINVAL)
  264. return r;
  265. fd = open_hole(cd, O_RDWR | O_SYNC, &length);
  266. if (fd < 0)
  267. return fd;
  268. if (length < ALIGN(sizeof(lm_t), true)) {
  269. close(fd);
  270. return -ENOSPC;
  271. }
  272. r = write_header(fd, (lm_t) {});
  273. close(fd);
  274. return r > 0 ? 0 : r;
  275. }
  276. int
  277. luksmeta_load(struct crypt_device *cd, int slot,
  278. luksmeta_uuid_t uuid, void *buf, size_t size)
  279. {
  280. uint32_t length = 0;
  281. lm_slot_t *s = NULL;
  282. lm_t lm = {};
  283. int fd = -1;
  284. int r = 0;
  285. if (slot < 0 || slot >= LUKS_NSLOTS)
  286. return -EBADSLT;
  287. s = &lm.slots[slot];
  288. fd = read_header(cd, O_RDONLY, &length, &lm);
  289. if (fd < 0)
  290. return fd;
  291. r = uuid_is_zero(s->uuid) ? -ENODATA : 0;
  292. if (r < 0)
  293. goto error;
  294. if (buf) {
  295. r = size >= s->length ? 0 : -E2BIG;
  296. if (r < 0)
  297. goto error;
  298. r = lseek(fd, s->offset - sizeof(lm), SEEK_CUR) == -1 ? -errno : 0;
  299. if (r < 0)
  300. goto error;
  301. r = readall(fd, buf, s->length);
  302. if (r < 0)
  303. goto error;
  304. r = crc32c(0, buf, s->length) == s->crc32c ? 0 : -EINVAL;
  305. if (r < 0)
  306. goto error;
  307. }
  308. memcpy(uuid, s->uuid, sizeof(luksmeta_uuid_t));
  309. close(fd);
  310. return s->length;
  311. error:
  312. close(fd);
  313. return r;
  314. }
  315. int
  316. luksmeta_save(struct crypt_device *cd, int slot,
  317. const luksmeta_uuid_t uuid, const void *buf, size_t size)
  318. {
  319. uint32_t length = 0;
  320. lm_slot_t *s = NULL;
  321. lm_t lm = {};
  322. int fd = -1;
  323. int r = 0;
  324. off_t off;
  325. if (uuid_is_zero(uuid))
  326. return -EKEYREJECTED;
  327. fd = read_header(cd, O_RDWR | O_SYNC, &length, &lm);
  328. if (fd < 0)
  329. return fd;
  330. if (slot == CRYPT_ANY_SLOT)
  331. slot = find_unused_slot(cd, &lm);
  332. r = slot >= 0 && slot < LUKS_NSLOTS ? 0 : -EBADSLT;
  333. if (r < 0)
  334. goto error;
  335. s = &lm.slots[slot];
  336. r = uuid_is_zero(s->uuid) ? 0 : -EALREADY;
  337. if (r < 0)
  338. goto error;
  339. s->offset = find_gap(&lm, length, size);
  340. r = s->offset >= ALIGN(sizeof(lm), true) ? 0 : -ENOSPC;
  341. if (r < 0)
  342. goto error;
  343. memcpy(s->uuid, uuid, sizeof(luksmeta_uuid_t));
  344. s->length = size;
  345. s->crc32c = crc32c(0, buf, size);
  346. off = s->offset - sizeof(lm);
  347. r = lseek(fd, off, SEEK_CUR) == -1 ? -errno : 0;
  348. if (r < 0)
  349. goto error;
  350. r = writeall(fd, buf, size);
  351. if (r < 0)
  352. goto error;
  353. off = s->offset + s->length;
  354. r = lseek(fd, -off, SEEK_CUR) == -1 ? -errno : 0;
  355. if (r < 0)
  356. goto error;
  357. r = write_header(fd, lm);
  358. error:
  359. close(fd);
  360. return r < 0 ? r : slot;
  361. }
  362. int
  363. luksmeta_wipe(struct crypt_device *cd, int slot, const luksmeta_uuid_t uuid)
  364. {
  365. uint8_t *zero = NULL;
  366. uint32_t length = 0;
  367. lm_slot_t *s = NULL;
  368. lm_t lm = {};
  369. int fd = -1;
  370. int r = 0;
  371. off_t off;
  372. if (slot < 0 || slot >= LUKS_NSLOTS)
  373. return -EBADSLT;
  374. s = &lm.slots[slot];
  375. fd = read_header(cd, O_RDWR | O_SYNC, &length, &lm);
  376. if (fd < 0)
  377. return fd;
  378. r = uuid_is_zero(s->uuid) ? -EALREADY : 0;
  379. if (r < 0)
  380. goto error;
  381. if (uuid && memcmp(uuid, s->uuid, sizeof(luksmeta_uuid_t)) != 0) {
  382. r = -EKEYREJECTED;
  383. goto error;
  384. }
  385. off = s->offset - sizeof(lm_t);
  386. r = lseek(fd, off, SEEK_CUR) == -1 ? -errno : 0;
  387. if (r < 0)
  388. goto error;
  389. r = (zero = calloc(1, s->length)) ? 0 : -errno;
  390. if (r < 0)
  391. goto error;
  392. r = writeall(fd, zero, s->length);
  393. free(zero);
  394. if (r < 0)
  395. goto error;
  396. off = s->offset + s->length;
  397. r = lseek(fd, -off, SEEK_CUR) == -1 ? -errno : 0;
  398. if (r < 0)
  399. goto error;
  400. memset(s, 0, sizeof(lm_slot_t));
  401. r = write_header(fd, lm);
  402. error:
  403. close(fd);
  404. return r < 0 ? r : 0;
  405. }