1 /*
2 * Copyright (c) 2024-2024 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 #include <vector>
16
17 #include "constant.h"
18 #include "pkcs7_data.h"
19 #include "local_signer.h"
20 #include "signer_config.h"
21 #include "signature_tools_log.h"
22 #include "signature_algorithm_helper.h"
23 #include "signature_tools_errno.h"
24 #include "bc_signeddata_generator.h"
25
26 namespace OHOS {
27 namespace SignatureTools {
28
GenerateSignedData(const std::string & content,SignerConfig * signerConfig,std::string & ret)29 int BCSignedDataGenerator::GenerateSignedData(const std::string& content,
30 SignerConfig* signerConfig, std::string& ret)
31 {
32 std::string sigAlg;
33 int result = RET_OK;
34 if (content.empty()) {
35 PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR,
36 "digest content is empty, generate signed data failed");
37 return INVALIDPARAM_ERROR;
38 }
39 if (signerConfig == NULL) {
40 PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR,
41 "signerConfig is NULL");
42 return INVALIDPARAM_ERROR;
43 }
44 std::shared_ptr<Signer> signer = signerConfig->GetSigner();
45 if (signer == NULL) {
46 PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR,
47 "signer is NULL");
48 return INVALIDPARAM_ERROR;
49 }
50 result = GetSigAlg(signerConfig, sigAlg);
51 if (result < 0) {
52 SIGNATURE_TOOLS_LOGE("get sign algorithm from signerConfig failed");
53 return INVALIDPARAM_ERROR;
54 }
55 result = PackageSignedData(content, signer, sigAlg, ret);
56 if (result < 0) {
57 SIGNATURE_TOOLS_LOGE("package signed data failed");
58 return result;
59 }
60 return result;
61 }
62
SetOwnerId(const std::string & ownerID)63 void BCSignedDataGenerator::SetOwnerId(const std::string& ownerID)
64 {
65 m_ownerID = ownerID;
66 }
67
PackageSignedData(const std::string & content,const std::shared_ptr<Signer> & signer,const std::string & sigAlg,std::string & ret)68 int BCSignedDataGenerator::PackageSignedData(const std::string& content, const std::shared_ptr<Signer>& signer,
69 const std::string& sigAlg, std::string& ret)
70 {
71 int result = RET_OK;
72 PKCS7Data p7Data(PKCS7_DETACHED_FLAGS);
73 std::vector<PKCS7Attr> attrs;
74 if (m_ownerID.empty() == false) {
75 if (AddOwnerID(attrs, m_ownerID) < 0) {
76 PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR,
77 "create ownerIDOid failed");
78 return INVALIDPARAM_ERROR;
79 }
80 }
81 // Generate PKCS#7
82 result = p7Data.Sign(content, signer, sigAlg, ret, attrs);
83 if (result < 0) {
84 SIGNATURE_TOOLS_LOGE("generate pkcs7 signed data block failed");
85 return SIGN_ERROR;
86 }
87 // Verify after parsing
88 result = p7Data.Parse(ret);
89 if (result < 0) {
90 SIGNATURE_TOOLS_LOGE("verify pkcs7 signed data block bytes failed");
91 return PARSE_ERROR;
92 }
93 result = p7Data.Verify(content);
94 if (result < 0) {
95 SIGNATURE_TOOLS_LOGE("verify pkcs7 signed data block failed");
96 return VERIFY_ERROR;
97 }
98 return result;
99 }
100
GetSigAlg(SignerConfig * signerConfig,std::string & sigAlg)101 int BCSignedDataGenerator::GetSigAlg(SignerConfig* signerConfig, std::string& sigAlg)
102 {
103 std::vector<SignatureAlgorithmHelper> sigs = signerConfig->GetSignatureAlgorithms();
104 if (sigs.size() != 1) {
105 PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR, "sigAlg count not equal to 1");
106 return INVALIDPARAM_ERROR;
107 }
108 SignatureAlgorithmHelper signatureAlg = sigs[0];
109 if (signatureAlg.m_id == SignatureAlgorithmId::ECDSA_WITH_SHA256) {
110 sigAlg = SIGN_ALG_SHA256;
111 } else if (signatureAlg.m_id == SignatureAlgorithmId::ECDSA_WITH_SHA384) {
112 sigAlg = SIGN_ALG_SHA384;
113 } else {
114 PrintErrorNumberMsg("INVALIDPARAM_ERROR", INVALIDPARAM_ERROR,
115 sigAlg + "is invalid sigAlg, please use SHA256withECDSA/SHA384withECDSA, sign failed");
116 return NOT_SUPPORT_ERROR;
117 }
118 return RET_OK;
119 }
120
CreateNIDFromOID(const std::string & oid,const std::string & shortName,const std::string & longName)121 int BCSignedDataGenerator::CreateNIDFromOID(const std::string& oid, const std::string& shortName,
122 const std::string& longName)
123 {
124 int nid = OBJ_txt2nid(oid.c_str());
125 if (nid == NID_undef) {
126 nid = OBJ_create(oid.c_str(), shortName.c_str(), longName.c_str());
127 }
128 return nid;
129 }
130
AddOwnerID(std::vector<PKCS7Attr> & attrs,const std::string & ownerID)131 int BCSignedDataGenerator::AddOwnerID(std::vector<PKCS7Attr>& attrs, const std::string& ownerID)
132 {
133 PKCS7Attr attr;
134 int nid = CreateNIDFromOID(OWNERID_OID, OWNERID_OID_SHORT_NAME, OWNERID_OID_LONG_NAME);
135 if (nid == NID_undef) {
136 return RET_FAILED;
137 }
138 ASN1_STRING* ownerIDAsn1 = ASN1_STRING_new();
139 if (ownerIDAsn1 == NULL) {
140 SIGNATURE_TOOLS_LOGE("asn1 string create error!\n");
141 return RET_FAILED;
142 }
143 ASN1_STRING_set(ownerIDAsn1, ownerID.c_str(), ownerID.length());
144 attr.nid = nid;
145 attr.atrtype = V_ASN1_UTF8STRING;
146 attr.value = ownerIDAsn1;
147 attrs.push_back(attr);
148 return RET_OK;
149 }
150 } // namespace SignatureTools
151 } // namespace OHOS