Linux Crypto(2):使用者层-用户空间(AF_ALG、add_key()/request_key()/keyctl()等)
Linux Crypto 子系统为用户空间提供了丰富而强大的加密能力,主要通过以下接口实现:
| 接口类型 | 主要作用 | 用户空间工具 | 内核对应模块 | 典型使用场景 |
|---|---|---|---|---|
| AF_ALG套接字 | 提供流式加密API | OpenSSL (afalg引擎) | crypto/af_alg.c |
实时网络加密/文件流加密 |
| Netlink接口 | 动态算法管理 | cryptouser (自定义) |
crypto/crypto_user.c |
算法加载/卸载/状态监控 |
| /proc/crypto | 算法信息查询 | cat, grep |
crypto/proc.c |
系统诊断/算法选择 |
| 密钥系统调用 | 安全密钥管理 | keyctl |
security/keys/ |
加密卷密钥/安全启动密钥 |
| 设备映射ioctl | 块设备加密管理 | cryptsetup |
drivers/md/dm-ioctl.c |
全盘加密/分区加密 |
| dmsetup控制 | 底层设备映射操作 | dmsetup |
drivers/md/dm-ioctl.c |
高级存储配置/故障诊断 |
| 磁盘加密设备 | 透明块设备加密 | cryptsetup open |
drivers/md/dm-crypt.c |
加密卷日常访问 |
2 AF_ALG套接字接口
功能特性
1. 算法组合支持:支持模板语法如 cbc(aes)
2. 零拷贝优化:避免不必要的数据复制
3. 硬件加速透明:自动选择最优实现
4. 异步操作:最大化硬件利用率
af_alg_init ->proto_register--注册alg_proto协议结构体。 ->sock_register--注册alg_family套接字协议族。 ->alg_create--创建ALG套接字核心函数。 ->sk_alloc--分配套接字内核对象,将具体的PF_ALG socket和alg_proto联系起来。 ->sock_init_data--初始化套接字数据结构,其操作函数集为alg_proto_ops。 ->alg_sock_destruct--定义套接字销毁回调。
alg_proto_ops定义了PF_ALG类型socket 系统调用的函数实现:
static const struct proto_ops alg_proto_ops = { .family = PF_ALG, -- 协议族标识:ALG类型 .owner = THIS_MODULE, -- 模块所有者:当前模块 .connect = sock_no_connect, -- 禁用连接操作 .socketpair = sock_no_socketpair, -- 禁用socketpair创建 .getname = sock_no_getname, -- 禁用获取套接字名 .ioctl = sock_no_ioctl, -- 禁用ioctl控制 .listen = sock_no_listen, -- 禁用监听操作 .shutdown = sock_no_shutdown, -- 禁用关闭连接 .mmap = sock_no_mmap, -- 禁用内存映射 .sendpage = sock_no_sendpage, -- 禁用页面发送 .sendmsg = sock_no_sendmsg, -- 禁用消息发送 .recvmsg = sock_no_recvmsg, -- 禁用消息接收 .bind = alg_bind, -- 绑定加密算法到套接字 .release = af_alg_release, -- 释放套接字资源 .setsockopt = alg_setsockopt, -- 设置套接字选项 .accept = alg_accept, -- 接受算法会话请求 };
通过openssl使用AF_ALG进行测试:
# 1. 创建测试文件 dd if=/dev/urandom of=testfile bs=1M count=100 # 2. 使用AF_ALG加密 time openssl enc -aes-256-cbc -in testfile -out testfile.enc \ -pass pass:test -md sha256 -engine afalg -pbkdf2 -iter 100000 # 3. 解密验证 time openssl enc -d -aes-256-cbc -in testfile.enc -out testfile.dec \ -pass pass:test -md sha256 -engine afalg -pbkdf2 -iter 100000 # 4. 完整性检查 diff testfile testfile.dec && echo "加密/解密完整"
3 Netlink接口
netlink crypto_user 是 Linux 内核中用于加密子系统(Crypto API)的用户空间通信接口,基于 Netlink 协议实现。它允许用户空间程序动态查询、配置和管理内核中的加密算法(如 AES、SHA 等)。以下是其核心作用说明:
1. 算法查询
- 获取内核支持的加密算法列表(如 aes-cbc, sha256)。
- 查看算法详细信息(优先级、驱动名称、密钥长度等)。
2. 动态管理
- 添加/删除算法模板(如 cbc(aes))。
- 配置算法属性(如优先级调整)。
3. 状态监控
- 接收算法注册/注销的实时通知(通过 Netlink 多播组)。
crypto_user_init -> register_pernet_subsys -- 注册网络命名空间子系统 -> crypto_netlink_net_ops -- 每个网络命名空间的初始化操作 -> crypto_netlink_init -- 网络命名空间初始化函数 -> netlink_kernel_create -- 创建内核级Netlink套接字 [创建参数:] NETLINK_CRYPTO, // 专用Netlink协议号 crypto_netlink_rcv // 接收回调函数 ->crypto_netlink_rcv -- 核心接收函数 -> netlink_rcv_skb -- Netlink消息处理框架 -> crypto_user_rcv_msg -- 消息分发处理器 -- 根据type找到对应消息类型的crypto_link处理函数 [处理步骤:] 1. netlink_dump_start -- 启动数据转储(批量查询) 2. nlmsg_parse_deprecated -- 解析消息属性 3. link->doit -- 执行具体操作
支持的类型包括:
enum { CRYPTO_MSG_BASE = 0x10, // 消息类型起始值(避免与系统消息冲突) CRYPTO_MSG_NEWALG = 0x10, // 注册新算法(如 cbc(aes)) CRYPTO_MSG_DELALG, // 删除算法(需管理员权限) CRYPTO_MSG_UPDATEALG, // 更新算法属性(如优先级) CRYPTO_MSG_GETALG, // 查询算法信息(最常用) CRYPTO_MSG_DELRNG, // 删除随机数生成器(RNG) CRYPTO_MSG_GETSTAT, // 获取加密子系统统计信息 __CRYPTO_MSG_MAX // 消息类型最大值(用于边界检查) };
4 /proc/crypto
/proc/crypto 是 Linux 内核提供的一个虚拟文件,它不是一个独立的“项目”,而是 Linux 内核加密子系统 (crypto API) 的一个关键接口。它的主要作用是向用户空间(系统管理员、开发者、安全工具)动态展示当前正在运行的内核所支持的所有加密算法及其详细信息。
核心功能与作用:
1. 实时算法清单: 提供一份内核当前可用的所有加密算法、哈希算法、认证算法、随机数生成器(RNG)、压缩算法等的完整列表。这包括:
- 对称密码: AES, DES, 3DES, ChaCha20, Salsa20, Serpent, Twofish, CAST5, Blowfish 等(包括 ECB, CBC, CTR, XTS, GCM, CCM 等多种模式)。
- 非对称密码: RSA, DSA, ECDSA, DH, ECDH 等(通常由内核模块或硬件加速提供)。
- 哈希函数: SHA-1, SHA-256, SHA-512, MD5, BLAKE2b/s, SM3 等。
- 消息认证码: HMAC, CMAC, CBC-MAC, Poly1305 等。
- 认证加密: AES-GCM, AES-CCM, ChaCha20-Poly1305 等(作为组合模式列出)。
- 压缩算法: Deflate。
- 随机数生成器: 如 stdrng (指向当前选择的默认 RNG), drbg_nopr_hmac_sha256 等。
- 其他杂项: 如 ansi_cprng, jitterentropy_rng 等。
2. 算法详细信息: 对于列出的每个算法,/proc/crypto 提供了丰富的元数据,包括:
- name: 算法的标准名称(例如 ctr(aes), sha256, ecb(des3_ede))。
- driver: 实现该算法的具体内核驱动或模块(例如 aes-generic, aesni-intel, ccp, kernel 等)。这是识别算法是由软件(通用实现)、特定 CPU 指令集(如 AES-NI)还是专用硬件(如加密加速卡)实现的关键。
- module: 提供该算法的内核模块名称(如果算法是模块化加载的)。
- priority: 算法的优先级(数值)。当同一个算法有多个实现(如通用软件实现和硬件加速实现)时,内核会选择优先级最高的实现来使用。
- refcnt: 引用计数,表示当前有多少用户(如 IPsec SA、dm-crypt 设备)正在使用该算法。
- selftest: 算法是否通过了内核内置的自检 (passed)。
- type: 算法类型(例如 skcipher, cipher, shash, ahash, akcipher, kpp, acomp, rng)。这决定了算法提供哪些操作接口。
- blocksize: 算法的块大小(对于分组密码和哈希)。
- digestsize: 哈希摘要的长度(对于哈希和 MAC)。
- ivsize: 初始化向量 (IV) 的长度(对于需要 IV 的加密模式)。
- seedsize: 种子长度(对于 DRBG)。
- chunksize: 内部处理块大小(主要针对流式哈希/AHASH)。
- key 相关信息: 最小/最大密钥长度、是否支持设置密钥 (setkey)。
- async: 标志位,指示该算法实现是否支持异步操作(利用硬件加速时非常重要,允许加密操作不阻塞 CPU)。
- internal: 标志位,指示该算法是否仅供内部使用(通常不可直接通过用户空间接口调用)。
5 密钥系统调用以及keyctl
密钥系统调用如下:
| 系统调用 | 功能描述 | 主要用途 | 权限要求 |
|---|---|---|---|
add_key() |
创建新密钥或密钥环 | 添加用户密钥、创建密钥环、存储加密密钥 | 对目标密钥环有write权限 |
request_key() |
请求密钥(可触发用户空间协助) | 动态获取加密密钥(如eCryptfs)、自动获取认证凭据 | 对目标密钥环有search和link权限 |
keyctl() |
密钥管理综合操作 | 更新/撤销/读取密钥、搜索密钥环、设置权限、密钥环管理 | 各子操作独立权限检查 |
keyctl命令使用这些系统调用进行密钥管理。
浙公网安备 33010602011771号