ATSHA204A加密芯片使用攻略——配置篇

2021-07-28 09:11
219

大家好,这是接上一篇使用篇的博客,本篇文章主讲atsha204a加密芯片的配置方式,前面讲到,atsha204a加密芯片内部rom分三个区域,一个是config zone,一个是slot zone,还有一个是OTP zone,本篇不只讲解config zone的配置,还讲解slot 和 OTP区域的配置方法,并且结合官方的库来演示一下代码。

首先约定一下,本文所有的通信接口均使用I2C协议,但所有的功能都能在单总线上实现。

开始,我想先讲几个细节,这是刚开始对于接触这款芯片的我的一些困扰。

1、芯片的config区和data区一旦锁定,没有办法解锁,锁的方法只能通过lock command来进行锁定。

2、config区在没锁定的时候,可以使用write command来进行写操作,但注意,0x00-0x03地址(word地址,详情请参考手册)不能被写,0x15word地址不能使用write command来写。

3、在config锁定前,data区(包括slot区和OTP区)既不能写也不能读。而在config锁定后,data区锁定前,data区只能写不能读,在data区锁定后,可以根据config中的配置来进行读写。

我之所以总结出这几点,是能让大家好理解这些区的读写属性,接下来进入正题。


1、通信包的格式

atsha204a的所有发送的数据包均是以下格式.



word address 指示这个数据包是为何作用,有如下值


最常用的就是0x03 命令数据包了


count是数据包的长度,包括count本身,data和CRC16。


data是数据内容,根据命令的不同而不同。


CRC16是数据包的校验码,校验内容从count到data。


再来看看配置区config的内容


对atsha204a的所有地址操作都是基于word地址进行的,如上图所示。


好了,现在我们先来看下读命令格式(也就是数据包data域里面的具体内容)


第一个字节是操作码,read command 的操作码是0x02,

第二个字节的最高位bit7指示是读取32字节还是4字节,1为读取32字节。bit0指示读哪个区。

第三个字节是Address地址。

关于这里的地址,datasheet手册上写着如下


读写命令中Param2的这个Address如上,高8位为0,低8位的前3位是偏移量,高5位是block,一个block为32字节,所以config 分3个block(0-3),slot分16个block(0-15),otp分2个block(0-1),如果是使用32字节进行读写的话,则忽略前3位offset。我们举个例子,比如说,我们要读config区的word地址0x09那4个字节,因为0x09是属于block1的,偏移是1(config的block划分是,word 0x00 -0x07是block,0,0x08-0x0F为block1,0x10-0x15是block2,反正就是32个字节为1个block,slot和otp相同)

Address[4:3] = 1;

如果是4字节读取,那么

Address[2:0] = 1;

如果是32字节读取

则忽略Address[2:0] 。


现在我们来举个例子,说说通信的数据包。

假设我们要读取config的word0地址那4个字节,那么数据包格式如下:



如果通信正常,那么芯片就会返回数据,返回的数据包格式如下


各数据域的意思与发送的数据一样。

根据刚才的例子,返回的数据就是如下:


因我们读的是芯片序列号,xx是每块芯片的唯一序列号一部分。


这里仅仅是演示了读的命令,如果是其他命令,则数据域会更加复杂,所幸ATMEL有专门的库来封装这些操作,官方库文件如下列表:


sha204_comm_marshling.h和sha204_comm_marshling.c这两个文件里面的

uint8_t sha204m_execute(

uint8_t op_code, uint8_t param1, uint16_t param2,

uint8_t datalen1, uint8_t *data1, uint8_t datalen2,

uint8_t *data2, uint8_t datalen3, uint8_t *data3,

uint8_t tx_size, uint8_t *tx_buffer, uint8_t rx_size,

uint8_t *rx_buffer);

这个函数封装了所有命令,使用起来非常方面,具体实现的话可以去下载库的源码进行查看,而移植性的文件则是sha204_i2c.c、sha204_physical.h、sha_timer_utilities.h和sha_timer_utilities.c这几个文件,做移植只需要简单修改里面几个关于i2c通信和延时的函数即可。


本节以一个简单的例子来讲述了命令的基本格式,并简单的介绍了官方库文件的结构,有问题的可以私信。


config区的配置

这节是这篇博客的重点,只有正确配置了config,atsha204a芯片才能按自己的意图办事。

我再放一下config zone的配置表


以下我讲的地址全部是word地址

配置区地址0x00-0x03是不允许写的,只能读。

从0x04开始讲起,首先是I2C Address,可以设置I2C的器件地址,如果I2C总线上挂了好几个atsha204a,可以修改一下这个地址,然后是CheckMacConfig,文档介绍如下


