static uint8_t key[AES_XTS_PLAIN_KEYSIZE / 8];
+int __vhd_util_calculate_keyhash(struct vhd_keyhash *, const uint8_t *, size_t);
+
+static int
+check_key(const uint8_t *key, unsigned int keysize,
+ const struct vhd_keyhash *vhdhash)
+{
+ int err;
+ struct vhd_keyhash keyhash;
+
+ memcpy(keyhash.nonce, vhdhash->nonce, sizeof(keyhash.nonce));
+ err = __vhd_util_calculate_keyhash(&keyhash, key, keysize);
+ if (err) {
+ DPRINTF("failed to calculate keyhash: %d\n", err);
+ goto out;
+ }
+
+ if (memcmp(keyhash.hash, vhdhash->hash, sizeof(keyhash.hash))) {
+ DPRINTF("key has mismatch\n");
+ goto out;
+ }
+
+out:
+ if (err) {
+ DPRINTF("key check failed\n");
+ err = -ENOKEY;
+ }
+ return err;
+}
+
int
vhd_open_crypto(vhd_context_t *vhd, const char *_name)
{
const char *keydir;
- char *name, *basename, *keyfile;
+ struct vhd_keyhash keyhash;
+ char *name, *basename, *ext, *keyfile;
int err, fd = -1;
if (vhd->xts_tfm)
return 0;
+ err = vhd_get_keyhash(vhd, &keyhash);
+ if (err) {
+ DPRINTF("error getting keyhash: %d\n", err);
+ return err;
+ }
+
keydir = getenv("TAPDISK2_CRYPTO_KEYDIR");
- if (keydir == NULL)
+ if (keydir == NULL) {
+ if (keyhash.cookie) {
+ DPRINTF("this vhd requires TAPDISK2_CRYPTO_KEYDIR\n");
+ return -ENOKEY;
+ }
return 0;
+ }
name = strdup(_name);
if (name == NULL)
basename++;
/* cut off .vhd extension */
- basename[strlen(basename) - 4] = 0;
+ ext = strstr(basename, ".vhd");
+ if (ext)
+ basename[ext - basename] = 0;
err = asprintf(&keyfile, "%s/%s,aes-xts-plain,%d.key", keydir,
basename, AES_XTS_PLAIN_KEYSIZE);
fd = open(keyfile, O_RDONLY);
if (fd == -1) {
- err = errno == ENOENT ? 0 : -errno;
+ if (keyhash.cookie)
+ err = errno;
+ else
+ err = errno == ENOENT ? 0 : -errno;
+
+ if (err)
+ DPRINTF("error opening %s: %d\n", keyfile, err);
+
goto out;
}
goto out;
}
+ err = check_key(key, sizeof(key), &keyhash);
+ if (err)
+ goto out;
+
vhd->xts_tfm = xts_aes_setup();
if (vhd->xts_tfm == NULL) {
err = -EINVAL;
goto out;
}
+ DPRINTF("using keyfile %s\n", keyfile);
xts_setkey(crypto_blkcipher_tfm(vhd->xts_tfm), key, sizeof(key));
err = 0;