密钥是动态创建的,它有生命周期,如图16-1所示。在数据结构中用flags来标识密钥的生命周期状态。
用户态进程首先会创建密钥,内核响应用户态进程的请求会生成一个密钥,分配内存。密钥的第二个状态是instantiated,内核将用户态进程提供的输入填入密钥的负载(payload)之中。这时的密钥就可以被用来做加解密使用了。密钥的“死亡”状态有三个,它们略有不同。revoke和invalidate都是由用户态进程发起的请求,内核对invalidate的响应是立即让密钥失效,收回密钥上的资源;内核对revoke的响应也是让密钥失效并收回资源,只是在此之前先调用密钥所属的类型(struct key_type)中定义的一个函数(revoke)。dead状态不是由用户态进程删除密钥导致的,而是由于一种类型(key_type)的密钥失效导致的,一般造成这种状况是因为相关的内核模块被卸载。
密钥的构造由用户态进程发起,密钥的payload数据由用户态进程提供,或者由用户态进程指令内核生成。当内核子系统要用到某个密钥,而这个密钥还不存在怎么办?一种简单的做法是由内核启动一个用户态进程,再由这个进程来填充密钥的payload。在发起新进程之前,内核首先分配一个密钥,将密钥的状态设置为“user_construct”。发起的新进程负责填充密钥的payload。这时,进程有两个选择,一个是立刻提供payload并通知内核将密钥的状态置为“instantiated”;另一个是不能马上提供payload数据,它就通知内核将密钥的状态置为“negative”,以后再提供数据并修改状态。在图16-1的基础上增加两个状态“user_construct”和“negative”就形成了图16-2。
图16-1 密钥的基本生命周期
图16-2 密钥的生命周期
下面看一下代码:
request_key.c调用了request_key_and_link:
(www.xing528.com)
request_key_and_link会尝试查找密钥,如果没有找到,request_key_and_link会调用construct_key_and_link:
下面来看construct_key:
如果密钥类型中没有特殊规定,函数call_sbin_request_key就会被调用。call_sbin_request_ key的定义为:
call_sbin_request_key函数定义比较长,上面只保留了核心部分,主要功能是用要实例化的密钥的序列号(key->serial)生成一个描述字符串(desc),用这个描述字符串生成一个钥匙串kering),然后将authkey链接入钥匙串。最后用钥匙串作为参数调用call_usermodehelper_keys call_usermodehelper_keys将会启动一个用户态进程,这个用户态进程负责实例化密钥。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。