密钥是一段数据,内核对它的管理有些类似对文件的管理。但Linux内核不愿意让密钥像文件那样“静态”存储在磁盘或者其他永久性存储介质上,所以内核对密钥的管理又有些像对进程的管理,有创建、实例化、删除等操作。

    从伪文件系统proc看起,内核密钥管理在proc文件系统中创建了两个只读文件:/proc/keys和/proc/key-users。
    它们没有被创建在/proc/pid目录下,而是被直接创建在了proc文件系统的根目录下。这就造成了进程根本无法查看到别的进程的密钥。
    keys文件列出当前进程可查看的密钥,所以不同的进程读出的内容会不同。
    列出的内容包括序列号、过期时间、访问允许位、uid、gid、类型、描述等。key-users列出密钥的统计信息,包括uid、使用计数、密钥总数量和实例化数量、密钥数量的配额信息、密钥占用内存的配额信息。

密钥
    密钥在内核代码中称为key,因为key是由用户态进程创建,由内核管理,其实体存储在内核申请的内存中,所以密钥管理需要实施配额管理。密钥有对称密钥和非对称密钥两大类,每类密钥又有很多种。密钥种类不同,payload中数据的格式和长度也不同。所以key数据结构中包含了数据成员type,其类型为key_type,其中包含若干函数指针,用于处理payload。主要内容可以参见include/linux/key-type.h。

include/linnux/key.h
struct key {
	...
	key_serial_t serial;       //内核通过此序列号来唯一地标识一个key
	struct key_user *user;     //包含一些和用户配额相关的数据,像用户拥有key的数量,用户拥有key占用总内存之类
	kuid_t uid;                //标识key的属主
	kgid_t gid;                //标识key的属组
	key_perm_t perm;           //key的访问权限
	void *security;            //被LSM使用,指向的内容由具体的LSM模块定义
	
	unsigned short datalen;    //标识payload的长度
	union {
		union{
			unsigned long value;
			void __rcu *rcudata;
			void *data;
			void *data2[2];
		} payload;
		struct assoc_array keys;
	};
	
	union {
		struct keyring_index_key index_key;
		struct {
			struct key_type *type;
			char *description;   //字符串,用于用户态进程查询密钥。用户态先用该字符串从内核查询到key对应的serial,后面直接用serial对key进行操作
		};
	};
	unsigned long flags;         //包含密钥的状态信息和密钥的生命周期有关
	...
};

include/linux/key_type.h
struct key_type {
	const char* name;
	...
	int (*instantiate)(struct key *key, struct key_preparsed_payload *prep);
	int (*update)(struct key *key, struct key_preparsed_payload *prep);
	int (*match)(const struct key *key, const void *desc);
	void (*revoke)(struct key *key);
	...
};

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