赞
踩
随着行业的技术发展和需求,车载OBD产品中有部分会增加蓝牙BLE和手机APP联系。兼于总体成本和成熟度的综合因素,目前市面上的OBD产品大都使用Microchip的PIC18F25K80。
基本框图如下所示:
PIC18F25K80是Microchip高性能的8位MCU,内置了ECAN模块,支持超低功耗模式。集成了常用的UART, SPI, I2C等接口,用于和外围器件通信。
详见如下链接:
https://www.microchip.com/wwwproducts/en/PIC18F25K80
由于目前国内对知识产权保护方面仍然不够完善,各个公司之间都是互相借鉴甚至直接克隆软硬件,使真正投入资源开发这类产品的公司遭受了巨大的损失。
我们知道,单纯依靠MCU本身的Flash锁定位来防止别人读出Flash中的内容已不足以防止别人的抄袭,此时只能依靠外部增加硬件的安全芯片来保护自己的设计不被非法克隆。
Microchip的ATSHA204A可以满足些类需求,详细资料可以在下面的链接中找到。
https://www.microchip.com/wwwproducts/en/ATSHA204A
ATSHA204A是支持硬件保护的安全芯片,能提供安全的存贮区域来保护用户的密钥和其它重要数据,并且支持SHA256的硬件加速引擎来完成身份验证等功能。是实现软硬件防克隆,IP保护,配件耗材管控的理想方案。
为了方便客户的硬件设计,ATSHA204A提供了丰富的封装选项,从最通用的SOIC8到最小尺寸的UDFN8(2*3mm)。
UDFN8, SOIC8, TSSOP8, SOT323, 3 PADS contact
和MCU的接口支持通用的I2C接口或单总线接口,占用MCU的脚位非常少。
ATSHA204A支持很宽的工作电压范围,2.0V~5.5V,和MCU的接口电压从1.8V到5.5V。可以非常方便地适配到大部分的系统中。
ATSHA204A内部有16个Slot可以存放数据,每个Slot都可以根据需要做不同的配置。由于这里只是演示简单的身份验证过程,只需要用一个Slot来保存密钥。可以使用ACES和CK101来对204做Provision,Slot 0用来保存密钥,所以需要设置成不可读,不可写。配置如下,
其它的Slot可以配置成可读可写的,这样就可以当作E2PROM来保存用户数据。
把配置区锁定后,就可以向Slot0中写入密钥。之后再把数据区锁定。
只有配置和数据区都锁定以后才能正常执行验证的完整过程。
AN_8834 - ATSHA204 Authentication Modes 中可以了解使用SHA256做身份验证的基本过程
上图是可以把Alice理解成MCU,Bob理解成外加的ATSHA204A安全芯片。
预先会在SHA204A中写入密钥,如上图中的Shared Key;
在现场验证时,MCU会产生一个随机数,将随机数发给ATSHA204A做Crypto Hash运算(实际上就是对密钥和随机数来做了SHA256的运算,产生一个HASH值);
同时MCU也会用代码做同样的运算(对密钥和随机数执行软件的SHA256运算,也会产生一个HASH值)
MCU等待一段时间后读取SHA204A的运算结果,和自己的结果做对比;
如果一致就可以认为外部的SHA204A是合法的,程序可以正常运行。否则就不运行。
所以,这里有两点需留意:
由于MCU中有保存密钥,所以密钥最好不要以明文形式存在,可以打散放置或做一些转化,如用位或非操作等。在需要验证前现场恢复密钥。
如果MCU中没有好的随机数生成器,可以用SHA204A来生成随机数Rm。为防止重复质询攻击,MCU需要对随机数Rm做一些处理,增加一些随机因子。比如用ADC来采样的数据替换Rm中的某些字节。再做一次SHA256运算得到Hm,用结果Hm来发起质询验证。
客户这个案子使用的是SOT23封装的单总线接口的ATSHA204A, 所以大部分的工作都是在实现MCU和SHA204A的单总线通信。
单总线的时序需求非常严格,逻辑位0和逻辑位1是通过不同的脉冲来区分的。如果开发过红外遥控的编解码程序应该对这种不会陌生。
MCU中实现单总线有两种方式:
MCU使用4MHz外部晶振,通过PLL倍频到16MHz。为了提高检测脉冲宽度的精度,使用TMR1来对SWI的脉宽测量,最小宽度63nS, 最大测试宽度为4ms,可以满足要求。
和时序相关的延时函数如下,都是通过等待TMR1的超时中断位来实现的:
void delay(uint16_t delay) { // Clearing IF flag. PIR1bits.TMR1IF = 0; TMR1H = (delay >> 8); TMR1L = delay & 0xFF; T1CONbits.TMR1ON = 1; while(!PIR1bits.TMR1IF); PIR1bits.TMR1IF = 0; T1CONbits.TMR1ON = 0; } void delay_ms(uint16_t ms) { while(ms --) { // Clearing IF flag. PIR1bits.TMR1IF = 0; TMR1H = 0xC1; TMR1L = 0xA0; T1CONbits.TMR1ON = 1; while(!PIR1bits.TMR1IF); } T1CONbits.TMR1ON = 0; PIR1bits.TMR1IF = 0; }
204A在每次操作之前都必须唤醒Wake,具体做法是将数据线拉低超过60uS即可,直接调用delay来实现。由于TMR1为累加到0xFFFF时就会产生溢出中断,所以实际延时周期是0xFFFF-X:
void swi_wake_token()
{
SDA_OUTPUT();
SDA_LOW();
delay(0xFFFF - 1000);
SDA_HIGH();
}
由于时序的要求,发送数据中途不能被中断打扰,所以必须关掉全局中断。MCU发送数据串的函数如下:
void swi_send_bytes(uint8_t count, uint8_t *buffer) { uint8_t i, bit_mask; INTERRUPT_GlobalInterruptDisable(); for(i = 0; i < count; i++) { for(bit_mask = 1; bit_mask > 0; bit_mask <<= 1) { if(bit_mask & buffer[i]) //!< Send Logic 1 (7F) { SDA_LOW(); delay(0xFFFF - 2); SDA_HIGH(); delay(0xFFFF - 410); //310 } else //!< Send Logic 0 (7D) { SDA_LOW(); delay(0xFFFF - 2); SDA_HIGH(); delay(0xFFFF - 2); SDA_LOW(); delay(0xFFFF - 2); SDA_HIGH(); delay(0xFFFF - 310); //225 } } } INTERRUPT_GlobalInterruptEnable(); }
MCU接收部分就比较复杂,每检测到SDA脚上有电平变化时就开始TMR1计时,等到下次变化时对计时做出有效性判断。为了提高容错性,可以对判断的范围适当放宽一点。如果产生了超时中断,则说明收到逻辑1或者超时出错了:
ATCA_STATUS swi_receive_bytes(uint8_t *buffer, uint8_t length)
{
ATCA_STATUS status = ATCA_SUCCESS;
uint8_t i;
uint8_t bit_mask;
uint8_t pulse_count;
uint16_t pulse_length;
SDA_INPUT();
INTERRUPT_GlobalInterruptDisable()
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。