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 "adaptor_algorithm.h"
17 #include <openssl/evp.h>
18 #include <openssl/hmac.h>
19 #include <openssl/rand.h>
20 #include <openssl/sha.h>
21 #include "adaptor_log.h"
22 #include "adaptor_memory.h"
23 #include "buffer.h"
24 #include "defines.h"
25 
26 #define OPENSSL_SUCCESS 1
27 
28 #define ED25519_FIX_PRIKEY_BUFFER_SIZE 32
29 #define ED25519_FIX_PUBKEY_BUFFER_SIZE 32
30 
31 #define SHA512_DIGEST_SIZE 64
32 
33 #define AES_GCM_TEXT_MAX_SIZE 1000
34 #define AES_GCM_AAD_MAX_SIZE 32
35 #define AES_GCM_256_KEY_SIZE 32
36 #define NO_PADDING 0
37 
38 #ifdef IAM_TEST_ENABLE
39 #define IAM_STATIC
40 #else
41 #define IAM_STATIC static
42 #endif
43 
CreateEd25519KeyPair(void)44 IAM_STATIC KeyPair *CreateEd25519KeyPair(void)
45 {
46     KeyPair *keyPair = Malloc(sizeof(KeyPair));
47     if (keyPair == NULL) {
48         LOG_ERROR("no memory for key pair");
49         return NULL;
50     }
51     keyPair->pubKey = CreateBufferBySize(ED25519_FIX_PUBKEY_BUFFER_SIZE);
52     if (keyPair->pubKey == NULL) {
53         LOG_ERROR("no memory for public key");
54         Free(keyPair);
55         return NULL;
56     }
57     keyPair->priKey = CreateBufferBySize(ED25519_FIX_PRIKEY_BUFFER_SIZE);
58     if (keyPair->priKey == NULL) {
59         LOG_ERROR("no memory for private key");
60         DestoryBuffer(keyPair->pubKey);
61         Free(keyPair);
62         return NULL;
63     }
64     return keyPair;
65 }
66 
DestoryKeyPair(KeyPair * keyPair)67 void DestoryKeyPair(KeyPair *keyPair)
68 {
69     if (keyPair == NULL) {
70         return;
71     }
72     if (keyPair->pubKey != NULL) {
73         DestoryBuffer(keyPair->pubKey);
74     }
75     if (keyPair->priKey != NULL) {
76         DestoryBuffer(keyPair->priKey);
77     }
78     Free(keyPair);
79 }
80 
IsEd25519KeyPairValid(const KeyPair * keyPair)81 bool IsEd25519KeyPairValid(const KeyPair *keyPair)
82 {
83     if (keyPair == NULL) {
84         LOG_ERROR("invalid key pair");
85         return false;
86     }
87     if (!CheckBufferWithSize(keyPair->pubKey, ED25519_FIX_PUBKEY_BUFFER_SIZE)) {
88         LOG_ERROR("invalid public key");
89         return false;
90     }
91     if (!CheckBufferWithSize(keyPair->priKey, ED25519_FIX_PRIKEY_BUFFER_SIZE)) {
92         LOG_ERROR("invalid private key");
93         return false;
94     }
95     return true;
96 }
97 
GenerateEd25519KeyPair(void)98 KeyPair *GenerateEd25519KeyPair(void)
99 {
100     KeyPair *keyPair = CreateEd25519KeyPair();
101     if (keyPair == NULL) {
102         LOG_ERROR("create key pair failed");
103         return NULL;
104     }
105     EVP_PKEY *key = NULL;
106     EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_ED25519, NULL);
107     if (ctx == NULL) {
108         LOG_ERROR("new ctx failed");
109         goto ERROR;
110     }
111     if (EVP_PKEY_keygen_init(ctx) != OPENSSL_SUCCESS) {
112         LOG_ERROR("init ctx failed");
113         goto ERROR;
114     }
115     if (EVP_PKEY_keygen(ctx, &key) != OPENSSL_SUCCESS) {
116         LOG_ERROR("generate key failed");
117         goto ERROR;
118     }
119     size_t pubKeySize = keyPair->pubKey->maxSize;
120     if (EVP_PKEY_get_raw_public_key(key, keyPair->pubKey->buf, &pubKeySize) != OPENSSL_SUCCESS) {
121         LOG_ERROR("get public key failed");
122         goto ERROR;
123     }
124     keyPair->pubKey->contentSize = pubKeySize;
125     size_t priKeySize = keyPair->priKey->maxSize;
126     if (EVP_PKEY_get_raw_private_key(key, keyPair->priKey->buf, &priKeySize) != OPENSSL_SUCCESS) {
127         LOG_ERROR("get private key failed");
128         goto ERROR;
129     }
130     keyPair->priKey->contentSize = priKeySize;
131     goto EXIT;
132 
133 ERROR:
134     DestoryKeyPair(keyPair);
135     keyPair = NULL;
136 EXIT:
137     if (key != NULL) {
138         EVP_PKEY_free(key);
139     }
140     if (ctx != NULL) {
141         EVP_PKEY_CTX_free(ctx);
142     }
143     return keyPair;
144 }
145 
Ed25519Sign(const KeyPair * keyPair,const Buffer * data,Buffer ** sign)146 int32_t Ed25519Sign(const KeyPair *keyPair, const Buffer *data, Buffer **sign)
147 {
148     if (!IsEd25519KeyPairValid(keyPair) || !IsBufferValid(data) || sign == NULL) {
149         LOG_ERROR("invalid params");
150         return RESULT_BAD_PARAM;
151     }
152     int32_t ret = RESULT_GENERAL_ERROR;
153     EVP_PKEY *key = EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, NULL,
154         keyPair->priKey->buf, keyPair->priKey->contentSize);
155     if (key == NULL) {
156         LOG_ERROR("get private key failed");
157         return ret;
158     }
159     EVP_MD_CTX *ctx = EVP_MD_CTX_new();
160     if (ctx == NULL) {
161         LOG_ERROR("get ctx failed");
162         EVP_PKEY_free(key);
163         return ret;
164     }
165     if (EVP_DigestSignInit(ctx, NULL, NULL, NULL, key) != OPENSSL_SUCCESS) {
166         LOG_ERROR("init sign failed");
167         goto EXIT;
168     }
169     *sign = CreateBufferBySize(ED25519_FIX_SIGN_BUFFER_SIZE);
170     if (!IsBufferValid(*sign)) {
171         LOG_ERROR("create buffer failed");
172         goto EXIT;
173     }
174     size_t signSize = (*sign)->maxSize;
175     if (EVP_DigestSign(ctx, (*sign)->buf, &signSize, data->buf, data->contentSize) != OPENSSL_SUCCESS) {
176         LOG_ERROR("sign failed");
177         DestoryBuffer(*sign);
178         *sign = NULL;
179         goto EXIT;
180     }
181     (*sign)->contentSize = signSize;
182     ret = RESULT_SUCCESS;
183 
184 EXIT:
185     EVP_PKEY_free(key);
186     EVP_MD_CTX_free(ctx);
187     return ret;
188 }
189 
Ed25519Verify(const Buffer * pubKey,const Buffer * data,const Buffer * sign)190 int32_t Ed25519Verify(const Buffer *pubKey, const Buffer *data, const Buffer *sign)
191 {
192     if (!CheckBufferWithSize(pubKey, ED25519_FIX_PUBKEY_BUFFER_SIZE) || !IsBufferValid(data) ||
193         !CheckBufferWithSize(sign, ED25519_FIX_SIGN_BUFFER_SIZE)) {
194         LOG_ERROR("bad param");
195         return RESULT_BAD_PARAM;
196     }
197     int32_t ret = RESULT_GENERAL_ERROR;
198     EVP_PKEY *key = EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, NULL, pubKey->buf, pubKey->contentSize);
199     if (key == NULL) {
200         LOG_ERROR("get public key failed");
201         return ret;
202     }
203     EVP_MD_CTX *ctx = EVP_MD_CTX_new();
204     if (ctx == NULL) {
205         LOG_ERROR("get ctx failed");
206         EVP_PKEY_free(key);
207         return ret;
208     }
209     if (EVP_DigestVerifyInit(ctx, NULL, NULL, NULL, key) != OPENSSL_SUCCESS) {
210         LOG_ERROR("init verify failed");
211         goto EXIT;
212     }
213     if (EVP_DigestVerify(ctx, sign->buf, sign->contentSize, data->buf, data->contentSize) != OPENSSL_SUCCESS) {
214         LOG_ERROR("verify failed");
215         goto EXIT;
216     }
217     ret = RESULT_SUCCESS;
218 
219 EXIT:
220     EVP_PKEY_free(key);
221     EVP_MD_CTX_free(ctx);
222     return ret;
223 }
224 
IamHmac(const EVP_MD * alg,const Buffer * hmacKey,const Buffer * data,Buffer * hmac)225 IAM_STATIC int32_t IamHmac(const EVP_MD *alg, const Buffer *hmacKey, const Buffer *data, Buffer *hmac)
226 {
227     if (!IsBufferValid(hmacKey) || hmacKey->contentSize > INT_MAX ||
228         !IsBufferValid(data) || !IsBufferValid(hmac) || hmac->maxSize > UINT_MAX) {
229         LOG_ERROR("bad param");
230         return RESULT_BAD_PARAM;
231     }
232     uint32_t hmacSize = hmac->maxSize;
233     uint8_t *hmacData = HMAC(alg, hmacKey->buf, (int)hmacKey->contentSize, data->buf, data->contentSize,
234         hmac->buf, &hmacSize);
235     if (hmacData == NULL) {
236         LOG_ERROR("hmac failed");
237         return RESULT_GENERAL_ERROR;
238     }
239     hmac->contentSize = hmacSize;
240     return RESULT_SUCCESS;
241 }
242 
HmacSha256(const Buffer * hmacKey,const Buffer * data,Buffer ** hmac)243 int32_t HmacSha256(const Buffer *hmacKey, const Buffer *data, Buffer **hmac)
244 {
245     if (hmac == NULL) {
246         LOG_ERROR("hmac is null");
247         return RESULT_BAD_PARAM;
248     }
249     const EVP_MD *alg = EVP_sha256();
250     if (alg == NULL) {
251         LOG_ERROR("no algo");
252         return RESULT_GENERAL_ERROR;
253     }
254     *hmac = CreateBufferBySize(SHA256_DIGEST_SIZE);
255     if (*hmac == NULL) {
256         LOG_ERROR("create buffer failed");
257         return RESULT_NO_MEMORY;
258     }
259     if (IamHmac(alg, hmacKey, data, *hmac) != RESULT_SUCCESS) {
260         DestoryBuffer(*hmac);
261         *hmac = NULL;
262         LOG_ERROR("hmac failed");
263         return RESULT_GENERAL_ERROR;
264     }
265     return RESULT_SUCCESS;
266 }
267 
SecureRandom(uint8_t * buffer,uint32_t size)268 int32_t SecureRandom(uint8_t *buffer, uint32_t size)
269 {
270     if (buffer == NULL || size > INT_MAX) {
271         LOG_ERROR("bad param");
272         return RESULT_BAD_PARAM;
273     }
274     if (RAND_bytes(buffer, (int)size) != OPENSSL_SUCCESS) {
275         LOG_ERROR("rand failed");
276         return RESULT_GENERAL_ERROR;
277     }
278     return RESULT_SUCCESS;
279 }
280 
CheckAesGcmParam(const AesGcmParam * aesGcmParam)281 IAM_STATIC bool CheckAesGcmParam(const AesGcmParam *aesGcmParam)
282 {
283     if (aesGcmParam == NULL) {
284         LOG_ERROR("get null AesGcmParam");
285         return false;
286     }
287     if (!CheckBufferWithSize(aesGcmParam->key, AES_GCM_256_KEY_SIZE)) {
288         LOG_ERROR("invalid key");
289         return false;
290     }
291     if (!CheckBufferWithSize(aesGcmParam->iv, AES_GCM_IV_SIZE)) {
292         LOG_ERROR("invalid iv");
293         return false;
294     }
295     if (aesGcmParam->aad == NULL) {
296         LOG_INFO("get null aad");
297         return true;
298     }
299     if (!IsBufferValid(aesGcmParam->aad)) {
300         return false;
301     }
302     if (aesGcmParam->aad->contentSize == 0 || aesGcmParam->aad->contentSize > AES_GCM_AAD_MAX_SIZE) {
303         LOG_ERROR("invalid aad");
304         return false;
305     }
306     return true;
307 }
308 
SetAesEncryptParam(EVP_CIPHER_CTX * ctx,const AesGcmParam * aesGcmParam)309 static bool SetAesEncryptParam(EVP_CIPHER_CTX *ctx, const AesGcmParam *aesGcmParam)
310 {
311     if (EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, (unsigned char *)aesGcmParam->key->buf, NULL) !=
312         OPENSSL_SUCCESS) {
313         LOG_ERROR("failed to init ctx");
314         return false;
315     }
316     if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, aesGcmParam->iv->contentSize, NULL) != OPENSSL_SUCCESS) {
317         LOG_ERROR("failed to set iv len");
318         return false;
319     }
320     if (EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, aesGcmParam->iv->buf) != OPENSSL_SUCCESS) {
321         LOG_ERROR("failed to init iv");
322         return false;
323     }
324     if (aesGcmParam->aad != NULL) {
325         int out;
326         if (EVP_EncryptUpdate(ctx, NULL, &out,
327             (unsigned char *)(aesGcmParam->aad->buf), aesGcmParam->aad->contentSize) != OPENSSL_SUCCESS) {
328             LOG_ERROR("failed to update aad");
329             return false;
330         }
331     }
332     if (EVP_CIPHER_CTX_set_padding(ctx, NO_PADDING) != OPENSSL_SUCCESS) {
333         LOG_ERROR("failed to set padding");
334         return false;
335     }
336     return true;
337 }
338 
AesGcmEncrypt(const Buffer * plaintext,const AesGcmParam * aesGcmParam,Buffer ** ciphertext,Buffer ** tag)339 int32_t AesGcmEncrypt(const Buffer *plaintext, const AesGcmParam *aesGcmParam, Buffer **ciphertext, Buffer **tag)
340 {
341     if (!IsBufferValid(plaintext) ||
342         plaintext->contentSize == 0 || plaintext->contentSize > AES_GCM_TEXT_MAX_SIZE ||
343         !CheckAesGcmParam(aesGcmParam) || ciphertext == NULL || tag == NULL) {
344         LOG_ERROR("bad param");
345         return RESULT_BAD_PARAM;
346     }
347     EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
348     (*ciphertext) = CreateBufferBySize(plaintext->contentSize);
349     (*tag) = CreateBufferBySize(AES_GCM_TAG_SIZE);
350     if (ctx == NULL || (*ciphertext) == NULL || (*tag) == NULL) {
351         LOG_ERROR("init fail");
352         goto FAIL;
353     }
354     if (!SetAesEncryptParam(ctx, aesGcmParam)) {
355         LOG_ERROR("SetAesEncryptParam fail");
356         goto FAIL;
357     }
358     int outLen = 0;
359     if (EVP_EncryptUpdate(ctx, (unsigned char *)((*ciphertext)->buf), &outLen,
360         (unsigned char *)plaintext->buf, plaintext->contentSize) != OPENSSL_SUCCESS) {
361         LOG_ERROR("failed to update");
362         goto FAIL;
363     }
364     if (outLen < 0 || (uint32_t)outLen > (*ciphertext)->maxSize) {
365         LOG_ERROR("outLen out of range");
366         goto FAIL;
367     }
368     (*ciphertext)->contentSize = (uint32_t)outLen;
369     if (EVP_EncryptFinal_ex(ctx, NULL, &outLen) != OPENSSL_SUCCESS || outLen != 0) { // no padding no out
370         LOG_ERROR("failed to finish");
371         goto FAIL;
372     }
373     if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, AES_GCM_TAG_SIZE, (*tag)->buf) != OPENSSL_SUCCESS) {
374         LOG_ERROR("failed to get tag");
375         goto FAIL;
376     }
377     (*tag)->contentSize = AES_GCM_TAG_SIZE;
378     EVP_CIPHER_CTX_free(ctx);
379     return RESULT_SUCCESS;
380 FAIL:
381     DestoryBuffer(*tag);
382     *tag = NULL;
383     DestoryBuffer(*ciphertext);
384     *ciphertext = NULL;
385     if (ctx != NULL) {
386         EVP_CIPHER_CTX_free(ctx);
387     }
388     return RESULT_GENERAL_ERROR;
389 }
390 
SetAesDecryptParam(EVP_CIPHER_CTX * ctx,const AesGcmParam * aesGcmParam)391 static bool SetAesDecryptParam(EVP_CIPHER_CTX *ctx, const AesGcmParam *aesGcmParam)
392 {
393     if (EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, (unsigned char *)aesGcmParam->key->buf, NULL) !=
394         OPENSSL_SUCCESS) {
395         LOG_ERROR("failed to init ctx");
396         return false;
397     }
398     if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, aesGcmParam->iv->contentSize, NULL) != OPENSSL_SUCCESS) {
399         LOG_ERROR("failed to set iv len");
400         return false;
401     }
402     if (EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, aesGcmParam->iv->buf) != OPENSSL_SUCCESS) {
403         LOG_ERROR("failed to init iv");
404         return false;
405     }
406     if (aesGcmParam->aad != NULL) {
407         int out;
408         if (EVP_DecryptUpdate(ctx, NULL, &out,
409             (unsigned char *)(aesGcmParam->aad->buf), aesGcmParam->aad->contentSize) != OPENSSL_SUCCESS) {
410             LOG_ERROR("failed to update aad");
411             return false;
412         }
413     }
414     if (EVP_CIPHER_CTX_set_padding(ctx, NO_PADDING) != OPENSSL_SUCCESS) {
415         LOG_ERROR("failed to set padding");
416         return false;
417     }
418     return true;
419 }
420 
AesGcmDecrypt(const Buffer * ciphertext,const AesGcmParam * aesGcmParam,const Buffer * tag,Buffer ** plaintext)421 int32_t AesGcmDecrypt(const Buffer *ciphertext, const AesGcmParam *aesGcmParam, const Buffer *tag, Buffer **plaintext)
422 {
423     if (!IsBufferValid(ciphertext) ||
424         ciphertext->contentSize == 0 || ciphertext->contentSize > AES_GCM_TEXT_MAX_SIZE ||
425         !CheckAesGcmParam(aesGcmParam) || !CheckBufferWithSize(tag, AES_GCM_TAG_SIZE) || plaintext == NULL) {
426         LOG_ERROR("bad param");
427         return RESULT_BAD_PARAM;
428     }
429     EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
430     (*plaintext) = CreateBufferBySize(ciphertext->contentSize);
431     if (ctx == NULL || (*plaintext) == NULL) {
432         LOG_ERROR("init fail");
433         goto FAIL;
434     }
435     if (!SetAesDecryptParam(ctx, aesGcmParam)) {
436         LOG_ERROR("SetAesEncryptParam fail");
437         goto FAIL;
438     }
439     int outLen = 0;
440     if (EVP_DecryptUpdate(ctx, (unsigned char *)((*plaintext)->buf), &outLen,
441         (unsigned char *)ciphertext->buf, ciphertext->contentSize) != OPENSSL_SUCCESS) {
442         LOG_ERROR("failed to update");
443         goto FAIL;
444     }
445     if (outLen < 0 || (uint32_t)outLen > (*plaintext)->maxSize) {
446         LOG_ERROR("outLen out of range");
447         goto FAIL;
448     }
449     (*plaintext)->contentSize = (uint32_t)outLen;
450     if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, AES_GCM_TAG_SIZE, tag->buf) != OPENSSL_SUCCESS) {
451         LOG_ERROR("failed to get tag");
452         goto FAIL;
453     }
454     if (EVP_DecryptFinal_ex(ctx, NULL, &outLen) != OPENSSL_SUCCESS || outLen != 0) { // no padding no out
455         LOG_ERROR("failed to finish");
456         goto FAIL;
457     }
458     EVP_CIPHER_CTX_free(ctx);
459     return RESULT_SUCCESS;
460 FAIL:
461     DestoryBuffer(*plaintext);
462     *plaintext = NULL;
463     if (ctx != NULL) {
464         EVP_CIPHER_CTX_free(ctx);
465     }
466     return RESULT_GENERAL_ERROR;
467 }
468 
Sha256Adaptor(const Buffer * data)469 static Buffer *Sha256Adaptor(const Buffer *data)
470 {
471     if (!IsBufferValid(data)) {
472         LOG_ERROR("bad param");
473         return NULL;
474     }
475     Buffer *result = CreateBufferBySize(SHA256_DIGEST_SIZE);
476     if (!IsBufferValid(result)) {
477         LOG_ERROR("create buffer failed");
478         return NULL;
479     }
480     if (SHA256(data->buf, data->contentSize, result->buf) != result->buf) {
481         LOG_ERROR("SHA256 failed");
482         DestoryBuffer(result);
483         return NULL;
484     }
485     result->contentSize = SHA256_DIGEST_SIZE;
486     return result;
487 }
488 
GetDistributeKey(const Buffer * peerUdid,const Buffer * salt,Buffer ** key)489 int32_t GetDistributeKey(const Buffer *peerUdid, const Buffer *salt, Buffer **key)
490 {
491     if (!IsBufferValid(peerUdid) || !IsBufferValid(salt) || (key == NULL)) {
492         LOG_ERROR("bad param");
493         return RESULT_BAD_PARAM;
494     }
495     Buffer *keyData = CreateBufferBySize(salt->contentSize + USER_AUTH_DISTRIBUTE_DEVICE_KEY_SIZE);
496     if (keyData == NULL) {
497         LOG_ERROR("CreateBufferBySize keyData fail");
498         return RESULT_NO_MEMORY;
499     }
500     if (memcpy_s(keyData->buf, keyData->maxSize, USER_AUTH_DISTRIBUTE_DEVICE_KEY, USER_AUTH_DISTRIBUTE_DEVICE_KEY_SIZE)
501         != EOK) {
502         LOG_ERROR("copy fix tag fail");
503         DestoryBuffer(keyData);
504         return RESULT_NO_MEMORY;
505     }
506     keyData->contentSize += USER_AUTH_DISTRIBUTE_DEVICE_KEY_SIZE;
507     if (memcpy_s(keyData->buf + keyData->contentSize, keyData->maxSize - keyData->contentSize, salt->buf,
508         salt->contentSize) != EOK) {
509         LOG_ERROR("copy salt fail");
510         DestoryBuffer(keyData);
511         return RESULT_NO_MEMORY;
512     }
513     keyData->contentSize += salt->contentSize;
514     *key = Sha256Adaptor(keyData);
515     DestoryBuffer(keyData);
516     if (*key == NULL) {
517         LOG_ERROR("calculate key fail");
518         return RESULT_NO_MEMORY;
519     }
520     return RESULT_SUCCESS;
521 }