zoukankan      html  css  js  c++  java
  • 使用Mbedtls做文件签名及校验

    交叉编译:
    先在shell里设置好编译器: export CC=....(gcc的全路径)
    然后执行编译命令:make
    最后在library目录下找到.a文件,我们可以链接使用的静态库,将其链接进我们的系统。
     
    我在君正X1000平台上链接mbedtls时,提示找不到 read,write,close等几个与文件操作的函数,就自己实现了几个空函数给它链接,因为我用不到文件操作的功能,我只需要使用它来实现固件升级时固件的合法性验证。基本思路是编译好固件后,对其签名,生成的签名结果数据加在固件最后面,升级时,MCU端收到所有数据(反正这个芯片内存足够大)后,按固定长度(签名结果是定长的)计算固件的hash值,将hash值与签名结果传给mbedtls相关的函数进行验证。
    如果内存不够大,不足以装下固件,可能需要在flash上划分一片区域来临时存放即将升级的固件。收到固件时一边写入FLASH,一边计算hash值。当所有固件都接收完,用最终的hash值与签名结果验证通过后再烧写到正确的位置。这个只是一个想法,并没有真正实现。
    固件中验证的代码:
    int make_hash( char * buffer ,int bufLen, char * hash, int hashLen)
    {
        int ret = -1;
        mbedtls_md_context_t ctx;
    const mbedtls_md_info_t *md_info=mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 );
        if( md_info == NULL )
            goto cleanup;
     
        mbedtls_md_init( &ctx );
    ret = mbedtls_md_setup( &ctx, md_info, 0 );
        if( ret != 0 )
            goto cleanup;
     
    ret = mbedtls_md_starts( &ctx );
        if( ret != 0 )
            goto cleanup;
        ret = mbedtls_md_update(&ctx, buffer, bufLen );
    if( ret != 0 )
    goto cleanup;
        ret = mbedtls_md_finish( &ctx, hash );
    cleanup:
        mbedtls_md_free( &ctx );
        return( ret );
    }
    int checkFWValidity( uint8_t * buffer, uint32_t length )
    {
    int fwLen = length - KEY_SIZE;
    uint8_t * signature = buffer+ fwLen;
    int ret=0;
    char hash[64];
    mbedtls_rsa_context rsa;
    mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V21, 0 );
    ret=mbedtls_mpi_read_string(&rsa.N,16,pubKey);
    ret=mbedtls_mpi_read_string(&rsa.E,16,keyEValue);
    rsa.len = ( mbedtls_mpi_bitlen( &rsa.N ) + 7 ) >> 3;
     
    ret= make_hash(buffer, fwLen, hash, sizeof(hash) );
    ret = mbedtls_rsa_pkcs1_verify( &rsa, NULL,NULL,MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA256,0x20, hash,signature );
    mbedtls_md_hmac_finish(NULL,NULL);
    return ret;
    }
    其中 pubKey和keyEValue是我们使用的public key相关的信息,保存在全局变量里即可。这个函数需要的public key不是pem格式的数据,具体叫什么格式我也没有明白。
     
    PC上需要运行的命令:
    交叉编译的同时可以编译一个X86版本的mbedtls, 与签名及验证相关的程序在programspkey目录中,将其中的
     
    运行gen_key,生成 keyfile.key
    运行:./key_app_writer  mode=private filename=keyfile.key output_mode=public output_file=public.key 得到public key
    运行: ./key_app_writer mode=public filename=public.key output_mode=public
    将其输出保存下来,大概内容如下(省略号代表的是很长的字符串)
    N: CBDB69551C.....08E5
    E: 010001
    N:开头的第一行为pubKey的内容(去掉N:)
    E:开头的第二行为keyEValue的内容(同理去掉E:)
     
    private key要保存好,以后用它来做签名
     
    签名的命令: rsa_sign_pss keyfile.key   file(要签名的文件)
    签名的结果自动写入file.sig文件中,可以使用命令 cat file file.sig > signed
    将源文件和签名结果合并写入到一个新文件:signed中。
     
    在君正X1000上,支持mbedtls之后,固件大小增加了100K,如果想要减少,应该可以通过修改config.h来实现。

  • 相关阅读:
    USART串行通信
    GPIO
    adb工具获取andriod设备日志
    [从今天开始修炼数据结构]线性索引查找
    [从今天开始修炼数据结构]有序表查找
    [从今天开始修炼数据结构]查找算法概论和顺序表查找
    [边缘计算]挑战与愿景
    [从今天开始修炼数据结构]无环图的应用 —— 拓扑排序和关键路径算法
    [从今天开始修炼数据结构]图的最短路径 —— 迪杰斯特拉算法和弗洛伊德算法的详解与Java实现
    [从今天开始修炼数据结构]图的最小生成树 —— 最清楚易懂的Prim算法和kruskal算法讲解和实现
  • 原文地址:https://www.cnblogs.com/ceblog/p/13527700.html
Copyright © 2011-2022 走看看