- Add support for loading passphrase from a file (-J and -j options).

This is especially useful for things like installers, where regular
  geli prompt can't be used.
- Add support for specifing multiple -K or -k options, so there is no
  need to cat all keyfiles and read them from standard input.

Requested by:	Kris Moore <kris@pcbsd.org>, thompsa
MFC after:	2 weeks
This commit is contained in:
Pawel Jakub Dawidek 2010-09-25 17:38:57 +00:00
parent 5c181adf40
commit 1cf3d5ee99
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=213172
2 changed files with 268 additions and 133 deletions

View File

@ -24,7 +24,7 @@
.\" .\"
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd September 23, 2010 .Dd September 25, 2010
.Dt GELI 8 .Dt GELI 8
.Os .Os
.Sh NAME .Sh NAME
@ -56,6 +56,7 @@ utility:
.Op Fl B Ar backupfile .Op Fl B Ar backupfile
.Op Fl e Ar ealgo .Op Fl e Ar ealgo
.Op Fl i Ar iterations .Op Fl i Ar iterations
.Op Fl J Ar newpassfile
.Op Fl K Ar newkeyfile .Op Fl K Ar newkeyfile
.Op Fl l Ar keylen .Op Fl l Ar keylen
.Op Fl s Ar sectorsize .Op Fl s Ar sectorsize
@ -66,6 +67,7 @@ utility:
.Nm .Nm
.Cm attach .Cm attach
.Op Fl dprv .Op Fl dprv
.Op Fl j Ar passfile
.Op Fl k Ar keyfile .Op Fl k Ar keyfile
.Ar prov .Ar prov
.Nm .Nm
@ -91,6 +93,8 @@ utility:
.Cm setkey .Cm setkey
.Op Fl pPv .Op Fl pPv
.Op Fl i Ar iterations .Op Fl i Ar iterations
.Op Fl j Ar passfile
.Op Fl J Ar newpassfile
.Op Fl k Ar keyfile .Op Fl k Ar keyfile
.Op Fl K Ar newkeyfile .Op Fl K Ar newkeyfile
.Op Fl n Ar keyno .Op Fl n Ar keyno
@ -223,7 +227,7 @@ The metadata can be recovered with the
subcommand described below. subcommand described below.
.Pp .Pp
Additional options include: Additional options include:
.Bl -tag -width ".Fl a Ar newkeyfile" .Bl -tag -width ".Fl J Ar newpassfile"
.It Fl a Ar aalgo .It Fl a Ar aalgo
Enable data integrity verification (authentication) using the given algorithm. Enable data integrity verification (authentication) using the given algorithm.
This will reduce size of available storage and also reduce speed. This will reduce size of available storage and also reduce speed.
@ -272,15 +276,19 @@ If this option is not specified,
.Nm .Nm
will find the number of iterations which is equal to 2 seconds of crypto work. will find the number of iterations which is equal to 2 seconds of crypto work.
If 0 is given, PKCS#5v2 will not be used. If 0 is given, PKCS#5v2 will not be used.
.It Fl J Ar newpassfile
Specifies a file which contains the passphrase or its part.
If
.Ar newpassfile
is given as -, standard input will be used.
Only the first line (excluding new-line character) is taken from the given file.
This argument can be specified multiple times.
.It Fl K Ar newkeyfile .It Fl K Ar newkeyfile
Specifies a file which contains part of the key. Specifies a file which contains part of the key.
If If
.Ar newkeyfile .Ar newkeyfile
is given as -, standard input will be used. is given as -, standard input will be used.
Here is how more than one file with a key component can be used: This argument can be specified multiple times.
.Bd -literal -offset indent
# cat key1 key2 key3 | geli init -K - /dev/da0
.Ed
.It Fl l Ar keylen .It Fl l Ar keylen
Key length to use with the given cryptographic algorithm. Key length to use with the given cryptographic algorithm.
If not given, the default key length for the given algorithm is used, which is: If not given, the default key length for the given algorithm is used, which is:
@ -309,7 +317,7 @@ provider's name with an
suffix. suffix.
.Pp .Pp
Additional options include: Additional options include:
.Bl -tag -width ".Fl a Ar keyfile" .Bl -tag -width ".Fl j Ar passfile"
.It Fl d .It Fl d
If specified, a decrypted provider will be detached automatically on last close. If specified, a decrypted provider will be detached automatically on last close.
This can help with short memory - user does not have to remember to detach the This can help with short memory - user does not have to remember to detach the
@ -321,6 +329,13 @@ Probably a better choice is the
option for the option for the
.Cm detach .Cm detach
subcommand. subcommand.
.It Fl j Ar passfile
Specifies a file which contains the passphrase or its part.
For more information see the description of the
.Fl J
option for the
.Cm init
subcommand.
.It Fl k Ar keyfile .It Fl k Ar keyfile
Specifies a file which contains part of the key. Specifies a file which contains part of the key.
For more information see the description of the For more information see the description of the
@ -409,13 +424,17 @@ When a provider is attached, the user does not have to provide
an old passphrase/keyfile. an old passphrase/keyfile.
.Pp .Pp
Additional options include: Additional options include:
.Bl -tag -width ".Fl a Ar iterations" .Bl -tag -width ".Fl J Ar newpassfile"
.It Fl i Ar iterations .It Fl i Ar iterations
Number of iterations to use with PKCS#5v2. Number of iterations to use with PKCS#5v2.
If 0 is given, PKCS#5v2 will not be used. If 0 is given, PKCS#5v2 will not be used.
To be able to use this option with To be able to use this option with
.Cm setkey .Cm setkey
subcommand, only one key have to be defined and this key has to be changed. subcommand, only one key have to be defined and this key has to be changed.
.It Fl j Ar passfile
Specifies a file which contains the old passphrase or its part.
.It Fl J Ar newpassfile
Specifies a file which contains the new passphrase or its part.
.It Fl k Ar keyfile .It Fl k Ar keyfile
Specifies a file which contains part of the old key. Specifies a file which contains part of the old key.
.It Fl K Ar newkeyfile .It Fl K Ar newkeyfile
@ -638,7 +657,7 @@ keyfile:
# dd if=/dev/random of=/boot/keys/da0.key0 bs=32k count=1 # dd if=/dev/random of=/boot/keys/da0.key0 bs=32k count=1
# dd if=/dev/random of=/boot/keys/da0.key1 bs=32k count=1 # dd if=/dev/random of=/boot/keys/da0.key1 bs=32k count=1
# dd if=/dev/random of=/boot/keys/da0.key2 bs=32k count=1 # dd if=/dev/random of=/boot/keys/da0.key2 bs=32k count=1
# cat /boot/keys/da0.key0 /boot/keys/da0.key1 /boot/keys/da0.key2 | geli init -b -K - da0 # geli init -b -K /boot/keys/da0.key0 -K /boot/keys/da0.key1 -K /boot/keys/da0.key2 da0
Enter new passphrase: Enter new passphrase:
Reenter new passphrase: Reenter new passphrase:
# dd if=/dev/random of=/dev/da1s3a bs=1m # dd if=/dev/random of=/dev/da1s3a bs=1m
@ -711,6 +730,22 @@ update the metadata:
# geli resize -s 1g ada0p1 # geli resize -s 1g ada0p1
# geli attach -k keyfile -p ada0p1 # geli attach -k keyfile -p ada0p1
.Ed .Ed
.Pp
Initialize provider with passphrase split into two files.
The provider can be attached by giving those two files or by giving
.Dq foobar
passphrase on
.Nm
prompt:
.Bd -literal -offset indent
# echo foo > da0.pass0
# echo bar > da0.pass1
# geli init -J da0.pass0 -J da0.pass1 da0
# geli attach -j da0.pass0 -j da0.pass1 da0
# geli detach da0
# geli attach da0
Enter passphrase: foobar
.Ed
.Sh ENCRYPTION MODES .Sh ENCRYPTION MODES
.Nm .Nm
supports two encryption modes: supports two encryption modes:

