vcpe/srcs/libs/crypto/symmetric.c

252 lines
9.6 KiB
C

//
// Created by xajhu on 2021/7/13 0013.
//
#include <string.h>
#include <openssl/aes.h>
#include <openssl/evp.h>
#include <openssl/sha.h>
#include "crypto.h"
#include "user_errno.h"
static int sha1prng_for_aes_key(const char *pKey, unsigned char *pShaPrng16) {
unsigned int outSize = EVP_MAX_MD_SIZE;
unsigned char data[SHA_DIGEST_LENGTH] = {0};
unsigned char *pHashValue = NULL;
int ret = hash_digest_mem(HASH_TYPE_SHA1, (const unsigned char *)pKey, strlen(pKey), &pHashValue, &outSize);
if (ret != ERR_SUCCESS) {
if (pHashValue) {
free(pHashValue);
}
return ret;
}
memcpy(data, pHashValue, SHA_DIGEST_LENGTH);
free(pHashValue);
ret = hash_digest_mem(HASH_TYPE_SHA1, data, SHA_DIGEST_LENGTH, &pHashValue, &outSize);
if (ret != ERR_SUCCESS) {
if (pHashValue) {
free(pHashValue);
}
return ret;
}
memcpy(pShaPrng16, pHashValue, 16);
free(pHashValue);
return ERR_SUCCESS;
}
#define EVP_ENV_INIT(algorithmType, pCipher, keyBuf, pKey) \
do { \
switch (algorithmType) { \
case DES3_ECB_PKCS7PADDING: \
pCipher = EVP_des_ede3(); \
strncpy((char *)keyBuf, pKey, EVP_CIPHER_key_length(pCipher)); \
break; \
case DES3_CBC_PKCS7PADDING: \
pCipher = EVP_des_ede3_cbc(); \
strncpy((char *)keyBuf, pKey, EVP_CIPHER_key_length(pCipher)); \
break; \
case DES3_OFB_PKCS7PADDING: \
pCipher = EVP_des_ede3_ofb(); \
strncpy((char *)keyBuf, pKey, EVP_CIPHER_key_length(pCipher)); \
break; \
case AES128_ECB_PKCS7PADDING: \
pCipher = EVP_aes_128_ecb(); \
strncpy((char *)keyBuf, pKey, EVP_CIPHER_key_length(pCipher)); \
break; \
case AES128_ECB_PKCS7PADDING_SHA1PRNG: \
if (sha1prng_for_aes_key(pKey, keyBuf) != ERR_SUCCESS) { \
EVP_CIPHER_CTX_cleanup(pCtx); \
return -ERR_AES128_KEYGEN; \
} \
pCipher = EVP_aes_128_ecb(); \
break; \
case AES128_CBC_PKCS7PADDING: \
pCipher = EVP_aes_128_cbc(); \
strncpy((char *)keyBuf, pKey, EVP_CIPHER_key_length(pCipher)); \
break; \
case AES128_OFB_PKCS7PADDING: \
pCipher = EVP_aes_128_ofb(); \
strncpy((char *)keyBuf, pKey, EVP_CIPHER_key_length(pCipher)); \
break; \
case AES192_ECB_PKCS7PADDING: \
pCipher = EVP_aes_192_ecb(); \
strncpy((char *)keyBuf, pKey, EVP_CIPHER_key_length(pCipher)); \
break; \
case AES192_CBC_PKCS7PADDING: \
pCipher = EVP_aes_192_cbc(); \
strncpy((char *)keyBuf, pKey, EVP_CIPHER_key_length(pCipher)); \
break; \
case AES192_OFB_PKCS7PADDING: \
pCipher = EVP_aes_192_ofb(); \
strncpy((char *)keyBuf, pKey, EVP_CIPHER_key_length(pCipher)); \
break; \
case AES256_ECB_PKCS7PADDING: \
pCipher = EVP_aes_256_ecb(); \
strncpy((char *)keyBuf, pKey, EVP_CIPHER_key_length(pCipher)); \
break; \
case AES256_CBC_PKCS7PADDING: \
pCipher = EVP_aes_256_cbc(); \
strncpy((char *)keyBuf, pKey, EVP_CIPHER_key_length(pCipher)); \
break; \
case AES256_OFB_PKCS7PADDING: \
pCipher = EVP_aes_256_ofb(); \
strncpy((char *)keyBuf, pKey, EVP_CIPHER_key_length(pCipher)); \
break; \
default: \
EVP_CIPHER_CTX_cleanup(pCtx); \
return -ERR_UNSUP_EVP_TYPE; \
} \
} while (0)
int symmetric_decrypto(AES_TYPE algorithmType, unsigned char *pInBuf, unsigned int inSize, unsigned char **pOutBuf,
int *pOutSize, const char *pKey) {
int enBytes = 0;
EVP_CIPHER_CTX *pCtx;
unsigned char *pAesBuf;
unsigned char keyBuf[EVP_MAX_KEY_LENGTH];
unsigned char iv[EVP_MAX_IV_LENGTH] = {0};
const EVP_CIPHER *pCipher;
if (!pInBuf || !pOutSize || !pKey || inSize < 0) {
return -ERR_INPUT_PARAMS;
}
*pOutSize = 0;
pCtx = EVP_CIPHER_CTX_new();
if (!pCtx) {
return -ERR_EVP_CREATE_CTX;
}
memset(keyBuf, 0, EVP_MAX_KEY_LENGTH);
memset(iv, '0', EVP_MAX_IV_LENGTH);
EVP_ENV_INIT(algorithmType, pCipher, keyBuf, pKey);
EVP_CIPHER_CTX_init(pCtx);
if (EVP_DecryptInit_ex(pCtx, pCipher, NULL, (const unsigned char *)keyBuf, iv) == 0) {
EVP_CIPHER_CTX_cleanup(pCtx);
EVP_CIPHER_CTX_free(pCtx);
return -ERR_EVP_INIT_KEY;
}
pAesBuf = malloc(inSize + EVP_MAX_BLOCK_LENGTH);
if (pAesBuf == NULL) {
EVP_CIPHER_CTX_cleanup(pCtx);
EVP_CIPHER_CTX_free(pCtx);
return -ERR_MALLOC_MEMORY;
}
memset(pAesBuf, 0, inSize + EVP_MAX_BLOCK_LENGTH);
if (EVP_DecryptUpdate(pCtx, pAesBuf, &enBytes, pInBuf, (int)inSize) == 0) {
free(pAesBuf);
EVP_CIPHER_CTX_cleanup(pCtx);
EVP_CIPHER_CTX_free(pCtx);
return -ERR_EVP_UPDATE;
}
*pOutBuf = pAesBuf;
pAesBuf += enBytes;
*pOutSize += enBytes;
if (EVP_DecryptFinal_ex(pCtx, pAesBuf, &enBytes) == 0) {
//free(pOutBuf); // Maybe exception
EVP_CIPHER_CTX_cleanup(pCtx);
EVP_CIPHER_CTX_free(pCtx);
return -ERR_EVP_FINALE;
}
*pOutSize += enBytes;
EVP_CIPHER_CTX_cleanup(pCtx);
EVP_CIPHER_CTX_free(pCtx);
return ERR_SUCCESS;
}
int symmetric_encrypto(AES_TYPE algorithmType, unsigned char *pInBuf, unsigned int inSize, unsigned char **pOutBuf,
int *pOutSize, const char *pKey) {
int enBytes = 0;
unsigned char *pAesBuf;
EVP_CIPHER_CTX *pCtx;
unsigned char keyBuf[EVP_MAX_KEY_LENGTH];
unsigned char iv[EVP_MAX_IV_LENGTH] = {0};
const EVP_CIPHER *pCipher;
if (!pInBuf || !pOutSize || !pKey || inSize < 0) {
return -ERR_INPUT_PARAMS;
}
*pOutSize = 0;
pCtx = EVP_CIPHER_CTX_new();
if (!pCtx) {
return -ERR_EVP_CREATE_CTX;
}
memset(keyBuf, 0, EVP_MAX_KEY_LENGTH);
memset(iv, '0', EVP_MAX_IV_LENGTH);
EVP_ENV_INIT(algorithmType, pCipher, keyBuf, pKey);
EVP_CIPHER_CTX_init(pCtx);
if (EVP_EncryptInit_ex(pCtx, pCipher, NULL, (const unsigned char *)keyBuf, iv) == 0) {
EVP_CIPHER_CTX_cleanup(pCtx);
EVP_CIPHER_CTX_free(pCtx);
return -ERR_EVP_INIT_KEY;
}
pAesBuf = malloc(inSize + EVP_MAX_BLOCK_LENGTH);
if (pAesBuf == NULL) {
EVP_CIPHER_CTX_cleanup(pCtx);
EVP_CIPHER_CTX_free(pCtx);
return -ERR_MALLOC_MEMORY;
}
memset(pAesBuf, 0, inSize + EVP_MAX_BLOCK_LENGTH);
if (EVP_EncryptUpdate(pCtx, pAesBuf, &enBytes, pInBuf, (int)inSize) == 0) {
free(pAesBuf);
EVP_CIPHER_CTX_cleanup(pCtx);
EVP_CIPHER_CTX_free(pCtx);
return -ERR_EVP_UPDATE;
}
*pOutBuf = pAesBuf;
pAesBuf += enBytes;
*pOutSize += enBytes;
if (EVP_EncryptFinal_ex(pCtx, pAesBuf, &enBytes) == 0) {
//free(pOutBuf); // Maybe exception
EVP_CIPHER_CTX_cleanup(pCtx);
EVP_CIPHER_CTX_free(pCtx);
return -ERR_EVP_FINALE;
}
*pOutSize += enBytes;
EVP_CIPHER_CTX_cleanup(pCtx);
EVP_CIPHER_CTX_free(pCtx);
return ERR_SUCCESS;
}