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 <gtest/gtest.h>
17 
18 #include "hks_mem.h"
19 #include "hks_test_log.h"
20 #include "hks_type.h"
21 #include "hks_param.h"
22 #include "hks_test_adapt_for_de.h"
23 #include "hks_three_stage_test_common.h"
24 
25 #include "hks_import_wrapped_test_common.h"
26 
27 using namespace testing::ext;
28 namespace Unittest::ImportWrappedKey {
29     static struct HksParam g_aesKekEncryptParams[] = {
30         {.tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES},
31         {.tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT},
32         {.tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256},
33         {.tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE},
34         {.tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM},
35         {.tag = HKS_TAG_DIGEST, .uint32Param = HKS_DIGEST_NONE},
36         {.tag = HKS_TAG_ASSOCIATED_DATA, .blob = {.size = Unittest::ImportWrappedKey::AAD_SIZE,
37                                                   .data = (uint8_t *) Unittest::ImportWrappedKey::AAD}
38         },
39         { .tag = HKS_TAG_NONCE, .blob = {.size = Unittest::ImportWrappedKey::NONCE_SIZE,
40                                          .data = (uint8_t *) Unittest::ImportWrappedKey::NONCE}
41         }
42     };
43 
44     static struct HksParam g_importAgreeKeyParams[] = {
45         {.tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES},
46         {.tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT},
47         {.tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256},
48         {.tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE},
49         {.tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM},
50         {.tag = HKS_TAG_DIGEST, .uint32Param = HKS_DIGEST_NONE},
51         {.tag = HKS_TAG_IV, .blob = {.size = Unittest::ImportWrappedKey::IV_SIZE,
52                                      .data = (uint8_t *) Unittest::ImportWrappedKey::IV }
53         }
54     };
55 
BuildWrappedKeyData(struct HksBlob ** blobArray,uint32_t size,struct HksBlob * outData)56     static int32_t BuildWrappedKeyData(struct HksBlob **blobArray, uint32_t size, struct HksBlob *outData)
57     {
58         uint32_t totalLength = size * sizeof(uint32_t);
59 
60         /* counter size */
61         for (uint32_t i = 0; i < size; ++i) {
62             totalLength += blobArray[i]->size;
63         }
64 
65         struct HksBlob outBlob = { 0, nullptr };
66         outBlob.size = totalLength;
67         (void)MallocAndCheckBlobData(&outBlob, outBlob.size);
68 
69         uint32_t offset = 0;
70 
71         /* copy data */
72         for (uint32_t i = 0; i < size; ++i) {
73             if (memcpy_s(outBlob.data + offset, totalLength - offset, reinterpret_cast<uint8_t *>(&blobArray[i]->size),
74                 sizeof(blobArray[i]->size)) != EOK) {
75                 return HKS_ERROR_BUFFER_TOO_SMALL;
76             }
77             offset += sizeof(blobArray[i]->size);
78 
79             if (memcpy_s(outBlob.data + offset, totalLength - offset, blobArray[i]->data,
80                 blobArray[i]->size) != EOK) {
81                 return HKS_ERROR_BUFFER_TOO_SMALL;
82             }
83             offset += blobArray[i]->size;
84         }
85 
86         outData->size = outBlob.size;
87         outData->data = outBlob.data;
88         return HKS_SUCCESS;
89     }
90 
CheckParamsValid(const struct HksImportWrappedKeyTestParams * params)91     static int32_t CheckParamsValid(const struct HksImportWrappedKeyTestParams *params)
92     {
93         if (params == nullptr) {
94             return HKS_ERROR_INVALID_ARGUMENT;
95         }
96 
97         if (params->wrappingKeyAlias == nullptr || params->genWrappingKeyParamSet == nullptr ||
98             params->agreeKeyAlgName == nullptr || params->callerKeyAlias == nullptr ||
99             params->genCallerKeyParamSet == nullptr || params->callerKekAlias == nullptr ||
100             params->callerKek == nullptr || params->importCallerKekParamSet == nullptr ||
101             params->callerAgreeKeyAlias == nullptr || params->agreeParamSet == nullptr ||
102             params->importWrappedKeyParamSet == nullptr || params->importedKeyAlias == nullptr ||
103             params->importedPlainKey == nullptr) {
104             return HKS_ERROR_INVALID_ARGUMENT;
105         }
106         return HKS_SUCCESS;
107     }
108 
GenerateAndExportHuksPublicKey(const struct HksImportWrappedKeyTestParams * params,struct HksBlob * huksPublicKey)109     static void GenerateAndExportHuksPublicKey(const struct HksImportWrappedKeyTestParams *params,
110         struct HksBlob *huksPublicKey)
111     {
112         HKS_TEST_LOG_I("-------------1. Test_GenerateHuks[%s]Key1\n",
113             reinterpret_cast<char *>(params->agreeKeyAlgName->data));
114         int32_t ret = HksGenerateKeyForDe(params->wrappingKeyAlias, params->genWrappingKeyParamSet, nullptr);
115         EXPECT_EQ(ret, HKS_SUCCESS) << "Generate huks key failed.";
116 
117         HKS_TEST_LOG_I("-------------2. Test_ExportHuks[%s]Key1\n",
118             reinterpret_cast<char *>(params->agreeKeyAlgName->data));
119         huksPublicKey->size = params->publicKeySize;
120 
121         EXPECT_EQ(MallocAndCheckBlobData(huksPublicKey, huksPublicKey->size),
122             HKS_SUCCESS) << "Malloc pub key failed.";
123         ret = HksExportPublicKeyForDe(params->wrappingKeyAlias, nullptr, huksPublicKey);
124         EXPECT_EQ(ret, HKS_SUCCESS) << "Export huks public key failed.";
125     }
126 
GenerateAndExportCallerPublicKey(const struct HksImportWrappedKeyTestParams * params,struct HksBlob * callerSelfPublicKey)127     static void GenerateAndExportCallerPublicKey(const struct HksImportWrappedKeyTestParams *params,
128         struct HksBlob *callerSelfPublicKey)
129     {
130         HKS_TEST_LOG_I("-------------3. Test_GenerateCallerSelf[%s]Key!\n",
131             reinterpret_cast<char *>(params->agreeKeyAlgName->data));
132         int32_t ret = HksGenerateKeyForDe(params->callerKeyAlias, params->genCallerKeyParamSet, nullptr);
133         EXPECT_EQ(ret, HKS_SUCCESS) << "Generate caller key failed.";
134 
135         callerSelfPublicKey->size = params->publicKeySize;
136         EXPECT_EQ(MallocAndCheckBlobData(callerSelfPublicKey,
137             callerSelfPublicKey->size), HKS_SUCCESS) << "malloc fail";
138         ret = HksExportPublicKeyForDe(params->callerKeyAlias, params->genWrappingKeyParamSet, callerSelfPublicKey);
139         EXPECT_EQ(ret, HKS_SUCCESS) << "Export caller public key failed.";
140     }
141 
ImportKekAndAgreeSharedSecret(const struct HksImportWrappedKeyTestParams * params,const struct HksBlob * huksPublicKey,struct HksBlob * outSharedKey)142     static void ImportKekAndAgreeSharedSecret(const struct HksImportWrappedKeyTestParams *params,
143         const struct HksBlob *huksPublicKey, struct HksBlob *outSharedKey)
144     {
145         HKS_TEST_LOG_I("-------------4. Test_ImportCallerSelfKek!\n");
146         int32_t ret = HksImportKeyForDe(params->callerKekAlias, params->importCallerKekParamSet, params->callerKek);
147         EXPECT_EQ(ret, HKS_SUCCESS) << "ImportCallerSelfKek failed.";
148 
149         HKS_TEST_LOG_I("-------------5. Test_CallerAgree[%s]Key and Import To Huks!\n",
150                        reinterpret_cast<char *>(params->agreeKeyAlgName->data));
151         EXPECT_EQ(MallocAndCheckBlobData(outSharedKey, outSharedKey->size), HKS_SUCCESS) << "Malloc sharedKey failed.";
152 
153         ret = HksAgreeKeyForDe(params->agreeParamSet, params->callerKeyAlias, huksPublicKey, outSharedKey);
154         EXPECT_EQ(ret, HKS_SUCCESS) << "HksAgreeKey with huks public key and caller private key failed.";
155 
156         struct HksParamSet *importAgreeKeyParams = nullptr;
157         ret = InitParamSet(&importAgreeKeyParams, g_importAgreeKeyParams,
158                            sizeof(g_importAgreeKeyParams) / sizeof(HksParam));
159         EXPECT_EQ(ret, HKS_SUCCESS) << "InitParamSet(importAgreeKey) failed.";
160 
161         ret = HksImportKeyForDe(params->callerAgreeKeyAlias, importAgreeKeyParams, outSharedKey);
162         EXPECT_EQ(ret, HKS_SUCCESS) << "import agree shared key failed.";
163         HksFreeParamSet(&importAgreeKeyParams);
164     }
165 
EncryptImportedPlainKeyAndKek(const struct HksImportWrappedKeyTestParams * params,struct HksBlob * plainCipherText,struct HksBlob * kekCipherText)166     static void EncryptImportedPlainKeyAndKek(const struct HksImportWrappedKeyTestParams *params,
167         struct HksBlob *plainCipherText, struct HksBlob *kekCipherText)
168     {
169         HKS_TEST_LOG_I("-------------6. Test_CallerEncryptPlainKeyUseKek!\n");
170         struct HksParamSet *encryptParamSet = nullptr;
171         int32_t ret = InitParamSet(&encryptParamSet, g_aesKekEncryptParams,
172                                    sizeof(g_aesKekEncryptParams) / sizeof(HksParam));
173         EXPECT_EQ(ret, HKS_SUCCESS) << "InitParamSet(aesKekEnc) failed.";
174         ret = HksEncryptForDe(params->callerKekAlias, encryptParamSet, params->importedPlainKey, plainCipherText);
175         EXPECT_EQ(ret, HKS_SUCCESS) << "HksEncrypt plain key to be imported failed.";
176 
177         HKS_TEST_LOG_I("-------------7. Test_CallerEncryptKekUseAgreeKey!\n");
178         ret = HksEncryptForDe(params->callerAgreeKeyAlias, encryptParamSet, params->callerKek, kekCipherText);
179         EXPECT_EQ(ret, HKS_SUCCESS) << "Kek encrypt failed.";
180         HksFreeParamSet(&encryptParamSet);
181     }
182 
ImportWrappedKey(const struct HksImportWrappedKeyTestParams * params,struct HksBlob * plainCipher,struct HksBlob * kekCipherText,struct HksBlob * peerPublicKey,struct HksBlob * wrappedKeyData)183     static void ImportWrappedKey(const struct HksImportWrappedKeyTestParams *params, struct HksBlob *plainCipher,
184         struct HksBlob *kekCipherText, struct HksBlob *peerPublicKey, struct HksBlob *wrappedKeyData)
185     {
186         HKS_TEST_LOG_I("-------------8. Test_ImportWrappedKey!\n");
187         struct HksBlob commonAad = {.size = Unittest::ImportWrappedKey::AAD_SIZE,
188                                     .data = reinterpret_cast<uint8_t *>(Unittest::ImportWrappedKey::AAD)};
189         struct HksBlob commonNonce = {.size = Unittest::ImportWrappedKey::NONCE_SIZE,
190                                       .data = reinterpret_cast<uint8_t *>(Unittest::ImportWrappedKey::NONCE)};
191         struct HksBlob keyMaterialLen = {.size = sizeof(uint32_t), .data = (uint8_t *)&params->keyMaterialLen };
192 
193         /* copy AEAD tag from cipher text and decrease its size */
194         const uint32_t tagSize = Unittest::ImportWrappedKey::AEAD_TAG_SIZE;
195         uint8_t kekTagBuf[tagSize] = {0};
196         struct HksBlob kekTag = { .size = tagSize, .data = kekTagBuf };
197         if (memcpy_s(kekTag.data, tagSize, plainCipher->data + (plainCipher->size - tagSize), tagSize) != EOK) {
198             EXPECT_EQ(HKS_ERROR_BUFFER_TOO_SMALL, EOK) << "memcpy kek tag failed.";
199         }
200         plainCipher->size -= tagSize;
201 
202         /* copy AEAD tag from kek cipher text and decrease its size */
203         uint8_t agreeKeyTagBuf[tagSize] = {0};
204         struct HksBlob agreeKeyTag = { .size = tagSize, .data = agreeKeyTagBuf };
205         if (memcpy_s(agreeKeyTagBuf, tagSize, kekCipherText->data + (kekCipherText->size - tagSize), tagSize) != EOK) {
206             EXPECT_EQ(HKS_ERROR_BUFFER_TOO_SMALL, EOK) << "memcpy agreekey tag failed.";
207         }
208         kekCipherText->size -= tagSize;
209 
210         struct HksBlob *blobArray[] = { peerPublicKey, &commonAad, &commonNonce, &agreeKeyTag, kekCipherText,
211                                         &commonAad, &commonNonce, &kekTag, &keyMaterialLen, plainCipher };
212         int32_t ret = BuildWrappedKeyData(blobArray, HKS_IMPORT_WRAPPED_KEY_TOTAL_BLOBS, wrappedKeyData);
213         EXPECT_EQ(ret, HKS_SUCCESS) << "BuildWrappedKeyData failed.";
214 
215         struct HksParam *purpose = nullptr;
216         ret = HksGetParam(params->importWrappedKeyParamSet, HKS_TAG_PURPOSE, &purpose);
217         EXPECT_EQ(ret, HKS_SUCCESS) << "Get wrapped purpose param failed.";
218 
219         ret = HksImportWrappedKeyForDe(params->importedKeyAlias, params->wrappingKeyAlias,
220             params->importWrappedKeyParamSet, wrappedKeyData);
221 
222         if (purpose->uint32Param == (uint32_t)HKS_KEY_PURPOSE_UNWRAP) {
223             EXPECT_EQ(ret, HKS_ERROR_INVALID_PURPOSE) << "Import unwrap purpose wrapped key shouldn't be success.";
224         } else {
225             EXPECT_EQ(ret, HKS_SUCCESS) << "HksImportWrappedKey failed.";
226         }
227     }
228 
HksImportWrappedKeyTestCommonCase(const struct HksImportWrappedKeyTestParams * params)229     void HksImportWrappedKeyTestCommonCase(const struct HksImportWrappedKeyTestParams *params)
230     {
231         int32_t ret = CheckParamsValid(params);
232         EXPECT_EQ(ret, HKS_SUCCESS) << "CheckParamsValid failed.";
233         if (ret != HKS_SUCCESS) {
234             return;
235         }
236 
237         struct HksBlob huksPublicKey = { 0, nullptr };
238         struct HksBlob callerSelfPublicKey = { 0, nullptr };
239         struct HksBlob outSharedKey = { .size = HKS_KEY_BYTES(HKS_AES_KEY_SIZE_256), .data = nullptr };
240         struct HksBlob wrappedKeyData = { 0, nullptr };
241         uint8_t plainKeyCipherBuffer[MAX_KEY_SIZE] = {0};
242         struct HksBlob plainCipherText = { MAX_KEY_SIZE, plainKeyCipherBuffer };
243         uint8_t kekCipherTextBuffer[MAX_KEY_SIZE] = {0};
244         struct HksBlob kekCipherText = { MAX_KEY_SIZE, kekCipherTextBuffer };
245 
246         GenerateAndExportHuksPublicKey(params, &huksPublicKey);
247         GenerateAndExportCallerPublicKey(params, &callerSelfPublicKey);
248         ImportKekAndAgreeSharedSecret(params, &huksPublicKey, &outSharedKey);
249         EncryptImportedPlainKeyAndKek(params, &plainCipherText, &kekCipherText);
250         ImportWrappedKey(params, &plainCipherText, &kekCipherText, &callerSelfPublicKey, &wrappedKeyData);
251 
252         HKS_FREE_BLOB(huksPublicKey);
253         HKS_FREE_BLOB(callerSelfPublicKey);
254         HKS_FREE_BLOB(outSharedKey);
255         HKS_FREE_BLOB(wrappedKeyData);
256     }
257 
HksClearKeysForWrappedKeyTest(const struct HksImportWrappedKeyTestParams * params)258     void HksClearKeysForWrappedKeyTest(const struct HksImportWrappedKeyTestParams *params)
259     {
260         int32_t ret = CheckParamsValid(params);
261         EXPECT_EQ(ret, HKS_SUCCESS) << "CheckParamsValid failed.";
262         if (ret != HKS_SUCCESS) {
263             return;
264         }
265         (void)HksDeleteKeyForDe(params->wrappingKeyAlias, nullptr);
266         (void)HksDeleteKeyForDe(params->callerKeyAlias, nullptr);
267         (void)HksDeleteKeyForDe(params->callerKekAlias, nullptr);
268         (void)HksDeleteKeyForDe(params->callerAgreeKeyAlias, nullptr);
269         (void)HksDeleteKeyForDe(params->importedKeyAlias, nullptr);
270     }
271 }
272