security

hmac_sha256.c

/*
 * Copyright (c) 2021 Midea Co., Ltd. All Rights Reserved.
 *
 * @author 霍长裕
 * @email huocy@midea.com
 * @date 2021-01-01 10:30
 * @des net work
 */

#include "hmac_sha256.h"
#include <stdlib.h>
#include <string.h>

#define SHA256_BLOCK_SIZE 64

static void* H(const void* x,
               const size_t xlen,
               const void* y,
               const size_t ylen,
               void* out,
               const size_t outlen);

static void* sha256(const void* data,
                    const size_t datalen,
                    void* out,
                    const size_t outlen);


size_t midea_hmac_sha256(const void* key,
                   const size_t keylen,
                   const void* data,
                   const size_t datalen,
                   void* out,
                   const size_t outlen) {
  uint8_t k[SHA256_BLOCK_SIZE];
  uint8_t k_ipad[SHA256_BLOCK_SIZE];
  uint8_t k_opad[SHA256_BLOCK_SIZE];
  uint8_t ihash[SHA256_HASH_SIZE];
  uint8_t ohash[SHA256_HASH_SIZE];
  size_t sz;
  int i;

  memset(k, 0, sizeof(k));
  memset(k_ipad, 0x36, SHA256_BLOCK_SIZE);
  memset(k_opad, 0x5c, SHA256_BLOCK_SIZE);

  if (keylen > SHA256_BLOCK_SIZE) {
    // If the key is larger than the hash algorithm's
    // block size, we must digest it first.
    sha256(key, keylen, k, sizeof(k));
  } else {
    memcpy(k, key, keylen);
  }

  for (i = 0; i < SHA256_BLOCK_SIZE; i++) {
    k_ipad[i] ^= k[i];
    k_opad[i] ^= k[i];
  }

  // Perform HMAC algorithm: ( https://tools.ietf.org/html/rfc2104 )
  //      `H(K XOR opad, H(K XOR ipad, data))`
  H(k_ipad, sizeof(k_ipad), data, datalen, ihash, sizeof(ihash));
  H(k_opad, sizeof(k_opad), ihash, sizeof(ihash), ohash, sizeof(ohash));

  sz = (outlen > SHA256_HASH_SIZE) ? SHA256_HASH_SIZE : outlen;
  memcpy(out, ohash, sz);
  return sz;
}

static void* H(const void* x,
               const size_t xlen,
               const void* y,
               const size_t ylen,
               void* out,
               const size_t outlen) {
  void* result;
  size_t buflen = (xlen + ylen);
  uint8_t* buf = (uint8_t*)malloc(buflen);

  memcpy(buf, x, xlen);
  memcpy(buf + xlen, y, ylen);
  result = sha256(buf, buflen, out, outlen);

  free(buf);
  return result;
}

static void* sha256(const void* data,
                    const size_t datalen,
                    void* out,
                    const size_t outlen) {
  size_t sz;
  Sha256Context ctx;
  SHA256_HASH hash;

  Sha256Initialise(&ctx);
  Sha256Update(&ctx, data, datalen);
  Sha256Finalise(&ctx, &hash);

  sz = (outlen > SHA256_HASH_SIZE) ? SHA256_HASH_SIZE : outlen;
  return memcpy(out, hash.bytes, sz);
}

hmac_sha256.h

/*
 * Copyright (c) 2021 Midea Co., Ltd. All Rights Reserved.
 *
 * @author 霍长裕
 * @email huocy@midea.com
 * @date 2021-01-01 10:30
 * @des hmac
 */


#ifndef _HMAC_SHA256_H_
#define _HMAC_SHA256_H_

#ifdef __cplusplus
extern "C" {
#endif  // __cplusplus

#include <stddef.h>
#include "midea_sha256_1.h"


size_t  // Returns the number of bytes written to `out`
midea_hmac_sha256(
    const void* key,
    const size_t keylen,
    const void* data,
    const size_t datalen,
    void* out,
    const size_t outlen);

#ifdef __cplusplus
}
#endif  // __cplusplus

#endif  // _HMAC_SHA256_H_

midea_data_security.c

/*
 * Copyright (c) 2021 Midea Co., Ltd. All Rights Reserved.
 *
 * @author 霍长裕
 * @email huocy@midea.com
 * @date 2021-01-06 10:30
 * @des 加密类
 */

#include "midea_data_security.h"
#include "midea_hmac_sha256.h"
#include "mbedtls/md5.h"
#include "mbedtls/aes.h"
#include "mbedtls/sha256.h"
#include "mbedtls/md.h"
#include "mbedtls/rsa.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ecdh.h"
#include "mbedtls/ecp.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/platform.h"

#define AES128_BLOCK_SIZE 16

