keyctl – 密钥管理控制接口

keyctl – 密钥管理控制接口

1. 函数介绍

keyctl 是一个 Linux 系统调用,用于管理和操作内核密钥保留服务(Key Retention Service)。它提供了对内核密钥管理子系统的完整控制接口,允许进程创建、检索、更新和删除各种类型的密钥。

密钥保留服务是 Linux 内核的安全基础设施组件,用于安全地存储和管理密钥、密码、证书等敏感信息。

2. 函数原型

#include <sys/types.h>
#include <keyutils.h>

long keyctl(int cmd, ...);

注意:这不是标准 C 库函数,需要通过 syscall() 调用或使用 libkeyutils 库。

3. 功能

执行各种密钥管理操作,包括:

  • 创建和删除密钥
  • 设置和获取密钥属性
  • 链接和取消链接密钥
  • 搜索和查找密钥
  • 设置密钥权限
  • 管理密钥环

4. 常用命令参数

// 密钥管理命令
#define KEYCTL_GET_KEYRING_ID     0  /* 获取密钥环 ID */
#define KEYCTL_JOIN_SESSION_KEYRING 1  /* 加入会话密钥环 */
#define KEYCTL_UPDATE             2  /* 更新密钥 */
#define KEYCTL_REVOKE             3  /* 撤销密钥 */
#define KEYCTL_CHOWN              4  /* 更改密钥所有者 */
#define KEYCTL_SETPERM            5  /* 设置密钥权限 */
#define KEYCTL_DESCRIBE           6  /* 描述密钥 */
#define KEYCTL_CLEAR              7  /* 清空密钥环 */
#define KEYCTL_LINK               8  /* 链接密钥 */
#define KEYCTL_UNLINK             9  /* 取消链接密钥 */
#define KEYCTL_SEARCH            10  /* 搜索密钥 */
#define KEYCTL_READ              11  /* 读取密钥 */
#define KEYCTL_INSTANTIATE       12  /* 实例化密钥 */
#define KEYCTL_NEGATE            13  /* 否定密钥 */
#define KEYCTL_SET_REQKEY_KEYRING 14 /* 设置请求密钥环 */
#define KEYCTL_SET_TIMEOUT       15  /* 设置密钥超时 */
#define KEYCTL_ASSUME_AUTHORITY  16  /* 假设权限 */
#define KEYCTL_GET_SECURITY      17  /* 获取安全上下文 */
#define KEYCTL_SESSION_TO_PARENT 18  /* 会话到父进程 */
#define KEYCTL_REJECT            19  /* 拒绝密钥 */
#define KEYCTL_INSTANTIATE_IOV   20  /* 实例化密钥 (iov) */
#define KEYCTL_INVALIDATE        21  /* 使密钥无效 */
#define KEYCTL_GET_PERSISTENT    22  /* 获取持久密钥环 */

5. 密钥类型

// 常见密钥类型
"user"        // 用户定义的密钥
"logon"       // 登录凭证密钥
"trusted"     // 受信任的密钥
"encrypted"   // 加密密钥
"dns_resolver" // DNS 解析器密钥
"rxrpc"       // RxRPC 密钥
"syzkaller"   // 系统调用模糊测试密钥

6. 返回值

  • 成功时:返回值取决于具体命令
  • 失败时:返回 -1,并设置 errno

7. 常见 errno 错误码

  • ENOKEY: 密钥不存在
  • EKEYEXPIRED: 密钥已过期
  • EKEYREVOKED: 密钥已被撤销
  • EACCES: 权限不足
  • EPERM: 操作被拒绝
  • EINVAL: 参数无效
  • ENOMEM: 内存不足
  • EDQUOT: 配额超限
  • EOPNOTSUPP: 操作不支持

8. 相似函数,或关联函数

  • add_key(): 添加新密钥
  • request_key(): 请求密钥
  • keyctl() 系列函数
  • /sbin/keyctl: 用户态密钥管理工具
  • /proc/keys: 查看系统密钥信息
  • /proc/key-users: 查看密钥用户信息

9. 示例代码

示例1:基本使用 – 密钥创建和管理

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <keyutils.h>
#include <errno.h>
#include <string.h>

#ifndef SYS_keyctl
# define SYS_keyctl 250  // x86_64 架构下的系统调用号
#endif