这个字节理解起来挺费劲的,这个字节只影响读写命令和CheckMac命令,对于Read和Write命令,在进行加密读\写的时候要匹配TempKey中的SourceFlag相应的位,否则加密读\写将会失败,什么是加密读写?在后面会介绍到,而对于CheckMac命令也是类似,可以参照一下文档具体使用。

接下来是OTP Mode

文档描述如下


OTP Mode = 0xAA 只读模式,在OTP锁定后,只能读取OTP区中的内容

OTP Mode = 0x55 消耗模式,在OTP锁定后,写操作只能使位1变0,不能再变为1,比如原先的内容是0xFF,写入0xFC,就变为0xFC,再写0xFF,则仍然是0xFC,写入0x00则立即清零并且不能再写其他值(这个过程有点像flash的烧写)。

OTP Mode = 0x00 传统模式,在OTP锁定后,不能读OTP0和OTP1,也不能以32字节读取。

其他值不被允许。

Selector Mode,这个字节定义0x15地址上的Selector更新方式,

Selector Mode = 0x00 ,使用UpdateExtra 命令可以随意更新Selector中的值,

Selector Mode = 其他值,只有当Selector中的值为0时,才能被UpdateExtra 命令命令更新。

这里顺便说一下Selector,当执行Pause Command命令的时候,Pause Command命令参数中指定的selector与配置中的selector相等时,器件将不会进入空闲模式。

对于一般用户,0x04地址的4个配置按默认值设置即可。


接下来是地址0x05-0x0C关于slot 的配置了,这里才是这节的重点,也是需要注意最多的地方。

每个slot config占用2个字节,每个位具体配置如下




一位一位的说

bit0-3:指定加密读的slot区,这里的意思是,如果你把slotX设置成可以加密读取,则这里要指定加密读取的密钥存放的slot,简单来说,你要读一个slotX,而slot config[X]已经被配置成可以加密读,但是需要知道slot config[X].ReadKey中指定的slot区的密钥。

bit4:0:这个slot区可以用于所有加密命令,1:这个slot只能用于CheckMac命令和GenDig命令。

bit5:0:此slot中存放的密钥可以无限使用,1:此slot存放的密钥有限使用,次数根据UseFlag或LastKeyFlag指定。

bit6 : 0:可以明文读取,1:必须加密读取。

bit7:0:此slot不是密钥区,可以随意读写,1:此slot作为密钥区,如果能读写则必须是加密进行。

说到这里大家先看一张表格


可以清楚看到IsSecret和EncryptRead位的配置对slot读操作的影响。

IsSecret = 1;EncryptRead = 0;slot不能被读。

IsSecret = 1;EncryptRead = 1;slot能被加密读。

IsSecret = 0;EncryptRead = 0;随意读。

说回slot config配置,bit8-bit11,指定加密写操作的slot区密钥,跟bit0-3类似,只不过这里是写操作,使用write command命令。

bit12-15 Write Config表,上述Write Config 那张表看起来有点费劲,bit12-15对于DeriveKey Command 和 Write command命令有不同的意思,对于DeriveKey Command,就是决定生成的新的密钥要通过什么途径来获取(Target?,Parent?),具体大家可以看我上一篇使用篇中对于DeriveKey Command的描述。而对于Write Command,定义如下

bit15 = 0;bit14 = 0;bit13 =0; 随意写

bit15 = x;bit14 = 0;bit13 =1; 不能写

bit15 = 1;bit14 = 0;bit13 =x; 不能写

bit15 = x;bit14 = 1;bit13 =x; 加密写


到此大致介绍完了slot区的配置,这里举个最简单的例子,如下

现在要把slot0和slot1设置成密钥区,不能进行任何读写,可以执行所有加密命令,无限次使用,则地址word0x04的配置应该是0x80 0xA0 0x80 0xA0,

根据手册,得知write command命令如下


我们要写config zone,地址是0x04,4字节写入,所以填充如下

opcode = 0x12,

zone = 0x00,

address = 0x04,

value = 0x80,0xA0,0x80,0xA0

数据包为如下格式



Data_2的MAC域在进行加密写操作的时候才会有内容,这里不进行加密写操作,所以上述数据包没有这个字段,大家如果使用官方封装的库,可以使用sha204m_execute函数


函数原型如下:

uint8_t sha204m_execute(uint8_t op_code, uint8_t param1, uint16_t param2,

uint8_t datalen1, uint8_t *data1, uint8_t datalen2, uint8_t *data2, uint8_t datalen3, uint8_t *data3,

uint8_t tx_size, uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer);


这个函数参数很多,主要是考虑到各种命令的各种不同内容,按上面的描述则调用这个函数时,具体内容为:

state = sha204m_execute(

0x12,

0x00,

0x05,

4,*yourbuffer,

0,0,0,0,

SHA204_CMD_SIZE_MIN,

txbuf,

WRITE_RSP_SIZE,

rxbuf

);

