Added support for TLS_FALLBACK_SCSV.
[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 ECDHE key exchange (part 1: generation of transient key, and
145 * computing of the point to send to the client). Returned value is the
146 * signature length (in bytes), or -x on error (with x being an error
147 * code). The encoded point is written in the ecdhe_point[] context buffer
148 * (length in ecdhe_point_len).
149 */
150 static int
151 do_ecdhe_part1(br_ssl_server_context *ctx, int curve)
152 {
153 int hash;
154 unsigned mask;
155 const unsigned char *order, *generator;
156 size_t olen, glen;
157 br_multihash_context mhc;
158 unsigned char head[4];
159 size_t hv_len, sig_len;
160
161 if (!((ctx->eng.iec->supported_curves >> curve) & 1)) {
162 return -BR_ERR_INVALID_ALGORITHM;
163 }
164 ctx->eng.ecdhe_curve = curve;
165
166 /*
167 * Generate our private key. We need a non-zero random value
168 * which is lower than the curve order, in a "large enough"
169 * range. We force the top bit to 0 and bottom bit to 1, which
170 * does the trick. Note that contrary to what happens in ECDSA,
171 * this is not a problem if we do not cover the full range of
172 * possible values.
173 */
174 order = ctx->eng.iec->order(curve, &olen);
175 mask = 0xFF;
176 while (mask >= order[0]) {
177 mask >>= 1;
178 }
179 br_hmac_drbg_generate(&ctx->eng.rng, ctx->ecdhe_key, olen);
180 ctx->ecdhe_key[0] &= mask;
181 ctx->ecdhe_key[olen - 1] |= 0x01;
182 ctx->ecdhe_key_len = olen;
183
184 /*
185 * Compute our ECDH point.
186 */
187 generator = ctx->eng.iec->generator(curve, &glen);
188 memcpy(ctx->eng.ecdhe_point, generator, glen);
189 ctx->eng.ecdhe_point_len = glen;
190 if (!ctx->eng.iec->mul(ctx->eng.ecdhe_point, glen,
191 ctx->ecdhe_key, olen, curve))
192 {
193 return -BR_ERR_INVALID_ALGORITHM;
194 }
195
196 /*
197 * Compute the signature.
198 */
199 br_multihash_zero(&mhc);
200 br_multihash_copyimpl(&mhc, &ctx->eng.mhash);
201 br_multihash_init(&mhc);
202 br_multihash_update(&mhc,
203 ctx->eng.client_random, sizeof ctx->eng.client_random);
204 br_multihash_update(&mhc,
205 ctx->eng.server_random, sizeof ctx->eng.server_random);
206 head[0] = 3;
207 head[1] = 0;
208 head[2] = curve;
209 head[3] = ctx->eng.ecdhe_point_len;
210 br_multihash_update(&mhc, head, sizeof head);
211 br_multihash_update(&mhc,
212 ctx->eng.ecdhe_point, ctx->eng.ecdhe_point_len);
213 hash = ctx->sign_hash_id;
214 if (hash) {
215 hv_len = br_multihash_out(&mhc, hash, ctx->eng.pad);
216 if (hv_len == 0) {
217 return -BR_ERR_INVALID_ALGORITHM;
218 }
219 } else {
220 if (!br_multihash_out(&mhc, br_md5_ID, ctx->eng.pad)
221 || !br_multihash_out(&mhc,
222 br_sha1_ID, ctx->eng.pad + 16))
223 {
224 return -BR_ERR_INVALID_ALGORITHM;
225 }
226 hv_len = 36;
227 }
228 sig_len = (*ctx->policy_vtable)->do_sign(ctx->policy_vtable,
229 hash, hv_len, ctx->eng.pad, sizeof ctx->eng.pad);
230 return sig_len ? (int)sig_len : -BR_ERR_INVALID_ALGORITHM;
231 }
232
233 /*
234 * Do the ECDHE key exchange (part 2: computation of the shared secret
235 * from the point sent by the client).
236 */
237 static void
238 do_ecdhe_part2(br_ssl_server_context *ctx, int prf_id,
239 unsigned char *cpoint, size_t cpoint_len)
240 {
241 int curve;
242 uint32_t x;
243
244 curve = ctx->eng.ecdhe_curve;
245
246 /*
247 * Finalise the key exchange.
248 */
249 x = ctx->eng.iec->mul(cpoint, cpoint_len,
250 ctx->ecdhe_key, ctx->ecdhe_key_len, curve);
251 ecdh_common(ctx, prf_id, cpoint, cpoint_len, x);
252
253 /*
254 * Clear the ECDHE private key. Forward Secrecy is achieved insofar
255 * as that key does not get stolen, so we'd better destroy it
256 * as soon as it ceases to be useful.
257 */
258 memset(ctx->ecdhe_key, 0, ctx->ecdhe_key_len);
259 }
260
261 }
262
263 \ =======================================================================
264
265 : addr-ctx:
266 next-word { field }
267 "addr-" field + 0 1 define-word
268 0 8191 "offsetof(br_ssl_server_context, " field + ")" + make-CX
269 postpone literal postpone ; ;
270
271 addr-ctx: flags
272 addr-ctx: client_max_version
273 addr-ctx: client_suites
274 addr-ctx: client_suites_num
275 addr-ctx: hashes
276 addr-ctx: curves
277 addr-ctx: sign_hash_id
278
279 \ Get address and length of the client_suites[] buffer. Length is expressed
280 \ in bytes.
281 : addr-len-client_suites ( -- addr len )
282 addr-client_suites
283 CX 0 1023 { BR_MAX_CIPHER_SUITES * sizeof(br_suite_translated) } ;
284
285 \ Check a server flag by index.
286 : flag? ( index -- bool )
287 addr-flags get32 swap >> 1 and neg ;
288
289 \ Read the client SNI extension.
290 : read-client-sni ( lim -- lim )
291 \ Open extension value.
292 read16 open-elt
293
294 \ Open ServerNameList.
295 read16 open-elt
296
297 \ Find if there is a name of type 0 (host_name) with a length
298 \ that fits in our dedicated buffer.
299 begin dup while
300 read8 if
301 read-ignore-16
302 else
303 read16
304 dup 255 <= if
305 dup addr-server_name + 0 swap set8
306 addr-server_name swap read-blob
307 else
308 skip-blob
309 then
310 then
311 repeat
312
313 \ Close ServerNameList.
314 close-elt
315
316 \ Close extension value.
317 close-elt ;
318
319 \ Set the new maximum fragment length. BEWARE: this shall be called only
320 \ after reading the ClientHello and before writing the ServerHello.
321 cc: set-max-frag-len ( len -- ) {
322 size_t max_frag_len = T0_POP();
323
324 br_ssl_engine_new_max_frag_len(ENG, max_frag_len);
325
326 /*
327 * We must adjust our own output limit. Since we call this only
328 * after receiving a ClientHello and before beginning to send
329 * the ServerHello, the next output record should be empty at
330 * that point, so we can use max_frag_len as a limit.
331 */
332 if (ENG->hlen_out > max_frag_len) {
333 ENG->hlen_out = max_frag_len;
334 }
335 }
336
337 \ Read the client Max Frag Length extension.
338 : read-client-frag ( lim -- lim )
339 \ Extension value must have length exactly 1 byte.
340 read16 1 <> if ERR_BAD_FRAGLEN fail then
341 read8
342
343 \ The byte value must be 1, 2, 3 or 4.
344 dup dup 0= swap 5 >= or if ERR_BAD_FRAGLEN fail then
345
346 \ If our own maximum fragment length is greater, then we reduce
347 \ our length.
348 8 + dup addr-log_max_frag_len get8 < if
349 dup 1 swap << set-max-frag-len
350 dup addr-log_max_frag_len set8
351 addr-peer_log_max_frag_len set8
352 else
353 drop
354 then ;
355
356 \ Read the Secure Renegotiation extension from the client.
357 : read-client-reneg ( lim -- lim )
358 \ Get value length.
359 read16
360
361 \ The "reneg" value is one of:
362 \ 0 on first handshake, client support is unknown
363 \ 1 client does not support secure renegotiation
364 \ 2 client supports secure renegotiation
365 addr-reneg get8 case
366 0 of
367 \ First handshake, value length shall be 1.
368 1 = ifnot ERR_BAD_SECRENEG fail then
369 read8 if ERR_BAD_SECRENEG fail then
370 2 addr-reneg set8
371 endof
372 2 of
373 \ Renegotiation, value shall consist of 13 bytes
374 \ (header + copy of the saved client "Finished").
375 13 = ifnot ERR_BAD_SECRENEG fail then
376 read8 12 = ifnot ERR_BAD_SECRENEG fail then
377 addr-pad 12 read-blob
378 addr-saved_finished addr-pad 12 memcmp ifnot
379 ERR_BAD_SECRENEG fail
380 then
381 endof
382
383 \ If "reneg" is 1 then the client is not supposed to support
384 \ the extension, and it sends it nonetheless, which means
385 \ foul play.
386 ERR_BAD_SECRENEG fail
387 endcase ;
388
389 \ Read the Signature Algorithms extension.
390 : read-signatures ( lim -- lim )
391 \ Open extension value.
392 read16 open-elt
393
394 \ Clear list of supported signature algorithms.
395 0 addr-hashes set16
396
397 \ Get list of algorithms length.
398 read16 open-elt
399 begin dup while
400 read8 { hash } read8 { sign }
401 \ We keep the value if the signature is either 1 (RSA) or
402 \ 3 (ECDSA), and the hash is one of the SHA-* functions
403 \ (2 to 6, from SHA-1 to SHA-512). Note that we reject
404 \ any use of MD5. Also, we do not keep track of the client
405 \ preferences.
406 hash 2 >= hash 6 <= and
407 sign 1 = sign 3 = or
408 and if
409 addr-hashes get16
410 1 sign 1- 2 << hash + << or addr-hashes set16
411 then
412 repeat
413 close-elt
414
415 \ Close extension value.
416 close-elt ;
417
418 \ Read the Supported Curves extension.
419 : read-supported-curves ( lim -- lim )
420 \ Open extension value.
421 read16 open-elt
422
423 \ Open list of curve identifiers.
424 read16 open-elt
425
426 \ Get all supported curves.
427 0 addr-curves set32
428 begin dup while
429 read16 dup 32 < if
430 1 swap << addr-curves get32 or addr-curves set32
431 else
432 drop
433 then
434 repeat
435 close-elt
436 close-elt ;
437
438 \ Call policy handler to get cipher suite, hash function identifier and
439 \ certificate chain. Returned value is 0 (false) on failure.
440 cc: call-policy-handler ( -- bool ) {
441 int x;
442 br_ssl_server_choices choices;
443
444 x = (*CTX->policy_vtable)->choose(
445 CTX->policy_vtable, CTX, &choices);
446 ENG->session.cipher_suite = choices.cipher_suite;
447 CTX->sign_hash_id = choices.hash_id;
448 CTX->chain = choices.chain;
449 CTX->chain_len = choices.chain_len;
450 T0_PUSHi(-(x != 0));
451 }
452
453 \ Check for a remembered session.
454 cc: check-resume ( -- bool ) {
455 if (ENG->session.session_id_len == 32
456 && CTX->cache_vtable != NULL && (*CTX->cache_vtable)->load(
457 CTX->cache_vtable, CTX, &ENG->session))
458 {
459 T0_PUSHi(-1);
460 } else {
461 T0_PUSH(0);
462 }
463 }
464
465 \ Save the current session.
466 cc: save-session ( -- ) {
467 if (CTX->cache_vtable != NULL) {
468 (*CTX->cache_vtable)->save(
469 CTX->cache_vtable, CTX, &ENG->session);
470 }
471 }
472
473 \ Read ClientHello. If the session is resumed, then -1 is returned.
474 : read-ClientHello ( -- resume )
475 \ Get header, and check message type.
476 read-handshake-header 1 = ifnot ERR_UNEXPECTED fail then
477
478 \ Get maximum protocol version from client.
479 read16 dup { client-version-max } addr-client_max_version set16
480
481 \ Client random.
482 addr-client_random 32 read-blob
483
484 \ Client session ID.
485 read8 dup 32 > if ERR_OVERSIZED_ID fail then
486 dup addr-session_id_len set8
487 addr-session_id swap read-blob
488
489 \ Lookup session for resumption. We should do that here because
490 \ we need to verify that the remembered cipher suite is still
491 \ matched by this ClientHello.
492 check-resume { resume }
493
494 \ Cipher suites. We read all cipher suites from client, each time
495 \ matching against our own list. We accumulare suites in the
496 \ client_suites[] context buffer: we keep suites that are
497 \ supported by both the client and the server (so the list size
498 \ cannot exceed that of the server list), and we keep them in
499 \ either client or server preference order (depending on the
500 \ relevant flag).
501 \
502 \ We also need to identify the pseudo cipher suite for secure
503 \ renegotiation here.
504 read16 open-elt
505 0 { reneg-scsv }
506 0 { resume-suite }
507 addr-len-client_suites dup2 bzero
508 over + { css-off css-max }
509 begin
510 dup while
511 read16 dup { suite }
512
513 \ Check that when resuming a session, the requested
514 \ suite is still valid.
515 resume if
516 dup addr-cipher_suite get16 = if
517 -1 >resume-suite
518 then
519 then
520
521 \ Special handling for TLS_EMPTY_RENEGOTIATION_INFO_SCSV.
522 \ This fake cipher suite may occur only in the first
523 \ handshake.
524 dup 0x00FF = if
525 addr-reneg get8 if ERR_BAD_SECRENEG fail then
526 -1 >reneg-scsv
527 then
528
529 \ Special handling for TLS_FALLBACK_SCSV. If the client
530 \ maximum version is less than our own maximum version,
531 \ then this is an undue downgrade. We mark it by setting
532 \ the client max version to 0x10000.
533 dup 0x5600 = if
534 client-version-max addr-version_min get16 >=
535 client-version-max addr-version_max get16 < and if
536 -1 >client-version-max
537 then
538 then
539
540 \ Test whether the suite is supported by the server.
541 scan-suite dup 0< if
542 \ We do not support this cipher suite. Note
543 \ that this also covers the case of pseudo
544 \ cipher suites.
545 drop
546 else
547 \ If we use server order, then we place the
548 \ suite at the computed offset; otherwise, we
549 \ append it to the list at the current place.
550 0 flag? if
551 2 << addr-client_suites + suite swap set16
552 else
553 drop
554 \ We need to test for list length because
555 \ the client list may have duplicates,
556 \ that we do not filter. Duplicates are
557 \ invalid so this is not a problem if we
558 \ reject such clients.
559 css-off css-max >= if
560 ERR_BAD_HANDSHAKE fail
561 then
562 suite css-off set16
563 css-off 4 + >css-off
564 then
565 then
566 repeat
567 drop
568
569 \ Compression methods. We need method 0 (no compression).
570 0 { ok-compression }
571 read8 open-elt
572 begin dup while
573 read8 ifnot -1 >ok-compression then
574 repeat
575 close-elt
576
577 \ Set default values for parameters that may be affected by
578 \ extensions:
579 \ -- server name is empty
580 \ -- client is reputed to know RSA and ECDSA, both with SHA-1
581 \ -- the default elliptic curve is P-256 (secp256r1, id = 23)
582 0 addr-server_name set8
583 0x404 addr-hashes set16
584 0x800000 addr-curves set32
585
586 \ Process extensions, if any.
587 dup if
588 read16 open-elt
589 begin dup while
590 read16 case
591 \ Server Name Indication.
592 0x0000 of
593 read-client-sni
594 endof
595 \ Max Frag Length.
596 0x0001 of
597 read-client-frag
598 endof
599 \ Secure Renegotiation.
600 0xFF01 of
601 read-client-reneg
602 endof
603 \ Signature Algorithms.
604 0x000D of
605 read-signatures
606 endof
607 \ Supported Curves.
608 0x000A of
609 read-supported-curves
610 endof
611 \ Supported Point Formats.
612 \ We only support "uncompressed", that all
613 \ implementations are supposed to support,
614 \ so we can simply ignore that extension.
615 \ 0x000B of
616 \ read-ignore-16
617 \ endof
618
619 \ Other extensions are ignored.
620 drop read-ignore-16 0
621 endcase
622 repeat
623 close-elt
624 then
625
626 \ Close message.
627 close-elt
628
629 \ Cancel session resumption if the cipher suite was not found.
630 resume resume-suite and >resume
631
632 \ Now check the received data. Since the client is expecting an
633 \ answer, we can send an appropriate fatal alert on any error.
634
635 \ Compute protocol version as the minimum of our maximum version,
636 \ and the maximum version sent by the client. If that is less than
637 \ 0x0300 (SSL-3.0), then fail. Otherwise, we may at least send an
638 \ alert with that version. We still reject versions lower than our
639 \ configured minimum.
640 \ As a special case, in case of undue downgrade, we send a specific
641 \ alert (see RFC 7507). Note that this case may happen only if
642 \ we would otherwise accept the client's version.
643 client-version-max 0< if
644 addr-client_max_version get16 addr-version_out set16
645 86 fail-alert
646 then
647 addr-version_max get16
648 dup client-version-max > if drop client-version-max then
649 dup 0x0300 < if ERR_BAD_VERSION fail then
650 client-version-max addr-version_min get16 < if
651 70 fail-alert
652 then
653 \ If resuming the session, then enforce the previously negotiated
654 \ version (if still possible).
655 resume if
656 addr-version get16 client-version-max <= if
657 drop addr-version get16
658 else
659 0 >resume
660 then
661 then
662 dup addr-version set16
663 dup addr-version_in set16
664 dup addr-version_out set16
665 0x0303 >= { can-tls12 }
666
667 \ If the client sent TLS_EMPTY_RENEGOTIATION_INFO_SCSV, then
668 \ we should mark the client as "supporting secure renegotiation".
669 reneg-scsv if 2 addr-reneg set8 then
670
671 \ Check compression.
672 ok-compression ifnot 40 fail-alert then
673
674 \ Filter hash function support by what the server also supports.
675 \ If no common hash function remains, then ECDHE suites are not
676 \ possible.
677 supported-hash-functions drop 257 *
678 addr-hashes get16 and dup addr-hashes set16
679 0<> { can-ecdhe }
680
681 \ Filter supported curves. If there is no common curve between
682 \ client and us, then ECDHE suites cannot be used. Note that we
683 \ may still allow ECDH, depending on the EC key handler.
684 addr-curves get32 supported-curves and dup addr-curves set32
685 ifnot 0 >can-ecdhe then
686
687 \ If resuming a session, then the next steps are not necessary;
688 \ we won't invoke the policy handler.
689 resume if -1 ret then
690
691 \ We are not resuming, so a new session ID should be generated.
692 addr-session_id 32 mkrand
693
694 \ Translate common cipher suites, then squeeze out holes: there
695 \ may be holes because of the way we fill the list when the
696 \ server preference order is enforced, and also in case some
697 \ suites are filtered out. In particular:
698 \ -- ECDHE suites are removed if there is no common hash function
699 \ (for signatures) or no common curve.
700 \ -- TLS-1.2-only suites are removed if the negociated version is
701 \ TLS-1.1 or lower.
702 addr-client_suites dup >css-off
703 begin dup css-max < while
704 dup get16 dup cipher-suite-to-elements
705 can-ecdhe ifnot
706 dup 12 >> dup 1 = swap 2 = or if
707 2drop 0 dup
708 then
709 then
710 can-tls12 ifnot
711 \ Suites compatible with TLS-1.0 and TLS-1.1 are
712 \ exactly the ones that use HMAC/SHA-1.
713 dup 0xF0 and 0x20 <> if
714 2drop 0 dup
715 then
716 then
717 dup if
718 css-off 2+ set16 css-off set16
719 css-off 4 + >css-off
720 else
721 2drop
722 then
723 4 +
724 repeat
725 drop
726 css-off addr-client_suites - 2 >>
727 dup ifnot
728 \ No common cipher suite: handshake failure.
729 40 fail-alert
730 then
731 addr-client_suites_num set8
732
733 \ Call policy handler to obtain the cipher suite and other
734 \ parameters.
735 call-policy-handler ifnot 40 fail-alert then
736
737 \ We are not resuming a session.
738 0 ;
739
740 \ Write ServerHello.
741 : write-ServerHello ( initial -- )
742 { initial }
743 \ Compute ServerHello length. Right now we only send the
744 \ "secure renegotiation" extension.
745 2 write8 70
746
747 addr-reneg get8 2 = if
748 initial if 5 else 29 then
749 else
750 0
751 then
752 { ext-reneg-len }
753 addr-peer_log_max_frag_len get8 if 5 else 0 then
754 { ext-max-frag-len }
755
756 ext-reneg-len ext-max-frag-len + dup if 2 + then +
757 write24
758
759 \ Protocol version
760 addr-version get16 write16
761
762 \ Server random
763 addr-server_random 4 bzero
764 addr-server_random 4 + 28 mkrand
765 addr-server_random 32 write-blob
766
767 \ Session ID
768 \ TODO: if we have no session cache at all, we might send here
769 \ an empty session ID. This would save a bit of network
770 \ bandwidth.
771 32 write8
772 addr-session_id 32 write-blob
773
774 \ Cipher suite
775 addr-cipher_suite get16 write16
776
777 \ Compression method
778 0 write8
779
780 \ Extensions
781 ext-reneg-len ext-max-frag-len + dup if
782 write16
783 ext-reneg-len dup if
784 0xFF01 write16
785 4 - dup write16
786 1- addr-saved_finished swap write-blob-head8
787 else
788 drop
789 then
790 ext-max-frag-len if
791 0x0001 write16
792 1 write16 addr-peer_log_max_frag_len get8 8 - write8
793 then
794 else
795 drop
796 then ;
797
798 \ Compute total chain length. This includes the individual certificate
799 \ headers, but not the total chain header. This also sets the cert_cur,
800 \ cert_len and chain_len context fields.
801 cc: total-chain-length ( -- len ) {
802 size_t u;
803 uint32_t total;
804
805 total = 0;
806 for (u = 0; u < CTX->chain_len; u ++) {
807 total += 3 + (uint32_t)CTX->chain[u].data_len;
808 }
809 T0_PUSH(total);
810 }
811
812 \ Get length for current certificate in the chain; if the chain end was
813 \ reached, then this returns -1.
814 cc: begin-cert ( -- len ) {
815 if (CTX->chain_len == 0) {
816 T0_PUSHi(-1);
817 } else {
818 CTX->cert_cur = CTX->chain->data;
819 CTX->cert_len = CTX->chain->data_len;
820 CTX->chain ++;
821 CTX->chain_len --;
822 T0_PUSH(CTX->cert_len);
823 }
824 }
825
826 \ Copy a chunk of certificate data into the pad. Returned value is the
827 \ chunk length, or 0 if the certificate end is reached.
828 cc: copy-cert-chunk ( -- len ) {
829 size_t clen;
830
831 clen = CTX->cert_len;
832 if (clen > sizeof ENG->pad) {
833 clen = sizeof ENG->pad;
834 }
835 memcpy(ENG->pad, CTX->cert_cur, clen);
836 CTX->cert_cur += clen;
837 CTX->cert_len -= clen;
838 T0_PUSH(clen);
839 }
840
841 \ Write the server Certificate.
842 : write-Certificate ( -- )
843 11 write8
844 total-chain-length
845 dup 3 + write24 write24
846 begin
847 begin-cert
848 dup 0< if drop ret then write24
849 begin copy-cert-chunk dup while
850 addr-pad swap write-blob
851 repeat
852 drop
853 again ;
854
855 \ Do the first part of ECDHE. Returned value is the computed signature
856 \ length, or a negative error code on error.
857 cc: do-ecdhe-part1 ( curve -- len ) {
858 int curve = T0_POPi();
859 T0_PUSHi(do_ecdhe_part1(CTX, curve));
860 }
861
862 \ Write the Server Key Exchange message (if applicable).
863 : write-ServerKeyExchange ( -- )
864 addr-cipher_suite get16 use-ecdhe? ifnot ret then
865
866 \ We must select an appropriate curve among the curves that
867 \ are supported both by us and the peer. Right now we use
868 \ the one with the smallest ID, which in practice means P-256.
869 \ (TODO: add some option to make that behaviour configurable.)
870 \
871 \ This loop always terminates because previous processing made
872 \ sure that ECDHE suites are not selectable if there is no common
873 \ curve.
874 addr-curves get32 0
875 begin dup2 >> 1 and 0= while 1+ repeat
876 { curve-id } drop
877
878 \ Compute the signed curve point to send.
879 curve-id do-ecdhe-part1 dup 0< if neg fail then { sig-len }
880
881 \ If using TLS-1.2+, then the hash function and signature
882 \ algorithm are explicitly encoded in the message.
883 addr-version get16 0x0303 >= { tls1.2+ }
884
885 12 write8
886 sig-len addr-ecdhe_point_len get8 + tls1.2+ 2 and + 6 + write24
887
888 \ Curve parameters: named curve with 16-bit ID.
889 3 write8 curve-id write16
890
891 \ Public point.
892 addr-ecdhe_point addr-ecdhe_point_len get8 write-blob-head8
893
894 \ If TLS-1.2+, write hash and signature identifiers.
895 tls1.2+ if
896 \ Hash identifier is in the sign_hash_id field.
897 addr-sign_hash_id get8 write8
898 \ 'use-rsa-ecdhe?' returns -1 for RSA, 0 for ECDSA.
899 \ The byte on the wire shall be 1 for RSA, 3 for ECDSA.
900 addr-cipher_suite get16 use-rsa-ecdhe? 1 << 3 + write8
901 then
902
903 \ Signature.
904 sig-len write16
905 addr-pad sig-len write-blob ;
906
907 \ Write the Server Hello Done message.
908 : write-ServerHelloDone ( -- )
909 14 write8 0 write24 ;
910
911 \ Perform RSA decryption of the client-sent pre-master secret. The value
912 \ is in the pad, and its length is provided as parameter.
913 cc: do-rsa-decrypt ( len prf_id -- ) {
914 int prf_id = T0_POPi();
915 size_t len = T0_POP();
916 do_rsa_decrypt(CTX, prf_id, ENG->pad, len);
917 }
918
919 \ Perform ECDH (not ECDHE). The point from the client is in the pad, and
920 \ its length is provided as parameter.
921 cc: do-ecdh ( len prf_id -- ) {
922 int prf_id = T0_POPi();
923 size_t len = T0_POP();
924 do_ecdh(CTX, prf_id, ENG->pad, len);
925 }
926
927 \ Do the second part of ECDHE.
928 cc: do-ecdhe-part2 ( len prf_id -- ) {
929 int prf_id = T0_POPi();
930 size_t len = T0_POP();
931 do_ecdhe_part2(CTX, prf_id, ENG->pad, len);
932 }
933
934 \ Read the Client Key Exchange.
935 : read-ClientKeyExchange ( -- )
936 \ Get header, and check message type.
937 read-handshake-header 16 = ifnot ERR_UNEXPECTED fail then
938
939 \ What we should get depends on the cipher suite.
940 addr-cipher_suite get16 use-rsa-keyx? if
941 \ RSA key exchange: we expect a RSA-encrypted value.
942 read16
943 dup 512 > if ERR_LIMIT_EXCEEDED fail then
944 dup { enc-rsa-len }
945 addr-pad swap read-blob
946 enc-rsa-len addr-cipher_suite get16 prf-id do-rsa-decrypt
947 then
948 addr-cipher_suite get16 dup use-ecdhe? swap use-ecdh? { ecdhe ecdh }
949 ecdh ecdhe or if
950 \ ECDH or ECDHE key exchange: we expect an EC point.
951 read8 dup { ec-point-len }
952 addr-pad swap read-blob
953 ec-point-len addr-cipher_suite get16 prf-id
954 ecdhe if do-ecdhe-part2 else do-ecdh then
955 then
956 close-elt ;
957
958 \ Send a HelloRequest.
959 : send-HelloRequest ( -- )
960 flush-record
961 begin can-output? not while wait-co drop repeat
962 22 addr-record_type_out set8
963 0 write8 0 write24 flush-record
964 23 addr-record_type_out set8 ;
965
966 \ Make a handshake.
967 : do-handshake ( initial -- )
968 0 addr-application_data set8
969 22 addr-record_type_out set8
970 multihash-init
971 read-ClientHello
972 more-incoming-bytes? if ERR_UNEXPECTED fail then
973 if
974 \ Session resumption
975 write-ServerHello
976 0 write-CCS-Finished
977 0 read-CCS-Finished
978 else
979 \ Not a session resumption
980 write-ServerHello
981 write-Certificate
982 write-ServerKeyExchange
983 write-ServerHelloDone
984 flush-record
985 read-ClientKeyExchange
986 0 read-CCS-Finished
987 0 write-CCS-Finished
988 save-session
989 then
990 1 addr-application_data set8
991 23 addr-record_type_out set8 ;
992
993 \ Entry point.
994 : main ( -- ! )
995 \ Perform initial handshake.
996 -1 do-handshake
997
998 begin
999 \ Wait for further invocation. At that point, we should
1000 \ get either an explicit call for renegotiation, or
1001 \ an incoming ClientHello handshake message.
1002 wait-co
1003 dup 0x07 and case
1004 0x00 of
1005 0x10 and if
1006 \ The best we can do is ask for a
1007 \ renegotiation, then wait for it
1008 \ to happen.
1009 send-HelloRequest
1010 then
1011 endof
1012 0x01 of
1013 \ Reject renegotiations if the peer does not
1014 \ support secure renegotiation. As allowed
1015 \ by RFC 5246, we do not send a
1016 \ no_renegotiation alert and just ignore the
1017 \ HelloRequest.
1018 drop
1019 addr-reneg get8 1 <> if
1020 0 do-handshake
1021 else
1022 flush-record
1023 begin can-output? not while
1024 wait-co drop
1025 repeat
1026 then
1027 endof
1028 ERR_UNEXPECTED fail
1029 endcase
1030 again
1031 ;