// keyctl 系统调用包装函数
long keyctl_wrapper(int cmd, ...) {
    va_list args;
    va_start(args, cmd);
    long result = syscall(SYS_keyctl, cmd, va_arg(args, long), 
                         va_arg(args, long), va_arg(args, long), 
                         va_arg(args, long));
    va_end(args);
    return result;
}

int main() {
    printf("=== keyctl 基本使用演示 ===\n");
    
    // 检查密钥支持
    key_serial_t session_keyring = keyctl(KEYCTL_GET_KEYRING_ID, 
                                         KEY_SPEC_SESSION_KEYRING, 0);
    if (session_keyring == -1) {
        printf("错误: 系统不支持密钥保留服务: %s\n", strerror(errno));
        return 1;
    }
    
    printf("✓ 密钥保留服务可用\n");
    printf("会话密钥环 ID: %d\n", session_keyring);
    
    // 创建一个用户密钥
    const char *key_desc = "my_test_key";
    const char *key_data = "This is my secret data";
    
    key_serial_t key = add_key("user", key_desc, key_data, strlen(key_data), 
                              KEY_SPEC_SESSION_KEYRING);
    if (key == -1) {
        printf("创建密钥失败: %s\n", strerror(errno));
        return 1;
    }
    
    printf("✓ 成功创建密钥,ID: %d\n", key);
    
    // 描述密钥
    char description[256];
    long desc_len = keyctl(KEYCTL_DESCRIBE, key, (long)description, 
                          sizeof(description), 0);
    if (desc_len != -1) {
        description[desc_len] = '\0';
        printf("密钥描述: %s\n", description);
    }
    
    // 读取密钥数据
    char read_data[256];
    long data_len = keyctl(KEYCTL_READ, key, (long)read_data, 
                          sizeof(read_data), 0);
    if (data_len != -1) {
        read_data[data_len] = '\0';
        printf("密钥数据: %s\n", read_data);
    }
    
    // 设置密钥超时(30秒后过期)
    if (keyctl(KEYCTL_SET_TIMEOUT, key, 30, 0, 0) == 0) {
        printf("✓ 设置密钥超时为 30 秒\n");
    }
    
    // 获取密钥安全上下文
    char security_context[256];
    long sec_len = keyctl(KEYCTL_GET_SECURITY, key, 
                         (long)security_context, sizeof(security_context), 0);
    if (sec_len != -1) {
        security_context[sec_len] = '\0';
        printf("安全上下文: %s\n", security_context);
    }
    
    // 撤销密钥
    if (keyctl(KEYCTL_REVOKE, key, 0, 0, 0) == 0) {
        printf("✓ 成功撤销密钥\n");
    }
    
    return 0;
}

示例2:密钥环操作

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <keyutils.h>
#include <errno.h>
#include <string.h>

void demonstrate_keyring_operations() {
    printf("=== 密钥环操作演示 ===\n");
    
    // 获取各种密钥环 ID
    key_serial_t session_ring = keyctl(KEYCTL_GET_KEYRING_ID, 
                                      KEY_SPEC_SESSION_KEYRING, 0);
    key_serial_t process_ring = keyctl(KEYCTL_GET_KEYRING_ID, 
                                      KEY_SPEC_PROCESS_KEYRING, 0);
    key_serial_t thread_ring = keyctl(KEYCTL_GET_KEYRING_ID, 
                                     KEY_SPEC_THREAD_KEYRING, 0);
    
    printf("密钥环 ID:\n");
    printf("  会话密钥环: %d\n", session_ring);
    printf("  进程密钥环: %d\n", process_ring);
    printf("  线程密钥环: %d\n", thread_ring);
    
    // 创建自定义密钥环
    key_serial_t custom_ring = add_key("keyring", "my_custom_ring", 
                                      NULL, 0, KEY_SPEC_SESSION_KEYRING);
    if (custom_ring != -1) {
        printf("✓ 创建自定义密钥环: %d\n", custom_ring);
        
        // 在自定义密钥环中创建密钥
        key_serial_t ring_key = add_key("user", "ring_key", 
                                       "data in ring", 12, custom_ring);
        if (ring_key != -1) {
            printf("✓ 在自定义密钥环中创建密钥: %d\n", ring_key);
        }
        
        // 清空自定义密钥环
        if (keyctl(KEYCTL_CLEAR, custom_ring, 0, 0, 0) == 0) {
            printf("✓ 清空自定义密钥环\n");
        }
        
        // 撤销自定义密钥环
        if (keyctl(KEYCTL_REVOKE, custom_ring, 0, 0, 0) == 0) {
            printf("✓ 撤销自定义密钥环\n");
        }
    }
    
    // 加入新的会话密钥环
    key_serial_t new_session = keyctl(KEYCTL_JOIN_SESSION_KEYRING, 
                                     (long)"new_session", 0, 0, 0);
    if (new_session != -1) {
        printf("✓ 加入新的会话密钥环: %d\n", new_session);
    }
}

