mbedtls移植之CTR_DRBG随机数生成器

本文介绍了如何在不支持硬件真随机数的情况下,通过MbedTLS库移植CTR_DRBG算法在嵌入式系统中生成伪随机数,包括配置、熵源添加和随机数生成过程。

一、概述

因使用真随机数需要硬件支持,在硬件不支持时,我们需要通过软件来实现伪随机数生成器。根据NITS SP 800-90A的推荐,推荐的随机数生成为HASH_DRBG、HMAC_DRBG、CTR_DRBG。本文主要介绍如何通过mbedtls移植实现CTR_DRBG生成随机数。

二、 mbedtls简要介绍

MbedTLS是一个开源、可移植、易使用、可读性高的SSL库,实现了常所用的加解密算法、X.509证书操作以及TLS协议操作。MbedTLS各功能模块独立性高、耦合度低,可以通过配置宏定义进行功能裁剪,非常适合对空间和效率要求高的嵌入式系统。

三、实现

3.1 移植MbedTLS代码

移植自mbedTLS 2.16版本
为实现CTR_DRBG需拷贝如下文件
在这里插入图片描述

随后对config.h进行编辑,通过设置宏来选择启用哪些功能
config.h如下

#ifndef MBEDTLS_CONFIG_H
#define MBEDTLS_CONFIG_H

/* AES-256-CBC */
#define MBEDTLS_AES_C
#define MBEDTLS_AES_ROM_TABLES

/* CTR_DRBG*/
#define MBEDTLS_CTR_DRBG_C
#define MBEDTLS_ENTROPY_C

/*是否自定义熵源,若在windows和linux下可注释,则使用默认熵源*/
#define MBEDTLS_NO_PLATFORM_ENTROPY

// SHA-256
#define MBEDTLS_SHA256_C

#endif /* MBEDTLS_CONFIG_H */

common.h如下:

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

#if defined(MBEDTLS_CONFIG_FILE)
#include MBEDTLS_CONFIG_FILE
#else
#include "mbedtls/config.h"
#endif

3.2 随机数生成器

3.2.1 添加熵源

若在windows和linux平台,mbedtls可使用默认熵源:

  1. linux:/dev/urandom
  2. windows:CryptGenRandom
    否则,需提供熵源。如下是以时间戳为熵源的示例
int get_clock_for_entropy( void *data,unsigned char *output, size_t len, size_t *olen ) {
    time_t now_time;
    time(&now_time);
    unsigned long timer = now_time;
    ((void) data);
    *olen = 0;

    if (len < sizeof(unsigned long))
        return (0);

    memcpy(output, &timer, sizeof(unsigned long));
    *olen = sizeof(unsigned long);
    return 0;
}

3.2.2 生成一个随机数

入参:

  1. random_number:一个unsigned char指针,用于存储最终生成的随机数
  2. random_length:生成的随机数长度

返回值:

  1. 0:成功
  2. -1:播种失败
  3. -2:随机数生成失败
int generate_one_random_by_ctr_drbg(unsigned char *random_number,size_t random_length){
    mbedtls_ctr_drbg_context ctr_drbg_context;
    mbedtls_entropy_context entropy_context;
    //个性化初始值:用于初始化伪随机数生成器,可设置为任意值
    const char *personalization = "RLOSLEFOS-DRBG-11";

    memset(random_number,'\0',random_length);

    mbedtls_entropy_init(&entropy_context);
    mbedtls_ctr_drbg_init(&ctr_drbg_context);
    //添加熵源
    mbedtls_entropy_add_source(&entropy_context,get_clock_for_entropy,NULL,MBEDTLS_ENTROPY_MIN_PLATFORM,MBEDTLS_ENTROPY_SOURCE_STRONG);
    //第一次播种,无TRNG作为种子
    int result = mbedtls_ctr_drbg_seed(&ctr_drbg_context, mbedtls_entropy_func, &entropy_context, personalization,
                                       strlen(personalization));
    if(result != 0){
        //播种失败
        return -1;
    }
    result = mbedtls_ctr_drbg_random(&ctr_drbg_context,random_number,random_length);
    if(result != 0 || random_number == NULL){
        //随机数生成失败
        return -2;
    }
    mbedtls_entropy_free(&entropy_context);
    mbedtls_ctr_drbg_free(&ctr_drbg_context);
    return 0;

}

3.2.3 生成多个随机数

3.2.3.1 初始化随机数生成器
int initialize_ctr_drbg(mbedtls_ctr_drbg_context *ctr_drbg_context){
    mbedtls_entropy_context entropy_context;
    //mbedtls_ctr_drbg_context  ctr_drbg_context;
    //个性化初始值:用于初始化伪随机数生成器,可设置为任意值
    const char *personalization = "RLOSLEFOS-DRBG-11";


    mbedtls_entropy_init(&entropy_context);
    mbedtls_ctr_drbg_init(ctr_drbg_context);

    //第一次播种,无TRNG作为种子
    int result = mbedtls_ctr_drbg_seed(ctr_drbg_context, mbedtls_entropy_func, &entropy_context, personalization,
                                       strlen(personalization));
    if(result != 0){
       //播种失败
       return -2;
    }

    return 0;
}
3.2.3.2 产生一个随机数

每次调用产生一个随机数,若需要N个随机数,则调用N次

