210 lines
6.4 KiB
C
210 lines
6.4 KiB
C
/**
|
|
* Copyright (2017) Baidu Inc. All rights reserved.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
// Author: Leliang Zhang(zhangleliang@baidu.com)
|
|
//
|
|
// Description: aes encryption implementation
|
|
|
|
#include "lightduer_aes.h"
|
|
#include "mbedtls/aes.h"
|
|
#include "lightduer_lib.h"
|
|
#include "lightduer_log.h"
|
|
#include "lightduer_memory.h"
|
|
#include "lightduer_types.h"
|
|
|
|
//#define LIGHTDUER_AES_DEBUG
|
|
#ifdef LIGHTDUER_AES_DEBUG
|
|
#define DUER_AES_PRINT printf
|
|
#else
|
|
#define DUER_AES_PRINT DUER_LOGD
|
|
#endif
|
|
|
|
typedef struct _duer_aes_context {
|
|
mbedtls_aes_context mbedctx; // used by the mbedtls aes algorithm
|
|
unsigned char key[32]; // the key use in the algorithm, max size is 32bytes
|
|
unsigned int keybits; // the length of the key, only 128, 192, 256 supported
|
|
unsigned char iv[16]; // the initial vector, it's 16bytes
|
|
} duer_aes_context_t;
|
|
|
|
duer_aes_context duer_aes_context_init(void)
|
|
{
|
|
duer_aes_context_t *aes_context = (duer_aes_context_t *)DUER_MALLOC(sizeof(duer_aes_context_t));
|
|
if (aes_context == NULL) {
|
|
DUER_LOGE("alloc duer_aes_context_t failed!");
|
|
return NULL;
|
|
}
|
|
DUER_MEMSET(aes_context->key, 0, sizeof(aes_context->key));
|
|
DUER_MEMSET(aes_context->iv, 0, sizeof(aes_context->iv));
|
|
aes_context->keybits = 0;
|
|
mbedtls_aes_init(&aes_context->mbedctx);
|
|
return aes_context;
|
|
}
|
|
|
|
int duer_aes_setkey(duer_aes_context ctx,
|
|
const unsigned char *key,
|
|
unsigned int keybits)
|
|
{
|
|
if (ctx == NULL) {
|
|
DUER_LOGW("ctx is NULL!");
|
|
return DUER_ERR_INVALID_PARAMETER;
|
|
}
|
|
if (keybits != 128 && keybits != 192 && keybits != 256) {
|
|
DUER_LOGW("keybits should be one of (128, 192, 256)");
|
|
return DUER_ERR_INVALID_PARAMETER;
|
|
}
|
|
duer_aes_context_t *aes_context = (duer_aes_context_t *)ctx;
|
|
DUER_MEMCPY(aes_context->key, key, keybits / 8);
|
|
aes_context->keybits = keybits;
|
|
return DUER_OK;
|
|
}
|
|
|
|
int duer_aes_setiv(duer_aes_context ctx, unsigned char iv[16])
|
|
{
|
|
if (ctx == NULL) {
|
|
DUER_LOGW("ctx is NULL!");
|
|
return DUER_ERR_INVALID_PARAMETER;
|
|
}
|
|
duer_aes_context_t *aes_context = (duer_aes_context_t *)ctx;
|
|
DUER_MEMCPY(aes_context->iv, iv, sizeof(aes_context->iv));
|
|
return DUER_OK;
|
|
}
|
|
|
|
|
|
int duer_aes_cbc_encrypt(duer_aes_context ctx,
|
|
size_t length,
|
|
const unsigned char *input,
|
|
unsigned char *output)
|
|
{
|
|
if (ctx == NULL) {
|
|
DUER_LOGW("ctx is NULL!");
|
|
return DUER_ERR_INVALID_PARAMETER;
|
|
}
|
|
duer_aes_context_t *aes_context = (duer_aes_context_t *)ctx;
|
|
|
|
unsigned char iv[16];
|
|
DUER_MEMCPY(iv, aes_context->iv, sizeof(iv));
|
|
|
|
#ifdef LIGHTDUER_AES_DEBUG
|
|
DUER_AES_PRINT("key:\n");
|
|
for (int i = 0; i < (aes_context->keybits / 8); ++i) {
|
|
DUER_AES_PRINT(" %x", (unsigned char)aes_context->key[i]);
|
|
}
|
|
DUER_AES_PRINT("\n");
|
|
DUER_AES_PRINT("iv:\n");
|
|
for (int i = 0; i < sizeof(iv); ++i) {
|
|
DUER_AES_PRINT(" %x", (unsigned char)iv[i]);
|
|
}
|
|
DUER_AES_PRINT("\n");
|
|
DUER_AES_PRINT("input data:\n");
|
|
for (int i = 0; i < length; ++i) {
|
|
DUER_AES_PRINT(" %x", (unsigned char)input[i]);
|
|
}
|
|
DUER_AES_PRINT("\n");
|
|
#endif
|
|
int res = 0;
|
|
do {
|
|
//TODO if this needed every time??
|
|
res = mbedtls_aes_setkey_enc(&aes_context->mbedctx, aes_context->key, aes_context->keybits);
|
|
if (res) {
|
|
break;
|
|
}
|
|
res = mbedtls_aes_crypt_cbc(&aes_context->mbedctx, MBEDTLS_AES_ENCRYPT,
|
|
length, iv, input, output);
|
|
} while (0);
|
|
|
|
if (res != 0) {
|
|
DUER_LOGW("encrypt fail!!res:%d", res);
|
|
return DUER_ERR_FAILED;
|
|
} else {
|
|
#ifdef LIGHTDUER_AES_DEBUG
|
|
DUER_AES_PRINT("encrypt output data:\n");
|
|
for (int i = 0; i < length; ++i) {
|
|
DUER_AES_PRINT(" %x", (unsigned char)output[i]);
|
|
}
|
|
DUER_AES_PRINT("\n");
|
|
#endif
|
|
return DUER_OK;
|
|
}
|
|
}
|
|
|
|
int duer_aes_cbc_decrypt(duer_aes_context ctx,
|
|
size_t length,
|
|
const unsigned char *input,
|
|
unsigned char *output)
|
|
{
|
|
if (ctx == NULL) {
|
|
DUER_LOGW("ctx is NULL!");
|
|
return DUER_ERR_INVALID_PARAMETER;
|
|
}
|
|
duer_aes_context_t *aes_context = (duer_aes_context_t *)ctx;
|
|
|
|
unsigned char iv[16];
|
|
DUER_MEMCPY(iv, aes_context->iv, sizeof(iv));
|
|
#ifdef LIGHTDUER_AES_DEBUG
|
|
DUER_AES_PRINT("key:\n");
|
|
for (int i = 0; i < (aes_context->keybits / 8); ++i) {
|
|
DUER_AES_PRINT(" %x", (unsigned char)aes_context->key[i]);
|
|
}
|
|
DUER_AES_PRINT("\n");
|
|
DUER_AES_PRINT("iv:\n");
|
|
for (int i = 0; i < sizeof(iv); ++i) {
|
|
DUER_AES_PRINT(" %x", (unsigned char)iv[i]);
|
|
}
|
|
DUER_AES_PRINT("\n");
|
|
DUER_AES_PRINT("input data:\n");
|
|
for (int i = 0; i < length; ++i) {
|
|
DUER_AES_PRINT(" %x", (unsigned char)input[i]);
|
|
}
|
|
DUER_AES_PRINT("\n");
|
|
#endif
|
|
int res = 0;
|
|
do {
|
|
//TODO if this needed every time??
|
|
res = mbedtls_aes_setkey_dec(&aes_context->mbedctx, aes_context->key, aes_context->keybits);
|
|
if (res) {
|
|
break;
|
|
}
|
|
res = mbedtls_aes_crypt_cbc(&aes_context->mbedctx, MBEDTLS_AES_DECRYPT,
|
|
length, iv, input, output);
|
|
} while (0);
|
|
|
|
if (res != 0) {
|
|
DUER_LOGW("decrypt faild!! res:%d", res);
|
|
return DUER_ERR_FAILED;
|
|
} else {
|
|
#ifdef LIGHTDUER_AES_DEBUG
|
|
DUER_AES_PRINT("decrypt output data:\n");
|
|
for (int i = 0; i < length; ++i) {
|
|
DUER_AES_PRINT(" %x", (unsigned char)output[i]);
|
|
}
|
|
DUER_AES_PRINT("\n");
|
|
#endif
|
|
return DUER_OK;
|
|
}
|
|
}
|
|
|
|
int duer_aes_context_destroy(duer_aes_context ctx)
|
|
{
|
|
if (ctx == NULL) {
|
|
DUER_LOGW("ctx is NULL!");
|
|
return DUER_ERR_INVALID_PARAMETER;
|
|
}
|
|
duer_aes_context_t *aes_context = (duer_aes_context_t *)ctx;
|
|
|
|
mbedtls_aes_free(&aes_context->mbedctx);
|
|
DUER_FREE(aes_context);
|
|
return DUER_OK;
|
|
}
|