ATECC508A芯片开发笔记(五):Provision执行过程及代码分析

ATECC508A芯片开发笔记(五):Provision过程及代码分析

  • Provision流程分析
  • Provision代码分析(508 Demo)

本节主要分析官方提供的Provision代码,并着重讲下508A配置ConfigZone流程,X.509证书重组及写入等。
代码可以在我分享的链接中下载:http://download.csdn.net/detail/howiexue/9900619


Provision流程分析

如下图:Provison实际分为Client Provision和Server Provision,根据需求的不同,以及508A扮演的角色不同会不一样。

ATECC508A芯片开发笔记(五):Provision执行过程及代码分析_第1张图片

一般的流程是:

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。


Provision代码分析(508 Demo)

代码链接:http://download.csdn.net/detail/howiexue/9900619

从Start Provisioning开始分析:

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
##谢谢

你可能感兴趣的:(嵌入式开发,网络安全-ATECC508A)