Hex2Bin转换软件、Bootloader 、OTA加密升级 、STM32程序加密、其他MCU同样适用

程序下载链接

下载链接: https://pan.baidu.com/s/1N91q3PTGwTd3s82rpImKxA

提取码: k2um 

说明:基础 Hex 转换为 Bin 功能免注册、免费使用。注册功能需要付费获取注册码后开启软件注册功能。

注册码获取链接:

https://item.taobao.com/item.htm?id=795374128097

软件说明:

1.这个工具可以将 Hex 文件 转换为 Bin 格式文件,软件是按自己开发 STM32 OAT 功能需求开发的一款辅助 上位机软件。

2.文章提供 CRC16,CRC32校验代码,AES加密、解密代码,方便移植验证使用。

文中的介绍时 bootloader = boot 

有兴趣的朋友可留言探讨。

1. 软件功能:

1.生成 bin:将 Hex 格式文件转换为 Bin 格式。

2.boot 打包为 bin:可以生成指定大小的 bin 格式文件,文件多余的空余位置填充随机数。可在生成的Bin文件指定位置填充加密后的指定数据,用于程序加密使用。

3.app 打包为 bin :可生成整个程序加密后的 Bin 文件,可用于 OTA 中的 APP 文件加密,防止APP泄漏。

4.bin 合并:可将 boot 和 app 合并为一个文件,方便生成时程序一次性烧录。

5.bin / app 加密:提供自定义秘钥的 app 加密功能,和自定义 boot 识别数据的填充设置。

说明:灰色部分为注册后才能使用。 

2. Bootload 加密思路

bootloader文件的构成: 

bootloader 编译文件 + flash加密数据区域 = 烧录用 bootloader;

例如:假设app的开始区域为 0x800A000 ,那boot的文件区域为 0x8000000 ~  0x800A000

1. Flash加密数据区域:

        假设取 0x8009800 ~ 0x800A000 共2kb区域作为加密数据的存储区域,简单说按app的前一个扇区作为加密数据存储区域,因为有的MCU一个扇区大小 2k ,有的 1k ,视具体型号而定,取app的上一个扇区即可。

2. boot 编译文件大小:

        调整Flash分区的大小,boot 的数据不要到 Flash加密数据区域,避免交叉导致 boot 被意外擦除。

3. Flash加密数据区域数据结构:

typedef struct
{
    uint32_t  app_state;            /* app 状态,无APP,有APP */
    uint32_t  mark[4];              /* 初始状态数据 */
    uint32_t  id_mark[4];           /* ID加密数据 */
    ...                             /* 根据需求自定义 */
}APP_t;

4. boot文件打包:

4.1.设定指定大小:

        使用专用 上位机软件导入 boot 程序后,按设定的大小输出输出 bin 文件,多余的地方填充随机数。例如:boot编译文件为 32k, 设定输出大小为40 k,那空余的 8k 全部填充随机数,这样混淆后即便读出boot程序也不知道boot程序具体多大。

4.2.插入加密数据:

        在预留的加密扇区内指定的位置插入加密数据。

        如:数据 mark[4] 是boot第一次运行时会检测的数据,检测这个数据和预期的相符才执行 boot 的加密工作,加密完成后再 修改或删除 mark[4] 数据,确保 boot 的加密工作只做一次。

        id_mark[4] 是加密数据,通过读取 MCU 的 ID ,再通过AES加密算法,加密后存储到 id_mark[4] 。 

uint32_t  mark[4];              /* 初始状态数据 */
uint32_t  id_mark[4];           /* ID加密数据 */

3. APP 加密思路

        1. app 按16字节凑整,即app的大小是 16 的整数倍,这样方便 AES 加密,加密前在app文件末尾插入app文件的 CRC16 校验值,这样boot可以校验app的完整性。在凑整和添加CRC16值后再AES加密文件,最终得到的bin文件作为 boot 升级用。

        2.app校验ID的有效性,app通过读取 boot 加密区域的 ID 加密数据,解密后与读取的MCU ID 做对比,判断程序的有效性。

4. boot 启动流程