int mss_md5_encrypt_to_lc_hex(uint8_t data[], size_t data_size, char **out)
{
    unsigned char decrypt[16];
    mbedtls_md5_context md5_ctx;
    mbedtls_md5_init(&md5_ctx);
    mbedtls_md5_starts(&md5_ctx);
    mbedtls_md5_update(&md5_ctx, data, data_size);
    mbedtls_md5_finish(&md5_ctx, decrypt);
    char *tmp = calloc(33, sizeof(char));
    for (int i = 0; i < 16; i++)
    {
        char t[3] = {0};
        sprintf(t, "%02x", decrypt[i]);
        strcat(tmp, t);
    }
    mbedtls_md5_free(&md5_ctx);
    *out = tmp;
    return 0;
}
int mss_md5_encrypt(uint8_t data[], size_t data_size, uint8_t **out, size_t *out_size)
{
    uint8_t *decrypt = calloc(16, sizeof(uint8_t));
    mbedtls_md5_context md5_ctx;
    mbedtls_md5_init(&md5_ctx);
    mbedtls_md5_starts(&md5_ctx);
    mbedtls_md5_update(&md5_ctx, data, data_size);
    mbedtls_md5_finish(&md5_ctx, decrypt);
    mbedtls_md5_free(&md5_ctx);
    *out = decrypt;
    *out_size = 16;
    return 0;
}
mss_aes128_result mss_crypto_aes128_ecrypt(uint8_t *data, size_t *len, const uint8_t *key, const uint8_t encrypt_type)
{
    int i, ret;
    size_t blocks = *len / AES128_BLOCK_SIZE;
    size_t rest_size = *len % AES128_BLOCK_SIZE;
    uint8_t temp_data[AES128_BLOCK_SIZE];
    uint8_t *data_offset_ptr = data;
    mbedtls_aes_context aes_ctx;
    unsigned char iv[16];
    switch (encrypt_type)
    {
    case 0x00:
        // Set AES128 key
        if (mbedtls_aes_setkey_enc(&aes_ctx, key, 128) != 0)
        {
            ret = MS_AES128_RESULT_ERROR;
            break;
        }
        // Encrypt AES128
        for (i = 0; i < blocks; i++)
        {
            if (mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, data_offset_ptr, temp_data) != 0)
            {
                ret = MS_AES128_RESULT_ERROR;
                break;
            }
            memcpy(data_offset_ptr, temp_data, AES128_BLOCK_SIZE);
            data_offset_ptr += AES128_BLOCK_SIZE;
        }

        // PKCS5_Padding
        rest_size = (uint16_t)AES128_BLOCK_SIZE - rest_size;
        memset(data + *len, (uint8_t)rest_size, (size_t)rest_size);
        if (mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, data_offset_ptr, temp_data) != 0)
        {
            ret = MS_AES128_RESULT_ERROR;
            break;
        }
        memcpy(data_offset_ptr, temp_data, AES128_BLOCK_SIZE);
        *len += rest_size;
        ret = MS_AES128_RESULT_SUCCESS;
        break;
    case 0x01:
    {
        memset(iv, 0, 16);
        mbedtls_aes_init(&aes_ctx);
        // Set AES128 key
        if (mbedtls_aes_setkey_enc(&aes_ctx, key, 128) != 0)
        {
            ret = MS_AES128_RESULT_ERROR;
            break;
        }
        // Encrypt AES128
        for (i = 0; i < blocks; i++)
        {
            if (mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_ENCRYPT, AES128_BLOCK_SIZE, iv, data_offset_ptr, temp_data) != 0)
            {
                ret = MS_AES128_RESULT_ERROR;
                break;
            }
            memcpy(data_offset_ptr, temp_data, AES128_BLOCK_SIZE);
            data_offset_ptr += AES128_BLOCK_SIZE;
        }
        // PKCS5_Padding
        rest_size = (uint16_t)AES128_BLOCK_SIZE - rest_size;
        memset(data + *len, (uint8_t)rest_size, (size_t)rest_size);
        if (mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_ENCRYPT, AES128_BLOCK_SIZE, iv, data_offset_ptr, temp_data) != 0)
        {
            ret = MS_AES128_RESULT_ERROR;
            break;
        }
        memcpy(data_offset_ptr, temp_data, AES128_BLOCK_SIZE);
        *len += rest_size;
        ret = MS_AES128_RESULT_SUCCESS;
    }
    break;
    default:
        ret = MS_AES128_RESULT_ERROR;
        break;
    }
    mbedtls_aes_free(&aes_ctx);
    return (mss_aes128_result)ret;
}

mss_aes128_result mss_crypto_aes128_ecrypt_h(uint8_t *data, size_t len, const uint8_t *key, const uint8_t encrypt_type,
                                                                                uint8_t **output,size_t *output_size)
{
    uint8_t *tmp_data=calloc(len+16,sizeof(uint8_t));
    memcpy(tmp_data,data,len);

    int i, ret;
    size_t blocks = len / AES128_BLOCK_SIZE;
    size_t rest_size = len % AES128_BLOCK_SIZE;
    uint8_t temp_data[AES128_BLOCK_SIZE];
    uint8_t *data_offset_ptr = tmp_data;
    mbedtls_aes_context aes_ctx;
    unsigned char iv[16];
    switch (encrypt_type)
    {
    case 0x00:
        // Set AES128 key
        if (mbedtls_aes_setkey_enc(&aes_ctx, key, 128) != 0)
        {
            ret = MS_AES128_RESULT_ERROR;
            break;
        }
        // Encrypt AES128
        for (i = 0; i < blocks; i++)
        {
            if (mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, data_offset_ptr, temp_data) != 0)
            {
                ret = MS_AES128_RESULT_ERROR;
                break;
            }
            memcpy(data_offset_ptr, temp_data, AES128_BLOCK_SIZE);
            data_offset_ptr += AES128_BLOCK_SIZE;
        }

        // PKCS5_Padding
        rest_size = (uint16_t)AES128_BLOCK_SIZE - rest_size;
        memset(tmp_data + len, (uint8_t)rest_size, (size_t)rest_size);
        if (mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, data_offset_ptr, temp_data) != 0)
        {
            ret = MS_AES128_RESULT_ERROR;
            break;
        }
        memcpy(data_offset_ptr, temp_data, AES128_BLOCK_SIZE);
         
        *output_size= len +rest_size;
        *output=tmp_data;
        ret = MS_AES128_RESULT_SUCCESS;
        break;
    case 0x01:
    {
        memset(iv, 0, 16);
        mbedtls_aes_init(&aes_ctx);
        // Set AES128 key
        if (mbedtls_aes_setkey_enc(&aes_ctx, key, 128) != 0)
        {
            ret = MS_AES128_RESULT_ERROR;
            break;
        }
        // Encrypt AES128
        for (i = 0; i < blocks; i++)
        {
            if (mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_ENCRYPT, AES128_BLOCK_SIZE, iv, data_offset_ptr, temp_data) != 0)
            {
                ret = MS_AES128_RESULT_ERROR;
                break;
            }
            memcpy(data_offset_ptr, temp_data, AES128_BLOCK_SIZE);
            data_offset_ptr += AES128_BLOCK_SIZE;
        }
        // PKCS5_Padding
        rest_size = (uint16_t)AES128_BLOCK_SIZE - rest_size;
        memset(tmp_data + len, (uint8_t)rest_size, (size_t)rest_size);
        if (mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_ENCRYPT, AES128_BLOCK_SIZE, iv, data_offset_ptr, temp_data) != 0)
        {
            ret = MS_AES128_RESULT_ERROR;
            break;
        }
        memcpy(data_offset_ptr, temp_data, AES128_BLOCK_SIZE);
        *output_size= len +rest_size;
        *output=tmp_data;
        ret = MS_AES128_RESULT_SUCCESS;
    }
    break;

    default:
        ret = MS_AES128_RESULT_ERROR;
        break;
    }
    mbedtls_aes_free(&aes_ctx);
    return (mss_aes128_result)ret;
}


