bignum: make mpi_init() and mpi_free() accept a single argument
[tropicssl.git] / programs / ssl / ssl_client2.c
blobd2556a43135fb706041f37662976d476725a542f
1 /*
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>
8 * All rights reserved.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
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
38 #endif
40 #include <string.h>
41 #include <stdio.h>
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"
55 #define GET_REQUEST \
56 "GET /hello/ HTTP/1.1\r\n" \
57 "Host: tropicssl.org\r\n\r\n"
59 #define DEBUG_LEVEL 0
61 static void my_debug(void *ctx, int level, const char *str)
63 if (level < DEBUG_LEVEL) {
64 fprintf((FILE *) ctx, "%s", str);
65 fflush((FILE *) ctx);
69 int main(void)
71 int ret, len, server_fd = -1;
72 unsigned char buf[1024];
73 havege_state hs;
74 ssl_context ssl;
75 ssl_session ssn;
76 x509_cert cacert;
77 x509_cert clicert;
78 rsa_context rsa;
81 * 0. Initialize the RNG and the session data
83 havege_init(&hs);
84 memset(&ssl, 0, sizeof(ssl));
85 memset(&ssn, 0, sizeof(ssl_session));
86 memset(&cacert, 0, sizeof(x509_cert));
87 memset(&clicert, 0, sizeof(x509_cert));
88 memset(&rsa, 0, sizeof(rsa_context));
91 * 1.1. Load the trusted CA
93 printf("\n . Loading the CA root certificate ...");
94 fflush(stdout);
98 * Alternatively, you may load the CA certificates from a .pem or
99 * .crt file by calling x509parse_crtfile( &cacert, "myca.crt" ).
101 ret = x509parse_crt(&cacert, (const unsigned char *)xyssl_ca_crt,
102 strlen(xyssl_ca_crt));
103 if (ret != 0) {
104 printf(" failed\n ! x509parse_crt returned %d\n\n", ret);
105 goto exit;
108 printf(" ok\n");
111 * 1.2. Load own certificate and private key
113 * (can be skipped if client authentication is not required)
115 printf(" . Loading the client cert. and key...");
116 fflush(stdout);
118 ret = x509parse_crt(&clicert, (const unsigned char *)test_cli_crt,
119 strlen(test_cli_crt));
120 if (ret != 0) {
121 printf(" failed\n ! x509parse_crt returned %d\n\n", ret);
122 goto exit;
125 ret = x509parse_key(&rsa, (const unsigned char *)test_cli_key,
126 strlen(test_cli_key), NULL, 0);
127 if (ret != 0) {
128 printf(" failed\n ! x509parse_key returned %d\n\n", ret);
129 goto exit;
132 printf(" ok\n");
135 * 2. Start the connection
137 printf(" . Connecting to tcp/%s/%-4d...", SERVER_NAME, SERVER_PORT);
138 fflush(stdout);
140 if ((ret = net_connect(&server_fd, SERVER_NAME, SERVER_PORT)) != 0) {
141 printf(" failed\n ! net_connect returned %d\n\n", ret);
142 goto exit;
145 printf(" ok\n");
148 * 3. Setup stuff
150 printf(" . Setting up the SSL/TLS structure...");
151 fflush(stdout);
153 havege_init(&hs);
155 if ((ret = ssl_init(&ssl)) != 0) {
156 printf(" failed\n ! ssl_init returned %d\n\n", ret);
157 goto exit;
160 printf(" ok\n");
162 ssl_set_endpoint(&ssl, SSL_IS_CLIENT);
163 ssl_set_authmode(&ssl, SSL_VERIFY_OPTIONAL);
165 ssl_set_rng(&ssl, havege_rand, &hs);
166 ssl_set_dbg(&ssl, my_debug, stdout);
167 ssl_set_bio(&ssl, net_recv, &server_fd, net_send, &server_fd);
169 ssl_set_ciphers(&ssl, ssl_default_ciphers);
170 ssl_set_session(&ssl, 1, 600, &ssn);
172 ssl_set_ca_chain(&ssl, &cacert, SERVER_NAME);
173 ssl_set_own_cert(&ssl, &clicert, &rsa);
175 ssl_set_hostname(&ssl, SERVER_NAME);
178 * 4. Handshake
180 printf(" . Performing the SSL/TLS handshake...");
181 fflush(stdout);
183 while ((ret = ssl_handshake(&ssl)) != 0) {
184 if (ret != TROPICSSL_ERR_NET_TRY_AGAIN) {
185 printf(" failed\n ! ssl_handshake returned %d\n\n",
186 ret);
187 goto exit;
191 printf(" ok\n [ Cipher is %s ]\n", ssl_get_cipher(&ssl));
194 * 5. Verify the server certificate
196 printf(" . Verifying peer X.509 certificate...");
198 if ((ret = ssl_get_verify_result(&ssl)) != 0) {
199 printf(" failed\n");
201 if ((ret & BADCERT_EXPIRED) != 0)
202 printf(" ! server certificate has expired\n");
204 if ((ret & BADCERT_REVOKED) != 0)
205 printf(" ! server certificate has been revoked\n");
207 if ((ret & BADCERT_CN_MISMATCH) != 0)
208 printf(" ! CN mismatch (expected CN=%s)\n",
209 SERVER_NAME);
211 if ((ret & BADCERT_NOT_TRUSTED) != 0)
212 printf
213 (" ! self-signed or not signed by a trusted CA\n");
215 printf("\n");
216 } else
217 printf(" ok\n");
219 printf(" . Peer certificate information ...\n");
220 x509parse_cert_info((char *) buf, sizeof( buf ) - 1,
221 " ", ssl.peer_cert);
222 printf("%s", buf);
225 * 6. Write the GET request
227 printf(" > Write to server:");
228 fflush(stdout);
230 len = sprintf((char *)buf, GET_REQUEST);
232 while ((ret = ssl_write(&ssl, buf, len)) <= 0) {
233 if (ret != TROPICSSL_ERR_NET_TRY_AGAIN) {
234 printf(" failed\n ! ssl_write returned %d\n\n", ret);
235 goto exit;
239 len = ret;
240 printf(" %d bytes written\n\n%s", len, (char *)buf);
243 * 7. Read the HTTP response
245 printf(" < Read from server:");
246 fflush(stdout);
248 do {
249 len = sizeof(buf) - 1;
250 memset(buf, 0, sizeof(buf));
251 ret = ssl_read(&ssl, buf, len);
253 if (ret == TROPICSSL_ERR_NET_TRY_AGAIN)
254 continue;
256 if (ret == TROPICSSL_ERR_SSL_PEER_CLOSE_NOTIFY)
257 break;
259 if (ret <= 0) {
260 printf("failed\n ! ssl_read returned %d\n\n", ret);
261 break;
264 len = ret;
265 printf(" %d bytes read\n\n%s", len, (char *)buf);
267 while (0);
269 ssl_close_notify(&ssl);
271 exit:
273 net_close(server_fd);
274 x509_free(&clicert);
275 x509_free(&cacert);
276 rsa_free(&rsa);
277 ssl_free(&ssl);
279 memset(&ssl, 0, sizeof(ssl));
281 #ifdef WIN32
282 printf(" + Press Enter to exit this program.\n");
283 fflush(stdout);
284 getchar();
285 #endif
287 return (ret);