4.1 boot跳转代码

 在 boot 需要跳转到app的地方调用这个函数

#define OTA_CODE_START_ADD              (0x0800A000)   /* app 区域储存的首地址 */

void qbt_jump_to_app(void)
{
    typedef void (*app_func_t)(void);
    u32 app_addr = OTA_CODE_START_ADD;
    u32 stk_addr = *((__IO uint32_t *)app_addr);
    app_func_t app_func = (app_func_t)(*((__IO uint32_t *)(app_addr + 4)));

    if ((((u32)app_func & 0xff000000) != 0x08000000) || ((stk_addr & 0x2ff00000) != 0x20000000))
    {
        return;
    }

    __disable_irq();  /*关闭总中断*/
    HAL_DeInit(); /*函数通过写复位寄存器,将所有模块复位。*/

    for (int i = 0; i < 128; i++)
    {
        HAL_NVIC_DisableIRQ((IRQn_Type) i);      /*失能中断*/
        HAL_NVIC_ClearPendingIRQ((IRQn_Type) i); /*清除中断标志位*/
    }

    /* 关闭滴答定时器,复位到默认值 */
    SysTick->CTRL = 0;
    SysTick->LOAD = 0;
    SysTick->VAL = 0;

    HAL_RCC_DeInit();    /*将RCC时钟配置重置为默认重置状态。*/

    __set_CONTROL(0);    /*设置CONTROL寄存器的值。在RTOS工程,这条语句很重要,设置为特权级模式,使用MSP指针*/
    __set_MSP(stk_addr); /* 设置MSP跳转的地址;设置主堆栈指针 */
    app_func();          /* Jump to application running */
}

5. App 启动流程

        app通过读取 boot 加密区域的 ID 加密数据,解密后与读取的 MCU ID 做对比,判断程序的有效性。

5.1 app跳转代码

#define OTA_CODE_START_ADD        (0x0800A000)       /* app 区域储存的首地址 */

/* app  初始化程序
 * main 函数放在最前面调用
 *  */
void app_init(void)
{
    SCB->VTOR = FLASH_BASE | OTA_CODE_START_ADD; /* 跳转到APP地址 */
    __enable_irq();
}

6. AES 加密算法代码

#include <stdio.h>
#include <stdint.h>
#include <string.h>

//----------------------------------------------------------------------------------------------------------------------------------------

//                        "0123456789ABCDEF"                  /* 长度参考 */
#define TEST_TINY_AES_IV  "0123456789ABCDEF"                  /* 初始向量IV,定长 */

//                        "0123456789ABCDEF0123456789ABCDEF"  /* 长度参考 */
#define TEST_TINY_AES_KEY "0123456789ABCDEF0123456789ABCDEF"  /* AES key,定长 */

#define AES_DATA_LEN   (16)                                   /* KEY 加密后的数据长度 */
#define AES_DEC_LEN    (16)                                   /* AES 数据解密后长度 */

#define AES_ENCRYPT     1
#define AES_DECRYPT     0



typedef struct
{
    int nr; /*!<  number of rounds  */
    uint32_t *rk; /*!<  AES round keys    */
    uint32_t buf[68]; /*!<  unaligned data    */
} tiny_aes_context;


/* aes.h ---------------------------------------------------------------- */
void tiny_aes_setkey_enc(tiny_aes_context * ctx, uint8_t *key, int keysize);
void tiny_aes_setkey_dec(tiny_aes_context * ctx, uint8_t *key, int keysize);
void tiny_aes_crypt_ecb(tiny_aes_context * ctx,int mode,uint8_t input[16], uint8_t output[16]);
void tiny_aes_crypt_cbc(tiny_aes_context * ctx,int mode,int length,uint8_t iv[16],uint8_t *input, uint8_t *output);
void tiny_aes_crypt_cfb128(tiny_aes_context * ctx,int mode,int length,int *iv_off,uint8_t iv[16],uint8_t *input, uint8_t *output);



/* aes.c ---------------------------------------------------------------- */
//#include <string.h>
#define TINY_CRYPT_AES

