1/* 2 * Copyright (C) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include <fstream> 17#include <iostream> 18#include "securec.h" 19#include "aes_openssl.h" 20#include "aes_common.h" 21#include "blob.h" 22#include "cipher.h" 23#include "detailed_iv_params.h" 24#include "detailed_gcm_params.h" 25#include "detailed_ccm_params.h" 26#include "log.h" 27#include "memory.h" 28#include "sym_common_defines.h" 29#include "sym_key_generator.h" 30#include "sm4_common.h" 31#include "sm4_openssl.h" 32 33using namespace std; 34 35HcfResult GenerateSm4SymKey(HcfSymKey **key) 36{ 37 HcfSymKeyGenerator *generator = nullptr; 38 39 HcfResult ret = HcfSymKeyGeneratorCreate("SM4_128", &generator); 40 if (ret != HCF_SUCCESS || generator == nullptr) { 41 LOGE("HcfSymKeyGeneratorCreate failed!"); 42 return ret; 43 } 44 45 ret = generator->generateSymKey(generator, key); 46 if (ret != HCF_SUCCESS) { 47 LOGE("generateSymKey failed!"); 48 } 49 HcfObjDestroy(generator); 50 return ret; 51} 52 53int32_t GenerateSymKeyForSm4(const char *algoName, HcfSymKey **key) 54{ 55 HcfSymKeyGenerator *generator = nullptr; 56 57 int32_t ret = HcfSymKeyGeneratorCreate(algoName, &generator); 58 if (ret != 0 || generator == nullptr) { 59 LOGE("HcfSymKeyGeneratorCreate failed!"); 60 return ret; 61 } 62 63 ret = generator->generateSymKey(generator, key); 64 if (ret != 0) { 65 LOGE("generateSymKey failed!"); 66 } 67 HcfObjDestroy(reinterpret_cast<HcfObjectBase *>(generator)); 68 return ret; 69} 70 71 72// use ECB, test abnormal input 73int32_t Sm4EncryptWithInput(HcfCipher *cipher, HcfSymKey *key, HcfBlob *input, 74 uint8_t *cipherText, int *cipherTextLen) 75{ 76 HcfBlob output = { .data = nullptr, .len = 0 }; 77 int32_t maxLen = *cipherTextLen; 78 int32_t ret = cipher->init(cipher, ENCRYPT_MODE, &(key->key), nullptr); 79 if (ret != 0) { 80 LOGE("init failed! %d", ret); 81 return ret; 82 } 83 84 ret = cipher->update(cipher, input, &output); 85 if (ret != 0) { 86 LOGE("update failed!"); 87 return ret; 88 } 89 *cipherTextLen = output.len; 90 if (output.data != nullptr) { 91 if (memcpy_s(cipherText, maxLen, output.data, output.len) != EOK) { 92 HcfBlobDataFree(&output); 93 return -1; 94 } 95 HcfBlobDataFree(&output); 96 } 97 98 ret = cipher->doFinal(cipher, nullptr, &output); 99 if (ret != 0) { 100 LOGE("doFinal failed!"); 101 return ret; 102 } 103 if (output.data != nullptr) { 104 if (memcpy_s(cipherText + *cipherTextLen, maxLen - *cipherTextLen, output.data, output.len) != EOK) { 105 HcfBlobDataFree(&output); 106 return -1; 107 } 108 *cipherTextLen += output.len; 109 HcfBlobDataFree(&output); 110 } 111 112 return 0; 113} 114 115// test encrypt and decrypt with null plain text 116int32_t Sm4DecryptEmptyMsg(HcfCipher *cipher, HcfSymKey *key, HcfParamsSpec *params, 117 uint8_t *cipherText, int cipherTextLen) 118{ 119 HcfBlob input = { .data = cipherText, .len = cipherTextLen }; 120 HcfBlob output = { .data = nullptr, .len = 0 }; 121 int32_t ret = cipher->init(cipher, DECRYPT_MODE, &(key->key), params); 122 if (ret != 0) { 123 LOGE("init failed! %d", ret); 124 return ret; 125 } 126 127 ret = cipher->doFinal(cipher, &input, &output); 128 if (ret != 0) { 129 LOGE("doFinal failed!"); 130 return ret; 131 } 132 if (output.len == 0 && output.data == nullptr) { 133 ret = 0; 134 } else { 135 ret = -1; 136 } 137 HcfBlobDataFree(&output); 138 return ret; 139} 140 141 142int32_t Sm4Encrypt(HcfCipher *cipher, HcfSymKey *key, HcfParamsSpec *params, 143 uint8_t *cipherText, int *cipherTextLen) 144{ 145 uint8_t plainText[] = "this is test!"; 146 HcfBlob input = {.data = reinterpret_cast<uint8_t *>(plainText), .len = 13}; 147 HcfBlob output = {}; 148 int32_t maxLen = *cipherTextLen; 149 int32_t ret = cipher->init(cipher, ENCRYPT_MODE, reinterpret_cast<HcfKey *>(key), params); 150 if (ret != 0) { 151 LOGE("init failed! "); 152 return ret; 153 } 154 155 ret = cipher->update(cipher, &input, &output); 156 if (ret != 0) { 157 LOGE("update failed!"); 158 return ret; 159 } 160 *cipherTextLen = output.len; 161 if (output.data != nullptr) { 162 if (memcpy_s(cipherText, maxLen, output.data, output.len) != EOK) { 163 HcfBlobDataFree(&output); 164 return -1; 165 } 166 HcfBlobDataFree(&output); 167 } 168 169 ret = cipher->doFinal(cipher, nullptr, &output); 170 if (ret != 0) { 171 LOGE("doFinal failed!"); 172 return ret; 173 } 174 if (output.data != nullptr) { 175 if (memcpy_s(cipherText + *cipherTextLen, maxLen - *cipherTextLen, output.data, output.len) != EOK) { 176 HcfBlobDataFree(&output); 177 return -1; 178 } 179 *cipherTextLen += output.len; 180 HcfBlobDataFree(&output); 181 } 182 return 0; 183} 184 185int32_t Sm4Decrypt(HcfCipher *cipher, HcfSymKey *key, HcfParamsSpec *params, 186 uint8_t *cipherText, int cipherTextLen) 187{ 188 uint8_t plainText[] = "this is test!"; 189 HcfBlob input = {.data = reinterpret_cast<uint8_t *>(cipherText), .len = cipherTextLen}; 190 HcfBlob output = {}; 191 int32_t maxLen = cipherTextLen; 192 int32_t ret = cipher->init(cipher, DECRYPT_MODE, reinterpret_cast<HcfKey *>(key), params); 193 if (ret != 0) { 194 LOGE("init failed! "); 195 return ret; 196 } 197 198 ret = cipher->update(cipher, &input, &output); 199 if (ret != 0) { 200 LOGE("update failed!"); 201 return ret; 202 } 203 cipherTextLen = output.len; 204 if (output.data != nullptr) { 205 if (memcpy_s(cipherText, maxLen, output.data, output.len) != EOK) { 206 HcfBlobDataFree(&output); 207 return -1; 208 } 209 HcfBlobDataFree(&output); 210 } 211 212 ret = cipher->doFinal(cipher, nullptr, &output); 213 if (ret != 0) { 214 LOGE("doFinal failed!"); 215 return ret; 216 } 217 if (output.data != nullptr) { 218 if (memcpy_s(cipherText + cipherTextLen, maxLen - cipherTextLen, output.data, output.len) != EOK) { 219 HcfBlobDataFree(&output); 220 return -1; 221 } 222 cipherTextLen += output.len; 223 HcfBlobDataFree(&output); 224 } 225 226 if (cipherTextLen != sizeof(plainText) - 1) { 227 return -1; 228 } 229 return memcmp(cipherText, plainText, cipherTextLen); 230} 231 232int32_t Sm4NoUpdateEncrypt(HcfCipher *cipher, HcfSymKey *key, HcfParamsSpec *params, 233 uint8_t *cipherText, int *cipherTextLen) 234{ 235 uint8_t plainText[] = "this is test!"; 236 HcfBlob input = {.data = reinterpret_cast<uint8_t *>(plainText), .len = 13}; 237 HcfBlob output = {}; 238 int32_t maxLen = *cipherTextLen; 239 int32_t ret = cipher->init(cipher, ENCRYPT_MODE, reinterpret_cast<HcfKey *>(key), params); 240 if (ret != 0) { 241 LOGE("init failed! "); 242 return ret; 243 } 244 245 *cipherTextLen = 0; 246 ret = cipher->doFinal(cipher, &input, &output); 247 if (ret != 0) { 248 LOGE("doFinal failed!"); 249 return ret; 250 } 251 if (output.data != nullptr) { 252 if (memcpy_s(cipherText, maxLen, output.data, output.len) != EOK) { 253 HcfBlobDataFree(&output); 254 return -1; 255 } 256 *cipherTextLen += output.len; 257 HcfBlobDataFree(&output); 258 } 259 return 0; 260} 261 262int32_t Sm4NoUpdateDecrypt(HcfCipher *cipher, HcfSymKey *key, HcfParamsSpec *params, 263 uint8_t *cipherText, int cipherTextLen) 264{ 265 uint8_t plainText[] = "this is test!"; 266 HcfBlob input = {.data = reinterpret_cast<uint8_t *>(cipherText), .len = cipherTextLen}; 267 HcfBlob output = {}; 268 int32_t maxLen = cipherTextLen; 269 int32_t ret = cipher->init(cipher, DECRYPT_MODE, reinterpret_cast<HcfKey *>(key), params); 270 if (ret != 0) { 271 LOGE("init failed! "); 272 return ret; 273 } 274 275 cipherTextLen = 0; 276 ret = cipher->doFinal(cipher, &input, &output); 277 if (ret != 0) { 278 LOGE("doFinal failed!"); 279 return ret; 280 } 281 if (output.data != nullptr) { 282 if (memcpy_s(cipherText, maxLen, output.data, output.len) != EOK) { 283 HcfBlobDataFree(&output); 284 return -1; 285 } 286 cipherTextLen += output.len; 287 HcfBlobDataFree(&output); 288 } 289 290 if (cipherTextLen != sizeof(plainText) - 1) { 291 return -1; 292 } 293 return memcmp(cipherText, plainText, cipherTextLen); 294} 295 296const char *GetMockClass(void) 297{ 298 return "HcfMock"; 299} 300 301HcfObjectBase obj = { 302 .getClass = GetMockClass, 303 .destroy = nullptr 304};