本节主要分析官方提供的Provision代码,并着重讲下508A配置ConfigZone流程,X.509证书重组及写入等。
代码可以在我分享的链接中下载:http://download.csdn.net/detail/howiexue/9900619
如下图:Provison实际分为Client Provision和Server Provision,根据需求的不同,以及508A扮演的角色不同会不一样。
一般的流程是:
1、Client一般是MCU在工厂生产所跑的程序代码,首先Client与Server和508Device建立链接,然后开始Provisioning过程。
2、Provisioning开始会根据之前的规划配置Write并Lock 508的ConfigZone,之后根据需求,在某个的slot通过**
GenKey()
产生唯一的一对公私密钥**,
3、然后将Publickey返回给Client,PrivateKey永久放在508内部,外界无法探知,Client拿到了508设备的PubKey,添加一些必要参数,如时间、CommonName等通过
GenCSR()
生成证书请求文件(CSR),并把CSR发送到Server中。
4、Server接受到device的CSR,根据CSR请求的数据组成X.509格式的设备证书(Build Certificate),
5、之后将Build后的Certificate 的TBS(To be Signed)部分发送给Signer去签名,这里Signer一般是自己公司或者公用可信的CA或二级CA
6、Signer将其签名后的证书返回给Server(签名数据附在证书内容后面)。
7、Server接受到Signer签名后的证书后,将证书发给Client,然后再由Client 将证书分解写入508A内部。
8、在数据全部写入后,Lock 508的Data Zone,这样以后就可以通过508A内部唯一的证书(由设备自己的私钥生成,并由CA进行签名)来进行设备认证了。
后面会介绍如何验证证书,以及Challenge 508A。
代码链接:http://download.csdn.net/detail/howiexue/9900619
int client_provision(void)
{
atcab_init();
ret = atcab_is_locked(LOCK_ZONE_CONFIG, &lockstate);
if (ret != ATCA_SUCCESS) return ret;
if (!lockstate)
{
ret = atcab_write_ecc_config_zone(g_ecc_configdata);
if (ret != ATCA_SUCCESS) return ret;
ret = atcab_lock_config_zone(&lock_response);
if (ret != ATCA_SUCCESS) return ret;
}
可以看出,设备开始client_provision
后,首先就是向Config 区写入配置数据g_ecc_configdata
,然后将其Lock,只有Lock后才能操作DataZone。官方Demo的g_ecc_configdata
数据如下:
数据对应了Config Zone存储空间的内容,如17byte就是I2C地址:0xC0。(我按照MarkDown指令做了,咋还不能代码高亮显示呢。。)
static const uint8_t g_ecc_configdata[128] = {
0x01, 0x23, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x04, 0x05, 0x06, 0x07, 0xEE, 0x00, 0x01, 0x00,
0xC0, 0x00, 0x55, 0x00, 0x8F, 0x20, 0xC4, 0x44, 0x87, 0x20, 0xC4, 0x44, 0x8F, 0x0F, 0x8F, 0x8F,
0x9F, 0x8F, 0x83, 0x64, 0xC4, 0x44, 0xC4, 0x44, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x33, 0x00, 0x1C, 0x00, 0x13, 0x00, 0x1C, 0x00, 0x3C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x33, 0x00,
0x1C, 0x00, 0x1C, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x3C, 0x00 };
Config Zone配置完后,开始写入密钥等数据
//Write data
ret = atcab_is_locked(LOCK_ZONE_DATA, &lockstate);
if (ret != ATCA_SUCCESS) return ret;
if (!lockstate)
{
ret = atcab_priv_write(signer_ca_private_key_slot, g_signer_ca_private_key, 0, NULL);
if (ret != ATCA_SUCCESS) return ret;
ret = atcab_write_zone(DEVZONE_DATA, access_key_slot, 0, 0, access_key, 32);
if (ret != ATCA_SUCCESS) return ret;
ret = atcab_lock_data_zone(&lock_response);
if (ret != ATCA_SUCCESS) return ret;
}
ret = atcab_genkey(signer_private_key_slot, signer_public_key);
if (ret != ATCA_SUCCESS) return ret;
ret = atcab_genkey(device_private_key_slot, device_public_key);
if (ret != ATCA_SUCCESS) return ret;
写入密钥等数据后,开始Build Signer证书和Device证书
signer_cert_ref_size = sizeof(signer_cert_ref);
ret = build_and_save_cert(
&g_cert_def_1_signer,
signer_cert_ref,
&signer_cert_ref_size,
g_signer_ca_public_key,
signer_public_key,
signer_id,
&signer_issue_date,
config64,
signer_ca_private_key_slot);
if (ret != ATCA_SUCCESS) return ret;
disp_size = sizeof(disp_str);
atcab_bin2hex( signer_cert_ref, signer_cert_ref_size, disp_str, &disp_size);
printf("Signer Certificate:\r\n%s\r\n", disp_str);
device_cert_ref_size = sizeof(device_cert_ref);
ret = build_and_save_cert(
&g_cert_def_2_device,
device_cert_ref,
&device_cert_ref_size,
signer_public_key,
device_public_key,
signer_id,
&device_issue_date,
config64,
signer_private_key_slot);
if (ret != ATCA_SUCCESS) return ret;
disp_size = sizeof(disp_str);
atcab_bin2hex( device_cert_ref, device_cert_ref_size, disp_str, &disp_size);
printf("Device Certificate:\r\n%s\r\n", disp_str);
Buid生成 Ceritificate代码实现:
if (cert_def->expire_years == 0)
{
ret = atcacert_date_get_max_date(cert_def->expire_date_format, &expire_date);
if (ret != ATCACERT_E_SUCCESS) return ret;
}
ret = atcacert_cert_build_start(&build_state, cert_def, cert, cert_size, ca_public_key);
if (ret != ATCACERT_E_SUCCESS) return ret;
ret = atcacert_set_subj_public_key(build_state.cert_def, build_state.cert, *build_state.cert_size, public_key);
if (ret != ATCACERT_E_SUCCESS) return ret;
ret = atcacert_set_issue_date(build_state.cert_def, build_state.cert, *build_state.cert_size, issue_date);
if (ret != ATCACERT_E_SUCCESS) return ret;
ret = atcacert_set_expire_date(build_state.cert_def, build_state.cert, *build_state.cert_size, &expire_date);
if (ret != ATCACERT_E_SUCCESS) return ret;
ret = atcacert_set_signer_id(build_state.cert_def, build_state.cert, *build_state.cert_size, signer_id);
if (ret != ATCACERT_E_SUCCESS) return ret;
ret = atcacert_cert_build_process(&build_state, &config32_dev_loc, config32);
if (ret != ATCACERT_E_SUCCESS) return ret;
ret = atcacert_cert_build_finish(&build_state);
if (ret != ATCACERT_E_SUCCESS) return ret;
ret = atcacert_get_tbs_digest(build_state.cert_def, build_state.cert, *build_state.cert_size, tbs_digest);
if (ret != ATCACERT_E_SUCCESS) return ret;
ret = atcab_sign(ca_slot, tbs_digest, signature);
if (ret != ATCA_SUCCESS) return ret;
ret = atcacert_set_signature(cert_def, cert, cert_size, max_cert_size, signature);
if (ret != ATCACERT_E_SUCCESS) return ret;
ret = atcacert_get_device_locs(cert_def, device_locs, &device_locs_count, sizeof(device_locs) / sizeof(device_locs[0]), 32);
if (ret != ATCACERT_E_SUCCESS) return ret;
##欢迎转载,Howie原创作品,本文地址:
http://blog.csdn.net/howiexue/article/details/75266589
##谢谢