当然这是一段伪代码, yourbuffer是data_1:value的存放地方,SHA204_CMD_SIZE_MIN和READ_32_RSP_SIZE在库中都有定义,实际上在这个函数实现内部SHA204_CMD_SIZE_MIN和WRITE_RSP_SIZE指定的大小均不起作用,在函数内部自动根据命令来调节收发数据包的大小,而用户只需要给定足够大的txbuf和rxbuf即可。


接下来是UseFlag,这里UseFlag里面的值指明了对应的slot区(只限slot0-7)中的key还能使用多少次,但前提是slot config.SingleUse = 1,UseFlag才会有用。在原datasheet的78页里面详细介绍了single-use key的用法,我截个图给大家看一下


大概的意思就是,slot0-7才有useflag这功能,slot8-14没有(slot15比较特殊)。如果相应slot config.singleuse = 1,那么当执行一些需要用到此slot的加密命令时而UseFlag[SlotID] = 0x00,那么这些命令就会返回错误。UseFlag的计数方式简单的说就是这个8位数位为1的个数,比如0xFF是八次,0x7F是7次,0x01是1次,如此类推。

当执行了一些加密命令时,UseFlag就会从最高位开始置零,DeriveKey命令可以更新UseFlag中的值,关于DeriveKey命令,大家可以看一下我上一篇使用篇的博客,因篇幅问题,不再讨论。

UpdateCount是对应的slot使用DeriveKey更新了多少次,到了0xFF就回滚至0x00。


然后是LastKeyUse0-15,首先注意,这个”Last”不是上一个的意思,而是最后一个的意思,也就是说,这LastKeyUse0-15都是为slot15服务的,真是厉害,其实LastKeyUse使用起来和UseFlag差不多,也是要slot15 config.singleuse = 1才有效,而计算剩余使用次数的方法是,所有LastKeyUse位1的个数加起来,那么总共就有16*8 = 128次了,不过用完后,slot15就彻底完了,不能再使用,无法被DeriveKey更新,这也是slot15比较特殊的地方。


地址0x15不能被write command写,只能通过其他命令,关于UserExtra,官方源文档中说了这个可以被UpdateExtra Command更新,它的用途主要是给用户使用的,其他用途不明,如果有其他人知道这个字节有什么用,也希望告知,谢谢。

Selector前文中提了一下:执行Pause Command命令的时候,Pause Command命令参数中指定的selector与配置中的selector相等时,器件将不会进入空闲模式。也可以被

UpdateExtra Command更新,

UpdateExtra Command命令格式如下:


参数一目了然,不再多说,这里只需要注意,

1、Mode.bit1 = 1时,这条命令做的操作是,减少NewValue中指定的SlotID的使用次数。

2、UserExtra中的值不为0,那么此条命令如果更新UserExtra的话将会返回失败。

3、如果SelectorMode不为0,而且Selector不为0,那么那么此条命令如果更新Selector的话将会返回失败。


Lock Data 和Lock Config是控制锁定数据区和配置区的两个字节,

LockData = 0x55,data区没有锁定可以进行写操作。

LockData = 0x00,data区进行锁定,读写需要根据配置来进行。


LockConfig =0x55,config区没有锁定可以进行读写操作。

LockConfig = 0x00,config区不能写。

这两个字节必须使用LockCommand来设置,LockCommand如下:


Zone.bit0决定的是锁config还是OTP区,Zone.bit7 = 1,则不计算需要锁定区域的CRC16值,否则需要输入一个CRC16值来校验。

Summary如果Zone.bit7=0,那么就这里就需要填入相应锁定区域的CRC16值,否则填0x0000。如果命令成功就返回0。


本节介绍了config zone的配置,用户可以根据自己的需要来对config 进行配置,强烈建议用户去多次阅读datasheet才能深刻理解。


slot区的配置

此区的配置没那么复杂,slot主要意图是存放密钥,当然也可以设置成eeprom来使用,但一般用户都不会这么做。


slot区一共分16部分,slot0-15,每部分可以存放32字节密钥,相信足够使用。

对slot区的配置无外乎读写内容,在config区锁定前,所有对slot区的读写操作均返回错误。在config区锁定后,data区锁定前,只能写slot区而不能读取,在二者都锁定后,可以根据上节所讲的slot config来进行读写。

假设我们配置完了config区,现在我们来写slot区,很简单,在data区锁定前可以随意读写,但强烈建议使用32字节来写操作,采用4字节写操作,会有很多的限制条件。

假如我们对slot0写入0x11,0x11,…..0x11(共32个0x11),使用write command,参数如下(这里我们暂时先不考虑各种加密读写,会在本文最后介绍加密读写)

opcode = 0x12,

