ThingWorx C SDK
twAxTls.h
1 /***************************************
2  * Copyright (C) 2015 ThingWorx Inc. *
3  ***************************************/
4 
10 #ifndef AXTLS_H
11 #define AXTLS_H
12 
13 #include "twOSPort.h"
14 #include "stringUtils.h"
15 
16 #include "stdio.h"
17 #include "string.h"
18 
19 #if defined WIN32
20 #define STDCALL __stdcall
21 #endif
22 #include "ssl.h"
23 
24 #ifdef __cplusplus
25 extern "C" {
26 #endif
27 
28 int16_t returnValue(int16_t v);
29 typedef struct ssl_struct {
30  SSL * ssl;
31  uint8_t * leftover_buf;
32  uint8_t * leftover_ptr;
33  uint16_t leftover_cnt;
34  uint16_t max_leftover;
35 } ssl_struct;
36 
37 #define TW_SSL_CTX SSL_CTX
38 #define TW_SSL ssl_struct
39 #define TW_SSL_SESSION_ID_SIZE SSL_SESSION_ID_SIZE
40 #define TW_SSL_SESSION_ID(a) a ? a->ssl->session_id : NULL
41 #define TW_GET_CERT_SIZE ssl_get_config(SSL_MAX_CERT_CFG_OFFSET)
42 #define TW_GET_CA_CERT_SIZE ssl_get_config(SSL_MAX_CA_CERT_CFG_OFFSET)
43 #define TW_NEW_SSL_CTX ssl_ctx_new(options | SSL_SERVER_VERIFY_LATER, SSL_DEFAULT_CLNT_SESS)
44 /*#define TW_NEW_SSL_CLIENT(a,b,c,d) ssl_client_new(a,b,c,d)
45 #define TW_NEW_SERVER(a, b) ssl_server_new(a,b)
46 #define TW_HANDSHAKE_SUCCEEDED(a) (a ? (ssl_handshake_status(a->ssl)) == SSL_OK) : FALSE)
47 #define TW_SSL_FREE(a) ssl_free(a)*/
48 #define TW_SSL_CTX_FREE(a) ssl_ctx_free(a)
49 #define TW_SSL_WRITE(a,b,c) ssl_write(a->ssl,(uint8_t *)b,c)
50 #define TW_USE_CERT_FILE(a,b,c) ssl_obj_load(a, SSL_OBJ_X509_CERT, b, NULL)
51 #define TW_USE_KEY_FILE(a,b,c,d) ssl_obj_load(a, SSL_OBJ_RSA_KEY, b, d)
52 #define TW_USE_CERT_CHAIN_FILE(a,b,c) ssl_obj_load(a, SSL_OBJ_X509_CACERT, b, NULL)
53 #define TW_SET_CLIENT_CA_LIST(a,b) ssl_obj_load(a, SSL_OBJ_X509_CACERT, (const char *)b, NULL)
54 #define TW_ENABLE_FIPS_MODE(a) returnValue(TW_FIPS_MODE_NOT_SUPPORTED)
55 #define TW_SHA1_CTX SHA1_CTX
56 #define TW_SHA1_INIT(a) SHA1_Init(a)
57 #define TW_SHA1_UPDATE(a,b,c) SHA1_Update(a,b,c)
58 #define TW_SHA1_FINAL(a,b) SHA1_Final(a,b)
59 #define TW_MD5_CTX MD5_CTX
60 #define TW_MD5_INIT(a) MD5_Init(a)
61 #define TW_MD5_UPDATE(a,b,c) MD5_Update(a,b,c)
62 #define TW_MD5_FINAL(a,b) MD5_Final(a,b)
63 #define DATA_AVAILABLE(a,b,c) 1
64 
65 static INLINE TW_SSL * TW_NEW_SSL_CLIENT(SSL_CTX *ssl_ctx, twSocket * client_fd, void * session_id, uint8_t sess_id_size) {
66  TW_SSL * s = (TW_SSL *)TW_CALLOC(sizeof(TW_SSL), 1);
67  if (!s) return NULL;
68  s->ssl = ssl_client_new(ssl_ctx, client_fd, (const uint8_t *)session_id, sess_id_size);
69  if (!s->ssl) {
70  TW_FREE(s);
71  s = NULL;
72  }
73  return s;
74 }
75 
76 static INLINE char TW_HANDSHAKE_SUCCEEDED(TW_SSL * s) {
77  if (!s || !s->ssl) return FALSE;
78  return (ssl_handshake_status(s->ssl) == SSL_OK);
79 }
80 
81 static INLINE TW_SSL * TW_NEW_SERVER(SSL_CTX *ssl_ctx, twSocket * client_fd) {
82  TW_SSL * s = (TW_SSL *)TW_CALLOC(sizeof(TW_SSL), 1);
83  if (!s) return NULL;
84  s->ssl = ssl_server_new(ssl_ctx, client_fd);
85  if (!s->ssl) {
86  TW_FREE(s);
87  s = NULL;
88  }
89  return s;
90 }
91 
92 static INLINE void TW_SSL_FREE(TW_SSL * s){
93  if(s) {
94  if (s->ssl) ssl_free(s->ssl);
95  if (s->leftover_buf) TW_FREE(s->leftover_buf);
96  TW_FREE(s);
97  }
98 }
99 
111 static INLINE int TW_SSL_READ(TW_SSL * ssl, char * buf, int len, int32_t timeout) {
112  int ret = -1;
113  uint8_t *read_buf = NULL;
114  DATETIME maxtime = twGetSystemMillisecondCount() + timeout;
115  if(!ssl || !buf) return -1;
116  /* Anything left from last read? */
117  if (ssl->leftover_cnt && ssl->leftover_ptr) {
118  uint16_t bytes = ssl->leftover_cnt > len ? len : ssl->leftover_cnt;
119  memcpy(buf, ssl->leftover_ptr, bytes);
120  if (ssl->leftover_cnt > len) {
121  ssl->leftover_cnt -= len;
122  ssl->leftover_ptr += bytes;
123  } else {
124  ssl->leftover_cnt = 0;
125  ssl->leftover_ptr = ssl->leftover_buf;
126  }
127  /*** printf("\n ############# AXTLS:SSL_READ - Reading from leftover data. Asked for %d, Returned %d\n\n", len, bytes); ***/
128  return bytes;
129  }
130  /* Loop until we are unblocked or timeout */
131  while (twTimeGreaterThan(maxtime, twGetSystemMillisecondCount()) && (ret = ssl_read(ssl->ssl, &read_buf)) == SSL_OK) {
132 
133  }
134  if (ret > SSL_OK) {
135  uint16_t bytes = ret > len ? len : ret;
136  memcpy(buf, read_buf, bytes);
137  ssl->leftover_cnt = ret > len ? ret - len : 0;
138  /*** printf("\n ############# AXTLS:SSL_READ - Asked for %d bytes, Read %d bytes\n\n", len, ret); ***/
139  if (ssl->leftover_cnt) {
140  if (ssl->leftover_cnt > ssl->max_leftover) {
141  if (ssl->leftover_buf) TW_FREE(ssl->leftover_buf);
142  /*** printf("\n ############# AXTLS:SSL_READ - Allocating %d bytes for leftover buffer\n\n", ssl->leftover_cnt); ***/
143  ssl->leftover_buf = (uint8_t *)TW_CALLOC(ssl->leftover_cnt,1);
144  if (!ssl->leftover_buf) {
145  printf("\nAXTLS - PANIC! Unable to allocate memory\n\n");
146  return -1;
147  }
148  ssl->leftover_ptr = ssl->leftover_buf;
149  ssl->max_leftover = ssl->leftover_cnt;
150  }
151  memcpy(ssl->leftover_buf, read_buf + bytes, ssl->leftover_cnt);
152  /*** printf("\n ############# AXTLS:SSL_READ - Copied %d bytes to leftover buffer\n\n", ssl->leftover_cnt); ***/
153  }
154  return bytes;
155  } else if (ret == SSL_OK) {
156  /* the WaitFor timed out, meaning we have no more data from the server */
157  /*** printf("\n ############# AXTLS:SSL_READ - WaitFor timeout while already begun reading TLS packet\n\n"); ***/
158  return TW_READ_TIMEOUT;
159  } else return ret;
160 }
161 
169 static int TW_SSL_ACCEPT(TW_SSL * s) {
170  if (!s || !s->ssl) return -1;
171  while (ssl_read(s->ssl, NULL) == SSL_OK) {
172  if (s->ssl->next_state == HS_CLIENT_HELLO)
173  return 0; /* we're done */
174  }
175  return -1;
176 }
177 
187 static INLINE int TW_VALIDATE_CERT(TW_SSL * ssl, char selfSignedOk) {
188  int res = 1;
189  if (!ssl || !ssl->ssl) return 1;
190  res = ssl_verify_cert ( ssl->ssl );
191  if (res) res = res - SSL_X509_OFFSET;
192  if (res == SSL_OK) return 0;
193  if( res != SSL_OK && (selfSignedOk && res == X509_VFY_ERROR_SELF_SIGNED)) return 0;
194  return 1;
195 }
196 
216 static INLINE char * TW_GET_X509_FIELD(TW_SSL * ssl, char field) {
217  const char * tmp = NULL;
218  if (!ssl || !ssl->ssl) return NULL;
219  switch (field) {
220  case TW_SUBJECT_CN:
221  tmp = ssl_get_cert_dn(ssl->ssl, SSL_X509_CERT_COMMON_NAME);
222  break;
223  case TW_SUBJECT_O:
224  tmp = ssl_get_cert_dn(ssl->ssl, SSL_X509_CERT_ORGANIZATION);
225  break;
226  case TW_SUBJECT_OU:
227  tmp = ssl_get_cert_dn(ssl->ssl, SSL_X509_CERT_ORGANIZATIONAL_NAME);
228  break;
229  case TW_ISSUER_CN:
230  tmp = ssl_get_cert_dn(ssl->ssl, SSL_X509_CA_CERT_COMMON_NAME);
231  break;
232  case TW_ISSUER_O:
233  tmp = ssl_get_cert_dn(ssl->ssl, SSL_X509_CA_CERT_ORGANIZATION);
234  break;
235  case TW_ISSUER_OU:
236  tmp = ssl_get_cert_dn(ssl->ssl, SSL_X509_CA_CERT_ORGANIZATIONAL_NAME);
237  break;
238  default:
239  tmp = NULL;
240  }
241  return duplicateString(tmp);
242 }
243 
244 #ifdef __cplusplus
245 }
246 #endif
247 
248 #endif /* AXTLS_H */
static INLINE TW_SSL * TW_NEW_SSL_CLIENT(TW_SSL_CTX *ctx, twSocket *sock, void *session_id, int session_size)
Creates a new #TW_SSL structure for connection with the specified settings (see SSL_new(), SSL_connect()).
Definition: twOpenSSL.h:102
char twTimeGreaterThan(DATETIME t1, DATETIME t2)
Compares two DATETIME variables to see if one is greater.
Definition: twIos.c:31
static INLINE int TW_SSL_READ(TW_SSL *ssl, char *buf, int len, int32_t timeout)
Reads len bytes of data from ssl into buf (see SSL_read()).
Definition: twOpenSSL.h:274
String utility function prototypes.
static INLINE char * TW_GET_X509_FIELD(TW_SSL *ssl, char field)
Gets an X509 field of ssl.
Definition: twOpenSSL.h:385
twSocket base type definition.
Definition: twOSPort.h:175
Wrappers for OS-specific functionality.
static INLINE TW_SSL * TW_NEW_SERVER(TW_SSL_CTX *ctx, twSocket *sock)
Creates a new #TW_SSL connection structure (see SSL_new()).
Definition: twOpenSSL.h:157
static INLINE int TW_SSL_ACCEPT(TW_SSL *s)
Waits for a #TW_SSL client to initiate a handshake with the server. Wrapper function for SSL_accept()...
Definition: twOpenSSL.h:195
Definition: twAxTls.h:29
static INLINE int TW_VALIDATE_CERT(TW_SSL *ssl, char selfSignedOk)
Validates the certificate of ssl.
Definition: twOpenSSL.h:363
uint64_t twGetSystemMillisecondCount()
Gets the current system time in milliseconds.
Definition: twIos.c:49
char * duplicateString(const char *input)
Copies a string.
Definition: stringUtils.c:38