: ext-point-format-length ( -- len )
supported-curves if 6 else 0 then ;
+\ Length of ALPN extension.
+cc: ext-ALPN-length ( -- len ) {
+ size_t u, len;
+
+ if (ENG->protocol_names_num == 0) {
+ T0_PUSH(0);
+ T0_RET();
+ }
+ len = 6;
+ for (u = 0; u < ENG->protocol_names_num; u ++) {
+ len += 1 + strlen(ENG->protocol_names[u]);
+ }
+ T0_PUSH(len);
+}
+
\ Write handshake message: ClientHello
: write-ClientHello ( -- )
{ ; total-ext-length }
ext-reneg-length ext-sni-length + ext-frag-length +
ext-signatures-length +
ext-supported-curves-length + ext-point-format-length +
+ ext-ALPN-length +
>total-ext-length
\ ClientHello type
0x0002 write16 \ extension length
0x0100 write16 \ value: 1 format: uncompressed
then
+ ext-ALPN-length dup if
+ 0x0010 write16 \ extension type (16)
+ 4 - dup write16 \ extension length
+ 2- write16 \ list length
+ addr-protocol_names_num get16 0
+ begin
+ dup2 > while
+ dup copy-protocol-name
+ dup write8 addr-pad swap write-blob
+ 1+
+ repeat
+ 2drop
+ else
+ drop
+ then
ext-padding-amount 0< ifnot
0x0015 write16 \ extension value (21)
ext-padding-amount
then
then ;
+\ Read the ALPN extension from the server. It must contain a single name,
+\ and that name must match one of our names.
+: read-ALPN-from-server ( lim -- lim )
+ \ Extension contents length.
+ read16 open-elt
+ \ Length of list of names.
+ read16 open-elt
+ \ There should be a single name.
+ read8 addr-pad swap dup { len } read-blob
+ close-elt
+ close-elt
+ len test-protocol-name dup 0< if
+ 3 flag? if ERR_UNEXPECTED fail then
+ drop
+ else
+ 1+ addr-selected_protocol set16
+ then ;
+
\ Save a value in a 16-bit field, or check it in case of session resumption.
: check-resume ( val addr resume -- )
if get16 = ifnot ERR_RESUME_MISMATCH fail then else set16 then ;
ext-signatures-length { ok-signatures }
ext-supported-curves-length { ok-curves }
ext-point-format-length { ok-points }
+ ext-ALPN-length { ok-ALPN }
begin dup while
read16
case
read-ignore-16
endof
+ \ ALPN.
+ 0x0010 of
+ ok-ALPN ifnot
+ ERR_EXTRA_EXTENSION fail
+ then
+ 0 >ok-ALPN
+ read-ALPN-from-server
+ endof
+
ERR_EXTRA_EXTENSION fail
endcase
repeat
: do-handshake ( -- )
0 addr-application_data set8
22 addr-record_type_out set8
+ 0 addr-selected_protocol set16
multihash-init
write-ClientHello