Introduce the 'n' flag for the geli attach command.

If the 'n' flag is provided the provided key number will be used to
decrypt device. This can be used combined with dryrun to verify if the key
is set correctly. This can be also used to determine which key slot we want to
change on already attached device.

Reviewed by:	allanjude
Differential Revision:	https://reviews.freebsd.org/D15309
This commit is contained in:
Mariusz Zaborski
2018-05-09 20:53:38 +00:00
parent c2ac0fc5e0
commit 31f7586d73
7 changed files with 85 additions and 39 deletions
+4
View File
@@ -68,6 +68,7 @@ utility:
.Nm
.Cm attach
.Op Fl Cdprv
.Op Fl n Ar keyno
.Op Fl j Ar passfile
.Op Fl k Ar keyfile
.Ar prov
@@ -407,6 +408,9 @@ Probably a better choice is the
option for the
.Cm detach
subcommand.
.It Fl n Ar keyno
Specifies the index number of the Master Key copy to use (could be 0 or 1).
If the index number is not provided all keys will be tested.
.It Fl j Ar passfile
Specifies a file which contains the passphrase component of the User Key
(or part of it).
+4 -3
View File
@@ -86,7 +86,7 @@ static int eli_backup_create(struct gctl_req *req, const char *prov,
*
* init [-bdgPTv] [-a aalgo] [-B backupfile] [-e ealgo] [-i iterations] [-l keylen] [-J newpassfile] [-K newkeyfile] [-s sectorsize] [-V version] prov
* label - alias for 'init'
* attach [-Cdprv] [-j passfile] [-k keyfile] prov
* attach [-Cdprv] [-n keyno] [-j passfile] [-k keyfile] prov
* detach [-fl] prov ...
* stop - alias for 'detach'
* onetime [-d] [-a aalgo] [-e ealgo] [-l keylen] prov
@@ -149,11 +149,12 @@ struct g_command class_commands[] = {
{ 'd', "detach", NULL, G_TYPE_BOOL },
{ 'j', "passfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI },
{ 'k', "keyfile", G_VAL_OPTIONAL, G_TYPE_STRING | G_TYPE_MULTI },
{ 'n', "keyno", "-1", G_TYPE_NUMBER },
{ 'p', "nopassphrase", NULL, G_TYPE_BOOL },
{ 'r', "readonly", NULL, G_TYPE_BOOL },
G_OPT_SENTINEL
},
"[-Cdprv] [-j passfile] [-k keyfile] prov"
"[-Cdprv] [-n keyno] [-j passfile] [-k keyfile] prov"
},
{ "detach", 0, NULL,
{
@@ -1129,7 +1130,7 @@ eli_setkey_detached(struct gctl_req *req, const char *prov,
}
/* Decrypt Master Key. */
error = g_eli_mkey_decrypt(md, key, mkey, &nkey);
error = g_eli_mkey_decrypt_any(md, key, mkey, &nkey);
bzero(key, sizeof(key));
if (error != 0) {
bzero(md, sizeof(*md));
+3 -3
View File
@@ -121,14 +121,14 @@ geli_findkey(struct geli_entry *ge, struct dsk *dskp, u_char *mkey)
int i;
if (ge->keybuf_slot >= 0) {
if (g_eli_mkey_decrypt(&ge->md, saved_keys[ge->keybuf_slot],
if (g_eli_mkey_decrypt_any(&ge->md, saved_keys[ge->keybuf_slot],
mkey, &keynum) == 0) {
return (0);
}
}
for (i = 0; i < nsaved_keys; i++) {
if (g_eli_mkey_decrypt(&ge->md, saved_keys[i], mkey,
if (g_eli_mkey_decrypt_any(&ge->md, saved_keys[i], mkey,
&keynum) == 0) {
ge->keybuf_slot = i;
return (0);
@@ -266,7 +266,7 @@ geli_attach(struct geli_entry *ge, struct dsk *dskp, const char *passphrase,
g_eli_crypto_hmac_final(&ctx, key, 0);
error = g_eli_mkey_decrypt(&geli_e->md, key, mkey, &keynum);
error = g_eli_mkey_decrypt_any(&geli_e->md, key, mkey, &keynum);
if (error == -1) {
explicit_bzero(mkey, sizeof(mkey));
explicit_bzero(key, sizeof(key));
+2 -2
View File
@@ -1086,7 +1086,7 @@ g_eli_taste(struct g_class *mp, struct g_provider *pp, int flags __unused)
memcpy(key, keybuf->kb_ents[i].ke_data,
sizeof(key));
if (g_eli_mkey_decrypt(&md, key,
if (g_eli_mkey_decrypt_any(&md, key,
mkey, &nkey) == 0 ) {
explicit_bzero(key, sizeof(key));
goto have_key;
@@ -1161,7 +1161,7 @@ g_eli_taste(struct g_class *mp, struct g_provider *pp, int flags __unused)
/*
* Decrypt Master-Key.
*/
error = g_eli_mkey_decrypt(&md, key, mkey, &nkey);
error = g_eli_mkey_decrypt_any(&md, key, mkey, &nkey);
bzero(key, sizeof(key));
if (error == -1) {
if (i == tries) {
+2
View File
@@ -688,6 +688,8 @@ void g_eli_crypto_ivgen(struct g_eli_softc *sc, off_t offset, u_char *iv,
void g_eli_mkey_hmac(unsigned char *mkey, const unsigned char *key);
int g_eli_mkey_decrypt(const struct g_eli_metadata *md,
const unsigned char *key, unsigned char *mkey, unsigned keyp);
int g_eli_mkey_decrypt_any(const struct g_eli_metadata *md,
const unsigned char *key, unsigned char *mkey, unsigned *nkeyp);
int g_eli_mkey_encrypt(unsigned algo, const unsigned char *key, unsigned keylen,
unsigned char *mkey);
+18 -4
View File
@@ -60,8 +60,8 @@ g_eli_ctl_attach(struct gctl_req *req, struct g_class *mp)
const char *name;
u_char *key, mkey[G_ELI_DATAIVKEYLEN];
int *nargs, *detach, *readonly, *dryrun;
int keysize, error;
u_int nkey;
int keysize, error, nkey;
intmax_t *valp;
g_topology_assert();
@@ -81,6 +81,17 @@ g_eli_ctl_attach(struct gctl_req *req, struct g_class *mp)
return;
}
valp = gctl_get_paraml(req, "keyno", sizeof(*valp));
if (valp == NULL) {
gctl_error(req, "No '%s' argument.", "keyno");
return;
}
nkey = *valp;
if (nkey < -1 || nkey >= G_ELI_MAXMKEYS) {
gctl_error(req, "Invalid '%s' argument.", "keyno");
return;
}
readonly = gctl_get_paraml(req, "readonly", sizeof(*readonly));
if (readonly == NULL) {
gctl_error(req, "No '%s' argument.", "readonly");
@@ -129,7 +140,10 @@ g_eli_ctl_attach(struct gctl_req *req, struct g_class *mp)
return;
}
error = g_eli_mkey_decrypt(&md, key, mkey, &nkey);
if (nkey == -1)
error = g_eli_mkey_decrypt_any(&md, key, mkey, &nkey);
else
error = g_eli_mkey_decrypt(&md, key, mkey, nkey);
explicit_bzero(key, keysize);
if (error == -1) {
explicit_bzero(&md, sizeof(md));
@@ -981,7 +995,7 @@ g_eli_ctl_resume(struct gctl_req *req, struct g_class *mp)
return;
}
error = g_eli_mkey_decrypt(&md, key, mkey, &nkey);
error = g_eli_mkey_decrypt_any(&md, key, mkey, &nkey);
explicit_bzero(key, keysize);
if (error == -1) {
explicit_bzero(&md, sizeof(md));
+52 -27
View File
@@ -103,54 +103,79 @@ g_eli_mkey_hmac(unsigned char *mkey, const unsigned char *key)
}
/*
* Find and decrypt Master Key encrypted with 'key'.
* Return decrypted Master Key number in 'nkeyp' if not NULL.
* Find and decrypt Master Key encrypted with 'key' at slot 'nkey'.
* Return 0 on success, > 0 on failure, -1 on bad key.
*/
int
g_eli_mkey_decrypt(const struct g_eli_metadata *md, const unsigned char *key,
unsigned char *mkey, unsigned *nkeyp)
unsigned char *mkey, unsigned nkey)
{
unsigned char tmpmkey[G_ELI_MKEYLEN];
unsigned char enckey[SHA512_MDLEN]; /* Key for encryption. */
const unsigned char *mmkey;
int bit, error, nkey;
int bit, error;
if (nkeyp != NULL)
*nkeyp = -1;
if (nkey > G_ELI_MKEYLEN)
return (-1);
/*
* The key for encryption is: enckey = HMAC_SHA512(Derived-Key, 1)
*/
g_eli_crypto_hmac(key, G_ELI_USERKEYLEN, "\x01", 1, enckey, 0);
mmkey = md->md_mkeys;
for (nkey = 0; nkey < G_ELI_MAXMKEYS; nkey++, mmkey += G_ELI_MKEYLEN) {
bit = (1 << nkey);
if (!(md->md_keys & bit))
continue;
bcopy(mmkey, tmpmkey, G_ELI_MKEYLEN);
error = g_eli_crypto_decrypt(md->md_ealgo, tmpmkey,
G_ELI_MKEYLEN, enckey, md->md_keylen);
if (error != 0) {
explicit_bzero(tmpmkey, sizeof(tmpmkey));
explicit_bzero(enckey, sizeof(enckey));
return (error);
}
if (g_eli_mkey_verify(tmpmkey, key)) {
bcopy(tmpmkey, mkey, G_ELI_DATAIVKEYLEN);
explicit_bzero(tmpmkey, sizeof(tmpmkey));
explicit_bzero(enckey, sizeof(enckey));
if (nkeyp != NULL)
*nkeyp = nkey;
return (0);
}
mmkey = md->md_mkeys + G_ELI_MKEYLEN * nkey;
bit = (1 << nkey);
if (!(md->md_keys & bit))
return (-1);
bcopy(mmkey, tmpmkey, G_ELI_MKEYLEN);
error = g_eli_crypto_decrypt(md->md_ealgo, tmpmkey,
G_ELI_MKEYLEN, enckey, md->md_keylen);
if (error != 0) {
explicit_bzero(tmpmkey, sizeof(tmpmkey));
explicit_bzero(enckey, sizeof(enckey));
return (error);
}
if (g_eli_mkey_verify(tmpmkey, key)) {
bcopy(tmpmkey, mkey, G_ELI_DATAIVKEYLEN);
explicit_bzero(tmpmkey, sizeof(tmpmkey));
explicit_bzero(enckey, sizeof(enckey));
return (0);
}
explicit_bzero(enckey, sizeof(enckey));
explicit_bzero(tmpmkey, sizeof(tmpmkey));
return (-1);
}
/*
* Find and decrypt Master Key encrypted with 'key'.
* Return decrypted Master Key number in 'nkeyp' if not NULL.
* Return 0 on success, > 0 on failure, -1 on bad key.
*/
int
g_eli_mkey_decrypt_any(const struct g_eli_metadata *md,
const unsigned char *key, unsigned char *mkey, unsigned *nkeyp)
{
int error, nkey;
if (nkeyp != NULL)
*nkeyp = -1;
error = -1;
for (nkey = 0; nkey < G_ELI_MAXMKEYS; nkey++) {
error = g_eli_mkey_decrypt(md, key, mkey, nkey);
if (error == 0) {
if (nkeyp != NULL)
*nkeyp = nkey;
break;
} else if (error > 0) {
break;
}
}
return (error);
}
/*
* Encrypt the Master-Key and calculate HMAC to be able to verify it in the
* future.