File Coverage

MatrixSSL3.xs
Criterion Covered Total %
statement 391 721 54.2
branch 267 1066 25.0
condition n/a
subroutine n/a
pod n/a
total 658 1787 36.8


line stmt bran cond sub pod time code
1             #include "EXTERN.h"
2             #include "perl.h"
3             #include "XSUB.h"
4             #define NEED_sv_2pv_flags
5             #include "ppport.h"
6              
7             #include "core/coreApi.h"
8             #include "crypto/cryptoApi.h"
9             #include "matrixssl/matrixssllib.h"
10             #include "matrixssl/matrixsslApi.h"
11             #include "matrixssl/version.h"
12             #include "MatrixSSL3.h"
13              
14             #ifndef WIN32
15             #include "regex.h"
16             #endif
17              
18             #include "inc/const-c.inc"
19              
20             /******************************************************************************/
21              
22             typedef sslKeys_t Crypt_MatrixSSL3_Keys;
23             typedef sslSessionId_t Crypt_MatrixSSL3_SessID;
24             typedef ssl_t Crypt_MatrixSSL3_Sess;
25             typedef tlsExtension_t Crypt_MatrixSSL3_HelloExt;
26              
27             static int matrixssl_initialized = 0;
28              
29             #ifdef MATRIX_DEBUG
30             static int objects = 0;
31             #endif
32              
33             sslSessOpts_t sslOpts;
34              
35              
36             /*****************************************************************************
37             ALPN extension helper structure. This holds the protocols the server is
38             implementing. Since ALPN usage is optional, if a virtual hosts has the
39             protocols specified, this list will be used when an ALPN extension is
40             received from the client. If not, the default server protocol list is
41             used if provided. If neither the virtual host or the default server have
42             protocols specified, the ALPN extension is ignored.
43             */
44              
45             typedef struct s_ALPN_data {
46             short protoCount;
47             char *proto[MAX_PROTO_EXT];
48             int32 protoLen[MAX_PROTO_EXT];
49             } t_ALPN_data;
50              
51             #define SZ_ALPN_DATA sizeof(t_ALPN_data)
52             typedef t_ALPN_data *p_ALPN_data;
53              
54              
55             /*****************************************************************************
56             SNI entries a.k.a virtual hosts
57              
58             For each host we can have:
59             Hostname regex
60             Certificate (not stored, used to initialize SSL keys)
61             Key (not stored, used to initialize SSL keys)
62             In the SSL keys:
63             - Session tickets keys
64             - DH params
65             - OCSP staple
66             - Certificate Transparency files
67             Protocols
68             */
69              
70             #define MAX_SNI_ENTRIES 16
71              
72             typedef struct s_SNI_entry {
73             #ifndef WIN32
74             regex_t regex_hostname;
75             #else
76             int32 hostnameLen;
77             unsigned char hostname[255];
78             #endif
79             sslKeys_t *keys;
80             p_ALPN_data alpn;
81             } t_SNI_entry;
82              
83             #define SZ_SNI_ENTRY sizeof(t_SNI_entry)
84             typedef t_SNI_entry *p_SNI_entry;
85              
86             /*****************************************************************************
87             SSL servers
88              
89             Each server can have maximum MAX_SNI_ENTRIES virtual hosts
90              
91             We can handle maximum MAX_SNI_SERVERS servers
92              
93             For each server we can have:
94             Virtual hosts
95             Protocols
96             */
97              
98             #define MAX_SSL_SERVERS 16
99              
100             typedef struct s_SSL_server {
101             t_SNI_entry *SNI_entries[MAX_SNI_ENTRIES];
102             int16 SNI_entries_number;
103             sslKeys_t *keys;
104             p_ALPN_data alpn;
105             } t_SSL_server;
106              
107             #define SZ_SSL_SERVER sizeof(t_SSL_server)
108             typedef t_SSL_server *p_SSL_server;
109              
110             p_SSL_server SSL_servers[MAX_SSL_SERVERS];
111             int16 SSL_server_index = 0;
112              
113              
114             /*****************************************************************************
115             SSL extra data
116              
117             For each SSL session we keep:
118             SSL ID - equal to the socket file number
119             ALPN data
120             Pointer to the server data on which the connection was accepted
121             */
122              
123             typedef struct s_SSL_data {
124             uint32_t ssl_id;
125             int server_index;
126             int cbALPN_done;
127             int cbSNI_done;
128             sslKeys_t *keys;
129             } t_SSL_data;
130              
131             #define SZ_SSL_DATA sizeof(t_SSL_data)
132             typedef t_SSL_data *p_SSL_data;
133              
134              
135             /*****************************************************************************
136             Support function
137             */
138              
139 233167           void add_obj() {
140             int rc;
141              
142 233167 100         if (!matrixssl_initialized) {
143 17           matrixssl_initialized = 1;
144            
145 17           rc = matrixSslOpen();
146 17 50         if (rc != PS_SUCCESS)
147 0           croak("%d", rc);
148             }
149             #ifdef MATRIX_DEBUG
150             warn("add_obj: objects number %d -> %d", objects, objects + 1);
151             objects++;
152             #endif
153 233167           }
154              
155              
156             #ifdef MATRIX_DEBUG
157             void del_obj() {
158             if (matrixssl_initialized) {
159             warn("del_obj: objects number %d -> %d", objects, objects - 1);
160             objects--;
161             }
162             }
163             #else
164             #define del_obj()
165             #endif
166              
167              
168             /*
169             * my_hv_store() helper macro to avoid writting hash key names twice or
170             * hardcoding their length
171             #define myVAL_LEN(k) (k), strlen((k))
172             */
173              
174             #define my_hv_store(myh1,myh2,myh3,myh4) hv_store((myh1),(myh2),(strlen((myh2))),(myh3),(myh4))
175              
176             /*
177             * Hash which will contain perl's certValidate CODEREF
178             * between matrixSslNew*Session() and matrixSslDeleteSession().
179             *
180             * Hash format:
181             * key integer representation of $ssl (ssl_t *)
182             * value \&cb_certValidate
183             */
184             static HV * certValidatorArg = NULL;
185              
186 119           int32 appCertValidator(ssl_t *ssl, psX509Cert_t *certInfo, int32 alert) {
187 119           dSP;
188             SV *key;
189             SV *callback;
190             AV *certs;
191             int res;
192              
193 119           ENTER;
194 119           SAVETMPS;
195              
196 119           key = sv_2mortal(newSViv(PTR2IV(ssl)));
197 119           callback = HeVAL(hv_fetch_ent(certValidatorArg, key, 0, 0));
198              
199             /* Convert (psX509Cert_t *) structs into array of hashes. */
200 119           certs = (AV *)sv_2mortal((SV *)newAV());
201 239 100         for (; certInfo != NULL; certInfo=certInfo->next) {
202             HV *sslCertInfo;
203             HV *subjectAltName;
204             HV *subject;
205             HV *issuer;
206              
207 120           subjectAltName = newHV();
208              
209 120           subject = newHV();
210 120 50         if (certInfo->subject.country != NULL)
211 120           my_hv_store(subject, "country",
212             newSVpv(certInfo->subject.country, 0), 0);
213 120 100         if (certInfo->subject.state != NULL)
214 119           my_hv_store(subject, "state",
215             newSVpv(certInfo->subject.state, 0), 0);
216 120 100         if (certInfo->subject.locality != NULL)
217 1           my_hv_store(subject, "locality",
218             newSVpv(certInfo->subject.locality, 0), 0);
219 120 50         if (certInfo->subject.organization != NULL)
220 120           my_hv_store(subject, "organization",
221             newSVpv(certInfo->subject.organization, 0), 0);
222 120 50         if (certInfo->subject.orgUnit != NULL)
223 0           my_hv_store(subject, "orgUnit",
224             newSVpv(certInfo->subject.orgUnit, 0), 0);
225 120 50         if (certInfo->subject.commonName != NULL)
226 120           my_hv_store(subject, "commonName",
227             newSVpv(certInfo->subject.commonName, 0), 0);
228              
229 120           issuer = newHV();
230 120 100         if (certInfo->issuer.country != NULL)
231 119           my_hv_store(issuer, "country",
232             newSVpv(certInfo->issuer.country, 0), 0);
233 120 100         if (certInfo->issuer.state != NULL)
234 118           my_hv_store(issuer, "state",
235             newSVpv(certInfo->issuer.state, 0), 0);
236 120 50         if (certInfo->issuer.locality != NULL)
237 0           my_hv_store(issuer, "locality",
238             newSVpv(certInfo->issuer.locality, 0), 0);
239 120 50         if (certInfo->issuer.organization != NULL)
240 120           my_hv_store(issuer, "organization",
241             newSVpv(certInfo->issuer.organization, 0), 0);
242 120 100         if (certInfo->issuer.orgUnit != NULL)
243 1           my_hv_store(issuer, "orgUnit",
244             newSVpv(certInfo->issuer.orgUnit, 0), 0);
245 120 50         if (certInfo->issuer.commonName != NULL)
246 120           my_hv_store(issuer, "commonName",
247             newSVpv(certInfo->issuer.commonName, 0), 0);
248              
249 120           sslCertInfo = newHV();
250 120 50         if (certInfo->notBefore != NULL)
251 120           my_hv_store(sslCertInfo, "notBefore",
252             newSVpv(certInfo->notBefore, 0), 0);
253 120 50         if (certInfo->notAfter != NULL)
254 120           my_hv_store(sslCertInfo, "notAfter",
255             newSVpv(certInfo->notAfter, 0), 0);
256 120           my_hv_store(sslCertInfo, "subjectAltName",
257             newRV_inc(sv_2mortal((SV *)subjectAltName)), 0);
258 120           my_hv_store(sslCertInfo, "subject",
259             newRV_inc(sv_2mortal((SV *)subject)), 0);
260 120           my_hv_store(sslCertInfo, "issuer",
261             newRV_inc(sv_2mortal((SV *)issuer)), 0);
262 120           my_hv_store(sslCertInfo, "authStatus",
263             newSViv(certInfo->authStatus), 0);
264              
265             /* TODO There is a lot more (less useful) fields available… */
266              
267 120           av_push(certs, newRV_inc(sv_2mortal((SV *)sslCertInfo)));
268             }
269              
270 119 50         PUSHMARK(SP);
271 119 50         XPUSHs(sv_2mortal(newRV_inc((SV *)certs)));
272 119 50         XPUSHs(sv_2mortal(newSViv(alert)));
273 119           PUTBACK;
274              
275 119           res = call_sv(callback, G_EVAL|G_SCALAR);
276              
277 119           SPAGAIN;
278              
279 119 50         if (res != 1)
280 0           croak("Internal error: perl callback doesn't return 1 scalar!");
281              
282 119 50         if (SvTRUE(ERRSV)) {
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    50          
    0          
    0          
    100          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
283 10 50         warn("%s", SvPV_nolen(ERRSV));
    50          
    50          
    0          
284 10           warn("die() in certValidate callback not allowed, continue...\n");
285 10           POPs;
286 10           res = -1;
287             } else {
288 109 50         res = POPi;
289             }
290              
291 119           PUTBACK;
292 119 50         FREETMPS;
293 119           LEAVE;
294              
295 119           return res;
296             }
297              
298             /*
299             * Hash which will contain perl's extCallback CODEREF
300             * between matrixSslNew*Session() and matrixSslDeleteSession().
301             *
302             * Hash format:
303             * key integer representation of $ssl (ssl_t *)
304             * value \&cb_certValidate
305             */
306             static HV * extensionCbackArg = NULL;
307              
308 0           int32 appExtensionCback(ssl_t *ssl, uint16_t type, uint8_t len, void *data) {
309 0           dSP;
310             SV *key;
311             SV *callback;
312             int res;
313              
314 0           ENTER;
315 0           SAVETMPS;
316              
317 0           key = sv_2mortal(newSViv(PTR2IV(ssl)));
318 0           callback = HeVAL(hv_fetch_ent(extensionCbackArg, key, 0, 0));
319              
320 0 0         PUSHMARK(SP);
321 0 0         XPUSHs(sv_2mortal(newSViv(type)));
322 0 0         XPUSHs(sv_2mortal(newSVpvn((const char*) data, len)));
323 0           PUTBACK;
324              
325 0           res = call_sv(callback, G_EVAL|G_SCALAR);
326              
327 0           SPAGAIN;
328              
329 0 0         if (res != 1)
330 0           croak("Internal error: perl callback doesn't return 1 scalar!");
331              
332 0 0         if (SvTRUE(ERRSV)) {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
333 0 0         warn("%s", SvPV_nolen(ERRSV));
    0          
    0          
    0          
334 0           warn("die() in extensionCback callback not allowed, continue...\n");
335 0           POPs;
336 0           res = -1;
337             } else {
338 0 0         res = POPi;
339             }
340              
341 0           PUTBACK;
342 0 0         FREETMPS;
343 0           LEAVE;
344              
345 0           return res;
346             }
347              
348             /* Perl callback that will get called when a client protocol is selected */
349             static SV* ALPNCallback = NULL;
350              
351             /* Perl callback that will get called when a hostname is successfully matched. */
352             static SV* VHIndexCallback = NULL;
353              
354             /*
355             * ALPN callback that gets called from matrixSSL whenever a client sends an ALPN extension.
356             *
357             * This function gets called only in a server socket context.
358             *
359             * ssl->userPtr is a pointer to a t_SSL_data structure containing our custom data
360             *
361             * Params:
362             * (in) ssl - pointer to the SSL session
363             * (in) protoCount - how many protocols does the client implement
364             * (in) proto - array with protocols
365             * (in) protoLen - length of each protocol name (in bytes)
366             * (out) index - it will be set to the index of the protocol the server supports or -1 if the server
367             * doesn't support any of the client's protocols
368             */
369 0           void ALPNCallbackXS(void *ssl, short protoCount, char *proto[MAX_PROTO_EXT], int32 protoLen[MAX_PROTO_EXT], int32 *index) {
370             ssl_t *pssl;
371 0           int32 res_cl = -1, res_sv = -1, i, j, res;
372             uint32_t ssl_id;
373 0           p_ALPN_data alpn = NULL;
374             p_SSL_data ssl_data;
375             p_SSL_server ss;
376             #ifndef WIN32
377 0           int regex_res = 0;
378             #if defined(MATRIX_DEBUG)
379             char regex_error[255];
380             #endif
381             #endif
382             #ifdef MATRIX_DEBUG
383             warn("alpncb: ssl = %p, userptr = %p, expectdName = %s", ssl, ((ssl_t *) ssl)->userPtr, ((ssl_t *) ssl)->expectedName);
384             #endif
385             /* get SSL session and our custom SSL session data */
386 0           pssl = (ssl_t *) ssl;
387 0           ssl_data = (p_SSL_data) pssl->userPtr;
388 0           ssl_id = ssl_data->ssl_id;
389 0           ss = SSL_servers[ssl_data->server_index];
390              
391             /* was there a SNI extension parsed? */
392 0 0         if (pssl->expectedName != NULL) {
393 0 0         for (i = 0; i < ss->SNI_entries_number; i++)
394             #ifndef WIN32
395 0 0         if ((regex_res = regexec(&(ss->SNI_entries[i]->regex_hostname), (const char *) pssl->expectedName, 0, NULL, 0)) == 0) {
396             #else
397             if (!stricmp(pssl->expectedName, ss->SNI_entries[i]->hostname)) {
398             #endif
399             #ifdef MATRIX_DEBUG
400             warn("SNI match for %s on %d", pssl->expectedName, i);
401             #endif
402             /* found a matching hostname so save the keys in case the SNI callback is called */
403 0           ssl_data->keys = ss->SNI_entries[i]->keys;
404              
405 0           break;
406             #if defined(MATRIX_DEBUG) && !defined(WIN32)
407             } else {
408             regerror(regex_res, &(ss->SNI_entries[i]->regex_hostname), regex_error, 255);
409             warn("Error matching %d SNI entry: %s", i, regex_error);
410             #endif
411             }
412              
413             /* test if a matching hostname was found */
414 0 0         if (i < ss->SNI_entries_number) {
415             /* get the protocols for the virtual host */
416 0           alpn = ss->SNI_entries[i]->alpn;
417              
418             /* test Perl SNI callback present and not already called */
419 0 0         if ((VHIndexCallback != NULL) && !ssl_data->cbSNI_done) {
    0          
420             /* execute Perl SNI callback */
421 0           dSP;
422              
423 0           ENTER;
424 0           SAVETMPS;
425              
426 0 0         PUSHMARK(SP);
427 0 0         XPUSHs(sv_2mortal(newSViv(ssl_id)));
428 0 0         XPUSHs(sv_2mortal(newSViv(i)));
429 0 0         XPUSHs(sv_2mortal(newSVpv(pssl->expectedName, strlen(pssl->expectedName))));
430 0           PUTBACK;
431              
432 0           res = call_sv(VHIndexCallback, G_EVAL|G_SCALAR);
433              
434 0           SPAGAIN;
435              
436 0 0         if (SvTRUE(ERRSV)) {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
437 0 0         warn("%s", SvPV_nolen(ERRSV));
    0          
    0          
    0          
438 0           warn("die() in SNI_callback callback not allowed, continue...\n");
439 0           POPs;
440 0           res = -1;
441             }
442              
443 0           PUTBACK;
444 0 0         FREETMPS;
445 0           LEAVE;
446              
447             ssl_data->cbSNI_done;
448             }
449             } else {
450             /* even if we didn't find a matching virtual host and we know the SSL connection
451             will fail, we will choose a protocol and let the SNI callback return NULL keys
452             so the client will get the apropiate SSL alert
453             */
454 0           alpn = ss->alpn;
455             }
456             } else {
457             /* no SNI extension was received from the client, use default server protocols */
458 0           alpn = ss->alpn;
459             }
460              
461             /* test if the server has protocol defines (it should) */
462 0 0         if (alpn != NULL) {
463             #ifdef MATRIX_DEBUG
464             warn("ALPN callback XS: protoCount = %d, server protoCount = %d, ssl_data = %p, ssl_id = %d", protoCount, alpn->protoCount, ssl_data, ssl_id);
465             #endif
466 0 0         for (i = 0; i < alpn->protoCount; i++) {
467 0 0         for (j = 0; j < protoCount; j++) {
468             #ifdef MATRIX_DEBUG
469             warn("Client protocol: %.*s, Server protocol: %.*s", protoLen[j], proto[j], alpn->protoLen[i], alpn->proto[i]);
470             #endif
471 0 0         if ((alpn->protoLen[i] == protoLen[j]) && !strncmp(alpn->proto[i], proto[j], protoLen[j])) {
    0          
472             #ifdef MATRIX_DEBUG
473             warn("Match on cl = %d, sv = %d: %.*s", j, i, protoLen[j], proto[j]);
474             #endif
475 0           res_sv = i;
476 0           res_cl = j;
477 0           break;
478             }
479             }
480              
481 0 0         if (res_cl != -1) break;
482             }
483             }
484              
485             /* execute Perl ALPN callback */
486 0 0         if ((ALPNCallback != NULL) && (res_sv != -1)) {
    0          
487 0           dSP;
488 0           ENTER;
489 0           SAVETMPS;
490              
491 0 0         PUSHMARK(SP);
492 0 0         XPUSHs(sv_2mortal(newSViv(ssl_id)));
493 0 0         XPUSHs(sv_2mortal(newSVpv(alpn->proto[res_sv], alpn->protoLen[res_sv])));
494 0           PUTBACK;
495              
496 0           call_sv(ALPNCallback, G_DISCARD|G_SCALAR);
497              
498 0           SPAGAIN;
499              
500 0 0         if (SvTRUE(ERRSV)) {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
501 0 0         warn("%s", SvPV_nolen(ERRSV));
    0          
    0          
    0          
502 0           warn("die() in ALPNCallback callback not allowed, continue...\n");
503 0           res_cl = -1;
504             }
505              
506 0           PUTBACK;
507 0 0         FREETMPS;
508 0           LEAVE;
509             }
510             #ifdef MATRIX_DEBUG
511             else
512             warn("ALPN data present but no ALPN callback set or no protocol could be selected (res_sv = %d)", res_sv);
513             #endif
514              
515             /* remember that the ALPN callback was executed */
516 0           ssl_data->cbALPN_done = 1;
517              
518             /* return selected protocol */
519 0           *index = res_cl;
520 0           }
521              
522             /*
523             * SNI callback that gets called from matrixSSL whenever a client send a SNI
524             * extension.
525             *
526             * ssl->userPtr is a pointer to a t_SSL_data structure containing our custom data
527             *
528             * This function gets called only in a server socket context.
529             *
530             * Params:
531             * (in) ssl - pointer to the SSL session
532             * (in) hostname - the hostname specified by the client in the SNI extension
533             * (in) hostnameLed - hostname length in bytes
534             * (out) newKeys - pointer that holds a pointer to a sslKeys_t structure. We will search through
535             * all the SNI entries of the specified SNI server (see below) and if we find a hostname
536             * that matches we will set this pointer to the address of the keys for the found SNI entry.
537             * The keys strcuture holds certificate, private key, session ticket keys, DH param) for
538             * a certain virtual host. This is initialized only once and is shared between all sessions
539             * accepted by the server socket
540             */
541 0           void SNI_callback(void *ssl, char *hostname, int32 hostnameLen, sslKeys_t **newKeys) {
542 0           int32 i = 0, res;
543             uint32_t ssl_id;
544             p_SSL_data ssl_data;
545             p_SSL_server ss;
546             unsigned char _hostname[255];
547             #ifndef WIN32
548 0           int regex_res = 0;
549             #if defined(MATRIX_DEBUG)
550             char regex_error[255];
551             #endif
552             #endif
553             /* get SSL session and our custom SSL session data */
554 0           ssl_data = (p_SSL_data) ((ssl_t *) ssl)->userPtr;
555 0           ssl_id = ssl_data->ssl_id;
556 0           ss = SSL_servers[ssl_data->server_index];
557              
558             /* check if the keys are already set in our custom SSL data
559             by a previous call to the ALPN callback */
560 0 0         if (ssl_data->keys != NULL) {
561             #ifdef MATRIX_DEBUG
562             warn("SNI_callback: Valid keys found, set by the ALPN callback. Returning");
563             #endif
564 0           *newKeys = ssl_data->keys;
565 0           return;
566             }
567              
568             /* TODO: modify matrixSSL so it returns a null terminated hostname so this is no longer necessary */
569 0 0         if (hostnameLen > 254) hostnameLen = 254;
570 0           memcpy(_hostname, hostname, hostnameLen);
571 0           _hostname[hostnameLen] = 0;
572              
573             #ifdef MATRIX_DEBUG
574             warn("SNI_callback: looking for hostname %s, ssl_data %p, ssl_id %d", _hostname, ssl_data, ssl_id);
575             #endif
576              
577 0           *newKeys = NULL;
578              
579 0 0         for (i = 0; i < ss->SNI_entries_number; i++)
580             #ifndef WIN32
581 0 0         if ((regex_res = regexec(&(ss->SNI_entries[i]->regex_hostname), (const char *) _hostname, 0, NULL, 0)) == 0) {
582             #else
583             if ((hostnameLen == ss->SNI_entries[i]->hostnameLen) && !stricmp(_hostname, ss->SNI_entries[i]->hostname)) {
584             #endif
585             #ifdef MATRIX_DEBUG
586             warn("SNI match for %s on %d", _hostname, i);
587             #endif
588 0           *newKeys = ss->SNI_entries[i]->keys;
589              
590 0           break;
591             #if defined(MATRIX_DEBUG) && !defined(WIN32)
592             } else {
593             regerror(regex_res, &(ss->SNI_entries[i]->regex_hostname), regex_error, 255);
594             warn("Error matching %d SNI entry: %s", i, regex_error);
595             #endif
596             }
597              
598             /* if the requested virtual host was not found we try to return the default server keys (if they are set) */
599 0 0         if (*newKeys == NULL) {
600 0 0         if (ss->keys != NULL) {
601 0           *newKeys = ss->keys;
602             /* set the index to -1 to singal that the default server keys are used */
603 0           i = -1;
604             }
605             }
606              
607             /* execute Perl SNI callback if necessary (might have been called already from the ALPN callback) */
608 0 0         if ((i < ss->SNI_entries_number) && (VHIndexCallback != NULL) && !ssl_data->cbSNI_done) {
    0          
    0          
609 0           dSP;
610              
611 0           ENTER;
612 0           SAVETMPS;
613              
614 0 0         PUSHMARK(SP);
615 0 0         XPUSHs(sv_2mortal(newSViv(ssl_id)));
616 0 0         XPUSHs(sv_2mortal(newSViv(i)));
617 0 0         XPUSHs(sv_2mortal(newSVpv(hostname, hostnameLen)));
618 0           PUTBACK;
619              
620 0           res = call_sv(VHIndexCallback, G_EVAL|G_SCALAR);
621              
622 0           SPAGAIN;
623              
624 0 0         if (SvTRUE(ERRSV)) {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
625 0 0         warn("%s", SvPV_nolen(ERRSV));
    0          
    0          
    0          
626 0           warn("die() in SNI_callback callback not allowed, continue...\n");
627 0           POPs;
628 0           res = -1;
629             }
630              
631 0           PUTBACK;
632 0 0         FREETMPS;
633 0           LEAVE;
634              
635 0           ssl_data->cbSNI_done = 1;
636             }
637             }
638              
639             /*
640             * Utility function for building the 'signed_certificate_timestamp' TLS extension data.
641             * This extension is sent by client who want to receive Certificate Transparancy information
642             *
643             * Params:
644             * (in) ar - Perl scalar - holds the file name which contains multiple SCT (Signed Certificate
645             * Timestamp) binary structures received from CT server logs. This file repesents a ready
646             * to use extension data
647             * - Perl array rference - holds as elements file names of individual SCT binary structures
648             * received from CT server logs. The function will concatenate all these files and build
649             * the extension data
650             * (out) buffer - a pointer to a pointer that will be allocated and will hold the extension data
651             * (out) buffer_size - a pointer to an int32 variable that will hold the extension data size
652             */
653 5           int build_SCT_buffer(SV *ar, unsigned char **buffer, int32 *buffer_size) {
654             #ifdef WIN32
655             struct _stat fstat;
656             #else
657             struct stat fstat;
658             #endif
659             AV *sct_array;
660             SV *item_sv;
661             unsigned char *item, *sct, *c;
662 5           STRLEN item_len = 0;
663 5           int sct_array_size = 0, i = 0, sct_total_size = 0, sct_size = 0, rc = PS_SUCCESS;
664              
665 5 50         if (SvOK(ar)) {
    0          
    0          
666 7 100         if (!SvROK(ar)) {
667             /* a single file */
668 3 50         item = SvPV(ar, item_len);
669             #ifdef MATRIX_DEBUG
670             warn("Loading SCT single file: %s", item);
671             #endif
672 3 50         if (item == NULL)
673 0           croak("build_SCT_buffer: expecting a scalar or array reference as first parameter");
674              
675 3 50         if ((rc = psGetFileBuf(NULL, item, buffer, buffer_size)) != PS_SUCCESS) {
676 0           warn("Error %d trying to read file %s", rc, item);
677 0           return rc;
678             }
679              
680 3           return 1;
681             } else {
682 2 50         if (SvTYPE(SvRV(ar)) != SVt_PVAV)
683 0           croak("build_SCT_buffer: expecting a scalar or array reference as first parameter");
684             }
685             } else {
686 0           croak("build_SCT_buffer: expecting a scalar or array reference as first parameter");
687             }
688              
689             /* get the SCT files array */
690 2           sct_array = (AV *) SvRV(ar);
691              
692             /* get number of SCT files */
693 2           sct_array_size = (uint16) av_len(sct_array) + 1;
694              
695             #ifdef MATRIX_DEBUG
696             warn("Preparing to read %d SCT files", sct_array_size);
697             #endif
698 6 100         for (i = 0; i < sct_array_size; i++) {
699 4           item_sv = *av_fetch(sct_array, i, 0);
700 4 50         item = SvPV(item_sv, item_len);
701              
702             #ifdef WIN32
703             if (_stat(item, &fstat) != 0) {
704             #else
705 4 50         if (stat(item, &fstat) != 0) {
706             #endif
707 0           warn("Error reading stats for SCT file %s", item);
708 0           return -1;
709             }
710             #ifdef MATRIX_DEBUG
711             warn("Reading SCT file %d - %s; size: %d", i, item, fstat.st_size);
712             #endif
713 4           sct_total_size += (size_t) fstat.st_size;
714             }
715              
716 2           sct_total_size += sct_array_size * 2;
717 2           *buffer_size = sct_total_size;
718              
719 2           c = *buffer = (unsigned char *) psMallocNative(sct_total_size);
720              
721 6 100         for (i = 0; i < sct_array_size; i++) {
722 4           item_sv = *av_fetch(sct_array, i, 0);
723 4 50         item = SvPV(item_sv, item_len);
724              
725 4 50         if ((rc = psGetFileBuf(NULL, item, &sct, &sct_size)) != PS_SUCCESS) {
726 0           warn("Error %d trying to read file %s", rc, item);
727 0           psFreeNative(*buffer);
728 0           *buffer = NULL;
729 0           *buffer_size = 0;
730 0           return rc;
731             }
732              
733 4           *c = (sct_size & 0xFF00) >> 8; c++;
734 4           *c = (sct_size & 0xFF); c++;
735 4           memcpy(c, sct, sct_size);
736 4           c+= sct_size;
737              
738 4           psFreeNative(sct);
739             }
740              
741 5           return sct_array_size;
742             }
743              
744              
745             MODULE = Crypt::MatrixSSL3 PACKAGE = Crypt::MatrixSSL3
746              
747             INCLUDE: inc/const-xs.inc
748              
749             PROTOTYPES: ENABLE
750              
751              
752             int _getObjCount()
753             CODE:
754             #ifdef MATRIX_DEBUG
755             RETVAL = objects;
756             #else
757 0           RETVAL = 0;
758             #endif
759             OUTPUT:
760             RETVAL
761              
762              
763             int set_cipher_suite_enabled_status(cipherId, status)
764             short cipherId;
765             int status;
766              
767             CODE:
768 7           add_obj();
769 7           RETVAL = matrixSslSetCipherSuiteEnabledStatus(NULL, cipherId, status);
770              
771             OUTPUT:
772             RETVAL
773              
774              
775             void Open()
776             CODE:
777 15           add_obj();
778              
779              
780             void Close()
781             int i = 0, j = 0, k = 0;
782             p_SNI_entry se = NULL;
783             p_SSL_server ss = NULL;
784              
785             CODE:
786             del_obj();
787              
788             /* release SSL servers */
789             #ifdef MATRIX_DEBUG
790             warn("----\nReleasing %d SSL servers", SSL_server_index);
791             #endif
792              
793 16 100         for (j = 0; j < SSL_server_index; j++) {
794 2           ss = SSL_servers[j];
795             #ifdef MATRIX_DEBUG
796             warn("Releasing resources for SSL server %d", j);
797             #endif
798 2 100         if (ss->alpn != NULL) {
799             #ifdef MATRIX_DEBUG
800             warn(" Releasing ALPN data: %d protocols", ss->alpn->protoCount);
801             #endif
802 3 100         for (k = 0; k < ss->alpn->protoCount; k++)
803 2 50         if (ss->alpn->proto[k] != NULL) free(ss->alpn->proto[k]);
804              
805 1           free(ss->alpn);
806             }
807             #ifdef MATRIX_DEBUG
808             warn(" Releasing %d SNI entries", ss->SNI_entries_number);
809             #endif
810 3 100         for (i = 0; i < ss->SNI_entries_number; i++) {
811 1           se = ss->SNI_entries[i];
812             #ifndef WIN32
813             #ifdef MATRIX_DEBUG
814             warn(" Releasing regex for SNI entry %d", i);
815             #endif
816 1           regfree(&(se->regex_hostname));
817             #endif
818             #ifdef MATRIX_DEBUG
819             warn(" Releasing keys for SNI entry %d", i);
820             #endif
821 1           matrixSslDeleteKeys(ss->SNI_entries[i]->keys);
822             del_obj();
823              
824 1 50         if (se->alpn != NULL) {
825             #ifdef MATRIX_DEBUG
826             warn(" Releasing ALPN data: %d protocols", se->alpn->protoCount);
827             #endif
828 0 0         for (k = 0; k < se->alpn->protoCount; k++)
829 0 0         if (se->alpn->proto[k] != NULL) free(se->alpn->proto[k]);
830              
831 0           free(se->alpn);
832             }
833             #ifdef MATRIX_DEBUG
834             warn(" Releasing SNI entry %d", i);
835             #endif
836 1           free(se);
837             }
838             #ifdef MATRIX_DEBUG
839             warn("Releasing SSL server %d", j);
840             #endif
841 2           free(ss);
842             }
843 14           SSL_server_index = 0;
844             #ifdef MATRIX_DEBUG
845             warn("Calling matrixSslClose()");
846             #endif
847 14           matrixSslClose();
848 14           matrixssl_initialized = 0;
849              
850              
851             int create_SSL_server()
852             CODE:
853             /* new SSL server, check limits */
854 2 50         if (SSL_server_index == MAX_SSL_SERVERS) {
855 0           warn("We have already initiazlied the maximum number of %d SSL servers", MAX_SSL_SERVERS);
856 0           XSRETURN_IV(-1);
857             }
858             #ifdef MATRIX_DEBUG
859             warn("create_SSL_server: allocating buffer for new SSL server at index %d", SSL_server_index);
860             #endif
861             /* allocate a new SSL server */
862 2           SSL_servers[SSL_server_index] = (p_SSL_server) malloc(SZ_SSL_SERVER);
863 2           memset(SSL_servers[SSL_server_index], 0, SZ_SSL_SERVER);
864              
865 2           RETVAL = SSL_server_index;
866              
867 2           SSL_server_index++;
868              
869             OUTPUT:
870             RETVAL
871              
872              
873             int refresh_OCSP_staple(server_index, index, OCSP_file)
874             int server_index = SvOK(ST(0)) ? SvIV(ST(0)) : -1;
875             int index = SvOK(ST(1)) ? SvIV(ST(1)): -1;
876             unsigned char *OCSP_file = SvOK(ST(2)) ? SvPV_nolen(ST(2)) : NULL;
877             unsigned char *buffer = NULL;
878             int32 buffer_size = 0, rc = 0;
879              
880             CODE:
881 1 50         if (server_index < 0)
882 0           croak("Invalid SSL server index %d", server_index);
883              
884 1 50         if (index < 0)
885 0           croak("OCSP staple for SSL (default) servers is refreshed using the keys now!");
886              
887 1 50         if (OCSP_file == NULL)
888 0           croak("You must specify a valid OCSP staple file");
889             #ifdef MATRIX_DEBUG
890             warn("Refresh OCSP staple buffer for SSL server %d/SNI entry %d", server_index, index);
891             #endif
892 1 50         if (server_index >= SSL_server_index)
893 0           croak("Out of range SSL server index spcified: %d > %d", server_index, SSL_server_index - 1);
894              
895 1 50         if (index >= SSL_servers[server_index]->SNI_entries_number)
896 0           croak("Out of range SNI entry index spcified for SSL server %d: %d > %d", server_index, index, SSL_servers[server_index]->SNI_entries_number - 1);
897              
898 1           rc = psGetFileBuf(NULL, OCSP_file, &buffer, &buffer_size);
899              
900 1 50         if (rc != PS_SUCCESS) {
901 0           warn("Failed to load OCSP staple %s; %d", OCSP_file, rc);
902 0           XSRETURN_IV(rc);
903             }
904              
905 1           rc = matrixSslLoadOCSPResponse(SSL_servers[server_index]->SNI_entries[index]->keys, buffer, buffer_size);
906              
907 1 50         if (buffer != NULL) psFreeNative(buffer);
908              
909 1 50         if (rc != PS_SUCCESS)
910 0           croak("matrixSslLoadOCSPResponse failed for SSL server %d, SNI entry %d: $d", server_index, index, rc);
911              
912 1           RETVAL = rc;
913              
914             OUTPUT:
915             RETVAL
916              
917              
918             int refresh_SCT_buffer(server_index, index, SCT_params)
919             int server_index = SvOK(ST(0)) ? SvIV(ST(0)) : -1;
920             int index = SvOK(ST(1)) ? SvIV(ST(1)): -1;
921             SV *SCT_params;
922             unsigned char *buffer = NULL;
923             int32 buffer_size = 0, res = 0, rc = 0;
924              
925             CODE:
926 2 50         if (server_index < 0)
927 0           croak("Invalid SSL server index %d", server_index);
928              
929 2 50         if (index < 0)
930 0           croak("SCT buffer for SSL (default) servers is refreshed using the keys now!");
931             #ifdef MATRIX_DEBUG
932             warn("Refresh SCT buffer for SSL server %d/SNI entry %d", server_index, index);
933             #endif
934 2 50         if (server_index >= SSL_server_index)
935 0           croak("Out of range SSL server index spcified: %d > %d", server_index, SSL_server_index - 1);
936              
937 2 50         if (index >= SSL_servers[server_index]->SNI_entries_number)
938 0           croak("Out of range SNI entry index spcified for SSL server %d: %d > %d", server_index, index, SSL_servers[server_index]->SNI_entries_number - 1);
939              
940 2           res = build_SCT_buffer(SCT_params, &buffer, &buffer_size);
941             #ifdef MATRIX_DEBUG
942             warn("Refreshed SCT buffer: Loaded %d SCT files, %p %d", rc, buffer, buffer_size);
943             #endif
944 2 50         if (res < 1) {
945 0 0         if (buffer != NULL) psFreeNative(buffer);
946 0           croak("Filed to build the SCT buffer for SSL server %d, SNI entry %d: %d", server_index, index, res);
947             }
948              
949 2           rc = matrixSslLoadSCTResponse(SSL_servers[server_index]->SNI_entries[index]->keys, buffer, buffer_size);
950              
951 2 50         if (buffer != NULL) psFreeNative(buffer);
952              
953 2 50         if (rc != PS_SUCCESS) {
954 0           croak("matrixSslLoadSCTResponse failed for SSL server %d, SNI entry %d: $d", server_index, index, rc);
955             XSRETURN_IV(0);
956             }
957              
958 2           RETVAL = res;
959              
960             OUTPUT:
961             RETVAL
962              
963              
964             int refresh_ALPN_data(server_index, index, ALPN_data)
965             int server_index = SvOK(ST(0)) ? SvIV(ST(0)) : -1;
966             int index = SvOK(ST(1)) ? SvIV(ST(1)): -1;
967             SV *ALPN_data;
968             AV *aproto = NULL;
969             p_ALPN_data alpn = NULL, *palpn = NULL;
970             SV *tmp_sv = NULL;
971             unsigned char *item = NULL;
972             STRLEN item_len = 0;
973             int i = 0;
974              
975             CODE:
976 1 50         if (!(SvROK(ALPN_data) && SvTYPE(SvRV(ALPN_data)) == SVt_PVAV))
    50          
977 0           croak("Expected ALPN data to be an array reference");
978              
979 1 50         if (server_index < 0)
980 0           croak("Invalid SSL server index %d", server_index);
981              
982 1 50         if (server_index >= SSL_server_index)
983 0           croak("Out of range SSL server index spcified: %d > %d", server_index, SSL_server_index - 1);
984              
985 1 50         if (index < 0) {
986             #ifdef MATRIX_DEBUG
987             warn("Refresh SSL (default) server %d ALPN data", server_index);
988             #endif
989 1           palpn = &(SSL_servers[server_index]->alpn);
990             } else {
991             #ifdef MATRIX_DEBUG
992             warn("Refresh ALPN_data for SSL server %d/SNI entry %d", server_index, index);
993             #endif
994 0 0         if (index >= SSL_servers[server_index]->SNI_entries_number)
995 0           croak("Out of range SNI entry index spcified for SSL server %d: %d > %d", server_index, index, SSL_servers[server_index]->SNI_entries_number - 1);
996              
997 0           palpn = &(SSL_servers[server_index]->SNI_entries[index]->alpn);
998             }
999              
1000             /* Check if we should allocate the ALPN data strcture */
1001 1 50         if (*palpn == NULL) {
1002 0           *palpn = (p_ALPN_data) malloc(SZ_ALPN_DATA);
1003 0           memset(*palpn, 0, SZ_ALPN_DATA);
1004             }
1005              
1006 1           alpn = *palpn;
1007 1           aproto = (AV *) SvRV(ALPN_data);
1008              
1009             /* Free previous allocated protocols (if any) */
1010             #ifdef MATRIX_DEBUG
1011             warn("Freeing %d protocols", alpn->protoCount);
1012             #endif
1013 1 50         for (i = 0; i > alpn->protoCount; i++)
1014 0 0         if (alpn->proto[i]) free(alpn->proto[i]);
1015              
1016             /* Load new protocols */
1017 1           alpn->protoCount = (short) av_len(aproto) + 1;
1018 1 50         if (alpn->protoCount > MAX_PROTO_EXT) alpn->protoCount = MAX_PROTO_EXT;
1019              
1020 3 100         for (i = 0; i < alpn->protoCount; i++) {
1021 2           tmp_sv = *av_fetch(aproto, i, 0);
1022 2 50         item = (unsigned char *) SvPV(tmp_sv, item_len);
1023             #ifdef MATRIX_DEBUG
1024             warn("Protocol %d: %.*s", i, item_len, item);
1025             #endif
1026 2           alpn->proto[i] = (unsigned char *) malloc(item_len);
1027 2           memcpy(alpn->proto[i], item, item_len);
1028 2           alpn->protoLen[i] = item_len;
1029             }
1030              
1031 1           RETVAL = alpn->protoCount;
1032              
1033             OUTPUT:
1034             RETVAL
1035              
1036              
1037             void set_VHIndex_callback(vh_index_cb)
1038             SV *vh_index_cb;
1039              
1040             CODE:
1041 0           VHIndexCallback = SvREFCNT_inc(SvRV(vh_index_cb));
1042              
1043              
1044             void set_ALPN_callback(alpn_cb)
1045             SV *alpn_cb;
1046              
1047             CODE:
1048 0           ALPNCallback = SvREFCNT_inc(SvRV(alpn_cb));
1049              
1050              
1051             unsigned int capabilities()
1052             CODE:
1053 2           RETVAL = 0;
1054             #ifdef USE_SHARED_SESSION_CACHE
1055             RETVAL |= SHARED_SESSION_CACHE_ENABLED;
1056             #endif
1057             #ifdef USE_STATELESS_SESSION_TICKETS
1058 2           RETVAL |= STATELESS_TICKETS_ENABLED;
1059             #endif
1060             #ifdef REQUIRE_DH_PARAMS
1061 2           RETVAL |= DH_PARAMS_ENABLED;
1062             #endif
1063             #ifdef USE_ALPN
1064 2           RETVAL |= ALPN_ENABLED;
1065             #endif
1066             #ifdef USE_OCSP
1067 2           RETVAL |= OCSP_STAPLES_ENABLED;
1068             #endif
1069             #ifdef USE_SCT
1070 2           RETVAL |= CERTIFICATE_TRANSPARENCY_ENABLED;
1071             #endif
1072 2           RETVAL |= SNI_ENABLED;
1073              
1074             OUTPUT:
1075             RETVAL
1076              
1077              
1078             MODULE = Crypt::MatrixSSL3 PACKAGE = Crypt::MatrixSSL3::KeysPtr PREFIX = keys_
1079              
1080              
1081             Crypt_MatrixSSL3_Keys *keys_new()
1082             INIT:
1083             sslKeys_t *keys;
1084             int rc;
1085              
1086             CODE:
1087 100807           add_obj();
1088 100807           rc = matrixSslNewKeys(&keys, NULL);
1089 100807 50         if (rc != PS_SUCCESS) {
1090             del_obj();
1091 0           croak("%d", rc);
1092             }
1093              
1094 100807           RETVAL = (Crypt_MatrixSSL3_Keys *)keys;
1095              
1096             OUTPUT:
1097             RETVAL
1098              
1099              
1100             void keys_DESTROY(keys);
1101             Crypt_MatrixSSL3_Keys *keys;
1102              
1103             CODE:
1104 100807           matrixSslDeleteKeys((sslKeys_t *)keys);
1105             del_obj();
1106              
1107              
1108             int keys_load_rsa(keys, certFile, privFile, privPass, trustedCAcertFiles)
1109             Crypt_MatrixSSL3_Keys *keys;
1110             char *certFile = SvOK(ST(1)) ? SvPV_nolen(ST(1)) : NULL;
1111             char *privFile = SvOK(ST(2)) ? SvPV_nolen(ST(2)) : NULL;
1112             char *privPass = SvOK(ST(3)) ? SvPV_nolen(ST(3)) : NULL;
1113             char *trustedCAcertFiles = SvOK(ST(4)) ? SvPV_nolen(ST(4)) : NULL;
1114              
1115             CODE:
1116 666           RETVAL = (int) matrixSslLoadRsaKeys((sslKeys_t *)keys, certFile, privFile, privPass, trustedCAcertFiles);
1117              
1118             OUTPUT:
1119             RETVAL
1120              
1121              
1122             int keys_load_rsa_mem(keys, cert, priv, trustedCA)
1123             Crypt_MatrixSSL3_Keys *keys;
1124             SV *cert;
1125             SV *priv;
1126             SV *trustedCA;
1127             unsigned char *certBuf = NULL;
1128             unsigned char *privBuf = NULL;
1129             unsigned char *trustedCABuf = NULL;
1130             STRLEN certLen = 0;
1131             STRLEN privLen = 0;
1132             STRLEN trustedCALen = 0;
1133              
1134             CODE:
1135             /* All bufs can contain \0, so SvPV must be used instead of strlen() */
1136 114 100         certBuf = SvOK(cert) ? (unsigned char *) SvPV(cert, certLen) : NULL;
    50          
    50          
    50          
1137 114 100         privBuf = SvOK(priv) ? (unsigned char *) SvPV(priv, privLen) : NULL;
    50          
    50          
    50          
1138 114 100         trustedCABuf= SvOK(trustedCA) ? (unsigned char *) SvPV(trustedCA, trustedCALen) : NULL;
    50          
    50          
    50          
1139              
1140 114           RETVAL = matrixSslLoadRsaKeysMem((sslKeys_t *)keys, certBuf, certLen, privBuf, privLen,
1141             trustedCABuf, trustedCALen);
1142              
1143             OUTPUT:
1144             RETVAL
1145              
1146              
1147             int keys_load_ecc(keys, certFile, privFile, privPass, trustedCAcertFiles)
1148             Crypt_MatrixSSL3_Keys *keys;
1149             char *certFile = SvOK(ST(1)) ? SvPV_nolen(ST(1)) : NULL;
1150             char *privFile = SvOK(ST(2)) ? SvPV_nolen(ST(2)) : NULL;
1151             char *privPass = SvOK(ST(3)) ? SvPV_nolen(ST(3)) : NULL;
1152             char *trustedCAcertFiles = SvOK(ST(4)) ? SvPV_nolen(ST(4)) : NULL;
1153              
1154             CODE:
1155 0           RETVAL = (int) matrixSslLoadEcKeys((sslKeys_t *)keys, certFile, privFile, privPass, trustedCAcertFiles);
1156              
1157             OUTPUT:
1158             RETVAL
1159              
1160              
1161             int keys_load_ecc_mem(keys, cert, priv, trustedCA)
1162             Crypt_MatrixSSL3_Keys *keys;
1163             SV *cert;
1164             SV *priv;
1165             SV *trustedCA;
1166             unsigned char *certBuf = NULL;
1167             unsigned char *privBuf = NULL;
1168             unsigned char *trustedCABuf = NULL;
1169             STRLEN certLen = 0;
1170             STRLEN privLen = 0;
1171             STRLEN trustedCALen = 0;
1172              
1173             CODE:
1174             /* All bufs can contain \0, so SvPV must be used instead of strlen() */
1175 0 0         certBuf = SvOK(cert) ? (unsigned char *) SvPV(cert, certLen) : NULL;
    0          
    0          
    0          
1176 0 0         privBuf = SvOK(priv) ? (unsigned char *) SvPV(priv, privLen) : NULL;
    0          
    0          
    0          
1177 0 0         trustedCABuf= SvOK(trustedCA) ? (unsigned char *) SvPV(trustedCA, trustedCALen) : NULL;
    0          
    0          
    0          
1178              
1179 0           RETVAL = matrixSslLoadEcKeysMem((sslKeys_t *)keys, certBuf, certLen, privBuf, privLen,
1180             trustedCABuf, trustedCALen);
1181              
1182             OUTPUT:
1183             RETVAL
1184              
1185              
1186             int keys_load_pkcs12(keys, p12File, importPass, macPass, flags)
1187             Crypt_MatrixSSL3_Keys *keys;
1188             char *p12File = SvOK(ST(1)) ? SvPV_nolen(ST(1)) : NULL;
1189             SV *importPass;
1190             SV *macPass;
1191             int flags;
1192             unsigned char *importPassBuf = NULL;
1193             unsigned char *macPassBuf = NULL;
1194             STRLEN importPassLen = 0;
1195             STRLEN macPassLen = 0;
1196              
1197             CODE:
1198 15 100         importPassBuf= SvOK(importPass) ? (unsigned char *) SvPV(importPass, importPassLen) : NULL;
    50          
    50          
    50          
1199 15 100         macPassBuf = SvOK(macPass) ? (unsigned char *) SvPV(macPass, macPassLen) : NULL;
    50          
    50          
    50          
1200              
1201 15           RETVAL = matrixSslLoadPkcs12((sslKeys_t *)keys, (unsigned char *) p12File, importPassBuf, importPassLen,
1202             macPassBuf, macPassLen, flags);
1203              
1204             OUTPUT:
1205             RETVAL
1206              
1207              
1208             int keys_load_session_ticket_keys(keys, name, symkey, hashkey)
1209             Crypt_MatrixSSL3_Keys *keys;
1210             SV *name;
1211             SV *symkey;
1212             SV *hashkey;
1213             char *nameBuf = NULL, *symkeyBuf = NULL, *hashkeyBuf = NULL;
1214             STRLEN symkeyLen = 0, hashkeyLen = 0;
1215              
1216             CODE:
1217 0 0         nameBuf = SvOK(name) ? SvPV_nolen(name) : NULL;
    0          
    0          
    0          
1218 0 0         symkeyBuf = SvOK(symkey) ? SvPV(symkey, symkeyLen) : NULL;
    0          
    0          
    0          
1219 0 0         hashkeyBuf = SvOK(hashkey) ? SvPV(hashkey, hashkeyLen) : NULL;
    0          
    0          
    0          
1220              
1221 0           RETVAL = (int) matrixSslLoadSessionTicketKeys(keys, nameBuf, symkeyBuf, symkeyLen, hashkeyBuf, hashkeyLen);
1222              
1223             OUTPUT:
1224             RETVAL
1225              
1226              
1227             int keys_load_DH_params(keys, paramsFile)
1228             Crypt_MatrixSSL3_Keys *keys;
1229             char *paramsFile = SvOK(ST(1)) ? SvPV_nolen(ST(1)) : NULL;
1230              
1231             CODE:
1232 0           RETVAL = (int) matrixSslLoadDhParams((sslKeys_t *)keys, paramsFile);
1233              
1234             OUTPUT:
1235             RETVAL
1236              
1237              
1238             int keys_load_OCSP_response(keys, OCSP_file)
1239             Crypt_MatrixSSL3_Keys *keys;
1240             char *OCSP_file = SvOK(ST(1)) ? SvPV_nolen(ST(1)) : NULL;
1241             unsigned char *buffer = NULL;
1242             int32 buffer_size = 0, rc;
1243              
1244             CODE:
1245 1 50         if ((rc = psGetFileBuf(NULL, OCSP_file, &buffer, &buffer_size)) != PS_SUCCESS) {
1246 0           croak("Error %d trying to read file %s", rc, OCSP_file);
1247             } else {
1248 1           rc = matrixSslLoadOCSPResponse(keys, buffer, buffer_size);
1249              
1250 1           psFreeNative(buffer);
1251              
1252 1 50         if (rc != PS_SUCCESS) {
1253 0           croak("Error %d while setting the OCSP response");
1254             }
1255             }
1256              
1257 1           RETVAL = rc;
1258              
1259             OUTPUT:
1260             RETVAL
1261              
1262              
1263             int keys_load_SCT_response(keys, SCT_params)
1264             Crypt_MatrixSSL3_Keys *keys;
1265             SV *SCT_params;
1266             unsigned char *buffer = NULL;
1267             int32 buffer_size = 0, res = 0, rc = 0;
1268              
1269             CODE:
1270 2 50         if ((res = build_SCT_buffer(SCT_params, &buffer, &buffer_size)) < 1) {
1271 0           croak("Error trying to build SCT buffer");
1272             } else {
1273 2           rc = matrixSslLoadSCTResponse(keys, buffer, buffer_size);
1274              
1275 2           psFreeNative(buffer);
1276              
1277 2 50         if (rc != PS_SUCCESS) {
1278 0           croak("Error %d while setting the SCT response");
1279             }
1280             }
1281              
1282 2           RETVAL = res;
1283              
1284             OUTPUT:
1285             RETVAL
1286              
1287              
1288             MODULE = Crypt::MatrixSSL3 PACKAGE = Crypt::MatrixSSL3::SessIDPtr PREFIX = sessid_
1289              
1290              
1291             Crypt_MatrixSSL3_SessID *sessid_new()
1292             INIT:
1293 110023           int rc = PS_SUCCESS;
1294 110023           sslSessionId_t *sessionId = NULL;
1295              
1296             CODE:
1297 110023           add_obj();
1298 110023           rc = matrixSslNewSessionId(&sessionId, NULL);
1299 110023 50         if (rc != PS_SUCCESS) {
1300             del_obj();
1301 0           croak("%d", rc);
1302             }
1303              
1304 110023           RETVAL = (Crypt_MatrixSSL3_SessID *)sessionId;
1305              
1306             OUTPUT:
1307             RETVAL
1308              
1309              
1310             void sessid_DESTROY(sessionId)
1311             Crypt_MatrixSSL3_SessID *sessionId;
1312              
1313             CODE:
1314 110023           matrixSslDeleteSessionId((sslSessionId_t *) sessionId);
1315             del_obj();
1316              
1317              
1318             void sessid_clear(sessionId)
1319             Crypt_MatrixSSL3_SessID *sessionId;
1320              
1321             CODE:
1322 1           matrixSslClearSessionId((sslSessionId_t *) sessionId);
1323              
1324              
1325             MODULE = Crypt::MatrixSSL3 PACKAGE = Crypt::MatrixSSL3::SessPtr PREFIX = sess_
1326              
1327              
1328             Crypt_MatrixSSL3_Sess *sess_new_client(keys, sessionId, cipherSuites, certValidator, expectedName, extensions, extensionCback)
1329             Crypt_MatrixSSL3_Keys *keys;
1330             Crypt_MatrixSSL3_SessID *sessionId;
1331             SV *cipherSuites;
1332             SV *certValidator;
1333             SV *expectedName;
1334             Crypt_MatrixSSL3_HelloExt * extensions;
1335             SV *extensionCback;
1336             ssl_t *ssl = NULL;
1337             SV *key = NULL;
1338             int rc = 0;
1339             uint8_t cipherCount = 0, i = 0;
1340             AV *cipherSuitesArray = NULL;
1341             SV **item = NULL;
1342              
1343             PREINIT:
1344             uint16_t cipherSuitesBuf[64];
1345              
1346             INIT:
1347 11156 50         if (SvROK(cipherSuites) && SvTYPE(SvRV(cipherSuites)) == SVt_PVAV) {
    0          
1348 0           cipherSuitesArray = (AV *) SvRV(cipherSuites);
1349              
1350 0           cipherCount = (uint16) av_len(cipherSuitesArray) + 1;
1351 0 0         if (cipherCount > 64)
1352 0           croak("cipherSuites should not contain more than 64 ciphers");
1353              
1354 0 0         for (i = 0; i < cipherCount; i++) {
1355 0           item = av_fetch(cipherSuitesArray, i, 0);
1356 0 0         cipherSuitesBuf[i] = (uint32) SvIV(*item);
1357             }
1358 11156 50         } else if (SvOK(cipherSuites)) {
    50          
    50          
1359 0           croak("cipherSuites should be undef or ARRAYREF");
1360             }
1361              
1362             CODE:
1363 11156           add_obj();
1364              
1365 11156           memset((void *) &sslOpts, 0, sizeof(sslSessOpts_t));
1366              
1367 34497 50         rc = matrixSslNewClientSession(&ssl,
    50          
    0          
    100          
1368             (sslKeys_t *) keys, (sslSessionId_t *) sessionId, cipherSuitesBuf, cipherCount,
1369 1029 50         (SvOK(certValidator) ? appCertValidator : NULL),
    50          
1370 11156 50         (SvOK(expectedName) ? (const char *) SvPV_nolen(expectedName) : NULL),
    50          
1371             (tlsExtension_t *) extensions,
1372 11156 50         (SvOK(extensionCback) ? appExtensionCback : NULL),
    50          
1373             &sslOpts);
1374              
1375 11156 50         if (rc != MATRIXSSL_REQUEST_SEND) {
1376             del_obj();
1377 0           croak("%d", rc);
1378             }
1379              
1380 11156           RETVAL = (Crypt_MatrixSSL3_Sess *)ssl;
1381              
1382 11156           ENTER;
1383 11156           SAVETMPS;
1384              
1385 11156           key = sv_2mortal(newSViv(PTR2IV(ssl)));
1386              
1387             /* keep real callback in global hash: $certValidatorArg{ssl}=certValidator */
1388 11156 100         if(SvOK(certValidator)) {
    50          
    50          
1389 10127 100         if(certValidatorArg==NULL)
1390 4           certValidatorArg = newHV();
1391 10127           hv_store_ent(certValidatorArg, key, SvREFCNT_inc(SvRV(certValidator)), 0);
1392             }
1393             /* keep real callback in global hash: $extensionCbackArg{ssl}=extensionCback */
1394 11156 50         if(SvOK(extensionCback)) {
    50          
    50          
1395 0 0         if(extensionCbackArg==NULL)
1396 0           extensionCbackArg = newHV();
1397 0           hv_store_ent(extensionCbackArg, key, SvREFCNT_inc(SvRV(extensionCback)), 0);
1398             }
1399              
1400 11156 50         FREETMPS;
1401 11156           LEAVE;
1402              
1403             OUTPUT:
1404             RETVAL
1405              
1406              
1407             Crypt_MatrixSSL3_Sess *sess_new_server(keys, certValidator)
1408             Crypt_MatrixSSL3_Keys *keys;
1409             SV *certValidator;
1410             ssl_t *ssl = NULL;
1411             SV *key = NULL;
1412             int rc = 0;
1413             p_SSL_data ssl_data = NULL;
1414              
1415             CODE:
1416 11158           add_obj();
1417              
1418 11158           memset((void *) &sslOpts, 0, sizeof(sslSessOpts_t));
1419              
1420 11158           ssl_data = malloc(SZ_SSL_DATA);
1421 11158           memset(ssl_data, 0, SZ_SSL_DATA);
1422              
1423 11158           sslOpts.userPtr = ssl_data;
1424              
1425 22316 50         rc = matrixSslNewServerSession(&ssl, (sslKeys_t *)keys,
1426 11158 50         (SvOK(certValidator) ? appCertValidator : NULL),
    50          
1427             &sslOpts);
1428             #ifdef MATRIX_DEBUG
1429             warn("new server: ssl = %p, ssl_data = %p", ssl, ssl_data);
1430             #endif
1431 11158 50         if (rc != PS_SUCCESS) {
1432             del_obj();
1433 0           croak("%d", rc);
1434             }
1435              
1436 11158           RETVAL = (Crypt_MatrixSSL3_Sess *)ssl;
1437              
1438 11158           ENTER;
1439 11158           SAVETMPS;
1440              
1441 11158           key = sv_2mortal(newSViv(PTR2IV(ssl)));
1442              
1443             /* keep real callback in global hash: $certValidatorArg{ssl}=certValidator */
1444 11158 50         if(SvOK(certValidator)) {
    50          
    50          
1445 0 0         if(certValidatorArg==NULL)
1446 0           certValidatorArg = newHV();
1447 0           hv_store_ent(certValidatorArg, key, SvREFCNT_inc(SvRV(certValidator)), 0);
1448             }
1449              
1450 11158 50         FREETMPS;
1451 11158           LEAVE;
1452              
1453             OUTPUT:
1454             RETVAL
1455              
1456             SV *get_SSL_secrets(ssl)
1457             Crypt_MatrixSSL3_Sess *ssl;
1458             HV *rh = NULL;
1459             sslSec_t *sec = NULL;
1460             const sslCipherSpec_t *cipher = NULL;
1461              
1462             CODE:
1463 0           rh = (HV *)sv_2mortal((SV *)newHV());
1464 0           sec = &(ssl->sec);
1465 0           cipher = ssl->cipher;
1466              
1467 0           my_hv_store(rh, "cipher_ident", newSViv(cipher->ident), 0);
1468 0           my_hv_store(rh, "cipher_type", newSViv(cipher->type), 0);
1469 0           my_hv_store(rh, "cipher_flags", newSViv(cipher->flags), 0);
1470 0           my_hv_store(rh, "cipher_macSize", newSViv(cipher->macSize), 0);
1471 0           my_hv_store(rh, "cipher_keySize", newSViv(cipher->keySize), 0);
1472 0           my_hv_store(rh, "cipher_ivSize", newSViv(cipher->ivSize), 0);
1473 0           my_hv_store(rh, "cipher_blockSize", newSViv(cipher->blockSize), 0);
1474              
1475 0           my_hv_store(rh, "clientRandom", newSVpvn(sec->clientRandom, SSL_HS_RANDOM_SIZE), 0);
1476 0           my_hv_store(rh, "serverRandom", newSVpvn(sec->serverRandom, SSL_HS_RANDOM_SIZE), 0);
1477 0           my_hv_store(rh, "masterSecret", newSVpvn(sec->masterSecret, SSL_HS_MASTER_SIZE), 0);
1478 0           my_hv_store(rh, "premaster", newSVpvn(sec->premaster, sec->premasterSize), 0);
1479              
1480 0           my_hv_store(rh, "writeMAC", newSVpvn(sec->writeMAC, cipher->macSize), 0);
1481 0           my_hv_store(rh, "readMAC", newSVpvn(sec->readMAC, cipher->macSize), 0);
1482 0           my_hv_store(rh, "writeKey", newSVpvn(sec->writeKey, cipher->keySize), 0);
1483 0           my_hv_store(rh, "readKey", newSVpvn(sec->readMAC, cipher->keySize), 0);
1484 0           my_hv_store(rh, "writeIV", newSVpvn(sec->writeIV, cipher->ivSize), 0);
1485 0           my_hv_store(rh, "readIV", newSVpvn(sec->readIV, cipher->ivSize), 0);
1486              
1487 0           RETVAL = newRV((SV *) rh);
1488              
1489             OUTPUT:
1490             RETVAL
1491              
1492             int sess_init_SNI(ssl, server_index, sni_data = NULL)
1493             Crypt_MatrixSSL3_Sess *ssl;
1494             int server_index = SvOK(ST(1)) ? SvIV(ST(1)) : -1;
1495             SV *sni_data;
1496             AV *sni_array = NULL;
1497             SV *sd_sv = NULL;
1498             HV *sd = NULL;
1499             HV *hitem = NULL;
1500             AV *aitem = NULL;
1501             SV *item_sv = NULL;
1502             SV *tmp_sv = NULL;
1503             unsigned char *buffer = NULL;
1504             int32 buffer_size = 0;
1505             unsigned char *item = NULL;
1506             SV *cert_sv = NULL;
1507             unsigned char *cert = NULL;
1508             SV *key_sv = NULL;
1509             unsigned char *key = NULL;
1510             SV *trustedCA_sv = NULL;
1511             unsigned char *trustedCA = NULL;
1512             STRLEN item_len = 0;
1513             int32 rc = PS_SUCCESS, i = 0, j = 0, res = 0;
1514             p_SSL_data ssl_data = NULL;
1515              
1516             PREINIT:
1517             unsigned char stk_id[16];
1518             unsigned char stk_ek[32];
1519 1           STRLEN stk_ek_len = 0;
1520             unsigned char stk_hk[32];
1521 1           STRLEN stk_hk_len = 0;
1522 1           t_SSL_server *ss = NULL;
1523             #ifndef WIN32
1524 1           int regex_res = 0;
1525             char regex_error[255];
1526             #endif
1527             CODE:
1528             #ifdef MATRIX_DEBUG
1529             warn("init_SNI: Setting up virtual hosts for SSL server %d", server_index);
1530             #endif
1531 1 50         if (server_index < 0)
1532 0           croak("Invalid SSL server index %d", server_index);
1533              
1534 1 50         if (server_index >= SSL_server_index)
1535 0           croak("Out of range SSL server index spcified: %d > %d", server_index, SSL_server_index - 1);
1536              
1537             /* set SSL server pointer */
1538 1           ss = SSL_servers[server_index];
1539              
1540 1 50         if (ss->SNI_entries_number > 0)
1541 0           croak("SNI already setup for SSL server %d", server_index);
1542              
1543             /* initialize SNI server structure */
1544 1 50         if (!(SvROK(sni_data) && SvTYPE(SvRV(sni_data)) == SVt_PVAV))
    50          
1545 0           croak("Expected SNI data to be an array reference");
1546              
1547             /* our array of arrays */
1548 1           sni_array = (AV *) SvRV(sni_data);
1549              
1550             /* get count */
1551 1           ss->SNI_entries_number = (uint16) av_len(sni_array) + 1;
1552             #ifdef MATRIX_DEBUG
1553             warn(" Got %d SNI entries", ss->SNI_entries_number);
1554             #endif
1555             /* check limits */
1556 1 50         if (ss->SNI_entries_number > MAX_SNI_ENTRIES)
1557 0           croak("Not enough room to load all SNI entries %d > %d", ss->SNI_entries_number, MAX_SNI_ENTRIES);
1558              
1559 2 100         for (i = 0; i < ss->SNI_entries_number; i++) {
1560             /* alocate memory for each SNI structure */
1561 1           ss->SNI_entries[i] = (t_SNI_entry *) malloc( sizeof(t_SNI_entry));
1562 1           memset(ss->SNI_entries[i], 0, sizeof(t_SNI_entry));
1563              
1564             /* get one array at the time */
1565 1           sd_sv = *av_fetch(sni_array, i, 0);
1566              
1567             /* make sure we have an array reference */
1568 1 50         if (!(SvROK(sd_sv) && SvTYPE(SvRV(sd_sv)) == SVt_PVHV))
    50          
1569 0           croak("Expected elements of SNI data to be hash references");
1570              
1571             /* get per host SNI data */
1572 1           sd = (HV *) SvRV(sd_sv);
1573              
1574             /* element 0 - hostname - we need to copy this in our structure */
1575 1 50         if (hv_exists(sd, "hostname", strlen("hostname"))) {
1576 1           item_sv = *hv_fetch(sd, "hostname", strlen("hostname"), 0);
1577 1 50         if (!SvOK(item_sv))
    0          
    0          
1578 0           croak("Hostname not specified in SNI entry %d", i);
1579              
1580 1 50         item = (unsigned char *) SvPV(item_sv , item_len);
1581             #ifdef MATRIX_DEBUG
1582             warn(" SNI entry %d Hostname = %s\n", i, item);
1583             #endif
1584             #ifdef WIN32
1585             if (item_len > 254) item_len = 254;
1586             memcpy(ss->SNI_entries[i]->hostname, item, item_len);
1587             ss->SNI_entries[i]->hostname[item_len] = 0;
1588             ss->SNI_entries[i]->hostnameLen = item_len;
1589             #else
1590 1           regex_res = regcomp(&(ss->SNI_entries[i]->regex_hostname), item, REG_EXTENDED | REG_ICASE | REG_NOSUB);
1591              
1592 1 50         if (regex_res != 0) {
1593 0           regerror(regex_res, &(ss->SNI_entries[i]->regex_hostname), regex_error, 255);
1594 0           croak("Error compiling hostname regex %s: %s", item, regex_error);
1595             }
1596             #endif
1597             } else
1598 0           croak("Hostname not specified in SNI entry %d", i);
1599              
1600 1 50         if (hv_exists(sd, "cert", strlen("cert")) && hv_exists(sd, "key", strlen("key"))) {
    50          
1601 1           cert_sv = *hv_fetch(sd, "cert", strlen("cert"), 0);
1602 1           key_sv = *hv_fetch(sd, "key", strlen("key"), 0);
1603              
1604             /* setup trusted CA certificate files if present */
1605 1 50         if (hv_exists(sd, "trustCA", strlen("trustCA"))) {
1606 0           trustedCA_sv = *hv_fetch(sd, "trustCA", strlen("trustCA"), 0);
1607              
1608 0 0         if (SvOK(trustedCA_sv)) {
    0          
    0          
1609 0 0         trustedCA = (unsigned char *) SvPV_nolen(trustedCA_sv);
1610             }
1611             }
1612              
1613 2 50         if (SvOK(cert_sv) && SvOK(key_sv)) {
    0          
    0          
    50          
    0          
    0          
1614 1 50         cert = (unsigned char *) SvPV_nolen(cert_sv);
1615 1 50         key = (unsigned char *) SvPV_nolen(key_sv);
1616             #ifdef MATRIX_DEBUG
1617             warn(" SNI entry %d cert %s; key %s", i, cert, key);
1618             #endif
1619 1           add_obj();
1620 1           rc = matrixSslNewKeys(&(ss->SNI_entries[i]->keys), NULL);
1621 1 50         if (rc != PS_SUCCESS) {
1622             del_obj();
1623 0           croak("SNI matrixSslNewKeys failed %d", rc);
1624             }
1625              
1626 1           rc = matrixSslLoadRsaKeys(ss->SNI_entries[i]->keys, cert, key, NULL, trustedCA);
1627 1 50         if (rc != PS_SUCCESS)
1628 0           croak("SNI matrixSslLoadRsaKeys failed %d; %s; %s", rc, cert, key);
1629             } else
1630 0           croak("Bad cert/key specified in SNI entry %d", i);
1631 0 0         } else if (hv_exists(sd, "ecc_cert", strlen("ecc_cert")) && hv_exists(sd, "ecc_key", strlen("ecc_key"))) {
    0          
1632 0           cert_sv = *hv_fetch(sd, "ecc_cert", strlen("ecc_cert"), 0);
1633 0           key_sv = *hv_fetch(sd, "ecc_key", strlen("ecc_key"), 0);
1634              
1635 0 0         if (SvOK(cert_sv) && SvOK(key_sv)) {
    0          
    0          
    0          
    0          
    0          
1636 0 0         cert = (unsigned char *) SvPV_nolen(cert_sv);
1637 0 0         key = (unsigned char *) SvPV_nolen(key_sv);
1638             #ifdef MATRIX_DEBUG
1639             warn(" SNI entry %d ecc_cert %s; ecc_key %s", i, cert, key);
1640             #endif
1641 0           add_obj();
1642 0           rc = matrixSslNewKeys(&(ss->SNI_entries[i]->keys), NULL);
1643 0 0         if (rc != PS_SUCCESS) {
1644             del_obj();
1645 0           croak("SNI matrixSslNewKeys failed %d", rc);
1646             }
1647              
1648 0           rc = matrixSslLoadEcKeys(ss->SNI_entries[i]->keys, cert, key, NULL, NULL);
1649 0 0         if (rc != PS_SUCCESS)
1650 0           croak("SNI matrixSslLoadEcKeys failed %d; %s; %s", rc, cert, key);
1651             } else
1652 0           croak("Bad ECC cert/key specified in SNI entry %d", i);
1653             } else
1654 0           croak("Missing [ECC] cert/key specified in SNI entry %d", i);
1655              
1656 1 50         if (hv_exists(sd, "DH_param", strlen("DH_param"))) {
1657 0           item_sv = *hv_fetch(sd, "DH_param", strlen("DH_param"), 0);
1658 0 0         if (!SvOK(item_sv))
    0          
    0          
1659 0           croak("undef DH param in SNI entry %d", i);
1660              
1661 0 0         item = (unsigned char *) SvPV_nolen(item_sv);
1662             #ifdef MATRIX_DEBUG
1663             warn(" SNI entry %d DH param %s", i, item);
1664             #endif
1665 0           rc = matrixSslLoadDhParams(ss->SNI_entries[i]->keys, item);
1666 0 0         if (rc != PS_SUCCESS)
1667 0           croak("SNI matrixSslLoadDhParams failed %d; %s", rc, item);
1668             }
1669              
1670 1 50         if (hv_exists(sd, "session_ticket_keys", strlen("session_ticket_keys"))) {
1671 1           hitem = (HV *) SvRV(*hv_fetch(sd, "session_ticket_keys", strlen("session_ticket_keys"), 0));
1672              
1673 3           if (!(hv_exists(hitem, "id", strlen("id")) &&
1674 1           hv_exists(hitem, "encrypt_key", strlen("encrypt_key")) &&
1675 1           hv_exists(hitem, "hash_key", strlen("hash_key"))))
1676 0           croak("id/encrypt_key/hash_key missing in session ticket for SNI entry %i", i);
1677              
1678 1           item_sv = *hv_fetch(hitem, "id", strlen("id"), 0);
1679 1 50         if (!SvOK(item_sv))
    0          
    0          
1680 0           croak("undef session tickets id in SNI structure %d", i);
1681              
1682 1 50         item = (unsigned char *) SvPV(item_sv, item_len);
1683             #ifdef MATRIX_DEBUG
1684             warn(" SNI entry %d session ticket ID %.16s", i, item);
1685             #endif
1686 1 50         if (item_len > 16) item_len = 16;
1687 1           memcpy(stk_id, item, item_len);
1688              
1689             /* get encryption key */
1690 1           item_sv = *hv_fetch(hitem, "encrypt_key", strlen("encrypt_key"), 0);
1691 1 50         if (!SvOK(item_sv))
    0          
    0          
1692 0           croak("undef sesion tickets encryption key in SNI structure %d", i);
1693              
1694 1 50         item = (unsigned char *) SvPV(item_sv, item_len);
1695 1 50         if (!((item_len == 16) || (item_len == 32)))
    50          
1696 0           croak("size of the encryption key in SNI structure %d must be 16/32. Now it is %d", i, item_len);
1697             #ifdef MATRIX_DEBUG
1698             warn(" SNI entry %d session ticket encryption key %.32s", i, item);
1699             #endif
1700 1           memcpy(stk_ek, item, item_len);
1701 1           stk_ek_len = item_len;
1702              
1703             /* hash key */
1704 1           item_sv = *hv_fetch(hitem, "hash_key", strlen("hash_key"), 0);
1705 1 50         if (!SvOK(item_sv))
    0          
    0          
1706 0           croak("undef hash key in SNI structure %d", i);
1707              
1708 1 50         item = (unsigned char *) SvPV(item_sv, item_len);
1709 1 50         if (item_len != 32)
1710 0           croak("size of the hash key in SNI structure %d must be 16/32. Now it is %d", i, item_len);
1711             #ifdef MATRIX_DEBUG
1712             warn(" SNI entry %d session ticket hash key %.32s", i, item);
1713             #endif
1714 1           memcpy(stk_hk, item, item_len);
1715 1           stk_hk_len = item_len;
1716              
1717 1           rc = matrixSslLoadSessionTicketKeys(ss->SNI_entries[i]->keys, stk_id, stk_ek, stk_ek_len, stk_hk, stk_hk_len);
1718 1 50         if (rc != PS_SUCCESS)
1719 0           croak("SNI matrixSslLoadSessionTicketKeys failed %d; %s; %s", rc, cert, key);
1720             }
1721              
1722             /* OCSP staple */
1723 1 50         if (hv_exists(sd, "OCSP_staple", strlen("OCSP_staple"))) {
1724 1           item_sv = *hv_fetch(sd, "OCSP_staple", strlen("OCSP_staple"), 0);
1725 1 50         if (!SvOK(item_sv))
    0          
    0          
1726 0           croak("undef OCSP_staple specified in SNI entry %d", i);
1727              
1728 1 50         item = (unsigned char *) SvPV_nolen(item_sv);
1729             #ifdef MATRIX_DEBUG
1730             warn(" SNI entry %d OCSP staple file %s", i, item);
1731             #endif
1732 1           rc = psGetFileBuf(NULL, item, &buffer, &buffer_size);
1733 1 50         if (rc != PS_SUCCESS)
1734 0           croak("SNI psGetFileBuf failed %d; %s", rc, item);
1735              
1736 1           rc = matrixSslLoadOCSPResponse(ss->SNI_entries[i]->keys, buffer, buffer_size);
1737              
1738 1 50         if (buffer != NULL) psFreeNative(buffer);
1739 1           buffer = NULL;
1740 1           buffer_size = 0;
1741              
1742 1 50         if (rc != PS_SUCCESS)
1743 0           croak("SNI matrixSslLoadOCSPResponse failed %d; %s", rc, item);
1744             }
1745              
1746             /* SCT params */
1747 1 50         if (hv_exists(sd, "SCT_params", strlen("SCT_params"))) {
1748 1           item_sv = *hv_fetch(sd, "SCT_params", strlen("SCT_params"), 0);
1749 1 50         if (!SvOK(item_sv))
    0          
    0          
1750 0           croak("undef SCT_params specified in SNI entry %d", i);
1751              
1752 1           res = build_SCT_buffer(item_sv, &buffer, &buffer_size);
1753             #ifdef MATRIX_DEBUG
1754             warn(" Read %d SCT files for SNI entry %d", res, i);
1755             #endif
1756 1 50         if (res < 1)
1757 0           croak("Failed to load SCT_params for SNI entry %d", i);
1758              
1759 1           rc = matrixSslLoadSCTResponse(ss->SNI_entries[i]->keys, buffer, buffer_size);
1760              
1761 1 50         if (buffer != NULL) psFreeNative(buffer);
1762 1           buffer = NULL;
1763 1           buffer_size = 0;
1764              
1765 1 50         if (rc != PS_SUCCESS)
1766 0           croak("SNI matrixSslLoadSCTResponse failed %d", rc);
1767             }
1768              
1769 1 50         if (hv_exists(sd, "ALPN", strlen("ALPN"))) {
1770 0           item_sv = *hv_fetch(sd, "ALPN", strlen("ALPN"), 0);
1771              
1772 0 0         if (!(SvROK(item_sv) && SvTYPE(SvRV(item_sv)) == SVt_PVAV))
    0          
1773 0           croak("Expected default server ALPN param to be an array reference");
1774              
1775 0           ss->SNI_entries[i]->alpn = (p_ALPN_data) malloc(SZ_ALPN_DATA);
1776 0           memset(ss->SNI_entries[i]->alpn, 0, SZ_ALPN_DATA);
1777              
1778 0           aitem = (AV *) SvRV(item_sv);
1779              
1780 0           ss->SNI_entries[i]->alpn->protoCount = (short) av_len(aitem) + 1;
1781 0 0         if (ss->SNI_entries[i]->alpn->protoCount > MAX_PROTO_EXT) ss->SNI_entries[i]->alpn->protoCount = MAX_PROTO_EXT;
1782              
1783 0 0         for (j = 0; j < ss->SNI_entries[i]->alpn->protoCount; j++) {
1784 0           tmp_sv = *av_fetch(aitem, j, 0);
1785 0 0         item = (unsigned char *) SvPV(tmp_sv, item_len);
1786              
1787 0           ss->SNI_entries[i]->alpn->proto[j] = (unsigned char *) malloc(item_len);
1788 0           memcpy(ss->SNI_entries[i]->alpn->proto[j], item, item_len);
1789 0           ss->SNI_entries[i]->alpn->protoLen[j] = item_len;
1790             }
1791             }
1792             }
1793              
1794 1           RETVAL = server_index;
1795              
1796             OUTPUT:
1797             RETVAL
1798              
1799              
1800             int sess_set_server_params(ssl, server_index, params = NULL)
1801             Crypt_MatrixSSL3_Sess *ssl;
1802             int server_index = SvOK(ST(1)) ? SvIV(ST(1)) : -1;
1803             SV *params;
1804             HV *hparams = NULL;
1805             HV *haux = NULL;
1806             AV *aaux = NULL;
1807             SV *item_sv = NULL;
1808             SV *tmp_sv = NULL;
1809             unsigned char *bufer = NULL;
1810             int32 buffer_size = 0;
1811             unsigned char *item = NULL;
1812             STRLEN item_len = 0;
1813             int i = 0, rc = PS_SUCCESS, ars = 0;
1814             p_SSL_server ss = NULL;
1815             p_SSL_data ssl_data = NULL;
1816             IV tmp = 0;
1817              
1818             CODE:
1819             #ifdef MATRIX_DEBUG
1820             warn("set_server_params: index %d", server_index);
1821             #endif
1822 1 50         if (server_index < 0)
1823 0           croak("Invalid SSL server index %d", server_index);
1824              
1825 1 50         if (server_index >= SSL_server_index)
1826 0           croak("Out of range SSL server index spcified: %d > %d", server_index, SSL_server_index - 1);
1827              
1828             /* set SSL server pointer */
1829 1           ss = SSL_servers[server_index];
1830              
1831             /* initialize default server structure */
1832 1 50         if (!(SvROK(params) && SvTYPE(SvRV(params)) == SVt_PVHV))
    50          
1833 0           croak("Expected default server params to be a hash reference");
1834              
1835 1           hparams = (HV *) SvRV(params);
1836              
1837 1 50         if (hv_exists(hparams, "keys", strlen("keys"))) {
1838 0           item_sv = *hv_fetch(hparams, "keys", strlen("keys"), 0);
1839 0 0         tmp = SvIV((SV*)SvRV(item_sv));
1840 0           ss->keys = INT2PTR(Crypt_MatrixSSL3_Keys *, tmp);
1841             }
1842              
1843 1 50         if (hv_exists(hparams, "ALPN", strlen("ALPN"))) {
1844 1           item_sv = *hv_fetch(hparams, "ALPN", strlen("ALPN"), 0);
1845              
1846 1 50         if (!(SvROK(item_sv) && SvTYPE(SvRV(item_sv)) == SVt_PVAV))
    50          
1847 0           croak("Expected default server ALPN param to be an array reference");
1848              
1849 1           ss->alpn = (p_ALPN_data) malloc(SZ_ALPN_DATA);
1850 1           memset(ss->alpn, 0, SZ_ALPN_DATA);
1851              
1852 1           aaux = (AV *) SvRV(item_sv);
1853              
1854 1           ss->alpn->protoCount = (short) av_len(aaux) + 1;
1855 1 50         if (ss->alpn->protoCount > MAX_PROTO_EXT) ss->alpn->protoCount = MAX_PROTO_EXT;
1856             #ifdef MATRIX_DEBUG
1857             warn("Loading %d protocols for SSL (default) server %d", ss->alpn->protoCount, server_index);
1858             #endif
1859 3 100         for (i = 0; i < ss->alpn->protoCount; i++) {
1860 2           tmp_sv = *av_fetch(aaux, i, 0);
1861 2 50         item = (unsigned char *) SvPV(tmp_sv, item_len);
1862             #ifdef MATRIX_DEBUG
1863             warn("Adding protocol for SSL (default) server %d: %s", server_index, item);
1864             #endif
1865 2           ss->alpn->proto[i] = (unsigned char *) malloc(item_len);
1866 2           memcpy(ss->alpn->proto[i], item, item_len);
1867 2           ss->alpn->protoLen[i] = item_len;
1868             }
1869             }
1870             #ifdef MATRIX_DEBUG
1871             warn("Returning SSL (default) server index: %d", server_index);
1872             #endif
1873 1           RETVAL = server_index;
1874              
1875             OUTPUT:
1876             RETVAL
1877              
1878              
1879             int sess_set_callbacks(ssl, server_index, ssl_id)
1880             Crypt_MatrixSSL3_Sess *ssl;
1881             int server_index = SvOK(ST(1)) ? SvIV(ST(1)) : -1;
1882             int ssl_id = SvOK(ST(2)) ? SvIV(ST(2)) : -1;
1883             p_SSL_data ssl_data = NULL;
1884             p_SSL_server ss = NULL;
1885              
1886             CODE:
1887             /* check if server_index points to a valid SSL server structure */
1888 0 0         if (server_index < 0)
1889 0           croak("Invalid SSL server index %d", server_index);
1890              
1891 0 0         if (server_index >= SSL_server_index)
1892 0           croak("Requested SSL server index out of range %d > %d", server_index, SSL_server_index - 1);
1893              
1894             /* just set the callback and we're done */
1895             #ifdef MATRIX_DEBUG
1896             warn("Setting up SNI/ALPN callbacks for SSL server %d, ssl_id = %d, %p", server_index, ssl_id, SSL_servers[server_index]);
1897             #endif
1898              
1899             /* set out SSL session custom data */
1900 0           ssl_data = (p_SSL_data) ssl->userPtr;
1901              
1902 0           ssl_data->ssl_id = ssl_id;
1903 0           ssl_data->server_index = server_index;
1904              
1905             /* get the SSL server strcuture */
1906 0           ss = SSL_servers[server_index];
1907              
1908             /* test if any visrtual hosts are present */
1909 0 0         if (ss->SNI_entries_number > 0) {
1910             /* setup SNI callback */
1911 0           matrixSslRegisterSNICallback(ssl, SNI_callback);
1912             /* setup ALPN callback */
1913 0           matrixSslRegisterALPNCallback(ssl, ALPNCallbackXS);
1914             } else {
1915             /* no virtual hosts, setup ALPN callback only if server has defined protocols */
1916 0 0         if (ss->alpn != NULL) matrixSslRegisterALPNCallback(ssl, ALPNCallbackXS);
1917             }
1918              
1919 0           RETVAL = server_index;
1920              
1921             OUTPUT:
1922             RETVAL
1923              
1924              
1925             void sess_DESTROY(ssl)
1926             Crypt_MatrixSSL3_Sess *ssl;
1927             SV *key = NULL;
1928              
1929             CODE:
1930 22314           ENTER;
1931 22314           SAVETMPS;
1932              
1933             /* delete callback from global hashes */
1934 22314           key = sv_2mortal(newSViv(PTR2IV(ssl)));
1935 22314 100         if(hv_exists_ent(certValidatorArg, key, 0))
1936 10126           hv_delete_ent(certValidatorArg, key, G_DISCARD, 0);
1937 22314 50         if(hv_exists_ent(extensionCbackArg, key, 0))
1938 0           hv_delete_ent(extensionCbackArg, key, G_DISCARD, 0);
1939              
1940 22314 50         FREETMPS;
1941 22314           LEAVE;
1942              
1943 22314 100         if (((ssl_t *) ssl)->userPtr != NULL) free(((ssl_t *) ssl)->userPtr);
1944 22314           matrixSslDeleteSession((ssl_t *) ssl);
1945             del_obj();
1946              
1947              
1948             int sess_get_outdata(ssl, outBuf)
1949             Crypt_MatrixSSL3_Sess *ssl;
1950             SV *outBuf;
1951             unsigned char *buf = NULL;
1952              
1953             CODE:
1954 11841           RETVAL = matrixSslGetOutdata((ssl_t *)ssl, &buf);
1955 11841 50         if (RETVAL < 0)
1956 0           croak("matrixSslGetOutdata returns %d", RETVAL);
1957             /* append answer to the output */
1958 11841 100         if (RETVAL > 0)
1959 6568           sv_catpvn_mg(outBuf, (const char *) buf, RETVAL);
1960              
1961             OUTPUT:
1962             RETVAL
1963              
1964              
1965             int sess_sent_data(ssl, bytes)
1966             Crypt_MatrixSSL3_Sess *ssl;
1967             int bytes;
1968              
1969             CODE:
1970 6568           RETVAL = matrixSslSentData((ssl_t *)ssl, bytes);
1971              
1972             OUTPUT:
1973             RETVAL
1974              
1975              
1976             int sess_received_data(ssl, inBuf, ptBuf)
1977             Crypt_MatrixSSL3_Sess *ssl;
1978             SV *inBuf;
1979             SV *ptBuf;
1980             unsigned char *readbuf = NULL;
1981             unsigned char *buf = NULL;
1982             STRLEN inbufsz = 0;
1983             unsigned int bufsz = 0;
1984             int32 readbufsz = 0;
1985              
1986             CODE:
1987 9678           readbufsz = matrixSslGetReadbuf((ssl_t *)ssl, &readbuf);
1988 9678 50         if (readbufsz < 0) {
1989             /* 0 isn't an error, but shouldn't happens anyway */
1990             /* when readbufsz == 0 the matrixSslReceivedData call below acts like a polling machanism
1991             useful for client which use false start */
1992 0           croak("matrixSslGetReadbuf returns %d", readbufsz);
1993             }
1994              
1995 9678 50         buf = (unsigned char *) SvPV(inBuf, inbufsz);
1996 9678 100         if((STRLEN) readbufsz > inbufsz)
1997 5546           readbufsz = inbufsz;
1998 9678           memcpy(readbuf, buf, readbufsz);
1999             /* remove from the input whatever got processed */
2000 9678           sv_setpvn_mg(inBuf, (const char *) buf+readbufsz, inbufsz-readbufsz);
2001 9678           buf = NULL;
2002              
2003 9678           RETVAL = matrixSslReceivedData((ssl_t *)ssl, readbufsz, &buf, (uint32 *) &bufsz);
2004 9678 100         sv_setpvn_mg(ptBuf, (const char *) buf, (buf==NULL ? 0 : bufsz));
2005              
2006             OUTPUT:
2007             RETVAL
2008              
2009              
2010             int sess_false_start_received_data(ssl, ptBuf)
2011             Crypt_MatrixSSL3_Sess *ssl;
2012             SV *ptBuf;
2013             unsigned char *buf = NULL;
2014             unsigned int bufsz = 0;
2015              
2016             CODE:
2017 0           RETVAL = matrixSslReceivedData((ssl_t *)ssl, 0, &buf, (uint32 *) &bufsz);
2018 0 0         if (RETVAL > 0) sv_setpvn_mg(ptBuf, (const char *) buf, (buf==NULL ? 0 : bufsz));
    0          
2019              
2020             OUTPUT:
2021             RETVAL
2022              
2023              
2024             int sess_processed_data(ssl, ptBuf)
2025             Crypt_MatrixSSL3_Sess *ssl;
2026             SV *ptBuf;
2027             unsigned char *buf = NULL;
2028             unsigned int bufsz = 0;
2029              
2030             CODE:
2031 4123           RETVAL = matrixSslProcessedData((ssl_t *)ssl, &buf, (uint32 *) &bufsz);
2032 4123 100         sv_setpvn_mg(ptBuf, (const char *) buf, (buf==NULL ? 0 : bufsz));
2033              
2034             OUTPUT:
2035             RETVAL
2036              
2037              
2038             int sess_encode_to_outdata(ssl, outBuf)
2039             Crypt_MatrixSSL3_Sess *ssl;
2040             SV *outBuf;
2041             unsigned char *buf = NULL;
2042             STRLEN bufsz = 0;
2043              
2044             CODE:
2045 4126 50         buf = (unsigned char *) SvPV(outBuf, bufsz);
2046 4126           RETVAL = matrixSslEncodeToOutdata((ssl_t *)ssl, buf, bufsz);
2047              
2048             OUTPUT:
2049             RETVAL
2050              
2051              
2052             int sess_get_anon_status(ssl)
2053             Crypt_MatrixSSL3_Sess *ssl;
2054             int32 anon = 0;
2055              
2056             CODE:
2057 2           matrixSslGetAnonStatus((ssl_t *)ssl, &anon);
2058 2           RETVAL = (int) anon;
2059              
2060             OUTPUT:
2061             RETVAL
2062              
2063              
2064             int sess_set_cipher_suite_enabled_status(ssl, cipherId, status);
2065             Crypt_MatrixSSL3_Sess *ssl;
2066             short cipherId;
2067             int status;
2068              
2069             CODE:
2070 6           RETVAL = matrixSslSetCipherSuiteEnabledStatus((ssl_t *)ssl, cipherId, status);
2071              
2072             OUTPUT:
2073             RETVAL
2074              
2075              
2076             int sess_encode_closure_alert(ssl)
2077             Crypt_MatrixSSL3_Sess *ssl;
2078              
2079             CODE:
2080 1           RETVAL = matrixSslEncodeClosureAlert((ssl_t *)ssl);
2081              
2082             OUTPUT:
2083             RETVAL
2084              
2085              
2086             int sess_encode_rehandshake(ssl, keys, certValidator, sessionOption, cipherSpecs)
2087             Crypt_MatrixSSL3_Sess *ssl;
2088             Crypt_MatrixSSL3_Keys *keys;
2089             SV *certValidator;
2090             int sessionOption;
2091             SV *cipherSpecs;
2092             SV *key = NULL;
2093             uint8_t cipherCount = 0, i = 0;
2094             AV *cipherSpecsArray = NULL;
2095             SV **item = NULL;
2096              
2097             PREINIT:
2098             uint16_t cipherSpecsBuf[64];
2099              
2100             INIT:
2101 10 100         if (SvROK(cipherSpecs) && SvTYPE(SvRV(cipherSpecs)) == SVt_PVAV) {
    50          
2102 2           cipherSpecsArray = (AV *) SvRV(cipherSpecs);
2103              
2104 2           cipherCount = (uint16) av_len(cipherSpecsArray) + 1;
2105 2 50         if (cipherCount > 64)
2106 0           croak("cipherSuites should not contain more than 64 ciphers");
2107              
2108 4 100         for (i = 0; i < cipherCount; i++) {
2109 2           item = av_fetch(cipherSpecsArray, i, 0);
2110 2 50         cipherSpecsBuf[i] = (uint32) SvIV(*item);
2111             }
2112 6 50         } else if (SvOK(cipherSpecs)) {
    50          
    50          
2113 0           croak("cipherSpecs should be undef or ARRAYREF");
2114             }
2115              
2116             CODE:
2117 14 100         RETVAL = matrixSslEncodeRehandshake((ssl_t *)ssl, (sslKeys_t *)keys,
2118 6 50         (SvOK(certValidator) ? appCertValidator : NULL),
    50          
2119             sessionOption, cipherSpecsBuf, cipherCount);
2120              
2121 8           ENTER;
2122 8           SAVETMPS;
2123              
2124             /* keep real callback in global hash: $certValidatorArg{ssl}=certValidator */
2125 8           key = sv_2mortal(newSViv(PTR2IV(ssl)));
2126 8 100         if(certValidatorArg==NULL)
2127 1           certValidatorArg = newHV();
2128 8 100         if(hv_exists_ent(certValidatorArg, key, 0))
2129 3           hv_delete_ent(certValidatorArg, key, G_DISCARD, 0); /* delete old callback */
2130 8 100         if(SvOK(certValidator))
    50          
    50          
2131 2           hv_store_ent(certValidatorArg, key, SvREFCNT_inc(SvRV(certValidator)), 0);
2132              
2133 8 50         FREETMPS;
2134 8           LEAVE;
2135              
2136             OUTPUT:
2137             RETVAL
2138              
2139              
2140             MODULE = Crypt::MatrixSSL3 PACKAGE = Crypt::MatrixSSL3::HelloExtPtr PREFIX = helloext_
2141              
2142              
2143             Crypt_MatrixSSL3_HelloExt *helloext_new()
2144             INIT:
2145             tlsExtension_t *extension;
2146             int rc;
2147              
2148             CODE:
2149 0           add_obj();
2150 0           rc = matrixSslNewHelloExtension(&extension, NULL);
2151 0 0         if (rc != PS_SUCCESS) {
2152             del_obj();
2153 0           croak("%d", rc);
2154             }
2155              
2156 0           RETVAL = (Crypt_MatrixSSL3_HelloExt *)extension;
2157              
2158             OUTPUT:
2159             RETVAL
2160              
2161              
2162             void helloext_DESTROY(extension)
2163             Crypt_MatrixSSL3_HelloExt *extension;
2164              
2165             CODE:
2166 0           matrixSslDeleteHelloExtension((tlsExtension_t *)extension);
2167             del_obj();
2168              
2169              
2170             int helloext_load(extension, ext, extType)
2171             Crypt_MatrixSSL3_HelloExt *extension;
2172             SV *ext;
2173             int extType;
2174             unsigned char *extData = NULL;
2175             STRLEN extLen = 0;
2176              
2177             CODE:
2178 0 0         extData = (unsigned char *) SvPV(ext, extLen);
2179 0           RETVAL = matrixSslLoadHelloExtension((tlsExtension_t *)extension, extData, extLen, extType);
2180              
2181             OUTPUT:
2182             RETVAL