* Copyright (c) 2023-2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "openssl_utils.h"
#include <mutex>
#include <openssl/pem.h>
#include "log.h"
namespace OHOS {
namespace Security {
namespace CodeSign {
void GetOpensslErrorMessage()
{
unsigned long retOpenssl;
char errOpenssl[OPENSSL_ERR_MESSAGE_MAX_LEN];
while ((retOpenssl = ERR_get_error()) != 0) {
ERR_error_string_n(retOpenssl, errOpenssl, OPENSSL_ERR_MESSAGE_MAX_LEN);
LOG_ERROR("openssl err: %{public}lu, message: %{public}s", retOpenssl, errOpenssl);
}
}
X509 *LoadCertFromBuffer(const uint8_t *buffer, const uint32_t size)
{
BIO *mem = BIO_new_mem_buf(buffer, size);
if (mem == nullptr) {
LOG_ERROR("Fail to create bio for cert.");
return nullptr;
}
X509 *cert = d2i_X509_bio(mem, nullptr);
if (cert == nullptr) {
ERR_LOG_WITH_OPEN_SSL_MSG("Certificate is invalid.");
}
BIO_free(mem);
return cert;
}
bool ConvertCertToPEMString(const ByteBuffer &certBuffer, std::string &pemString)
{
X509 *cert = LoadCertFromBuffer(certBuffer.GetBuffer(), certBuffer.GetSize());
if (cert == nullptr) {
return false;
}
BIO *mem = BIO_new(BIO_s_mem());
if (mem == nullptr) {
X509_free(cert);
return false;
}
bool ret = false;
do {
if (!PEM_write_bio_X509(mem, cert)) {
ERR_LOG_WITH_OPEN_SSL_MSG("convert to pem failed.");
break;
}
uint8_t *outData = nullptr;
int32_t len = BIO_get_mem_data(mem, &outData);
if (len < 0) {
break;
}
pemString = std::string(reinterpret_cast<char *>(outData), len);
ret = true;
} while (0);
BIO_free(mem);
X509_free(cert);
return ret;
}
STACK_OF(X509) *MakeStackOfCerts(const std::vector<ByteBuffer> &certChain)
{
STACK_OF(X509)* certs = sk_X509_new_null();
if (certs == nullptr) {
return nullptr;
}
for (const ByteBuffer &cert: certChain) {
X509 *tmp = LoadCertFromBuffer(cert.GetBuffer(), cert.GetSize());
if ((tmp == nullptr) || (!sk_X509_push(certs, tmp))) {
sk_X509_pop_free(certs, X509_free);
certs = nullptr;
ERR_LOG_WITH_OPEN_SSL_MSG("Push cert failed.");
break;
}
}
return certs;
}
int CreateNIDFromOID(const std::string &oid, const std::string &shortName,
const std::string &longName)
{
static std::mutex oidLock;
std::lock_guard<std::mutex> lock(oidLock);
int nid = OBJ_txt2nid(oid.c_str());
if (nid == NID_undef) {
nid = OBJ_create(oid.c_str(), shortName.c_str(), longName.c_str());
}
return nid;
}
}
}
}