diff options
author | Milan Broz <gmazyland@gmail.com> | 2012-12-10 16:36:22 +0100 |
---|---|---|
committer | Milan Broz <gmazyland@gmail.com> | 2012-12-10 16:36:22 +0100 |
commit | 549ab6435806fe48206f9051f2acd13829030c27 (patch) | |
tree | b2f03bbf63fdb9ab36b949645e6d7b36982ee354 /lib | |
parent | e8d09733d40cf5e41a7767623192fb012865bbe6 (diff) | |
download | cryptsetup-549ab6435806fe48206f9051f2acd13829030c27.tar.gz cryptsetup-549ab6435806fe48206f9051f2acd13829030c27.tar.bz2 cryptsetup-549ab6435806fe48206f9051f2acd13829030c27.zip |
TCRYPT: properly wipe all buffers; use prefix for all functions.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/setup.c | 2 | ||||
-rw-r--r-- | lib/tcrypt/tcrypt.c | 145 |
2 files changed, 85 insertions, 62 deletions
diff --git a/lib/setup.c b/lib/setup.c index fd65e8f..5e01f99 100644 --- a/lib/setup.c +++ b/lib/setup.c @@ -1424,6 +1424,8 @@ void crypt_free(struct crypt_device *cd) } free(cd->type); + /* Some structures can contain keys (TCRYPT), wipe it */ + memset(cd, 0, sizeof(*cd)); free(cd); } } diff --git a/lib/tcrypt/tcrypt.c b/lib/tcrypt/tcrypt.c index 0e7872a..b1ebd05 100644 --- a/lib/tcrypt/tcrypt.c +++ b/lib/tcrypt/tcrypt.c @@ -163,9 +163,9 @@ static struct tcrypt_algs tcrypt_cipher[] = { {} }; -static int hdr_from_disk(struct tcrypt_phdr *hdr, - struct crypt_params_tcrypt *params, - int kdf_index, int cipher_index) +static int TCRYPT_hdr_from_disk(struct tcrypt_phdr *hdr, + struct crypt_params_tcrypt *params, + int kdf_index, int cipher_index) { uint32_t crc32; size_t size; @@ -223,7 +223,7 @@ static int hdr_from_disk(struct tcrypt_phdr *hdr, /* * Kernel implements just big-endian version of blowfish, hack it here */ -static void blowfish_le(char *buf) +static void TCRYPT_swab_le(char *buf) { uint32_t *l = (uint32_t*)&buf[0]; uint32_t *r = (uint32_t*)&buf[4]; @@ -234,9 +234,9 @@ static void blowfish_le(char *buf) static int decrypt_blowfish_le_cbc(struct tcrypt_alg *alg, const char *key, char *buf) { - char iv[alg->iv_size], iv_old[alg->iv_size]; - struct crypt_cipher *cipher = NULL; int bs = alg->iv_size; + char iv[bs], iv_old[bs]; + struct crypt_cipher *cipher = NULL; int i, j, r; assert(bs == 2*sizeof(uint32_t)); @@ -249,10 +249,10 @@ static int decrypt_blowfish_le_cbc(struct tcrypt_alg *alg, memcpy(iv, &key[alg->iv_offset], alg->iv_size); for (i = 0; i < TCRYPT_HDR_LEN; i += bs) { memcpy(iv_old, &buf[i], bs); - blowfish_le(&buf[i]); + TCRYPT_swab_le(&buf[i]); r = crypt_cipher_decrypt(cipher, &buf[i], &buf[i], bs, NULL, 0); - blowfish_le(&buf[i]); + TCRYPT_swab_le(&buf[i]); if (r < 0) break; for (j = 0; j < bs; j++) @@ -261,10 +261,12 @@ static int decrypt_blowfish_le_cbc(struct tcrypt_alg *alg, } crypt_cipher_destroy(cipher); + memset(iv, 0, bs); + memset(iv_old, 0, bs); return r; } -static void remove_whitening(char *buf, const char *key) +static void TCRYPT_remove_whitening(char *buf, const char *key) { int j; @@ -272,8 +274,8 @@ static void remove_whitening(char *buf, const char *key) buf[j] ^= key[j % 8]; } -static void copy_key(struct tcrypt_alg *alg, const char *mode, - char *out_key, const char *key) +static void TCRYPT_copy_key(struct tcrypt_alg *alg, const char *mode, + char *out_key, const char *key) { int ks2; if (!strncmp(mode, "xts", 3)) { @@ -289,8 +291,8 @@ static void copy_key(struct tcrypt_alg *alg, const char *mode, } } -static int decrypt_hdr_one(struct tcrypt_alg *alg, const char *mode, - const char *key,struct tcrypt_phdr *hdr) +static int TCRYPT_decrypt_hdr_one(struct tcrypt_alg *alg, const char *mode, + const char *key,struct tcrypt_phdr *hdr) { char backend_key[TCRYPT_HDR_KEY_LEN]; char iv[TCRYPT_HDR_IV_LEN] = {}; @@ -308,22 +310,23 @@ static int decrypt_hdr_one(struct tcrypt_alg *alg, const char *mode, if (!strncmp(mode, "lrw", 3)) iv[alg->iv_size - 1] = 1; else if (!strncmp(mode, "cbc", 3)) { - remove_whitening(buf, &key[8]); + TCRYPT_remove_whitening(buf, &key[8]); if (!strcmp(alg->name, "blowfish_le")) return decrypt_blowfish_le_cbc(alg, key, buf); memcpy(iv, &key[alg->iv_offset], alg->iv_size); } - copy_key(alg, mode, backend_key, key); + TCRYPT_copy_key(alg, mode, backend_key, key); r = crypt_cipher_init(&cipher, alg->name, mode_name, backend_key, alg->key_size); - memset(backend_key, 0, sizeof(backend_key)); - if (r < 0) - return r; - - r = crypt_cipher_decrypt(cipher, buf, buf, TCRYPT_HDR_LEN, iv, alg->iv_size); - crypt_cipher_destroy(cipher); + if (!r) { + r = crypt_cipher_decrypt(cipher, buf, buf, TCRYPT_HDR_LEN, + iv, alg->iv_size); + crypt_cipher_destroy(cipher); + } + memset(backend_key, 0, sizeof(backend_key)); + memset(iv, 0, TCRYPT_HDR_IV_LEN); return r; } @@ -331,8 +334,8 @@ static int decrypt_hdr_one(struct tcrypt_alg *alg, const char *mode, * For chanined ciphers and CBC mode we need "outer" decryption. * Backend doesn't provide this, so implement it here directly using ECB. */ -static int decrypt_hdr_cbci(struct tcrypt_algs *ciphers, - const char *key, struct tcrypt_phdr *hdr) +static int TCRYPT_decrypt_cbci(struct tcrypt_algs *ciphers, + const char *key, struct tcrypt_phdr *hdr) { struct crypt_cipher *cipher[ciphers->chain_count]; unsigned int bs = ciphers->cipher[0].iv_size; @@ -340,7 +343,7 @@ static int decrypt_hdr_cbci(struct tcrypt_algs *ciphers, unsigned int i, j; int r = -EINVAL; - remove_whitening(buf, &key[8]); + TCRYPT_remove_whitening(buf, &key[8]); memcpy(iv, &key[ciphers->cipher[0].iv_offset], bs); @@ -373,11 +376,13 @@ out: if (cipher[j]) crypt_cipher_destroy(cipher[j]); + memset(iv, 0, bs); + memset(iv_old, 0, bs); return r; } -static int decrypt_hdr(struct crypt_device *cd, struct tcrypt_phdr *hdr, - const char *key, int legacy_modes) +static int TCRYPT_decrypt_hdr(struct crypt_device *cd, struct tcrypt_phdr *hdr, + const char *key, int legacy_modes) { struct tcrypt_phdr hdr2; int i, j, r = -EINVAL; @@ -391,11 +396,11 @@ static int decrypt_hdr(struct crypt_device *cd, struct tcrypt_phdr *hdr, memcpy(&hdr2.e, &hdr->e, TCRYPT_HDR_LEN); if (!strncmp(tcrypt_cipher[i].mode, "cbci", 4)) - r = decrypt_hdr_cbci(&tcrypt_cipher[i], key, &hdr2); + r = TCRYPT_decrypt_cbci(&tcrypt_cipher[i], key, &hdr2); else for (j = tcrypt_cipher[i].chain_count - 1; j >= 0 ; j--) { if (!tcrypt_cipher[i].cipher[j].name) continue; - r = decrypt_hdr_one(&tcrypt_cipher[i].cipher[j], + r = TCRYPT_decrypt_hdr_one(&tcrypt_cipher[i].cipher[j], tcrypt_cipher[i].mode, key, &hdr2); if (r < 0) break; @@ -412,19 +417,19 @@ static int decrypt_hdr(struct crypt_device *cd, struct tcrypt_phdr *hdr, if (!strncmp(hdr2.d.magic, TCRYPT_HDR_MAGIC, TCRYPT_HDR_MAGIC_LEN)) { log_dbg("TCRYPT: Signature magic detected."); memcpy(&hdr->e, &hdr2.e, TCRYPT_HDR_LEN); - memset(&hdr2.e, 0, TCRYPT_HDR_LEN); r = i; break; } r = -EPERM; } + memset(&hdr2, 0, sizeof(hdr2)); return r; } -static int pool_keyfile(struct crypt_device *cd, - unsigned char pool[TCRYPT_KEY_POOL_LEN], - const char *keyfile) +static int TCRYPT_pool_keyfile(struct crypt_device *cd, + unsigned char pool[TCRYPT_KEY_POOL_LEN], + const char *keyfile) { unsigned char data[TCRYPT_KEYFILE_LEN]; int i, j, fd, data_size; @@ -481,7 +486,7 @@ static int TCRYPT_init_hdr(struct crypt_device *cd, /* Calculate pool content from keyfiles */ for (i = 0; i < params->keyfiles_count; i++) { - r = pool_keyfile(cd, pwd, params->keyfiles[i]); + r = TCRYPT_pool_keyfile(cd, pwd, params->keyfiles[i]); if (r < 0) goto out; } @@ -506,7 +511,7 @@ static int TCRYPT_init_hdr(struct crypt_device *cd, break; /* Decrypt header */ - r = decrypt_hdr(cd, hdr, key, legacy_modes); + r = TCRYPT_decrypt_hdr(cd, hdr, key, legacy_modes); if (r == -ENOENT) { skipped++; continue; @@ -521,7 +526,7 @@ static int TCRYPT_init_hdr(struct crypt_device *cd, if (r < 0) goto out; - r = hdr_from_disk(hdr, params, i, r); + r = TCRYPT_hdr_from_disk(hdr, params, i, r); if (!r) { log_dbg("TCRYPT: Header version: %d, req. %d, sector %d" ", mk_offset %" PRIu64 ", hidden_size %" PRIu64 @@ -585,19 +590,21 @@ int TCRYPT_read_phdr(struct crypt_device *cd, r = TCRYPT_init_hdr(cd, hdr, params); close(devfd); + if (r < 0) + memset(hdr, 0, sizeof (*hdr)); return r; } -static struct tcrypt_algs *get_algs(struct crypt_params_tcrypt *params) +static struct tcrypt_algs *TCRYPT_get_algs(const char *cipher, const char *mode) { int i; - if (!params->cipher || !params->mode) + if (!cipher || !mode) return NULL; for (i = 0; tcrypt_cipher[i].chain_count; i++) - if (!strcmp(tcrypt_cipher[i].long_name, params->cipher) && - !strcmp(tcrypt_cipher[i].mode, params->mode)) + if (!strcmp(tcrypt_cipher[i].long_name, cipher) && + !strcmp(tcrypt_cipher[i].mode, mode)) return &tcrypt_cipher[i]; return NULL; @@ -641,7 +648,7 @@ int TCRYPT_activate(struct crypt_device *cd, return -ENOTSUP; } - algs = get_algs(params); + algs = TCRYPT_get_algs(params->cipher, params->mode); if (!algs) return -EINVAL; @@ -672,7 +679,8 @@ int TCRYPT_activate(struct crypt_device *cd, snprintf(cipher, sizeof(cipher), "%s-%s", algs->cipher[i-1].name, algs->mode); - copy_key(&algs->cipher[i-1], algs->mode, dmd.u.crypt.vk->key, hdr->d.keys); + TCRYPT_copy_key(&algs->cipher[i-1], algs->mode, + dmd.u.crypt.vk->key, hdr->d.keys); if (algs->chain_count != i) { snprintf(dm_dev_name, sizeof(dm_dev_name), "%s/%s_%d", @@ -704,7 +712,7 @@ int TCRYPT_activate(struct crypt_device *cd, return r; } -static int remove_one(struct crypt_device *cd, const char *name, +static int TCRYPT_remove_one(struct crypt_device *cd, const char *name, const char *base_uuid, int index) { struct crypt_dm_active_device dmd = {}; @@ -741,11 +749,11 @@ int TCRYPT_deactivate(struct crypt_device *cd, const char *name) if (r < 0) goto out; - r = remove_one(cd, name, dmd.uuid, 1); + r = TCRYPT_remove_one(cd, name, dmd.uuid, 1); if (r < 0) goto out; - r = remove_one(cd, name, dmd.uuid, 2); + r = TCRYPT_remove_one(cd, name, dmd.uuid, 2); if (r < 0) goto out; out: @@ -753,10 +761,10 @@ out: return (r == -ENODEV) ? 0 : r; } -static int status_one(struct crypt_device *cd, const char *name, - const char *base_uuid, int index, - size_t *key_size, char *cipher, uint64_t *data_offset, - struct device **device) +static int TCRYPT_status_one(struct crypt_device *cd, const char *name, + const char *base_uuid, int index, + size_t *key_size, char *cipher, + uint64_t *data_offset, struct device **device) { struct crypt_dm_active_device dmd = {}; char dm_name[PATH_MAX], *c; @@ -801,7 +809,10 @@ int TCRYPT_init_by_name(struct crypt_device *cd, const char *name, struct crypt_params_tcrypt *tcrypt_params, struct tcrypt_phdr *tcrypt_hdr) { - char cipher[MAX_CIPHER_LEN * 4], *mode; + struct tcrypt_algs *algs; + char cipher[MAX_CIPHER_LEN * 4], mode[MAX_CIPHER_LEN], *tmp; + size_t key_size; + int r; memset(tcrypt_params, 0, sizeof(*tcrypt_params)); memset(tcrypt_hdr, 0, sizeof(*tcrypt_hdr)); @@ -809,19 +820,29 @@ int TCRYPT_init_by_name(struct crypt_device *cd, const char *name, tcrypt_hdr->d.mk_offset = dmd->u.crypt.offset * SECTOR_SIZE; strncpy(cipher, dmd->u.crypt.cipher, MAX_CIPHER_LEN); + tmp = strchr(cipher, '-'); + if (!tmp) + return -EINVAL; + *tmp = '\0'; + strncpy(mode, ++tmp, MAX_CIPHER_LEN); - if ((mode = strchr(cipher, '-'))) { - *mode = '\0'; - tcrypt_params->mode = strdup(++mode); - } - tcrypt_params->key_size = dmd->u.crypt.vk->keylength; + key_size = dmd->u.crypt.vk->keylength; + r = TCRYPT_status_one(cd, name, dmd->uuid, 1, &key_size, + cipher, &tcrypt_hdr->d.mk_offset, device); + if (!r) + r = TCRYPT_status_one(cd, name, dmd->uuid, 2, &key_size, + cipher, &tcrypt_hdr->d.mk_offset, device); + + if (r < 0 && r != -ENODEV) + return r; - if (!status_one(cd, name, dmd->uuid, 1, &tcrypt_params->key_size, - cipher, &tcrypt_hdr->d.mk_offset, device)) - status_one(cd, name, dmd->uuid, 2, &tcrypt_params->key_size, - cipher, &tcrypt_hdr->d.mk_offset, device); + algs = TCRYPT_get_algs(cipher, mode); + if (!algs || key_size != algs->chain_key_size) + return -EINVAL; - tcrypt_params->cipher = strdup(cipher); + tcrypt_params->key_size = algs->chain_key_size; + tcrypt_params->cipher = algs->long_name; + tcrypt_params->mode = algs->mode; return 0; } @@ -887,7 +908,7 @@ int TCRYPT_get_volume_key(struct crypt_device *cd, return -ENOTSUP; } - algs = get_algs(params); + algs = TCRYPT_get_algs(params->cipher, params->mode); if (!algs) return -EINVAL; @@ -896,8 +917,8 @@ int TCRYPT_get_volume_key(struct crypt_device *cd, return -ENOMEM; for (i = 0, key_index = 0; i < algs->chain_count; i++) { - copy_key(&algs->cipher[i], algs->mode, - &(*vk)->key[key_index], hdr->d.keys); + TCRYPT_copy_key(&algs->cipher[i], algs->mode, + &(*vk)->key[key_index], hdr->d.keys); key_index += algs->cipher[i].key_size; } |