GCC Code Coverage Report


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