Skip to content

Commit e85913e

Browse files
committed
add session-tickets and resumption
1 parent 539a282 commit e85913e

4 files changed

Lines changed: 651 additions & 0 deletions

File tree

tls-options/Makefile

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# TLS Examples Makefile
2+
CC = gcc
3+
LIB_PATH = /usr/local
4+
CFLAGS = -Wall -I$(LIB_PATH)/include
5+
LIBS = -L$(LIB_PATH)/lib -lm
6+
7+
# option variables
8+
DYN_LIB = -lwolfssl
9+
STATIC_LIB = $(LIB_PATH)/lib/libwolfssl.a
10+
DEBUG_FLAGS = -g -DDEBUG
11+
DEBUG_INC_PATHS = -MD
12+
OPTIMIZE = -Os
13+
14+
# Options
15+
#CFLAGS+=$(DEBUG_FLAGS)
16+
CFLAGS+=$(OPTIMIZE)
17+
#LIBS+=$(STATIC_LIB)
18+
LIBS+=$(DYN_LIB)
19+
20+
# build targets
21+
SRC=$(wildcard *.c)
22+
TARGETS=$(patsubst %.c, %, $(SRC))
23+
24+
all: $(TARGETS)
25+
26+
debug: CFLAGS+=$(DEBUG_FLAGS)
27+
debug: all
28+
29+
# add the -pthread flag to any threaded examples
30+
%-threaded: CFLAGS+=-pthread
31+
%-writedup: CFLAGS+=-pthread
32+
memory-tls: CFLAGS+=-pthread
33+
34+
# compile tcp examples without the LIBS variable
35+
%-tcp: LIBS=
36+
37+
# build template
38+
%: %.c
39+
$(CC) -o $@ $< $(CFLAGS) $(LIBS)
40+
41+
clean:
42+
rm -f $(TARGETS)
43+
rm -f session.bin

tls-options/README.md

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# wolfSSL TLS with Some Options Example
2+
3+
This example implements a simple echo client and server that uses TLS with some options.
4+
5+
## Building
6+
7+
You need to have wolfSSL installed on your computer prior to building.
8+
9+
To compile these programs use `make` in this directory.
10+
11+
## Running
12+
13+
### Session Tickets and Resumption
14+
15+
Here is an example of suspending a session once started and resuming the session later.
16+
17+
1. Establish the first session with `client-tls-session`.
18+
This program outputs a session ticket as a binary file.
19+
2. Resume a previously interrupted session with `client-tls-resume`.
20+
21+
#### Make session ticket
22+
23+
On one console run the server, this should be executed first or the handshake will fail.
24+
25+
You can use them as a server:
26+
- TLS 1.2: ../tls/server-tls
27+
- TLS 1.3: ../tls/server-tls13
28+
29+
These are in different directories, so you need to use `make` again.
30+
31+
```sh
32+
cd ../tls && make
33+
./server-tls13
34+
```
35+
36+
Then in another terminal run the client:
37+
38+
```sh
39+
./client-tls-session
40+
```
41+
42+
You will be able to send a message from client to server.
43+
44+
Sending "break" as a message to the server will generate "session.bin"
45+
46+
47+
#### Resume
48+
49+
You can resume earlier session by doing:
50+
51+
```sh
52+
./client-tls-resume
53+
```
54+
55+
"session.bin" is referenced as a session ticket.
56+
If it doesn't exist or is invalid, this program will start a new session.
57+
58+
You will be able to send a message from client to server.
59+
60+
Sending "break" as a message to the server will break the session.
61+
If you use TLS 1.3 server, You can resume many times.
62+
63+
64+
## Cleaning Up
65+
66+
You can remove executable files by doing:
67+
68+
```sh
69+
make clean
70+
```
71+

tls-options/client-tls-resume.c