#if 0
#define AES_ENCRYPT     1
#define AES_DECRYPT     0

typedef struct {
    int nr;         /*!<  number of rounds  */
    uint32_t *rk;  /*!<  AES round keys    */
    uint32_t buf[68];  /*!<  unaligned data    */
} tiny_aes_context;
#endif

#if defined(TINY_CRYPT_AES)

/*
 * 32-bit integer manipulation macros (little endian)
 */
#ifndef GET_ULONG_LE
#define GET_ULONG_LE(n,b,i)                             \
{                                                       \
    (n) = ( (uint32_t) (b)[(i)    ]       )        \
        | ( (uint32_t) (b)[(i) + 1] <<  8 )        \
        | ( (uint32_t) (b)[(i) + 2] << 16 )        \
        | ( (uint32_t) (b)[(i) + 3] << 24 );       \
}
#endif

#ifndef PUT_ULONG_LE
#define PUT_ULONG_LE(n,b,i)                             \
{                                                       \
    (b)[(i)    ] = (uint8_t) ( (n)       );       \
    (b)[(i) + 1] = (uint8_t) ( (n) >>  8 );       \
    (b)[(i) + 2] = (uint8_t) ( (n) >> 16 );       \
    (b)[(i) + 3] = (uint8_t) ( (n) >> 24 );       \
}
#endif

#if defined(TINY_CRYPT_AES_ROM_TABLES)

#else

/*
 * Forward S-box & tables
 */
static uint8_t FSb[256];
static uint32_t FT0[256];
static uint32_t FT1[256];
static uint32_t FT2[256];
static uint32_t FT3[256];

/*
 * Reverse S-box & tables
 */
static uint8_t RSb[256];
static uint32_t RT0[256];
static uint32_t RT1[256];
static uint32_t RT2[256];
static uint32_t RT3[256];

/*
 * Round constants
 */
static uint32_t RCON[10];

/*
 * Tables generation code
 */
#define ROTL8(x) ( ( x << 8 ) & 0xFFFFFFFF ) | ( x >> 24 )
#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) )
#define MUL(x,y) ( ( x && y ) ? pow[(log[x]+log[y]) % 255] : 0 )

static int aes_init_done = 0;

static void aes_gen_tables(void)
{
    int i, x, y, z;
    int pow[256];
    int log[256];

    /*
     * compute pow and log tables over GF(2^8)
     */
    for (i = 0, x = 1; i < 256; i++) {
        pow[i] = x;
        log[x] = i;
        x = (x ^ XTIME(x)) & 0xFF;
    }

    /*
     * calculate the round constants
     */
    for (i = 0, x = 1; i < 10; i++) {
        RCON[i] = (uint32_t)x;
        x = XTIME(x) & 0xFF;
    }

    /*
     * generate the forward and reverse S-boxes
     */
    FSb[0x00] = 0x63;
    RSb[0x63] = 0x00;

    for (i = 1; i < 256; i++) {
        x = pow[255 - log[i]];

        y = x;
        y = ((y << 1) | (y >> 7)) & 0xFF;
        x ^= y;
        y = ((y << 1) | (y >> 7)) & 0xFF;
        x ^= y;
        y = ((y << 1) | (y >> 7)) & 0xFF;
        x ^= y;
        y = ((y << 1) | (y >> 7)) & 0xFF;
        x ^= y ^ 0x63;

        FSb[i] = (uint8_t)x;
        RSb[x] = (uint8_t)i;
    }

    /*
     * generate the forward and reverse tables
     */
    for (i = 0; i < 256; i++) {
        x = FSb[i];
        y = XTIME(x) & 0xFF;
        z = (y ^ x) & 0xFF;

        FT0[i] = ((uint32_t)y) ^
            ((uint32_t)x << 8) ^
            ((uint32_t)x << 16) ^ ((uint32_t)z << 24);

        FT1[i] = ROTL8(FT0[i]);
        FT2[i] = ROTL8(FT1[i]);
        FT3[i] = ROTL8(FT2[i]);

        x = RSb[i];

        RT0[i] = ((uint32_t)MUL(0x0E, x)) ^
            ((uint32_t)MUL(0x09, x) << 8) ^
            ((uint32_t)MUL(0x0D, x) << 16) ^
            ((uint32_t)MUL(0x0B, x) << 24);

        RT1[i] = ROTL8(RT0[i]);
        RT2[i] = ROTL8(RT1[i]);
        RT3[i] = ROTL8(RT2[i]);
    }
}

