Skip to content

Commit 86bdfb7

Browse files
committed
wolfKeyMgr v0.7
* Fix for HTTP header encode/decode conflict with variable `i`. * Fix for HTTP server response parsing with no null termination issue. * Added expires data to HTTP response. * Added ETSI client GET caching. * Added etsi_client `-r` support for GET (test caching).
1 parent 65970e4 commit 86bdfb7

File tree

10 files changed

+94
-42
lines changed

10 files changed

+94
-42
lines changed

configure.ac

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
AC_PREREQ(2.59)
77

8-
AC_INIT([wolfKeyManager],[0.6],[http://www.wolfssl.com])
8+
AC_INIT([wolfKeyManager],[0.7],[http://www.wolfssl.com])
99
AC_CONFIG_AUX_DIR(config)
1010
AC_CONFIG_HEADERS([wolfkeymgr/config.h])
1111
AC_CONFIG_MACRO_DIR(m4)
@@ -71,7 +71,7 @@ LT_PREREQ([2.2])
7171
LT_INIT([disable-static win32-dll])
7272

7373
# Shared library versioning
74-
WOLFKM_LIBRARY_VERSION=4:0:0
74+
WOLFKM_LIBRARY_VERSION=4:1:0
7575
# | | |
7676
# +------+ | +---+
7777
# | | |

examples/etsi_client/etsi_client.c

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ typedef struct WorkThreadInfo {
4444
const char* keyPass;
4545
const char* clientCertFile;
4646
const char* caFile;
47+
EtsiKey key;
4748
WOLFSSL_CTX* ctx; /* test ctx loading static ephemeral key */
4849
} WorkThreadInfo;
4950

@@ -84,12 +85,20 @@ static int DoKeyRequest(EtsiClientCtx* client, WorkThreadInfo* info)
8485
/* push: will wait for server to push new keys */
8586
/* get: will ask server for key and return */
8687
if (info->useGet) {
87-
EtsiKey key;
88-
memset(&key, 0, sizeof(key));
89-
90-
ret = wolfEtsiClientGet(client, &key, keyType, NULL, NULL, info->timeoutSec);
91-
if (ret == 0) {
92-
keyCb(client, &key, info);
88+
ret = wolfEtsiClientGet(client, &info->key, keyType, NULL, NULL,
89+
info->timeoutSec);
90+
/* positive return means new key returned */
91+
/* zero means, same key is used */
92+
/* negative means error */
93+
if (ret > 0) {
94+
/* use same "push" callback to test key use / print */
95+
keyCb(client, &info->key, info);
96+
ret = 0;
97+
}
98+
else if (ret == 0) {
99+
XLOG(WOLFKM_LOG_INFO, "ETSI Key Cached (valid for %lu sec)\n",
100+
info->key.expires - wolfGetCurrentTimeT());
101+
sleep(1); /* wait 1 second */
93102
}
94103
}
95104
else {
@@ -264,7 +273,6 @@ int main(int argc, char** argv)
264273
wolfEtsiClientInit();
265274

266275
if (poolSize == 0) {
267-
info.requests = 1; /* only 1 request for this */
268276
DoRequests(&info);
269277
}
270278
else {

examples/etsi_client/etsi_client.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@ extern "C" {
2929
/* for client tests only */
3030
#define WOLFKM_DEFAULT_HOST "localhost"
3131
#define WOLFKM_DEFAULT_ETSISVC_PORT "8119"
32-
#define WOLFKM_DEFAULT_REQUESTS 100 /* per thread */
33-
#define WOLFKM_ERROR_MODE_MAX 5 /* error mode type for forcing errors */
32+
#define WOLFKM_DEFAULT_REQUESTS 1 /* per thread */
3433

3534
/* example certificate and key for mutual authentication to key manager */
3635
/* see ./certs/test-cert.sh for generation and signing */

src/mod_etsi.c

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -168,15 +168,18 @@ int wolfEtsiClientGet(EtsiClientCtx* client, EtsiKey* key,
168168
int pos, i;
169169
HttpRsp rsp;
170170
const char* group;
171+
time_t now;
171172

172173
if (client == NULL || key == NULL) {
173174
return WOLFKM_BAD_ARGS;
174175
}
175176

176177
/* Has current key expired? */
178+
now = wolfGetCurrentTimeT();
177179
if (key->type == keyType && key->responseSz > 0 &&
178-
key->expires > 0 && key->expires < wolfGetCurrentTimeT()) {
180+
key->expires > 0 && key->expires >= now) {
179181
/* key is still valid, use existing */
182+
/* return zero, indicating no key change */
180183
return 0;
181184
}
182185

@@ -209,6 +212,7 @@ int wolfEtsiClientGet(EtsiClientCtx* client, EtsiKey* key,
209212
/* get key response */
210213
/* TODO: handle HTTP chunked content type */
211214
/* TODO: handle multiple packets */
215+
/* TODO: Integrate HTTP processing with read to handle larger payloads */
212216
key->responseSz = sizeof(key->response);
213217
do {
214218
ret = wolfTlsRead(client->ssl, (byte*)key->response, key->responseSz,
@@ -237,15 +241,24 @@ int wolfEtsiClientGet(EtsiClientCtx* client, EtsiKey* key,
237241
memset(&tm, 0, sizeof(tm));
238242
/* Convert string to time_t */
239243
/* HTTP expires example: "Wed, 21 Oct 2015 07:28:00 GMT" */
240-
if (strptime(rsp.headers[i].string,
241-
"%a, %d %b %Y %H:%M:%s %Z", &tm) != NULL) {
244+
if (strptime(rsp.headers[i].string, HTTP_DATE_FMT,
245+
&tm) != NULL) {
242246
key->expires = mktime(&tm);
247+
/* sanity check time against current time */
248+
/* if this is past current here then it has already
249+
expired or is invalid */
250+
if (key->expires < now) {
251+
XLOG(WOLFKM_LOG_WARN,
252+
"Key expires time invalid %lu < %lu\n",
253+
key->expires, now);
254+
key->expires = 0;
255+
}
243256
}
244257
break;
245258
}
246259
}
247260

248-
/* move payload (body) to response */
261+
/* move payload (body) to response (same buffer) */
249262
memcpy(key->response, rsp.body, rsp.bodySz);
250263
key->responseSz = rsp.bodySz;
251264
}
@@ -256,7 +269,9 @@ int wolfEtsiClientGet(EtsiClientCtx* client, EtsiKey* key,
256269

257270
if (ret == 0) {
258271
/* asymmetric key package response */
259-
XLOG(WOLFKM_LOG_INFO, "Got ETSI response (%d bytes)\n", key->responseSz);
272+
XLOG(WOLFKM_LOG_INFO, "Got ETSI response (%d bytes)\n",
273+
key->responseSz);
274+
ret = key->responseSz; /* return key size */
260275
}
261276

262277
return ret;

src/mod_http.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,10 @@ int wolfHttpServer_ParseRequest(HttpReq* req, byte* buf, word32 sz)
199199
*endline = '\0'; /* null terminate line */
200200
HttpParseHeader(req->headers, &req->headerCount, sec);
201201
endline += 2; /* 2=length of CRLF */
202+
203+
/* check if we have reached end of incoming buffer */
204+
if (endline >= (char*)buf + sz)
205+
break;
202206
endline = strstr(endline, kCrlf); /* Find end of line */
203207
}
204208

@@ -209,7 +213,7 @@ int wolfHttpServer_EncodeResponse(int rspCode, const char* message,
209213
byte* response, word32* responseSz, HttpHeader* headers, word32 headerCount,
210214
const byte* body, word32 bodySz)
211215
{
212-
int i;
216+
int i, c;
213217
HttpHeader* hdr;
214218
char* out = (char*)response;
215219
word32 remain;
@@ -236,8 +240,8 @@ int wolfHttpServer_EncodeResponse(int rspCode, const char* message,
236240
}
237241

238242
/* append headers */
239-
for (i=0; i<headerCount && remain > 0; i++) {
240-
hdr = &headers[i];
243+
for (c=0; c<headerCount && remain > 0; c++) {
244+
hdr = &headers[c];
241245

242246
i = snprintf(out, remain, "%s%s\r\n",
243247
wolfHttpGetHeaderStr(hdr->type, NULL), hdr->string);
@@ -352,7 +356,7 @@ int wolfHttpClient_ParseResponse(HttpRsp* rsp, char* buf, word32 sz)
352356
int wolfHttpClient_EncodeRequest(HttpMethodType type, const char* uri,
353357
byte* request, word32* requestSz, HttpHeader* headers, word32 headerCount)
354358
{
355-
int i;
359+
int i, c;
356360
HttpHeader* hdr;
357361
char* out = (char*)request;
358362
word32 remain;
@@ -372,8 +376,8 @@ int wolfHttpClient_EncodeRequest(HttpMethodType type, const char* uri,
372376
}
373377

374378
/* append headers */
375-
for (i=0; i<headerCount && remain > 0; i++) {
376-
hdr = &headers[i];
379+
for (c=0; c<headerCount && remain > 0; c++) {
380+
hdr = &headers[c];
377381

378382
i = snprintf(out, remain, "%s%s\r\n",
379383
wolfHttpGetHeaderStr(hdr->type, NULL), hdr->string);

src/sock_mgr.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,15 @@ static void ThreadEventProcess(int fd, short which, void* arg)
559559
return;
560560
}
561561
else if (memcmp(buffer, &kNotify, sizeof(kNotify)) == 0) {
562-
svcConn* conn = me->activeSvcConns.head;
562+
svcConn* conn = me->activeSvcConns.head, conn_lcl;
563+
if (conn == NULL) {
564+
/* Setup an empty connection for notify only */
565+
memset(&conn_lcl, 0, sizeof(conn_lcl));
566+
conn = &conn_lcl;
567+
conn->svc = me->svc;
568+
conn->svcThreadCtx = me->svcThreadCtx;
569+
conn->me = me;
570+
}
563571
while (conn) {
564572
if (conn->svc->notifyCb) {
565573
conn->svc->notifyCb(conn);

src/svc_etsi.c

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ typedef struct etsiSvcCtx {
3535
pthread_mutex_t lock; /* queue lock */
3636
pthread_t thread; /* key gen worker */
3737
} etsiSvcCtx;
38-
static etsiSvcCtx svcCtx;
38+
static etsiSvcCtx gSvcCtx;
3939

4040
/* the top level service */
4141
static svcInfo etsiService = {
@@ -57,14 +57,14 @@ static svcInfo etsiService = {
5757
.caBuffer = NULL,
5858
.caBufferSz = 0,
5959

60-
.svcCtx = &svcCtx,
60+
.svcCtx = &gSvcCtx,
6161
};
6262

6363
/* worker thread objects */
6464
typedef struct etsiSvcThread {
65-
word32 index;
66-
byte* httpRspBuf;
67-
word32 httpRspSz;
65+
word32 index;
66+
byte* httpRspBuf;
67+
word32 httpRspSz;
6868
} etsiSvcThread;
6969

7070
typedef struct etsiSvcConn {
@@ -109,16 +109,26 @@ static int SetupKeyPackage(etsiSvcCtx* svcCtx, etsiSvcThread* etsiThread)
109109
int ret = 0;
110110
byte rsp[ETSI_MAX_RESPONSE_SZ], keyBuf[ECC_BUFSIZE];
111111
word32 rspSz = (word32)sizeof(rsp), keyBufSz = (word32)sizeof(keyBuf);
112-
HttpHeader headers[2];
112+
char expiresStr[100];
113+
HttpHeader headers[3];
113114
headers[0].type = HTTP_HDR_CONTENT_TYPE;
114115
headers[0].string = "application/pkcs8";
115116
headers[1].type = HTTP_HDR_CONNECTION;
116117
headers[1].string = "Keep-Alive";
117-
/* TODO: Add key expiration using HTTP_HDR_EXPIRES */
118-
/* Example "Expires: Wed, 21 Oct 2015 07:28:00 GMT" */
118+
headers[2].type = HTTP_HDR_EXPIRES;
119+
headers[2].string = expiresStr;
120+
memset(expiresStr, 0, sizeof(expiresStr));
119121

120122
pthread_mutex_lock(&svcCtx->lock);
123+
XLOG(WOLFKM_LOG_DEBUG, "Synchronizing key to worker thread\n");
121124
if (etsiThread->index != svcCtx->index) {
125+
/* Format Expires Time */
126+
time_t t = wolfGetCurrentTimeT();
127+
struct tm tm;
128+
t += svcCtx->renewSec; /* offset by key renewal period */
129+
localtime_r(&t, &tm);
130+
strftime(expiresStr, sizeof(expiresStr), HTTP_DATE_FMT, &tm);
131+
122132
/* Export as DER IETF RFC 5915 */
123133
ret = wc_EccKeyToDer(&svcCtx->key, keyBuf, keyBufSz);
124134
if (ret < 0) {
@@ -259,14 +269,13 @@ void wolfEtsiSvc_ConnClose(svcConn* conn)
259269

260270
int wolfEtsiSvc_DoNotify(svcConn* conn)
261271
{
262-
int ret = 0;
272+
int ret;
263273
svcInfo* svc;
264274
etsiSvcCtx* svcCtx;
265275
etsiSvcThread* etsiThread;
266276
etsiSvcConn* etsiConn;
267277

268-
if (conn == NULL || conn->stream == NULL || conn->svc == NULL ||
269-
conn->svcThreadCtx == NULL || conn->svcConnCtx == NULL) {
278+
if (conn == NULL || conn->svc == NULL || conn->svcThreadCtx == NULL) {
270279
XLOG(WOLFKM_LOG_ERROR, "Bad ETSI notify pointers\n");
271280
return WOLFKM_BAD_ARGS;
272281
}
@@ -276,13 +285,14 @@ int wolfEtsiSvc_DoNotify(svcConn* conn)
276285
etsiThread = (etsiSvcThread*)conn->svcThreadCtx;
277286
etsiConn = (etsiSvcConn*)conn->svcConnCtx;
278287

279-
if (etsiConn->req.type == HTTP_METHOD_PUT) {
280-
/* updated key */
281-
ret = SetupKeyPackage(svcCtx, etsiThread);
282-
if (ret == 0) {
283-
/* send updated key */
284-
ret = wolfEtsiSvc_DoResponse(conn);
285-
}
288+
/* update key */
289+
ret = SetupKeyPackage(svcCtx, etsiThread);
290+
291+
/* push key to active push threads */
292+
if (ret == 0 && etsiConn != NULL &&
293+
etsiConn->req.type == HTTP_METHOD_PUT) {
294+
/* send updated key */
295+
ret = wolfEtsiSvc_DoResponse(conn);
286296
}
287297

288298
return ret;

wolfkeymgr/mod_etsi.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,10 @@ WOLFKM_API int wolfEtsiClientMakeRequest(EtsiClientType type, const char* finger
112112
/* Fingerprint is a SHA256 hash of public key first 80 bits of digest in big-
113113
endian format as HEX string (10 characters max) */
114114
/* keyType can be DHE/ECDHE/X25519/X448 */
115+
/* return:
116+
- zero response means existing key is used,
117+
- negative is error
118+
- positive means new key retrieved */
115119
WOLFKM_API int wolfEtsiClientGet(EtsiClientCtx* client, EtsiKey* key,
116120
EtsiKeyType keyType, const char* fingerprint, const char* contextStr,
117121
int timeoutSec);

wolfkeymgr/mod_http.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ extern "C" {
3333
#define HTTP_HDR_MAX_ITEMS 10
3434
#endif
3535

36+
#ifndef HTTP_DATE_FMT
37+
#define HTTP_DATE_FMT "%a, %d %b %Y %H:%M:%S %Z"
38+
#endif
39+
3640
/* HTTP Types */
3741
typedef enum HttpMethodType {
3842
HTTP_METHOD_UNKNOWN,

wolfkeymgr/version.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
extern "C" {
2828
#endif
2929

30-
#define LIBWOLFSSL_VERSION_STRING "0.6"
30+
#define LIBWOLFSSL_VERSION_STRING "0.7"
3131
#define LIBWOLFSSL_VERSION_HEX @HEX_VERSION@
3232

3333
#ifdef __cplusplus

0 commit comments

Comments
 (0)