1 /*
2  * Copyright (c) 2023 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 <cstring>
17 #include <iostream>
18 #include <vector>
19 #include <string>
20 
21 #include <openssl/ssl.h>
22 
23 #include "net_ssl.h"
24 #include "net_ssl_c.h"
25 #include "net_ssl_c_type.h"
26 #include "securec.h"
27 #include "netstack_log.h"
28 #include "net_ssl_verify_cert.h"
29 #include "net_manager_constants.h"
30 #include "net_conn_client.h"
31 
SwitchToCertBlob(const struct NetStack_CertBlob cert)32 struct OHOS::NetStack::Ssl::CertBlob SwitchToCertBlob(const struct NetStack_CertBlob cert)
33 {
34     OHOS::NetStack::Ssl::CertBlob cb;
35     switch (cert.type) {
36         case NETSTACK_CERT_TYPE_PEM:
37             cb.type = OHOS::NetStack::Ssl::CertType::CERT_TYPE_PEM;
38             break;
39         case NETSTACK_CERT_TYPE_DER:
40             cb.type = OHOS::NetStack::Ssl::CertType::CERT_TYPE_DER;
41             break;
42         case NETSTACK_CERT_TYPE_INVALID:
43             cb.type = OHOS::NetStack::Ssl::CertType::CERT_TYPE_MAX;
44             break;
45         default:
46             break;
47     }
48     cb.size = cert.size;
49     cb.data = cert.data;
50     return cb;
51 }
52 
VerifyCert_With_RootCa(const struct NetStack_CertBlob * cert)53 uint32_t VerifyCert_With_RootCa(const struct NetStack_CertBlob *cert)
54 {
55     uint32_t verifyResult = X509_V_ERR_UNSPECIFIED;
56     OHOS::NetStack::Ssl::CertBlob cb = SwitchToCertBlob(*cert);
57     verifyResult = OHOS::NetStack::Ssl::NetStackVerifyCertification(&cb);
58     return verifyResult;
59 }
60 
VerifyCert_With_DesignatedCa(const struct NetStack_CertBlob * cert,const struct NetStack_CertBlob * caCert)61 uint32_t VerifyCert_With_DesignatedCa(const struct NetStack_CertBlob *cert, const struct NetStack_CertBlob *caCert)
62 {
63     uint32_t verifyResult = X509_V_ERR_UNSPECIFIED;
64     OHOS::NetStack::Ssl::CertBlob cb = SwitchToCertBlob(*cert);
65     OHOS::NetStack::Ssl::CertBlob caCb = SwitchToCertBlob(*caCert);
66     verifyResult = OHOS::NetStack::Ssl::NetStackVerifyCertification(&cb, &caCb);
67     return verifyResult;
68 }
69 
OH_NetStack_CertVerification(const struct NetStack_CertBlob * cert,const struct NetStack_CertBlob * caCert)70 uint32_t OH_NetStack_CertVerification(const struct NetStack_CertBlob *cert, const struct NetStack_CertBlob *caCert)
71 {
72     if (cert == nullptr) {
73         return X509_V_ERR_INVALID_CALL;
74     }
75     if (caCert == nullptr) {
76         return VerifyCert_With_RootCa(cert);
77     } else {
78         return VerifyCert_With_DesignatedCa(cert, caCert);
79     }
80 }
81 
OH_NetStack_GetPinSetForHostName(const char * hostname,NetStack_CertificatePinning * pin)82 int32_t OH_NetStack_GetPinSetForHostName(const char *hostname, NetStack_CertificatePinning *pin)
83 {
84     if (hostname == nullptr || pin == nullptr) {
85         NETSTACK_LOGE("OH_NetStack_GetPinSetForHostName received invalid parameters");
86         return OHOS::NetManagerStandard::NETMANAGER_ERR_PARAMETER_ERROR;
87     }
88 
89     std::string innerHostname = std::string(hostname);
90     std::string innerPins;
91 
92     int32_t ret = OHOS::NetManagerStandard::NetConnClient::GetInstance().GetPinSetForHostName(innerHostname, innerPins);
93     if (ret != OHOS::NetManagerStandard::NETMANAGER_SUCCESS) {
94         return ret;
95     }
96 
97     if (innerPins.length() <= 0) {
98         pin->hashAlgorithm = NetStack_HashAlgorithm::SHA_256;
99         pin->kind = NetStack_CertificatePinningKind::PUBLIC_KEY;
100         pin->publicKeyHash = nullptr;
101         return OHOS::NetManagerStandard::NETMANAGER_SUCCESS;
102     }
103 
104     size_t size = innerPins.length() + 1;
105     char *key = (char *)malloc(size);
106     if (key == nullptr) {
107         NETSTACK_LOGE("OH_NetStack_GetPinSetForHostName malloc failed");
108         return OHOS::NetStack::Ssl::SslErrorCode::SSL_X509_V_ERR_OUT_OF_MEMORY;
109     }
110 
111     if (strcpy_s(key, size, innerPins.c_str()) != 0) {
112         free(key);
113         NETSTACK_LOGE("OH_NetStack_GetPinSetForHostName string copy failed");
114         return OHOS::NetStack::Ssl::SslErrorCode::SSL_X509_V_ERR_OUT_OF_MEMORY;
115     }
116     pin->hashAlgorithm = NetStack_HashAlgorithm::SHA_256;
117     pin->kind = NetStack_CertificatePinningKind::PUBLIC_KEY;
118     pin->publicKeyHash = key;
119 
120     return OHOS::NetManagerStandard::NETMANAGER_SUCCESS;
121 }
122 
OH_NetStack_GetCertificatesForHostName(const char * hostname,NetStack_Certificates * certs)123 int32_t OH_NetStack_GetCertificatesForHostName(const char *hostname, NetStack_Certificates *certs)
124 {
125     if (hostname == nullptr || certs == nullptr) {
126         NETSTACK_LOGE("OH_NetStack_GetCertificatesForHostName received invalid parameters");
127         return OHOS::NetManagerStandard::NETMANAGER_ERR_PARAMETER_ERROR;
128     }
129 
130     std::string innerHostname = std::string(hostname);
131     std::vector<std::string> innerCerts;
132 
133     int32_t ret = OHOS::NetManagerStandard::NetConnClient::GetInstance()
134                   .GetTrustAnchorsForHostName(innerHostname, innerCerts);
135     if (ret != OHOS::NetManagerStandard::NETMANAGER_SUCCESS) {
136         return ret;
137     }
138 
139     size_t innerCertsLength = innerCerts.size();
140     if (innerCertsLength <= 0) {
141         certs->length = 0;
142         certs->content = nullptr;
143         return OHOS::NetManagerStandard::NETMANAGER_SUCCESS;
144     }
145 
146     size_t contentPtrSize = innerCertsLength * sizeof(char *);
147     size_t totalMallocSize = contentPtrSize;
148     for (size_t i = 0; i < innerCertsLength; ++i) {
149         totalMallocSize += innerCerts[i].size() + 1;
150     }
151     char *ptr = (char *)malloc(totalMallocSize);
152     if (ptr == nullptr) {
153         NETSTACK_LOGE("OH_NetStack_GetCertificatesForHostName malloc failed");
154         return OHOS::NetStack::Ssl::SslErrorCode::SSL_X509_V_ERR_OUT_OF_MEMORY;
155     }
156     char **contentPtr = reinterpret_cast<char **>(ptr);
157     char *certPtr = ptr + contentPtrSize;
158 
159     for (size_t i = 0; i < innerCertsLength; ++i) {
160         size_t certLen = innerCerts[i].size() + 1;
161         if (strcpy_s(certPtr, certLen, innerCerts[i].c_str()) != 0) {
162             free(ptr);
163             NETSTACK_LOGE("OH_NetStack_GetCertificatesForHostName string copy failed");
164             return OHOS::NetStack::Ssl::SslErrorCode::SSL_X509_V_ERR_OUT_OF_MEMORY;
165         }
166         contentPtr[i] = certPtr;
167         certPtr += certLen;
168     }
169 
170     certs->length = innerCertsLength;
171     certs->content = contentPtr;
172     return OHOS::NetManagerStandard::NETMANAGER_SUCCESS;
173 }
174 
OH_Netstack_DestroyCertificatesContent(NetStack_Certificates * certs)175 void OH_Netstack_DestroyCertificatesContent(NetStack_Certificates *certs)
176 {
177     if (certs == nullptr) {
178         NETSTACK_LOGE("OH_Netstack_DestroyCertificatesContent received invalid parameters");
179         return;
180     }
181 
182     if (certs->content == nullptr) {
183         return;
184     }
185 
186     free(certs->content);
187     certs->content = nullptr;
188     certs->length = 0;
189 }
190