Added ALPN support (client and server).
[BearSSL] / src / ssl / ssl_hs_server.t0
1 \ Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
2 \
3 \ Permission is hereby granted, free of charge, to any person obtaining
4 \ a copy of this software and associated documentation files (the
5 \ "Software"), to deal in the Software without restriction, including
6 \ without limitation the rights to use, copy, modify, merge, publish,
7 \ distribute, sublicense, and/or sell copies of the Software, and to
8 \ permit persons to whom the Software is furnished to do so, subject to
9 \ the following conditions:
10 \
11 \ The above copyright notice and this permission notice shall be
12 \ included in all copies or substantial portions of the Software.
13 \
14 \ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 \ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 \ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 \ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
18 \ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19 \ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 \ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 \ SOFTWARE.
22
23 \ ----------------------------------------------------------------------
24 \ Handshake processing code, for the server.
25 \ The common T0 code (ssl_hs_common.t0) shall be read first.
26
27 preamble {
28
29 /*
30 * This macro evaluates to a pointer to the server context, under that
31 * specific name. It must be noted that since the engine context is the
32 * first field of the br_ssl_server_context structure ('eng'), then
33 * pointers values of both types are interchangeable, modulo an
34 * appropriate cast. This also means that "adresses" computed as offsets
35 * within the structure work for both kinds of context.
36 */
37 #define CTX ((br_ssl_server_context *)ENG)
38
39 /*
40 * Decrypt the pre-master secret (RSA key exchange).
41 */
42 static void
43 do_rsa_decrypt(br_ssl_server_context *ctx, int prf_id,
44 unsigned char *epms, size_t len)
45 {
46 uint32_t x;
47 unsigned char rpms[48];
48
49 /*
50 * Decrypt the PMS.
51 */
52 x = (*ctx->policy_vtable)->do_keyx(ctx->policy_vtable, epms, len);
53
54 /*
55 * Set the first two bytes to the maximum supported client
56 * protocol version. These bytes are used for version rollback
57 * detection; forceing the two bytes will make the master secret
58 * wrong if the bytes are not correct. This process is
59 * recommended by RFC 5246 (section 7.4.7.1).
60 */
61 br_enc16be(epms, ctx->client_max_version);
62
63 /*
64 * Make a random PMS and copy it above the decrypted value if the
65 * decryption failed. Note that we use a constant-time conditional
66 * copy.
67 */
68 br_hmac_drbg_generate(&ctx->eng.rng, rpms, sizeof rpms);
69 br_ccopy(x ^ 1, epms, rpms, sizeof rpms);
70
71 /*
72 * Compute master secret.
73 */
74 br_ssl_engine_compute_master(&ctx->eng, prf_id, epms, 48);
75
76 /*
77 * Clear the pre-master secret from RAM: it is normally a buffer
78 * in the context, hence potentially long-lived.
79 */
80 memset(epms, 0, len);
81 }
82
83 /*
84 * Common part for ECDH and ECDHE.
85 */
86 static void
87 ecdh_common(br_ssl_server_context *ctx, int prf_id,
88 unsigned char *cpoint, size_t cpoint_len, uint32_t ctl)
89 {
90 unsigned char rpms[80];
91 size_t pms_len;
92
93 /*
94 * The point length is supposed to be 1+2*Xlen, where Xlen is
95 * the length (in bytes) of the X coordinate, i.e. the pre-master
96 * secret. If the provided point is too large, then it is
97 * obviously incorrect (i.e. everybody can see that it is
98 * incorrect), so leaking that fact is not a problem.
99 */
100 pms_len = cpoint_len >> 1;
101 if (pms_len > sizeof rpms) {
102 pms_len = sizeof rpms;
103 ctl = 0;
104 }
105
106 /*
107 * Make a random PMS and copy it above the decrypted value if the
108 * decryption failed. Note that we use a constant-time conditional
109 * copy.
110 */
111 br_hmac_drbg_generate(&ctx->eng.rng, rpms, pms_len);
112 br_ccopy(ctl ^ 1, cpoint + 1, rpms, pms_len);
113
114 /*
115 * Compute master secret.
116 */
117 br_ssl_engine_compute_master(&ctx->eng, prf_id, cpoint + 1, pms_len);
118
119 /*
120 * Clear the pre-master secret from RAM: it is normally a buffer
121 * in the context, hence potentially long-lived.
122 */
123 memset(cpoint, 0, cpoint_len);
124 }
125
126 /*
127 * Do the ECDH key exchange (not ECDHE).
128 */
129 static void
130 do_ecdh(br_ssl_server_context *ctx, int prf_id,
131 unsigned char *cpoint, size_t cpoint_len)
132 {
133 uint32_t x;
134
135 /*
136 * Finalise the key exchange.
137 */
138 x = (*ctx->policy_vtable)->do_keyx(ctx->policy_vtable,
139 cpoint, cpoint_len);
140 ecdh_common(ctx, prf_id, cpoint, cpoint_len, x);
141 }
142
143 /*
144 * Do the full static ECDH key exchange. When this function is called,
145 * it has already been verified that the cipher suite uses ECDH (not ECDHE),
146 * and the client's public key (from its certificate) has type EC and is
147 * apt for key exchange.
148 */
149 static void
150 do_static_ecdh(br_ssl_server_context *ctx, int prf_id)
151 {
152 unsigned char cpoint[133];
153 size_t cpoint_len;
154 const br_x509_class **xc;
155 const br_x509_pkey *pk;
156
157 xc = ctx->eng.x509ctx;
158 pk = (*xc)->get_pkey(xc, NULL);
159 cpoint_len = pk->key.ec.qlen;
160 if (cpoint_len > sizeof cpoint) {
161 /*
162 * If the point is larger than our buffer then we need to
163 * restrict it. Length 2 is not a valid point length, so
164 * the ECDH will fail.
165 */
166 cpoint_len = 2;
167 }
168 memcpy(cpoint, pk->key.ec.q, cpoint_len);
169 do_ecdh(ctx, prf_id, cpoint, cpoint_len);
170 }
171
172 /*
173 * Do the ECDHE key exchange (part 1: generation of transient key, and
174 * computing of the point to send to the client). Returned value is the
175 * signature length (in bytes), or -x on error (with x being an error
176 * code). The encoded point is written in the ecdhe_point[] context buffer
177 * (length in ecdhe_point_len).
178 */
179 static int
180 do_ecdhe_part1(br_ssl_server_context *ctx, int curve)
181 {
182 int hash;
183 unsigned mask;
184 const unsigned char *order, *generator;
185 size_t olen, glen;
186 br_multihash_context mhc;
187 unsigned char head[4];
188 size_t hv_len, sig_len;
189
190 if (!((ctx->eng.iec->supported_curves >> curve) & 1)) {
191 return -BR_ERR_INVALID_ALGORITHM;
192 }
193 ctx->eng.ecdhe_curve = curve;
194
195 /*
196 * Generate our private key. We need a non-zero random value
197 * which is lower than the curve order, in a "large enough"
198 * range. We force the top bit to 0 and bottom bit to 1, which
199 * does the trick. Note that contrary to what happens in ECDSA,
200 * this is not a problem if we do not cover the full range of
201 * possible values.
202 */
203 order = ctx->eng.iec->order(curve, &olen);
204 mask = 0xFF;
205 while (mask >= order[0]) {
206 mask >>= 1;
207 }
208 br_hmac_drbg_generate(&ctx->eng.rng, ctx->ecdhe_key, olen);
209 ctx->ecdhe_key[0] &= mask;
210 ctx->ecdhe_key[olen - 1] |= 0x01;
211 ctx->ecdhe_key_len = olen;
212
213 /*
214 * Compute our ECDH point.
215 */
216 generator = ctx->eng.iec->generator(curve, &glen);
217 memcpy(ctx->eng.ecdhe_point, generator, glen);
218 ctx->eng.ecdhe_point_len = glen;
219 if (!ctx->eng.iec->mul(ctx->eng.ecdhe_point, glen,
220 ctx->ecdhe_key, olen, curve))
221 {
222 return -BR_ERR_INVALID_ALGORITHM;
223 }
224
225 /*
226 * Compute the signature.
227 */
228 br_multihash_zero(&mhc);
229 br_multihash_copyimpl(&mhc, &ctx->eng.mhash);
230 br_multihash_init(&mhc);
231 br_multihash_update(&mhc,
232 ctx->eng.client_random, sizeof ctx->eng.client_random);
233 br_multihash_update(&mhc,
234 ctx->eng.server_random, sizeof ctx->eng.server_random);
235 head[0] = 3;
236 head[1] = 0;
237 head[2] = curve;
238 head[3] = ctx->eng.ecdhe_point_len;
239 br_multihash_update(&mhc, head, sizeof head);
240 br_multihash_update(&mhc,
241 ctx->eng.ecdhe_point, ctx->eng.ecdhe_point_len);
242 hash = ctx->sign_hash_id;
243 if (hash) {
244 hv_len = br_multihash_out(&mhc, hash, ctx->eng.pad);
245 if (hv_len == 0) {
246 return -BR_ERR_INVALID_ALGORITHM;
247 }
248 } else {
249 if (!br_multihash_out(&mhc, br_md5_ID, ctx->eng.pad)
250 || !br_multihash_out(&mhc,
251 br_sha1_ID, ctx->eng.pad + 16))
252 {
253 return -BR_ERR_INVALID_ALGORITHM;
254 }
255 hv_len = 36;
256 }
257 sig_len = (*ctx->policy_vtable)->do_sign(ctx->policy_vtable,
258 hash, hv_len, ctx->eng.pad, sizeof ctx->eng.pad);
259 return sig_len ? (int)sig_len : -BR_ERR_INVALID_ALGORITHM;
260 }
261
262 /*
263 * Do the ECDHE key exchange (part 2: computation of the shared secret
264 * from the point sent by the client).
265 */
266 static void
267 do_ecdhe_part2(br_ssl_server_context *ctx, int prf_id,
268 unsigned char *cpoint, size_t cpoint_len)
269 {
270 int curve;
271 uint32_t x;
272
273 curve = ctx->eng.ecdhe_curve;
274
275 /*
276 * Finalise the key exchange.
277 */
278 x = ctx->eng.iec->mul(cpoint, cpoint_len,
279 ctx->ecdhe_key, ctx->ecdhe_key_len, curve);
280 ecdh_common(ctx, prf_id, cpoint, cpoint_len, x);
281
282 /*
283 * Clear the ECDHE private key. Forward Secrecy is achieved insofar
284 * as that key does not get stolen, so we'd better destroy it
285 * as soon as it ceases to be useful.
286 */
287 memset(ctx->ecdhe_key, 0, ctx->ecdhe_key_len);
288 }
289
290 /*
291 * Offset for hash value within the pad (when obtaining all hash values,
292 * in preparation for verification of the CertificateVerify message).
293 * Order is MD5, SHA-1, SHA-224, SHA-256, SHA-384, SHA-512; last value
294 * is used to get the total length.
295 */
296 static const unsigned char HASH_PAD_OFF[] = { 0, 16, 36, 64, 96, 144, 208 };
297
298 /*
299 * OID for hash functions in RSA signatures.
300 */
301 static const unsigned char HASH_OID_SHA1[] = {
302 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A
303 };
304
305 static const unsigned char HASH_OID_SHA224[] = {
306 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04
307 };
308
309 static const unsigned char HASH_OID_SHA256[] = {
310 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01
311 };
312
313 static const unsigned char HASH_OID_SHA384[] = {
314 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02
315 };
316
317 static const unsigned char HASH_OID_SHA512[] = {
318 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03
319 };
320
321 static const unsigned char *HASH_OID[] = {
322 HASH_OID_SHA1,
323 HASH_OID_SHA224,
324 HASH_OID_SHA256,
325 HASH_OID_SHA384,
326 HASH_OID_SHA512
327 };
328
329 /*
330 * Verify the signature in CertificateVerify. Returned value is 0 on
331 * success, or a non-zero error code. Lack of implementation of the
332 * designated signature algorithm is reported as a "bad signature"
333 * error (because it means that the peer did not honour our advertised
334 * set of supported signature algorithms).
335 */
336 static int
337 verify_CV_sig(br_ssl_server_context *ctx, size_t sig_len)
338 {
339 const br_x509_class **xc;
340 const br_x509_pkey *pk;
341 int id;
342
343 id = ctx->hash_CV_id;
344 xc = ctx->eng.x509ctx;
345 pk = (*xc)->get_pkey(xc, NULL);
346 if (pk->key_type == BR_KEYTYPE_RSA) {
347 unsigned char tmp[64];
348 const unsigned char *hash_oid;
349
350 if (id == 0) {
351 hash_oid = NULL;
352 } else {
353 hash_oid = HASH_OID[id - 2];
354 }
355 if (ctx->eng.irsavrfy == 0) {
356 return BR_ERR_BAD_SIGNATURE;
357 }
358 if (!ctx->eng.irsavrfy(ctx->eng.pad, sig_len,
359 hash_oid, ctx->hash_CV_len, &pk->key.rsa, tmp)
360 || memcmp(tmp, ctx->hash_CV, ctx->hash_CV_len) != 0)
361 {
362 return BR_ERR_BAD_SIGNATURE;
363 }
364 } else {
365 if (ctx->eng.iecdsa == 0) {
366 return BR_ERR_BAD_SIGNATURE;
367 }
368 if (!ctx->eng.iecdsa(ctx->eng.iec,
369 ctx->hash_CV, ctx->hash_CV_len,
370 &pk->key.ec, ctx->eng.pad, sig_len))
371 {
372 return BR_ERR_BAD_SIGNATURE;
373 }
374 }
375 return 0;
376 }
377
378 }
379
380 \ =======================================================================
381
382 : addr-ctx:
383 next-word { field }
384 "addr-" field + 0 1 define-word
385 0 8191 "offsetof(br_ssl_server_context, " field + ")" + make-CX
386 postpone literal postpone ; ;
387
388 addr-ctx: client_max_version
389 addr-ctx: client_suites
390 addr-ctx: client_suites_num
391 addr-ctx: hashes
392 addr-ctx: curves
393 addr-ctx: sign_hash_id
394
395 \ Get address and length of the client_suites[] buffer. Length is expressed
396 \ in bytes.
397 : addr-len-client_suites ( -- addr len )
398 addr-client_suites
399 CX 0 1023 { BR_MAX_CIPHER_SUITES * sizeof(br_suite_translated) } ;
400
401 \ Read the client SNI extension.
402 : read-client-sni ( lim -- lim )
403 \ Open extension value.
404 read16 open-elt
405
406 \ Open ServerNameList.
407 read16 open-elt
408
409 \ Find if there is a name of type 0 (host_name) with a length
410 \ that fits in our dedicated buffer.
411 begin dup while
412 read8 if
413 read-ignore-16
414 else
415 read16
416 dup 255 <= if
417 dup addr-server_name + 0 swap set8
418 addr-server_name swap read-blob
419 else
420 skip-blob
421 then
422 then
423 repeat
424
425 \ Close ServerNameList.
426 close-elt
427
428 \ Close extension value.
429 close-elt ;
430
431 \ Set the new maximum fragment length. BEWARE: this shall be called only
432 \ after reading the ClientHello and before writing the ServerHello.
433 cc: set-max-frag-len ( len -- ) {
434 size_t max_frag_len = T0_POP();
435
436 br_ssl_engine_new_max_frag_len(ENG, max_frag_len);
437
438 /*
439 * We must adjust our own output limit. Since we call this only
440 * after receiving a ClientHello and before beginning to send
441 * the ServerHello, the next output record should be empty at
442 * that point, so we can use max_frag_len as a limit.
443 */
444 if (ENG->hlen_out > max_frag_len) {
445 ENG->hlen_out = max_frag_len;
446 }
447 }
448
449 \ Read the client Max Frag Length extension.
450 : read-client-frag ( lim -- lim )
451 \ Extension value must have length exactly 1 byte.
452 read16 1 <> if ERR_BAD_FRAGLEN fail then
453 read8
454
455 \ The byte value must be 1, 2, 3 or 4.
456 dup dup 0= swap 5 >= or if ERR_BAD_FRAGLEN fail then
457
458 \ If our own maximum fragment length is greater, then we reduce
459 \ our length.
460 8 + dup addr-log_max_frag_len get8 < if
461 dup 1 swap << set-max-frag-len
462 dup addr-log_max_frag_len set8
463 addr-peer_log_max_frag_len set8
464 else
465 drop
466 then ;
467
468 \ Read the Secure Renegotiation extension from the client.
469 : read-client-reneg ( lim -- lim )
470 \ Get value length.
471 read16
472
473 \ The "reneg" value is one of:
474 \ 0 on first handshake, client support is unknown
475 \ 1 client does not support secure renegotiation
476 \ 2 client supports secure renegotiation
477 addr-reneg get8 case
478 0 of
479 \ First handshake, value length shall be 1.
480 1 = ifnot ERR_BAD_SECRENEG fail then
481 read8 if ERR_BAD_SECRENEG fail then
482 2 addr-reneg set8
483 endof
484 2 of
485 \ Renegotiation, value shall consist of 13 bytes
486 \ (header + copy of the saved client "Finished").
487 13 = ifnot ERR_BAD_SECRENEG fail then
488 read8 12 = ifnot ERR_BAD_SECRENEG fail then
489 addr-pad 12 read-blob
490 addr-saved_finished addr-pad 12 memcmp ifnot
491 ERR_BAD_SECRENEG fail
492 then
493 endof
494
495 \ If "reneg" is 1 then the client is not supposed to support
496 \ the extension, and it sends it nonetheless, which means
497 \ foul play.
498 ERR_BAD_SECRENEG fail
499 endcase ;
500
501 \ Read the Signature Algorithms extension.
502 : read-signatures ( lim -- lim )
503 \ Open extension value.
504 read16 open-elt
505
506 read-list-sign-algos addr-hashes set16
507
508 \ Close extension value.
509 close-elt ;
510
511 \ Read the Supported Curves extension.
512 : read-supported-curves ( lim -- lim )
513 \ Open extension value.
514 read16 open-elt
515
516 \ Open list of curve identifiers.
517 read16 open-elt
518
519 \ Get all supported curves.
520 0 addr-curves set32
521 begin dup while
522 read16 dup 32 < if
523 1 swap << addr-curves get32 or addr-curves set32
524 else
525 drop
526 then
527 repeat
528 close-elt
529 close-elt ;
530
531 \ Read the ALPN extension from client.
532 : read-ALPN-from-client ( lim -- lim )
533 \ If we do not have configured names, then we just ignore the
534 \ extension.
535 addr-protocol_names_num get16 ifnot read-ignore-16 ret then
536
537 \ Open extension value.
538 read16 open-elt
539
540 \ Open list of protocol names.
541 read16 open-elt
542
543 \ Get all names and test for their support. We keep the one with
544 \ the lowest index (because we apply server's preferences, as
545 \ recommended by RFC 7301, section 3.2. We set the 'found' variable
546 \ to -2 and use an unsigned comparison, making -2 a huge value.
547 -2 { found }
548 begin dup while
549 read8 dup { len } addr-pad swap read-blob
550 len test-protocol-name dup found u< if
551 >found
552 else
553 drop
554 then
555 repeat
556
557 \ End of extension.
558 close-elt
559 close-elt
560
561 \ Write back found name index (or not). If no match was found,
562 \ then we write -1 (0xFFFF) in the index value, not 0, so that
563 \ the caller knows that we tried to match, and failed.
564 found 1+ addr-selected_protocol set16 ;
565
566 \ Call policy handler to get cipher suite, hash function identifier and
567 \ certificate chain. Returned value is 0 (false) on failure.
568 cc: call-policy-handler ( -- bool ) {
569 int x;
570 br_ssl_server_choices choices;
571
572 x = (*CTX->policy_vtable)->choose(
573 CTX->policy_vtable, CTX, &choices);
574 ENG->session.cipher_suite = choices.cipher_suite;
575 CTX->sign_hash_id = choices.hash_id;
576 ENG->chain = choices.chain;
577 ENG->chain_len = choices.chain_len;
578 T0_PUSHi(-(x != 0));
579 }
580
581 \ Check for a remembered session.
582 cc: check-resume ( -- bool ) {
583 if (ENG->session.session_id_len == 32
584 && CTX->cache_vtable != NULL && (*CTX->cache_vtable)->load(
585 CTX->cache_vtable, CTX, &ENG->session))
586 {
587 T0_PUSHi(-1);
588 } else {
589 T0_PUSH(0);
590 }
591 }
592
593 \ Save the current session.
594 cc: save-session ( -- ) {
595 if (CTX->cache_vtable != NULL) {
596 (*CTX->cache_vtable)->save(
597 CTX->cache_vtable, CTX, &ENG->session);
598 }
599 }
600
601 \ Read ClientHello. If the session is resumed, then -1 is returned.
602 : read-ClientHello ( -- resume )
603 \ Get header, and check message type.
604 read-handshake-header 1 = ifnot ERR_UNEXPECTED fail then
605
606 \ Get maximum protocol version from client.
607 read16 dup { client-version-max } addr-client_max_version set16
608
609 \ Client random.
610 addr-client_random 32 read-blob
611
612 \ Client session ID.
613 read8 dup 32 > if ERR_OVERSIZED_ID fail then
614 dup addr-session_id_len set8
615 addr-session_id swap read-blob
616
617 \ Lookup session for resumption. We should do that here because
618 \ we need to verify that the remembered cipher suite is still
619 \ matched by this ClientHello.
620 check-resume { resume }
621
622 \ Cipher suites. We read all cipher suites from client, each time
623 \ matching against our own list. We accumulate suites in the
624 \ client_suites[] context buffer: we keep suites that are
625 \ supported by both the client and the server (so the list size
626 \ cannot exceed that of the server list), and we keep them in
627 \ either client or server preference order (depending on the
628 \ relevant flag).
629 \
630 \ We also need to identify the pseudo cipher suite for secure
631 \ renegotiation here.
632 read16 open-elt
633 0 { reneg-scsv }
634 0 { resume-suite }
635 addr-len-client_suites dup2 bzero
636 over + { css-off css-max }
637 begin
638 dup while
639 read16 dup { suite }
640
641 \ Check that when resuming a session, the requested
642 \ suite is still valid.
643 resume if
644 dup addr-cipher_suite get16 = if
645 -1 >resume-suite
646 then
647 then
648
649 \ Special handling for TLS_EMPTY_RENEGOTIATION_INFO_SCSV.
650 \ This fake cipher suite may occur only in the first
651 \ handshake.
652 dup 0x00FF = if
653 addr-reneg get8 if ERR_BAD_SECRENEG fail then
654 -1 >reneg-scsv
655 then
656
657 \ Special handling for TLS_FALLBACK_SCSV. If the client
658 \ maximum version is less than our own maximum version,
659 \ then this is an undue downgrade. We mark it by setting
660 \ the client max version to 0x10000.
661 dup 0x5600 = if
662 client-version-max addr-version_min get16 >=
663 client-version-max addr-version_max get16 < and if
664 -1 >client-version-max
665 then
666 then
667
668 \ Test whether the suite is supported by the server.
669 scan-suite dup 0< if
670 \ We do not support this cipher suite. Note
671 \ that this also covers the case of pseudo
672 \ cipher suites.
673 drop
674 else
675 \ If we use server order, then we place the
676 \ suite at the computed offset; otherwise, we
677 \ append it to the list at the current place.
678 0 flag? if
679 2 << addr-client_suites + suite swap set16
680 else
681 drop
682 \ We need to test for list length because
683 \ the client list may have duplicates,
684 \ that we do not filter. Duplicates are
685 \ invalid so this is not a problem if we
686 \ reject such clients.
687 css-off css-max >= if
688 ERR_BAD_HANDSHAKE fail
689 then
690 suite css-off set16
691 css-off 4 + >css-off
692 then
693 then
694 repeat
695 drop
696
697 \ Compression methods. We need method 0 (no compression).
698 0 { ok-compression }
699 read8 open-elt
700 begin dup while
701 read8 ifnot -1 >ok-compression then
702 repeat
703 close-elt
704
705 \ Set default values for parameters that may be affected by
706 \ extensions:
707 \ -- server name is empty
708 \ -- client is reputed to know RSA and ECDSA, both with SHA-1
709 \ -- the default elliptic curve is P-256 (secp256r1, id = 23)
710 0 addr-server_name set8
711 0x404 addr-hashes set16
712 0x800000 addr-curves set32
713
714 \ Process extensions, if any.
715 dup if
716 read16 open-elt
717 begin dup while
718 read16 case
719 \ Server Name Indication.
720 0x0000 of
721 read-client-sni
722 endof
723 \ Max Frag Length.
724 0x0001 of
725 read-client-frag
726 endof
727 \ Secure Renegotiation.
728 0xFF01 of
729 read-client-reneg
730 endof
731 \ Signature Algorithms.
732 0x000D of
733 read-signatures
734 endof
735 \ Supported Curves.
736 0x000A of
737 read-supported-curves
738 endof
739 \ Supported Point Formats.
740 \ We only support "uncompressed", that all
741 \ implementations are supposed to support,
742 \ so we can simply ignore that extension.
743 \ 0x000B of
744 \ read-ignore-16
745 \ endof
746
747 \ ALPN
748 0x0010 of
749 read-ALPN-from-client
750 endof
751
752 \ Other extensions are ignored.
753 drop read-ignore-16 0
754 endcase
755 repeat
756 close-elt
757 then
758
759 \ Close message.
760 close-elt
761
762 \ Cancel session resumption if the cipher suite was not found.
763 resume resume-suite and >resume
764
765 \ Now check the received data. Since the client is expecting an
766 \ answer, we can send an appropriate fatal alert on any error.
767
768 \ Compute protocol version as the minimum of our maximum version,
769 \ and the maximum version sent by the client. If that is less than
770 \ 0x0300 (SSL-3.0), then fail. Otherwise, we may at least send an
771 \ alert with that version. We still reject versions lower than our
772 \ configured minimum.
773 \ As a special case, in case of undue downgrade, we send a specific
774 \ alert (see RFC 7507). Note that this case may happen only if
775 \ we would otherwise accept the client's version.
776 client-version-max 0< if
777 addr-client_max_version get16 addr-version_out set16
778 86 fail-alert
779 then
780 addr-version_max get16
781 dup client-version-max > if drop client-version-max then
782 dup 0x0300 < if ERR_BAD_VERSION fail then
783 client-version-max addr-version_min get16 < if
784 70 fail-alert
785 then
786 \ If resuming the session, then enforce the previously negotiated
787 \ version (if still possible).
788 resume if
789 addr-version get16 client-version-max <= if
790 drop addr-version get16
791 else
792 0 >resume
793 then
794 then
795 dup addr-version set16
796 dup addr-version_in set16
797 dup addr-version_out set16
798 0x0303 >= { can-tls12 }
799
800 \ If the client sent TLS_EMPTY_RENEGOTIATION_INFO_SCSV, then
801 \ we should mark the client as "supporting secure renegotiation".
802 reneg-scsv if 2 addr-reneg set8 then
803
804 \ Check compression.
805 ok-compression ifnot 40 fail-alert then
806
807 \ Filter hash function support by what the server also supports.
808 \ If no common hash function remains with RSA and/or ECDSA, then
809 \ the corresponding ECDHE suites are not possible.
810 supported-hash-functions drop 257 *
811 addr-hashes get16 and dup addr-hashes set16
812 \ In 'can-ecdhe', bit 12 is set if ECDHE_RSA is possible, bit 13 is
813 \ set if ECDHE_ECDSA is possible.
814 dup 0xFF and 0<> neg
815 swap 8 >> 0<> 2 and or 12 << { can-ecdhe }
816
817 \ Filter supported curves. If there is no common curve between
818 \ client and us, then ECDHE suites cannot be used. Note that we
819 \ may still allow ECDH, depending on the EC key handler.
820 addr-curves get32 supported-curves and dup addr-curves set32
821 ifnot 0 >can-ecdhe then
822
823 \ If resuming a session, then the next steps are not necessary;
824 \ we won't invoke the policy handler.
825 resume if -1 ret then
826
827 \ We are not resuming, so a new session ID should be generated.
828 \ We don't check that the new ID is distinct from the one sent
829 \ by the client because probability of such an event is 2^(-256),
830 \ i.e. much (much) lower than that of an undetected transmission
831 \ error or hardware miscomputation, and with similar consequences
832 \ (handshake simply fails).
833 addr-session_id 32 mkrand
834 32 addr-session_id_len set8
835
836 \ Translate common cipher suites, then squeeze out holes: there
837 \ may be holes because of the way we fill the list when the
838 \ server preference order is enforced, and also in case some
839 \ suites are filtered out. In particular:
840 \ -- ECDHE suites are removed if there is no common hash function
841 \ (for the relevant signature algorithm) or no common curve.
842 \ -- TLS-1.2-only suites are removed if the negociated version is
843 \ TLS-1.1 or lower.
844 addr-client_suites dup >css-off
845 begin dup css-max < while
846 dup get16 dup cipher-suite-to-elements
847 dup 12 >> dup 1 = swap 2 = or if
848 dup can-ecdhe and ifnot
849 2drop 0 dup
850 then
851 then
852 can-tls12 ifnot
853 \ Suites compatible with TLS-1.0 and TLS-1.1 are
854 \ exactly the ones that use HMAC/SHA-1.
855 dup 0xF0 and 0x20 <> if
856 2drop 0 dup
857 then
858 then
859 dup if
860 css-off 2+ set16 css-off set16
861 css-off 4 + >css-off
862 else
863 2drop
864 then
865 4 +
866 repeat
867 drop
868 css-off addr-client_suites - 2 >>
869 dup ifnot
870 \ No common cipher suite: handshake failure.
871 40 fail-alert
872 then
873 addr-client_suites_num set8
874
875 \ Check ALPN.
876 addr-selected_protocol get16 0xFFFF = if
877 3 flag? if 120 fail-alert then
878 0 addr-selected_protocol set16
879 then
880
881 \ Call policy handler to obtain the cipher suite and other
882 \ parameters.
883 call-policy-handler ifnot 40 fail-alert then
884
885 \ We are not resuming a session.
886 0 ;
887
888 \ Write ServerHello.
889 : write-ServerHello ( initial -- )
890 { initial }
891 \ Compute ServerHello length.
892 2 write8 70
893
894 \ Compute length of Secure Renegotiation extension.
895 addr-reneg get8 2 = if
896 initial if 5 else 29 then
897 else
898 0
899 then
900 { ext-reneg-len }
901
902 \ Compute length of Max Fragment Length extension.
903 addr-peer_log_max_frag_len get8 if 5 else 0 then
904 { ext-max-frag-len }
905
906 \ Compute length of ALPN extension. This also copy the
907 \ selected protocol name into the pad.
908 addr-selected_protocol get16 dup if 1- copy-protocol-name 7 + then
909 { ext-ALPN-len }
910
911 \ Adjust ServerHello length to account for the extensions.
912 ext-reneg-len ext-max-frag-len + ext-ALPN-len + dup if 2 + then +
913 write24
914
915 \ Protocol version
916 addr-version get16 write16
917
918 \ Server random
919 addr-server_random 4 bzero
920 addr-server_random 4 + 28 mkrand
921 addr-server_random 32 write-blob
922
923 \ Session ID
924 \ TODO: if we have no session cache at all, we might send here
925 \ an empty session ID. This would save a bit of network
926 \ bandwidth.
927 32 write8
928 addr-session_id 32 write-blob
929
930 \ Cipher suite
931 addr-cipher_suite get16 write16
932
933 \ Compression method
934 0 write8
935
936 \ Extensions
937 ext-reneg-len ext-max-frag-len + ext-ALPN-len + dup if
938 write16
939 ext-reneg-len dup if
940 0xFF01 write16
941 4 - dup write16
942 1- addr-saved_finished swap write-blob-head8
943 else
944 drop
945 then
946 ext-max-frag-len if
947 0x0001 write16
948 1 write16 addr-peer_log_max_frag_len get8 8 - write8
949 then
950 ext-ALPN-len dup if
951 \ Note: the selected protocol name was previously
952 \ copied into the pad.
953 0x0010 write16
954 4 - dup write16
955 2- dup write16
956 1- addr-pad swap write-blob-head8
957 else
958 drop
959 then
960 else
961 drop
962 then ;
963
964 \ Do the first part of ECDHE. Returned value is the computed signature
965 \ length, or a negative error code on error.
966 cc: do-ecdhe-part1 ( curve -- len ) {
967 int curve = T0_POPi();
968 T0_PUSHi(do_ecdhe_part1(CTX, curve));
969 }
970
971 \ Write the Server Key Exchange message (if applicable).
972 : write-ServerKeyExchange ( -- )
973 addr-cipher_suite get16 use-ecdhe? ifnot ret then
974
975 \ We must select an appropriate curve among the curves that
976 \ are supported both by us and the peer. Right now we use
977 \ the one with the smallest ID, which in practice means P-256.
978 \ (TODO: add some option to make that behaviour configurable.)
979 \
980 \ This loop always terminates because previous processing made
981 \ sure that ECDHE suites are not selectable if there is no common
982 \ curve.
983 addr-curves get32 0
984 begin dup2 >> 1 and 0= while 1+ repeat
985 { curve-id } drop
986
987 \ Compute the signed curve point to send.
988 curve-id do-ecdhe-part1 dup 0< if neg fail then { sig-len }
989
990 \ If using TLS-1.2+, then the hash function and signature
991 \ algorithm are explicitly encoded in the message.
992 addr-version get16 0x0303 >= { tls1.2+ }
993
994 12 write8
995 sig-len addr-ecdhe_point_len get8 + tls1.2+ 2 and + 6 + write24
996
997 \ Curve parameters: named curve with 16-bit ID.
998 3 write8 curve-id write16
999
1000 \ Public point.
1001 addr-ecdhe_point addr-ecdhe_point_len get8 write-blob-head8
1002
1003 \ If TLS-1.2+, write hash and signature identifiers.
1004 tls1.2+ if
1005 \ Hash identifier is in the sign_hash_id field.
1006 addr-sign_hash_id get8 write8
1007 \ 'use-rsa-ecdhe?' returns -1 for RSA, 0 for ECDSA.
1008 \ The byte on the wire shall be 1 for RSA, 3 for ECDSA.
1009 addr-cipher_suite get16 use-rsa-ecdhe? 1 << 3 + write8
1010 then
1011
1012 \ Signature.
1013 sig-len write16
1014 addr-pad sig-len write-blob ;
1015
1016 \ Get length of the list of anchor names to send to the client. The length
1017 \ includes the per-name 2-byte header, but _not_ the 2-byte header for
1018 \ the list itself. If no client certificate is requested, then this
1019 \ returns 0.
1020 cc: ta-names-total-length ( -- len ) {
1021 size_t u, len;
1022
1023 len = 0;
1024 if (CTX->ta_names != NULL) {
1025 for (u = 0; u < CTX->num_tas; u ++) {
1026 len += CTX->ta_names[u].len + 2;
1027 }
1028 } else if (CTX->tas != NULL) {
1029 for (u = 0; u < CTX->num_tas; u ++) {
1030 len += CTX->tas[u].dn.len + 2;
1031 }
1032 }
1033 T0_PUSH(len);
1034 }
1035
1036 \ Compute length and optionally write the contents of the list of
1037 \ supported client authentication methods.
1038 : write-list-auth ( do_write -- len )
1039 0
1040 addr-cipher_suite get16 use-ecdh? if
1041 2+ over if 65 write8 66 write8 then
1042 then
1043 supports-rsa-sign? if 1+ over if 1 write8 then then
1044 supports-ecdsa? if 1+ over if 64 write8 then then
1045 swap drop ;
1046
1047 : write-signhash-inner2 ( dow algo hashes len id -- dow algo hashes len )
1048 { id }
1049 over 1 id << and ifnot ret then
1050 2+
1051 3 pick if id write8 2 pick write8 then ;
1052
1053 : write-signhash-inner1 ( dow algo hashes -- dow len )
1054 0
1055 4 write-signhash-inner2
1056 5 write-signhash-inner2
1057 6 write-signhash-inner2
1058 3 write-signhash-inner2
1059 2 write-signhash-inner2
1060 -rot 2drop ;
1061
1062 \ Compute length and optionally write the contents of the list of
1063 \ supported sign+hash algorithms.
1064 : write-list-signhash ( do_write -- len )
1065 0 { len }
1066 \ If supporting neither RSA nor ECDSA in the engine, then we
1067 \ will do only static ECDH, and thus we claim support for
1068 \ everything (for the X.509 validator).
1069 supports-rsa-sign? supports-ecdsa? or ifnot
1070 1 0x7C write-signhash-inner1 >len
1071 3 0x7C write-signhash-inner1 len +
1072 swap drop ret
1073 then
1074 supports-rsa-sign? if
1075 1 supported-hash-functions drop
1076 write-signhash-inner1 >len
1077 then
1078 supports-ecdsa? if
1079 3 supported-hash-functions drop
1080 write-signhash-inner1 len + >len
1081 then
1082 drop len ;
1083
1084 \ Initialise index for sending the list of anchor DN.
1085 cc: begin-ta-name-list ( -- ) {
1086 CTX->cur_dn_index = 0;
1087 }
1088
1089 \ Switch to next DN in the list. Returned value is the DN length, or -1
1090 \ if the end of the list was reached.
1091 cc: begin-ta-name ( -- len ) {
1092 const br_x500_name *dn;
1093 if (CTX->cur_dn_index >= CTX->num_tas) {
1094 T0_PUSHi(-1);
1095 } else {
1096 if (CTX->ta_names == NULL) {
1097 dn = &CTX->tas[CTX->cur_dn_index].dn;
1098 } else {
1099 dn = &CTX->ta_names[CTX->cur_dn_index];
1100 }
1101 CTX->cur_dn_index ++;
1102 CTX->cur_dn = dn->data;
1103 CTX->cur_dn_len = dn->len;
1104 T0_PUSH(CTX->cur_dn_len);
1105 }
1106 }
1107
1108 \ Copy a chunk of the current DN into the pad. Returned value is the
1109 \ chunk length; this is 0 when the end of the current DN is reached.
1110 cc: copy-dn-chunk ( -- len ) {
1111 size_t clen;
1112
1113 clen = CTX->cur_dn_len;
1114 if (clen > sizeof ENG->pad) {
1115 clen = sizeof ENG->pad;
1116 }
1117 memcpy(ENG->pad, CTX->cur_dn, clen);
1118 CTX->cur_dn += clen;
1119 CTX->cur_dn_len -= clen;
1120 T0_PUSH(clen);
1121 }
1122
1123 \ Write a CertificateRequest message.
1124 : write-CertificateRequest ( -- )
1125 \ The list of client authentication types includes:
1126 \ rsa_sign (1)
1127 \ ecdsa_sign (64)
1128 \ rsa_fixed_ecdh (65)
1129 \ ecdsa_fixed_ecdh (66)
1130 \ rsa_sign and ecdsa_sign require, respectively, RSA and ECDSA
1131 \ support. Static ECDH requires that the cipher suite is ECDH.
1132 \ When we ask for static ECDH, we always send both rsa_fixed_ecdh
1133 \ and ecdsa_fixed_ecdh because what matters there is what the
1134 \ X.509 engine may support, and we do not control that.
1135 \
1136 \ With TLS 1.2, we must also send a list of supported signature
1137 \ and hash algorithms. That list is supposed to qualify both
1138 \ the engine itself, and the X.509 validator, which are separate
1139 \ in BearSSL. There again, we use the engine capabilities in that
1140 \ list, and resort to a generic all-support list if only
1141 \ static ECDH is accepted.
1142 \
1143 \ (In practice, client implementations tend to have at most one
1144 \ or two certificates, and send the chain regardless of what
1145 \ algorithms are used in it.)
1146
1147 0 write-list-auth
1148 addr-version get16 0x0303 >= if
1149 2+ 0 write-list-signhash +
1150 then
1151 ta-names-total-length + 3 +
1152
1153 \ Message header
1154 13 write8 write24
1155
1156 \ List of authentication methods
1157 0 write-list-auth write8 1 write-list-auth drop
1158
1159 \ For TLS 1.2+, list of sign+hash
1160 addr-version get16 0x0303 >= if
1161 0 write-list-signhash write16 1 write-list-signhash drop
1162 then
1163
1164 \ Trust anchor names
1165 ta-names-total-length write16
1166 begin-ta-name-list
1167 begin
1168 begin-ta-name
1169 dup 0< if drop ret then write16
1170 begin copy-dn-chunk dup while
1171 addr-pad swap write-blob
1172 repeat
1173 drop
1174 again ;
1175
1176 \ Write the Server Hello Done message.
1177 : write-ServerHelloDone ( -- )
1178 14 write8 0 write24 ;
1179
1180 \ Perform RSA decryption of the client-sent pre-master secret. The value
1181 \ is in the pad, and its length is provided as parameter.
1182 cc: do-rsa-decrypt ( len prf_id -- ) {
1183 int prf_id = T0_POPi();
1184 size_t len = T0_POP();
1185 do_rsa_decrypt(CTX, prf_id, ENG->pad, len);
1186 }
1187
1188 \ Perform ECDH (not ECDHE). The point from the client is in the pad, and
1189 \ its length is provided as parameter.
1190 cc: do-ecdh ( len prf_id -- ) {
1191 int prf_id = T0_POPi();
1192 size_t len = T0_POP();
1193 do_ecdh(CTX, prf_id, ENG->pad, len);
1194 }
1195
1196 \ Do the second part of ECDHE.
1197 cc: do-ecdhe-part2 ( len prf_id -- ) {
1198 int prf_id = T0_POPi();
1199 size_t len = T0_POP();
1200 do_ecdhe_part2(CTX, prf_id, ENG->pad, len);
1201 }
1202
1203 \ Perform static ECDH. The point from the client is the public key
1204 \ extracted from its certificate.
1205 cc: do-static-ecdh ( prf_id -- ) {
1206 do_static_ecdh(CTX, T0_POP());
1207 }
1208
1209 \ Read a ClientKeyExchange header.
1210 : read-ClientKeyExchange-header ( -- len )
1211 read-handshake-header 16 = ifnot ERR_UNEXPECTED fail then ;
1212
1213 \ Read the Client Key Exchange contents (non-empty case).
1214 : read-ClientKeyExchange-contents ( lim -- )
1215 \ What we should get depends on the cipher suite.
1216 addr-cipher_suite get16 use-rsa-keyx? if
1217 \ RSA key exchange: we expect a RSA-encrypted value.
1218 read16
1219 dup 512 > if ERR_LIMIT_EXCEEDED fail then
1220 dup { enc-rsa-len }
1221 addr-pad swap read-blob
1222 enc-rsa-len addr-cipher_suite get16 prf-id do-rsa-decrypt
1223 then
1224 addr-cipher_suite get16 dup use-ecdhe? swap use-ecdh? { ecdhe ecdh }
1225 ecdh ecdhe or if
1226 \ ECDH or ECDHE key exchange: we expect an EC point.
1227 read8 dup { ec-point-len }
1228 addr-pad swap read-blob
1229 ec-point-len addr-cipher_suite get16 prf-id
1230 ecdhe if do-ecdhe-part2 else do-ecdh then
1231 then
1232 close-elt ;
1233
1234 \ Read the Client Key Exchange (normal case).
1235 : read-ClientKeyExchange ( -- )
1236 read-ClientKeyExchange-header
1237 read-ClientKeyExchange-contents ;
1238
1239 \ Obtain all possible hash values for handshake messages so far. This
1240 \ is done because we need the hash value for the CertificateVerify
1241 \ _before_ knowing which hash function will actually be used, as this
1242 \ information is obtained from decoding the message header itself.
1243 \ All hash values are stored in the pad (208 bytes in total).
1244 cc: compute-hash-CV ( -- ) {
1245 int i;
1246
1247 for (i = 1; i <= 6; i ++) {
1248 br_multihash_out(&ENG->mhash, i,
1249 ENG->pad + HASH_PAD_OFF[i - 1]);
1250 }
1251 }
1252
1253 \ Copy the proper hash value from the pad into the dedicated buffer.
1254 \ Returned value is true (-1) on success, false (0) on error (error
1255 \ being an unimplemented hash function). The id has already been verified
1256 \ to be either 0 (for MD5+SHA-1) or one of the SHA-* functions.
1257 cc: copy-hash-CV ( hash_id -- bool ) {
1258 int id = T0_POP();
1259 size_t off, len;
1260
1261 if (id == 0) {
1262 off = 0;
1263 len = 36;
1264 } else {
1265 if (br_multihash_getimpl(&ENG->mhash, id) == 0) {
1266 T0_PUSH(0);
1267 T0_RET();
1268 }
1269 off = HASH_PAD_OFF[id - 1];
1270 len = HASH_PAD_OFF[id] - off;
1271 }
1272 memcpy(CTX->hash_CV, ENG->pad + off, len);
1273 CTX->hash_CV_len = len;
1274 CTX->hash_CV_id = id;
1275 T0_PUSHi(-1);
1276 }
1277
1278 \ Verify signature in CertificateVerify. Output is 0 on success, or a
1279 \ non-zero error code.
1280 cc: verify-CV-sig ( sig-len -- err ) {
1281 int err;
1282
1283 err = verify_CV_sig(CTX, T0_POP());
1284 T0_PUSHi(err);
1285 }
1286
1287 \ Process static ECDH.
1288 : process-static-ECDH ( ktu -- )
1289 \ Static ECDH is allowed only if the cipher suite uses ECDH, and
1290 \ the client's public key has type EC and allows key exchange.
1291 \ BR_KEYTYPE_KEYX is 0x10, and BR_KEYTYPE_EC is 2.
1292 0x1F and 0x12 = ifnot ERR_WRONG_KEY_USAGE fail then
1293 addr-cipher_suite get16
1294 dup use-ecdh? ifnot ERR_UNEXPECTED fail then
1295 prf-id
1296 do-static-ecdh ;
1297
1298 \ Read CertificateVerify header.
1299 : read-CertificateVerify-header ( -- lim )
1300 compute-hash-CV
1301 read-handshake-header 15 = ifnot ERR_UNEXPECTED fail then ;
1302
1303 \ Read CertificateVerify. The client key type + usage is expected on the
1304 \ stack.
1305 : read-CertificateVerify ( ktu -- )
1306 \ Check that the key allows for signatures.
1307 dup 0x20 and ifnot ERR_WRONG_KEY_USAGE fail then
1308 0x0F and { key-type }
1309
1310 \ Get header.
1311 read-CertificateVerify-header
1312
1313 \ With TLS 1.2+, there is an explicit hash + signature indication,
1314 \ which must be compatible with the key type.
1315 addr-version get16 0x0303 >= if
1316 \ Get hash function, then signature algorithm. The
1317 \ signature algorithm is 1 (RSA) or 3 (ECDSA) while our
1318 \ symbolic constants for key types are 1 (RSA) or 2 (EC).
1319 read16
1320 dup 0xFF and 1+ 1 >> key-type = ifnot
1321 ERR_BAD_SIGNATURE fail
1322 then
1323 8 >>
1324
1325 \ We support only SHA-1, SHA-224, SHA-256, SHA-384
1326 \ and SHA-512. We explicitly reject MD5.
1327 dup 2 < over 6 > or if ERR_INVALID_ALGORITHM fail then
1328 else
1329 \ With TLS 1.0 and 1.1, hash is MD5+SHA-1 (0) for RSA,
1330 \ SHA-1 (2) for ECDSA.
1331 key-type 0x01 = if 0 else 2 then
1332 then
1333 copy-hash-CV ifnot ERR_INVALID_ALGORITHM fail then
1334
1335 \ Read signature.
1336 read16 dup { sig-len }
1337 dup 512 > if ERR_LIMIT_EXCEEDED fail then
1338 addr-pad swap read-blob
1339 sig-len verify-CV-sig
1340 dup if fail then drop
1341
1342 close-elt ;
1343
1344 \ Send a HelloRequest.
1345 : send-HelloRequest ( -- )
1346 flush-record
1347 begin can-output? not while wait-co drop repeat
1348 22 addr-record_type_out set8
1349 0 write8 0 write24 flush-record
1350 23 addr-record_type_out set8 ;
1351
1352 \ Make a handshake.
1353 : do-handshake ( initial -- )
1354 0 addr-application_data set8
1355 22 addr-record_type_out set8
1356 0 addr-selected_protocol set16
1357 multihash-init
1358 read-ClientHello
1359 more-incoming-bytes? if ERR_UNEXPECTED fail then
1360 if
1361 \ Session resumption
1362 write-ServerHello
1363 0 write-CCS-Finished
1364 0 read-CCS-Finished
1365 else
1366 \ Not a session resumption
1367 write-ServerHello
1368 write-Certificate drop
1369 write-ServerKeyExchange
1370 ta-names-total-length if
1371 write-CertificateRequest
1372 then
1373 write-ServerHelloDone
1374 flush-record
1375
1376 \ If we sent a CertificateRequest then we expect a
1377 \ Certificate message.
1378 ta-names-total-length if
1379 \ Read client certificate.
1380 0 read-Certificate
1381
1382 choice
1383 dup 0< uf
1384 \ Client certificate validation failed.
1385 2 flag? ifnot neg fail then
1386 drop
1387 read-ClientKeyExchange
1388 read-CertificateVerify-header
1389 dup skip-blob drop
1390 enduf
1391 dup 0= uf
1392 \ Client sent no certificate at all.
1393 drop
1394 2 flag? ifnot
1395 ERR_NO_CLIENT_AUTH fail
1396 then
1397 read-ClientKeyExchange
1398 enduf
1399
1400 \ Client certificate was validated.
1401 read-ClientKeyExchange-header
1402 dup ifnot
1403 \ Empty ClientKeyExchange.
1404 drop
1405 process-static-ECDH
1406 else
1407 read-ClientKeyExchange-contents
1408 read-CertificateVerify
1409 then
1410 endchoice
1411 else
1412 \ No client certificate request, we just expect
1413 \ a non-empty ClientKeyExchange.
1414 read-ClientKeyExchange
1415 then
1416 0 read-CCS-Finished
1417 0 write-CCS-Finished
1418 save-session
1419 then
1420 1 addr-application_data set8
1421 23 addr-record_type_out set8 ;
1422
1423 \ Entry point.
1424 : main ( -- ! )
1425 \ Perform initial handshake.
1426 -1 do-handshake
1427
1428 begin
1429 \ Wait for further invocation. At that point, we should
1430 \ get either an explicit call for renegotiation, or
1431 \ an incoming ClientHello handshake message.
1432 wait-co
1433 dup 0x07 and case
1434 0x00 of
1435 0x10 and if
1436 \ The best we can do is ask for a
1437 \ renegotiation, then wait for it
1438 \ to happen.
1439 send-HelloRequest
1440 then
1441 endof
1442 0x01 of
1443 \ Reject renegotiations if the peer does not
1444 \ support secure renegotiation, or if the
1445 \ "no renegotiation" flag is set.
1446 drop
1447 addr-reneg get8 1 = 1 flag? or if
1448 flush-record
1449 begin can-output? not while
1450 wait-co drop
1451 repeat
1452 100 send-warning
1453 else
1454 0 do-handshake
1455 then
1456 endof
1457 ERR_UNEXPECTED fail
1458 endcase
1459 again
1460 ;