#endif

/*
 * AES key schedule (encryption)
 */
void tiny_aes_setkey_enc(tiny_aes_context * ctx, uint8_t *key, int keysize)
{
    int i;
    uint32_t *RK;

#if !defined(TINY_CRYPT_AES_ROM_TABLES)
    if (aes_init_done == 0) {
        aes_gen_tables();
        aes_init_done = 1;
    }
#endif

    switch (keysize) {
    case 128:
        ctx->nr = 10;
        break;
    case 192:
        ctx->nr = 12;
        break;
    case 256:
        ctx->nr = 14;
        break;
    default:
        return;
    }

    ctx->rk = RK = ctx->buf;

    for (i = 0; i < (keysize >> 5); i++) {
        GET_ULONG_LE(RK[i], key, i << 2);
    }

    switch (ctx->nr) {
    case 10:

        for (i = 0; i < 10; i++, RK += 4) {
            RK[4] = RK[0] ^ RCON[i] ^
                ((uint32_t)FSb[(RK[3] >> 8) & 0xFF]) ^
                ((uint32_t)FSb[(RK[3] >> 16) & 0xFF] << 8) ^
                ((uint32_t)FSb[(RK[3] >> 24) & 0xFF] << 16) ^
                ((uint32_t)FSb[(RK[3]) & 0xFF] << 24);

            RK[5] = RK[1] ^ RK[4];
            RK[6] = RK[2] ^ RK[5];
            RK[7] = RK[3] ^ RK[6];
        }
        break;

    case 12:

        for (i = 0; i < 8; i++, RK += 6) {
            RK[6] = RK[0] ^ RCON[i] ^
                ((uint32_t)FSb[(RK[5] >> 8) & 0xFF]) ^
                ((uint32_t)FSb[(RK[5] >> 16) & 0xFF] << 8) ^
                ((uint32_t)FSb[(RK[5] >> 24) & 0xFF] << 16) ^
                ((uint32_t)FSb[(RK[5]) & 0xFF] << 24);

            RK[7] = RK[1] ^ RK[6];
            RK[8] = RK[2] ^ RK[7];
            RK[9] = RK[3] ^ RK[8];
            RK[10] = RK[4] ^ RK[9];
            RK[11] = RK[5] ^ RK[10];
        }
        break;

    case 14:

        for (i = 0; i < 7; i++, RK += 8) {
            RK[8] = RK[0] ^ RCON[i] ^
                ((uint32_t)FSb[(RK[7] >> 8) & 0xFF]) ^
                ((uint32_t)FSb[(RK[7] >> 16) & 0xFF] << 8) ^
                ((uint32_t)FSb[(RK[7] >> 24) & 0xFF] << 16) ^
                ((uint32_t)FSb[(RK[7]) & 0xFF] << 24);

            RK[9] = RK[1] ^ RK[8];
            RK[10] = RK[2] ^ RK[9];
            RK[11] = RK[3] ^ RK[10];

            RK[12] = RK[4] ^
                ((uint32_t)FSb[(RK[11]) & 0xFF]) ^
                ((uint32_t)FSb[(RK[11] >> 8) & 0xFF] << 8) ^
                ((uint32_t)FSb[(RK[11] >> 16) & 0xFF] << 16) ^
                ((uint32_t)FSb[(RK[11] >> 24) & 0xFF] << 24);

            RK[13] = RK[5] ^ RK[12];
            RK[14] = RK[6] ^ RK[13];
            RK[15] = RK[7] ^ RK[14];
        }
        break;

    default:

        break;
    }
}

/*
 * AES key schedule (decryption)
 */