Lines changed: 280 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,280 @@
1+
/* client-tls-resume.c
2+
*
3+
* Copyright (C) 2006-2023 wolfSSL Inc.
4+
*
5+
* This file is part of wolfSSL. (formerly known as CyaSSL)
6+
*
7+
* wolfSSL is free software; you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation; either version 2 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* wolfSSL is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program; if not, write to the Free Software
19+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
20+
*/
21+
22+
/* the usual suspects */
23+
#include <stdlib.h>
24+
#include <stdio.h>
25+
#include <string.h>
26+
27+
/* socket includes */
28+
#include <sys/socket.h>
29+
#include <arpa/inet.h>
30+
#include <netinet/in.h>
31+
#include <unistd.h>
32+
33+
/* wolfSSL */
34+
#include <wolfssl/options.h>
35+
#include <wolfssl/ssl.h>
36+
37+
#define CERT_FILE "../certs/client-cert.pem"
38+
#define KEY_FILE "../certs/client-key.pem"
39+
#define CA_CERT_FILE "../certs/ca-cert.pem"
40+
#define LOCALHOST "127.0.0.1"
41+
#define DEFAULT_PORT 11111
42+
#define SAVED_SESS "session.bin"
43+
44+
#define MSG_SIZE 256
45+
46+
/* Print SSL error message */
47+
static void print_SSL_error(const char* msg, SSL* ssl)
48+
{
49+
int err;
50+
51+
if (ssl != NULL) {
52+
err = wolfSSL_get_error(ssl, 0);
53+
fprintf(stderr, "ERROR: %s (err %d, %s)\n", msg, err,
54+
ERR_error_string(err, NULL));
55+
}
56+
else {
57+
fprintf(stderr, "ERROR: %s \n", msg);
58+
}
59+
}
60+
61+
/* read a session from the file if exists */
62+
static int read_SESS(const char* file, SSL* ssl)
63+
{
64+
FILE* fp = NULL;
65+
unsigned char* buff = NULL;
66+
const unsigned char* p = NULL;
67+
size_t sz;
68+
WOLFSSL_SESSION* sess = NULL;
69+
int ret = WOLFSSL_FAILURE;
70+
71+
if (((fp = fopen(file, "rb")) == NULL) ||
72+
(fseek(fp, 0, SEEK_END) != 0) ||
73+
((sz = ftell(fp)) == -1)) {
74+
fprintf(stderr, "ERROR : failed file %s operation \n", file);
75+
goto cleanup;
76+
}
77+
78+
rewind(fp);
79+
if ((buff = (unsigned char*)malloc(sz)) == NULL ||
80+
(fread(buff, 1, sz, fp) != sz)) {
81+
fprintf(stderr, "ERROR : failed reading file\n");
82+
goto cleanup;
83+
}
84+
85+
printf("%s size = %ld\n", SAVED_SESS, sz);
86+
87+
p = buff;
88+
if((sess = wolfSSL_d2i_SSL_SESSION(NULL, (const unsigned char**)&p, sz)) == NULL) {
89+
print_SSL_error("wolfSSL_d2i_SSL_SESSION", NULL);
90+
}
91+
92+
if(sess != NULL && (ret = wolfSSL_set_session(ssl, sess) != WOLFSSL_SUCCESS)) {
93+
print_SSL_error("failed SSL session", ssl);
94+
} else {
95+
printf("Resuming session\n");
96+
ret = WOLFSSL_SUCCESS;
97+
}
98+
99+
cleanup:
100+
if (sess)
101+
wolfSSL_SESSION_free(sess);
102+
if (fp)
103+
fclose(fp);
104+
if (buff)
105+
free(buff);
106+
return ret;
107+
}
108+
109+
int main(int argc, char **argv)
110+
{
111+
struct sockaddr_in servAddr;
112+
int sockfd = -1;
113+
char *ipadd = LOCALHOST;
114+
char *ca_cert = CA_CERT_FILE;
115+
int port = DEFAULT_PORT;
116+
static const char kHttpGetMsg[] = "GET /index.html HTTP/1.0\r\n\r\n";
117+
struct hostent *host;
118+
119+
char msg[MSG_SIZE];
120+
int ret = WOLFSSL_FAILURE;
121+
122+
(void)ipadd;
123+
124+
/* SSL objects */
125+
WOLFSSL_CTX* ctx = NULL;
126+
WOLFSSL* ssl = NULL;
127+
128+
memset(&servAddr, 0, sizeof(servAddr));
129+
130+
/* Check for proper calling convention */
131+
if (argc == 1)
132+
fprintf(stderr, "Send to localhost(%s)\n", LOCALHOST);
133+
if (argc >=2) {
134+
host = gethostbyname(argv[1]);
135+
memcpy(&servAddr.sin_addr, host->h_addr_list[0], host->h_length);
136+
}
137+
if (argc >= 3)
138+
ca_cert = argv[2];
139+
if (argc == 4)
140+
port = atoi(argv[3]);
141+
if (argc >= 5) {
142+
fprintf(stderr, "ERROR: Too many arguments.\n");
143+
goto cleanup;
144+
}
145+
146+
/* Initialize library */
147+
if (wolfSSL_library_init() != WOLFSSL_SUCCESS) {
148+
fprintf(stderr, "ERROR: failed to initialize the library\n");
149+
goto cleanup;
150+
}
151+
152+
/* Create and initialize an SSL context object*/
153+
if ((ctx = wolfSSL_CTX_new(SSLv23_client_method())) == NULL) {
154+
fprintf(stderr, "ERROR: failed to create an SSL context object\n");
155+
goto cleanup;
156+
}
157+
158+
/* Load client certificate into WOLFwolfSSL_CTX */
159+
if ((ret = wolfSSL_CTX_use_certificate_file(ctx, CERT_FILE,
160+
WOLFSSL_FILETYPE_PEM)) != WOLFSSL_SUCCESS) {
161+
fprintf(stderr, "ERROR: failed to load %s, please check the file.\n",
162+
CERT_FILE);
163+
goto cleanup;
164+
}
165+
166+
/* Load client key into WOLFwolfSSL_CTX */
167+
if ((ret = wolfSSL_CTX_use_PrivateKey_file(ctx, KEY_FILE,
168+
WOLFSSL_FILETYPE_PEM)) != WOLFSSL_SUCCESS) {
169+
fprintf(stderr, "ERROR: failed to load %s, please check the file.\n",
170+
KEY_FILE);
171+
goto cleanup;
172+
}
173+
174+
/* Load CA certificate to the context */
175+
if ((ret = wolfSSL_CTX_load_verify_locations(ctx, ca_cert, NULL))
176+
!= WOLFSSL_SUCCESS) {
177+
fprintf(stderr, "ERROR: failed to load %s \n", ca_cert);
178+
goto cleanup;
179+
}
180+
181+
/*
182+
* Set up a TCP Socket and connect to the server
183+
*/
184+
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
185+
fprintf(stderr, "ERROR: failed to create a socket. errno %d\n", errno);
186+
goto cleanup;
187+
}
188+
189+
servAddr.sin_family = AF_INET; /* using IPv4 */
190+
servAddr.sin_port = htons(port); /* on DEFAULT_PORT */
191+
192+
if ((ret = connect(sockfd, (struct sockaddr *)&servAddr, sizeof(servAddr)))
193+
== -1) {
194+
fprintf(stderr, "ERROR: failed to connect. errno %d\n", errno);
195+
goto cleanup;
196+
}
197+
198+
/* Create an SSL object */
199+
if ((ssl = wolfSSL_new(ctx)) == NULL) {
200+
fprintf(stderr, "ERROR: failed to create an SSL object\n");
201+
goto cleanup;
202+
}
203+
204+
/* read a seesion from file */
205+
if ((ret = read_SESS(SAVED_SESS, ssl)) != WOLFSSL_SUCCESS) {
206+
fprintf(stderr, "ERROR: failed to read session information\n");
207+
goto cleanup;
208+
}
209+
210+
/* Attach the socket to the SSL */
211+
if ((ret = wolfSSL_set_fd(ssl, sockfd)) != WOLFSSL_SUCCESS) {
212+
fprintf(stderr, "ERROR: Failed to set the file descriptor\n");
213+
goto cleanup;
214+
}
215+
/* SSL connect to the server */
216+
if ((ret = wolfSSL_connect(ssl)) != WOLFSSL_SUCCESS) {
217+
print_SSL_error("failed SSL connect", ssl);
218+
goto cleanup;
219+
}
220+
221+
/* check if session is resued */
222+
if (wolfSSL_session_reused(ssl) == 1) {
223+
printf("Session is reused\n");
224+
}
225+
else {
226+
printf("Session is not reused. New session was negotiated.\n");
227+
}
228+
229+
/*
230+
* Application messaging
231+
*/
232+
while (1) {
233+
printf("Message to send: ");
234+
if(fgets(msg, sizeof(msg), stdin) <= 0)
235+
break;
236+
if (strcmp(msg, "\n") == 0){ /* if empty send HTTP request */
237+
strncpy(msg, kHttpGetMsg, sizeof(msg));
238+
} else
239+
msg[strnlen(msg, sizeof(msg))-1] = '\0';
240+
/* send a message to the server */
241+
if ((ret = wolfSSL_write(ssl, msg, strnlen(msg, sizeof(msg)))) < 0) {
242+
print_SSL_error("failed SSL write", ssl);
243+
break;
244+
}
245+
246+
/*
247+
* closing the session, and write session information into a file
248+
* before writing session information, the file is removed if exists
249+
*/
250+
if (strcmp(msg, "break") == 0) {
251+
printf("Sending break command\n");
252+
ret = WOLFSSL_SUCCESS;
253+
break;
254+
}
255+
256+
/* receive a message from the server */
257+
if ((ret = wolfSSL_read(ssl, msg, sizeof(msg) - 1)) < 0) {
258+
print_SSL_error("failed SSL read", ssl);
259+
break;
260+
}
261+
msg[ret] = '\0';
262+
printf("Received: %s\n", msg);
263+
}
264+
265+
/* Cleanup and return */
266+
cleanup:
267+
if (ssl != NULL) {
268+
wolfSSL_shutdown(ssl);
269+
wolfSSL_free(ssl);
270+
}
271+
if (sockfd != -1)
272+
close(sockfd);
273+
if (ctx != NULL)
274+
wolfSSL_CTX_free(ctx);
275+
if (ret != WOLFSSL_SUCCESS)
276+
ret = WOLFSSL_FAILURE;
277+
printf("End of TLS Client\n");
278+
return ret;
279+
}
280+

0 commit comments

Comments
 (0)