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

    本篇文章主讲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的所有发送的数据包均是以下格式.
    atsha204a加密芯片使用攻略——配置篇

    word address 指示这个数据包是为何作用,有如下值
    atsha204a加密芯片使用攻略——配置篇最常用的就是0x03 命令数据包了

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

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

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

    再来看看配置区config的内容
    atsha204a加密芯片使用攻略——配置篇
    对atsha204a的所有地址操作都是基于word地址进行的,如上图所示。

    好了,现在我们先来看下读命令格式(也就是数据包data域里面的具体内容)
    atsha204a加密芯片使用攻略——配置篇
    第一个字节是操作码,read command 的操作码是0x02,
    第二个字节的最高位bit7指示是读取32字节还是4字节,1为读取32字节。bit0指示读哪个区。
    第三个字节是Address地址。
    关于这里的地址,datasheet手册上写着如下
    atsha204a加密芯片使用攻略——配置篇
    读写命令中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个字节,那么数据包格式如下:
    atsha204a加密芯片使用攻略——配置篇

    如果通信正常,那么芯片就会返回数据,返回的数据包格式如下
    atsha204a加密芯片使用攻略——配置篇
    各数据域的意思与发送的数据一样。
    根据刚才的例子,返回的数据就是如下:

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

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

    这里仅仅是演示了读的命令,如果是其他命令,则数据域会更加复杂,所幸ATMEL有专门的库来封装这些操作,官方库文件如下列表:
    atsha204a加密芯片使用攻略——配置篇
    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的配置表
    atsha204a加密芯片使用攻略——配置篇以下我讲的地址全部是word地址
    配置区地址0x00-0x03是不允许写的,只能读。
    从0x04开始讲起,首先是I2C Address,可以设置I2C的器件地址,如果I2C总线上挂了好几个atsha204a,可以修改一下这个地址,然后是CheckMacConfig,文档介绍如下
    atsha204a加密芯片使用攻略——配置篇这个字节理解起来挺费劲的,这个字节只影响读写命令和CheckMac命令,对于Read和Write命令,在进行加密读\写的时候要匹配TempKey中的SourceFlag相应的位,否则加密读\写将会失败,什么是加密读写?在后面会介绍到,而对于CheckMac命令也是类似,可以参照一下文档具体使用。
    接下来是OTP Mode
    文档描述如下
    atsha204a加密芯片使用攻略——配置篇
    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个字节,每个位具体配置如下
    atsha204a加密芯片使用攻略——配置篇
    atsha204a加密芯片使用攻略——配置篇一位一位的说
    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作为密钥区,如果能读写则必须是加密进行。
    说到这里大家先看一张表格
    atsha204a加密芯片使用攻略——配置篇可以清楚看到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命令如下
    atsha204a加密芯片使用攻略——配置篇我们要写config zone,地址是0x04,4字节写入,所以填充如下
    opcode = 0x12,
    zone = 0x00,
    address = 0x04,
    value = 0x80,0xA0,0x80,0xA0
    数据包为如下格式
    atsha204a加密芯片使用攻略——配置篇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的用法,我截个图给大家看一下
    atsha204a加密芯片使用攻略——配置篇
    大概的意思就是,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命令格式如下:
    atsha204a加密芯片使用攻略——配置篇参数一目了然,不再多说,这里只需要注意,
    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如下:
    atsha204a加密芯片使用攻略——配置篇
    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的一幅图,
    atsha204a加密芯片使用攻略——配置篇
    这个流程图其实非常明了,主要步骤如下:
    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 原文):
    atsha204a加密芯片使用攻略——配置篇

    GenDig command 使用SHA-256算法结合TempKey中的值去更新TempKey,在执行这条命令前,TempKey中的值必须是合法的。
    因为一些加密命令如MAC,HMAC命令都需要用到TempKey值,使用这条命令可以多增加一些slot区的使用验证,从而达到更加安全的验证。而在加密读的过程中,这条命令必须被正确执行,相应的区才能被正确的加密读取。
    关于Nonce 命令和Read 命令,分别在我上一篇配置篇和上文中都提到了,这里不再讨论。

    加密写,加密写稍微复杂一点,这里还是放Atmel-8981文档的图
    atsha204a加密芯片使用攻略——配置篇

    同样,加密写也是为了防止别人在总线上获取密钥。与加密读过程类似,不过主机这里还要计算一个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,都没有明文在总线上传输,嗅探者也就不能截获我们设置的密钥了。

    IAR 快捷键列表 嵌入式开发

    IAR 快捷键列表

    *Ctrl+Shift+V 列出剪切板中所有的字符串供选择粘贴 Ctrl+B 智能选择光标所在括弧内的区域,多次使用可选更大的区域 Ctrl+T 对选择区域进行自动缩进 Ctrl+K 注释掉选择区域 ...
    IAR更改代码字体 嵌入式开发

    IAR更改代码字体

    在IAR Option选项里,可供选择的字体太少,大多数还是不好看的。其实是可以通过配置文件调用所有系统字体的。如下: 首先在你的系统盘里找到这个文件,地址是: C:\Users\你的用户名\AppD...
    IAR常用快捷键和使用小技巧 嵌入式开发

    IAR常用快捷键和使用小技巧

    这篇文章主要是我在IAR使用过程中用到的一些很方便的快捷键和小技巧,方便自己查阅而使用。 1、复制和粘贴几行的部分代码 需求:有时候我们需要复制几行代码的后半部分,不需要复制前半部分。 方法:按住Al...