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 EVP_PKEY_free(pubKey); 145 X509_free(rcert); 146 PKG_LOGE("Failed to verify digest by pubKey"); 147 return PKG_INVALID_SIGNATURE; 148 } 149 EVP_PKEY_free(pubKey); 150 X509_free(rcert); 151 return 0; 152 } 153 GetSignAlgorithm(const std::string & path,uint8_t signMethod,uint8_t type)154 SignAlgorithm::SignAlgorithmPtr PkgAlgorithmFactory::GetSignAlgorithm(const std::string &path, 155 uint8_t signMethod, uint8_t type) 156 { 157 switch (signMethod) { 158 case PKG_SIGN_METHOD_RSA: 159 return std::make_shared<SignAlgorithmRsa>(path, type); 160 case PKG_SIGN_METHOD_ECDSA: 161 return std::make_shared<SignAlgorithmEcc>(path, type); 162 default: 163 break; 164 } 165 return nullptr; 166 } 167 GetVerifyAlgorithm(const std::string & path,uint8_t type)168 SignAlgorithm::SignAlgorithmPtr PkgAlgorithmFactory::GetVerifyAlgorithm(const std::string &path, uint8_t type) 169 { 170 return std::make_shared<VerifyAlgorithm>(path, type); 171 } 172 } // namespace Hpackage 173