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(¶ms);
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 }