cryptsetupの暗号化方式について

■cryptsetupの暗号化方式について
 以下では、暗号化アルゴリズムをaes、ハッシュアルゴリズムをsha256、キーサイズを256とした。

 debian Wheezyにdm_cryptを導入
 http://d.hatena.ne.jp/labunix/20130516

■dm-cryptとLUKSの組み合わせであること。

$ man cryptsetup | grep -A 1 -B 1 "cbc\-essiv\:sha256"
              cryptsetup  --help shows the compiled-in defaults.  The current default in
              the distributed sources is "aes-cbc-essiv:sha256" for both plain  dm-crypt
              and LUKS.

■LUKS1のコンパイルのデフォルトをセットアップしたことが分かる。
 
$ sudo cryptsetup --help | tail -7
Default compiled-in keyfile parameters:
        Maximum keyfile size: 8192kB, Maximum interactive passphrase length 512 (characters)

Default compiled-in device cipher parameters:
        loop-AES: aes, Key 256 bits
        plain: aes-cbc-essiv:sha256, Key: 256 bits, Password hashing: ripemd160
        LUKS1: aes-cbc-essiv:sha256, Key: 256 bits, LUKS header hashing: sha1, RNG: /dev/urandom

■key-sizeは「LUKS header」に埋め込まれる。

$ man cryptsetup | grep -A 10 "\-\-key\-size, \-s"
       --key-size, -s <bits>
              Sets key size in bits. The argument has to be a multiple of 8. The  possi‐
              ble key-sizes are limited by the cipher and mode used.

              See  /proc/crypto for more information. Note that key-size in /proc/crypto
              is stated in bytes.

              This option can be used for create or luksFormat. All other  LUKS  actions
              will use the key-size specified in the LUKS header.  Use cryptsetup --help
              to show the compiled-in defaults.

■「LUKS header」をdumpすると確かに「MK bits:256」の表記がある。
 「Hash spec」はデフォルトのsha1。

$ sudo cryptsetup luksClose luks
$ sudo cryptsetup luksDump luks.img
LUKS header information for /dev/loop0

Version:        1
Cipher name:    aes
Cipher mode:    cbc-essiv:sha256
Hash spec:      sha1
Payload offset: 4096
MK bits:        256
MK digest:      54 98 43 1d a2 11 b0 0a 5b 58 7e e0 0c 3f b0 8f 1c 80 dc 60
MK salt:        07 34 a1 20 57 80 17 d7 24 ea ce 04 93 5d 1f 7b
                4c 7e 78 3e e4 d8 a4 fd 5d 22 aa 0a 2f 91 bb f6
MK iterations:  8875
UUID:           417053cc-72f7-45c0-9203-2d4922d199e9

Key Slot 0: ENABLED
        Iterations:             35996
        Salt:                   e9 75 cb e4 2a 23 40 a9 a1 4a 21 06 65 dd 16 e8
                                da fd 8d 69 0c 49 a6 f8 16 4b d9 af 7e ad c8 8d
        Key material offset:    8
        AF stripes:             4000
Key Slot 1: DISABLED
Key Slot 2: DISABLED
Key Slot 3: DISABLED
Key Slot 4: DISABLED
Key Slot 5: DISABLED
Key Slot 6: DISABLED
Key Slot 7: DISABLED

■「cryptsetup」を導入すると以下のようになる。

 *cipherが暗号化アルゴリズム
 *hashがハッシュ化アルゴリズム
 *rndが乱数生成(Random Number Generator)

$ sudo cryptsetup luksClose luks.img luks
$ grep "driver\|module\|type" /proc/crypto | awk '{if($1!="type")printf "%-30s,\t",$0"";else print $0}'
driver       : sha256-generic , module       : sha256_generic , type         : shash
driver       : sha224-generic , module       : sha256_generic , type         : shash
driver       : cbc(aes-asm)   , module       : kernel         , type         : givcipher
driver       : cbc(aes-asm)   , module       : cbc            , type         : blkcipher
driver       : aes-asm        , module       : aes_i586       , type         : cipher
driver       : aes-generic    , module       : aes_generic    , type         : cipher
driver       : krng           , module       : kernel         , type         : rng
driver       : md5-generic    , module       : kernel         , type         : shash

