goahead-openssl.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879
  1. /*
  2. goahead-openssl.c - OpensSSL socket layer for GoAhead
  3. This is the interface between GoAhead and the OpenSSL stack.
  4. Copyright (c) All Rights Reserved. See details at the end of the file.
  5. */
  6. /************************************ Include *********************************/
  7. #include "goahead.h"
  8. #if ME_COM_OPENSSL
  9. #if ME_UNIX_LIKE
  10. /*
  11. Mac OS X OpenSSL stack is deprecated. Suppress those warnings.
  12. */
  13. #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
  14. #endif
  15. /* Clashes with WinCrypt.h */
  16. #undef OCSP_RESPONSE
  17. #ifndef ME_GOAHEAD_SSL_HANDSHAKES
  18. #define ME_GOAHEAD_SSL_HANDSHAKES 0 /* Defaults to infinite */
  19. #endif
  20. #ifndef ME_GOAHEAD_SSL_RENEGOTIATE
  21. #define ME_GOAHEAD_SSL_RENEGOTIATE 1
  22. #endif
  23. /*
  24. Indent includes to bypass MakeMe dependencies
  25. */
  26. #include <openssl/ssl.h>
  27. #include <openssl/evp.h>
  28. #include <openssl/rand.h>
  29. #include <openssl/err.h>
  30. #include <openssl/dh.h>
  31. /************************************* Defines ********************************/
  32. /*
  33. Default ciphers from Mozilla (https://wiki.mozilla.org/Security/Server_Side_TLS) without SSLv3 ciphers.
  34. TLSv1 and TLSv2 only. Recommended RSA and DH parameter size: 2048 bits.
  35. */
  36. #define OPENSSL_DEFAULT_CIPHERS "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4:!SSLv3"
  37. /*
  38. Map Iana names to OpenSSL names
  39. */
  40. typedef struct CipherMap {
  41. int code;
  42. char *name;
  43. char *ossName;
  44. } CipherMap;
  45. static CipherMap cipherMap[] = {
  46. { 0x0004, "TLS_RSA_WITH_RC4_128_MD5", "RC4-MD5" },
  47. { 0x0005, "TLS_RSA_WITH_RC4_128_SHA", "RC4-SHA" },
  48. { 0x0007, "TLS_RSA_WITH_IDEA_CBC_SHA", "IDEA-CBC-SHA" },
  49. { 0x0009, "TLS_RSA_WITH_DES_CBC_SHA", "DES-CBC-SHA" },
  50. { 0x000A, "TLS_RSA_WITH_3DES_EDE_CBC_SHA", "DES-CBC3-SHA" },
  51. { 0x000C, "TLS_DH_DSS_WITH_DES_CBC_SHA", "DH-DSS-DES-CBC-SHA" },
  52. { 0x000D, "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA", "DH-DSS-DES-CBC3-SHA" },
  53. { 0x000F, "TLS_DH_RSA_WITH_DES_CBC_SHA", "DH-RSA-DES-CBC-SHA" },
  54. { 0x0010, "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA", "DH-RSA-DES-CBC3-SHA" },
  55. { 0x0012, "TLS_DHE_DSS_WITH_DES_CBC_SHA", "EDH-DSS-DES-CBC-SHA" },
  56. { 0x0013, "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA", "EDH-DSS-DES-CBC3-SHA" },
  57. { 0x0015, "TLS_DHE_RSA_WITH_DES_CBC_SHA", "EDH-RSA-DES-CBC-SHA" },
  58. { 0x0016, "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA", "EDH-RSA-DES-CBC3-SHA" },
  59. { 0x002F, "TLS_RSA_WITH_AES_128_CBC_SHA", "AES128-SHA" },
  60. { 0x0030, "TLS_DH_DSS_WITH_AES_128_CBC_SHA", "DH-DSS-AES128-SHA" },
  61. { 0x0031, "TLS_DH_RSA_WITH_AES_128_CBC_SHA", "DH-RSA-AES128-SHA" },
  62. { 0x0032, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA", "DHE-DSS-AES128-SHA" },
  63. { 0x0033, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", "DHE-RSA-AES128-SHA" },
  64. { 0x0035, "TLS_RSA_WITH_AES_256_CBC_SHA", "AES256-SHA" },
  65. { 0x0036, "TLS_DH_DSS_WITH_AES_256_CBC_SHA", "DH-DSS-AES256-SHA" },
  66. { 0x0037, "TLS_DH_RSA_WITH_AES_256_CBC_SHA", "DH-RSA-AES256-SHA" },
  67. { 0x0038, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA", "DHE-DSS-AES256-SHA" },
  68. { 0x0039, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA", "DHE-RSA-AES256-SHA" },
  69. { 0x003C, "TLS_RSA_WITH_AES_128_CBC_SHA256", "AES128-SHA256" },
  70. { 0x003D, "TLS_RSA_WITH_AES_256_CBC_SHA256", "AES256-SHA256" },
  71. { 0x003E, "TLS_DH_DSS_WITH_AES_128_CBC_SHA256", "DH-DSS-AES128-SHA256" },
  72. { 0x003F, "TLS_DH_RSA_WITH_AES_128_CBC_SHA256", "DH-RSA-AES128-SHA256" },
  73. { 0x0040, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256", "DHE-DSS-AES128-SHA256" },
  74. { 0x0041, "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA", "CAMELLIA128-SHA" },
  75. { 0x0042, "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA", "DH-DSS-CAMELLIA128-SHA" },
  76. { 0x0043, "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA", "DH-RSA-CAMELLIA128-SHA" },
  77. { 0x0044, "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA", "DHE-DSS-CAMELLIA128-SHA" },
  78. { 0x0045, "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA", "DHE-RSA-CAMELLIA128-SHA" },
  79. { 0x0067, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256", "DHE-RSA-AES128-SHA256" },
  80. { 0x0068, "TLS_DH_DSS_WITH_AES_256_CBC_SHA256", "DH-DSS-AES256-SHA256" },
  81. { 0x0069, "TLS_DH_RSA_WITH_AES_256_CBC_SHA256", "DH-RSA-AES256-SHA256" },
  82. { 0x006A, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256", "DHE-DSS-AES256-SHA256" },
  83. { 0x006B, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256", "DHE-RSA-AES256-SHA256" },
  84. { 0x0084, "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA", "CAMELLIA256-SHA" },
  85. { 0x0085, "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA", "DH-DSS-CAMELLIA256-SHA" },
  86. { 0x0086, "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA", "DH-RSA-CAMELLIA256-SHA" },
  87. { 0x0087, "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA", "DHE-DSS-CAMELLIA256-SHA" },
  88. { 0x0088, "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA", "DHE-RSA-CAMELLIA256-SHA" },
  89. { 0x008A, "TLS_PSK_WITH_RC4_128_SHA", "PSK-RC4-SHA" },
  90. { 0x008B, "TLS_PSK_WITH_3DES_EDE_CBC_SHA", "PSK-3DES-EDE-CBC-SHA" },
  91. { 0x008C, "TLS_PSK_WITH_AES_128_CBC_SHA", "PSK-AES128-CBC-SHA" },
  92. { 0x008D, "TLS_PSK_WITH_AES_256_CBC_SHA", "PSK-AES256-CBC-SHA" },
  93. { 0x0096, "TLS_RSA_WITH_SEED_CBC_SHA", "SEED-SHA" },
  94. { 0x0097, "TLS_DH_DSS_WITH_SEED_CBC_SHA", "DH-DSS-SEED-SHA" },
  95. { 0x0098, "TLS_DH_RSA_WITH_SEED_CBC_SHA", "DH-RSA-SEED-SHA" },
  96. { 0x0099, "TLS_DHE_DSS_WITH_SEED_CBC_SHA", "DHE-DSS-SEED-SHA" },
  97. { 0x009A, "TLS_DHE_RSA_WITH_SEED_CBC_SHA", "DHE-RSA-SEED-SHA" },
  98. { 0x009C, "TLS_RSA_WITH_AES_128_GCM_SHA256", "AES128-GCM-SHA256" },
  99. { 0x009D, "TLS_RSA_WITH_AES_256_GCM_SHA384", "AES256-GCM-SHA384" },
  100. { 0x009E, "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", "DHE-RSA-AES128-GCM-SHA256" },
  101. { 0x009F, "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", "DHE-RSA-AES256-GCM-SHA384" },
  102. { 0x00A0, "TLS_DH_RSA_WITH_AES_128_GCM_SHA256", "DH-RSA-AES128-GCM-SHA256" },
  103. { 0x00A1, "TLS_DH_RSA_WITH_AES_256_GCM_SHA384", "DH-RSA-AES256-GCM-SHA384" },
  104. { 0x00A2, "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256", "DHE-DSS-AES128-GCM-SHA256" },
  105. { 0x00A3, "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384", "DHE-DSS-AES256-GCM-SHA384" },
  106. { 0x00A4, "TLS_DH_DSS_WITH_AES_128_GCM_SHA256", "DH-DSS-AES128-GCM-SHA256" },
  107. { 0x00A5, "TLS_DH_DSS_WITH_AES_256_GCM_SHA384", "DH-DSS-AES256-GCM-SHA384" },
  108. { 0xC002, "TLS_ECDH_ECDSA_WITH_RC4_128_SHA", "ECDH-ECDSA-RC4-SHA" },
  109. { 0xC003, "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA", "ECDH-ECDSA-DES-CBC3-SHA" },
  110. { 0xC004, "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA", "ECDH-ECDSA-AES128-SHA" },
  111. { 0xC005, "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA", "ECDH-ECDSA-AES256-SHA" },
  112. { 0xC007, "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", "ECDHE-ECDSA-RC4-SHA" },
  113. { 0xC008, "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", "ECDHE-ECDSA-DES-CBC3-SHA" },
  114. { 0xC009, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", "ECDHE-ECDSA-AES128-SHA" },
  115. { 0xC00A, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", "ECDHE-ECDSA-AES256-SHA" },
  116. { 0xC00C, "TLS_ECDH_RSA_WITH_RC4_128_SHA", "ECDH-RSA-RC4-SHA" },
  117. { 0xC00D, "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA", "ECDH-RSA-DES-CBC3-SHA" },
  118. { 0xC00E, "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA", "ECDH-RSA-AES128-SHA" },
  119. { 0xC00F, "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA", "ECDH-RSA-AES256-SHA" },
  120. { 0xC011, "TLS_ECDHE_RSA_WITH_RC4_128_SHA", "ECDHE-RSA-RC4-SHA" },
  121. { 0xC012, "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", "ECDHE-RSA-DES-CBC3-SHA" },
  122. { 0xC013, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", "ECDHE-RSA-AES128-SHA" },
  123. { 0xC014, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", "ECDHE-RSA-AES256-SHA" },
  124. { 0xC01A, "TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA", "SRP-3DES-EDE-CBC-SHA" },
  125. { 0xC01B, "TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA", "SRP-RSA-3DES-EDE-CBC-SHA" },
  126. { 0xC01C, "TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA", "SRP-DSS-3DES-EDE-CBC-SHA" },
  127. { 0xC01D, "TLS_SRP_SHA_WITH_AES_128_CBC_SHA", "SRP-AES-128-CBC-SHA" },
  128. { 0xC01E, "TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA", "SRP-RSA-AES-128-CBC-SHA" },
  129. { 0xC01F, "TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA", "SRP-DSS-AES-128-CBC-SHA" },
  130. { 0xC020, "TLS_SRP_SHA_WITH_AES_256_CBC_SHA", "SRP-AES-256-CBC-SHA" },
  131. { 0xC021, "TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA", "SRP-RSA-AES-256-CBC-SHA" },
  132. { 0xC022, "TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA", "SRP-DSS-AES-256-CBC-SHA" },
  133. { 0xC023, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", "ECDHE-ECDSA-AES128-SHA256" },
  134. { 0xC024, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", "ECDHE-ECDSA-AES256-SHA384" },
  135. { 0xC025, "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256", "ECDH-ECDSA-AES128-SHA256" },
  136. { 0xC026, "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384", "ECDH-ECDSA-AES256-SHA384" },
  137. { 0xC027, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", "ECDHE-RSA-AES128-SHA256" },
  138. { 0xC028, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", "ECDHE-RSA-AES256-SHA384" },
  139. { 0xC029, "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256", "ECDH-RSA-AES128-SHA256" },
  140. { 0xC02A, "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384", "ECDH-RSA-AES256-SHA384" },
  141. { 0xC02B, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "ECDHE-ECDSA-AES128-GCM-SHA256" },
  142. { 0xC02C, "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "ECDHE-ECDSA-AES256-GCM-SHA384" },
  143. { 0xC02D, "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", "ECDH-ECDSA-AES128-GCM-SHA256" },
  144. { 0xC02E, "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384", "ECDH-ECDSA-AES256-GCM-SHA384" },
  145. { 0xC02F, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "ECDHE-RSA-AES128-GCM-SHA256" },
  146. { 0xC030, "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "ECDHE-RSA-AES256-GCM-SHA384" },
  147. { 0xC031, "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256", "ECDH-RSA-AES128-GCM-SHA256" },
  148. { 0xC032, "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384", "ECDH-RSA-AES256-GCM-SHA384" },
  149. { 0x0000, 0 },
  150. };
  151. /*
  152. OpenSSL context (singleton)
  153. */
  154. static SSL_CTX *sslctx = NULL;
  155. typedef struct RandBuf {
  156. time_t now;
  157. int pid;
  158. } RandBuf;
  159. #define VERIFY_DEPTH 10
  160. /*
  161. Used for OpenSSL versions < 1.0.2
  162. */
  163. #ifndef ME_GOAHEAD_SSL_CURVE
  164. #define ME_GOAHEAD_SSL_CURVE "prime256v1"
  165. #endif
  166. /*
  167. DH parameters
  168. */
  169. static DH *dhKey;
  170. static int maxHandshakes;
  171. /************************************ Forwards ********************************/
  172. static DH *dhcallback(SSL *handle, int is_export, int keylength);
  173. static DH *getDhKey();
  174. static char *mapCipherNames(char *ciphers);
  175. static int sslSetCertFile(char *certFile);
  176. static int sslSetKeyFile(char *keyFile);
  177. static int verifyClientCertificate(int ok, X509_STORE_CTX *ctx);
  178. static void infoCallback(const SSL *ssl, int where, int rc);
  179. /************************************** Code **********************************/
  180. /*
  181. Open the SSL module
  182. */
  183. PUBLIC int sslOpen()
  184. {
  185. RandBuf randBuf;
  186. X509_STORE *store;
  187. uchar resume[16];
  188. char *ciphers;
  189. trace(7, "Initializing SSL");
  190. randBuf.now = time(0);
  191. randBuf.pid = getpid();
  192. RAND_seed((void*) &randBuf, sizeof(randBuf));
  193. #if ME_UNIX_LIKE
  194. trace(6, "OpenSsl: Before calling RAND_load_file");
  195. RAND_load_file("/dev/urandom", 256);
  196. trace(6, "OpenSsl: After calling RAND_load_file");
  197. #endif
  198. CRYPTO_malloc_init();
  199. #if !ME_WIN_LIKE
  200. OpenSSL_add_all_algorithms();
  201. #endif
  202. SSL_library_init();
  203. SSL_load_error_strings();
  204. SSLeay_add_ssl_algorithms();
  205. if ((sslctx = SSL_CTX_new(SSLv23_server_method())) == 0) {
  206. error("Unable to create SSL context");
  207. return -1;
  208. }
  209. /*
  210. Set the server certificate and key files
  211. */
  212. if (*ME_GOAHEAD_SSL_KEY && sslSetKeyFile(ME_GOAHEAD_SSL_KEY) < 0) {
  213. sslClose();
  214. return -1;
  215. }
  216. if (*ME_GOAHEAD_SSL_CERTIFICATE && sslSetCertFile(ME_GOAHEAD_SSL_CERTIFICATE) < 0) {
  217. sslClose();
  218. return -1;
  219. }
  220. if (ME_GOAHEAD_SSL_VERIFY_PEER) {
  221. SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verifyClientCertificate);
  222. SSL_CTX_set_verify_depth(sslctx, VERIFY_DEPTH);
  223. } else {
  224. SSL_CTX_set_verify(sslctx, SSL_VERIFY_NONE, verifyClientCertificate);
  225. }
  226. /*
  227. Set the client certificate verification locations
  228. */
  229. if (ME_GOAHEAD_SSL_AUTHORITY && *ME_GOAHEAD_SSL_AUTHORITY) {
  230. if ((!SSL_CTX_load_verify_locations(sslctx, ME_GOAHEAD_SSL_AUTHORITY, NULL)) ||
  231. (!SSL_CTX_set_default_verify_paths(sslctx))) {
  232. error("Unable to read cert verification locations");
  233. sslClose();
  234. return -1;
  235. }
  236. /*
  237. Define the list of CA certificates to send to the client before they send their client
  238. certificate for validation
  239. */
  240. SSL_CTX_set_client_CA_list(sslctx, SSL_load_client_CA_file(ME_GOAHEAD_SSL_AUTHORITY));
  241. }
  242. if (ME_GOAHEAD_SSL_REVOKE && *ME_GOAHEAD_SSL_REVOKE) {
  243. store = SSL_CTX_get_cert_store(sslctx);
  244. if (!X509_STORE_load_locations(store, ME_GOAHEAD_SSL_REVOKE, 0)) {
  245. error("Cannot load certificate revoke list: %s", ME_GOAHEAD_SSL_REVOKE);
  246. sslClose();
  247. return -1;
  248. }
  249. }
  250. /*
  251. Configure DH parameters
  252. */
  253. dhKey = getDhKey();
  254. SSL_CTX_set_tmp_dh_callback(sslctx, dhcallback);
  255. /*
  256. Configure cipher suite
  257. */
  258. if (ME_GOAHEAD_SSL_CIPHERS && *ME_GOAHEAD_SSL_CIPHERS) {
  259. ciphers = ME_GOAHEAD_SSL_CIPHERS;
  260. } else {
  261. ciphers = OPENSSL_DEFAULT_CIPHERS;
  262. }
  263. ciphers = mapCipherNames(ciphers);
  264. trace(5, "Using OpenSSL ciphers: %s", ciphers);
  265. if (SSL_CTX_set_cipher_list(sslctx, ciphers) != 1) {
  266. error("Unable to set cipher list \"%s\"", ciphers);
  267. sslClose();
  268. wfree(ciphers);
  269. return -1;
  270. }
  271. wfree(ciphers);
  272. /*
  273. Define default OpenSSL options
  274. */
  275. SSL_CTX_set_options(sslctx, SSL_OP_ALL);
  276. /*
  277. Ensure we generate a new private key for each connection
  278. */
  279. SSL_CTX_set_options(sslctx, SSL_OP_SINGLE_DH_USE);
  280. /*
  281. Define a session reuse context
  282. */
  283. RAND_bytes(resume, sizeof(resume));
  284. SSL_CTX_set_session_id_context(sslctx, resume, sizeof(resume));
  285. /*
  286. Elliptic Curve initialization
  287. */
  288. #if SSL_OP_SINGLE_ECDH_USE
  289. #ifdef SSL_CTX_set_ecdh_auto
  290. SSL_CTX_set_ecdh_auto(sslctx, 1);
  291. #else
  292. {
  293. EC_KEY *ecdh;
  294. cchar *name;
  295. int nid;
  296. name = ME_GOAHEAD_SSL_CURVE;
  297. if ((nid = OBJ_sn2nid(name)) == 0) {
  298. error("Unknown curve name \"%s\"", name);
  299. sslClose();
  300. return -1;
  301. }
  302. if ((ecdh = EC_KEY_new_by_curve_name(nid)) == 0) {
  303. error("Unable to create curve \"%s\"", name);
  304. sslClose();
  305. return -1;
  306. }
  307. SSL_CTX_set_options(sslctx, SSL_OP_SINGLE_ECDH_USE);
  308. SSL_CTX_set_tmp_ecdh(sslctx, ecdh);
  309. EC_KEY_free(ecdh);
  310. }
  311. #endif
  312. #endif
  313. SSL_CTX_set_mode(sslctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
  314. #ifdef SSL_OP_MSIE_SSLV2_RSA_PADDING
  315. SSL_CTX_set_options(sslctx, SSL_OP_MSIE_SSLV2_RSA_PADDING);
  316. #endif
  317. #ifdef SSL_MODE_RELEASE_BUFFERS
  318. SSL_CTX_set_mode(sslctx, SSL_MODE_RELEASE_BUFFERS);
  319. #endif
  320. #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
  321. SSL_CTX_set_mode(sslctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
  322. #endif
  323. /*
  324. Select the required protocols
  325. Disable both SSLv2 and SSLv3 by default - they are insecure
  326. */
  327. SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv2);
  328. SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv3);
  329. #if defined(SSL_OP_NO_TLSv1) && ME_GOAHEAD_SSL_NO_V1
  330. SSL_CTX_set_options(sslctx, SSL_OP_NO_TLSv1);
  331. #endif
  332. #if defined(SSL_OP_NO_TLSv1_1) && ME_GOAHEAD_SSL_NO_V1_1
  333. SSL_CTX_set_options(sslctx, SSL_OP_NO_TLSv1_1);
  334. #endif
  335. #if defined(SSL_OP_NO_TLSv1_2) && ME_GOAHEAD_SSL_NO_V1_2
  336. SSL_CTX_set_options(sslctx, SSL_OP_NO_TLSv1_2);
  337. #endif
  338. #if defined(SSL_OP_NO_TICKET)
  339. /*
  340. Ticket based session reuse is enabled by default
  341. */
  342. #if defined(ME_GOAHEAD_SSL_TICKET)
  343. if (ME_GOAHEAD_SSL_TICKET) {
  344. SSL_CTX_clear_options(sslctx, SSL_OP_NO_TICKET);
  345. } else {
  346. SSL_CTX_set_options(sslctx, SSL_OP_NO_TICKET);
  347. }
  348. #else
  349. SSL_CTX_clear_options(sslctx, SSL_OP_NO_TICKET);
  350. #endif
  351. #endif
  352. #if defined(SSL_OP_NO_COMPRESSION)
  353. /*
  354. CRIME attack targets compression
  355. */
  356. SSL_CTX_clear_options(sslctx, SSL_OP_NO_COMPRESSION);
  357. #endif
  358. #if defined(ME_GOAHEAD_SSL_HANDSHAKES)
  359. maxHandshakes = ME_GOAHEAD_SSL_HANDSHAKES;
  360. #endif
  361. #if defined(SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)
  362. /*
  363. Disables a countermeasure against a SSL 3.0/TLS 1.0 protocol vulnerability affecting CBC ciphers.
  364. Defaults to true.
  365. */
  366. #if defined(ME_GOAHEAD_SSL_EMPTY_FRAGMENTS)
  367. if (ME_GOAHEAD_SSL_EMPTY_FRAGMENTS) {
  368. /* SSL_OP_ALL disables empty fragments. Only needed for ancient browsers like IE-6 on SSL-3.0/TLS-1.0 */
  369. SSL_CTX_clear_options(sslctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
  370. } else {
  371. SSL_CTX_set_options(sslctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
  372. }
  373. #else
  374. SSL_CTX_set_options(sslctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
  375. #endif
  376. #endif
  377. #if defined(ME_GOAHEAD_SSL_CACHE)
  378. /*
  379. Set the number of sessions supported. Default in OpenSSL is 20K.
  380. */
  381. SSL_CTX_sess_set_cache_size(sslctx, ME_GOAHEAD_SSL_CACHE);
  382. #else
  383. SSL_CTX_sess_set_cache_size(sslctx, 256);
  384. #endif
  385. return 0;
  386. }
  387. /*
  388. Close the SSL module
  389. */
  390. PUBLIC void sslClose()
  391. {
  392. if (sslctx != NULL) {
  393. SSL_CTX_free(sslctx);
  394. sslctx = NULL;
  395. if (dhKey) {
  396. DH_free(dhKey);
  397. dhKey = NULL;
  398. }
  399. }
  400. }
  401. /*
  402. Upgrade a socket to use SSL
  403. */
  404. PUBLIC int sslUpgrade(Webs *wp)
  405. {
  406. WebsSocket *sptr;
  407. BIO *bio;
  408. assert(wp);
  409. sptr = socketPtr(wp->sid);
  410. if ((wp->ssl = SSL_new(sslctx)) == 0) {
  411. return -1;
  412. }
  413. /*
  414. Create a socket bio. We don't use the BIO except as storage for the fd.
  415. */
  416. if ((bio = BIO_new_socket((int) sptr->sock, BIO_NOCLOSE)) == 0) {
  417. return -1;
  418. }
  419. SSL_set_bio(wp->ssl, bio, bio);
  420. SSL_set_accept_state(wp->ssl);
  421. SSL_set_app_data(wp->ssl, (void*) wp);
  422. if (ME_GOAHEAD_SSL_HANDSHAKES) {
  423. SSL_CTX_set_info_callback(sslctx, infoCallback);
  424. }
  425. return 0;
  426. }
  427. static void infoCallback(const SSL *ssl, int where, int rc)
  428. {
  429. Webs *wp;
  430. WebsSocket *sp;
  431. if (where & SSL_CB_HANDSHAKE_START) {
  432. if ((wp = (Webs*) SSL_get_app_data(ssl)) == 0) {
  433. return;
  434. }
  435. if ((sp = socketPtr(wp->sid)) != 0) {
  436. sp->handshakes++;
  437. }
  438. }
  439. }
  440. PUBLIC void sslFree(Webs *wp)
  441. {
  442. if (wp->ssl) {
  443. SSL_set_shutdown(wp->ssl, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
  444. SSL_free(wp->ssl);
  445. wp->ssl = 0;
  446. }
  447. }
  448. /*
  449. Return the number of bytes read. Return -1 on errors and EOF. Distinguish EOF via mprIsSocketEof.
  450. If non-blocking, may return zero if no data or still handshaking.
  451. */
  452. PUBLIC ssize sslRead(Webs *wp, void *buf, ssize len)
  453. {
  454. WebsSocket *sp;
  455. char ebuf[ME_GOAHEAD_LIMIT_STRING];
  456. ulong serror;
  457. int rc, err, retries, i;
  458. if (wp->ssl == 0 || len <= 0) {
  459. return -1;
  460. }
  461. /*
  462. Limit retries on WANT_READ. If non-blocking and no data, then this can spin forever.
  463. */
  464. sp = socketPtr(wp->sid);
  465. retries = 5;
  466. for (i = 0; i < retries; i++) {
  467. rc = SSL_read(wp->ssl, buf, (int) len);
  468. if (rc < 0) {
  469. err = SSL_get_error(wp->ssl, rc);
  470. if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_CONNECT || err == SSL_ERROR_WANT_ACCEPT) {
  471. continue;
  472. }
  473. serror = ERR_get_error();
  474. ERR_error_string_n(serror, ebuf, sizeof(ebuf) - 1);
  475. trace(5, "SSL_read %s", ebuf);
  476. }
  477. break;
  478. }
  479. if (maxHandshakes && sp->handshakes > maxHandshakes) {
  480. error("TLS renegotiation attack");
  481. rc = -1;
  482. sp->flags |= SOCKET_EOF;
  483. return -1;
  484. }
  485. if (rc <= 0) {
  486. err = SSL_get_error(wp->ssl, rc);
  487. if (err == SSL_ERROR_WANT_READ) {
  488. rc = 0;
  489. } else if (err == SSL_ERROR_WANT_WRITE) {
  490. rc = 0;
  491. } else if (err == SSL_ERROR_ZERO_RETURN) {
  492. sp->flags |= SOCKET_EOF;
  493. rc = -1;
  494. } else if (err == SSL_ERROR_SYSCALL) {
  495. sp->flags |= SOCKET_EOF;
  496. rc = -1;
  497. } else if (err != SSL_ERROR_ZERO_RETURN) {
  498. serror = ERR_get_error();
  499. ERR_error_string_n(serror, ebuf, sizeof(ebuf) - 1);
  500. trace(4, "OpenSSL: connection with protocol error: %s", ebuf);
  501. rc = -1;
  502. sp->flags |= SOCKET_EOF;
  503. }
  504. } else if (SSL_pending(wp->ssl) > 0) {
  505. socketHiddenData(sp, SSL_pending(wp->ssl), SOCKET_READABLE);
  506. }
  507. return rc;
  508. }
  509. PUBLIC ssize sslWrite(Webs *wp, void *buf, ssize len)
  510. {
  511. WebsSocket *sp;
  512. ssize totalWritten;
  513. int err, rc;
  514. if (wp->ssl == 0 || len <= 0) {
  515. return -1;
  516. }
  517. sp = socketPtr(wp->sid);
  518. totalWritten = 0;
  519. err = 0;
  520. ERR_clear_error();
  521. do {
  522. rc = SSL_write(wp->ssl, buf, (int) len);
  523. trace(7, "OpenSSL: written %d, requested len %d", rc, len);
  524. if (rc <= 0) {
  525. err = SSL_get_error(wp->ssl, rc);
  526. if (err == SSL_ERROR_NONE || err == SSL_ERROR_WANT_WRITE) {
  527. break;
  528. }
  529. trace(7, "OpenSSL: error %d", err);
  530. return -1;
  531. } else if (maxHandshakes && sp->handshakes > maxHandshakes) {
  532. error("TLS renegotiation attack");
  533. rc = -1;
  534. sp->flags |= SOCKET_EOF;
  535. return -1;
  536. }
  537. totalWritten += rc;
  538. buf = (void*) ((char*) buf + rc);
  539. len -= rc;
  540. trace(7, "OpenSSL: write: len %d, written %d, total %d", len, rc, totalWritten);
  541. } while (len > 0);
  542. if (totalWritten == 0 && err == SSL_ERROR_WANT_WRITE) {
  543. socketSetError(EAGAIN);
  544. return -1;
  545. }
  546. return totalWritten;
  547. }
  548. /*
  549. Set certificate file for SSL context
  550. */
  551. static int sslSetCertFile(char *certFile)
  552. {
  553. X509 *cert;
  554. BIO *bio;
  555. char *buf;
  556. int rc;
  557. assert(sslctx);
  558. assert(certFile);
  559. rc = -1;
  560. bio = 0;
  561. buf = 0;
  562. cert = 0;
  563. if (sslctx == NULL) {
  564. return rc;
  565. }
  566. if ((buf = websReadWholeFile(certFile)) == 0) {
  567. error("Unable to read certificate %s", certFile);
  568. } else if ((bio = BIO_new_mem_buf(buf, -1)) == 0) {
  569. error("Unable to allocate memory for certificate %s", certFile);
  570. } else if ((cert = PEM_read_bio_X509(bio, NULL, 0, NULL)) == 0) {
  571. error("Unable to parse certificate %s", certFile);
  572. } else if (SSL_CTX_use_certificate(sslctx, cert) != 1) {
  573. error("Unable to use certificate %s", certFile);
  574. } else if (!SSL_CTX_check_private_key(sslctx)) {
  575. error("Unable to check certificate key %s", certFile);
  576. } else {
  577. rc = 0;
  578. }
  579. wfree(buf);
  580. if (bio) {
  581. BIO_free(bio);
  582. }
  583. if (cert) {
  584. X509_free(cert);
  585. }
  586. return rc;
  587. }
  588. /*
  589. Set key file for SSL context
  590. */
  591. static int sslSetKeyFile(char *keyFile)
  592. {
  593. RSA *key;
  594. BIO *bio;
  595. char *buf;
  596. int rc;
  597. assert(sslctx);
  598. assert(keyFile);
  599. key = 0;
  600. bio = 0;
  601. buf = 0;
  602. rc = -1;
  603. if (sslctx == NULL) {
  604. ;
  605. } else if ((buf = websReadWholeFile(keyFile)) == 0) {
  606. error("Unable to read certificate %s", keyFile);
  607. } else if ((bio = BIO_new_mem_buf(buf, -1)) == 0) {
  608. error("Unable to allocate memory for key %s", keyFile);
  609. } else if ((key = PEM_read_bio_RSAPrivateKey(bio, NULL, 0, NULL)) == 0) {
  610. error("Unable to parse key %s", keyFile);
  611. } else if (SSL_CTX_use_RSAPrivateKey(sslctx, key) != 1) {
  612. error("Unable to use key %s", keyFile);
  613. } else {
  614. rc = 0;
  615. }
  616. wfree(buf);
  617. if (bio) {
  618. BIO_free(bio);
  619. }
  620. if (key) {
  621. RSA_free(key);
  622. }
  623. return rc;
  624. }
  625. static int verifyClientCertificate(int ok, X509_STORE_CTX *xContext)
  626. {
  627. X509 *cert;
  628. char subject[260], issuer[260], peer[260];
  629. int error, depth;
  630. subject[0] = issuer[0] = '\0';
  631. cert = X509_STORE_CTX_get_current_cert(xContext);
  632. error = X509_STORE_CTX_get_error(xContext);
  633. depth = X509_STORE_CTX_get_error_depth(xContext);
  634. ok = 1;
  635. if (X509_NAME_oneline(X509_get_subject_name(cert), subject, sizeof(subject) - 1) < 0) {
  636. ok = 0;
  637. }
  638. if (X509_NAME_oneline(X509_get_issuer_name(xContext->current_cert), issuer, sizeof(issuer) - 1) < 0) {
  639. ok = 0;
  640. }
  641. if (X509_NAME_get_text_by_NID(X509_get_subject_name(xContext->current_cert), NID_commonName, peer,
  642. sizeof(peer) - 1) < 0) {
  643. ok = 0;
  644. }
  645. if (ok && VERIFY_DEPTH < depth) {
  646. if (error == 0) {
  647. error = X509_V_ERR_CERT_CHAIN_TOO_LONG;
  648. }
  649. }
  650. switch (error) {
  651. case X509_V_OK:
  652. break;
  653. case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
  654. case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
  655. if (ME_GOAHEAD_SSL_VERIFY_ISSUER) {
  656. logmsg(3, "Self-signed certificate");
  657. ok = 0;
  658. }
  659. case X509_V_ERR_CERT_UNTRUSTED:
  660. case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
  661. if (ME_GOAHEAD_SSL_VERIFY_ISSUER) {
  662. logmsg(3, "Certificate not trusted");
  663. ok = 0;
  664. }
  665. break;
  666. case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
  667. case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
  668. if (ME_GOAHEAD_SSL_VERIFY_ISSUER) {
  669. logmsg(3, "Certificate not trusted");
  670. ok = 0;
  671. }
  672. break;
  673. case X509_V_ERR_CERT_CHAIN_TOO_LONG:
  674. case X509_V_ERR_CERT_HAS_EXPIRED:
  675. case X509_V_ERR_CERT_NOT_YET_VALID:
  676. case X509_V_ERR_CERT_REJECTED:
  677. case X509_V_ERR_CERT_SIGNATURE_FAILURE:
  678. case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
  679. case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
  680. case X509_V_ERR_INVALID_CA:
  681. default:
  682. logmsg(3, "Certificate verification error %d", error);
  683. ok = 0;
  684. break;
  685. }
  686. if (ok) {
  687. trace(3, "OpenSSL: Certificate verified: subject %s", subject);
  688. } else {
  689. trace(1, "OpenSSL: Certification failed: subject %s (more trace at level 4)", subject);
  690. trace(4, "OpenSSL: Error: %d: %s", error, X509_verify_cert_error_string(error));
  691. }
  692. trace(4, "OpenSSL: Issuer: %s", issuer);
  693. trace(4, "OpenSSL: Peer: %s", peer);
  694. return ok;
  695. }
  696. /*
  697. Map iana names to OpenSSL names so users can provide IANA names as well as OpenSSL cipher names
  698. */
  699. static char *mapCipherNames(char *ciphers)
  700. {
  701. WebsBuf buf;
  702. CipherMap *cp;
  703. char *cipher, *next, *str;
  704. if (!ciphers || *ciphers == 0) {
  705. return 0;
  706. }
  707. bufCreate(&buf, 0, 0);
  708. ciphers = sclone(ciphers);
  709. for (next = ciphers; (cipher = stok(next, ":, \t", &next)) != 0; ) {
  710. for (cp = cipherMap; cp->name; cp++) {
  711. if (smatch(cp->name, cipher)) {
  712. bufPut(&buf, "%s:", cp->ossName);
  713. break;
  714. }
  715. }
  716. if (cp->name == 0) {
  717. bufPut(&buf, "%s:", cipher);
  718. }
  719. }
  720. wfree(ciphers);
  721. str = sclone(bufStart(&buf));
  722. bufFree(&buf);
  723. return str;
  724. }
  725. /*
  726. Get the DH parameters
  727. */
  728. static DH *getDhKey()
  729. {
  730. static unsigned char dh2048_p[] = {
  731. 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
  732. 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
  733. 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
  734. 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
  735. 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
  736. 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
  737. 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
  738. 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
  739. 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
  740. 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
  741. 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
  742. 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
  743. 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
  744. 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
  745. 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
  746. 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  747. };
  748. static unsigned char dh2048_g[] = {
  749. 0x02,
  750. };
  751. DH *dh;
  752. if ((dh = DH_new()) == 0) {
  753. return 0;
  754. }
  755. dh->p = BN_bin2bn(dh2048_p, sizeof(dh2048_p), NULL);
  756. dh->g = BN_bin2bn(dh2048_g, sizeof(dh2048_g), NULL);
  757. if ((dh->p == 0) || (dh->g == 0)) {
  758. DH_free(dh);
  759. return 0;
  760. }
  761. return dh;
  762. }
  763. /*
  764. Set the ephemeral DH key
  765. */
  766. static DH *dhcallback(SSL *handle, int isExport, int keyLength)
  767. {
  768. return dhKey;
  769. }
  770. void opensslDummy() {}
  771. #endif
  772. /*
  773. Copyright (c) Embedthis Software. All Rights Reserved.
  774. This software is distributed under commercial and open source licenses.
  775. You may use the Embedthis GoAhead open source license or you may acquire
  776. a commercial license from Embedthis Software. You agree to be fully bound
  777. by the terms of either license. Consult the LICENSE.md distributed with
  778. this software for full details and other copyrights.
  779. */