void demonstrate_key_search() {
    printf("\n=== 密钥搜索演示 ===\n");
    
    // 创建测试密钥
    key_serial_t test_key = add_key("user", "search_test", 
                                   "search data", 11, 
                                   KEY_SPEC_SESSION_KEYRING);
    if (test_key == -1) {
        printf("创建测试密钥失败: %s\n", strerror(errno));
        return;
    }
    
    printf("创建测试密钥: %d\n", test_key);
    
    // 搜索密钥
    key_serial_t found_key = keyctl(KEYCTL_SEARCH, 
                                   KEY_SPEC_SESSION_KEYRING,
                                   (long)"user", (long)"search_test", 0);
    if (found_key != -1) {
        printf("✓ 找到密钥: %d\n", found_key);
        
        // 验证找到的密钥
        if (found_key == test_key) {
            printf("✓ 验证成功:找到的密钥 ID 匹配\n");
        }
    } else {
        printf("搜索密钥失败: %s\n", strerror(errno));
    }
    
    // 撤销测试密钥
    keyctl(KEYCTL_REVOKE, test_key, 0, 0, 0);
}

void demonstrate_key_permissions() {
    printf("\n=== 密钥权限演示 ===\n");
    
    // 创建测试密钥
    key_serial_t perm_key = add_key("user", "perm_test", 
                                   "permission data", 15, 
                                   KEY_SPEC_SESSION_KEYRING);
    if (perm_key == -1) {
        printf("创建权限测试密钥失败: %s\n", strerror(errno));
        return;
    }
    
    printf("创建权限测试密钥: %d\n", perm_key);
    
    // 设置密钥权限
    // 权限格式: possessor|user|group|other
    // 每个字段: view|read|write|search|link|setattr|all
    key_perm_t permissions = KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ;
    
    if (keyctl(KEYCTL_SETPERM, perm_key, permissions, 0, 0) == 0) {
        printf("✓ 设置密钥权限成功\n");
        
        // 描述密钥查看权限
        char desc[256];
        long desc_len = keyctl(KEYCTL_DESCRIBE, perm_key, 
                              (long)desc, sizeof(desc), 0);
        if (desc_len != -1) {
            desc[desc_len] = '\0';
            printf("更新后的密钥描述: %s", desc);
        }
    } else {
        printf("设置密钥权限失败: %s\n", strerror(errno));
    }
    
    // 更改密钥所有者(需要特权)
    if (keyctl(KEYCTL_CHOWN, perm_key, getuid(), 0, 0) == 0) {
        printf("✓ 更改密钥所有者成功\n");
    } else {
        if (errno == EPERM) {
            printf("ℹ 更改所有者需要特权权限\n");
        } else {
            printf("更改所有者失败: %s\n", strerror(errno));
        }
    }
    
    // 撤销密钥
    keyctl(KEYCTL_REVOKE, perm_key, 0, 0, 0);
}

int main() {
    printf("=== keyctl 密钥环操作演示 ===\n");
    
    // 检查密钥支持
    if (keyctl(KEYCTL_GET_KEYRING_ID, KEY_SPEC_SESSION_KEYRING, 0) == -1) {
        printf("错误: 系统不支持密钥保留服务\n");
        return 1;
    }
    
    demonstrate_keyring_operations();
    demonstrate_key_search();
    demonstrate_key_permissions();
    
    return 0;
}

示例3:密钥安全和加密操作

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <keyutils.h>
#include <errno.h>
#include <string.h>
#include <time.h>

