• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "adaptor_algorithm.h"
17 #include <openssl/evp.h>
18 #include <openssl/hmac.h>
19 #include <openssl/rand.h>
20 #include <openssl/kdf.h>
21 #include <openssl/sha.h>
22 #include "securec.h"
23 #include "adaptor_log.h"
24 #include "adaptor_memory.h"
25 #include "buffer.h"
26 #include "defines.h"
27 
28 #define OPENSSL_SUCCESS 1
29 
30 #define ED25519_FIX_PRIKEY_BUFFER_SIZE 32
31 #define ED25519_FIX_PUBKEY_BUFFER_SIZE 32
32 
33 #define SHA512_DIGEST_SIZE 64
34 #define NO_PADDING 0
35 
CreateEd25519KeyPair(void)36 static KeyPair *CreateEd25519KeyPair(void)
37 {
38     KeyPair *keyPair = Malloc(sizeof(KeyPair));
39     if (keyPair == NULL) {
40         LOG_ERROR("no memory for key pair");
41         return NULL;
42     }
43     keyPair->pubKey = CreateBufferBySize(ED25519_FIX_PUBKEY_BUFFER_SIZE);
44     if (keyPair->pubKey == NULL) {
45         LOG_ERROR("no memory for pub key");
46         Free(keyPair);
47         return NULL;
48     }
49     keyPair->priKey = CreateBufferBySize(ED25519_FIX_PRIKEY_BUFFER_SIZE);
50     if (keyPair->priKey == NULL) {
51         LOG_ERROR("no memory for pri key");
52         DestoryBuffer(keyPair->pubKey);
53         Free(keyPair);
54         return NULL;
55     }
56     return keyPair;
57 }
58 
DestoryKeyPair(KeyPair * keyPair)59 void DestoryKeyPair(KeyPair *keyPair)
60 {
61     if (keyPair == NULL) {
62         return;
63     }
64     if (keyPair->pubKey != NULL) {
65         DestoryBuffer(keyPair->pubKey);
66     }
67     if (keyPair->priKey != NULL) {
68         DestoryBuffer(keyPair->priKey);
69     }
70     Free(keyPair);
71 }
72 
IsEd25519KeyPairValid(const KeyPair * keyPair)73 bool IsEd25519KeyPairValid(const KeyPair *keyPair)
74 {
75     if (keyPair == NULL) {
76         LOG_ERROR("invalid key pair");
77         return false;
78     }
79     if (!CheckBufferWithSize(keyPair->pubKey, ED25519_FIX_PUBKEY_BUFFER_SIZE)) {
80         LOG_ERROR("invalid pub key");
81         return false;
82     }
83     if (!CheckBufferWithSize(keyPair->priKey, ED25519_FIX_PRIKEY_BUFFER_SIZE)) {
84         LOG_ERROR("invalid pri key");
85         return false;
86     }
87     return true;
88 }
89 
GenerateEd25519KeyPair(void)90 KeyPair *GenerateEd25519KeyPair(void)
91 {
92     KeyPair *keyPair = CreateEd25519KeyPair();
93     if (keyPair == NULL) {
94         LOG_ERROR("create key pair fail");
95         return NULL;
96     }
97     EVP_PKEY *key = NULL;
98     EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_ED25519, NULL);
99     if (ctx == NULL) {
100         LOG_ERROR("new ctx fail");
101         goto ERROR;
102     }
103     if (EVP_PKEY_keygen_init(ctx) != OPENSSL_SUCCESS) {
104         LOG_ERROR("init ctx fail");
105         goto ERROR;
106     }
107     if (EVP_PKEY_keygen(ctx, &key) != OPENSSL_SUCCESS) {
108         LOG_ERROR("generate key fail");
109         goto ERROR;
110     }
111     size_t pubKeySize = keyPair->pubKey->maxSize;
112     if (EVP_PKEY_get_raw_public_key(key, keyPair->pubKey->buf, &pubKeySize) != OPENSSL_SUCCESS) {
113         LOG_ERROR("get pub key fail");
114         goto ERROR;
115     }
116     keyPair->pubKey->contentSize = pubKeySize;
117     size_t priKeySize = keyPair->priKey->maxSize;
118     if (EVP_PKEY_get_raw_private_key(key, keyPair->priKey->buf, &priKeySize) != OPENSSL_SUCCESS) {
119         LOG_ERROR("get pri key fail");
120         goto ERROR;
121     }
122     keyPair->priKey->contentSize = priKeySize;
123     goto EXIT;
124 
125 ERROR:
126     DestoryKeyPair(keyPair);
127     keyPair = NULL;
128 EXIT:
129     if (key != NULL) {
130         EVP_PKEY_free(key);
131     }
132     if (ctx != NULL) {
133         EVP_PKEY_CTX_free(ctx);
134     }
135     return keyPair;
136 }
137 
Ed25519Sign(const KeyPair * keyPair,const Buffer * data,Buffer ** sign)138 int32_t Ed25519Sign(const KeyPair *keyPair, const Buffer *data, Buffer **sign)
139 {
140     if (!IsEd25519KeyPairValid(keyPair) || !IsBufferValid(data) || sign == NULL) {
141         LOG_ERROR("bad param");
142         return RESULT_BAD_PARAM;
143     }
144     int32_t ret = RESULT_GENERAL_ERROR;
145     EVP_PKEY *key = EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, NULL,
146         keyPair->priKey->buf, keyPair->priKey->contentSize);
147     if (key == NULL) {
148         LOG_ERROR("get pri key fail");
149         return ret;
150     }
151     EVP_MD_CTX *ctx = EVP_MD_CTX_new();
152     if (ctx == NULL) {
153         LOG_ERROR("get ctx fail");
154         EVP_PKEY_free(key);
155         return ret;
156     }
157     if (EVP_DigestSignInit(ctx, NULL, NULL, NULL, key) != OPENSSL_SUCCESS) {
158         LOG_ERROR("init sign fail");
159         goto EXIT;
160     }
161     *sign = CreateBufferBySize(ED25519_FIX_SIGN_BUFFER_SIZE);
162     if (!IsBufferValid(*sign)) {
163         LOG_ERROR("create buffer fail");
164         goto EXIT;
165     }
166     size_t signSize = (*sign)->maxSize;
167     if (EVP_DigestSign(ctx, (*sign)->buf, &signSize, data->buf, data->contentSize) != OPENSSL_SUCCESS) {
168         LOG_ERROR("sign fail");
169         DestoryBuffer(*sign);
170         *sign = NULL;
171         goto EXIT;
172     }
173     (*sign)->contentSize = signSize;
174     ret = RESULT_SUCCESS;
175 
176 EXIT:
177     EVP_PKEY_free(key);
178     EVP_MD_CTX_free(ctx);
179     return ret;
180 }
181 
Ed25519Verify(const Buffer * pubKey,const Buffer * data,const Buffer * sign)182 int32_t Ed25519Verify(const Buffer *pubKey, const Buffer *data, const Buffer *sign)
183 {
184     if (!CheckBufferWithSize(pubKey, ED25519_FIX_PUBKEY_BUFFER_SIZE) || !IsBufferValid(data) ||
185         !CheckBufferWithSize(sign, ED25519_FIX_SIGN_BUFFER_SIZE)) {
186         LOG_ERROR("bad param");
187         return RESULT_BAD_PARAM;
188     }
189     int32_t ret = RESULT_GENERAL_ERROR;
190     EVP_PKEY *key = EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, NULL, pubKey->buf, pubKey->contentSize);
191     if (key == NULL) {
192         LOG_ERROR("get pub key fail");
193         return ret;
194     }
195     EVP_MD_CTX *ctx = EVP_MD_CTX_new();
196     if (ctx == NULL) {
197         LOG_ERROR("get ctx fail");
198         EVP_PKEY_free(key);
199         return ret;
200     }
201     if (EVP_DigestVerifyInit(ctx, NULL, NULL, NULL, key) != OPENSSL_SUCCESS) {
202         LOG_ERROR("init verify fail");
203         goto EXIT;
204     }
205     if (EVP_DigestVerify(ctx, sign->buf, sign->contentSize, data->buf, data->contentSize) != OPENSSL_SUCCESS) {
206         LOG_ERROR("verify fail");
207         goto EXIT;
208     }
209     ret = RESULT_SUCCESS;
210 
211 EXIT:
212     EVP_PKEY_free(key);
213     EVP_MD_CTX_free(ctx);
214     return ret;
215 }
216 
IamHmac(const EVP_MD * alg,const Buffer * hmacKey,const Buffer * data,Buffer * hmac)217 static int32_t IamHmac(const EVP_MD *alg,
218     const Buffer *hmacKey, const Buffer *data, Buffer *hmac)
219 {
220     if (!IsBufferValid(hmacKey) || hmacKey->contentSize > INT_MAX ||
221         !IsBufferValid(data) || !IsBufferValid(hmac) || hmac->maxSize > UINT_MAX) {
222         LOG_ERROR("bad param");
223         return RESULT_BAD_PARAM;
224     }
225     unsigned int hmacSize = hmac->maxSize;
226     uint8_t *hmacData = HMAC(alg, hmacKey->buf, (int)hmacKey->contentSize, data->buf, data->contentSize,
227         hmac->buf, &hmacSize);
228     if (hmacData == NULL) {
229         LOG_ERROR("hmac fail");
230         return RESULT_GENERAL_ERROR;
231     }
232     hmac->contentSize = hmacSize;
233     return RESULT_SUCCESS;
234 }
235 
HmacSha256(const Buffer * hmacKey,const Buffer * data,Buffer ** hmac)236 int32_t HmacSha256(const Buffer *hmacKey, const Buffer *data, Buffer **hmac)
237 {
238     const EVP_MD *alg = EVP_sha256();
239     if (alg == NULL) {
240         LOG_ERROR("no algo");
241         return RESULT_GENERAL_ERROR;
242     }
243     *hmac = CreateBufferBySize(SHA256_DIGEST_SIZE);
244     if (*hmac == NULL) {
245         LOG_ERROR("create buffer fail");
246         return RESULT_NO_MEMORY;
247     }
248     if (IamHmac(alg, hmacKey, data, *hmac) != RESULT_SUCCESS) {
249         DestoryBuffer(*hmac);
250         *hmac = NULL;
251         LOG_ERROR("hmac fail");
252         return RESULT_GENERAL_ERROR;
253     }
254     return RESULT_SUCCESS;
255 }
256 
HmacSha512(const Buffer * hmacKey,const Buffer * data,Buffer ** hmac)257 int32_t HmacSha512(const Buffer *hmacKey, const Buffer *data, Buffer **hmac)
258 {
259     const EVP_MD *alg = EVP_sha512();
260     if (alg == NULL) {
261         LOG_ERROR("no algo");
262         return RESULT_GENERAL_ERROR;
263     }
264     *hmac = CreateBufferBySize(SHA512_DIGEST_SIZE);
265     if (*hmac == NULL) {
266         LOG_ERROR("create buffer fail");
267         return RESULT_NO_MEMORY;
268     }
269     if (IamHmac(alg, hmacKey, data, *hmac) != RESULT_SUCCESS) {
270         DestoryBuffer(*hmac);
271         *hmac = NULL;
272         LOG_ERROR("hmac fail");
273         return RESULT_GENERAL_ERROR;
274     }
275     return RESULT_SUCCESS;
276 }
277 
SecureRandom(uint8_t * buffer,uint32_t size)278 int32_t SecureRandom(uint8_t *buffer, uint32_t size)
279 {
280     if (buffer == NULL || size > INT_MAX) {
281         LOG_ERROR("bad param");
282         return RESULT_BAD_PARAM;
283     }
284     if (RAND_bytes(buffer, (int)size) != OPENSSL_SUCCESS) {
285         LOG_ERROR("rand fail");
286         return RESULT_GENERAL_ERROR;
287     }
288     return RESULT_SUCCESS;
289 }
290 
SetAesEncryptVi(EVP_CIPHER_CTX * ctx,const Buffer * vi)291 static int32_t SetAesEncryptVi(EVP_CIPHER_CTX *ctx, const Buffer *vi)
292 {
293     if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, vi->contentSize, NULL) != OPENSSL_SUCCESS) {
294         LOG_ERROR("failed to set vi len");
295         return RESULT_GENERAL_ERROR;
296     }
297     if (EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, vi->buf) != OPENSSL_SUCCESS) {
298         LOG_ERROR("failed to init vi");
299         return RESULT_GENERAL_ERROR;
300     }
301     return RESULT_SUCCESS;
302 }
303 
CreateCiphertext(EVP_CIPHER_CTX * ctx,const Buffer * plaintext)304 static Buffer *CreateCiphertext(EVP_CIPHER_CTX *ctx, const Buffer *plaintext)
305 {
306     Buffer *ciphertext = CreateBufferBySize(plaintext->contentSize);
307     if (!IsBufferValid(ciphertext)) {
308         LOG_ERROR("ciphertext is invalid");
309         return NULL;
310     }
311     if (EVP_CIPHER_CTX_set_padding(ctx, NO_PADDING) != OPENSSL_SUCCESS) {
312         LOG_ERROR("failed to set padding");
313         DestoryBuffer(ciphertext);
314         return NULL;
315     }
316     int32_t outLen = 0;
317     if (EVP_EncryptUpdate(ctx, (unsigned char *)(ciphertext->buf), &outLen,
318         (unsigned char *)plaintext->buf, plaintext->contentSize) != OPENSSL_SUCCESS) {
319         LOG_ERROR("failed to update");
320         DestoryBuffer(ciphertext);
321         return NULL;
322     }
323     if (outLen < 0) {
324         LOG_ERROR("outLen out of range");
325         DestoryBuffer(ciphertext);
326         return NULL;
327     }
328     ciphertext->contentSize = (uint32_t)outLen;
329     if (ciphertext->maxSize < ciphertext->contentSize) {
330         LOG_ERROR("memory overflow occurred, please check");
331         DestoryBuffer(ciphertext);
332         return NULL;
333     }
334     if (EVP_EncryptFinal_ex(ctx, NULL, &outLen) != OPENSSL_SUCCESS || outLen != 0) { // no padding no out
335         LOG_ERROR("failed to finish");
336         DestoryBuffer(ciphertext);
337         return NULL;
338     }
339     return ciphertext;
340 }
341 
SpliceOutput(const Buffer * vi,const Buffer * tag,const Buffer * ciphertext,Buffer * cipherInfo)342 static int32_t SpliceOutput(const Buffer *vi, const Buffer *tag, const Buffer *ciphertext, Buffer *cipherInfo)
343 {
344     if (cipherInfo->contentSize != 0) {
345         LOG_ERROR("cipherInfo is not 0 bytes");
346         return RESULT_BAD_PARAM;
347     }
348     if (cipherInfo->maxSize < ciphertext->contentSize ||
349         cipherInfo->maxSize - ciphertext->contentSize < vi->contentSize + tag->contentSize) {
350         LOG_ERROR("bad param");
351         return RESULT_BAD_PARAM;
352     }
353     if (memcpy_s(cipherInfo->buf, cipherInfo->maxSize, vi->buf, vi->contentSize) != EOK) {
354         LOG_ERROR("failed to copy vi");
355         return RESULT_BAD_COPY;
356     }
357     cipherInfo->contentSize += vi->contentSize;
358     if (memcpy_s(cipherInfo->buf + cipherInfo->contentSize, cipherInfo->maxSize - cipherInfo->contentSize,
359         tag->buf, tag->contentSize) != EOK) {
360         LOG_ERROR("failed to copy tag");
361         return RESULT_BAD_COPY;
362     }
363     cipherInfo->contentSize += tag->contentSize;
364     if (memcpy_s(cipherInfo->buf + cipherInfo->contentSize, cipherInfo->maxSize - cipherInfo->contentSize,
365         ciphertext->buf, ciphertext->contentSize) != EOK) {
366         LOG_ERROR("failed to copy ciphertext");
367         return RESULT_BAD_COPY;
368     }
369     cipherInfo->contentSize += ciphertext->contentSize;
370     return RESULT_SUCCESS;
371 }
372 
DoAes256GcmEncryptNoPadding(const Buffer * plaintext,const Buffer * key,Buffer * cipherInfo)373 static int32_t DoAes256GcmEncryptNoPadding(const Buffer *plaintext, const Buffer *key, Buffer *cipherInfo)
374 {
375     EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
376     Buffer *vi = CreateBufferBySize(AES_GCM_VI_SIZE);
377     Buffer *tag = CreateBufferBySize(AES_GCM_TAG_SIZE);
378     Buffer *ciphertext = NULL;
379     if (ctx == NULL || !IsBufferValid(vi) || !IsBufferValid(tag)) {
380         LOG_ERROR("failed to init");
381         goto FAIL;
382     }
383     vi->contentSize = AES_GCM_VI_SIZE;
384     if (SecureRandom(vi->buf, vi->contentSize) != RESULT_SUCCESS ||
385         EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, (unsigned char *)key->buf, NULL) != OPENSSL_SUCCESS ||
386         SetAesEncryptVi(ctx, vi) != RESULT_SUCCESS) {
387         LOG_ERROR("failed to call algorithm interface");
388         goto FAIL;
389     }
390     ciphertext = CreateCiphertext(ctx, plaintext);
391     if (!IsBufferValid(ciphertext)) {
392         LOG_ERROR("failed to create ciphertext");
393         goto FAIL;
394     }
395     if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, AES_GCM_TAG_SIZE, tag->buf) != OPENSSL_SUCCESS) {
396         LOG_ERROR("failed to get tag");
397         goto FAIL;
398     }
399     tag->contentSize = AES_GCM_TAG_SIZE;
400     if (SpliceOutput(vi, tag, ciphertext, cipherInfo) != RESULT_SUCCESS) {
401         LOG_ERROR("failed to splice");
402         goto FAIL;
403     }
404     DestoryBuffer(vi);
405     DestoryBuffer(ciphertext);
406     DestoryBuffer(tag);
407     EVP_CIPHER_CTX_free(ctx);
408     return RESULT_SUCCESS;
409 FAIL:
410     DestoryBuffer(vi);
411     DestoryBuffer(ciphertext);
412     DestoryBuffer(tag);
413     if (ctx != NULL) {
414         EVP_CIPHER_CTX_free(ctx);
415     }
416     return RESULT_GENERAL_ERROR;
417 }
418 
419 // Return is 12 byte VI, 16 byte tag, and the AES ciphertext corresponding to plaintext, is used to parse plaintext.
Aes256GcmEncryptNoPadding(const Buffer * plaintext,const Buffer * key)420 Buffer *Aes256GcmEncryptNoPadding(const Buffer *plaintext, const Buffer *key)
421 {
422     if (!IsBufferValid(plaintext) || plaintext->contentSize == 0 || plaintext->contentSize > CIPHER_INFO_MAX_SIZE ||
423         plaintext->contentSize % AES256_BLOCK_SIZE != 0 || !IsBufferValid(key) || key->contentSize != AES256_KEY_SIZE) {
424         LOG_ERROR("bad param");
425         return NULL;
426     }
427     Buffer *cipherInfo = CreateBufferBySize(CIPHER_INFO_MAX_SIZE);
428     if (!IsBufferValid(cipherInfo)) {
429         LOG_ERROR("failed to create cipherInfo");
430         return NULL;
431     }
432     if (DoAes256GcmEncryptNoPadding(plaintext, key, cipherInfo) != RESULT_SUCCESS) {
433         LOG_ERROR("failed to encrypt");
434         DestoryBuffer(cipherInfo);
435         return NULL;
436     }
437     return cipherInfo;
438 }
439 
SplitInput(const Buffer * cipherInfo,Buffer * vi,Buffer * tag,Buffer * ciphertext)440 static int32_t SplitInput(const Buffer *cipherInfo, Buffer *vi, Buffer *tag, Buffer *ciphertext)
441 {
442     if (cipherInfo->contentSize <= AES_GCM_VI_SIZE + AES_GCM_TAG_SIZE ||
443         cipherInfo->contentSize - (AES_GCM_VI_SIZE + AES_GCM_TAG_SIZE) > ciphertext->maxSize) {
444         LOG_ERROR("bad param");
445         return RESULT_BAD_PARAM;
446     }
447     uint32_t offset = 0;
448     if (memcpy_s(vi->buf, vi->maxSize, cipherInfo->buf, AES_GCM_VI_SIZE) != EOK) {
449         LOG_ERROR("failed to copy vi");
450         return RESULT_BAD_COPY;
451     }
452     vi->contentSize = AES_GCM_VI_SIZE;
453     offset += AES_GCM_VI_SIZE;
454     if (memcpy_s(tag->buf, tag->maxSize, cipherInfo->buf + offset, AES_GCM_TAG_SIZE) != EOK) {
455         LOG_ERROR("failed to copy tag");
456         return RESULT_BAD_COPY;
457     }
458     tag->contentSize = AES_GCM_TAG_SIZE;
459     offset += AES_GCM_TAG_SIZE;
460     if (memcpy_s(ciphertext->buf, ciphertext->maxSize,
461         cipherInfo->buf + offset, cipherInfo->contentSize - offset) != EOK) {
462         LOG_ERROR("failed to copy ciphertext");
463         return RESULT_BAD_COPY;
464     }
465     ciphertext->contentSize = cipherInfo->contentSize - offset;
466     return RESULT_SUCCESS;
467 }
468 
SetAesDecryptVi(EVP_CIPHER_CTX * ctx,const Buffer * vi)469 static int32_t SetAesDecryptVi(EVP_CIPHER_CTX *ctx, const Buffer *vi)
470 {
471     if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, vi->contentSize, NULL) != OPENSSL_SUCCESS) {
472         LOG_ERROR("failed to set vi len");
473         return RESULT_GENERAL_ERROR;
474     }
475     if (EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, vi->buf) != OPENSSL_SUCCESS) {
476         LOG_ERROR("failed to init vi");
477         return RESULT_GENERAL_ERROR;
478     }
479     return RESULT_SUCCESS;
480 }
481 
SetPlaintext(EVP_CIPHER_CTX * ctx,const Buffer * ciphertext,const Buffer * tag,Buffer * plaintext)482 static int32_t SetPlaintext(EVP_CIPHER_CTX *ctx, const Buffer *ciphertext, const Buffer *tag, Buffer *plaintext)
483 {
484     if (EVP_CIPHER_CTX_set_padding(ctx, NO_PADDING) != OPENSSL_SUCCESS) {
485         LOG_ERROR("failed to set padding");
486         return RESULT_GENERAL_ERROR;
487     }
488     int32_t outLen = 0;
489     if (EVP_DecryptUpdate(ctx, (unsigned char *)(plaintext->buf), &outLen,
490         (unsigned char *)ciphertext->buf, ciphertext->contentSize) != OPENSSL_SUCCESS) {
491         LOG_ERROR("failed to update");
492         return RESULT_GENERAL_ERROR;
493     }
494     if (outLen < 0) {
495         LOG_ERROR("outLen out of range");
496         return RESULT_GENERAL_ERROR;
497     }
498     plaintext->contentSize = (uint32_t)outLen;
499     if (plaintext->maxSize < plaintext->contentSize) {
500         LOG_ERROR("memory overflow occurred, please check");
501         return RESULT_GENERAL_ERROR;
502     }
503     if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, tag->contentSize, tag->buf) != OPENSSL_SUCCESS) {
504         LOG_ERROR("failed to set tag");
505         return RESULT_GENERAL_ERROR;
506     }
507     if (EVP_DecryptFinal_ex(ctx, NULL, &outLen) != OPENSSL_SUCCESS || outLen != 0) { // no padding no out
508         LOG_ERROR("failed to finish");
509         return RESULT_GENERAL_ERROR;
510     }
511     return RESULT_SUCCESS;
512 }
513 
DoAes256GcmDecryptNoPadding(const Buffer * cipherInfo,const Buffer * key,Buffer * plaintext)514 static int32_t DoAes256GcmDecryptNoPadding(const Buffer *cipherInfo, const Buffer *key, Buffer *plaintext)
515 {
516     EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
517     Buffer *vi = CreateBufferBySize(AES_GCM_VI_SIZE);
518     Buffer *tag = CreateBufferBySize(AES_GCM_TAG_SIZE);
519     Buffer *ciphertext = CreateBufferBySize(cipherInfo->contentSize);
520     if (ctx == NULL || !IsBufferValid(vi) || !IsBufferValid(tag) || !IsBufferValid(ciphertext)) {
521         LOG_ERROR("failed to init");
522         goto FAIL;
523     }
524     if (SplitInput(cipherInfo, vi, tag, ciphertext) != RESULT_SUCCESS ||
525         EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, (unsigned char *)key->buf, NULL) != OPENSSL_SUCCESS ||
526         SetAesDecryptVi(ctx, vi) != RESULT_SUCCESS ||
527         SetPlaintext(ctx, ciphertext, tag, plaintext) != RESULT_SUCCESS) {
528         LOG_ERROR("failed to call algorithm interface");
529         goto FAIL;
530     }
531     DestoryBuffer(vi);
532     DestoryBuffer(ciphertext);
533     DestoryBuffer(tag);
534     EVP_CIPHER_CTX_free(ctx);
535     return RESULT_SUCCESS;
536 FAIL:
537     DestoryBuffer(vi);
538     DestoryBuffer(ciphertext);
539     DestoryBuffer(tag);
540     if (ctx != NULL) {
541         EVP_CIPHER_CTX_free(ctx);
542     }
543     return RESULT_GENERAL_ERROR;
544 }
545 
Aes256GcmDecryptNoPadding(const Buffer * cipherInfo,const Buffer * key)546 Buffer *Aes256GcmDecryptNoPadding(const Buffer *cipherInfo, const Buffer *key)
547 {
548     if (!IsBufferValid(cipherInfo) || cipherInfo->contentSize <= AES_GCM_VI_SIZE + AES_GCM_TAG_SIZE ||
549         cipherInfo->contentSize > CIPHER_INFO_MAX_SIZE || !IsBufferValid(key) || key->contentSize != AES256_KEY_SIZE) {
550         LOG_ERROR("bad param");
551         return NULL;
552     }
553     Buffer *plaintext = CreateBufferBySize(cipherInfo->contentSize);
554     if (!IsBufferValid(plaintext)) {
555         LOG_ERROR("failed to create cipherInfo");
556         return NULL;
557     }
558     if (DoAes256GcmDecryptNoPadding(cipherInfo, key, plaintext) != RESULT_SUCCESS) {
559         LOG_ERROR("failed to do decrypt");
560         DestoryBuffer(plaintext);
561         return NULL;
562     }
563     return plaintext;
564 }
565 
566 // Here is the piling code. The real implementation needs to call the security interface.
DeriveDeviceKey(const Buffer * pinData,const Buffer * secret)567 Buffer *DeriveDeviceKey(const Buffer *pinData, const Buffer *secret)
568 {
569     if (!IsBufferValid(secret) || secret->contentSize != SECRET_SIZE || !IsBufferValid(pinData)) {
570         LOG_ERROR("bad param");
571         return NULL;
572     }
573     return CopyBuffer(secret);
574 }
575 
Hkdf(const Buffer * salt,const Buffer * rootKey)576 Buffer *Hkdf(const Buffer *salt, const Buffer *rootKey)
577 {
578     if (!IsBufferValid(salt) || salt->contentSize != HKDF_SALT_SIZE ||
579         !IsBufferValid(rootKey) || rootKey->contentSize != HKDF_KEY_SIZE) {
580         LOG_ERROR("bad param");
581         return NULL;
582     }
583     EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL);
584     if (ctx == NULL) {
585         LOG_ERROR("pctx is null");
586         return NULL;
587     }
588     Buffer *key = CreateBufferBySize(SHA256_DIGEST_SIZE);
589     if (!IsBufferValid(key)) {
590         LOG_ERROR("failed to create buffer");
591         EVP_PKEY_CTX_free(ctx);
592         return NULL;
593     }
594     size_t outLen = SHA256_DIGEST_SIZE;
595     if (EVP_PKEY_derive_init(ctx) != OPENSSL_SUCCESS ||
596         EVP_PKEY_CTX_set_hkdf_md(ctx, EVP_sha256()) != OPENSSL_SUCCESS ||
597         EVP_PKEY_CTX_set1_hkdf_salt(ctx, salt->buf, salt->contentSize) != OPENSSL_SUCCESS ||
598         EVP_PKEY_CTX_set1_hkdf_key(ctx, rootKey->buf, rootKey->contentSize) != OPENSSL_SUCCESS ||
599         EVP_PKEY_derive(ctx, key->buf, &outLen) != OPENSSL_SUCCESS ||
600         outLen > key->maxSize) {
601         LOG_ERROR("failed to call algorithm interface");
602         DestoryBuffer(key);
603         EVP_PKEY_CTX_free(ctx);
604         return NULL;
605     }
606     key->contentSize = outLen;
607     EVP_PKEY_CTX_free(ctx);
608     return key;
609 }
610 
Sha256Adaptor(const Buffer * data)611 Buffer *Sha256Adaptor(const Buffer *data)
612 {
613     if (!IsBufferValid(data)) {
614         LOG_ERROR("bad param");
615         return NULL;
616     }
617     Buffer *result = CreateBufferBySize(SHA256_DIGEST_SIZE);
618     if (!IsBufferValid(result)) {
619         LOG_ERROR("failed to create buffer");
620         return NULL;
621     }
622     if (SHA256(data->buf, data->contentSize, result->buf) != result->buf) {
623         LOG_ERROR("failed to do sha256");
624         DestoryBuffer(result);
625         return NULL;
626     }
627     result->contentSize = SHA256_DIGEST_SIZE;
628     return result;
629 }