Lines Matching +full:data +full:- +full:addr
23 \ ----------------------------------------------------------------------
37 #define ENG ((br_ssl_engine_context *)(void *)((unsigned char *)t0ctx - offsetof(br_ssl_engine_con…
44 \ This code handles all records except application data records.
45 \ Application data is accepted (incoming records, outgoing payload data)
64 \ -- Some handshake data is expected.
66 \ -- The handshake is finished, and application data may flow. There may
67 \ be some incoming handshake data (HelloRequest from the server). This
70 \ -- Some change-cipher-spec data is expected.
72 \ -- An alert record is expected. Other types of incoming records will be
75 \ -- Waiting for the currently accumulated record to be sent and the
79 : NYI ( -- ! )
80 "NOT YET IMPLEMENTED!" puts cr -1 fail ;
83 cc: DBG ( addr -- ) {
91 cc: DBG2 ( addr x -- ) {
101 cc: fail ( err -- ! ) {
107 cc: get8 ( addr -- val ) {
108 size_t addr = (size_t)T0_POP();
109 T0_PUSH(*((unsigned char *)ENG + addr));
112 \ Read a 16-bit word from the context (address is offset in context).
113 cc: get16 ( addr -- val ) {
114 size_t addr = (size_t)T0_POP();
115 T0_PUSH(*(uint16_t *)(void *)((unsigned char *)ENG + addr));
118 \ Read a 32-bit word from the context (address is offset in context).
119 cc: get32 ( addr -- val ) {
120 size_t addr = (size_t)T0_POP();
121 T0_PUSH(*(uint32_t *)(void *)((unsigned char *)ENG + addr));
125 cc: set8 ( val addr -- ) {
126 size_t addr = (size_t)T0_POP();
127 *((unsigned char *)ENG + addr) = (unsigned char)T0_POP();
130 \ Set a 16-bit word in the context (address is offset in context).
131 cc: set16 ( val addr -- ) {
132 size_t addr = (size_t)T0_POP();
133 *(uint16_t *)(void *)((unsigned char *)ENG + addr) = (uint16_t)T0_POP();
136 \ Set a 32-bit word in the context (address is offset in context).
137 cc: set32 ( val addr -- ) {
138 size_t addr = (size_t)T0_POP();
139 *(uint32_t *)(void *)((unsigned char *)ENG + addr) = (uint32_t)T0_POP();
144 \ source. For field 'foo', the defined word is 'addr-foo'.
145 : addr-eng:
146 next-word { field }
147 "addr-" field + 0 1 define-word
148 0 8191 "offsetof(br_ssl_engine_context, " field + ")" + make-CX
151 addr-eng: max_frag_len
152 addr-eng: log_max_frag_len
153 addr-eng: peer_log_max_frag_len
154 addr-eng: shutdown_recv
155 addr-eng: record_type_in
156 addr-eng: record_type_out
157 addr-eng: version_in
158 addr-eng: version_out
159 addr-eng: application_data
160 addr-eng: version_min
161 addr-eng: version_max
162 addr-eng: suites_buf
163 addr-eng: suites_num
164 addr-eng: server_name
165 addr-eng: client_random
166 addr-eng: server_random
167 addr-eng: ecdhe_curve
168 addr-eng: ecdhe_point
169 addr-eng: ecdhe_point_len
170 addr-eng: reneg
171 addr-eng: saved_finished
172 addr-eng: flags
173 addr-eng: pad
174 addr-eng: action
175 addr-eng: alert
176 addr-eng: close_received
177 addr-eng: protocol_names_num
178 addr-eng: selected_protocol
180 \ Similar to 'addr-eng:', for fields in the 'session' substructure.
181 : addr-session-field:
182 next-word { field }
183 "addr-" field + 0 1 define-word
184 …setof(br_ssl_engine_context, session) + offsetof(br_ssl_session_parameters, " field + ")" + make-CX
187 addr-session-field: session_id
188 addr-session-field: session_id_len
189 addr-session-field: version
190 addr-session-field: cipher_suite
191 addr-session-field: master_secret
194 : flag? ( index -- bool )
195 addr-flags get32 swap >> 1 and neg ;
200 next-word { name }
201 name 0 1 define-word
202 0 63 "BR_" name + make-CX postpone literal postpone ; ;
235 cc: supported-curves ( -- x ) {
236 uint32_t x = ENG->iec == NULL ? 0 : ENG->iec->supported_curves;
242 cc: supported-hash-functions ( -- x num ) {
249 if (br_multihash_getimpl(&ENG->mhash, i)) {
259 cc: supports-rsa-sign? ( -- bool ) {
260 T0_PUSHi(-(ENG->irsavrfy != 0));
264 cc: supports-ecdsa? ( -- bool ) {
265 T0_PUSHi(-(ENG->iecdsa != 0));
269 cc: multihash-init ( -- ) {
270 br_multihash_init(&ENG->mhash);
273 \ Flush the current record: if some payload data has been accumulated,
274 \ close the record and schedule it for sending. If there is no such data,
276 cc: flush-record ( -- ) {
283 \ 0x01 handshake data is available
284 \ 0x02 change-cipher-spec data is available
285 \ 0x04 some data other than handshake or change-cipher-spec is available
289 : wait-co ( -- state )
292 addr-action get8 dup if
294 1 of 0 do-close endof
295 2 of addr-application_data get8 1 = if
302 addr-close_received get8 ifnot
303 has-input? if
304 addr-record_type_in get8 case
309 \ Alert -- if close_notify received, trigger
311 21 of process-alerts if -1 do-close then endof
321 can-output? if 0x08 or then ;
325 : send-alert ( level alert -- )
326 21 addr-record_type_out set8
327 swap write8-native drop write8-native drop
328 flush-record ;
332 : send-warning ( alert -- )
333 1 swap send-alert ;
336 : fail-alert ( alert -- ! )
338 flush-record
339 begin can-output? not while wait-co drop repeat
340 2 alert send-alert
341 begin can-output? not while wait-co drop repeat
345 \ -- Prevent new application data from the caller.
346 \ -- Incoming data is discarded (except alerts).
347 \ -- Outgoing data is flushed.
348 \ -- A close_notify alert is sent.
349 \ -- If 'cnr' is zero, then incoming data is discarded until a close_notify
351 \ -- At the end, the context is terminated.
353 \ cnr shall be either 0 or -1.
354 : do-close ( cnr -- ! )
355 \ 'cnr' is set to non-zero when a close_notify is received from
359 \ Get out of application data state. If we were accepting
360 \ application data (flag is 1), and we still expect a close_notify
363 addr-application_data get8 cnr not and 1 << addr-application_data set8
366 flush-record
371 begin can-output? not while cnr wait-for-close >cnr repeat
374 \ 21 addr-record_type_out set8
375 \ 1 write8-native 0 write8-native 2drop
376 \ flush-record
377 0 send-warning
383 dup can-output? and if ERR_OK fail then
384 wait-for-close
390 : wait-for-close ( cnr -- cnr )
393 has-input? if
394 addr-record_type_in get8 21 = if
395 drop process-alerts
398 \ data records.
399 0 addr-application_data set8
401 discard-input
408 cc: payload-to-send? ( -- bool ) {
409 T0_PUSHi(-br_ssl_engine_has_pld_to_send(ENG));
412 \ Test whether there is some available input data.
413 cc: has-input? ( -- bool ) {
414 T0_PUSHi(-(ENG->hlen_in != 0));
418 cc: can-output? ( -- bool ) {
419 T0_PUSHi(-(ENG->hlen_out > 0));
423 cc: discard-input ( -- ) {
424 ENG->hlen_in = 0;
427 \ Low-level read for one byte. If there is no available byte right
428 \ away, then -1 is returned. Otherwise, the byte value is returned.
430 \ injected in the multi-hasher.
431 cc: read8-native ( -- x ) {
432 if (ENG->hlen_in > 0) {
435 x = *ENG->hbuf_in ++;
436 if (ENG->record_type_in == BR_SSL_HANDSHAKE) {
437 br_multihash_update(&ENG->mhash, &x, 1);
440 ENG->hlen_in --;
442 T0_PUSHi(-1);
446 \ Low-level read for several bytes. On entry, this expects an address
453 \ injected in the multi-hasher.
454 cc: read-chunk-native ( addr len -- addr len ) {
455 size_t clen = ENG->hlen_in;
457 uint32_t addr, len;
460 addr = T0_POP();
464 memcpy((unsigned char *)ENG + addr, ENG->hbuf_in, clen);
465 if (ENG->record_type_in == BR_SSL_HANDSHAKE) {
466 br_multihash_update(&ENG->mhash, ENG->hbuf_in, clen);
468 T0_PUSH(addr + (uint32_t)clen);
469 T0_PUSH(len - (uint32_t)clen);
470 ENG->hbuf_in += clen;
471 ENG->hlen_in -= clen;
476 \ context is terminated; otherwise, this returns either true (-1) if a
478 : process-alerts ( -- bool )
480 begin has-input? while read8-native process-alert-byte or repeat
481 dup if 1 addr-shutdown_recv set8 then ;
483 \ Process an alert byte. Returned value is non-zero if this is a close_notify,
485 : process-alert-byte ( x -- bool )
486 addr-alert get8 case
492 addr-alert set8 0
495 0 addr-alert set8
506 \ In general we only deal with handshake data here. Alerts are processed
508 \ its own handling code. So we need to check that the data is "handshake"
511 \ Yield control to the engine. Alerts are processed; if incoming data is
513 : wait-for-handshake ( -- )
514 wait-co 0x07 and 0x01 > if ERR_UNEXPECTED fail then ;
516 \ Flush outgoing data (if any), then wait for the output buffer to be
519 : wait-rectype-out ( rectype -- )
521 flush-record
523 can-output? if rectype addr-record_type_out set8 ret then
524 wait-co drop
527 \ Read one byte of handshake data. Block until that byte is available.
529 : read8-nc ( -- x )
531 read8-native dup 0< ifnot ret then
532 drop wait-for-handshake
538 cc: more-incoming-bytes? ( -- bool ) {
539 T0_PUSHi(ENG->hlen_in != 0 || !br_ssl_engine_recvrec_finished(ENG));
546 : check-len ( lim len -- lim )
547 - dup 0< if ERR_BAD_PARAM fail then ;
549 \ Read one byte of handshake data. This pushes an integer in the 0..255 range.
550 : read8 ( lim -- lim x )
551 1 check-len read8-nc ;
553 \ Read a 16-bit value (in the 0..65535 range)
554 : read16 ( lim -- lim n )
555 2 check-len read8-nc 8 << read8-nc + ;
557 \ Read a 24-bit value (in the 0..16777215 range)
558 : read24 ( lim -- lim n )
559 3 check-len read8-nc 8 << read8-nc + 8 << read8-nc + ;
563 : read-blob ( lim addr len -- lim )
564 { addr len }
565 len check-len
566 addr len
568 read-chunk-native
570 wait-for-handshake
574 : skip-blob ( lim len -- lim )
575 swap over check-len swap
576 begin dup while read8-nc drop 1- repeat
579 \ Read a 16-bit length, then skip exactly that many bytes.
580 : read-ignore-16 ( lim -- lim )
581 read16 skip-blob ;
585 : open-elt ( lim len -- lim-outer lim-inner )
587 - dup 0< if ERR_BAD_PARAM fail then
591 : close-elt ( lim -- )
594 \ Write one byte of handshake data.
595 : write8 ( n -- )
597 dup write8-native if drop ret then
598 wait-co drop
601 \ Low-level write for one byte. On exit, it pushes either -1 (byte was
603 cc: write8-native ( x -- bool ) {
607 if (ENG->hlen_out > 0) {
608 if (ENG->record_type_out == BR_SSL_HANDSHAKE) {
609 br_multihash_update(&ENG->mhash, &x, 1);
611 *ENG->hbuf_out ++ = x;
612 ENG->hlen_out --;
613 T0_PUSHi(-1);
619 \ Write a 16-bit value.
620 : write16 ( n -- )
623 \ Write a 24-bit value.
624 : write24 ( n -- )
629 : write-blob ( addr len -- )
631 write-blob-chunk
633 wait-co drop
636 cc: write-blob-chunk ( addr len -- addr len ) {
637 size_t clen = ENG->hlen_out;
639 uint32_t addr, len;
642 addr = T0_POP();
646 memcpy(ENG->hbuf_out, (unsigned char *)ENG + addr, clen);
647 if (ENG->record_type_out == BR_SSL_HANDSHAKE) {
648 br_multihash_update(&ENG->mhash, ENG->hbuf_out, clen);
650 T0_PUSH(addr + (uint32_t)clen);
651 T0_PUSH(len - (uint32_t)clen);
652 ENG->hbuf_out += clen;
653 ENG->hlen_out -= clen;
658 : write-blob-head8 ( addr len -- )
659 dup write8 write-blob ;
662 : write-blob-head16 ( addr len -- )
663 dup write16 write-blob ;
665 \ Perform a byte-to-byte comparison between two blobs. Each blob is
667 \ length is common. Returned value is true (-1) if the two blobs are
669 cc: memcmp ( addr1 addr2 len -- bool ) {
674 T0_PUSH((uint32_t)-(x == 0));
679 cc: memcpy ( dst src len -- ) {
686 \ Get string length (zero-terminated). The string address is provided as
689 cc: strlen ( str -- len ) {
695 cc: bzero ( addr len -- ) {
697 void *addr = (unsigned char *)ENG + (size_t)T0_POP();
698 memset(addr, 0, len);
702 \ then the list index at which it was found is returned; otherwise, -1
704 : scan-suite ( suite -- index )
706 addr-suites_num get8 { num }
709 dup 1 << addr-suites_buf + get16 suite = if ret then
712 drop -1 ;
717 cc: mkrand ( addr len -- ) {
719 void *addr = (unsigned char *)ENG + (size_t)T0_POP();
720 br_hmac_drbg_generate(&ENG->rng, addr, len);
725 : read-handshake-header-core ( -- lim type )
726 read8-nc 3 read24 swap drop swap ;
731 : read-handshake-header ( -- lim type )
733 read-handshake-header-core dup 0= while
744 \ as a sequence of pairs of 16-bit words, the first being the cipher suite
753 \ -- Server key type:
755 \ 1 ECDHE-RSA (ECDHE key exchange, RSA signature)
756 \ 2 ECDHE-ECDSA (ECDHE key exchange, ECDSA signature)
757 \ 3 ECDH-RSA (ECDH key exchange, certificate is RSA-signed)
758 \ 4 ECDH-ECDSA (ECDH key exchange, certificate is ECDSA-signed)
759 \ -- Encryption algorithm:
761 \ 1 AES-128/CBC
762 \ 2 AES-256/CBC
763 \ 3 AES-128/GCM
764 \ 4 AES-256/GCM
766 \ 6 AES-128/CCM
767 \ 7 AES-256/CCM
768 \ 8 AES-128/CCM8
769 \ 9 AES-256/CCM8
770 \ -- MAC algorithm:
772 \ 2 HMAC/SHA-1
773 \ 4 HMAC/SHA-256
774 \ 5 HMAC/SHA-384
775 \ -- PRF for TLS-1.2:
776 \ 4 with SHA-256
777 \ 5 with SHA-384
779 \ WARNING: if adding a new cipher suite that does not use SHA-256 for the
783 data: cipher-suite-def
840 : cipher-suite-to-elements ( suite -- elts )
842 cipher-suite-def
844 dup 2+ swap data-get16
846 id = if data-get16 ret then
851 \ returns true (-1) for the TLS_FALLBACK_SCSV pseudo-ciphersuite.
852 : suite-supported? ( suite -- bool )
853 dup 0x5600 = if drop -1 ret then
854 cipher-suite-to-elements 0<> ;
860 : expected-key-type ( suite -- key-type )
861 cipher-suite-to-elements 12 >>
872 : use-rsa-keyx? ( suite -- bool )
873 cipher-suite-to-elements 12 >> 0= ;
876 : use-rsa-ecdhe? ( suite -- bool )
877 cipher-suite-to-elements 12 >> 1 = ;
880 : use-ecdsa-ecdhe? ( suite -- bool )
881 cipher-suite-to-elements 12 >> 2 = ;
884 : use-ecdhe? ( suite -- bool )
885 cipher-suite-to-elements 12 >> dup 0> swap 3 < and ;
888 : use-ecdh? ( suite -- bool )
889 cipher-suite-to-elements 12 >> 2 > ;
892 : prf-id ( suite -- id )
893 cipher-suite-to-elements 15 and ;
895 \ Test whether a cipher suite is only for TLS-1.2. Cipher suites that
896 \ can be used with TLS-1.0 or 1.1 use HMAC/SHA-1. RFC do not formally
897 \ forbid using a CBC-based TLS-1.2 cipher suite, e.g. based on HMAC/SHA-256,
902 : use-tls12? ( suite -- bool )
903 cipher-suite-to-elements 0xF0 and 0x20 <> ;
906 : switch-encryption ( is-client for-input -- )
907 { for-input }
908 addr-cipher_suite get16 cipher-suite-to-elements { elts }
920 for-input if
921 switch-cbc-in
923 switch-cbc-out
927 \ AES-128/CBC
929 for-input if
930 switch-cbc-in
932 switch-cbc-out
936 \ AES-256/CBC
938 for-input if
939 switch-cbc-in
941 switch-cbc-out
945 \ AES-128/GCM
947 for-input if
948 switch-aesgcm-in
950 switch-aesgcm-out
954 \ AES-256/GCM
956 for-input if
957 switch-aesgcm-in
959 switch-aesgcm-out
965 for-input if
966 switch-chapol-in
968 switch-chapol-out
990 8 and 16 swap -
991 for-input if
992 switch-aesccm-in
994 switch-aesccm-out
1000 cc: switch-cbc-out ( is_client prf_id mac_id aes cipher_key_len -- ) {
1010 aes ? ENG->iaes_cbcenc : ENG->ides_cbcenc, cipher_key_len);
1013 cc: switch-cbc-in ( is_client prf_id mac_id aes cipher_key_len -- ) {
1023 aes ? ENG->iaes_cbcdec : ENG->ides_cbcdec, cipher_key_len);
1026 cc: switch-aesgcm-out ( is_client prf_id cipher_key_len -- ) {
1034 ENG->iaes_ctr, cipher_key_len);
1037 cc: switch-aesgcm-in ( is_client prf_id cipher_key_len -- ) {
1045 ENG->iaes_ctr, cipher_key_len);
1048 cc: switch-chapol-out ( is_client prf_id -- ) {
1056 cc: switch-chapol-in ( is_client prf_id -- ) {
1064 cc: switch-aesccm-out ( is_client prf_id cipher_key_len tag_len -- ) {
1073 ENG->iaes_ctrcbc, cipher_key_len, tag_len);
1076 cc: switch-aesccm-in ( is_client prf_id cipher_key_len tag_len -- ) {
1085 ENG->iaes_ctrcbc, cipher_key_len, tag_len);
1089 : write-Finished ( from_client -- )
1090 compute-Finished
1091 20 write8 12 write24 addr-pad 12 write-blob ;
1094 : read-Finished ( from_client -- )
1095 compute-Finished
1096 read-handshake-header 20 <> if ERR_UNEXPECTED fail then
1097 addr-pad 12 + 12 read-blob
1098 close-elt
1099 addr-pad dup 12 + 12 memcmp ifnot ERR_BAD_FINISHED fail then ;
1102 \ expected value). The 12-byte string is written in the pad. The
1103 \ "from_client" value is non-zero for the Finished sent by the client.
1106 : compute-Finished ( from_client -- )
1107 dup addr-saved_finished swap ifnot 12 + then swap
1108 addr-cipher_suite get16 prf-id compute-Finished-inner
1109 addr-pad 12 memcpy ;
1111 cc: compute-Finished-inner ( from_client prf_id -- ) {
1118 seed.data = tmp;
1119 if (ENG->session.version >= BR_TLS12) {
1120 seed.len = br_multihash_out(&ENG->mhash, prf_id, tmp);
1122 br_multihash_out(&ENG->mhash, br_md5_ID, tmp);
1123 br_multihash_out(&ENG->mhash, br_sha1_ID, tmp + 16);
1126 prf(ENG->pad, 12, ENG->session.master_secret,
1127 sizeof ENG->session.master_secret,
1133 : read-CCS-Finished ( is-client -- )
1134 has-input? if
1135 addr-record_type_in get8 20 <> if ERR_UNEXPECTED fail then
1138 wait-co 0x07 and dup 0x02 <> while
1143 read8-nc 1 <> more-incoming-bytes? or if ERR_BAD_CCS fail then
1144 dup 1 switch-encryption
1147 not read-Finished ;
1150 : write-CCS-Finished ( is-client -- )
1154 20 wait-rectype-out
1156 flush-record
1157 dup 0 switch-encryption
1158 22 wait-rectype-out
1159 write-Finished
1160 flush-record ;
1164 : read-list-sign-algos ( lim -- lim value )
1166 read16 open-elt
1174 \ SHA-* functions (2 to 6). Note that we reject MD5.
1183 hashes 1 sign 1- 2 << hash + << or >hashes
1187 close-elt
1195 cc: total-chain-length ( -- len ) {
1200 for (u = 0; u < ENG->chain_len; u ++) {
1201 total += 3 + (uint32_t)ENG->chain[u].data_len;
1207 \ reached, then this returns -1.
1208 cc: begin-cert ( -- len ) {
1209 if (ENG->chain_len == 0) {
1210 T0_PUSHi(-1);
1212 ENG->cert_cur = ENG->chain->data;
1213 ENG->cert_len = ENG->chain->data_len;
1214 ENG->chain ++;
1215 ENG->chain_len --;
1216 T0_PUSH(ENG->cert_len);
1220 \ Copy a chunk of certificate data into the pad. Returned value is the
1222 cc: copy-cert-chunk ( -- len ) {
1225 clen = ENG->cert_len;
1226 if (clen > sizeof ENG->pad) {
1227 clen = sizeof ENG->pad;
1229 memcpy(ENG->pad, ENG->cert_cur, clen);
1230 ENG->cert_cur += clen;
1231 ENG->cert_len -= clen;
1235 \ Write a Certificate message. Total chain length (excluding the 3-byte
1237 : write-Certificate ( -- total_chain_len )
1239 total-chain-length dup
1242 begin-cert
1244 begin copy-cert-chunk dup while
1245 addr-pad swap write-blob
1250 cc: x509-start-chain ( by_client -- ) {
1255 xc = *(ENG->x509ctx);
1256 xc->start_chain(ENG->x509ctx, bc ? ENG->server_name : NULL);
1259 cc: x509-start-cert ( length -- ) {
1262 xc = *(ENG->x509ctx);
1263 xc->start_cert(ENG->x509ctx, T0_POP());
1266 cc: x509-append ( length -- ) {
1270 xc = *(ENG->x509ctx);
1272 xc->append(ENG->x509ctx, ENG->pad, len);
1275 cc: x509-end-cert ( -- ) {
1278 xc = *(ENG->x509ctx);
1279 xc->end_cert(ENG->x509ctx);
1282 cc: x509-end-chain ( -- err ) {
1285 xc = *(ENG->x509ctx);
1286 T0_PUSH(xc->end_chain(ENG->x509ctx));
1289 cc: get-key-type-usages ( -- key-type-usages ) {
1294 xc = *(ENG->x509ctx);
1295 pk = xc->get_pkey(ENG->x509ctx, &usages);
1299 T0_PUSH(pk->key_type | usages);
1304 \ Parameter: non-zero if this is a read by the client of a certificate
1307 \ - Empty: 0
1308 \ - Valid: combination of key type and allowed key usages.
1309 \ - Invalid: negative (-x for error code x)
1310 : read-Certificate ( by_client -- key-type-usages )
1312 read-handshake-header 11 = ifnot ERR_UNEXPECTED fail then
1321 swap x509-start-chain
1323 \ Total chain length is a 24-bit integer.
1324 read24 open-elt
1327 read24 open-elt
1328 dup x509-start-cert
1331 \ as to use the existing reading function (read-blob)
1336 addr-pad len read-blob
1337 len x509-append
1339 close-elt
1340 x509-end-cert
1344 close-elt
1345 close-elt
1348 x509-end-chain
1352 get-key-type-usages ;
1358 cc: copy-protocol-name ( idx -- len ) {
1360 size_t len = strlen(ENG->protocol_names[idx]);
1361 memcpy(ENG->pad, ENG->protocol_names[idx], len);
1366 \ If a match is found, then the index is returned; otherwise, -1
1368 cc: test-protocol-name ( len -- n ) {
1372 for (u = 0; u < ENG->protocol_names_num; u ++) {
1375 name = ENG->protocol_names[u];
1376 if (len == strlen(name) && memcmp(ENG->pad, name, len) == 0) {
1381 T0_PUSHi(-1);