mbedtls_stubs.c 18 KB

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