lemon-tls 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +432 -122
- package/index.cjs +28 -0
- package/index.d.ts +283 -0
- package/index.js +70 -15
- package/lemontls.svg +1 -1
- package/package.json +120 -62
- package/src/compat.js +235 -0
- package/src/crypto.js +580 -0
- package/src/record.js +232 -0
- package/{secure_context.js → src/secure_context.js} +196 -196
- package/src/session/ecdh.js +61 -0
- package/src/session/message.js +203 -0
- package/src/session/signing.js +129 -0
- package/src/tls_session.js +2204 -0
- package/src/tls_socket.js +877 -0
- package/{utils.js → src/utils.js} +100 -87
- package/{wire.js → src/wire.js} +1499 -1672
- package/crypto.js +0 -383
- package/tls_server.js +0 -0
- package/tls_session.js +0 -1441
- package/tls_socket.js +0 -456
package/{wire.js → src/wire.js}
RENAMED
|
@@ -1,1672 +1,1499 @@
|
|
|
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
|
-
if (
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
} else {
|
|
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
|
-
return
|
|
311
|
-
};
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
}
|
|
324
|
-
return
|
|
325
|
-
};
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
}
|
|
338
|
-
return
|
|
339
|
-
};
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
}
|
|
352
|
-
return
|
|
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
|
-
off =
|
|
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
|
-
off =
|
|
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
|
-
off =
|
|
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
|
-
off =
|
|
1258
|
-
off = w_u8(
|
|
1259
|
-
off = w_u16(
|
|
1260
|
-
off =
|
|
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
|
-
if (ext.type === 0x2b) { // supported_versions
|
|
1503
|
-
var len = ext_data[0];
|
|
1504
|
-
for (var i = 1; i < 1 + len; i += 2) {
|
|
1505
|
-
var ver = (ext_data[i] << 8) | ext_data[i + 1];
|
|
1506
|
-
supported_versions.push(ver);
|
|
1507
|
-
}
|
|
1508
|
-
}
|
|
1509
|
-
if (ext.type === 0x0a) { // supported_groups
|
|
1510
|
-
var len = (ext_data[0] << 8) | ext_data[1];
|
|
1511
|
-
for (var i = 2; i < 2 + len; i += 2) {
|
|
1512
|
-
supported_groups.push((ext_data[i] << 8) | ext_data[i + 1]);
|
|
1513
|
-
}
|
|
1514
|
-
}
|
|
1515
|
-
if (ext.type === 0x0d) { // signature_algorithms
|
|
1516
|
-
var len = (ext_data[0] << 8) | ext_data[1];
|
|
1517
|
-
for (var i = 2; i < 2 + len; i += 2) {
|
|
1518
|
-
signature_algorithms.push((ext_data[i] << 8) | ext_data[i + 1]);
|
|
1519
|
-
}
|
|
1520
|
-
}
|
|
1521
|
-
if (ext.type === 0x10) { // ALPN
|
|
1522
|
-
var list_len = (ext_data[0] << 8) | ext_data[1];
|
|
1523
|
-
var i = 2;
|
|
1524
|
-
while (i < 2 + list_len) {
|
|
1525
|
-
var name_len = ext_data[i++];
|
|
1526
|
-
var proto = new TextDecoder().decode(ext_data.slice(i, i + name_len));
|
|
1527
|
-
alpn.push(proto);
|
|
1528
|
-
i += name_len;
|
|
1529
|
-
}
|
|
1530
|
-
}
|
|
1531
|
-
if (ext.type === 0x39) { // quic_transport_parameters
|
|
1532
|
-
unknown_extensions = ext.data;
|
|
1533
|
-
}
|
|
1534
|
-
if (ext.type === 0x01) { // Max Fragment Length
|
|
1535
|
-
max_fragment_length = ext_data[0];
|
|
1536
|
-
}
|
|
1537
|
-
if (ext.type === 0x15) { // Padding
|
|
1538
|
-
padding = ext_data;
|
|
1539
|
-
}
|
|
1540
|
-
if (ext.type === 0x002a) { // Cookie
|
|
1541
|
-
var len = (ext_data[0] << 8) | ext_data[1];
|
|
1542
|
-
cookie = ext_data.slice(2, 2 + len);
|
|
1543
|
-
}
|
|
1544
|
-
if (ext.type === 0x2d) { // PSK Key Exchange Modes
|
|
1545
|
-
var len = ext_data[0];
|
|
1546
|
-
for (var i = 1; i <= len; i++) {
|
|
1547
|
-
psk_key_exchange_modes.push(ext_data[i]);
|
|
1548
|
-
}
|
|
1549
|
-
}
|
|
1550
|
-
if (ext.type === 0x29) { // PreSharedKey (placeholder)
|
|
1551
|
-
pre_shared_key = ext_data;
|
|
1552
|
-
}
|
|
1553
|
-
if (ext.type === 0xff01) { // Renegotiation Info
|
|
1554
|
-
renegotiation_info = ext_data;
|
|
1555
|
-
}
|
|
1556
|
-
}
|
|
1557
|
-
|
|
1558
|
-
return {
|
|
1559
|
-
legacy_version,
|
|
1560
|
-
random,
|
|
1561
|
-
session_id,
|
|
1562
|
-
cipher_suites,
|
|
1563
|
-
compression_methods,
|
|
1564
|
-
extensions,
|
|
1565
|
-
sni,
|
|
1566
|
-
key_shares,
|
|
1567
|
-
supported_versions,
|
|
1568
|
-
supported_groups,
|
|
1569
|
-
signature_algorithms,
|
|
1570
|
-
alpn,
|
|
1571
|
-
max_fragment_length,
|
|
1572
|
-
padding,
|
|
1573
|
-
cookie,
|
|
1574
|
-
psk_key_exchange_modes,
|
|
1575
|
-
pre_shared_key,
|
|
1576
|
-
renegotiation_info,
|
|
1577
|
-
unknown_extensions
|
|
1578
|
-
};
|
|
1579
|
-
}
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
function build_server_hello(params){
|
|
1585
|
-
var version = params.version|0;
|
|
1586
|
-
var body = [];
|
|
1587
|
-
|
|
1588
|
-
// 1) legacy_version
|
|
1589
|
-
var legacy_version = (version === 0x0304) ? 0x0303 : 0x0303;
|
|
1590
|
-
body.push((legacy_version>>>8)&0xFF, legacy_version&0xFF);
|
|
1591
|
-
|
|
1592
|
-
// 2) random
|
|
1593
|
-
var rnd = params.server_random;
|
|
1594
|
-
for (var i=0;i<rnd.length;i++) body.push(rnd[i]);
|
|
1595
|
-
|
|
1596
|
-
// 3) legacy_session_id
|
|
1597
|
-
var sid = params.legacy_session_id || new Uint8Array(0);
|
|
1598
|
-
body.push(sid.length & 0xFF);
|
|
1599
|
-
for (var i=0;i<sid.length;i++) body.push(sid[i]);
|
|
1600
|
-
|
|
1601
|
-
// 4) cipher_suite
|
|
1602
|
-
var cs = params.cipher_suite|0;
|
|
1603
|
-
body.push((cs>>>8)&0xFF, cs&0xFF);
|
|
1604
|
-
|
|
1605
|
-
// 5) legacy_compression_method
|
|
1606
|
-
body.push(params.compression_method|0);
|
|
1607
|
-
|
|
1608
|
-
// 6) extensions
|
|
1609
|
-
var exts = [];
|
|
1610
|
-
|
|
1611
|
-
if (version === 0x0304){
|
|
1612
|
-
// --- TLS 1.3 extensions ---
|
|
1613
|
-
|
|
1614
|
-
// supported_versions (0x002b)
|
|
1615
|
-
exts.push(0x00,0x2b); // type
|
|
1616
|
-
exts.push(0x00,0x02); // len=2
|
|
1617
|
-
exts.push(0x03,0x04); // TLS1.3
|
|
1618
|
-
|
|
1619
|
-
// key_share (0x0033)
|
|
1620
|
-
var group = params.selected_group|0;
|
|
1621
|
-
var pub = params.server_key_share;
|
|
1622
|
-
var ks = [];
|
|
1623
|
-
ks.push((group>>>8)&0xFF, group&0xFF);
|
|
1624
|
-
ks.push((pub.length>>>8)&0xFF, pub.length&0xFF);
|
|
1625
|
-
for (var j=0;j<pub.length;j++) ks.push(pub[j]);
|
|
1626
|
-
|
|
1627
|
-
exts.push(0x00,0x33); // type
|
|
1628
|
-
exts.push((ks.length>>>8)&0xFF, ks.length&0xFF);
|
|
1629
|
-
for (var j=0;j<ks.length;j++) exts.push(ks[j]);
|
|
1630
|
-
|
|
1631
|
-
} else if (version === 0x0303){
|
|
1632
|
-
// --- TLS 1.2 extensions (אופציונלי) ---
|
|
1633
|
-
|
|
1634
|
-
if (params.secure_renegotiation){
|
|
1635
|
-
// renegotiation_info (0xFF01), length=1, value=0x00
|
|
1636
|
-
exts.push(0xFF,0x01);
|
|
1637
|
-
exts.push(0x00,0x01);
|
|
1638
|
-
exts.push(0x00);
|
|
1639
|
-
}
|
|
1640
|
-
if (params.extended_master_secret){
|
|
1641
|
-
// extended_master_secret (0x0017), empty
|
|
1642
|
-
exts.push(0x00,0x17);
|
|
1643
|
-
exts.push(0x00,0x00);
|
|
1644
|
-
}
|
|
1645
|
-
}
|
|
1646
|
-
|
|
1647
|
-
if (params.extra_extensions && params.extra_extensions.length){
|
|
1648
|
-
for (var e=0;e<params.extra_extensions.length;e++){
|
|
1649
|
-
var ext = params.extra_extensions[e];
|
|
1650
|
-
var et = ext.type|0;
|
|
1651
|
-
var ed = ext.data;
|
|
1652
|
-
exts.push((et>>>8)&0xFF, et&0xFF);
|
|
1653
|
-
exts.push((ed.length>>>8)&0xFF, ed.length&0xFF);
|
|
1654
|
-
for (var k=0;k<ed.length;k++) exts.push(ed[k]);
|
|
1655
|
-
}
|
|
1656
|
-
}
|
|
1657
|
-
|
|
1658
|
-
body.push((exts.length>>>8)&0xFF, exts.length&0xFF);
|
|
1659
|
-
for (var i=0;i<exts.length;i++) body.push(exts[i]);
|
|
1660
|
-
|
|
1661
|
-
// 7) Handshake header (ServerHello=2)
|
|
1662
|
-
var sh = [];
|
|
1663
|
-
sh.push(2); // msg_type=server_hello
|
|
1664
|
-
var len = body.length;
|
|
1665
|
-
sh.push((len>>>16)&0xFF, (len>>>8)&0xFF, len&0xFF);
|
|
1666
|
-
for (var i=0;i<body.length;i++) sh.push(body[i]);
|
|
1667
|
-
|
|
1668
|
-
return new Uint8Array(sh);
|
|
1669
|
-
}
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
*/
|
|
1
|
+
|
|
2
|
+
import {
|
|
3
|
+
concatUint8Arrays
|
|
4
|
+
} from './utils.js';
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
const TLS_VERSION = {
|
|
8
|
+
TLS1_0: 0x0301,
|
|
9
|
+
TLS1_1: 0x0302,
|
|
10
|
+
TLS1_2: 0x0303,
|
|
11
|
+
TLS1_3: 0x0304
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const TLS_CONTENT_TYPE = {
|
|
15
|
+
CHANGE_CIPHER_SPEC: 20,
|
|
16
|
+
ALERT: 21,
|
|
17
|
+
HANDSHAKE: 22,
|
|
18
|
+
APPLICATION_DATA: 23
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const TLS_ALERT_LEVEL = {
|
|
22
|
+
WARNING: 1,
|
|
23
|
+
FATAL: 2
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const TLS_ALERT = {
|
|
27
|
+
CLOSE_NOTIFY: 0,
|
|
28
|
+
UNEXPECTED_MESSAGE: 10,
|
|
29
|
+
BAD_RECORD_MAC: 20,
|
|
30
|
+
RECORD_OVERFLOW: 22,
|
|
31
|
+
HANDSHAKE_FAILURE: 40,
|
|
32
|
+
BAD_CERTIFICATE: 42,
|
|
33
|
+
CERTIFICATE_EXPIRED: 45,
|
|
34
|
+
CERTIFICATE_UNKNOWN: 46,
|
|
35
|
+
ILLEGAL_PARAMETER: 47,
|
|
36
|
+
UNKNOWN_CA: 48,
|
|
37
|
+
DECODE_ERROR: 50,
|
|
38
|
+
DECRYPT_ERROR: 51,
|
|
39
|
+
PROTOCOL_VERSION: 70,
|
|
40
|
+
INSUFFICIENT_SECURITY: 71,
|
|
41
|
+
INTERNAL_ERROR: 80,
|
|
42
|
+
USER_CANCELED: 90,
|
|
43
|
+
MISSING_EXTENSION: 109,
|
|
44
|
+
UNSUPPORTED_EXTENSION: 110,
|
|
45
|
+
UNRECOGNIZED_NAME: 112,
|
|
46
|
+
NO_APPLICATION_PROTOCOL: 120
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const TLS_MESSAGE_TYPE = {
|
|
50
|
+
CLIENT_HELLO: 1,
|
|
51
|
+
SERVER_HELLO: 2,
|
|
52
|
+
NEW_SESSION_TICKET: 4,
|
|
53
|
+
END_OF_EARLY_DATA: 5,
|
|
54
|
+
ENCRYPTED_EXTENSIONS: 8,
|
|
55
|
+
CERTIFICATE: 11,
|
|
56
|
+
SERVER_KEY_EXCHANGE: 12,
|
|
57
|
+
CERTIFICATE_REQUEST: 13,
|
|
58
|
+
SERVER_HELLO_DONE: 14,
|
|
59
|
+
CERTIFICATE_VERIFY: 15,
|
|
60
|
+
CLIENT_KEY_EXCHANGE: 16,
|
|
61
|
+
FINISHED: 20,
|
|
62
|
+
KEY_UPDATE: 24,
|
|
63
|
+
MESSAGE_HASH: 254 // HRR flow marker
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// RFC 8446 §4.1.3: special sentinel random that identifies a ServerHello as HelloRetryRequest
|
|
67
|
+
const TLS13_HRR_RANDOM = new Uint8Array([
|
|
68
|
+
0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11,
|
|
69
|
+
0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91,
|
|
70
|
+
0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E,
|
|
71
|
+
0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C
|
|
72
|
+
]);
|
|
73
|
+
|
|
74
|
+
const TLS_EXT = {
|
|
75
|
+
SERVER_NAME: 0,
|
|
76
|
+
MAX_FRAGMENT_LENGTH: 1,
|
|
77
|
+
STATUS_REQUEST: 5,
|
|
78
|
+
SUPPORTED_GROUPS: 10,
|
|
79
|
+
SIGNATURE_ALGORITHMS: 13,
|
|
80
|
+
USE_SRTP: 14,
|
|
81
|
+
HEARTBEAT: 15,
|
|
82
|
+
ALPN: 16,
|
|
83
|
+
SCT: 18,
|
|
84
|
+
CLIENT_CERT_TYPE: 19,
|
|
85
|
+
SERVER_CERT_TYPE: 20,
|
|
86
|
+
PADDING: 21,
|
|
87
|
+
PRE_SHARED_KEY: 41,
|
|
88
|
+
EARLY_DATA: 42,
|
|
89
|
+
SUPPORTED_VERSIONS: 43,
|
|
90
|
+
COOKIE: 44,
|
|
91
|
+
PSK_KEY_EXCHANGE_MODES: 45,
|
|
92
|
+
CERTIFICATE_AUTHORITIES: 47,
|
|
93
|
+
OID_FILTERS: 48,
|
|
94
|
+
POST_HANDSHAKE_AUTH: 49,
|
|
95
|
+
SIGNATURE_ALGORITHMS_CERT: 50,
|
|
96
|
+
KEY_SHARE: 51,
|
|
97
|
+
RENEGOTIATION_INFO: 0xFF01
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
/* =============================== Small utils ============================== */
|
|
101
|
+
|
|
102
|
+
function toU8(x) {
|
|
103
|
+
if (x == null) return new Uint8Array(0);
|
|
104
|
+
if (x instanceof Uint8Array) return x;
|
|
105
|
+
if (typeof x === 'string') return (new TextEncoder()).encode(x);
|
|
106
|
+
return new Uint8Array(0);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/* ============================ Binary write helpers ============================ */
|
|
110
|
+
function w_u8(buf, off, v) {
|
|
111
|
+
buf[off++] = v & 0xFF;
|
|
112
|
+
return off;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function w_u16(buf, off, v) {
|
|
116
|
+
buf[off++] = (v >>> 8) & 0xFF;
|
|
117
|
+
buf[off++] = v & 0xFF;
|
|
118
|
+
return off;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function w_u24(buf, off, v) {
|
|
122
|
+
buf[off++] = (v >>> 16) & 0xFF;
|
|
123
|
+
buf[off++] = (v >>> 8) & 0xFF;
|
|
124
|
+
buf[off++] = v & 0xFF;
|
|
125
|
+
return off;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function w_bytes(buf, off, b) {
|
|
129
|
+
buf.set(b, off);
|
|
130
|
+
return off + b.length;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/* ============================ Binary read helpers ============================ */
|
|
134
|
+
function r_u8(buf, off) {
|
|
135
|
+
return [buf[off++] >>> 0, off];
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function r_u16(buf, off) {
|
|
139
|
+
let v = ((buf[off] << 8) | buf[off + 1]) >>> 0;
|
|
140
|
+
return [v, off + 2];
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function r_u24(buf, off) {
|
|
144
|
+
let v = ((buf[off] << 16) | (buf[off + 1] << 8) | buf[off + 2]) >>> 0;
|
|
145
|
+
return [v, off + 3];
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function r_bytes(buf, off, n) {
|
|
149
|
+
let slice;
|
|
150
|
+
if (buf instanceof Uint8Array) {
|
|
151
|
+
// real slice from Uint8Array
|
|
152
|
+
slice = buf.slice(off, off + n);
|
|
153
|
+
} else if (typeof Buffer !== "undefined" && Buffer.isBuffer && Buffer.isBuffer(buf)) {
|
|
154
|
+
// Node Buffer slice returns view, copy to Uint8Array
|
|
155
|
+
let tmp = buf.slice(off, off + n);
|
|
156
|
+
slice = new Uint8Array(tmp);
|
|
157
|
+
} else if (Array.isArray(buf)) {
|
|
158
|
+
// plain array
|
|
159
|
+
let tmp = buf.slice(off, off + n);
|
|
160
|
+
slice = new Uint8Array(tmp);
|
|
161
|
+
} else {
|
|
162
|
+
throw new Error("r_bytes: unsupported buffer type " + (typeof buf));
|
|
163
|
+
}
|
|
164
|
+
return [slice, off + n];
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
/* ================================= Vectors ================================= */
|
|
169
|
+
function veclen(lenBytes, inner) {
|
|
170
|
+
let out, off = 0;
|
|
171
|
+
|
|
172
|
+
if (lenBytes === 1) {
|
|
173
|
+
out = new Uint8Array(1 + inner.length);
|
|
174
|
+
off = w_u8(out, off, inner.length);
|
|
175
|
+
off = w_bytes(out, off, inner);
|
|
176
|
+
return out;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (lenBytes === 2) {
|
|
180
|
+
out = new Uint8Array(2 + inner.length);
|
|
181
|
+
off = w_u16(out, off, inner.length);
|
|
182
|
+
off = w_bytes(out, off, inner);
|
|
183
|
+
return out;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (lenBytes === 3) {
|
|
187
|
+
out = new Uint8Array(3 + inner.length);
|
|
188
|
+
off = w_u24(out, off, inner.length);
|
|
189
|
+
off = w_bytes(out, off, inner);
|
|
190
|
+
return out;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
throw new Error('veclen only supports 1/2/3');
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function readVec(buf, off, lenBytes) {
|
|
197
|
+
let n, off2 = off;
|
|
198
|
+
|
|
199
|
+
if (lenBytes === 1) {
|
|
200
|
+
[n, off2] = r_u8(buf, off2);
|
|
201
|
+
} else if (lenBytes === 2) {
|
|
202
|
+
[n, off2] = r_u16(buf, off2);
|
|
203
|
+
} else {
|
|
204
|
+
[n, off2] = r_u24(buf, off2);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
let b;
|
|
208
|
+
[b, off2] = r_bytes(buf, off2, n);
|
|
209
|
+
return [b, off2];
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/* =========================== Extensions registry =========================== */
|
|
213
|
+
let exts = {};
|
|
214
|
+
|
|
215
|
+
// Predeclare wanted entries
|
|
216
|
+
exts.SERVER_NAME = { encode: null, decode: null };
|
|
217
|
+
exts.SUPPORTED_VERSIONS = { encode: null, decode: null };
|
|
218
|
+
exts.SUPPORTED_GROUPS = { encode: null, decode: null };
|
|
219
|
+
exts.SIGNATURE_ALGORITHMS = { encode: null, decode: null };
|
|
220
|
+
exts.PSK_KEY_EXCHANGE_MODES = { encode: null, decode: null };
|
|
221
|
+
exts.KEY_SHARE = { encode: null, decode: null };
|
|
222
|
+
exts.ALPN = { encode: null, decode: null };
|
|
223
|
+
exts.RENEGOTIATION_INFO = { encode: null, decode: null };
|
|
224
|
+
|
|
225
|
+
/* ------------------------------ SERVER_NAME (0) ------------------------------ */
|
|
226
|
+
exts.SERVER_NAME.encode = function (value) {
|
|
227
|
+
let host = toU8(value || "");
|
|
228
|
+
|
|
229
|
+
// one name: type(1)=0, len(2), bytes
|
|
230
|
+
const inner = new Uint8Array(1 + 2 + host.length);
|
|
231
|
+
let off = 0;
|
|
232
|
+
|
|
233
|
+
off = w_u8(inner, off, 0);
|
|
234
|
+
off = w_u16(inner, off, host.length);
|
|
235
|
+
off = w_bytes(inner, off, host);
|
|
236
|
+
|
|
237
|
+
// ServerNameList is vector<2>
|
|
238
|
+
return veclen(2, inner);
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
exts.SERVER_NAME.decode = function (data) {
|
|
242
|
+
let off = 0;
|
|
243
|
+
let list;
|
|
244
|
+
[list, off] = readVec(data, off, 2);
|
|
245
|
+
|
|
246
|
+
let off2 = 0;
|
|
247
|
+
let host = "";
|
|
248
|
+
|
|
249
|
+
while (off2 < list.length) {
|
|
250
|
+
let typ;
|
|
251
|
+
[typ, off2] = r_u8(list, off2);
|
|
252
|
+
|
|
253
|
+
let l;
|
|
254
|
+
[l, off2] = r_u16(list, off2);
|
|
255
|
+
|
|
256
|
+
let v;
|
|
257
|
+
[v, off2] = r_bytes(list, off2, l);
|
|
258
|
+
|
|
259
|
+
if (typ === 0) {
|
|
260
|
+
host = (new TextDecoder()).decode(v);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Return just the value (string), not {host: ...}
|
|
265
|
+
return host;
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
/* --------------------------- SUPPORTED_VERSIONS (43) --------------------------- */
|
|
269
|
+
exts.SUPPORTED_VERSIONS.encode = function (value) {
|
|
270
|
+
// ServerHello form: selected (number)
|
|
271
|
+
if (typeof value === 'number') {
|
|
272
|
+
const out = new Uint8Array(2);
|
|
273
|
+
let off = 0;
|
|
274
|
+
off = w_u16(out, off, value);
|
|
275
|
+
return out;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// ClientHello form: array of versions
|
|
279
|
+
let arr = Array.isArray(value) ? value : [TLS_VERSION.TLS1_3, TLS_VERSION.TLS1_2];
|
|
280
|
+
|
|
281
|
+
const body = new Uint8Array(1 + arr.length * 2);
|
|
282
|
+
let off2 = 0;
|
|
283
|
+
|
|
284
|
+
off2 = w_u8(body, off2, arr.length * 2);
|
|
285
|
+
for (let i = 0; i < arr.length; i++) {
|
|
286
|
+
off2 = w_u16(body, off2, arr[i]);
|
|
287
|
+
}
|
|
288
|
+
return body;
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
exts.SUPPORTED_VERSIONS.decode = function (data) {
|
|
292
|
+
// ServerHello form: 2 bytes
|
|
293
|
+
if (data.length === 2) {
|
|
294
|
+
let v, off = 0;
|
|
295
|
+
[v, off] = r_u16(data, off);
|
|
296
|
+
return [v]; // return the selected version (number)
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// ClientHello form: vector<1> of versions (u16 each)
|
|
300
|
+
let off2 = 0;
|
|
301
|
+
let n;
|
|
302
|
+
[n, off2] = r_u8(data, off2);
|
|
303
|
+
|
|
304
|
+
let out = [];
|
|
305
|
+
for (let i = 0; i < n; i += 2) {
|
|
306
|
+
let vv;
|
|
307
|
+
[vv, off2] = r_u16(data, off2);
|
|
308
|
+
out.push(vv);
|
|
309
|
+
}
|
|
310
|
+
return out; // return the array directly
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
/* ---------------------------- SUPPORTED_GROUPS (10) ---------------------------- */
|
|
314
|
+
exts.SUPPORTED_GROUPS.encode = function (value) {
|
|
315
|
+
let groups = Array.isArray(value) && value.length>0 ? value : [23, 29]; // secp256r1, x25519
|
|
316
|
+
|
|
317
|
+
const body = new Uint8Array(2 + groups.length * 2);
|
|
318
|
+
let off = 0;
|
|
319
|
+
|
|
320
|
+
off = w_u16(body, off, groups.length * 2);
|
|
321
|
+
for (let i = 0; i < groups.length; i++) {
|
|
322
|
+
off = w_u16(body, off, groups[i]);
|
|
323
|
+
}
|
|
324
|
+
return body;
|
|
325
|
+
};
|
|
326
|
+
|
|
327
|
+
exts.SUPPORTED_GROUPS.decode = function (data) {
|
|
328
|
+
let off = 0;
|
|
329
|
+
let n;
|
|
330
|
+
[n, off] = r_u16(data, off);
|
|
331
|
+
|
|
332
|
+
let out = [];
|
|
333
|
+
for (let i = 0; i < n; i += 2) {
|
|
334
|
+
let g;
|
|
335
|
+
[g, off] = r_u16(data, off);
|
|
336
|
+
out.push(g);
|
|
337
|
+
}
|
|
338
|
+
return out; // array of named groups
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
/* -------------------------- SIGNATURE_ALGORITHMS (13) -------------------------- */
|
|
342
|
+
exts.SIGNATURE_ALGORITHMS.encode = function (value) {
|
|
343
|
+
let algs = Array.isArray(value) && value.length>0 ? value : [0x0403, 0x0804, 0x0401];
|
|
344
|
+
|
|
345
|
+
const body = new Uint8Array(2 + algs.length * 2);
|
|
346
|
+
let off = 0;
|
|
347
|
+
|
|
348
|
+
off = w_u16(body, off, algs.length * 2);
|
|
349
|
+
for (let i = 0; i < algs.length; i++) {
|
|
350
|
+
off = w_u16(body, off, algs[i]);
|
|
351
|
+
}
|
|
352
|
+
return body;
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
exts.SIGNATURE_ALGORITHMS.decode = function (data) {
|
|
356
|
+
let off = 0;
|
|
357
|
+
let n;
|
|
358
|
+
[n, off] = r_u16(data, off);
|
|
359
|
+
|
|
360
|
+
let out = [];
|
|
361
|
+
for (let i = 0; i < n; i += 2) {
|
|
362
|
+
let a;
|
|
363
|
+
[a, off] = r_u16(data, off);
|
|
364
|
+
out.push(a);
|
|
365
|
+
}
|
|
366
|
+
return out; // array of sigalgs (u16)
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
/* ------------------------ PSK_KEY_EXCHANGE_MODES (45) ------------------------ */
|
|
370
|
+
exts.PSK_KEY_EXCHANGE_MODES.encode = function (value) {
|
|
371
|
+
let modes = Array.isArray(value) ? value : [1]; // 0=psk_ke, 1=psk_dhe_ke
|
|
372
|
+
|
|
373
|
+
const body = new Uint8Array(1 + modes.length);
|
|
374
|
+
let off = 0;
|
|
375
|
+
|
|
376
|
+
off = w_u8(body, off, modes.length);
|
|
377
|
+
for (let i = 0; i < modes.length; i++) {
|
|
378
|
+
off = w_u8(body, off, modes[i]);
|
|
379
|
+
}
|
|
380
|
+
return body;
|
|
381
|
+
};
|
|
382
|
+
|
|
383
|
+
exts.PSK_KEY_EXCHANGE_MODES.decode = function (data) {
|
|
384
|
+
let off = 0;
|
|
385
|
+
let n;
|
|
386
|
+
[n, off] = r_u8(data, off);
|
|
387
|
+
|
|
388
|
+
let out = [];
|
|
389
|
+
for (let i = 0; i < n; i++) {
|
|
390
|
+
let m;
|
|
391
|
+
[m, off] = r_u8(data, off);
|
|
392
|
+
out.push(m);
|
|
393
|
+
}
|
|
394
|
+
return out; // array of modes (u8)
|
|
395
|
+
};
|
|
396
|
+
|
|
397
|
+
/* ------------------------------- PRE_SHARED_KEY (41) ------------------------------- */
|
|
398
|
+
exts.PRE_SHARED_KEY = { encode: null, decode: null };
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Encode pre_shared_key for ClientHello.
|
|
402
|
+
* value = { identities: [{identity, age}], binders: [Uint8Array] }
|
|
403
|
+
* For ServerHello: value = { selected: number }
|
|
404
|
+
*/
|
|
405
|
+
exts.PRE_SHARED_KEY.encode = function (value) {
|
|
406
|
+
if (typeof value.selected === 'number') {
|
|
407
|
+
// ServerHello: just selected_identity (u16)
|
|
408
|
+
let out = new Uint8Array(2);
|
|
409
|
+
w_u16(out, 0, value.selected);
|
|
410
|
+
return out;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// ClientHello: identities + binders
|
|
414
|
+
let identities = value.identities || [];
|
|
415
|
+
let binders = value.binders || [];
|
|
416
|
+
|
|
417
|
+
// Build identities list
|
|
418
|
+
let idParts = [];
|
|
419
|
+
for (let i = 0; i < identities.length; i++) {
|
|
420
|
+
let id = identities[i].identity;
|
|
421
|
+
if (!(id instanceof Uint8Array)) id = new Uint8Array(id);
|
|
422
|
+
let age = identities[i].age || 0;
|
|
423
|
+
let entry = new Uint8Array(2 + id.length + 4);
|
|
424
|
+
let off = 0;
|
|
425
|
+
off = w_u16(entry, off, id.length);
|
|
426
|
+
off = w_bytes(entry, off, id);
|
|
427
|
+
entry[off++] = (age >>> 24) & 0xff;
|
|
428
|
+
entry[off++] = (age >>> 16) & 0xff;
|
|
429
|
+
entry[off++] = (age >>> 8) & 0xff;
|
|
430
|
+
entry[off++] = age & 0xff;
|
|
431
|
+
idParts.push(entry);
|
|
432
|
+
}
|
|
433
|
+
let idList = concatUint8Arrays(idParts);
|
|
434
|
+
let idVec = veclen(2, idList);
|
|
435
|
+
|
|
436
|
+
// Build binders list
|
|
437
|
+
let binderParts = [];
|
|
438
|
+
for (let i = 0; i < binders.length; i++) {
|
|
439
|
+
let b = binders[i];
|
|
440
|
+
if (!(b instanceof Uint8Array)) b = new Uint8Array(b);
|
|
441
|
+
let entry = new Uint8Array(1 + b.length);
|
|
442
|
+
entry[0] = b.length;
|
|
443
|
+
entry.set(b, 1);
|
|
444
|
+
binderParts.push(entry);
|
|
445
|
+
}
|
|
446
|
+
let binderList = concatUint8Arrays(binderParts);
|
|
447
|
+
let binderVec = veclen(2, binderList);
|
|
448
|
+
|
|
449
|
+
return concatUint8Arrays([idVec, binderVec]);
|
|
450
|
+
};
|
|
451
|
+
|
|
452
|
+
exts.PRE_SHARED_KEY.decode = function (data) {
|
|
453
|
+
let off = 0;
|
|
454
|
+
|
|
455
|
+
// Try ServerHello (2 bytes = selected_identity)
|
|
456
|
+
if (data.length === 2) {
|
|
457
|
+
let sel;
|
|
458
|
+
[sel, off] = r_u16(data, off);
|
|
459
|
+
return { selected: sel };
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
// ClientHello: identities + binders
|
|
463
|
+
let idLen;
|
|
464
|
+
[idLen, off] = r_u16(data, off);
|
|
465
|
+
let idEnd = off + idLen;
|
|
466
|
+
let identities = [];
|
|
467
|
+
while (off < idEnd) {
|
|
468
|
+
let idL;
|
|
469
|
+
[idL, off] = r_u16(data, off);
|
|
470
|
+
let identity;
|
|
471
|
+
[identity, off] = r_bytes(data, off, idL);
|
|
472
|
+
let age = (data[off] << 24) | (data[off+1] << 16) | (data[off+2] << 8) | data[off+3];
|
|
473
|
+
off += 4;
|
|
474
|
+
identities.push({ identity: identity, age: age >>> 0 });
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
let binderLen;
|
|
478
|
+
[binderLen, off] = r_u16(data, off);
|
|
479
|
+
let binderEnd = off + binderLen;
|
|
480
|
+
let binders = [];
|
|
481
|
+
while (off < binderEnd) {
|
|
482
|
+
let bL;
|
|
483
|
+
[bL, off] = r_u8(data, off);
|
|
484
|
+
let binder;
|
|
485
|
+
[binder, off] = r_bytes(data, off, bL);
|
|
486
|
+
binders.push(binder);
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
return { identities: identities, binders: binders };
|
|
490
|
+
};
|
|
491
|
+
|
|
492
|
+
/* --------------------------------- KEY_SHARE (51) -------------------------------- */
|
|
493
|
+
exts.KEY_SHARE.encode = function (value) {
|
|
494
|
+
// ServerHello form: { group:number, key_exchange:Uint8Array }
|
|
495
|
+
if (value && typeof value.group === 'number' && value.key_exchange) {
|
|
496
|
+
let ke = toU8(value.key_exchange);
|
|
497
|
+
|
|
498
|
+
const out = new Uint8Array(2 + 2 + ke.length);
|
|
499
|
+
let off = 0;
|
|
500
|
+
|
|
501
|
+
off = w_u16(out, off, value.group);
|
|
502
|
+
off = w_u16(out, off, ke.length);
|
|
503
|
+
off = w_bytes(out, off, ke);
|
|
504
|
+
|
|
505
|
+
return out;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// ClientHello form: [{ group:number, key_exchange:Uint8Array }, ...]
|
|
509
|
+
let list = Array.isArray(value) ? value : [];
|
|
510
|
+
|
|
511
|
+
let parts = [];
|
|
512
|
+
for (let i = 0; i < list.length; i++) {
|
|
513
|
+
let e = list[i];
|
|
514
|
+
let ke2 = toU8(e.key_exchange || new Uint8Array(0));
|
|
515
|
+
|
|
516
|
+
const ent = new Uint8Array(2 + 2 + ke2.length);
|
|
517
|
+
let o2 = 0;
|
|
518
|
+
|
|
519
|
+
o2 = w_u16(ent, o2, e.group >>> 0);
|
|
520
|
+
o2 = w_u16(ent, o2, ke2.length);
|
|
521
|
+
o2 = w_bytes(ent, o2, ke2);
|
|
522
|
+
|
|
523
|
+
parts.push(ent);
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
return veclen(2, concatUint8Arrays(parts));
|
|
527
|
+
};
|
|
528
|
+
|
|
529
|
+
exts.KEY_SHARE.decode = function (data) {
|
|
530
|
+
// Try ServerHello form: group(2) + len(2) + key
|
|
531
|
+
if (data.length >= 4) {
|
|
532
|
+
let g, off = 0;
|
|
533
|
+
[g, off] = r_u16(data, off);
|
|
534
|
+
|
|
535
|
+
let l;
|
|
536
|
+
[l, off] = r_u16(data, off);
|
|
537
|
+
|
|
538
|
+
if (4 + l === data.length) {
|
|
539
|
+
let ke;
|
|
540
|
+
[ke, off] = r_bytes(data, off, l);
|
|
541
|
+
// Two fields required → return object
|
|
542
|
+
return [{ group: g, key_exchange: ke }];
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
// ClientHello form: vector<2> of KeyShareEntry
|
|
547
|
+
let off2 = 0;
|
|
548
|
+
let listBytes;
|
|
549
|
+
[listBytes, off2] = r_u16(data, off2);
|
|
550
|
+
|
|
551
|
+
let end = off2 + listBytes;
|
|
552
|
+
let out = [];
|
|
553
|
+
|
|
554
|
+
while (off2 < end) {
|
|
555
|
+
let g2;
|
|
556
|
+
[g2, off2] = r_u16(data, off2);
|
|
557
|
+
|
|
558
|
+
let l2;
|
|
559
|
+
[l2, off2] = r_u16(data, off2);
|
|
560
|
+
|
|
561
|
+
let ke2;
|
|
562
|
+
[ke2, off2] = r_bytes(data, off2, l2);
|
|
563
|
+
|
|
564
|
+
out.push({ group: g2, key_exchange: ke2 });
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
return out; // array of entries
|
|
568
|
+
};
|
|
569
|
+
|
|
570
|
+
/* ------------------------------------ ALPN (16) ----------------------------------- */
|
|
571
|
+
exts.ALPN.encode = function (value) {
|
|
572
|
+
let list = Array.isArray(value) ? value : [];
|
|
573
|
+
|
|
574
|
+
let total = 2; // vec16 length
|
|
575
|
+
let items = [];
|
|
576
|
+
|
|
577
|
+
for (let i = 0; i < list.length; i++) {
|
|
578
|
+
let p = toU8(list[i]);
|
|
579
|
+
items.push(p);
|
|
580
|
+
total += 1 + p.length;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
const out = new Uint8Array(total);
|
|
584
|
+
let off = 0;
|
|
585
|
+
|
|
586
|
+
off = w_u16(out, off, total - 2);
|
|
587
|
+
for (let j = 0; j < items.length; j++) {
|
|
588
|
+
off = w_u8(out, off, items[j].length);
|
|
589
|
+
off = w_bytes(out, off, items[j]);
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
return out;
|
|
593
|
+
};
|
|
594
|
+
|
|
595
|
+
exts.ALPN.decode = function (data) {
|
|
596
|
+
let off = 0;
|
|
597
|
+
let n;
|
|
598
|
+
[n, off] = r_u16(data, off);
|
|
599
|
+
|
|
600
|
+
let end = off + n;
|
|
601
|
+
let out = [];
|
|
602
|
+
|
|
603
|
+
while (off < end) {
|
|
604
|
+
let l;
|
|
605
|
+
[l, off] = r_u8(data, off);
|
|
606
|
+
|
|
607
|
+
let v;
|
|
608
|
+
[v, off] = r_bytes(data, off, l);
|
|
609
|
+
|
|
610
|
+
out.push((new TextDecoder()).decode(v));
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
return out; // array of protocol strings
|
|
614
|
+
};
|
|
615
|
+
|
|
616
|
+
/* ----------------------------- RENEGOTIATION_INFO (FF01) ----------------------------- */
|
|
617
|
+
exts.RENEGOTIATION_INFO.encode = function (value) {
|
|
618
|
+
// value is Uint8Array of renegotiated_connection data
|
|
619
|
+
let rb = toU8(value || new Uint8Array(0));
|
|
620
|
+
return veclen(1, rb);
|
|
621
|
+
};
|
|
622
|
+
|
|
623
|
+
exts.RENEGOTIATION_INFO.decode = function (data) {
|
|
624
|
+
let off = 0;
|
|
625
|
+
let v;
|
|
626
|
+
[v, off] = readVec(data, off, 1);
|
|
627
|
+
return v; // return raw bytes (Uint8Array)
|
|
628
|
+
};
|
|
629
|
+
|
|
630
|
+
/* ============================= Extensions helpers ============================= */
|
|
631
|
+
function ext_name_by_code(code) {
|
|
632
|
+
// best-effort pretty name
|
|
633
|
+
for (let k in TLS_EXT) {
|
|
634
|
+
if ((TLS_EXT[k] >>> 0) === (code >>> 0)) return k;
|
|
635
|
+
}
|
|
636
|
+
return 'EXT_' + code;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
function build_extensions(list) {
|
|
640
|
+
// list items may be {type:number|string, value:any, data?:Uint8Array}
|
|
641
|
+
if (!list || !list.length) {
|
|
642
|
+
const e = new Uint8Array(2);
|
|
643
|
+
w_u16(e, 0, 0);
|
|
644
|
+
return e;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
let parts = [];
|
|
648
|
+
let total = 2; // vec16
|
|
649
|
+
|
|
650
|
+
for (let i = 0; i < list.length; i++) {
|
|
651
|
+
let t = list[i].type;
|
|
652
|
+
|
|
653
|
+
// allow symbolic name e.g. 'SERVER_NAME'
|
|
654
|
+
if (typeof t === 'string') {
|
|
655
|
+
t = TLS_EXT[t];
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
let payload;
|
|
659
|
+
if (list[i].data) {
|
|
660
|
+
payload = list[i].data;
|
|
661
|
+
} else {
|
|
662
|
+
// try registry
|
|
663
|
+
let regKey = ext_name_by_code(t);
|
|
664
|
+
let enc = exts[regKey] && exts[regKey].encode;
|
|
665
|
+
payload = enc ? enc(list[i].value) : new Uint8Array(0);
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
const rec = new Uint8Array(4 + payload.length);
|
|
669
|
+
let off = 0;
|
|
670
|
+
|
|
671
|
+
off = w_u16(rec, off, t >>> 0);
|
|
672
|
+
off = w_u16(rec, off, payload.length);
|
|
673
|
+
off = w_bytes(rec, off, payload);
|
|
674
|
+
|
|
675
|
+
parts.push(rec);
|
|
676
|
+
total += rec.length;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
const out = new Uint8Array(total);
|
|
680
|
+
let off2 = 0;
|
|
681
|
+
|
|
682
|
+
off2 = w_u16(out, off2, total - 2);
|
|
683
|
+
|
|
684
|
+
for (let j = 0; j < parts.length; j++) {
|
|
685
|
+
off2 = w_bytes(out, off2, parts[j]);
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
return out;
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
function parse_extensions(buf) {
|
|
692
|
+
let off = 0;
|
|
693
|
+
let n;
|
|
694
|
+
[n, off] = r_u16(buf, off);
|
|
695
|
+
|
|
696
|
+
let end = off + n;
|
|
697
|
+
let out = [];
|
|
698
|
+
|
|
699
|
+
while (off < end) {
|
|
700
|
+
let t;
|
|
701
|
+
[t, off] = r_u16(buf, off);
|
|
702
|
+
|
|
703
|
+
let l;
|
|
704
|
+
[l, off] = r_u16(buf, off);
|
|
705
|
+
|
|
706
|
+
let d;
|
|
707
|
+
[d, off] = r_bytes(buf, off, l);
|
|
708
|
+
|
|
709
|
+
let name = ext_name_by_code(t);
|
|
710
|
+
let dec = exts[name] && exts[name].decode;
|
|
711
|
+
let val = dec ? dec(d) : null;
|
|
712
|
+
|
|
713
|
+
out.push({ type: t, name: name, data: d, value: val });
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
return out;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
|
|
720
|
+
/* ================================ Hello I/O ================================ */
|
|
721
|
+
function build_hello(kind, params) {
|
|
722
|
+
params = params || {};
|
|
723
|
+
|
|
724
|
+
let legacy_version = TLS_VERSION.TLS1_2; // even for TLS1.3 legacy fields
|
|
725
|
+
|
|
726
|
+
let sid = toU8(params.session_id || "");
|
|
727
|
+
if (sid.length > 32) sid = sid.subarray(0, 32);
|
|
728
|
+
|
|
729
|
+
let extsBuf = build_extensions(params.extensions || []);
|
|
730
|
+
|
|
731
|
+
if (kind === 'client') {
|
|
732
|
+
let cs = params.cipher_suites || [0x1301, 0x1302, 0x1303, 0xC02F, 0xC02B];
|
|
733
|
+
|
|
734
|
+
const csBlock = new Uint8Array(2 + cs.length * 2);
|
|
735
|
+
let o = 0;
|
|
736
|
+
o = w_u16(csBlock, o, cs.length * 2);
|
|
737
|
+
for (let i = 0; i < cs.length; i++) {
|
|
738
|
+
o = w_u16(csBlock, o, cs[i]);
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
let comp = params.legacy_compression || [0]; // for TLS1.3 must be [0]
|
|
742
|
+
const compBlock = new Uint8Array(1 + comp.length);
|
|
743
|
+
let oc = 0;
|
|
744
|
+
oc = w_u8(compBlock, oc, comp.length);
|
|
745
|
+
for (let j = 0; j < comp.length; j++) {
|
|
746
|
+
oc = w_u8(compBlock, oc, comp[j]);
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
const out = new Uint8Array(
|
|
750
|
+
2 + 32 + 1 + sid.length + csBlock.length + compBlock.length + extsBuf.length
|
|
751
|
+
);
|
|
752
|
+
|
|
753
|
+
let off = 0;
|
|
754
|
+
off = w_u16(out, off, legacy_version);
|
|
755
|
+
off = w_bytes(out, off, params.random);
|
|
756
|
+
off = w_u8(out, off, sid.length);
|
|
757
|
+
off = w_bytes(out, off, sid);
|
|
758
|
+
off = w_bytes(out, off, csBlock);
|
|
759
|
+
off = w_bytes(out, off, compBlock);
|
|
760
|
+
off = w_bytes(out, off, extsBuf);
|
|
761
|
+
|
|
762
|
+
return out;
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
if (kind === 'server') {
|
|
766
|
+
let cipher_suite = (typeof params.cipher_suite === 'number') ? params.cipher_suite : 0x1301;
|
|
767
|
+
|
|
768
|
+
const out2 = new Uint8Array(2 + 32 + 1 + sid.length + 2 + 1 + extsBuf.length);
|
|
769
|
+
let off2 = 0;
|
|
770
|
+
|
|
771
|
+
off2 = w_u16(out2, off2, legacy_version);
|
|
772
|
+
off2 = w_bytes(out2, off2, params.random);
|
|
773
|
+
off2 = w_u8(out2, off2, sid.length);
|
|
774
|
+
off2 = w_bytes(out2, off2, sid);
|
|
775
|
+
off2 = w_u16(out2, off2, cipher_suite);
|
|
776
|
+
off2 = w_u8(out2, off2, 0); // compression method = 0
|
|
777
|
+
off2 = w_bytes(out2, off2, extsBuf);
|
|
778
|
+
|
|
779
|
+
return out2;
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
throw new Error('build_hello: kind must be "client" or "server"');
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
function parse_hello(hsType, body) {
|
|
786
|
+
let isClient = (hsType === TLS_MESSAGE_TYPE.CLIENT_HELLO || hsType === 'client_hello');
|
|
787
|
+
let off = 0;
|
|
788
|
+
|
|
789
|
+
// --- שדות משותפים ---
|
|
790
|
+
let legacy_version; [legacy_version, off] = r_u16(body, off);
|
|
791
|
+
let random; [random, off] = r_bytes(body, off, 32);
|
|
792
|
+
let sidLen; [sidLen, off] = r_u8(body, off);
|
|
793
|
+
let session_id; [session_id, off] = r_bytes(body, off, sidLen);
|
|
794
|
+
|
|
795
|
+
let cipher_suites = [];
|
|
796
|
+
let legacy_compression = [];
|
|
797
|
+
let type = isClient ? 'client_hello' : 'server_hello';
|
|
798
|
+
|
|
799
|
+
if (isClient) {
|
|
800
|
+
// --- ClientHello ---
|
|
801
|
+
let csLen; [csLen, off] = r_u16(body, off);
|
|
802
|
+
let csEnd = off + csLen;
|
|
803
|
+
while (off < csEnd) {
|
|
804
|
+
let cs; [cs, off] = r_u16(body, off);
|
|
805
|
+
cipher_suites.push(cs);
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
let compLen; [compLen, off] = r_u8(body, off);
|
|
809
|
+
for (let i = 0; i < compLen; i++) {
|
|
810
|
+
let c; [c, off] = r_u8(body, off);
|
|
811
|
+
legacy_compression.push(c);
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
} else {
|
|
815
|
+
// --- ServerHello ---
|
|
816
|
+
let cipher_suite; [cipher_suite, off] = r_u16(body, off);
|
|
817
|
+
cipher_suites = [cipher_suite];
|
|
818
|
+
|
|
819
|
+
let comp; [comp, off] = r_u8(body, off);
|
|
820
|
+
legacy_compression = [comp];
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
// --- extensions (זהה לשני הצדדים, נעשה פעם אחת בלבד) ---
|
|
824
|
+
let extensions = [];
|
|
825
|
+
if (body.length > off) {
|
|
826
|
+
let extRaw = body.subarray(off);
|
|
827
|
+
extensions = parse_extensions(extRaw);
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
// --- version תמיד ערך יחיד ---
|
|
831
|
+
let version = legacy_version;
|
|
832
|
+
|
|
833
|
+
// --- החזרה ---
|
|
834
|
+
return {
|
|
835
|
+
type: type, // 'client_hello' / 'server_hello'
|
|
836
|
+
legacy_version: legacy_version, // single (u16)
|
|
837
|
+
version: version, // single (u16)
|
|
838
|
+
random: random, // single (Uint8Array(32))
|
|
839
|
+
session_id: session_id, // single (Uint8Array)
|
|
840
|
+
cipher_suites: cipher_suites, // array
|
|
841
|
+
legacy_compression: legacy_compression, // array
|
|
842
|
+
extensions: extensions // array (לא נוגעים בפנים)
|
|
843
|
+
};
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
|
|
847
|
+
|
|
848
|
+
|
|
849
|
+
function isVec2(u8){
|
|
850
|
+
if (!(u8 instanceof Uint8Array) || u8.length < 2) return false;
|
|
851
|
+
let len = (u8[0] << 8) | u8[1];
|
|
852
|
+
return u8.length === 2 + len;
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
/* ===================== Certificate / CertificateVerify / Finished ===================== */
|
|
856
|
+
|
|
857
|
+
function build_certificate(params) {
|
|
858
|
+
// Unified API:
|
|
859
|
+
// { version: TLS_VERSION.TLS1_2 | TLS_VERSION.TLS1_3,
|
|
860
|
+
// entries?: [ { cert: Uint8Array|string, extensions?: Uint8Array|ext-list } ],
|
|
861
|
+
// request_context?: Uint8Array|string,
|
|
862
|
+
// // backward-compat:
|
|
863
|
+
// certs?: [Uint8Array|string] }
|
|
864
|
+
//
|
|
865
|
+
// TLS 1.3 → מחזיר: request_context (vec<1>) || certificate_list (vec<3> של [ cert(vec<3>) || extensions(vec<2>) ]*)
|
|
866
|
+
// TLS 1.2 → מחזיר: certificate_list (vec<3> של cert(vec<3>)*), מתעלם מ-extensions/request_context
|
|
867
|
+
|
|
868
|
+
let v = params.version || TLS_VERSION.TLS1_2;
|
|
869
|
+
|
|
870
|
+
// Normalize to entries[] always
|
|
871
|
+
let entries = Array.isArray(params.entries) ? params.entries.slice() : null;
|
|
872
|
+
if (!entries && Array.isArray(params.certs)) {
|
|
873
|
+
// backward-compat: { certs:[...] } → entries:[{cert},...]
|
|
874
|
+
entries = params.certs.map(function (c) { return { cert: c }; });
|
|
875
|
+
}
|
|
876
|
+
if (!entries) entries = [];
|
|
877
|
+
|
|
878
|
+
if (v === TLS_VERSION.TLS1_3) {
|
|
879
|
+
let ctx = toU8(params.request_context || new Uint8Array(0));
|
|
880
|
+
|
|
881
|
+
let entryParts = [];
|
|
882
|
+
for (let i = 0; i < entries.length; i++) {
|
|
883
|
+
let certBytes = toU8(entries[i].cert || new Uint8Array(0));
|
|
884
|
+
let certVec = veclen(3, certBytes); // cert_data vec<3>
|
|
885
|
+
|
|
886
|
+
let extRaw = entries[i].extensions;
|
|
887
|
+
if (Array.isArray(extRaw)) {
|
|
888
|
+
// list of ext objects → encode to vec<2>
|
|
889
|
+
extRaw = build_extensions(extRaw);
|
|
890
|
+
} else if (extRaw instanceof Uint8Array) {
|
|
891
|
+
// already raw bytes; ensure it's vec<2>
|
|
892
|
+
extRaw = isVec2 && isVec2(extRaw) ? extRaw : veclen(2, extRaw);
|
|
893
|
+
} else {
|
|
894
|
+
// no extensions
|
|
895
|
+
extRaw = veclen(2, new Uint8Array(0));
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
entryParts.push(certVec, extRaw);
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
let ctxVec = veclen(1, ctx);
|
|
902
|
+
let listVec = veclen(3, concatUint8Arrays(entryParts));
|
|
903
|
+
return concatUint8Arrays([ctxVec, listVec]);
|
|
904
|
+
|
|
905
|
+
} else {
|
|
906
|
+
// TLS 1.2: only certificate_list (vec<3> of cert(vec<3>)*), ignore per-entry extensions & request_context
|
|
907
|
+
let certListParts = [];
|
|
908
|
+
for (let j = 0; j < entries.length; j++) {
|
|
909
|
+
let c = toU8(entries[j].cert || new Uint8Array(0));
|
|
910
|
+
certListParts.push(veclen(3, c));
|
|
911
|
+
}
|
|
912
|
+
return veclen(3, concatUint8Arrays(certListParts));
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
function parse_certificate(body) {
|
|
917
|
+
// always returns:
|
|
918
|
+
// {
|
|
919
|
+
// version: TLS_VERSION.TLS1_2 | TLS_VERSION.TLS1_3,
|
|
920
|
+
// request_context?: Uint8Array, // רק ב-1.3
|
|
921
|
+
// entries: [ { cert: Uint8Array, extensions?: any[] } ] // ב-1.2 אין extensions
|
|
922
|
+
// }
|
|
923
|
+
|
|
924
|
+
// Try to detect TLS 1.3: rc(vec<1>) ואז list(vec<3> של [cert(vec<3>) || exts(vec<2>)]*)
|
|
925
|
+
if (body && body.length >= 4) {
|
|
926
|
+
let off = 0;
|
|
927
|
+
let rcLen; [rcLen, off] = r_u8(body, off); // 1 byte
|
|
928
|
+
const afterCtx = off + rcLen; // off מצביע אחרי rcLen (כלומר 1)
|
|
929
|
+
if (afterCtx + 3 <= body.length) {
|
|
930
|
+
let listLen, off2 = afterCtx; // התחלת certificate_list
|
|
931
|
+
[listLen, off2] = r_u24(body, off2); // 3 bytes
|
|
932
|
+
if (afterCtx + 3 + listLen === body.length) {
|
|
933
|
+
// looks like valid TLS 1.3
|
|
934
|
+
const request_context = body.subarray(off, off + rcLen);
|
|
935
|
+
off = off2;
|
|
936
|
+
const end = off2 + listLen;
|
|
937
|
+
|
|
938
|
+
const entries = [];
|
|
939
|
+
while (off < end) {
|
|
940
|
+
let certLen; [certLen, off] = r_u24(body, off); // cert_data vec<3>
|
|
941
|
+
let cert; [cert, off] = r_bytes(body, off, certLen);
|
|
942
|
+
|
|
943
|
+
let extLen; [extLen, off] = r_u16(body, off); // extensions vec<2>
|
|
944
|
+
let extRaw; [extRaw, off] = r_bytes(body, off, extLen);
|
|
945
|
+
|
|
946
|
+
const extensions = extLen ? parse_extensions(extRaw) : [];
|
|
947
|
+
entries.push({ cert, extensions });
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
return {
|
|
951
|
+
version: TLS_VERSION.TLS1_3,
|
|
952
|
+
request_context,
|
|
953
|
+
entries
|
|
954
|
+
};
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
// otherwise: TLS 1.2 — certificate_list(vec<3>) של cert(vec<3>)* ללא הרחבות
|
|
960
|
+
let off3 = 0;
|
|
961
|
+
let listLen2; [listLen2, off3] = r_u24(body, off3);
|
|
962
|
+
|
|
963
|
+
const end2 = off3 + listLen2;
|
|
964
|
+
if (end2 !== body.length) {
|
|
965
|
+
// graceful recovery: אם האורך לא תואם, ננסה לפחות לא לקרוס (אפשר גם לזרוק שגיאה)
|
|
966
|
+
// throw new Error('Bad TLS1.2 Certificate length');
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
const entries12 = [];
|
|
970
|
+
while (off3 < Math.min(end2, body.length)) {
|
|
971
|
+
let len3; [len3, off3] = r_u24(body, off3);
|
|
972
|
+
let cert; [cert, off3] = r_bytes(body, off3, len3);
|
|
973
|
+
entries12.push({ cert }); // no per-entry extensions in 1.2
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
return {
|
|
977
|
+
version: TLS_VERSION.TLS1_2,
|
|
978
|
+
entries: entries12
|
|
979
|
+
};
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
|
|
983
|
+
// CertificateVerify (TLS 1.2/1.3 share the same wire framing at this level)
|
|
984
|
+
// struct {
|
|
985
|
+
// SignatureScheme algorithm; // u16
|
|
986
|
+
// opaque signature<0..2^16-1>;
|
|
987
|
+
// } CertificateVerify;
|
|
988
|
+
function build_certificate_verify(scheme, signature) {
|
|
989
|
+
let sig = toU8(signature || new Uint8Array(0));
|
|
990
|
+
let alg = scheme >>> 0;
|
|
991
|
+
|
|
992
|
+
const out = new Uint8Array(2 + 2 + sig.length);
|
|
993
|
+
let off = 0;
|
|
994
|
+
|
|
995
|
+
off = w_u16(out, off, alg);
|
|
996
|
+
off = w_u16(out, off, sig.length);
|
|
997
|
+
off = w_bytes(out, off, sig);
|
|
998
|
+
|
|
999
|
+
return out;
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
function parse_certificate_verify(body) {
|
|
1003
|
+
let off = 0;
|
|
1004
|
+
|
|
1005
|
+
let alg;
|
|
1006
|
+
[alg, off] = r_u16(body, off);
|
|
1007
|
+
|
|
1008
|
+
let slen;
|
|
1009
|
+
[slen, off] = r_u16(body, off);
|
|
1010
|
+
|
|
1011
|
+
let sig;
|
|
1012
|
+
[sig, off] = r_bytes(body, off, slen);
|
|
1013
|
+
|
|
1014
|
+
return { scheme: alg, signature: sig };
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
/* ============================ TLS 1.3 Post-Handshake ============================ */
|
|
1018
|
+
// NewSessionTicket (TLS1.3)
|
|
1019
|
+
// struct {
|
|
1020
|
+
// uint32 ticket_lifetime;
|
|
1021
|
+
// uint32 ticket_age_add;
|
|
1022
|
+
// opaque ticket_nonce<0..2^8-1>;
|
|
1023
|
+
// opaque ticket<1..2^16-1>;
|
|
1024
|
+
// Extension extensions<0..2^16-1>;
|
|
1025
|
+
// } NewSessionTicket;
|
|
1026
|
+
function build_new_session_ticket(p) {
|
|
1027
|
+
let lifetime = (p && p.ticket_lifetime) >>> 0;
|
|
1028
|
+
let age_add = (p && p.ticket_age_add) >>> 0;
|
|
1029
|
+
let nonce = toU8(p && p.ticket_nonce || new Uint8Array(0));
|
|
1030
|
+
let ticket = toU8(p && p.ticket || new Uint8Array(0));
|
|
1031
|
+
let extsBuf = Array.isArray(p && p.extensions) ? build_extensions(p.extensions) : (p && p.extensions) || veclen(2, new Uint8Array(0));
|
|
1032
|
+
|
|
1033
|
+
const out = new Uint8Array(4 + 4 + 1 + nonce.length + 2 + ticket.length + extsBuf.length);
|
|
1034
|
+
let off = 0;
|
|
1035
|
+
|
|
1036
|
+
// u32 big-endian
|
|
1037
|
+
off = w_u8(out, off, (lifetime>>>24)&0xFF);
|
|
1038
|
+
off = w_u8(out, off, (lifetime>>>16)&0xFF);
|
|
1039
|
+
off = w_u8(out, off, (lifetime>>>8)&0xFF);
|
|
1040
|
+
off = w_u8(out, off, (lifetime)&0xFF);
|
|
1041
|
+
|
|
1042
|
+
off = w_u8(out, off, (age_add>>>24)&0xFF);
|
|
1043
|
+
off = w_u8(out, off, (age_add>>>16)&0xFF);
|
|
1044
|
+
off = w_u8(out, off, (age_add>>>8)&0xFF);
|
|
1045
|
+
off = w_u8(out, off, (age_add)&0xFF);
|
|
1046
|
+
|
|
1047
|
+
off = w_u8(out, off, nonce.length);
|
|
1048
|
+
off = w_bytes(out, off, nonce);
|
|
1049
|
+
|
|
1050
|
+
off = w_u16(out, off, ticket.length);
|
|
1051
|
+
off = w_bytes(out, off, ticket);
|
|
1052
|
+
|
|
1053
|
+
off = w_bytes(out, off, extsBuf);
|
|
1054
|
+
|
|
1055
|
+
return out;
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
function parse_new_session_ticket(body) {
|
|
1059
|
+
let off = 0;
|
|
1060
|
+
|
|
1061
|
+
let lifetime = (body[off]<<24 | body[off+1]<<16 | body[off+2]<<8 | body[off+3]) >>> 0; off+=4;
|
|
1062
|
+
let age_add = (body[off]<<24 | body[off+1]<<16 | body[off+2]<<8 | body[off+3]) >>> 0; off+=4;
|
|
1063
|
+
|
|
1064
|
+
let nlen;
|
|
1065
|
+
[nlen, off] = r_u8(body, off);
|
|
1066
|
+
let nonce;
|
|
1067
|
+
[nonce, off] = r_bytes(body, off, nlen);
|
|
1068
|
+
|
|
1069
|
+
let tlen;
|
|
1070
|
+
[tlen, off] = r_u16(body, off);
|
|
1071
|
+
let ticket;
|
|
1072
|
+
[ticket, off] = r_bytes(body, off, tlen);
|
|
1073
|
+
|
|
1074
|
+
let extBuf = body.subarray(off);
|
|
1075
|
+
let extensions = extBuf.length ? parse_extensions(extBuf) : [];
|
|
1076
|
+
|
|
1077
|
+
return {
|
|
1078
|
+
ticket_lifetime: lifetime,
|
|
1079
|
+
ticket_age_add: age_add,
|
|
1080
|
+
ticket_nonce: nonce,
|
|
1081
|
+
ticket: ticket,
|
|
1082
|
+
extensions: extensions
|
|
1083
|
+
};
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
|
|
1087
|
+
/* ================================ CertificateRequest ================================ */
|
|
1088
|
+
// TLS 1.3:
|
|
1089
|
+
// struct {
|
|
1090
|
+
// opaque certificate_request_context<0..2^8-1>;
|
|
1091
|
+
// Extension extensions<0..2^16-1>;
|
|
1092
|
+
// } CertificateRequest;
|
|
1093
|
+
//
|
|
1094
|
+
// TLS 1.2:
|
|
1095
|
+
// struct {
|
|
1096
|
+
// ClientCertificateType certificate_types<1..2^8-1>;
|
|
1097
|
+
// SignatureAndHashAlgorithm signature_algorithms<2..2^16-2>; // optional in <1.2
|
|
1098
|
+
// DistinguishedName certificate_authorities<0..2^16-1>; // vector of DNs, each DN is opaque<1..2^16-1>
|
|
1099
|
+
// } CertificateRequest;
|
|
1100
|
+
|
|
1101
|
+
function build_certificate_request(params) {
|
|
1102
|
+
let v = params && params.version || TLS_VERSION.TLS1_3;
|
|
1103
|
+
|
|
1104
|
+
if (v === TLS_VERSION.TLS1_3) {
|
|
1105
|
+
let ctx = toU8((params && params.request_context) || new Uint8Array(0));
|
|
1106
|
+
let extsBuf = Array.isArray(params && params.extensions)
|
|
1107
|
+
? build_extensions(params.extensions)
|
|
1108
|
+
: (params && params.extensions) || veclen(2, new Uint8Array(0));
|
|
1109
|
+
|
|
1110
|
+
let ctxVec = veclen(1, ctx);
|
|
1111
|
+
return concatUint8Arrays([ctxVec, extsBuf]);
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
// TLS 1.2 / 1.0 / 1.1
|
|
1115
|
+
let typesArr = (params && params.certificate_types) || [1]; // rsa_sign(1) as default
|
|
1116
|
+
const typesBuf = new Uint8Array(typesArr.length);
|
|
1117
|
+
for (let i = 0; i < typesArr.length; i++) typesBuf[i] = typesArr[i] & 0xFF;
|
|
1118
|
+
let typesVec = veclen(1, typesBuf);
|
|
1119
|
+
|
|
1120
|
+
let sigalgs = (params && params.signature_algorithms) || [];
|
|
1121
|
+
const sigBuf = new Uint8Array(sigalgs.length * 2);
|
|
1122
|
+
let o = 0;
|
|
1123
|
+
for (let j = 0; j < sigalgs.length; j++) o = w_u16(sigBuf, o, sigalgs[j]);
|
|
1124
|
+
let sigVec = sigalgs.length ? veclen(2, sigBuf) : new Uint8Array(0);
|
|
1125
|
+
|
|
1126
|
+
let cas = (params && params.certificate_authorities) || [];
|
|
1127
|
+
let caParts = [];
|
|
1128
|
+
let caTotal = 0;
|
|
1129
|
+
for (let k = 0; k < cas.length; k++) {
|
|
1130
|
+
let dn = toU8(cas[k]);
|
|
1131
|
+
const ent = new Uint8Array(2 + dn.length);
|
|
1132
|
+
let oo = 0; oo = w_u16(ent, oo, dn.length); oo = w_bytes(ent, oo, dn);
|
|
1133
|
+
caParts.push(ent); caTotal += ent.length;
|
|
1134
|
+
}
|
|
1135
|
+
let caVec = veclen(2, caParts.length ? concatUint8Arrays(caParts) : new Uint8Array(0));
|
|
1136
|
+
|
|
1137
|
+
return concatUint8Arrays([typesVec, sigVec, caVec]);
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
function parse_certificate_request(body) {
|
|
1141
|
+
// Try TLS 1.3 form first: ctx<1> + extensions<2>
|
|
1142
|
+
if (body.length >= 3) {
|
|
1143
|
+
let ctxLen = body[0];
|
|
1144
|
+
if (1 + ctxLen + 2 <= body.length) {
|
|
1145
|
+
let extLen = (body[1 + ctxLen] << 8) | body[2 + ctxLen];
|
|
1146
|
+
if (1 + ctxLen + 2 + extLen === body.length) {
|
|
1147
|
+
let ctx = body.subarray(1, 1 + ctxLen);
|
|
1148
|
+
let extBuf = body.subarray(1 + ctxLen + 2);
|
|
1149
|
+
return {
|
|
1150
|
+
version: TLS_VERSION.TLS1_3,
|
|
1151
|
+
request_context: ctx,
|
|
1152
|
+
extensions: parse_extensions(extBuf)
|
|
1153
|
+
};
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
// Otherwise TLS 1.2/1.1/1.0
|
|
1159
|
+
let off = 0;
|
|
1160
|
+
|
|
1161
|
+
let typesBytes, off1;
|
|
1162
|
+
[typesBytes, off1] = readVec(body, off, 1);
|
|
1163
|
+
off = off1;
|
|
1164
|
+
let certificate_types = [];
|
|
1165
|
+
for (let i = 0; i < typesBytes.length; i++) certificate_types.push(typesBytes[i] >>> 0);
|
|
1166
|
+
|
|
1167
|
+
let signature_algorithms = [];
|
|
1168
|
+
if (off + 2 <= body.length) {
|
|
1169
|
+
let sigLen = (body[off] << 8) | body[off + 1];
|
|
1170
|
+
if (off + 2 + sigLen <= body.length) {
|
|
1171
|
+
off += 2;
|
|
1172
|
+
let endSig = off + sigLen;
|
|
1173
|
+
while (off < endSig) {
|
|
1174
|
+
let alg;
|
|
1175
|
+
[alg, off] = r_u16(body, off);
|
|
1176
|
+
signature_algorithms.push(alg);
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
let cas = [];
|
|
1182
|
+
if (off + 2 <= body.length) {
|
|
1183
|
+
let caLen;
|
|
1184
|
+
[caLen, off] = r_u16(body, off);
|
|
1185
|
+
let end = off + caLen;
|
|
1186
|
+
while (off < end) {
|
|
1187
|
+
let dnLen;
|
|
1188
|
+
[dnLen, off] = r_u16(body, off);
|
|
1189
|
+
let dn;
|
|
1190
|
+
[dn, off] = r_bytes(body, off, dnLen);
|
|
1191
|
+
cas.push(dn);
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
return {
|
|
1196
|
+
version: TLS_VERSION.TLS1_2,
|
|
1197
|
+
certificate_types: certificate_types,
|
|
1198
|
+
signature_algorithms: signature_algorithms,
|
|
1199
|
+
certificate_authorities: cas
|
|
1200
|
+
};
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
|
|
1204
|
+
|
|
1205
|
+
/* ============================== TLS 1.3 HelloRetryRequest ============================== */
|
|
1206
|
+
function build_hello_retry_request(params) {
|
|
1207
|
+
// params: { cipher_suite, selected_version, selected_group, cookie?: Uint8Array|string, other_exts?: list }
|
|
1208
|
+
let rnd = TLS13_HRR_RANDOM;
|
|
1209
|
+
const sid = new Uint8Array(0);
|
|
1210
|
+
let legacy_version = TLS_VERSION.TLS1_2;
|
|
1211
|
+
|
|
1212
|
+
let extList = [];
|
|
1213
|
+
// supported_versions (selected)
|
|
1214
|
+
extList.push({ type: 'SUPPORTED_VERSIONS', value: (params && params.selected_version) || TLS_VERSION.TLS1_3 });
|
|
1215
|
+
// key_share: only selected_group (no key)
|
|
1216
|
+
if (params && params.selected_group != null) {
|
|
1217
|
+
extList.push({ type: 'KEY_SHARE', value: { selected_group: params.selected_group, key_exchange: new Uint8Array(0) } });
|
|
1218
|
+
}
|
|
1219
|
+
// cookie if supplied
|
|
1220
|
+
if (params && params.cookie) {
|
|
1221
|
+
if (!exts.COOKIE) { exts.COOKIE = { encode: function(v){ return veclen(2, toU8(v||'')); }, decode: function(d){ let off=0,v; [v,off]=readVec(d,0,2); return v; } }; }
|
|
1222
|
+
extList.push({ type: 'COOKIE', value: params.cookie });
|
|
1223
|
+
}
|
|
1224
|
+
// other extensions passthrough
|
|
1225
|
+
if (params && Array.isArray(params.other_exts)) {
|
|
1226
|
+
for (let i=0;i<params.other_exts.length;i++) extList.push(params.other_exts[i]);
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
let extsBuf = build_extensions(extList);
|
|
1230
|
+
let cipher_suite = (params && typeof params.cipher_suite==='number') ? params.cipher_suite : 0x1301;
|
|
1231
|
+
|
|
1232
|
+
// Wire = legacy_version + random + sid + cipher_suite + compression(0) + extensions
|
|
1233
|
+
const out = new Uint8Array(2 + 32 + 1 + 0 + 2 + 1 + extsBuf.length);
|
|
1234
|
+
let off = 0;
|
|
1235
|
+
off = w_u16(out, off, legacy_version);
|
|
1236
|
+
off = w_bytes(out, off, rnd);
|
|
1237
|
+
off = w_u8(out, off, 0);
|
|
1238
|
+
off = w_u16(out, off, cipher_suite);
|
|
1239
|
+
off = w_u8(out, off, 0);
|
|
1240
|
+
off = w_bytes(out, off, extsBuf);
|
|
1241
|
+
return out;
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
/* ============================== TLS 1.2 ServerKeyExchange ============================== */
|
|
1245
|
+
// We'll implement the common ECDHE form and basic DHE form.
|
|
1246
|
+
// ECDHE ServerKeyExchange:
|
|
1247
|
+
// struct {
|
|
1248
|
+
// ECParameters curve; // curve_type(1)=3, named_curve(2)
|
|
1249
|
+
// opaque ec_point<1..2^8-1>; // server's ephemeral ECDH public key
|
|
1250
|
+
// digitally-signed struct { .. } // in TLS1.2: SignatureAndHashAlgorithm(2) + signature<2>
|
|
1251
|
+
// }
|
|
1252
|
+
function build_server_key_exchange_ecdhe(p) {
|
|
1253
|
+
// p: { group:u16, public:Uint8Array|string, sig_alg:u16, signature:Uint8Array|string }
|
|
1254
|
+
let pub = toU8(p.public_key||new Uint8Array(0));
|
|
1255
|
+
|
|
1256
|
+
const head = new Uint8Array(1+2 + 1 + pub.length);
|
|
1257
|
+
let off = 0;
|
|
1258
|
+
off = w_u8(head, off, 3); // curve_type = named_curve
|
|
1259
|
+
off = w_u16(head, off, p.group>>>0); // named group
|
|
1260
|
+
off = w_u8(head, off, pub.length); // ec_point length
|
|
1261
|
+
off = w_bytes(head, off, pub);
|
|
1262
|
+
|
|
1263
|
+
let sig = toU8(p.signature||new Uint8Array(0));
|
|
1264
|
+
const sigpart = new Uint8Array(2 + 2 + sig.length);
|
|
1265
|
+
let o2 = 0;
|
|
1266
|
+
o2 = w_u16(sigpart, o2, p.sig_alg>>>0);
|
|
1267
|
+
o2 = w_u16(sigpart, o2, sig.length);
|
|
1268
|
+
o2 = w_bytes(sigpart, o2, sig);
|
|
1269
|
+
|
|
1270
|
+
return concatUint8Arrays([head, sigpart]);
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1273
|
+
function parse_server_key_exchange(body) {
|
|
1274
|
+
let off = 0;
|
|
1275
|
+
let curve_type;
|
|
1276
|
+
[curve_type, off] = r_u8(body, off);
|
|
1277
|
+
|
|
1278
|
+
if (curve_type === 3) { // named_curve (ECDHE)
|
|
1279
|
+
let group;
|
|
1280
|
+
[group, off] = r_u16(body, off);
|
|
1281
|
+
|
|
1282
|
+
let plen;
|
|
1283
|
+
[plen, off] = r_u8(body, off);
|
|
1284
|
+
|
|
1285
|
+
let pub;
|
|
1286
|
+
[pub, off] = r_bytes(body, off, plen);
|
|
1287
|
+
|
|
1288
|
+
let sig_alg;
|
|
1289
|
+
[sig_alg, off] = r_u16(body, off);
|
|
1290
|
+
|
|
1291
|
+
let slen;
|
|
1292
|
+
[slen, off] = r_u16(body, off);
|
|
1293
|
+
|
|
1294
|
+
let sig;
|
|
1295
|
+
[sig, off] = r_bytes(body, off, slen);
|
|
1296
|
+
|
|
1297
|
+
return { kex: 'ECDHE', group: group, public_key: pub, sig_alg: sig_alg, signature: sig };
|
|
1298
|
+
}
|
|
1299
|
+
|
|
1300
|
+
// Basic DHE: dh_p<2>, dh_g<2>, dh_Ys<2>, then SignatureAndHashAlgorithm + signature<2>
|
|
1301
|
+
let pLen;
|
|
1302
|
+
[pLen, off] = r_u16(body, off);
|
|
1303
|
+
let dh_p;
|
|
1304
|
+
[dh_p, off] = r_bytes(body, off, pLen);
|
|
1305
|
+
|
|
1306
|
+
let gLen;
|
|
1307
|
+
[gLen, off] = r_u16(body, off);
|
|
1308
|
+
let dh_g;
|
|
1309
|
+
[dh_g, off] = r_bytes(body, off, gLen);
|
|
1310
|
+
|
|
1311
|
+
let yLen;
|
|
1312
|
+
[yLen, off] = r_u16(body, off);
|
|
1313
|
+
let dh_Ys;
|
|
1314
|
+
[dh_Ys, off] = r_bytes(body, off, yLen);
|
|
1315
|
+
|
|
1316
|
+
let sig_alg2;
|
|
1317
|
+
[sig_alg2, off] = r_u16(body, off);
|
|
1318
|
+
|
|
1319
|
+
let s2len;
|
|
1320
|
+
[s2len, off] = r_u16(body, off);
|
|
1321
|
+
let sig2;
|
|
1322
|
+
[sig2, off] = r_bytes(body, off, s2len);
|
|
1323
|
+
|
|
1324
|
+
return { kex: 'DHE', dh_p: dh_p, dh_g: dh_g, dh_Ys: dh_Ys, sig_alg: sig_alg2, signature: sig2 };
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
/* ============================== TLS 1.2 ClientKeyExchange ============================== */
|
|
1328
|
+
// Two common forms:
|
|
1329
|
+
// 1) ECDHE: opaque ec_point<1..2^8-1>
|
|
1330
|
+
// 2) RSA : EncryptedPreMasterSecret opaque<2>
|
|
1331
|
+
function build_client_key_exchange_ecdhe(pubkey) {
|
|
1332
|
+
let p = toU8(pubkey||new Uint8Array(0));
|
|
1333
|
+
return veclen(1, p);
|
|
1334
|
+
}
|
|
1335
|
+
function parse_client_key_exchange_ecdhe(body) {
|
|
1336
|
+
let off=0; let v; [v,off]=readVec(body,0,1); return v;
|
|
1337
|
+
}
|
|
1338
|
+
|
|
1339
|
+
function build_client_key_exchange_rsa(enc_pms) {
|
|
1340
|
+
let e = toU8(enc_pms||new Uint8Array(0));
|
|
1341
|
+
return veclen(2, e);
|
|
1342
|
+
}
|
|
1343
|
+
function parse_client_key_exchange_rsa(body) {
|
|
1344
|
+
let off=0; let v; [v,off]=readVec(body,0,2); return v;
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1347
|
+
/* ============================== TLS 1.2 NewSessionTicket ============================== */
|
|
1348
|
+
// struct {
|
|
1349
|
+
// uint32 ticket_lifetime_hint;
|
|
1350
|
+
// opaque ticket<0..2^16-1>;
|
|
1351
|
+
// } NewSessionTicket;
|
|
1352
|
+
function build_new_session_ticket_tls12(p) {
|
|
1353
|
+
let hint = (p && p.ticket_lifetime_hint) >>> 0;
|
|
1354
|
+
let ticket = toU8(p && p.ticket || new Uint8Array(0));
|
|
1355
|
+
const out = new Uint8Array(4 + 2 + ticket.length);
|
|
1356
|
+
let off = 0;
|
|
1357
|
+
off = w_u8(out, off, (hint>>>24)&0xFF);
|
|
1358
|
+
off = w_u8(out, off, (hint>>>16)&0xFF);
|
|
1359
|
+
off = w_u8(out, off, (hint>>>8)&0xFF);
|
|
1360
|
+
off = w_u8(out, off, (hint)&0xFF);
|
|
1361
|
+
off = w_u16(out, off, ticket.length);
|
|
1362
|
+
off = w_bytes(out, off, ticket);
|
|
1363
|
+
return out;
|
|
1364
|
+
}
|
|
1365
|
+
function parse_new_session_ticket_tls12(body) {
|
|
1366
|
+
let off=0;
|
|
1367
|
+
let hint = (body[off]<<24 | body[off+1]<<16 | body[off+2]<<8 | body[off+3])>>>0; off+=4;
|
|
1368
|
+
let tlen; [tlen,off]=r_u16(body,off); let t; [t,off]=r_bytes(body,off,tlen);
|
|
1369
|
+
return { ticket_lifetime_hint: hint, ticket: t };
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1372
|
+
/* ============================= Handshake message ============================= */
|
|
1373
|
+
|
|
1374
|
+
|
|
1375
|
+
function build_message(type,body) {
|
|
1376
|
+
|
|
1377
|
+
const out = new Uint8Array(4 + body.length);
|
|
1378
|
+
let off = 0;
|
|
1379
|
+
|
|
1380
|
+
off = w_u8(out, off, type);
|
|
1381
|
+
off = w_u24(out, off, body.length);
|
|
1382
|
+
off = w_bytes(out, off, body);
|
|
1383
|
+
|
|
1384
|
+
return out;
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
function parse_message(buf) {
|
|
1388
|
+
let off = 0;
|
|
1389
|
+
let t;
|
|
1390
|
+
[t, off] = r_u8(buf, off);
|
|
1391
|
+
|
|
1392
|
+
let l;
|
|
1393
|
+
[l, off] = r_u24(buf, off);
|
|
1394
|
+
|
|
1395
|
+
let b;
|
|
1396
|
+
[b, off] = r_bytes(buf, off, l);
|
|
1397
|
+
|
|
1398
|
+
return { type: t, body: b };
|
|
1399
|
+
}
|
|
1400
|
+
|
|
1401
|
+
|
|
1402
|
+
// Build ServerECDHParams structure for ECDHE in TLS 1.2
|
|
1403
|
+
// group: u16 (e.g. 0x001D or 0x0017)
|
|
1404
|
+
// public_key: Uint8Array (already normalized for wire format)
|
|
1405
|
+
function build_server_ecdh_params(group, public_key) {
|
|
1406
|
+
const params = new Uint8Array(1 + 2 + 1 + public_key.length);
|
|
1407
|
+
let off = 0;
|
|
1408
|
+
off = w_u8(params, off, 3); // curve_type = named_curve
|
|
1409
|
+
off = w_u16(params, off, group >>> 0); // namedcurve
|
|
1410
|
+
off = w_u8(params, off, public_key.length); // pubkey length
|
|
1411
|
+
off = w_bytes(params, off, public_key); // pubkey
|
|
1412
|
+
return params;
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
|
|
1416
|
+
/* ========================= KeyUpdate (RFC 8446 §4.6.3) ========================= */
|
|
1417
|
+
|
|
1418
|
+
/**
|
|
1419
|
+
* Build KeyUpdate message body.
|
|
1420
|
+
* request_update: 0 = update_not_requested, 1 = update_requested
|
|
1421
|
+
*/
|
|
1422
|
+
function build_key_update(request_update) {
|
|
1423
|
+
return new Uint8Array([request_update ? 1 : 0]);
|
|
1424
|
+
}
|
|
1425
|
+
|
|
1426
|
+
/**
|
|
1427
|
+
* Parse KeyUpdate message body.
|
|
1428
|
+
* Returns { request_update: 0|1 }
|
|
1429
|
+
*/
|
|
1430
|
+
function parse_key_update(body) {
|
|
1431
|
+
return { request_update: body[0] || 0 };
|
|
1432
|
+
}
|
|
1433
|
+
|
|
1434
|
+
|
|
1435
|
+
/* ================================ Exports ================================= */
|
|
1436
|
+
export {
|
|
1437
|
+
TLS_VERSION,
|
|
1438
|
+
TLS_CONTENT_TYPE,
|
|
1439
|
+
TLS_ALERT_LEVEL,
|
|
1440
|
+
TLS_ALERT,
|
|
1441
|
+
TLS_MESSAGE_TYPE,
|
|
1442
|
+
TLS_EXT,
|
|
1443
|
+
|
|
1444
|
+
w_u8,
|
|
1445
|
+
w_u16,
|
|
1446
|
+
w_u24,
|
|
1447
|
+
w_bytes,
|
|
1448
|
+
r_u8,
|
|
1449
|
+
r_u16,
|
|
1450
|
+
r_u24,
|
|
1451
|
+
r_bytes,
|
|
1452
|
+
veclen,
|
|
1453
|
+
readVec,
|
|
1454
|
+
|
|
1455
|
+
exts,
|
|
1456
|
+
build_extensions,
|
|
1457
|
+
parse_extensions,
|
|
1458
|
+
|
|
1459
|
+
build_message,
|
|
1460
|
+
parse_message,
|
|
1461
|
+
build_hello,
|
|
1462
|
+
parse_hello,
|
|
1463
|
+
|
|
1464
|
+
build_certificate,
|
|
1465
|
+
parse_certificate,
|
|
1466
|
+
|
|
1467
|
+
build_certificate_verify,
|
|
1468
|
+
parse_certificate_verify,
|
|
1469
|
+
|
|
1470
|
+
build_new_session_ticket,
|
|
1471
|
+
parse_new_session_ticket,
|
|
1472
|
+
|
|
1473
|
+
build_certificate_request,
|
|
1474
|
+
parse_certificate_request,
|
|
1475
|
+
|
|
1476
|
+
build_hello_retry_request,
|
|
1477
|
+
TLS13_HRR_RANDOM,
|
|
1478
|
+
|
|
1479
|
+
build_server_key_exchange_ecdhe,
|
|
1480
|
+
parse_server_key_exchange,
|
|
1481
|
+
|
|
1482
|
+
build_client_key_exchange_ecdhe,
|
|
1483
|
+
parse_client_key_exchange_ecdhe,
|
|
1484
|
+
|
|
1485
|
+
build_client_key_exchange_rsa,
|
|
1486
|
+
parse_client_key_exchange_rsa,
|
|
1487
|
+
|
|
1488
|
+
build_new_session_ticket_tls12,
|
|
1489
|
+
parse_new_session_ticket_tls12,
|
|
1490
|
+
|
|
1491
|
+
build_server_ecdh_params,
|
|
1492
|
+
|
|
1493
|
+
build_key_update,
|
|
1494
|
+
parse_key_update,
|
|
1495
|
+
};
|
|
1496
|
+
|
|
1497
|
+
|
|
1498
|
+
|
|
1499
|
+
|