1/* 2 * Copyright (C) 2022-2023 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 "cipher.h" 17#include "aes_openssl.h" 18#include "config.h" 19#include "securec.h" 20#include "result.h" 21#include "string.h" 22#include "log.h" 23#include "memory.h" 24#include "cipher_rsa_openssl.h" 25#include "cipher_sm2_openssl.h" 26#include "sm4_openssl.h" 27#include "utils.h" 28 29typedef HcfResult (*HcfCipherGeneratorSpiCreateFunc)(CipherAttr *, HcfCipherGeneratorSpi **); 30 31typedef struct { 32 HcfCipher super; 33 HcfCipherGeneratorSpi *spiObj; 34 char algoName[HCF_MAX_ALGO_NAME_LEN]; 35} CipherGenImpl; 36 37typedef struct { 38 HcfCipherGeneratorSpiCreateFunc createFunc; 39} HcfCipherGenFuncSet; 40 41typedef struct { 42 HcfAlgValue algo; 43 HcfCipherGenFuncSet funcSet; 44} HcfCipherGenAbility; 45 46static const HcfCipherGenAbility CIPHER_ABILITY_SET[] = { 47 { HCF_ALG_RSA, { HcfCipherRsaCipherSpiCreate } }, 48 { HCF_ALG_SM2, { HcfCipherSm2CipherSpiCreate } }, 49 { HCF_ALG_AES, { HcfCipherAesGeneratorSpiCreate } }, 50 { HCF_ALG_DES, { HcfCipherDesGeneratorSpiCreate } }, 51 { HCF_ALG_SM4, { HcfCipherSm4GeneratorSpiCreate } } 52}; 53 54static void SetKeyType(HcfAlgParaValue value, void *cipher) 55{ 56 CipherAttr *cipherAttr = (CipherAttr *)cipher; 57 58 cipherAttr->keySize = 0; 59 60 switch (value) { 61 case HCF_ALG_AES_DEFAULT: 62 cipherAttr->algo = HCF_ALG_AES; 63 break; 64 case HCF_ALG_SM4_DEFAULT: 65 cipherAttr->algo = HCF_ALG_SM4; 66 break; 67 case HCF_ALG_3DES_DEFAULT: 68 cipherAttr->algo = HCF_ALG_DES; 69 break; 70 case HCF_ALG_RSA_DEFAULT: 71 cipherAttr->algo = HCF_ALG_RSA; 72 break; 73 case HCF_ALG_SM2_DEFAULT: 74 cipherAttr->algo = HCF_ALG_SM2; 75 break; 76 default: 77 LOGE("Invalid algo %u.", value); 78 break; 79 } 80} 81 82static void SetKeyLength(HcfAlgParaValue value, void *cipher) 83{ 84 CipherAttr *cipherAttr = (CipherAttr *)cipher; 85 86 cipherAttr->keySize = value; 87 88 switch (value) { 89 case HCF_ALG_AES_128: 90 case HCF_ALG_AES_192: 91 case HCF_ALG_AES_256: 92 cipherAttr->algo = HCF_ALG_AES; 93 break; 94 case HCF_ALG_SM4_128: 95 cipherAttr->algo = HCF_ALG_SM4; 96 break; 97 case HCF_ALG_3DES_192: 98 cipherAttr->algo = HCF_ALG_DES; 99 break; 100 case HCF_OPENSSL_RSA_512: 101 case HCF_OPENSSL_RSA_768: 102 case HCF_OPENSSL_RSA_1024: 103 case HCF_OPENSSL_RSA_2048: 104 case HCF_OPENSSL_RSA_3072: 105 case HCF_OPENSSL_RSA_4096: 106 case HCF_OPENSSL_RSA_8192: 107 cipherAttr->algo = HCF_ALG_RSA; 108 break; 109 case HCF_ALG_SM2_256: 110 cipherAttr->algo = HCF_ALG_SM2; 111 break; 112 default: 113 LOGE("Invalid algo %u.", value); 114 break; 115 } 116} 117 118static void SetMode(HcfAlgParaValue value, void *cipher) 119{ 120 CipherAttr *cipherAttr = (CipherAttr *)cipher; 121 cipherAttr->mode = value ; 122} 123 124static void SetPadding(HcfAlgParaValue value, void *cipher) 125{ 126 CipherAttr *cipherAttr = (CipherAttr *)cipher; 127 cipherAttr->paddingMode = value; 128} 129 130static void SetDigest(HcfAlgParaValue value, CipherAttr *cipher) 131{ 132 cipher->md = value; 133} 134 135static void SetMgf1Digest(HcfAlgParaValue value, CipherAttr *cipher) 136{ 137 cipher->mgf1md = value; 138} 139 140static HcfResult OnSetParameter(const HcfParaConfig *config, void *cipher) 141{ 142 if ((config == NULL) || (cipher == NULL)) { 143 LOGE("Invalid cipher params"); 144 return HCF_INVALID_PARAMS; 145 } 146 HcfResult ret = HCF_SUCCESS; 147 LOGD("Set Parameter:%s", config->tag); 148 switch (config->paraType) { 149 case HCF_ALG_TYPE: 150 SetKeyType(config->paraValue, cipher); 151 break; 152 case HCF_ALG_KEY_TYPE: 153 SetKeyLength(config->paraValue, cipher); 154 break; 155 case HCF_ALG_MODE: 156 SetMode(config->paraValue, cipher); 157 break; 158 case HCF_ALG_PADDING_TYPE: 159 SetPadding(config->paraValue, cipher); 160 break; 161 case HCF_ALG_DIGEST: 162 SetDigest(config->paraValue, cipher); 163 break; 164 case HCF_ALG_MGF1_DIGEST: 165 SetMgf1Digest(config->paraValue, cipher); 166 break; 167 case HCF_ALG_TEXT_FORMAT: 168 if (config->paraValue == HCF_ALG_TEXT_FORMAT_C1C2C3) { 169 LOGE("Not Support C1C2C3 Format"); 170 ret = HCF_INVALID_PARAMS; 171 } 172 break; 173 default: 174 ret = HCF_INVALID_PARAMS; 175 break; 176 } 177 return ret; 178} 179 180static const char *GetCipherGeneratorClass(void) 181{ 182 return "HcfCipherGenerator"; 183} 184 185static const char *GetAlgorithm(HcfCipher *self) 186{ 187 if (self == NULL) { 188 LOGE("The input self ptr is NULL!"); 189 return NULL; 190 } 191 if (!HcfIsClassMatch((HcfObjectBase *)self, GetCipherGeneratorClass())) { 192 LOGE("Class is not match."); 193 return NULL; 194 } 195 return ((CipherGenImpl *)self)->algoName; 196} 197 198static void CipherDestroy(HcfObjectBase *self) 199{ 200 if (self == NULL) { 201 return; 202 } 203 if (!HcfIsClassMatch(self, GetCipherGeneratorClass())) { 204 LOGE("Class not match."); 205 return; 206 } 207 CipherGenImpl *impl = (CipherGenImpl *)self; 208 HcfObjDestroy(impl->spiObj); 209 impl->spiObj = NULL; 210 HcfFree(impl); 211} 212 213static HcfResult SetCipherSpecUint8Array(HcfCipher *self, CipherSpecItem item, HcfBlob pSource) 214{ 215 // only implemented for OAEP_MGF1_PSRC_UINT8ARR 216 // if pSource == NULL or len == 0, it means cleaning the pSource 217 if (self == NULL) { 218 LOGE("Invalid input parameter."); 219 return HCF_INVALID_PARAMS; 220 } 221 if (item != OAEP_MGF1_PSRC_UINT8ARR) { 222 LOGE("Spec item not support."); 223 return HCF_INVALID_PARAMS; 224 } 225 if (!HcfIsClassMatch((HcfObjectBase *)self, GetCipherGeneratorClass())) { 226 LOGE("Class not match."); 227 return HCF_INVALID_PARAMS; 228 } 229 CipherGenImpl *impl = (CipherGenImpl *)self; 230 return impl->spiObj->setCipherSpecUint8Array(impl->spiObj, item, pSource); 231} 232 233static bool CheckCipherSpecString(CipherSpecItem item) 234{ 235 return ((item == OAEP_MD_NAME_STR) || (item == OAEP_MGF_NAME_STR) || 236 (item == OAEP_MGF1_MD_STR) || (item == SM2_MD_NAME_STR)); 237} 238 239static HcfResult GetCipherSpecString(HcfCipher *self, CipherSpecItem item, char **returnString) 240{ 241 if (self == NULL || returnString == NULL) { 242 LOGE("Invalid input parameter."); 243 return HCF_INVALID_PARAMS; 244 } 245 if (!CheckCipherSpecString(item)) { 246 LOGE("Spec item not support."); 247 return HCF_INVALID_PARAMS; 248 } 249 if (!HcfIsClassMatch((HcfObjectBase *)self, GetCipherGeneratorClass())) { 250 LOGE("Class not match."); 251 return HCF_INVALID_PARAMS; 252 } 253 CipherGenImpl *impl = (CipherGenImpl *)self; 254 return impl->spiObj->getCipherSpecString(impl->spiObj, item, returnString); 255} 256 257static HcfResult GetCipherSpecUint8Array(HcfCipher *self, CipherSpecItem item, HcfBlob *returnUint8Array) 258{ 259 if (self == NULL || returnUint8Array == NULL) { 260 LOGE("Invalid input parameter."); 261 return HCF_INVALID_PARAMS; 262 } 263 if (item != OAEP_MGF1_PSRC_UINT8ARR) { 264 LOGE("Spec item not support."); 265 return HCF_INVALID_PARAMS; 266 } 267 if (!HcfIsClassMatch((HcfObjectBase *)self, GetCipherGeneratorClass())) { 268 LOGE("Class not match."); 269 return HCF_INVALID_PARAMS; 270 } 271 CipherGenImpl *impl = (CipherGenImpl *)self; 272 return impl->spiObj->getCipherSpecUint8Array(impl->spiObj, item, returnUint8Array); 273} 274 275static HcfResult CipherInit(HcfCipher *self, enum HcfCryptoMode opMode, 276 HcfKey *key, HcfParamsSpec *params) 277{ 278 if (self == NULL || key == NULL) { /* params maybe is NULL */ 279 LOGE("Invalid input parameter."); 280 return HCF_INVALID_PARAMS; 281 } 282 if (!HcfIsClassMatch((HcfObjectBase *)self, GetCipherGeneratorClass())) { 283 LOGE("Class is not match."); 284 return HCF_INVALID_PARAMS; 285 } 286 CipherGenImpl *impl = (CipherGenImpl *)self; 287 return impl->spiObj->init(impl->spiObj, opMode, key, params); 288} 289 290static HcfResult CipherUpdate(HcfCipher *self, HcfBlob *input, HcfBlob *output) 291{ 292 if ((self == NULL) || (input == NULL) || (output == NULL)) { 293 LOGE("Invalid input parameter."); 294 return HCF_INVALID_PARAMS; 295 } 296 if (!HcfIsClassMatch((HcfObjectBase *)self, GetCipherGeneratorClass())) { 297 LOGE("Class is not match."); 298 return HCF_INVALID_PARAMS; 299 } 300 CipherGenImpl *impl = (CipherGenImpl *)self; 301 return impl->spiObj->update(impl->spiObj, input, output); 302} 303 304static HcfResult CipherFinal(HcfCipher *self, HcfBlob *input, HcfBlob *output) 305{ 306 if ((self == NULL) || (output == NULL)) { 307 LOGE("Invalid input parameter!"); 308 return HCF_INVALID_PARAMS; 309 } 310 if (!HcfIsClassMatch((HcfObjectBase *)self, GetCipherGeneratorClass())) { 311 LOGE("Class is not match."); 312 return HCF_INVALID_PARAMS; 313 } 314 CipherGenImpl *impl = (CipherGenImpl *)self; 315 return impl->spiObj->doFinal(impl->spiObj, input, output); 316} 317 318static void InitCipher(HcfCipherGeneratorSpi *spiObj, CipherGenImpl *cipher) 319{ 320 cipher->super.init = CipherInit; 321 cipher->super.update = CipherUpdate; 322 cipher->super.doFinal = CipherFinal; 323 cipher->super.getAlgorithm = GetAlgorithm; 324 cipher->super.base.destroy = CipherDestroy; 325 cipher->super.base.getClass = GetCipherGeneratorClass; 326 cipher->super.getCipherSpecString = GetCipherSpecString; 327 cipher->super.getCipherSpecUint8Array = GetCipherSpecUint8Array; 328 cipher->super.setCipherSpecUint8Array = SetCipherSpecUint8Array; 329} 330 331static const HcfCipherGenFuncSet *FindAbility(CipherAttr *attr) 332{ 333 if (attr == NULL) { 334 return NULL; 335 } 336 for (uint32_t i = 0; i < sizeof(CIPHER_ABILITY_SET) / sizeof(HcfCipherGenAbility); i++) { 337 if (CIPHER_ABILITY_SET[i].algo == attr->algo) { 338 return &(CIPHER_ABILITY_SET[i].funcSet); 339 } 340 } 341 LOGE("Algo not support! [Algo]: %d", attr->algo); 342 return NULL; 343} 344 345HcfResult HcfCipherCreate(const char *transformation, HcfCipher **returnObj) 346{ 347 CipherAttr attr = {0}; 348 if (!HcfIsStrValid(transformation, HCF_MAX_ALGO_NAME_LEN) || (returnObj == NULL)) { 349 LOGE("Invalid input params while creating cipher!"); 350 return HCF_INVALID_PARAMS; 351 } 352 if (ParseAndSetParameter(transformation, (void *)&attr, OnSetParameter) != HCF_SUCCESS) { 353 LOGE("ParseAndSetParameter failed!"); 354 return HCF_NOT_SUPPORT; 355 } 356 357 const HcfCipherGenFuncSet *funcSet = FindAbility(&attr); 358 if (funcSet == NULL) { 359 LOGE("FindAbility failed!"); 360 return HCF_NOT_SUPPORT; 361 } 362 CipherGenImpl *returnGenerator = (CipherGenImpl *)HcfMalloc(sizeof(CipherGenImpl), 0); 363 if (returnGenerator == NULL) { 364 LOGE("failed to allocate returnGenerator memory!"); 365 return HCF_ERR_MALLOC; 366 } 367 if (strcpy_s(returnGenerator->algoName, HCF_MAX_ALGO_NAME_LEN, transformation) != EOK) { 368 LOGE("Failed to copy algoName!"); 369 HcfFree(returnGenerator); 370 return HCF_INVALID_PARAMS; 371 } 372 HcfCipherGeneratorSpi *spiObj = NULL; 373 HcfResult res = funcSet->createFunc(&attr, &spiObj); 374 if (res != HCF_SUCCESS) { 375 LOGE("Failed to create spi object!"); 376 HcfFree(returnGenerator); 377 return res; 378 } 379 returnGenerator->spiObj = spiObj; 380 InitCipher(spiObj, returnGenerator); 381 382 *returnObj = (HcfCipher *)returnGenerator; 383 return res; 384} 385