配置加密芯片atsha204a驱动

说明

一个i2c接口的加密芯片,适配到linux RK3576 上。

步骤

注意i2c的速率要100K,太高通讯不上的,然后唤醒就话需要SDA长时间的拉低,时钟太快的话就会唤不醒芯片的。

    QY:配置加密芯片 未完成只是probe上了

diff --git a/arch/arm64/boot/dts/rockchip/rk3576-qiyang.dts b/arch/arm64/boot/dts/rockchip/rk3576-qiyang.dts
index c457ca39a9d4..f88958347093 100644
--- a/arch/arm64/boot/dts/rockchip/rk3576-qiyang.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3576-qiyang.dts
@@ -415,6 +415,7 @@ rgmii_phy1: phy@7 {

 &i2c0 {
        status = "okay";
+       clock-frequency = <100000>;
        pinctrl-names = "default";
        pinctrl-0 = <&i2c0m1_xfer>;

@@ -425,6 +426,13 @@ rtc_sd3078: sd30783@32 {
                status = "okay";
     };

+       atsha204a: atsha204a@64 {
+               compatible = "atmel,atsha204a";
+               clock-frequency = <100000>;
+               reg = <0x64>;
+               status = "okay";
+       };
+
        usbc0: fusb302@22 {
                compatible = "fcs,fusb302";
                reg = <0x22>;
diff --git a/arch/arm64/configs/rockchip_linux_defconfig b/arch/arm64/configs/rockchip_linux_defconfig
index cf7f3c0cc844..7fa639e06768 100644
--- a/arch/arm64/configs/rockchip_linux_defconfig
+++ b/arch/arm64/configs/rockchip_linux_defconfig
@@ -286,7 +286,6 @@ CONFIG_SERIAL_8250_NR_UARTS=32
 CONFIG_SERIAL_8250_RUNTIME_UARTS=15
 CONFIG_SERIAL_8250_DW=y
 CONFIG_SERIAL_OF_PLATFORM=y
-CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_ROCKCHIP=y
 CONFIG_TCG_TPM=y
 CONFIG_TCG_TIS_I2C_INFINEON=y
@@ -690,6 +689,7 @@ CONFIG_CRYPTO_SHA1_ARM64_CE=y
 CONFIG_CRYPTO_SHA2_ARM64_CE=y
 CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
 CONFIG_CRYPTO_AES_ARM64_CE_CCM=y
+CONFIG_CRYPTO_DEV_ATMEL_SHA204A=y
 CONFIG_CRYPTO_DEV_ROCKCHIP=y
 CONFIG_CRYPTO_DEV_ROCKCHIP_DEV=y
 CONFIG_CRC_CCITT=y
diff --git a/drivers/crypto/atmel-i2c.c b/drivers/crypto/atmel-i2c.c
index 81ce09bedda8..87dab61c4605 100644
--- a/drivers/crypto/atmel-i2c.c
+++ b/drivers/crypto/atmel-i2c.c
@@ -315,7 +315,7 @@ static int device_sanity_check(struct i2c_client *client)
         */
        if (cmd->data[LOCK_CONFIG_IDX] || cmd->data[LOCK_VALUE_IDX]) {
                dev_err(&client->dev, "Configuration or Data and OTP zones are unlocked!\n");
-               ret = -ENOTSUPP;
+               // ret = -ENOTSUPP;
        }

        /* fall through */

应用测试

基于对称密钥的挑战-响应认证.

先设备树上不要配置OKAY,然后配置i2c的总线为100K,使用C程序直接操作加密芯片。

当总线上有多个 ATSHA204 设备且 I2C 接口以 133KHz 或更慢的速度运行时,某些数据模式 (如 0x00) 的传输将导致总线上的所有 ATSHA204 设备被唤醒。

由于沿总线传输的后续设备地址只会匹配所需的设备,未使用的设备将保持非活动状态,不会引起任何总线冲突。

在 I2C 模式下,当设备已经处于清醒状态时,设备将忽略发送的唤醒序列。

在解析参数和随后执行正确接收的命令期间,设备将处于忙碌状态,不会响应引脚上的转换。

唤醒

发送 0x00

回复 0x04 0x11 0x33 0x43

0x04 总数
0x11 唤醒回复的状态码
0x33 CRC[7:0] – 对前两个字节(0x04 0x11)计算出的 CRC‑16 校验值的低字节。
0x43 CRC[15:8] – CRC 校验值的高字节。

手册上的:

alt text

加密芯片使用的CRC16算法

alt text

demo里面的实现:

void sha204c_calculate_crc(uint8_t length, uint8_t *data, uint8_t *crc) {
    uint8_t counter;
    uint16_t crc_register = 0;
    uint16_t polynom = 0x8005;
    uint8_t shift_register;
    uint8_t data_bit, crc_bit;

    for (counter = 0; counter < length; counter++) {
        for (shift_register = 0x01; shift_register > 0x00; shift_register <<= 1) {
            data_bit = (data[counter] & shift_register) ? 1 : 0;
            crc_bit = crc_register >> 15;
            crc_register <<= 1;
            if (data_bit != crc_bit)
                crc_register ^= polynom;
        }
    }
    crc[0] = (uint8_t) (crc_register & 0x00FF);
    crc[1] = (uint8_t) (crc_register >> 8);
}

写

大致发送的格式:

字节位置 内容 说明
0 0x03 command flag
1 len 总长度
2 op_code 操作码
3 param1 参数1
4 param2低 参数2低8位
5 param2高 参数2高8位
6-... data1 数据块1(如果有)
... data2 数据块2(如果有)
... data3 数据块3(如果有)
最后2字节 CRC 校验码

返回的是写的状态码。

alt text

现在一直返回0xFF 一般是格式或者参数错误。

测试代码,读取SN码

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>
#include <linux/i2c.h>
#include <stdint.h>

/* ========== 根据自己的硬件修改以下定义 ========== */
#define I2C_BUS         "/dev/i2c-0"    // I2C 设备节点
#define DEVICE_ADDR     0x64            // 芯片 7 位地址,默认 0x60
#define WAIT_WAKE_US    3400            // 唤醒后等待时间 (us)
#define WAIT_CMD_MS     3              // 命令执行等待时间 (ms)
/* ============================================== */

#define SHA204_WRITE   0x01
#define SHA204_READ    0x03

static int atsha_wake(int fd) {
    uint8_t dummy;
    struct i2c_msg msg = {
        .addr  = DEVICE_ADDR,
        .flags = I2C_M_IGNORE_NAK,   // 忽略 NACK 以确保总线释放
        .len   = 0,
        .buf   = &dummy
    };
    struct i2c_rdwr_ioctl_data ioctl_data = {
        .msgs  = &msg,
        .nmsgs = 1
    };
    if (ioctl(fd, I2C_RDWR, &ioctl_data) < 0) {
        perror("Wake ioctl failed");
        return -1;
    }
    usleep(WAIT_WAKE_US);
    printf("Wake-up sequence sent.\n");

    unsigned char buf[4] = {0};
    struct i2c_msg msg1 = {
        .addr  = DEVICE_ADDR,
        .flags = I2C_M_RD,   // 这次是读操作,不忽略 NAK
        .len   = 4,
        .buf   = buf
    };

    struct i2c_rdwr_ioctl_data ioctl_data1 = {
        .msgs  = &msg1,
        .nmsgs = 1
    };

    if (ioctl(fd, I2C_RDWR, &ioctl_data1) < 0) {
        perror("Read after wake failed - check wiring / address");
        close(fd);
        return 1;
    }

    printf("Chip response: 0x%02X 0x%02X 0x%02X 0x%02X\n",
           buf[0], buf[1], buf[2], buf[3]);

    if (buf[0] == 0x04 && buf[1] == 0x11 &&
        buf[2] == 0x33 && buf[3] == 0x43) {
        printf("ATSHA204A woke up successfully.\n");
        // close(fd);
    } else {
        printf("Unexpected response, wake may have failed.\n");
    }

    return 0;
}


// struct my_i2c_msg packet;
int main()
{
    int fd;
    uint8_t packet[8];
    fd = open("/dev/i2c-0", O_RDWR);
    if(fd < 0){
        printf("sha204 open failed!");
    }



    atsha_wake(fd);


    packet[0] = 0x03; //0x03, 0x07, 0x02, 0x00, 0x00, 0x00
    packet[1] = 0x07;
    packet[2] = 0x02;
    packet[3] = 0x00;
    packet[4] = 0x00;
    packet[5] = 0x00;
    packet[6] = 0x1e;
    packet[7] = 0x2d;

for(int i = 0; i < 8; i++) {
    printf("0x%02X ", packet[i]);
}
    printf("\n");
   // 通过 I2C 发送命令包
    struct i2c_msg msg_wr = {
        .addr  = DEVICE_ADDR,
        .flags = 0,                       // 写操作
        .len   = 8,
        .buf   = (uint8_t *)packet
    };
    struct i2c_rdwr_ioctl_data ioctl_wr = {
        .msgs  = &msg_wr,
        .nmsgs = 1
    };

    if (ioctl(fd, I2C_RDWR, &ioctl_wr) < 0) {
        perror("Send command failed");
        return -1;
    }
    usleep(3000);
    // //4.read data
    uint8_t count_buf[7] = {0};
    struct i2c_msg msg_rd = {
        .addr  = DEVICE_ADDR,
        .flags = I2C_M_RD,
        .len   = 7,
        .buf   = count_buf
    };
    struct i2c_rdwr_ioctl_data ioctl_rd = {
        .msgs  = &msg_rd,
        .nmsgs = 1
    };
    if (ioctl(fd, I2C_RDWR, &ioctl_rd) < 0) {
        perror("Read response failed-----yx");
        return -1;
    }
    for(int i = 0; i < 7; i++) {
        printf("0x%02X ", count_buf[i]);
    }
    printf("\n");

    close(fd);
    return 0;

alt text

参考:

https://www.cnblogs.com/iotrookie/articles/6043170.html

https://blog.csdn.net/lijunyan797/article/details/53584345

https://blog.csdn.net/liuxd3000/article/details/105822086

https://blog.csdn.net/qq_30624591/article/details/85251307

https://blog.csdn.net/qq_30624591/article/details/85251307

http://idkt.com/h-nd-32.html

https://blog.wudilabs.com/entry/c4a0811d/

https://www.microchip.com/en-us/products/security/trust-platform

https://microchiptech.github.io/cryptoauthlib/

官方库:

https://github.com/MicrochipTech/cryptoauthlib

posted @ 2026-02-24 11:52  杨旭0324  阅读(129)  评论(0)    收藏  举报