void demonstrate_encrypted_keys() {
    printf("=== 加密密钥演示 ===\n");
    
    // 检查是否支持加密密钥
    printf("系统支持的密钥类型:\n");
    system("cat /proc/key-types 2>/dev/null | grep -E 'user|encrypted|trusted' || "
           "echo '无法读取密钥类型信息'");
    
    // 创建用户密钥(基础加密)
    const char *encrypted_data = "sensitive_encrypted_data";
    key_serial_t enc_key = add_key("user", "encrypted_secret", 
                                  encrypted_data, strlen(encrypted_data),
                                  KEY_SPEC_SESSION_KEYRING);
    
    if (enc_key != -1) {
        printf("✓ 创建加密数据密钥: %d\n", enc_key);
        
        // 设置超时以增强安全性
        if (keyctl(KEYCTL_SET_TIMEOUT, enc_key, 300, 0, 0) == 0) {  // 5分钟
            printf("✓ 设置密钥超时为 5 分钟\n");
        }
        
        // 读取密钥数据
        char buffer[256];
        long read_len = keyctl(KEYCTL_READ, enc_key, (long)buffer, 
                              sizeof(buffer), 0);
        if (read_len != -1) {
            buffer[read_len] = '\0';
            printf("读取加密数据长度: %ld 字节\n", read_len);
        }
    } else {
        printf("创建加密密钥失败: %s\n", strerror(errno));
    }
}

void demonstrate_key_lifecycle() {
    printf("\n=== 密钥生命周期管理 ===\n");
    
    // 创建密钥
    const char *key_data = "lifecycle_test_data";
    key_serial_t key = add_key("user", "lifecycle_test", 
                              key_data, strlen(key_data),
                              KEY_SPEC_SESSION_KEYRING);
    
    if (key == -1) {
        printf("创建密钥失败: %s\n", strerror(errno));
        return;
    }
    
    printf("1. 创建密钥: %d\n", key);
    
    // 描述密钥状态
    char desc[256];
    long desc_len = keyctl(KEYCTL_DESCRIBE, key, (long)desc, sizeof(desc), 0);
    if (desc_len != -1) {
        desc[desc_len] = '\0';
        printf("2. 密钥状态: %s", desc);
    }
    
    // 更新密钥数据
    const char *new_data = "updated_lifecycle_data";
    if (keyctl(KEYCTL_UPDATE, key, (long)new_data, strlen(new_data), 0) == 0) {
        printf("3. ✓ 更新密钥数据成功\n");
    }
    
    // 设置短期超时
    if (keyctl(KEYCTL_SET_TIMEOUT, key, 10, 0, 0) == 0) {  // 10秒
        printf("4. ✓ 设置 10 秒超时\n");
    }
    
    // 等待几秒观察超时效果
    printf("5. 等待 12 秒观察超时效果...\n");
    sleep(12);
    
    // 尝试访问已过期的密钥
    char buffer[256];
    long read_len = keyctl(KEYCTL_READ, key, (long)buffer, sizeof(buffer), 0);
    if (read_len == -1) {
        if (errno == EKEYEXPIRED) {
            printf("6. ✓ 密钥已正确过期\n");
        } else {
            printf("6. 访问密钥失败: %s\n", strerror(errno));
        }
    }
    
    // 撤销密钥(即使已过期)
    if (keyctl(KEYCTL_REVOKE, key, 0, 0, 0) == 0) {
        printf("7. ✓ 撤销密钥成功\n");
    }
}

void demonstrate_key_security_analysis() {
    printf("\n=== 密钥安全分析 ===\n");
    
    // 显示当前用户的密钥使用情况
    printf("当前密钥使用情况:\n");
    system("cat /proc/key-users 2>/dev/null | head -10 || echo '无法读取密钥用户信息'");
    
    // 显示系统密钥信息
    printf("\n系统密钥信息:\n");
    system("cat /proc/keys 2>/dev/null | head -10 || echo '无法读取密钥信息'");
    
    // 显示密钥配额信息
    printf("\n密钥配额信息:\n");
    system("cat /proc/sys/kernel/keys/* 2>/dev/null || echo '无法读取密钥配额'");
    
    // 安全建议
    printf("\n密钥安全最佳实践:\n");
    printf("  • 使用适当的超时设置\n");
    printf("  • 设置最小必要权限\n");
    printf("  • 定期清理过期密钥\n");
    printf("  • 避免在日志中记录密钥数据\n");
    printf("  • 使用加密存储敏感数据\n");
    printf("  • 监控密钥使用情况\n");
}