mss_aes128_result mss_crypto_aes128_decrypt(uint8_t *data, size_t *len, const uint8_t *key, const uint8_t decrypt_type)
{
    int i, ret;
    size_t blocks = *len / AES128_BLOCK_SIZE;
    size_t rest_size = *len % AES128_BLOCK_SIZE;
    uint8_t temp_data[AES128_BLOCK_SIZE];
    uint8_t *data_offset_ptr = data;
    mbedtls_aes_context aes_ctx;
    unsigned char iv[16];

    if (rest_size != 0)
    {
        return MS_AES128_RESULT_ERROR;
    }

    switch (decrypt_type)
    {
    case 0x00:
        // Set AES128 key
        if (mbedtls_aes_setkey_dec(&aes_ctx, key, 128) != 0)
        {
            ret = MS_AES128_RESULT_ERROR;
            break;
        }
        // Decrypt AES128
        for (i = 0; i < blocks; i++)
        {
            if (mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_DECRYPT, data_offset_ptr, temp_data) != 0)
            {
                ret = MS_AES128_RESULT_ERROR;
                break;
            }
            memcpy(data_offset_ptr, temp_data, AES128_BLOCK_SIZE);
            data_offset_ptr += AES128_BLOCK_SIZE;
        }
        // PKCS5_Padding
        rest_size = data[(*len) - 1];
        if (rest_size > 16 || rest_size == 0)
        {
            ret = MS_AES128_RESULT_ERROR;
            break;
        }
        *len -= rest_size;
        memset(data + *len, 0, (size_t)rest_size);
        ret = MS_AES128_RESULT_SUCCESS;
        break;
    case 0x01:
    {
        memset(iv, 0, 16);
        mbedtls_aes_init(&aes_ctx);
        // Set AES128 key
        ret = mbedtls_aes_setkey_dec(&aes_ctx, key, 128);
        if (ret != 0)
        {
            ret = MS_AES128_RESULT_ERROR;
            break;
        }
        // Decrypt AES128
        for (i = 0; i < blocks; i++)
        {
            if (mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_DECRYPT, AES128_BLOCK_SIZE, (uint8_t *)iv, (uint8_t *)data_offset_ptr, (uint8_t *)temp_data) != 0)
            {
                ret = MS_AES128_RESULT_ERROR;
                break;
            }
            memcpy(data_offset_ptr, temp_data, AES128_BLOCK_SIZE);
            data_offset_ptr += AES128_BLOCK_SIZE;
        }
        // PKCS5_Padding
        rest_size = data[(*len) - 1];
        if (rest_size > 16 || rest_size == 0)
        {
            ret = MS_AES128_RESULT_ERROR;
            break;
        }
        *len -= rest_size;
        memset(data + *len, 0, (size_t)rest_size);

        mbedtls_aes_free(&aes_ctx);

        ret = MS_AES128_RESULT_SUCCESS;
    }
    break;
    default:
        ret = MS_AES128_RESULT_ERROR;
        break;
    }
    mbedtls_aes_free(&aes_ctx);
    return (mss_aes128_result)ret;
}

int mss_hmac_sha256_to_lc_hex(const void *key,const size_t key_size,const void *data,const size_t data_size,char **output)
{
    uint8_t out[SHA256_HASH_SIZE];
    char *out_str = calloc(SHA256_HASH_SIZE * 2 + 1, sizeof(char));
    unsigned i;
    midea_hmac_sha256(key, key_size, data, data_size, &out, sizeof(out));
    for (i = 0; i < 32; i++)
    {
        char t[3] = {0};
        sprintf(t, "%02x", out[i]);
        strcat(out_str, t);
    }
    *output = out_str;
    return 0;
}

int mss_sha256(uint8_t *input, size_t input_size, uint8_t **hash_value, size_t *hash_value_size)
{
    int ret = 0;
    mbedtls_sha256_context ctx;
    mbedtls_sha256_init(&ctx);
    do
    {
        /* SHA-256 */
        if ((ret = mbedtls_sha256_starts_ret(&ctx, 0)) != 0)
        {
            mbedtls_sha256_free(&ctx);
            break;
        }
        ret = mbedtls_sha256_update_ret(&ctx, input, input_size);
        if (ret != 0)
        {
            mbedtls_sha256_free(&ctx);
            break;
        }
        uint8_t *password_sha256_out = calloc(32, sizeof(uint8_t));
        if (password_sha256_out == NULL)
        {
            return -1;
            // return get_error_code(BC_OTHER, SRC_SDK, CODE_ALLOC_MEMORY_FAILED);
        }
        if ((ret = mbedtls_sha256_finish_ret(&ctx, password_sha256_out)) != 0)
        {
            mbedtls_sha256_free(&ctx);
            break;
        }
        *hash_value = password_sha256_out;
        *hash_value_size = 32;
        mbedtls_sha256_free(&ctx);
    } while (0);
     return (ret);
}

int mss_sha256_to_lc_hex(uint8_t *input, size_t input_size, char **hex_hash_value)
{
    uint8_t *hash_value;
    size_t hash_value_size=0;
    int ret=mss_sha256(input,input_size,&hash_value,&hash_value_size);
    if(ret != 0){
        return ret;
    }
    ret=midea_bytes_to_lc_hex_string(hash_value,hash_value_size,hex_hash_value);
    if(ret != 0){
        return ret;
    }
    free(hash_value);
    return 0;
}

