1 /*
2 * Copyright (c) 2024-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 <cstdlib>
17 #include <fcntl.h>
18 #include <gtest/gtest.h>
19 #include <string>
20 #include <openssl/pem.h>
21 #include <openssl/x509.h>
22
23 #include "access_token_setter.h"
24 #include "byte_buffer.h"
25 #include "huks_attest_verifier.h"
26 #include "log.h"
27
28 using namespace OHOS::Security::CodeSign;
29 using namespace std;
30 using namespace testing::ext;
31
32 namespace OHOS {
33 namespace Security {
34 namespace CodeSign {
35 const std::string SIGNING_CERT_CHAIN_PEM =
36 "-----BEGIN CERTIFICATE-----\n" \
37 "MIIDgzCCAm2gAwIBAgIBATALBgkqhkiG9w0BAQswfzELMAkGA1UEBhMCQ04xEzAR\n" \
38 "BgNVBAgMCmhlbGxvd29ybGQxEzARBgNVBAoMCmhlbGxvd29ybGQxEzARBgNVBAsM\n" \
39 "CmhlbGxvd29ybGQxFjAUBgNVBAMMDWhlbGxvd29ybGQxMTExGTAXBgkqhkiG9w0B\n" \
40 "CQEWCmhlbGxvd29ybGQwHhcNMjQwODA5MDkzMDEyWhcNMzQwODA5MDkzMDEyWjAa\n" \
41 "MRgwFgYDVQQDEw9BIEtleW1hc3RlciBLZXkwWTATBgcqhkjOPQIBBggqhkjOPQMB\n" \
42 "BwNCAATJqTRIhGKhLmXuJbPI311/5gEljqPbpJpXNp6oe8dOmnyJ9SQQZmMomB5u\n" \
43 "lC5aZIoNrCuKHTAgY1PpNNcFSBBpo4IBPDCCATgwCwYDVR0PBAQDAgeAMAgGA1Ud\n" \
44 "HwQBADCCAR0GDCsGAQQBj1sCgngBAwSCAQswggEHAgEAMDQCAQAGDSsGAQQBj1sC\n" \
45 "gngCAQQEIOIC9EG2Dn3zqle0WWjiHwk2CIP3hJuPjjQwi7z4FaFFMCICAQIGDSsG\n" \
46 "AQQBj1sCgngCAQIEDkxPQ0FMX1NJR05fS0VZMFwCAQIGDSsGAQQBj1sCgngCAQMw\n" \
47 "SAYOKwYBBAGPWwKCeAIBAwEENnsicHJvY2Vzc05hbWUiOiJsb2NhbF9jb2RlX3Np\n" \
48 "Z24iLCJBUEwiOiJzeXN0ZW1fYmFzaWMifTAYAgECBg0rBgEEAY9bAoJ4AgELBAQA\n" \
49 "AAAAMBgCAQIGDSsGAQQBj1sCgngCAQUEBAIAAAAwFgIBAgYOKwYBBAGPWwKCeAIE\n" \
50 "AQUBAf8wCwYJKoZIhvcNAQELA4IBAQB8zqqeaXux3qkQF0GFax7I4YWtTpoeQeJU\n" \
51 "BjyMk/eGmeX+ZD9absOQDzH/wH6MddzPLjoaIuoR+oxDXn2yqQ5xyGQp6uN0E8IB\n" \
52 "OFCjeTbRBR86A+CulTGuitszOpfyKF7SvmzfGx+ij2OtQnZ7QZp+I2YEr1Jc4ESr\n" \
53 "xXXt0zPslidnf7qso+f09C6U9YOnaxISfjxEqFn25+yWX2tXBJ62L6R7+zpKU3ee\n" \
54 "0ljf4jYtlza7s5mYJ2+OHlwdXuF38cpS59cG48UpsL0DAqywqjs5uaGthkrWo2YB\n" \
55 "FlAL4bVfBj2FmcqNhz+j3dgLTNA3VczwkNbj/FIY1T+FDTqnsCED\n" \
56 "-----END CERTIFICATE-----";
57
58 const std::string ISSUER_CERT_CHAIN_PEM =
59 "-----BEGIN CERTIFICATE-----\n" \
60 "MIIDyzCCArOgAwIBAgIBAzANBgkqhkiG9w0BAQsFADB+MQswCQYDVQQGEwJDTjET\n" \
61 "MBEGA1UECAwKaGVsbG93b3JsZDETMBEGA1UECgwKaGVsbG93b3JsZDETMBEGA1UE\n" \
62 "CwwKaGVsbG93b3JsZDEVMBMGA1UEAwwMaGVsbG93b3JsZDExMRkwFwYJKoZIhvcN\n" \
63 "AQkBFgpoZWxsb3dvcmxkMB4XDTIyMDEyMjA5MjUzM1oXDTMyMDEyMDA5MjUzM1ow\n" \
64 "fzELMAkGA1UEBhMCQ04xEzARBgNVBAgMCmhlbGxvd29ybGQxEzARBgNVBAoMCmhl\n" \
65 "bGxvd29ybGQxEzARBgNVBAsMCmhlbGxvd29ybGQxFjAUBgNVBAMMDWhlbGxvd29y\n" \
66 "bGQxMTExGTAXBgkqhkiG9w0BCQEWCmhlbGxvd29ybGQwggEiMA0GCSqGSIb3DQEB\n" \
67 "AQUAA4IBDwAwggEKAoIBAQC8HHhVEbY3uuriW3wAcAMFwIUd+VImAUKnWAYlsiHL\n" \
68 "Ps3BhpHHb67kjzP3rcQbZ2l1LSMWjoV8jXckVMOFqOlTlrYlGM3G80bVaWcEgw4c\n" \
69 "+nkSk+ApGmNUa69HK3h+5vfz81fVmJL1zX0VaYiA+wCzrFc1w5aGKhsFIcIY8FUo\n" \
70 "i15xrwAURQ+/EylzeF302qGwkCHYy4zQqn3ohku25rPLUOyOp6gJNs/3BVh76b9/\n" \
71 "1iTyP7ldDD7VV4UQCTDppFtrDQY/UrBhe9sPn0+6GWBfkkjz5n1aGE7JP2vmB3qM\n" \
72 "gxIpEkmVLVIxh6dwBOmtr+sT7xJ+UzmTWbbhNGCkzSPxAgMBAAGjUzBRMB0GA1Ud\n" \
73 "DgQWBBSDTqp6QOdxk9zF2H+7IGOckq/A1DAfBgNVHSMEGDAWgBRNYAEJlwxPOj5F\n" \
74 "B7M4mTsMpokRLzAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQB4\n" \
75 "CkKbJQWuC2pj0cS+zb4v8fRq8OPjRVPylqjHX4IMpmnl2VM0DkNXD0SYPC5IxkK4\n" \
76 "bgtglG0Rkr4blYf+PdNenbebWZvw4Y3JUoQgSasfdIA/rJXZtf3mVUNLmPlcRWZC\n" \
77 "OtGJmvlntp7/qWl7JCIaiD732baJU1DZchy3am2WWGpchBESBOtoSvdywG+T0xQQ\n" \
78 "cXzYQ+mHPsym30JCzChvZCKz+QJlIZUJ3XgoKH7MVviASXGcWLKOBYYUDt3J8/PM\n" \
79 "shbsqb+rm+VqU5ohV8Rr/nQ+QLvEFa8rrz7qY6/2QSbUy7QvFCv7MXFD1kCH92FL\n" \
80 "GwkmWDavM1kdVMXZmV54\n" \
81 "-----END CERTIFICATE-----";
82
83 const std::string INTER_CA_CHAIN_PEM =
84 "-----BEGIN CERTIFICATE-----\n" \
85 "MIID3zCCAsegAwIBAgIBAjANBgkqhkiG9w0BAQsFADCBkjELMAkGA1UEBhMCQ04x\n" \
86 "EzARBgNVBAgMCmhlbGxvd29ybGQxEzARBgNVBAcMCmhlbGxvd29ybGQxEzARBgNV\n" \
87 "BAoMCmhlbGxvd29ybGQxEzARBgNVBAsMCmhlbGxvd29ybGQxFDASBgNVBAMMC2hl\n" \
88 "bGxvd29ybGQxMRkwFwYJKoZIhvcNAQkBFgpoZWxsb3dvcmxkMB4XDTIyMDEyMjA5\n" \
89 "MjM0OFoXDTMyMDEyMDA5MjM0OFowfjELMAkGA1UEBhMCQ04xEzARBgNVBAgMCmhl\n" \
90 "bGxvd29ybGQxEzARBgNVBAoMCmhlbGxvd29ybGQxEzARBgNVBAsMCmhlbGxvd29y\n" \
91 "bGQxFTATBgNVBAMMDGhlbGxvd29ybGQxMTEZMBcGCSqGSIb3DQEJARYKaGVsbG93\n" \
92 "b3JsZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALTJF+SAh/ccmcxF\n" \
93 "+le0m8Wx7N9kclMYoUVGyJOPDv0L9kE/1hg9HEavCBWal9ZK69r+i1YiH18Y0F5o\n" \
94 "AuqP0teedDByPii8IaDquJKZ1hlMi13vPY1cgUcG77cKzC5TMlmNTLes0ddn9/lY\n" \
95 "4ajl4kgUr3bCEXlp4uhBQPYlntujctcjmEdMtcJQmhHpr2Js9cq2kZney59ae5kk\n" \
96 "LCzpFqpj7cunz5Rs3RZs1+Njw5oABS18qAy1CEBnecLOi6lIPvIckngBHduwczOM\n" \
97 "5YBBXeqOeNk7FWTiIf5MuXlqOSlZ57Wp8SqfDzwS49awwI9dvGpjgyGh3ZQA5TXX\n" \
98 "GGIsn5cCAwEAAaNTMFEwHQYDVR0OBBYEFE1gAQmXDE86PkUHsziZOwymiREvMB8G\n" \
99 "A1UdIwQYMBaAFJp3c+VFpGlC/r/UiPCozoH1UcgMMA8GA1UdEwEB/wQFMAMBAf8w\n" \
100 "DQYJKoZIhvcNAQELBQADggEBAArLbWZWG3cHuCnMBGo28F0KVKctxjLVOCzDhKnH\n" \
101 "IusLVqTnZ7AHeUU56NyoRfSRSIEJ2TNXkHO8MyxNN3lP4RapQavOvENLE99s269I\n" \
102 "suLPCp3k6znJX1ZW7MIrSp7Bz+6rBTuh2H874H/BcvPXaCZB4X3Npjfu4tRcKEtS\n" \
103 "JKdVmIlotjX1qM5eYHY5BDSR0MvRYvSlH7/wA9FEGJ8GHI7vaHxIMxf4+OOz+E4w\n" \
104 "qKIZZfYeVBdEpZvfVGHRbS5dEofqc4NthlObTWlwAIhFgTzLqy8y2Y2jDWcJk91/\n" \
105 "y9u8F1jQAuoemDCY5BalZ+Bn0eZQQHlXujwyZfoIK+oCuUo=\n" \
106 "-----END CERTIFICATE-----";
107
108 const uint8_t CHALLENGE[] = {
109 0xe2, 0x2, 0xf4, 0x41, 0xb6, 0xe, 0x7d, 0xf3,
110 0xaa, 0x57, 0xb4, 0x59, 0x68, 0xe2, 0x1f, 0x9,
111 0x36, 0x8, 0x83, 0xf7, 0x84, 0x9b, 0x8f, 0x8e,
112 0x34, 0x30, 0x8b, 0xbc, 0xf8, 0x15, 0xa1, 0x45
113 };
114
115 static ByteBuffer g_issuerCert;
116 static ByteBuffer g_signingCert;
117 static ByteBuffer g_interCA;
118 static ByteBuffer g_invalidCert;
119 static ByteBuffer g_rootCA;
120
CastToUint8Ptr(uint32_t * ptr)121 static inline uint8_t *CastToUint8Ptr(uint32_t *ptr)
122 {
123 return reinterpret_cast<uint8_t *>(ptr);
124 }
125
LoadPemString(const std::string & pemData)126 static X509 *LoadPemString(const std::string &pemData)
127 {
128 BIO *mem = BIO_new_mem_buf(pemData.c_str(), pemData.length());
129 if (mem == nullptr) {
130 return nullptr;
131 }
132
133 X509 *x509 = PEM_read_bio_X509(mem, nullptr, nullptr, nullptr);
134 EXPECT_NE(x509, nullptr);
135 BIO_free(mem);
136 return x509;
137 }
138
LoadDerFormPemString(const std::string & pemData,ByteBuffer & certBuffer)139 void LoadDerFormPemString(const std::string &pemData, ByteBuffer &certBuffer)
140 {
141 X509 *x509 = LoadPemString(pemData);
142 uint8_t *derTemp = nullptr;
143 int32_t derTempLen = i2d_X509(x509, &derTemp);
144 EXPECT_NE(derTemp, nullptr);
145 if (derTempLen < 0) {
146 X509_free(x509);
147 return;
148 }
149
150 certBuffer.CopyFrom(derTemp, static_cast<uint32_t>(derTempLen));
151
152 X509_free(x509);
153 OPENSSL_free(derTemp);
154 }
155
FormattedCertChain(const std::vector<ByteBuffer> & certChain,ByteBuffer & buffer)156 static void FormattedCertChain(const std::vector<ByteBuffer> &certChain, ByteBuffer &buffer)
157 {
158 uint32_t certsCount = certChain.size();
159 uint32_t totalLen = sizeof(uint32_t);
160 for (uint32_t i = 0; i < certsCount; i++) {
161 totalLen += sizeof(uint32_t) + certChain[i].GetSize();
162 }
163 buffer.Resize(totalLen);
164 if (!buffer.PutData(0, CastToUint8Ptr(&certsCount), sizeof(uint32_t))) {
165 return;
166 }
167 uint32_t pos = sizeof(uint32_t);
168 for (uint32_t i = 0; i < certsCount; i++) {
169 uint32_t size = certChain[i].GetSize();
170 if (!buffer.PutData(pos, CastToUint8Ptr(&size), sizeof(uint32_t))) {
171 return;
172 }
173 pos += sizeof(uint32_t);
174 if (!buffer.PutData(pos, certChain[i].GetBuffer(), certChain[i].GetSize())) {
175 return;
176 }
177 pos += certChain[i].GetSize();
178 }
179 }
180
181 class CertChainVerifierTest : public testing::Test {
182 public:
CertChainVerifierTest()183 CertChainVerifierTest() {};
~CertChainVerifierTest()184 virtual ~CertChainVerifierTest() {};
SetUpTestCase()185 static void SetUpTestCase()
186 {
187 LoadDerFormPemString(SIGNING_CERT_CHAIN_PEM, g_signingCert);
188 LoadDerFormPemString(ISSUER_CERT_CHAIN_PEM, g_issuerCert);
189 LoadDerFormPemString(INTER_CA_CHAIN_PEM, g_interCA);
190 // fake root CA, no use in verifying
191 uint8_t tmp = 0;
192 g_rootCA.CopyFrom(&tmp, sizeof(tmp));
193 g_invalidCert.CopyFrom(&tmp, sizeof(tmp));
194 }
TearDownTestCase()195 static void TearDownTestCase() {};
SetUp()196 void SetUp() {};
TearDown()197 void TearDown() {};
198 };
199
200 /**
201 * @tc.name: CertChainVerifierTest_001
202 * @tc.desc: Get chain from empty buffer
203 * @tc.type: Func
204 * @tc.require: IAJ4QG
205 */
206 HWTEST_F(CertChainVerifierTest, CertChainVerifierTest_001, TestSize.Level0)
207 {
208 ByteBuffer cert, challenge, certBuffer;
209 EXPECT_EQ(GetVerifiedCert(cert, challenge, certBuffer), false);
210 }
211
212 /**
213 * @tc.name: CertChainVerifierTest_0002
214 * @tc.desc: Get chain from empty cert chain
215 * @tc.type: Func
216 * @tc.require: IAJ4QG
217 */
218 HWTEST_F(CertChainVerifierTest, CertChainVerifierTest_002, TestSize.Level0)
219 {
220 ByteBuffer cert, challenge, certBuffer;
221 uint32_t count = 0;
222 cert.CopyFrom(reinterpret_cast<uint8_t *>(&count), sizeof(count));
223 EXPECT_EQ(GetVerifiedCert(cert, challenge, certBuffer), false);
224 }
225
226
227 /**
228 * @tc.name: CertChainVerifierTest_0003
229 * @tc.desc: Get chain from invalid formatted buffer
230 * @tc.type: Func
231 * @tc.require: IAJ4QG
232 */
233 HWTEST_F(CertChainVerifierTest, CertChainVerifierTest_003, TestSize.Level0)
234 {
235 ByteBuffer cert, challenge, certBuffer;
236 std::vector<uint32_t> tmpBuffer = {0};
237 cert.CopyFrom(reinterpret_cast<uint8_t *>(tmpBuffer.data()), tmpBuffer.size() * sizeof(uint32_t));
238 EXPECT_EQ(GetVerifiedCert(cert, challenge, certBuffer), false);
239
240 // one cert in cert chain, classify as root CA
241 tmpBuffer[0] = 1;
242 // load issuer failed
243 cert.CopyFrom(reinterpret_cast<uint8_t *>(tmpBuffer.data()), tmpBuffer.size() * sizeof(uint32_t));
244 EXPECT_EQ(GetVerifiedCert(cert, challenge, certBuffer), false);
245
246 // two certs in cert chain
247 tmpBuffer[0] = 2;
248 // cert size
249 tmpBuffer.push_back(sizeof(uint32_t));
250 cert.CopyFrom(reinterpret_cast<uint8_t *>(tmpBuffer.data()), tmpBuffer.size() * sizeof(uint32_t));
251 // no content to load cert, convert from formatted buffer failed
252 EXPECT_EQ(GetVerifiedCert(cert, challenge, certBuffer), false);
253
254 // fill issuer
255 tmpBuffer.push_back(0);
256 cert.CopyFrom(reinterpret_cast<uint8_t *>(tmpBuffer.data()), tmpBuffer.size() * sizeof(uint32_t));
257 // invalid content, convert content to x509 failed
258 EXPECT_EQ(GetVerifiedCert(cert, challenge, certBuffer), false);
259 }
260
261 /**
262 * @tc.name: CertChainVerifierTest_0004
263 * @tc.desc: Get verified failed with invalid issuer format
264 * @tc.type: Func
265 * @tc.require: IAJ4QG
266 */
267 HWTEST_F(CertChainVerifierTest, CertChainVerifierTest_004, TestSize.Level0)
268 {
269 ByteBuffer formattedCert, challenge, certBuffer;
270 std::vector<ByteBuffer> certs;
271 certs.push_back(g_signingCert);
272 certs.push_back(g_invalidCert);
273 certs.push_back(g_interCA);
274 certs.push_back(g_rootCA);
275 FormattedCertChain(certs, formattedCert);
276 EXPECT_EQ(GetVerifiedCert(formattedCert, challenge, certBuffer), false);
277 }
278
279 /**
280 * @tc.name: CertChainVerifierTest_0005
281 * @tc.desc: Get verified failed with invalid interCA format
282 * @tc.type: Func
283 * @tc.require: IAJ4QG
284 */
285 HWTEST_F(CertChainVerifierTest, CertChainVerifierTest_005, TestSize.Level0)
286 {
287 ByteBuffer formattedCert, challenge, certBuffer;
288 std::vector<ByteBuffer> certs;
289 certs.push_back(g_signingCert);
290 certs.push_back(g_issuerCert);
291 certs.push_back(g_invalidCert);
292 certs.push_back(g_rootCA);
293 FormattedCertChain(certs, formattedCert);
294 EXPECT_EQ(GetVerifiedCert(formattedCert, challenge, certBuffer), false);
295 }
296
297 /**
298 * @tc.name: CertChainVerifierTest_0006
299 * @tc.desc: verifying issuer cert failed
300 * @tc.type: Func
301 * @tc.require: IAJ4QG
302 */
303 HWTEST_F(CertChainVerifierTest, CertChainVerifierTest_006, TestSize.Level0)
304 {
305 ByteBuffer formattedCert, challenge, certBuffer;
306 std::vector<ByteBuffer> certs;
307 certs.push_back(g_signingCert);
308 certs.push_back(g_signingCert);
309 certs.push_back(g_interCA);
310 certs.push_back(g_rootCA);
311 FormattedCertChain(certs, formattedCert);
312 EXPECT_EQ(GetVerifiedCert(formattedCert, challenge, certBuffer), false);
313 }
314
315 /**
316 * @tc.name: CertChainVerifierTest_0007
317 * @tc.desc: verify signing cert failed
318 * @tc.type: Func
319 * @tc.require: IAJ4QG
320 */
321 HWTEST_F(CertChainVerifierTest, CertChainVerifierTest_007, TestSize.Level0)
322 {
323 ByteBuffer challenge;
324 //parse pub key of failed
325 EXPECT_EQ(VerifyCertAndExtension(nullptr, nullptr, challenge), false);
326
327 X509 *signingCert = LoadPemString(SIGNING_CERT_CHAIN_PEM);
328 X509 *issuerCert = LoadPemString(ISSUER_CERT_CHAIN_PEM);
329 // verify signature failed
330 EXPECT_EQ(VerifyCertAndExtension(issuerCert, signingCert, challenge), false);
331
332 // verify extension failed
333 const char *invalidChallenge = "invalid";
334 challenge.CopyFrom(reinterpret_cast<const uint8_t *>(invalidChallenge),
335 sizeof(invalidChallenge));
336 EXPECT_EQ(VerifyCertAndExtension(signingCert, issuerCert, challenge), false);
337
338 // verify extension success
339 challenge.CopyFrom(CHALLENGE, sizeof(CHALLENGE));
340 EXPECT_EQ(VerifyCertAndExtension(signingCert, issuerCert, challenge), true);
341 X509_free(signingCert);
342 X509_free(issuerCert);
343 }
344
345 /**
346 * @tc.name: CertChainVerifierTest_0008
347 * @tc.desc: verifying issuer cert success
348 * @tc.type: Func
349 * @tc.require: IAJ4QG
350 */
351 HWTEST_F(CertChainVerifierTest, CertChainVerifierTest_008, TestSize.Level0)
352 {
353 ByteBuffer formattedCert, challenge, certBuffer;
354 std::vector<ByteBuffer> certs;
355 certs.push_back(g_signingCert);
356 certs.push_back(g_issuerCert);
357 certs.push_back(g_interCA);
358 certs.push_back(g_rootCA);
359 FormattedCertChain(certs, formattedCert);
360 // verify extension success
361 challenge.CopyFrom(CHALLENGE, sizeof(CHALLENGE));
362 #ifdef CODE_SIGNATURE_OH_ROOT_CA
363 EXPECT_EQ(GetVerifiedCert(formattedCert, challenge, certBuffer), true);
364 #else
365 EXPECT_EQ(GetVerifiedCert(formattedCert, challenge, certBuffer), false);
366 #endif
367 }
368
369 } // namespace CodeSign
370 } // namespace Security
371 } // namespace OHOS