quinnwencn / blog

Apache License 2.0
0 stars 0 forks source link

[Crypto] PKCS11中slot和token的理解 #46

Open quinnwencn opened 2 weeks ago

quinnwencn commented 2 weeks ago

理解

PKCS11 定义了独立于HSM、HSE等安全模块平台等接口,对于遵循PKCS11标准的安全硬件,都可以使用PKCS11的接口管理和使用这些安全硬件。PKCS11中提出了Slot和Token的概念,这两个概念在使用中非常难以理解,如果不理解透彻,甚至在使用中会经常犯错。我也经常困惑于这两个概念,对于一些开源代码,也很好奇为什么他们都默认使用Slot 0,而不是用其他slot,为什么指定了Slot后,还需要初始化token。今天,我就按自己的理解,尝试将slot和token的关系说明白。 我们可以理解为PKCS11类似于规定了一排标准的HSM插槽,每个插槽也就是Slot都可以插入一个HSM/HSE等安全硬件模块(只要这些安全硬件模块等插口严格按照PKCS11的标准制造)。这样,我们在使用时,只要在插入安全硬件到某个slot后,就可以通过这个slot使用安全硬件模块。 image

图中的外框可以理解为PKCS11,PKCS11规定了每一个插槽的大小(操作API),只要HSM/HSE等制造商按照这个标准制造安全硬件模块,那么就可以插上PKCS11的框进行使用。而插入slot的安全硬件被PKCS11成为token,也就是令牌,不管是HSM还是HSE,都统一称为token。

使用

在pkcs11的示例代码如:cryptoki中,默认使用slot 0生成和存储密钥:

pub fn init_pins() -> (Pkcs11, Slot) {
    let pkcs11 = get_pkcs11();

    // initialize the library
    pkcs11.initialize(CInitializeArgs::OsThreads).unwrap();

    // find a slot, get the first one
    let slot = pkcs11.get_slots_with_token().unwrap().remove(0);

    let so_pin = AuthPin::new(SO_PIN.into());
    pkcs11.init_token(slot, &so_pin, "Test Token").unwrap();

    {
        // open a session
        let session = pkcs11.open_rw_session(slot).unwrap();
        // log in the session
        session.login(UserType::So, Some(&so_pin)).unwrap();
        session.init_pin(&AuthPin::new(USER_PIN.into())).unwrap();
    }

    (pkcs11, slot)
}

这是因为slot的使用有一个比较常见的原则(或者叫惯例?),如果系统中只有一个HSM/或者说token,那么通常使用slot 0插入这个token;如果存在多个token,那么可以根据需求自由选择使用的slot,并添加token标签进行管理。

疑问

但是,用于管理HSM的PIN码应该如何保存呢? HSM中存在两种管理者:安全管理者(Security Officer)和用户管理者(User Officer),他们分别都有一个PIN码。由于PIN码控制着对HSM的访问,因此需要妥善管理存放这两个PIN码。但是,对于单一HSM的环境,比如汽车的控制器上,如何保存PIN码我至今仍没有想到比较合理的方法。

quinnwencn commented 2 weeks ago

或许将pin码存储在keyring是一个可行的方案,reference to keyring