■「dmcrypt」のモジュールもロードされているはず。

$ lsmod | grep dm
dm_crypt               18039  0
dm_mod                 57362  1 dm_crypt

$ lsmod | grep dm | awk '{print $1}' | sudo modinfo `xargs` | grep "filename\|alias\|desc"
filename:       /lib/modules/3.2.0-4-686-pae/kernel/drivers/md/dm-crypt.ko
description:    device-mapper target for transparent encryption / decryption
filename:       /lib/modules/3.2.0-4-686-pae/kernel/drivers/md/dm-mod.ko
description:    device-mapper driver
alias:          devname:mapper/control
alias:          char-major-10-236

■kernelモジュールに組み込まれているアルゴリズム

「cbc(aes-asm)」	暗号化アルゴリズム
「md5-generic」		ハッシュアルゴリズム

$ find linux-3.2.41/ -type f -name "*cbc.*" -exec grep DESC {} \;
MODULE_DESCRIPTION("CBC block cipher algorithm");
MODULE_DESCRIPTION("PCBC block cipher algorithm");
MODULE_DESCRIPTION("XCBC keyed hash algorithm");

$ find linux-3.2.41/ -type f -name "*md5.*" -exec grep "DESC" {} \;
MODULE_DESCRIPTION("MD5 Message Digest Algorithm");

■krngは「Kernel Random Number Generator」の略で、
 実態は「/dev/random」か「/dev/urandom」。
 ボリュームキーのSALTに使われる。
 RNDは「Random Number Generator」のことだと分かる。
 デフォルトで「/dev/urandom」を使用している。

$ tar Jtvf linux_3.2.41.orig.tar.xz | grep "krng"
$ xzcat linux_3.2.41.orig.tar.xz | tar xvf - linux-3.2.41/crypto/krng.c
$ grep "DESC" linux-3.2.41/crypto/krng.c
MODULE_DESCRIPTION("Kernel Random Number Generator");

$ strings /sbin/cryptsetup | grep "^Use.*random"
Use /dev/random for generating volume key.
Use /dev/urandom for generating volume key.

$ grep "define.*random" cryptsetup-1.4.3/lib/random.c
#define URANDOM_DEVICE  "/dev/urandom"
#define RANDOM_DEVICE   "/dev/random"

$ grep -A 5 "_SALT" cryptsetup-1.4.3/lib/random.c
        case CRYPT_RND_SALT:
                if (crypt_fips_mode())
                        status = crypt_backend_rng(buf, len, quality, 1);
                else
                        status = _get_urandom(ctx, buf, len);
                break;

■moduleがkernelに組み込まれていなければ、別途ロードされている。

$ lsmod | grep "aes\|cbc\|sha"
sha256_generic         16709  0
aes_i586               16647  0
aes_generic            32970  1 aes_i586
cbc                    12666  0

■以下のようにすればファイル名と何を指定できるかが「alias」で分かる。

$ lsmod | grep "aes\|cbc\|sha" | awk '{print $1}' | sudo modinfo `xargs` | grep "alias\|desc\|filename"
filename:       /lib/modules/3.2.0-4-686-pae/kernel/crypto/sha256_generic.ko
alias:          sha256
alias:          sha224
description:    SHA-224 and SHA-256 Secure Hash Algorithm
filename:       /lib/modules/3.2.0-4-686-pae/kernel/arch/x86/crypto/aes-i586.ko
alias:          aes-asm
alias:          aes
description:    Rijndael (AES) Cipher Algorithm, asm optimized
filename:       /lib/modules/3.2.0-4-686-pae/kernel/crypto/aes_generic.ko
alias:          aes
description:    Rijndael (AES) Cipher Algorithm
filename:       /lib/modules/3.2.0-4-686-pae/kernel/crypto/cbc.ko
description:    CBC block cipher algorithm

