1 /*
2  * Copyright (C) 2022 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 "log.h"
17 #include "memory.h"
18 #include "result.h"
19 #include "securec.h"
20 #include "utils.h"
21 #include "sym_common_defines.h"
22 #include "openssl_adapter.h"
23 #include "openssl_common.h"
24 
25 #define MAX_KEY_STR_SIZE 12
26 #define MAX_KEY_LEN 4096
27 #define KEY_BIT 8
28 #define AES_ALG_NAME "AES"
29 #define SM4_ALG_NAME "SM4"
30 #define DES_ALG_NAME "3DES"
31 #define HMAC_ALG_NAME "HMAC"
32 
33 typedef struct {
34     HcfSymKeyGeneratorSpi base;
35     SymKeyAttr attr;
36 } HcfSymKeyGeneratorSpiOpensslImpl;
37 
GetEncoded(HcfKey * self,HcfBlob * key)38 static HcfResult GetEncoded(HcfKey *self, HcfBlob *key)
39 {
40     if ((self == NULL) || (key == NULL)) {
41         LOGE("Invalid input parameter!");
42         return HCF_INVALID_PARAMS;
43     }
44     if (!HcfIsClassMatch((const HcfObjectBase *)self, OPENSSL_SYM_KEY_CLASS)) {
45         LOGE("Class is not match.");
46         return HCF_INVALID_PARAMS;
47     }
48     SymKeyImpl *impl = (SymKeyImpl *)self;
49     if ((impl->keyMaterial.data == NULL) || (impl->keyMaterial.len == 0)) {
50         LOGE("Invalid SymKeyImpl parameter!");
51         return HCF_INVALID_PARAMS;
52     }
53     key->data = (uint8_t *)HcfMalloc(impl->keyMaterial.len, 0);
54     if (key->data == NULL) {
55         LOGE("malloc keyMaterial failed!");
56         return HCF_ERR_MALLOC;
57     }
58     (void)memcpy_s(key->data, impl->keyMaterial.len, impl->keyMaterial.data, impl->keyMaterial.len);
59     key->len = impl->keyMaterial.len;
60     return HCF_SUCCESS;
61 }
62 
ClearMem(HcfSymKey * self)63 static void ClearMem(HcfSymKey *self)
64 {
65     if (self == NULL) {
66         LOGE("symKey is NULL.");
67         return;
68     }
69     if (!HcfIsClassMatch((const HcfObjectBase *)self, OPENSSL_SYM_KEY_CLASS)) {
70         LOGE("Class is not match.");
71         return;
72     }
73     SymKeyImpl *impl = (SymKeyImpl *)self;
74     if ((impl->keyMaterial.data != NULL) && (impl->keyMaterial.len > 0)) {
75         (void)memset_s(impl->keyMaterial.data, impl->keyMaterial.len, 0, impl->keyMaterial.len);
76     }
77 }
78 
GetFormat(HcfKey * self)79 static const char *GetFormat(HcfKey *self)
80 {
81     if (self == NULL) {
82         LOGE("Invalid input parameter!");
83         return NULL;
84     }
85     if (!HcfIsClassMatch((const HcfObjectBase *)self, OPENSSL_SYM_KEY_CLASS)) {
86         LOGE("Class is not match.");
87         return NULL;
88     }
89 
90     return "PKCS#8";
91 }
92 
GetSymKeyGeneratorClass(void)93 static const char *GetSymKeyGeneratorClass(void)
94 {
95     return OPENSSL_SYM_GENERATOR_CLASS;
96 }
97 
GetSymKeyClass(void)98 static const char *GetSymKeyClass(void)
99 {
100     return OPENSSL_SYM_KEY_CLASS;
101 }
102 
GetAlgorithm(HcfKey * self)103 static const char *GetAlgorithm(HcfKey *self)
104 {
105     if (self == NULL) {
106         LOGE("Invalid input parameter!");
107         return NULL;
108     }
109     if (!HcfIsClassMatch((const HcfObjectBase *)self, OPENSSL_SYM_KEY_CLASS)) {
110         LOGE("Class is not match.");
111         return NULL;
112     }
113     SymKeyImpl *impl = (SymKeyImpl *)self;
114     return (const char *)impl->algoName;
115 }
116 
RandomSymmKey(int32_t keyLen,HcfBlob * symmKey)117 static HcfResult RandomSymmKey(int32_t keyLen, HcfBlob *symmKey)
118 {
119     uint8_t *keyMaterial = (uint8_t *)HcfMalloc(keyLen, 0);
120     if (keyMaterial == NULL) {
121         LOGE("keyMaterial malloc failed!");
122         return HCF_ERR_MALLOC;
123     }
124     int ret = OpensslRandPrivBytes(keyMaterial, keyLen);
125     if (ret != HCF_OPENSSL_SUCCESS) {
126         LOGD("[error] RAND_bytes failed!");
127         HcfPrintOpensslError();
128         HcfFree(keyMaterial);
129         return HCF_ERR_CRYPTO_OPERATION;
130     }
131     symmKey->data = keyMaterial;
132     symmKey->len = keyLen;
133     return HCF_SUCCESS;
134 }
135 
HcfSymmKeySpiCreate(int32_t keyLen,SymKeyImpl * symKey)136 static HcfResult HcfSymmKeySpiCreate(int32_t keyLen, SymKeyImpl *symKey)
137 {
138     if ((keyLen == 0) || (symKey == NULL)) {
139         LOGE("Invalid input parameter!");
140         return HCF_INVALID_PARAMS;
141     }
142     HcfResult res = RandomSymmKey(keyLen, &symKey->keyMaterial);
143     if (res != HCF_SUCCESS) {
144         LOGD("[error] RandomSymmKey failed!");
145         return res;
146     }
147     return res;
148 }
149 
DestroySymKeyGeneratorSpi(HcfObjectBase * base)150 static void DestroySymKeyGeneratorSpi(HcfObjectBase *base)
151 {
152     if (base == NULL) {
153         LOGE("Invalid input parameter!");
154         return;
155     }
156     if (!HcfIsClassMatch(base, GetSymKeyGeneratorClass())) {
157         LOGE("Class is not match!");
158         return;
159     }
160     HcfFree(base);
161 }
162 
DestroySymKeySpi(HcfObjectBase * base)163 static void DestroySymKeySpi(HcfObjectBase *base)
164 {
165     if (base == NULL) {
166         LOGE("Invalid input parameter!");
167         return;
168     }
169     if (!HcfIsClassMatch(base, OPENSSL_SYM_KEY_CLASS)) {
170         LOGE("Class is not match.");
171         return;
172     }
173     SymKeyImpl *impl = (SymKeyImpl *)base;
174     if (impl->algoName != NULL) {
175         HcfFree(impl->algoName);
176         impl->algoName = NULL;
177     }
178     if (impl->keyMaterial.data != NULL) {
179         (void)memset_s(impl->keyMaterial.data, impl->keyMaterial.len, 0, impl->keyMaterial.len);
180         HcfFree(impl->keyMaterial.data);
181         impl->keyMaterial.data = NULL;
182         impl->keyMaterial.len = 0;
183     }
184     HcfFree(impl);
185 }
186 
GetAlgoNameType(HcfAlgValue type)187 static char *GetAlgoNameType(HcfAlgValue type)
188 {
189     switch (type) {
190         case HCF_ALG_AES:
191             return AES_ALG_NAME;
192         case HCF_ALG_SM4:
193             return SM4_ALG_NAME;
194         case HCF_ALG_DES:
195             return DES_ALG_NAME;
196         case HCF_ALG_HMAC:
197             return HMAC_ALG_NAME;
198         default:
199             LOGE("unsupport type!");
200             break;
201     }
202     return NULL;
203 }
204 
GetAlgoName(HcfSymKeyGeneratorSpiOpensslImpl * impl,int keySize)205 static char *GetAlgoName(HcfSymKeyGeneratorSpiOpensslImpl *impl, int keySize)
206 {
207     char keySizeChar[MAX_KEY_STR_SIZE] = { 0 };
208     if (sprintf_s(keySizeChar, MAX_KEY_STR_SIZE, "%d", keySize) < 0) {
209         LOGE("Invalid input parameter!");
210         return NULL;
211     }
212     char *nameType = GetAlgoNameType(impl->attr.algo);
213     if (nameType == NULL) {
214         LOGE("get algo name type failed!");
215         return NULL;
216     }
217     int32_t nameSize = strlen(nameType);
218     char *algoName = (char *)HcfMalloc(MAX_KEY_STR_SIZE, 0);
219     if (algoName == NULL) {
220         LOGE("algoName malloc failed!");
221         return NULL;
222     }
223     if (strcpy_s(algoName, MAX_KEY_STR_SIZE, nameType) != EOK) {
224         LOGE("algoName strcpy_s failed!");
225         goto clearup;
226     }
227     if (strcpy_s(algoName + nameSize, MAX_KEY_STR_SIZE - nameSize, keySizeChar) != EOK) {
228         LOGE("algoName size strcpy_s failed!");
229         goto clearup;
230     }
231     return algoName;
232 clearup:
233     HcfFree(algoName);
234     return NULL;
235 }
236 
CopySymmKey(const HcfBlob * srcKey,HcfBlob * dstKey)237 static HcfResult CopySymmKey(const HcfBlob *srcKey, HcfBlob *dstKey)
238 {
239     if ((srcKey->data == NULL) || (srcKey->len == 0)) {
240         LOGE("Invalid input parameter!");
241         return HCF_INVALID_PARAMS;
242     }
243     uint8_t *keyMaterial = (uint8_t *)HcfMalloc(srcKey->len, 0);
244     if (keyMaterial == NULL) {
245         LOGE("keyMaterial malloc failed!");
246         return HCF_ERR_MALLOC;
247     }
248     (void)memcpy_s(keyMaterial, srcKey->len, srcKey->data, srcKey->len);
249     dstKey->data = keyMaterial;
250     dstKey->len = srcKey->len;
251     return HCF_SUCCESS;
252 }
253 
GenerateSymmKey(HcfSymKeyGeneratorSpi * self,HcfSymKey ** symmKey)254 static HcfResult GenerateSymmKey(HcfSymKeyGeneratorSpi *self, HcfSymKey **symmKey)
255 {
256     if ((self == NULL) || (symmKey == NULL)) {
257         LOGE("Invalid input parameter!");
258         return HCF_INVALID_PARAMS;
259     }
260     if (!HcfIsClassMatch((const HcfObjectBase *)self, GetSymKeyGeneratorClass())) {
261         LOGE("Class is not match!");
262         return HCF_INVALID_PARAMS;
263     }
264     SymKeyImpl *returnSymmKey = (SymKeyImpl *)HcfMalloc(sizeof(SymKeyImpl), 0);
265     if (returnSymmKey == NULL) {
266         LOGE("Failed to allocate returnKeyPair memory!");
267         return HCF_ERR_MALLOC;
268     }
269     HcfSymKeyGeneratorSpiOpensslImpl *impl = (HcfSymKeyGeneratorSpiOpensslImpl *)self;
270     HcfResult res = HcfSymmKeySpiCreate(impl->attr.keySize / KEY_BIT, returnSymmKey);
271     if (res != HCF_SUCCESS) {
272         HcfFree(returnSymmKey);
273         return res;
274     }
275     returnSymmKey->algoName = GetAlgoName(impl, impl->attr.keySize);
276     returnSymmKey->key.clearMem = ClearMem;
277     returnSymmKey->key.key.getEncoded = GetEncoded;
278     returnSymmKey->key.key.getFormat = GetFormat;
279     returnSymmKey->key.key.getAlgorithm = GetAlgorithm;
280     returnSymmKey->key.key.base.destroy = DestroySymKeySpi;
281     returnSymmKey->key.key.base.getClass = GetSymKeyClass;
282     *symmKey = (HcfSymKey *)returnSymmKey;
283     return HCF_SUCCESS;
284 }
285 
IsBlobKeyLenValid(SymKeyAttr attr,const HcfBlob * key)286 static bool IsBlobKeyLenValid(SymKeyAttr attr, const HcfBlob *key)
287 {
288     if ((key->len == 0) || (key->len > MAX_KEY_LEN)) {
289         return false;
290     }
291 
292     if ((attr.keySize / KEY_BIT) == (int32_t)key->len) {
293         return true;
294     }
295 
296     if ((attr.algo == HCF_ALG_HMAC) && (attr.keySize == 0)) {
297         return true;
298     }
299 
300     return false;
301 }
302 
ConvertSymmKey(HcfSymKeyGeneratorSpi * self,const HcfBlob * key,HcfSymKey ** symmKey)303 static HcfResult ConvertSymmKey(HcfSymKeyGeneratorSpi *self, const HcfBlob *key, HcfSymKey **symmKey)
304 {
305     if ((self == NULL) || (symmKey == NULL) || !HcfIsBlobValid(key)) {
306         LOGE("Invalid input parameter.");
307         return HCF_INVALID_PARAMS;
308     }
309     if (!HcfIsClassMatch((const HcfObjectBase *)self, GetSymKeyGeneratorClass())) {
310         LOGE("Class is not match.");
311         return HCF_INVALID_PARAMS;
312     }
313     HcfSymKeyGeneratorSpiOpensslImpl *impl = (HcfSymKeyGeneratorSpiOpensslImpl *)self;
314 
315     if (!IsBlobKeyLenValid(impl->attr, key)) {
316         LOGE("Invalid param: input key length is invalid!");
317         return HCF_INVALID_PARAMS;
318     }
319 
320     SymKeyImpl *returnSymmKey = (SymKeyImpl *)HcfMalloc(sizeof(SymKeyImpl), 0);
321     if (returnSymmKey == NULL) {
322         LOGE("Failed to allocate returnKeyPair memory!");
323         return HCF_ERR_MALLOC;
324     }
325     HcfResult res = CopySymmKey(key, &returnSymmKey->keyMaterial);
326     if (res != HCF_SUCCESS) {
327         HcfFree(returnSymmKey);
328         return res;
329     }
330     int keySize = impl->attr.keySize;
331     if (impl->attr.algo == HCF_ALG_HMAC && keySize == 0) {
332         keySize = (int)returnSymmKey->keyMaterial.len * KEY_BIT;
333     }
334     returnSymmKey->algoName = GetAlgoName(impl, keySize);
335     returnSymmKey->key.clearMem = ClearMem;
336     returnSymmKey->key.key.getEncoded = GetEncoded;
337     returnSymmKey->key.key.getFormat = GetFormat;
338     returnSymmKey->key.key.getAlgorithm = GetAlgorithm;
339     returnSymmKey->key.key.base.destroy = DestroySymKeySpi;
340     returnSymmKey->key.key.base.getClass = GetSymKeyClass;
341     *symmKey = (HcfSymKey *)returnSymmKey;
342     return HCF_SUCCESS;
343 }
344 
HcfSymKeyGeneratorSpiCreate(SymKeyAttr * attr,HcfSymKeyGeneratorSpi ** generator)345 HcfResult HcfSymKeyGeneratorSpiCreate(SymKeyAttr *attr, HcfSymKeyGeneratorSpi **generator)
346 {
347     if ((attr == NULL) || (generator == NULL)) {
348         LOGE("Invalid input parameter.");
349         return HCF_INVALID_PARAMS;
350     }
351     HcfSymKeyGeneratorSpiOpensslImpl *returnGenerator = (HcfSymKeyGeneratorSpiOpensslImpl *)HcfMalloc(
352         sizeof(HcfSymKeyGeneratorSpiOpensslImpl), 0);
353     if (returnGenerator == NULL) {
354         LOGE("Failed to allocate returnGenerator memory!");
355         return HCF_ERR_MALLOC;
356     }
357     (void)memcpy_s(&returnGenerator->attr, sizeof(SymKeyAttr), attr, sizeof(SymKeyAttr));
358     returnGenerator->base.engineGenerateSymmKey = GenerateSymmKey;
359     returnGenerator->base.engineConvertSymmKey = ConvertSymmKey;
360     returnGenerator->base.base.destroy = DestroySymKeyGeneratorSpi;
361     returnGenerator->base.base.getClass = GetSymKeyGeneratorClass;
362     *generator = (HcfSymKeyGeneratorSpi *)returnGenerator;
363     return HCF_SUCCESS;
364 }
365