int main() {
    printf("=== keyctl 安全和加密操作演示 ===\n");
    
    // 检查密钥支持
    if (keyctl(KEYCTL_GET_KEYRING_ID, KEY_SPEC_SESSION_KEYRING, 0) == -1) {
        printf("错误: 系统不支持密钥保留服务\n");
        return 1;
    }
    
    printf("✓ 密钥保留服务可用\n");
    
    demonstrate_encrypted_keys();
    demonstrate_key_lifecycle();
    demonstrate_key_security_analysis();
    
    return 0;
}

示例4:密钥管理工具和监控

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <keyutils.h>
#include <errno.h>
#include <string.h>
#include <time.h>

void show_key_statistics() {
    printf("=== 密钥统计信息 ===\n");
    
    // 显示密钥数量
    printf("系统密钥统计:\n");
    system("wc -l /proc/keys 2>/dev/null | awk '{print \"总密钥数: \" $1-1}' || "
           "echo '无法统计密钥数量'");
    
    // 显示密钥用户信息
    printf("\n密钥用户统计:\n");
    system("cat /proc/key-users 2>/dev/null | head -5 || echo '无法读取用户统计'");
    
    // 显示密钥类型分布
    printf("\n密钥类型分布:\n");
    system("awk '{print $4}' /proc/keys 2>/dev/null | sort | uniq -c | head -10 || "
           "echo '无法分析密钥类型'");
}

void interactive_key_manager() {
    int choice;
    char input[256];
    
    while (1) {
        printf("\n=== 密钥管理菜单 ===\n");
        printf("1. 列出当前密钥\n");
        printf("2. 创建新密钥\n");
        printf("3. 查找密钥\n");
        printf("4. 删除密钥\n");
        printf("5. 显示密钥统计\n");
        printf("6. 清空会话密钥环\n");
        printf("0. 退出\n");
        printf("请选择操作: ");
        
        if (scanf("%d", &choice) != 1) {
            printf("输入无效,请重新选择\n");
            while (getchar() != '\n');  // 清空输入缓冲区
            continue;
        }
        
        switch (choice) {
            case 1:
                printf("当前会话密钥:\n");
                system("keyctl list @s 2>/dev/null || echo '无法列出密钥'");
                break;
                
            case 2: {
                printf("输入密钥描述: ");
                scanf("%255s", input);
                
                printf("输入密钥数据: ");
                scanf("%255s", input + 128);  // 简化处理
                
                key_serial_t new_key = add_key("user", input, 
                                              input + 128, 
                                              strlen(input + 128),
                                              KEY_SPEC_SESSION_KEYRING);
                if (new_key != -1) {
                    printf("✓ 成功创建密钥: %d\n", new_key);
                } else {
                    printf("❌ 创建密钥失败: %s\n", strerror(errno));
                }
                break;
            }
            
            case 3: {
                printf("输入要查找的密钥描述: ");
                scanf("%255s", input);
                
                key_serial_t found_key = keyctl(KEYCTL_SEARCH,
                                               KEY_SPEC_SESSION_KEYRING,
                                               (long)"user", (long)input, 0);
                if (found_key != -1) {
                    printf("✓ 找到密钥: %d\n", found_key);
                } else {
                    printf("❌ 未找到密钥: %s\n", strerror(errno));
                }
                break;
            }
            
            case 4: {
                printf("输入要删除的密钥 ID: ");
                int key_id;
                if (scanf("%d", &key_id) == 1) {
                    if (keyctl(KEYCTL_REVOKE, key_id, 0, 0, 0) == 0) {
                        printf("✓ 成功撤销密钥: %d\n", key_id);
                    } else {
                        printf("❌ 撤销密钥失败: %s\n", strerror(errno));
                    }
                } else {
                    printf("输入无效\n");
                }
                break;
            }
            
            case 5:
                show_key_statistics();
                break;
                
            case 6:
                if (keyctl(KEYCTL_CLEAR, KEY_SPEC_SESSION_KEYRING, 0, 0, 0) == 0) {
                    printf("✓ 成功清空会话密钥环\n");
                } else {
                    printf("❌ 清空密钥环失败: %s\n", strerror(errno));
                }
                break;
                
            case 0:
                printf("退出密钥管理工具\n");
                return;
                
            default:
                printf("无效选择,请重新输入\n");
                break;
        }
    }
}

