* This file is part of the openHiTLS project.
*
* openHiTLS is licensed under the Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include <string.h>
#include <stdio.h>
#include "crypt_modes_cbc.h"
#include "modes_local.h"
#include "crypt_errno.h"
#ifdef __FRAMAC__
#include "__fc_builtin.h"
void *BSL_SAL_Calloc(uint32_t num, uint32_t size) {
return Frama_C_alloc_by_stack((size_t)num * (size_t)size);
}
void BSL_ERR_PUSH_ERROR(int err_code) {
return;
}
void BSL_SAL_Free(void *ptr) {
return;
}
#endif __FRAMAC__
int run_sm4_cbc_test(void) {
printf("--- 开始 SM4-CBC 端到端测试 ---\n");
const uint8_t key[16] = {
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10
};
const uint8_t iv[16] = {
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10
};
const char* plaintext_str = "这是一条用于测试SM4-CBC模式的机密消息。";
const uint8_t* plaintext = (const uint8_t*)plaintext_str;
const uint32_t plaintext_len = strlen(plaintext_str);
uint8_t ciphertext[256];
uint8_t recovered_plaintext[256];
uint32_t ciphertext_len = 0;
uint32_t temp_out_len = 0;
uint32_t recovered_len = 0;
int32_t ret;
printf("加密中...\n");
MODES_CipherCtx *ctx_enc = MODES_CBC_NewCtx(CRYPT_CIPHER_SM4_CBC);
if (ctx_enc == NULL) {
printf("错误:创建加密上下文失败。\n");
return -1;
}
ret = SM4_CBC_InitCtx(ctx_enc, key, sizeof(key), iv, sizeof(iv), true);
if (ret != CRYPT_SUCCESS) {
printf("错误:初始化加密上下文失败。\n");
MODES_CBC_FreeCtx(ctx_enc);
return -1;
}
int32_t padding = CRYPT_PADDING_PKCS7;
MODES_CBC_Ctrl(ctx_enc, CRYPT_CTRL_SET_PADDING, &padding, sizeof(padding));
ret = SM4_CBC_Update(ctx_enc, plaintext, plaintext_len, ciphertext, &temp_out_len);
if (ret != CRYPT_SUCCESS) {
printf("错误:加密更新操作失败。\n");
MODES_CBC_FreeCtx(ctx_enc);
return -1;
}
ciphertext_len += temp_out_len;
ret = SM4_CBC_Final(ctx_enc, ciphertext + ciphertext_len, &temp_out_len);
if (ret != CRYPT_SUCCESS) {
printf("错误:加密终结操作失败。\n");
MODES_CBC_FreeCtx(ctx_enc);
return -1;
}
ciphertext_len += temp_out_len;
printf("加密成功。明文长度: %u, 密文长度: %u\n", plaintext_len, ciphertext_len);
MODES_CBC_FreeCtx(ctx_enc);
printf("解密中...\n");
temp_out_len = 0;
MODES_CipherCtx *ctx_dec = MODES_CBC_NewCtx(CRYPT_CIPHER_SM4_CBC);
if (ctx_dec == NULL) {
printf("错误:创建解密上下文失败。\n");
return -1;
}
ret = SM4_CBC_InitCtx(ctx_dec, key, sizeof(key), iv, sizeof(iv), false);
if (ret != CRYPT_SUCCESS) {
printf("错误:初始化解密上下文失败。\n");
MODES_CBC_FreeCtx(ctx_dec);
return -1;
}
MODES_CBC_Ctrl(ctx_dec, CRYPT_CTRL_SET_PADDING, &padding, sizeof(padding));
ret = SM4_CBC_Update(ctx_dec, ciphertext, ciphertext_len, recovered_plaintext, &temp_out_len);
if (ret != CRYPT_SUCCESS) {
printf("错误:解密更新操作失败。\n");
MODES_CBC_FreeCtx(ctx_dec);
return -1;
}
recovered_len += temp_out_len;
ret = SM4_CBC_Final(ctx_dec, recovered_plaintext + recovered_len, &temp_out_len);
if (ret != CRYPT_SUCCESS) {
printf("错误:解密终结操作失败。\n");
MODES_CBC_FreeCtx(ctx_dec);
return -1;
}
recovered_len += temp_out_len;
printf("解密成功。恢复的明文长度: %u\n", recovered_len);
MODES_CBC_FreeCtx(ctx_dec);
printf("验证中...\n");
if (recovered_len != plaintext_len) {
printf("失败:长度不匹配!原始长度: %u, 恢复后长度: %u\n", plaintext_len, recovered_len);
return -1;
}
if (memcmp(plaintext, recovered_plaintext, plaintext_len) != 0) {
printf("失败:内容不匹配!\n");
return -1;
}
printf("--- 成功:测试通过!恢复的明文与原始明文完全匹配。 ---\n");
return 0;
}
int main(void) {
int result = run_sm4_cbc_test();
if (result == 0) {
printf("测试驱动成功结束。\n");
} else {
printf("测试驱动因错误结束。\n");
}
return result;
}