• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2025 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 <gtest/gtest.h>
18 #include <string>
19 
20 #include <openssl/asn1.h>
21 #include <openssl/pkcs7.h>
22 #include <openssl/x509v3.h>
23 #include "access_token_setter.h"
24 #include "byte_buffer.h"
25 #include "code_sign_test_common.h"
26 #include "code_sign_utils.h"
27 #include "local_code_sign_kit.h"
28 #include "local_key_helper.h"
29 #include "log.h"
30 
31 using namespace OHOS::Security::CodeSign;
32 using namespace testing::ext;
33 using namespace std;
34 
35 namespace OHOS {
36 namespace Security {
37 namespace CodeSign {
38 static const std::string AN_BASE_PATH = "/data/local/ark-cache/tmp/";
39 static const std::string DEMO_AN_PATH = AN_BASE_PATH + "demo.an";
40 static const std::string DEMO_TAMPER_AN_PATH = AN_BASE_PATH + "fake_demo.an";
41 
42 static const char *VALID_CALLER = "compiler_service";
43 
44 static const std::string FAKE_SERIAL_NUMBER = "0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
45 static const std::string FAKE_CONTENT = "FAKE";
46 
47 static const int MAX_TEST_BUF_LEN = 1024;
48 
ModifySignatureFormat(ByteBuffer & pkcs7Data)49 static void ModifySignatureFormat(ByteBuffer &pkcs7Data)
50 {
51     uint8_t *data = pkcs7Data.GetBuffer();
52     (void) memcpy_s(data, pkcs7Data.GetSize(), FAKE_CONTENT.c_str(), FAKE_CONTENT.length());
53 }
54 
ModifySignatureValue(PKCS7_SIGNER_INFO * p7info)55 static void ModifySignatureValue(PKCS7_SIGNER_INFO *p7info)
56 {
57     const uint8_t *data = ASN1_STRING_get0_data(p7info->enc_digest);
58     int len = ASN1_STRING_length(p7info->enc_digest);
59     if (len <= 0 || len > MAX_TEST_BUF_LEN) {
60         return;
61     }
62     uint8_t *fdata = static_cast<uint8_t *>(malloc(len));
63     if (fdata == nullptr) {
64         return;
65     }
66     (void)memcpy_s(fdata, len, data, len);
67     (void)memcpy_s(fdata, len, FAKE_CONTENT.c_str(), FAKE_CONTENT.length());
68     ASN1_STRING_set0(p7info->enc_digest, fdata, len);
69 }
70 
ModifySignatureSigner(PKCS7_SIGNER_INFO * p7info)71 static void ModifySignatureSigner(PKCS7_SIGNER_INFO *p7info)
72 {
73     ASN1_INTEGER *serial = s2i_ASN1_INTEGER(nullptr, FAKE_SERIAL_NUMBER.c_str());
74     ASN1_INTEGER_free(p7info->issuer_and_serial->serial);
75     p7info->issuer_and_serial->serial = ASN1_INTEGER_dup(serial);
76 }
77 
GetSignerInfo(PKCS7 * p7)78 static PKCS7_SIGNER_INFO *GetSignerInfo(PKCS7 *p7)
79 {
80     STACK_OF(PKCS7_SIGNER_INFO) *signInfos = PKCS7_get_signer_info(p7);
81     // only one signer
82     if (sk_PKCS7_SIGNER_INFO_num(signInfos) < 1) {
83         return nullptr;
84     }
85     return sk_PKCS7_SIGNER_INFO_value(signInfos, 0);
86 }
87 
LoadPKCS7Data(ByteBuffer & pkcs7Data)88 static PKCS7 *LoadPKCS7Data(ByteBuffer &pkcs7Data)
89 {
90     BIO *mem = BIO_new_mem_buf(pkcs7Data.GetBuffer(), pkcs7Data.GetSize());
91     return d2i_PKCS7_bio(mem, nullptr);
92 }
93 
DumpPKCS7Data(PKCS7 * p7,ByteBuffer & pkcs7Data)94 static bool DumpPKCS7Data(PKCS7 *p7, ByteBuffer &pkcs7Data)
95 {
96     BIO *bio = BIO_new(BIO_s_mem());
97     bool ret = false;
98     do {
99         if (bio == nullptr) {
100             break;
101         }
102         if (!i2d_PKCS7_bio(bio, p7)) {
103             break;
104         }
105         uint8_t *tmp = nullptr;
106         long tmpSize = BIO_get_mem_data(bio, &tmp);
107         if ((tmpSize < 0) || (tmpSize > UINT32_MAX)) {
108             break;
109         }
110         if (!pkcs7Data.CopyFrom(tmp, static_cast<uint32_t>(tmpSize))) {
111             break;
112         }
113         ret = true;
114     } while (0);
115     BIO_free(bio);
116     return ret;
117 }
118 
ModifyPkcs7SignerwithTargetFunc(ByteBuffer & src,ByteBuffer & dst,void (* modifyFunc)(PKCS7_SIGNER_INFO * p7))119 static bool ModifyPkcs7SignerwithTargetFunc(ByteBuffer &src, ByteBuffer &dst,
120     void (*modifyFunc)(PKCS7_SIGNER_INFO *p7))
121 {
122     PKCS7 *p7 = LoadPKCS7Data(src);
123     if (p7 == nullptr) {
124         return false;
125     }
126     PKCS7_SIGNER_INFO *signer = GetSignerInfo(p7);
127     if (signer == nullptr) {
128         return false;
129     }
130     modifyFunc(signer);
131     if (!DumpPKCS7Data(p7, dst)) {
132         return false;
133     }
134     PKCS7_free(p7);
135     return true;
136 }
137 
InvokeLocalCodeSign(const std::string & filePath,ByteBuffer & sig)138 static void InvokeLocalCodeSign(const std::string &filePath, ByteBuffer &sig)
139 {
140     uint64_t selfTokenId = GetSelfTokenID();
141     EXPECT_TRUE(MockTokenId(VALID_CALLER));
142     int ret = LocalCodeSignKit::SignLocalCode(filePath, sig);
143     EXPECT_EQ(0, SetSelfTokenID(selfTokenId));
144     EXPECT_EQ(ret, CS_SUCCESS);
145 }
146 
147 class SignAndEnforceTest : public testing::Test {
148 public:
SignAndEnforceTest()149     SignAndEnforceTest() {};
~SignAndEnforceTest()150     virtual ~SignAndEnforceTest() {};
SetUpTestCase()151     static void SetUpTestCase() {};
TearDownTestCase()152     static void TearDownTestCase() {};
SetUp()153     void SetUp() {};
TearDown()154     void TearDown() {};
155 };
156 
157 /**
158  * @tc.name: SignAndEnforceTest_0001
159  * @tc.desc: sign AN file and enforce with null
160  * @tc.type: Func
161  * @tc.require:
162  */
163 HWTEST_F(SignAndEnforceTest, SignAndEnforceTest_0001, TestSize.Level0)
164 {
165     ByteBuffer sig;
166     InvokeLocalCodeSign(DEMO_AN_PATH, sig);
167     ByteBuffer empty;
168     int32_t ret = CodeSignUtils::EnforceCodeSignForFile(DEMO_AN_PATH, empty);
169     EXPECT_EQ(ret, CS_ERR_NO_SIGNATURE);
170 }
171 
172 /**
173  * @tc.name: SignAndEnforceTest_0002
174  * @tc.desc: sign AN file and enforce tampered one
175  * @tc.type: Func
176  * @tc.require:
177  */
178 HWTEST_F(SignAndEnforceTest, SignAndEnforceTest_0002, TestSize.Level0)
179 {
180     ByteBuffer sig;
181     InvokeLocalCodeSign(DEMO_AN_PATH, sig);
182     int32_t ret = CodeSignUtils::EnforceCodeSignForFile(DEMO_TAMPER_AN_PATH, sig);
183     EXPECT_EQ(ret, CS_ERR_ENABLE);
184 }
185 
186 /**
187  * @tc.name: SignAndEnforceTest_0003
188  * @tc.desc: sign AN file and enforce it with wrong signature fromat
189  * @tc.type: Func
190  * @tc.require:
191  */
192 HWTEST_F(SignAndEnforceTest, SignAndEnforceTest_0003, TestSize.Level0)
193 {
194     ByteBuffer sig;
195     InvokeLocalCodeSign(DEMO_AN_PATH, sig);
196     ModifySignatureFormat(sig);
197     int32_t ret = CodeSignUtils::EnforceCodeSignForFile(DEMO_AN_PATH, sig);
198     EXPECT_EQ(ret, CS_ERR_ENABLE);
199 }
200 
201 /**
202  * @tc.name: SignAndEnforceTest_0004
203  * @tc.desc: sign AN file and enforce it with wrong signature value
204  * @tc.type: Func
205  * @tc.require:
206  */
207 HWTEST_F(SignAndEnforceTest, SignAndEnforceTest_0004, TestSize.Level0)
208 {
209     ByteBuffer sig;
210     InvokeLocalCodeSign(DEMO_AN_PATH, sig);;
211     ByteBuffer wrongSig;
212     EXPECT_EQ(ModifyPkcs7SignerwithTargetFunc(sig, wrongSig, ModifySignatureValue), true);
213     int32_t ret = CodeSignUtils::EnforceCodeSignForFile(DEMO_AN_PATH, wrongSig);
214     EXPECT_EQ(ret, CS_ERR_ENABLE);
215 }
216 
217 /**
218  * @tc.name: SignAndEnforceTest_0005
219  * @tc.desc: sign AN file and enforce it using signature with wrong signer
220  * @tc.type: Func
221  * @tc.require:
222  */
223 HWTEST_F(SignAndEnforceTest, SignAndEnforceTest_0005, TestSize.Level0)
224 {
225     ByteBuffer sig;
226     InvokeLocalCodeSign(DEMO_AN_PATH, sig);
227     ByteBuffer wrongSig;
228     EXPECT_EQ(ModifyPkcs7SignerwithTargetFunc(sig, wrongSig, ModifySignatureSigner), true);
229     int32_t ret = CodeSignUtils::EnforceCodeSignForFile(DEMO_AN_PATH, wrongSig);
230     EXPECT_EQ(ret, CS_ERR_ENABLE);
231 }
232 
233 /**
234  * @tc.name: SignAndEnforceTest_0006
235  * @tc.desc: sign AN file and enforce it
236  * @tc.type: Func
237  * @tc.require:
238  */
239 HWTEST_F(SignAndEnforceTest, SignAndEnforceTest_0006, TestSize.Level0)
240 {
241     ByteBuffer sig;
242     InvokeLocalCodeSign(DEMO_AN_PATH, sig);
243     int32_t ret = CodeSignUtils::EnforceCodeSignForFile(DEMO_AN_PATH, sig);
244     EXPECT_EQ(ret, GetEnforceFileResult());
245 }
246 } // namespace CodeSign
247 } // namespace Security
248 } // namespace OHOS