1 /*
2 * Copyright (c) 2023-2024 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
16 #include "openssl_utils.h"
17
18 #include <mutex>
19 #include <openssl/pem.h>
20 #include "log.h"
21
22 namespace OHOS {
23 namespace Security {
24 namespace CodeSign {
GetOpensslErrorMessage()25 void GetOpensslErrorMessage()
26 {
27 unsigned long retOpenssl;
28 char errOpenssl[OPENSSL_ERR_MESSAGE_MAX_LEN];
29 while ((retOpenssl = ERR_get_error()) != 0) {
30 // error string is written no more than OPENSSL_ERR_MESSAGE_MAX_LEN in errOpenssl
31 ERR_error_string_n(retOpenssl, errOpenssl, OPENSSL_ERR_MESSAGE_MAX_LEN);
32 LOG_ERROR("openssl err: %{public}lu, message: %{public}s", retOpenssl, errOpenssl);
33 }
34 }
35
LoadCertFromBuffer(const uint8_t * buffer,const uint32_t size)36 X509 *LoadCertFromBuffer(const uint8_t *buffer, const uint32_t size)
37 {
38 BIO *mem = BIO_new_mem_buf(buffer, size);
39 if (mem == nullptr) {
40 LOG_ERROR("Fail to create bio for cert.");
41 return nullptr;
42 }
43 X509 *cert = d2i_X509_bio(mem, nullptr);
44 if (cert == nullptr) {
45 ERR_LOG_WITH_OPEN_SSL_MSG("Certificate is invalid.");
46 }
47 BIO_free(mem);
48 return cert;
49 }
50
ConvertCertToPEMString(const ByteBuffer & certBuffer,std::string & pemString)51 bool ConvertCertToPEMString(const ByteBuffer &certBuffer, std::string &pemString)
52 {
53 X509 *cert = LoadCertFromBuffer(certBuffer.GetBuffer(), certBuffer.GetSize());
54 if (cert == nullptr) {
55 return false;
56 }
57 BIO *mem = BIO_new(BIO_s_mem());
58 if (mem == nullptr) {
59 X509_free(cert);
60 return false;
61 }
62 bool ret = false;
63 do {
64 if (!PEM_write_bio_X509(mem, cert)) {
65 ERR_LOG_WITH_OPEN_SSL_MSG("convert to pem failed.");
66 break;
67 }
68 uint8_t *outData = nullptr;
69 int32_t len = BIO_get_mem_data(mem, &outData);
70 if (len < 0) {
71 break;
72 }
73 pemString = std::string(reinterpret_cast<char *>(outData), len);
74 ret = true;
75 } while (0);
76 BIO_free(mem);
77 X509_free(cert);
78 return ret;
79 }
80
STACK_OF(X509)81 STACK_OF(X509) *MakeStackOfCerts(const std::vector<ByteBuffer> &certChain)
82 {
83 STACK_OF(X509)* certs = sk_X509_new_null();
84 if (certs == nullptr) {
85 return nullptr;
86 }
87
88 for (const ByteBuffer &cert: certChain) {
89 X509 *tmp = LoadCertFromBuffer(cert.GetBuffer(), cert.GetSize());
90
91 if ((tmp == nullptr) || (!sk_X509_push(certs, tmp))) {
92 // including each cert in certs and stack of certs
93 sk_X509_pop_free(certs, X509_free);
94 certs = nullptr;
95 ERR_LOG_WITH_OPEN_SSL_MSG("Push cert failed.");
96 break;
97 }
98 }
99 return certs;
100 }
101
CreateNIDFromOID(const std::string & oid,const std::string & shortName,const std::string & longName)102 int CreateNIDFromOID(const std::string &oid, const std::string &shortName,
103 const std::string &longName)
104 {
105 static std::mutex oidLock;
106 std::lock_guard<std::mutex> lock(oidLock);
107 int nid = OBJ_txt2nid(oid.c_str());
108 if (nid == NID_undef) {
109 nid = OBJ_create(oid.c_str(), shortName.c_str(), longName.c_str());
110 }
111 return nid;
112 }
113 }
114 }
115 }
116