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 "rand.h"
17 
18 #include <limits.h>
19 #include <securec.h>
20 #include "rand_spi.h"
21 #ifdef CRYPTO_MBEDTLS
22 #include "mbedtls_rand.h"
23 #else
24 #include "rand_openssl.h"
25 #endif
26 #include "log.h"
27 #include "config.h"
28 #include "memory.h"
29 #include "utils.h"
30 
31 typedef HcfResult (*HcfRandSpiCreateFunc)(HcfRandSpi **);
32 
33 typedef struct {
34     HcfRand base;
35 
36     HcfRandSpi *spiObj;
37 
38     const char *algoName;
39 } HcfRandImpl;
40 
41 typedef struct {
42     char *algoName;
43 
44     HcfRandSpiCreateFunc createSpiFunc;
45 } HcfRandAbility;
46 
GetRandClass(void)47 static const char *GetRandClass(void)
48 {
49     return "Rand";
50 }
51 
52 static const HcfRandAbility RAND_ABILITY_SET[] = {
53 #ifdef CRYPTO_MBEDTLS
54     { "MbedtlsRand", MbedtlsRandSpiCreate }
55 #else
56     { "OpensslRand", HcfRandSpiCreate }
57 #endif
58 };
59 
FindAbility(const char *algoName)60 static HcfRandSpiCreateFunc FindAbility(const char *algoName)
61 {
62     for (uint32_t i = 0; i < (sizeof(RAND_ABILITY_SET) / sizeof(RAND_ABILITY_SET[0])); i++) {
63         if (strcmp(RAND_ABILITY_SET[i].algoName, algoName) == 0) {
64             return RAND_ABILITY_SET[i].createSpiFunc;
65         }
66     }
67     LOGE("Algo not support! [Algo]: %s", algoName);
68     return NULL;
69 }
70 
GenerateRandom(HcfRand *self, int32_t numBytes, HcfBlob *random)71 static HcfResult GenerateRandom(HcfRand *self, int32_t numBytes, HcfBlob *random)
72 {
73     if ((self == NULL) || (random == NULL)) {
74         LOGE("Invalid params!");
75         return HCF_INVALID_PARAMS;
76     }
77     if (numBytes <= 0) {
78         LOGE("Invalid numBytes!");
79         return HCF_INVALID_PARAMS;
80     }
81     if (!HcfIsClassMatch((HcfObjectBase *)self, GetRandClass())) {
82         LOGE("Class is not match.");
83         return HCF_INVALID_PARAMS;
84     }
85     return ((HcfRandImpl *)self)->spiObj->engineGenerateRandom(
86         ((HcfRandImpl *)self)->spiObj, numBytes, random);
87 }
88 
GetAlgoName(HcfRand *self)89 static const char *GetAlgoName(HcfRand *self)
90 {
91     if (self == NULL) {
92         LOGE("The input self ptr is NULL!");
93         return NULL;
94     }
95     if (!HcfIsClassMatch((HcfObjectBase *)self, GetRandClass())) {
96         LOGE("Class is not match!");
97         return NULL;
98     }
99     return ((HcfRandImpl *)self)->spiObj->engineGetAlgoName(((HcfRandImpl *)self)->spiObj);
100 }
101 
SetSeed(HcfRand *self, HcfBlob *seed)102 static HcfResult SetSeed(HcfRand *self, HcfBlob *seed)
103 {
104     if ((self == NULL) || (!HcfIsBlobValid(seed)) || (seed->len > INT_MAX)) {
105         LOGE("The input self ptr is NULL!");
106         return HCF_INVALID_PARAMS;
107     }
108     if (!HcfIsClassMatch((HcfObjectBase *)self, GetRandClass())) {
109         LOGE("Class is not match.");
110         return HCF_INVALID_PARAMS;
111     }
112     ((HcfRandImpl *)self)->spiObj->engineSetSeed(
113         ((HcfRandImpl *)self)->spiObj, seed);
114     return HCF_SUCCESS;
115 }
116 
HcfRandDestroy(HcfObjectBase *self)117 static void HcfRandDestroy(HcfObjectBase *self)
118 {
119     if (self == NULL) {
120         LOGE("The input self ptr is NULL!");
121         return;
122     }
123     if (!HcfIsClassMatch((HcfObjectBase *)self, GetRandClass())) {
124         LOGE("Class is not match.");
125         return;
126     }
127     HcfRandImpl *impl = (HcfRandImpl *)self;
128     HcfObjDestroy(impl->spiObj);
129     HcfFree(impl);
130 }
131 
HcfRandCreate(HcfRand **random)132 HcfResult HcfRandCreate(HcfRand **random)
133 {
134     if (random == NULL) {
135         LOGE("Invalid input params while creating rand!");
136         return HCF_INVALID_PARAMS;
137     }
138 #ifdef CRYPTO_MBEDTLS
139     HcfRandSpiCreateFunc createSpiFunc = FindAbility("MbedtlsRand");
140 #else
141     HcfRandSpiCreateFunc createSpiFunc = FindAbility("OpensslRand");
142 #endif
143     if (createSpiFunc == NULL) {
144         LOGE("Algo not supported!");
145         return HCF_NOT_SUPPORT;
146     }
147     HcfRandImpl *returnRandApi = (HcfRandImpl *)HcfMalloc(sizeof(HcfRandImpl), 0);
148     if (returnRandApi == NULL) {
149         LOGE("Failed to allocate Rand Obj memory!");
150         return HCF_ERR_MALLOC;
151     }
152     HcfRandSpi *spiObj = NULL;
153     HcfResult res = createSpiFunc(&spiObj);
154     if (res != HCF_SUCCESS) {
155         LOGE("Failed to create spi object!");
156         HcfFree(returnRandApi);
157         return res;
158     }
159     returnRandApi->base.base.getClass = GetRandClass;
160     returnRandApi->base.base.destroy = HcfRandDestroy;
161     returnRandApi->base.generateRandom = GenerateRandom;
162     returnRandApi->base.getAlgoName = GetAlgoName;
163     returnRandApi->base.setSeed = SetSeed;
164     returnRandApi->spiObj = spiObj;
165     *random = (HcfRand *)returnRandApi;
166     return HCF_SUCCESS;
167 }