View File

@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h> #include <sys/types.h>
#include <sys/sysctl.h> #include <sys/sysctl.h>
#include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
@ -79,14 +80,14 @@ static int eli_backup_create(struct gctl_req *req, const char *prov,
/* /*
* Available commands: * Available commands:
* *
* init [-bhPv] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-K newkeyfile] prov * init [-bhPv] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] prov
* label - alias for 'init' * label - alias for 'init'
* attach [-dprv] [-k keyfile] prov * attach [-dprv] [-j passfile] [-k keyfile] prov
* detach [-fl] prov ... * detach [-fl] prov ...
* stop - alias for 'detach' * stop - alias for 'detach'
* onetime [-d] [-a aalgo] [-e ealgo] [-l keylen] prov * onetime [-d] [-a aalgo] [-e ealgo] [-l keylen] prov
* configure [-bB] prov ... * configure [-bB] prov ...
* setkey [-pPv] [-n keyno] [-k keyfile] [-K newkeyfile] prov * setkey [-pPv] [-n keyno] [-j passfile] [-J newpassfile] [-k keyfile] [-K newkeyfile] prov
* delkey [-afv] [-n keyno] prov * delkey [-afv] [-n keyno] prov
* kill [-av] [prov ...] * kill [-av] [prov ...]
* backup [-v] prov file * backup [-v] prov file
@ -103,13 +104,14 @@ struct g_command class_commands[] = {
{ 'B', "backupfile", "", G_TYPE_STRING }, { 'B', "backupfile", "", G_TYPE_STRING },
{ 'e', "ealgo", GELI_ENC_ALGO, G_TYPE_STRING }, { 'e', "ealgo", GELI_ENC_ALGO, G_TYPE_STRING },
{ 'i', "iterations", "-1", G_TYPE_NUMBER }, { 'i', "iterations", "-1", G_TYPE_NUMBER },
{ 'K', "newkeyfile", "", G_TYPE_STRING }, { 'J', "newpassfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI },
{ 'K', "newkeyfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI },
{ 'l', "keylen", "0", G_TYPE_NUMBER }, { 'l', "keylen", "0", G_TYPE_NUMBER },
{ 'P', "nonewpassphrase", NULL, G_TYPE_BOOL }, { 'P', "nonewpassphrase", NULL, G_TYPE_BOOL },
{ 's', "sectorsize", "0", G_TYPE_NUMBER }, { 's', "sectorsize", "0", G_TYPE_NUMBER },
G_OPT_SENTINEL G_OPT_SENTINEL
}, },
"[-bPv] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-K newkeyfile] [-s sectorsize] prov" "[-bPv] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] [-s sectorsize] prov"
}, },
{ "label", G_FLAG_VERBOSE, eli_main, { "label", G_FLAG_VERBOSE, eli_main,
{ {
@ -118,7 +120,8 @@ struct g_command class_commands[] = {
{ 'B', "backupfile", "", G_TYPE_STRING }, { 'B', "backupfile", "", G_TYPE_STRING },
{ 'e', "ealgo", GELI_ENC_ALGO, G_TYPE_STRING }, { 'e', "ealgo", GELI_ENC_ALGO, G_TYPE_STRING },
{ 'i', "iterations", "-1", G_TYPE_NUMBER }, { 'i', "iterations", "-1", G_TYPE_NUMBER },
{ 'K', "newkeyfile", "", G_TYPE_STRING }, { 'J', "newpassfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI },
{ 'K', "newkeyfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI },
{ 'l', "keylen", "0", G_TYPE_NUMBER }, { 'l', "keylen", "0", G_TYPE_NUMBER },
{ 'P', "nonewpassphrase", NULL, G_TYPE_BOOL }, { 'P', "nonewpassphrase", NULL, G_TYPE_BOOL },
{ 's', "sectorsize", "0", G_TYPE_NUMBER }, { 's', "sectorsize", "0", G_TYPE_NUMBER },
@ -129,12 +132,13 @@ struct g_command class_commands[] = {
{ "attach", G_FLAG_VERBOSE | G_FLAG_LOADKLD, eli_main, { "attach", G_FLAG_VERBOSE | G_FLAG_LOADKLD, eli_main,
{ {
{ 'd', "detach", NULL, G_TYPE_BOOL }, { 'd', "detach", NULL, G_TYPE_BOOL },
{ 'k', "keyfile", "", G_TYPE_STRING }, { 'j', "passfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI },
{ 'k', "keyfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI },
{ 'p', "nopassphrase", NULL, G_TYPE_BOOL }, { 'p', "nopassphrase", NULL, G_TYPE_BOOL },
{ 'r', "readonly", NULL, G_TYPE_BOOL }, { 'r', "readonly", NULL, G_TYPE_BOOL },
G_OPT_SENTINEL G_OPT_SENTINEL
}, },
"[-dprv] [-k keyfile] prov" "[-dprv] [-j passfile] [-k keyfile] prov"
}, },
{ "detach", 0, NULL, { "detach", 0, NULL,
{ {
@ -174,14 +178,16 @@ struct g_command class_commands[] = {
{ "setkey", G_FLAG_VERBOSE, eli_main, { "setkey", G_FLAG_VERBOSE, eli_main,
{ {
{ 'i', "iterations", "-1", G_TYPE_NUMBER }, { 'i', "iterations", "-1", G_TYPE_NUMBER },
{ 'k', "keyfile", "", G_TYPE_STRING }, { 'j', "passfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI },
{ 'K', "newkeyfile", "", G_TYPE_STRING }, { 'J', "newpassfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI },
{ 'k', "keyfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI },
{ 'K', "newkeyfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI },
{ 'n', "keyno", "-1", G_TYPE_NUMBER }, { 'n', "keyno", "-1", G_TYPE_NUMBER },
{ 'p', "nopassphrase", NULL, G_TYPE_BOOL }, { 'p', "nopassphrase", NULL, G_TYPE_BOOL },
{ 'P', "nonewpassphrase", NULL, G_TYPE_BOOL }, { 'P', "nonewpassphrase", NULL, G_TYPE_BOOL },
G_OPT_SENTINEL G_OPT_SENTINEL
}, },
"[-pPv] [-n keyno] [-i iterations] [-k keyfile] [-K newkeyfile] prov" "[-pPv] [-n keyno] [-i iterations] [-j passfile] [-J newpassfile] [-k keyfile] [-K newkeyfile] prov"
}, },
{ "delkey", G_FLAG_VERBOSE, eli_main, { "delkey", G_FLAG_VERBOSE, eli_main,
{ {
@ -249,7 +255,7 @@ eli_protect(struct gctl_req *req)
} }
static void static void
eli_main(struct gctl_req *req, unsigned flags) eli_main(struct gctl_req *req, unsigned int flags)
{ {
const char *name; const char *name;
@ -295,7 +301,7 @@ arc4rand(unsigned char *buf, size_t size)
{ {
uint32_t *buf4; uint32_t *buf4;
size_t size4; size_t size4;
unsigned i; unsigned int i;
buf4 = (uint32_t *)buf; buf4 = (uint32_t *)buf;
size4 = size / 4; size4 = size / 4;
@ -324,123 +330,216 @@ eli_is_attached(const char *prov)
return (0); return (0);
} }
static int
eli_genkey_files(struct gctl_req *req, bool new, const char *type,
struct hmac_ctx *ctxp, char *passbuf, size_t passbufsize)
{
char *p, buf[MAXPHYS], argname[16];
const char *file;
int error, fd, i;
ssize_t done;
assert((strcmp(type, "keyfile") == 0 && ctxp != NULL &&
passbuf == NULL && passbufsize == 0) ||
(strcmp(type, "passfile") == 0 && ctxp == NULL &&
passbuf != NULL && passbufsize > 0));
assert(strcmp(type, "keyfile") == 0 || passbuf[0] == '\0');
for (i = 0; ; i++) {
snprintf(argname, sizeof(argname), "%s%s%d",
new ? "new" : "", type, i);
/* No more {key,pass}files? */
if (!gctl_has_param(req, argname))
return (i);
file = gctl_get_ascii(req, argname);
assert(file != NULL);
if (strcmp(file, "-") == 0)
fd = STDIN_FILENO;
else {
fd = open(file, O_RDONLY);
if (fd == -1) {
gctl_error(req, "Cannot open %s %s: %s.",
type, file, strerror(errno));
return (-1);
}
}
if (strcmp(type, "keyfile") == 0) {
while ((done = read(fd, buf, sizeof(buf))) > 0)
g_eli_crypto_hmac_update(ctxp, buf, done);
} else /* if (strcmp(type, "passfile") == 0) */ {
while ((done = read(fd, buf, sizeof(buf) - 1)) > 0) {
buf[done] = '\0';
p = strchr(buf, '\n');
if (p != NULL) {
*p = '\0';
done = p - buf;
}
if (strlcat(passbuf, buf, passbufsize) >=
passbufsize) {
gctl_error(req,
"Passphrase in %s too long.", file);
bzero(buf, sizeof(buf));
return (-1);
}
if (p != NULL)
break;
}
}
error = errno;
if (strcmp(file, "-") != 0)
close(fd);
bzero(buf, sizeof(buf));
if (done == -1) {
gctl_error(req, "Cannot read %s %s: %s.",
type, file, strerror(error));
return (-1);
}
}
/* NOTREACHED */
}
static int
eli_genkey_passphrase_prompt(struct gctl_req *req, bool new, char *passbuf,
size_t passbufsize)
{
char *p;
for (;;) {
p = readpassphrase(
new ? "Enter new passphrase:" : "Enter passphrase:",
passbuf, passbufsize, RPP_ECHO_OFF | RPP_REQUIRE_TTY);
if (p == NULL) {
bzero(passbuf, passbufsize);
gctl_error(req, "Cannot read passphrase: %s.",
strerror(errno));
return (-1);
}
if (new) {
char tmpbuf[BUFSIZ];
p = readpassphrase("Reenter new passphrase: ",
tmpbuf, sizeof(tmpbuf),
RPP_ECHO_OFF | RPP_REQUIRE_TTY);
if (p == NULL) {
bzero(passbuf, passbufsize);
gctl_error(req,
"Cannot read passphrase: %s.",
strerror(errno));
return (-1);
}
if (strcmp(passbuf, tmpbuf) != 0) {
bzero(passbuf, passbufsize);
fprintf(stderr, "They didn't match.\n");
continue;
}
bzero(tmpbuf, sizeof(tmpbuf));
}
return (0);
}
/* NOTREACHED */
}
static int
eli_genkey_passphrase(struct gctl_req *req, struct g_eli_metadata *md, bool new,
struct hmac_ctx *ctxp)
{
char passbuf[MAXPHYS];
bool nopassphrase;
int nfiles;
nopassphrase =
gctl_get_int(req, new ? "nonewpassphrase" : "nopassphrase");
if (nopassphrase) {
if (gctl_has_param(req, new ? "newpassfile0" : "passfile0")) {
gctl_error(req,
"Options -%c and -%c are mutually exclusive.",
new ? 'J' : 'j', new ? 'P' : 'p');
return (-1);
}
return (0);
}
if (!new && md->md_iterations == -1) {
gctl_error(req, "Missing -p flag.");
return (-1);
}
passbuf[0] = '\0';
nfiles = eli_genkey_files(req, new, "passfile", NULL, passbuf,
sizeof(passbuf));
if (nfiles == -1)
return (-1);
else if (nfiles == 0) {
if (eli_genkey_passphrase_prompt(req, new, passbuf,
sizeof(passbuf)) == -1) {
return (-1);
}
}
/*
* Field md_iterations equal to -1 means "choose some sane
* value for me".
*/
if (md->md_iterations == -1) {
assert(new);
if (verbose)
printf("Calculating number of iterations...\n");
md->md_iterations = pkcs5v2_calculate(2000000);
assert(md->md_iterations > 0);
if (verbose) {
printf("Done, using %d iterations.\n",
md->md_iterations);
}
}
/*
* If md_iterations is equal to 0, user doesn't want PKCS#5v2.
*/
if (md->md_iterations == 0) {
g_eli_crypto_hmac_update(ctxp, md->md_salt,
sizeof(md->md_salt));
g_eli_crypto_hmac_update(ctxp, passbuf, strlen(passbuf));
} else /* if (md->md_iterations > 0) */ {
unsigned char dkey[G_ELI_USERKEYLEN];
pkcs5v2_genkey(dkey, sizeof(dkey), md->md_salt,
sizeof(md->md_salt), passbuf, md->md_iterations);
g_eli_crypto_hmac_update(ctxp, dkey, sizeof(dkey));
bzero(dkey, sizeof(dkey));
}
bzero(passbuf, sizeof(passbuf));
return (0);
}
static unsigned char * static unsigned char *
eli_genkey(struct gctl_req *req, struct g_eli_metadata *md, unsigned char *key, eli_genkey(struct gctl_req *req, struct g_eli_metadata *md, unsigned char *key,
int new) bool new)
{ {
struct hmac_ctx ctx; struct hmac_ctx ctx;
const char *str; bool nopassphrase;
int error, nopassphrase; int nfiles;
nopassphrase = nopassphrase =
gctl_get_int(req, new ? "nonewpassphrase" : "nopassphrase"); gctl_get_int(req, new ? "nonewpassphrase" : "nopassphrase");
g_eli_crypto_hmac_init(&ctx, NULL, 0); g_eli_crypto_hmac_init(&ctx, NULL, 0);
str = gctl_get_ascii(req, new ? "newkeyfile" : "keyfile"); nfiles = eli_genkey_files(req, new, "keyfile", &ctx, NULL, 0);
if (str[0] == '\0' && nopassphrase) { if (nfiles == -1)
return (NULL);
else if (nfiles == 0 && nopassphrase) {
gctl_error(req, "No key components given."); gctl_error(req, "No key components given.");
return (NULL); return (NULL);
} else if (str[0] != '\0') {
char buf[MAXPHYS];
ssize_t done;
int fd;
if (strcmp(str, "-") == 0)
fd = STDIN_FILENO;
else {
fd = open(str, O_RDONLY);
if (fd == -1) {
gctl_error(req, "Cannot open keyfile %s: %s.",
str, strerror(errno));
return (NULL);
}
}
while ((done = read(fd, buf, sizeof(buf))) > 0)
g_eli_crypto_hmac_update(&ctx, buf, done);
error = errno;
if (strcmp(str, "-") != 0)
close(fd);
bzero(buf, sizeof(buf));
if (done == -1) {
gctl_error(req, "Cannot read keyfile %s: %s.", str,
strerror(error));
return (NULL);
}
} }
if (!nopassphrase) { if (eli_genkey_passphrase(req, md, new, &ctx) == -1)
char buf1[BUFSIZ], buf2[BUFSIZ], *p; return (NULL);
if (!new && md->md_iterations == -1) {
gctl_error(req, "Missing -p flag.");
return (NULL);
}
for (;;) {
p = readpassphrase(
new ? "Enter new passphrase:" : "Enter passphrase:",
buf1, sizeof(buf1), RPP_ECHO_OFF | RPP_REQUIRE_TTY);
if (p == NULL) {
bzero(buf1, sizeof(buf1));
gctl_error(req, "Cannot read passphrase: %s.",
strerror(errno));
return (NULL);
}
if (new) {
p = readpassphrase("Reenter new passphrase: ",
buf2, sizeof(buf2),
RPP_ECHO_OFF | RPP_REQUIRE_TTY);
if (p == NULL) {
bzero(buf1, sizeof(buf1));
gctl_error(req,
"Cannot read passphrase: %s.",
strerror(errno));
return (NULL);
}
if (strcmp(buf1, buf2) != 0) {
bzero(buf2, sizeof(buf2));
fprintf(stderr, "They didn't match.\n");
continue;
}
bzero(buf2, sizeof(buf2));
}
break;
}
/*
* Field md_iterations equal to -1 means "choose some sane
* value for me".
*/
if (md->md_iterations == -1) {
assert(new);
if (verbose)
printf("Calculating number of iterations...\n");
md->md_iterations = pkcs5v2_calculate(2000000);
assert(md->md_iterations > 0);
if (verbose) {
printf("Done, using %d iterations.\n",
md->md_iterations);
}
}
/*
* If md_iterations is equal to 0, user don't want PKCS#5v2.
*/
if (md->md_iterations == 0) {
g_eli_crypto_hmac_update(&ctx, md->md_salt,
sizeof(md->md_salt));
g_eli_crypto_hmac_update(&ctx, buf1, strlen(buf1));
} else /* if (md->md_iterations > 0) */ {
unsigned char dkey[G_ELI_USERKEYLEN];
pkcs5v2_genkey(dkey, sizeof(dkey), md->md_salt,
sizeof(md->md_salt), buf1, md->md_iterations);
g_eli_crypto_hmac_update(&ctx, dkey, sizeof(dkey));
bzero(dkey, sizeof(dkey));
}
bzero(buf1, sizeof(buf1));
}
g_eli_crypto_hmac_final(&ctx, key, 0); g_eli_crypto_hmac_final(&ctx, key, 0);
return (key); return (key);
} }
@ -640,7 +739,7 @@ eli_init(struct gctl_req *req)
arc4rand(md.md_mkeys, sizeof(md.md_mkeys)); arc4rand(md.md_mkeys, sizeof(md.md_mkeys));
/* Generate user key. */ /* Generate user key. */
if (eli_genkey(req, &md, key, 1) == NULL) { if (eli_genkey(req, &md, key, true) == NULL) {
bzero(key, sizeof(key)); bzero(key, sizeof(key));
bzero(&md, sizeof(md)); bzero(&md, sizeof(md));
return; return;
@ -720,7 +819,7 @@ eli_attach(struct gctl_req *req)
return; return;
} }
if (eli_genkey(req, &md, key, 0) == NULL) { if (eli_genkey(req, &md, key, false) == NULL) {
bzero(key, sizeof(key)); bzero(key, sizeof(key));
return; return;
} }
@ -734,7 +833,7 @@ eli_attach(struct gctl_req *req)
} }
static void static void
eli_configure_detached(struct gctl_req *req, const char *prov, int boot) eli_configure_detached(struct gctl_req *req, const char *prov, bool boot)
{ {
struct g_eli_metadata md; struct g_eli_metadata md;
@ -761,7 +860,8 @@ static void
eli_configure(struct gctl_req *req) eli_configure(struct gctl_req *req)
{ {
const char *prov; const char *prov;
int i, nargs, boot, noboot; bool boot, noboot;
int i, nargs;
nargs = gctl_get_int(req, "nargs"); nargs = gctl_get_int(req, "nargs");
if (nargs == 0) { if (nargs == 0) {
@ -806,7 +906,7 @@ eli_setkey_attached(struct gctl_req *req, struct g_eli_metadata *md)
old = md->md_iterations; old = md->md_iterations;
/* Generate key for Master Key encryption. */ /* Generate key for Master Key encryption. */
if (eli_genkey(req, md, key, 1) == NULL) { if (eli_genkey(req, md, key, true) == NULL) {
bzero(key, sizeof(key)); bzero(key, sizeof(key));
return; return;
} }
@ -831,8 +931,8 @@ eli_setkey_detached(struct gctl_req *req, const char *prov,
{ {
unsigned char key[G_ELI_USERKEYLEN], mkey[G_ELI_DATAIVKEYLEN]; unsigned char key[G_ELI_USERKEYLEN], mkey[G_ELI_DATAIVKEYLEN];
unsigned char *mkeydst; unsigned char *mkeydst;
unsigned int nkey;
intmax_t val; intmax_t val;
unsigned nkey;
int error; int error;
if (md->md_keys == 0) { if (md->md_keys == 0) {
@ -841,7 +941,7 @@ eli_setkey_detached(struct gctl_req *req, const char *prov,
} }
/* Generate key for Master Key decryption. */ /* Generate key for Master Key decryption. */
if (eli_genkey(req, md, key, 0) == NULL) { if (eli_genkey(req, md, key, false) == NULL) {
bzero(key, sizeof(key)); bzero(key, sizeof(key));
return; return;
} }
@ -897,7 +997,7 @@ eli_setkey_detached(struct gctl_req *req, const char *prov,
bzero(mkey, sizeof(mkey)); bzero(mkey, sizeof(mkey));
/* Generate key for Master Key encryption. */ /* Generate key for Master Key encryption. */
if (eli_genkey(req, md, key, 1) == NULL) { if (eli_genkey(req, md, key, true) == NULL) {
bzero(key, sizeof(key)); bzero(key, sizeof(key));
bzero(md, sizeof(*md)); bzero(md, sizeof(*md));
return; return;
@ -959,9 +1059,9 @@ eli_delkey_detached(struct gctl_req *req, const char *prov)
{ {
struct g_eli_metadata md; struct g_eli_metadata md;
unsigned char *mkeydst; unsigned char *mkeydst;
unsigned int nkey;
intmax_t val; intmax_t val;
unsigned nkey; bool all, force;
int all, force;
if (eli_metadata_read(req, prov, &md) == -1) if (eli_metadata_read(req, prov, &md) == -1)
return; return;