X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=lib%2Ftcrypt%2Ftcrypt.c;h=69a70b49a5bbf8de50dd28757237109c65863a89;hb=eac953c6e42ae7652b822ac906a7ee6bfc711cb4;hp=8e7f07d833e5a604925ae9c6cced5b9a517adc13;hpb=46cf1c6ce092b7dcd6a033be861cf161ff942bd8;p=platform%2Fupstream%2Fcryptsetup.git diff --git a/lib/tcrypt/tcrypt.c b/lib/tcrypt/tcrypt.c index 8e7f07d..69a70b4 100644 --- a/lib/tcrypt/tcrypt.c +++ b/lib/tcrypt/tcrypt.c @@ -244,7 +244,7 @@ static int decrypt_blowfish_le_cbc(struct tcrypt_alg *alg, r = crypt_cipher_init(&cipher, "blowfish", "ecb", &key[alg->key_offset], alg->key_size); if (r < 0) - goto out; + return r; memcpy(iv, &key[alg->iv_offset], alg->iv_size); for (i = 0; i < TCRYPT_HDR_LEN; i += bs) { @@ -254,12 +254,12 @@ static int decrypt_blowfish_le_cbc(struct tcrypt_alg *alg, bs, NULL, 0); blowfish_le(&buf[i]); if (r < 0) - goto out; + break; for (j = 0; j < bs; j++) buf[i + j] ^= iv[j]; memcpy(iv, iv_old, bs); } -out: + crypt_cipher_destroy(cipher); return r; } @@ -394,10 +394,16 @@ static int decrypt_hdr(struct crypt_device *cd, struct tcrypt_phdr *hdr, continue; r = decrypt_hdr_one(&tcrypt_cipher[i].cipher[j], tcrypt_cipher[i].mode, key, &hdr2); - if (r < 0) { - log_dbg("Error %s.", tcrypt_cipher[i].cipher[j].name); + if (r < 0) break; - } + } + + if (r < 0) { + log_dbg("TCRYPT: returned error %d, skipped.", r); + if (r == -ENOTSUP) + break; + r = -ENOENT; + continue; } if (!strncmp(hdr2.d.magic, TCRYPT_HDR_MAGIC, TCRYPT_HDR_MAGIC_LEN)) { @@ -460,7 +466,7 @@ static int TCRYPT_init_hdr(struct crypt_device *cd, unsigned char pwd[TCRYPT_KEY_POOL_LEN] = {}; size_t passphrase_size; char *key; - int r = -EINVAL, i, legacy_modes; + int r = -EINVAL, i, legacy_modes, skipped = 0; if (posix_memalign((void*)&key, crypt_getpagesize(), TCRYPT_HDR_KEY_LEN)) return -ENOMEM; @@ -498,19 +504,27 @@ static int TCRYPT_init_hdr(struct crypt_device *cd, /* Decrypt header */ r = decrypt_hdr(cd, hdr, key, legacy_modes); + if (r == -ENOENT) { + skipped++; + continue; + } if (r != -EPERM) break; } + if (skipped == i || r == -ENOTSUP) + log_err(cd, _("Required kernel crypto interface not available.\n" + "Ensure you have algif_skcipher kernel module loaded.\n")); if (r < 0) goto out; r = hdr_from_disk(hdr, params, i, r); if (!r) { log_dbg("TCRYPT: Header version: %d, req. %d, sector %d" - ", PBKDF2 hash %s", (int)hdr->d.version, + ", mk_offset %" PRIu64 ", hidden_size %" PRIu64 + ", volume size %" PRIu64, (int)hdr->d.version, (int)hdr->d.version_tc, (int)hdr->d.sector_size, - params->hash_name); + hdr->d.mk_offset, hdr->d.hidden_volume_size, hdr->d.volume_size); log_dbg("TCRYPT: Header cipher %s-%s, key size %d", params->cipher, params->mode, params->key_size); } @@ -528,7 +542,7 @@ int TCRYPT_read_phdr(struct crypt_device *cd, { struct device *device = crypt_metadata_device(cd); ssize_t hdr_size = sizeof(struct tcrypt_phdr); - int devfd = 0, r = -EIO, bs; + int devfd = 0, r, bs; assert(sizeof(struct tcrypt_phdr) == 512); @@ -545,13 +559,24 @@ int TCRYPT_read_phdr(struct crypt_device *cd, return -EINVAL; } + r = -EIO; if (params->flags & CRYPT_TCRYPT_HIDDEN_HEADER) { - if (lseek(devfd, TCRYPT_HDR_HIDDEN_OFFSET, SEEK_SET) >= 0 && - read_blockwise(devfd, bs, hdr, hdr_size) == hdr_size) - r = TCRYPT_init_hdr(cd, hdr, params); - if (r && - lseek(devfd, TCRYPT_HDR_HIDDEN_OFFSET_OLD, SEEK_END) >= 0 && - read_blockwise(devfd, bs, hdr, hdr_size) == hdr_size) + if (params->flags & CRYPT_TCRYPT_BACKUP_HEADER) { + if (lseek(devfd, TCRYPT_HDR_HIDDEN_OFFSET_BCK, SEEK_END) >= 0 && + read_blockwise(devfd, bs, hdr, hdr_size) == hdr_size) + r = TCRYPT_init_hdr(cd, hdr, params); + } else { + if (lseek(devfd, TCRYPT_HDR_HIDDEN_OFFSET, SEEK_SET) >= 0 && + read_blockwise(devfd, bs, hdr, hdr_size) == hdr_size) + r = TCRYPT_init_hdr(cd, hdr, params); + if (r && + lseek(devfd, TCRYPT_HDR_HIDDEN_OFFSET_OLD, SEEK_END) >= 0 && + read_blockwise(devfd, bs, hdr, hdr_size) == hdr_size) + r = TCRYPT_init_hdr(cd, hdr, params); + } + } else if (params->flags & CRYPT_TCRYPT_BACKUP_HEADER) { + if (lseek(devfd, TCRYPT_HDR_OFFSET_BCK, SEEK_END) >= 0 && + read_blockwise(devfd, bs, hdr, hdr_size) == hdr_size) r = TCRYPT_init_hdr(cd, hdr, params); } else if (read_blockwise(devfd, bs, hdr, hdr_size) == hdr_size) r = TCRYPT_init_hdr(cd, hdr, params); @@ -616,6 +641,11 @@ int TCRYPT_activate(struct crypt_device *cd, if (!algs) return -EINVAL; + if (params->flags & CRYPT_TCRYPT_HIDDEN_HEADER) + dmd.size = hdr->d.hidden_volume_size / hdr->d.sector_size; + else + dmd.size = hdr->d.volume_size / hdr->d.sector_size; + r = device_block_adjust(cd, dmd.data_device, DEV_EXCL, dmd.u.crypt.offset, &dmd.size, &dmd.flags); if (r) @@ -791,19 +821,49 @@ int TCRYPT_init_by_name(struct crypt_device *cd, const char *name, return 0; } -uint64_t TCRYPT_get_data_offset(struct tcrypt_phdr *hdr) +uint64_t TCRYPT_get_data_offset(struct crypt_device *cd, + struct tcrypt_phdr *hdr, + struct crypt_params_tcrypt *params) { + uint64_t size; + + if (params->mode && !strncmp(params->mode, "xts", 3)) { + if (hdr->d.version < 3) + return 1; + + if (params->flags & CRYPT_TCRYPT_HIDDEN_HEADER) { + if (hdr->d.version > 3) + return (hdr->d.mk_offset / hdr->d.sector_size); + if (device_size(crypt_metadata_device(cd), &size) < 0) + return 0; + return (size - hdr->d.hidden_volume_size + + (TCRYPT_HDR_HIDDEN_OFFSET_OLD)) / hdr->d.sector_size; + } + return (hdr->d.mk_offset / hdr->d.sector_size); + } + + if (params->flags & CRYPT_TCRYPT_HIDDEN_HEADER) { + if (device_size(crypt_metadata_device(cd), &size) < 0) + return 0; + return (size - hdr->d.hidden_volume_size + + (TCRYPT_HDR_HIDDEN_OFFSET_OLD)) / hdr->d.sector_size; + } + // FIXME: system vol. - if (!hdr->d.mk_offset) - return 1; - return (hdr->d.mk_offset / hdr->d.sector_size); + return hdr->d.mk_offset / hdr->d.sector_size; } -uint64_t TCRYPT_get_iv_offset(struct tcrypt_phdr *hdr) +uint64_t TCRYPT_get_iv_offset(struct crypt_device *cd, + struct tcrypt_phdr *hdr, + struct crypt_params_tcrypt *params +) { - if (!hdr->d.mk_offset) + if (params->mode && !strncmp(params->mode, "xts", 3)) + return TCRYPT_get_data_offset(cd, hdr, params); + else if (params->mode && !strncmp(params->mode, "lrw", 3)) return 0; - return (hdr->d.mk_offset / hdr->d.sector_size); + + return hdr->d.mk_offset / hdr->d.sector_size; } int TCRYPT_get_volume_key(struct crypt_device *cd,