void demonstrate_advanced_key_operations() {
    printf("\n=== 高级密钥操作 ===\n");
    
    // 创建密钥环
    key_serial_t keyring = add_key("keyring", "advanced_test_ring", 
                                  NULL, 0, KEY_SPEC_SESSION_KEYRING);
    if (keyring != -1) {
        printf("✓ 创建测试密钥环: %d\n", keyring);
        
        // 在密钥环中创建多个密钥
        for (int i = 1; i <= 3; i++) {
            char desc[32], data[32];
            snprintf(desc, sizeof(desc), "key_%d", i);
            snprintf(data, sizeof(data), "data_%d", i);
            
            key_serial_t key = add_key("user", desc, data, strlen(data), keyring);
            if (key != -1) {
                printf("  ✓ 创建密钥 %s: %d\n", desc, key);
            }
        }
        
        // 列出密钥环内容
        printf("密钥环内容:\n");
        char buffer[1024];
        long len = keyctl(KEYCTL_READ, keyring, (long)buffer, sizeof(buffer), 0);
        if (len != -1) {
            // 简化显示
            printf("  密钥环包含 %ld 字节数据\n", len);
        }
        
        // 清空密钥环
        if (keyctl(KEYCTL_CLEAR, keyring, 0, 0, 0) == 0) {
            printf("✓ 清空密钥环成功\n");
        }
        
        // 撤销密钥环
        keyctl(KEYCTL_REVOKE, keyring, 0, 0, 0);
    }
}

void key_monitoring_demo() {
    printf("\n=== 密钥监控演示 ===\n");
    
    printf("实时密钥监控 (按 Ctrl+C 停止):\n");
    
    // 显示初始状态
    printf("初始密钥数量: ");
    system("wc -l /proc/keys 2>/dev/null | awk '{print $1-1}' || echo 'unknown'");
    
    // 创建测试密钥并监控变化
    key_serial_t test_key = add_key("user", "monitor_test", 
                                   "monitor data", 12, 
                                   KEY_SPEC_SESSION_KEYRING);
    if (test_key != -1) {
        printf("创建测试密钥后数量: ");
        system("wc -l /proc/keys 2>/dev/null | awk '{print $1-1}' || echo 'unknown'");
        
        // 撤销密钥
        keyctl(KEYCTL_REVOKE, test_key, 0, 0, 0);
        printf("撤销测试密钥后数量: ");
        system("wc -l /proc/keys 2>/dev/null | awk '{print $1-1}' || echo 'unknown'");
    }
}

int main() {
    printf("=== keyctl 高级管理和监控工具 ===\n");
    
    // 检查密钥支持
    if (keyctl(KEYCTL_GET_KEYRING_ID, KEY_SPEC_SESSION_KEYRING, 0) == -1) {
        printf("错误: 系统不支持密钥保留服务\n");
        return 1;
    }
    
    printf("✓ 密钥保留服务可用\n");
    
    // 显示系统信息
    printf("\n系统密钥信息:\n");
    system("uname -a");
    
    // 执行高级操作演示
    demonstrate_advanced_key_operations();
    
    // 显示统计信息
    show_key_statistics();
    
    // 监控演示
    key_monitoring_demo();
    
    // 启动交互式管理器(如果需要)
    char choice;
    printf("\n是否启动交互式密钥管理器? (y/N): ");
    if (scanf(" %c", &choice) == 1 && (choice == 'y' || choice == 'Y')) {
        interactive_key_manager();
    }
    
    return 0;
}

10. 密钥权限说明

// 密钥权限位定义
#define KEY_POS_VIEW    0x01000000  /* 持有者可查看 */
#define KEY_POS_READ    0x02000000  /* 持有者可读取 */
#define KEY_POS_WRITE   0x04000000  /* 持有者可写入 */
#define KEY_POS_SEARCH  0x08000000  /* 持有者可搜索 */
#define KEY_POS_LINK    0x10000000  /* 持有者可链接 */
#define KEY_POS_SETATTR 0x20000000  /* 持有者可设置属性 */
#define KEY_POS_ALL     0x3f000000  /* 持有者所有权限 */

