• 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 #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 }