2 * SSL client with certificate authentication
4 * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
6 * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
14 * * Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * * Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * * Neither the names of PolarSSL or XySSL nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 #ifndef _CRT_SECURE_NO_DEPRECATE
37 #define _CRT_SECURE_NO_DEPRECATE 1
43 #include "tropicssl/net.h"
44 #include "tropicssl/ssl.h"
45 #include "tropicssl/havege.h"
46 #include "tropicssl/certs.h"
47 #include "tropicssl/x509.h"
49 #define SERVER_PORT 443
51 #define SERVER_NAME "localhost"
52 #define GET_REQUEST "GET / HTTP/1.0\r\n\r\n"
54 #define SERVER_NAME "tropicssl.org"
56 "GET /hello/ HTTP/1.1\r\n" \
57 "Host: tropicssl.org\r\n\r\n"
61 static void my_debug(void *ctx
, int level
, const char *str
)
63 if (level
< DEBUG_LEVEL
) {
64 fprintf((FILE *) ctx
, "%s", str
);
71 int ret
, len
, server_fd
;
72 unsigned char buf
[1024];
81 * 0. Initialize the RNG and the session data
84 memset(&ssn
, 0, sizeof(ssl_session
));
87 * 1.1. Load the trusted CA
89 printf("\n . Loading the CA root certificate ...");
92 memset(&cacert
, 0, sizeof(x509_cert
));
95 * Alternatively, you may load the CA certificates from a .pem or
96 * .crt file by calling x509parse_crtfile( &cacert, "myca.crt" ).
98 ret
= x509parse_crt(&cacert
, (const unsigned char *)xyssl_ca_crt
,
99 strlen(xyssl_ca_crt
));
101 printf(" failed\n ! x509parse_crt returned %d\n\n", ret
);
108 * 1.2. Load own certificate and private key
110 * (can be skipped if client authentication is not required)
112 printf(" . Loading the client cert. and key...");
115 memset(&clicert
, 0, sizeof(x509_cert
));
117 ret
= x509parse_crt(&clicert
, (const unsigned char *)test_cli_crt
,
118 strlen(test_cli_crt
));
120 printf(" failed\n ! x509parse_crt returned %d\n\n", ret
);
124 ret
= x509parse_key(&rsa
, (const unsigned char *)test_cli_key
,
125 strlen(test_cli_key
), NULL
, 0);
127 printf(" failed\n ! x509parse_key returned %d\n\n", ret
);
134 * 2. Start the connection
136 printf(" . Connecting to tcp/%s/%-4d...", SERVER_NAME
, SERVER_PORT
);
139 if ((ret
= net_connect(&server_fd
, SERVER_NAME
, SERVER_PORT
)) != 0) {
140 printf(" failed\n ! net_connect returned %d\n\n", ret
);
149 printf(" . Setting up the SSL/TLS structure...");
154 if ((ret
= ssl_init(&ssl
)) != 0) {
155 printf(" failed\n ! ssl_init returned %d\n\n", ret
);
161 ssl_set_endpoint(&ssl
, SSL_IS_CLIENT
);
162 ssl_set_authmode(&ssl
, SSL_VERIFY_OPTIONAL
);
164 ssl_set_rng(&ssl
, havege_rand
, &hs
);
165 ssl_set_dbg(&ssl
, my_debug
, stdout
);
166 ssl_set_bio(&ssl
, net_recv
, &server_fd
, net_send
, &server_fd
);
168 ssl_set_ciphers(&ssl
, ssl_default_ciphers
);
169 ssl_set_session(&ssl
, 1, 600, &ssn
);
171 ssl_set_ca_chain(&ssl
, &cacert
, SERVER_NAME
);
172 ssl_set_own_cert(&ssl
, &clicert
, &rsa
);
174 ssl_set_hostname(&ssl
, SERVER_NAME
);
179 printf(" . Performing the SSL/TLS handshake...");
182 while ((ret
= ssl_handshake(&ssl
)) != 0) {
183 if (ret
!= TROPICSSL_ERR_NET_TRY_AGAIN
) {
184 printf(" failed\n ! ssl_handshake returned %d\n\n",
190 printf(" ok\n [ Cipher is %s ]\n", ssl_get_cipher(&ssl
));
193 * 5. Verify the server certificate
195 printf(" . Verifying peer X.509 certificate...");
197 if ((ret
= ssl_get_verify_result(&ssl
)) != 0) {
200 if ((ret
& BADCERT_EXPIRED
) != 0)
201 printf(" ! server certificate has expired\n");
203 if ((ret
& BADCERT_REVOKED
) != 0)
204 printf(" ! server certificate has been revoked\n");
206 if ((ret
& BADCERT_CN_MISMATCH
) != 0)
207 printf(" ! CN mismatch (expected CN=%s)\n",
210 if ((ret
& BADCERT_NOT_TRUSTED
) != 0)
212 (" ! self-signed or not signed by a trusted CA\n");
218 printf(" . Peer certificate information ...\n");
219 x509parse_cert_info((char *) buf
, sizeof( buf
) - 1,
224 * 6. Write the GET request
226 printf(" > Write to server:");
229 len
= sprintf((char *)buf
, GET_REQUEST
);
231 while ((ret
= ssl_write(&ssl
, buf
, len
)) <= 0) {
232 if (ret
!= TROPICSSL_ERR_NET_TRY_AGAIN
) {
233 printf(" failed\n ! ssl_write returned %d\n\n", ret
);
239 printf(" %d bytes written\n\n%s", len
, (char *)buf
);
242 * 7. Read the HTTP response
244 printf(" < Read from server:");
248 len
= sizeof(buf
) - 1;
249 memset(buf
, 0, sizeof(buf
));
250 ret
= ssl_read(&ssl
, buf
, len
);
252 if (ret
== TROPICSSL_ERR_NET_TRY_AGAIN
)
255 if (ret
== TROPICSSL_ERR_SSL_PEER_CLOSE_NOTIFY
)
259 printf("failed\n ! ssl_read returned %d\n\n", ret
);
264 printf(" %d bytes read\n\n%s", len
, (char *)buf
);
268 ssl_close_notify(&ssl
);
272 net_close(server_fd
);
278 memset(&ssl
, 0, sizeof(ssl
));
281 printf(" + Press Enter to exit this program.\n");