/**
 * @brief ecdh 算法生成共享密钥(用于密钥协商)。类存储外设公钥
 *
 * @param device_publicKey 外设公钥
 * @param finalKey  输出共享密钥buf。
 * @return int
 */
int mss_ecdh_shared_finalKey(uint8_t * finalKey,uint8_t * device_publicKey,uint8_t * client_publicKey){
    /** APP向模组请求ECDH公钥A ;模组返回ECDH公钥A;APP将公钥A与自身生成的ECDH私钥生成共享会话密钥,用该会话密钥加密验证密文。将APP的ECDH公钥B与验证密文一起用初始默认密钥加密,发送给模组*/
    int ret = 0;
    mbedtls_ecp_group grp;
    mbedtls_mpi cli_secret;
    mbedtls_mpi cli_pri;
    mbedtls_ecp_point cli_pub, srv_pub;
    mbedtls_entropy_context entropy;
    mbedtls_ctr_drbg_context ctr_drbg;
    const char *pers = "simple_ecdh";

    mbedtls_mpi_init(&cli_pri); //初始化客户端私钥
    mbedtls_mpi_init(&cli_secret);//初始化云端公钥和客户端私钥生成的共享密钥
    mbedtls_ecp_group_init(&grp); //初始化椭圆曲线群结构体
    mbedtls_ecp_point_init(&cli_pub); //初始化椭圆曲线点结构体 客户端公钥
    mbedtls_ecp_point_init(&srv_pub);//初始化椭圆曲线点结构体 设备端公钥
    mbedtls_entropy_init(&entropy); //初始化熵结构体
    mbedtls_ctr_drbg_init(&ctr_drbg);//初始化随机数结构体

    mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
                                (const uint8_t *) pers, strlen(pers));

    //加载椭圆曲线,选择SECP256R1
    ret = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP256R1);
    if(ret != 0){
        return ret;
    }
    
    //客户端生成公开参数
    ret = mbedtls_ecdh_gen_public(&grp,    //椭圆曲线结构体
                                  &cli_pri,//输出cli私密参数d
                                  &cli_pub,//输出cli公开参数Q
                                  mbedtls_ctr_drbg_random, &ctr_drbg);
    if(ret != 0){
        return ret;
    }
    
    unsigned char client_publicKey_buf[65];
    size_t client_publicKey_olen;
    //将客户端的公开参数(一个点Q)导出为(公钥)无符号二进制数据
    mbedtls_ecp_point_write_binary(&grp, &cli_pub,
                            MBEDTLS_ECP_PF_UNCOMPRESSED, &client_publicKey_olen, client_publicKey_buf, sizeof(client_publicKey_buf));
    //去掉首字节04,后面的64字节作为客户端ECDH公钥二进制传给设备
    memcpy(client_publicKey, &client_publicKey_buf[1], 64);
    
    //第一个字节手动设置为04
    unsigned char device_pub_keys[65];
    device_pub_keys[0] = 0x04;
    //后面64个字节为设备传过来的ecdh公钥
    memcpy(&device_pub_keys[1], device_publicKey, 64);
    //从设备端的device_publicKey无符号二进制数据导入为公开参数(一个点 Q)
    mbedtls_ecp_point_read_binary(&grp, &srv_pub, device_pub_keys, 65);
    
    //根据客户端的私钥d和设备端的Q  客户端计算共享密钥
    ret = mbedtls_ecdh_compute_shared(&grp,    //椭圆曲线结构体
                                      &cli_secret, //客户端计算出的共享密钥
                                      &srv_pub, //输入设备端公开参数Q
                                      &cli_pri, //输入客户端本身的私密参数d
                                      mbedtls_ctr_drbg_random, &ctr_drbg);
    if(ret != 0){
        return ret;
    }
 
    //把客户端计算出的共享密钥导出buf中
    unsigned char client_secret_buf[65];
    ret = mbedtls_mpi_write_binary(&cli_secret, client_secret_buf, mbedtls_mpi_size(&cli_secret));
    if(ret != 0){
        return ret;
    }
    memcpy(finalKey, &client_secret_buf[0], 16);

cleanup:
    mbedtls_mpi_free(&cli_pri);
    mbedtls_mpi_free(&cli_secret);
    mbedtls_ecp_group_free(&grp);
    mbedtls_ecp_point_free(&cli_pub);
    mbedtls_ecp_point_free(&srv_pub);
    mbedtls_entropy_free(&entropy);
    mbedtls_ctr_drbg_free(&ctr_drbg);

    return 0;
}

midea_data_security.h

/*
 * Copyright (c) 2021 Midea Co., Ltd. All Rights Reserved.
 *
 * @author 霍长裕
 * @email huocy@midea.com
 * @date 2021-01-06 10:30
 * @des 加密类
 */

#ifndef ms_data_security_h
#define ms_data_security_h

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "midea_hmac_sha256.h"
#include "mbedtls/aes.h"
#include "mbedtls/md5.h"
#include "mbedtls/sha256.h"
#include "mbedtls/md.h"
#include "mbedtls/rsa.h"
#include "mbedtls/entropy.h"

typedef enum
{
    MS_AES128_RESULT_SUCCESS = 0,
    MS_AES128_RESULT_ERROR = 1,
}mss_aes128_result;

typedef signed char     int8_t;
typedef unsigned char   uint8_t;

typedef signed short    int16_t;
typedef unsigned short  uint16_t;

/**
 * @brief 使用md5加密,返回16进制字符串,需要释放。
 * 
 * @param data 输入子节
 * @param out 输出 ,需要释放。
 * @return int 
 */
int mss_md5_encrypt_to_lc_hex(uint8_t data[], size_t data_size, char **out);

int mss_md5_encrypt(uint8_t data[], size_t data_size, uint8_t **out ,size_t *out_size);

///AES加解密
///data:The address of the source data will decrypt and after decrypted sucessful,the decrypted data will store in the same address
///len:The length of the data will be decrypted and after decrypted sucessful,it will be the decrypted sucessful data length
///key:the key used to decrypted
///decrypt_type:0:ECB, 1:CBC
mss_aes128_result mss_crypto_aes128_ecrypt(uint8_t *data, size_t *len, const uint8_t *key, const uint8_t encrypt_type);
mss_aes128_result mss_crypto_aes128_decrypt(uint8_t *data, size_t *len, const uint8_t *key, const uint8_t decrypt_type);

/**
 * @brief AES128加密
 * 
 * @param data 加密数据
 * @param len  长度
 * @param key  加密key
 * @param encrypt_type 加密类型
 * @param output 输出加密后的结果 需要自己管理释放
 * @param output_size 加密后数据长度
 * @return int 
 */
mss_aes128_result mss_crypto_aes128_ecrypt_h(uint8_t *data, size_t len, const uint8_t *key, const uint8_t encrypt_type,
                                                                                uint8_t **output,size_t *output_size);
/**
 * @brief HMAC-SHA256,输出小写16进制字符串,需要释放内存
 * 
 * @param key  密钥
 * @param key_size  密钥长度
 * @param data 数据
 * @param data_size 数据长度
 * @param output 输出小写16进制字符串
 * @return int 
 */
int mss_hmac_sha256_to_lc_hex(const void *key,const size_t key_size,const void *data,const size_t data_size,char **output);
/**
 * @brief sha256 ,返回子节数组,需要释放内存
 * 
 * @param input 输入子节
 * @param len 输入子节长度
 * @param hash_value hash值
 * @param hash_value_size hash值长度
 * @return int 0:成功
 */
int mss_sha256(uint8_t *input, size_t input_size, uint8_t **hash_value, size_t *hash_value_size);

/**
 * @brief  sha256 ,返回小写16进制字符串,需要释放内存
 * 
 * @param input 输入子节
 * @param input_size 输入子节长度
 * @param hex_hash_value 小写16进制字符串
 * @return int 
 */
int mss_sha256_to_lc_hex(uint8_t *input, size_t input_size, char **hex_hash_value);

/**
 * @brief ecdh 算法生成共享密钥(用于密钥协商)。类存储外设公钥
 *
 * @param device_publicKey 外设公钥
 * @param finalKey  输出共享密钥buf。
 * @return int
 */
int mss_ecdh_shared_finalKey(uint8_t * finalKey,uint8_t * device_publicKey,uint8_t * client_publicKey);
#endif

midea_hmac_sha256.c

/*
   hmac_sha256.c
   Originally written by https://github.com/h5p9sl
 */

#include "hmac_sha256.h"
#include <stdlib.h>
#include <string.h>

#define SHA256_BLOCK_SIZE 64

/* LOCAL FUNCTIONS */

// Concatenate X & Y, return hash.
static void* H(const void* x,
               const size_t xlen,
               const void* y,
               const size_t ylen,
               void* out,
               const size_t outlen);

// Wrapper for sha256
static void* sha256(const void* data,
                    const size_t datalen,
                    void* out,
                    const size_t outlen);

// Declared in hmac_sha256.h
size_t hmac_sha256(const void* key,
                   const size_t keylen,
                   const void* data,
                   const size_t datalen,
                   void* out,
                   const size_t outlen) {
  uint8_t k[SHA256_BLOCK_SIZE];
  uint8_t k_ipad[SHA256_BLOCK_SIZE];
  uint8_t k_opad[SHA256_BLOCK_SIZE];
  uint8_t ihash[SHA256_HASH_SIZE];
  uint8_t ohash[SHA256_HASH_SIZE];
  size_t sz;
  int i;

  memset(k, 0, sizeof(k));
  memset(k_ipad, 0x36, SHA256_BLOCK_SIZE);
  memset(k_opad, 0x5c, SHA256_BLOCK_SIZE);

  if (keylen > SHA256_BLOCK_SIZE) {
    // If the key is larger than the hash algorithm's
    // block size, we must digest it first.
    sha256(key, keylen, k, sizeof(k));
  } else {
    memcpy(k, key, keylen);
  }

  for (i = 0; i < SHA256_BLOCK_SIZE; i++) {
    k_ipad[i] ^= k[i];
    k_opad[i] ^= k[i];
  }

  // Perform HMAC algorithm: ( https://tools.ietf.org/html/rfc2104 )
  //      `H(K XOR opad, H(K XOR ipad, data))`
  H(k_ipad, sizeof(k_ipad), data, datalen, ihash, sizeof(ihash));
  H(k_opad, sizeof(k_opad), ihash, sizeof(ihash), ohash, sizeof(ohash));

  sz = (outlen > SHA256_HASH_SIZE) ? SHA256_HASH_SIZE : outlen;
  memcpy(out, ohash, sz);
  return sz;
}

static void* H(const void* x,
               const size_t xlen,
               const void* y,
               const size_t ylen,
               void* out,
               const size_t outlen) {
  void* result;
  size_t buflen = (xlen + ylen);
  uint8_t* buf = (uint8_t*)malloc(buflen);

  memcpy(buf, x, xlen);
  memcpy(buf + xlen, y, ylen);
  result = sha256(buf, buflen, out, outlen);

  free(buf);
  return result;
}

static void* sha256(const void* data,
                    const size_t datalen,
                    void* out,
                    const size_t outlen) {
  size_t sz;
  Sha256Context ctx;
  SHA256_HASH hash;

  Sha256Initialise(&ctx);
  Sha256Update(&ctx, data, datalen);
  Sha256Finalise(&ctx, &hash);

  sz = (outlen > SHA256_HASH_SIZE) ? SHA256_HASH_SIZE : outlen;
  return memcpy(out, hash.bytes, sz);
}

midea_hmac_sha256.h

/*
    hmac_sha256.h
    Originally written by https://github.com/h5p9sl
*/

#ifndef _HMAC_SHA256_H_
#define _HMAC_SHA256_H_

#ifdef __cplusplus
extern "C" {
#endif  // __cplusplus

#include <stddef.h>
#include "midea_sha256_1.h"


size_t  // Returns the number of bytes written to `out`
hmac_sha256(
    // [in]: The key and its length.
    //      Should be at least 32 bytes long for optimal security.
    const void* key,
    const size_t keylen,

    // [in]: The data to hash alongside the key.
    const void* data,
    const size_t datalen,

    // [out]: The output hash.
    //      Should be 32 bytes long. If it's less than 32 bytes,
    //      the resulting hash will be truncated to the specified length.
    void* out,
    const size_t outlen);

#ifdef __cplusplus
}
#endif  // __cplusplus

#endif  // _HMAC_SHA256_H_

midea_security_utils.c

/*
 * Copyright (c) 2021 Midea Co., Ltd. All Rights Reserved.
 *
 * @author 张笔峰
 * @email bifeng.zhang@midea.com
 * @data 2022-03-14 18:23
 */
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "midea_common/midea_data_center.h"
#include "midea_data_security.h"
#include "midea_common/midea_utils.h"

/**
 * @brief 需要释放
 * 国内:md5(app_key),然后取16个字符。
 * 海内:sha256(app_key),然后取16个字符。
 * @param app_key
 * @param out encode后的数据
 * @return int
 */
static int encode_data_key(char *app_key, char **out)
{
    char *encode_data;
    int ret = 0;
    // if (mss_data_center_is_overseas() == 1)
    // {
    //     ret = mss_sha256_to_lc_hex(app_key, strlen(app_key), &encode_data);
    // }
    // else
    // {
        ret = mss_md5_encrypt_to_lc_hex((uint8_t *)app_key, strlen(app_key), &encode_data);
    // }
    if (ret != 0)
    {
        return ret;
    }
    ret = midea_str_substring(encode_data, 0, 16, out);
    return ret;
}

/**
 * @brief 海外接口CBC加密需要IV, 需要释放。
 *
 * @param app_key
 * @param out
 * @return int
 */
static int encode_data_iv(char *app_key, char **out)
{
    // if (mss_data_center_is_overseas() == 1)
    // {
    //     char *encode_data;
    //     int ret = mss_sha256_to_lc_hex(app_key, strlen(app_key), &encode_data);
    //     if (ret != 0)
    //     {
    //         return ret;
    //     }
    //     ret = str_substring(encode_data, 16, 32, out);
    //     return ret;
    // }
    return 0;
}

int mss_decode_aes128_with_app_key(char *encrypt_hex_str, uint8_t **out, size_t *out_size)
{
    char *app_key = mss_share_instance()->ms_config->app_key;
    if (app_key == NULL)
    {
        // todo 后续可以增加一个错误码,处理未设置配置参数的问题
        return -1;
    }
    if (encrypt_hex_str == NULL)
    {
        return -1;
    }

    char *data_key_out = NULL; //需要释放
    int ret = encode_data_key(app_key, &data_key_out);
    if (ret != 0)
    {
        return ret;
    }

    //海外
    // char *data_iv_out = NULL; //需要释放
    // ret = encode_data_iv(app_key, &data_iv_out);
    // if (ret != 0)
    // {
    //     return ret;
    // }

    uint8_t *encrypt_data; //需要释放
    size_t encrypt_data_size;
    ret = midea_hex_string_to_bytes(encrypt_hex_str, &encrypt_data, &encrypt_data_size);
    if (ret != 0)
    {
        return ret;
    }
    printf("The decrypt data size :%d", encrypt_data_size);
    ret = mss_crypto_aes128_decrypt(encrypt_data, &encrypt_data_size, (uint8_t *)data_key_out, 0);

    if (ret != 0)
    {
        free(encrypt_data);
        return ret;
    }
    *out = encrypt_data;
    *out_size = encrypt_data_size;
    return 0;
}

int mss_decode_aes128_with_data_key(char *encrypt_hex_str, uint8_t **out, size_t *out_size)
{

    char *data_key = mss_share_instance()->login_info->data_key;
    if (data_key == NULL)
    {
        // todo 后续可以增加一个错误码,处理未设置配置参数的问题
        return -1;
    }
    if (encrypt_hex_str == NULL)
    {
        return -1;
    }
    uint8_t *data; //需要释放
    size_t data_size;
    int ret = midea_hex_string_to_bytes(encrypt_hex_str, &data, &data_size);
    if (ret != 0)
    {
        return ret;
    }

    ret = mss_crypto_aes128_decrypt(data, &data_size, data_key, 0);
    if (ret != 0)
    {
        return ret;
    }
    *out = data;
    *out_size = data_size;
    return 0;
}

int mss_encode_aes128_with_data_key(char *encrypt_str, char **out)
{
    uint8_t *encrypt_data = (uint8_t *)encrypt_str;
    size_t encrypt_data_len = strlen(encrypt_str);
    printf("开始加密");
    // if (mss_data_center_is_overseas() == 1)
    // {
    //     // todo 海外加密方式
    //     return -1;
    // }
    // else
    // {
    uint8_t *out_put;
    size_t len;
    int ret = mss_crypto_aes128_ecrypt_h(encrypt_data, encrypt_data_len, mss_share_instance()->login_info->data_key, 0, &out_put, &len);
    if (ret != 0)
    {
        return ret;
    }
    char *hex_str = NULL;
    ret = midea_bytes_to_lc_hex_string(out_put, len, &hex_str);
  
    if (ret != 0)
    {
        return ret;
    }
    *out = hex_str;
    // }
    return 0;
}

///设置登录信息
int mss_set_login_info(char *access_token, char *encode_data_key, char *encode_data_iv)
{
    MS_DATA_CENTER *data_center = mss_share_instance();
    //复制AT
    strcpy(data_center->login_info->access_token, access_token);
     
    //解密data key
    uint8_t *data_key_out;
    size_t data_key_out_size;
    int ret = mss_decode_aes128_with_app_key(encode_data_key, &data_key_out, &data_key_out_size);
    if(ret != 0){
        return ret;
    }
    data_center->login_info->data_key_size=data_key_out_size;
    //复制data key
    memcpy(data_center->login_info->data_key, data_key_out, data_key_out_size);
    
    if (encode_data_iv != NULL)
    {
        //解密data iv
        uint8_t *data_iv_out;
        size_t data_iv_out_size;
        int ret = mss_decode_aes128_with_app_key(encode_data_iv, &data_iv_out, &data_iv_out_size);
        if(ret != 0){
            return ret;
        }
        data_center->login_info->data_iv_size=data_iv_out_size;
        //复制data iv
        memcpy(data_center->login_info->data_iv, data_iv_out, data_iv_out_size);
    }
    return 0;
}

midea_security_utils.h

/*
 * Copyright (c) 2021 Midea Co., Ltd. All Rights Reserved.
 * 加密/解密的逻辑过程封装工具
 * @author 张笔峰
 * @email bifeng.zhang@midea.com
 * @data 2022-03-14 18:23
 */

#ifndef MS_SECURITY_UTIL_H
#define MS_SECURITY_UTIL_H
#include "midea_data_types.h"
/**
 * @brief 使用app key解密数据,需要释放内存
 *
 * @param encrypt_hex_str 已加密的16进制字符串数据
 * @param out 解密后的数据
 * @param out_size 解密后的数据长度
 * @return int
 */
int mss_decode_aes128_with_app_key(char *encrypt_hex_str, uint8_t **out, size_t *out_size);

/**
 * @brief 使用data key解密数据,需要释放内存
 * 
 * @param encrypt_hex_str  已加密的16进制字符串数据
 * @param out 解密后的数据
 * @param out_size 解密后的数据长度
 * @return int 
 */
int mss_decode_aes128_with_data_key(char *encrypt_hex_str, uint8_t **out, size_t *out_size);


/**
 * @brief 使用data key加密数据,需要释放内存
 * 
 * @param encrypt_str 待加密的字符串
 * @param out 加密后的16进制字符串
 * @return int 0:成功
 */
int mss_encode_aes128_with_data_key(char *encrypt_str, char **out);

///设置登录信息
int mss_set_login_info(char *access_token ,char *encode_data_key, char *encode_data_iv);
#endif

midea_sha256_1.c

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  WjCryptLib_Sha256
//
//  Implementation of SHA256 hash function.
//  Original author: Tom St Denis, tomstdenis@gmail.com, http://libtom.org
//  Modified by WaterJuice retaining Public Domain license.
//
//  This is free and unencumbered software released into the public domain -
//  June 2013 waterjuice.org
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  IMPORTS
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include "midea_sha256_1.h"
#include <memory.h>

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  MACROS
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#define ror(value, bits) (((value) >> (bits)) | ((value) << (32 - (bits))))

#define MIN(x, y) (((x) < (y)) ? (x) : (y))

#define STORE32H(x, y)                     \
  {                                        \
    (y)[0] = (uint8_t)(((x) >> 24) & 255); \
    (y)[1] = (uint8_t)(((x) >> 16) & 255); \
    (y)[2] = (uint8_t)(((x) >> 8) & 255);  \
    (y)[3] = (uint8_t)((x)&255);           \
  }

#define LOAD32H(x, y)                                                         \
  {                                                                           \
    x = ((uint32_t)((y)[0] & 255) << 24) | ((uint32_t)((y)[1] & 255) << 16) | \
        ((uint32_t)((y)[2] & 255) << 8) | ((uint32_t)((y)[3] & 255));         \
  }

#define STORE64H(x, y)                     \
  {                                        \
    (y)[0] = (uint8_t)(((x) >> 56) & 255); \
    (y)[1] = (uint8_t)(((x) >> 48) & 255); \
    (y)[2] = (uint8_t)(((x) >> 40) & 255); \
    (y)[3] = (uint8_t)(((x) >> 32) & 255); \
    (y)[4] = (uint8_t)(((x) >> 24) & 255); \
    (y)[5] = (uint8_t)(((x) >> 16) & 255); \
    (y)[6] = (uint8_t)(((x) >> 8) & 255);  \
    (y)[7] = (uint8_t)((x)&255);           \
  }

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  CONSTANTS
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// The K array
static const uint32_t K[64] = {
    0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,
    0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL,
    0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL,
    0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
    0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL,
    0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL,
    0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL,
    0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
    0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL,
    0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL,
    0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL,
    0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
    0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL};

#define BLOCK_SIZE 64

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  INTERNAL FUNCTIONS
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// Various logical functions
#define Ch(x, y, z) (z ^ (x & (y ^ z)))
#define Maj(x, y, z) (((x | y) & z) | (x & y))
#define S(x, n) ror((x), (n))
#define R(x, n) (((x)&0xFFFFFFFFUL) >> (n))
#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22))
#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25))
#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3))
#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10))

#define Sha256Round(a, b, c, d, e, f, g, h, i)    \
  t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
  t1 = Sigma0(a) + Maj(a, b, c);                  \
  d += t0;                                        \
  h = t0 + t1;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  TransformFunction
//
//  Compress 512-bits
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void TransformFunction(Sha256Context* Context, uint8_t const* Buffer) {
  uint32_t S[8];
  uint32_t W[64];
  uint32_t t0;
  uint32_t t1;
  uint32_t t;
  int i;

  // Copy state into S
  for (i = 0; i < 8; i++) {
    S[i] = Context->state[i];
  }

  // Copy the state into 512-bits into W[0..15]
  for (i = 0; i < 16; i++) {
    LOAD32H(W[i], Buffer + (4 * i));
  }

  // Fill W[16..63]
  for (i = 16; i < 64; i++) {
    W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
  }

  // Compress
  for (i = 0; i < 64; i++) {
    Sha256Round(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i);
    t = S[7];
    S[7] = S[6];
    S[6] = S[5];
    S[5] = S[4];
    S[4] = S[3];
    S[3] = S[2];
    S[2] = S[1];
    S[1] = S[0];
    S[0] = t;
  }

  // Feedback
  for (i = 0; i < 8; i++) {
    Context->state[i] = Context->state[i] + S[i];
  }
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  PUBLIC FUNCTIONS
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  Sha256Initialise
//
//  Initialises a SHA256 Context. Use this to initialise/reset a context.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Sha256Initialise(Sha256Context* Context  // [out]
) {
  Context->curlen = 0;
  Context->length = 0;
  Context->state[0] = 0x6A09E667UL;
  Context->state[1] = 0xBB67AE85UL;
  Context->state[2] = 0x3C6EF372UL;
  Context->state[3] = 0xA54FF53AUL;
  Context->state[4] = 0x510E527FUL;
  Context->state[5] = 0x9B05688CUL;
  Context->state[6] = 0x1F83D9ABUL;
  Context->state[7] = 0x5BE0CD19UL;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  Sha256Update
//
//  Adds data to the SHA256 context. This will process the data and update the
//  internal state of the context. Keep on calling this function until all the
//  data has been added. Then call Sha256Finalise to calculate the hash.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Sha256Update(Sha256Context* Context,  // [in out]
                  void const* Buffer,      // [in]
                  uint32_t BufferSize      // [in]
) {
  uint32_t n;

  if (Context->curlen > sizeof(Context->buf)) {
    return;
  }

  while (BufferSize > 0) {
    if (Context->curlen == 0 && BufferSize >= BLOCK_SIZE) {
      TransformFunction(Context, (uint8_t*)Buffer);
      Context->length += BLOCK_SIZE * 8;
      Buffer = (uint8_t*)Buffer + BLOCK_SIZE;
      BufferSize -= BLOCK_SIZE;
    } else {
      n = MIN(BufferSize, (BLOCK_SIZE - Context->curlen));
      memcpy(Context->buf + Context->curlen, Buffer, (size_t)n);
      Context->curlen += n;
      Buffer = (uint8_t*)Buffer + n;
      BufferSize -= n;
      if (Context->curlen == BLOCK_SIZE) {
        TransformFunction(Context, Context->buf);
        Context->length += 8 * BLOCK_SIZE;
        Context->curlen = 0;
      }
    }
  }
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  Sha256Finalise
//
//  Performs the final calculation of the hash and returns the digest (32 byte
//  buffer containing 256bit hash). After calling this, Sha256Initialised must
//  be used to reuse the context.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Sha256Finalise(Sha256Context* Context,  // [in out]
                    SHA256_HASH* Digest      // [out]
) {
  int i;

  if (Context->curlen >= sizeof(Context->buf)) {
    return;
  }

  // Increase the length of the message
  Context->length += Context->curlen * 8;

  // Append the '1' bit
  Context->buf[Context->curlen++] = (uint8_t)0x80;

  // if the length is currently above 56 bytes we append zeros
  // then compress.  Then we can fall back to padding zeros and length
  // encoding like normal.
  if (Context->curlen > 56) {
    while (Context->curlen < 64) {
      Context->buf[Context->curlen++] = (uint8_t)0;
    }
    TransformFunction(Context, Context->buf);
    Context->curlen = 0;
  }

  // Pad up to 56 bytes of zeroes
  while (Context->curlen < 56) {
    Context->buf[Context->curlen++] = (uint8_t)0;
  }

  // Store length
  STORE64H(Context->length, Context->buf + 56);
  TransformFunction(Context, Context->buf);

  // Copy output
  for (i = 0; i < 8; i++) {
    STORE32H(Context->state[i], Digest->bytes + (4 * i));
  }
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  Sha256Calculate
//
//  Combines Sha256Initialise, Sha256Update, and Sha256Finalise into one
//  function. Calculates the SHA256 hash of the buffer.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Sha256Calculate(void const* Buffer,   // [in]
                     uint32_t BufferSize,  // [in]
                     SHA256_HASH* Digest   // [in]
) {
  Sha256Context context;

  Sha256Initialise(&context);
  Sha256Update(&context, Buffer, BufferSize);
  Sha256Finalise(&context, Digest);
}

midea_sha256_1.h

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  WjCryptLib_Sha256
//
//  Implementation of SHA256 hash function.
//  Original author: Tom St Denis, tomstdenis@gmail.com, http://libtom.org
//  Modified by WaterJuice retaining Public Domain license.
//
//  This is free and unencumbered software released into the public domain -
//  June 2013 waterjuice.org
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#pragma once

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  IMPORTS
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

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

typedef struct {
  uint64_t length;
  uint32_t state[8];
  uint32_t curlen;
  uint8_t buf[64];
} Sha256Context;

#define SHA256_HASH_SIZE (256 / 8)

typedef struct {
  uint8_t bytes[SHA256_HASH_SIZE];
} SHA256_HASH;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  PUBLIC FUNCTIONS
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  Sha256Initialise
//
//  Initialises a SHA256 Context. Use this to initialise/reset a context.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Sha256Initialise(Sha256Context* Context  // [out]
);

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  Sha256Update
//
//  Adds data to the SHA256 context. This will process the data and update the
//  internal state of the context. Keep on calling this function until all the
//  data has been added. Then call Sha256Finalise to calculate the hash.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Sha256Update(Sha256Context* Context,  // [in out]
                  void const* Buffer,      // [in]
                  uint32_t BufferSize      // [in]
);

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  Sha256Finalise
//
//  Performs the final calculation of the hash and returns the digest (32 byte
//  buffer containing 256bit hash). After calling this, Sha256Initialised must
//  be used to reuse the context.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Sha256Finalise(Sha256Context* Context,  // [in out]
                    SHA256_HASH* Digest      // [out]
);

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  Sha256Calculate
//
//  Combines Sha256Initialise, Sha256Update, and Sha256Finalise into one
//  function. Calculates the SHA256 hash of the buffer.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Sha256Calculate(void const* Buffer,   // [in]
                     uint32_t BufferSize,  // [in]
                     SHA256_HASH* Digest   // [in]
);
posted on 2024-11-21 15:48  AtlasLapetos  阅读(17)  评论(0)    收藏  举报