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 "mbedtls_rand.h"
17 
18 #include "mbedtls/entropy.h"
19 #include "mbedtls/ctr_drbg.h"
20 #include "securec.h"
21 #include "log.h"
22 #include "memory.h"
23 #include "utils.h"
24 
25 typedef struct {
26     HcfRandSpi base;
27     mbedtls_entropy_context *entropy;
28     mbedtls_ctr_drbg_context *ctrDrbg;
29 } HcfRandSpiImpl;
30 
GetMbedtlsRandClass(void)31 static const char *GetMbedtlsRandClass(void)
32 {
33     return "RandMbedtls";
34 }
35 
MbedtlsGetMdEntropy(HcfRandSpi *self)36 static mbedtls_entropy_context *MbedtlsGetMdEntropy(HcfRandSpi *self)
37 {
38     if (!HcfIsClassMatch((HcfObjectBase *)self, GetMbedtlsRandClass())) {
39         LOGE("Class is not match.");
40         return NULL;
41     }
42 
43     return ((HcfRandSpiImpl *)self)->entropy;
44 }
45 
MbedtlsGetMdCtrDrbg(HcfRandSpi *self)46 static mbedtls_ctr_drbg_context *MbedtlsGetMdCtrDrbg(HcfRandSpi *self)
47 {
48     if (!HcfIsClassMatch((HcfObjectBase *)self, GetMbedtlsRandClass())) {
49         LOGE("Class is not match.");
50         return NULL;
51     }
52     return ((HcfRandSpiImpl *)self)->ctrDrbg;
53 }
54 
MbedtlsGenerateRandom(HcfRandSpi *self, int32_t numBytes, HcfBlob *random)55 static HcfResult MbedtlsGenerateRandom(HcfRandSpi *self, int32_t numBytes, HcfBlob *random)
56 {
57     if ((self == NULL) || (random == NULL)) {
58         LOGE("Invalid params!");
59         return HCF_INVALID_PARAMS;
60     }
61     if (numBytes <= 0) {
62         LOGE("Invalid numBytes!");
63         return HCF_INVALID_PARAMS;
64     }
65     mbedtls_ctr_drbg_context *ctrDrbg = MbedtlsGetMdCtrDrbg(self);
66     if (ctrDrbg == NULL) {
67         LOGE("Invalid ctrDrbg null!");
68         return HCF_INVALID_PARAMS;
69     }
70     random->data = (uint8_t *)HcfMalloc(numBytes, 0);
71     if (random->data == NULL) {
72         LOGE("Failed to allocate random->data memory!");
73         return HCF_ERR_MALLOC;
74     }
75     int32_t ret = mbedtls_ctr_drbg_random(ctrDrbg, random->data, numBytes);
76     if (ret != 0) {
77         LOGE("RAND_bytes return is %d error!", ret);
78         HcfFree(random->data);
79         random->data = NULL;
80         return HCF_ERR_CRYPTO_OPERATION;
81     }
82     random->len = numBytes;
83 
84     return HCF_SUCCESS;
85 }
86 
MbedtlsGetRandAlgoName(HcfRandSpi *self)87 static const char *MbedtlsGetRandAlgoName(HcfRandSpi *self)
88 {
89     if (self == NULL) {
90         LOGE("Invalid input parameter.");
91         return NULL;
92     }
93     if (!HcfIsClassMatch((HcfObjectBase *)self, GetMbedtlsRandClass())) {
94         LOGE("Class is not match.");
95         return NULL;
96     }
97 
98     return MBEDTLS_RAND_ALGORITHM;
99 }
100 
MbedtlsSetSeed(HcfRandSpi *self, HcfBlob *seed)101 static void MbedtlsSetSeed(HcfRandSpi *self, HcfBlob *seed)
102 {
103     if ((self == NULL) || (seed == NULL)) {
104         LOGE("Invalid params!");
105         return;
106     }
107     if ((seed->data == NULL) || (seed->len == 0)) {
108         LOGE("Invalid numBytes!");
109         return;
110     }
111     mbedtls_ctr_drbg_context *ctrDrbg = MbedtlsGetMdCtrDrbg(self);
112     if (ctrDrbg == NULL) {
113         LOGE("Invalid ctrDrbg params!");
114         return;
115     }
116     mbedtls_entropy_context *entropy = MbedtlsGetMdEntropy(self);
117     if (entropy == NULL) {
118         LOGE("Invalid entropy params!");
119         return;
120     }
121     int32_t ret = mbedtls_ctr_drbg_seed(ctrDrbg, mbedtls_entropy_func, entropy,
122         (const unsigned char *)seed->data, seed->len);
123     if (ret != 0) {
124         LOGE("seed return is %d error!", ret);
125         return;
126     }
127 }
128 
DestroyMbedtlsRand(HcfObjectBase *self)129 static void DestroyMbedtlsRand(HcfObjectBase *self)
130 {
131     if (self == NULL) {
132         LOGE("Self ptr is NULL!");
133         return;
134     }
135     if (!HcfIsClassMatch(self, GetMbedtlsRandClass())) {
136         LOGE("Class is not match.");
137         return;
138     }
139     mbedtls_ctr_drbg_context *ctrDrbg = MbedtlsGetMdCtrDrbg((HcfRandSpi *)self);
140     if (ctrDrbg != NULL) {
141         mbedtls_ctr_drbg_free(ctrDrbg);
142         HcfFree(ctrDrbg);
143     }
144     mbedtls_entropy_context *entropy = MbedtlsGetMdEntropy((HcfRandSpi *)self);
145     if (entropy != NULL) {
146         mbedtls_entropy_free(entropy);
147         HcfFree(entropy);
148     }
149     HcfFree(self);
150 }
151 
MbedtlsRandInitEx(mbedtls_entropy_context **entropy, mbedtls_ctr_drbg_context **ctrDrbg)152 static int32_t MbedtlsRandInitEx(mbedtls_entropy_context **entropy, mbedtls_ctr_drbg_context **ctrDrbg)
153 {
154     if ((entropy == NULL) || (ctrDrbg == NULL)) {
155         LOGE("Invalid input parameter.");
156         return HCF_INVALID_PARAMS;
157     }
158     *entropy = (mbedtls_entropy_context *)HcfMalloc(sizeof(mbedtls_entropy_context), 0);
159     if (*entropy == NULL) {
160         LOGE("Failed to allocate *entropy memory!");
161         return HCF_ERR_MALLOC;
162     }
163     *ctrDrbg = (mbedtls_ctr_drbg_context *)HcfMalloc(sizeof(mbedtls_ctr_drbg_context), 0);
164     if (*ctrDrbg == NULL) {
165         HcfFree(*entropy);
166         LOGE("Failed to allocate *ctrDrbg memory!");
167         return HCF_ERR_MALLOC;
168     }
169     mbedtls_entropy_init(*entropy);
170     mbedtls_ctr_drbg_init(*ctrDrbg);
171     int32_t ret = mbedtls_ctr_drbg_seed(*ctrDrbg, mbedtls_entropy_func, *entropy, NULL, 0);
172     if (ret != 0) {
173         LOGE("Failed seed ret is %d!", ret);
174         mbedtls_entropy_free(*entropy);
175         mbedtls_ctr_drbg_free(*ctrDrbg);
176         HcfFree(*entropy);
177         HcfFree(*ctrDrbg);
178         return HCF_ERR_CRYPTO_OPERATION;
179     }
180 
181     return HCF_SUCCESS;
182 }
183 
MbedtlsRandSpiCreate(HcfRandSpi **spiObj)184 HcfResult MbedtlsRandSpiCreate(HcfRandSpi **spiObj)
185 {
186     if (spiObj == NULL) {
187         LOGE("Invalid input parameter.");
188         return HCF_INVALID_PARAMS;
189     }
190     HcfRandSpiImpl *returnSpiImpl = (HcfRandSpiImpl *)HcfMalloc(sizeof(HcfRandSpiImpl), 0);
191     if (returnSpiImpl == NULL) {
192         LOGE("Failed to allocate *returnSpiImpl memory!");
193         return HCF_ERR_MALLOC;
194     }
195     int32_t ret = MbedtlsRandInitEx(&(returnSpiImpl->entropy), &(returnSpiImpl->ctrDrbg));
196     if (ret != HCF_SUCCESS) {
197         LOGE("Failed to allocate entropy ctrDrbg memory!");
198         return HCF_ERR_MALLOC;
199     }
200     returnSpiImpl->base.base.getClass = GetMbedtlsRandClass;
201     returnSpiImpl->base.base.destroy = DestroyMbedtlsRand;
202     returnSpiImpl->base.engineGenerateRandom = MbedtlsGenerateRandom;
203     returnSpiImpl->base.engineSetSeed = MbedtlsSetSeed;
204     returnSpiImpl->base.engineGetAlgoName = MbedtlsGetRandAlgoName;
205     *spiObj = (HcfRandSpi *)returnSpiImpl;
206 
207     return HCF_SUCCESS;
208 }
209