void tiny_aes_setkey_dec(tiny_aes_context * ctx, uint8_t *key, int keysize)
{
    int i, j;
    tiny_aes_context cty;
    uint32_t *RK;
    uint32_t *SK;

    switch (keysize) {
    case 128:
        ctx->nr = 10;
        break;
    case 192:
        ctx->nr = 12;
        break;
    case 256:
        ctx->nr = 14;
        break;
    default:
        return;
    }

    ctx->rk = RK = ctx->buf;

    tiny_aes_setkey_enc(&cty, key, keysize);
    SK = cty.rk + cty.nr * 4;

    *RK++ = *SK++;
    *RK++ = *SK++;
    *RK++ = *SK++;
    *RK++ = *SK++;

    for (i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8) {
        for (j = 0; j < 4; j++, SK++) {
            *RK++ = RT0[FSb[(*SK) & 0xFF]] ^
                RT1[FSb[(*SK >> 8) & 0xFF]] ^
                RT2[FSb[(*SK >> 16) & 0xFF]] ^
                RT3[FSb[(*SK >> 24) & 0xFF]];
        }
    }

    *RK++ = *SK++;
    *RK++ = *SK++;
    *RK++ = *SK++;
    *RK++ = *SK++;

    memset(&cty, 0, sizeof(tiny_aes_context));
}

#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3)     \
{                                               \
    X0 = *RK++ ^ FT0[ ( Y0       ) & 0xFF ] ^   \
                 FT1[ ( Y1 >>  8 ) & 0xFF ] ^   \
                 FT2[ ( Y2 >> 16 ) & 0xFF ] ^   \
                 FT3[ ( Y3 >> 24 ) & 0xFF ];    \
                                                \
    X1 = *RK++ ^ FT0[ ( Y1       ) & 0xFF ] ^   \
                 FT1[ ( Y2 >>  8 ) & 0xFF ] ^   \
                 FT2[ ( Y3 >> 16 ) & 0xFF ] ^   \
                 FT3[ ( Y0 >> 24 ) & 0xFF ];    \
                                                \
    X2 = *RK++ ^ FT0[ ( Y2       ) & 0xFF ] ^   \
                 FT1[ ( Y3 >>  8 ) & 0xFF ] ^   \
                 FT2[ ( Y0 >> 16 ) & 0xFF ] ^   \
                 FT3[ ( Y1 >> 24 ) & 0xFF ];    \
                                                \
    X3 = *RK++ ^ FT0[ ( Y3       ) & 0xFF ] ^   \
                 FT1[ ( Y0 >>  8 ) & 0xFF ] ^   \
                 FT2[ ( Y1 >> 16 ) & 0xFF ] ^   \
                 FT3[ ( Y2 >> 24 ) & 0xFF ];    \
}

#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3)     \
{                                               \
    X0 = *RK++ ^ RT0[ ( Y0       ) & 0xFF ] ^   \
                 RT1[ ( Y3 >>  8 ) & 0xFF ] ^   \
                 RT2[ ( Y2 >> 16 ) & 0xFF ] ^   \
                 RT3[ ( Y1 >> 24 ) & 0xFF ];    \
                                                \
    X1 = *RK++ ^ RT0[ ( Y1       ) & 0xFF ] ^   \
                 RT1[ ( Y0 >>  8 ) & 0xFF ] ^   \
                 RT2[ ( Y3 >> 16 ) & 0xFF ] ^   \
                 RT3[ ( Y2 >> 24 ) & 0xFF ];    \
                                                \
    X2 = *RK++ ^ RT0[ ( Y2       ) & 0xFF ] ^   \
                 RT1[ ( Y1 >>  8 ) & 0xFF ] ^   \
                 RT2[ ( Y0 >> 16 ) & 0xFF ] ^   \
                 RT3[ ( Y3 >> 24 ) & 0xFF ];    \
                                                \
    X3 = *RK++ ^ RT0[ ( Y3       ) & 0xFF ] ^   \
                 RT1[ ( Y2 >>  8 ) & 0xFF ] ^   \
                 RT2[ ( Y1 >> 16 ) & 0xFF ] ^   \
                 RT3[ ( Y0 >> 24 ) & 0xFF ];    \
}

