• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "cert_context.h"
17 
18 #include <map>
19 #include <node_api.h>
20 #include <openssl/ssl.h>
21 
22 #include "napi_utils.h"
23 #include "net_ssl_exec.h"
24 #include "netstack_common_utils.h"
25 #include "netstack_log.h"
26 
27 static constexpr const int PARAM_JUST_CERT = 1;
28 
29 static constexpr const int PARAM_CERT_AND_CACERT = 2;
30 
31 namespace OHOS::NetStack::Ssl {
32 
33 enum SslErrorCode {
34     SSL_NONE_ERR = 0,
35     SSL_ERROR_CODE_BASE = 2305000,
36     SSL_X509_V_ERR_UNSPECIFIED = SSL_ERROR_CODE_BASE + X509_V_ERR_UNSPECIFIED,
37     SSL_X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT = SSL_ERROR_CODE_BASE + X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT,
38     SSL_X509_V_ERR_UNABLE_TO_GET_CRL = SSL_ERROR_CODE_BASE + X509_V_ERR_UNABLE_TO_GET_CRL,
39     SSL_X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE = SSL_ERROR_CODE_BASE + X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE,
40     SSL_X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE = SSL_ERROR_CODE_BASE + X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE,
41     SSL_X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY =
42         SSL_ERROR_CODE_BASE + X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY,
43     SSL_X509_V_ERR_CERT_SIGNATURE_FAILURE = SSL_ERROR_CODE_BASE + X509_V_ERR_CERT_SIGNATURE_FAILURE,
44     SSL_X509_V_ERR_CRL_SIGNATURE_FAILURE = SSL_ERROR_CODE_BASE + X509_V_ERR_CRL_SIGNATURE_FAILURE,
45     SSL_X509_V_ERR_CERT_NOT_YET_VALID = SSL_ERROR_CODE_BASE + X509_V_ERR_CERT_NOT_YET_VALID,
46     SSL_X509_V_ERR_CERT_HAS_EXPIRED = SSL_ERROR_CODE_BASE + X509_V_ERR_CERT_HAS_EXPIRED,
47     SSL_X509_V_ERR_CRL_NOT_YET_VALID = SSL_ERROR_CODE_BASE + X509_V_ERR_CRL_NOT_YET_VALID,
48     SSL_X509_V_ERR_CRL_HAS_EXPIRED = SSL_ERROR_CODE_BASE + X509_V_ERR_CRL_HAS_EXPIRED,
49     SSL_X509_V_ERR_CERT_REVOKED = SSL_ERROR_CODE_BASE + X509_V_ERR_CERT_REVOKED,
50     SSL_X509_V_ERR_INVALID_CA = SSL_ERROR_CODE_BASE + X509_V_ERR_INVALID_CA,
51     SSL_X509_V_ERR_CERT_UNTRUSTED = SSL_ERROR_CODE_BASE + X509_V_ERR_CERT_UNTRUSTED
52 };
53 
54 static const std::map<int32_t, const char *> SSL_ERR_MAP = {
55     {SslErrorCode::SSL_NONE_ERR, "Verify success."},
56     {SslErrorCode::SSL_X509_V_ERR_UNSPECIFIED, "Unspecified error."},
57     {SslErrorCode::SSL_X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT, "Unable to get issuer certificate."},
58     {SslErrorCode::SSL_X509_V_ERR_UNABLE_TO_GET_CRL, "Unable to get certificate revocation list (CRL)."},
59     {SslErrorCode::SSL_X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE, "Unable to decrypt certificate signature."},
60     {SslErrorCode::SSL_X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE, "Unable to decrypt CRL signature."},
61     {SslErrorCode::SSL_X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY, "Unable to decode issuer public key."},
62     {SslErrorCode::SSL_X509_V_ERR_CERT_SIGNATURE_FAILURE, "Certificate signature failure."},
63     {SslErrorCode::SSL_X509_V_ERR_CRL_SIGNATURE_FAILURE, "CRL signature failure."},
64     {SslErrorCode::SSL_X509_V_ERR_CERT_NOT_YET_VALID, "Certificate is not yet valid."},
65     {SslErrorCode::SSL_X509_V_ERR_CERT_HAS_EXPIRED, "Certificate has expired."},
66     {SslErrorCode::SSL_X509_V_ERR_CRL_NOT_YET_VALID, "CRL is not yet valid."},
67     {SslErrorCode::SSL_X509_V_ERR_CRL_HAS_EXPIRED, "CRL has expired."},
68     {SslErrorCode::SSL_X509_V_ERR_CERT_REVOKED, "Certificate has been revoked."},
69     {SslErrorCode::SSL_X509_V_ERR_INVALID_CA, "Invalid certificate authority (CA)."},
70     {SslErrorCode::SSL_X509_V_ERR_CERT_UNTRUSTED, "Certificate is untrusted."},
71 
72 };
73 
CertContext(napi_env env,EventManager * manager)74 CertContext::CertContext(napi_env env, EventManager *manager)
75     : BaseContext(env, manager), certBlob_(nullptr), certBlobClient_(nullptr)
76 {
77     manager_ = new EventManager;
78 }
79 
ParseParams(napi_value * params,size_t paramsCount)80 void CertContext::ParseParams(napi_value *params, size_t paramsCount)
81 {
82     bool valid = CheckParamsType(params, paramsCount);
83     if (valid) {
84         if (paramsCount == PARAM_JUST_CERT) {
85             certBlob_ = ParseCertBlobFromValue(GetEnv(), params[0]);
86             SetParseOK(certBlob_ != nullptr);
87         } else if (paramsCount == PARAM_CERT_AND_CACERT) {
88             certBlob_ = ParseCertBlobFromValue(GetEnv(), params[0]);
89             certBlobClient_ = ParseCertBlobFromValue(GetEnv(), params[1]);
90             SetParseOK(certBlob_ != nullptr && certBlobClient_ != nullptr);
91         }
92     } else {
93         SetErrorCode(PARSE_ERROR_CODE);
94     }
95 }
96 
CheckParamsType(napi_value * params,size_t paramsCount)97 bool CertContext::CheckParamsType(napi_value *params, size_t paramsCount)
98 {
99     if (paramsCount == PARAM_JUST_CERT) {
100         return NapiUtils::GetValueType(GetEnv(), params[0]) == napi_object;
101     } else if (paramsCount == PARAM_CERT_AND_CACERT) {
102         return NapiUtils::GetValueType(GetEnv(), params[0]) == napi_object &&
103                NapiUtils::GetValueType(GetEnv(), params[1]) == napi_object;
104     }
105     return false;
106 }
107 
ParseCertBlobFromValue(napi_env env,napi_value value)108 CertBlob *CertContext::ParseCertBlobFromValue(napi_env env, napi_value value)
109 {
110     napi_value typeValue;
111     napi_value dataValue;
112     napi_get_named_property(env, value, "type", &typeValue);
113     napi_get_named_property(env, value, "data", &dataValue);
114     if (typeValue == nullptr || dataValue == nullptr) {
115         SetErrorCode(PARSE_ERROR_CODE);
116         return new CertBlob{CERT_TYPE_MAX, 0, nullptr};
117     }
118     return ParseCertBlobFromData(env, value, typeValue, dataValue);
119 }
120 
ParseCertBlobFromData(napi_env env,napi_value value,napi_value typeValue,napi_value dataValue)121 CertBlob *CertContext::ParseCertBlobFromData(napi_env env, napi_value value, napi_value typeValue, napi_value dataValue)
122 {
123     size_t dataSize = 0;
124     uint32_t type;
125     uint32_t size = 0;
126     uint8_t *data = nullptr;
127     napi_get_value_uint32(env, typeValue, &type);
128     CertType certType = static_cast<CertType>(type);
129     if (certType == CERT_TYPE_PEM) {
130         NETSTACK_LOGD("CERT_TYPE_PEM\n");
131         napi_valuetype valueType;
132         napi_typeof(env, dataValue, &valueType);
133         if (valueType != napi_string) {
134             NETSTACK_LOGE("pem but not string\n");
135             return new CertBlob{CERT_TYPE_MAX, 0, nullptr};
136         }
137         napi_get_value_string_utf8(env, dataValue, nullptr, 0, &dataSize);
138         if (dataSize + 1 < SIZE_MAX / sizeof(uint8_t)) {
139             data = new uint8_t[dataSize + 1];
140             napi_get_value_string_utf8(env, dataValue, reinterpret_cast<char *>(data), dataSize + 1, &dataSize);
141             size = static_cast<uint32_t>(dataSize);
142         } else {
143             return new CertBlob{CERT_TYPE_MAX, 0, nullptr};
144         }
145     } else if (certType == CERT_TYPE_DER) {
146         NETSTACK_LOGD("CERT_TYPE_DER\n");
147         bool isArrayBuffer = false;
148         napi_is_buffer(env, dataValue, &isArrayBuffer);
149         if (!isArrayBuffer) {
150             NETSTACK_LOGE("der but bot arraybuffer\n");
151             return new CertBlob{CERT_TYPE_MAX, 0, nullptr};
152         }
153         void *dataArray = nullptr;
154         napi_get_arraybuffer_info(env, dataValue, &dataArray, &dataSize);
155         if (dataSize < SIZE_MAX / sizeof(uint8_t)) {
156             data = new uint8_t[dataSize];
157             std::copy(static_cast<uint8_t *>(dataArray), static_cast<uint8_t *>(dataArray) + dataSize, data);
158             size = static_cast<uint32_t>(dataSize);
159         } else {
160             return new CertBlob{CERT_TYPE_MAX, 0, nullptr};
161         }
162     } else {
163         return new CertBlob{CERT_TYPE_MAX, 0, nullptr};
164     }
165     return new CertBlob{static_cast<CertType>(type), static_cast<uint32_t>(size), static_cast<uint8_t *>(data)};
166 }
167 
GetCertBlob()168 CertBlob *CertContext::GetCertBlob()
169 {
170     return certBlob_;
171 }
172 
GetCertBlobClient()173 CertBlob *CertContext::GetCertBlobClient()
174 {
175     return certBlobClient_;
176 }
177 
GetErrorMessage() const178 std::string CertContext::GetErrorMessage() const
179 {
180     auto err = BaseContext::GetErrorCode();
181     if (err == PARSE_ERROR_CODE) {
182         return PARSE_ERROR_MSG;
183     }
184 
185     auto pos = SSL_ERR_MAP.find(err);
186     if (pos != SSL_ERR_MAP.end()) {
187         return pos->second;
188     }
189     return SSL_ERR_MAP.at(SslErrorCode::SSL_X509_V_ERR_CERT_UNTRUSTED);
190 }
191 
~CertContext()192 CertContext::~CertContext()
193 {
194     if (certBlob_ != nullptr) {
195         if (certBlob_->data != nullptr) {
196             delete certBlob_->data;
197             certBlob_->data = nullptr;
198         }
199         delete certBlob_;
200         certBlob_ = nullptr;
201     }
202 
203     if (certBlobClient_ != nullptr) {
204         if (certBlobClient_->data != nullptr) {
205             delete certBlobClient_->data;
206             certBlobClient_->data = nullptr;
207         }
208         delete certBlobClient_;
209         certBlobClient_ = nullptr;
210     }
211     if (manager_ != nullptr) {
212         delete manager_;
213         manager_ = nullptr;
214     }
215     NETSTACK_LOGD("CertContext is destructed by the destructor");
216 }
217 } // namespace OHOS::NetStack::Ssl
218