Split out the IV generation function so that we can add other ones in the future. The cryptoloop compatible one is too predictable. The -cbc cipher suffix is therefore changed to -plain. [Christophe Saout] --- diff/drivers/md/dm-crypt.c 2004-01-03 12:14:25.000000000 +0000 +++ source/drivers/md/dm-crypt.c 2004-01-03 12:14:31.000000000 +0000 @@ -62,6 +62,7 @@ */ struct crypto_tfm *tfm; sector_t iv_offset; + int (*iv_generator)(struct crypt_config *cc, u8 *iv, sector_t sector); int iv_size; int key_size; u8 key[0]; @@ -86,6 +87,20 @@ __free_page(page); } + +/* + * Different IV generation algorithms + */ +static int crypt_iv_plain(struct crypt_config *cc, u8 *iv, sector_t sector) +{ + *(u32 *)iv = cpu_to_le32(sector & 0xffffffff); + if (cc->iv_size > sizeof(u32) / sizeof(u8)) + memset(iv + (sizeof(u32) / sizeof(u8)), 0, + cc->iv_size - (sizeof(u32) / sizeof(u8))); + + return 0; +} + /* * Encrypt / decrypt a single sector, source and destination buffers * are stored in scatterlists. In CBC mode initialise the "previous @@ -100,11 +115,10 @@ u8 iv[cc->iv_size]; int r; - if (cc->iv_size) { - *(u32 *)iv = cpu_to_le32(sector & 0xffffffff); - if (cc->iv_size > sizeof(u32) / sizeof(u8)) - memset(iv + (sizeof(u32) / sizeof(u8)), 0, - cc->iv_size - (sizeof(u32) / sizeof(u8))); + if (cc->iv_generator) { + r = cc->iv_generator(cc, iv, sector); + if (r < 0) + return r; if (write) r = crypto_cipher_encrypt_iv(cc->tfm, out, in, length, iv); @@ -428,7 +442,6 @@ char *cipher; char *mode; int crypto_flags; - int iv_size; int key_size; if (argc != 5) { @@ -443,88 +456,99 @@ if (tmp) DMWARN("dm-crypt: Unexpected additional cipher options"); - if (!mode || strcmp(mode, "cbc") == 0) - crypto_flags = CRYPTO_TFM_MODE_CBC; + key_size = strlen(argv[1]) >> 1; + + cc = kmalloc(sizeof(*cc) + key_size * sizeof(u8), GFP_KERNEL); + if (cc == NULL) { + ti->error = + "dm-crypt: Cannot allocate transparent encryption context"; + return -ENOMEM; + } + + if (!mode || strcmp(mode, "plain") == 0) + cc->iv_generator = crypt_iv_plain; else if (strcmp(mode, "ecb") == 0) - crypto_flags = CRYPTO_TFM_MODE_ECB; + cc->iv_generator = NULL; else { ti->error = "dm-crypt: Invalid chaining mode"; return -EINVAL; } + if (cc->iv_generator) + crypto_flags = CRYPTO_TFM_MODE_CBC; + else + crypto_flags = CRYPTO_TFM_MODE_ECB; + tfm = crypto_alloc_tfm(cipher, crypto_flags); if (!tfm) { ti->error = "dm-crypt: Error allocating crypto tfm"; - return -EINVAL; + goto bad1; } - key_size = strlen(argv[1]) >> 1; if (tfm->crt_u.cipher.cit_decrypt_iv && tfm->crt_u.cipher.cit_encrypt_iv) - iv_size = max(crypto_tfm_alg_ivsize(tfm), sizeof(u32) / sizeof(u8)); - else - iv_size = 0; - - cc = kmalloc(sizeof(*cc) + key_size * sizeof(u8), GFP_KERNEL); - if (cc == NULL) { - ti->error = - "dm-crypt: Cannot allocate transparent encryption context"; - crypto_free_tfm(tfm); - return -ENOMEM; + /* at least a 32 bit sector number should fit in our buffer */ + cc->iv_size = max(crypto_tfm_alg_ivsize(tfm), sizeof(u32) / sizeof(u8)); + else { + cc->iv_size = 0; + if (cc->iv_generator) { + DMWARN("dm-crypt: Selected cipher does not support IVs"); + cc->iv_generator = NULL; + } } cc->io_pool = mempool_create(MIN_IOS, mempool_alloc_slab, mempool_free_slab, _crypt_io_pool); if (!cc->io_pool) { ti->error = "dm-crypt: Cannot allocate crypt io mempool"; - goto bad1; + goto bad2; } cc->page_pool = mempool_create(MIN_POOL_PAGES, mempool_alloc_page, mempool_free_page, NULL); if (!cc->page_pool) { ti->error = "dm-crypt: Cannot allocate page mempool"; - goto bad2; + goto bad3; } cc->tfm = tfm; - cc->iv_size = iv_size; cc->key_size = key_size; if ((key_size == 0 && strcmp(argv[1], "-") != 0) || crypt_decode_key(cc->key, argv[1], key_size) < 0) { ti->error = "dm-crypt: Error decoding key"; - goto bad3; + goto bad4; } if (tfm->crt_u.cipher.cit_setkey(tfm, cc->key, key_size) < 0) { ti->error = "dm-crypt: Error setting key"; - goto bad3; + goto bad4; } if (sscanf(argv[2], SECTOR_FORMAT, &cc->iv_offset) != 1) { ti->error = "dm-crypt: Invalid iv_offset sector"; - goto bad3; + goto bad4; } if (sscanf(argv[4], SECTOR_FORMAT, &cc->start) != 1) { ti->error = "dm-crypt: Invalid device sector"; - goto bad3; + goto bad4; } if (dm_get_device(ti, argv[3], cc->start, ti->len, dm_table_get_mode(ti->table), &cc->dev)) { ti->error = "dm-crypt: Device lookup failed"; - goto bad3; + goto bad4; } ti->private = cc; return 0; -bad3: +bad4: mempool_destroy(cc->page_pool); -bad2: +bad3: mempool_destroy(cc->io_pool); -bad1: +bad2: crypto_free_tfm(tfm); +bad1: kfree(cc); return -EINVAL; }