Obtains entry points of Cryptoki library functions.
C_GetInfo
Obtains general information about Cryptoki
C_GetSlotInfo
Obtains information about a particular slot
C_GetTokenInfo
Obtains information about a particular token
C_GetSlotList
Obtain list of slots in the system.Only a fixed slot with fixed token is supported. Dynamic slot or token addition is not supported.
C_OpenSessionC_CloseSessionC_CloseAllSessions
Opens/Closes a session. All types of sessions are supported with Token. Only Token Objects can be created/destroyed, Session Objects are not supported.
C_LoginC_Logout
Logs into a token.Logs out from a token
C_CreateObject
Creates an object (RSA Keys of size up to 2048bits are supported)
C_DestroyObject
Destroys an object
C_FindObjectsInitC_FindObjectsC_FindObjectsFinal
Objects search operations.RSA Public and Private key objects of size up to 2048bits are supported.ECDSA Public and Private key objects of size 256 & 384 bits are supported.
C_GetAttributeValue
Obtains the value of one or more attributes of the objects.
C_GetMechanismList
Obtains List of mechanism supported by token.
C_GetMechanismInfo
Obtains the information about a mechanism.
C_GenerateKeyPair
Generates a public-key/private-key pair (RSA Keys of size up to 2048bits are supported)
C_SignInitC_SignC_SignUpdateC_SignFinal
Initialize a signature operation.Signs single-part data.Continues a multiple-part signature operation.Finishes a multiple-part signature operation.Mechanisms supported: RSA-based Mechanisms CKM_RSA_PKCS CKM_MD5_RSA_PKCS CKM_SHA1_RSA_PKCS CKM_SHA256_RSA_PKCS CKM_SHA384_RSA_PKCS CKM_SHA512_RSA_PKCS ECDSA-based Mechanisms (Single Part Only) CKM_ECDSA CKM_ECDSA_SHA1
C_DigestInitC_DigestC_DigestUpdateC_DigestFinal
Initializes a message-digesting operation.Digests single-part data.Continues a multiple-part digesting operation.Finishes a multiple-part digesting operation.Mechanisms supported: CKM_MD5 CKM_SHA1 CKM_SHA256 CKM_SHA384* CKM_SHA512
C_DecryptInitC_Decrypt
Initializes a decryption operation.Decrypts single-part encrypted data.Mechanisms supported: CKM_RSA_PKCS CKM_RSA_PKCS_OAEP
As per the following examples, generate a private key in the HSM with sobj_app, This will also create a fake PEM file “dev_key.pem” having information to get the required key from HSM.
// The first command creates a self-signed Certificate for “NXP Semiconductor". The signing is done using the key specified by the fake PEM file.
$ openssl req -new -key dev_key.pem -out req.pem -text -x509 -subj "/CN=NXP Semiconductor"
// creates a self-signed certificate for the request, the private key used to sign the certificate is the same private key used to create the request.
$ openssl x509 -signkey dev_key.pem -in req.pem -out cert.pem
Here are the steps to use OpenVPN with PKCS#11 in Ubuntu:
Install OpenVPN: Open a terminal window and run the following command to install OpenVPN: sudo apt-get install openvpn
Install PKCS#11 library: Install the PKCS#11 library for your token. The library is usually provided by the manufacturer of the token. You can download the library from the manufacturer's website and install it on your system. For example, if you are using a YubiKey, you can download the YubiKey PKCS#11 library from the Yubico website.
Configure OpenVPN: Create an OpenVPN configuration file and specify the PKCS#11 library path and the certificate and key for your PKCS#11 token. You can use the following sample configuration file as a starting point:
client
dev tun
proto udp
remote vpn.example.com 1194
resolv-retry infinite
nobind
persist-key
persist-tun
pkcs11-providers /usr/local/lib/libykcs11.so
pkcs11-id "pkcs11:object=YubiKey;type=private"
comp-lzo
verb 3
In this example, /usr/local/lib/libykcs11.so is the path to the YubiKey PKCS#11 library, and YubiKey is the name of the object that contains the private key in the token.
Start OpenVPN: Open a terminal window and run the following command to start OpenVPN using the configuration file that you have created: sudo openvpn --config /path/to/config-file.ovpn
Replace /path/to/config-file.ovpn with the path to your OpenVPN configuration file.
That's it! OpenVPN will now use the PKCS#11 token for secure authentication and key management.
1. Overview
PKCS#11标准定义了与密码令牌(如硬件安全模块(HSM)和智能卡)的独立于平台的API,并将API本身命名为
Cryptoki
(来自“加密令牌接口”,发音为“crypto-key” - 但是“PKCS#11”通常用于指代API以及定义它的标准)。 API定义了最常用的加密对像类型(RSA密钥,X.509证书,DES / 三重DES密钥等)以及使用,创建/生成,修改和删除这些对象所需的所有功能。参考:http://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/os/pkcs11-base-v2.40-os.html本文使用NXP LS1046A来对pkcs11进行验证。pkcs11对硬件有所要求,需要智能卡或者HSM。因此,本文会着重整理关于pkcs11如何和HSM进行配置的部分。NXP提供了Virual HSM,其底层使用OPTEE-OS进行实现;中间层使用
Secure Object Library
,在用户侧使用Cryptoki
对其进行封装,用户只需要按照要求调用API即可。总结顺序为:OPTEE-OS-> Secure Object Library(SOL) -> Cryptoki APIs。另外,Secure Object Libray还可以被OpenSSL API作为engine使用。SOL对HSM要求是:
导入私钥进入HSM内部
私钥对于用户侧永远不可见。
OPTEE内部实现框图如图所示:
2. API
2.1 用户侧API(Cryptoki)
用户侧的API来源于Cryptoki,这些API的实际实现来源于
libpkcs11.so
。在NXP的Layerscape中支持的API的列表为:2.2 中间层API (Secure Object Library)
中间层的API,请参考:https://docs.nxp.com/bundle/GUID-1441E561-3EAD-47FD-A50D-72E1A4E4D69E/page/GUID-81BC632C-6F59-49B1-8573-419306674DD3.html
这里面规定了如何:
用户甚至可以直接使用Secure Object Library来操作HSM/Token。NXP提供了
sobj_app
用来直接访问Secure Object Library:https://docs.nxp.com/bundle/GUID-1441E561-3EAD-47FD-A50D-72E1A4E4D69E/page/GUID-94DA27FA-ADB5-432E-87A4-0AA3B0BB99B1.html#GUID-94DA27FA-ADB5-432E-87A4-0AA3B0BB99B1
3. Secure Object集成
3.1 Cryptoki
Cryptoki可以分为两个访问方法
命令行的
p11tool
比较常用,该命令行参数在https://www.gnutls.org/manual/html_node/p11tool-Invocation.html 。如果是ubuntu系统可以通过sudo apt install gnutls-bin
来安装p11toolWe have tested this library with p11tool for following operations:
NXP把p11tool又包装了一层
pkcs11_app
工具,可以参考:https://docs.nxp.com/bundle/GUID-1441E561-3EAD-47FD-A50D-72E1A4E4D69E/page/GUID-E9CE3DC0-9C77-45C4-BE72-0E86FC5233ED.html#GUID-E9CE3DC0-9C77-45C4-BE72-0E86FC5233ED__UL_DDX_JML_XCB这里涉及了一些具体的签名和验签操作。
3.2 OpenSSL
OpenSSL通过SOL可以实现使用Engine进行加解密,进而可以调用到NXP的CAAM来对加密算法加速运算。有两种方法可以实现使用OpenSSL的API来访问Secure Objects:
3.2.1 使用libeng_secure_obj (非PKCS#11)
如果engine基于SOL,是有限制的,只能是:
OpenSSL不能够通过调用接口产生RSA Keys。这个Key需要通过
sobj_app
预置到HSM中。OpenSSL只能使用HSM中的key。3.2.1.1 配置openssl
如果使用命令行的openssl,我们需要对openssl进行配置,在
openssl.cnf
中 (often in/etc/ssl/openssl.cnf
) 的最前面:openssl_conf = conf_section
如果配置RSA相应的配置,Add following section at bottom of file:
如果配置ECC,配置:
default_algorithms = RSA, EC
测试: To verify that the engine is properly operating, you can use the following example:
If you do not update the OpenSSL configuration file, specify the engine configuration explicitly.
3.2.1.2 使用openssl
RSA
Following commands can be used to generate RSA/ECDSA key-pair and use them in signing any data and verifying the signatures generated.
注意,这个地方并没有使用PKCS#11,只是普通的签名算法和验签算法。
ECDSA
Same thing can be done for ECDSA keys of prime256v1 by using following commands:
For ECDSA secp384r1 curve us following commands:
x.509
下面描述一下怎么创建一个self-sign的cert。这个key由HSM产生并且无法暴露出来。
As per the following examples, generate a private key in the HSM with sobj_app, This will also create a fake PEM file “dev_key.pem” having information to get the required key from HSM.
Following command is generating RSA key-pair:
ECDSA key-pair can also be generated using following command:
产生一个cert用SOL:
3.2.2 使用OpenSC/libp11
libp11
对PKCS#11 API进行了比较薄的封装,参考https://github.com/OpenSC/libp11 。这个仓库提供了:对于Ubuntu系统可以
sudo apt-get install libengine-pkcs11-openssl
。上面的命令可以安装libpkcs11.so
(pkcs11 engine) 到/usr/lib/aarch64-linux-gnu/engines-1.1/libpkcs11.so
。同样需要更改openssl的配置文件:
This should be added to the bottom of the file:
如何测试
To verify that the engine is properly operating you can use the following example.
使用p11tool
下面的测试用例是使用命令行产生一个自签的cert,这个key产生一个token,并且key不能被导出。
sudo apt-get install gnutls-bin
NXP提供的
sobj_app
也可以查看由p11tool产生的key:注意,有两个libpkcs11.so,一个是NXP的,一个是openssl engine用的:
The following commands utilize p11tool for that.
产生一个在PKCS#11里面的证书:
4. Example OpenVPN
OpenVPN https://openvpn.net/vpn-server-resources/support-of-pkcs11-physical-tokens-for-openvpn-connect/
Here are the steps to use OpenVPN with PKCS#11 in Ubuntu:
sudo apt-get install openvpn
In this example,
/usr/local/lib/libykcs11.so
is the path to the YubiKey PKCS#11 library, andYubiKey
is the name of the object that contains the private key in the token.sudo openvpn --config /path/to/config-file.ovpn
Replace
/path/to/config-file.ovpn
with the path to your OpenVPN configuration file.That's it! OpenVPN will now use the PKCS#11 token for secure authentication and key management.
4.1 启动 tee-supplicant
由于NXP的layerscape是使用optee模拟的HSM,因此需要在用户侧启动tee服务程序:
tee-supplicant &
运行
xtest
测试OPTEE 是否可以正常运行。4.2 在HSM中产生key
产生Key名字叫做com_rsa_2048:
sobj_app -G -m rsa-pair -s 2048 -l "comrsa2048" -i 2
查看Key
4.3 配置OpenVPN
配置OpenVPN有两种方式:
OpenVPN开始SSL模式,有个互相challenge的过程。因此,必须提供ca.cert证书,作为client和server之间的互信。
4.3.1 传统的证书方式
客户端需要:
这几个证书的生成过程如图所示:
CSR生成
ca.crt是需要手动拷贝的,需要从ca.crt的服务器上获取,csr的生成需要:
https://myssl.com/csr_create.html
实际上产生的命令如下:
openssl req -new -SHA256 -newkey rsa:2048 -nodes -keyout mlts.tech.key -out mlts.tech.csr -subj "/C=CN/ST=Guangdong/L=Shenzhen/O=multibeans/OU=ite dept/CN=mlts.tech"
这个命令会生输出:
这里生成CSR必须要私钥信息,因为CSR需要签名信息,公钥信息也会被放置到CSR里面。
服务器CA返回CERT
服务器端(CA服务器)会对CSR文件进行校验,签署,这里模拟CA服务器的命令:
openssl x509 -req -days 365 -in mlts.tech.csr -signkey server.key -out client.crt
服务器需要用自己的server.key对csr进行签名和转换,输出client.crt,然后把client.crt转给client端。有的CA可能为了防攻击还需要申请者提供CA.cert以确保自身的身份需要验证。
以上是一个CSR请求证书的示例,通过HTTPS做CERT。
4.3.2 PKCS#11
OpenVPN 中通过修改配置来接入 PKCS#11 认证,分别为 pkcs11-providers 、pkcs11-id 属性赋值。libhpkcs11.so 为HSM提供的 PKCS#11 共享库,pkcs11-id 值在使用过程 中通过调用命令openvpn show-pkcs11-help libhpkcs11.so来动态读取。
要配置 OpenVPN 客户端使用 PKCS#11 进行身份验证,您需要执行以下步骤:
安装 PKCS#11 库:首先,需要为硬件令牌安装适当的 PKCS#11 库。您可以查看令牌制造商提供的文档以确定要使用哪个库以及如何将其安装到您的系统上。NXP的令牌就在
/usr/lib/libpkcs11.so
中。配置 OpenVPN 以使用 PKCS#11:接下来,需要配置 OpenVPN 以使用 PKCS#11 进行身份验证。这涉及修改 OpenVPN 配置文件以包含适当的 PKCS#11 指令。这是一个示例配置:
4.3.2.1 remote
需要在host里面添加:
120.78.72.155 sz.vehicle.vpn.autox.tech
。这个就是remote地址。4.3.2.2 pkcs11-providers
这个就是PKCS#11的库,NXP的Layerscape的目录是在:
/usr/lib/libpkcs11.so
4.3.2.3 pkcs11-id
PKCS#11驱动目前不支持生成密钥的功能。一个密钥对可以通过sobj_app生成。with the identifier of the object containing the private key and certificate on the hardware token.
通过命令来查看:
4.3.2.4 pkcs11-pin
存在HSM内部的私钥的password,如果有的话需要指定。with the PIN needed to access the token.
4.3.2.5 cert
OpenVPN配置文件中的
<cert>
标记指的是将用于身份验证的客户端证书。这通常是由OpenVPN服务器配置为信任的CA(证书颁发机构)签署的用户特定证书。当使用PKCS#11进行身份验证时,客户端证书和私钥存储在硬件令牌上,PKCS#11库提供对它们的访问。在OpenVPN配置中,可以在<cert>
标签之间包含证书数据,也可以指定包含证书数据的文件的路径。生成RSA key在HSM中
按照步骤我们先生成一个RSA 2048的key放入HSM,名字就是
doge
sobj_app -G -m rsa-pair -s 2048 -l "doge" -i 1 -w doge_fake.pem
同时也生成一个
doge_fake.pem
文件,该文件并不是真正的私钥,读出对应的RSA 2048的公钥:
pkcs11-tool --module /usr/lib/libpkcs11.so --read-object --type pubkey --label doge -o doge_public.key
使用openssl接入engine产生CSR
配置openssl
openssl需要配置,在
/etc/ssl/openssl.cnf
中在文件头部添加:在环境变量中使能配置文件路径:
export OPENSSL_CONF=/etc/ssl/openssl.cnf
检测之后,代表pkcs11的engine已经在openssl启动:
使用openssl生成CSR
接下来使用openssl生成CSR:
token的名字通过
pkcs11-tool --module /usr/lib/libpkcs11.so --list-token
查找,object的名字通过pkcs11-tool --module /usr/lib/libpkcs11.so --list-objects
查找。openssl req -engine pkcs11 -keyform engine -key "pkcs11:token=TEE_BASED_TOKEN;object=doge" -new -out doge.csr
接下来就开始输入CSR的一些信息:
生成了doge.csr
向CA请求csr签名获取证书
根据公司的业务不同,CSR的请求接口形式上可能有差异,但最终公司CA进行核查后,CA 会根据 CSR 中的信息创建服务器证书,使用私钥对其进行签名,然后将证书发送给自己。CA 还会向您发送一个根 CA 证书和一个中间 CA 证书(如果适用)。所以一个CSR可以获取:
本公司的API使用的https的接口,因此需要为https指定HTTPS的cert、key、ca_cert。bash脚本如下:
将证书import进入HSM
p11tool --provider /usr/lib/libpkcs11.so --list-cert
p11tool --provider /usr/lib/libpkcs11.so --list-privKeys
附录:PKCS#11常用操作指南
显示关于cryptoki版本的信息,以及PKCS#11驱动^1。
关于可用插槽的信息。列出的插槽取决于
p11nethsm.conf
配置文件中的插槽阵列的配置。生成密钥,产生一个密钥对并将其存储在VirtualHSM上。
显示NetHSM上Key Store 中的密钥和证书的信息。
从NetHSM上的Key Store 读取密钥和证书。不可能从NetHSM上读取私钥。
一个密钥对的公钥可以读作如下。
一个密钥对的证书可以读作以下内容。
返回的证书或公钥是ASN.1编码的。这些数据可以用dumpasn1 工具进行解码,因为它包含DER格式的数据。DER格式可以用OpenSSL转换为PEM格式。
将密钥和证书写入NetHSM上的Key Store 。
钥匙对的私钥可以写成如下形:
一个密钥对的公钥可以写成如下。
一个密钥对的证书可以写成以下样子。
NetHSM可以为存储在NetHSM的Key Store中的私钥签署数据。对于使用RSA和ECDSA密钥的签名,必须先计算出摘要。
要计算一个摘要,首先需要数据。一个信息的创建方法如下。
创建的签名可以用OpenSSL进行验证,方法如下。
Ref
https://support.pervices.com/application-notes/pvan-7/