■「cryptsetup」で「generating volume key」するなら、「luks1」フォーマットが使われる。

$ grep -A 1 "=.*crypt_format_" cryptsetup-1.4.3/lib/setup.c | grep -v else
                r = _crypt_format_plain(cd, cipher, cipher_mode,
                                        uuid, volume_key_size, params);
--
                r = _crypt_format_luks1(cd, cipher, cipher_mode,
                                        uuid, volume_key, volume_key_size, params);
--
                r = _crypt_format_loopaes(cd, cipher, uuid, volume_key_size, params);

■以下の通り、「type:    LUKS1」となっている。

$ sudo cryptsetup status luks
/dev/mapper/luks is active.
  type:    LUKS1
  cipher:  aes-cbc-essiv:sha256
  keysize: 256 bits
  device:  /dev/loop0
  loop:    /home/labunix/luks.img
  offset:  4096 sectors
  size:    200704 sectors
  mode:    read/write

■LUKS1のデフォルトではユーザのパスフレーズの入力でマウントを行う。
 「key-file」の指定はオプションになっている。

$ man cryptsetup | grep -A 10 "luksOpen <"
       luksOpen <device> <name>

              Opens the LUKS device <device> and sets up a mapping <name> after success‐
              ful verification of the supplied passphrase.  If  the  passphrase  is  not
              supplied via --key-file, the command prompts for it interactively.

              The  <device>  parameter  can be also specified by LUKS UUID in the format
              UUID=<uuid>, which uses the symlinks in /dev/disk/by-uuid.

              <options> can be [--key-file,  --keyfile-offset,  --keyfile-size,  --read‐
              only, --allow-discards, --header, --key-slot, --master-key-file].


■パスフレーズにSALT無しのハッシュを使うPLAIN MODEも可能。
 デフォルトでパスワードハッシュアルゴリズムは「ripemd160」を使用するがドライバはロードされていない。

$ man cryptsetup | grep -A 10 "^PLAIN MODE"
PLAIN MODE
       Plain  dm-crypt  encrypts  the  device sector-by-sector with a single, non-salted
       hash of the passphrase. No checks are performed, no metadata is used. There is no
       formatting  operation.  When the raw device is mapped (created), the usual device
       operations can be used on  the  mapped  device,  including  filesystem  creation.
       Mapped devices usually reside in /dev/mapper/<name>.

       There are four operations:

       create <name> <device>

■gpgで暗号化した<keyfile>と組み合わせたloopaesOpen/loopaesCloseでパスフレーズの入力をしないで済むようにも設定可能。
 「key-size」は「256 bits」がデフォルト。

$ man cryptsetup | grep -A 22 "loopaesOpen <"
       loopaesOpen <device> <name> --key-file <keyfile>

              Opens the loop-AES <device> and sets up a mapping <name>.

              If the key file is encrypted with GnuPG, then you have to use --key-file=-
              and decrypt it before use, e.g. like this:
              gpg --decrypt <keyfile> |  cryptsetup  loopaesOpen  --key-file=-  <device>
              <name>

              Use --key-file-size to specify the proper key length if needed.

              Use  --offset  to  specify  device  offset. Note that the units need to be
              specified in number of 512 byte sectors.

              Use --skip to specify the IV offset. If the original device used an offset
              and  but  did not use it in IV sector calculations, you have to explicitly
              use --skip 0 in addition to the offset parameter.

              Use --hash to override the default hash function  for  passphrase  hashing
              (otherwise it is detected according to key size).

              <options>  can  be  [--key-file,  --key-size,  --offset,  --skip,  --hash,
              --readonly, --allow-discards].