1 /*
2 * Copyright (c) 2023 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 "signer_info.h"
17
18 #include <openssl/asn1.h>
19 #include <openssl/pem.h>
20 #include <openssl/obj_mac.h>
21 #include <openssl/pkcs7.h>
22 #include <openssl/x509.h>
23 #include <openssl/objects.h>
24 #include <securec.h>
25
26 #include "errcode.h"
27 #include "log.h"
28 #include "openssl_utils.h"
29
30 namespace OHOS {
31 namespace Security {
32 namespace CodeSign {
33 static constexpr int INVALID_SIGN_ALGORITHM_NID = -1;
34 static constexpr int MAX_SIGNATURE_SIZE = 1024; // 1024: max signature length
35
36 // OID used for code signing to mark owner ID
37 const std::string SignerInfo::OWNERID_OID = "1.3.6.1.4.1.2011.2.376.1.4.1";
38 const std::string SignerInfo::OWNERID_OID_SHORT_NAME = "ownerID";
39 const std::string SignerInfo::OWNERID_OID_LONG_NAME = "Code Signature Owner ID";
40 const std::string SignerInfo::PLUGINID_OID = "1.3.6.1.4.1.2011.2.376.1.4.2";
41 const std::string SignerInfo::PLUGINID_OID_SHORT_NAME = "pluginID";
42 const std::string SignerInfo::PLUGINID_OID_LONG_NAME = "Code Signature Plugin ID";
43
InitSignerInfo(const std::string & ownerID,X509 * cert,const EVP_MD * md,const ByteBuffer & contentData,bool carrySigningTime)44 bool SignerInfo::InitSignerInfo(const std::string &ownerID, X509 *cert, const EVP_MD *md,
45 const ByteBuffer &contentData, bool carrySigningTime)
46 {
47 if ((cert == nullptr) || (md == nullptr)) {
48 return false;
49 }
50 md_ = md;
51 carrySigningTime_ = carrySigningTime;
52 p7info_ = PKCS7_SIGNER_INFO_new();
53 if (p7info_ == nullptr) {
54 ERR_LOG_WITH_OPEN_SSL_MSG("Create pkcs7 signer info failed");
55 return false;
56 }
57 bool ret = false;
58 do {
59 // set default information, pkcs7 signer info version is 1
60 if (!ASN1_INTEGER_set(p7info_->version, 1)) {
61 break;
62 }
63
64 // add sign cert info
65 if (!X509_NAME_set(&p7info_->issuer_and_serial->issuer,
66 X509_get_issuer_name(cert))) {
67 break;
68 }
69 ASN1_INTEGER_free(p7info_->issuer_and_serial->serial);
70 if (!(p7info_->issuer_and_serial->serial =
71 ASN1_INTEGER_dup(X509_get_serialNumber(cert)))) {
72 break;
73 }
74
75 // add digest and signature algorithm
76 if (!X509_ALGOR_set0(p7info_->digest_alg, OBJ_nid2obj(EVP_MD_type(md)),
77 V_ASN1_NULL, nullptr)) {
78 break;
79 }
80 int signatureNid = GetSignAlgorithmID(cert);
81 if (signatureNid < 0) {
82 break;
83 }
84 if (!X509_ALGOR_set0(p7info_->digest_enc_alg, OBJ_nid2obj(signatureNid),
85 V_ASN1_NULL, nullptr)) {
86 break;
87 }
88
89 if (!AddAttrsToSignerInfo(ownerID, contentData)) {
90 ERR_LOG_WITH_OPEN_SSL_MSG("Add attributes to signer info failed");
91 break;
92 }
93 ret = true;
94 } while (0);
95 if (!ret) {
96 PKCS7_SIGNER_INFO_free(p7info_);
97 ERR_LOG_WITH_OPEN_SSL_MSG("Init pkcs7 signer info failed");
98 }
99 return ret;
100 }
101
AddAttrsToSignerInfo(const std::string & ownerID,const ByteBuffer & contentData)102 bool SignerInfo::AddAttrsToSignerInfo(const std::string &ownerID, const ByteBuffer &contentData)
103 {
104 if (!carrySigningTime_ && ownerID.empty()) {
105 unsignedData_ = std::make_unique<ByteBuffer>();
106 if (!unsignedData_->CopyFrom(contentData.GetBuffer(), contentData.GetSize())) {
107 unsignedData_.reset(nullptr);
108 return false;
109 }
110 return true;
111 }
112
113 if (!ownerID.empty()) {
114 AddOwnerID(ownerID);
115 }
116
117 if (!PKCS7_add_attrib_content_type(p7info_, nullptr)) {
118 return false;
119 }
120
121 if (carrySigningTime_) {
122 if (!PKCS7_add0_attrib_signing_time(p7info_, nullptr)) {
123 return false;
124 }
125 }
126
127 ByteBuffer digest;
128 if (!ComputeDigest(contentData, digest)) {
129 return false;
130 }
131 if (!PKCS7_add1_attrib_digest(p7info_, digest.GetBuffer(), digest.GetSize())) {
132 ERR_LOG_WITH_OPEN_SSL_MSG("PKCS7_add1_attrib_digest fail");
133 return false;
134 }
135 return true;
136 }
137
GetDataToSign(uint32_t & len)138 uint8_t *SignerInfo::GetDataToSign(uint32_t &len)
139 {
140 if (p7info_ == nullptr) {
141 return nullptr;
142 }
143
144 uint8_t *data = nullptr;
145 if (p7info_->auth_attr != nullptr) {
146 int itemLen = ASN1_item_i2d(reinterpret_cast<ASN1_VALUE *>(p7info_->auth_attr), &data,
147 ASN1_ITEM_rptr(PKCS7_ATTR_SIGN));
148 if (itemLen < 0) {
149 return nullptr;
150 }
151 len = static_cast<uint32_t>(itemLen);
152 } else {
153 if (unsignedData_ == nullptr) {
154 return nullptr;
155 }
156 data = unsignedData_->GetBuffer();
157 len = unsignedData_->GetSize();
158 }
159 return data;
160 }
161
AddSignatureInSignerInfo(const ByteBuffer & signature)162 bool SignerInfo::AddSignatureInSignerInfo(const ByteBuffer &signature)
163 {
164 if (p7info_ == nullptr) {
165 return false;
166 }
167 uint32_t signatureSize = signature.GetSize();
168 // tmp will be free when freeing p7info_
169 if (signatureSize == 0 || signatureSize > MAX_SIGNATURE_SIZE) {
170 return false;
171 }
172 uint8_t *tmp = static_cast<uint8_t *>(malloc(signatureSize));
173 if (tmp == nullptr) {
174 return false;
175 }
176 (void)memcpy_s(tmp, signatureSize, signature.GetBuffer(), signatureSize);
177 ASN1_STRING_set0(p7info_->enc_digest, tmp, signatureSize);
178 return true;
179 }
180
ComputeDigest(const ByteBuffer & data,ByteBuffer & digest)181 bool SignerInfo::ComputeDigest(const ByteBuffer &data, ByteBuffer &digest)
182 {
183 uint8_t mdBuffer[EVP_MAX_MD_SIZE];
184 uint32_t mdLen = 0;
185 EVP_MD_CTX *mCtx = EVP_MD_CTX_new();
186 bool ret = false;
187 do {
188 if (mCtx == nullptr) {
189 break;
190 }
191 if (!EVP_DigestInit_ex(mCtx, md_, nullptr)) {
192 break;
193 }
194 if (!EVP_DigestUpdate(mCtx, data.GetBuffer(), data.GetSize())) {
195 break;
196 }
197 if (!EVP_DigestFinal_ex(mCtx, mdBuffer, &mdLen)) {
198 break;
199 }
200 ret = true;
201 } while (0);
202 if (!ret) {
203 ERR_LOG_WITH_OPEN_SSL_MSG("Compute digest failed.");
204 } else if (!digest.CopyFrom(mdBuffer, mdLen)) {
205 ret = false;
206 }
207 EVP_MD_CTX_free(mCtx);
208 return ret;
209 }
210
GetSignAlgorithmID(const X509 * cert)211 int SignerInfo::GetSignAlgorithmID(const X509 *cert)
212 {
213 X509_PUBKEY *xpkey = X509_get_X509_PUBKEY(cert);
214 ASN1_OBJECT *koid = nullptr;
215 if (!X509_PUBKEY_get0_param(&koid, nullptr, nullptr, nullptr, xpkey)) {
216 return INVALID_SIGN_ALGORITHM_NID;
217 }
218 int signatureNid = OBJ_obj2nid(koid);
219 if (signatureNid == NID_rsaEncryption) {
220 return signatureNid;
221 }
222 OBJ_find_sigid_by_algs(&signatureNid, EVP_MD_type(md_), signatureNid);
223 return signatureNid;
224 }
225
GetSignerInfo()226 PKCS7_SIGNER_INFO *SignerInfo::GetSignerInfo()
227 {
228 return p7info_;
229 }
230
AddID(const std::string & id,int nid)231 int SignerInfo::AddID(const std::string &id, int nid)
232 {
233 ASN1_STRING *idAsn1 = ASN1_STRING_new();
234 ASN1_STRING_set(idAsn1, id.c_str(), id.length());
235 int ret = PKCS7_add_signed_attribute(p7info_, nid, V_ASN1_UTF8STRING, idAsn1);
236 if (ret == 0) {
237 ASN1_STRING_free(idAsn1);
238 ERR_LOG_WITH_OPEN_SSL_MSG("PKCS7_add_signed_attribute failed");
239 return CS_ERR_OPENSSL_PKCS7;
240 }
241
242 return CS_SUCCESS;
243 }
244
ParseIdFromSignature(const ByteBuffer & sigbuffer,std::string & id,int nid)245 int SignerInfo::ParseIdFromSignature(const ByteBuffer &sigbuffer, std::string &id, int nid)
246 {
247 BIO *bio = BIO_new_mem_buf(sigbuffer.GetBuffer(), sigbuffer.GetSize());
248 if (bio == nullptr) {
249 ERR_LOG_WITH_OPEN_SSL_MSG("BIO_new_mem_buf failed");
250 return CS_ERR_OPENSSL_BIO;
251 }
252 PKCS7 *p7 = d2i_PKCS7_bio(bio, nullptr);
253 if (p7 == nullptr) {
254 BIO_free(bio);
255 ERR_LOG_WITH_OPEN_SSL_MSG("d2i_PKCS7_bio failed");
256 return CS_ERR_OPENSSL_PKCS7;
257 }
258
259 STACK_OF(PKCS7_SIGNER_INFO) *signerInfosk = PKCS7_get_signer_info(p7);
260 if (signerInfosk == nullptr) {
261 BIO_free(bio);
262 PKCS7_free(p7);
263 ERR_LOG_WITH_OPEN_SSL_MSG("PKCS7_get_signer_info failed");
264 return CS_ERR_OPENSSL_PKCS7;
265 }
266 for (int i = 0; i < sk_PKCS7_SIGNER_INFO_num(signerInfosk); i++) {
267 PKCS7_SIGNER_INFO *signerInfo = sk_PKCS7_SIGNER_INFO_value(signerInfosk, i);
268 ASN1_TYPE *asn1Type = PKCS7_get_signed_attribute(signerInfo, nid);
269 if (asn1Type != nullptr && asn1Type->type == V_ASN1_UTF8STRING) {
270 ASN1_STRING *result = asn1Type->value.asn1_string;
271 id.assign(reinterpret_cast<const char *>(ASN1_STRING_get0_data(result)), ASN1_STRING_length(result));
272 break;
273 }
274 }
275 BIO_free(bio);
276 PKCS7_free(p7);
277 return CS_SUCCESS;
278 }
279
AddOwnerID(const std::string & ownerID)280 int SignerInfo::AddOwnerID(const std::string &ownerID)
281 {
282 int nid = CreateNIDFromOID(OWNERID_OID, OWNERID_OID_SHORT_NAME, OWNERID_OID_LONG_NAME);
283
284 return AddID(ownerID, nid);
285 }
286
ParseOwnerIdFromSignature(const ByteBuffer & sigbuffer,std::string & ownerID)287 int SignerInfo::ParseOwnerIdFromSignature(const ByteBuffer &sigbuffer, std::string &ownerID)
288 {
289 int nid = CreateNIDFromOID(OWNERID_OID, OWNERID_OID_SHORT_NAME, OWNERID_OID_LONG_NAME);
290 int err = ParseIdFromSignature(sigbuffer, ownerID, nid);
291 if (err != CS_SUCCESS) {
292 return err;
293 }
294 if (ownerID.empty()) {
295 return CS_ERR_NO_OWNER_ID;
296 }
297 return CS_SUCCESS;
298 }
299
ParsePluginIdFromSignature(const ByteBuffer & sigbuffer,std::string & pluginID)300 int SignerInfo::ParsePluginIdFromSignature(const ByteBuffer &sigbuffer, std::string &pluginID)
301 {
302 int nid = CreateNIDFromOID(PLUGINID_OID, PLUGINID_OID_SHORT_NAME, PLUGINID_OID_LONG_NAME);
303 int err = ParseIdFromSignature(sigbuffer, pluginID, nid);
304 if (err != CS_SUCCESS) {
305 return err;
306 }
307 if (pluginID.empty()) {
308 return CS_ERR_NO_PLUGIN_ID;
309 }
310 return CS_SUCCESS;
311 }
312
313 }
314 }
315 }
316