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 }