int generate_random_by_ctr_drbg(mbedtls_ctr_drbg_context *ctr_drbg_context, unsigned char *random_number){
    if(ctr_drbg_context == NULL){
        return -1;
    }
    int result = mbedtls_ctr_drbg_random(ctr_drbg_context,random_number,RANDOM_NUMBER_LENGTH);
    if(result != 0){
        return -2;
    }
    return 0;
}
3.2.3.3 清理环境

当使用完成后,需释放相关句柄

void ctr_drbg_free(mbedtls_ctr_drbg_context *ctr_drbg_context){
    mbedtls_ctr_drbg_free(ctr_drbg_context);
}

3.3 获取一个随机数

如下即可获取一个32bits的随机数

int main() {
    unsigned char random_number[4];
    int result = generate_one_random_by_ctr_drbg(random_number,4);
    if(result != 0){
        printf("get random failed \n");
        return -1;
    }
    printf("random hex:");
    for(int t=0;t<4;t++){
        printf("%02x", random_number[t]);
    }
    printf("\n");
    return 0;
}

在这里插入图片描述

int get_proof(unsigned char* priv_key, uint16_t priv_key_len, unsigned char* noc, uint16_t noc_len, unsigned char* dev_pk, uint16_t dev_pk_len, unsigned char* user_pk, uint16_t user_pk_len, unsigned char* out, int *olen) { unsigned char dgest[32] = { 0 }; uint16_t in_len = noc_len + dev_pk_len + user_pk_len; int error = 0; unsigned char* input = malloc(in_len); EC_KEY* ec_key = NULL; EC_GROUP* group = NULL; EC_POINT* point = NULL; BIGNUM* bignum_key = NULL; if (NULL == input) { return -1; } memcpy(input, noc, noc_len); memcpy(input + noc_len, dev_pk, dev_pk_len); memcpy(input + noc_len + dev_pk_len, user_pk, user_pk_len); Hash_Sha256_complete(input, in_len, dgest, 32); ec_key = EC_KEY_new(); if (NULL == ec_key) { goto exit; } group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); EC_KEY_set_group(ec_key, group); bignum_key = BN_new(); if (bignum_key == NULL) { goto exit; } if (!BN_bin2bn(priv_key, priv_key_len, bignum_key)) { goto exit; } EC_KEY_set_private_key(ec_key, bignum_key); if (ECDSA_sign(0, dgest, 32, out, (unsigned int *)olen, ec_key) != 1) { PAKEDebug("Signature failed.\n"); } print_hex("sign dgest", dgest, 32); print_hex("sign priv_key", priv_key, priv_key_len); print_hex("sign output", out, *olen); exit: if (input) free(input); if (ec_key) EC_KEY_free(ec_key); if (group) EC_GROUP_free(group); if (point) EC_POINT_free(point); if (bignum_key) BN_free(bignum_key); return 0; }这是原实现,将其移植mbedtls2.17,写成这样int get_proof(unsigned char *priv_key, uint16_t priv_key_len, unsigned char *noc, uint16_t noc_len, unsigned char *dev_pk, uint16_t dev_pk_len, unsigned char *user_pk, uint16_t user_pk_len, unsigned char *out, int *olen) { int ret; unsigned char dgest[32] = {0}; // SHA-256 摘要 uint16_t in_len = noc_len + dev_pk_len + user_pk_len; unsigned char *input = malloc(in_len); mbedtls_ecdsa_context ecdsa; mbedtls_ctr_drbg_context ctr_drbg; mbedtls_entropy_context entropy; // 内存分配检查 if (input == NULL) { return -1; } // 构造输入数据: noc || dev_pk || user_pk memcpy(input, noc, noc_len); memcpy(input + noc_len, dev_pk, dev_pk_len); memcpy(input + noc_len + dev_pk_len, user_pk, user_pk_len); // 计算 SHA-256 哈希 Hash_Sha256_complete(input, in_len, dgest, 32); // 初始化上下文 mbedtls_ecdsa_init(&ecdsa); mbedtls_ctr_drbg_init(&ctr_drbg); mbedtls_entropy_init(&entropy); // 设置随机数生成器种子 ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *)"ECDSA_SIGN", 10); if (ret != 0) { goto exit; } // 加载椭圆曲线参数(secp256r1) ret = mbedtls_ecp_group_load(&ecdsa.grp, MBEDTLS_ECP_DP_SECP256R1); if (ret != 0) { goto exit; } // 读取私钥到 ecdsa.d ret = mbedtls_mpi_read_binary(&ecdsa.d, priv_key, priv_key_len); if (ret != 0) { goto exit; } // 执行 ECDSA 签名 size_t sig_len = 0; ret = mbedtls_ecdsa_write_signature(&ecdsa, MBEDTLS_MD_SHA256, dgest, 32, out, &sig_len, mbedtls_ctr_drbg_random, &ctr_drbg); if (ret != 0) { goto exit; } // 返回签名长度 *olen = (int)sig_len; exit: // 释放资源 free(input); mbedtls_ecdsa_free(&ecdsa); mbedtls_ctr_drbg_free(&ctr_drbg); mbedtls_entropy_free(&entropy); return (ret == 0) ? 0 : -1; } 对吗
最新发布
10-24
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值