1fb299fa2Sopenharmony_ci/* 2fb299fa2Sopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd. 3fb299fa2Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4fb299fa2Sopenharmony_ci * you may not use this file except in compliance with the License. 5fb299fa2Sopenharmony_ci * You may obtain a copy of the License at 6fb299fa2Sopenharmony_ci * 7fb299fa2Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8fb299fa2Sopenharmony_ci * 9fb299fa2Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10fb299fa2Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11fb299fa2Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12fb299fa2Sopenharmony_ci * See the License for the specific language governing permissions and 13fb299fa2Sopenharmony_ci * limitations under the License. 14fb299fa2Sopenharmony_ci */ 15fb299fa2Sopenharmony_ci 16fb299fa2Sopenharmony_ci#include "openssl_util.h" 17fb299fa2Sopenharmony_ci#include <fstream> 18fb299fa2Sopenharmony_ci#include <openssl/pem.h> 19fb299fa2Sopenharmony_ci#include <openssl/sha.h> 20fb299fa2Sopenharmony_ci#include <openssl/x509.h> 21fb299fa2Sopenharmony_ci#include "dump.h" 22fb299fa2Sopenharmony_ci 23fb299fa2Sopenharmony_cinamespace Hpackage { 24fb299fa2Sopenharmony_cinamespace { 25fb299fa2Sopenharmony_ciconstexpr uint32_t HASH_SOURCE_BLOCK_LEN = 4096; 26fb299fa2Sopenharmony_ci 27fb299fa2Sopenharmony_civoid GetTextContentFromX509Name(X509_NAME *name, int nId, std::string &textContent) 28fb299fa2Sopenharmony_ci{ 29fb299fa2Sopenharmony_ci int contentLen = X509_NAME_get_text_by_NID(name, nId, nullptr, 0); 30fb299fa2Sopenharmony_ci if (contentLen <= 0) { 31fb299fa2Sopenharmony_ci return; 32fb299fa2Sopenharmony_ci } 33fb299fa2Sopenharmony_ci 34fb299fa2Sopenharmony_ci std::unique_ptr<char[]> textBuffer = std::make_unique<char[]>(contentLen + 1); 35fb299fa2Sopenharmony_ci if (textBuffer == nullptr) { 36fb299fa2Sopenharmony_ci return; 37fb299fa2Sopenharmony_ci } 38fb299fa2Sopenharmony_ci 39fb299fa2Sopenharmony_ci if (X509_NAME_get_text_by_NID(name, nId, textBuffer.get(), contentLen + 1) != contentLen) { 40fb299fa2Sopenharmony_ci return; 41fb299fa2Sopenharmony_ci } 42fb299fa2Sopenharmony_ci textContent = std::string(textBuffer.get()); 43fb299fa2Sopenharmony_ci textBuffer.reset(nullptr); 44fb299fa2Sopenharmony_ci 45fb299fa2Sopenharmony_ci return; 46fb299fa2Sopenharmony_ci} 47fb299fa2Sopenharmony_ci} 48fb299fa2Sopenharmony_ci 49fb299fa2Sopenharmony_ciint32_t GetASN1OctetStringData(const ASN1_OCTET_STRING *octString, std::vector<uint8_t> &asn1Data) 50fb299fa2Sopenharmony_ci{ 51fb299fa2Sopenharmony_ci if (octString == nullptr) { 52fb299fa2Sopenharmony_ci return -1; 53fb299fa2Sopenharmony_ci } 54fb299fa2Sopenharmony_ci const uint8_t *octChar = ASN1_STRING_get0_data(octString); 55fb299fa2Sopenharmony_ci if (octChar == nullptr) { 56fb299fa2Sopenharmony_ci PKG_LOGE("get asn1 obj string failed!"); 57fb299fa2Sopenharmony_ci return -1; 58fb299fa2Sopenharmony_ci } 59fb299fa2Sopenharmony_ci 60fb299fa2Sopenharmony_ci int32_t octLen = ASN1_STRING_length(octString); 61fb299fa2Sopenharmony_ci if (octLen <= 0) { 62fb299fa2Sopenharmony_ci PKG_LOGE("invalid asn1 obj string len %d!", octLen); 63fb299fa2Sopenharmony_ci return -1; 64fb299fa2Sopenharmony_ci } 65fb299fa2Sopenharmony_ci asn1Data.assign(octChar, octChar + octLen); 66fb299fa2Sopenharmony_ci 67fb299fa2Sopenharmony_ci return 0; 68fb299fa2Sopenharmony_ci} 69fb299fa2Sopenharmony_ci 70fb299fa2Sopenharmony_ciint32_t GetX509AlgorithmNid(const X509_ALGOR *x509Algo, int32_t &algoNid) 71fb299fa2Sopenharmony_ci{ 72fb299fa2Sopenharmony_ci if (x509Algo == nullptr) { 73fb299fa2Sopenharmony_ci return -1; 74fb299fa2Sopenharmony_ci } 75fb299fa2Sopenharmony_ci 76fb299fa2Sopenharmony_ci const ASN1_OBJECT *algObj = nullptr; 77fb299fa2Sopenharmony_ci X509_ALGOR_get0(&algObj, nullptr, nullptr, x509Algo); 78fb299fa2Sopenharmony_ci if (algObj == nullptr) { 79fb299fa2Sopenharmony_ci PKG_LOGE("x509 algor get0 fail!"); 80fb299fa2Sopenharmony_ci return -1; 81fb299fa2Sopenharmony_ci } 82fb299fa2Sopenharmony_ci algoNid = OBJ_obj2nid(algObj); 83fb299fa2Sopenharmony_ci if (algoNid <= 0) { 84fb299fa2Sopenharmony_ci PKG_LOGE("invalid algo nid %d!", algoNid); 85fb299fa2Sopenharmony_ci return -1; 86fb299fa2Sopenharmony_ci } 87fb299fa2Sopenharmony_ci 88fb299fa2Sopenharmony_ci return 0; 89fb299fa2Sopenharmony_ci} 90fb299fa2Sopenharmony_ci 91fb299fa2Sopenharmony_ciX509 *GetX509CertFromPemString(const std::string &pemString) 92fb299fa2Sopenharmony_ci{ 93fb299fa2Sopenharmony_ci BIO *pemBio = BIO_new(BIO_s_mem()); 94fb299fa2Sopenharmony_ci if (pemBio == nullptr) { 95fb299fa2Sopenharmony_ci return nullptr; 96fb299fa2Sopenharmony_ci } 97fb299fa2Sopenharmony_ci int strLen = static_cast<int>(pemString.size()); 98fb299fa2Sopenharmony_ci if (BIO_write(pemBio, pemString.c_str(), strLen) != strLen) { 99fb299fa2Sopenharmony_ci BIO_free_all(pemBio); 100fb299fa2Sopenharmony_ci return nullptr; 101fb299fa2Sopenharmony_ci } 102fb299fa2Sopenharmony_ci 103fb299fa2Sopenharmony_ci X509 *cert = PEM_read_bio_X509(pemBio, nullptr, nullptr, nullptr); 104fb299fa2Sopenharmony_ci if (cert == nullptr) { 105fb299fa2Sopenharmony_ci PKG_LOGE("pem read x509 fail"); 106fb299fa2Sopenharmony_ci } 107fb299fa2Sopenharmony_ci BIO_free_all(pemBio); 108fb299fa2Sopenharmony_ci 109fb299fa2Sopenharmony_ci return cert; 110fb299fa2Sopenharmony_ci} 111fb299fa2Sopenharmony_ci 112fb299fa2Sopenharmony_ciX509 *GetX509CertFromPemFile(const std::string &filePath) 113fb299fa2Sopenharmony_ci{ 114fb299fa2Sopenharmony_ci std::ifstream ifs(filePath); 115fb299fa2Sopenharmony_ci if (!ifs.is_open()) { 116fb299fa2Sopenharmony_ci PKG_LOGE("file %s not exist", filePath.c_str()); 117fb299fa2Sopenharmony_ci return nullptr; 118fb299fa2Sopenharmony_ci } 119fb299fa2Sopenharmony_ci BIO *certbio = BIO_new_file(filePath.c_str(), "r"); 120fb299fa2Sopenharmony_ci if (certbio == nullptr) { 121fb299fa2Sopenharmony_ci PKG_LOGE("Failed to create BIO"); 122fb299fa2Sopenharmony_ci return nullptr; 123fb299fa2Sopenharmony_ci } 124fb299fa2Sopenharmony_ci 125fb299fa2Sopenharmony_ci X509 *cert = PEM_read_bio_X509(certbio, nullptr, nullptr, nullptr); 126fb299fa2Sopenharmony_ci if (cert == nullptr) { 127fb299fa2Sopenharmony_ci PKG_LOGE("Failed to read x509 certificate"); 128fb299fa2Sopenharmony_ci BIO_free_all(certbio); 129fb299fa2Sopenharmony_ci return nullptr; 130fb299fa2Sopenharmony_ci } 131fb299fa2Sopenharmony_ci BIO_free_all(certbio); 132fb299fa2Sopenharmony_ci 133fb299fa2Sopenharmony_ci return cert; 134fb299fa2Sopenharmony_ci} 135fb299fa2Sopenharmony_ci 136fb299fa2Sopenharmony_cibool VerifyX509CertByIssuerCert(X509 *cert, X509 *issuerCert) 137fb299fa2Sopenharmony_ci{ 138fb299fa2Sopenharmony_ci if (cert == nullptr || issuerCert == nullptr) { 139fb299fa2Sopenharmony_ci return false; 140fb299fa2Sopenharmony_ci } 141fb299fa2Sopenharmony_ci 142fb299fa2Sopenharmony_ci EVP_PKEY *pubKey = X509_get_pubkey(issuerCert); 143fb299fa2Sopenharmony_ci if (pubKey == nullptr) { 144fb299fa2Sopenharmony_ci PKG_LOGE("get pubkey fial."); 145fb299fa2Sopenharmony_ci return false; 146fb299fa2Sopenharmony_ci } 147fb299fa2Sopenharmony_ci 148fb299fa2Sopenharmony_ci bool ret = (X509_verify(cert, pubKey) == 1); 149fb299fa2Sopenharmony_ci EVP_PKEY_free(pubKey); 150fb299fa2Sopenharmony_ci return ret; 151fb299fa2Sopenharmony_ci} 152fb299fa2Sopenharmony_ci 153fb299fa2Sopenharmony_ciint32_t VerifyDigestByPubKey(EVP_PKEY *pubKey, const int nid, const std::vector<uint8_t> &digestData, 154fb299fa2Sopenharmony_ci const std::vector<uint8_t> &signature) 155fb299fa2Sopenharmony_ci{ 156fb299fa2Sopenharmony_ci Updater::UPDATER_INIT_RECORD; 157fb299fa2Sopenharmony_ci if (pubKey == nullptr) { 158fb299fa2Sopenharmony_ci PKG_LOGE("pubKey is empty"); 159fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(-1); 160fb299fa2Sopenharmony_ci return -1; 161fb299fa2Sopenharmony_ci } 162fb299fa2Sopenharmony_ci 163fb299fa2Sopenharmony_ci EVP_MD_CTX *mdCtx = EVP_MD_CTX_create(); 164fb299fa2Sopenharmony_ci if (mdCtx == nullptr) { 165fb299fa2Sopenharmony_ci PKG_LOGE("EVP_MD_CTX_create failed"); 166fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(-1); 167fb299fa2Sopenharmony_ci return -1; 168fb299fa2Sopenharmony_ci } 169fb299fa2Sopenharmony_ci EVP_PKEY_CTX *pkeyCtx = nullptr; 170fb299fa2Sopenharmony_ci if (EVP_DigestVerifyInit(mdCtx, &pkeyCtx, EVP_get_digestbynid(nid), nullptr, pubKey) != 1) { 171fb299fa2Sopenharmony_ci PKG_LOGE("EVP init, error"); 172fb299fa2Sopenharmony_ci EVP_MD_CTX_destroy(mdCtx); 173fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(-1); 174fb299fa2Sopenharmony_ci return -1; 175fb299fa2Sopenharmony_ci } 176fb299fa2Sopenharmony_ci if (EVP_DigestVerifyUpdate(mdCtx, digestData.data(), digestData.size()) != 1) { 177fb299fa2Sopenharmony_ci PKG_LOGE("EVP update, error"); 178fb299fa2Sopenharmony_ci EVP_MD_CTX_destroy(mdCtx); 179fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(-1); 180fb299fa2Sopenharmony_ci return -1; 181fb299fa2Sopenharmony_ci } 182fb299fa2Sopenharmony_ci 183fb299fa2Sopenharmony_ci int ret = EVP_DigestVerifyFinal(mdCtx, signature.data(), signature.size()); 184fb299fa2Sopenharmony_ci if (ret != 1) { 185fb299fa2Sopenharmony_ci PKG_LOGE("EVP final, error"); 186fb299fa2Sopenharmony_ci EVP_MD_CTX_destroy(mdCtx); 187fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(-1); 188fb299fa2Sopenharmony_ci return -1; 189fb299fa2Sopenharmony_ci } 190fb299fa2Sopenharmony_ci 191fb299fa2Sopenharmony_ci EVP_MD_CTX_destroy(mdCtx); 192fb299fa2Sopenharmony_ci return 0; 193fb299fa2Sopenharmony_ci} 194fb299fa2Sopenharmony_ci 195fb299fa2Sopenharmony_ciint32_t CalcSha256Digest(const PkgStreamPtr srcData, const size_t dataLen, std::vector<uint8_t> &result) 196fb299fa2Sopenharmony_ci{ 197fb299fa2Sopenharmony_ci Updater::UPDATER_INIT_RECORD; 198fb299fa2Sopenharmony_ci if (srcData == nullptr || dataLen == 0) { 199fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(-1); 200fb299fa2Sopenharmony_ci return -1; 201fb299fa2Sopenharmony_ci } 202fb299fa2Sopenharmony_ci if (result.size() != SHA256_DIGEST_LENGTH) { 203fb299fa2Sopenharmony_ci result.resize(SHA256_DIGEST_LENGTH); 204fb299fa2Sopenharmony_ci } 205fb299fa2Sopenharmony_ci SHA256_CTX ctx; 206fb299fa2Sopenharmony_ci SHA256_Init(&ctx); 207fb299fa2Sopenharmony_ci 208fb299fa2Sopenharmony_ci size_t offset = 0; 209fb299fa2Sopenharmony_ci size_t remainLen = dataLen; 210fb299fa2Sopenharmony_ci size_t blockLen = HASH_SOURCE_BLOCK_LEN; 211fb299fa2Sopenharmony_ci PkgBuffer buffer(blockLen); 212fb299fa2Sopenharmony_ci size_t readLen = 0; 213fb299fa2Sopenharmony_ci int32_t ret = 0; 214fb299fa2Sopenharmony_ci while (remainLen >= blockLen) { 215fb299fa2Sopenharmony_ci ret = srcData->Read(buffer, offset, blockLen, readLen); 216fb299fa2Sopenharmony_ci if (ret != 0) { 217fb299fa2Sopenharmony_ci PKG_LOGE("Fail read data"); 218fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(-1); 219fb299fa2Sopenharmony_ci return -1; 220fb299fa2Sopenharmony_ci } 221fb299fa2Sopenharmony_ci SHA256_Update(&ctx, buffer.buffer, blockLen); 222fb299fa2Sopenharmony_ci offset += readLen; 223fb299fa2Sopenharmony_ci remainLen -= readLen; 224fb299fa2Sopenharmony_ci } 225fb299fa2Sopenharmony_ci if (remainLen > 0) { 226fb299fa2Sopenharmony_ci ret = srcData->Read(buffer, offset, remainLen, readLen); 227fb299fa2Sopenharmony_ci if (ret != 0) { 228fb299fa2Sopenharmony_ci PKG_LOGE("Fail read data"); 229fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(-1); 230fb299fa2Sopenharmony_ci return -1; 231fb299fa2Sopenharmony_ci } 232fb299fa2Sopenharmony_ci SHA256_Update(&ctx, buffer.buffer, readLen); 233fb299fa2Sopenharmony_ci } 234fb299fa2Sopenharmony_ci 235fb299fa2Sopenharmony_ci if (SHA256_Final(result.data(), &ctx) != 1) { 236fb299fa2Sopenharmony_ci PKG_LOGE("SHA256_Final(), error"); 237fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(-1); 238fb299fa2Sopenharmony_ci return -1; 239fb299fa2Sopenharmony_ci } 240fb299fa2Sopenharmony_ci 241fb299fa2Sopenharmony_ci return 0; 242fb299fa2Sopenharmony_ci} 243fb299fa2Sopenharmony_ci 244fb299fa2Sopenharmony_cistd::string GetStringFromX509Name(X509_NAME *x509Name) 245fb299fa2Sopenharmony_ci{ 246fb299fa2Sopenharmony_ci if (x509Name == nullptr) { 247fb299fa2Sopenharmony_ci return ""; 248fb299fa2Sopenharmony_ci } 249fb299fa2Sopenharmony_ci 250fb299fa2Sopenharmony_ci std::string country; 251fb299fa2Sopenharmony_ci GetTextContentFromX509Name(x509Name, NID_countryName, country); 252fb299fa2Sopenharmony_ci 253fb299fa2Sopenharmony_ci std::string organization; 254fb299fa2Sopenharmony_ci GetTextContentFromX509Name(x509Name, NID_organizationName, organization); 255fb299fa2Sopenharmony_ci 256fb299fa2Sopenharmony_ci std::string organizationalUnitName; 257fb299fa2Sopenharmony_ci GetTextContentFromX509Name(x509Name, NID_organizationalUnitName, organizationalUnitName); 258fb299fa2Sopenharmony_ci 259fb299fa2Sopenharmony_ci std::string commonName; 260fb299fa2Sopenharmony_ci GetTextContentFromX509Name(x509Name, NID_commonName, commonName); 261fb299fa2Sopenharmony_ci 262fb299fa2Sopenharmony_ci return "C=" + country + ", O=" + organization + ", OU=" + organizationalUnitName + ", CN=" + commonName; 263fb299fa2Sopenharmony_ci} 264fb299fa2Sopenharmony_ci 265fb299fa2Sopenharmony_cistd::string GetX509CertSubjectName(X509 *cert) 266fb299fa2Sopenharmony_ci{ 267fb299fa2Sopenharmony_ci if (cert == nullptr) { 268fb299fa2Sopenharmony_ci return ""; 269fb299fa2Sopenharmony_ci } 270fb299fa2Sopenharmony_ci 271fb299fa2Sopenharmony_ci X509_NAME *subjectName = X509_get_subject_name(cert); 272fb299fa2Sopenharmony_ci if (subjectName == nullptr) { 273fb299fa2Sopenharmony_ci PKG_LOGE("cert subject name is null"); 274fb299fa2Sopenharmony_ci return ""; 275fb299fa2Sopenharmony_ci } 276fb299fa2Sopenharmony_ci 277fb299fa2Sopenharmony_ci return GetStringFromX509Name(subjectName); 278fb299fa2Sopenharmony_ci} 279fb299fa2Sopenharmony_ci 280fb299fa2Sopenharmony_cistd::string GetX509CertIssuerName(X509 *cert) 281fb299fa2Sopenharmony_ci{ 282fb299fa2Sopenharmony_ci if (cert == nullptr) { 283fb299fa2Sopenharmony_ci return ""; 284fb299fa2Sopenharmony_ci } 285fb299fa2Sopenharmony_ci 286fb299fa2Sopenharmony_ci X509_NAME *issuerName = X509_get_issuer_name(cert); 287fb299fa2Sopenharmony_ci if (issuerName == nullptr) { 288fb299fa2Sopenharmony_ci PKG_LOGE("cert issuer name is null"); 289fb299fa2Sopenharmony_ci return ""; 290fb299fa2Sopenharmony_ci } 291fb299fa2Sopenharmony_ci 292fb299fa2Sopenharmony_ci return GetStringFromX509Name(issuerName); 293fb299fa2Sopenharmony_ci} 294fb299fa2Sopenharmony_ci} 295