• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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