• 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 "pkg_algorithm.h"
26 #include "pkg_utils.h"
27 
28 using namespace updater;
29 
30 namespace hpackage {
31 #ifndef BIO_FP_READ
32 constexpr uint32_t BIO_FP_READ = 0x02;
33 #endif
SignBuffer(const PkgBuffer & buffer,std::vector<uint8_t> & signedData,size_t & signLen) const34 int32_t SignAlgorithmRsa::SignBuffer(const PkgBuffer &buffer, std::vector<uint8_t> &signedData,
35     size_t &signLen) const
36 {
37     PKG_CHECK(buffer.buffer != nullptr, return PKG_INVALID_PARAM, "Param null!");
38     BIO *in = BIO_new(BIO_s_file());
39     PKG_CHECK(in != nullptr, return PKG_INVALID_PARAM, "Failed to new BIO ");
40 
41     int32_t ret = BIO_ctrl(in, BIO_C_SET_FILENAME, BIO_CLOSE | BIO_FP_READ, const_cast<char*>(keyName_.c_str()));
42     PKG_CHECK(ret == 1, BIO_free(in);
43         return PKG_INVALID_PARAM, "Failed to BIO_read_filename ret %d %s", ret, keyName_.c_str());
44 
45     RSA *rsa = PEM_read_bio_RSAPrivateKey(in, nullptr, nullptr, nullptr);
46     BIO_free(in);
47     PKG_CHECK(rsa != nullptr, return PKG_INVALID_SIGNATURE, "Failed to PEM_read_bio_RSAPrivateKey ");
48 
49     // Adjust key size
50     uint32_t size = RSA_size(rsa);
51     signedData.resize(size);
52     ret = 0;
53     if (digestMethod_ == PKG_DIGEST_TYPE_SHA256) {
54         ret = RSA_sign(NID_sha256, buffer.buffer, buffer.length, signedData.data(), &size, rsa);
55     } else if (digestMethod_ == PKG_DIGEST_TYPE_SHA384) {
56         ret = RSA_sign(NID_sha384, buffer.buffer, buffer.length, signedData.data(), &size, rsa);
57     }
58     signLen = size;
59     RSA_free(rsa);
60     return ((ret == 1) ? PKG_SUCCESS : PKG_INVALID_SIGNATURE);
61 }
62 
SignBuffer(const PkgBuffer & buffer,std::vector<uint8_t> & signedData,size_t & signLen) const63 int32_t SignAlgorithmEcc::SignBuffer(const PkgBuffer &buffer, std::vector<uint8_t> &signedData,
64     size_t &signLen) const
65 {
66     PKG_CHECK(buffer.buffer != nullptr, return PKG_INVALID_PARAM, "Param null!");
67     BIO *in = BIO_new(BIO_s_file());
68     PKG_CHECK(in != nullptr, return PKG_INVALID_PARAM, "Failed to new BIO ");
69 
70     int ret = BIO_ctrl(in, BIO_C_SET_FILENAME, BIO_CLOSE | BIO_FP_READ, const_cast<char*>(keyName_.c_str()));
71     PKG_CHECK(ret == 1, BIO_free(in);
72         return PKG_INVALID_PARAM, "Failed to BIO_read_filename ret %d %s", ret, keyName_.c_str());
73 
74     EC_KEY *ecKey = PEM_read_bio_ECPrivateKey(in, nullptr, nullptr, nullptr);
75     BIO_free(in);
76     PKG_CHECK(ecKey != nullptr, return PKG_INVALID_PARAM, "Failed to PEM_read_bio_ECPrivateKey %s", keyName_.c_str());
77 
78     // Adjust key size
79     uint32_t size = ECDSA_size(ecKey);
80     signedData.resize(size + sizeof(uint32_t));
81     ret = ECDSA_sign(0, buffer.buffer, buffer.length, signedData.data() + sizeof(uint32_t), &size, ecKey);
82     WriteLE32(signedData.data(), size);
83     signLen = size + sizeof(uint32_t);
84     EC_KEY_free(ecKey);
85     return ((ret == 1) ? PKG_SUCCESS : PKG_INVALID_SIGNATURE);
86 }
87 
CheckRsaKey(const RSA * rsakey,int & hashLen) const88 bool VerifyAlgorithm::CheckRsaKey(const RSA *rsakey, int &hashLen) const
89 {
90     const BIGNUM *rsaN = nullptr;
91     const BIGNUM *rsaE = nullptr;
92     RSA_get0_key(rsakey, &rsaN, &rsaE, nullptr);
93     auto modulusbits = BN_num_bits(rsaN);
94     if (modulusbits == 2048) { // 2048 hash leng
95         hashLen = SHA256_DIGEST_LENGTH;
96     } else if (modulusbits == 3072) { // 3072 hash leng
97         hashLen = SHA384_DIGEST_LENGTH;
98     } else {
99         PKG_LOGE("Modulus should be 2048 bits long, actual:%d ", modulusbits);
100         return false;
101     }
102     BN_ULONG exponent = BN_get_word(rsaE);
103     PKG_CHECK(!(exponent != 3 && exponent != 65537),
104         return false, "Public exponent should be 3 or 65537, actual:%d \n", exponent);
105     return true;
106 }
107 
CheckEccKey(const EC_KEY * eccKey) const108 bool VerifyAlgorithm::CheckEccKey(const EC_KEY *eccKey) const
109 {
110     const EC_GROUP *eccgroup = EC_KEY_get0_group(eccKey);
111     PKG_CHECK(eccgroup != nullptr, return false, "Failed to get the ec_group from the ecKey");
112     auto eccdegree = EC_GROUP_get_degree(eccgroup);
113     PKG_CHECK(eccdegree == 256, return false,
114         "Field size of the ec key should be 256 bits long, actual:%d ", eccdegree);
115     return true;
116 }
117 
LoadPubKey(const std::string & keyfile,struct CertKeySt & certs) const118 bool VerifyAlgorithm::LoadPubKey(const std::string &keyfile, struct CertKeySt &certs) const
119 {
120     BIO *certbio = BIO_new_file(keyfile.c_str(), "r");
121     PKG_CHECK(certbio != nullptr, return false, "Failed to create BIO");
122 
123     X509 *rcert = PEM_read_bio_X509(certbio, nullptr, 0, nullptr);
124     BIO_free(certbio);
125     PKG_CHECK(rcert != nullptr, return false, "Failed to read x509 certificate ");
126     int nid = X509_get_signature_nid(rcert);
127     PKG_CHECK((nid == NID_sha256WithRSAEncryption || nid == NID_ecdsa_with_SHA256), X509_free(rcert);
128         return false, "Unrecognized nid %d", nid);
129 
130     certs.hashLen = SHA256_DIGEST_LENGTH;
131     EVP_PKEY *pubKey = X509_get_pubkey(rcert);
132     PKG_CHECK(pubKey != nullptr, X509_free(rcert);
133         return false, "Failed to extract the public key from x509 certificate %s", keyfile.c_str());
134 
135     bool ret = false;
136     int keyType = EVP_PKEY_id(pubKey);
137     if (keyType == EVP_PKEY_RSA) {
138         certs.keyType = KEY_TYPE_RSA;
139         certs.rsa = EVP_PKEY_get1_RSA(pubKey);
140         PKG_CHECK(certs.rsa != nullptr, X509_free(rcert); return false, "Failed to get rsa");
141         ret = CheckRsaKey(certs.rsa, certs.hashLen);
142         PKG_CHECK(ret == true, RSA_free(certs.rsa); X509_free(rcert); return false, "Check rsa key failed");
143     }
144     if (keyType == EVP_PKEY_EC) {
145         certs.keyType = KEY_TYPE_EC;
146         certs.ecKey = EVP_PKEY_get1_EC_KEY(pubKey);
147         PKG_CHECK(certs.ecKey != nullptr, X509_free(rcert); return false, "Failed to get ec key");
148         ret = CheckEccKey(certs.ecKey);
149         PKG_CHECK(ret == true, EC_KEY_free(certs.ecKey); X509_free(rcert); return false, "Check ec key failed");
150     }
151     EVP_PKEY_free(pubKey);
152     certs.cert = rcert;
153     return ret;
154 }
155 
VerifyBuffer(const std::vector<uint8_t> & digest,const std::vector<uint8_t> & signature)156 int32_t VerifyAlgorithm::VerifyBuffer(const std::vector<uint8_t> &digest, const std::vector<uint8_t> &signature)
157 {
158     struct CertKeySt certs {};
159     bool isValid = LoadPubKey(keyName_, certs);
160     PKG_CHECK(isValid, return PKG_INVALID_SIGNATURE, "Failed to load public key");
161 
162     int hashNid = NID_sha1;
163     if (certs.hashLen == SHA256_DIGEST_LENGTH) {
164         hashNid = NID_sha256;
165     } else if (certs.hashLen == SHA384_DIGEST_LENGTH) {
166         hashNid = NID_sha384;
167     }
168     int ret = 0;
169     if (certs.keyType == KEY_TYPE_RSA) {
170         ret = RSA_verify(hashNid, digest.data(), digest.size(), signature.data(), signature.size(), certs.rsa);
171         RSA_free(certs.rsa);
172     } else if (certs.keyType == KEY_TYPE_EC && certs.hashLen == SHA256_DIGEST_LENGTH) {
173         int dataLen = ReadLE32(signature.data());
174         ret = ECDSA_verify(0, digest.data(), digest.size(), signature.data() + sizeof(uint32_t), dataLen, certs.ecKey);
175         EC_KEY_free(certs.ecKey);
176     }
177     X509_free(certs.cert);
178     return ((ret == 1) ? PKG_SUCCESS : PKG_INVALID_SIGNATURE);
179 }
180 
GetSignAlgorithm(const std::string & path,uint8_t signMethod,uint8_t type)181 SignAlgorithm::SignAlgorithmPtr PkgAlgorithmFactory::GetSignAlgorithm(const std::string &path,
182     uint8_t signMethod, uint8_t type)
183 {
184     switch (signMethod) {
185         case PKG_SIGN_METHOD_RSA:
186             return std::make_shared<SignAlgorithmRsa>(path, type);
187         case PKG_SIGN_METHOD_ECDSA:
188             return std::make_shared<SignAlgorithmEcc>(path, type);
189         default:
190             break;
191     }
192     return nullptr;
193 }
194 
GetVerifyAlgorithm(const std::string & path,uint8_t type)195 SignAlgorithm::SignAlgorithmPtr PkgAlgorithmFactory::GetVerifyAlgorithm(const std::string &path, uint8_t type)
196 {
197     return std::make_shared<VerifyAlgorithm>(path, type);
198 }
199 } // namespace hpackage
200