GCC Code Coverage Report


Directory: src/gate/
File: src/gate/net/sslsessions.c
Date: 2025-12-12 23:40:09
Exec Total Coverage
Lines: 4 428 0.9%
Functions: 1 28 3.6%
Branches: 2 224 0.9%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2025, Stefan Meislinger <sm@opengate.at> |
4 | All rights reserved. |
5 | |
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28
29 #include "gate/net/sslsessions.h"
30 #include "gate/results.h"
31 #include "gate/debugging.h"
32
33 #if defined(GATE_SYS_WIN)
34 # if (defined(GATE_NET_SSL_API_OPENSSL) || defined(GATE_NET_SSL_API_RESSL))
35 # define GATE_NET_SSLSESSION_OPENSSL 1
36 # if defined(GATE_SYS_WINCE)
37 # pragma comment(lib, "ws2.lib")
38 # endif
39 # else
40 # if defined(GATE_SYS_WINSTORE) || defined(GATE_SYS_WIN16)
41 # define GATE_NET_SSLSESSION_NO_IMPL 1
42 # else
43 # define GATE_NET_SSLSESSION_WINCRYPT 1
44 # endif
45 # endif
46 #elif defined(GATE_SYS_POSIX)
47 # define GATE_NET_SSLSESSION_OPENSSL 1
48 #else
49 # define GATE_NET_SSLSESSION_NO_IMPL 1
50 #endif
51
52
53
54 /* generic implementation */
55
56 typedef struct gate_sslstream_class
57 {
58 GATE_INTERFACE_VTBL(gate_stream) const* vtbl;
59
60 gate_atomic_int_t ref_counter;
61
62 gate_ssl_session_t session;
63 gate_stream_t* transport;
64 char transport_readbuffer[GATE_MAX_COPYBUFFER_LENGTH];
65 gate_size_t transport_readbuffer_used;
66
67 } gate_sslstream_t;
68
69 static gate_result_t send_data_from_ssl_output(gate_ssl_session_t session, gate_stream_t* transport)
70 {
71 gate_result_t ret;
72 char buffer[GATE_MAX_COPYBUFFER_LENGTH];
73 gate_size_t buffer_used;
74 gate_size_t transmitted;
75
76 do
77 {
78 gate_mem_clear(buffer, sizeof(buffer));
79 buffer_used = 0;
80 ret = gate_ssl_session_get_encoded_data(session, buffer, sizeof(buffer), &buffer_used);
81 if (GATE_FAILED(ret) || (buffer_used == 0))
82 {
83 /* no more data in the session to be transmitted */
84 ret = GATE_RESULT_OK;
85 break;
86 }
87
88 ret = gate_stream_write_block(transport, buffer, buffer_used, &transmitted);
89 GATE_BREAK_IF_FAILED(ret);
90
91 if (transmitted != buffer_used)
92 {
93 ret = GATE_RESULT_INVALIDOUTPUT;
94 break;
95 }
96 } while (GATE_SUCCEEDED(ret));
97 return ret;
98 }
99
100 static gate_result_t read_data_from_transport_and_add_to_ssl(gate_stream_t* transport, gate_ssl_session_t session)
101 {
102 char buffer[GATE_MAX_COPYBUFFER_LENGTH];
103 gate_size_t buffer_used;
104 gate_size_t transmitted;
105 gate_size_t added;
106 gate_result_t ret;
107
108 do
109 {
110 ret = gate_stream_read(transport, buffer, sizeof(buffer), &buffer_used);
111 GATE_BREAK_IF_FAILED(ret);
112 if (buffer_used == 0)
113 {
114 ret = GATE_RESULT_ENDOFSTREAM;
115 break;
116 }
117
118 added = 0;
119 while (added < buffer_used)
120 {
121 transmitted = 0;
122 ret = gate_ssl_session_add_encoded_data(session, &buffer[added], buffer_used - added, &transmitted);
123 if (GATE_RESULT_NOTREADY == ret)
124 {
125 ret = send_data_from_ssl_output(session, transport);
126 GATE_BREAK_IF_FAILED(ret);
127 transmitted = 0;
128 }
129 else if (GATE_FAILED(ret))
130 {
131 break;
132 }
133 added += transmitted;
134 }
135 GATE_BREAK_IF_FAILED(ret);
136 } while (0);
137 return ret;
138 }
139
140
141 static gate_result_t sslstream_negotiate(gate_sslstream_t* self)
142 {
143 gate_result_t ret = GATE_RESULT_FAILED;
144 gate_bool_t is_neg_completed = false;
145
146 while (!is_neg_completed)
147 {
148 /* check if we are already negotiated */
149 ret = gate_ssl_session_is_negotiated(self->session, &is_neg_completed);
150 GATE_BREAK_IF_FAILED(ret);
151 if (is_neg_completed)
152 {
153 break;
154 }
155
156 ret = gate_ssl_session_negotiate(self->session);
157 GATE_BREAK_IF_FAILED(ret);
158
159 /* extract encoded data and send it to transport output */
160 ret = send_data_from_ssl_output(self->session, self->transport);
161 GATE_BREAK_IF_FAILED(ret);
162
163 /* check if we are already negotiated */
164 ret = gate_ssl_session_is_negotiated(self->session, &is_neg_completed);
165 GATE_BREAK_IF_FAILED(ret);
166 if (is_neg_completed)
167 {
168 break;
169 }
170
171 /* read encoded data from transport input and add it to SSL session */
172 ret = read_data_from_transport_and_add_to_ssl(self->transport, self->session);
173 GATE_BREAK_IF_FAILED(ret);
174 }
175 return ret;
176 }
177
178 static char const* sslstream_get_interface_name(void* obj)
179 {
180 GATE_UNUSED_ARG(obj);
181 return GATE_INTERFACE_NAME_STREAM;
182 }
183 static void sslstream_release(void* obj)
184 {
185 gate_sslstream_t* self = (gate_sslstream_t*)obj;
186 if (gate_atomic_int_dec(&self->ref_counter) == 0)
187 {
188 if (self->transport)
189 {
190 gate_object_release(self->transport);
191 }
192 gate_ssl_session_destroy(self->session);
193 }
194 }
195 static int sslstream_retain(void* obj)
196 {
197 gate_sslstream_t* self = (gate_sslstream_t*)obj;
198 return gate_atomic_int_inc(&self->ref_counter);
199 }
200
201 static gate_result_t sslstream_read(void* obj, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
202 {
203 gate_result_t ret;
204 gate_sslstream_t* self = (gate_sslstream_t*)obj;
205 gate_size_t bytes_read;
206
207 do
208 {
209 if (!buffer || (bufferlength == 0))
210 {
211 ret = GATE_RESULT_INVALIDARG;
212 break;
213 }
214
215 ret = sslstream_negotiate(self);
216 GATE_BREAK_IF_FAILED(ret);
217
218 do
219 {
220 ret = gate_ssl_session_read(self->session, buffer, bufferlength, &bytes_read);
221 GATE_BREAK_IF_FAILED(ret);
222
223 if (bytes_read > 0)
224 {
225 if (returned)
226 {
227 *returned = bytes_read;
228 }
229 /* bytes received -> success case */
230 break;
231 }
232
233 /* nothing to decode, we need more data from transport */
234 ret = read_data_from_transport_and_add_to_ssl(self->transport, self->session);
235 if (GATE_RESULT_ENDOFSTREAM == ret)
236 {
237 if (returned)
238 {
239 *returned = 0;
240 }
241 ret = GATE_RESULT_OK;
242 break;
243 }
244 } while (GATE_SUCCEEDED(ret));
245 } while (0);
246 return ret;
247 }
248 static gate_result_t sslstream_peek(void* obj, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
249 {
250 gate_sslstream_t* self = (gate_sslstream_t*)obj;
251 GATE_UNUSED_ARG(self);
252 GATE_UNUSED_ARG(buffer);
253 GATE_UNUSED_ARG(bufferlength);
254 GATE_UNUSED_ARG(returned);
255 return GATE_RESULT_NOTSUPPORTED;
256 }
257 static gate_result_t sslstream_write(void* obj, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
258 {
259 gate_result_t ret;
260 gate_sslstream_t* self = (gate_sslstream_t*)obj;
261
262 do
263 {
264 ret = sslstream_negotiate(self);
265 GATE_BREAK_IF_FAILED(ret);
266
267 ret = gate_ssl_session_write(self->session, buffer, bufferlength, written);
268 GATE_BREAK_IF_FAILED(ret);
269
270 ret = send_data_from_ssl_output(self->session, self->transport);
271 } while (0);
272 return ret;
273 }
274 static gate_result_t sslstream_flush(void* obj)
275 {
276 gate_result_t ret;
277 gate_sslstream_t* self = (gate_sslstream_t*)obj;
278 do
279 {
280 ret = sslstream_negotiate(self);
281 GATE_BREAK_IF_FAILED(ret);
282 ret = send_data_from_ssl_output(self->session, self->transport);
283 } while (0);
284 return ret;
285 }
286
287
288 static GATE_INTERFACE_VTBL(gate_stream) sslstream_vtbl;
289
290 static void gate_init_sslstream_vtbl()
291 {
292 if (!sslstream_vtbl.get_interface_name)
293 {
294 GATE_INTERFACE_VTBL(gate_stream) const local_vtbl =
295 {
296 &sslstream_get_interface_name,
297 &sslstream_release,
298 &sslstream_retain,
299
300 &sslstream_read,
301 &sslstream_peek,
302 &sslstream_write,
303 &sslstream_flush
304 };
305 sslstream_vtbl = local_vtbl;
306 }
307 }
308
309 gate_result_t gate_ssl_stream_create(gate_ssl_session_params_t const* params, gate_stream_t* transport_stream, gate_stream_t** ptr_ssl_stream)
310 {
311 gate_result_t ret = GATE_RESULT_FAILED;
312 gate_sslstream_t* sslstream = NULL;
313 do
314 {
315 if (!params || !transport_stream)
316 {
317 ret = GATE_RESULT_INVALIDARG;
318 break;
319 }
320
321 sslstream = (gate_sslstream_t*)gate_mem_alloc(sizeof(gate_sslstream_t));
322 if (NULL == sslstream)
323 {
324 ret = GATE_RESULT_OUTOFMEMORY;
325 break;
326 }
327 gate_mem_clear(sslstream, sizeof(gate_sslstream_t));
328 gate_init_sslstream_vtbl();
329 sslstream->vtbl = &sslstream_vtbl;
330 gate_atomic_int_init(&sslstream->ref_counter, 1);
331
332 ret = gate_ssl_session_create(params, &sslstream->session);
333 GATE_BREAK_IF_FAILED(ret);
334
335 sslstream->transport = transport_stream;
336 gate_object_retain(sslstream->transport);
337
338 ret = GATE_RESULT_OK;
339 if (ptr_ssl_stream)
340 {
341 *ptr_ssl_stream = (gate_stream_t*)sslstream;
342 sslstream = NULL;
343 }
344
345 } while (0);
346
347 if (sslstream)
348 {
349 gate_object_release(sslstream);
350 }
351 return ret;
352 }
353
354
355
356
357
358 #if defined(GATE_NET_SSLSESSION_WINCRYPT)
359
360 # ifndef SECURITY_WIN32
361 # define SECURITY_WIN32
362 # endif
363 # ifndef _WIN32_WINNT
364 # define _WIN32_WINNT 0x0400
365 # endif
366 # if !defined(GATE_COMPILER_MSVC98)
367 # include <winsock2.h>
368 # endif
369 # include <windows.h>
370 # include <schnlsp.h>
371 # include <wincrypt.h>
372 # include <tchar.h>
373 # include <security.h>
374 //# include <schannel.h>
375
376 #include "gate/platforms.h"
377
378 #if defined(GATE_COMPILER_MSVC)
379 # if defined(GATE_SYS_WINCE)
380 # pragma comment(lib, "ws2.lib")
381 # else
382 # pragma comment(lib,"ws2_32.lib")
383 # endif
384
385 #endif
386
387 #ifndef SCHANNEL_CRED_VERSION
388 #define SCHANNEL_CRED_VERSION 0x00000004
389 #endif
390
391 #ifndef SCH_CRED_NO_DEFAULT_CREDS
392 #define SCH_CRED_NO_DEFAULT_CREDS 0x00000010
393 #endif
394
395 #ifndef SCH_CRED_NO_SYSTEM_MAPPER
396 #define SCH_CRED_NO_SYSTEM_MAPPER 0x00000002
397 #endif
398
399 #ifndef SCH_CRED_REVOCATION_CHECK_CHAIN
400 #define SCH_CRED_REVOCATION_CHECK_CHAIN 0x00000200
401 #endif
402
403 #ifndef SCHANNEL_NAME
404 #define SCHANNEL_NAME _T("Schannel")
405 #endif
406
407 #ifndef SECPKG_CRED_OUTBOUND
408 #define SECPKG_CRED_OUTBOUND 0x00000002
409 #endif
410 #ifndef SEC_E_OK
411 #define SEC_E_OK ((HRESULT)0x00000000L)
412 #endif
413
414 #ifndef SP_PROT_SSL2_SERVER
415 #define SP_PROT_SSL2_SERVER 0x00000004
416 #endif
417
418 #ifndef SP_PROT_SSL3_SERVER
419 #define SP_PROT_SSL3_SERVER 0x00000010
420 #endif
421
422 #ifndef SP_PROT_TLS1_SERVER
423 #define SP_PROT_TLS1_SERVER 0x00000040
424 #endif
425
426 #ifndef SP_PROT_SSL3TLS1_SERVERS
427 #define SP_PROT_SSL3TLS1_SERVERS (SP_PROT_TLS1_SERVER | SP_PROT_SSL3_SERVER)
428 #endif
429
430 #ifndef SP_PROT_TLS1_0_SERVER
431 #define SP_PROT_TLS1_0_SERVER SP_PROT_TLS1_SERVER
432 #endif
433
434 #ifndef SP_PROT_TLS1_1_SERVER
435 #define SP_PROT_TLS1_1_SERVER 0x00000100
436 #endif
437
438 #ifndef SP_PROT_TLS1_2_SERVER
439 #define SP_PROT_TLS1_2_SERVER 0x00000400
440 #endif
441
442 #ifndef CERT_STORE_PROV_MEMORY
443 #define CERT_STORE_PROV_MEMORY ((LPCSTR) 2)
444 #endif
445
446 #ifndef X509_ASN_ENCODING
447 #define X509_ASN_ENCODING 0x00000001
448 #endif
449
450 #ifndef PKCS_7_ASN_ENCODING
451 #define PKCS_7_ASN_ENCODING 0x00010000
452 #endif
453
454 #ifndef CERT_COMPARE_SHIFT
455 #define CERT_COMPARE_SHIFT 16
456 #endif
457
458 #ifndef CERT_COMPARE_ANY
459 #define CERT_COMPARE_ANY 0
460 #endif
461
462 #ifndef CERT_FIND_ANY
463 #define CERT_FIND_ANY (CERT_COMPARE_ANY << CERT_COMPARE_SHIFT)
464 #endif
465
466 #ifndef PROV_RSA_FULL
467 #define PROV_RSA_FULL 1
468 #endif
469
470 #ifndef CRYPT_NEWKEYSET
471 #define CRYPT_NEWKEYSET 0x00000008
472 #endif
473
474 #ifndef CRYPT_MACHINE_KEYSET
475 #define CRYPT_MACHINE_KEYSET 0x00000020
476 #endif
477
478 #ifndef AT_SIGNATURE
479 #define AT_SIGNATURE 2
480 #endif
481
482 #ifndef CRYPT_EXPORTABLE
483 #define CRYPT_EXPORTABLE 0x00000001
484 #endif
485
486 #ifndef CERT_X500_NAME_STR
487 #define CERT_X500_NAME_STR 3
488 #endif
489
490 #ifndef szOID_RSA_SHA1RSA
491 #define szOID_RSA_SHA1RSA "1.2.840.113549.1.1.5"
492 #endif
493
494 #ifndef CERT_STORE_ADD_REPLACE_EXISTING
495 #define CERT_STORE_ADD_REPLACE_EXISTING 3
496 #endif
497
498 #ifndef CRYPT_DECODE_ALLOC_FLAG
499 #define CRYPT_DECODE_ALLOC_FLAG 0x8000
500 #endif
501
502 #ifndef PKCS_RSA_PRIVATE_KEY
503 #define PKCS_RSA_PRIVATE_KEY ((LPCSTR) 43)
504 #endif
505
506 #ifndef CERT_KEY_PROV_HANDLE_PROP_ID
507 #define CERT_KEY_PROV_HANDLE_PROP_ID 1
508 #endif
509
510 #ifndef AT_KEYEXCHANGE
511 #define AT_KEYEXCHANGE 1
512 #endif
513
514 #ifndef AT_SIGNATURE
515 #define AT_SIGNATURE 2
516 #endif
517
518 #ifndef CERT_KEY_PROV_INFO_PROP_ID
519 #define CERT_KEY_PROV_INFO_PROP_ID 2
520 #endif
521
522 #ifndef SECPKG_CRED_INBOUND
523 #define SECPKG_CRED_INBOUND 0x00000001
524 #endif
525
526 #ifndef ISC_REQ_REPLAY_DETECT
527 #define ISC_REQ_REPLAY_DETECT 0x00000004
528 #endif
529
530 #ifndef ISC_REQ_SEQUENCE_DETECT
531 #define ISC_REQ_SEQUENCE_DETECT 0x00000008
532 #endif
533
534 #ifndef ISC_RET_EXTENDED_ERROR
535 #define ISC_RET_EXTENDED_ERROR 0x00004000
536 #endif
537
538 #ifndef ISC_REQ_STREAM
539 #define ISC_REQ_STREAM 0x00008000
540 #endif
541
542 #ifndef ISC_REQ_CONFIDENTIALITY
543 #define ISC_REQ_CONFIDENTIALITY 0x00000010
544 #endif
545
546 #ifndef ISC_REQ_ALLOCATE_MEMORY
547 #define ISC_REQ_ALLOCATE_MEMORY 0x00000100
548 #endif
549
550 #ifndef ISC_REQ_MANUAL_CRED_VALIDATION
551 #define ISC_REQ_MANUAL_CRED_VALIDATION 0x00080000
552 #endif
553
554 #ifndef SECBUFFER_TOKEN
555 #define SECBUFFER_TOKEN 2
556 #endif
557
558 #ifndef SECBUFFER_EMPTY
559 #define SECBUFFER_EMPTY 0
560 #endif
561
562 #ifndef SECBUFFER_VERSION
563 #define SECBUFFER_VERSION 0
564 #endif
565
566 #ifndef ASC_REQ_ALLOCATE_MEMORY
567 #define ASC_REQ_ALLOCATE_MEMORY 0x00000100
568 #endif
569
570 #ifndef SEC_E_INCOMPLETE_MESSAGE
571 #define SEC_E_INCOMPLETE_MESSAGE _HRESULT_TYPEDEF_(0x80090318L)
572 #endif
573
574 #ifndef SEC_I_CONTINUE_NEEDED
575 #define SEC_I_CONTINUE_NEEDED _HRESULT_TYPEDEF_(0x00090312L)
576 #endif
577
578 #ifndef S_OK
579 #define S_OK ((HRESULT)0L)
580 #endif
581
582 #ifndef SECPKG_ATTR_STREAM_SIZES
583 #define SECPKG_ATTR_STREAM_SIZES 4
584 #endif
585
586 #ifndef SECBUFFER_DATA
587 #define SECBUFFER_DATA 1
588 #endif
589
590 #ifndef SECBUFFER_EXTRA
591 #define SECBUFFER_EXTRA 5
592 #endif
593
594 #ifndef SECBUFFER_STREAM_TRAILER
595 #define SECBUFFER_STREAM_TRAILER 6
596 #endif
597
598 #ifndef SECBUFFER_STREAM_HEADER
599 #define SECBUFFER_STREAM_HEADER 7
600 #endif
601
602 #ifndef SEC_I_CONTEXT_EXPIRED
603 #define SEC_I_CONTEXT_EXPIRED _HRESULT_TYPEDEF_(0x00090317L)
604 #endif
605
606 #ifndef SEC_I_RENEGOTIATE
607 #define SEC_I_RENEGOTIATE _HRESULT_TYPEDEF_(0x00090321L)
608 #endif
609
610 #ifndef SEC_Entry
611 #define SEC_Entry WINAPI
612 #endif
613
614 typedef struct gate_win32_crypt_functions_class
615 {
616 PCCERT_CONTEXT(WINAPI* Crypt32CertCreateCertificateContext)(DWORD dwCertEncodingType, BYTE const* pbCertEncoded, DWORD cbCertEncoded);
617 BOOL(WINAPI* Crypt32CryptAcquireCertificatePrivateKey)(PCCERT_CONTEXT pCert, DWORD dwFlags, void* pvReserved,
618 HCRYPTPROV* phCryptProv, DWORD* pdwKeySpec, BOOL* pfCallerFreeProv);
619 BOOL(WINAPI* Crypt32CryptDecodeObjectEx)(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE* pbEncoded, DWORD cbEncoded,
620 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void* pvStructInfo, DWORD* pcbStructInfo);
621 BOOL(WINAPI* Crypt32CertFreeCertificateContext)(PCCERT_CONTEXT pCertContext);
622 BOOL(WINAPI* Crypt32CertAddCertificateContextToStore)(HCERTSTORE hCertStore, PCCERT_CONTEXT pCertContext,
623 DWORD dwAddDisposition, PCCERT_CONTEXT* ppStoreContext);
624 BOOL(WINAPI* Crypt32CertCloseStore)(HCERTSTORE hCertStore, DWORD dwFlags);
625 BOOL(WINAPI* Crypt32CertSetCertificateContextProperty)(PCCERT_CONTEXT pCertContext, DWORD dwPropId, DWORD dwFlags, const void* pvData);
626 PCCERT_CONTEXT(WINAPI* Crypt32CertFindCertificateInStore)(HCERTSTORE hCertStore, DWORD dwCertEncodingType, DWORD dwFindFlags,
627 DWORD dwFindType, const void* pvFindPara, PCCERT_CONTEXT pPrevCertContext);
628 HCERTSTORE(WINAPI* Crypt32CertOpenStore)(LPCSTR lpszStoreProvider, DWORD dwMsgAndCertEncodingType,
629 HCRYPTPROV hCryptProv, DWORD dwFlags, const void* pvPara);
630 BOOL(WINAPI* Crypt32CertStrToNameW)(DWORD dwCertEncodingType, LPCWSTR pszX500, DWORD dwStrType, void* pvReserved,
631 BYTE* pbEncoded, DWORD* pcbEncoded, LPCWSTR* ppszError);
632
633
634 SECURITY_STATUS(SEC_Entry* Sec32EncryptMessage)(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo);
635 SECURITY_STATUS(SEC_Entry* Sec32AcceptSecurityContext)(PCredHandle phCredential, PCtxtHandle phContext, PSecBufferDesc pInput,
636 ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext,
637 PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsTimeStamp);
638 SECURITY_STATUS(SEC_Entry* Sec32DeleteSecurityContext)(PCtxtHandle phContext);
639 SECURITY_STATUS(SEC_Entry* Sec32QueryContextAttributes)(PCtxtHandle phContext, ULONG ulAttribute, PVOID pBuffer);
640 SECURITY_STATUS(SEC_Entry* Sec32AcquireCredentialsHandleW)(SEC_WCHAR* pszPrincipal, SEC_WCHAR* pszPackage, ULONG fCredentialUse,
641 PLUID pvLogonID, PVOID pAuthData, SEC_GET_KEY_FN pGetKeyFn,
642 PVOID pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry);
643 SECURITY_STATUS(SEC_Entry* Sec32FreeCredentialsHandle)(PCredHandle phCredential);
644 SECURITY_STATUS(SEC_Entry* Sec32DecryptMessage)(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP);
645 SECURITY_STATUS(SEC_Entry* Sec32InitializeSecurityContextW)(PCredHandle phCredential, PCtxtHandle phContext, SEC_WCHAR* pszTargetName, ULONG fContextReq,
646 ULONG Reserved1, ULONG TargetDataRep, PSecBufferDesc pInput, ULONG Reserved2,
647 PCtxtHandle phNewContext, PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry);
648 SECURITY_STATUS(SEC_Entry* Sec32FreeContextBuffer)(PVOID pvContextBuffer);
649
650
651
652 } gate_win32_crypt_functions_t;
653
654 static gate_win32_crypt_functions_t wincrypt32 = GATE_INIT_EMPTY;
655 static gate_bool_t volatile wincrypt32_loaded = false;
656
657 gate_result_t gate_ssl_load_win32_crypto_functions()
658 {
659 gate_result_t ret = GATE_RESULT_FAILED;
660 static HMODULE hmod_crypt32 = NULL;
661 static HMODULE hmod_sec32 = NULL;
662 gate_bool_t success;
663
664 do
665 {
666 if (wincrypt32_loaded)
667 {
668 ret = GATE_RESULT_OK;
669 break;
670 }
671
672 if (NULL == hmod_crypt32)
673 {
674 hmod_crypt32 = gate_win32_load_library(_T("crypt32"), 0);
675 if (NULL == hmod_crypt32)
676 {
677 ret = GATE_RESULT_NOTAVAILABLE;
678 break;
679 }
680 }
681
682 if (NULL == hmod_sec32)
683 {
684 hmod_sec32 = gate_win32_load_library(_T("secur32"), 0);
685 if (NULL == hmod_sec32)
686 {
687 ret = GATE_RESULT_NOTAVAILABLE;
688 break;
689 }
690 }
691
692 success = true;
693 success &= gate_win32_get_proc_address(hmod_crypt32, "CertCreateCertificateContext", &wincrypt32.Crypt32CertCreateCertificateContext);
694 success &= gate_win32_get_proc_address(hmod_crypt32, "CryptAcquireCertificatePrivateKey", &wincrypt32.Crypt32CryptAcquireCertificatePrivateKey);
695 success &= gate_win32_get_proc_address(hmod_crypt32, "CryptDecodeObjectEx", &wincrypt32.Crypt32CryptDecodeObjectEx);
696 success &= gate_win32_get_proc_address(hmod_crypt32, "CertFreeCertificateContext", &wincrypt32.Crypt32CertFreeCertificateContext);
697 success &= gate_win32_get_proc_address(hmod_crypt32, "CertAddCertificateContextToStore", &wincrypt32.Crypt32CertAddCertificateContextToStore);
698 success &= gate_win32_get_proc_address(hmod_crypt32, "CertCloseStore", &wincrypt32.Crypt32CertCloseStore);
699 success &= gate_win32_get_proc_address(hmod_crypt32, "CertSetCertificateContextProperty", &wincrypt32.Crypt32CertSetCertificateContextProperty);
700 success &= gate_win32_get_proc_address(hmod_crypt32, "CertFindCertificateInStore", &wincrypt32.Crypt32CertFindCertificateInStore);
701 success &= gate_win32_get_proc_address(hmod_crypt32, "CertOpenStore", &wincrypt32.Crypt32CertOpenStore);
702 success &= gate_win32_get_proc_address(hmod_crypt32, "CertStrToNameW", &wincrypt32.Crypt32CertStrToNameW);
703
704 success &= gate_win32_get_proc_address(hmod_sec32, "EncryptMessage", &wincrypt32.Sec32EncryptMessage);
705 success &= gate_win32_get_proc_address(hmod_sec32, "AcceptSecurityContext", &wincrypt32.Sec32AcceptSecurityContext);
706 success &= gate_win32_get_proc_address(hmod_sec32, "DeleteSecurityContext", &wincrypt32.Sec32DeleteSecurityContext);
707 success &= gate_win32_get_proc_address(hmod_sec32, "QueryContextAttributesW", &wincrypt32.Sec32QueryContextAttributes);
708 success &= gate_win32_get_proc_address(hmod_sec32, "AcquireCredentialsHandleW", &wincrypt32.Sec32AcquireCredentialsHandleW);
709 success &= gate_win32_get_proc_address(hmod_sec32, "FreeCredentialsHandle", &wincrypt32.Sec32FreeCredentialsHandle);
710 success &= gate_win32_get_proc_address(hmod_sec32, "DecryptMessage", &wincrypt32.Sec32DecryptMessage);
711 success &= gate_win32_get_proc_address(hmod_sec32, "InitializeSecurityContextW", &wincrypt32.Sec32InitializeSecurityContextW);
712 success &= gate_win32_get_proc_address(hmod_sec32, "FreeContextBuffer", &wincrypt32.Sec32FreeContextBuffer);
713
714
715 if (success)
716 {
717 wincrypt32_loaded = true;
718 ret = GATE_RESULT_OK;
719 }
720 } while (0);
721
722 return ret;
723 }
724
725
726 typedef struct gate_ssl_session_impl_class
727 {
728 bool server;
729 PCCERT_CONTEXT certificate;
730 SCHANNEL_CRED channel_cred;
731 CredHandle hcred;
732 CtxtHandle hctxt;
733 bool is_init;
734 bool is_negotiated;
735 gate_memstream_t* plain_output_buffer;
736 gate_memstream_t* crypt_output_buffer;
737 gate_memstream_t* crypt_input_buffer;
738 gate_memstream_t* plain_input_buffer;
739 } gate_ssl_session_impl_t;
740
741 static gate_atomic_lock_t gate_ssl_session_lock = GATE_ATOMIC_LOCK_INIT;
742 static gate_atomic_int_t gate_ssl_session_counter = 0;
743 static HCERTSTORE gate_ssl_session_certstore = NULL;
744
745
746 static gate_result_t gate_ssl_session_init()
747 {
748 gate_result_t ret = gate_ssl_load_win32_crypto_functions();
749
750 gate_atomic_lock_acquire(&gate_ssl_session_lock);
751
752 do
753 {
754 if (1 == gate_atomic_int_inc(&gate_ssl_session_counter))
755 {
756 /* first instantiation */
757 gate_ssl_session_certstore = wincrypt32.Crypt32CertOpenStore(CERT_STORE_PROV_MEMORY, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, 0, NULL);
758 if (gate_ssl_session_certstore == NULL)
759 {
760 gate_atomic_int_dec(&gate_ssl_session_counter);
761 ret = GATE_RESULT_FAILED;
762 break;
763 }
764 }
765 else
766 {
767 ret = GATE_RESULT_OK;
768 }
769
770 } while (0);
771
772 gate_atomic_lock_release(&gate_ssl_session_lock);
773
774 return ret;
775 }
776
777 #define GATE_SSL_SESSION_CRYPTO_CONTAINER "gate_crypto_container"
778 #define GATE_SSL_SESSION_CRYPTO_CONTAINER_T _T("gate_crypto_container")
779 #define GATE_SSL_SESSION_CRYPTO_CONTAINER_W L"gate_crypto_container"
780
781 #define GATE_SSL_SESSION_CRYPTO_NAME "CN=ssl, O=opengate.at"
782 #define GATE_SSL_SESSION_CRYPTO_NAME_W L"CN=ssl, O=opengate.at"
783
784 HCRYPTPROV gate_ssl_session_cryptoprovider()
785 {
786 HCRYPTPROV hCryptProv = 0;
787 if (gate_platform.AdvCryptAcquireContext)
788 {
789 if (!gate_platform.AdvCryptAcquireContext(&hCryptProv, GATE_SSL_SESSION_CRYPTO_CONTAINER_T, NULL, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET))
790 {
791 gate_platform.AdvCryptAcquireContext(&hCryptProv, GATE_SSL_SESSION_CRYPTO_CONTAINER_T, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET | CRYPT_MACHINE_KEYSET);
792 }
793 }
794 return hCryptProv;
795 }
796
797 typedef ULONG_PTR HCRYPTPROV_OR_NCRYPT_KEY_HANDLE;
798
799 typedef PCCERT_CONTEXT(WINAPI* CertCreateSelfSignCertificatePtr)(
800 HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProvOrNCryptKey,
801 PCERT_NAME_BLOB pSubjectIssuerBlob,
802 DWORD dwFlags,
803 PCRYPT_KEY_PROV_INFO pKeyProvInfo,
804 PCRYPT_ALGORITHM_IDENTIFIER pSignatureAlgorithm,
805 SYSTEMTIME* pStartTime,
806 SYSTEMTIME* pEndTime,
807 PCERT_EXTENSIONS pExtensions
808 );
809
810 static PCCERT_CONTEXT create_self_sign_certificate(
811 HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProvOrNCryptKey,
812 PCERT_NAME_BLOB pSubjectIssuerBlob,
813 DWORD dwFlags,
814 PCRYPT_KEY_PROV_INFO pKeyProvInfo,
815 PCRYPT_ALGORITHM_IDENTIFIER pSignatureAlgorithm,
816 SYSTEMTIME* pStartTime,
817 SYSTEMTIME* pEndTime,
818 PCERT_EXTENSIONS pExtensions
819 )
820 {
821 PCCERT_CONTEXT ret = NULL;
822 CertCreateSelfSignCertificatePtr func = NULL;
823 /*TODO*/
824 if (func != NULL)
825 {
826 ret = func(hCryptProvOrNCryptKey, pSubjectIssuerBlob, dwFlags, pKeyProvInfo,
827 pSignatureAlgorithm, pStartTime, pEndTime, pExtensions);
828 }
829 return ret;
830 }
831
832
833 static gate_result_t gate_ssl_session_uninit()
834 {
835 gate_result_t ret = GATE_RESULT_OK;
836
837 gate_atomic_lock_acquire(&gate_ssl_session_lock);
838
839 do
840 {
841 if (0 == gate_atomic_int_dec(&gate_ssl_session_counter))
842 {
843 wincrypt32.Crypt32CertCloseStore(gate_ssl_session_certstore, 0);
844 gate_ssl_session_certstore = NULL;
845 }
846
847 } while (0);
848 gate_atomic_lock_release(&gate_ssl_session_lock);
849 return ret;
850 }
851
852 static PCCERT_CONTEXT gate_ssl_session_get_random_certificate(HCERTSTORE certstore)
853 {
854 PCCERT_CONTEXT ret = NULL;
855 HCRYPTPROV hCryptProv = 0;
856 HCRYPTKEY hKey = 0;
857 HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProvOrNCryptKey = 0;
858 BYTE* pbEncoded = NULL;
859 DWORD cbEncoded = 0;
860 CERT_NAME_BLOB SubjectIssuerBlob;
861 CRYPT_KEY_PROV_INFO KeyProvInfo;
862 WCHAR container_name[] = GATE_SSL_SESSION_CRYPTO_CONTAINER_W;
863 CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm;
864 SYSTEMTIME EndTime;
865 DWORD keySpec;
866 BOOL fCallerFreeProvOrNCryptKey;
867
868 do
869 {
870 ret = wincrypt32.Crypt32CertFindCertificateInStore(gate_ssl_session_certstore,
871 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, NULL);
872
873 if (ret != NULL)
874 {
875 break;
876 }
877
878 hCryptProv = gate_ssl_session_cryptoprovider();
879 if (0 == (gate_uintptr_t)hCryptProv)
880 {
881 break;
882 }
883
884 /* create private key for certificate */
885 if (!gate_platform.AdvCryptGenKey(hCryptProv, AT_SIGNATURE, CRYPT_EXPORTABLE | 0x08000000 /*RSA-2048-BIT_KEY*/, &hKey))
886 {
887 break;
888 }
889
890 if (!wincrypt32.Crypt32CertStrToNameW(X509_ASN_ENCODING, GATE_SSL_SESSION_CRYPTO_NAME_W, CERT_X500_NAME_STR, NULL, pbEncoded, &cbEncoded, NULL))
891 {
892 break;
893 }
894 if (NULL == (pbEncoded = (BYTE*)gate_mem_alloc(cbEncoded)))
895 {
896 break;
897 }
898 if (!wincrypt32.Crypt32CertStrToNameW(X509_ASN_ENCODING, GATE_SSL_SESSION_CRYPTO_NAME_W, CERT_X500_NAME_STR, NULL, pbEncoded, &cbEncoded, NULL))
899 {
900 break;
901 }
902
903 gate_mem_clear(&SubjectIssuerBlob, sizeof(SubjectIssuerBlob));
904 SubjectIssuerBlob.cbData = cbEncoded;
905 SubjectIssuerBlob.pbData = pbEncoded;
906
907 /* Prepare key provider structure for self-signed certificate */
908
909 gate_mem_clear(&KeyProvInfo, sizeof(KeyProvInfo));
910 KeyProvInfo.pwszContainerName = container_name;
911 KeyProvInfo.pwszProvName = NULL;
912 KeyProvInfo.dwProvType = PROV_RSA_FULL;
913 KeyProvInfo.dwFlags = CRYPT_MACHINE_KEYSET;
914 KeyProvInfo.cProvParam = 0;
915 KeyProvInfo.rgProvParam = NULL;
916 KeyProvInfo.dwKeySpec = AT_SIGNATURE;
917
918 /* Prepare algorithm structure for self-signed certificate */
919 gate_mem_clear(&SignatureAlgorithm, sizeof(SignatureAlgorithm));
920 SignatureAlgorithm.pszObjId = szOID_RSA_SHA1RSA;
921
922 /* Prepare Expiration date for self-signed certificate */
923 GetSystemTime(&EndTime);
924 EndTime.wYear += 5;
925
926 ret = create_self_sign_certificate(0, &SubjectIssuerBlob, 0, &KeyProvInfo, &SignatureAlgorithm, 0, &EndTime, 0);
927 if (ret == NULL)
928 {
929 break;
930 }
931 if (!wincrypt32.Crypt32CertAddCertificateContextToStore(certstore, ret, CERT_STORE_ADD_REPLACE_EXISTING, 0))
932 {
933 break;
934 }
935
936 keySpec = 0;
937 if (!wincrypt32.Crypt32CryptAcquireCertificatePrivateKey(ret, 0, NULL, &hCryptProvOrNCryptKey, &keySpec, &fCallerFreeProvOrNCryptKey))
938 {
939 break;
940 }
941
942 } while (0);
943
944 if (hKey != 0)
945 {
946 gate_platform.AdvCryptDestroyKey(hKey);
947 }
948
949 if (pbEncoded != NULL)
950 {
951 gate_mem_dealloc(pbEncoded);
952 }
953
954 if (hCryptProvOrNCryptKey != 0)
955 {
956 gate_platform.AdvCryptReleaseContext(hCryptProvOrNCryptKey, 0);
957 }
958 if (hCryptProv)
959 {
960 gate_platform.AdvCryptReleaseContext(hCryptProv, 0);
961 }
962 return ret;
963 }
964
965 #if defined(GATE_SYS_WINCE)
966
967 static gate_size_t decode_b64_cert(void const* cert, gate_size_t cert_length, char* buffer, gate_size_t bufferlen)
968 {
969 gate_size_t ret = 0;
970 /*
971 StrToken block((char const*)data, datalen);
972 static StrToken const beginning("-----BEGIN");
973 static StrToken const ending("-----END");
974 static StrToken const header("-----");
975 size_t posBegin = block.indexOf(beginning);
976 if(posBegin != StrToken::npos)
977 {
978 size_t pos = block.indexOf(header, posBegin + beginning.size());
979 if(pos != StrToken::npos)
980 {
981 size_t posEnd = block.indexOf(ending, pos + header.size());
982 if(posEnd != StrToken::npos)
983 {
984 block = block.subString(pos + header.size(), posEnd - pos - header.size());
985 }
986 }
987 }
988 String b64 = Base64::stripUnknownChars(block);
989 String decoded = Base64::decodeData(b64);
990 buffer.allocate(decoded.size());
991 Mem::copy(&buffer[0], &decoded[0], decoded.size());
992 */
993 return ret;
994 }
995
996 #else
997
998 static gate_size_t decode_b64_cert(void const* cert, gate_size_t cert_length, char* buffer, gate_size_t bufferlen)
999 {
1000 gate_result_t ret = 0;
1001 /*
1002 String strCert((char const*)cert, certLen);
1003 WinString winstrCert(to_winapi_str(strCert));
1004
1005 DWORD certBufferLen = 16384;
1006 buffer.allocateItems(certBufferLen);
1007 BYTE* certBuffer = &buffer[0];
1008
1009 //if(!CryptStringToBinary(winstrCert.c_str(), (DWORD)winstrCert.size(), CRYPT_STRING_BASE64HEADER, certBuffer, &certBufferLen, NULL, NULL))
1010 if(!CryptStringToBinary(winstrCert.c_str(), (DWORD)winstrCert.size(), CRYPT_STRING_BASE64_ANY, certBuffer, &certBufferLen, NULL, NULL))
1011 {
1012 throw Exception(results::Failed, "Failed to convert private key", FuncName, (int)GetLastError());
1013 }
1014 buffer.allocateItems(certBufferLen);
1015 */
1016 return ret;
1017 }
1018
1019 #endif
1020
1021 static PCCERT_CONTEXT gate_ssl_session_load_server_certificate(void const* cert, gate_size_t cert_length,
1022 void const* private_key, gate_size_t private_key_len)
1023 {
1024 PCCERT_CONTEXT ret = NULL;
1025 PCCERT_CONTEXT ctx = NULL;
1026 char buffer[GATE_MAX_STACK_COPYBUFFER_LENGTH];
1027 DWORD bufferused;
1028 void* private_key_data = NULL;
1029 DWORD private_key_data_len;
1030 HCRYPTPROV cryptoprov = ((HCRYPTPROV)0);
1031 HCRYPTKEY hkey;
1032 CRYPT_KEY_PROV_PARAM param;
1033 CRYPT_KEY_PROV_INFO key_info;
1034 WCHAR crypt_container[] = GATE_SSL_SESSION_CRYPTO_CONTAINER_W;
1035
1036 do
1037 {
1038 bufferused = (DWORD)decode_b64_cert(cert, cert_length, buffer, sizeof(buffer));
1039 if (bufferused == 0)
1040 {
1041 GATE_DEBUG_TRACE("decode_b64_cert() failed");
1042 break;
1043 }
1044 ctx = wincrypt32.Crypt32CertCreateCertificateContext((PKCS_7_ASN_ENCODING | X509_ASN_ENCODING), (BYTE const*)buffer, bufferused);
1045
1046 if (ctx == NULL)
1047 {
1048 GATE_DEBUG_TRACE("Crypt32CertCreateCertificateContext() failed");
1049 break;
1050 }
1051 bufferused = (DWORD)decode_b64_cert(private_key, private_key_len, buffer, sizeof(buffer));
1052
1053 private_key_data_len = 0;
1054 if (!wincrypt32.Crypt32CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY,
1055 (BYTE const*)&buffer[0], bufferused, CRYPT_DECODE_ALLOC_FLAG, NULL, &private_key_data, &private_key_data_len))
1056 {
1057 GATE_DEBUG_TRACE("Crypt32CryptDecodeObjectEx() failed");
1058 break;
1059 }
1060
1061 cryptoprov = gate_ssl_session_cryptoprovider();
1062
1063 if (!gate_platform.AdvCryptImportKey(cryptoprov, (BYTE*)private_key_data, private_key_data_len, 0, 0, &hkey))
1064 {
1065 GATE_DEBUG_TRACE("AdvCryptImportKey() failed");
1066 break;
1067 }
1068 if (!wincrypt32.Crypt32CertSetCertificateContextProperty(ctx, CERT_KEY_PROV_HANDLE_PROP_ID, CERT_KEY_PROV_HANDLE_PROP_ID, &cryptoprov))
1069 {
1070 GATE_DEBUG_TRACE("Crypt32CertSetCertificateContextProperty() failed");
1071 break;
1072 }
1073
1074 param.dwParam = 0;
1075 param.pbData = (BYTE*)private_key_data;
1076 param.cbData = private_key_data_len;
1077 param.dwFlags = 0;
1078
1079 gate_mem_clear(&key_info, sizeof(key_info));
1080 key_info.pwszContainerName = crypt_container;
1081 key_info.pwszProvName = NULL;
1082 key_info.dwProvType = PROV_RSA_FULL;
1083 key_info.dwFlags = CRYPT_MACHINE_KEYSET;
1084 key_info.cProvParam = 0;
1085 key_info.rgProvParam = NULL;
1086 key_info.dwKeySpec = AT_KEYEXCHANGE;
1087
1088 if (!wincrypt32.Crypt32CertSetCertificateContextProperty(ctx, CERT_KEY_PROV_INFO_PROP_ID, 0, &key_info))
1089 {
1090 GATE_DEBUG_TRACE("Crypt32CertSetCertificateContextProperty() failed");
1091 break;
1092 }
1093
1094 /* all steps succeeded */
1095 GATE_DEBUG_TRACE("gate_ssl_session_load_server_certificate() succeeded");
1096 ret = ctx;
1097 ctx = NULL;
1098
1099 } while (0);
1100
1101 if (private_key_data != NULL)
1102 {
1103 LocalFree(private_key_data);
1104 }
1105
1106 if (cryptoprov != 0)
1107 {
1108 gate_platform.AdvCryptReleaseContext(cryptoprov, 0);
1109 }
1110
1111 if (ctx != NULL)
1112 {
1113 wincrypt32.Crypt32CertFreeCertificateContext(ctx);
1114 }
1115
1116 return ret;
1117 }
1118
1119 #ifndef SP_PROT_TLS1_3_SERVER
1120 #define SP_PROT_TLS1_3_SERVER 0x00001000
1121 #endif
1122
1123 #ifndef SP_PROT_TLS1_3_CLIENT
1124 #define SP_PROT_TLS1_3_CLIENT 0x00002000
1125 #endif
1126
1127 gate_result_t gate_ssl_init(gate_bool_t crypto_api_only)
1128 {
1129 gate_result_t ret;
1130
1131 GATE_UNUSED_ARG(crypto_api_only);
1132
1133 do
1134 {
1135 if (!gate_platform.AdvCryptAcquireContext || !gate_platform.AdvCryptGenKey
1136 || !gate_platform.AdvCryptImportKey || gate_platform.AdvCryptDestroyKey
1137 || !gate_platform.AdvCryptReleaseContext)
1138 {
1139 GATE_DEBUG_TRACE("Missing Adv Crypt functions");
1140 ret = GATE_RESULT_NOTSUPPORTED;
1141 break;
1142 }
1143
1144 ret = gate_ssl_load_win32_crypto_functions();
1145 GATE_BREAK_IF_FAILED(ret);
1146
1147 ret = GATE_RESULT_OK;
1148 } while (0);
1149
1150 return ret;
1151 }
1152
1153
1154 gate_result_t gate_ssl_thread_init()
1155 {
1156 gate_result_t ret;
1157
1158 do
1159 {
1160 ret = gate_ssl_init(false);
1161 GATE_BREAK_IF_FAILED(ret);
1162
1163 gate_ssl_session_init(); /* optional */
1164 ret = GATE_RESULT_OK;
1165 } while (0);
1166
1167 return ret;
1168 }
1169
1170 #ifndef SCHANNEL_NAME_W
1171 #define SCHANNEL_NAME_W L"Schannel"
1172 #endif
1173
1174 gate_result_t gate_ssl_session_create(gate_ssl_session_params_t const* params, gate_ssl_session_t* session)
1175 {
1176 gate_result_t ret;
1177 gate_ssl_session_impl_t* impl = NULL;
1178 SECURITY_STATUS sec_status;
1179 wchar_t provider_name[] = SCHANNEL_NAME_W;
1180 gate_bool_t session_init = false;
1181
1182 do
1183 {
1184 if ((params == NULL) || (session == NULL))
1185 {
1186 ret = GATE_RESULT_INVALIDARG;
1187 break;
1188 }
1189
1190 ret = gate_ssl_session_init();
1191 if (GATE_FAILED(ret))
1192 {
1193 break;
1194 }
1195 session_init = true;
1196
1197 impl = (gate_ssl_session_impl_t*)gate_mem_alloc(sizeof(gate_ssl_session_impl_t));
1198 if (impl == NULL)
1199 {
1200 ret = GATE_RESULT_OUTOFMEMORY;
1201 break;
1202 }
1203 gate_mem_clear(impl, sizeof(gate_ssl_session_impl_t));
1204 impl->is_negotiated = false;
1205 impl->plain_output_buffer = gate_memstream_create(0);
1206 impl->crypt_output_buffer = gate_memstream_create(0);
1207 impl->crypt_input_buffer = gate_memstream_create(0);
1208 impl->plain_input_buffer = gate_memstream_create(0);
1209 if ((impl->plain_output_buffer == NULL) || (impl->crypt_output_buffer == NULL)
1210 || (impl->crypt_input_buffer == NULL) || (impl->plain_input_buffer == NULL))
1211 {
1212 ret = GATE_RESULT_OUTOFMEMORY;
1213 break;
1214 }
1215
1216 if (params->server_side)
1217 {
1218 impl->server = true;
1219 //loadCryptLibrary();
1220
1221 if ((NULL == params->certificate) || (0 == params->certificate_length))
1222 {
1223 impl->certificate = gate_ssl_session_get_random_certificate(gate_ssl_session_certstore);
1224 }
1225 else
1226 {
1227 impl->certificate = gate_ssl_session_load_server_certificate(params->certificate, params->certificate_length,
1228 params->privatekey, params->privatekey_length);
1229 }
1230 if (impl->certificate == NULL)
1231 {
1232 GATE_DEBUG_TRACE("No server certificate loaded");
1233 ret = GATE_RESULT_INVALIDCONTENT;
1234 break;
1235 }
1236
1237 impl->channel_cred.dwVersion = SCHANNEL_CRED_VERSION;
1238 #if !defined(GATE_COMPILER_MSVC98)
1239 impl->channel_cred.dwFlags = (SCH_CRED_NO_DEFAULT_CREDS | SCH_CRED_NO_SYSTEM_MAPPER | SCH_CRED_REVOCATION_CHECK_CHAIN);
1240 #endif
1241 impl->channel_cred.hRootStore = NULL;
1242 impl->channel_cred.dwMinimumCipherStrength = 128;
1243 switch (params->session_version)
1244 {
1245 case GATE_SSL_SESSION_TYPE_AUTO:
1246 impl->channel_cred.grbitEnabledProtocols = SP_PROT_SSL3_SERVER
1247 | SP_PROT_TLS1_SERVER | SP_PROT_TLS1_1_SERVER | SP_PROT_TLS1_2_SERVER | SP_PROT_TLS1_3_SERVER;
1248 break;
1249 case GATE_SSL_SESSION_TYPE_SSL_3: impl->channel_cred.grbitEnabledProtocols = SP_PROT_SSL3_SERVER; break;
1250 case GATE_SSL_SESSION_TYPE_TLS_1_0: impl->channel_cred.grbitEnabledProtocols = SP_PROT_TLS1_SERVER; break;
1251 case GATE_SSL_SESSION_TYPE_TLS_1_1: impl->channel_cred.grbitEnabledProtocols = SP_PROT_TLS1_1_SERVER; break;
1252 case GATE_SSL_SESSION_TYPE_TLS_1_2: impl->channel_cred.grbitEnabledProtocols = SP_PROT_TLS1_2_SERVER; break;
1253 case GATE_SSL_SESSION_TYPE_TLS_1_3: impl->channel_cred.grbitEnabledProtocols = SP_PROT_TLS1_3_SERVER; break;
1254 default:
1255 break;
1256 }
1257
1258 if (impl->channel_cred.grbitEnabledProtocols == 0)
1259 {
1260 GATE_DEBUG_TRACE("Protocol not supported");
1261 ret = GATE_RESULT_NOTSUPPORTED;
1262 break;
1263 }
1264
1265 impl->channel_cred.cCreds = 1;
1266 impl->channel_cred.paCred = &impl->certificate;
1267
1268 sec_status = wincrypt32.Sec32AcquireCredentialsHandleW(NULL,
1269 provider_name,
1270 SECPKG_CRED_INBOUND,
1271 NULL,
1272 &impl->channel_cred,
1273 0,
1274 NULL,
1275 &impl->hcred,
1276 0);
1277 if (sec_status != SEC_E_OK)
1278 {
1279 GATE_DEBUG_TRACE("Sec32AcquireCredentialsHandleW() failed");
1280 ret = GATE_RESULT_FAILED;
1281 break;
1282 }
1283 }
1284 else
1285 {
1286 impl->server = false;
1287
1288 gate_mem_clear(&impl->channel_cred, sizeof(impl->channel_cred));
1289 impl->channel_cred.dwVersion = SCHANNEL_CRED_VERSION;
1290 #if !defined(GATE_COMPILER_MSVC98)
1291 impl->channel_cred.dwFlags = (SCH_CRED_NO_DEFAULT_CREDS | SCH_CRED_NO_SYSTEM_MAPPER | SCH_CRED_REVOCATION_CHECK_CHAIN);
1292 #endif
1293 if (params->certificate != NULL)
1294 {
1295 impl->channel_cred.cCreds = 1;
1296 impl->channel_cred.paCred = (PCCERT_CONTEXT*)params->certificate;
1297 }
1298
1299 sec_status = wincrypt32.Sec32AcquireCredentialsHandleW(0,
1300 provider_name,
1301 SECPKG_CRED_OUTBOUND,
1302 0,
1303 &impl->channel_cred,
1304 NULL,
1305 NULL,
1306 &impl->hcred,
1307 NULL);
1308 if (sec_status != SEC_E_OK)
1309 {
1310 GATE_DEBUG_TRACE("Sec32AcquireCredentialsHandleW() failed");
1311 ret = GATE_RESULT_FAILED;
1312 break;
1313 }
1314 }
1315
1316 /* initialization was successful */
1317
1318 *session = impl;
1319 impl = NULL;
1320 } while (0);
1321
1322 if (impl != NULL)
1323 {
1324 if (impl->plain_output_buffer != NULL) gate_object_release(impl->plain_output_buffer);
1325 if (impl->crypt_output_buffer != NULL) gate_object_release(impl->crypt_output_buffer);
1326 if (impl->crypt_input_buffer != NULL) gate_object_release(impl->crypt_input_buffer);
1327 if (impl->plain_input_buffer != NULL) gate_object_release(impl->plain_input_buffer);
1328
1329 gate_mem_dealloc(impl);
1330 }
1331
1332 if (GATE_FAILED(ret) && session_init)
1333 {
1334 gate_ssl_session_uninit();
1335 }
1336
1337 return ret;
1338 }
1339 gate_result_t gate_ssl_session_destroy(gate_ssl_session_t session)
1340 {
1341 gate_result_t ret = GATE_RESULT_OK;
1342 gate_ssl_session_impl_t* impl = (gate_ssl_session_impl_t*)session;
1343 SECURITY_STATUS sec_status;
1344 if (impl)
1345 {
1346 gate_object_release(impl->crypt_input_buffer);
1347 gate_object_release(impl->crypt_output_buffer);
1348 gate_object_release(impl->plain_input_buffer);
1349 gate_object_release(impl->plain_output_buffer);
1350
1351 sec_status = wincrypt32.Sec32FreeCredentialsHandle(&impl->hcred);
1352 if (FAILED(sec_status))
1353 {
1354 ret = GATE_RESULT_FAILED;
1355 }
1356
1357 sec_status = wincrypt32.Sec32DeleteSecurityContext(&impl->hctxt);
1358 if (FAILED(sec_status))
1359 {
1360 ret = GATE_RESULT_FAILED;
1361 }
1362
1363 if (!wincrypt32.Crypt32CertFreeCertificateContext(impl->certificate))
1364 {
1365 ret = GATE_RESULT_FAILED;
1366 }
1367 gate_mem_dealloc(impl);
1368 }
1369 return ret;
1370 }
1371
1372 gate_result_t gate_ssl_session_is_negotiated(gate_ssl_session_t session, gate_bool_t* completed)
1373 {
1374 gate_ssl_session_impl_t* impl = (gate_ssl_session_impl_t*)session;
1375 if (session == NULL)
1376 {
1377 return GATE_RESULT_INVALIDARG;
1378 }
1379 else
1380 {
1381 if (completed)
1382 {
1383 *completed = impl->is_negotiated;
1384 }
1385 GATE_DEBUG_TRACE_VALUE(impl->is_negotiated);
1386 return GATE_RESULT_OK;
1387 }
1388 }
1389 gate_result_t gate_ssl_session_negotiate(gate_ssl_session_t session)
1390 {
1391 gate_ssl_session_impl_t* impl = (gate_ssl_session_impl_t*)session;
1392 gate_result_t ret = GATE_RESULT_FAILED;
1393 DWORD sspi_flags;
1394 unsigned long sspi_out_flags;
1395 SecBuffer input_buffer[2];
1396 SecBufferDesc input_buffer_descr;
1397 SecBuffer output_buffer[4];
1398 SecBufferDesc output_buffer_descr;
1399 ULONG context_attr = 0;
1400 SECURITY_STATUS sec_status;
1401 gate_size_t written;
1402
1403 do
1404 {
1405 if (impl->is_negotiated)
1406 {
1407 ret = GATE_RESULT_OK;
1408 break;
1409 }
1410
1411 if (impl->server)
1412 {
1413 /* server side implementation */
1414
1415 if (gate_memstream_size(impl->plain_output_buffer) == 0)
1416 {
1417 GATE_DEBUG_TRACE("No data in plain-output-buffer");
1418 ret = GATE_RESULT_NODATA;
1419 break;
1420 }
1421
1422 sspi_flags = ISC_REQ_SEQUENCE_DETECT
1423 | ISC_REQ_REPLAY_DETECT
1424 | ISC_REQ_CONFIDENTIALITY
1425 | ISC_RET_EXTENDED_ERROR
1426 | ISC_REQ_ALLOCATE_MEMORY
1427 | ISC_REQ_STREAM
1428 | ISC_REQ_MANUAL_CRED_VALIDATION
1429 ;
1430
1431 ;
1432
1433 input_buffer[0].BufferType = SECBUFFER_TOKEN;
1434 input_buffer[0].cbBuffer = (unsigned long)gate_memstream_size(impl->crypt_input_buffer);
1435 input_buffer[0].pvBuffer = (void*)gate_memstream_get_data(impl->crypt_input_buffer);
1436 input_buffer[1].BufferType = SECBUFFER_EMPTY;
1437 input_buffer[1].cbBuffer = 0;
1438 input_buffer[1].pvBuffer = 0;
1439
1440 input_buffer_descr.ulVersion = SECBUFFER_VERSION;
1441 input_buffer_descr.pBuffers = input_buffer;
1442 input_buffer_descr.cBuffers = 2;
1443
1444 output_buffer[0].BufferType = SECBUFFER_TOKEN;
1445 output_buffer[0].cbBuffer = 0;
1446 output_buffer[0].pvBuffer = NULL;
1447 output_buffer[1].BufferType = SECBUFFER_EMPTY;
1448 output_buffer[1].cbBuffer = 0;
1449 output_buffer[1].pvBuffer = NULL;
1450 output_buffer[2].BufferType = SECBUFFER_EMPTY;
1451 output_buffer[2].cbBuffer = 0;
1452 output_buffer[2].pvBuffer = NULL;
1453 output_buffer[3].BufferType = SECBUFFER_EMPTY;
1454 output_buffer[3].cbBuffer = 0;
1455 output_buffer[3].pvBuffer = NULL;
1456
1457 output_buffer_descr.ulVersion = SECBUFFER_VERSION;
1458 output_buffer_descr.pBuffers = output_buffer;
1459 output_buffer_descr.cBuffers = 2;
1460
1461 context_attr = 0;
1462 sec_status = wincrypt32.Sec32AcceptSecurityContext(&impl->hcred,
1463 impl->is_init ? &impl->hctxt : NULL,
1464 &input_buffer_descr,
1465 ASC_REQ_ALLOCATE_MEMORY,
1466 0,
1467 impl->is_init ? 0 : &impl->hctxt,
1468 &output_buffer_descr,
1469 &context_attr,
1470 NULL);
1471
1472 impl->is_init = true;
1473
1474 if (sec_status == SEC_E_INCOMPLETE_MESSAGE)
1475 {
1476 GATE_DEBUG_TRACE("Sec32AcceptSecurityContext() incomplete message OK");
1477 ret = GATE_RESULT_OK_PARTIAL;
1478 break;
1479 }
1480
1481 gate_memstream_reset(impl->crypt_input_buffer);
1482
1483 if (FAILED(sec_status) || ((sec_status != SEC_I_CONTINUE_NEEDED) && (sec_status != S_OK)))
1484 {
1485 GATE_DEBUG_TRACE("Sec32AcceptSecurityContext() failed");
1486 ret = GATE_RESULT_FAILED;
1487 break;
1488 }
1489
1490 ret = GATE_RESULT_OK;
1491 if (output_buffer[0].cbBuffer > 0)
1492 {
1493 ret = gate_stream_write_block((gate_stream_t*)impl->crypt_output_buffer,
1494 (char const*)output_buffer[0].pvBuffer, output_buffer[0].cbBuffer, &written);
1495 wincrypt32.Sec32FreeContextBuffer(output_buffer[0].pvBuffer);
1496 }
1497
1498 if (GATE_SUCCEEDED(ret))
1499 {
1500 GATE_DEBUG_TRACE("data successfully written to crypt-output-buffer");
1501 if (sec_status == S_OK)
1502 {
1503 GATE_DEBUG_TRACE("security context accepted");
1504 impl->is_negotiated = true;
1505 ret = GATE_RESULT_OK;
1506 }
1507 else
1508 {
1509 GATE_DEBUG_TRACE("security context partially accepted");
1510 ret = GATE_RESULT_OK_PARTIAL;
1511 }
1512 }
1513 else
1514 {
1515 GATE_DEBUG_TRACE("failed to write data to crypt-output-buffer");
1516 }
1517 }
1518 else
1519 {
1520 /* client side implementation */
1521 sspi_flags = ISC_REQ_SEQUENCE_DETECT
1522 | ISC_REQ_REPLAY_DETECT
1523 | ISC_REQ_CONFIDENTIALITY
1524 | ISC_RET_EXTENDED_ERROR
1525 | ISC_REQ_ALLOCATE_MEMORY
1526 | ISC_REQ_STREAM
1527 | ISC_REQ_MANUAL_CRED_VALIDATION;
1528
1529 if (impl->is_init)
1530 {
1531 if (gate_memstream_size(impl->crypt_input_buffer) == 0)
1532 {
1533 /* no encrypted data received, no progress possible */
1534 GATE_DEBUG_TRACE("no data in crypt-input-buffer");
1535 ret = GATE_RESULT_OK_PARTIAL;
1536 break;
1537 }
1538
1539 input_buffer[0].BufferType = SECBUFFER_TOKEN;
1540 input_buffer[0].cbBuffer = (unsigned long)gate_memstream_size(impl->crypt_input_buffer);
1541 input_buffer[0].pvBuffer = (void*)gate_memstream_get_data(impl->crypt_input_buffer);
1542 input_buffer[1].BufferType = SECBUFFER_EMPTY;
1543 input_buffer[1].cbBuffer = 0;
1544 input_buffer[1].pvBuffer = 0;
1545
1546 input_buffer_descr.ulVersion = SECBUFFER_VERSION;
1547 input_buffer_descr.pBuffers = input_buffer;
1548 input_buffer_descr.cBuffers = 2;
1549
1550 }
1551
1552
1553 output_buffer[0].BufferType = SECBUFFER_TOKEN;
1554 output_buffer[0].cbBuffer = 0;
1555 output_buffer[0].pvBuffer = NULL;
1556
1557 output_buffer_descr.ulVersion = SECBUFFER_VERSION;
1558 output_buffer_descr.pBuffers = output_buffer;
1559 output_buffer_descr.cBuffers = 1;
1560
1561 sspi_out_flags = 0;
1562
1563 sec_status = wincrypt32.Sec32InitializeSecurityContextW(&impl->hcred,
1564 impl->is_init ? &impl->hctxt : NULL, NULL, sspi_flags, 0, 0,
1565 impl->is_init ? &input_buffer_descr : NULL, 0,
1566 impl->is_init ? 0 : &impl->hctxt, &output_buffer_descr, &sspi_out_flags, 0);
1567
1568 if (sec_status == SEC_E_INCOMPLETE_MESSAGE)
1569 {
1570 GATE_DEBUG_TRACE("Sec32InitializeSecurityContextW() incomplete message OK");
1571 ret = GATE_RESULT_OK_PARTIAL;
1572 break;
1573 }
1574
1575 gate_memstream_reset(impl->crypt_input_buffer);
1576
1577 if (FAILED(sec_status))
1578 {
1579 GATE_DEBUG_TRACE("Sec32InitializeSecurityContextW() failed");
1580 ret = GATE_RESULT_FAILED;
1581 break;
1582 }
1583
1584 if (!impl->is_init && (sec_status != SEC_I_CONTINUE_NEEDED))
1585 {
1586 GATE_DEBUG_TRACE("Sec32InitializeSecurityContextW() invalid state");
1587 ret = GATE_RESULT_FAILED;
1588 break;
1589 }
1590
1591 ret = GATE_RESULT_OK;
1592 if (output_buffer->cbBuffer > 0)
1593 {
1594 ret = gate_stream_write_block((gate_stream_t*)impl->crypt_output_buffer,
1595 (char const*)output_buffer->pvBuffer, output_buffer->cbBuffer, &written);
1596 wincrypt32.Sec32FreeContextBuffer(output_buffer->pvBuffer);
1597 }
1598
1599 if (SUCCEEDED(ret))
1600 {
1601 GATE_DEBUG_TRACE("data written to crypt-output-buffer");
1602 if (!impl->is_init)
1603 {
1604 impl->is_init = true;
1605 ret = GATE_RESULT_OK_PARTIAL;
1606 break;
1607 }
1608
1609 if (sec_status == S_OK)
1610 {
1611 GATE_DEBUG_TRACE("security context successfully created");
1612 impl->is_negotiated = true;
1613 }
1614 else
1615 {
1616 GATE_DEBUG_TRACE("security context partially created");
1617 ret = GATE_RESULT_OK_PARTIAL;
1618 }
1619 }
1620 else
1621 {
1622 GATE_DEBUG_TRACE("failed to write data to crypt-output-buffer");
1623 }
1624 }
1625
1626 } while (0);
1627
1628 return ret;
1629 }
1630
1631 gate_result_t gate_ssl_session_write(gate_ssl_session_t session, char const* plaindatabuffer, gate_size_t bufferlen, gate_size_t* datawritten)
1632 {
1633 gate_result_t ret = GATE_RESULT_FAILED;
1634 gate_ssl_session_impl_t* impl = (gate_ssl_session_impl_t*)session;
1635 SecPkgContext_StreamSizes spc_stream_sizes;
1636 SECURITY_STATUS sec_status;
1637 char* buffer_header = NULL;
1638 char* buffer_message = NULL;
1639 char* buffer_trailer = NULL;
1640 gate_size_t length;
1641 SecBuffer sec_buffer[4];
1642 SecBufferDesc sec_buffer_descr;
1643
1644
1645 do
1646 {
1647 if (bufferlen == 0)
1648 {
1649 GATE_DEBUG_TRACE("No data to write to session");
1650 ret = GATE_RESULT_OK_PARTIAL;
1651 break;
1652 }
1653
1654 sec_status = wincrypt32.Sec32QueryContextAttributes(&impl->hctxt, SECPKG_ATTR_STREAM_SIZES, &spc_stream_sizes);
1655 if (FAILED(sec_status))
1656 {
1657 GATE_DEBUG_TRACE("Sec32QueryContextAttributes() failed");
1658 if (datawritten != NULL)
1659 {
1660 *datawritten = 0;
1661 ret = GATE_RESULT_OK_PARTIAL;
1662 }
1663 break;
1664 }
1665
1666 buffer_header = (char*)gate_mem_alloc((gate_size_t)spc_stream_sizes.cbHeader * 2);
1667 buffer_message = (char*)gate_mem_alloc((gate_size_t)spc_stream_sizes.cbMaximumMessage * 2);
1668 buffer_trailer = (char*)gate_mem_alloc((gate_size_t)spc_stream_sizes.cbTrailer * 2);
1669 if ((buffer_header == NULL) || (buffer_message == NULL) || (buffer_trailer == NULL))
1670 {
1671 ret = GATE_RESULT_OUTOFMEMORY;
1672 break;
1673 }
1674
1675 length = (bufferlen < spc_stream_sizes.cbMaximumMessage) ? bufferlen : spc_stream_sizes.cbMaximumMessage;
1676 gate_mem_copy(&buffer_message[0], plaindatabuffer, length);
1677
1678 if (datawritten != NULL)
1679 {
1680 *datawritten = length;
1681 }
1682
1683 sec_buffer[0].BufferType = SECBUFFER_STREAM_HEADER;
1684 sec_buffer[0].cbBuffer = spc_stream_sizes.cbHeader;
1685 sec_buffer[0].pvBuffer = &buffer_header[0];
1686
1687 sec_buffer[1].BufferType = SECBUFFER_DATA;
1688 sec_buffer[1].cbBuffer = (unsigned long)length;
1689 sec_buffer[1].pvBuffer = &buffer_message[0];
1690
1691 sec_buffer[2].BufferType = SECBUFFER_STREAM_TRAILER;
1692 sec_buffer[2].cbBuffer = spc_stream_sizes.cbTrailer;
1693 sec_buffer[2].pvBuffer = &buffer_trailer[0];
1694
1695 sec_buffer[3].BufferType = SECBUFFER_EMPTY;
1696 sec_buffer[3].cbBuffer = 0;
1697 sec_buffer[3].pvBuffer = 0;
1698
1699 sec_buffer_descr.ulVersion = SECBUFFER_VERSION;
1700 sec_buffer_descr.pBuffers = sec_buffer;
1701 sec_buffer_descr.cBuffers = sizeof(sec_buffer) / sizeof(sec_buffer[0]);
1702
1703 sec_status = wincrypt32.Sec32EncryptMessage(&impl->hctxt, 0, &sec_buffer_descr, 0);
1704 if (FAILED(sec_status))
1705 {
1706 GATE_DEBUG_TRACE("Sec32EncryptMessage() failed");
1707 gate_win32_setlasterror(sec_status);
1708 ret = GATE_RESULT_FAILED;
1709 break;
1710 }
1711
1712 GATE_BREAK_IF_FAILED(ret = gate_stream_write_block((gate_stream_t*)impl->crypt_output_buffer,
1713 (char const*)sec_buffer[0].pvBuffer, (size_t)sec_buffer[0].cbBuffer, &length));
1714 GATE_BREAK_IF_FAILED(ret = gate_stream_write_block((gate_stream_t*)impl->crypt_output_buffer,
1715 (char const*)sec_buffer[1].pvBuffer, (size_t)sec_buffer[1].cbBuffer, &length));
1716 GATE_BREAK_IF_FAILED(ret = gate_stream_write_block((gate_stream_t*)impl->crypt_output_buffer,
1717 (char const*)sec_buffer[2].pvBuffer, (size_t)sec_buffer[2].cbBuffer, &length));
1718
1719 ret = GATE_RESULT_OK;
1720
1721 } while (0);
1722
1723 if (buffer_header != NULL) gate_mem_dealloc(buffer_header);
1724 if (buffer_message != NULL) gate_mem_dealloc(buffer_message);
1725 if (buffer_trailer != NULL) gate_mem_dealloc(buffer_trailer);
1726
1727 return ret;
1728 }
1729 gate_result_t gate_ssl_session_get_encoded_data(gate_ssl_session_t session, char* encodedbuffer, gate_size_t bufferlen, gate_size_t* bufferused)
1730 {
1731 gate_result_t ret = GATE_RESULT_FAILED;
1732 gate_ssl_session_impl_t* impl = (gate_ssl_session_impl_t*)session;
1733 gate_size_t encoded_bytes_extracted;
1734 gate_size_t crypt_buffer_len = gate_memstream_size(impl->crypt_output_buffer);
1735 char const* crypt_buffer = gate_memstream_get_data(impl->crypt_output_buffer);
1736
1737 do
1738 {
1739 if (crypt_buffer_len == 0)
1740 {
1741 GATE_DEBUG_TRACE("No data in crypt-output-buffer");
1742 ret = GATE_RESULT_OK_PARTIAL;
1743 break;
1744 }
1745 encoded_bytes_extracted = (crypt_buffer_len < bufferlen) ? crypt_buffer_len : bufferlen;
1746 gate_mem_copy(encodedbuffer, crypt_buffer, encoded_bytes_extracted);
1747 gate_memstream_discard(impl->crypt_output_buffer, encoded_bytes_extracted);
1748
1749 GATE_DEBUG_TRACE_VALUE(encoded_bytes_extracted);
1750 if (bufferused != NULL)
1751 {
1752 *bufferused = encoded_bytes_extracted;
1753 }
1754
1755 ret = GATE_RESULT_OK;
1756 } while (0);
1757
1758 return ret;
1759 }
1760
1761 gate_result_t gate_ssl_session_add_encoded_data(gate_ssl_session_t session, char const* encodedbuffer, gate_size_t bufferlen, gate_size_t* bytesadded)
1762 {
1763 gate_ssl_session_impl_t* impl = (gate_ssl_session_impl_t*)session;
1764 return gate_stream_write_block((gate_stream_t*)impl->crypt_input_buffer, encodedbuffer, bufferlen, bytesadded);
1765 }
1766 gate_result_t gate_ssl_session_read(gate_ssl_session_t session, char* paindatabuffer, gate_size_t bufferlen, gate_size_t* datareturned)
1767 {
1768 gate_result_t ret = GATE_RESULT_FAILED;
1769 gate_ssl_session_impl_t* impl = (gate_ssl_session_impl_t*)session;
1770 gate_size_t dataread = 0;
1771 gate_size_t crypt_buffer_length = gate_memstream_size(impl->crypt_input_buffer);
1772 char const* crypt_buffer = gate_memstream_get_data(impl->crypt_input_buffer);
1773 SECURITY_STATUS sec_status;
1774 SecPkgContext_StreamSizes spc_stream_sizes;
1775 SecBuffer sec_buffers[4] = GATE_INIT_EMPTY;
1776 SecBufferDesc sec_buffer_descr;
1777 char* message_buffer = NULL;
1778 gate_size_t message_buffer_length = 0;
1779 unsigned int ndx;
1780
1781 do
1782 {
1783 if (!impl->is_init)
1784 {
1785 if (datareturned) *datareturned = 0;
1786 ret = GATE_RESULT_OK_PARTIAL;
1787 break;
1788 }
1789
1790 if (crypt_buffer_length != 0)
1791 {
1792 sec_status = wincrypt32.Sec32QueryContextAttributes(&impl->hctxt, SECPKG_ATTR_STREAM_SIZES, &spc_stream_sizes);
1793 if (FAILED(sec_status))
1794 {
1795 GATE_DEBUG_TRACE("Sec32QueryContextAttributes() failed");
1796 gate_win32_setlasterror(sec_status);
1797 ret = GATE_RESULT_FAILED;
1798 break;
1799 }
1800
1801 message_buffer_length = crypt_buffer_length;
1802 if (spc_stream_sizes.cbMaximumMessage != 0)
1803 {
1804 message_buffer_length = spc_stream_sizes.cbMaximumMessage - (crypt_buffer_length % spc_stream_sizes.cbMaximumMessage);
1805 }
1806 message_buffer = (char*)gate_mem_alloc(message_buffer_length);
1807 if (message_buffer == NULL)
1808 {
1809 ret = GATE_RESULT_OUTOFMEMORY;
1810 break;
1811 }
1812 gate_mem_copy(message_buffer, crypt_buffer, crypt_buffer_length);
1813
1814 sec_buffers[0].BufferType = SECBUFFER_DATA;
1815 sec_buffers[0].cbBuffer = (unsigned long)crypt_buffer_length;
1816 sec_buffers[0].pvBuffer = &message_buffer[0];
1817
1818 sec_buffers[1].BufferType = SECBUFFER_EMPTY;
1819 sec_buffers[2].BufferType = SECBUFFER_EMPTY;
1820 sec_buffers[3].BufferType = SECBUFFER_EMPTY;
1821
1822 sec_buffer_descr.ulVersion = SECBUFFER_VERSION;
1823 sec_buffer_descr.cBuffers = sizeof(sec_buffers) / sizeof(sec_buffers[0]);
1824 sec_buffer_descr.pBuffers = sec_buffers;
1825
1826 sec_status = wincrypt32.Sec32DecryptMessage(&impl->hctxt, &sec_buffer_descr, 0, NULL);
1827 if (sec_status == SEC_E_INCOMPLETE_MESSAGE)
1828 {
1829 GATE_DEBUG_TRACE("Sec32DecryptMessage() incomplete message OK");
1830 gate_memstream_discard(impl->crypt_input_buffer, crypt_buffer_length);
1831 ret = GATE_RESULT_OK_PARTIAL;
1832 break;
1833 }
1834 else if ((sec_status != SEC_I_CONTEXT_EXPIRED) && (sec_status != SEC_I_RENEGOTIATE) && (sec_status != SEC_E_OK))
1835 {
1836 GATE_DEBUG_TRACE("Sec32DecryptMessage() failed");
1837 gate_win32_setlasterror(sec_status);
1838 ret = GATE_RESULT_FAILED;
1839 break;
1840 }
1841
1842 gate_memstream_discard(impl->crypt_input_buffer, crypt_buffer_length);
1843 /* input buffer is now empty */
1844
1845 ret = GATE_RESULT_OK;
1846
1847 for (ndx = 0; ndx != sec_buffer_descr.cBuffers; ++ndx)
1848 {
1849 if (sec_buffers[ndx].BufferType == SECBUFFER_EXTRA)
1850 {
1851 ret = gate_stream_write_block((gate_stream_t*)impl->crypt_input_buffer,
1852 (char const*)sec_buffers[ndx].pvBuffer, sec_buffers[ndx].cbBuffer, NULL);
1853 GATE_BREAK_IF_FAILED(ret);
1854 }
1855 else if (sec_buffers[ndx].BufferType == SECBUFFER_DATA)
1856 {
1857 ret = gate_stream_write_block((gate_stream_t*)impl->plain_input_buffer,
1858 (char const*)sec_buffers[ndx].pvBuffer, sec_buffers[ndx].cbBuffer, NULL);
1859 GATE_BREAK_IF_FAILED(ret);
1860 }
1861 }
1862 GATE_BREAK_IF_FAILED(ret);
1863
1864 if (sec_status == SEC_I_RENEGOTIATE)
1865 {
1866 GATE_DEBUG_TRACE("re-negotiate required");
1867 impl->is_negotiated = false;
1868 ret = GATE_RESULT_OK_PARTIAL;
1869 break;
1870 }
1871
1872 /* decryption succeeded, continue reading from buffer: */
1873 }
1874
1875 crypt_buffer_length = gate_memstream_size(impl->plain_input_buffer);
1876 crypt_buffer = gate_memstream_get_data(impl->plain_input_buffer);
1877
1878 dataread = (bufferlen < crypt_buffer_length) ? bufferlen : crypt_buffer_length;
1879 GATE_DEBUG_TRACE_VALUE(dataread);
1880
1881 /* success state reached */
1882 if (dataread == 0)
1883 {
1884 ret = GATE_RESULT_OK_PARTIAL;
1885 }
1886 else
1887 {
1888 gate_mem_copy(paindatabuffer, crypt_buffer, dataread);
1889 gate_memstream_discard(impl->plain_input_buffer, dataread);
1890 ret = GATE_RESULT_OK;
1891 }
1892 } while (0);
1893
1894 if (datareturned)
1895 {
1896 *datareturned = dataread;
1897 }
1898
1899 if (message_buffer != NULL)
1900 {
1901 gate_mem_dealloc(message_buffer);
1902 }
1903 return ret;
1904 }
1905
1906 #endif /* GATE_NET_SSLSESSION_WINCRYPT */
1907
1908
1909
1910 #if defined(GATE_NET_SSLSESSION_OPENSSL)
1911
1912 #include "gate/net/platform/openssl_api.h"
1913
1914 static gate_libcrypto_api_t libcrypto;
1915 static gate_libssl_api_t libssl;
1916
1917 typedef gate_bool_t(*gate_ssl_alpn_callback_t)(gate_uint8_t const**, gate_uint8_t, gate_uint8_t const*, gate_uint8_t, void*);
1918
1919 typedef struct gate_ssl_session_impl_class
1920 {
1921 gate_bool_t is_server;
1922 SSL_CTX* ctx;
1923 SSL* session;
1924 BIO* read_buffer;
1925 BIO* write_buffer;
1926 gate_ssl_alpn_callback_t alpn_callback;
1927 } gate_ssl_session_impl_t;
1928
1929 static void swap_pointers(void** ptr_to_ptr1, void** ptr_to_ptr2)
1930 {
1931 void* ptr_tmp = *ptr_to_ptr1;
1932 *ptr_to_ptr1 = *ptr_to_ptr2;
1933 *ptr_to_ptr2 = ptr_tmp;
1934 }
1935
1936 static gate_result_t gate_ssl_session_create_BIO(gate_ssl_session_impl_t* impl)
1937 {
1938 gate_result_t ret = GATE_RESULT_FAILED;
1939 BIO* read_bio = NULL;
1940 BIO* write_bio = NULL;
1941 do
1942 {
1943 read_bio = libcrypto.api_BIO_new(libcrypto.api_BIO_s_mem());
1944 if (NULL == read_bio)
1945 {
1946 GATE_DEBUG_TRACE("libssl.BIO_new[read] failed");
1947 ret = GATE_RESULT_OUTOFMEMORY;
1948 break;
1949 }
1950
1951 write_bio = libcrypto.api_BIO_new(libcrypto.api_BIO_s_mem());
1952 if (NULL == write_bio)
1953 {
1954 GATE_DEBUG_TRACE("libssl.BIO_new[write] failed");
1955 ret = GATE_RESULT_OUTOFMEMORY;
1956 break;
1957 }
1958
1959 libssl.api_SSL_set_bio(impl->session, read_bio, write_bio);
1960 ret = GATE_RESULT_OK;
1961 swap_pointers((void**)&read_bio, (void**)&impl->read_buffer);
1962 swap_pointers((void**)&write_bio, (void**)&impl->write_buffer);
1963 } while (0);
1964
1965 if (read_bio != NULL)
1966 {
1967 libcrypto.api_BIO_free(read_bio);
1968 }
1969 if (write_bio != NULL)
1970 {
1971 libcrypto.api_BIO_free(write_bio);
1972 }
1973
1974 return ret;
1975 }
1976
1977 static gate_result_t gate_ssl_session_load_certificate(SSL_CTX* ssl_ctx, void const* cert_bytes, gate_size_t cert_length)
1978 {
1979 gate_result_t ret = GATE_RESULT_FAILED;
1980 X509* x509cert = NULL;
1981 BIO* certbio = NULL;
1982
1983 do
1984 {
1985 int result_code;
1986 certbio = libcrypto.api_BIO_new_mem_buf((void*)cert_bytes, (long)cert_length);
1987 if (NULL == certbio)
1988 {
1989 GATE_DEBUG_TRACE("libssl.BIO_new_mem_buf() failed");
1990 ret = GATE_RESULT_OUTOFMEMORY;
1991 break;
1992 }
1993
1994 x509cert = libcrypto.api_PEM_read_bio_X509(certbio, NULL, 0, NULL);
1995 if (NULL == x509cert)
1996 {
1997 GATE_DEBUG_TRACE("libssl.PEM_read_bio_X509() failed");
1998 ret = GATE_RESULT_INVALIDDATA;
1999 break;
2000 }
2001
2002 result_code = libssl.api_SSL_CTX_use_certificate(ssl_ctx, x509cert);
2003
2004 if (result_code != 1)
2005 {
2006 GATE_DEBUG_TRACE("libssl.SSL_CTX_use_certificate() failed");
2007 GATE_DEBUG_TRACE_VALUE(result_code);
2008 ret = GATE_RESULT_FAILED;
2009 break;
2010 }
2011
2012 ret = GATE_RESULT_OK;
2013 } while (0);
2014
2015 if (NULL != x509cert)
2016 {
2017 libcrypto.api_X509_free(x509cert);
2018 }
2019
2020 if (NULL != certbio)
2021 {
2022 libcrypto.api_BIO_free(certbio);
2023 }
2024
2025 return ret;
2026 }
2027
2028 static gate_result_t gate_ssl_session_load_private_key(SSL_CTX* ssl_ctx, void const* key_bytes, gate_size_t key_length)
2029 {
2030 gate_result_t ret = GATE_RESULT_FAILED;
2031 RSA* rsa = NULL;
2032 BIO* key_bio = NULL;
2033
2034 do
2035 {
2036 int result_code;
2037 key_bio = libcrypto.api_BIO_new_mem_buf((void*)key_bytes, (int)key_length);
2038 if (NULL == key_bio)
2039 {
2040 GATE_DEBUG_TRACE("libssl.BIO_new_mem_buf() failed");
2041 ret = GATE_RESULT_OUTOFMEMORY;
2042 break;
2043 }
2044
2045 rsa = libcrypto.api_PEM_read_bio_RSAPrivateKey(key_bio, NULL, 0, NULL);
2046 if (NULL == rsa)
2047 {
2048 GATE_DEBUG_TRACE("libssl.PEM_read_bio_RSAPrivateKey() failed");
2049 ret = GATE_RESULT_INVALIDDATA;
2050 break;
2051 }
2052
2053 result_code = libssl.api_SSL_CTX_use_RSAPrivateKey(ssl_ctx, rsa);
2054 if (result_code != 1)
2055 {
2056 GATE_DEBUG_TRACE("libssl.SSL_CTX_use_RSAPrivateKey() failed");
2057 ret = GATE_RESULT_FAILED;
2058 break;
2059 }
2060
2061 ret = GATE_RESULT_OK;
2062
2063 } while (0);
2064
2065 if (NULL != rsa)
2066 {
2067 libcrypto.api_RSA_free(rsa);
2068 }
2069
2070 if (NULL != key_bio)
2071 {
2072 libcrypto.api_BIO_free(key_bio);
2073 }
2074
2075 return ret;
2076 }
2077
2078 static int alpn_select_cb(SSL* ssl, const unsigned char** out, unsigned char* outlen, const unsigned char* in, unsigned int inlen, void* arg)
2079 {
2080 gate_ssl_session_impl_t* const impl = (gate_ssl_session_impl_t*)arg;
2081 /* TODO */
2082 (void)impl;
2083 return SSL_TLSEXT_ERR_OK;
2084 /* return SSL_TLSEXT_ERR_NOACK; */
2085 }
2086
2087 1 gate_result_t gate_ssl_init(gate_bool_t crypto_api_only)
2088 {
2089 1 gate_result_t result = gate_libcrypto_load_api(&libcrypto);
2090
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (GATE_SUCCEEDED(result) && !crypto_api_only)
2091 {
2092 result = gate_libssl_load_api(&libssl);
2093 }
2094 1 return result;
2095 }
2096
2097 gate_result_t gate_ssl_thread_init()
2098 {
2099 return gate_ssl_init(false);
2100 }
2101
2102 gate_result_t gate_ssl_thread_uninit()
2103 {
2104 if (libcrypto.api_ERR_clear_error)
2105 {
2106 libcrypto.api_ERR_clear_error();
2107 }
2108 if (libcrypto.api_ERR_remove_thread_state)
2109 {
2110 libcrypto.api_ERR_remove_thread_state(NULL);
2111 }
2112 return GATE_RESULT_OK;
2113 }
2114
2115 gate_result_t gate_ssl_session_create(gate_ssl_session_params_t const* params, gate_ssl_session_t* session)
2116 {
2117 gate_result_t ret;
2118 SSL_METHOD const* ssl_method = NULL;
2119 gate_ssl_session_impl_t* impl = NULL;
2120
2121 do
2122 {
2123 ret = gate_ssl_thread_init();
2124 if (GATE_FAILED(ret))
2125 {
2126 GATE_DEBUG_TRACE("libssl not available or cannot be completely imported");
2127 break;
2128 }
2129
2130 if (!params || !session)
2131 {
2132 ret = GATE_RESULT_INVALIDARG;
2133 break;
2134 }
2135
2136 impl = (gate_ssl_session_impl_t*)gate_mem_alloc(sizeof(gate_ssl_session_impl_t));
2137 if (NULL == impl)
2138 {
2139 ret = GATE_RESULT_OUTOFMEMORY;
2140 GATE_DEBUG_TRACE("Failed to allocate SSL session base");
2141 break;
2142 }
2143
2144 gate_mem_clear(impl, sizeof(gate_ssl_session_impl_t));
2145
2146 if (params->server_side)
2147 {
2148 /* service endpoint */
2149 #if defined(GATE_NET_SSL_OLDPROTOCOLS)
2150 switch (params->session_version)
2151 {
2152 case GATE_SSL_SESSION_TYPE_TLS_1_0: ssl_method = libssl.api_TLSv1_server_method ? libssl.api_TLSv1_server_method() : NULL; break;
2153 case GATE_SSL_SESSION_TYPE_TLS_1_1: ssl_method = libssl.api_TLSv1_1_server_method ? libssl.api_TLSv1_1_server_method() : NULL; break;
2154 case GATE_SSL_SESSION_TYPE_TLS_1_2: ssl_method = libssl.api_TLSv1_2_server_method ? libssl.api_TLSv1_2_server_method() : NULL; break;
2155 default: break;
2156 }
2157 #endif
2158 switch (params->session_version)
2159 {
2160 case GATE_SSL_SESSION_TYPE_SSL_3: ssl_method = libssl.api_SSLv3_server_method ? libssl.api_SSLv3_server_method() : NULL; break;
2161 case GATE_SSL_SESSION_TYPE_TLS_1_3: ssl_method = libssl.api_TLSv1_3_server_method ? libssl.api_TLSv1_3_server_method() : NULL; break;
2162 case GATE_SSL_SESSION_TYPE_AUTO: ssl_method = libssl.api_TLS_server_method ? libssl.api_TLS_server_method() : NULL; break;
2163 default: break;
2164 }
2165
2166
2167 if (ssl_method == NULL)
2168 {
2169 GATE_DEBUG_TRACE("Requested ssl/tls version not available or not supported");
2170 ret = GATE_RESULT_NOTSUPPORTED;
2171 break;
2172 }
2173
2174 impl->ctx = libssl.api_SSL_CTX_new(ssl_method);
2175 if (NULL == impl->ctx)
2176 {
2177 GATE_DEBUG_TRACE("libssl.SSL_CTX_new() failed");
2178 ret = GATE_RESULT_OUTOFRESOURCES;
2179 break;
2180 }
2181
2182 ret = gate_ssl_session_load_certificate(impl->ctx, params->certificate, params->certificate_length);
2183 GATE_BREAK_IF_FAILED(ret);
2184
2185 if (params->privatekey_length > 0)
2186 {
2187 ret = gate_ssl_session_load_private_key(impl->ctx, params->privatekey, params->privatekey_length);
2188 GATE_BREAK_IF_FAILED(ret);
2189 }
2190
2191 impl->session = libssl.api_SSL_new(impl->ctx);
2192 if (NULL == impl->session)
2193 {
2194 GATE_DEBUG_TRACE("libssl.SSL_new() failed");
2195 ret = GATE_RESULT_FAILED;
2196 break;
2197 }
2198
2199 libssl.api_SSL_set_accept_state(impl->session);
2200
2201 if (libssl.api_SSL_CTX_set_alpn_select_cb)
2202 {
2203 libssl.api_SSL_CTX_set_alpn_select_cb(impl->ctx, &alpn_select_cb, impl);
2204 }
2205
2206 /*
2207 if(!!protoCb)
2208 {
2209 Code.func_SSL_CTX_set_alpn_select_cb(this->m_ctx, &protocol_cb_handler, static_cast<void*>(this));
2210 }
2211 */
2212
2213 ret = gate_ssl_session_create_BIO(impl);
2214 GATE_BREAK_IF_FAILED(ret);
2215 }
2216 else
2217 {
2218 /* client endpoint */
2219 #if defined(GATE_NET_SSL_OLDPROTOCOLS)
2220 switch (params->session_version)
2221 {
2222 case GATE_SSL_SESSION_TYPE_TLS_1_0: ssl_method = libssl.api_TLSv1_client_method ? libssl.api_TLSv1_client_method() : NULL; break;
2223 case GATE_SSL_SESSION_TYPE_TLS_1_1: ssl_method = libssl.api_TLSv1_1_client_method ? libssl.api_TLSv1_1_client_method() : NULL; break;
2224 case GATE_SSL_SESSION_TYPE_TLS_1_2: ssl_method = libssl.api_TLSv1_2_client_method ? libssl.api_TLSv1_2_client_method() : NULL; break;
2225 default: break;
2226 }
2227 #endif
2228 switch (params->session_version)
2229 {
2230 case GATE_SSL_SESSION_TYPE_SSL_3: ssl_method = libssl.api_SSLv3_client_method ? libssl.api_SSLv3_client_method() : NULL; break;
2231 case GATE_SSL_SESSION_TYPE_TLS_1_3: ssl_method = libssl.api_TLSv1_3_client_method ? libssl.api_TLSv1_3_client_method() : NULL; break;
2232 case GATE_SSL_SESSION_TYPE_AUTO: ssl_method = libssl.api_TLS_client_method ? libssl.api_TLS_client_method() : NULL; break;
2233 default: break;
2234 }
2235
2236 if (ssl_method == NULL)
2237 {
2238 GATE_DEBUG_TRACE("Requested ssl/tls version not available or not supported");
2239 ret = GATE_RESULT_NOTSUPPORTED;
2240 break;
2241 }
2242
2243 impl->ctx = libssl.api_SSL_CTX_new(ssl_method);
2244 if (NULL == impl->ctx)
2245 {
2246 GATE_DEBUG_TRACE("libssl.SSL_CTX_new() failed");
2247 ret = GATE_RESULT_OUTOFRESOURCES;
2248 break;
2249 }
2250
2251 impl->session = libssl.api_SSL_new(impl->ctx);
2252 if (NULL == impl->session)
2253 {
2254 GATE_DEBUG_TRACE("libssl.SSL_new() failed");
2255 ret = GATE_RESULT_OUTOFRESOURCES;
2256 break;
2257 }
2258
2259 ret = gate_ssl_session_create_BIO(impl);
2260 GATE_BREAK_IF_FAILED(ret);
2261
2262 libssl.api_SSL_set_connect_state(impl->session);
2263 }
2264
2265 /* success case reached */
2266 ret = GATE_RESULT_OK;
2267 *session = (gate_ssl_session_t)impl;
2268 impl = NULL;
2269
2270 } while (0);
2271
2272 if (NULL != impl)
2273 {
2274 gate_ssl_session_destroy(impl);
2275 }
2276
2277 return ret;
2278 }
2279 gate_result_t gate_ssl_session_destroy(gate_ssl_session_t session)
2280 {
2281 gate_result_t ret = GATE_RESULT_OK;
2282 do
2283 {
2284 gate_ssl_session_impl_t* impl = (gate_ssl_session_impl_t*)session;
2285 if (!impl)
2286 {
2287 break;
2288 }
2289 if (impl->session)
2290 {
2291 libssl.api_SSL_free(impl->session);
2292 impl->session = NULL;
2293 }
2294
2295 if (impl->ctx)
2296 {
2297 libssl.api_SSL_CTX_free(impl->ctx);
2298 impl->ctx = NULL;
2299 }
2300
2301 if (impl->read_buffer)
2302 {
2303 impl->read_buffer = NULL;
2304 }
2305
2306 if (impl->write_buffer)
2307 {
2308 impl->write_buffer = NULL;
2309 }
2310
2311 gate_mem_dealloc(impl);
2312 } while (0);
2313
2314 return ret;
2315 }
2316
2317 gate_result_t gate_ssl_session_is_negotiated(gate_ssl_session_t session, gate_bool_t* completed)
2318 {
2319 gate_result_t ret = GATE_RESULT_OK;
2320 int ssl_state;
2321 gate_ssl_session_impl_t* impl = (gate_ssl_session_impl_t*)session;
2322
2323 ssl_state = libssl.api_SSL_state(impl->session);
2324 if (completed)
2325 {
2326 *completed = (ssl_state == SSL_ST_OK);
2327 }
2328 GATE_DEBUG_TRACE_VALUE(ssl_state);
2329 return ret;
2330 }
2331 gate_result_t gate_ssl_session_negotiate(gate_ssl_session_t session)
2332 {
2333 gate_result_t ret = GATE_RESULT_OK;
2334 gate_ssl_session_impl_t* impl = (gate_ssl_session_impl_t*)session;
2335 int handshake_result = libssl.api_SSL_do_handshake(impl->session);
2336 do
2337 {
2338 if (handshake_result != 1)
2339 { /* handshake incomplete, further communication required */
2340 int error_code = libssl.api_SSL_get_error(impl->session, handshake_result);
2341 switch (error_code)
2342 {
2343 case SSL_ERROR_WANT_READ:
2344 case SSL_ERROR_WANT_WRITE:
2345 {
2346 GATE_DEBUG_TRACE("libssl.SSL_do_handshake() not completed (read/write required)");
2347 ret = GATE_RESULT_OK_PARTIAL;
2348 break;
2349 }
2350 case SSL_ERROR_SSL:
2351 {
2352 GATE_DEBUG_TRACE("libssl.SSL_do_handshake() failed");
2353 ret = GATE_RESULT_FAILED;
2354 break;
2355 }
2356 default:
2357 {
2358 GATE_DEBUG_TRACE("libssl.SSL_do_handshake() failed with unknown error");
2359 GATE_DEBUG_TRACE_VALUE(handshake_result);
2360 GATE_DEBUG_TRACE_VALUE(error_code);
2361 ret = GATE_RESULT_UNKNOWNERROR;
2362 break;
2363 }
2364 }
2365 break;
2366 }
2367 ret = GATE_RESULT_OK;
2368 } while (0);
2369 return ret;
2370 }
2371
2372 gate_result_t gate_ssl_session_write(gate_ssl_session_t session, char const* plaindatabuffer, gate_size_t bufferlen, gate_size_t* datawritten)
2373 {
2374 gate_result_t ret = GATE_RESULT_FAILED;
2375 gate_ssl_session_impl_t* impl = (gate_ssl_session_impl_t*)session;
2376
2377 do
2378 {
2379 int ssl_bytes_written = libssl.api_SSL_write(impl->session, plaindatabuffer, (int)bufferlen);
2380 if (ssl_bytes_written > 0)
2381 {
2382 if (datawritten != NULL)
2383 {
2384 *datawritten = (gate_size_t)ssl_bytes_written;
2385 }
2386 GATE_DEBUG_TRACE_VALUE(ssl_bytes_written);
2387 ret = GATE_RESULT_OK;
2388 }
2389 else
2390 {
2391 int error_code = libssl.api_SSL_get_error(impl->session, ssl_bytes_written);
2392 switch (error_code)
2393 {
2394 case SSL_ERROR_WANT_READ:
2395 case SSL_ERROR_WANT_WRITE:
2396 {
2397 GATE_DEBUG_TRACE("libssl.SSL_write() failed (read/write required)");
2398 ret = GATE_RESULT_NOTREADY;
2399 break;
2400 }
2401 case SSL_ERROR_SSL:
2402 {
2403 GATE_DEBUG_TRACE("libssl.SSL_write() failed with SSL error");
2404 ret = GATE_RESULT_FAILED;
2405 break;
2406 }
2407 default:
2408 {
2409 GATE_DEBUG_TRACE("Unknown error in libssl.SSL_write()");
2410 GATE_DEBUG_TRACE_VALUE(error_code);
2411 ret = GATE_RESULT_UNKNOWNERROR;
2412 break;
2413 }
2414 }
2415 }
2416 } while (0);
2417 return ret;
2418 }
2419
2420 gate_result_t gate_ssl_session_get_encoded_data(gate_ssl_session_t session, char* encodedbuffer, gate_size_t bufferlen, gate_size_t* bufferused)
2421 {
2422 gate_result_t ret = GATE_RESULT_FAILED;
2423
2424 do
2425 {
2426 gate_ssl_session_impl_t* impl = (gate_ssl_session_impl_t*)session;
2427 int ssl_bytes_encoded = libcrypto.api_BIO_read(impl->write_buffer, encodedbuffer, (int)bufferlen);
2428 if (ssl_bytes_encoded >= 0)
2429 {
2430 if (bufferused)
2431 {
2432 *bufferused = (gate_size_t)ssl_bytes_encoded;
2433 }
2434 GATE_DEBUG_TRACE_VALUE(ssl_bytes_encoded);
2435 ret = GATE_RESULT_OK;
2436 }
2437 else
2438 {
2439 GATE_DEBUG_TRACE("libssl.BIO_read() failed");
2440 ret = GATE_RESULT_FAILED;
2441 }
2442 } while (0);
2443
2444 return ret;
2445 }
2446
2447 gate_result_t gate_ssl_session_add_encoded_data(gate_ssl_session_t session, char const* encodedbuffer, gate_size_t bufferlen, gate_size_t* bytesadded)
2448 {
2449 gate_result_t ret = GATE_RESULT_FAILED;
2450 do
2451 {
2452 gate_ssl_session_impl_t* impl = (gate_ssl_session_impl_t*)session;
2453 int encoded_bytes_written = 0;
2454 if (bufferlen == 0)
2455 {
2456 if (bytesadded)
2457 {
2458 *bytesadded = encoded_bytes_written;
2459 }
2460 GATE_DEBUG_TRACE_VALUE(encoded_bytes_written);
2461 ret = GATE_RESULT_OK;
2462 }
2463 else
2464 {
2465 encoded_bytes_written = libcrypto.api_BIO_write(impl->read_buffer, encodedbuffer, (int)bufferlen);
2466 if (encoded_bytes_written > 0)
2467 {
2468 if (bytesadded)
2469 {
2470 *bytesadded = encoded_bytes_written;
2471 }
2472 GATE_DEBUG_TRACE_VALUE(encoded_bytes_written);
2473 ret = GATE_RESULT_OK;
2474 }
2475 else
2476 {
2477 GATE_DEBUG_TRACE("libssl.BIO_write() failed");
2478 GATE_DEBUG_TRACE_VALUE(encoded_bytes_written);
2479 ret = GATE_RESULT_FAILED;
2480 }
2481 }
2482 } while (0);
2483
2484 return ret;
2485 }
2486
2487 gate_result_t gate_ssl_session_read(gate_ssl_session_t session, char* paindatabuffer, gate_size_t bufferlen, gate_size_t* datareturned)
2488 {
2489 gate_result_t ret = GATE_RESULT_FAILED;
2490 do
2491 {
2492 gate_ssl_session_impl_t* impl = (gate_ssl_session_impl_t*)session;
2493 int ssl_bytes_decoded = libssl.api_SSL_read(impl->session, paindatabuffer, (int)bufferlen);
2494 if (ssl_bytes_decoded > 0)
2495 {
2496 if (NULL != datareturned)
2497 {
2498 *datareturned = (gate_size_t)ssl_bytes_decoded;
2499 }
2500 GATE_DEBUG_TRACE_VALUE(ssl_bytes_decoded);
2501 ret = GATE_RESULT_OK;
2502 }
2503 else
2504 {
2505 /* read failed */
2506 int error_code = libssl.api_SSL_get_error(impl->session, ssl_bytes_decoded);
2507 if ((error_code == SSL_ERROR_ZERO_RETURN) && (ssl_bytes_decoded == 0))
2508 {
2509 /* end of stream / SSL shutdown */
2510 if (NULL != datareturned)
2511 {
2512 *datareturned = 0;
2513 }
2514 ret = GATE_RESULT_OK;
2515 }
2516 else if (error_code == SSL_ERROR_WANT_READ)
2517 {
2518 /* no more data available to decode */
2519 if (NULL != datareturned)
2520 {
2521 *datareturned = 0;
2522 }
2523 ret = GATE_RESULT_OK_PARTIAL;
2524 }
2525 else
2526 {
2527 GATE_DEBUG_TRACE("Unknown error in libssl.SSL_read()");
2528 GATE_DEBUG_TRACE_VALUE(ssl_bytes_decoded);
2529 GATE_DEBUG_TRACE_VALUE(error_code);
2530 ret = GATE_RESULT_FAILED;
2531 }
2532 }
2533 } while (0);
2534
2535 return ret;
2536 }
2537
2538
2539 #endif /* GATE_NET_SSLSESSION_OPENSSL */
2540
2541
2542
2543 #if defined(GATE_NET_SSLSESSION_NO_IMPL)
2544
2545 gate_result_t gate_ssl_init(gate_bool_t crypto_api_only)
2546 {
2547 GATE_UNUSED_ARG(crypto_api_only);
2548 return GATE_RESULT_NOTIMPLEMENTED;
2549 }
2550
2551 gate_result_t gate_ssl_thread_init()
2552 {
2553 return GATE_RESULT_NOTIMPLEMENTED;
2554 }
2555
2556 gate_result_t gate_ssl_thread_uninit()
2557 {
2558 return GATE_RESULT_NOTIMPLEMENTED;
2559 }
2560
2561 gate_result_t gate_ssl_session_create(gate_ssl_session_params_t const* params, gate_ssl_session_t* session)
2562 {
2563 GATE_UNUSED_ARG(params);
2564 GATE_UNUSED_ARG(session);
2565 return GATE_RESULT_NOTIMPLEMENTED;
2566 }
2567 gate_result_t gate_ssl_session_destroy(gate_ssl_session_t session)
2568 {
2569 GATE_UNUSED_ARG(session);
2570 return GATE_RESULT_NOTIMPLEMENTED;
2571 }
2572
2573 gate_result_t gate_ssl_session_is_negotiated(gate_ssl_session_t session, gate_bool_t* completed)
2574 {
2575 GATE_UNUSED_ARG(session);
2576 GATE_UNUSED_ARG(completed);
2577 return GATE_RESULT_NOTIMPLEMENTED;
2578 }
2579 gate_result_t gate_ssl_session_negotiate(gate_ssl_session_t session)
2580 {
2581 GATE_UNUSED_ARG(session);
2582 return GATE_RESULT_NOTIMPLEMENTED;
2583 }
2584
2585 gate_result_t gate_ssl_session_write(gate_ssl_session_t session, char const* plaindatabuffer,
2586 gate_size_t bufferlen, gate_size_t* datawritten)
2587 {
2588 GATE_UNUSED_ARG(session);
2589 GATE_UNUSED_ARG(plaindatabuffer);
2590 GATE_UNUSED_ARG(bufferlen);
2591 GATE_UNUSED_ARG(datawritten);
2592 return GATE_RESULT_NOTIMPLEMENTED;
2593 }
2594 gate_result_t gate_ssl_session_get_encoded_data(gate_ssl_session_t session, char* encodedbuffer,
2595 gate_size_t bufferlen, gate_size_t* bufferused)
2596 {
2597 GATE_UNUSED_ARG(session);
2598 GATE_UNUSED_ARG(encodedbuffer);
2599 GATE_UNUSED_ARG(bufferlen);
2600 GATE_UNUSED_ARG(bufferused);
2601 return GATE_RESULT_NOTIMPLEMENTED;
2602 }
2603
2604 gate_result_t gate_ssl_session_add_encoded_data(gate_ssl_session_t session, char const* encodedbuffer,
2605 gate_size_t bufferlen, gate_size_t* bytesadded)
2606 {
2607 GATE_UNUSED_ARG(session);
2608 GATE_UNUSED_ARG(encodedbuffer);
2609 GATE_UNUSED_ARG(bufferlen);
2610 GATE_UNUSED_ARG(bytesadded);
2611 return GATE_RESULT_NOTIMPLEMENTED;
2612 }
2613 gate_result_t gate_ssl_session_read(gate_ssl_session_t session, char* paindatabuffer,
2614 gate_size_t bufferlen, gate_size_t* datareturned)
2615 {
2616 GATE_UNUSED_ARG(session);
2617 GATE_UNUSED_ARG(paindatabuffer);
2618 GATE_UNUSED_ARG(bufferlen);
2619 GATE_UNUSED_ARG(datareturned);
2620 return GATE_RESULT_NOTIMPLEMENTED;
2621 }
2622
2623 #endif /* GATE_NET_SSLSESSION_NO_IMPL */
2624