3 Minimal CyaSSL/OpenSSL Helper
4 Copyright (C) 2006-2009 Jonathan Zarate
5 Copyright (C) 2010 Fedor Kozhevnikov
7 Licensed under GNU GPL v2 or later
23 #include <openssl/ssl.h>
24 #include <openssl/err.h>
26 #include <openssl/rsa.h>
27 #include <openssl/crypto.h>
28 #include <openssl/x509.h>
29 #include <openssl/pem.h>
31 #define _dprintf(args...) while (0) {}
33 const char *allowedCiphers
= "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA";
42 static inline void mssl_print_err(SSL
* ssl
)
44 ERR_print_errors_fp(stderr
);
47 static inline void mssl_cleanup(int err
)
49 if (err
) mssl_print_err(NULL
);
54 static ssize_t
mssl_read(void *cookie
, char *buf
, size_t len
)
56 _dprintf("%s()\n", __FUNCTION__
);
58 mssl_cookie_t
*kuki
= cookie
;
63 n
= SSL_read(kuki
->ssl
, &(buf
[total
]), len
- total
);
64 _dprintf("SSL_read(max=%d) returned %d\n", len
- total
, n
);
66 err
= SSL_get_error(kuki
->ssl
, n
);
71 case SSL_ERROR_ZERO_RETURN
:
74 case SSL_ERROR_WANT_WRITE
:
75 case SSL_ERROR_WANT_READ
:
78 _dprintf("%s(): SSL error %d\n", __FUNCTION__
, err
);
79 mssl_print_err(kuki
->ssl
);
80 if (total
== 0) total
= -1;
83 } while ((len
- total
> 0) && SSL_pending(kuki
->ssl
));
86 _dprintf("%s() returns %d\n", __FUNCTION__
, total
);
90 static ssize_t
mssl_write(void *cookie
, const char *buf
, size_t len
)
92 _dprintf("%s()\n", __FUNCTION__
);
94 mssl_cookie_t
*kuki
= cookie
;
99 n
= SSL_write(kuki
->ssl
, &(buf
[total
]), len
- total
);
100 _dprintf("SSL_write(max=%d) returned %d\n", len
- total
, n
);
101 err
= SSL_get_error(kuki
->ssl
, n
);
106 case SSL_ERROR_ZERO_RETURN
:
109 case SSL_ERROR_WANT_WRITE
:
110 case SSL_ERROR_WANT_READ
:
113 _dprintf("%s(): SSL error %d\n", __FUNCTION__
, err
);
114 mssl_print_err(kuki
->ssl
);
115 if (total
== 0) total
= -1;
121 _dprintf("%s() returns %d\n", __FUNCTION__
, total
);
125 static int mssl_seek(void *cookie
, __offmax_t
*pos
, int whence
)
127 _dprintf("%s()\n", __FUNCTION__
);
132 static int mssl_close(void *cookie
)
134 _dprintf("%s()\n", __FUNCTION__
);
136 mssl_cookie_t
*kuki
= cookie
;
140 SSL_shutdown(kuki
->ssl
);
148 static const cookie_io_functions_t mssl
= {
149 mssl_read
, mssl_write
, mssl_seek
, mssl_close
152 static FILE *_ssl_fopen(int sd
, int client
)
159 _dprintf("%s()\n", __FUNCTION__
);
160 //fprintf(stderr,"[ssl_fopen] ssl_fopen start!\n"); // tmp test
162 if ((kuki
= calloc(1, sizeof(*kuki
))) == NULL
) {
168 // Create new SSL object
169 if ((kuki
->ssl
= SSL_new(ctx
)) == NULL
) {
170 fprintf(stderr
,"[ssl_fopen] SSL_new failed!\n"); // tmp test
171 _dprintf("%s: SSL_new failed\n", __FUNCTION__
);
175 // SSL structure for client authenticate after SSL_new()
176 SSL_set_verify(kuki
->ssl
, SSL_VERIFY_NONE
, NULL
);
177 SSL_set_mode(kuki
->ssl
, SSL_MODE_AUTO_RETRY
);
179 // Bind the socket to SSL structure
180 // kuki->ssl : SSL structure
181 // kuki->sd : socket_fd
184 #ifdef NID_X9_62_prime256v1
186 if (ecdh
= EC_KEY_new_by_curve_name(NID_X9_62_prime256v1
)) {
187 SSL_CTX_set_tmp_ecdh(ctx
, ecdh
);
192 // Setup available ciphers
193 if (SSL_CTX_set_cipher_list(ctx
, allowedCiphers
) != 1) {
197 // Enforce our desired cipher order, disable obsolete protocols
198 SSL_CTX_set_options(ctx
, SSL_OP_NO_SSLv2
|
200 SSL_OP_CIPHER_SERVER_PREFERENCE
|
201 SSL_OP_SAFARI_ECDHE_ECDSA_BUG
);
203 r
= SSL_set_fd(kuki
->ssl
, kuki
->sd
);
204 //fprintf(stderr,"[ssl_fopen] set_fd=%d\n", r); // tmp test
207 // Do the SSL Handshake
208 r
= SSL_accept(kuki
->ssl
);
211 // Connect to the server, SSL layer
212 r
= SSL_connect(kuki
->ssl
);
215 //fprintf(stderr,"[ssl_fopen] client=%d, r=%d\n", client, r); // tmp test
216 // r = 0 show unknown CA, but we don't have any CA, so ignore.
218 // Check error in connect or accept
219 err
= SSL_get_error(kuki
->ssl
, r
);
220 fprintf(stderr
,"[ssl_fopen] SSL error #%d in client=%d\n", err
, client
); // tmp test
221 mssl_print_err(kuki
->ssl
);
225 _dprintf("SSL connection using %s cipher\n", SSL_get_cipher(kuki
->ssl
));
227 if ((f
= fopencookie(kuki
, "r+", mssl
)) == NULL
) {
228 _dprintf("%s: fopencookie failed\n", __FUNCTION__
);
232 //fprintf(stderr,"[ssl_fopen] SUCCESS!\n", r); // tmp test
233 _dprintf("%s() success\n", __FUNCTION__
);
237 fprintf(stderr
,"[ssl_fopen] ERROR!\n"); // tmp test
242 FILE *ssl_server_fopen(int sd
)
244 _dprintf("%s()\n", __FUNCTION__
);
245 return _ssl_fopen(sd
, 0);
248 FILE *ssl_client_fopen(int sd
)
250 _dprintf("%s()\n", __FUNCTION__
);
251 return _ssl_fopen(sd
, 1);
254 int mssl_init(char *cert
, char *priv
)
256 _dprintf("%s()\n", __FUNCTION__
);
258 int server
= (cert
!= NULL
);
259 //fprintf(stderr,"[ssl_init] server=%d\n", server); // tmp test
261 // Register error strings for libcrypto and libssl functions
262 SSL_load_error_strings();
263 SSLeay_add_ssl_algorithms();
265 // Create the new CTX with the method
266 // If server=1, use TLSv1_server_method() or SSLv23_server_method()
267 // else use TLSv1_client_method() or SSLv23_client_method()
268 ctx
= SSL_CTX_new(server
? SSLv23_server_method() : SSLv23_client_method());
271 fprintf(stderr
,"[ssl_init] SSL_CTX_new() failed\n"); // tmp test
272 _dprintf("SSL_CTX_new() failed\n");
273 mssl_print_err(NULL
);
277 SSL_CTX_set_verify(ctx
, SSL_VERIFY_NONE
, NULL
);
280 // Set the certificate to be used
281 _dprintf("SSL_CTX_use_certificate_chain_file(%s)\n", cert
);
282 if (SSL_CTX_use_certificate_chain_file(ctx
, cert
) <= 0) {
283 _dprintf("SSL_CTX_use_certificate_chain_file() failed\n");
287 // Indicate the key file to be used
288 _dprintf("SSL_CTX_use_PrivateKey_file(%s)\n", priv
);
289 if (SSL_CTX_use_PrivateKey_file(ctx
, priv
, SSL_FILETYPE_PEM
) <= 0) {
290 _dprintf("SSL_CTX_use_PrivateKey_file() failed\n");
294 // Make sure the key and certificate file match
295 if (!SSL_CTX_check_private_key(ctx
)) {
296 _dprintf("Private key does not match the certificate public key\n");
302 fprintf(stderr
,"[ssl_init] success!!\n"); // tmp test
303 _dprintf("%s() success\n", __FUNCTION__
);