/*
 * AES-ECB block encryption/decryption
 */
void tiny_aes_crypt_ecb(tiny_aes_context * ctx,
           int mode, uint8_t input[16], uint8_t output[16])
{
    int i;
    uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3;

    RK = ctx->rk;

    GET_ULONG_LE(X0, input, 0);
    X0 ^= *RK++;
    GET_ULONG_LE(X1, input, 4);
    X1 ^= *RK++;
    GET_ULONG_LE(X2, input, 8);
    X2 ^= *RK++;
    GET_ULONG_LE(X3, input, 12);
    X3 ^= *RK++;

    if (mode == AES_DECRYPT) {
        for (i = (ctx->nr >> 1) - 1; i > 0; i--) {
            AES_RROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3);
            AES_RROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3);
        }

        AES_RROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3);

        X0 = *RK++ ^
            ((uint32_t)RSb[(Y0) & 0xFF]) ^
            ((uint32_t)RSb[(Y3 >> 8) & 0xFF] << 8) ^
            ((uint32_t)RSb[(Y2 >> 16) & 0xFF] << 16) ^
            ((uint32_t)RSb[(Y1 >> 24) & 0xFF] << 24);

        X1 = *RK++ ^
            ((uint32_t)RSb[(Y1) & 0xFF]) ^
            ((uint32_t)RSb[(Y0 >> 8) & 0xFF] << 8) ^
            ((uint32_t)RSb[(Y3 >> 16) & 0xFF] << 16) ^
            ((uint32_t)RSb[(Y2 >> 24) & 0xFF] << 24);

        X2 = *RK++ ^
            ((uint32_t)RSb[(Y2) & 0xFF]) ^
            ((uint32_t)RSb[(Y1 >> 8) & 0xFF] << 8) ^
            ((uint32_t)RSb[(Y0 >> 16) & 0xFF] << 16) ^
            ((uint32_t)RSb[(Y3 >> 24) & 0xFF] << 24);

        X3 = *RK++ ^
            ((uint32_t)RSb[(Y3) & 0xFF]) ^
            ((uint32_t)RSb[(Y2 >> 8) & 0xFF] << 8) ^
            ((uint32_t)RSb[(Y1 >> 16) & 0xFF] << 16) ^
            ((uint32_t)RSb[(Y0 >> 24) & 0xFF] << 24);
    } else {        /* AES_ENCRYPT */
        for (i = (ctx->nr >> 1) - 1; i > 0; i--) {
            AES_FROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3);
            AES_FROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3);
        }

        AES_FROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3);

        X0 = *RK++ ^
            ((uint32_t)FSb[(Y0) & 0xFF]) ^
            ((uint32_t)FSb[(Y1 >> 8) & 0xFF] << 8) ^
            ((uint32_t)FSb[(Y2 >> 16) & 0xFF] << 16) ^
            ((uint32_t)FSb[(Y3 >> 24) & 0xFF] << 24);

        X1 = *RK++ ^
            ((uint32_t)FSb[(Y1) & 0xFF]) ^
            ((uint32_t)FSb[(Y2 >> 8) & 0xFF] << 8) ^
            ((uint32_t)FSb[(Y3 >> 16) & 0xFF] << 16) ^
            ((uint32_t)FSb[(Y0 >> 24) & 0xFF] << 24);

        X2 = *RK++ ^
            ((uint32_t)FSb[(Y2) & 0xFF]) ^
            ((uint32_t)FSb[(Y3 >> 8) & 0xFF] << 8) ^
            ((uint32_t)FSb[(Y0 >> 16) & 0xFF] << 16) ^
            ((uint32_t)FSb[(Y1 >> 24) & 0xFF] << 24);

        X3 = *RK++ ^
            ((uint32_t)FSb[(Y3) & 0xFF]) ^
            ((uint32_t)FSb[(Y0 >> 8) & 0xFF] << 8) ^
            ((uint32_t)FSb[(Y1 >> 16) & 0xFF] << 16) ^
            ((uint32_t)FSb[(Y2 >> 24) & 0xFF] << 24);
    }

    PUT_ULONG_LE(X0, output, 0);
    PUT_ULONG_LE(X1, output, 4);
    PUT_ULONG_LE(X2, output, 8);
    PUT_ULONG_LE(X3, output, 12);
}

