Advertisement
Guest User

geli_external_header_patch

a guest
Jun 8th, 2013
164
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 38.37 KB | None | 0 0
  1. --- sbin/geom/class/eli/geom_eli.c.orig 2013-05-29 22:29:59.535524720 +0300
  2. +++ sbin/geom/class/eli/geom_eli.c  2013-06-02 12:53:31.992323211 +0300
  3. @@ -81,23 +81,23 @@
  4.  /*
  5.   * Available commands:
  6.   *
  7. - * init [-bhPv] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] prov
  8. + * init [-bPv] [-B backupfile] [-H headerfile] [-a aalgo] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] prov
  9.   * label - alias for 'init'
  10. - * attach [-dprv] [-j passfile] [-k keyfile] prov
  11. + * attach [-dprv] [-H headerfile] [-j passfile] [-k keyfile] prov
  12.   * detach [-fl] prov ...
  13.   * stop - alias for 'detach'
  14.   * onetime [-d] [-a aalgo] [-e ealgo] [-l keylen] prov
  15. - * configure [-bB] prov ...
  16. - * setkey [-pPv] [-n keyno] [-j passfile] [-J newpassfile] [-k keyfile] [-K newkeyfile] prov
  17. - * delkey [-afv] [-n keyno] prov
  18. + * configure [-bB] [-H headerfile] prov ...
  19. + * setkey [-pPv] [-H headerfile] [-n keyno] [-j passfile] [-J newpassfile] [-k keyfile] [-K newkeyfile] prov
  20. + * delkey [-afv] [-H headerfile] [-n keyno] prov
  21.   * suspend [-v] -a | prov ...
  22. - * resume [-pv] [-j passfile] [-k keyfile] prov
  23. + * resume [-pv] [-H headerfile] [-j passfile] [-k keyfile] prov
  24.   * kill [-av] [prov ...]
  25.   * backup [-v] prov file
  26.   * restore [-fv] file prov
  27. - * resize [-v] -s oldsize prov
  28. + * resize [-v] [-H headerfile] -s oldsize prov
  29.   * clear [-v] prov ...
  30. - * dump [-v] prov ...
  31. + * dump [-v] [-H headerfile] prov ...
  32.   */
  33.  struct g_command class_commands[] = {
  34.     { "init", G_FLAG_VERBOSE, eli_main,
  35. @@ -112,9 +112,10 @@
  36.         { 'l', "keylen", "0", G_TYPE_NUMBER },
  37.         { 'P', "nonewpassphrase", NULL, G_TYPE_BOOL },
  38.         { 's', "sectorsize", "0", G_TYPE_NUMBER },
  39. +       { 'H', "header", "", G_TYPE_STRING },
  40.         G_OPT_SENTINEL
  41.         },
  42. -       "[-bPv] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] [-s sectorsize] prov"
  43. +       "[-bPv] [-H headerfile] [-B backupfile] [-a aalgo] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] [-s sectorsize] prov"
  44.     },
  45.     { "label", G_FLAG_VERBOSE, eli_main,
  46.         {
  47. @@ -128,6 +129,7 @@
  48.         { 'l', "keylen", "0", G_TYPE_NUMBER },
  49.         { 'P', "nonewpassphrase", NULL, G_TYPE_BOOL },
  50.         { 's', "sectorsize", "0", G_TYPE_NUMBER },
  51. +       { 'H', "header", "", G_TYPE_STRING },
  52.         G_OPT_SENTINEL
  53.         },
  54.         "- an alias for 'init'"
  55. @@ -139,9 +141,10 @@
  56.         { 'k', "keyfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI },
  57.         { 'p', "nopassphrase", NULL, G_TYPE_BOOL },
  58.         { 'r', "readonly", NULL, G_TYPE_BOOL },
  59. +       { 'H', "header", "", G_TYPE_STRING },
  60.         G_OPT_SENTINEL
  61.         },
  62. -       "[-dprv] [-j passfile] [-k keyfile] prov"
  63. +       "[-dprv] [-H headerfile] [-j passfile] [-k keyfile] prov"
  64.     },
  65.     { "detach", 0, NULL,
  66.         {
  67. @@ -170,13 +173,14 @@
  68.         },
  69.         "[-d] [-a aalgo] [-e ealgo] [-l keylen] [-s sectorsize] prov"
  70.     },
  71. -   { "configure", G_FLAG_VERBOSE, eli_main,
  72. +   { "configure", G_FLAG_VERBOSE | G_FLAG_LOADKLD, eli_main,
  73.         {
  74.         { 'b', "boot", NULL, G_TYPE_BOOL },
  75.         { 'B', "noboot", NULL, G_TYPE_BOOL },
  76. +       { 'H', "header", "", G_TYPE_STRING },
  77.         G_OPT_SENTINEL
  78.         },
  79. -       "[-bB] prov ..."
  80. +       "[-bB] [-H headerfile] prov ..."
  81.     },
  82.     { "setkey", G_FLAG_VERBOSE, eli_main,
  83.         {
  84. @@ -188,18 +192,20 @@
  85.         { 'n', "keyno", "-1", G_TYPE_NUMBER },
  86.         { 'p', "nopassphrase", NULL, G_TYPE_BOOL },
  87.         { 'P', "nonewpassphrase", NULL, G_TYPE_BOOL },
  88. +       { 'H', "header", "", G_TYPE_STRING },
  89.         G_OPT_SENTINEL
  90.         },
  91. -       "[-pPv] [-n keyno] [-i iterations] [-j passfile] [-J newpassfile] [-k keyfile] [-K newkeyfile] prov"
  92. +       "[-pPv] [-H headerfile] [-n keyno] [-i iterations] [-j passfile] [-J newpassfile] [-k keyfile] [-K newkeyfile] prov"
  93.     },
  94.     { "delkey", G_FLAG_VERBOSE, eli_main,
  95.         {
  96.         { 'a', "all", NULL, G_TYPE_BOOL },
  97.         { 'f', "force", NULL, G_TYPE_BOOL },
  98.         { 'n', "keyno", "-1", G_TYPE_NUMBER },
  99. +       { 'H', "header", "", G_TYPE_STRING },
  100.         G_OPT_SENTINEL
  101.         },
  102. -       "[-afv] [-n keyno] prov"
  103. +       "[-afv] [-H headerfile] [-n keyno] prov"
  104.     },
  105.     { "suspend", G_FLAG_VERBOSE, NULL,
  106.         {
  107. @@ -213,9 +219,10 @@
  108.         { 'j', "passfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI },
  109.         { 'k', "keyfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI },
  110.         { 'p', "nopassphrase", NULL, G_TYPE_BOOL },
  111. +       { 'H', "header", "", G_TYPE_STRING },
  112.         G_OPT_SENTINEL
  113.         },
  114. -       "[-pv] [-j passfile] [-k keyfile] prov"
  115. +       "[-pv] [-H headerfile] [-j passfile] [-k keyfile] prov"
  116.     },
  117.     { "kill", G_FLAG_VERBOSE, eli_main,
  118.         {
  119. @@ -237,15 +244,20 @@
  120.     { "resize", G_FLAG_VERBOSE, eli_main,
  121.         {
  122.         { 's', "oldsize", NULL, G_TYPE_NUMBER },
  123. +       { 'H', "header", "", G_TYPE_STRING },
  124.         G_OPT_SENTINEL
  125.         },
  126. -       "[-v] -s oldsize prov"
  127. +       "[-v] [-H headerfile] -s oldsize prov"
  128.     },
  129.     { "clear", G_FLAG_VERBOSE, eli_main, G_NULL_OPTS,
  130.         "[-v] prov ..."
  131.     },
  132. -   { "dump", G_FLAG_VERBOSE, eli_main, G_NULL_OPTS,
  133. -       "[-v] prov ..."
  134. +   { "dump", G_FLAG_VERBOSE, eli_main,
  135. +       {
  136. +       { 'H', "header", "", G_TYPE_STRING },
  137. +       G_OPT_SENTINEL
  138. +       },
  139. +       "[-v] [-H headerfile] prov ..."
  140.     },
  141.     G_CMD_SENTINEL
  142.  };
  143. @@ -646,19 +658,48 @@
  144.     return (0);
  145.  }
  146.  
  147. +static int
  148. +eli_header_store(struct gctl_req *req, const char *header,
  149. +       unsigned char *hd, size_t hdsize)
  150. +{
  151. +   int fd;
  152. +
  153. +   fd = open(header, O_WRONLY | O_TRUNC | O_CREAT);
  154. +   if (fd == -1) {
  155. +       gctl_error(req, "Cannot open %s: %s.", header,
  156. +           strerror(errno));
  157. +       return (-1);
  158. +   }
  159. +
  160. +   if ((size_t)write(fd, hd, hdsize) != hdsize) {
  161. +       gctl_error(req, "Cannot write metadata to %s: %s.",
  162. +               header, strerror(errno));
  163. +       return(-1);
  164. +   }
  165. +
  166. +   (void)fsync(fd);
  167. +   close(fd);
  168. +
  169. +   return (0);
  170. +}
  171. +
  172.  static void
  173.  eli_init(struct gctl_req *req)
  174.  {
  175.     struct g_eli_metadata md;
  176.     unsigned char sector[sizeof(struct g_eli_metadata)];
  177.     unsigned char key[G_ELI_USERKEYLEN];
  178. +   unsigned char *hd;
  179.     char backfile[MAXPATHLEN];
  180. -   const char *str, *prov;
  181. +   const char *str, *prov, *header;
  182.     unsigned secsize;
  183.     off_t mediasize;
  184. +   size_t hdsize;
  185.     intmax_t val;
  186.     int error, nargs;
  187.  
  188. +   hd = NULL;
  189. +
  190.     nargs = gctl_get_int(req, "nargs");
  191.     if (nargs != 1) {
  192.         gctl_error(req, "Invalid number of arguments.");
  193. @@ -666,7 +707,7 @@
  194.     }
  195.     prov = gctl_get_ascii(req, "arg0");
  196.     mediasize = g_get_mediasize(prov);
  197. -   secsize = g_get_sectorsize(prov);
  198. +   hdsize = secsize = g_get_sectorsize(prov);
  199.     if (mediasize == 0 || secsize == 0) {
  200.         gctl_error(req, "Cannot get informations about %s: %s.", prov,
  201.             strerror(errno));
  202. @@ -770,23 +811,39 @@
  203.     error = g_eli_mkey_encrypt(md.md_ealgo, key, md.md_keylen, md.md_mkeys);
  204.     bzero(key, sizeof(key));
  205.     if (error != 0) {
  206. -       bzero(&md, sizeof(md));
  207.         gctl_error(req, "Cannot encrypt Master Key: %s.",
  208.             strerror(error));
  209. -       return;
  210. +       goto out;
  211.     }
  212.  
  213. -   eli_metadata_encode(&md, sector);
  214. -   bzero(&md, sizeof(md));
  215. -   error = g_metadata_store(prov, sector, sizeof(sector));
  216. -   bzero(sector, sizeof(sector));
  217. -   if (error != 0) {
  218. -       gctl_error(req, "Cannot store metadata on %s: %s.", prov,
  219. -           strerror(error));
  220. -       return;
  221. +   header = gctl_get_ascii(req, "header");
  222. +   if (header[0] != '\0') {
  223. +       hd = malloc(hdsize);
  224. +       if (hd == NULL) {
  225. +           gctl_error(req, "Cannot allocate %zd bytes of memory.", hdsize);
  226. +           goto out;
  227. +       }
  228. +       bzero(hd, hdsize);
  229. +
  230. +       eli_metadata_encode(&md, hd);
  231. +       eli_header_store(req, header, hd, hdsize);
  232. +   } else {
  233. +       eli_metadata_encode(&md, sector);
  234. +       error = g_metadata_store(prov, sector, sizeof(sector));
  235. +       bzero(sector, sizeof(sector));
  236. +       if (error != 0) {
  237. +           gctl_error(req, "Cannot store metadata on %s: %s.", prov,
  238. +               strerror(error));
  239. +           goto out;
  240. +       }
  241. +   }
  242. +
  243. +   if (verbose) {
  244. +       if (header[0] != '\0')
  245. +           printf("Metadata value stored in %s.\n", header);
  246. +       else
  247. +           printf("Metadata value stored on %s.\n", prov);
  248.     }
  249. -   if (verbose)
  250. -       printf("Metadata value stored on %s.\n", prov);
  251.     /* Backup metadata to a file. */
  252.     str = gctl_get_ascii(req, "backupfile");
  253.     if (str[0] != '\0') {
  254. @@ -807,12 +864,25 @@
  255.                 backfile[i] = '_';
  256.         }
  257.     }
  258. -   if (strcmp(backfile, "none") != 0 &&
  259. -       eli_backup_create(req, prov, backfile) == 0) {
  260. +   if (strcmp(backfile, "none") != 0) {
  261. +       if (header[0] != '\0')
  262. +           error = eli_header_store(req, backfile, hd, hdsize);
  263. +       else
  264. +           error = eli_backup_create(req, prov, backfile);
  265. +
  266. +       if (error != 0)
  267. +           goto out;
  268. +
  269.         printf("\nMetadata backup can be found in %s and\n", backfile);
  270.         printf("can be restored with the following command:\n");
  271.         printf("\n\t# geli restore %s %s\n\n", backfile, prov);
  272.     }
  273. +out:
  274. +   bzero(&md, sizeof(md));
  275. +   if (hd != NULL) {
  276. +       bzero(hd, hdsize);
  277. +       free(hd);
  278. +   }
  279.  }
  280.  
  281.  static void
  282. @@ -820,8 +890,10 @@
  283.  {
  284.     struct g_eli_metadata md;
  285.     unsigned char key[G_ELI_USERKEYLEN];
  286. -   const char *prov;
  287. +   unsigned char *hd = NULL;
  288. +   const char *str, *prov, *header;
  289.     off_t mediasize;
  290. +   size_t hdsize = 0;
  291.     int nargs;
  292.  
  293.     nargs = gctl_get_int(req, "nargs");
  294. @@ -829,14 +901,23 @@
  295.         gctl_error(req, "Invalid number of arguments.");
  296.         return;
  297.     }
  298. +  
  299.     prov = gctl_get_ascii(req, "arg0");
  300. +   header = gctl_get_ascii(req, "header");
  301. +
  302. +   if (header[0] != '\0')
  303. +       str = header;
  304. +   else
  305. +       str = prov;
  306.  
  307. -   if (eli_metadata_read(req, prov, &md) == -1)
  308. +   if (eli_metadata_read(req, str, &md) == -1)
  309.         return;
  310.  
  311. +   hdsize = g_get_sectorsize(prov);
  312.     mediasize = g_get_mediasize(prov);
  313. +
  314.     if (md.md_provsize != (uint64_t)mediasize) {
  315. -       gctl_error(req, "Provider size mismatch.");
  316. +       gctl_error(req, "Provider size mismatch (expected %zd).", md.md_provsize);
  317.         return;
  318.     }
  319.  
  320. @@ -845,21 +926,53 @@
  321.         return;
  322.     }
  323.  
  324. +   if (header[0] != '\0') {
  325. +       hd = malloc(hdsize);
  326. +       if (hd == NULL) {
  327. +           gctl_error(req, "Cannot allocate %zd bytes of memory.", hdsize);
  328. +           return;
  329. +       }
  330. +       bzero(hd, hdsize);
  331. +       eli_metadata_encode(&md, hd);
  332. +       gctl_ro_param(req, "hd", hdsize, hd);
  333. +   }
  334. +
  335.     gctl_ro_param(req, "key", sizeof(key), key);
  336.     if (gctl_issue(req) == NULL) {
  337.         if (verbose)
  338.             printf("Attached to %s.\n", prov);
  339.     }
  340.     bzero(key, sizeof(key));
  341. +   if (hd != NULL) {
  342. +       bzero(hd, hdsize);
  343. +       free(hd);
  344. +   }
  345.  }
  346.  
  347.  static void
  348.  eli_configure_detached(struct gctl_req *req, const char *prov, bool boot)
  349.  {
  350.     struct g_eli_metadata md;
  351. +   unsigned char *hd;
  352. +   const char *str, *header;
  353. +   size_t hdsize;
  354. +   off_t mediasize;
  355. +
  356. +   header = gctl_get_ascii(req, "header");
  357. +
  358. +   if (header[0] != '\0')
  359. +       str = header;
  360. +   else
  361. +       str = prov;
  362. +
  363. +   if (eli_metadata_read(req, str, &md) == -1)
  364. +       return;
  365.  
  366. -   if (eli_metadata_read(req, prov, &md) == -1)
  367. +   mediasize = g_get_mediasize(prov);
  368. +   if (md.md_provsize != (uint64_t)mediasize) {
  369. +       gctl_error(req, "Provider size mismatch (expected %zd).", md.md_provsize);
  370.         return;
  371. +   }
  372.  
  373.     if (boot && (md.md_flags & G_ELI_FLAG_BOOT)) {
  374.         if (verbose)
  375. @@ -872,16 +985,40 @@
  376.             md.md_flags |= G_ELI_FLAG_BOOT;
  377.         else
  378.             md.md_flags &= ~G_ELI_FLAG_BOOT;
  379. -       eli_metadata_store(req, prov, &md);
  380. +
  381. +       if (header[0] != '\0') {
  382. +           hdsize = g_get_sectorsize(prov);
  383. +
  384. +           hd = malloc(hdsize);
  385. +           if (hd == NULL) {
  386. +               gctl_error(req, "Cannot allocate %zd bytes of memory.", hdsize);
  387. +               return;
  388. +           }
  389. +           bzero(hd, hdsize);
  390. +
  391. +           eli_metadata_encode(&md, hd);
  392. +           eli_header_store(req, header, hd, hdsize);
  393. +
  394. +           bzero(hd, hdsize);
  395. +           free(hd);
  396. +       }
  397. +       else {
  398. +           eli_metadata_store(req, prov, &md);
  399. +       }
  400.     }
  401. +
  402.     bzero(&md, sizeof(md));
  403.  }
  404.  
  405.  static void
  406.  eli_configure(struct gctl_req *req)
  407.  {
  408. -   const char *prov;
  409. +   struct g_eli_metadata md;
  410. +   const char *prov, *header;
  411. +   unsigned char *hd;
  412.     bool boot, noboot;
  413. +   off_t mediasize;
  414. +   size_t hdsize;
  415.     int i, nargs;
  416.  
  417.     nargs = gctl_get_int(req, "nargs");
  418. @@ -902,8 +1039,46 @@
  419.         return;
  420.     }
  421.  
  422. +   prov = gctl_get_ascii(req, "arg0");
  423. +   header = gctl_get_ascii(req, "header");
  424. +
  425. +   if ((header[0] != '\0') && eli_is_attached(prov)) {
  426. +       if(nargs != 1) {
  427. +           gctl_error(req, "Too many arguments.");
  428. +           return;
  429. +       }
  430. +
  431. +       if (eli_metadata_read(req, header, &md) == -1)
  432. +           return;
  433. +
  434. +       hdsize = g_get_sectorsize(prov);
  435. +       mediasize = g_get_mediasize(prov);
  436. +       if (md.md_provsize != (uint64_t)mediasize) {
  437. +           gctl_error(req, "Provider size mismatch (expected %zd).", md.md_provsize);
  438. +           return;
  439. +       }
  440. +
  441. +       hd = malloc(hdsize);
  442. +       if (hd == NULL) {
  443. +           gctl_error(req, "Cannot allocate %zd bytes of memory.", hdsize);
  444. +           return;
  445. +       }
  446. +       bzero(hd, hdsize);
  447. +
  448. +       eli_metadata_encode(&md, hd);
  449. +       gctl_rw_param(req, "hd", hdsize, hd);
  450. +   }
  451. +
  452.     /* First attached providers. */
  453.     gctl_issue(req);
  454. +
  455. +   if ((header[0] != '\0') && eli_is_attached(prov)) {
  456. +       eli_header_store(req, header, hd, hdsize);
  457. +       bzero(&md, sizeof(md));
  458. +       bzero(hd, hdsize);
  459. +       free(hd);
  460. +   }
  461. +
  462.     /* Now the rest. */
  463.     for (i = 0; i < nargs; i++) {
  464.         prov = gctl_get_ascii(req, "arg%d", i);
  465. @@ -915,8 +1090,12 @@
  466.  static void
  467.  eli_setkey_attached(struct gctl_req *req, struct g_eli_metadata *md)
  468.  {
  469. +   const char *prov, *header;
  470.     unsigned char key[G_ELI_USERKEYLEN];
  471. +   unsigned char *hd;
  472.     intmax_t val, old = 0;
  473. +   off_t mediasize;
  474. +   size_t hdsize;
  475.     int error;
  476.  
  477.     val = gctl_get_intmax(req, "iterations");
  478. @@ -941,19 +1120,52 @@
  479.         assert(error == 0);
  480.     }
  481.  
  482. +   header = gctl_get_ascii(req, "header");
  483. +   if (header[0] != '\0') {
  484. +       prov = gctl_get_ascii(req, "arg0");
  485. +
  486. +       hdsize = g_get_sectorsize(prov);
  487. +       mediasize = g_get_mediasize(prov);
  488. +       if (md->md_provsize != (uint64_t)mediasize) {
  489. +           gctl_error(req, "Provider size mismatch (expected %zd).", md->md_provsize);
  490. +           return;
  491. +       }
  492. +
  493. +       hd = malloc(hdsize);
  494. +       if (hd == NULL) {
  495. +           gctl_error(req, "Cannot allocate %zd bytes of memory.", hdsize);
  496. +           return;
  497. +       }
  498. +       bzero(hd, hdsize);
  499. +
  500. +       eli_metadata_encode(md, hd);
  501. +       gctl_rw_param(req, "hd", hdsize, hd);
  502. +   }
  503. +
  504.     gctl_ro_param(req, "key", sizeof(key), key);
  505.     gctl_issue(req);
  506.     bzero(key, sizeof(key));
  507. +
  508. +   if (header[0] != '\0') {
  509. +       eli_metadata_decode(hd, md);
  510. +       eli_header_store(req, header, hd, hdsize);
  511. +
  512. +       bzero(hd, hdsize);
  513. +       free(hd);
  514. +   }
  515.  }
  516.  
  517.  static void
  518.  eli_setkey_detached(struct gctl_req *req, const char *prov,
  519.   struct g_eli_metadata *md)
  520.  {
  521. +   const char *header;
  522.     unsigned char key[G_ELI_USERKEYLEN], mkey[G_ELI_DATAIVKEYLEN];
  523. -   unsigned char *mkeydst;
  524. +   unsigned char *mkeydst, *hd = NULL;
  525.     unsigned int nkey;
  526.     intmax_t val;
  527. +   off_t mediasize;
  528. +   size_t hdsize = 0;
  529.     int error;
  530.  
  531.     if (md->md_keys == 0) {
  532. @@ -1035,7 +1247,31 @@
  533.     }
  534.  
  535.     /* Store metadata with fresh key. */
  536. -   eli_metadata_store(req, prov, md);
  537. +   header = gctl_get_ascii(req, "header");
  538. +   if (header[0] != '\0') {
  539. +       hdsize = g_get_sectorsize(prov);
  540. +       mediasize = g_get_mediasize(prov);
  541. +       if (md->md_provsize != (uint64_t)mediasize) {
  542. +           gctl_error(req, "Provider size mismatch (expected %zd).", md->md_provsize);
  543. +           return;
  544. +       }
  545. +      
  546. +       hd = malloc(hdsize);
  547. +       if (hd == NULL) {
  548. +           gctl_error(req, "Cannot allocate %zd bytes of memory.", hdsize);
  549. +           return;
  550. +       }
  551. +       bzero(hd, hdsize);
  552. +
  553. +       eli_metadata_encode(md, hd);
  554. +       eli_header_store(req, header, hd, hdsize);
  555. +
  556. +       bzero(hd, hdsize);
  557. +       free(hd);
  558. +   } else {
  559. +       eli_metadata_store(req, prov, md);
  560. +   }
  561. +
  562.     bzero(md, sizeof(*md));
  563.  }
  564.  
  565. @@ -1043,7 +1279,7 @@
  566.  eli_setkey(struct gctl_req *req)
  567.  {
  568.     struct g_eli_metadata md;
  569. -   const char *prov;
  570. +   const char *str, *prov, *header;
  571.     int nargs;
  572.  
  573.     nargs = gctl_get_int(req, "nargs");
  574. @@ -1051,9 +1287,16 @@
  575.         gctl_error(req, "Invalid number of arguments.");
  576.         return;
  577.     }
  578. +
  579.     prov = gctl_get_ascii(req, "arg0");
  580. +   header = gctl_get_ascii(req, "header");
  581. +
  582. +   if (header[0] != '\0')
  583. +       str = header;
  584. +   else
  585. +       str = prov;
  586.  
  587. -   if (eli_metadata_read(req, prov, &md) == -1)
  588. +   if (eli_metadata_read(req, str, &md) == -1)
  589.         return;
  590.  
  591.     if (eli_is_attached(prov))
  592. @@ -1066,25 +1309,71 @@
  593.             "and/or passphrase may still exists in a metadata backup "
  594.             "file.\n");
  595.     }
  596. +
  597. +   bzero(&md, sizeof(md));
  598.  }
  599.  
  600.  static void
  601.  eli_delkey_attached(struct gctl_req *req, const char *prov __unused)
  602.  {
  603. +   struct g_eli_metadata md;
  604. +   const char *header;
  605. +   unsigned char *hd;
  606. +   off_t mediasize;
  607. +   size_t hdsize;
  608. +
  609. +   header = gctl_get_ascii(req, "header");
  610. +   if (header[0] != '\0') {
  611. +       if (eli_metadata_read(req, header, &md) == -1)
  612. +           return;
  613. +
  614. +       hdsize = g_get_sectorsize(prov);
  615. +       mediasize = g_get_mediasize(prov);
  616. +       if (md.md_provsize != (uint64_t)mediasize) {
  617. +           gctl_error(req, "Provider size mismatch (expected %zd).", md.md_provsize);
  618. +           return;
  619. +       }
  620. +
  621. +       hd = malloc(hdsize);
  622. +       if (hd == NULL) {
  623. +           gctl_error(req, "Cannot allocate %zd bytes of memory.", hdsize);
  624. +           return;
  625. +       }
  626. +       bzero(hd, hdsize);
  627. +
  628. +       eli_metadata_encode(&md, hd);
  629. +       bzero(&md, sizeof(md));
  630. +       gctl_rw_param(req, "hd", hdsize, hd);
  631. +   }
  632.  
  633.     gctl_issue(req);
  634. +
  635. +   if (header[0] != '\0') {
  636. +       eli_header_store(req, header, hd, hdsize);
  637. +       bzero(hd, hdsize);
  638. +       free(hd);
  639. +   }
  640.  }
  641.  
  642.  static void
  643.  eli_delkey_detached(struct gctl_req *req, const char *prov)
  644.  {
  645.     struct g_eli_metadata md;
  646. -   unsigned char *mkeydst;
  647. +   const char *str, *header;
  648. +   unsigned char *mkeydst, *hd;
  649.     unsigned int nkey;
  650. +   off_t mediasize;
  651. +   size_t hdsize;
  652.     intmax_t val;
  653.     bool all, force;
  654.  
  655. -   if (eli_metadata_read(req, prov, &md) == -1)
  656. +   header = gctl_get_ascii(req, "header");
  657. +   if (header[0] != '\0')
  658. +       str = header;
  659. +   else
  660. +       str = prov;
  661. +
  662. +   if (eli_metadata_read(req, str, &md) == -1)
  663.         return;
  664.  
  665.     all = gctl_get_int(req, "all");
  666. @@ -1116,7 +1405,29 @@
  667.         arc4rand(mkeydst, G_ELI_MKEYLEN);
  668.     }
  669.  
  670. -   eli_metadata_store(req, prov, &md);
  671. +   if (header[0] != '\0') {
  672. +       hdsize = g_get_sectorsize(prov);
  673. +       mediasize = g_get_mediasize(prov);
  674. +       if (md.md_provsize != (uint64_t)mediasize) {
  675. +           gctl_error(req, "Provider size mismatch (expected %zd).", md.md_provsize);
  676. +           return;
  677. +       }
  678. +
  679. +       hd = malloc(hdsize);
  680. +       if (hd == NULL) {
  681. +           gctl_error(req, "Cannot allocate %zd bytes of memory.", hdsize);
  682. +           return;
  683. +       }
  684. +       bzero(hd, hdsize);
  685. +
  686. +       eli_metadata_encode(&md, hd);
  687. +       eli_header_store(req, header, hd, hdsize);
  688. +
  689. +       bzero(hd, hdsize);
  690. +       free(hd);
  691. +   } else {
  692. +       eli_metadata_store(req, prov, &md);
  693. +   }
  694.     bzero(&md, sizeof(md));
  695.  }
  696.  
  697. @@ -1144,8 +1455,10 @@
  698.  {
  699.     struct g_eli_metadata md;
  700.     unsigned char key[G_ELI_USERKEYLEN];
  701. -   const char *prov;
  702. +   unsigned char *hd = NULL;
  703. +   const char *str, *prov, *header;
  704.     off_t mediasize;
  705. +   size_t hdsize = 0;
  706.     int nargs;
  707.  
  708.     nargs = gctl_get_int(req, "nargs");
  709. @@ -1154,13 +1467,19 @@
  710.         return;
  711.     }
  712.     prov = gctl_get_ascii(req, "arg0");
  713. +   header = gctl_get_ascii(req, "header");
  714.  
  715. -   if (eli_metadata_read(req, prov, &md) == -1)
  716. +   if (header[0] != '\0')
  717. +       str = header;
  718. +   else
  719. +       str = prov;
  720. +
  721. +   if (eli_metadata_read(req, str, &md) == -1)
  722.         return;
  723.  
  724.     mediasize = g_get_mediasize(prov);
  725.     if (md.md_provsize != (uint64_t)mediasize) {
  726. -       gctl_error(req, "Provider size mismatch.");
  727. +       gctl_error(req, "Provider size mismatch (expected %zd).", md.md_provsize);
  728.         return;
  729.     }
  730.  
  731. @@ -1169,11 +1488,31 @@
  732.         return;
  733.     }
  734.  
  735. +   if(header[0] != '\0') {
  736. +       hdsize = g_get_sectorsize(prov);
  737. +
  738. +       hd = malloc(hdsize);
  739. +       if (hd == NULL) {
  740. +           gctl_error(req, "Cannot allocate %zd bytes of memory.", hdsize);
  741. +           return;
  742. +       }
  743. +       bzero(hd, hdsize);
  744. +
  745. +       eli_metadata_encode(&md, hd);
  746. +       gctl_ro_param(req, "hd", hdsize, hd);
  747. +   }
  748. +
  749.     gctl_ro_param(req, "key", sizeof(key), key);
  750.     if (gctl_issue(req) == NULL) {
  751.         if (verbose)
  752.             printf("Resumed %s.\n", prov);
  753.     }
  754. +
  755. +   if (hd != NULL) {
  756. +       bzero(hd, hdsize);
  757. +       free(hd);
  758. +   }
  759. +
  760.     bzero(key, sizeof(key));
  761.  }
  762.  
  763. @@ -1336,11 +1675,13 @@
  764.         gctl_error(req, "Cannot read metadata: %s.", strerror(errno));
  765.         goto out;
  766.     }
  767. +
  768.     /* Check if this is geli provider. */
  769.     if (eli_metadata_decode(sector, &md) != 0) {
  770.         gctl_error(req, "MD5 hash mismatch: not a geli provider?");
  771.         goto out;
  772.     }
  773. +
  774.     /* Write metadata to the destination file. */
  775.     if (write(filefd, sector, secsize) != secsize) {
  776.         gctl_error(req, "Cannot write to %s: %s.", file,
  777. @@ -1469,9 +1810,10 @@
  778.  eli_resize(struct gctl_req *req)
  779.  {
  780.     struct g_eli_metadata md;
  781. -   const char *prov;
  782. -   unsigned char *sector;
  783. +   const char *prov, *header;
  784. +   unsigned char *sector, *hd;
  785.     ssize_t secsize;
  786. +   size_t hdsize;
  787.     off_t mediasize, oldsize;
  788.     int nargs, provfd;
  789.  
  790. @@ -1480,20 +1822,28 @@
  791.         gctl_error(req, "Invalid number of arguments.");
  792.         return;
  793.     }
  794. +
  795.     prov = gctl_get_ascii(req, "arg0");
  796. +   header = gctl_get_ascii(req, "header");
  797.  
  798.     provfd = -1;
  799.     sector = NULL;
  800.     secsize = 0;
  801.  
  802. -   provfd = g_open(prov, 1);
  803. -   if (provfd == -1) {
  804. -       gctl_error(req, "Cannot open %s: %s.", prov, strerror(errno));
  805. -       goto out;
  806. +   if (header[0] == '\0') {
  807. +       provfd = g_open(prov, 1);
  808. +       if (provfd == -1) {
  809. +           gctl_error(req, "Cannot open %s: %s.", prov, strerror(errno));
  810. +           goto out;
  811. +       }
  812. +
  813. +       mediasize = g_mediasize(provfd);
  814. +       secsize = g_sectorsize(provfd);
  815. +   } else {
  816. +       mediasize = g_get_mediasize(prov);
  817. +       secsize = g_get_sectorsize(prov);
  818.     }
  819.  
  820. -   mediasize = g_mediasize(provfd);
  821. -   secsize = g_sectorsize(provfd);
  822.     if (mediasize == -1 || secsize == -1) {
  823.         gctl_error(req, "Cannot get information about %s: %s.", prov,
  824.             strerror(errno));
  825. @@ -1516,17 +1866,25 @@
  826.         goto out;
  827.     }
  828.  
  829. -   /* Read metadata from the 'oldsize' offset. */
  830. -   if (pread(provfd, sector, secsize, oldsize - secsize) != secsize) {
  831. -       gctl_error(req, "Cannot read old metadata: %s.",
  832. -           strerror(errno));
  833. -       goto out;
  834. -   }
  835. +   if (header[0] != '\0') {
  836. +       if (eli_metadata_read(req, header, &md) == -1) {
  837. +           gctl_error(req, "Cannot read old metadata: %s.",
  838. +                   header);
  839. +           goto out;
  840. +       }
  841. +   } else {
  842. +       /* Read metadata from the 'oldsize' offset. */
  843. +       if (pread(provfd, sector, secsize, oldsize - secsize) != secsize) {
  844. +           gctl_error(req, "Cannot read old metadata: %s.",
  845. +               strerror(errno));
  846. +           goto out;
  847. +       }
  848.  
  849. -   /* Check if this sector contains geli metadata. */
  850. -   if (eli_metadata_decode(sector, &md) != 0) {
  851. -       gctl_error(req, "MD5 hash mismatch: no metadata for oldsize.");
  852. -       goto out;
  853. +       /* Check if this sector contains geli metadata. */
  854. +       if (eli_metadata_decode(sector, &md) != 0) {
  855. +           gctl_error(req, "MD5 hash mismatch: no metadata for oldsize.");
  856. +           goto out;
  857. +       }
  858.     }
  859.  
  860.     /*
  861. @@ -1543,16 +1901,41 @@
  862.      * it back to the correct place on the provider.
  863.      */
  864.     md.md_provsize = mediasize;
  865. -   eli_metadata_encode(&md, sector);
  866. -   if (pwrite(provfd, sector, secsize, mediasize - secsize) != secsize) {
  867. -       gctl_error(req, "Cannot write metadata: %s.", strerror(errno));
  868. -       goto out;
  869. +
  870. +   if (header[0] != '\0') {
  871. +       hdsize = g_get_sectorsize(prov);
  872. +
  873. +       hd = malloc(hdsize);
  874. +       if (hd == NULL) {
  875. +           gctl_error(req, "Cannot allocate %zd bytes of memory.", hdsize);
  876. +           return;
  877. +       }
  878. +       bzero(hd, hdsize);
  879. +
  880. +       eli_metadata_encode(&md, hd);
  881. +       eli_header_store(req, header, hd, hdsize);
  882. +
  883. +       bzero(hd, hdsize);
  884. +       free(hd);
  885. +   } else {
  886. +       sector = malloc(secsize);
  887. +       if (sector == NULL) {
  888. +           gctl_error(req, "Cannot allocate memory.");
  889. +           goto out;
  890. +       }
  891. +
  892. +       eli_metadata_encode(&md, sector);
  893. +       if (pwrite(provfd, sector, secsize, mediasize - secsize) != secsize) {
  894. +           gctl_error(req, "Cannot write metadata: %s.", strerror(errno));
  895. +           goto out;
  896. +       }
  897. +       (void)g_flush(provfd);
  898. +
  899. +       /* Now trash the old metadata. */
  900. +       if (eli_trash_metadata(req, prov, provfd, oldsize - secsize) == -1)
  901. +           goto out;
  902.     }
  903. -   (void)g_flush(provfd);
  904.  
  905. -   /* Now trash the old metadata. */
  906. -   if (eli_trash_metadata(req, prov, provfd, oldsize - secsize) == -1)
  907. -       goto out;
  908.  out:
  909.     if (provfd >= 0)
  910.         (void)g_close(provfd);
  911. @@ -1592,7 +1975,8 @@
  912.  eli_dump(struct gctl_req *req)
  913.  {
  914.     struct g_eli_metadata md, tmpmd;
  915. -   const char *name;
  916. +   const char *name, *header;
  917. +   size_t hdsize;
  918.     int error, i, nargs;
  919.  
  920.     nargs = gctl_get_int(req, "nargs");
  921. @@ -1601,15 +1985,44 @@
  922.         return;
  923.     }
  924.  
  925. -   for (i = 0; i < nargs; i++) {
  926. -       name = gctl_get_ascii(req, "arg%d", i);
  927. -       error = g_metadata_read(name, (unsigned char *)&tmpmd,
  928. -           sizeof(tmpmd), G_ELI_MAGIC);
  929. -       if (error != 0) {
  930. +   header = gctl_get_ascii(req, "header");
  931. +   if (header[0] != '\0') {
  932. +       if (nargs != 1) {
  933. +           gctl_error(req, "Too many arguments.");
  934. +           return;
  935. +       }
  936. +
  937. +       if (eli_metadata_read(req, header, &tmpmd) == -1)
  938. +           return;
  939. +
  940. +       name = gctl_get_ascii(req, "arg0");
  941. +       hdsize = g_get_sectorsize(name);
  942. +
  943. +       if (hdsize != tmpmd.md_sectorsize) {
  944. +           gctl_error(req, "Provider sector size mismatch (expected %zd)", tmpmd.md_sectorsize);
  945. +           return;
  946. +       }
  947. +
  948. +       if (strcmp(tmpmd.md_magic, G_ELI_MAGIC) != 0) {
  949. +           error = EINVAL;
  950.             fprintf(stderr, "Cannot read metadata from %s: %s.\n",
  951. -               name, strerror(error));
  952. +                   name, strerror(error));
  953.             gctl_error(req, "Not fully done.");
  954. -           continue;
  955. +           return;
  956. +       }
  957. +   }
  958. +
  959. +   for (i = 0; i < nargs; i++) {
  960. +       if (header[0] == '\0') {
  961. +           name = gctl_get_ascii(req, "arg%d", i);
  962. +           error = g_metadata_read(name, (unsigned char *)&tmpmd,
  963. +               sizeof(tmpmd), G_ELI_MAGIC);
  964. +           if (error != 0) {
  965. +               fprintf(stderr, "Cannot read metadata from %s: %s.\n",
  966. +                   name, strerror(error));
  967. +               gctl_error(req, "Not fully done.");
  968. +               continue;
  969. +           }
  970.         }
  971.         if (eli_metadata_decode((unsigned char *)&tmpmd, &md) != 0) {
  972.             fprintf(stderr, "MD5 hash mismatch for %s, skipping.\n",
  973. --- sbin/geom/class/eli/geli.8.orig 2013-05-29 22:30:05.118234254 +0300
  974. +++ sbin/geom/class/eli/geli.8  2013-05-20 10:50:15.945898303 +0300
  975. @@ -52,6 +52,7 @@
  976.  .Nm
  977.  .Cm init
  978.  .Op Fl bPv
  979. +.Op Fl H Ar headerfile
  980.  .Op Fl a Ar aalgo
  981.  .Op Fl B Ar backupfile
  982.  .Op Fl e Ar ealgo
  983. @@ -67,6 +68,7 @@
  984.  .Nm
  985.  .Cm attach
  986.  .Op Fl dprv
  987. +.Op Fl H Ar headerfile
  988.  .Op Fl j Ar passfile
  989.  .Op Fl k Ar keyfile
  990.  .Ar prov
  991. @@ -88,10 +90,12 @@
  992.  .Nm
  993.  .Cm configure
  994.  .Op Fl bB
  995. +.Op Fl H Ar headerfile
  996.  .Ar prov ...
  997.  .Nm
  998.  .Cm setkey
  999.  .Op Fl pPv
  1000. +.Op Fl H Ar headerfile
  1001.  .Op Fl i Ar iterations
  1002.  .Op Fl j Ar passfile
  1003.  .Op Fl J Ar newpassfile
  1004. @@ -102,6 +106,7 @@
  1005.  .Nm
  1006.  .Cm delkey
  1007.  .Op Fl afv
  1008. +.Op Fl H Ar headerfile
  1009.  .Op Fl n Ar keyno
  1010.  .Ar prov
  1011.  .Nm
  1012. @@ -125,12 +130,14 @@
  1013.  .Nm
  1014.  .Cm resume
  1015.  .Op Fl pv
  1016. +.Op Fl H Ar headerfile
  1017.  .Op Fl j Ar passfile
  1018.  .Op Fl k Ar keyfile
  1019.  .Ar prov
  1020.  .Nm
  1021.  .Cm resize
  1022.  .Op Fl v
  1023. +.Op Fl H Ar headerfile
  1024.  .Fl s Ar oldsize
  1025.  .Ar prov
  1026.  .Nm
  1027. @@ -140,6 +147,7 @@
  1028.  .Nm
  1029.  .Cm dump
  1030.  .Op Fl v
  1031. +.Op Fl H Ar headerfile
  1032.  .Ar prov ...
  1033.  .Nm
  1034.  .Cm list
  1035. @@ -240,6 +248,8 @@
  1036.  .Pp
  1037.  Additional options include:
  1038.  .Bl -tag -width ".Fl J Ar newpassfile"
  1039. +.It Fl H Ar headerfile
  1040. +Store GELI metadata (header) in the external file
  1041.  .It Fl a Ar aalgo
  1042.  Enable data integrity verification (authentication) using the given algorithm.
  1043.  This will reduce size of available storage and also reduce speed.
  1044. @@ -341,6 +351,8 @@
  1045.  option for the
  1046.  .Cm detach
  1047.  subcommand.
  1048. +.It Fl H Ar headerfile
  1049. +Read metadata from a file instead from a provider
  1050.  .It Fl j Ar passfile
  1051.  Specifies a file which contains the passphrase or its part.
  1052.  For more information see the description of the
  1053. @@ -415,7 +427,9 @@
  1054.  Change configuration of the given providers.
  1055.  .Pp
  1056.  Additional options include:
  1057. -.Bl -tag -width ".Fl b"
  1058. +.Bl -tag -width ".Fl H Ar headerfile"
  1059. +.It Fl H Ar headerfile
  1060. +Handle external metadata
  1061.  .It Fl b
  1062.  Set the BOOT flag on the given providers.
  1063.  For more information, see the description of the
  1064. @@ -437,6 +451,8 @@
  1065.  .Pp
  1066.  Additional options include:
  1067.  .Bl -tag -width ".Fl J Ar newpassfile"
  1068. +.It Fl H Ar headerfile
  1069. +Handle external metadata
  1070.  .It Fl i Ar iterations
  1071.  Number of iterations to use with PKCS#5v2.
  1072.  If 0 is given, PKCS#5v2 will not be used.
  1073. @@ -472,7 +488,9 @@
  1074.  subcommand.
  1075.  .Pp
  1076.  Additional options include:
  1077. -.Bl -tag -width ".Fl a Ar keyno"
  1078. +.Bl -tag -width ".Fl H Ar headerfile"
  1079. +.It Fl H Ar headerfile
  1080. +Handle external metadata
  1081.  .It Fl a
  1082.  Destroy all keys (does not need
  1083.  .Fl f
  1084. @@ -567,7 +585,9 @@
  1085.  utility is stored is bad idea.
  1086.  .Pp
  1087.  Additional options include:
  1088. -.Bl -tag -width ".Fl j Ar passfile"
  1089. +.Bl -tag -width ".Fl H Ar headerfile"
  1090. +.It Fl H Ar headerfile
  1091. +Handle external metadata
  1092.  .It Fl j Ar passfile
  1093.  Specifies a file which contains the passphrase or its part.
  1094.  For more information see the description of the
  1095. @@ -593,7 +613,9 @@
  1096.  provider and the provider size is updated.
  1097.  .Pp
  1098.  Additional options include:
  1099. -.Bl -tag -width ".Fl s Ar oldsize"
  1100. +.Bl -tag -width ".Fl H Ar headerfile"
  1101. +.It Fl H Ar headerfile
  1102. +Handle external metadata
  1103.  .It Fl s Ar oldsize
  1104.  The size of the provider before it was resized.
  1105.  .El
  1106. @@ -764,6 +786,9 @@
  1107.  # dd if=/dev/random of=/dev/da1s3a bs=1m
  1108.  # dd if=/dev/random of=/boot/keys/da1s3a.key bs=128k count=1
  1109.  # geli init -b -P -K /boot/keys/da1s3a.key da1s3a
  1110. +# dd if=/dev/random of=/dev/ada1 bs=1m
  1111. +# dd if=/dev/random of=/boot/keys/ada1.key bs=8 count=8
  1112. +# geli init -b -H /boot/hd/ada1.hd -P -K /boot/keys/ada1.key ada1
  1113.  .Ed
  1114.  .Pp
  1115.  The providers are initialized, now we have to add those lines to
  1116. @@ -782,6 +807,13 @@
  1117.  geli_da1s3a_keyfile0_load="YES"
  1118.  geli_da1s3a_keyfile0_type="da1s3a:geli_keyfile0"
  1119.  geli_da1s3a_keyfile0_name="/boot/keys/da1s3a.key"
  1120. +
  1121. +geli_ada1_header_load="YES"
  1122. +geli_ada1_header_type="ada1:geli_header"
  1123. +geli_ada1_header_name="/boot/hd/ada1.hd"
  1124. +geli_ada1_keyfile0_load="YES"
  1125. +geli_ada1_keyfile0_type="ada1:geli_keyfile0"
  1126. +geli_ada1_keyfile0_name="/boot/keys/ada1.key"
  1127.  .Ed
  1128.  .Pp
  1129.  Not only configure encryption, but also data integrity verification using
  1130. --- sys/geom/eli/g_eli.c.orig   2013-05-31 01:23:18.992933645 +0300
  1131. +++ sys/geom/eli/g_eli.c    2013-05-31 01:55:28.009101681 +0300
  1132. @@ -1013,6 +1013,47 @@
  1133.     }
  1134.  }
  1135.  
  1136. +static int
  1137. +g_eli_header_load(struct g_eli_metadata *md, const char *provider)
  1138. +{
  1139. +   unsigned char *headfile, *data;
  1140. +   char *file, name[64];
  1141. +   size_t size;
  1142. +
  1143. +   snprintf(name, sizeof(name), "%s:geli_header", provider);
  1144. +   headfile = preload_search_by_type(name);
  1145. +   if (headfile == NULL)
  1146. +       return (1);
  1147. +
  1148. +   data = preload_fetch_addr(headfile);
  1149. +   if (data == NULL) {
  1150. +       G_ELI_DEBUG(0, "Cannot find header file data for %s.",
  1151. +               name);
  1152. +       return (1);
  1153. +   }
  1154. +
  1155. +   size = preload_fetch_size(headfile);
  1156. +   if (size == 0) {
  1157. +       G_ELI_DEBUG(0, "Cannot find header file size for %s.",
  1158. +               name);
  1159. +       return (1);
  1160. +   }
  1161. +
  1162. +   file = preload_search_info(headfile, MODINFO_NAME);
  1163. +   if (file == NULL) {
  1164. +       G_ELI_DEBUG(0, "Cannot find header file name for %s.",
  1165. +               name);
  1166. +       return (1);
  1167. +   }
  1168. +
  1169. +   G_ELI_DEBUG(1, "Loaded header %s for %s (type: %s).", file,
  1170. +           provider, name);
  1171. +
  1172. +   eli_metadata_decode(data, md);
  1173. +
  1174. +   return (0);
  1175. +}
  1176. +
  1177.  /*
  1178.   * Tasting is only made on boot.
  1179.   * We detect providers which should be attached before root is mounted.
  1180. @@ -1036,9 +1077,11 @@
  1181.  
  1182.     G_ELI_DEBUG(3, "Tasting %s.", pp->name);
  1183.  
  1184. -   error = g_eli_read_metadata(mp, pp, &md);
  1185. -   if (error != 0)
  1186. -       return (NULL);
  1187. +   if(g_eli_header_load(&md, pp->name) != 0) {
  1188. +       error = g_eli_read_metadata(mp, pp, &md);
  1189. +       if (error != 0)
  1190. +           return (NULL);
  1191. +   }
  1192.     gp = NULL;
  1193.  
  1194.     if (strcmp(md.md_magic, G_ELI_MAGIC) != 0)
  1195. --- sys/geom/eli/g_eli_ctl.c.orig   2013-05-31 01:23:25.741791390 +0300
  1196. +++ sys/geom/eli/g_eli_ctl.c    2013-05-31 20:23:43.382321683 +0300
  1197. @@ -56,7 +56,8 @@
  1198.     struct g_eli_metadata md;
  1199.     struct g_provider *pp;
  1200.     const char *name;
  1201. -   u_char *key, mkey[G_ELI_DATAIVKEYLEN];
  1202. +   u_char *key, *hd, mkey[G_ELI_DATAIVKEYLEN];
  1203. +   size_t hdsize;
  1204.     int *nargs, *detach, *readonly;
  1205.     int keysize, error;
  1206.     u_int nkey;
  1207. @@ -97,12 +98,19 @@
  1208.         gctl_error(req, "Provider %s is invalid.", name);
  1209.         return;
  1210.     }
  1211. -   error = g_eli_read_metadata(mp, pp, &md);
  1212. -   if (error != 0) {
  1213. -       gctl_error(req, "Cannot read metadata from %s (error=%d).",
  1214. -           name, error);
  1215. -       return;
  1216. +
  1217. +   hd = gctl_get_param(req, "hd", &hdsize);
  1218. +   if (hd == NULL) {
  1219. +       error = g_eli_read_metadata(mp, pp, &md);
  1220. +       if (error != 0) {
  1221. +           gctl_error(req, "Cannot read metadata from %s (error=%d).",
  1222. +               name, error);
  1223. +           return;
  1224. +       }
  1225. +   } else {
  1226. +       eli_metadata_decode(hd, &md);
  1227.     }
  1228. +
  1229.     if (md.md_keys == 0x00) {
  1230.         bzero(&md, sizeof(md));
  1231.         gctl_error(req, "No valid keys on %s.", pp->name);
  1232. @@ -376,7 +384,8 @@
  1233.     struct g_consumer *cp;
  1234.     char param[16];
  1235.     const char *prov;
  1236. -   u_char *sector;
  1237. +   u_char *sector, *hd;
  1238. +   size_t hdsize;
  1239.     int *nargs, *boot, *noboot;
  1240.     int error;
  1241.     u_int i;
  1242. @@ -393,6 +402,12 @@
  1243.         return;
  1244.     }
  1245.  
  1246. +   hd = gctl_get_param(req, "hd", &hdsize);
  1247. +   if ((hd != NULL) && (*nargs != 1)) {
  1248. +       gctl_error(req, "Too much device(s).");
  1249. +       return;
  1250. +   }
  1251. +
  1252.     boot = gctl_get_paraml(req, "boot", sizeof(*boot));
  1253.     if (boot == NULL) {
  1254.         gctl_error(req, "No '%s' argument.", "boot");
  1255. @@ -413,6 +428,7 @@
  1256.     }
  1257.  
  1258.     for (i = 0; i < *nargs; i++) {
  1259. +       sector = NULL;
  1260.         snprintf(param, sizeof(param), "arg%d", i);
  1261.         prov = gctl_get_asciiparam(req, param);
  1262.         if (prov == NULL) {
  1263. @@ -443,14 +459,18 @@
  1264.                 "read-only provider %s.", prov);
  1265.             continue;
  1266.         }
  1267. -       cp = LIST_FIRST(&sc->sc_geom->consumer);
  1268. -       pp = cp->provider;
  1269. -       error = g_eli_read_metadata(mp, pp, &md);
  1270. -       if (error != 0) {
  1271. -           gctl_error(req,
  1272. -               "Cannot read metadata from %s (error=%d).",
  1273. -               prov, error);
  1274. -           continue;
  1275. +       if (hd == NULL) {
  1276. +           cp = LIST_FIRST(&sc->sc_geom->consumer);
  1277. +           pp = cp->provider;
  1278. +           error = g_eli_read_metadata(mp, pp, &md);
  1279. +           if (error != 0) {
  1280. +               gctl_error(req,
  1281. +                   "Cannot read metadata from %s (error=%d).",
  1282. +                   prov, error);
  1283. +               continue;
  1284. +           }
  1285. +       } else {
  1286. +           eli_metadata_decode(hd, &md);
  1287.         }
  1288.  
  1289.         if (*boot) {
  1290. @@ -461,18 +481,26 @@
  1291.             sc->sc_flags &= ~G_ELI_FLAG_BOOT;
  1292.         }
  1293.  
  1294. -       sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO);
  1295. -       eli_metadata_encode(&md, sector);
  1296. -       error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector,
  1297. -           pp->sectorsize);
  1298. -       if (error != 0) {
  1299. -           gctl_error(req,
  1300. -               "Cannot store metadata on %s (error=%d).",
  1301. -               prov, error);
  1302. +       if (hd == NULL) {
  1303. +           sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO);
  1304. +           eli_metadata_encode(&md, sector);
  1305. +           error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector,
  1306. +               pp->sectorsize);
  1307. +           if (error != 0) {
  1308. +               gctl_error(req,
  1309. +                   "Cannot store metadata on %s (error=%d).",
  1310. +                   prov, error);
  1311. +           }
  1312. +       } else {
  1313. +           eli_metadata_encode(&md, hd);
  1314. +           gctl_set_param(req, "hd", hd, hdsize);
  1315.         }
  1316. +
  1317.         bzero(&md, sizeof(md));
  1318. -       bzero(sector, sizeof(sector));
  1319. -       free(sector, M_ELI);
  1320. +       if (sector != NULL) {
  1321. +           bzero(sector, sizeof(sector));
  1322. +           free(sector, M_ELI);
  1323. +       }
  1324.     }
  1325.  }
  1326.  
  1327. @@ -485,6 +513,8 @@
  1328.     struct g_consumer *cp;
  1329.     const char *name;
  1330.     u_char *key, *mkeydst, *sector;
  1331. +   unsigned char *hd;
  1332. +   size_t hdsize;
  1333.     intmax_t *valp;
  1334.     int keysize, nkey, error;
  1335.  
  1336. @@ -507,11 +537,16 @@
  1337.     cp = LIST_FIRST(&sc->sc_geom->consumer);
  1338.     pp = cp->provider;
  1339.  
  1340. -   error = g_eli_read_metadata(mp, pp, &md);
  1341. -   if (error != 0) {
  1342. -       gctl_error(req, "Cannot read metadata from %s (error=%d).",
  1343. -           name, error);
  1344. -       return;
  1345. +   hd = gctl_get_param(req, "hd", &hdsize);
  1346. +   if (hd == NULL) {
  1347. +       error = g_eli_read_metadata(mp, pp, &md);
  1348. +       if (error != 0) {
  1349. +           gctl_error(req, "Cannot read metadata from %s (error=%d).",
  1350. +               name, error);
  1351. +           return;
  1352. +       }
  1353. +   } else {
  1354. +       eli_metadata_decode(hd, &md);
  1355.     }
  1356.  
  1357.     valp = gctl_get_paraml(req, "keyno", sizeof(*valp));
  1358. @@ -569,19 +604,28 @@
  1359.         return;
  1360.     }
  1361.  
  1362. -   sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO);
  1363.     /* Store metadata with fresh key. */
  1364. -   eli_metadata_encode(&md, sector);
  1365. -   bzero(&md, sizeof(md));
  1366. -   error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector,
  1367. -       pp->sectorsize);
  1368. -   bzero(sector, sizeof(sector));
  1369. -   free(sector, M_ELI);
  1370. -   if (error != 0) {
  1371. -       gctl_error(req, "Cannot store metadata on %s (error=%d).",
  1372. -           pp->name, error);
  1373. -       return;
  1374. +   if (hd == NULL) {
  1375. +       sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO);
  1376. +       eli_metadata_encode(&md, sector);
  1377. +       bzero(&md, sizeof(md));
  1378. +
  1379. +       error = g_write_data(cp, pp->mediasize - pp->sectorsize, sector,
  1380. +           pp->sectorsize);
  1381. +
  1382. +       bzero(sector, sizeof(sector));
  1383. +       free(sector, M_ELI);
  1384. +
  1385. +       if (error != 0) {
  1386. +           gctl_error(req, "Cannot store metadata on %s (error=%d).",
  1387. +               pp->name, error);
  1388. +           return;
  1389. +       }
  1390. +   } else {
  1391. +       eli_metadata_encode(&md, hd);
  1392. +       gctl_set_param(req, "hd", hd, hdsize);
  1393.     }
  1394. +
  1395.     G_ELI_DEBUG(1, "Key %u changed on %s.", nkey, pp->name);
  1396.  }
  1397.  
  1398. @@ -593,7 +637,8 @@
  1399.     struct g_provider *pp;
  1400.     struct g_consumer *cp;
  1401.     const char *name;
  1402. -   u_char *mkeydst, *sector;
  1403. +   u_char *mkeydst, *sector, *hd;
  1404. +   size_t hdsize;
  1405.     intmax_t *valp;
  1406.     size_t keysize;
  1407.     int error, nkey, *all, *force;
  1408. @@ -620,11 +665,16 @@
  1409.     cp = LIST_FIRST(&sc->sc_geom->consumer);
  1410.     pp = cp->provider;
  1411.  
  1412. -   error = g_eli_read_metadata(mp, pp, &md);
  1413. -   if (error != 0) {
  1414. -       gctl_error(req, "Cannot read metadata from %s (error=%d).",
  1415. -           name, error);
  1416. -       return;
  1417. +   hd = gctl_get_param(req, "hd", &hdsize);
  1418. +   if (hd == NULL) {
  1419. +       error = g_eli_read_metadata(mp, pp, &md);
  1420. +       if (error != 0) {
  1421. +           gctl_error(req, "Cannot read metadata from %s (error=%d).",
  1422. +               name, error);
  1423. +           return;
  1424. +       }
  1425. +   } else {
  1426. +       eli_metadata_decode(hd, &md);
  1427.     }
  1428.  
  1429.     all = gctl_get_paraml(req, "all", sizeof(*all));
  1430. @@ -670,6 +720,13 @@
  1431.         keysize = G_ELI_MKEYLEN;
  1432.     }
  1433.  
  1434. +   if (hd != NULL) {
  1435. +       bzero(mkeydst, keysize);
  1436. +       eli_metadata_encode(&md, hd);
  1437. +       gctl_set_param(req, "hd", hd, hdsize);
  1438. +       goto out;
  1439. +   }
  1440. +
  1441.     sector = malloc(pp->sectorsize, M_ELI, M_WAITOK | M_ZERO);
  1442.     for (i = 0; i <= g_eli_overwrites; i++) {
  1443.         if (i == g_eli_overwrites)
  1444. @@ -690,9 +747,11 @@
  1445.          */
  1446.         (void)g_io_flush(cp);
  1447.     }
  1448. -   bzero(&md, sizeof(md));
  1449.     bzero(sector, sizeof(sector));
  1450.     free(sector, M_ELI);
  1451. +
  1452. +out:
  1453. +   bzero(&md, sizeof(md));
  1454.     if (*all)
  1455.         G_ELI_DEBUG(1, "All keys removed from %s.", pp->name);
  1456.     else
  1457. @@ -816,6 +875,8 @@
  1458.     struct g_consumer *cp;
  1459.     const char *name;
  1460.     u_char *key, mkey[G_ELI_DATAIVKEYLEN];
  1461. +   unsigned char *hd;
  1462. +   size_t hdsize;
  1463.     int *nargs, keysize, error;
  1464.     u_int nkey;
  1465.  
  1466. @@ -843,11 +904,17 @@
  1467.     }
  1468.     cp = LIST_FIRST(&sc->sc_geom->consumer);
  1469.     pp = cp->provider;
  1470. -   error = g_eli_read_metadata(mp, pp, &md);
  1471. -   if (error != 0) {
  1472. -       gctl_error(req, "Cannot read metadata from %s (error=%d).",
  1473. -           name, error);
  1474. -       return;
  1475. +
  1476. +   hd = gctl_get_param(req, "hd", &hdsize);
  1477. +   if (hd == NULL) {
  1478. +       error = g_eli_read_metadata(mp, pp, &md);
  1479. +       if (error != 0) {
  1480. +           gctl_error(req, "Cannot read metadata from %s (error=%d).",
  1481. +               name, error);
  1482. +           return;
  1483. +       }
  1484. +   } else {
  1485. +       eli_metadata_decode(hd, &md);
  1486.     }
  1487.     if (md.md_keys == 0x00) {
  1488.         bzero(&md, sizeof(md));
  1489. @@ -889,6 +956,7 @@
  1490.     mtx_unlock(&sc->sc_queue_mtx);
  1491.     bzero(mkey, sizeof(mkey));
  1492.     bzero(&md, sizeof(md));
  1493. +   G_ELI_DEBUG(0, "Device %s has been resumed.", sc->sc_name);
  1494.  }
  1495.  
  1496.  static int
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement