Files
luban-lite/bsp/examples/test-mbedtls/crypto.c
刘可亮 3e10f578d3 v1.2.2
2025-10-21 13:59:50 +08:00

400 lines
9.7 KiB
C

/*
* Copyright (c) 2024-2025, ArtInChip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Authors: Wu Dehuang <dehuang.wu@artinchip.com>
*/
#include <string.h>
#include <aic_core.h>
#include <aic_utils.h>
#include "crypto.h"
struct aes_ctx_s {
mbedtls_aes_context cipher_ctx;
uint8_t key[AES_128_BLOCK_SIZE];
uint8_t iv[AES_128_BLOCK_SIZE];
aes_direction_t direction;
uint8_t block_offset;
size_t ctr_nc_off;
uint8_t ctr_nonce_counter[AES_128_BLOCK_SIZE];
uint8_t ctr_encrypted_counter[AES_128_BLOCK_SIZE];
};
#define SALT_PK "UxPlay-Persistent-Not-Secure-Public-Key"
uint8_t waste[AES_128_BLOCK_SIZE];
sha_ctx_t *sha_init(void)
{
const mbedtls_md_info_t *md_info;
mbedtls_md_context_t *ctx;
int ret = 0;
ctx = malloc(sizeof(mbedtls_md_context_t));
assert(ctx != NULL);
if (!ctx) {
printf("Allocater context failure\n");
return NULL;
}
mbedtls_md_init(ctx);
md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA512);
if (!md_info)
goto cleanup;
if ((ret = mbedtls_md_setup(ctx, md_info, 0)) != 0)
goto cleanup;
if ((ret = mbedtls_md_starts(ctx)) != 0)
goto cleanup;
return (sha_ctx_t *)ctx;
cleanup:
if (ctx)
free(ctx);
return NULL;
}
int sha_update(sha_ctx_t *ctx, const uint8_t *in, int len)
{
mbedtls_md_context_t *md_ctx = (mbedtls_md_context_t *)ctx;
if (!ctx) {
printf("Invalid parameter\n");
return -1;
}
return mbedtls_md_update(md_ctx, (const unsigned char *)in, (size_t)len);
}
int sha_final(sha_ctx_t *ctx, const uint8_t *out, int len)
{
mbedtls_md_context_t *md_ctx = (mbedtls_md_context_t *)ctx;
if (!ctx || len != 64) {
printf("Invalid parameter\n");
return -1;
}
return mbedtls_md_finish(md_ctx, (unsigned char *)out);
}
int sha_reset(sha_ctx_t *ctx)
{
mbedtls_md_context_t *md_ctx = (mbedtls_md_context_t *)ctx;
int ret = 0;
if (!ctx) {
printf("Invalid parameter\n");
return -1;
}
if ((ret = mbedtls_md_starts(md_ctx)) != 0)
return ret;
return 0;
}
void sha_destroy(sha_ctx_t *ctx)
{
mbedtls_md_context_t *md_ctx = (mbedtls_md_context_t *)ctx;
if (ctx) {
mbedtls_md_free(md_ctx);
free(ctx);
}
}
aes_ctx_t *aes_ctr_init(const uint8_t *key, const uint8_t *iv)
{
struct aes_ctx_s *ctx;
int ret = 0;
if (!key || !iv) {
printf("Invalid parameter\n");
return NULL;
}
ctx = malloc(sizeof(struct aes_ctx_s));
if (!ctx) {
printf("Fail to alloc context\n");
return NULL;
}
memset(ctx, 0, sizeof(*ctx));
memcpy(ctx->key, key, AES_128_BLOCK_SIZE);
memcpy(ctx->iv, iv, AES_128_BLOCK_SIZE); /* Backup */
memcpy(ctx->ctr_nonce_counter, iv, AES_128_BLOCK_SIZE);
mbedtls_aes_init(&ctx->cipher_ctx);
ret = mbedtls_aes_setkey_enc(&ctx->cipher_ctx, key, 128);
if (ret) {
printf("Set AES key failure.\n");
goto cleanup;
}
return (aes_ctx_t *)ctx;
cleanup:
if (ctx)
free(ctx);
return NULL;
}
int aes_ctr_encrypt(aes_ctx_t *ctx, const uint8_t *in, uint8_t *out, int len)
{
struct aes_ctx_s *aes_ctx = (struct aes_ctx_s *)ctx;
int ret = 0;
if (!ctx) {
printf("AES CTR Invalid parameter\n");
return -1;
}
ret = mbedtls_aes_crypt_ctr(&aes_ctx->cipher_ctx, len, &aes_ctx->ctr_nc_off,
aes_ctx->ctr_nonce_counter, aes_ctx->ctr_encrypted_counter,
in, out);
if (ret)
return ret;
aes_ctx->block_offset = (aes_ctx->block_offset + len) % AES_128_BLOCK_SIZE;
return ret;
}
void aes_ctr_start_fresh_block(aes_ctx_t *ctx)
{
struct aes_ctx_s *aes_ctx = (struct aes_ctx_s *)ctx;
// Is there a better way to do this?
if (aes_ctx->block_offset == 0)
return;
aes_ctr_encrypt(ctx, waste, waste, AES_128_BLOCK_SIZE - aes_ctx->block_offset);
}
int aes_ctr_decrypt(aes_ctx_t *ctx, const uint8_t *in, uint8_t *out, int len)
{
struct aes_ctx_s *aes_ctx = (struct aes_ctx_s *)ctx;
int ret = 0;
if (!ctx) {
printf("AES CTR Invalid parameter\n");
return -1;
}
ret = mbedtls_aes_crypt_ctr(&aes_ctx->cipher_ctx, len, &aes_ctx->ctr_nc_off,
aes_ctx->ctr_nonce_counter, aes_ctx->ctr_encrypted_counter,
in, out);
return ret;
}
void aes_ctr_reset(aes_ctx_t *ctx)
{
struct aes_ctx_s *aes_ctx = (struct aes_ctx_s *)ctx;
if (!ctx) {
printf("AES CTR Invalid parameter\n");
return;
}
aes_ctx->block_offset = 0;
aes_ctx->ctr_nc_off = 0;
memcpy(aes_ctx->ctr_nonce_counter, aes_ctx->iv, AES_128_BLOCK_SIZE);
memset(aes_ctx->ctr_encrypted_counter, 0, AES_128_BLOCK_SIZE);
}
void aes_ctr_destroy(aes_ctx_t *ctx)
{
struct aes_ctx_s *aes_ctx = (struct aes_ctx_s *)ctx;
if (!ctx) {
printf("AES CTR Invalid parameter\n");
return;
}
mbedtls_aes_free(&aes_ctx->cipher_ctx);
free(aes_ctx);
}
aes_ctx_t *aes_cbc_init(const uint8_t *key, const uint8_t *iv, aes_direction_t direction)
{
struct aes_ctx_s *ctx;
int ret = 0;
if (!key || !iv) {
printf("Invalid parameter\n");
return NULL;
}
ctx = malloc(sizeof(struct aes_ctx_s));
if (!ctx) {
printf("Fail to alloc context\n");
return NULL;
}
memset(ctx, 0, sizeof(*ctx));
memcpy(ctx->key, key, AES_128_BLOCK_SIZE);
memcpy(ctx->iv, iv, AES_128_BLOCK_SIZE);
mbedtls_aes_init(&ctx->cipher_ctx);
ctx->direction = direction;
if (direction == AES_ENCRYPT)
ret = mbedtls_aes_setkey_enc(&ctx->cipher_ctx, key, 128);
else
ret = mbedtls_aes_setkey_dec(&ctx->cipher_ctx, key, 128);
if (ret) {
printf("Set AES key failure.\n");
goto cleanup;
}
return (aes_ctx_t *)ctx;
cleanup:
if (ctx)
free(ctx);
return NULL;
}
int aes_cbc_encrypt(aes_ctx_t *ctx, const uint8_t *in, uint8_t *out, int len)
{
struct aes_ctx_s *aes_ctx = (struct aes_ctx_s *)ctx;
int ret = 0;
if (!ctx) {
printf("AES CBC Invalid parameter\n");
return -1;
}
if (aes_ctx->direction == AES_ENCRYPT) {
ret = mbedtls_aes_crypt_cbc(&aes_ctx->cipher_ctx, MBEDTLS_AES_ENCRYPT, len, aes_ctx->iv,
in, out);
} else {
printf("AES CBC crypt direction is wrong.\n");
return -1;
}
return ret;
}
int aes_cbc_decrypt(aes_ctx_t *ctx, const uint8_t *in, uint8_t *out, int len)
{
struct aes_ctx_s *aes_ctx = (struct aes_ctx_s *)ctx;
int ret = 0;
if (!ctx) {
printf("AES CBC Invalid parameter\n");
return -1;
}
if (aes_ctx->direction == AES_DECRYPT) {
ret = mbedtls_aes_crypt_cbc(&aes_ctx->cipher_ctx, MBEDTLS_AES_DECRYPT, len, aes_ctx->iv,
in, out);
} else {
printf("AES CBC crypt direction is wrong.\n");
return -1;
}
return ret;
}
void aes_cbc_reset(aes_ctx_t *ctx)
{
}
void aes_cbc_destroy(aes_ctx_t *ctx)
{
struct aes_ctx_s *aes_ctx = (struct aes_ctx_s *)ctx;
if (!ctx) {
printf("AES CBC Invalid parameter\n");
return;
}
mbedtls_aes_free(&aes_ctx->cipher_ctx);
free(aes_ctx);
}
int aes_gcm_encrypt(const unsigned char *plaintext, int plaintext_len, unsigned char *ciphertext,
unsigned char *key, unsigned char *iv, unsigned char *tag)
{
mbedtls_gcm_context gcm_ctx;
int ret = 0;
mbedtls_gcm_init(&gcm_ctx);
ret = mbedtls_gcm_setkey(&gcm_ctx, MBEDTLS_CIPHER_ID_AES, key, 128);
if (ret) {
printf("Set key failed.\n");
return 0;
}
/*IV and tag size is 16 */
ret = mbedtls_gcm_crypt_and_tag(&gcm_ctx, MBEDTLS_GCM_ENCRYPT, plaintext_len, iv, 16, NULL, 0,
plaintext, ciphertext, 16, tag);
if (ret) {
printf("GCM crypt failed.\n");
return 0;
}
mbedtls_gcm_free(&gcm_ctx);
return plaintext_len;
}
int aes_gcm_decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *plaintext,
unsigned char *key, unsigned char *iv, unsigned char *tag)
{
mbedtls_gcm_context gcm_ctx;
int ret = 0;
mbedtls_gcm_init(&gcm_ctx);
ret = mbedtls_gcm_setkey(&gcm_ctx, MBEDTLS_CIPHER_ID_AES, key, 128);
if (ret) {
printf("Set key failed.\n");
return 0;
}
/*IV and tag size is 16 */
ret = mbedtls_gcm_crypt_and_tag(&gcm_ctx, MBEDTLS_GCM_DECRYPT, ciphertext_len, iv, 16, NULL, 0,
ciphertext, plaintext, 16, tag);
if (ret) {
printf("GCM crypt failed.\n");
return 0;
}
mbedtls_gcm_free(&gcm_ctx);
return ciphertext_len;
}
int get_random_bytes(unsigned char *buf, int num)
{
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
char *per = "personalized string for crypto";
int ret;
mbedtls_entropy_init(&entropy);
mbedtls_ctr_drbg_init(&ctr_drbg);
ret = mbedtls_ctr_drbg_seed(&ctr_drbg,
mbedtls_entropy_func,
&entropy,
(const unsigned char *)per,
strlen(per));
if (ret) {
goto cleanup;
}
ret = mbedtls_ctr_drbg_random(&ctr_drbg, buf, num);
if (ret) {
goto cleanup;
}
mbedtls_ctr_drbg_free(&ctr_drbg);
mbedtls_entropy_free(&entropy);
return 1;
cleanup:
return 0;
}
void pk_to_base64(const unsigned char *pk, int pk_len, unsigned char *pk_base64, int len)
{
size_t dlen, slen;
dlen = len;
slen = pk_len;
mbedtls_base64_encode(pk_base64, dlen, &dlen, pk, slen);
}