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