]>
Commit | Line | Data |
---|---|---|
2cb4b5f6 MC |
1 | /* |
2 | * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. | |
3 | * | |
4 | * Licensed under the OpenSSL license (the "License"). You may not use | |
5 | * this file except in compliance with the License. You can obtain a copy | |
6 | * in the file LICENSE in the source distribution or at | |
7 | * https://www.openssl.org/source/license.html | |
8 | */ | |
9 | ||
10 | #include "ssltestlib.h" | |
11 | ||
12 | int create_ssl_ctx_pair(const SSL_METHOD *sm, const SSL_METHOD *cm, | |
13 | SSL_CTX **sctx, SSL_CTX **cctx, char *certfile, | |
14 | char *privkeyfile) | |
15 | { | |
16 | SSL_CTX *serverctx = NULL; | |
17 | SSL_CTX *clientctx = NULL; | |
18 | ||
fe964f0c MC |
19 | serverctx = SSL_CTX_new(sm); |
20 | clientctx = SSL_CTX_new(cm); | |
2cb4b5f6 MC |
21 | if (serverctx == NULL || clientctx == NULL) { |
22 | printf("Failed to create SSL_CTX\n"); | |
23 | goto err; | |
24 | } | |
25 | ||
26 | if (SSL_CTX_use_certificate_file(serverctx, certfile, | |
27 | SSL_FILETYPE_PEM) <= 0) { | |
28 | printf("Failed to load server certificate\n"); | |
29 | goto err; | |
30 | } | |
31 | if (SSL_CTX_use_PrivateKey_file(serverctx, privkeyfile, | |
32 | SSL_FILETYPE_PEM) <= 0) { | |
33 | printf("Failed to load server private key\n"); | |
34 | } | |
35 | if (SSL_CTX_check_private_key(serverctx) <= 0) { | |
36 | printf("Failed to check private key\n"); | |
37 | goto err; | |
38 | } | |
39 | ||
40 | *sctx = serverctx; | |
41 | *cctx = clientctx; | |
42 | ||
43 | return 1; | |
44 | err: | |
45 | SSL_CTX_free(serverctx); | |
46 | SSL_CTX_free(clientctx); | |
47 | return 0; | |
48 | } | |
49 | ||
50 | #define MAXLOOPS 100000 | |
51 | ||
52 | /* | |
53 | * NOTE: Transfers control of the BIOs - this function will free them on error | |
54 | */ | |
55 | int create_ssl_connection(SSL_CTX *serverctx, SSL_CTX *clientctx, SSL **sssl, | |
56 | SSL **cssl, BIO *s_to_c_fbio, BIO *c_to_s_fbio) | |
57 | { | |
58 | int retc = -1, rets = -1, err, abortctr = 0; | |
eaa776da | 59 | int clienterr = 0, servererr = 0; |
2cb4b5f6 MC |
60 | SSL *serverssl, *clientssl; |
61 | BIO *s_to_c_bio = NULL, *c_to_s_bio = NULL; | |
62 | ||
eaa776da MC |
63 | if (*sssl == NULL) |
64 | serverssl = SSL_new(serverctx); | |
65 | else | |
66 | serverssl = *sssl; | |
67 | if (*cssl == NULL) | |
68 | clientssl = SSL_new(clientctx); | |
69 | else | |
70 | clientssl = *cssl; | |
2cb4b5f6 MC |
71 | |
72 | if (serverssl == NULL || clientssl == NULL) { | |
73 | printf("Failed to create SSL object\n"); | |
74 | goto error; | |
75 | } | |
76 | ||
77 | s_to_c_bio = BIO_new(BIO_s_mem()); | |
78 | c_to_s_bio = BIO_new(BIO_s_mem()); | |
79 | if (s_to_c_bio == NULL || c_to_s_bio == NULL) { | |
80 | printf("Failed to create mem BIOs\n"); | |
81 | goto error; | |
82 | } | |
83 | ||
84 | if (s_to_c_fbio != NULL) | |
85 | s_to_c_bio = BIO_push(s_to_c_fbio, s_to_c_bio); | |
86 | if (c_to_s_fbio != NULL) | |
87 | c_to_s_bio = BIO_push(c_to_s_fbio, c_to_s_bio); | |
88 | if (s_to_c_bio == NULL || c_to_s_bio == NULL) { | |
89 | printf("Failed to create chained BIOs\n"); | |
90 | goto error; | |
91 | } | |
92 | ||
93 | /* Set Non-blocking IO behaviour */ | |
94 | BIO_set_mem_eof_return(s_to_c_bio, -1); | |
95 | BIO_set_mem_eof_return(c_to_s_bio, -1); | |
96 | ||
97 | /* Up ref these as we are passing them to two SSL objects */ | |
98 | BIO_up_ref(s_to_c_bio); | |
99 | BIO_up_ref(c_to_s_bio); | |
100 | ||
101 | SSL_set_bio(serverssl, c_to_s_bio, s_to_c_bio); | |
102 | SSL_set_bio(clientssl, s_to_c_bio, c_to_s_bio); | |
103 | ||
104 | /* BIOs will now be freed when SSL objects are freed */ | |
105 | s_to_c_bio = c_to_s_bio = NULL; | |
106 | s_to_c_fbio = c_to_s_fbio = NULL; | |
107 | ||
108 | do { | |
109 | err = SSL_ERROR_WANT_WRITE; | |
eaa776da | 110 | while (!clienterr && retc <= 0 && err == SSL_ERROR_WANT_WRITE) { |
2cb4b5f6 MC |
111 | retc = SSL_connect(clientssl); |
112 | if (retc <= 0) | |
113 | err = SSL_get_error(clientssl, retc); | |
114 | } | |
115 | ||
eaa776da | 116 | if (!clienterr && retc <= 0 && err != SSL_ERROR_WANT_READ) { |
2cb4b5f6 | 117 | printf("SSL_connect() failed %d, %d\n", retc, err); |
eaa776da | 118 | clienterr = 1; |
2cb4b5f6 MC |
119 | } |
120 | ||
121 | err = SSL_ERROR_WANT_WRITE; | |
eaa776da | 122 | while (!servererr && rets <= 0 && err == SSL_ERROR_WANT_WRITE) { |
2cb4b5f6 MC |
123 | rets = SSL_accept(serverssl); |
124 | if (rets <= 0) | |
125 | err = SSL_get_error(serverssl, rets); | |
126 | } | |
127 | ||
eaa776da | 128 | if (!servererr && rets <= 0 && err != SSL_ERROR_WANT_READ) { |
2cb4b5f6 | 129 | printf("SSL_accept() failed %d, %d\n", retc, err); |
eaa776da | 130 | servererr = 1; |
2cb4b5f6 | 131 | } |
eaa776da MC |
132 | if (clienterr && servererr) |
133 | goto error; | |
2cb4b5f6 MC |
134 | if (++abortctr == MAXLOOPS) { |
135 | printf("No progress made\n"); | |
136 | goto error; | |
137 | } | |
138 | } while (retc <=0 || rets <= 0); | |
139 | ||
140 | *sssl = serverssl; | |
141 | *cssl = clientssl; | |
142 | ||
143 | return 1; | |
144 | ||
145 | error: | |
eaa776da MC |
146 | if (*sssl == NULL) { |
147 | SSL_free(serverssl); | |
148 | BIO_free(s_to_c_bio); | |
149 | BIO_free(s_to_c_fbio); | |
150 | } | |
151 | if (*cssl == NULL) { | |
152 | SSL_free(clientssl); | |
153 | BIO_free(c_to_s_bio); | |
154 | BIO_free(c_to_s_fbio); | |
155 | } | |
2cb4b5f6 MC |
156 | |
157 | return 0; | |
158 | } |