/*
 * AES-CBC buffer encryption/decryption
 */
void tiny_aes_crypt_cbc(tiny_aes_context * ctx,
           int mode,
           int length,
           uint8_t iv[16],
           uint8_t *input, uint8_t *output)
{
    int i;
    uint8_t temp[16];

    if (mode == AES_DECRYPT) {
        while (length > 0) {
            memcpy(temp, input, 16);
            tiny_aes_crypt_ecb(ctx, mode, input, output);

            for (i = 0; i < 16; i++)
                output[i] = (uint8_t)(output[i] ^ iv[i]);

            memcpy(iv, temp, 16);

            input += 16;
            output += 16;
            length -= 16;
        }
    } else {
        while (length > 0) {
            for (i = 0; i < 16; i++)
                output[i] = (uint8_t)(input[i] ^ iv[i]);

            tiny_aes_crypt_ecb(ctx, mode, output, output);
            memcpy(iv, output, 16);

            input += 16;
            output += 16;
            length -= 16;
        }
    }
}

/*
 * AES-CFB128 buffer encryption/decryption
 */
void tiny_aes_crypt_cfb128(tiny_aes_context * ctx,
              int mode,
              int length,
              int *iv_off,
              uint8_t iv[16],
              uint8_t *input, uint8_t *output)
{
    int c, n = *iv_off;

    if (mode == AES_DECRYPT) {
        while (length--) {
            if (n == 0)
                tiny_aes_crypt_ecb(ctx, AES_ENCRYPT, iv, iv);

            c = *input++;
            *output++ = (uint8_t)(c ^ iv[n]);
            iv[n] = (uint8_t)c;

            n = (n + 1) & 0x0F;
        }
    } else {
        while (length--) {
            if (n == 0)
                tiny_aes_crypt_ecb(ctx, AES_ENCRYPT, iv, iv);

            iv[n] = *output++ = (uint8_t)(iv[n] ^ *input++);

            n = (n + 1) & 0x0F;
        }
    }

    *iv_off = n;
}

#endif

/* mode: 0 dec 解密, 1 enc 加密
 * k_check_t *cd   :输入数据
 * uint8_t *enc_db :输出数据
 * */
uint8_t key_aes_enc_dec(uint8_t mode,uint8_t *cd,uint8_t *enc_db)
{
    tiny_aes_context ctx;
    uint8_t iv[16 + 1];
    uint8_t private_key[32 + 1];

#if 1
    if ((mode == 1)&&(enc_db != NULL))
    {
        /* encrypt */
        memcpy(iv, TEST_TINY_AES_IV, strlen(TEST_TINY_AES_IV));
        iv[sizeof(iv) - 1] = '\0';
        memcpy(private_key, TEST_TINY_AES_KEY, strlen(TEST_TINY_AES_KEY));
        private_key[sizeof(private_key) - 1] = '\0';

        memset(enc_db, 0x0, sizeof(AES_DATA_LEN));
        tiny_aes_setkey_enc(&ctx, (uint8_t *) private_key, 256);
        tiny_aes_crypt_cbc(&ctx, AES_ENCRYPT, AES_DEC_LEN, iv, (uint8_t *)cd, enc_db);
    }
#endif

    if ((mode == 0)&&(enc_db != NULL))
    {
        /* decrypt */
        memcpy(iv, TEST_TINY_AES_IV, strlen(TEST_TINY_AES_IV));
        iv[sizeof(iv) - 1] = '\0';

        memcpy(private_key, TEST_TINY_AES_KEY, strlen(TEST_TINY_AES_KEY));

        private_key[sizeof(private_key) - 1] = '\0';

        tiny_aes_setkey_dec(&ctx, (uint8_t *) private_key, 256);
        tiny_aes_crypt_cbc(&ctx, AES_DECRYPT, AES_DEC_LEN, iv,(uint8_t *)cd ,(uint8_t *)enc_db);
    }
    return 1;
}

