19 #include <openssl/bio.h>
20 #include <openssl/ssl.h>
21 #include <openssl/err.h>
22 #include <openssl/pem.h>
23 #include <openssl/x509.h>
24 #include <openssl/x509_vfy.h>
25 #include <openssl/sha.h>
26 #include <openssl/md5.h>
32 #define TW_SSL_CTX SSL_CTX
34 #define TW_SSL_SESSION_ID_SIZE sizeof(void *)
35 #define TW_SSL_SESSION_ID(a) SSL_get1_session(a)
36 #define TW_GET_CERT_SIZE ssl_get_config(SSL_MAX_CERT_CFG_OFFSET)
37 #define TW_GET_CA_CERT_SIZE ssl_get_config(SSL_MAX_CA_CERT_CFG_OFFSET)
38 #define TW_HANDSHAKE_SUCCEEDED(a) (a && SSL_get_state(a) == SSL_ST_OK)
39 #define TW_SSL_FREE(a) SSL_free(a)
40 #define TW_SSL_CTX_FREE(a) SSL_CTX_free(a)
41 #define TW_USE_CERT_FILE(a,b,c) SSL_CTX_use_PrivateKey_file(a, b, SSL_FILETYPE_PEM)
42 #define TW_USE_CERT_CHAIN_FILE(a,b,c) SSL_CTX_load_verify_locations(a, b, NULL)
43 #define TW_SET_CLIENT_CA_LIST(a,b) SSL_CTX_use_certificate_chain_file(a,b)
44 #define DATA_AVAILABLE(a,b,c) (twSocket_WaitFor(a, b) || SSL_pending(c))
52 #define TW_SHA1_CTX SHA_CTX
53 #define TW_SHA1_INIT(a) SHA1_Init(a)
54 #define TW_SHA1_UPDATE(a,b,c) SHA1_Update(a,b,c)
55 #define TW_SHA1_FINAL(a,b) SHA1_Final(a,b)
57 #define TW_MD5_CTX MD5_CTX
58 #define TW_MD5_INIT(a) MD5_Init(a)
59 #define TW_MD5_UPDATE(a,b,c) MD5_Update(a,b,c)
60 #define TW_MD5_FINAL(a,b) MD5_Final(a,b)
63 static char fips_enabled = FALSE;
75 ret = FIPS_mode_set(1);
77 TW_LOG(
TW_ERROR,
"TW_NEW_SSL_CTX_FUNC: FIPS_mode_set failed: %s.", ERR_error_string(ERR_get_error(), NULL));
79 return TW_ENABLE_FIPS_MODE_FAILED;
108 TW_LOG(
TW_ERROR,
"TW_NEW_SSL_CLIENT: Error creating SSL session. Error: %s", ERR_error_string(ERR_get_error(), NULL));
111 if (session_id) SSL_set_session(ssl, (SSL_SESSION *)session_id);
112 bio=BIO_new_socket(sock->
sock,BIO_NOCLOSE);
114 TW_LOG(
TW_ERROR,
"TW_NEW_SSL_CLIENT: Error creating SSL BIO. Error: %s.", ERR_error_string(ERR_get_error(), NULL));
118 SSL_set_bio(ssl,bio,bio);
119 res = SSL_connect(ssl);
121 const char * tmp = NULL;
123 TW_LOG(
TW_ERROR,
"TW_NEW_SSL_CLIENT: SSL handshake error. Error: %s.", ERR_error_string(ERR_get_error(), NULL));
125 tmp = SSL_get_cipher_list(ssl,index);
127 TW_LOG(
TW_TRACE,
"TW_NEW_SSL_CLIENT: Ciphers Supported: %s", tmp);
138 extern unsigned char default_private_key[];
139 extern int default_private_key_len;
140 extern unsigned char default_certificate[];
141 extern int default_certificate_len;
143 static const unsigned char s_server_session_id_context[SSL_MAX_SSL_SESSION_ID_LENGTH] = {
""};
162 unsigned char * p = NULL;
163 if (!ctx || !sock)
return NULL;
165 p = default_private_key;
166 r = d2i_RSAPrivateKey(NULL, (
const unsigned char **)&p, default_private_key_len);
167 p = default_certificate;
168 x = d2i_X509(NULL, (
const unsigned char **)&p, default_certificate_len);
169 SSL_CTX_use_RSAPrivateKey(ctx, r);
170 SSL_CTX_use_certificate(ctx, x);
171 SSL_CTX_set_session_id_context(ctx, s_server_session_id_context,
sizeof s_server_session_id_context);
174 TW_LOG(
TW_ERROR,
"TW_NEW_SERVER: Error creating SSL session. Error: %s", ERR_error_string(ERR_get_error(), NULL));
177 bio=BIO_new_socket(sock->
sock,BIO_NOCLOSE);
179 TW_LOG(
TW_ERROR,
"TW_NEW_SERVER: Error creating SSL BIO. Error: %s.", ERR_error_string(ERR_get_error(), NULL));
183 SSL_set_bio(ssl,bio,bio);
196 int res = SSL_accept(s);
198 const char * tmp = NULL;
200 TW_LOG(
TW_ERROR,
"TW_SSL_ACCEPT: SSL handshake error. Error: %s.", ERR_error_string(ERR_get_error(), NULL));
202 tmp = SSL_get_cipher_list(s,index);
204 TW_LOG(
TW_TRACE,
" Ciphers Supported: %s", tmp);
226 static INLINE
int TW_USE_KEY_FILE(SSL_CTX * ctx,
const char * file,
int type,
char * passwd) {
227 SSL_CTX_set_default_passwd_cb_userdata(ctx, passwd);
228 if (SSL_CTX_use_PrivateKey_file(ctx, file, type) <= 0) {
229 TW_LOG(
TW_ERROR,
"TW_USE_KEY_FILE: Error setting the key file.");
245 SSL_CTX * ctx = NULL;
246 if (SSL_library_init() != 1) {
247 TW_LOG(
TW_ERROR,
"TW_NEW_SSL_CTX_FUNC: Error initializing OpenSSL library: %lx.", ERR_get_error());
250 OpenSSL_add_all_algorithms();
251 SSL_load_error_strings();
252 ERR_load_crypto_strings();
253 ctx = SSL_CTX_new(SSLv23_method());
255 if (ctx) SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
258 #define TW_NEW_SSL_CTX TW_NEW_SSL_CTX_FUNC()
274 static INLINE
int TW_SSL_READ(TW_SSL * ssl,
char * buf,
int len, int32_t timeout) {
275 int32_t ret = SSL_ERROR_NONE;
279 if (!ssl || !buf)
return -1;
282 ret = SSL_read(ssl, buf, len);
283 switch (SSL_get_error(ssl,ret)) {
286 case SSL_ERROR_WANT_WRITE:
287 case SSL_ERROR_WANT_READ:
288 case SSL_ERROR_WANT_X509_LOOKUP:
290 TW_LOG(
TW_INFO,
"TW_SSL_READ: Read BLOCK on try %d. Error: %s", retries, ERR_error_string(ret, NULL));
294 case SSL_ERROR_SYSCALL:
296 TW_LOG(
TW_ERROR,
"TW_SSL_READ: Error reading from SSL stream");
298 case SSL_ERROR_ZERO_RETURN:
299 TW_LOG(
TW_TRACE,
"TW_SSL_READ: Read 0 bytes");
307 TW_LOG(
TW_ERROR,
"TW_SSL_READ: Timed out or error waiting reading from socket. Error: %s", ERR_error_string(ret, NULL));
308 return TW_TIMEOUT_READING_FROM_SOCKET;
329 while (retries < 3) {
330 result = SSL_write(ssl, buf, len);
331 switch (SSL_get_error(ssl,result)) {
334 case SSL_ERROR_WANT_WRITE:
335 case SSL_ERROR_WANT_READ:
336 case SSL_ERROR_WANT_X509_LOOKUP:
339 TW_LOG(
TW_ERROR,
"TW_SSL_WRITE: Write BLOCK. Retry %d in 5 msec", retries);
342 case SSL_ERROR_SYSCALL:
344 TW_LOG(
TW_ERROR,
"TW_SSL_WRITE: Write failed. Error: %s", ERR_error_string(result, NULL));
346 case SSL_ERROR_ZERO_RETURN:
347 TW_LOG(
TW_WARN,
"TW_SSL_WRITE: Zero bytes written.");
364 int32_t res = SSL_get_verify_result(ssl);
365 if( res != X509_V_OK && !(selfSignedOk && (res == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT || res == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN))) {
366 TW_LOG(
TW_ERROR,
"TW_VALIDATE_CERT: Certificate rejected. Code: %d, Reason = %s",res, X509_verify_cert_error_string(res));
367 return TW_INVALID_SSL_CERT;
390 X509_NAME * name = NULL;
391 if (!ssl)
return NULL;
392 cert = SSL_get_peer_certificate(ssl);
393 if (!cert)
return NULL;
396 nid = OBJ_txt2nid(
"CN");
397 name = X509_get_subject_name(cert);
398 X509_NAME_get_text_by_NID(name, nid, tmp, 255);
401 nid = OBJ_txt2nid(
"O");
402 name = X509_get_subject_name(cert);
403 X509_NAME_get_text_by_NID(name, nid, tmp, 255);
406 nid = OBJ_txt2nid(
"OU");
407 name = X509_get_subject_name(cert);
408 X509_NAME_get_text_by_NID(name, nid, tmp, 255);
411 nid = OBJ_txt2nid(
"CN");
412 name = X509_get_issuer_name(cert);
413 X509_NAME_get_text_by_NID(name, nid, tmp, 255);
416 nid = OBJ_txt2nid(
"O");
417 name = X509_get_issuer_name(cert);
418 X509_NAME_get_text_by_NID(name, nid, tmp, 255);
421 nid = OBJ_txt2nid(
"OU");
422 name = X509_get_issuer_name(cert);
423 X509_NAME_get_text_by_NID(name, nid, tmp, 255);
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
DATETIME twGetSystemTime(char utc)
Gets the current system time.
Definition: twIos.c:43
TW_SOCKET_TYPE sock
Definition: twOSPort.h:176
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.
Definition: twLogger.h:30
static INLINE char * TW_GET_X509_FIELD(TW_SSL *ssl, char field)
Gets an X509 field of ssl.
Definition: twOpenSSL.h:385
char twTimeLessThan(DATETIME t1, DATETIME t2)
Compares two DATETIME variables to see if one is smaller.
Definition: twIos.c:35
Definition: twLogger.h:31
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: twLogger.h:27
static INLINE int TW_VALIDATE_CERT(TW_SSL *ssl, char selfSignedOk)
Validates the certificate of ssl.
Definition: twOpenSSL.h:363
static INLINE SSL_CTX * TW_NEW_SSL_CTX_FUNC()
Create a new #SSL_CTX stucture as framework for TLS/SSL enabled functions. Wrapper function for SSL_C...
Definition: twOpenSSL.h:244
uint32_t default_message_timeout
Definition: twDefaultSettings.h:175
static INLINE int TW_ENABLE_FIPS_MODE(TW_SSL_CTX *ctx)
Enables FIPS mode for a twTlsClient.
Definition: twOpenSSL.h:72
Definition: twLogger.h:29
DATETIME twAddMilliseconds(DATETIME t1, int32_t msec)
Adds milliseconds to a DATETIME.
Definition: twIos.c:39
static INLINE int TW_USE_KEY_FILE(SSL_CTX *ctx, const char *file, int type, char *passwd)
Loads the certificate authority cert chain used to validate the server's certificate in file into ctx...
Definition: twOpenSSL.h:226
static INLINE int TW_SSL_WRITE(TW_SSL *ssl, char *buf, int len)
Writes len bytes of data in buf to ssl.
Definition: twOpenSSL.h:326
Structure definitions and function prototypes for the ThingWorx logging facility. ...
char * duplicateString(const char *input)
Copies a string.
Definition: stringUtils.c:38