X-Git-Url: https://www.bearssl.org/gitweb//home/git/?p=BearSSL;a=blobdiff_plain;f=src%2Fssl%2Fssl_hs_server.t0;h=a31ab6aaeba94934dfa525ec48aac7441b5729ca;hp=862e0fbfbfb761e6ba298df15dee4228be0526e5;hb=44c79c1add4cd4a217b1dd77c8421c1d3a08dcef;hpb=e61ad42191511226309bad2cbde8cd9e8cc743cb diff --git a/src/ssl/ssl_hs_server.t0 b/src/ssl/ssl_hs_server.t0 index 862e0fb..a31ab6a 100644 --- a/src/ssl/ssl_hs_server.t0 +++ b/src/ssl/ssl_hs_server.t0 @@ -181,7 +181,7 @@ do_ecdhe_part1(br_ssl_server_context *ctx, int curve) { int hash; unsigned mask; - const unsigned char *order, *generator; + const unsigned char *order; size_t olen, glen; br_multihash_context mhc; unsigned char head[4]; @@ -213,6 +213,8 @@ do_ecdhe_part1(br_ssl_server_context *ctx, int curve) /* * Compute our ECDH point. */ +#if 0 +/* obsolete */ generator = ctx->eng.iec->generator(curve, &glen); memcpy(ctx->eng.ecdhe_point, generator, glen); ctx->eng.ecdhe_point_len = glen; @@ -221,6 +223,10 @@ do_ecdhe_part1(br_ssl_server_context *ctx, int curve) { return -BR_ERR_INVALID_ALGORITHM; } +#endif + glen = ctx->eng.iec->mulgen(ctx->eng.ecdhe_point, + ctx->ecdhe_key, olen, curve); + ctx->eng.ecdhe_point_len = glen; /* * Compute the signature. @@ -528,6 +534,41 @@ cc: set-max-frag-len ( len -- ) { close-elt close-elt ; +\ Read the ALPN extension from client. +: read-ALPN-from-client ( lim -- lim ) + \ If we do not have configured names, then we just ignore the + \ extension. + addr-protocol_names_num get16 ifnot read-ignore-16 ret then + + \ Open extension value. + read16 open-elt + + \ Open list of protocol names. + read16 open-elt + + \ Get all names and test for their support. We keep the one with + \ the lowest index (because we apply server's preferences, as + \ recommended by RFC 7301, section 3.2. We set the 'found' variable + \ to -2 and use an unsigned comparison, making -2 a huge value. + -2 { found } + begin dup while + read8 dup { len } addr-pad swap read-blob + len test-protocol-name dup found u< if + >found + else + drop + then + repeat + + \ End of extension. + close-elt + close-elt + + \ Write back found name index (or not). If no match was found, + \ then we write -1 (0xFFFF) in the index value, not 0, so that + \ the caller knows that we tried to match, and failed. + found 1+ addr-selected_protocol set16 ; + \ Call policy handler to get cipher suite, hash function identifier and \ certificate chain. Returned value is 0 (false) on failure. cc: call-policy-handler ( -- bool ) { @@ -585,7 +626,7 @@ cc: save-session ( -- ) { check-resume { resume } \ Cipher suites. We read all cipher suites from client, each time - \ matching against our own list. We accumulare suites in the + \ matching against our own list. We accumulate suites in the \ client_suites[] context buffer: we keep suites that are \ supported by both the client and the server (so the list size \ cannot exceed that of the server list), and we keep them in @@ -709,6 +750,11 @@ cc: save-session ( -- ) { \ read-ignore-16 \ endof + \ ALPN + 0x0010 of + read-ALPN-from-client + endof + \ Other extensions are ignored. drop read-ignore-16 0 endcase @@ -772,7 +818,7 @@ cc: save-session ( -- ) { \ In 'can-ecdhe', bit 12 is set if ECDHE_RSA is possible, bit 13 is \ set if ECDHE_ECDSA is possible. dup 0xFF and 0<> neg - swap 8 >> 0<> 2 and or { can-ecdhe } + swap 8 >> 0<> 2 and or 12 << { can-ecdhe } \ Filter supported curves. If there is no common curve between \ client and us, then ECDHE suites cannot be used. Note that we @@ -832,6 +878,12 @@ cc: save-session ( -- ) { then addr-client_suites_num set8 + \ Check ALPN. + addr-selected_protocol get16 0xFFFF = if + 3 flag? if 120 fail-alert then + 0 addr-selected_protocol set16 + then + \ Call policy handler to obtain the cipher suite and other \ parameters. call-policy-handler ifnot 40 fail-alert then @@ -842,20 +894,28 @@ cc: save-session ( -- ) { \ Write ServerHello. : write-ServerHello ( initial -- ) { initial } - \ Compute ServerHello length. Right now we only send the - \ "secure renegotiation" extension. + \ Compute ServerHello length. 2 write8 70 + \ Compute length of Secure Renegotiation extension. addr-reneg get8 2 = if initial if 5 else 29 then else 0 then { ext-reneg-len } + + \ Compute length of Max Fragment Length extension. addr-peer_log_max_frag_len get8 if 5 else 0 then { ext-max-frag-len } - ext-reneg-len ext-max-frag-len + dup if 2 + then + + \ Compute length of ALPN extension. This also copy the + \ selected protocol name into the pad. + addr-selected_protocol get16 dup if 1- copy-protocol-name 7 + then + { ext-ALPN-len } + + \ Adjust ServerHello length to account for the extensions. + ext-reneg-len ext-max-frag-len + ext-ALPN-len + dup if 2 + then + write24 \ Protocol version @@ -880,7 +940,7 @@ cc: save-session ( -- ) { 0 write8 \ Extensions - ext-reneg-len ext-max-frag-len + dup if + ext-reneg-len ext-max-frag-len + ext-ALPN-len + dup if write16 ext-reneg-len dup if 0xFF01 write16 @@ -893,6 +953,16 @@ cc: save-session ( -- ) { 0x0001 write16 1 write16 addr-peer_log_max_frag_len get8 8 - write8 then + ext-ALPN-len dup if + \ Note: the selected protocol name was previously + \ copied into the pad. + 0x0010 write16 + 4 - dup write16 + 2- dup write16 + 1- addr-pad swap write-blob-head8 + else + drop + then else drop then ; @@ -1289,6 +1359,7 @@ cc: verify-CV-sig ( sig-len -- err ) { : do-handshake ( initial -- ) 0 addr-application_data set8 22 addr-record_type_out set8 + 0 addr-selected_protocol set16 multihash-init read-ClientHello more-incoming-bytes? if ERR_UNEXPECTED fail then