//测试
int main()
{
	uint8_t data[] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F};
	uint8_t output_enc[16]; // 加密数据
	uint8_t output_dec[16]; // 解密数据
	
	key_aes_enc_dec(1,data,output_enc); //加密
	printf("enc:");
    for (uint8_t var = 0; var < 16; ++var)
    {
   		 printf("%02X",output_enc[var]);
    }
	printf("\n");
	
	key_aes_enc_dec(0,output_enc,output_dec); //解密
	printf("dec:");
    for (uint8_t var = 0; var < 16; ++var)
    {
   		 printf("%02X",output_dec[var]);
    }
	printf("\n");
  
    return 0;
}

//计算结果
//enc:7A34715E1C18847155B58997C76E3ECC
//dec:000102030405060708090A0B0C0D0E0F

7. CRC16 校验算法代码

 CRC16 算法代码 1:

/* CRC16 余式表 */
static uint16_t crctalbeabs[] =
{
    0x0000, 0xCC01, 0xD801, 0x1400, 0xF001, 0x3C00, 0x2800, 0xE401,
    0xA001, 0x6C00, 0x7800, 0xB401, 0x5000, 0x9C01, 0x8801, 0x4400
};
 
/*!
 *  功  能: CRC16校验
 *  param1: 指向要校验的数据的指针
 *  param2: 要校验的数据的长度
 *  retval: 校验所得到的值,uint16_t 类型
 *
 *  说  明: 本次CRC校验为查表法,多项式为 x16+x15+x2+1(0x8005),CRC的初始值为0xFFFF
 */
uint16_t Crc16_C(uint8_t *ptr, uint32_t len)
{
    uint16_t crc = 0xffff;
    uint32_t i;
    uint8_t ch;
 
    for (i = 0; i < len; i++)
    {
        ch = *ptr++;
        crc = crctalbeabs[(ch ^ crc) & 15] ^ (crc >> 4);
        crc = crctalbeabs[((ch >> 4) ^ crc) & 15] ^ (crc >> 4);
    }
 
    return crc;
}
 
//测试代码
int main() 
{
    uint8_t data[] = {0x12, 0x34, 0x56, 0x78};
    uint32_t crc = Crc16_C(data, sizeof(data));
 
    printf("CRC16: 0x%04X\n", crc);
 
    return 0;
}
 
//输出结果
CRC16: 0x107B

CRC16 算法代码 2:

#include <stdio.h>
#include <stdint.h>
 
static uint16_t yl_crc16(unsigned char *buffer, uint16_t len)
{
    uint16_t wcrc = 0XFFFF;         //16位crc寄存器预置
    uint8_t temp;
    uint16_t i = 0, j = 0;          //计数
    for (i = 0; i < len; i++)       //循环计算每个数据
    {
        temp = *buffer & 0X00FF;    //将八位数据与crc寄存器亦或
        buffer++;                   //指针地址增加,指向下个数据
        wcrc ^= temp;               //将数据存入crc寄存器
        for (j = 0; j < 8; j++)     //循环计算数据的
        {
            if (wcrc & 0X0001)      //判断右移出的是不是1,如果是1则与多项式进行异或。
            {
                wcrc >>= 1;         //先将数据右移一位
                wcrc ^= 0XA001;     //与上面的多项式进行异或
            }
            else                    //如果不是1,则直接移出
            {
                wcrc >>= 1;         //直接移出
            }
        }
    }
 
    return wcrc;
}
 
int main() 
{
    unsigned char data[] = {0x12, 0x34, 0x56, 0x78};
    int len = sizeof(data) / sizeof(data[0]);
    uint16_t crc = yl_crc16(data, len);
    printf("CRC16: 0x%04X\n", crc);
    return 0;
}
 
//输出结果
CRC16: 0x107B

8.程序下载链接

链接: https://pan.baidu.com/s/1N91q3PTGwTd3s82rpImKxA

提取码: k2um 

  • 18
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值