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 <gtest/gtest.h>
17 #include <fstream>
18 #include <iostream>
19 #include "crypto_common.h"
20 #include "crypto_sym_cipher.h"
21 #include "sym_key.h"
22 #include "log.h"
23 #include "memory.h"
24 #include "memory_mock.h"
25 #include "securec.h"
26 
27 using namespace std;
28 using namespace testing::ext;
29 
30 static constexpr int32_t GCM_TAG_LEN = 16;
31 
32 namespace {
33 class NativeSymCipherTest : public testing::Test {
34 public:
35     static void SetUpTestCase();
36     static void TearDownTestCase();
37     void SetUp();
38     void TearDown();
39 };
40 
SetUpTestCase()41 void NativeSymCipherTest::SetUpTestCase() {}
TearDownTestCase()42 void NativeSymCipherTest::TearDownTestCase() {}
43 
SetUp()44 void NativeSymCipherTest::SetUp() // add init here, this will be called before test.
45 {
46 }
47 
TearDown()48 void NativeSymCipherTest::TearDown() // add destroy here, this will be called when test case done.
49 {
50 }
51 
AesEncrypt(OH_CryptoSymCipher * cipher,OH_CryptoSymKey * key,OH_CryptoSymCipherParams * params,uint8_t * cipherText,int * cipherTextLen)52 OH_Crypto_ErrCode AesEncrypt(OH_CryptoSymCipher *cipher, OH_CryptoSymKey *key, OH_CryptoSymCipherParams *params,
53     uint8_t *cipherText, int *cipherTextLen)
54 {
55     uint8_t plainText[] = "this is test!";
56     Crypto_DataBlob input = {.data = reinterpret_cast<uint8_t *>(plainText), .len = 13};
57     Crypto_DataBlob output = {};
58     int32_t maxLen = *cipherTextLen;
59     OH_Crypto_ErrCode ret = OH_CryptoSymCipher_Init(cipher, CRYPTO_ENCRYPT_MODE, key, params);
60     if (ret != CRYPTO_SUCCESS) {
61         LOGE("init failed! %d", ret);
62         return ret;
63     }
64 
65     ret = OH_CryptoSymCipher_Update(cipher, &input, &output);
66     if (ret != CRYPTO_SUCCESS) {
67         LOGE("update failed!");
68         return ret;
69     }
70     *cipherTextLen = output.len;
71     if (output.data != nullptr) {
72         if (memcpy_s(cipherText, maxLen, output.data, output.len) != EOK) {
73             OH_Crypto_FreeDataBlob(&output);
74             return CRYPTO_INVALID_PARAMS;
75         }
76         OH_Crypto_FreeDataBlob(&output);
77     }
78 
79     ret = OH_CryptoSymCipher_Final(cipher, nullptr, &output);
80     if (ret != CRYPTO_SUCCESS) {
81         LOGE("doFinal failed!");
82         return ret;
83     }
84     if (output.data != nullptr) {
85         if (memcpy_s(cipherText + *cipherTextLen, maxLen - *cipherTextLen, output.data, output.len) != EOK) {
86             OH_Crypto_FreeDataBlob(&output);
87             return CRYPTO_INVALID_PARAMS;
88         }
89         *cipherTextLen += output.len;
90         OH_Crypto_FreeDataBlob(&output);
91     }
92 
93     return CRYPTO_SUCCESS;
94 }
95 
AesDecrypt(OH_CryptoSymCipher * cipher,OH_CryptoSymKey * key,OH_CryptoSymCipherParams * params,uint8_t * cipherText,int cipherTextLen)96 OH_Crypto_ErrCode AesDecrypt(OH_CryptoSymCipher *cipher, OH_CryptoSymKey *key, OH_CryptoSymCipherParams *params,
97     uint8_t *cipherText, int cipherTextLen)
98 {
99     uint8_t plainText[] = "this is test!";
100     Crypto_DataBlob input = {.data = reinterpret_cast<uint8_t *>(cipherText), .len = cipherTextLen};
101     Crypto_DataBlob output = {};
102     int32_t maxLen = cipherTextLen;
103     OH_Crypto_ErrCode ret = OH_CryptoSymCipher_Init(cipher, CRYPTO_DECRYPT_MODE, key, params);
104     if (ret != CRYPTO_SUCCESS) {
105         LOGE("init failed! %d", ret);
106         return ret;
107     }
108 
109     ret = OH_CryptoSymCipher_Update(cipher, &input, &output);
110     if (ret != CRYPTO_SUCCESS) {
111         LOGE("update failed!");
112         return ret;
113     }
114     cipherTextLen = output.len;
115     if (output.data != nullptr) {
116         if (memcpy_s(cipherText, maxLen, output.data, output.len) != EOK) {
117             OH_Crypto_FreeDataBlob(&output);
118             return CRYPTO_INVALID_PARAMS;
119         }
120         OH_Crypto_FreeDataBlob(&output);
121     }
122 
123     ret = OH_CryptoSymCipher_Final(cipher, nullptr, &output);
124     if (ret != CRYPTO_SUCCESS) {
125         LOGE("doFinal failed!");
126         return ret;
127     }
128     if (output.data != nullptr) {
129         if (memcpy_s(cipherText + cipherTextLen, maxLen - cipherTextLen, output.data, output.len) != EOK) {
130             OH_Crypto_FreeDataBlob(&output);
131             return CRYPTO_INVALID_PARAMS;
132         }
133         cipherTextLen += output.len;
134         OH_Crypto_FreeDataBlob(&output);
135     }
136 
137     if (cipherTextLen != sizeof(plainText) - 1) {
138         return CRYPTO_INVALID_PARAMS;
139     }
140     if (memcmp(cipherText, plainText, cipherTextLen) != 0) {
141         return CRYPTO_INVALID_PARAMS;
142     }
143     return CRYPTO_SUCCESS;
144 }
145 
146 HWTEST_F(NativeSymCipherTest, NativeSymCipherTest001, TestSize.Level0)
147 {
148     uint8_t aad[8] = {0};
149     uint8_t tag[16] = {0};
150     uint8_t iv[12] = {0};
151     uint8_t cipherText[128] = {0};
152     int cipherTextLen = 128;
153     Crypto_DataBlob ivData = { .data = iv, .len = sizeof(iv) };
154     Crypto_DataBlob aadData = { .data = aad, .len = sizeof(aad) };
155     Crypto_DataBlob tagData = { .data = tag, .len = sizeof(tag) };
156     OH_CryptoSymCipherParams *params = nullptr;
157     OH_Crypto_ErrCode ret = OH_CryptoSymCipherParams_Create(&params);
158     EXPECT_EQ(ret, CRYPTO_SUCCESS);
159 
160     ret = OH_CryptoSymCipherParams_SetParam(params, CRYPTO_IV_DATABLOB, &ivData);
161     EXPECT_EQ(ret, CRYPTO_SUCCESS);
162     ret = OH_CryptoSymCipherParams_SetParam(params, CRYPTO_AAD_DATABLOB, &aadData);
163     EXPECT_EQ(ret, CRYPTO_SUCCESS);
164     ret = OH_CryptoSymCipherParams_SetParam(params, CRYPTO_TAG_DATABLOB, &tagData);
165     EXPECT_EQ(ret, CRYPTO_SUCCESS);
166 
167     OH_CryptoSymKeyGenerator *ctx = nullptr;
168     OH_CryptoSymKey *symKey = nullptr;
169     ret = OH_CryptoSymKeyGenerator_Create("AES128", &ctx);
170     EXPECT_EQ(ret, CRYPTO_SUCCESS);
171     ret = OH_CryptoSymKeyGenerator_Generate(ctx, &symKey);
172     EXPECT_EQ(ret, CRYPTO_SUCCESS);
173 
174     OH_CryptoSymCipher *cipher = nullptr;
175     ret = OH_CryptoSymCipher_Create("AES128|GCM|PKCS7", &cipher);
176     EXPECT_EQ(ret, CRYPTO_SUCCESS);
177 
178     ret = AesEncrypt(cipher, symKey, params, cipherText, &cipherTextLen);
179     EXPECT_EQ(ret, CRYPTO_SUCCESS);
180 
181     (void)memcpy_s(tagData.data, GCM_TAG_LEN, cipherText + cipherTextLen - GCM_TAG_LEN, GCM_TAG_LEN);
182     cipherTextLen -= GCM_TAG_LEN;
183     ret = OH_CryptoSymCipherParams_SetParam(params, CRYPTO_TAG_DATABLOB, &tagData);
184     EXPECT_EQ(ret, CRYPTO_SUCCESS);
185     ret = AesDecrypt(cipher, symKey, params, cipherText, cipherTextLen);
186     EXPECT_EQ(ret, CRYPTO_SUCCESS);
187 
188     OH_CryptoSymCipherParams_Destroy(params);
189     OH_CryptoSymCipher_Destroy(cipher);
190     OH_CryptoSymKey_Destroy(symKey);
191     OH_CryptoSymKeyGenerator_Destroy(ctx);
192 }
193 }