mbedtls_stubs.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  1. #include <string.h>
  2. #include <stdio.h>
  3. #ifdef _WIN32
  4. #include <windows.h>
  5. #include <wincrypt.h>
  6. #endif
  7. #ifdef __APPLE__
  8. #include <Security/Security.h>
  9. #endif
  10. #include <caml/mlvalues.h>
  11. #include <caml/alloc.h>
  12. #include <caml/memory.h>
  13. #include <caml/fail.h>
  14. #include <caml/callback.h>
  15. #include <caml/custom.h>
  16. #include "mbedtls/error.h"
  17. #include "mbedtls/ssl.h"
  18. #include "mbedtls/entropy.h"
  19. #include "mbedtls/ctr_drbg.h"
  20. #include "mbedtls/oid.h"
  21. #define PVoid_val(v) (*((void**) Data_custom_val(v)))
  22. void debug(void* ctx, int debug_level, const char* file_name, int line, const char* message) {
  23. printf("%s:%i: %s", file_name, line, message);
  24. }
  25. #define Val_none Val_int(0)
  26. static value Val_some(value v) {
  27. CAMLparam1(v);
  28. CAMLlocal1(some);
  29. some = caml_alloc(1, 0);
  30. Store_field(some, 0, v);
  31. CAMLreturn(some);
  32. }
  33. CAMLprim value ml_mbedtls_strerror(value code) {
  34. CAMLparam1(code);
  35. CAMLlocal1(r);
  36. char buf[128];
  37. mbedtls_strerror(Int_val(code), buf, sizeof(buf));
  38. r = caml_copy_string(buf);
  39. CAMLreturn(r);
  40. }
  41. // CtrDrbg
  42. #define CtrDrbg_val(v) (*((mbedtls_ctr_drbg_context**) Data_custom_val(v)))
  43. static void ml_mbedtls_ctr_drbg_finalize(value v) {
  44. mbedtls_ctr_drbg_context* ctr_drbg = CtrDrbg_val(v);
  45. if (ctr_drbg != NULL) {
  46. mbedtls_ctr_drbg_free(ctr_drbg);
  47. }
  48. }
  49. static struct custom_operations ctr_drbg_ops = {
  50. .identifier = "ml_ctr_drbg",
  51. .finalize = ml_mbedtls_ctr_drbg_finalize,
  52. .compare = custom_compare_default,
  53. .hash = custom_hash_default,
  54. .serialize = custom_serialize_default,
  55. .deserialize = custom_deserialize_default,
  56. };
  57. CAMLprim value ml_mbedtls_ctr_drbg_init(void) {
  58. CAMLparam0();
  59. CAMLlocal1(obj);
  60. obj = caml_alloc_custom(&ctr_drbg_ops, sizeof(mbedtls_ctr_drbg_context*), 0, 1);
  61. mbedtls_ctr_drbg_context* ctr_drbg = malloc(sizeof(mbedtls_ctr_drbg_context));
  62. mbedtls_ctr_drbg_init(ctr_drbg);
  63. CtrDrbg_val(obj) = ctr_drbg;
  64. CAMLreturn(obj);
  65. }
  66. CAMLprim value ml_mbedtls_ctr_drbg_random(value p_rng, value output, value output_len) {
  67. CAMLparam3(p_rng, output, output_len);
  68. CAMLreturn(Val_int(mbedtls_ctr_drbg_random(CtrDrbg_val(p_rng), Bytes_val(output), Int_val(output_len))));
  69. }
  70. CAMLprim value ml_mbedtls_ctr_drbg_seed(value ctx, value p_entropy, value custom) {
  71. CAMLparam2(ctx, custom);
  72. CAMLreturn(Val_int(mbedtls_ctr_drbg_seed(CtrDrbg_val(ctx), mbedtls_entropy_func, PVoid_val(p_entropy), NULL, 0)));
  73. }
  74. // Entropy
  75. #define Entropy_val(v) (*((mbedtls_entropy_context**) Data_custom_val(v)))
  76. static void ml_mbedtls_entropy_finalize(value v) {
  77. mbedtls_entropy_context* entropy = Entropy_val(v);
  78. if (entropy != NULL) {
  79. mbedtls_entropy_free(entropy);
  80. }
  81. }
  82. static struct custom_operations entropy_ops = {
  83. .identifier = "ml_entropy",
  84. .finalize = ml_mbedtls_entropy_finalize,
  85. .compare = custom_compare_default,
  86. .hash = custom_hash_default,
  87. .serialize = custom_serialize_default,
  88. .deserialize = custom_deserialize_default,
  89. };
  90. CAMLprim value ml_mbedtls_entropy_init(void) {
  91. CAMLparam0();
  92. CAMLlocal1(obj);
  93. obj = caml_alloc_custom(&entropy_ops, sizeof(mbedtls_entropy_context*), 0, 1);
  94. mbedtls_entropy_context* entropy = malloc(sizeof(mbedtls_entropy_context));
  95. mbedtls_entropy_init(entropy);
  96. Entropy_val(obj) = entropy;
  97. CAMLreturn(obj);
  98. }
  99. CAMLprim value ml_mbedtls_entropy_func(value data, value output, value len) {
  100. CAMLparam3(data, output, len);
  101. CAMLreturn(Val_int(mbedtls_entropy_func(PVoid_val(data), Bytes_val(output), Int_val(len))));
  102. }
  103. // Certificate
  104. #define X509Crt_val(v) (*((mbedtls_x509_crt**) Data_custom_val(v)))
  105. static void ml_mbedtls_x509_crt_finalize(value v) {
  106. mbedtls_x509_crt* x509_crt = X509Crt_val(v);
  107. if (x509_crt != NULL) {
  108. mbedtls_x509_crt_free(x509_crt);
  109. }
  110. }
  111. static struct custom_operations x509_crt_ops = {
  112. .identifier = "ml_x509_crt",
  113. .finalize = ml_mbedtls_x509_crt_finalize,
  114. .compare = custom_compare_default,
  115. .hash = custom_hash_default,
  116. .serialize = custom_serialize_default,
  117. .deserialize = custom_deserialize_default,
  118. };
  119. CAMLprim value ml_mbedtls_x509_crt_init(void) {
  120. CAMLparam0();
  121. CAMLlocal1(obj);
  122. obj = caml_alloc_custom(&x509_crt_ops, sizeof(mbedtls_x509_crt*), 0, 1);
  123. mbedtls_x509_crt* x509_crt = malloc(sizeof(mbedtls_x509_crt));
  124. mbedtls_x509_crt_init(x509_crt);
  125. X509Crt_val(obj) = x509_crt;
  126. CAMLreturn(obj);
  127. }
  128. CAMLprim value ml_mbedtls_x509_next(value chain) {
  129. CAMLparam1(chain);
  130. CAMLlocal2(r, obj);
  131. mbedtls_x509_crt* cert = X509Crt_val(chain);
  132. if (cert->next == NULL) {
  133. CAMLreturn(Val_none);
  134. }
  135. obj = caml_alloc_custom(&x509_crt_ops, sizeof(mbedtls_x509_crt*), 0, 1);
  136. X509Crt_val(obj) = cert->next;
  137. CAMLreturn(Val_some(obj));
  138. }
  139. CAMLprim value ml_mbedtls_x509_crt_parse(value chain, value bytes) {
  140. CAMLparam2(chain, bytes);
  141. const unsigned char* buf = Bytes_val(bytes);
  142. int len = caml_string_length(bytes);
  143. CAMLreturn(Val_int(mbedtls_x509_crt_parse(X509Crt_val(chain), buf, len + 1)));
  144. }
  145. CAMLprim value ml_mbedtls_x509_crt_parse_file(value chain, value path) {
  146. CAMLparam2(chain, path);
  147. CAMLreturn(Val_int(mbedtls_x509_crt_parse_file(X509Crt_val(chain), String_val(path))));
  148. }
  149. CAMLprim value ml_mbedtls_x509_crt_parse_path(value chain, value path) {
  150. CAMLparam2(chain, path);
  151. CAMLreturn(Val_int(mbedtls_x509_crt_parse_path(X509Crt_val(chain), String_val(path))));
  152. }
  153. // Certificate Haxe API
  154. value caml_string_of_asn1_buf(mbedtls_asn1_buf* dat) {
  155. CAMLparam0();
  156. CAMLlocal1(s);
  157. s = caml_alloc_initialized_string(dat->len, (const char *)dat->p);
  158. CAMLreturn(s);
  159. }
  160. CAMLprim value hx_cert_get_alt_names(value chain) {
  161. CAMLparam1(chain);
  162. CAMLlocal1(obj);
  163. mbedtls_x509_crt* cert = X509Crt_val(chain);
  164. #if MBEDTLS_VERSION_MAJOR >= 3
  165. if (!mbedtls_x509_crt_has_ext_type(cert, MBEDTLS_X509_EXT_SUBJECT_ALT_NAME)) {
  166. #else
  167. if ((cert->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) == 0) {
  168. #endif
  169. obj = Atom(0);
  170. } else {
  171. mbedtls_asn1_sequence* cur = &cert->subject_alt_names;
  172. int i = 0;
  173. while (cur != NULL) {
  174. ++i;
  175. cur = cur->next;
  176. }
  177. obj = caml_alloc(i, 0);
  178. cur = &cert->subject_alt_names;
  179. i = 0;
  180. while (cur != NULL) {
  181. Store_field(obj, i, caml_string_of_asn1_buf(&cur->buf));
  182. ++i;
  183. cur = cur->next;
  184. }
  185. }
  186. CAMLreturn(obj);
  187. }
  188. CAMLprim value hx_cert_get_subject(value chain, value objname) {
  189. CAMLparam2(chain, objname);
  190. mbedtls_x509_name *obj;
  191. mbedtls_x509_crt* cert = X509Crt_val(chain);
  192. const char *oname, *rname;
  193. obj = &cert->subject;
  194. rname = String_val(objname);
  195. while (obj != NULL) {
  196. int r = mbedtls_oid_get_attr_short_name(&obj->oid, &oname);
  197. if (r == 0 && strcmp(oname, rname) == 0) {
  198. CAMLreturn(Val_some(caml_string_of_asn1_buf(&obj->val)));
  199. }
  200. obj = obj->next;
  201. }
  202. CAMLreturn(Val_none);
  203. }
  204. CAMLprim value hx_cert_get_issuer(value chain, value objname) {
  205. CAMLparam2(chain, objname);
  206. mbedtls_x509_name *obj;
  207. mbedtls_x509_crt* cert = X509Crt_val(chain);
  208. int r;
  209. const char *oname, *rname;
  210. obj = &cert->issuer;
  211. rname = String_val(objname);
  212. while (obj != NULL) {
  213. r = mbedtls_oid_get_attr_short_name(&obj->oid, &oname);
  214. if (r == 0 && strcmp(oname, rname) == 0) {
  215. CAMLreturn(Val_some(caml_string_of_asn1_buf(&obj->val)));
  216. }
  217. obj = obj->next;
  218. }
  219. CAMLreturn(Val_none);
  220. }
  221. time_t time_to_time_t(mbedtls_x509_time* t) {
  222. struct tm info;
  223. info.tm_year = t->year - 1900;
  224. info.tm_mon = t->mon - 1;
  225. info.tm_mday = t->day;
  226. info.tm_hour = t->hour;
  227. info.tm_min = t->min;
  228. info.tm_sec = t->sec;
  229. return mktime(&info);
  230. }
  231. CAMLprim value hx_cert_get_notafter(value chain) {
  232. CAMLparam1(chain);
  233. mbedtls_x509_crt* cert = X509Crt_val(chain);
  234. mbedtls_x509_time *t = &cert->valid_to;
  235. time_t time = time_to_time_t(t);
  236. CAMLreturn(caml_copy_double((double)time));
  237. }
  238. CAMLprim value hx_cert_get_notbefore(value chain) {
  239. CAMLparam1(chain);
  240. mbedtls_x509_crt* cert = X509Crt_val(chain);
  241. mbedtls_x509_time *t = &cert->valid_from;
  242. time_t time = time_to_time_t(t);
  243. CAMLreturn(caml_copy_double((double)time));
  244. }
  245. // Config
  246. #define Config_val(v) (*((mbedtls_ssl_config**) Data_custom_val(v)))
  247. static void ml_mbedtls_ssl_config_finalize(value v) {
  248. mbedtls_ssl_config* ssl_config = Config_val(v);
  249. if (ssl_config != NULL) {
  250. mbedtls_ssl_config_free(ssl_config);
  251. }
  252. }
  253. static struct custom_operations ssl_config_ops = {
  254. .identifier = "ml_ssl_config",
  255. .finalize = ml_mbedtls_ssl_config_finalize,
  256. .compare = custom_compare_default,
  257. .hash = custom_hash_default,
  258. .serialize = custom_serialize_default,
  259. .deserialize = custom_deserialize_default,
  260. };
  261. CAMLprim value ml_mbedtls_ssl_config_init(void) {
  262. CAMLparam0();
  263. CAMLlocal1(obj);
  264. obj = caml_alloc_custom(&ssl_config_ops, sizeof(mbedtls_ssl_config*), 0, 1);
  265. mbedtls_ssl_config* ssl_config = malloc(sizeof(mbedtls_ssl_config));
  266. mbedtls_ssl_config_init(ssl_config);
  267. Config_val(obj) = ssl_config;
  268. CAMLreturn(obj);
  269. }
  270. CAMLprim value ml_mbedtls_ssl_conf_authmode(value conf, value authmode) {
  271. CAMLparam2(conf, authmode);
  272. mbedtls_ssl_conf_authmode(Config_val(conf), Int_val(authmode));
  273. CAMLreturn(Val_unit);
  274. }
  275. CAMLprim value ml_mbedtls_ssl_conf_ca_chain(value conf, value ca_chain) {
  276. CAMLparam2(conf, ca_chain);
  277. mbedtls_ssl_conf_ca_chain(Config_val(conf), X509Crt_val(ca_chain), NULL);
  278. CAMLreturn(Val_unit);
  279. }
  280. CAMLprim value ml_mbedtls_ssl_config_defaults(value conf, value endpoint, value transport, value preset) {
  281. CAMLparam4(conf, endpoint, transport, preset);
  282. CAMLreturn(Val_int(mbedtls_ssl_config_defaults(Config_val(conf), Int_val(endpoint), Int_val(transport), Int_val(preset))));
  283. }
  284. CAMLprim value ml_mbedtls_ssl_conf_rng(value conf, value p_rng) {
  285. CAMLparam2(conf, p_rng);
  286. mbedtls_ssl_conf_rng(Config_val(conf), mbedtls_ctr_drbg_random, PVoid_val(p_rng));
  287. CAMLreturn(Val_unit);
  288. }
  289. // Pk
  290. #define PkContext_val(v) (*((mbedtls_pk_context**) Data_custom_val(v)))
  291. static void ml_mbedtls_pk_context_finalize(value v) {
  292. mbedtls_pk_context* pk_context = PkContext_val(v);
  293. if (pk_context != NULL) {
  294. mbedtls_pk_free(pk_context);
  295. }
  296. }
  297. static struct custom_operations pk_context_ops = {
  298. .identifier = "ml_pk_context",
  299. .finalize = ml_mbedtls_pk_context_finalize,
  300. .compare = custom_compare_default,
  301. .hash = custom_hash_default,
  302. .serialize = custom_serialize_default,
  303. .deserialize = custom_deserialize_default,
  304. };
  305. CAMLprim value ml_mbedtls_pk_init(void) {
  306. CAMLparam0();
  307. CAMLlocal1(obj);
  308. obj = caml_alloc_custom(&pk_context_ops, sizeof(mbedtls_pk_context*), 0, 1);
  309. mbedtls_pk_context* pk_context = malloc(sizeof(mbedtls_pk_context));
  310. mbedtls_pk_init(pk_context);
  311. PkContext_val(obj) = pk_context;
  312. CAMLreturn(obj);
  313. }
  314. CAMLprim value ml_mbedtls_pk_parse_key(value ctx, value key, value password, value rng) {
  315. CAMLparam4(ctx, key, password, rng);
  316. const unsigned char* pwd = NULL;
  317. size_t pwdlen = 0;
  318. if (password != Val_none) {
  319. pwd = Bytes_val(Field(password, 0));
  320. pwdlen = caml_string_length(Field(password, 0));
  321. }
  322. #if MBEDTLS_VERSION_MAJOR >= 3
  323. mbedtls_ctr_drbg_context *ctr_drbg = CtrDrbg_val(rng);
  324. CAMLreturn(mbedtls_pk_parse_key(PkContext_val(ctx), Bytes_val(key), caml_string_length(key) + 1, pwd, pwdlen, mbedtls_ctr_drbg_random, NULL));
  325. #else
  326. CAMLreturn(mbedtls_pk_parse_key(PkContext_val(ctx), Bytes_val(key), caml_string_length(key) + 1, pwd, pwdlen));
  327. #endif
  328. }
  329. CAMLprim value ml_mbedtls_pk_parse_keyfile(value ctx, value path, value password, value rng) {
  330. CAMLparam4(ctx, path, password, rng);
  331. const char* pwd = NULL;
  332. if (password != Val_none) {
  333. pwd = String_val(Field(password, 0));
  334. }
  335. #if MBEDTLS_VERSION_MAJOR >= 3
  336. mbedtls_ctr_drbg_context *ctr_drbg = CtrDrbg_val(rng);
  337. CAMLreturn(mbedtls_pk_parse_keyfile(PkContext_val(ctx), String_val(path), pwd, mbedtls_ctr_drbg_random, ctr_drbg));
  338. #else
  339. CAMLreturn(mbedtls_pk_parse_keyfile(PkContext_val(ctx), String_val(path), pwd));
  340. #endif
  341. }
  342. CAMLprim value ml_mbedtls_pk_parse_public_key(value ctx, value key) {
  343. CAMLparam2(ctx, key);
  344. CAMLreturn(mbedtls_pk_parse_public_key(PkContext_val(ctx), Bytes_val(key), caml_string_length(key) + 1));
  345. }
  346. CAMLprim value ml_mbedtls_pk_parse_public_keyfile(value ctx, value path) {
  347. CAMLparam2(ctx, path);
  348. CAMLreturn(mbedtls_pk_parse_public_keyfile(PkContext_val(ctx), String_val(path)));
  349. }
  350. // Ssl
  351. #define SslContext_val(v) (*((mbedtls_ssl_context**) Data_custom_val(v)))
  352. static void ml_mbedtls_ssl_context_finalize(value v) {
  353. mbedtls_ssl_context* ssl_context = SslContext_val(v);
  354. if (ssl_context != NULL) {
  355. mbedtls_ssl_free(ssl_context);
  356. }
  357. }
  358. static struct custom_operations ssl_context_ops = {
  359. .identifier = "ml_ssl_context",
  360. .finalize = ml_mbedtls_ssl_context_finalize,
  361. .compare = custom_compare_default,
  362. .hash = custom_hash_default,
  363. .serialize = custom_serialize_default,
  364. .deserialize = custom_deserialize_default,
  365. };
  366. CAMLprim value ml_mbedtls_ssl_init(void) {
  367. CAMLparam0();
  368. CAMLlocal1(obj);
  369. obj = caml_alloc_custom(&ssl_context_ops, sizeof(mbedtls_ssl_context*), 0, 1);
  370. mbedtls_ssl_context* ssl_context = malloc(sizeof(mbedtls_ssl_context));
  371. mbedtls_ssl_init(ssl_context);
  372. SslContext_val(obj) = ssl_context;
  373. CAMLreturn(obj);
  374. }
  375. CAMLprim value ml_mbedtls_ssl_get_peer_cert(value ssl) {
  376. CAMLparam1(ssl);
  377. CAMLlocal1(obj);
  378. mbedtls_ssl_context* ssl_context = SslContext_val(ssl);
  379. mbedtls_x509_crt* crt = (mbedtls_x509_crt*)mbedtls_ssl_get_peer_cert(ssl_context);
  380. if (crt == NULL) {
  381. CAMLreturn(Val_none);
  382. }
  383. obj = caml_alloc_custom(&x509_crt_ops, sizeof(mbedtls_x509_crt*), 0, 1);
  384. X509Crt_val(obj) = crt;
  385. CAMLreturn(Val_some(obj));
  386. }
  387. CAMLprim value ml_mbedtls_ssl_handshake(value ssl) {
  388. CAMLparam1(ssl);
  389. CAMLreturn(Val_int(mbedtls_ssl_handshake(SslContext_val(ssl))));
  390. }
  391. CAMLprim value ml_mbedtls_ssl_read(value ssl, value buf, value pos, value len) {
  392. CAMLparam4(ssl, buf, pos, len);
  393. CAMLreturn(Val_int(mbedtls_ssl_read(SslContext_val(ssl), Bytes_val(buf) + Int_val(pos), Int_val(len))));
  394. }
  395. static int bio_write_cb(void* ctx, const unsigned char* buf, size_t len) {
  396. CAMLparam0();
  397. CAMLlocal3(r, s, vctx);
  398. vctx = *(value*)ctx;
  399. s = caml_alloc_initialized_string(len, (const char*)buf);
  400. r = caml_callback2(Field(vctx, 1), Field(vctx, 0), s);
  401. CAMLreturn(Int_val(r));
  402. }
  403. static int bio_read_cb(void* ctx, unsigned char* buf, size_t len) {
  404. CAMLparam0();
  405. CAMLlocal3(r, s, vctx);
  406. vctx = *(value*)ctx;
  407. s = caml_alloc_string(len);
  408. r = caml_callback2(Field(vctx, 2), Field(vctx, 0), s);
  409. memcpy(buf, String_val(s), len);
  410. CAMLreturn(Int_val(r));
  411. }
  412. CAMLprim value ml_mbedtls_ssl_set_bio(value ssl, value p_bio, value f_send, value f_recv) {
  413. CAMLparam4(ssl, p_bio, f_send, f_recv);
  414. CAMLlocal1(ctx);
  415. ctx = caml_alloc(3, 0);
  416. Store_field(ctx, 0, p_bio);
  417. Store_field(ctx, 1, f_send);
  418. Store_field(ctx, 2, f_recv);
  419. // TODO: this allocation is leaked
  420. value *location = malloc(sizeof(value));
  421. *location = ctx;
  422. caml_register_generational_global_root(location);
  423. mbedtls_ssl_set_bio(SslContext_val(ssl), (void*)location, bio_write_cb, bio_read_cb, NULL);
  424. CAMLreturn(Val_unit);
  425. }
  426. CAMLprim value ml_mbedtls_ssl_set_hostname(value ssl, value hostname) {
  427. CAMLparam2(ssl, hostname);
  428. CAMLreturn(Val_int(mbedtls_ssl_set_hostname(SslContext_val(ssl), String_val(hostname))));
  429. }
  430. CAMLprim value ml_mbedtls_ssl_setup(value ssl, value conf) {
  431. CAMLparam2(ssl, conf);
  432. CAMLreturn(Val_int(mbedtls_ssl_setup(SslContext_val(ssl), Config_val(conf))));
  433. }
  434. CAMLprim value ml_mbedtls_ssl_write(value ssl, value buf, value pos, value len) {
  435. CAMLparam4(ssl, buf, pos, len);
  436. CAMLreturn(Val_int(mbedtls_ssl_write(SslContext_val(ssl), Bytes_val(buf) + Int_val(pos), Int_val(len))));
  437. }
  438. // glue
  439. CAMLprim value hx_cert_load_defaults(value certificate) {
  440. CAMLparam1(certificate);
  441. int r = 1;
  442. mbedtls_x509_crt *chain = X509Crt_val(certificate);
  443. #ifdef _WIN32
  444. HCERTSTORE store;
  445. PCCERT_CONTEXT cert;
  446. if (store = CertOpenSystemStore(0, "Root")) {
  447. cert = NULL;
  448. while (cert = CertEnumCertificatesInStore(store, cert)) {
  449. r = mbedtls_x509_crt_parse_der(chain, (unsigned char *)cert->pbCertEncoded, cert->cbCertEncoded);
  450. if (r != 0) {
  451. CAMLreturn(Val_int(r));
  452. }
  453. }
  454. CertCloseStore(store, 0);
  455. }
  456. #endif
  457. #ifdef __APPLE__
  458. CFArrayRef certs;
  459. if (SecTrustCopyAnchorCertificates(&certs) == errSecSuccess) {
  460. CFIndex count = CFArrayGetCount(certs);
  461. for(CFIndex i = 0; i < count; i++) {
  462. SecCertificateRef item = (SecCertificateRef)CFArrayGetValueAtIndex(certs, i);
  463. // Get certificate in DER format
  464. CFDataRef data = SecCertificateCopyData(item);
  465. if(data) {
  466. r = mbedtls_x509_crt_parse_der(chain, (unsigned char *)CFDataGetBytePtr(data), CFDataGetLength(data));
  467. CFRelease(data);
  468. if (r != 0) {
  469. CAMLreturn(Val_int(r));
  470. }
  471. }
  472. }
  473. CFRelease(certs);
  474. }
  475. #endif
  476. CAMLreturn(Val_int(r));
  477. }
  478. static value build_fields(int num_fields, const char* names[], int values[]) {
  479. CAMLparam0();
  480. CAMLlocal2(ret, tuple);
  481. ret = caml_alloc(num_fields, 0);
  482. for (int i = 0; i < num_fields; ++i) {
  483. tuple = caml_alloc_tuple(2);
  484. Store_field(tuple, 0, caml_copy_string(names[i]));
  485. Store_field(tuple, 1, Val_int(values[i]));
  486. Store_field(ret, i, tuple);
  487. }
  488. CAMLreturn(ret);
  489. }
  490. CAMLprim value hx_get_ssl_authmode_flags(value unit) {
  491. CAMLparam1(unit);
  492. const char* names[] = {"SSL_VERIFY_NONE", "SSL_VERIFY_OPTIONAL", "SSL_VERIFY_REQUIRED"};
  493. int values[] = {MBEDTLS_SSL_VERIFY_NONE, MBEDTLS_SSL_VERIFY_OPTIONAL, MBEDTLS_SSL_VERIFY_REQUIRED};
  494. CAMLreturn(build_fields(sizeof(values) / sizeof(values[0]), names, values));
  495. }
  496. CAMLprim value hx_get_ssl_endpoint_flags(value unit) {
  497. CAMLparam1(unit);
  498. const char* names[] = {"SSL_IS_CLIENT", "SSL_IS_SERVER"};
  499. int values[] = {MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_IS_SERVER};
  500. CAMLreturn(build_fields(sizeof(values) / sizeof(values[0]), names, values));
  501. }
  502. CAMLprim value hx_get_ssl_preset_flags(value unit) {
  503. CAMLparam1(unit);
  504. const char* names[] = {"SSL_PRESET_DEFAULT", "SSL_PRESET_SUITEB"};
  505. int values[] = {MBEDTLS_SSL_PRESET_DEFAULT, MBEDTLS_SSL_PRESET_SUITEB};
  506. CAMLreturn(build_fields(sizeof(values) / sizeof(values[0]), names, values));
  507. }
  508. CAMLprim value hx_get_ssl_transport_flags(value unit) {
  509. CAMLparam1(unit);
  510. const char* names[] = {"SSL_TRANSPORT_STREAM", "SSL_TRANSPORT_DATAGRAM"};
  511. int values[] = {MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_TRANSPORT_DATAGRAM};
  512. CAMLreturn(build_fields(sizeof(values) / sizeof(values[0]), names, values));
  513. }