/* * Copyright (C) 2024 Huawei Device Co., Ltd. * 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. */ #include #include #include "securec.h" #include "aes_openssl.h" #include "aes_common.h" #include "blob.h" #include "cipher.h" #include "detailed_iv_params.h" #include "detailed_gcm_params.h" #include "detailed_ccm_params.h" #include "log.h" #include "memory.h" #include "sym_common_defines.h" #include "sym_key_generator.h" #include "sm4_common.h" #include "sm4_openssl.h" using namespace std; HcfResult GenerateSm4SymKey(HcfSymKey **key) { HcfSymKeyGenerator *generator = nullptr; HcfResult ret = HcfSymKeyGeneratorCreate("SM4_128", &generator); if (ret != HCF_SUCCESS || generator == nullptr) { LOGE("HcfSymKeyGeneratorCreate failed!"); return ret; } ret = generator->generateSymKey(generator, key); if (ret != HCF_SUCCESS) { LOGE("generateSymKey failed!"); } HcfObjDestroy(generator); return ret; } int32_t GenerateSymKeyForSm4(const char *algoName, HcfSymKey **key) { HcfSymKeyGenerator *generator = nullptr; int32_t ret = HcfSymKeyGeneratorCreate(algoName, &generator); if (ret != 0 || generator == nullptr) { LOGE("HcfSymKeyGeneratorCreate failed!"); return ret; } ret = generator->generateSymKey(generator, key); if (ret != 0) { LOGE("generateSymKey failed!"); } HcfObjDestroy(reinterpret_cast(generator)); return ret; } // use ECB, test abnormal input int32_t Sm4EncryptWithInput(HcfCipher *cipher, HcfSymKey *key, HcfBlob *input, uint8_t *cipherText, int *cipherTextLen) { HcfBlob output = { .data = nullptr, .len = 0 }; int32_t maxLen = *cipherTextLen; int32_t ret = cipher->init(cipher, ENCRYPT_MODE, &(key->key), nullptr); if (ret != 0) { LOGE("init failed! %d", ret); return ret; } ret = cipher->update(cipher, input, &output); if (ret != 0) { LOGE("update failed!"); return ret; } *cipherTextLen = output.len; if (output.data != nullptr) { if (memcpy_s(cipherText, maxLen, output.data, output.len) != EOK) { HcfBlobDataFree(&output); return -1; } HcfBlobDataFree(&output); } ret = cipher->doFinal(cipher, nullptr, &output); if (ret != 0) { LOGE("doFinal failed!"); return ret; } if (output.data != nullptr) { if (memcpy_s(cipherText + *cipherTextLen, maxLen - *cipherTextLen, output.data, output.len) != EOK) { HcfBlobDataFree(&output); return -1; } *cipherTextLen += output.len; HcfBlobDataFree(&output); } return 0; } // test encrypt and decrypt with null plain text int32_t Sm4DecryptEmptyMsg(HcfCipher *cipher, HcfSymKey *key, HcfParamsSpec *params, uint8_t *cipherText, int cipherTextLen) { HcfBlob input = { .data = cipherText, .len = cipherTextLen }; HcfBlob output = { .data = nullptr, .len = 0 }; int32_t ret = cipher->init(cipher, DECRYPT_MODE, &(key->key), params); if (ret != 0) { LOGE("init failed! %d", ret); return ret; } ret = cipher->doFinal(cipher, &input, &output); if (ret != 0) { LOGE("doFinal failed!"); return ret; } if (output.len == 0 && output.data == nullptr) { ret = 0; } else { ret = -1; } HcfBlobDataFree(&output); return ret; } int32_t Sm4Encrypt(HcfCipher *cipher, HcfSymKey *key, HcfParamsSpec *params, uint8_t *cipherText, int *cipherTextLen) { uint8_t plainText[] = "this is test!"; HcfBlob input = {.data = reinterpret_cast(plainText), .len = 13}; HcfBlob output = {}; int32_t maxLen = *cipherTextLen; int32_t ret = cipher->init(cipher, ENCRYPT_MODE, reinterpret_cast(key), params); if (ret != 0) { LOGE("init failed! "); return ret; } ret = cipher->update(cipher, &input, &output); if (ret != 0) { LOGE("update failed!"); return ret; } *cipherTextLen = output.len; if (output.data != nullptr) { if (memcpy_s(cipherText, maxLen, output.data, output.len) != EOK) { HcfBlobDataFree(&output); return -1; } HcfBlobDataFree(&output); } ret = cipher->doFinal(cipher, nullptr, &output); if (ret != 0) { LOGE("doFinal failed!"); return ret; } if (output.data != nullptr) { if (memcpy_s(cipherText + *cipherTextLen, maxLen - *cipherTextLen, output.data, output.len) != EOK) { HcfBlobDataFree(&output); return -1; } *cipherTextLen += output.len; HcfBlobDataFree(&output); } return 0; } int32_t Sm4Decrypt(HcfCipher *cipher, HcfSymKey *key, HcfParamsSpec *params, uint8_t *cipherText, int cipherTextLen) { uint8_t plainText[] = "this is test!"; HcfBlob input = {.data = reinterpret_cast(cipherText), .len = cipherTextLen}; HcfBlob output = {}; int32_t maxLen = cipherTextLen; int32_t ret = cipher->init(cipher, DECRYPT_MODE, reinterpret_cast(key), params); if (ret != 0) { LOGE("init failed! "); return ret; } ret = cipher->update(cipher, &input, &output); if (ret != 0) { LOGE("update failed!"); return ret; } cipherTextLen = output.len; if (output.data != nullptr) { if (memcpy_s(cipherText, maxLen, output.data, output.len) != EOK) { HcfBlobDataFree(&output); return -1; } HcfBlobDataFree(&output); } ret = cipher->doFinal(cipher, nullptr, &output); if (ret != 0) { LOGE("doFinal failed!"); return ret; } if (output.data != nullptr) { if (memcpy_s(cipherText + cipherTextLen, maxLen - cipherTextLen, output.data, output.len) != EOK) { HcfBlobDataFree(&output); return -1; } cipherTextLen += output.len; HcfBlobDataFree(&output); } if (cipherTextLen != sizeof(plainText) - 1) { return -1; } return memcmp(cipherText, plainText, cipherTextLen); } int32_t Sm4NoUpdateEncrypt(HcfCipher *cipher, HcfSymKey *key, HcfParamsSpec *params, uint8_t *cipherText, int *cipherTextLen) { uint8_t plainText[] = "this is test!"; HcfBlob input = {.data = reinterpret_cast(plainText), .len = 13}; HcfBlob output = {}; int32_t maxLen = *cipherTextLen; int32_t ret = cipher->init(cipher, ENCRYPT_MODE, reinterpret_cast(key), params); if (ret != 0) { LOGE("init failed! "); return ret; } *cipherTextLen = 0; ret = cipher->doFinal(cipher, &input, &output); if (ret != 0) { LOGE("doFinal failed!"); return ret; } if (output.data != nullptr) { if (memcpy_s(cipherText, maxLen, output.data, output.len) != EOK) { HcfBlobDataFree(&output); return -1; } *cipherTextLen += output.len; HcfBlobDataFree(&output); } return 0; } int32_t Sm4NoUpdateDecrypt(HcfCipher *cipher, HcfSymKey *key, HcfParamsSpec *params, uint8_t *cipherText, int cipherTextLen) { uint8_t plainText[] = "this is test!"; HcfBlob input = {.data = reinterpret_cast(cipherText), .len = cipherTextLen}; HcfBlob output = {}; int32_t maxLen = cipherTextLen; int32_t ret = cipher->init(cipher, DECRYPT_MODE, reinterpret_cast(key), params); if (ret != 0) { LOGE("init failed! "); return ret; } cipherTextLen = 0; ret = cipher->doFinal(cipher, &input, &output); if (ret != 0) { LOGE("doFinal failed!"); return ret; } if (output.data != nullptr) { if (memcpy_s(cipherText, maxLen, output.data, output.len) != EOK) { HcfBlobDataFree(&output); return -1; } cipherTextLen += output.len; HcfBlobDataFree(&output); } if (cipherTextLen != sizeof(plainText) - 1) { return -1; } return memcmp(cipherText, plainText, cipherTextLen); } const char *GetMockClass(void) { return "HcfMock"; } HcfObjectBase obj = { .getClass = GetMockClass, .destroy = nullptr };