#define KEY_USR_VIEW    0x00010000  /* 用户可查看 */
#define KEY_USR_READ    0x00020000  /* 用户可读取 */
#define KEY_USR_WRITE   0x00040000  /* 用户可写入 */
#define KEY_USR_SEARCH  0x00080000  /* 用户可搜索 */
#define KEY_USR_LINK    0x00100000  /* 用户可链接 */
#define KEY_USR_SETATTR 0x00200000  /* 用户可设置属性 */
#define KEY_USR_ALL     0x003f0000  /* 用户所有权限 */

#define KEY_GRP_VIEW    0x00000100  /* 组可查看 */
#define KEY_GRP_READ    0x00000200  /* 组可读取 */
#define KEY_GRP_WRITE   0x00000400  /* 组可写入 */
#define KEY_GRP_SEARCH  0x00000800  /* 组可搜索 */
#define KEY_GRP_LINK    0x00001000  /* 组可链接 */
#define KEY_GRP_SETATTR 0x00002000  /* 组可设置属性 */
#define KEY_GRP_ALL     0x00003f00  /* 组所有权限 */

#define KEY_OTH_VIEW    0x00000001  /* 其他可查看 */
#define KEY_OTH_READ    0x00000002  /* 其他可读取 */
#define KEY_OTH_WRITE   0x00000004  /* 其他可写入 */
#define KEY_OTH_SEARCH  0x00000008  /* 其他可搜索 */
#define KEY_OTH_LINK    0x00000010  /* 其他可链接 */
#define KEY_OTH_SETATTR 0x00000020  /* 其他可设置属性 */
#define KEY_OTH_ALL     0x0000003f  /* 其他所有权限 */

11. 实际应用场景

场景1:网络认证

void network_authentication_keys() {
    // 存储网络认证凭证
    add_key("user", "wifi_password", "secret123", 9, 
            KEY_SPEC_SESSION_KEYRING);
}

场景2:文件系统加密

void filesystem_encryption_keys() {
    // 存储加密文件系统密钥
    add_key("encrypted", "fs_encryption_key", key_data, key_len,
            KEY_SPEC_SESSION_KEYRING);
}

场景3:安全通信

void secure_communication_keys() {
    // 存储 TLS/SSL 会话密钥
    add_key("user", "tls_session_key", session_key, key_len,
            KEY_SPEC_PROCESS_KEYRING);
}

12. 注意事项

使用 keyctl 时需要注意:

  1. 权限要求: 某些操作需要特殊权限
  2. 内存安全: 密钥数据在内存中的安全处理
  3. 生命周期: 正确管理密钥的创建、使用和销毁
  4. 超时设置: 合理设置密钥超时以增强安全性
  5. 权限控制: 设置最小必要权限
  6. 系统资源: 监控密钥使用对系统资源的影响

13. 系统配置检查

# 检查密钥支持
grep CONFIG_KEYS /boot/config-$(uname -r)

# 查看密钥信息
cat /proc/keys
cat /proc/key-users

# 检查密钥配额
cat /proc/sys/kernel/keys/maxkeys
cat /proc/sys/kernel/keys/maxbytes

# 使用 keyctl 工具
keyctl list @s
keyctl show

总结

keyctl 是 Linux 系统中强大的密钥管理接口:

关键特性:
1. 安全存储: 内核级密钥安全存储
2. 权限控制: 细粒度的访问控制
3. 生命周期管理: 完整的密钥生命周期控制
4. 多种密钥类型: 支持各种应用场景
5. 系统集成: 与 Linux 安全子系统深度集成

主要应用:
1. 网络认证和安全通信
2. 文件系统加密
3. 应用程序密钥管理
4. 系统安全服务
5. 容器和虚拟化安全

使用要点:
1. 需要理解密钥权限模型
2. 注意密钥生命周期管理
3. 合理设置超时和权限
4. 监控密钥使用情况
5. 配合用户态工具使用效果更佳

正确使用 keyctl 可以显著提高应用程序的安全性,是现代 Linux 系统安全架构的重要组成部分。

此条目发表在linux文章分类目录。将固定链接加入收藏夹。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注