aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/restricted/aws/s2n/api/s2n.h
blob: adc970386c8d8157700d30466ba887b6798d5be9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

/**
 * @file s2n.h
 * s2n-tls is a C99 implementation of the TLS/SSL protocols that is designed to
 * be simple, small, fast, and with security as a priority. <br> It is released and 
 * licensed under the Apache License 2.0.
 */

#pragma once

#if ((__GNUC__ >= 4) || defined(__clang__)) && defined(S2N_EXPORTS)
/**
 * Marks a function as belonging to the public s2n API.
 */
#    define S2N_API __attribute__((visibility("default")))
#else
/**
 * Marks a function as belonging to the public s2n API.
 */
#    define S2N_API
#endif /* __GNUC__ >= 4 || defined(__clang__) */

#ifdef __cplusplus
extern "C" {
#endif

#include <sys/types.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/uio.h>

/**
 *  Function return code
 */
#define S2N_SUCCESS 0
/**
 * Function return code
 */
#define S2N_FAILURE -1

/**
 * Callback return code 
 */
#define S2N_CALLBACK_BLOCKED -2

/**
 * s2n minimum supported TLS record major version 
 */
#define S2N_MINIMUM_SUPPORTED_TLS_RECORD_MAJOR_VERSION 2

/**
 * s2n maximum supported TLS record major version
 */
#define S2N_MAXIMUM_SUPPORTED_TLS_RECORD_MAJOR_VERSION 3
    
/**
 * s2n SSL 2.0 Version Constant
 */
#define S2N_SSLv2 20

/**
 * s2n SSL 3.0 Version Constant
 */
#define S2N_SSLv3 30

/**
 * s2n TLS 1.0 Version Constant
 */
#define S2N_TLS10 31

/**
 * s2n TLS 1.1 Version Constant
 */
#define S2N_TLS11 32

/**
 * s2n TLS 1.2 Version Constant
 */
#define S2N_TLS12 33
    
/**
 * s2n TLS 1.3 Version Constant
 */
#define S2N_TLS13 34

/**
 * s2n Unknown TLS Version
 */
#define S2N_UNKNOWN_PROTOCOL_VERSION 0

/** 
 * s2n-tls functions that return 'int' return 0 to indicate success and -1 to indicate
 * failure. 
 *
 * s2n-tls functions that return pointer types return NULL in the case of
 * failure. 
 *
 * When an s2n-tls function returns a failure, s2n_errno will be set to a value
 * corresponding to the error. This error value can be translated into a string
 * explaining the error in English by calling s2n_strerror(s2n_errno, "EN").
 * A string containing human readable error name; can be generated with `s2n_strerror_name`.
 * A string containing internal debug information, including filename and line number, can be generated with `s2n_strerror_debug`.
 * This string is useful to include when reporting issues to the s2n-tls development team.
 *
 * @warning To avoid possible confusion, s2n_errno should be cleared after processing an error: `s2n_errno = S2N_ERR_T_OK`
 */
S2N_API
extern __thread int s2n_errno;

/**
 * This function can be used instead of trying to resolve `s2n_errno` directly
 * in runtimes where thread-local variables may not be easily accessible.
 *
 * @returns The address of the thread-local `s2n_errno` variable
 */
S2N_API
extern int *s2n_errno_location(void);

/**
 * Used to help applications determine why an s2n-tls function failed.
 *
 * This enum is optimized for use in C switch statements. Each value in the enum represents
 * an error "category".
 */
typedef enum {
    S2N_ERR_T_OK=0,
    S2N_ERR_T_IO,
    S2N_ERR_T_CLOSED,
    S2N_ERR_T_BLOCKED,
    S2N_ERR_T_ALERT,
    S2N_ERR_T_PROTO,
    S2N_ERR_T_INTERNAL,
    S2N_ERR_T_USAGE
} s2n_error_type;

/**
 * Gets the category of error from an error.
 * 
 * s2n-tls organizes errors into different "types" to allow applications to do logic on error values without catching all possibilities.
 * Applications using non-blocking I/O should check error type to determine if the I/O operation failed because 
 * it would block or for some other error.
 *
 * @param error The error from s2n. Usually this is `s2n_errno`.
 * @returns An s2n_error_type
 */
S2N_API
extern int s2n_error_get_type(int error);

/**
 * An opaque configuration object, used by clients and servers for holding cryptographic certificates, keys and preferences.
 */
struct s2n_config;

/**
 * An opaque connection. Used to track each s2n connection.
 */
struct s2n_connection;

/**
 * Prevents S2N from calling `OPENSSL_crypto_init`/`OPENSSL_cleanup`/`EVP_cleanup` on OpenSSL versions
 * prior to 1.1.x. This allows applications or languages that also init OpenSSL to interoperate
 * with S2N.
 *
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_crypto_disable_init(void);

/**
 * Prevents S2N from installing an atexit handler, which allows safe shutdown of S2N from within a
 * re-entrant shared library
 *
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_disable_atexit(void);

/**
 * Fetches the OpenSSL version s2n-tls was compiled with. This can be used by applications to validate at runtime
 * that the versions of s2n-tls and Openssl that they have loaded are correct.
 *
 * @returns the version number of OpenSSL that s2n-tls was compiled with 
 */
S2N_API
extern unsigned long s2n_get_openssl_version(void);

/**
 * Initializes the s2n-tls library and should be called once in your application, before any other s2n-tls
 * functions are called. Failure to call s2n_init() will result in errors from other s2n-tls functions.
 *
 * @warning This function is not thread safe and should only be called once.
 *
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_init(void);

/**
 * Cleans up any internal resources used by s2n-tls. This function should be called from each thread or process
 * that is created subsequent to calling `s2n_init` when that thread or process is done calling other s2n-tls functions.
 *
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_cleanup(void);

/**
 * Create a new s2n_config object. This object can (and should) be associated with many connection objects.
 *
 * @returns returns a new configuration object suitable for associating certs and keys. 
 */
S2N_API
extern struct s2n_config *s2n_config_new(void);

/**
 * Frees the memory associated with an `s2n_config` object.
 *
 * @param config The configuration object being freed
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_config_free(struct s2n_config *config);

/**
 * Frees the DH params associated with an `s2n_config` object.
 *
 * @param config The configuration object with DH params being freed
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_config_free_dhparams(struct s2n_config *config);

/**
 * Frees the certificate chain and key associated with an `s2n_config` object.
 *
 * @param config The configuration object with DH params being freed
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_config_free_cert_chain_and_key(struct s2n_config *config);

/**
 * Callback function type used to get the system time.
 *
 * Takes two arguments. A pointer to arbitrary data for use within the callback and a pointer to a 64 bit int.
 * the callback and a pointer to a 64 bit int. The 64 bit pointer should be set to the
 * number of nanoseconds since the Unix epoch.
 *
 * The function should return 0 on success and -1 on failure.
 */
typedef int (*s2n_clock_time_nanoseconds) (void *, uint64_t *);

/**
 * Cache callback function that allows the caller to retrieve SSL session data
 * from a cache. 
 *
 * The callback function takes six arguments:
 * a pointer to the s2n_connection object, 
 * a pointer to arbitrary data for use within the callback, 
 * a pointer to a key which can be used to retrieve the cached entry, 
 * a 64 bit unsigned integer specifying the size of this key, 
 * a pointer to a memory location where the value should be stored, 
 * and a pointer to a 64 bit unsigned integer specifying the size of this value. 
 *
 * Initially *value_size will be set to the amount of space allocated for the value,
 * the callback should set *value_size to the actual size of the data returned. 
 * If there is insufficient space, -1 should be returned. 
 * If the cache is not ready to provide data for the request, 
 * S2N_CALLBACK_BLOCKED should be returned. 
 *
 * This will cause s2n_negotiate() to return S2N_BLOCKED_ON_APPLICATION_INPUT.
 */
typedef int (*s2n_cache_retrieve_callback) (struct s2n_connection *conn, void *, const void *key, uint64_t key_size, void *value, uint64_t *value_size);

/**
 * Cache callback function that allows the caller to store SSL session data in a
 * cache. 
 *
 * The callback function takes seven arguments:
 * a pointer to the s2n_connection object, 
 * a pointer to arbitrary data for use within the callback, 
 * a 64-bit unsigned integer specifying the number of seconds the session data may be stored for, 
 * a pointer to a key which can be used to retrieve the cached entry,
 * a 64 bit unsigned integer specifying the size of this key, 
 * a pointer to a value which should be stored, 
 * and a 64 bit unsigned integer specified the size of this value.
 */
typedef int (*s2n_cache_store_callback) (struct s2n_connection *conn, void *, uint64_t ttl_in_seconds, const void *key, uint64_t key_size, const void *value, uint64_t value_size);

/**
*  Cache callback function that allows the caller to set a callback function 
*  that will be used to delete SSL session data from a cache. 
*
*  The callback function takes four arguments:
*  a pointer to s2n_connection object,
*  a pointer to arbitrary data for use within the callback, 
*  a pointer to a key which can be used to delete the cached entry, 
*  and a 64 bit unsigned integer specifying the size of this key.
*/ 
typedef int (*s2n_cache_delete_callback) (struct s2n_connection *conn,  void *, const void *key, uint64_t key_size);

/** 
 * Allows the caller to set a callback function that will be used to get the
 * system time. 
 * @param config The configuration object being updated
 * @param clock_fn The wall clock time callback function
 * @param ctx An opaque pointer that the callback will be invoked with
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_config_set_wall_clock(struct s2n_config *config, s2n_clock_time_nanoseconds clock_fn, void *ctx);

/** 
 * Allows the caller to set a callback function that will be used to get 
 * monotonic time.
 * @param config The configuration object being updated
 * @param clock_fn The monotonic time callback function
 * @param ctx An opaque pointer that the callback will be invoked with
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_config_set_monotonic_clock(struct s2n_config *config, s2n_clock_time_nanoseconds clock_fn, void *ctx);

/**
 * Translates an s2n_error code to a human readable string explaining the error.
 *
 * @param error The error code to explain. Usually this is s2n_errno
 * @param lang The language to explain the error code. Pass "EN" or NULL for English.
 * @returns The error string
 */
S2N_API
extern const char *s2n_strerror(int error, const char *lang);

/**
 * Translates an s2n_error code to a human readable string containing internal debug
 * information, including file name and line number. This function is useful when
 * reporting issues to the s2n-tls development team.
 *
 * @param error The error code to explain. Usually this is s2n_errno
 * @param lang The language to explain the error code. Pass "EN" or NULL for English.
 * @returns The error string
 */
S2N_API
extern const char *s2n_strerror_debug(int error, const char *lang);

/**
 * Translates an s2n_error code to a human readable string.
 *
 * @param error The error code to explain. Usually this is s2n_errno
 * @returns The error string
 */
S2N_API
extern const char *s2n_strerror_name(int error); 

/**
 * Opaque stack trace structure.
 */
struct s2n_stacktrace;

/**
 * Checks if s2n stack trace captures are enabled.
 *
 * @returns True if stack traces are enabled. False if they are disabled.
 */
S2N_API
extern bool s2n_stack_traces_enabled(void);

/**
 * Configures the s2n stack trace captures option.
 *
 * @param newval Boolean to determine if stack traces should be enabled. True to enable them. False to disable them.
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_stack_traces_enabled_set(bool newval);

/**
 * Calculates the s2n stack trace.
 *
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_calculate_stacktrace(void);

/**
 * Prints the s2n stack trace to a file. The file descriptor is expected to be
 * open and ready for writing.
 *
 * @param fptr A pointer to the file s2n-tls should write the stack trace to.
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_print_stacktrace(FILE *fptr);

/**
 * Clean up the memory used to contain the stack trace.
 *
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_free_stacktrace(void);

/**
 * Export the s2n_stacktrace.
 *
 * @param trace A pointer to the s2n_stacktrace to fill.
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_get_stacktrace(struct s2n_stacktrace *trace);

/**
 * Allows the caller to set a callback function that will be used to store SSL
 * session data in a cache.
 *
 * @param config The configuration object being updated
 * @param cache_store_callback The cache store callback function.
 * @param data An opaque context pointer that the callback will be invoked with.
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_config_set_cache_store_callback(struct s2n_config *config, s2n_cache_store_callback cache_store_callback, void *data);

/**
 * Allows the caller to set a callback function that will be used to retrieve SSL
 * session data from a cache.
 *
 * @param config The configuration object being updated
 * @param cache_retrieve_callback The cache retrieve callback function.
 * @param data An opaque context pointer that the callback will be invoked with.
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_config_set_cache_retrieve_callback(struct s2n_config *config, s2n_cache_retrieve_callback cache_retrieve_callback, void *data);

/**
 * Allows the caller to set a callback function that will be used to delete SSL
 * session data from a cache.
 *
 * @param config The configuration object being updated
 * @param cache_delete_callback The cache delete callback function.
 * @param data An opaque context pointer that the callback will be invoked with.
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_config_set_cache_delete_callback(struct s2n_config *config, s2n_cache_delete_callback cache_delete_callback, void *data);

/**
 * A function that will be called when s2n-tls is initialized.
 */
typedef int (*s2n_mem_init_callback)(void);

/**
 * Will be called when `s2n_cleanup` is executed.
 */
typedef int (*s2n_mem_cleanup_callback)(void);

/**
 * A function that can allocate at least `requested` bytes of memory and
 * store the location of that memory in **\*ptr**, and the size of the allocated
 * data in **\*allocated**. The function may choose to allocate more memory
 * than was requested. s2n-tls will consider all allocated memory available for
 * use, and will attempt to free all allocated memory when able.
 */
typedef int (*s2n_mem_malloc_callback)(void **ptr, uint32_t requested, uint32_t *allocated);

/**
 * A function that can free memory.
 */
typedef int (*s2n_mem_free_callback)(void *ptr, uint32_t size);

/**
 * Allows the caller to over-ride s2n-tls's internal memory handling functions.
 * 
 * @warning This function must be called before s2n_init().
 * 
 * @param mem_init_callback The s2n_mem_init_callback
 * @param mem_cleanup_callback The s2n_mem_cleanup_callback
 * @param mem_malloc_callback The s2n_mem_malloc_callback
 * @param mem_free_callback The s2n_mem_free_callback
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_mem_set_callbacks(s2n_mem_init_callback mem_init_callback, s2n_mem_cleanup_callback mem_cleanup_callback,
                                 s2n_mem_malloc_callback mem_malloc_callback, s2n_mem_free_callback mem_free_callback);

/**
 * A callback function that will be called when s2n-tls is initialized.
 */
typedef int (*s2n_rand_init_callback)(void);

/**
 * A callback function that will be called when `s2n_cleanup` is executed.
 */
typedef int (*s2n_rand_cleanup_callback)(void);

/**
 * A callback function that will be used to provide entropy to the s2n-tls
 * random number generators.
 */
typedef int (*s2n_rand_seed_callback)(void *data, uint32_t size);

/**
 * A callback function that will be used to mix in entropy every time the RNG
 * is invoked.
 */
typedef int (*s2n_rand_mix_callback)(void *data, uint32_t size);

/**
 * Allows the caller to over-ride s2n-tls's entropy functions.
 * 
 * @warning This function must be called before s2n_init().
 * 
 * @param rand_init_callback The s2n_rand_init_callback
 * @param rand_cleanup_callback The s2n_rand_cleanup_callback
 * @param rand_seed_callback The s2n_rand_seed_callback
 * @param rand_mix_callback The s2n_rand_mix_callback
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_rand_set_callbacks(s2n_rand_init_callback rand_init_callback, s2n_rand_cleanup_callback rand_cleanup_callback,
        s2n_rand_seed_callback rand_seed_callback, s2n_rand_mix_callback rand_mix_callback);

/**
 * TLS extensions supported by s2n-tls
 */
typedef enum {
    S2N_EXTENSION_SERVER_NAME = 0,
    S2N_EXTENSION_MAX_FRAG_LEN = 1,
    S2N_EXTENSION_OCSP_STAPLING = 5,
    S2N_EXTENSION_SUPPORTED_GROUPS = 10,
    S2N_EXTENSION_EC_POINT_FORMATS = 11,
    S2N_EXTENSION_SIGNATURE_ALGORITHMS = 13,
    S2N_EXTENSION_ALPN = 16,
    S2N_EXTENSION_CERTIFICATE_TRANSPARENCY = 18,
    S2N_EXTENSION_RENEGOTIATION_INFO = 65281,
} s2n_tls_extension_type;

/**
 * MFL configurations from https://datatracker.ietf.org/doc/html/rfc6066#section-4.
 */
typedef enum {
    S2N_TLS_MAX_FRAG_LEN_512 = 1,
    S2N_TLS_MAX_FRAG_LEN_1024 = 2,
    S2N_TLS_MAX_FRAG_LEN_2048 = 3,
    S2N_TLS_MAX_FRAG_LEN_4096 = 4,
} s2n_max_frag_len;

/**
 * Opaque certificate type.
 */
struct s2n_cert;

/**
 * Opaque certificate chain and key type.
 */
struct s2n_cert_chain_and_key;

/**
 * Opaque key type.
 */
struct s2n_pkey;

/**
 * Opaque public key type.
 */
typedef struct s2n_pkey s2n_cert_public_key;

/**
 * Opaque private key type.
 */
typedef struct s2n_pkey s2n_cert_private_key;

/**
 * Creates a new s2n_cert_chain_and_key object. This object can be associated
 * with many config objects. It is used to represent a certificate and key pair.
 *
 * @returns A new object used to represent a certificate-chain/key pair
 */
S2N_API
extern struct s2n_cert_chain_and_key *s2n_cert_chain_and_key_new(void);

/**
 * Associates a certificate chain and private key with an `s2n_cert_chain_and_key` object.
 * 
 * `cert_chain_pem` should be a PEM encoded certificate chain, with the first
 * certificate in the chain being your leaf certificate. `private_key_pem`
 * should be a PEM encoded private key corresponding to the leaf certificate.
 *
 * @note Prefer using s2n_cert_chain_and_key_load_pem_bytes.
 *
 * @param chain_and_key The certificate chain and private key handle
 * @param chain_pem A byte array of a PEM encoded certificate chain.
 * @param private_key_pem A byte array of a PEM encoded key.
 *
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_cert_chain_and_key_load_pem(struct s2n_cert_chain_and_key *chain_and_key, const char *chain_pem, const char *private_key_pem);

/**
 * Associates a certificate chain and private key with an `s2n_cert_chain_and_key` object.
 * 
 * `cert_chain_pem` should be a PEM encoded certificate chain, with the first
 * certificate in the chain being your leaf certificate. `private_key_pem`
 * should be a PEM encoded private key corresponding to the leaf certificate.
 *
 * @param chain_and_key The certificate chain and private key handle
 * @param chain_pem A byte array of a PEM encoded certificate chain.
 * @param chain_pem_len Size of `chain_pem`
 * @param private_key_pem A byte array of a PEM encoded key.
 * @param private_key_pem_len Size of `private_key_pem`
 *
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_cert_chain_and_key_load_pem_bytes(struct s2n_cert_chain_and_key *chain_and_key, uint8_t *chain_pem, uint32_t chain_pem_len, uint8_t *private_key_pem, uint32_t private_key_pem_len);

/**
 * Associates a public certificate chain with a `s2n_cert_chain_and_key` object. It does
 * NOT set a private key, so the connection will need to be configured to
 * [offload private key operations](https://github.com/aws/s2n-tls/blob/main/docs/USAGE-GUIDE.md#offloading-asynchronous-private-key-operations).
 *
 * @param chain_and_key The certificate chain and private key handle
 * @param chain_pem A byte array of a PEM encoded certificate chain.
 * @param chain_pem_len Size of `chain_pem`
 *
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_cert_chain_and_key_load_public_pem_bytes(struct s2n_cert_chain_and_key *chain_and_key, uint8_t *chain_pem, uint32_t chain_pem_len);

/**
 * Frees the memory associated with an `s2n_cert_chain_and_key` object.
 *
 * @param cert_and_key The certificate chain and private key handle
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_cert_chain_and_key_free(struct s2n_cert_chain_and_key *cert_and_key);

/**
 * Adds a context to the `s2n_cert_chain_and_key` object.
 *
 * @param cert_and_key The certificate chain and private key handle
 * @param ctx An opaque pointer to user supplied data.
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_cert_chain_and_key_set_ctx(struct s2n_cert_chain_and_key *cert_and_key, void *ctx);

/**
 * Get the user supplied context from the `s2n_cert_chain_and_key` object.
 *
 * @param cert_and_key The certificate chain and private key handle
 * @returns The user supplied pointer from s2n_cert_chain_and_key_set_ctx()
 */
S2N_API
extern void *s2n_cert_chain_and_key_get_ctx(struct s2n_cert_chain_and_key *cert_and_key);

/**
 * Get the private key from the `s2n_cert_chain_and_key` object.
 *
 * @param cert_and_key The certificate chain and private key handle
 * @returns A pointer to the `s2n_cert_private_key`
 */
S2N_API
extern s2n_cert_private_key *s2n_cert_chain_and_key_get_private_key(struct s2n_cert_chain_and_key *cert_and_key);

/**
 * A callback function that is invoked if s2n-tls cannot resolve a conflict between 
 * two certificates with the same domain name. This function is invoked while certificates
 * are added to an `s2n_config`. 
 *
 * Currently, the only builtin resolution for domain name conflicts is certificate type(RSA, 
 * ECDSA, etc). The callback should return a pointer to the `s2n_cert_chain_and_key` that
 * should be used for dns name `name`. 
 *
 * If NULL is returned, the first certificate will be used. Typically an application
 * will use properties like trust and expiry to implement tiebreaking.
 */
typedef struct s2n_cert_chain_and_key* (*s2n_cert_tiebreak_callback) (struct s2n_cert_chain_and_key *cert1, struct s2n_cert_chain_and_key *cert2, uint8_t *name, uint32_t name_len);

/**
 * Sets the `s2n_cert_tiebreak_callback` for resolving domain name conflicts. 
 * If no callback is set, the first certificate added for a domain name will always be preferred.
 *
 * @param config The configuration object being updated
 * @param cert_tiebreak_cb The pointer to the certificate tiebreak function
 *
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_config_set_cert_tiebreak_callback(struct s2n_config *config, s2n_cert_tiebreak_callback cert_tiebreak_cb);

/**
 * Associates a certificate chain and a private key, with an `s2n_config` object. 
 * At present, only one certificate-chain/key pair may be associated with a config. 
 * `cert_chain_pem` should be a PEM encoded certificate chain, with the first certificate 
 * in the chain being your servers certificate. `private_key_pem` should be a
 * PEM encoded private key corresponding to the server certificate.
 *
 * @param config The configuration object being updated
 * @param cert_chain_pem A byte array of a PEM encoded certificate chain.
 * @param private_key_pem A byte array of a PEM encoded key.
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_config_add_cert_chain_and_key(struct s2n_config *config, const char *cert_chain_pem, const char *private_key_pem);

/**
 * The preferred method of associating a certificate chain and private key pair with an `s2n_config` object.
 * This method may be called multiple times to support multiple key types(RSA, ECDSA) and multiple domains.
 * On the server side, the certificate selected will be based on the incoming SNI value and the
 * client's capabilities(supported ciphers).
 *
 * In the case of no certificate matching the client's SNI extension or if no SNI extension was sent by
 * the client, the certificate from the `first` call to `s2n_config_add_cert_chain_and_key_to_store`
 * will be selected.
 * 
 * @warning It is not recommended to free or modify the `cert_key_pair` as any subsequent changes will be
 * reflected in the config. 
 *
 * @param config The configuration object being updated
 * @param cert_key_pair The certificate chain and private key handle
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_config_add_cert_chain_and_key_to_store(struct s2n_config *config, struct s2n_cert_chain_and_key *cert_key_pair);

/**
 * Explicitly sets certificate chain and private key pairs to be used as defaults for each auth
 * method (key type). A "default" certificate is used when there is not an SNI match with any other
 * configured certificate.
 *
 * Only one certificate can be set as the default per auth method (one RSA default, one ECDSA default,
 * etc.). All previous default certificates will be cleared and re-set when this API is called.
 *
 * This API is called for a specific `s2n_config` object. s2n-tls will attempt to automatically choose
 * default certificates for each auth method (key type) based on the order that `s2n_cert_chain_and_key`
 * are added to the `s2n_config` using one of the APIs listed above.
 * `s2n_config_set_cert_chain_and_key_defaults` can be called at any time; s2n-tls will clear defaults
 * and no longer attempt to automatically choose any default certificates.
 *
 * @param config The configuration object being updated
 * @param cert_key_pairs An array of certificate chain and private key handles
 * @param num_cert_key_pairs The amount of handles in cert_key_pairs
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_config_set_cert_chain_and_key_defaults(struct s2n_config *config,
                                                      struct s2n_cert_chain_and_key **cert_key_pairs,
                                                      uint32_t num_cert_key_pairs);

/**
 * Adds to the trust store from a CA file or directory containing trusted certificates.
 * To completely override those locations, call s2n_config_wipe_trust_store() before calling
 * this function. 
 *
 * @note The trust store will be initialized with the common locations for the host
 * operating system by default.
 * @param config The configuration object being updated
 * @param ca_pem_filename A string for the file path of the CA PEM file.
 * @param ca_dir A string for the directory of the CA PEM files.
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_config_set_verification_ca_location(struct s2n_config *config, const char *ca_pem_filename, const char *ca_dir);

/**
 * Adds a PEM to the trust store. This will allocate memory, and load PEM into the
 * Trust Store. Note that the trust store will be initialized with the common locations
 * for the host operating system by default. To completely override those locations,
 * call s2n_config_wipe_trust_store before calling this function.
 *
 * @param config The configuration object being updated
 * @param pem The string value of the PEM certificate.
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_config_add_pem_to_trust_store(struct s2n_config *config, const char *pem);

/**
 * Clear the trust store.
 *
 * Note that the trust store will be initialized with the common locations for
 * the host operating system by default. To completely override those locations,
 * call this before functions like `s2n_config_set_verification_ca_location()`
 * or `s2n_config_add_pem_to_trust_store()`
 *
 * @param config The configuration object being updated
 *
 * @returns 0 on success and -1 on error
 */
S2N_API
extern int s2n_config_wipe_trust_store(struct s2n_config *config);

/** 
 * A callback function invoked (usually multiple times) during X.509 validation for each
 * name encountered in the leaf certificate.
 *
 * Return 1 to trust that hostname or 0 to not trust the hostname.
 *
 * If this function returns 1, then the certificate is considered trusted and that portion
 * of the X.509 validation will succeed.
 *
 * If no hostname results in a 1 being returned, the certificate will be untrusted and the
 * validation will terminate immediately. The default behavior is to reject all host names
 * found in a certificate if client mode or client authentication is being used.
 *
 * Data is a opaque user context set in s2n_config_set_verify_host_callback().
 */
typedef uint8_t (*s2n_verify_host_fn) (const char *host_name, size_t host_name_len, void *data);

/**
 * Sets the callback to use for verifying that a hostname from an X.509 certificate is trusted.
 * By default, no certificate will be trusted. To override this behavior, set this callback.
 *
 * This change will be inherited by s2n_connections using this config. If s2n_connection specifies
 * a callback, that callback will be used for that connection.
 *
 * If a separate callback for different connections using the same config is desired,
 * see s2n_connection_set_verify_host_callback().
 *
 * @param config The configuration object being updated
 * @param data A user supplied opaque context to pass back to the callback
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_config_set_verify_host_callback(struct s2n_config *config, s2n_verify_host_fn, void *data);

/**
 * Toggles whether or not to validate stapled OCSP responses.
 *
 * 1 means OCSP responses will be validated when they are encountered, while 0 means this step will
 * be skipped.
 *
 * The default value is 1 if the underlying libCrypto implementation supports OCSP. 
 *
 * @param config The configuration object being updated
 * @param check_ocsp The desired OCSP response check configuration
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_config_set_check_stapled_ocsp_response(struct s2n_config *config, uint8_t check_ocsp);

/**
 * Turns off all X.509 validation during the negotiation phase of the connection. This should only
 * be used for testing or debugging purposes.
 *
 * @param config The configuration object being updated
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_config_disable_x509_verification(struct s2n_config *config);

/**
 * Sets the maximum allowed depth of a cert chain used for X509 validation. The default value is
 * 7. If this limit is exceeded, validation will fail if s2n_config_disable_x509_verification()
 * has not been called. 0 is an illegal value and will return an error.
 * 1 means only a root certificate will be used.
 *
 * @param config The configuration object being updated
 * @param max_depth The number of allowed certificates in the certificate chain
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_config_set_max_cert_chain_depth(struct s2n_config *config, uint16_t max_depth);

/**
 * Associates a set of Diffie-Hellman parameters with an `s2n_config` object.
 * @note `dhparams_pem` should be PEM encoded DH parameters.
 *
 * @param config The configuration object being updated
 * @param dhparams_pem A string containing the PEM encoded DH parameters.
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_config_add_dhparams(struct s2n_config *config, const char *dhparams_pem);

/**
 * Sets the security policy that includes the cipher/kem/signature/ecc preferences and
 * protocol version.
 *
 * See the [USAGE-GUIDE.md](https://github.com/aws/s2n-tls/blob/main/docs/USAGE-GUIDE.md) for how to use security policies.
 */
S2N_API
extern int s2n_config_set_cipher_preferences(struct s2n_config *config, const char *version);

/**
 * Appends the provided application protocol to the preference list
 *
 * The data provided in `protocol` parameter will be copied into an internal buffer
 *
 * @param config The configuration object being updated
 * @param protocol A pointer to a byte array value
 * @param protocol_len The length of bytes that should be read from `protocol`. Note: this value cannot be 0, otherwise an error will be returned.
 */
S2N_API
extern int s2n_config_append_protocol_preference(struct s2n_config *config, const uint8_t *protocol, uint8_t protocol_len);

/**
 * Sets the application protocol preferences on an `s2n_config` object. 
 * `protocols` is a list in order of preference, with most preferred protocol first, and of
 * length `protocol_count`. 
 *
 * When acting as an `S2N_CLIENT` the protocol list is included in the Client Hello message
 * as the ALPN extension. 
 *
 * As an `S2N_SERVER`, the list is used to negotiate a mutual application protocol with the
 * client. After the negotiation for the connection has completed, the agreed upon protocol
 * can be retrieved with s2n_get_application_protocol()
 *
 * @param config The configuration object being updated
 * @param protocols The list of preferred protocols, in order of preference
 * @param protocol_count The size of the protocols list
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_config_set_protocol_preferences(struct s2n_config *config, const char * const *protocols, int protocol_count);

/**
 * Enum used to define the type, if any, of certificate status request
 * an S2N_CLIENT should make during the handshake. The only supported status request type is
 * OCSP, `S2N_STATUS_REQUEST_OCSP`.
*/
typedef enum { S2N_STATUS_REQUEST_NONE = 0, S2N_STATUS_REQUEST_OCSP = 1 } s2n_status_request_type;

/**
 * Sets up an S2N_CLIENT to request the server certificate status during an SSL handshake. If set
 * to S2N_STATUS_REQUEST_NONE, no status request is made.
 *
 * @param config The configuration object being updated
 * @param type The desired request status type
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_config_set_status_request_type(struct s2n_config *config, s2n_status_request_type type);

/**
 * Enum to set Certificate Transparency Support level. 
 */
typedef enum { S2N_CT_SUPPORT_NONE = 0, S2N_CT_SUPPORT_REQUEST = 1 } s2n_ct_support_level;

/**
 * Set the Certificate Transparency Support level.
 *
 * @param config The configuration object being updated
 * @param level The desired Certificate Transparency Support configuration
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_config_set_ct_support_level(struct s2n_config *config, s2n_ct_support_level level);

/**
 * Sets whether or not a connection should terminate on receiving a WARNING alert from its peer.
 *
 * `alert_behavior` can take the following values:
 * - `S2N_ALERT_FAIL_ON_WARNINGS` default behavior: s2n-tls will terminate the connection if its peer sends a WARNING alert.
 * - `S2N_ALERT_IGNORE_WARNINGS` - with the exception of `close_notify` s2n-tls will ignore all WARNING alerts and keep communicating with its peer. This setting is ignored in TLS1.3
 *
 * @note TLS1.3 terminates a connection for all alerts except user_canceled.
 */
typedef enum { S2N_ALERT_FAIL_ON_WARNINGS = 0, S2N_ALERT_IGNORE_WARNINGS = 1 } s2n_alert_behavior;

/**
 * Sets the config's alert behavior based on the `s2n_alert_behavior` enum.
 *
 * @param config The configuration object being updated
 * @param alert_behavior The desired alert behavior.
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_config_set_alert_behavior(struct s2n_config *config, s2n_alert_behavior alert_behavior);

/**
 * Sets the extension data in the `s2n_config` object for the specified extension. 
 * This method will clear any existing data that is set. If the data and length
 * parameters are set to NULL, no new data is set in the `s2n_config` object,
 * effectively clearing existing data.
 *
 * @param config The configuration object being updated
 * @param type The extension type
 * @param data Data for the extension
 * @param length Length of the `data` buffer
 */
S2N_API
extern int s2n_config_set_extension_data(struct s2n_config *config, s2n_tls_extension_type type, const uint8_t *data, uint32_t length);

/**
 * Allows the caller to set a TLS Maximum Fragment Length extension that will be used
 * to fragment outgoing messages. s2n-tls currently does not reject fragments larger
 * than the configured maximum when in server mode. The TLS negotiated maximum fragment
 * length overrides the preference set by the `s2n_connection_prefer_throughput` and
 * `s2n_connection_prefer_low_latency`.
 *
 * @param config The configuration object being updated
 * @param mfl_code The selected MFL size
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_config_send_max_fragment_length(struct s2n_config *config, s2n_max_frag_len mfl_code);

/**
 * Allows the server to opt-in to accept client's TLS maximum fragment length extension
 * requests. If this API is not called, and client requests the extension, server will ignore
 * the request and continue TLS handshake with default maximum fragment length of 8k bytes
 *
 * @param config The configuration object being updated
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_config_accept_max_fragment_length(struct s2n_config *config);

/**
 * Sets the lifetime of the cached session state. The default value is 15 hours.
 *
 * @param config The configuration object being updated
 * @param lifetime_in_secs The desired lifetime of the session state in seconds
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_config_set_session_state_lifetime(struct s2n_config *config, uint64_t lifetime_in_secs);

/**
 * Enable or disable session resumption using session ticket.
 *
 * @param config The configuration object being updated
 * @param enabled The configuration object being updated. Set to 1 to enable. Set to 0 to disable.
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_config_set_session_tickets_onoff(struct s2n_config *config, uint8_t enabled);

/**
 * Enable or disable session caching.
 *
 * @param config The configuration object being updated
 * @param enabled The configuration object being updated. Set to 1 to enable. Set to 0 to disable.
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_config_set_session_cache_onoff(struct s2n_config *config, uint8_t enabled);

/**
 * Sets how long a session ticket key will be in a state where it can be used for both encryption
 * and decryption of tickets on the server side.
 *
 * @note The default value is 2 hours.
 * @param config The configuration object being updated
 * @param lifetime_in_secs The desired lifetime of decrypting and encrypting tickets in seconds
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_config_set_ticket_encrypt_decrypt_key_lifetime(struct s2n_config *config, uint64_t lifetime_in_secs);

/**
 * Sets how long a session ticket key will be in a state where it can used just for decryption of
 * already assigned tickets on the server side. Once decrypted, the session will resume and the
 * server will issue a new session ticket encrypted using a key in encrypt-decrypt state.
 *
 * @note The default value is 13 hours.
 * @param config The configuration object being updated
 * @param lifetime_in_secs The desired lifetime of decrypting and encrypting tickets in seconds
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_config_set_ticket_decrypt_key_lifetime(struct s2n_config *config, uint64_t lifetime_in_secs);


/**
 * Adds session ticket key on the server side. It would be ideal to add new keys after every
 * (encrypt_decrypt_key_lifetime_in_nanos/2) nanos because this will allow for gradual and
 * linear transition of a key from encrypt-decrypt state to decrypt-only state.
 *
 * @param config The configuration object being updated
 * @param name Name of the session ticket key that should be randomly generated to avoid collisions
 * @param name_len Length of session ticket key name
 * @param key Key used to perform encryption/decryption of session ticket
 * @param key_len Length of the session ticket key
 * @param intro_time_in_seconds_from_epoch Time at which the session ticket key is introduced. If this is 0, then intro_time_in_seconds_from_epoch is set to now. 
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_config_add_ticket_crypto_key(struct s2n_config *config,
                                            const uint8_t *name, uint32_t name_len,
                                            uint8_t *key, uint32_t key_len,
                                            uint64_t intro_time_in_seconds_from_epoch);
/**
 * Sets user defined context on the `s2n_config` object.
 *
 * @param config The configuration object being updated
 * @param ctx A pointer to the user defined ctx.
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_config_set_ctx(struct s2n_config *config, void *ctx);

/**
 * Gets the user defined context from the `s2n_config` object.
 * The context is set by calling s2n_config_set_ctx()
 *
 * @param config The configuration object being accessed
 * @param ctx A pointer to the user defined ctx.
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_config_get_ctx(struct s2n_config *config, void **ctx);

/**
 * Used to declare connections as server or client type, respectively.
 */
typedef enum { S2N_SERVER, S2N_CLIENT } s2n_mode;

/**
 * Creates a new connection object. Each s2n-tls SSL/TLS connection uses
 * one of these objects. These connection objects can be operated on by up
 * to two threads at a time, one sender and one receiver, but neither sending
 * nor receiving are atomic, so if these objects are being called by multiple
 * sender or receiver threads, you must perform your own locking to ensure 
 * that only one sender or receiver is active at a time. 
 *
 * The `mode` parameters specifies if the caller is a server, or is a client.
 * Connections objects are re-usable across many connections, and should be
 * re-used (to avoid deallocating and allocating memory). You should wipe
 * connections immediately after use.
 *
 * @param mode The desired connection type
 * @returns A s2n_connection handle
 */
S2N_API
extern struct s2n_connection *s2n_connection_new(s2n_mode mode);

/**
 * Associates a configuration object with a connection.
 *
 * @param conn The connection object being associated
 * @param config The configuration object being associated
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_connection_set_config(struct s2n_connection *conn, struct s2n_config *config);

/**
 * Sets user defined context in `s2n_connection` object.
 *
 * @param conn The connection object being updated
 * @param ctx A pointer to the user defined context
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_connection_set_ctx(struct s2n_connection *conn, void *ctx);

/**
 * Gets user defined context from a `s2n_connection` object.
 *
 * @param conn The connection object that contains the desired context
 */
S2N_API
extern void *s2n_connection_get_ctx(struct s2n_connection *conn);

/**
 * The callback function takes a s2n-tls connection as input, which receives the ClientHello
 * and the context previously provided in `s2n_config_set_client_hello_cb`. The callback can
 * access any ClientHello information from the connection and use the `s2n_connection_set_config`
 * call to change the config of the connection.
 */
typedef int s2n_client_hello_fn(struct s2n_connection *conn, void *ctx);

/**
 * Client Hello callback modes
 * - `S2N_CLIENT_HELLO_CB_BLOCKING` (default):
 *   - In this mode s2n-tls expects the callback to complete its work and return the appropriate response code before the handshake continues. If any of the connection properties were changed based on the server_name extension the callback must either return a value greater than 0 or invoke `s2n_connection_server_name_extension_used`, otherwise the callback returns 0 to continue the handshake.
 * - `S2N_CLIENT_HELLO_CB_NONBLOCKING`:
 *   - In non-blocking mode, s2n-tls expects the callback to not complete its work. If the callback returns a response code of 0 s2n-tls will return `S2N_FAILURE` with `S2N_ERR_T_BLOCKED` error type and `s2n_blocked_status` set to `S2N_BLOCKED_ON_APPLICATION_INPUT`. The handshake is paused and further calls to `s2n_negotiate` will continue to return the same error until `s2n_client_hello_cb_done` is invoked for the `s2n_connection` to resume the handshake. This allows s2n-tls clients to process client_hello without blocking and then resume the handshake at a later time. If any of the connection properties were changed on the basis of the server_name extension then `s2n_connection_server_name_extension_used` must be invoked before marking the callback done.
 */
typedef enum { S2N_CLIENT_HELLO_CB_BLOCKING, S2N_CLIENT_HELLO_CB_NONBLOCKING } s2n_client_hello_cb_mode;

/**
 * Allows the caller to set a callback function that will be called after ClientHello was parsed.
 *
 * @param config The configuration object being updated
 * @param client_hello_callback The client hello callback function
 * @param ctx A pointer to a user defined context that the Client Hello callback will be invoked with. 
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_config_set_client_hello_cb(struct s2n_config *config, s2n_client_hello_fn client_hello_callback, void *ctx);

/**
 * Sets the callback execution mode.
 *
 * See s2n_client_hello_cb_mode for each mode's behavior.
 *
 * @param config The configuration object being updated
 * @param cb_mode The desired callback mode
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_config_set_client_hello_cb_mode(struct s2n_config *config, s2n_client_hello_cb_mode cb_mode);

/**
 * Marks the non-blocking callback as complete. Can be invoked from within the callback when
 * operating in non-blocking mode to continue the handshake.
 *
 * @param conn The connection object being updated
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_client_hello_cb_done(struct s2n_connection *conn);

/**
 * Must be invoked if any of the connection properties were changed on the basis of the server_name
 * extension. This must be invoked before marking the Client Hello callback done.
 *
 * @param conn The connection object being updated
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_connection_server_name_extension_used(struct s2n_connection *conn);

/**
 * Opaque client hello handle
 */
struct s2n_client_hello;

/**
 * Get the Client Hello from a s2n_connection.
 *
 * Earliest point during the handshake when this structure is available for use is in the
 * client_hello_callback (see s2n_config_set_client_hello_cb()).
 *
 * @param conn The connection object containing the client hello
 * @returns A handle to the s2n_client_hello structure holding the client hello message sent by the client during the handshake. NULL is returned if a Client Hello has not yet been received and parsed.
 */
S2N_API
extern struct s2n_client_hello *s2n_connection_get_client_hello(struct s2n_connection *conn);

/**
 * Function to determine the size of the raw Client Hello buffer. 
 *
 * Can be used to determine the necessary size of the `out` buffer for 
 * s2n_client_hello_get_raw_message()
 *
 * @param ch The Client Hello handle
 * @returns The size of the ClientHello message received by the server
 */
S2N_API
extern ssize_t s2n_client_hello_get_raw_message_length(struct s2n_client_hello *ch);

/**
 * Copies `max_length` bytes of the ClientHello message into the `out` buffer.
 * The ClientHello instrumented using this function will have the Random bytes
 * zero-ed out. For SSLv2 ClientHello messages, the raw message contains only
 * the cipher_specs, session_id and members portions of the hello message
 * (see [RFC5246](https://tools.ietf.org/html/rfc5246#appendix-E.2)). To access other
 * members, you may use s2n_connection_get_client_hello_version(),
 * s2n_connection_get_client_protocol_version() and s2n_connection_get_session_id_length()
 * accessors functions.
 *
 * @param ch The Client Hello handle
 * @param out The destination buffer for the raw Client Hello
 * @param max_length The size of out in bytes
 * @returns The number of copied bytes
 */
S2N_API
extern ssize_t s2n_client_hello_get_raw_message(struct s2n_client_hello *ch, uint8_t *out, uint32_t max_length);

/**
 * Function to determine the size of the Client Hello cipher suites.
 * This can be used to allocate the `out` buffer for s2n_client_hello_get_cipher_suites().
 *
 * @param ch The Client Hello handle
 * @returns the number of bytes the cipher_suites takes on the ClientHello message received by the server
 */
S2N_API
extern ssize_t s2n_client_hello_get_cipher_suites_length(struct s2n_client_hello *ch);

/**
 * Copies into the `out` buffer `max_length` bytes of the cipher_suites on the ClientHello.
 *
 * @param ch The Client Hello handle
 * @param out The destination buffer for the raw Client Hello cipher suites
 * @param max_length The size of out in bytes
 * @returns The number of copied bytes
 */
S2N_API
extern ssize_t s2n_client_hello_get_cipher_suites(struct s2n_client_hello *ch, uint8_t *out, uint32_t max_length);

/**
 * Function to determine the size of the Client Hello extensions.
 * This can be used to allocate the `out` buffer for s2n_client_hello_get_extensions().
 *
 * @param ch The Client Hello handle
 * @returns the number of bytes the extensions take in the ClientHello message received by the server
 */
S2N_API
extern ssize_t s2n_client_hello_get_extensions_length(struct s2n_client_hello *ch);

/**
 * Copies into the `out` buffer `max_length` bytes of the extensions in the ClientHello.
 *
 * @param ch The Client Hello handle
 * @param out The destination buffer for the raw Client Hello extensions
 * @param max_length The size of out in bytes
 * @returns The number of copied bytes
 */
S2N_API
extern ssize_t s2n_client_hello_get_extensions(struct s2n_client_hello *ch, uint8_t *out, uint32_t max_length);

/**
 * Query the ClientHello message received by the server. Use this function to allocate the `out` buffer for
 * other client hello extension functions.
 *
 * @param ch A pointer to the Client Hello
 * @param extension_type Indicates the desired extension
 * @returns The number of bytes the given extension type takes
 */
S2N_API
extern ssize_t s2n_client_hello_get_extension_length(struct s2n_client_hello *ch, s2n_tls_extension_type extension_type);

/**
 * Copies into the `out` buffer `max_length` bytes of a given extension type on the ClientHello
 *
 * `ch` is a pointer to the `s2n_client_hello` of the `s2n_connection` which can be obtained using s2n_connection_get_client_hello(). 
 *
 * @param ch A pointer to the Client Hello
 * @param extension_type Indicates the desired extension
 * @param out A pointer to the buffer that s2n will write the client session id to. This buffer MUST be the size of `max_length`
 * @param max_length The size of `out`.
 * @returns The number of copied bytes
 */
S2N_API
extern ssize_t s2n_client_hello_get_extension_by_id(struct s2n_client_hello *ch, s2n_tls_extension_type extension_type, uint8_t *out, uint32_t max_length);

/**
 * Used to check if a particular extension exists in the client hello.
 *
 * `ch` is a pointer to the `s2n_client_hello` of the `s2n_connection` which can be obtained using s2n_connection_get_client_hello(). 
 *
 * @param ch A pointer to the client hello object
 * @param extension_iana The iana value of the extension
 * @param exists A pointer that will be set to whether or not the extension exists
 */
S2N_API
extern int s2n_client_hello_has_extension(struct s2n_client_hello *ch, uint16_t extension_iana, bool *exists);

/**
 * Get the the ClientHello session id length in bytes
 * 
 * `ch` is a pointer to the `s2n_client_hello` of the `s2n_connection` which can be obtained using s2n_connection_get_client_hello(). 
 *
 * @param ch A pointer to the Client Hello
 * @param out_length An out pointer. s2n will set it's value to the size of the session_id in bytes.
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_client_hello_get_session_id_length(struct s2n_client_hello *ch, uint32_t *out_length);

/**
 * Copies up to `max_length` bytes of the ClientHello session_id into the `out` buffer and stores the number of copied bytes in `out_length`.
 *
 * Retrieve the session id as sent by the client in the ClientHello message. The session id on the `s2n_connection` may change later
 * when the server sends the ServerHello; see `s2n_connection_get_session_id` for how to get the final session id used for future session resumption.
 * 
 * Use s2n_client_hello_get_session_id_length() to get the the ClientHello session id length in bytes. `ch` is a pointer to the `s2n_client_hello`
 * of the `s2n_connection` which can be obtained using s2n_connection_get_client_hello(). 
 *
 * @param ch A pointer to the Client Hello
 * @param out A pointer to the buffer that s2n will write the client session id to. This buffer MUST be the size of `max_length`
 * @param out_length An out pointer. s2n will set it's value to the size of the session_id in bytes.
 * @param max_length The size of `out`.
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_client_hello_get_session_id(struct s2n_client_hello *ch, uint8_t *out, uint32_t *out_length, uint32_t max_length);

/**
 * Sets the file descriptor for a s2n connection.
 *
 * @warning If the read end of the pipe is closed unexpectedly, writing to the pipe will raise a SIGPIPE signal.
 * **s2n-tls does NOT handle SIGPIPE.** A SIGPIPE signal will cause the process to terminate unless it is handled
 * or ignored by the application.
 * @note This file-descriptor should be active and connected
 * @param conn A pointer to the s2n connection
 * @param fd The new file descriptor
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_connection_set_fd(struct s2n_connection *conn, int fd);

/**
 * Sets the file descriptor for the read channel of an s2n connection.
 *
 * @warning If the read end of the pipe is closed unexpectedly, writing to the pipe will raise a SIGPIPE signal.
 * **s2n-tls does NOT handle SIGPIPE.** A SIGPIPE signal will cause the process to terminate unless it is handled
 * or ignored by the application.
 * @note This file-descriptor should be active and connected
 * @param conn A pointer to the s2n connection
 * @param readfd The new read file descriptor
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_connection_set_read_fd(struct s2n_connection *conn, int readfd);

/**
 * Sets the assigned file descriptor for the write channel of an s2n connection.
 *
 * @note This file-descriptor should be active and connected
 * @param conn A pointer to the s2n connection
 * @param writefd The new write file descriptor
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_connection_set_write_fd(struct s2n_connection *conn, int writefd);

/**
 * Gets the assigned file descriptor for the read channel of an s2n connection.
 *
 * @param conn A pointer to the s2n connection
 * @param readfd pointer to place the used file descriptor.
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_connection_get_read_fd(struct s2n_connection *conn, int *readfd);

/**
 * Gets the assigned file descriptor for the write channel of an s2n connection.
 *
 * @param conn A pointer to the s2n connection
 * @param writefd pointer to place the used file descriptor.
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_connection_get_write_fd(struct s2n_connection *conn, int *writefd);

/**
 * Indicates to s2n that the connection is using corked IO.
 *
 * @warning This API should only be used when using managed send IO.
 *
 * @param conn The connection object being updated
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_connection_use_corked_io(struct s2n_connection *conn);

/**
 * Function pointer for a user provided send callback.
 */
typedef int s2n_recv_fn(void *io_context, uint8_t *buf, uint32_t len);

/**
 * Function pointer for a user provided send callback.
 */
typedef int s2n_send_fn(void *io_context, const uint8_t *buf, uint32_t len);

/**
 * Set a context containing anything needed in the recv callback function (for example,
 * a file descriptor), the buffer holding data to be sent or received, and the length of the buffer. 
 *
 * @note The `io_context` passed to the callbacks may be set separately using `s2n_connection_set_recv_ctx` and `s2n_connection_set_send_ctx`.
 *
 * @param conn The connection object being updated
 * @param ctx A user provided context that the callback will be invoked with
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_connection_set_recv_ctx(struct s2n_connection *conn, void *ctx);

/**
 * Set a context containing anything needed in the send callback function (for example,
 * a file descriptor), the buffer holding data to be sent or received, and the length of the buffer. 
 *
 * @note The `io_context` passed to the callbacks may be set separately using `s2n_connection_set_recv_ctx` and `s2n_connection_set_send_ctx`.
 *
 * @param conn The connection object being updated
 * @param ctx A user provided context that the callback will be invoked with
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_connection_set_send_ctx(struct s2n_connection *conn, void *ctx);

/**
 * Configure a connection to use a recv callback to receive data.
 *
 * @note This callback may be blocking or nonblocking.
 * @note The callback may receive less than the requested length. The function should return the number
 * of bytes received, or set errno and return an error code < 0.
 *
 * @param conn The connection object being updated
 * @param recv A recv callback function pointer
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_connection_set_recv_cb(struct s2n_connection *conn, s2n_recv_fn recv);

/**
 * Configure a connection to use a send callback to send data.
 *
 * @note This callback may be blocking or nonblocking.
 * @note The callback may send less than the requested length. The function should return the
 * number of bytes sent or set errno and return an error code < 0.
 *
 * @param conn The connection object being updated
 * @param send A send callback function pointer
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_connection_set_send_cb(struct s2n_connection *conn, s2n_send_fn send);

/**
 * Change the behavior of s2n-tls when sending data to prefer high throughput. Connections preferring throughput will use
 * large record sizes that minimize overhead.
 *
 * @param conn The connection object being updated
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_connection_prefer_throughput(struct s2n_connection *conn);

/**
 * Change the behavior of s2n-tls when sending data to prefer low latency. Connections preferring low latency will be encrypted
 * using small record sizes that can be decrypted sooner by the recipient. 
 *
 * @param conn The connection object being updated
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_connection_prefer_low_latency(struct s2n_connection *conn);

/**
 * Provides a smooth transition from s2n_connection_prefer_low_latency() to s2n_connection_prefer_throughput().
 *
 * @param conn The connection object being updated
 * @param resize_threshold The number of bytes to send before changing the record size
 * @param timeout_threshold Reset record size back to a single segment after threshold seconds of inactivity
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_connection_set_dynamic_record_threshold(struct s2n_connection *conn, uint32_t resize_threshold, uint16_t timeout_threshold);

/** 
 * Sets the callback to use for verifying that a hostname from an X.509 certificate is trusted. By default, 
 * no certificate will be trusted. To override this behavior, set this callback. See s2n_verify_host_fn()
 * for details. This configuration will be inherited by default to new instances of `s2n_connection`. 
 *
 * If a separate callback for different connections using the same config is desired, see s2n_connection_set_verify_host_callback()
 *
 * @note If you don't want to use the configuration wide callback, you can set this per connection and it will be honored.
 *
 * @param config A pointer to a s2n_config object
 * @param host_fn A pointer to a callback function that s2n will invoke in order to verify the hostname of an X.509 certificate
 * @param data Opaque pointer to data that the verify host function will be invoked with
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_connection_set_verify_host_callback(struct s2n_connection *config, s2n_verify_host_fn host_fn, void *data);

/**
 * Used to opt-out of s2n-tls's built-in blinding. Blinding is a
 * mitigation against timing side-channels which in some cases can leak information
 * about encrypted data. By default s2n-tls will cause a thread to sleep between 10 and
 * 30 seconds whenever tampering is detected.
 * 
 * Setting the S2N_SELF_SERVICE_BLINDING option with s2n_connection_set_blinding()
 * turns off this behavior. This is useful for applications that are handling many connections
 * in a single thread. In that case, if s2n_recv() or s2n_negotiate() return an error,
 * self-service applications should call *2n_connection_get_delay() and pause
 * activity on the connection  for the specified number of nanoseconds before calling
 * close() or shutdown().
 */
typedef enum { S2N_BUILT_IN_BLINDING, S2N_SELF_SERVICE_BLINDING } s2n_blinding;

/**
 * Used to configure s2n-tls to either use built-in blinding (set blinding to S2N_BUILT_IN_BLINDING) or 
 * self-service blinding (set blinding to S2N_SELF_SERVICE_BLINDING).
 *
 * @param conn The connection object being updated
 * @param blinding The desired blinding mode for the connection
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_connection_set_blinding(struct s2n_connection *conn, s2n_blinding blinding);

/**
 * Query the connection object for the configured blinding delay.
 * @param conn The connection object being updated
 * @returns the number of nanoseconds an application using self-service blinding should pause before calling close() or shutdown().
 */
S2N_API
extern uint64_t s2n_connection_get_delay(struct s2n_connection *conn);

/**
 * Sets the cipher preference override for the s2n_connection. Calling this function is not necessary
 * unless you want to set the cipher preferences on the connection to something different than what is in the s2n_config.
 *
 * @param conn The connection object being updated
 * @param version The human readable string representation of the security policy version.
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_connection_set_cipher_preferences(struct s2n_connection *conn, const char *version);

/**
 * Appends the provided application protocol to the preference list
 *
 * The data provided in `protocol` parameter will be copied into an internal buffer
 *
 * @param conn The connection object being updated
 * @param protocol A pointer to a slice of bytes
 * @param protocol_len The length of bytes that should be read from `protocol`. Note: this value cannot be 0, otherwise an error will be returned.
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_connection_append_protocol_preference(struct s2n_connection *conn, const uint8_t *protocol, uint8_t protocol_len);

/**
 * Sets the protocol preference override for the s2n_connection. Calling this function is not necessary unless you want
 * to set the protocol preferences on the connection to something different than what is in the s2n_config.
 *
 * @param conn The connection object being updated
 * @param protocols A pointer to an array of protocol strings
 * @param protocol_count The number of protocols contained in protocols
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_connection_set_protocol_preferences(struct s2n_connection *conn, const char * const *protocols, int protocol_count);

/**
 * Sets the server name for the connection. 
 *
 * @note In the future, this can be used by clients who wish to use the TLS "Server Name indicator"
 * extension. At present, client functionality is disabled.
 *
 * @param conn The connection object being queried
 * @param server_name A pointer to a string containing the desired server name
 * @warning `server_name` must be a NULL terminated string.
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_set_server_name(struct s2n_connection *conn, const char *server_name);

/**
 * Query the connection for the selected server name.
 *
 * This can be used by a server to determine which server name the client is using. This function returns the first ServerName entry
 * in the ServerNameList sent by the client. Subsequent entries are not returned.
 *
 * @param conn The connection object being queried
 * @returns The server name associated with a connection, or NULL if none is found. 
 */
S2N_API
extern const char *s2n_get_server_name(struct s2n_connection *conn);

/**
 * Query the connection for the selected application protocol.
 *
 * @param conn The connection object being queried
 * @returns The negotiated application protocol for a `s2n_connection`.  In the event of no protocol being negotiated, NULL is returned.
 */
S2N_API
extern const char *s2n_get_application_protocol(struct s2n_connection *conn);

/**
 * Query the connection for a buffer containing the OCSP reponse.
 * 
 * @param conn The connection object being queried
 * @param length A pointer that is set to the certificate transparency response buffer's size
 * @returns A pointer to the OCSP response sent by a server during the handshake.  If no status response is received, NULL is returned.
 */
S2N_API
extern const uint8_t *s2n_connection_get_ocsp_response(struct s2n_connection *conn, uint32_t *length);

/**
 * Query the connection for a buffer containing the Certificate Transparency response.
 *
 * @param conn The connection object being queried
 * @param length A pointer that is set to the certificate transparency response buffer's size
 * @returns A pointer to the certificate transparency response buffer.
 */
S2N_API
extern const uint8_t *s2n_connection_get_sct_list(struct s2n_connection *conn, uint32_t *length);

/**
 * Used in non-blocking mode to indicate in which direction s2n-tls became blocked on I/O before it 
 * returned control to the caller. This allows an application to avoid retrying s2n-tls operations 
 * until I/O is possible in that direction.
 */
typedef enum {
    S2N_NOT_BLOCKED = 0,
    S2N_BLOCKED_ON_READ,
    S2N_BLOCKED_ON_WRITE,
    S2N_BLOCKED_ON_APPLICATION_INPUT,
    S2N_BLOCKED_ON_EARLY_DATA,
} s2n_blocked_status;

/**
 * Performs the initial "handshake" phase of a TLS connection and must be called before any s2n_recv() or s2n_send() calls.
 *
 * @param conn A pointer to the s2n_connection object
 * @param blocked A pointer which will be set to the blocked status. 
 * @returns The number of bytes written, and may indicate a partial write
 */
S2N_API
extern int s2n_negotiate(struct s2n_connection *conn, s2n_blocked_status *blocked);

/**
 * Writes and encrypts `size` of `buf` data to the associated connection. s2n_send() will return the number of bytes 
 * written, and may indicate a partial write. 
 *
 * @note Partial writes are possible not just for non-blocking I/O, but also for connections aborted while active. 
 * @note Unlike OpenSSL, repeated calls to s2n_send() should not duplicate the original parameters, but should 
 * update `buf` and `size` per the indication of size written. For example;
 * ```c
 * s2n_blocked_status blocked;
 * int written = 0;
 * char data[10]; 
 * do {
 *     int w = s2n_send(conn, data + written, 10 - written, &blocked);
 *     if (w < 0) {
 *         break;
 *     }
 *     written += w;
 * } while (blocked != S2N_NOT_BLOCKED);
 * ```
 *
 * @param conn A pointer to the s2n_connection object
 * @param buf A pointer to a buffer that s2n will write data from
 * @param size The size of buf
 * @param blocked A pointer which will be set to the blocked status, as in s2n_negotiate()
 * @returns The number of bytes written, and may indicate a partial write
 */
S2N_API
extern ssize_t s2n_send(struct s2n_connection *conn, const void *buf, ssize_t size, s2n_blocked_status *blocked);

/**
 * Works in the same way as s2n_sendv_with_offset() except that the latter's `offs` parameter is implicitly assumed to be 0. 
 * Therefore in the partial write case, the caller would have to make sure that `bufs` and `count` fields are modified in a way that takes 
 * the partial writes into account.
 *
 * @param conn A pointer to the s2n_connection object
 * @param bufs A pointer to a vector of buffers that s2n will write data from.
 * @param count The number of buffers in `bufs`
 * @param blocked A pointer which will be set to the blocked status, as in s2n_negotiate()
 * @returns The number of bytes written, and may indicate a partial write. 
 */
S2N_API
extern ssize_t s2n_sendv(struct s2n_connection *conn, const struct iovec *bufs, ssize_t count, s2n_blocked_status *blocked);

/**
 * Works in the same way as s2n_send() except that it accepts vectorized buffers. Will return the number of bytes written, and may indicate a partial write. Partial writes are possible not just for non-blocking I/O, but also for connections aborted while active. 
 *
 * @note Partial writes are possible not just for non-blocking I/O, but also for connections aborted while active.
 *
 * @note Unlike OpenSSL, repeated calls to s2n_sendv_with_offset() should not duplicate the original parameters, but should update `bufs` and `count` per the indication of size written. For example;
 * 
 * ```c
 * s2n_blocked_status blocked;
 * int written = 0;
 * char data[10]; 
 * struct iovec iov[1];
 * iov[0].iov_base = data;
 * iov[0].iov_len = 10;
 * do {
 *     int w = s2n_sendv_with_offset(conn, iov, 1, written, &blocked);
 *     if (w < 0) {
 *         break;
 *     }
 *     written += w;
 * } while (blocked != S2N_NOT_BLOCKED);
 * ```
 *
 * @param conn A pointer to the s2n_connection object
 * @param bufs A pointer to a vector of buffers that s2n will write data from.
 * @param count The number of buffers in `bufs`
 * @param offs The write cursor offset. This should be updated as data is written. See the example code.
 * @param blocked A pointer which will be set to the blocked status, as in s2n_negotiate()
 * @returns The number of bytes written, and may indicate a partial write. 
 */
S2N_API
extern ssize_t s2n_sendv_with_offset(struct s2n_connection *conn, const struct iovec *bufs, ssize_t count, ssize_t offs, s2n_blocked_status *blocked);

/**
 * Decrypts and reads **size* to `buf` data from the associated
 * connection. 
 * 
 * @note Unlike OpenSSL, repeated calls to `s2n_recv` should not duplicate the original parameters, but should update `buf` and `size` per the indication of size read. For example;
 * ```c
 * s2n_blocked_status blocked;
 * int bytes_read = 0;
 * char data[10];
 * do {
 *     int r = s2n_recv(conn, data + bytes_read, 10 - bytes_read, &blocked);
 *     if (r < 0) {
 *         break;
 *     }
 *     bytes_read += r;
 * } while (blocked != S2N_NOT_BLOCKED);
 * ```
 *
 * @param conn A pointer to the s2n_connection object
 * @param buf A pointer to a buffer that s2n will place read data into.
 * @param size Size of `buf`
 * @param blocked A pointer which will be set to the blocked status, as in s2n_negotiate()
 * @returns number of bytes read. 0 if the connection was shutdown by peer.
 */
S2N_API
extern ssize_t s2n_recv(struct s2n_connection *conn,  void *buf, ssize_t size, s2n_blocked_status *blocked);

/**
 * Allows users of s2n-tls to peek inside the data buffer of an s2n-tls connection to see if there more data to be read without actually reading it. 
 *
 * This is useful when using select() on the underlying s2n-tls file descriptor with a message based application layer protocol. As a single call 
 * to s2n_recv may read all data off the underlying file descriptor, select() will be unable to tell you there if there is more application data 
 * ready for processing already loaded into the s2n-tls buffer. 
 *
 * @note can then be used to determine if s2n_recv() needs to be called before more data comes in on the raw fd
 * @param conn A pointer to the s2n_connection object
 * @returns The number of bytes that can be read from the connection
 */
S2N_API
extern uint32_t s2n_peek(struct s2n_connection *conn);

/** 
 * Wipes and releases buffers and memory allocated during the TLS handshake.
 *
 * @note This function should be called after the handshake is successfully negotiated and logging or recording of handshake data is complete.
 *
 * @param conn A pointer to the s2n_connection object
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_connection_free_handshake(struct s2n_connection *conn);

/** 
 * Wipes and free the `in` and `out` buffers associated with a connection.
 *
 * @note This function may be called when a connection is
 * in keep-alive or idle state to reduce memory overhead of long lived connections.
 *
 * @param conn A pointer to the s2n_connection object
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_connection_release_buffers(struct s2n_connection *conn);

/** 
 * Wipes an existing connection and allows it to be reused. Erases all data associated with a connection including
 * pending reads. 
 *
 * @note This function should be called after all I/O is completed and s2n_shutdown has been called.
 * @note Reusing the same connection handle(s) is more performant than repeatedly calling s2n_connection_new() and s2n_connection_free().
 *
 * @param conn A pointer to the s2n_connection object
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_connection_wipe(struct s2n_connection *conn);

/** 
 * Frees the memory associated with an s2n_connection
 * handle. The handle is considered invalid after `s2n_connection_free` is used.
 * s2n_connection_wipe() does not need to be called prior to this function. `s2n_connection_free` performs its own wipe
 * of sensitive data.
 *
 * @param conn A pointer to the s2n_connection object
 * @returns 0 on success. -1 on failure
 */
S2N_API
extern int s2n_connection_free(struct s2n_connection *conn);

/**
 * Attempts a closure at the TLS layer. Does not close the underlying transport. This call may block in either direction.
 *
 * Unlike other TLS implementations, `s2n_shutdown` attempts a graceful shutdown by default. It will not return with success unless a close_notify alert is successfully
 * sent and received. As a result, `s2n_shutdown` may fail when interacting with a non-conformant TLS implementation.
 *
 * Once `s2n_shutdown` is complete:
 * * The s2n_connection handle cannot be used for reading for writing.
 * * The underlying transport can be closed. Most likely via `close()`.
 * * The s2n_connection handle can be freed via s2n_connection_free() or reused via s2n_connection_wipe()
 *
 * @param conn A pointer to the s2n_connection object
 * @param blocked A pointer which will be set to the blocked status, as in s2n_negotiate()
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_shutdown(struct s2n_connection *conn, s2n_blocked_status *blocked);

/**
 * Used to declare what type of client certificate authentication to use.
 *
 * Currently the default for s2n-tls is for neither the server side or the client side to use Client (aka Mutual) authentication.
 */
typedef enum { S2N_CERT_AUTH_NONE, S2N_CERT_AUTH_REQUIRED, S2N_CERT_AUTH_OPTIONAL } s2n_cert_auth_type;

/**
 * Gets Client Certificate authentication method the s2n_config object is using.
 *
 * @param config A pointer to a s2n_config object
 * @param client_auth_type A pointer to a client auth policy. This will be updated to the s2n_config value.
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_config_get_client_auth_type(struct s2n_config *config, s2n_cert_auth_type *client_auth_type);

/**
 * Sets whether or not a Client Certificate should be required to complete the TLS Connection. 
 *
 * If this is set to `S2N_CERT_AUTH_OPTIONAL` the server will request a client certificate but allow the client to not provide one.
 * Rejecting a client certificate when using `S2N_CERT_AUTH_OPTIONAL` will terminate the handshake.
 *
 * @param config A pointer to a s2n_config object
 * @param client_auth_type The client auth policy for the connection
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_config_set_client_auth_type(struct s2n_config *config, s2n_cert_auth_type client_auth_type);

/**
 * Gets Client Certificate authentication method the s2n_connection object is using.
 *
 * @param conn A pointer to the s2n_connection object
 * @param client_auth_type A pointer to a client auth policy. This will be updated to the s2n_connection value.
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_connection_get_client_auth_type(struct s2n_connection *conn, s2n_cert_auth_type *client_auth_type);

/**
 * Sets whether or not a Client Certificate should be required to complete the TLS Connection. 
 *
 * If this is set to `S2N_CERT_AUTH_OPTIONAL` the server will request a client certificate but allow the client to not provide one.
 * Rejecting a client certificate when using `S2N_CERT_AUTH_OPTIONAL` will terminate the handshake.
 *
 * @param conn A pointer to the s2n_connection object
 * @param client_auth_type The client auth policy for the connection
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_connection_set_client_auth_type(struct s2n_connection *conn, s2n_cert_auth_type client_auth_type);

/**
 * Gets the client certificate chain and places it in the `der_cert_chain_out` buffer. `cert_chain_len` is updated
 * to match the size the chain buffer.
 *
 * @warning The buffers share a lifetime with the s2n_connection object.
 *
 * @param conn A pointer to the s2n_connection object
 * @param der_cert_chain_out A uint8_t pointer. This will be updated to point to the client certificate chain.
 * @param cert_chain_len A pointer to a uint32_t. This will be updated to match the size of the buffer `der_cert_chain_out` points to.
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_connection_get_client_cert_chain(struct s2n_connection *conn, uint8_t **der_cert_chain_out, uint32_t *cert_chain_len);

/**
 * Sets the initial number of session tickets to send after a >=TLS1.3 handshake. The default value is one ticket.
 *
 * @param config A pointer to the config object.
 * @param num The number of session tickets that will be sent.
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_config_set_initial_ticket_count(struct s2n_config *config, uint8_t num);

/**
 * Increases the number of session tickets to send after a >=TLS1.3 handshake.
 *
 * @param conn A pointer to the connection object.
 * @param num The number of additional session tickets to send.
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_connection_add_new_tickets_to_send(struct s2n_connection *conn, uint8_t num);

/**
 * Returns the number of session tickets issued by the server.
 *
 * In TLS1.3, this number can be up to the limit configured by s2n_config_set_initial_ticket_count
 * and s2n_connection_add_new_tickets_to_send. In earlier versions of TLS, this number will be either 0 or 1.
 *
 * This method only works for server connections.
 *
 * @param conn A pointer to the connection object.
 * @param num The number of additional session tickets sent.
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_connection_get_tickets_sent(struct s2n_connection *conn, uint16_t *num);

/**
 * Sets the keying material lifetime for >=TLS1.3 session tickets so that one session doesn't get re-used ad infinitum.
 * The default value is one week.
 *
 * @param conn A pointer to the connection object.
 * @param lifetime_in_secs Lifetime of keying material in seconds.
 * @returns S2N_SUCCESS on success. S2N_FAILURE on failure
 */
S2N_API
extern int s2n_connection_set_server_keying_material_lifetime(struct s2n_connection *conn, uint32_t lifetime_in_secs);

struct s2n_session_ticket;

/**
 * Callback function for receiving a session ticket.
 *
 * # Safety
 *
 * `ctx` is a void pointer and the caller is responsible for ensuring it is cast to the correct type.
 * `ticket` is valid only within the scope of this callback.
 *
 * @param conn A pointer to the connection object.
 * @param ctx Context for the session ticket callback function.
 * @param ticket Pointer to the received session ticket object.
 */
typedef int (*s2n_session_ticket_fn)(struct s2n_connection *conn, void *ctx, struct s2n_session_ticket *ticket);

/**
 * Sets a session ticket callback to be called when a client receives a new session ticket.
 *
 * # Safety
 *
 * `callback` MUST cast `ctx` into the same type of pointer that was originally created.
 * `ctx` MUST be valid for the lifetime of the config, or until a different context is set.
 *
 * @param config A pointer to the config object.
 * @param callback The function that should be called when the callback is triggered.
 * @param ctx The context to be passed when the callback is called.
 */
S2N_API
extern int s2n_config_set_session_ticket_cb(struct s2n_config *config, s2n_session_ticket_fn callback, void *ctx);

/**
 * Gets the length of the session ticket from a session ticket object.
 *
 * @param ticket Pointer to the session ticket object.
 * @param data_len Pointer to be set to the length of the session ticket on success.
 */
S2N_API
extern int s2n_session_ticket_get_data_len(struct s2n_session_ticket *ticket, size_t *data_len);

/**
 * Gets the session ticket data from a session ticket object.
 *
 * # Safety
 * The entire session ticket will be copied into `data` on success. Therefore, `data` MUST have enough
 * memory to store the session ticket data.
 *
 * @param ticket Pointer to the session ticket object.
 * @param max_data_len Maximum length of data that can be written to the 'data' pointer.
 * @param data Pointer to where the session ticket data will be stored.
 */
S2N_API
extern int s2n_session_ticket_get_data(struct s2n_session_ticket *ticket, size_t max_data_len, uint8_t *data);

/**
 * Gets the lifetime in seconds of the session ticket from a session ticket object.
 *
 * @param ticket Pointer to the session ticket object.
 * @param session_lifetime Pointer to a variable where the lifetime of the session ticket will be stored.
 */
S2N_API
extern int s2n_session_ticket_get_lifetime(struct s2n_session_ticket *ticket, uint32_t *session_lifetime);

/**
 * De-serializes the session state and updates the connection accordingly.
 *
 * @param conn A pointer to the s2n_connection object
 * @param session A pointer to a buffer of size `length`
 * @param length The size of the `session` buffer
 *
 * @returns The number of copied bytes 
 */
S2N_API
extern int s2n_connection_set_session(struct s2n_connection *conn, const uint8_t *session, size_t length);

/**
 * Serializes the session state from connection and copies into the `session` buffer and returns the number of copied bytes
 *
 * The output of this function depends on whether session ids or session tickets are being used for resumption.
 *
 * @note This is for < TLS 1.3 session resumption.
 *
 * @param conn A pointer to the s2n_connection object
 * @param session A pointer to a buffer of size `max_length`
 * @param max_length The size of the `session` buffer
 *
 * @returns The number of copied bytes 
 */
S2N_API
extern int s2n_connection_get_session(struct s2n_connection *conn, uint8_t *session, size_t max_length);

/**
 * Get the lifetime hint for a session.
 *
 * @param conn A pointer to the s2n_connection object
 *
 * @returns The session ticket lifetime hint in seconds from the server or -1 when session ticket was not used for resumption.
 */
S2N_API
extern int s2n_connection_get_session_ticket_lifetime_hint(struct s2n_connection *conn);

/**
 * Use this to query the serialized session state size before copying it into a buffer.
 *
 * @param conn A pointer to the s2n_connection object
 *
 * @returns number of bytes needed to store serialized session state
 */
S2N_API
extern int s2n_connection_get_session_length(struct s2n_connection *conn);

/**
 * Gets the latest session id's length from the connection.
 *
 * Use this to query the session id size before copying it into a buffer.
 *
 * @param conn A pointer to the s2n_connection object
 *
 * @returns The latest session id length from the connection. Session id length will be 0 for TLS versions >= TLS1.3 as stateful session resumption has not yet been implemented in TLS1.3.
 */
S2N_API
extern int s2n_connection_get_session_id_length(struct s2n_connection *conn);

/**
* Gets the latest session id from the connection, copies it into the `session_id` buffer, and returns the number of copied bytes. 
*
* The session id may change between s2n receiving the ClientHello and sending the ServerHello, but this function will always describe the latest session id. 
*
* See s2n_client_hello_get_session_id() to get the session id as it was sent by the client in the ClientHello message.
 *
 * @param conn A pointer to the s2n_connection object
 * @param session_id A pointer to a buffer of size `max_length`
 * @param max_length The size of the `session_id` buffer
 *
 * @returns The number of copied bytes.
 */
S2N_API
extern int s2n_connection_get_session_id(struct s2n_connection *conn, uint8_t *session_id, size_t max_length);

/**
 * Check if the connection was resumed from an earlier handshake.
 *
 * @param conn A pointer to the s2n_connection object
 *
 * @returns returns 1 if the handshake was abbreviated, otherwise returns 0
 */
S2N_API
extern int s2n_connection_is_session_resumed(struct s2n_connection *conn);

/**
 * Check is the connection is OCSP stapled.
 *
 * @param conn A pointer to the s2n_connection object
 *
 * @returns 1 if OCSP response was sent (if connection is in S2N_SERVER mode) or received (if connection is in S2N_CLIENT mode) during handshake, otherwise it returns 0.
 */
S2N_API
extern int s2n_connection_is_ocsp_stapled(struct s2n_connection *conn);

/** 
 * TLS Signature Algorithms - RFC 5246 7.4.1.4.1 
 * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-16 
 */
typedef enum {
    S2N_TLS_SIGNATURE_ANONYMOUS = 0,
    S2N_TLS_SIGNATURE_RSA = 1,
    S2N_TLS_SIGNATURE_ECDSA = 3,

    /* Use Private Range for RSA PSS since it's not defined there */
    S2N_TLS_SIGNATURE_RSA_PSS_RSAE = 224,
    S2N_TLS_SIGNATURE_RSA_PSS_PSS
} s2n_tls_signature_algorithm;

/** TLS Hash Algorithms - https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 
 * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-18 
 */
typedef enum {
    S2N_TLS_HASH_NONE = 0,
    S2N_TLS_HASH_MD5 = 1,
    S2N_TLS_HASH_SHA1 = 2,
    S2N_TLS_HASH_SHA224 = 3,
    S2N_TLS_HASH_SHA256 = 4,
    S2N_TLS_HASH_SHA384 = 5,
    S2N_TLS_HASH_SHA512 = 6,
    
    /* Use Private Range for MD5_SHA1 */
    S2N_TLS_HASH_MD5_SHA1 = 224
} s2n_tls_hash_algorithm;

/**
 * Get the connection's selected signature algorithm.
 *
 * @param conn A pointer to the s2n_connection object
 * @param chosen_alg A pointer to a s2n_tls_signature_algorithm object. This is an output parameter.
 *
 * @returns S2N_SUCCESS on success. S2N_FAILURE if bad parameters are received. 
 */
S2N_API
extern int s2n_connection_get_selected_signature_algorithm(struct s2n_connection *conn, s2n_tls_signature_algorithm *chosen_alg);

/**
 * Get the connection's selected digest algorithm.
 *
 * @param conn A pointer to the s2n_connection object
 * @param chosen_alg A pointer to a s2n_tls_hash_algorithm object. This is an output parameter.
 *
 * @returns S2N_SUCCESS on success. S2N_FAILURE if bad parameters are received. 
 */
S2N_API
extern int s2n_connection_get_selected_digest_algorithm(struct s2n_connection *conn, s2n_tls_hash_algorithm *chosen_alg);

/**
 * Get the client certificate's signature algorithm.
 *
 * @param conn A pointer to the s2n_connection object
 * @param chosen_alg A pointer to a s2n_tls_signature_algorithm object. This is an output parameter.
 *
 * @returns S2N_SUCCESS on success. S2N_FAILURE if bad parameters are received. 
 */
S2N_API
extern int s2n_connection_get_selected_client_cert_signature_algorithm(struct s2n_connection *conn, s2n_tls_signature_algorithm *chosen_alg);

/**
 * Get the client certificate's digest algorithm.
 *
 * @param conn A pointer to the s2n_connection object
 * @param chosen_alg A pointer to a s2n_tls_hash_algorithm object. This is an output parameter.
 *
 * @returns S2N_SUCCESS on success. S2N_FAILURE if bad parameters are received. 
 */
S2N_API
extern int s2n_connection_get_selected_client_cert_digest_algorithm(struct s2n_connection *conn, s2n_tls_hash_algorithm *chosen_alg);

/**
 * Get the certificate used during the TLS handshake
 *
 * - If `conn` is a server connection, the certificate selected will depend on the
 *   ServerName sent by the client and supported ciphers.
 * - If `conn` is a client connection, the certificate sent in response to a CertificateRequest
 *   message is returned. Currently s2n-tls supports loading only one certificate in client mode. Note that
 *   not all TLS endpoints will request a certificate.
 *
 * @param conn A pointer to the s2n_connection object
 *
 * @returns NULL if the certificate selection phase of the handshake has not completed or if a certificate was not requested by the peer
 */
S2N_API
extern struct s2n_cert_chain_and_key *s2n_connection_get_selected_cert(struct s2n_connection *conn);

/**
 * @param chain_and_key A pointer to the s2n_cert_chain_and_key object being read.
 * @param cert_length This return value represents the length of the s2n certificate chain `chain_and_key`.
 * @returns the length of the s2n certificate chain `chain_and_key`.
 */
S2N_API
extern int s2n_cert_chain_get_length(const struct s2n_cert_chain_and_key *chain_and_key, uint32_t *cert_length);

/**
 * Returns the certificate `out_cert` present at the index `cert_idx` of the certificate chain `chain_and_key`.
 * 
 * Note that the index of the leaf certificate is zero. If the certificate chain `chain_and_key` is NULL or the
 * certificate index value is not in the acceptable range for the input certificate chain, an error is returned.
 * 
 * # Safety 
 *
 * There is no memory allocation required for `out_cert` buffer prior to calling the `s2n_cert_chain_get_cert` API.
 * The `out_cert` will contain the pointer to the s2n_cert initialized within the input s2n_cert_chain_and_key `chain_and_key`.
 * The pointer to the output s2n certificate `out_cert` is valid until `chain_and_key` is freed up. 
 * If a caller wishes to persist the `out_cert` beyond the lifetime of `chain_and_key`, the contents would need to be
 * copied prior to freeing `chain_and_key`.
 *
 * @param chain_and_key A pointer to the s2n_cert_chain_and_key object being read.
 * @param out_cert A pointer to the output s2n_cert `out_cert` present at the index `cert_idx` of the certificate chain `chain_and_key`.
 * @param cert_idx The certificate index for the requested certificate within the s2n certificate chain.
 */
S2N_API
extern int s2n_cert_chain_get_cert(const struct s2n_cert_chain_and_key *chain_and_key, struct s2n_cert **out_cert, const uint32_t cert_idx);

/**
 * Returns the s2n certificate in DER format along with its length.
 * 
 * The API gets the s2n certificate `cert` in DER format. The certificate is returned in the `out_cert_der` buffer.
 * Here, `cert_len` represents the length of the certificate.
 * 
 * A caller can use certificate parsing tools such as the ones provided by OpenSSL to parse the DER encoded certificate chain returned.
 *
 * # Safety
 * 
 * The memory for the `out_cert_der` buffer is allocated and owned by s2n-tls. 
 * Since the size of the certificate can potentially be very large, a pointer to internal connection data is returned instead of 
 * copying the contents into a caller-provided buffer.
 * 
 * The pointer to the output buffer `out_cert_der` is valid only while the connection exists.
 * The `s2n_connection_free` API frees the memory associated with the out_cert_der buffer and after the `s2n_connection_wipe` API is
 * called the memory pointed by out_cert_der is invalid.
 * 
 * If a caller wishes to persist the `out_cert_der` beyond the lifetime of the connection, the contents would need to be
 * copied prior to the connection termination.
 * 
 * @param cert A pointer to the s2n_cert object being read.
 * @param out_cert_der A pointer to the output buffer which will hold the s2n certificate `cert` in DER format.
 * @param cert_length This return value represents the length of the certificate.
 */
S2N_API
extern int s2n_cert_get_der(const struct s2n_cert *cert, const uint8_t **out_cert_der, uint32_t *cert_length);

/**
 * Returns the validated peer certificate chain as a `s2n_cert_chain_and_key` opaque object.
 * 
 * The `s2n_cert_chain_and_key` parameter must be allocated by the caller using the `s2n_cert_chain_and_key_new` API
 * prior to this function call and must be empty. To free the memory associated with the `s2n_cert_chain_and_key` object use the 
 * `s2n_cert_chain_and_key_free` API.
 * 
 * @param conn A pointer to the s2n_connection object being read.
 * @param cert_chain The returned validated peer certificate chain `cert_chain` retrieved from the s2n connection.
 */
S2N_API
extern int s2n_connection_get_peer_cert_chain(const struct s2n_connection *conn, struct s2n_cert_chain_and_key *cert_chain);

/**
 * Returns the length of the DER encoded extension value of the ASN.1 X.509 certificate extension.
 * 
 * @param cert A pointer to the s2n_cert object being read.
 * @param oid A null-terminated cstring that contains the OID of the X.509 certificate extension to be read.
 * @param ext_value_len This return value contains the length of DER encoded extension value of the ASN.1 X.509 certificate extension.
 */
S2N_API 
extern int s2n_cert_get_x509_extension_value_length(struct s2n_cert *cert, const uint8_t *oid, uint32_t *ext_value_len);

/**
 * Returns the DER encoding of an ASN.1 X.509 certificate extension value, it's length and a boolean critical.
 * 
 * @param cert A pointer to the s2n_cert object being read.
 * @param oid A null-terminated cstring that contains the OID of the X.509 certificate extension to be read.
 * @param ext_value A pointer to the output buffer which will hold the DER encoding of an ASN.1 X.509 certificate extension value returned. 
 * @param ext_value_len  This value is both an input and output parameter and represents the length of the output buffer `ext_value`. 
 * When used as an input parameter, the caller must use this parameter to convey the maximum length of `ext_value`. 
 * When used as an output parameter, `ext_value_len` holds the actual length of the DER encoding of the ASN.1 X.509 certificate extension value returned. 
 * @param critical This return value contains the boolean value for `critical`.
 */
S2N_API 
extern int s2n_cert_get_x509_extension_value(struct s2n_cert *cert, const uint8_t *oid, uint8_t *ext_value, uint32_t *ext_value_len, bool *critical);

/**
 * Returns the UTF8 String length of the ASN.1 X.509 certificate extension data. 
 * 
 * @param extension_data A pointer to the DER encoded ASN.1 X.509 certificate extension value being read.
 * @param extension_len represents the length of the input buffer `extension_data`.
 * @param utf8_str_len This return value contains the UTF8 String length of the ASN.1 X.509 certificate extension data.
 */
S2N_API 
extern int s2n_cert_get_utf8_string_from_extension_data_length(const uint8_t *extension_data, uint32_t extension_len, uint32_t *utf8_str_len);

/**
 * Returns the UTF8 String representation of the DER encoded ASN.1 X.509 certificate extension data.
 * 
 * @param extension_data A pointer to the DER encoded ASN.1 X.509 certificate extension value being read.
 * @param extension_len represents the length of the input buffer `extension_data`.
 * @param out_data A pointer to the output buffer which will hold the UTF8 String representation of the DER encoded ASN.1 X.509 
 * certificate extension data returned. 
 * @param out_len This value is both an input and output parameter and represents the length of the output buffer `out_data`.
 * When used as an input parameter, the caller must use this parameter to convey the maximum length of `out_data`. 
 * When used as an output parameter, `out_len` holds the actual length of UTF8 String returned.
 */
S2N_API 
extern int s2n_cert_get_utf8_string_from_extension_data(const uint8_t *extension_data, uint32_t extension_len, uint8_t *out_data, uint32_t *out_len);

/** 
 * Pre-shared key (PSK) Hash Algorithm - RFC 8446 Section-2.2
 */
typedef enum {
    S2N_PSK_HMAC_SHA256,
    S2N_PSK_HMAC_SHA384,
} s2n_psk_hmac;

/**
 * Opaque pre shared key handle
 */
struct s2n_psk;

/**
 * Creates a new s2n external pre-shared key (PSK) object with `S2N_PSK_HMAC_SHA256` as the default 
 * PSK hash algorithm. An external PSK is a key established outside of TLS using a secure mutually agreed upon mechanism.
 * 
 * Use `s2n_psk_free` to free the memory allocated to the s2n external PSK object created by this API. 
 *
 * @returns struct s2n_psk* Returns a pointer to the newly created external PSK object.
 */
S2N_API
struct s2n_psk* s2n_external_psk_new(void);

/**
 * Frees the memory associated with the external PSK object.
 *
 * @param psk Pointer to the PSK object to be freed.
 */
S2N_API 
int s2n_psk_free(struct s2n_psk **psk);

/**
 * Sets the identity for a given external PSK object.
 * The identity is a unique identifier for the pre-shared secret.
 * It is a non-secret value represented by raw bytes.
 *
 * # Safety 
 *
 * The identity is transmitted over the network unencrypted and is a non-secret value.
 * Do not include confidential information in the identity.
 * 
 * Note that the identity is copied into s2n-tls memory and the caller is responsible for 
 * freeing the memory associated with the identity input. 
 *
 * @param psk A pointer to a PSK object to be updated with the identity.
 * @param identity The identity in raw bytes format to be copied.
 * @param identity_size The length of the PSK identity being set.
 */
S2N_API 
int s2n_psk_set_identity(struct s2n_psk *psk, const uint8_t *identity, uint16_t identity_size);

/**
 * Sets the out-of-band/externally provisioned secret for a given external PSK object.
 *
 * # Safety
 *
 * Note that the secret is copied into s2n-tls memory and the caller is responsible for 
 * freeing the memory associated with the `secret` input. 
 *
 * Deriving a shared secret from a password or other low-entropy source
 * is not secure and is subject to dictionary attacks.
 * See https://tools.ietf.org/rfc/rfc8446#section-2.2 for more information.
 *
 * @param psk A pointer to a PSK object to be updated with the secret.
 * @param secret The secret in raw bytes format to be copied.
 * @param secret_size The length of the pre-shared secret being set.
 */
S2N_API 
int s2n_psk_set_secret(struct s2n_psk *psk, const uint8_t *secret, uint16_t secret_size);

/**
 * Sets the hash algorithm for a given external PSK object. The supported PSK hash 
 * algorithms are as listed in the enum `s2n_psk_hmac` above.
 * 
 * @param psk A pointer to the external PSK object to be updated with the PSK hash algorithm.
 * @param hmac The PSK hash algorithm being set.  
 */
S2N_API 
int s2n_psk_set_hmac(struct s2n_psk *psk, s2n_psk_hmac hmac);

/**
 * Appends a PSK object to the list of PSKs supported by the s2n connection. 
 * If a PSK with a duplicate identity is found, an error is returned and the PSK is not added to the list.
 * Note that a copy of `psk` is stored on the connection. The user is still responsible for freeing the 
 * memory associated with `psk`.
 *
 * @param conn A pointer to the s2n_connection object that contains the list of PSKs supported.
 * @param psk A pointer to the `s2n_psk` object to be appended to the list of PSKs on the s2n connection.
 */
S2N_API 
int s2n_connection_append_psk(struct s2n_connection *conn, struct s2n_psk *psk);

/**
 * The list of PSK modes supported by s2n-tls for TLS versions >= TLS1.3.
 * Currently s2n-tls supports two modes - `S2N_PSK_MODE_RESUMPTION`, which represents the PSKs established 
 * using the previous connection via session resumption, and `S2N_PSK_MODE_EXTERNAL`, which represents PSKs 
 * established out-of-band/externally using a secure mutually agreed upon mechanism.
 */ 
typedef enum {
    S2N_PSK_MODE_RESUMPTION,
    S2N_PSK_MODE_EXTERNAL 
} s2n_psk_mode;

/**
 * Sets the PSK mode on the s2n config object. 
 * The supported PSK modes are listed in the enum `s2n_psk_mode` above. 
 * 
 * @param config A pointer to the s2n_config object being updated.
 * @param mode The PSK mode to be set.
 */
S2N_API 
int s2n_config_set_psk_mode(struct s2n_config *config, s2n_psk_mode mode);

/**
 * Sets the PSK mode on the s2n connection object.
 * The supported PSK modes are listed in the enum `s2n_psk_mode` above. 
 * This API overrides the PSK mode set on config for this connection.
 *
 * @param conn A pointer to the s2n_connection object being updated.
 * @param mode The PSK mode to be set.
 */
S2N_API 
int s2n_connection_set_psk_mode(struct s2n_connection *conn, s2n_psk_mode mode);

/**
 * Gets the negotiated PSK identity length from the s2n connection object. The negotiated PSK 
 * refers to the chosen PSK by the server to be used for the connection. 
 * 
 * This API can be used to determine if the negotiated PSK exists. If negotiated PSK exists a 
 * call to this API returns a value greater than zero. If the negotiated PSK does not exist, the 
 * value `0` is returned.
 * 
 * @param conn A pointer to the s2n_connection object that successfully negotiated a PSK connection.
 * @param identity_length The length of the negotiated PSK identity. 
 */
S2N_API 
int s2n_connection_get_negotiated_psk_identity_length(struct s2n_connection *conn, uint16_t *identity_length);

/**
 * Gets the negotiated PSK identity from the s2n connection object. 
 * If the negotiated PSK does not exist, the PSK identity will not be obtained and no error will be returned. 
 * Prior to this API call, use `s2n_connection_get_negotiated_psk_identity_length` to determine if a 
 * negotiated PSK exists or not. 
 *
 * # Safety
 *
 * The negotiated PSK identity will be copied into the identity buffer on success.
 * Therefore, the identity buffer must have enough memory to fit the identity length.
 * 
 * @param conn A pointer to the s2n_connection object.
 * @param identity The negotiated PSK identity obtained from the s2n_connection object. 
 * @param max_identity_length The maximum length for the PSK identity. If the negotiated psk_identity length is 
 * greater than this `max_identity_length` value an error will be returned.
 */
S2N_API 
int s2n_connection_get_negotiated_psk_identity(struct s2n_connection *conn, uint8_t *identity, uint16_t max_identity_length);

struct s2n_offered_psk;

/**
 * Creates a new s2n offered PSK object. 
 * An offered PSK object represents a single PSK sent by the client.
 * 
 * # Safety
 * 
 * Use `s2n_offered_psk_free` to free the memory allocated to the s2n offered PSK object created by this API. 
 *
 * @returns struct s2n_offered_psk* Returns a pointer to the newly created offered PSK object.
 */
S2N_API 
struct s2n_offered_psk* s2n_offered_psk_new(void);

/**
 * Frees the memory associated with the `s2n_offered_psk` object.
 *
 * @param psk A pointer to the `s2n_offered_psk` object to be freed.
 */
S2N_API 
int s2n_offered_psk_free(struct s2n_offered_psk **psk);

/**
 * Gets the PSK identity and PSK identity length for a given offered PSK object. 
 * 
 * @param psk A pointer to the offered PSK object being read.
 * @param identity The PSK identity being obtained.
 * @param size The length of the PSK identity being obtained.
 */
S2N_API 
int s2n_offered_psk_get_identity(struct s2n_offered_psk *psk, uint8_t** identity, uint16_t *size);

struct s2n_offered_psk_list;

/**
 * Checks whether the offered PSK list has an offered psk object next in line in the list.
 * An offered PSK list contains all the PSKs offered by the client for the server to select.
 * 
 * # Safety 
 * 
 * This API returns a pointer to the s2n-tls internal memory with limited lifetime. 
 * After the completion of `s2n_psk_selection_callback` this pointer is invalid.
 *
 * @param psk_list A pointer to the offered PSK list being read.
 * @returns bool A boolean value representing whether an offered psk object is present next in line in the offered PSK list.
 */
S2N_API 
bool s2n_offered_psk_list_has_next(struct s2n_offered_psk_list *psk_list);

/**
 * Obtains the next offered PSK object from the list of offered PSKs. Use `s2n_offered_psk_list_has_next` 
 * prior to this API call to ensure we have not reached the end of the list.
 * 
 * @param psk_list A pointer to the offered PSK list being read.
 * @param psk A pointer to the next offered PSK object being obtained.
 */
S2N_API 
int s2n_offered_psk_list_next(struct s2n_offered_psk_list *psk_list, struct s2n_offered_psk *psk);

/**
 * Returns the offered PSK list to its original read state.
 *
 * When `s2n_offered_psk_list_reread` is called, `s2n_offered_psk_list_next` will return the first PSK 
 * in the offered PSK list.
 *
 * @param psk_list A pointer to the offered PSK list being reread.
 */
S2N_API 
int s2n_offered_psk_list_reread(struct s2n_offered_psk_list *psk_list);

/**
 * Chooses a PSK from the offered PSK list to be used for the connection.  
 * This API matches the PSK identity received from the client against the server's known PSK identities 
 * list, in order to choose the PSK to be used for the connection. If the PSK identity sent from the client 
 * is NULL, no PSK is chosen for the connection. If the client offered PSK identity has no matching PSK identity 
 * with the server, an error will be returned. Use this API along with the `s2n_psk_selection_callback` callback 
 * to select a PSK identity.
 * 
 * @param psk_list A pointer to the server's known PSK list used to compare for a matching PSK with the client.
 * @param psk A pointer to the client's PSK object used to compare with the server's known PSK identities.
 */
S2N_API int s2n_offered_psk_list_choose_psk(struct s2n_offered_psk_list *psk_list, struct s2n_offered_psk *psk);

/**
 * Callback function to select a PSK from a list of offered PSKs.
 * Use this callback to implement custom PSK selection logic. The s2n-tls default PSK selection logic 
 * chooses the first matching PSK from the list of offered PSKs sent by the client.
 * 
 * # Safety
 *
 * `context` is a void pointer and the caller is responsible for ensuring it is cast to the correct type.
 * After the completion of this callback, the pointer to `psk_list` is invalid.
 *
 * @param conn A pointer to the s2n_connection object.
 * @param context A pointer to a context for the caller to pass state to the callback, if needed.
 * @param psk_list A pointer to the offered PSK list being read.
 */
typedef int (*s2n_psk_selection_callback)(struct s2n_connection *conn, void *context,
                                          struct s2n_offered_psk_list *psk_list);

/**
 * Sets the callback to select the matching PSK. 
 * If this callback is not set s2n-tls uses a default PSK selection logic that selects the first matching 
 * server PSK.
 * 
 * @param config A pointer to the s2n_config object.
 * @param cb The function that should be called when the callback is triggered.
 * @param context A pointer to a context for the caller to pass state to the callback, if needed.
 */
S2N_API 
int s2n_config_set_psk_selection_callback(struct s2n_config *config, s2n_psk_selection_callback cb, void *context);

/**
 * Get the number of bytes the connection has received.
 *
 * @param conn A pointer to the connection
 * @returns return the number of bytes received by s2n-tls "on the wire"
 */
S2N_API
extern uint64_t s2n_connection_get_wire_bytes_in(struct s2n_connection *conn);

/**
 * Get the number of bytes the connection has transmitted out.
 *
 * @param conn A pointer to the connection
 * @returns return the number of bytes transmitted out by s2n-tls "on the wire"
 */
S2N_API
extern uint64_t s2n_connection_get_wire_bytes_out(struct s2n_connection *conn);

/**
 * Access the protocol version supported by the client of the connection.
 *
 * @param conn A pointer to the connection
 * @returns returns the protocol version number supported by the client_auth_type
 */
S2N_API
extern int s2n_connection_get_client_protocol_version(struct s2n_connection *conn);

/**
 * Access the protocol version supported by the server of the connection.
 *
 * @param conn A pointer to the connection
 * @returns Returns the protocol version number supported by the server
 */
S2N_API
extern int s2n_connection_get_server_protocol_version(struct s2n_connection *conn);

/**
 * Access the protocol version selected for the connection.
 *
 * @param conn A pointer to the connection
 * @returns The protocol version number actually used by s2n-tls for the connection
 */
S2N_API
extern int s2n_connection_get_actual_protocol_version(struct s2n_connection *conn);

/**
 * Access the client hello protocol version for the connection.
 *
 * @param conn A pointer to the connection
 * @returns The protocol version used to send the initial client hello message. 
 */
S2N_API
extern int s2n_connection_get_client_hello_version(struct s2n_connection *conn);

/**
 * Check if Client Auth was used for a connection.
 *
 * @param conn A pointer to the connection
 * @returns 1 if the handshake completed and Client Auth was negotiated during then
 * handshake.
 */
S2N_API
extern int s2n_connection_client_cert_used(struct s2n_connection *conn);

/**
 * A function that provides a human readable string of the cipher suite that was chosen
 * for a connection.
 *
 * @warning The string "TLS_NULL_WITH_NULL_NULL" is returned before the TLS handshake has been performed.
 * This does not mean that the ciphersuite "TLS_NULL_WITH_NULL_NULL" will be used by the connection,
 * it is merely being used as a placeholder.
 *
 * @note This function is only accurate after the TLS handshake.
 *
 * @param conn A pointer to the connection
 * @returns A string indicating the cipher suite negotiated by s2n in OpenSSL format.
 */
S2N_API
extern const char *s2n_connection_get_cipher(struct s2n_connection *conn);

/**
 * Returns the IANA value for the connection's negotiated cipher suite.
 *
 * The value is returned in the form of `first,second`, in order to closely match
 * the values defined in the [IANA Registry](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#table-tls-parameters-4).
 * For example if the connection's negotiated cipher suite is `TLS_AES_128_GCM_SHA256`,
 * which is registered as `0x13,0x01`, then `first = 0x13` and `second = 0x01`.
 *
 * This method will only succeed after the cipher suite has been negotiated with the peer.
 *
 * @param conn A pointer to the connection being read
 * @param first A pointer to a single byte, which will be updated with the first byte in the registered IANA value.
 * @param second A pointer to a single byte, which will be updated with the second byte in the registered IANA value.
 * @returns A POSIX error signal. If an error was returned, the values contained in `first` and `second` should be considered invalid.
 */
S2N_API
extern int s2n_connection_get_cipher_iana_value(struct s2n_connection *conn, uint8_t *first, uint8_t *second);

/**
 * Function to check if the cipher used by current connection is supported by the current
 * cipher preferences.
 * @param conn A pointer to the s2n connection
 * @param version A string representing the security policy to check against.
 * @returns 1 if the connection satisfies the cipher suite. 0 if the connection does not satisfy the cipher suite. -1 if there is an error.
 */
S2N_API
extern int s2n_connection_is_valid_for_cipher_preferences(struct s2n_connection *conn, const char *version);

/**
 * Function to get the human readable elliptic curve name for the connection.
 *
 * @param conn A pointer to the s2n connection
 * @returns A string indicating the elliptic curve used during ECDHE key exchange. The string "NONE" is returned if no curve was used.
 */
S2N_API
extern const char *s2n_connection_get_curve(struct s2n_connection *conn);

/**
 * Function to get the human readable KEM name for the connection.
 *
 * @param conn A pointer to the s2n connection
 * @returns A human readable string for the KEM group. If there is no KEM configured returns "NONE"
 */
S2N_API
extern const char *s2n_connection_get_kem_name(struct s2n_connection *conn);

/**
 * Function to get the human readable KEM group name for the connection.
 *
 * @param conn A pointer to the s2n connection
 * @returns A human readable string for the KEM group. If the connection is < TLS1.3 or there is no KEM group configured returns "NONE"
 */
S2N_API
extern const char *s2n_connection_get_kem_group_name(struct s2n_connection *conn);

/**
 * Function to get the alert that caused a connection to close. s2n-tls considers all
 * TLS alerts fatal and shuts down a connection whenever one is received.
 *
 * @param conn A pointer to the s2n connection
 * @returns The TLS alert code that caused a connection to be shut down
 */
S2N_API
extern int s2n_connection_get_alert(struct s2n_connection *conn);

/**
 * Function to return the last TLS handshake type that was processed. The returned format is a human readable string.
 *
 * @param conn A pointer to the s2n connection
 * @returns A human-readable handshake type name, e.g. "NEGOTIATED|FULL_HANDSHAKE|PERFECT_FORWARD_SECRECY"
 */
S2N_API
extern const char *s2n_connection_get_handshake_type_name(struct s2n_connection *conn);

/**
 * Function to return the last TLS message that was processed. The returned format is a human readable string.
 * @param conn A pointer to the s2n connection
 * @returns The last message name in the TLS state machine, e.g. "SERVER_HELLO", "APPLICATION_DATA". 
 */
S2N_API
extern const char *s2n_connection_get_last_message_name(struct s2n_connection *conn);

/**
 * Opaque async private key operation handle
 */
struct s2n_async_pkey_op;

/**
 * Sets whether or not a connection should enforce strict signature validation during the
 * `s2n_async_pkey_op_apply` call.
 *
 * `mode` can take the following values:
 * - `S2N_ASYNC_PKEY_VALIDATION_FAST` - default behavior: s2n-tls will perform only the minimum validation required for safe use of the asyn pkey operation.
 * - `S2N_ASYNC_PKEY_VALIDATION_STRICT` - in addition to the previous checks, s2n-tls will also ensure that the signature created as a result of the async private key sign operation matches the public key on the connection.
 */
typedef enum { S2N_ASYNC_PKEY_VALIDATION_FAST, S2N_ASYNC_PKEY_VALIDATION_STRICT } s2n_async_pkey_validation_mode;

/**
 * The type of private key operation
 */
typedef enum { S2N_ASYNC_DECRYPT, S2N_ASYNC_SIGN } s2n_async_pkey_op_type;

/**
 * Callback function for handling private key operations
 *
 * Invoked every time an operation requiring the private key is encountered
 * during the handshake.
 *
 * # Safety
 * * `op` is owned by the application and MUST be freed.
 *
 * @param conn Connection which triggered the callback
 * @param op An opaque object representing the private key operation
 */
typedef int (*s2n_async_pkey_fn)(struct s2n_connection *conn, struct s2n_async_pkey_op *op);

/**
 * Sets up the callback to invoke when private key operations occur.
 *
 * @param config Config to set the callback
 * @param fn The function that should be called for each private key operation
 */
S2N_API
extern int s2n_config_set_async_pkey_callback(struct s2n_config *config, s2n_async_pkey_fn fn);

/**
 * Performs a private key operation using the given private key.
 *
 * # Safety
 * * Can only be called once. Any subsequent calls will produce a `S2N_ERR_T_USAGE` error.
 * * Safe to call from inside s2n_async_pkey_fn
 * * Safe to call from a different thread, as long as no other thread is operating on `op`.
 *
 * @param op An opaque object representing the private key operation
 * @param key The private key used for the operation. It can be extracted from
 * `conn` through the `s2n_connection_get_selected_cert` and `s2n_cert_chain_and_key_get_key` calls
 */
S2N_API
extern int s2n_async_pkey_op_perform(struct s2n_async_pkey_op *op, s2n_cert_private_key *key);

/**
 * Finalizes a private key operation and unblocks the connection.
 *
 * # Safety
 * * `conn` must match the connection that originally triggered the callback.
 * * Must be called after the operation is performed.
 * * Can only be called once. Any subsequent calls will produce a `S2N_ERR_T_USAGE` error.
 * * Safe to call from inside s2n_async_pkey_fn
 * * Safe to call from a different thread, as long as no other thread is operating on `op`.
 *
 * @param op An opaque object representing the private key operation
 * @param conn The connection associated with the operation that should be unblocked
 */
S2N_API
extern int s2n_async_pkey_op_apply(struct s2n_async_pkey_op *op, struct s2n_connection *conn);

/**
 * Frees the opaque structure representing a private key operation.
 *
 * # Safety
 * * MUST be called for every operation passed to s2n_async_pkey_fn
 * * Safe to call before or after the connection that created the operation is freed
 *
 * @param op An opaque object representing the private key operation
 */
S2N_API
extern int s2n_async_pkey_op_free(struct s2n_async_pkey_op *op);

/**
 * Configures whether or not s2n-tls will perform potentially expensive validation of
 * the results of a private key operation.
 *
 * @param config Config to set the validation mode for
 * @param mode What level of validation to perform
 */
S2N_API
extern int s2n_config_set_async_pkey_validation_mode(struct s2n_config *config, s2n_async_pkey_validation_mode mode);

/**
 * Returns the type of the private key operation.
 *
 * @param op An opaque object representing the private key operation
 * @param type A pointer to be set to the type
 */
S2N_API
extern int s2n_async_pkey_op_get_op_type(struct s2n_async_pkey_op *op, s2n_async_pkey_op_type *type);

/**
 * Returns the size of the input to the private key operation.
 *
 * @param op An opaque object representing the private key operation
 * @param data_len A pointer to be set to the size
 */
S2N_API
extern int s2n_async_pkey_op_get_input_size(struct s2n_async_pkey_op *op, uint32_t *data_len);

/**
 * Returns the input to the private key operation.
 *
 * When signing, the input is the digest to sign.
 * When decrypting, the input is the data to decrypt.
 *
 * # Safety
 * * `data` must be sufficiently large to contain the input.
 *   `s2n_async_pkey_op_get_input_size` can be called to determine how much memory is required.
 * * s2n-tls does not take ownership of `data`.
 *   The application still owns the memory and must free it if necessary.
 *
 * @param op An opaque object representing the private key operation
 * @param data A pointer to a buffer to copy the input into
 * @param data_len The maximum size of the `data` buffer
 */
S2N_API
extern int s2n_async_pkey_op_get_input(struct s2n_async_pkey_op *op, uint8_t *data, uint32_t data_len);

/**
 * Sets the output of the private key operation.
 *
 * # Safety
 * * s2n-tls does not take ownership of `data`.
 *   The application still owns the memory and must free it if necessary.
 *
 * @param op An opaque object representing the private key operation
 * @param data A pointer to a buffer containing the output
 * @param data_len The size of the `data` buffer
 */
S2N_API
extern int s2n_async_pkey_op_set_output(struct s2n_async_pkey_op *op, const uint8_t *data, uint32_t data_len);

/**
 * Callback function for handling key log events
 *
 * THIS SHOULD BE USED FOR DEBUGGING PURPOSES ONLY!
 *
 * Each log line is formatted with the
 * [NSS Key Log Format](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format)
 * without a newline.
 *
 * # Safety
 *
 * * `ctx` MUST be cast into the same type of pointer that was originally created
 * * `logline` bytes MUST be copied or discarded before this function returns
 *
 * @param ctx Context for the callback
 * @param conn Connection for which the log line is being emitted
 * @param logline Pointer to the log line data
 * @param len Length of the log line data
 */
typedef int (*s2n_key_log_fn)(void *ctx, struct s2n_connection *conn, uint8_t *logline, size_t len);

/**
 * Sets a key logging callback on the provided config
 *
 * THIS SHOULD BE USED FOR DEBUGGING PURPOSES ONLY!
 *
 * Setting this function enables configurations to emit secrets in the
 * [NSS Key Log Format](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format)
 *
 * # Safety
 *
 * * `callback` MUST cast `ctx` into the same type of pointer that was originally created
 * * `ctx` MUST live for at least as long as it is set on the config
 *
 * @param config Config to set the callback
 * @param callback The function that should be called for each secret log entry
 * @param ctx The context to be passed when the callback is called
 */
S2N_API
extern int s2n_config_set_key_log_cb(struct s2n_config *config, s2n_key_log_fn callback, void *ctx);

/** 
 * s2n_config_enable_cert_req_dss_legacy_compat adds a dss cert type in the server certificate request when being called.
 * It only sends the dss cert type in the cert request but does not succeed the handshake if a dss cert is received.
 * Please DO NOT call this api unless you know you actually need legacy DSS certificate type compatibility
 * @param config Config to enable legacy DSS certificates for
 */
S2N_API
extern int s2n_config_enable_cert_req_dss_legacy_compat(struct s2n_config *config);

/**
 * Sets the maximum bytes of early data the server will accept.
 *
 * The default maximum is 0. If the maximum is 0, the server rejects all early data requests.
 * The config maximum can be overridden by the connection maximum or the maximum on an external pre-shared key.
 *
 * @param config A pointer to the config
 * @param max_early_data_size The maximum early data that the server will accept
 * @returns A POSIX error signal. If successful, the maximum early data size was updated.
 */
S2N_API int s2n_config_set_server_max_early_data_size(struct s2n_config *config, uint32_t max_early_data_size);

/**
 * Sets the maximum bytes of early data the server will accept.
 *
 * The default maximum is 0. If the maximum is 0, the server rejects all early data requests.
 * The connection maximum can be overridden by the maximum on an external pre-shared key.
 *
 * @param conn A pointer to the connection
 * @param max_early_data_size The maximum early data the server will accept
 * @returns A POSIX error signal. If successful, the maximum early data size was updated.
 */
S2N_API int s2n_connection_set_server_max_early_data_size(struct s2n_connection *conn, uint32_t max_early_data_size);

/**
 * Sets the user context associated with early data on a server.
 *
 * This context is passed to the `s2n_early_data_cb` callback to help decide whether to accept or reject early data.
 *
 * Unlike most contexts, the early data context is a byte buffer instead of a void pointer.
 * This is because we need to serialize the context into session tickets.
 *
 * This API is intended for use with session resumption, and will not affect pre-shared keys.
 *
 * @param conn A pointer to the connection
 * @param context A pointer to the user context data. This data will be copied.
 * @param context_size The size of the data to read from the `context` pointer.
 * @returns A POSIX error signal. If successful, the context was updated.
 */
S2N_API int s2n_connection_set_server_early_data_context(struct s2n_connection *conn, const uint8_t *context, uint16_t context_size);

/**
 * Configures a particular pre-shared key to allow early data.
 *
 * `max_early_data_size` must be set to the maximum early data accepted by the server.
 *
 * In order to use early data, the cipher suite set on the pre-shared key must match the cipher suite
 * ultimately negotiated by the TLS handshake. Additionally, the cipher suite must have the same
 * hmac algorithm as the pre-shared key.
 *
 * @param psk A pointer to the pre-shared key, created with `s2n_external_psk_new`.
 * @param max_early_data_size The maximum early data that can be sent or received using this key.
 * @param cipher_suite_first_byte The first byte in the registered IANA value of the associated cipher suite.
 * @param cipher_suite_second_byte The second byte in the registered IANA value of the associated cipher suite.
 * @returns A POSIX error signal. If successful, `psk` was updated.
 */
S2N_API int s2n_psk_configure_early_data(struct s2n_psk *psk, uint32_t max_early_data_size,
        uint8_t cipher_suite_first_byte, uint8_t cipher_suite_second_byte);

/**
 * Sets the optional `application_protocol` associated with the given pre-shared key.
 *
 * In order to use early data, the `application_protocol` set on the pre-shared key must match
 * the `application_protocol` ultimately negotiated by the TLS handshake.
 *
 * @param psk A pointer to the pre-shared key, created with `s2n_external_psk_new`.
 * @param application_protocol A pointer to the associated application protocol data. This data will be copied.
 * @param size The size of the data to read from the `application_protocol` pointer.
 * @returns A POSIX error signal. If successful, the application protocol was set.
 */
S2N_API int s2n_psk_set_application_protocol(struct s2n_psk *psk, const uint8_t *application_protocol, uint8_t size);

/**
 * Sets the optional user early data context associated with the given pre-shared key.
 *
 * The early data context is passed to the `s2n_early_data_cb` callback to help decide whether
 * to accept or reject early data.
 *
 * @param psk A pointer to the pre-shared key, created with `s2n_external_psk_new`.
 * @param context A pointer to the associated user context data. This data will be copied.
 * @param size The size of the data to read from the `context` pointer.
 * @returns A POSIX error signal. If successful, the context was set.
 */
S2N_API int s2n_psk_set_early_data_context(struct s2n_psk *psk, const uint8_t *context, uint16_t size);

/** 
 * The status of early data on a connection.
 *
 * S2N_EARLY_DATA_STATUS_OK: Early data is in progress.
 * S2N_EARLY_DATA_STATUS_NOT_REQUESTED: The client did not request early data, so none was sent or received.
 * S2N_EARLY_DATA_STATUS_REJECTED: The client requested early data, but the server rejected the request.
 *                                 Early data may have been sent, but was not received.
 * S2N_EARLY_DATA_STATUS_END: All early data was successfully sent and received.
 */
typedef enum {
    S2N_EARLY_DATA_STATUS_OK,
    S2N_EARLY_DATA_STATUS_NOT_REQUESTED,
    S2N_EARLY_DATA_STATUS_REJECTED,
    S2N_EARLY_DATA_STATUS_END,
} s2n_early_data_status_t;

/**
 * Reports the current state of early data for a connection.
 *
 * See `s2n_early_data_status_t` for all possible states.
 *
 * @param conn A pointer to the connection
 * @param status A pointer which will be set to the current early data status
 * @returns A POSIX error signal.
 */
S2N_API int s2n_connection_get_early_data_status(struct s2n_connection *conn, s2n_early_data_status_t *status);

/**
 * Reports the remaining size of the early data allowed by a connection.
 *
 * If early data was rejected or not requested, the remaining early data size is 0.
 * Otherwise, the remaining early data size is the maximum early data allowed by the connection,
 * minus the early data sent or received so far.
 *
 * @param conn A pointer to the connection
 * @param allowed_early_data_size A pointer which will be set to the remaining early data currently allowed by `conn`
 * @returns A POSIX error signal.
 */
S2N_API int s2n_connection_get_remaining_early_data_size(struct s2n_connection *conn, uint32_t *allowed_early_data_size);

/**
 * Reports the maximum size of the early data allowed by a connection.
 *
 * This is the maximum amount of early data that can ever be sent and received for a connection.
 * It is not affected by the actual status of the early data, so can be non-zero even if early data
 * is rejected or not requested.
 *
 * @param conn A pointer to the connection
 * @param max_early_data_size A pointer which will be set to the maximum early data allowed by `conn`
 * @returns A POSIX error signal.
 */
S2N_API int s2n_connection_get_max_early_data_size(struct s2n_connection *conn, uint32_t *max_early_data_size);

/**
 * Called by the client to begin negotiation and send early data.
 *
 * See https://github.com/aws/s2n-tls/blob/main/docs/USAGE-GUIDE.md#using-early-data--0rtt
 * for usage and examples. DO NOT USE unless you have considered the security issues and
 * implemented mitigation for anti-replay attacks.
 *
 * @param conn A pointer to the connection
 * @param data A pointer to the early data to be sent
 * @param data_len The size of the early data to send
 * @param data_sent A pointer which will be set to the size of the early data sent
 * @param blocked A pointer which will be set to the blocked status, as in `s2n_negotiate`.
 * @returns A POSIX error signal. The error should be handled as in `s2n_negotiate`.
 */
S2N_API int s2n_send_early_data(struct s2n_connection *conn, const uint8_t *data, ssize_t data_len,
        ssize_t *data_sent, s2n_blocked_status *blocked);

/**
 * Called by the server to begin negotiation and accept any early data the client sends.
 *
 * See https://github.com/aws/s2n-tls/blob/main/docs/USAGE-GUIDE.md#using-early-data--0rtt
 * for usage and examples. DO NOT USE unless you have considered the security issues and
 * implemented mitigation for anti-replay attacks.
 *
 * @param conn A pointer to the connection
 * @param data A pointer to a buffer to store the early data received
 * @param max_data_len The size of the early data buffer
 * @param data_received A pointer which will be set to the size of the early data received
 * @param blocked A pointer which will be set to the blocked status, as in `s2n_negotiate`.
 * @returns A POSIX error signal. The error should be handled as in `s2n_negotiate`.
 */
S2N_API int s2n_recv_early_data(struct s2n_connection *conn, uint8_t *data, ssize_t max_data_len,
        ssize_t *data_received, s2n_blocked_status *blocked);

struct s2n_offered_early_data;

/**
 * A callback which can be implemented to accept or reject early data.
 *
 * This callback is triggered only after the server has determined early data is otherwise acceptable according
 * to the TLS early data specification. Implementations therefore only need to cover application-specific checks,
 * not the standard TLS early data validation.
 *
 * This callback can be synchronous or asynchronous. For asynchronous behavior, return success without
 * calling `s2n_offered_early_data_reject` or `s2n_offered_early_data_accept`. `early_data` will
 * still be a valid reference, and the connection will block until `s2n_offered_early_data_reject` or
 * `s2n_offered_early_data_accept` is called.
 *
 * @param conn A pointer to the connection
 * @param early_data A pointer which can be used to access information about the proposed early data
 *                   and then accept or reject it.
 * @returns A POSIX error signal. If unsuccessful, the connection will be closed with an error.
 */
typedef int (*s2n_early_data_cb)(struct s2n_connection *conn, struct s2n_offered_early_data *early_data);

/**
 * Set a callback to accept or reject early data.
 *
 * @param config A pointer to the connection config
 * @param cb A pointer to the implementation of the callback.
 * @returns A POSIX error signal. If successful, the callback was set.
 */
S2N_API int s2n_config_set_early_data_cb(struct s2n_config *config, s2n_early_data_cb cb);

/**
 * Get the length of the early data context set by the user.
 *
 * @param early_data A pointer to the early data information
 * @param context_len The length of the user context
 * @returns A POSIX error signal.
 */
S2N_API int s2n_offered_early_data_get_context_length(struct s2n_offered_early_data *early_data, uint16_t *context_len);

/**
 * Get the early data context set by the user.
 *
 * @param early_data A pointer to the early data information
 * @param context A byte buffer to copy the user context into
 * @param max_len The size of `context`. Must be >= to the result of `s2n_offered_early_data_get_context_length`.
 * @returns A POSIX error signal.
 */
S2N_API int s2n_offered_early_data_get_context(struct s2n_offered_early_data *early_data, uint8_t *context, uint16_t max_len);

/**
 * Reject early data offered by the client.
 *
 * @param early_data A pointer to the early data information
 * @returns A POSIX error signal. If success, the client's early data will be rejected.
 */
S2N_API int s2n_offered_early_data_reject(struct s2n_offered_early_data *early_data);

/**
 * Accept early data offered by the client.
 *
 * @param early_data A pointer to the early data information
 * @returns A POSIX error signal. If success, the client's early data will be accepted.
 */
S2N_API int s2n_offered_early_data_accept(struct s2n_offered_early_data *early_data);

#ifdef __cplusplus
}
#endif