key_mgmt密钥管理组件常见问题解答
Q1. 如何使用key_mgmt密钥服务
- 使用key_mgmt服务需要提供相关skynet环境变量(配置在framework进程config文件):
KSF_PATH = "/data/opt/bmc/ksf/" -- ksf文件存放目录
KSF_BAK_PATH = "/data/opt/bmc/ksf/" -- ksf bak文件存放目录
BIOS_KSF_FILE_NAME = "datatocheck_xxx.dat" -- ksf文件名
BIOS_KSF_BACK_NAME = "datatocheck_xxx_bak.dat" -- ksf bak文件名
HARDWARE_ROOTKEY_ENABLE = true -- 目前密钥服务均为硬件根密钥模式,统一配置为true- 业务代码注册服务,获取到domainId:
local key_mgmt_client = require 'key_mgmt.key_client_lib'
-- 初始化kmcClient客户端
local client = key_mgmt_client.new(bus, "Login credentials", function()
-- 在密钥更新后,需要刷新加密数据,即对加密数据重新解密加密
local plaintext = kmc.decrypt_data(domain_id, saved_ciphertext)
saved_ciphertext = kmc.encrypt_data(domain_id, kmc.WsecAlgId.WSEC_ALGID_AES256_GCM,
kmc.WsecAlgId.WSEC_ALGID_UNKNOWN, plaintext)
...
end)
self.key_mgmt_client = client -- 对象需要保存,如果被回收,回调函数会失效
self.m_domain_id = client.m_domain_id -- 调用kmc加解密接口需要用到的domainId- 加解密接口使用:
-- 解密
local ciphertext = "******"
local plaintext = kmc.decrypt_data(domain_id, ciphertext)
-- 加密
local new_ciphertext = kmc.encrypt_data(domain_id, kmc.WsecAlgId.WSEC_ALGID_AES256_GCM,
kmc.WsecAlgId.WSEC_ALGID_UNKNOWN, plaintext)Q2. kmc解密接口报268错误
268错误码表示MK不存在,即该进程中不存在该domainId。原因为domainId和ksf文件不匹配,可能是运行过程中数据库被破坏,导致domainId被key_mgmt重新匹配;或由于业务场景考虑不充分,导致旧密钥被误删,从而加解密失败。
解决方法:
- 如果是ipmi命令报错,重新设置密码即可:
busctl --user call bmc.kepler.iam /bmc/kepler/AccountService/Accounts/2 bmc.kepler.AccountService.ManagerAccount ChangePwd a{ss}ay 3 Interface Web UserName Administrator ClientAddr 127.0.0.1 11 65 100 109 105 110 64 57 48 48 48 48- 如果web界面无法访问,日志显示证书解密失败,则重新导入证书:
date -s "2023-10-01 10:00:00" && busctl --user call bmc.kepler.trust /bmc/kepler/CertificateService bmc.kepler.CertificateService ImportCertWithKey a{ss}sss 3 Interface Busctl UserName Administrator ClientIp 127.0.0.1 URI /tmp/IISCert.p12 123456涉及kmc的组件都存在这种情况,可以根据对应业务场景删除相应数据,并重新触发加密,即可正常使用
所有涉及kmc的组件都存在这种情况,可以直接彻底重置kmc数据,删除数据库domainId分配信息,重启key_mgmt,重新导入证书,设置密码等。但kmc业务面涉及较广,难以将数据清除干净,不建议使用:
sqlite3 /data/trust/persistence/per_poweroff.db
DELETE FROM persist_table where table_name = 't_master_key';
.exit
killall key_mgmt- 多个组件依赖同一个密钥的场景,需要考虑将domain进行拆分,并且兼容降级场景,此时则需要先更新密钥的组件不删除旧domainId
Q3. 服务中断,skynet日志报kmc 155错误码
155错误码表示APP调用顺序错误。在组件向key_mgmt注册密钥后,会开启线程定时刷新内存中的密钥掩码,如果注册失败,注册掩码会抛出错误,需要查看为什么会注册失败。仔细查看Q1,检查是否有环节出现纰漏。
Q4. 注册kmc服务,接口nil错误
一般是kmc启动异常,导致资源树接口没有注册回调,需要具体排查key_mgmt为什么启动异常。
Q5. 集成测试,触发密钥更新,报263错误码
集成测试为单进程模式,key_mgmt作为master服务和使用kmc的agent组件在同一进程里运行,同一进程注册kmc服务会重新初始化kmc数据,会导致domain丢失,需要将相关代码删除才可保证集成测试正常运行。
使用key_mgmt 1.0.2及以后版本,在准备测试数据时去掉相关代码,即在prepare_test_data方法内添加如下代码:
-- 由于集成测试是单进程,必须去掉kmc重复初始化流程,业务才能正常使用kmc服务
os.execute("sed -i '/kmc.initialize/,+4d' temp/opt/bmc/lualib/key_mgmt/key_client_lib.lua")Q6. 进程初始化,kmc初始化报287错误码
287错误码代表ksf文件损坏,正常情况下不会有这种情况,一般是初始化步骤或m3访问有问题,需要具体定位。
Q7. 定位问题时需要持续更新主密钥,如何绕过密钥更新周期检查?
使用mdbctl setprop set KeyService_0 bmc.kepler.KeyService LastUpdateTime 1684327765 命令设置密钥更新时间早于当前时间,便可通过更新周期检查。
Q8. key_mgmt密钥过期warning日志频繁输出
之前BMC版本密钥默认自动更新周期为0,即关闭。由于密钥的有效期为一年,因此在启动阶段,时间从1970跳变到系统时间必然会导致密钥过期,但对功能没有影响。此时如果有业务场景(例如新增账号、更改密码等涉及加解密的场景),则会触发密钥更新,检查密钥是否有效,从而打印该密钥过期提示日志。
此日志频繁输出问题已在BMC 5.5.0版本进行解决,默认只打印ERROR级别日志;而密钥默认自动更新时间在BMC 5.8.0版本修改为一年更新一次。
Q9. cli执行更新密钥命令,业务组件名称发生大小写变化
使用cli执行更新密钥操作时会记录操作日志,key_mgmt只定义日志格式为Update %s master key successfully,具体传入的业务组件名称为业务组件初始化时指定。
如果发现业务组件名称与之前存在变化的情况,先咨询业务组件是否进行整改。
Q10. 如何通过kmc接口生成指定密钥的ksf文件
通过测试用例调用kmc接口生成ksf文件:
function TestKmc:test_kmc_a_primitive()
if kmc.initialize(false, kmc.KmcRoleType.KMC_ROLE_MASTER,
{master_file = self.master_file, backup_file = self.backup_file}) == kmc.WSEC_ERR_KMC_INI_MUL_CALL then
kmc.reset(false, {master_file = self.master_file, backup_file = self.backup_file})
end
--默认情况下,生成两个域:
--1)Domain=0: 组件内部生成域,组件初始化的时候Master会在0号域内部自动生成一个Domain=0,KeyId=1 的有效密钥,Agent不生成;
--2)Domain=1: APP应用自行注册密钥,组件不会内部生成。
lu.assertEquals(kmc.get_domain_count(), 2)
local info = kmc.KmcMkInfo.new()
--creaet_mk_ex,在指定域中创建密钥,并返回相应的keyid信息,调用者无需指定密钥内容
local key_id = kmc.creaet_mk_ex(0)
--activate_mk,激活对应密钥
kmc.activate_mk(0, key_id)
--生成ksf文件
kmc.generate_ksf_all(utils_core.getcwd() .. '/datatocheck_default.dat')
end注意:由于domainId为1的域是KMC默认域,只能通过导入的方式注册密钥,不能调用create接口创建密钥。如果需要生成domainId为1的密钥,可通过调用KmcRegisterMkEx来注册密钥。
附录
WSEC_SUCCESS值为零,返回WSEC_SUCCESS为成功,返回其它值为失败,可能错误码如下表(表中错误码为相对编译宏WSEC_ERR_CODE_BASE所表示数值的偏移量)。
| 错误码宏 | 偏移量 | 错误信息 |
|---|---|---|
| WSEC_FAILURE | 1 | 通用错误 |
| WSEC_ERR_OPEN_FILE_FAIL | 11 | 打开文件失败 |
| WSEC_ERR_READ_FILE_FAIL | 12 | 读文件失败 |
| WSEC_ERR_WRI_FILE_FAIL | 13 | 写文件失败 |
| WSEC_ERR_GET_FILE_LEN_FAIL | 14 | 获取文件长度失败 |
| WSEC_ERR_FILE_FORMAT | 15 | 文件格式错误 |
| WSEC_ERR_FILE_COPY_FAIL | 16 | 文件拷贝失败 |
| WSEC_ERR_FILE_FLUSH_FAIL | 17 | 文件落盘失败 |
| WSEC_ERR_FILE_LEN_TOO_MAX | 18 | 文件过长 |
| WSEC_ERR_MALLOC_FAIL | 51 | 内存分配失败 |
| WSEC_ERR_MEMCPY_FAIL | 52 | 内存拷贝失败 |
| WSEC_ERR_MEMCLONE_FAIL | 53 | 内存克隆失败 |
| WSEC_ERR_STRCPY_FAIL | 54 | 字符串拷贝失败 |
| WSEC_ERR_OPER_ARRAY_FAIL | 55 | 数组操作失败 |
| WSEC_ERR_MEMSET_FAIL | 56 | 内存置值失败 |
| WSEC_ERR_ARRAY_ITEM_REPEAT | 57 | 成员重复 |
| WSEC_ERR_CRPTO_LIB_FAIL | 101 | 加密(iPSI或openssl)操作失败 |
| WSEC_ERR_GEN_HASH_CODE_FAIL | 102 | 生成Hash值失败 |
| WSEC_ERR_HASH_NOT_MATCH | 103 | Hash值不匹配 |
| WSEC_ERR_INTEGRITY_FAIL | 104 | 完整性被破坏 |
| WSEC_ERR_HMAC_FAIL | 105 | HMAC失败 |
| WSEC_ERR_HMAC_AUTH_FAIL | 106 | HMAC验证失败 |
| WSEC_ERR_GET_RAND_FAIL | 107 | 获取随机数失败 |
| WSEC_ERR_PBKDF2_FAIL | 108 | 推演密钥失败 |
| WSEC_ERR_ENCRPT_FAIL | 109 | 数据加密失败 |
| WSEC_ERR_DECRPT_FAIL | 110 | 数据解密失败 |
| WSEC_ERR_GET_ALG_NAME_FAIL | 111 | 获取安全算法名失败 |
| WSEC_ERR_INVALID_ARG | 151 | 非法参数 |
| WSEC_ERR_OUTPUT_BUFF_NOT_ENOUGH | 152 | 输出缓冲区不足 |
| WSEC_ERR_INPUT_BUFF_NOT_ENOUGH | 153 | 输入缓冲区不足 |
| WSEC_ERR_CANCEL_BY_APP | 154 | APP取消操作 |
| WSEC_ERR_INVALID_CALL_SEQ | 155 | APP调用顺序错误 |
| WSEC_ERR_CALLBACKS_NOT_REG | 156 | 回调函数未注册 |
| WSEC_ERR_INVALID_INSTANCE | 157 | 实例flag为错误值 |
| WSEC_ERR_USE_WRONG_RANDOM_CALLBACK | 158 | 注册与实例不符的随机数回调函数 |
| WSEC_ERR_GET_CURRENT_TIME_FAIL | 201 | 获取当前时间失败 |
| WSEC_ERR_CALC_DIFF_DAY_FAIL | 202 | 计算相差天数失败 |
| WSEC_ERR_KMC_CALLBACK_KMCCFG_FAIL | 251 | 回调获取KMC配置数据失败 |
| WSEC_ERR_KMC_KMCCFG_INVALID | 252 | KMC配置数据非法 |
| WSEC_ERR_KMC_KSF_DATA_INVALID | 253 | KSF存在非法配置数据 |
| WSEC_ERR_KMC_INI_MUL_CALL | 254 | 多次调用初始化 |
| WSEC_ERR_KMC_NOT_KSF_FORMAT | 255 | 不是KSF格式 |
| WSEC_ERR_KMC_READ_DIFF_VER_KSF_FAIL | 256 | 读取其它版本的KSF失败 |
| WSEC_ERR_KMC_READ_MK_FAIL | 257 | 读取MK失败 |
| WSEC_ERR_KMC_MK_LEN_TOO_LONG | 258 | MK密钥超长 |
| WSEC_ERR_KMC_REG_REPEAT_MK | 259 | 试图注册重复的MK,这里指试图注册重复的Domain+keyId 。 |
| WSEC_ERR_KMC_ADD_REPEAT_DOMAIN | 260 | 试图增加重复的Domain(ID重复) |
| WSEC_ERR_KMC_ADD_REPEAT_KEY_TYPE | 261 | 试图增加重复的KeyType(同一Domain下KeyType重复) |
| WSEC_ERR_KMC_ADD_REPEAT_MK | 262 | 试图增加重复的MK(同一Domain下KeyId重复) |
| WSEC_ERR_KMC_DOMAIN_MISS | 263 | DOMAIN不存在 |
| WSEC_ERR_KMC_DOMAIN_KEYTYPE_MISS | 264 | DOMAIN KeyType不存在 |
| WSEC_ERR_KMC_DOMAIN_NUM_OVERFLOW | 265 | DOMAIN配置数量超限 |
| WSEC_ERR_KMC_KEYTYPE_NUM_OVERFLOW | 266 | KeyType配置数量超限 |
| WSEC_ERR_KMC_MK_NUM_OVERFLOW | 267 | MK数量超限 |
| WSEC_ERR_KMC_MK_MISS | 268 | MK不存在 |
| WSEC_ERR_KMC_RECREATE_MK | 269 | 重新创建MK失败 |
| WSEC_ERR_KMC_CBB_NOT_INIT | 270 | CBB尚未初始化 |
| WSEC_ERR_KMC_CANNOT_REG_AUTO_KEY | 271 | 不能注册系统自动生成的密钥 |
| WSEC_ERR_KMC_CANNOT_RMV_ACTIVE_MK | 272 | 不能删除处于活动状态的MK |
| WSEC_ERR_KMC_CANNOT_SET_EXPIRETIME_FOR_INACTIVE_MK | 273 | 不能对inactive的MK设置过期时间 |
| WSEC_ERR_KMC_RK_GENTYPE_REJECT_THE_OPER | 274 | RK的生成方式不支持该操作 |
| WSEC_ERR_KMC_MK_GENTYPE_REJECT_THE_OPER | 275 | MK的生成方式不支持该操作 |
| WSEC_ERR_KMC_ADD_DOMAIN_DISCREPANCY_MK | 276 | 待增DOMAIN与残留的MK矛盾 |
| WSEC_ERR_KMC_IMPORT_MK_CONFLICT_DOMAIN | 277 | 导入的MK与Domain配置冲突 |
| WSEC_ERR_KMC_CANNOT_ACCESS_PRI_DOMAIN | 278 | 私有Domain不可访问 |
| WSEC_ERR_KMC_INVALID_ROLETYPE | 279 | 非法的身份信息 |
| WSEC_ERR_KMC_ROLLBACK_FAIL | 280 | 回滚操作失败 |
| WSEC_ERR_KMC_INVALID_KEYHASH_LEN | 281 | 查询MK的密钥HASH长度错误 |
| WSEC_ERR_KMC_CANNOT_FIND_ACTIVEKEY | 282 | 找不到有效的密钥 |
| WSEC_ERR_KMC_KEYSTOREMEM_NOTEXIST | 283 | 内存中的Keystore不存在 |
| WSEC_ERR_KMC_KEYCFGMEM_NOTEXIST | 284 | 内存中的keycfg不存在 |
| WSEC_ERR_KMC_MKID_OVERFLOW | 285 | 一个内部生成域生成密钥ID出现反转错误 |
| WSEC_ERR_KMC_READMK_NOTCOMPLETE | 286 | 读取MK不完全 |
| WSEC_ERR_KMC_KSF_CORRUPT | 287 | KMC Ksf 损坏 |
| WSEC_ERR_LARGER_THAN_MAX_MK_RECORD_LEN | 288 | MK记录超过最大 |
| WSEC_ERR_KMC_KSF_VERSION_INVALID | 289 | KSF版本号错误 |
| WSEC_ERR_KMC_HARDWARE_RK_NOT_FOUND | 290 | 硬件根密钥未查找到 |
| WSEC_ERR_KMC_SYNC_MK_FAILED | 291 | MK同步失败 |
| WSEC_ERR_KMC_DOMAIN_TYPE_ERROR | 292 | 不正确域类型 |
| WSEC_ERR_KMC_FILTER_MK_COUNT_ZERO | 293 | 过滤密钥MK数量为零 |
| WSEC_ERR_KMC_IMPORT_MK_NUM_OVERFLOW | 294 | 将要导入的密钥过多 |
| WSEC_ERR_KMC_INVALID_IMPORT_TYPE | 295 | 不支持的密钥导入方式 |
| WSEC_ERR_KMC_MK_NOT_SUPPORT_EXP_IMP | 296 | MK不支持导入导出 |
| WSEC_ERR_KMC_BATCH_DOAMIN_COUNT_EXCEED | 297 | domainId计数超出 |
| WSEC_ERR_KMC_SYNC_CNF_COUNT_FAILED | 298 | Sync msg消息数量错误 |
| WSEC_ERR_KMC_SYNC_CNF_COUNT_INVALID | 299 | Sync msg消息数量非法 |
| WSEC_ERR_KMC_SYNC_CNF_SEND_FAILED | 300 | Sync msg发送异常 |
| WSEC_ERR_KMC_SYNC_CNF_RECV_FAILED | 301 | Sync msg接收异常 |
| WSEC_ERR_KMC_SYNC_HEADER_SEND_FAILED | 302 | 发送消息头msg header异常 |
| WSEC_ERR_KMC_SYNC_HEADER_RECV_FAILED | 303 | 接收消息头msg header异常 |
| WSEC_ERR_KMC_SYNC_HEADER_MSGTYPE_INVALID | 304 | 消息头类型异常 |
| WSEC_ERR_KMC_SYNC_HEADER_VER_INVALID | 305 | 消息头版本异常 |
| WSEC_ERR_KMC_SYNC_HEADER_MSGLEN_INVALID | 306 | 消息头长度异常 |
| WSEC_ERR_KMC_SYNC_AGENT_RESPONSE | 307 | Agent response失败 |
| WSEC_ERR_KMC_PRI_ALG_NOT_SUPPORTED | 320 | 算法不支持 |
| WSEC_ERR_SDP_PWD_VERIFY_FAIL | 351 | SDP的密码校验错误 |
| WSEC_ERR_SDP_CONFIG_INCONSISTENT_WITH_USE | 352 | 配置数据与使用不一致 |
| WSEC_ERR_SDP_INVALID_CIPHER_TEXT | 353 | 密文格式解析错误 |
| WSEC_ERR_SDP_VERSION_INCOMPATIBLE | 354 | 密文版本与当前版本不兼容 |
| WSEC_ERR_SDP_ALG_NOT_SUPPORTED | 355 | 算法不存在或不支持 |
| WSEC_ERR_SDP_DOMAIN_UNEXPECTED | 356 | 密文来自非预期Domain |
| WSEC_ERR_SDP_CIPHER_LENGTH_NOT_ENOUGH | 357 | 输入的密文长度预留空间不足 |
| WSEC_ERR_SDP_ZERO_CIPHER_LENGTH | 358 | 密文头中密文长度字段为0 |
| WSEC_ERR_SDP_RAND_INIT_FAILED | 359 | 随机数初始化失败 |
| WSEC_ERR_SDP_ARG_CIPHER_LEN | 363 | 通过明文长度获取密文长度接口,入参密文长度为NULL |
| WSEC_ERR_SDP_ARG_PLAIN_LEN | 364 | 通过明文长度获取密文长度接口,入参用户配置参数盐值不是16或者32 |
| WSEC_ERR_SDP_ARG_SALT_LEN | 365 | 通过明文长度获取密文长度接口,入参明文长度非法 |
| WSEC_ERR_TPM_CAPABILITY_NOT_GOT | 500 | TPM容量无法获取 |
| WSEC_ERR_TPM_RESOURCE_NOT_ENOUGH | 501 | TPM资源不足 |
| WSEC_ERR_KMC_NOT_HARDWARE | 502 | TEE模式不支持V3模式 |
| WSEC_ERR_MEMINFO_PROTECT_FAIL | 600 | 内存信息掩码保护失败 |
| WSEC_ERR_MASK_INIT_FAIL | 601 | 初始化掩码失败 |
| WSEC_ERR_KEYRING_REQKEY | 602 | Request KeyRing异常 |
| WSEC_ERR_KEYRING_READKEY | 603 | Read KeyRing异常 |
| WSEC_ERR_KEYRING_COMPAREKEY | 604 | Compare KeyRing异常 |
| WSEC_ERR_CA_INTI_CONTEXT | 700 | 初始化context错误 |
| WSEC_ERR_CA_OPEN_SESSION | 701 | Open Session失败 |
| WSEC_ERR_CA_INVALID_PARAM_FORMAT | 702 | 传入TA参数格式异常 |
| WSEC_ERR_CA_INVALID_ARG | 703 | 传入TA参数错误 |
| WSEC_ERR_CA_BUFFER_NOT_ENOUGH | 704 | 传入TAbuffer不足 |
| WSEC_ERR_CA_ACCESS_DENIED | 705 | 没有权限访问TA |
| WSEC_ERR_CA_OPERATION_NOT_SUPPORTED | 706 | 非TEE模式不支持 |
| WSEC_ERR_CA_GENERIC_ERROR | 707 | 调用TA通用错误 |
| WSEC_ERR_CA_INVALID_TA_PATH | 708 | TA的路径异常 |
| WSEC_ERR_CA_EXCEED_MAX_SESSION_NUM | 709 | Session个数超过上限 |
| WSEC_ERR_CA_BUFFER_TOO_LARGE | 710 | 传入buffer过长 |
| WSEC_ERR_CA_INVALID_TA_PATH_SUFFIX | 711 | TA路径链接符号异常 |
| WSEC_ERR_CA_UNSUPPORT_TEE_MODE | 712 | 不支持TEE模式 |
| WSEC_ERR_CA_TEE_NOT_SUPPORT | 713 | 不支持TEE模式 |
| WSEC_ERR_CA_RK_LEN_INVAILD | 714 | TEE模式RK长度异常 |
| WSEC_ERR_CA_TRUSTED_APP_LOAD_ERROR | 715 | TEE未初始化加载KSFV4文件 |
| WSEC_ERR_CA_TEEMODE_NOT_SUPPORT_HW | 716 | TEE模式不支持硬件 |
| WSEC_ERR_TLV_CORRUPT | 800 | Tlv数据异常 |
| WSEC_ERR_MATCH_TLV_TAG | 801 | Tlv未能匹配tag值 |
| WSEC_ERR_MATCH_TLV_LEN | 802 | Tlv长度异常 |
| WSEC_ERR_FILL_TLV | 803 | 填充Tlv异常 |
| WSEC_ERR_MAX | 5000 | CBB最大错误码 |