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 #include "log.h"
18 #include "openssl/asn1.h"
19 #include "openssl/pem.h"
20 #include "openssl_utils.h"
21 #include "securec.h"
22
23 namespace OHOS {
24 namespace Security {
25 namespace CodeSign {
26 static constexpr int INVALID_SIGN_ALGORITHM_NID = -1;
27 static constexpr int MAX_SIGNATURE_SIZE = 1024; // 1024: max signature length
28
InitSignerInfo(X509 * cert,const EVP_MD * md,const ByteBuffer & contentData,bool carrySigningTime)29 bool SignerInfo::InitSignerInfo(X509 *cert, const EVP_MD *md,
30 const ByteBuffer &contentData, bool carrySigningTime)
31 {
32 if ((cert == nullptr) || (md == nullptr)) {
33 return false;
34 }
35 md_ = md;
36 carrySigningTime_ = carrySigningTime;
37 p7info_ = PKCS7_SIGNER_INFO_new();
38 if (p7info_ == nullptr) {
39 ErrLogWithOpenSSLMsg("Create pkcs7 signer info failed");
40 return false;
41 }
42 bool ret = false;
43 do {
44 // set default information, pkcs7 signer info version is 1
45 if (!ASN1_INTEGER_set(p7info_->version, 1)) {
46 break;
47 }
48
49 // add sign cert info
50 if (!X509_NAME_set(&p7info_->issuer_and_serial->issuer,
51 X509_get_issuer_name(cert))) {
52 break;
53 }
54 ASN1_INTEGER_free(p7info_->issuer_and_serial->serial);
55 if (!(p7info_->issuer_and_serial->serial =
56 ASN1_INTEGER_dup(X509_get_serialNumber(cert)))) {
57 break;
58 }
59
60 // add digest and signature algorithm
61 if (!X509_ALGOR_set0(p7info_->digest_alg, OBJ_nid2obj(EVP_MD_type(md)),
62 V_ASN1_NULL, nullptr)) {
63 break;
64 }
65 int signatureNid = GetSignAlgorithmID(cert);
66 if (signatureNid < 0) {
67 break;
68 }
69 if (!X509_ALGOR_set0(p7info_->digest_enc_alg, OBJ_nid2obj(signatureNid),
70 V_ASN1_NULL, nullptr)) {
71 break;
72 }
73 if (!AddAttrsToSignerInfo(contentData)) {
74 ErrLogWithOpenSSLMsg("Add attributes to signer info failed");
75 break;
76 }
77 ret = true;
78 } while (0);
79 if (!ret) {
80 PKCS7_SIGNER_INFO_free(p7info_);
81 ErrLogWithOpenSSLMsg("Init pkcs7 signer info failed");
82 }
83 return ret;
84 }
85
AddAttrsToSignerInfo(const ByteBuffer & contentData)86 bool SignerInfo::AddAttrsToSignerInfo(const ByteBuffer &contentData)
87 {
88 if (!carrySigningTime_) {
89 unsignedData_ = std::make_unique<ByteBuffer>();
90 if (!unsignedData_->CopyFrom(contentData.GetBuffer(), contentData.GetSize())) {
91 unsignedData_.reset(nullptr);
92 return false;
93 }
94 return true;
95 }
96 if (!PKCS7_add_attrib_content_type(p7info_, nullptr)) {
97 return false;
98 }
99 if (!PKCS7_add0_attrib_signing_time(p7info_, nullptr)) {
100 return false;
101 }
102 ByteBuffer digest;
103 if (!ComputeDigest(contentData, digest)) {
104 return false;
105 }
106 if (!PKCS7_add1_attrib_digest(p7info_, digest.GetBuffer(), digest.GetSize())) {
107 return false;
108 }
109 return true;
110 }
111
GetDataToSign(uint32_t & len)112 uint8_t *SignerInfo::GetDataToSign(uint32_t &len)
113 {
114 if (p7info_ == nullptr) {
115 return nullptr;
116 }
117
118 uint8_t *data = nullptr;
119 if (carrySigningTime_) {
120 int itemLen = ASN1_item_i2d(reinterpret_cast<ASN1_VALUE *>(p7info_->auth_attr), &data,
121 ASN1_ITEM_rptr(PKCS7_ATTR_SIGN));
122 if (itemLen < 0) {
123 return nullptr;
124 }
125 len = itemLen;
126 } else {
127 if (unsignedData_ == nullptr) {
128 return nullptr;
129 }
130 data = unsignedData_->GetBuffer();
131 len = unsignedData_->GetSize();
132 }
133 return data;
134 }
135
AddSignatureInSignerInfo(const ByteBuffer & signature)136 bool SignerInfo::AddSignatureInSignerInfo(const ByteBuffer &signature)
137 {
138 if (p7info_ == nullptr) {
139 return false;
140 }
141 uint32_t signatureSize = signature.GetSize();
142 // tmp will be free when freeing p7info_
143 if (signatureSize == 0 || signatureSize > MAX_SIGNATURE_SIZE) {
144 return false;
145 }
146 uint8_t *tmp = static_cast<uint8_t *>(malloc(signatureSize));
147 if (tmp == nullptr) {
148 return false;
149 }
150 (void)memcpy_s(tmp, signatureSize, signature.GetBuffer(), signatureSize);
151 ASN1_STRING_set0(p7info_->enc_digest, tmp, signatureSize);
152 return true;
153 }
154
ComputeDigest(const ByteBuffer & data,ByteBuffer & digest)155 bool SignerInfo::ComputeDigest(const ByteBuffer &data, ByteBuffer &digest)
156 {
157 uint8_t mdBuffer[EVP_MAX_MD_SIZE];
158 uint32_t mdLen = 0;
159 EVP_MD_CTX *mCtx = EVP_MD_CTX_new();
160 bool ret = false;
161 do {
162 if (mCtx == nullptr) {
163 break;
164 }
165 if (!EVP_DigestInit_ex(mCtx, md_, nullptr)) {
166 break;
167 }
168 if (!EVP_DigestUpdate(mCtx, data.GetBuffer(), data.GetSize())) {
169 break;
170 }
171 if (!EVP_DigestFinal_ex(mCtx, mdBuffer, &mdLen)) {
172 break;
173 }
174 ret = true;
175 } while (0);
176 if (!ret) {
177 ErrLogWithOpenSSLMsg("Compute digest failed.");
178 } else if (!digest.CopyFrom(mdBuffer, mdLen)) {
179 ret = false;
180 }
181 EVP_MD_CTX_free(mCtx);
182 return ret;
183 }
184
GetSignAlgorithmID(const X509 * cert)185 int SignerInfo::GetSignAlgorithmID(const X509 *cert)
186 {
187 X509_PUBKEY *xpkey = X509_get_X509_PUBKEY(cert);
188 ASN1_OBJECT *koid = nullptr;
189 if (!X509_PUBKEY_get0_param(&koid, nullptr, nullptr, nullptr, xpkey)) {
190 return INVALID_SIGN_ALGORITHM_NID;
191 }
192 int signatureNid = OBJ_obj2nid(koid);
193 if (signatureNid == NID_rsaEncryption) {
194 return signatureNid;
195 }
196 OBJ_find_sigid_by_algs(&signatureNid, EVP_MD_type(md_), signatureNid);
197 return signatureNid;
198 }
199
GetSignerInfo()200 PKCS7_SIGNER_INFO *SignerInfo::GetSignerInfo()
201 {
202 return p7info_;
203 }
204 }
205 }
206 }