zone = 0x80|0x02; //32字节写,写slot区。

address = 0x00;

data_1 = 32个字节 0x11;

data_2 不填

如果写入成功,atsha204a将会返回0。


OTP区配置

OTP区和slot区配置类似,在atsha204a里,OTP分16部分,每部分4字节,默认值都是0xffffffff,OTP区在config区锁定前无法进行任何读写操作,在config锁定后,data区锁定前,不能读,只能写,与slot区不同的是,OTP区并没有加密读写这一概念,另外也强烈建议使用32字节写,4字节写入会有很多限制,在data区锁定后,OTP区的读写操作由OTP Mode决定,在config区那节已经进行描述,这里不再论述。

关于OTP区的作用,一是用户可以自定义用途,二是OTP区要参与一些加密命令的MAC摘要计算,如果还有其他用途,欢迎读者补充。


加密读写

本人觉得加密读写是高级用户需要的功能,既然atsha204a提供这个功能,那想必此功能也十分有用,废话不多说,进入正题。

加密读,只有当slot config.EncryptRead = 1和slot config.IsSecret = 1时才能进行。

加密读是为了防止别人在总线上嗅探到密钥,这里我借用官方文档Atmel-8981的一幅图,


这个流程图其实非常明了,主要步骤如下:

1、首先发送Nonce Command命令,更新TempKey中的值,主机这边根据命令返回的randout来使用SHA-256算法计算出TempKey中的值。

2、发送GenDig Command,Gen Dig 命令中的参数KeyID ,就是slot config.ReadKey,比如说,我们要读取slot1的密钥,而slot config[0].ReadKey 设置为0,那么我们就需要知道slot0中存放的密钥才能读取slot1的密钥,发送完这个命令后如果执行正确,TempKey中的值会被重新计算,而主机需要根据Read Key等一些列参数计算TempKey中的值。

3、执行读命令,读取slot区中的值,这时候返回来的内容是经过异或加密的,密钥是第2步计算出来的摘要,也就是说:读回来的值^第二步计算出来的摘要 = 原文。


这里说下GenDig Command,这个命令在我上一篇使用篇的博客中没有提到,这里说一下,这条命令作用如下(datasheet 原文):



GenDig command 使用SHA-256算法结合TempKey中的值去更新TempKey,在执行这条命令前,TempKey中的值必须是合法的。

因为一些加密命令如MAC,HMAC命令都需要用到TempKey值,使用这条命令可以多增加一些slot区的使用验证,从而达到更加安全的验证。而在加密读的过程中,这条命令必须被正确执行,相应的区才能被正确的加密读取。

关于Nonce 命令和Read 命令,分别在我上一篇配置篇和上文中都提到了,这里不再讨论。


加密写,加密写稍微复杂一点,这里还是放Atmel-8981文档的图



同样,加密写也是为了防止别人在总线上获取密钥。与加密读过程类似,不过主机这里还要计算一个MAC发送给atsha204a。

1、发送Nonce Command命令,更新TempKey中的值,主机这边根据命令返回的randout来使用SHA-256算法计算出TempKey中的值。

2、发送GenDig command,KeyID 是所要写的slot config.writekey中指定的ID,比如我们要写slot1,而slot config[1].writekey 设置为0,那这个keyID就是0。然后主机这边根据Slot0中的密钥和其他参数计算出一个摘要(Session Key),当然atsha204a那边也会进行同样的计算并存在TempKey中。

3、我们要写的密钥和第二步计算出来的摘要进行异或运算等到加密文。

4、再根据第二步生成的摘要和明文还有其他参数(参照流程图中指示)计算出一个Host MAC。

5、执行写命令,写命令中参数value是加密文,而参数MAC是Host MAC(关于Write command的格式请回看上文)。

6、atsha204a收到这个命令后,会对value解密(就是和自己的TempKey做异或运算),然后再执行类似第4步的计算过程得到Client MAC,比较Host MAC和Client MAC就知道写入的数据是否正确了。


这样,整个加密写过程就是如此,在这整个过程中,无论是密钥,还是Write Key,都没有明文在总线上传输,嗅探者也就不能截获我们设置的密钥了。


总结

本文介绍了atsha204a这款芯片的一系列配置方法,这是本人多日来研究所得,不过总结的最全的还是原datasheet,本人写的博客可能没有彻彻底底的把这款芯片的所有功能以及用途介绍清楚,开发者根据这么多的配置项,完全可以配置成自己所要的功能(如防抄板、产品匹对,密钥验证等)。另外本文中的不足之处,恳请指正

————————————————

版权声明:本文为CSDN博主「tw」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/a5882230/article/details/52214845



kevin
13924645577
电话咨询
13924649321
微信
微信
微信咨询
邮箱
kevin@idkt.com