• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 "pkg_algo_sign.h"
16 #include <openssl/bio.h>
17 #include <openssl/bn.h>
18 #include <openssl/ec.h>
19 #include <openssl/ecdsa.h>
20 #include <openssl/evp.h>
21 #include <openssl/obj_mac.h>
22 #include <openssl/pem.h>
23 #include <openssl/rsa.h>
24 #include <openssl/sha.h>
25 #include "openssl_util.h"
26 #include "pkg_algorithm.h"
27 #include "pkg_utils.h"
28 
29 using namespace Updater;
30 
31 namespace Hpackage {
32 #ifndef BIO_FP_READ
33 constexpr uint32_t BIO_FP_READ = 0x02;
34 #endif
SignBuffer(const PkgBuffer & buffer,std::vector<uint8_t> & sign,size_t & signLen) const35 int32_t SignAlgorithmRsa::SignBuffer(const PkgBuffer &buffer, std::vector<uint8_t> &sign, size_t &signLen) const
36 {
37     if (buffer.buffer == nullptr) {
38         PKG_LOGE("Param null!");
39         return PKG_INVALID_PARAM;
40     }
41     BIO *in = BIO_new(BIO_s_file());
42     if (in == nullptr) {
43         PKG_LOGE("Failed to new BIO");
44         return PKG_INVALID_PARAM;
45     }
46 
47     int32_t ret = BIO_ctrl(in, BIO_C_SET_FILENAME, BIO_CLOSE | BIO_FP_READ, const_cast<char*>(keyName_.c_str()));
48     if (ret != 1) {
49         PKG_LOGE("Failed to BIO_read_filename ret %d %s", ret, keyName_.c_str());
50         BIO_free(in);
51         return PKG_INVALID_PARAM;
52     }
53 
54     RSA *rsa = PEM_read_bio_RSAPrivateKey(in, nullptr, nullptr, nullptr);
55     BIO_free(in);
56     if (rsa == nullptr) {
57         PKG_LOGE("Failed to PEM_read_bio_RSAPrivateKey ");
58         return PKG_INVALID_SIGNATURE;
59     }
60 
61     // Adjust key size
62     uint32_t size = static_cast<uint32_t>(RSA_size(rsa));
63     sign.resize(size);
64     ret = 0;
65     if (digestMethod_ == PKG_DIGEST_TYPE_SHA256) {
66         ret = RSA_sign(NID_sha256, buffer.buffer, buffer.length, sign.data(), &size, rsa);
67     } else if (digestMethod_ == PKG_DIGEST_TYPE_SHA384) {
68         ret = RSA_sign(NID_sha384, buffer.buffer, buffer.length, sign.data(), &size, rsa);
69     }
70     signLen = size;
71     RSA_free(rsa);
72     return ((ret == 1) ? PKG_SUCCESS : PKG_INVALID_SIGNATURE);
73 }
74 
SignBuffer(const PkgBuffer & buffer,std::vector<uint8_t> & sign,size_t & signLen) const75 int32_t SignAlgorithmEcc::SignBuffer(const PkgBuffer &buffer, std::vector<uint8_t> &sign, size_t &signLen) const
76 {
77     if (buffer.buffer == nullptr) {
78         PKG_LOGE("Param null!");
79         return PKG_INVALID_PARAM;
80     }
81     BIO *in = BIO_new(BIO_s_file());
82     if (in == nullptr) {
83         PKG_LOGE("Failed to new BIO ");
84         return PKG_INVALID_PARAM;
85     }
86 
87     int ret = BIO_ctrl(in, BIO_C_SET_FILENAME, BIO_CLOSE | BIO_FP_READ, const_cast<char*>(keyName_.c_str()));
88     if (ret != 1) {
89         PKG_LOGE("Failed to BIO_read_filename ret %d %s", ret, keyName_.c_str());
90         BIO_free(in);
91         return PKG_INVALID_PARAM;
92     }
93 
94     EC_KEY *ecKey = PEM_read_bio_ECPrivateKey(in, nullptr, nullptr, nullptr);
95     BIO_free(in);
96     if (ecKey == nullptr) {
97         PKG_LOGE("Failed to PEM_read_bio_ECPrivateKey %s", keyName_.c_str());
98         return PKG_INVALID_PARAM;
99     }
100 
101     // Adjust key size
102     uint32_t size = static_cast<uint32_t>(ECDSA_size(ecKey));
103     sign.resize(size + sizeof(uint32_t));
104     ret = ECDSA_sign(0, buffer.buffer, buffer.length, sign.data() + sizeof(uint32_t), &size, ecKey);
105     WriteLE32(sign.data(), size);
106     signLen = size + sizeof(uint32_t);
107     EC_KEY_free(ecKey);
108     return ((ret == 1) ? PKG_SUCCESS : PKG_INVALID_SIGNATURE);
109 }
110 
GetPubkey() const111 X509 *SignAlgorithm::GetPubkey() const
112 {
113     BIO *certbio = BIO_new_file(keyName_.c_str(), "r");
114     if (certbio == nullptr) {
115         PKG_LOGE("Failed to create BIO");
116         return nullptr;
117     }
118     X509 *rcert = PEM_read_bio_X509(certbio, nullptr, nullptr, nullptr);
119     if (rcert == nullptr) {
120         PKG_LOGE("Failed to read x509 certificate");
121         BIO_free(certbio);
122         return nullptr;
123     }
124     BIO_free(certbio);
125     return rcert;
126 }
127 
VerifyDigest(const std::vector<uint8_t> & digest,const std::vector<uint8_t> & signature)128 int32_t SignAlgorithm::VerifyDigest(const std::vector<uint8_t> &digest, const std::vector<uint8_t> &signature)
129 {
130     X509 *rcert = GetPubkey();
131     if (rcert == nullptr) {
132         PKG_LOGE("get pubkey fail");
133         return PKG_INVALID_SIGNATURE;
134     }
135     EVP_PKEY *pubKey = X509_get_pubkey(rcert);
136     if (pubKey == nullptr) {
137         X509_free(rcert);
138         PKG_LOGE("get pubkey from cert fail");
139         return PKG_INVALID_SIGNATURE;
140     }
141     int nid = EVP_MD_type(EVP_sha256());
142     int ret = VerifyDigestByPubKey(pubKey, nid, digest, signature);
143     if (ret != 0) {
144         X509_free(rcert);
145         PKG_LOGE("Failed to verify digest by pubKey");
146         return PKG_INVALID_SIGNATURE;
147     }
148     X509_free(rcert);
149     return 0;
150 }
151 
GetSignAlgorithm(const std::string & path,uint8_t signMethod,uint8_t type)152 SignAlgorithm::SignAlgorithmPtr PkgAlgorithmFactory::GetSignAlgorithm(const std::string &path,
153     uint8_t signMethod, uint8_t type)
154 {
155     switch (signMethod) {
156         case PKG_SIGN_METHOD_RSA:
157             return std::make_shared<SignAlgorithmRsa>(path, type);
158         case PKG_SIGN_METHOD_ECDSA:
159             return std::make_shared<SignAlgorithmEcc>(path, type);
160         default:
161             break;
162     }
163     return nullptr;
164 }
165 
GetVerifyAlgorithm(const std::string & path,uint8_t type)166 SignAlgorithm::SignAlgorithmPtr PkgAlgorithmFactory::GetVerifyAlgorithm(const std::string &path, uint8_t type)
167 {
168     return std::make_shared<VerifyAlgorithm>(path, type);
169 }
170 } // namespace Hpackage
171