cryptsetup用kernel里的加密算法通过dm-crypt对磁盘进行加密,能使用的加密算法可以通过/proc/crypt 文件查看,但是如果想使用自己的加密算法该怎么做呢。
这里涉及到三部分,cryptsetup、dm-crypt、kernel里的加密算法模块,因为这几部分是高度模块化的,cryptsetup、dm-crypt根本不管你用什么算法加密数据,它只需要知道算法名称,然后调用该算法的加解密接口就行了,所以我们要实现扩展自己的加密算法只需要自己写一个加密模块,然后将加密算法的名称通过cryptsetup参数传到dm-crypt就可以。
该文不研究加密算法,只关系接口扩展。
先看一下luks命令行操作流程:
-
cryptsetup luksFormat /dev/centos/testcrypt -d key.bin
-
cryptsetup open /dev/centos/testcrypt qcrypt -d key.bin
-
//只有就可以执行格式化挂载等操作了。
-
mkfs.xfs /dev/mapper/qcrypt
-
mount /dev/mapper/qcrypt /mnt/test
上面luksFormat时没有指定加密算法等表示使用默认算法:
LUKS1: aes-xts-plain64, Key: 256 bits, LUKS header hashing: sha256, RNG: /dev/urandom
对上面 aes-xts-plain64不是很了解的可以参考下面:
扩展kernel里的加密算法主要是实现并注册一个struct crypto_alg结构体:
-
struct crypto_alg {
-
struct list_head cra_list;
-
struct list_head cra_users;
-
-
-
u32 cra_flags;
-
unsigned int cra_blocksize; //每一次加密操作的块大小
-
unsigned int cra_ctxsize; //
-
unsigned int cra_alignmask;
-
-
-
int cra_priority;
-
atomic_t cra_refcnt;
-
-
-
char cra_name[CRYPTO_MAX_ALG_NAME]; //算法名称,将来调用cryptsetup时需要使用
-
char cra_driver_name[CRYPTO_MAX_ALG_NAME]; //
-
-
-
const struct crypto_type *cra_type;
-
-
-
union { //加密算法实现
-
struct ablkcipher_alg ablkcipher;
-
struct aead_alg aead;
-
struct blkcipher_alg blkcipher;
-
struct cipher_alg cipher;
-
struct compress_alg compress;
-
struct rng_alg rng;
-
} cra_u;
-
-
-
int (*cra_init)(struct crypto_tfm *tfm);
-
void (*cra_exit)(struct crypto_tfm *tfm);
-
void (*cra_destroy)(struct crypto_alg *alg);
-
-
struct module *cra_module;
-
};
对比aes的实现基本也能明白每个字段的含义:
-
static struct crypto_alg aes_alg = {
-
.cra_name = "aes",
-
.cra_driver_name = "aes-generic",
-
.cra_priority = 100,
-
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
-
.cra_blocksize = AES_BLOCK_SIZE,
-
.cra_ctxsize = sizeof(struct crypto_aes_ctx),
-
.cra_alignmask = 3,
-
.cra_module = THIS_MODULE,
-
.cra_u = {
-
.cipher = {
-
.cia_min_keysize = AES_MIN_KEY_SIZE,
-
.cia_max_keysize = AES_MAX_KEY_SIZE,
-
.cia_setkey = crypto_aes_set_key,
-
.cia_encrypt = aes_encrypt,
-
.cia_decrypt = aes_decrypt
-
}
-
}
-
};
实现了该结构体后就需要将该算法注册到内核中的算法表里:
int crypto_register_alg(struct crypto_alg *alg)
注销算法:
int crypto_unregister_alg(struct crypto_alg *alg)
知道了上面这些内容基本就可以扩展一个自己的算法了:
-
static struct crypto_alg qcrypt_algs[] = { {
-
.cra_name = "qes",
-
.cra_driver_name = "qes-generic",
-
.cra_priority = 0,
-
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
-
.cra_blocksize = AES_BLOCK_SIZE,
-
.cra_ctxsize = sizeof(struct crypto_aes_ctx),
-
.cra_alignmask = 3,
-
.cra_module = THIS_MODULE,
-
.cra_u = {
-
.cipher = {
-
.cia_setkey = crypto_qes_set_key,
-
.cia_min_keysize = AES_MIN_KEY_SIZE,
-
.cia_max_keysize = AES_MAX_KEY_SIZE,
-
.cia_encrypt = qes_encrypt,
-
.cia_decrypt = qes_decrypt,
-
},
-
},
-
} };
-
-
-
-
-
static const struct x86_cpu_id qcrypt_cpu_id[] = {
-
X86_FEATURE_MATCH(X86_FEATURE_AES),
-
{}
-
};
-
MODULE_DEVICE_TABLE(x86cpu, qcrypt_cpu_id);
-
-
-
static int __init qcrypt_init(void)
-
{
-
return crypto_register_algs(qcrypt_algs, ARRAY_SIZE(qcrypt_algs));
-
}
-
-
-
static void __exit qcrypt_exit(void)
-
{
-
crypto_unregister_algs(qcrypt_algs, ARRAY_SIZE(qcrypt_algs));
-
}
-
-
-
module_init(qcrypt_init);
-
module_exit(qcrypt_exit);
-
-
-
MODULE_DESCRIPTION("Qgx Cipher Algorithm, test disk crypt");
-
MODULE_LICENSE("GPL");
-
MODULE_ALIAS("qcrypt");
crypto_qes_set_key、qes_encrypt、qes_decrypt可以直接参考aes实现,编译加载模块后就能在 /proc/crypt里看到自己的算法qes了。
使用该算法加密磁盘:
cryptsetup luksFormat /dev/centos/testcrypt -d key.bin -c qes-cbc-plain64
cryptsetup open /dev/centos/testcrypt qcrypt -d key.bin
mkfs.xfs /dev/mapper/qcrypt
mount /dev/mapper/qcrypt /mnt/test
阅读(8063) | 评论(0) | 转发(0) |