aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/asn1/doc/src/notes.xml22
-rw-r--r--lib/asn1/vsn.mk2
-rw-r--r--lib/common_test/doc/src/Makefile2
-rw-r--r--lib/common_test/doc/src/notes.xml20
-rw-r--r--lib/common_test/vsn.mk2
-rw-r--r--lib/compiler/doc/src/Makefile2
-rw-r--r--lib/compiler/doc/src/notes.xml84
-rw-r--r--lib/compiler/src/Makefile31
-rw-r--r--lib/compiler/src/beam_a.erl26
-rw-r--r--lib/compiler/src/beam_block.erl601
-rw-r--r--lib/compiler/src/beam_bs.erl141
-rw-r--r--lib/compiler/src/beam_clean.erl162
-rw-r--r--lib/compiler/src/beam_dead.erl971
-rw-r--r--lib/compiler/src/beam_disasm.erl17
-rw-r--r--lib/compiler/src/beam_except.erl62
-rw-r--r--lib/compiler/src/beam_flatten.erl5
-rw-r--r--lib/compiler/src/beam_jump.erl228
-rw-r--r--lib/compiler/src/beam_kernel_to_ssa.erl1330
-rw-r--r--lib/compiler/src/beam_listing.erl7
-rw-r--r--lib/compiler/src/beam_peep.erl73
-rw-r--r--lib/compiler/src/beam_receive.erl416
-rw-r--r--lib/compiler/src/beam_record.erl131
-rw-r--r--lib/compiler/src/beam_reorder.erl150
-rw-r--r--lib/compiler/src/beam_split.erl94
-rw-r--r--lib/compiler/src/beam_ssa.erl771
-rw-r--r--lib/compiler/src/beam_ssa.hrl66
-rw-r--r--lib/compiler/src/beam_ssa_codegen.erl1850
-rw-r--r--lib/compiler/src/beam_ssa_dead.erl1001
-rw-r--r--lib/compiler/src/beam_ssa_lint.erl349
-rw-r--r--lib/compiler/src/beam_ssa_opt.erl1650
-rw-r--r--lib/compiler/src/beam_ssa_pp.erl238
-rw-r--r--lib/compiler/src/beam_ssa_pre_codegen.erl2433
-rw-r--r--lib/compiler/src/beam_ssa_recv.erl278
-rw-r--r--lib/compiler/src/beam_ssa_type.erl1193
-rw-r--r--lib/compiler/src/beam_trim.erl2
-rw-r--r--lib/compiler/src/beam_type.erl1117
-rw-r--r--lib/compiler/src/beam_utils.erl570
-rw-r--r--lib/compiler/src/beam_validator.erl360
-rw-r--r--lib/compiler/src/beam_z.erl2
-rw-r--r--lib/compiler/src/compile.erl144
-rw-r--r--lib/compiler/src/compiler.app.src17
-rwxr-xr-xlib/compiler/src/genop.tab5
-rw-r--r--lib/compiler/src/v3_codegen.erl2925
-rw-r--r--lib/compiler/src/v3_core.erl22
-rw-r--r--lib/compiler/src/v3_kernel.erl11
-rw-r--r--lib/compiler/src/v3_kernel.hrl2
-rw-r--r--lib/compiler/test/Makefile8
-rw-r--r--lib/compiler/test/andor_SUITE.erl2
-rw-r--r--lib/compiler/test/apply_SUITE.erl2
-rw-r--r--lib/compiler/test/beam_except_SUITE.erl2
-rw-r--r--lib/compiler/test/beam_jump_SUITE.erl2
-rw-r--r--lib/compiler/test/beam_reorder_SUITE.erl2
-rw-r--r--lib/compiler/test/beam_ssa_SUITE.erl471
-rw-r--r--lib/compiler/test/beam_type_SUITE.erl144
-rw-r--r--lib/compiler/test/bif_SUITE.erl2
-rw-r--r--lib/compiler/test/bs_bincomp_SUITE.erl2
-rw-r--r--lib/compiler/test/bs_bit_binaries_SUITE.erl2
-rw-r--r--lib/compiler/test/bs_match_SUITE.erl44
-rw-r--r--lib/compiler/test/bs_utf_SUITE.erl2
-rw-r--r--lib/compiler/test/compilation_SUITE.erl8
-rw-r--r--lib/compiler/test/compile_SUITE.erl41
-rw-r--r--lib/compiler/test/core_alias_SUITE.erl2
-rw-r--r--lib/compiler/test/core_fold_SUITE.erl13
-rw-r--r--lib/compiler/test/error_SUITE.erl2
-rw-r--r--lib/compiler/test/float_SUITE.erl2
-rw-r--r--lib/compiler/test/guard_SUITE.erl57
-rw-r--r--lib/compiler/test/guard_SUITE_data/guard_SUITE_tuple_size.S30
-rw-r--r--lib/compiler/test/inline_SUITE.erl14
-rw-r--r--lib/compiler/test/map_SUITE.erl74
-rw-r--r--lib/compiler/test/match_SUITE.erl16
-rw-r--r--lib/compiler/test/misc_SUITE.erl107
-rw-r--r--lib/compiler/test/overridden_bif_SUITE.erl2
-rw-r--r--lib/compiler/test/receive_SUITE_data/ref_opt/no_5.erl38
-rw-r--r--lib/compiler/test/receive_SUITE_data/ref_opt/yes_14.S71
-rw-r--r--lib/compiler/test/receive_SUITE_data/ref_opt/yes_14.erl27
-rw-r--r--lib/compiler/test/record_SUITE.erl2
-rw-r--r--lib/compiler/test/regressions_SUITE.erl2
-rw-r--r--lib/compiler/test/test_lib.erl8
-rw-r--r--lib/compiler/test/warnings_SUITE.erl2
-rw-r--r--lib/compiler/vsn.mk2
-rw-r--r--lib/configure.in.src62
-rw-r--r--lib/crypto/c_src/Makefile.in60
-rw-r--r--lib/crypto/c_src/crypto.c715
-rw-r--r--lib/crypto/c_src/otp_test_engine.c3
-rw-r--r--lib/crypto/configure.in775
-rw-r--r--lib/crypto/doc/specs/.gitignore1
-rw-r--r--lib/crypto/doc/src/Makefile9
-rw-r--r--lib/crypto/doc/src/algorithm_details.xml297
-rw-r--r--lib/crypto/doc/src/crypto.xml1509
-rw-r--r--lib/crypto/doc/src/engine_keys.xml4
-rw-r--r--lib/crypto/doc/src/engine_load.xml33
-rw-r--r--lib/crypto/doc/src/notes.xml142
-rw-r--r--lib/crypto/doc/src/specs.xml4
-rw-r--r--lib/crypto/doc/src/usersguide.xml1
-rw-r--r--lib/crypto/src/crypto.erl1414
-rw-r--r--lib/crypto/test/crypto_SUITE.erl619
-rw-r--r--lib/crypto/test/crypto_SUITE_data/VADT128.rsp1823
-rw-r--r--lib/crypto/test/crypto_SUITE_data/VADT192.rsp1823
-rw-r--r--lib/crypto/test/crypto_SUITE_data/VADT256.rsp1823
-rw-r--r--lib/crypto/test/crypto_SUITE_data/VNT128.rsp456
-rw-r--r--lib/crypto/test/crypto_SUITE_data/VNT192.rsp456
-rw-r--r--lib/crypto/test/crypto_SUITE_data/VNT256.rsp456
-rw-r--r--lib/crypto/test/crypto_SUITE_data/VPT128.rsp1383
-rw-r--r--lib/crypto/test/crypto_SUITE_data/VPT192.rsp1383
-rw-r--r--lib/crypto/test/crypto_SUITE_data/VPT256.rsp1383
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT128.rsp1589
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT128.txt1589
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT192.rsp1589
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT192.txt1589
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT256.rsp1589
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT256.txt1589
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/Readme.txt9
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VADT128.rsp1823
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VADT192.rsp1823
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VADT256.rsp1823
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VNT128.rsp456
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VNT192.rsp456
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VNT256.rsp456
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VPT128.rsp1383
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VPT192.rsp1383
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VPT256.rsp1383
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VTT128.rsp393
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VTT192.rsp393
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VTT256.rsp393
-rw-r--r--lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/ccmtestvectors.zipbin0 -> 319267 bytes
-rw-r--r--lib/crypto/test/engine_SUITE.erl278
-rw-r--r--lib/crypto/vsn.mk2
-rw-r--r--lib/debugger/doc/src/notes.xml15
-rw-r--r--lib/debugger/vsn.mk2
-rw-r--r--lib/dialyzer/doc/src/notes.xml15
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/left_assoc2
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/left_assoc.erl96
-rw-r--r--lib/dialyzer/vsn.mk2
-rw-r--r--lib/diameter/doc/src/Makefile2
-rw-r--r--lib/diameter/doc/src/notes.xml20
-rw-r--r--lib/diameter/src/base/diameter_peer_fsm.erl4
-rw-r--r--lib/diameter/src/diameter.appup.src6
-rw-r--r--lib/diameter/vsn.mk2
-rw-r--r--lib/edoc/doc/src/notes.xml15
-rw-r--r--lib/edoc/vsn.mk2
-rw-r--r--lib/eldap/doc/src/notes.xml15
-rw-r--r--lib/eldap/vsn.mk2
-rw-r--r--lib/erl_docgen/doc/src/notes.xml18
-rw-r--r--lib/erl_docgen/priv/xsl/db_eix.xsl81
-rw-r--r--lib/erl_docgen/vsn.mk2
-rw-r--r--lib/erl_interface/configure.in5
-rw-r--r--lib/erl_interface/doc/src/Makefile2
-rw-r--r--lib/erl_interface/doc/src/notes.xml47
-rw-r--r--lib/erl_interface/src/legacy/erl_marshal.c2
-rw-r--r--lib/erl_interface/src/misc/ei_pthreads.c2
-rw-r--r--lib/erl_interface/test/ei_connect_SUITE.erl2
-rw-r--r--lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c2
-rw-r--r--lib/erl_interface/test/ei_decode_SUITE.erl2
-rw-r--r--lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c2
-rw-r--r--lib/erl_interface/test/ei_decode_encode_SUITE.erl2
-rw-r--r--lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c2
-rw-r--r--lib/erl_interface/test/ei_encode_SUITE.erl2
-rw-r--r--lib/erl_interface/test/ei_format_SUITE.erl2
-rw-r--r--lib/erl_interface/test/ei_print_SUITE.erl2
-rw-r--r--lib/erl_interface/test/ei_tmo_SUITE.erl2
-rw-r--r--lib/erl_interface/test/erl_connect_SUITE.erl2
-rw-r--r--lib/erl_interface/test/erl_eterm_SUITE.erl2
-rw-r--r--lib/erl_interface/test/erl_ext_SUITE.erl2
-rw-r--r--lib/erl_interface/test/erl_ext_SUITE_data/ext_test.c14
-rw-r--r--lib/erl_interface/test/erl_format_SUITE.erl2
-rw-r--r--lib/erl_interface/test/erl_global_SUITE.erl2
-rw-r--r--lib/erl_interface/test/erl_match_SUITE.erl2
-rw-r--r--lib/erl_interface/test/port_call_SUITE.erl2
-rw-r--r--lib/erl_interface/vsn.mk2
-rw-r--r--lib/et/doc/src/et_collector.xml2
-rw-r--r--lib/et/doc/src/et_selector.xml2
-rw-r--r--lib/et/doc/src/notes.xml15
-rw-r--r--lib/et/src/et_collector.erl2
-rw-r--r--lib/et/vsn.mk2
-rw-r--r--lib/eunit/doc/src/notes.xml15
-rw-r--r--lib/eunit/vsn.mk2
-rw-r--r--lib/ftp/doc/src/notes.xml17
-rw-r--r--lib/ftp/src/ftp.app.src2
-rw-r--r--lib/ftp/vsn.mk2
-rw-r--r--lib/hipe/doc/src/Makefile2
-rw-r--r--lib/hipe/doc/src/notes.xml15
-rw-r--r--lib/hipe/icode/hipe_beam_to_icode.erl38
-rw-r--r--lib/hipe/vsn.mk2
-rw-r--r--lib/inets/doc/src/mod_security.xml2
-rw-r--r--lib/inets/doc/src/notes.xml81
-rw-r--r--lib/inets/src/http_client/httpc_handler.erl18
-rw-r--r--lib/inets/src/http_client/httpc_manager.erl2
-rw-r--r--lib/inets/src/http_server/httpd_example.erl8
-rw-r--r--lib/inets/src/http_server/httpd_file.erl2
-rw-r--r--lib/inets/src/http_server/mod_esi.erl15
-rw-r--r--lib/inets/src/inets_app/inets.appup.src2
-rw-r--r--lib/inets/test/httpc_SUITE.erl56
-rw-r--r--lib/inets/test/httpd_SUITE.erl39
-rw-r--r--lib/inets/vsn.mk2
-rw-r--r--lib/jinterface/doc/src/Makefile2
-rw-r--r--lib/jinterface/doc/src/notes.xml15
-rw-r--r--lib/jinterface/vsn.mk2
-rw-r--r--lib/kernel/doc/src/gen_sctp.xml69
-rw-r--r--lib/kernel/doc/src/gen_tcp.xml28
-rw-r--r--lib/kernel/doc/src/gen_udp.xml35
-rw-r--r--lib/kernel/doc/src/inet.xml123
-rw-r--r--lib/kernel/doc/src/logger.xml2
-rw-r--r--lib/kernel/doc/src/logger_chapter.xml14
-rw-r--r--lib/kernel/doc/src/logger_formatter.xml7
-rw-r--r--lib/kernel/doc/src/logger_std_h.xml23
-rw-r--r--lib/kernel/doc/src/net_kernel.xml2
-rw-r--r--lib/kernel/doc/src/notes.xml122
-rw-r--r--lib/kernel/src/error_logger.erl29
-rw-r--r--lib/kernel/src/gen_sctp.erl18
-rw-r--r--lib/kernel/src/gen_tcp.erl16
-rw-r--r--lib/kernel/src/gen_udp.erl19
-rw-r--r--lib/kernel/src/inet.erl17
-rw-r--r--lib/kernel/src/inet6_tcp.erl8
-rw-r--r--lib/kernel/src/inet_int.hrl7
-rw-r--r--lib/kernel/src/inet_tcp.erl8
-rw-r--r--lib/kernel/src/kernel.app.src2
-rw-r--r--lib/kernel/src/logger.erl166
-rw-r--r--lib/kernel/src/logger_backend.erl2
-rw-r--r--lib/kernel/src/logger_config.erl23
-rw-r--r--lib/kernel/src/logger_disk_log_h.erl10
-rw-r--r--lib/kernel/src/logger_formatter.erl68
-rw-r--r--lib/kernel/src/logger_h_common.erl23
-rw-r--r--lib/kernel/src/logger_server.erl79
-rw-r--r--lib/kernel/src/logger_std_h.erl10
-rw-r--r--lib/kernel/src/net_kernel.erl132
-rw-r--r--lib/kernel/test/disk_log_SUITE.erl99
-rw-r--r--lib/kernel/test/erl_distribution_SUITE.erl1
-rw-r--r--lib/kernel/test/gen_tcp_misc_SUITE.erl232
-rw-r--r--lib/kernel/test/gen_udp_SUITE.erl164
-rw-r--r--lib/kernel/test/global_SUITE.erl30
-rw-r--r--lib/kernel/test/logger_SUITE.erl266
-rw-r--r--lib/kernel/test/logger_disk_log_h_SUITE.erl66
-rw-r--r--lib/kernel/test/logger_formatter_SUITE.erl7
-rw-r--r--lib/kernel/test/logger_simple_h_SUITE.erl3
-rw-r--r--lib/kernel/test/logger_std_h_SUITE.erl2
-rw-r--r--lib/kernel/vsn.mk2
-rw-r--r--lib/megaco/configure.in115
-rw-r--r--lib/megaco/doc/src/Makefile2
-rw-r--r--lib/megaco/doc/src/book.xml2
-rw-r--r--lib/megaco/doc/src/notes.xml17
-rw-r--r--lib/megaco/src/flex/Makefile.in40
-rw-r--r--lib/megaco/vsn.mk2
-rw-r--r--lib/mnesia/doc/src/mnesia_frag_hash.xml2
-rw-r--r--lib/mnesia/doc/src/notes.xml50
-rw-r--r--lib/mnesia/src/mnesia_index.erl2
-rw-r--r--lib/mnesia/test/mnesia_evil_coverage_test.erl58
-rw-r--r--lib/mnesia/vsn.mk2
-rw-r--r--lib/observer/doc/src/notes.xml15
-rw-r--r--lib/observer/vsn.mk2
-rw-r--r--lib/odbc/configure.in6
-rw-r--r--lib/odbc/doc/src/Makefile2
-rw-r--r--lib/odbc/doc/src/notes.xml19
-rw-r--r--lib/odbc/vsn.mk2
-rw-r--r--lib/os_mon/doc/src/notes.xml15
-rw-r--r--lib/os_mon/vsn.mk2
-rw-r--r--lib/otp_mibs/doc/src/Makefile2
-rw-r--r--lib/otp_mibs/doc/src/notes.xml15
-rw-r--r--lib/otp_mibs/vsn.mk2
-rw-r--r--lib/parsetools/doc/src/Makefile2
-rw-r--r--lib/parsetools/doc/src/notes.xml15
-rw-r--r--lib/parsetools/vsn.mk2
-rw-r--r--lib/public_key/doc/specs/.gitignore1
-rw-r--r--lib/public_key/doc/src/Makefile9
-rw-r--r--lib/public_key/doc/src/notes.xml35
-rw-r--r--lib/public_key/doc/src/public_key.xml684
-rw-r--r--lib/public_key/doc/src/specs.xml4
-rw-r--r--lib/public_key/src/public_key.erl441
-rw-r--r--lib/public_key/test/public_key_SUITE.erl4
-rw-r--r--lib/public_key/vsn.mk2
-rw-r--r--lib/reltool/doc/src/Makefile2
-rw-r--r--lib/reltool/doc/src/notes.xml17
-rw-r--r--lib/reltool/doc/src/reltool.xml2
-rw-r--r--lib/reltool/vsn.mk2
-rw-r--r--lib/runtime_tools/c_src/Makefile.in8
-rw-r--r--lib/runtime_tools/doc/src/notes.xml17
-rw-r--r--lib/runtime_tools/vsn.mk2
-rw-r--r--lib/sasl/doc/src/notes.xml15
-rw-r--r--lib/sasl/test/sasl_report_SUITE.erl3
-rw-r--r--lib/sasl/vsn.mk2
-rw-r--r--lib/snmp/doc/src/Makefile2
-rw-r--r--lib/snmp/doc/src/notes.xml45
-rw-r--r--lib/snmp/doc/src/snmp.xml33
-rw-r--r--lib/snmp/doc/src/snmp_impl_example_agent.xml2
-rw-r--r--lib/snmp/doc/src/snmpa.xml38
-rw-r--r--lib/snmp/doc/src/snmpm.xml38
-rw-r--r--lib/snmp/src/agent/snmpa_net_if.erl111
-rw-r--r--lib/snmp/src/compile/snmpc.erl6
-rw-r--r--lib/snmp/src/misc/snmp_log.erl334
-rw-r--r--lib/snmp/test/snmp_agent_test.erl2
-rw-r--r--lib/snmp/test/snmp_to_snmpnet_SUITE.erl2
-rw-r--r--lib/snmp/vsn.mk4
-rw-r--r--lib/ssh/doc/src/notes.xml39
-rw-r--r--lib/ssh/doc/src/ssh_app.xml8
-rw-r--r--lib/ssh/src/ssh.hrl14
-rw-r--r--lib/ssh/src/ssh_connection_handler.erl15
-rw-r--r--lib/ssh/src/ssh_message.erl8
-rw-r--r--lib/ssh/src/ssh_transport.erl203
-rw-r--r--lib/ssh/src/ssh_xfer.erl2
-rw-r--r--lib/ssh/test/ssh_bench_SUITE.erl35
-rw-r--r--lib/ssh/vsn.mk2
-rw-r--r--lib/ssl/doc/src/Makefile2
-rw-r--r--lib/ssl/doc/src/notes.xml134
-rw-r--r--lib/ssl/examples/src/client_server.erl2
-rw-r--r--lib/ssl/src/Makefile11
-rw-r--r--lib/ssl/src/dtls.erl113
-rw-r--r--lib/ssl/src/dtls_connection.erl67
-rw-r--r--lib/ssl/src/dtls_handshake.erl2
-rw-r--r--lib/ssl/src/dtls_handshake.hrl7
-rw-r--r--lib/ssl/src/dtls_socket.erl10
-rw-r--r--lib/ssl/src/dtls_v1.erl8
-rw-r--r--lib/ssl/src/inet_tls_dist.erl15
-rw-r--r--lib/ssl/src/ssl.app.src5
-rw-r--r--lib/ssl/src/ssl.appup.src4
-rw-r--r--lib/ssl/src/ssl.erl151
-rw-r--r--lib/ssl/src/ssl_alert.erl4
-rw-r--r--lib/ssl/src/ssl_alert.hrl5
-rw-r--r--lib/ssl/src/ssl_api.hrl14
-rw-r--r--lib/ssl/src/ssl_certificate.erl97
-rw-r--r--lib/ssl/src/ssl_cipher.erl1851
-rw-r--r--lib/ssl/src/ssl_cipher.hrl17
-rw-r--r--lib/ssl/src/ssl_cipher_format.erl1854
-rw-r--r--lib/ssl/src/ssl_connection.erl563
-rw-r--r--lib/ssl/src/ssl_connection.hrl4
-rw-r--r--lib/ssl/src/ssl_handshake.erl112
-rw-r--r--lib/ssl/src/ssl_handshake.hrl57
-rw-r--r--lib/ssl/src/ssl_internal.hrl3
-rw-r--r--lib/ssl/src/ssl_manager.erl2
-rw-r--r--lib/ssl/src/ssl_pem_cache.erl2
-rw-r--r--lib/ssl/src/ssl_pkix_db.erl2
-rw-r--r--lib/ssl/src/ssl_record.erl5
-rw-r--r--lib/ssl/src/ssl_v3.erl4
-rw-r--r--lib/ssl/src/tls.erl112
-rw-r--r--lib/ssl/src/tls_connection.erl217
-rw-r--r--lib/ssl/src/tls_handshake.erl17
-rw-r--r--lib/ssl/src/tls_handshake_1_3.erl149
-rw-r--r--lib/ssl/src/tls_handshake_1_3.hrl226
-rw-r--r--lib/ssl/src/tls_sender.erl397
-rw-r--r--lib/ssl/src/tls_socket.erl9
-rw-r--r--lib/ssl/src/tls_v1.erl73
-rw-r--r--lib/ssl/test/Makefile3
-rw-r--r--lib/ssl/test/property_test/ssl_eqc_handshake.erl192
-rw-r--r--lib/ssl/test/ssl_basic_SUITE.erl57
-rw-r--r--lib/ssl/test/ssl_certificate_verify_SUITE.erl36
-rw-r--r--lib/ssl/test/ssl_eqc_SUITE.erl58
-rw-r--r--lib/ssl/test/ssl_handshake_SUITE.erl26
-rw-r--r--lib/ssl/test/ssl_pem_cache_SUITE.erl2
-rw-r--r--lib/ssl/test/ssl_session_cache_SUITE.erl6
-rw-r--r--lib/ssl/test/ssl_test_lib.erl48
-rw-r--r--lib/ssl/test/ssl_to_openssl_SUITE.erl187
-rw-r--r--lib/stdlib/doc/src/ets.xml23
-rw-r--r--lib/stdlib/doc/src/filename.xml34
-rw-r--r--lib/stdlib/doc/src/gen_statem.xml228
-rw-r--r--lib/stdlib/doc/src/notes.xml35
-rw-r--r--lib/stdlib/doc/src/rand.xml61
-rw-r--r--lib/stdlib/doc/src/supervisor.xml14
-rw-r--r--lib/stdlib/src/dets.erl23
-rw-r--r--lib/stdlib/src/filename.erl31
-rw-r--r--lib/stdlib/src/gen_statem.erl261
-rw-r--r--lib/stdlib/src/io_lib.erl49
-rw-r--r--lib/stdlib/src/io_lib_format.erl11
-rw-r--r--lib/stdlib/src/ms_transform.erl6
-rw-r--r--lib/stdlib/src/proc_lib.erl93
-rw-r--r--lib/stdlib/src/rand.erl433
-rw-r--r--lib/stdlib/test/beam_lib_SUITE.erl2
-rw-r--r--lib/stdlib/test/dets_SUITE.erl15
-rw-r--r--lib/stdlib/test/ets_SUITE.erl1534
-rw-r--r--lib/stdlib/test/ets_SUITE_data/visualize_throughput.html253
-rw-r--r--lib/stdlib/test/gen_statem_SUITE.erl73
-rw-r--r--lib/stdlib/test/io_SUITE.erl12
-rw-r--r--lib/stdlib/test/rand_SUITE.erl373
-rw-r--r--lib/stdlib/test/rand_Xoroshiro928ss_dev.txt343
-rw-r--r--lib/stdlib/test/re_SUITE_data/testoutput216
-rw-r--r--lib/stdlib/test/re_SUITE_data/testoutput58
-rw-r--r--lib/stdlib/test/supervisor_SUITE.erl7
-rw-r--r--lib/stdlib/vsn.mk2
-rw-r--r--lib/syntax_tools/doc/src/notes.xml38
-rw-r--r--lib/syntax_tools/src/erl_syntax.erl17
-rw-r--r--lib/syntax_tools/test/merl_SUITE.erl14
-rw-r--r--lib/syntax_tools/test/syntax_tools_SUITE.erl79
-rw-r--r--lib/syntax_tools/vsn.mk2
-rw-r--r--lib/tftp/doc/src/notes.xml17
-rw-r--r--lib/tftp/src/tftp.app.src2
-rw-r--r--lib/tftp/vsn.mk2
-rw-r--r--lib/tools/doc/src/notes.xml22
-rw-r--r--lib/tools/emacs/erlang.el2
-rw-r--r--lib/tools/src/Makefile2
-rw-r--r--lib/tools/src/cover.erl2
-rw-r--r--lib/tools/test/xref_SUITE.erl2
-rw-r--r--lib/tools/vsn.mk2
-rw-r--r--lib/wx/c_src/wxe_driver.h2
-rw-r--r--lib/wx/doc/src/notes.xml15
-rwxr-xr-xlib/wx/test/wxt2
-rw-r--r--lib/wx/vsn.mk2
-rw-r--r--lib/xmerl/doc/src/notes.xml15
-rw-r--r--lib/xmerl/src/xmerl_scan.erl2
-rw-r--r--lib/xmerl/vsn.mk2
396 files changed, 61443 insertions, 14387 deletions
diff --git a/lib/asn1/doc/src/notes.xml b/lib/asn1/doc/src/notes.xml
index c86fa79c2c..086b5f38c6 100644
--- a/lib/asn1/doc/src/notes.xml
+++ b/lib/asn1/doc/src/notes.xml
@@ -32,6 +32,28 @@
<p>This document describes the changes made to the asn1 application.</p>
+<section><title>Asn1 5.0.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>A bug in ASN.1 BER decoding has been fixed. When
+ decoding a recursively enclosed term the length was not
+ propagated to that term decoding, so if the length of the
+ enclosed term was longer than the enclosing that error
+ was not detected.</p> <p>A hard coded C stack limitation
+ for decoding recursive ASN.1 terms has been introduced.
+ This is currently set to 8 kWords giving a nesting depth
+ of about 1000 levels. Deeper terms can not be decoded,
+ which should not be much of a real world limitation.</p>
+ <p>
+ Own Id: OTP-14440 Aux Id: ERIERL-220 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Asn1 5.0.6</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/asn1/vsn.mk b/lib/asn1/vsn.mk
index 30cbca3773..970479cc44 100644
--- a/lib/asn1/vsn.mk
+++ b/lib/asn1/vsn.mk
@@ -1 +1 @@
-ASN1_VSN = 5.0.6
+ASN1_VSN = 5.0.7
diff --git a/lib/common_test/doc/src/Makefile b/lib/common_test/doc/src/Makefile
index 4d6161d3ae..b5acdc6f95 100644
--- a/lib/common_test/doc/src/Makefile
+++ b/lib/common_test/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2003-2017. All Rights Reserved.
+# Copyright Ericsson AB 2003-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/lib/common_test/doc/src/notes.xml b/lib/common_test/doc/src/notes.xml
index df22896b27..dc18def838 100644
--- a/lib/common_test/doc/src/notes.xml
+++ b/lib/common_test/doc/src/notes.xml
@@ -33,6 +33,26 @@
<file>notes.xml</file>
</header>
+<section><title>Common_Test 1.16.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The Logger handler cth_log_redirect earlier called the
+ report callback (report_cb) before calling the logger
+ formatter. In some cases this would fail, since
+ cth_log_redirect could not handle report callbacks with
+ two arguments. This is now corrected, so only the
+ formatter will call the report callback.</p>
+ <p>
+ Own Id: OTP-15307</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Common_Test 1.16</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/common_test/vsn.mk b/lib/common_test/vsn.mk
index 2dc1965878..fd5d4a57aa 100644
--- a/lib/common_test/vsn.mk
+++ b/lib/common_test/vsn.mk
@@ -1 +1 @@
-COMMON_TEST_VSN = 1.16
+COMMON_TEST_VSN = 1.16.1
diff --git a/lib/compiler/doc/src/Makefile b/lib/compiler/doc/src/Makefile
index 661415899f..32f150eef8 100644
--- a/lib/compiler/doc/src/Makefile
+++ b/lib/compiler/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2017. All Rights Reserved.
+# Copyright Ericsson AB 1997-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/lib/compiler/doc/src/notes.xml b/lib/compiler/doc/src/notes.xml
index 671126b73b..b175669bd8 100644
--- a/lib/compiler/doc/src/notes.xml
+++ b/lib/compiler/doc/src/notes.xml
@@ -32,6 +32,74 @@
<p>This document describes the changes made to the Compiler
application.</p>
+<section><title>Compiler 7.2.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed a bug that prevented certain variable-sized
+ binary comprehensions from compiling.</p>
+ <p>
+ Own Id: OTP-15186 Aux Id: ERL-665 </p>
+ </item>
+ <item>
+ <p>When compiling from Core Erlang, funs created in
+ certain expressions that were only used for their
+ side-effects were subtly broken.</p>
+ <p>
+ Own Id: OTP-15188 Aux Id: ERL-658 </p>
+ </item>
+ <item>
+ <p>There could be an internal consistency failure when a
+ <c>receive</c> was nested in a
+ <c>try</c>/<c>catch</c>.</p>
+ <p>
+ Own Id: OTP-15218 Aux Id: ERL-684 </p>
+ </item>
+ <item>
+ <p>In rare circumstances, the matched out tail of a
+ binary could be the entire original binary.</p>
+ <p>
+ Own Id: OTP-15219 Aux Id: ERL-689 </p>
+ </item>
+ <item>
+ <p>When <c>is_map_key/2</c> was used in a guard together
+ with the <c>not/1</c> or <c>or/2</c> operators, the error
+ behavior could be wrong when <c>is_map_key/2</c> was
+ passed a non-map as the second argument. </p>
+ <p>In rare circumstances, compiling code that uses
+ <c>is_map_key/2</c> could cause an internal consistency
+ check failure.</p>
+ <p>
+ Own Id: OTP-15227 Aux Id: ERL-699 </p>
+ </item>
+ <item>
+ <p>The compiler could crash when compiling a function
+ with multiple receives in multiple clauses.</p>
+ <p>
+ Own Id: OTP-15235 Aux Id: ERL-703 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Compiler 7.2.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fix a regression in OTP-15204 that removed
+ <c>.beam</c> file metadata that some external build tools
+ relied on.</p>
+ <p>
+ Own Id: OTP-15292</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Compiler 7.2.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -314,6 +382,22 @@
</section>
+<section><title>Compiler 7.1.5.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fix a regression in OTP-15204 that removed
+ <c>.beam</c> file metadata that some external build tools
+ relied on.</p>
+ <p>
+ Own Id: OTP-15292</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Compiler 7.1.5.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/compiler/src/Makefile b/lib/compiler/src/Makefile
index 2408c76b48..522523726b 100644
--- a/lib/compiler/src/Makefile
+++ b/lib/compiler/src/Makefile
@@ -52,7 +52,6 @@ MODULES = \
beam_bs \
beam_bsm \
beam_clean \
- beam_dead \
beam_dict \
beam_disasm \
beam_except \
@@ -61,12 +60,17 @@ MODULES = \
beam_listing \
beam_opcodes \
beam_peep \
- beam_receive \
- beam_reorder \
- beam_record \
- beam_split \
+ beam_ssa \
+ beam_ssa_codegen \
+ beam_ssa_dead \
+ beam_ssa_lint \
+ beam_ssa_opt \
+ beam_ssa_pp \
+ beam_ssa_pre_codegen \
+ beam_ssa_recv \
+ beam_ssa_type \
+ beam_kernel_to_ssa \
beam_trim \
- beam_type \
beam_utils \
beam_validator \
beam_z \
@@ -90,7 +94,6 @@ MODULES = \
sys_core_fold_lists \
sys_core_inline \
sys_pre_attributes \
- v3_codegen \
v3_core \
v3_kernel \
v3_kernel_pp
@@ -99,6 +102,7 @@ BEAM_H = $(wildcard ../priv/beam_h/*.h)
HRL_FILES= \
beam_disasm.hrl \
+ beam_ssa.hrl \
core_parse.hrl \
v3_kernel.hrl
@@ -185,7 +189,17 @@ release_docs_spec:
# ----------------------------------------------------
$(EBIN)/beam_disasm.beam: $(EGEN)/beam_opcodes.hrl beam_disasm.hrl
-$(EBIN)/beam_listing.beam: core_parse.hrl v3_kernel.hrl
+$(EBIN)/beam_listing.beam: core_parse.hrl v3_kernel.hrl beam_ssa.hrl
+$(EBIN)/beam_kernel_to_ssa.beam: v3_kernel.hrl beam_ssa.hrl
+$(EBIN)/beam_ssa.beam: beam_ssa.hrl
+$(EBIN)/beam_ssa_codegen.beam: beam_ssa.hrl
+$(EBIN)/beam_ssa_dead.beam: beam_ssa.hrl
+$(EBIN)/beam_ssa_lint.beam: beam_ssa.hrl
+$(EBIN)/beam_ssa_opt.beam: beam_ssa.hrl
+$(EBIN)/beam_ssa_pp.beam: beam_ssa.hrl
+$(EBIN)/beam_ssa_pre_codegen.beam: beam_ssa.hrl
+$(EBIN)/beam_ssa_recv.beam: beam_ssa.hrl
+$(EBIN)/beam_ssa_type.beam: beam_ssa.hrl
$(EBIN)/cerl.beam: core_parse.hrl
$(EBIN)/compile.beam: core_parse.hrl ../../stdlib/include/erl_compile.hrl
$(EBIN)/core_lib.beam: core_parse.hrl
@@ -197,7 +211,6 @@ $(EBIN)/sys_core_dsetel.beam: core_parse.hrl
$(EBIN)/sys_core_fold.beam: core_parse.hrl
$(EBIN)/sys_core_fold_lists.beam: core_parse.hrl
$(EBIN)/sys_core_inline.beam: core_parse.hrl
-$(EBIN)/v3_codegen.beam: v3_kernel.hrl
$(EBIN)/v3_core.beam: core_parse.hrl
$(EBIN)/v3_kernel.beam: core_parse.hrl v3_kernel.hrl
$(EBIN)/v3_kernel_pp.beam: v3_kernel.hrl
diff --git a/lib/compiler/src/beam_a.erl b/lib/compiler/src/beam_a.erl
index 6fd4ace540..0abc845310 100644
--- a/lib/compiler/src/beam_a.erl
+++ b/lib/compiler/src/beam_a.erl
@@ -39,14 +39,26 @@ function({function,Name,Arity,CLabel,Is0}) ->
%% Remove unusued labels for cleanliness and to help
%% optimization passes and HiPE.
- Is = beam_jump:remove_unused_labels(Is1),
- {function,Name,Arity,CLabel,Is}
+ Is2 = beam_jump:remove_unused_labels(Is1),
+
+ %% Some optimization passes can't handle consecutive labels.
+ %% Coalesce multiple consecutive labels.
+ Is = coalesce_consecutive_labels(Is2, [], []),
+
+ {function,Name,Arity,CLabel,Is}
catch
Class:Error:Stack ->
io:fwrite("Function: ~w/~w\n", [Name,Arity]),
erlang:raise(Class, Error, Stack)
end.
+rename_instrs([{test,is_eq_exact,_,[Dst,Src]}=Test,
+ {move,Src,Dst}|Is]) ->
+ %% The move instruction is not needed.
+ rename_instrs([Test|Is]);
+rename_instrs([{test,is_eq_exact,_,[Same,Same]}|Is]) ->
+ %% Same literal or same register. Will always succeed.
+ rename_instrs(Is);
rename_instrs([{apply_last,A,N}|Is]) ->
[{apply,A},{deallocate,N},return|rename_instrs(Is)];
rename_instrs([{call_last,A,F,N}|Is]) ->
@@ -113,6 +125,8 @@ rename_instr({put_map_exact,Fail,S,D,R,L}) ->
{put_map,Fail,exact,S,D,R,L};
rename_instr({test,has_map_fields,Fail,Src,{list,List}}) ->
{test,has_map_fields,Fail,[Src|List]};
+rename_instr({test,is_nil,Fail,[Src]}) ->
+ {test,is_eq_exact,Fail,[Src,nil]};
rename_instr({select_val=I,Reg,Fail,{list,List}}) ->
{select,I,Reg,Fail,List};
rename_instr({select_tuple_arity=I,Reg,Fail,{list,List}}) ->
@@ -120,3 +134,11 @@ rename_instr({select_tuple_arity=I,Reg,Fail,{list,List}}) ->
rename_instr(send) ->
{call_ext,2,send};
rename_instr(I) -> I.
+
+coalesce_consecutive_labels([{label,L}=Lbl,{label,Alias}|Is], Replace, Acc) ->
+ coalesce_consecutive_labels([Lbl|Is], [{Alias,L}|Replace], Acc);
+coalesce_consecutive_labels([I|Is], Replace, Acc) ->
+ coalesce_consecutive_labels(Is, Replace, [I|Acc]);
+coalesce_consecutive_labels([], Replace, Acc) ->
+ D = maps:from_list(Replace),
+ beam_utils:replace_labels(Acc, [], D, fun(L) -> L end).
diff --git a/lib/compiler/src/beam_block.erl b/lib/compiler/src/beam_block.erl
index fe43163455..d28c0fd9e4 100644
--- a/lib/compiler/src/beam_block.erl
+++ b/lib/compiler/src/beam_block.erl
@@ -17,39 +17,24 @@
%%
%% %CopyrightEnd%
%%
-%% Purpose : Partitions assembly instructions into basic blocks and
-%% optimizes them.
+%% Purpose: Partition BEAM instructions into basic blocks.
-module(beam_block).
-export([module/2]).
--import(lists, [reverse/1,reverse/2,member/2]).
+-import(lists, [reverse/1,splitwith/2]).
-spec module(beam_utils:module_code(), [compile:option()]) ->
{'ok',beam_utils:module_code()}.
-module({Mod,Exp,Attr,Fs0,Lc}, Opts) ->
- Blockify = not member(no_blockify, Opts),
- Fs = [function(F, Blockify) || F <- Fs0],
+module({Mod,Exp,Attr,Fs0,Lc}, _Opts) ->
+ Fs = [function(F) || F <- Fs0],
{ok,{Mod,Exp,Attr,Fs,Lc}}.
-function({function,Name,Arity,CLabel,Is0}, Blockify) ->
+function({function,Name,Arity,CLabel,Is0}) ->
try
- %% Collect basic blocks and optimize them.
- Is1 = case Blockify of
- false -> Is0;
- true -> blockify(Is0)
- end,
- Is2 = embed_lines(Is1),
- Is3 = local_cse(Is2),
- Is4 = beam_utils:anno_defs(Is3),
- Is5 = move_allocates(Is4),
- Is6 = beam_utils:live_opt(Is5),
- Is7 = opt_blocks(Is6),
- Is8 = beam_utils:delete_annos(Is7),
- Is = opt_allocs(Is8),
-
- %% Done.
+ Is1 = blockify(Is0),
+ Is = embed_lines(Is1),
{function,Name,Arity,CLabel,Is}
catch
Class:Error:Stack ->
@@ -80,12 +65,10 @@ collect_block(Is) ->
collect_block(Is, []).
collect_block([{allocate,N,R}|Is0], Acc) ->
- {Inits,Is} = lists:splitwith(fun ({init,{y,_}}) -> true;
- (_) -> false
- end, Is0),
+ {Inits,Is} = splitwith(fun ({init,{y,_}}) -> true;
+ (_) -> false
+ end, Is0),
collect_block(Is, [{set,[],[],{alloc,R,{nozero,N,0,Inits}}}|Acc]);
-collect_block([{allocate_zero,Ns,R},{test_heap,Nh,R}|Is], Acc) ->
- collect_block(Is, [{set,[],[],{alloc,R,{zero,Ns,Nh,[]}}}|Acc]);
collect_block([I|Is]=Is0, Acc) ->
case collect(I) of
error -> {reverse(Acc),Is0};
@@ -100,23 +83,20 @@ collect({allocate_heap,Ns,Nh,R}) -> {set,[],[],{alloc,R,{nozero,Ns,Nh,[]}}};
collect({allocate_heap_zero,Ns,Nh,R}) -> {set,[],[],{alloc,R,{zero,Ns,Nh,[]}}};
collect({init,D}) -> {set,[D],[],init};
collect({test_heap,N,R}) -> {set,[],[],{alloc,R,{nozero,nostack,N,[]}}};
-collect({bif,N,F,As,D}) -> {set,[D],As,{bif,N,F}};
-collect({gc_bif,N,F,R,As,D}) -> {set,[D],As,{alloc,R,{gc_bif,N,F}}};
+collect({bif,N,{f,0},As,D}) -> {set,[D],As,{bif,N,{f,0}}};
+collect({gc_bif,N,{f,0},R,As,D}) -> {set,[D],As,{alloc,R,{gc_bif,N,{f,0}}}};
collect({move,S,D}) -> {set,[D],[S],move};
collect({put_list,S1,S2,D}) -> {set,[D],[S1,S2],put_list};
collect({put_tuple,A,D}) -> {set,[D],[],{put_tuple,A}};
collect({put,S}) -> {set,[],[S],put};
+collect({put_tuple2,D,{list,Els}}) -> {set,[D],Els,put_tuple2};
collect({get_tuple_element,S,I,D}) -> {set,[D],[S],{get_tuple_element,I}};
collect({set_tuple_element,S,D,I}) -> {set,[],[S,D],{set_tuple_element,I}};
collect({get_hd,S,D}) -> {set,[D],[S],get_hd};
collect({get_tl,S,D}) -> {set,[D],[S],get_tl};
collect(remove_message) -> {set,[],[],remove_message};
-collect({put_map,F,Op,S,D,R,{list,Puts}}) ->
- {set,[D],[S|Puts],{alloc,R,{put_map,Op,F}}};
-collect({'catch'=Op,R,L}) ->
- {set,[R],[],{try_catch,Op,L}};
-collect({'try'=Op,R,L}) ->
- {set,[R],[],{try_catch,Op,L}};
+collect({put_map,{f,0},Op,S,D,R,{list,Puts}}) ->
+ {set,[D],[S|Puts],{alloc,R,{put_map,Op,{f,0}}}};
collect(fclearerror) -> {set,[],[],fclearerror};
collect({fcheckerror,{f,0}}) -> {set,[],[],fcheckerror};
collect({fmove,S,D}) -> {set,[D],[S],fmove};
@@ -137,557 +117,6 @@ embed_lines([{block,B2},{line,_}=Line,{block,B1}|T], Acc) ->
embed_lines([{block,B1},{line,_}=Line|T], Acc) ->
B = {block,[{set,[],[],Line}|B1]},
embed_lines([B|T], Acc);
-embed_lines([{block,B2},{block,B1}|T], Acc) ->
- %% This can only happen when beam_block is run for
- %% the second time.
- B = {block,B1++B2},
- embed_lines([B|T], Acc);
embed_lines([I|Is], Acc) ->
embed_lines(Is, [I|Acc]);
embed_lines([], Acc) -> Acc.
-
-opt_blocks([{block,Bl0}|Is]) ->
- %% The live annotation at the beginning is not useful.
- [{'%anno',_}|Bl] = Bl0,
- [{block,opt_block(Bl)}|opt_blocks(Is)];
-opt_blocks([I|Is]) ->
- [I|opt_blocks(Is)];
-opt_blocks([]) -> [].
-
-opt_block(Is0) ->
- find_fixpoint(fun(Is) ->
- opt_tuple_element(opt(Is))
- end, Is0).
-
-find_fixpoint(OptFun, Is0) ->
- case OptFun(Is0) of
- Is0 -> Is0;
- Is1 -> find_fixpoint(OptFun, Is1)
- end.
-
-%% move_allocates(Is0) -> Is
-%% Move allocate instructions upwards in the instruction stream
-%% (within the same block), in the hope of getting more possibilities
-%% for optimizing away moves later.
-%%
-%% For example, we can transform the following instructions:
-%%
-%% get_tuple_element x(1) Element => x(2)
-%% allocate_zero StackSize 3 %% x(0), x(1), x(2) are live
-%%
-%% to the following instructions:
-%%
-%% allocate_zero StackSize 2 %% x(0) and x(1) are live
-%% get_tuple_element x(1) Element => x(2)
-%%
-%% NOTE: Since the beam_reorder pass has been run, it is no longer
-%% safe to assume that if x(N) is initialized, then all lower-numbered
-%% x registers are also initialized.
-%%
-%% For example, we must be careful when transforming the following
-%% instructions:
-%%
-%% get_tuple_element x(0) Element => x(1)
-%% allocate_zero StackSize 3 %x(0), x(1), x(2) are live
-%%
-%% to the following instructions:
-%%
-%% allocate_zero StackSize 3
-%% get_tuple_element x(0) Element => x(1)
-%%
-%% The transformation is safe if and only if x(1) has been
-%% initialized previously. We will use the annotations added by
-%% beam_utils:anno_defs/1 to determine whether x(a) has been
-%% initialized.
-
-move_allocates([{block,Bl0}|Is]) ->
- Bl = move_allocates_1(reverse(Bl0), []),
- [{block,Bl}|move_allocates(Is)];
-move_allocates([I|Is]) ->
- [I|move_allocates(Is)];
-move_allocates([]) -> [].
-
-move_allocates_1([{'%anno',_}|Is], Acc) ->
- move_allocates_1(Is, Acc);
-move_allocates_1([I|Is], [{set,[],[],{alloc,Live0,Info0}}|Acc]=Acc0) ->
- case alloc_may_pass(I) of
- false ->
- move_allocates_1(Is, [I|Acc0]);
- true ->
- case alloc_live_regs(I, Is, Live0) of
- not_possible ->
- move_allocates_1(Is, [I|Acc0]);
- Live when is_integer(Live) ->
- Info = safe_info(Info0),
- A = {set,[],[],{alloc,Live,Info}},
- move_allocates_1(Is, [A,I|Acc])
- end
- end;
-move_allocates_1([I|Is], Acc) ->
- move_allocates_1(Is, [I|Acc]);
-move_allocates_1([], Acc) -> Acc.
-
-alloc_may_pass({set,_,[{fr,_}],fmove}) -> false;
-alloc_may_pass({set,_,_,{alloc,_,_}}) -> false;
-alloc_may_pass({set,_,_,{set_tuple_element,_}}) -> false;
-alloc_may_pass({set,_,_,put_list}) -> false;
-alloc_may_pass({set,_,_,put}) -> false;
-alloc_may_pass({set,_,_,_}) -> true.
-
-safe_info({nozero,Stack,Heap,_}) ->
- %% nozero is not safe if the allocation instruction is moved
- %% upwards past an instruction that may throw an exception
- %% (such as element/2).
- {zero,Stack,Heap,[]};
-safe_info(Info) -> Info.
-
-%% opt([Instruction]) -> [Instruction]
-%% Optimize the instruction stream inside a basic block.
-
-opt([{set,[X],[X],move}|Is]) -> opt(Is);
-opt([{set,[Dst],_,move},{set,[Dst],[Src],move}=I|Is]) when Dst =/= Src ->
- opt([I|Is]);
-opt([{set,[{x,0}],[S1],move}=I1,{set,[D2],[{x,0}],move}|Is]) ->
- opt([I1,{set,[D2],[S1],move}|Is]);
-opt([{set,[{x,0}],[S1],move}=I1,{set,[D2],[S2],move}|Is0]) when S1 =/= D2 ->
- %% Place move S x0 at the end of move sequences so that
- %% loader can merge with the following instruction
- {Ds,Is} = opt_moves([D2], Is0),
- [{set,Ds,[S2],move}|opt([I1|Is])];
-opt([{set,_,_,{line,_}}=Line1,
- {set,[D1],[{integer,Idx1},Reg],{bif,element,{f,0}}}=I1,
- {set,_,_,{line,_}}=Line2,
- {set,[D2],[{integer,Idx2},Reg],{bif,element,{f,0}}}=I2|Is])
- when Idx1 < Idx2, D1 =/= D2, D1 =/= Reg, D2 =/= Reg ->
- opt([Line2,I2,Line1,I1|Is]);
-opt([{set,[D1],[{integer,Idx1},Reg],{bif,element,{f,L}}}=I1,
- {set,[D2],[{integer,Idx2},Reg],{bif,element,{f,L}}}=I2|Is])
- when Idx1 < Idx2, D1 =/= D2, D1 =/= Reg, D2 =/= Reg ->
- opt([I2,I1|Is]);
-opt([{set,Hd0,Cons,get_hd}=GetHd,
- {set,Tl0,Cons,get_tl}=GetTl|Is0]) ->
- case {opt_moves(Hd0, [GetTl|Is0]),opt_moves(Tl0, [GetHd|Is0])} of
- {{Hd0,Is},{Tl0,_}} ->
- [GetHd|opt(Is)];
- {{Hd,Is},{Tl0,_}} ->
- [{set,Hd,Cons,get_hd}|opt(Is)];
- {{_,_},{Tl,Is}} ->
- [{set,Tl,Cons,get_tl}|opt(Is)]
- end;
-opt([{set,Ds0,Ss,Op}|Is0]) ->
- {Ds,Is} = opt_moves(Ds0, Is0),
- [{set,Ds,Ss,Op}|opt(Is)];
-opt([{'%anno',_}=I|Is]) ->
- [I|opt(Is)];
-opt([]) -> [].
-
-%% opt_moves([Dest], [Instruction]) -> {[Dest],[Instruction]}
-%% For each Dest, does the optimization described in opt_move/2.
-
-opt_moves([], Is0) -> {[],Is0};
-opt_moves([D0]=Ds, Is0) ->
- case opt_move(D0, Is0) of
- not_possible -> {Ds,Is0};
- {D1,Is} -> {[D1],Is}
- end.
-
-%% opt_move(Dest, [Instruction]) -> {UpdatedDest,[Instruction]} | not_possible
-%% If there is a {move,Dest,FinalDest} instruction
-%% in the instruction stream, remove the move instruction
-%% and let FinalDest be the destination.
-
-opt_move(Dest, Is) ->
- opt_move_1(Dest, Is, []).
-
-opt_move_1(R, [{set,[D],[R],move}|Is0], Acc) ->
- %% Provided that the source register is killed by instructions
- %% that follow, the optimization is safe.
- case eliminate_use_of_from_reg(Is0, R, D) of
- {yes,Is} -> opt_move_rev(D, Acc, Is);
- no -> not_possible
- end;
-opt_move_1(_R, [{set,_,_,{alloc,_,_}}|_], _) ->
- %% The optimization is either not possible or not safe.
- %%
- %% If R is an X register killed by allocation, the optimization is
- %% not safe. On the other hand, if the X register is killed, there
- %% will not follow a 'move' instruction with this X register as
- %% the source.
- %%
- %% If R is a Y register, the optimization is still not safe
- %% because the new target register is an X register that cannot
- %% safely pass the alloc instruction.
- not_possible;
-opt_move_1(R, [{set,_,_,_}=I|Is], Acc) ->
- %% If the source register is either killed or used by this
- %% instruction, the optimimization is not possible.
- case is_killed_or_used(R, I) of
- true -> not_possible;
- false -> opt_move_1(R, Is, [I|Acc])
- end;
-opt_move_1(_, _, _) ->
- not_possible.
-
-%% opt_tuple_element([Instruction]) -> [Instruction]
-%% If possible, move get_tuple_element instructions forward
-%% in the instruction stream to a move instruction, eliminating
-%% the move instruction. Example:
-%%
-%% get_tuple_element Tuple Pos Dst1
-%% ...
-%% move Dst1 Dst2
-%%
-%% This code may be possible to rewrite to:
-%%
-%% %%(Moved get_tuple_element instruction)
-%% ...
-%% get_tuple_element Tuple Pos Dst2
-%%
-
-opt_tuple_element([{set,[D],[S],{get_tuple_element,_}}=I|Is0]) ->
- case opt_tuple_element_1(Is0, I, {S,D}, []) of
- no ->
- [I|opt_tuple_element(Is0)];
- {yes,Is} ->
- opt_tuple_element(Is)
- end;
-opt_tuple_element([I|Is]) ->
- [I|opt_tuple_element(Is)];
-opt_tuple_element([]) -> [].
-
-opt_tuple_element_1([{set,_,_,{alloc,_,_}}|_], _, _, _) ->
- no;
-opt_tuple_element_1([{set,_,_,{try_catch,_,_}}|_], _, _, _) ->
- no;
-opt_tuple_element_1([{set,[D],[S],move}|Is0], I0, {_,S}, Acc) ->
- case eliminate_use_of_from_reg(Is0, S, D) of
- no ->
- no;
- {yes,Is1} ->
- {set,[S],Ss,Op} = I0,
- I = {set,[D],Ss,Op},
- case opt_move_rev(S, Acc, [I|Is1]) of
- not_possible ->
- %% Not safe because the move of the
- %% get_tuple_element instruction would cause the
- %% result of a previous instruction to be ignored.
- no;
- {_,Is} ->
- {yes,Is}
- end
- end;
-opt_tuple_element_1([{set,Ds,Ss,_}=I|Is], MovedI, {S,D}=Regs, Acc) ->
- case member(S, Ds) orelse member(D, Ss) of
- true ->
- no;
- false ->
- opt_tuple_element_1(Is, MovedI, Regs, [I|Acc])
- end;
-opt_tuple_element_1(_, _, _, _) -> no.
-
-%% Reverse the instructions, while checking that there are no
-%% instructions that would interfere with using the new destination
-%% register (D).
-
-opt_move_rev(D, [I|Is], Acc) ->
- case is_killed_or_used(D, I) of
- true -> not_possible;
- false -> opt_move_rev(D, Is, [I|Acc])
- end;
-opt_move_rev(D, [], Acc) -> {D,Acc}.
-
-%% is_killed_or_used(Register, {set,_,_,_}) -> bool()
-%% Test whether the register is used by the instruction.
-
-is_killed_or_used(R, {set,Ss,Ds,_}) ->
- member(R, Ds) orelse member(R, Ss).
-
-%% eliminate_use_of_from_reg([Instruction], FromRegister, ToRegister, Acc) ->
-%% {yes,Is} | no
-%% Eliminate any use of FromRegister in the instruction sequence
-%% by replacing uses of FromRegister with ToRegister. If FromRegister
-%% is referenced by an allocation instruction, return 'no' to indicate
-%% that FromRegister is still used and that the optimization is not
-%% possible.
-
-eliminate_use_of_from_reg(Is, From, To) ->
- try
- eliminate_use_of_from_reg(Is, From, To, [])
- catch
- throw:not_possible ->
- no
- end.
-
-eliminate_use_of_from_reg([{set,_,_,{alloc,Live,_}}|_]=Is0, {x,X}, _, Acc) ->
- if
- X < Live ->
- no;
- true ->
- {yes,reverse(Acc, Is0)}
- end;
-eliminate_use_of_from_reg([{set,Ds,Ss0,Op}=I0|Is], From, To, Acc) ->
- ensure_safe_tuple(I0, To),
- I = case member(From, Ss0) of
- true ->
- Ss = [case S of
- From -> To;
- _ -> S
- end || S <- Ss0],
- {set,Ds,Ss,Op};
- false ->
- I0
- end,
- case member(From, Ds) of
- true ->
- {yes,reverse(Acc, [I|Is])};
- false ->
- case member(To, Ds) of
- true ->
- case beam_utils:is_killed_block(From, Is) of
- true ->
- {yes,reverse(Acc, [I|Is])};
- false ->
- no
- end;
- false ->
- eliminate_use_of_from_reg(Is, From, To, [I|Acc])
- end
- end;
-eliminate_use_of_from_reg([I]=Is, From, _To, Acc) ->
- case beam_utils:is_killed_block(From, [I]) of
- true ->
- {yes,reverse(Acc, Is)};
- false ->
- no
- end.
-
-ensure_safe_tuple({set,[To],[],{put_tuple,_}}, To) ->
- throw(not_possible);
-ensure_safe_tuple(_, _) -> ok.
-
-%% opt_allocs(Instructions) -> Instructions. Optimize allocate
-%% instructions inside blocks. If safe, replace an allocate_zero
-%% instruction with the slightly cheaper allocate instruction.
-
-opt_allocs(Is) ->
- D = beam_utils:index_labels(Is),
- opt_allocs_1(Is, D).
-
-opt_allocs_1([{block,Bl0}|Is], D) ->
- Bl = opt_alloc(Bl0, {D,Is}),
- [{block,Bl}|opt_allocs_1(Is, D)];
-opt_allocs_1([I|Is], D) ->
- [I|opt_allocs_1(Is, D)];
-opt_allocs_1([], _) -> [].
-
-%% opt_alloc(Instructions) -> Instructions'
-%% Optimises all allocate instructions.
-
-opt_alloc([{set,[],[],{alloc,Live0,Info0}},
- {set,[],[],{alloc,Live,Info}}|Is], D) ->
- Live = Live0, %Assertion.
- Alloc = combine_alloc(Info0, Info),
- I = {set,[],[],{alloc,Live,Alloc}},
- opt_alloc([I|Is], D);
-opt_alloc([{set,[],[],{alloc,R,{_,Ns,Nh,[]}}}|Is], D) ->
- [{set,[],[],opt_alloc(Is, D, Ns, Nh, R)}|Is];
-opt_alloc([I|Is], D) -> [I|opt_alloc(Is, D)];
-opt_alloc([], _) -> [].
-
-combine_alloc({_,Ns,Nh1,Init}, {_,nostack,Nh2,[]}) ->
- {zero,Ns,beam_utils:combine_heap_needs(Nh1, Nh2),Init}.
-
-%% opt_alloc(Instructions, FrameSize, HeapNeed, LivingRegs) -> [Instr]
-%% Generates the optimal sequence of instructions for
-%% allocating and initalizing the stack frame and needed heap.
-
-opt_alloc(_Is, _D, nostack, Nh, LivingRegs) ->
- {alloc,LivingRegs,{nozero,nostack,Nh,[]}};
-opt_alloc(Bl, {D,OuterIs}, Ns, Nh, LivingRegs) ->
- Is = [{block,Bl}|OuterIs],
- InitRegs = init_yregs(Ns, Is, D),
- case count_ones(InitRegs) of
- N when N*2 > Ns ->
- {alloc,LivingRegs,{nozero,Ns,Nh,gen_init(Ns, InitRegs)}};
- _ ->
- {alloc,LivingRegs,{zero,Ns,Nh,[]}}
- end.
-
-gen_init(Fs, Regs) -> gen_init(Fs, Regs, 0, []).
-
-gen_init(SameFs, _Regs, SameFs, Acc) -> reverse(Acc);
-gen_init(Fs, Regs, Y, Acc) when Regs band 1 =:= 0 ->
- gen_init(Fs, Regs bsr 1, Y+1, [{init,{y,Y}}|Acc]);
-gen_init(Fs, Regs, Y, Acc) ->
- gen_init(Fs, Regs bsr 1, Y+1, Acc).
-
-init_yregs(Y, Is, D) when Y >= 0 ->
- case beam_utils:is_killed({y,Y}, Is, D) of
- true ->
- (1 bsl Y) bor init_yregs(Y-1, Is, D);
- false ->
- init_yregs(Y-1, Is, D)
- end;
-init_yregs(_, _, _) -> 0.
-
-count_ones(Bits) -> count_ones(Bits, 0).
-count_ones(0, Acc) -> Acc;
-count_ones(Bits, Acc) ->
- count_ones(Bits bsr 1, Acc + (Bits band 1)).
-
-%% Calculate the new number of live registers when we move an allocate
-%% instruction upwards, passing a 'set' instruction.
-
-alloc_live_regs({set,Ds,Ss,_}, Is, Regs0) ->
- Rset = x_live(Ss, x_dead(Ds, (1 bsl Regs0)-1)),
- Live = live_regs(0, Rset),
- case ensure_contiguous(Rset, Live) of
- not_possible ->
- %% Liveness information (looking forward in the
- %% instruction stream) can't prove that moving this
- %% allocation instruction is safe. Now use the annotation
- %% of defined registers at the beginning of the current
- %% block to see whether moving would be safe.
- Def0 = defined_regs(Is, 0),
- Def = Def0 band ((1 bsl Live) - 1),
- ensure_contiguous(Rset bor Def, Live);
- Live ->
- %% Safe based on liveness information.
- Live
- end.
-
-live_regs(N, 0) ->
- N;
-live_regs(N, Regs) ->
- live_regs(N+1, Regs bsr 1).
-
-ensure_contiguous(Regs, Live) ->
- case (1 bsl Live) - 1 of
- Regs -> Live;
- _ -> not_possible
- end.
-
-x_dead([{x,N}|Rs], Regs) -> x_dead(Rs, Regs band (bnot (1 bsl N)));
-x_dead([_|Rs], Regs) -> x_dead(Rs, Regs);
-x_dead([], Regs) -> Regs.
-
-x_live([{x,N}|Rs], Regs) -> x_live(Rs, Regs bor (1 bsl N));
-x_live([_|Rs], Regs) -> x_live(Rs, Regs);
-x_live([], Regs) -> Regs.
-
-%% defined_regs(ReversedInstructions) -> RegBitmap.
-%% Given a reversed instruction stream, determine the
-%% the registers that are defined.
-
-defined_regs([{'%anno',{def,Def}}|_], Regs) ->
- Def bor Regs;
-defined_regs([{set,Ds,_,{alloc,Live,_}}|_], Regs) ->
- x_live(Ds, Regs bor ((1 bsl Live) - 1));
-defined_regs([{set,Ds,_,_}|Is], Regs) ->
- defined_regs(Is, x_live(Ds, Regs)).
-
-%%%
-%%% Do local common sub expression elimination (CSE) in each block.
-%%%
-
-local_cse([{block,Bl0}|Is]) ->
- Bl = cse_block(Bl0, orddict:new(), []),
- [{block,Bl}|local_cse(Is)];
-local_cse([I|Is]) ->
- [I|local_cse(Is)];
-local_cse([]) -> [].
-
-cse_block([I|Is], Es0, Acc0) ->
- Es1 = cse_clear(I, Es0),
- case cse_expr(I) of
- none ->
- %% Instruction is not suitable for CSE.
- cse_block(Is, Es1, [I|Acc0]);
- {ok,D,Expr} ->
- %% Suitable instruction. First update the dictionary of
- %% suitable expressions for the next iteration.
- Es = cse_add(D, Expr, Es1),
-
- %% Search for a previous identical expression.
- case cse_find(Expr, Es0) of
- error ->
- %% Nothing found
- cse_block(Is, Es, [I|Acc0]);
- Src ->
- %% Use the previously calculated result.
- %% Also eliminate any line instruction.
- Move = {set,[D],[Src],move},
- case Acc0 of
- [{set,_,_,{line,_}}|Acc] ->
- cse_block(Is, Es, [Move|Acc]);
- [_|_] ->
- cse_block(Is, Es, [Move|Acc0])
- end
- end
- end;
-cse_block([], _, Acc) ->
- reverse(Acc).
-
-%% cse_find(Expr, Expressions) -> error | Register.
-%% Find a previously evaluated expression whose result can be reused,
-%% or return 'error' if no such expression is found.
-
-cse_find(Expr, Es) ->
- case orddict:find(Expr, Es) of
- {ok,{Src,_}} -> Src;
- error -> error
- end.
-
-cse_expr({set,[D],Ss,{bif,N,_}}) ->
- case D of
- {fr,_} ->
- %% There are too many things that can go wrong.
- none;
- _ ->
- {ok,D,{{bif,N},Ss}}
- end;
-cse_expr({set,[D],Ss,{alloc,_,{gc_bif,N,_}}}) ->
- {ok,D,{{gc_bif,N},Ss}};
-cse_expr({set,[D],Ss,put_list}) ->
- {ok,D,{put_list,Ss}};
-cse_expr(_) -> none.
-
-%% cse_clear(Instr, Expressions0) -> Expressions.
-%% Remove all previous expressions that will become
-%% invalid when this instruction is executed. Basically,
-%% an expression is no longer safe to reuse when the
-%% register it has been stored to has been modified, killed,
-%% or if any of the source operands have changed.
-
-cse_clear({set,Ds,_,{alloc,Live,_}}, Es) ->
- cse_clear_1(Es, Live, Ds);
-cse_clear({set,Ds,_,_}, Es) ->
- cse_clear_1(Es, all, Ds).
-
-cse_clear_1(Es, Live, Ds0) ->
- Ds = ordsets:from_list(Ds0),
- [E || E <- Es, cse_is_safe(E, Live, Ds)].
-
-cse_is_safe({_,{Dst,Interfering}}, Live, Ds) ->
- ordsets:is_disjoint(Interfering, Ds) andalso
- case Dst of
- {x,X} ->
- X < Live;
- _ ->
- true
- end.
-
-%% cse_add(Dest, Expr, Expressions0) -> Expressions.
-%% Provided that it is safe, add a new expression to the dictionary
-%% of already evaluated expressions.
-
-cse_add(D, {_,Ss}=Expr, Es) ->
- case member(D, Ss) of
- false ->
- Interfering = ordsets:from_list([D|Ss]),
- orddict:store(Expr, {D,Interfering}, Es);
- true ->
- %% Unsafe because the instruction overwrites one of
- %% source operands.
- Es
- end.
diff --git a/lib/compiler/src/beam_bs.erl b/lib/compiler/src/beam_bs.erl
index 5f1b9ed488..15d8d687fc 100644
--- a/lib/compiler/src/beam_bs.erl
+++ b/lib/compiler/src/beam_bs.erl
@@ -17,26 +17,24 @@
%%
%% %CopyrightEnd%
%%
-%% Purpose : Partitions assembly instructions into basic blocks and
-%% optimizes them.
+%% Purpose: Peephole optimization of binary syntax instructions.
-module(beam_bs).
-export([module/2]).
--import(lists, [mapfoldl/3,reverse/1]).
+-import(lists, [reverse/1]).
-spec module(beam_utils:module_code(), [compile:option()]) ->
{'ok',beam_utils:module_code()}.
-module({Mod,Exp,Attr,Fs0,Lc0}, _Opt) ->
- {Fs,Lc} = mapfoldl(fun function/2, Lc0, Fs0),
+module({Mod,Exp,Attr,Fs0,Lc}, _Opt) ->
+ Fs = [function(F) || F <- Fs0],
{ok,{Mod,Exp,Attr,Fs,Lc}}.
-function({function,Name,Arity,CLabel,Is0}, Lc0) ->
+function({function,Name,Arity,CLabel,Is0}) ->
try
- Is1 = bs_put_opt(Is0),
- {Is,Lc} = bsm_opt(Is1, Lc0),
- {{function,Name,Arity,CLabel,Is},Lc}
+ Is = bs_opt(Is0),
+ {function,Name,Arity,CLabel,Is}
catch
Class:Error:Stack ->
io:fwrite("Function: ~w/~w\n", [Name,Arity]),
@@ -44,16 +42,25 @@ function({function,Name,Arity,CLabel,Is0}, Lc0) ->
end.
%%%
-%%% Evaluation of constant bit fields.
+%%% Evaluate construction of constant bit fields.
+%%% Combine bs_skip_bits2 and bs_test_tail2 instructions.
%%%
-bs_put_opt([{bs_put,_,_,_}=I|Is0]) ->
+bs_opt([{bs_put,_,_,_}=I|Is0]) ->
{BsPuts0,Is} = collect_bs_puts(Is0, [I]),
BsPuts = opt_bs_puts(BsPuts0),
- BsPuts ++ bs_put_opt(Is);
-bs_put_opt([I|Is]) ->
- [I|bs_put_opt(Is)];
-bs_put_opt([]) -> [].
+ BsPuts ++ bs_opt(Is);
+bs_opt([{test,bs_skip_bits2,F,[Ctx,{integer,I},Unit,_Flags]},
+ {test,bs_test_tail2,F,[Ctx,Bits]}|Is]) ->
+ [{test,bs_test_tail2,F,[Ctx,Bits+I*Unit]}|bs_opt(Is)];
+bs_opt([{test,bs_skip_bits2,F,[Ctx,{integer,I1},Unit1,Flags]},
+ {test,bs_skip_bits2,F,[Ctx,{integer,I2},Unit2,_]}|Is]) ->
+ I = {test,bs_skip_bits2,F,
+ [Ctx,{integer,I1*Unit1+I2*Unit2},1,Flags]},
+ bs_opt([I|Is]);
+bs_opt([I|Is]) ->
+ [I|bs_opt(Is)];
+bs_opt([]) -> [].
collect_bs_puts([{bs_put,_,_,_}=I|Is], Acc) ->
collect_bs_puts(Is, [I|Acc]);
@@ -174,107 +181,3 @@ bs_split_int_1(N, ByteSz, Sz, Fail, Acc) when Sz > 0 ->
[{integer,ByteSz},{integer,N band Mask}]},
bs_split_int_1(N bsr ByteSz, 8, Sz-ByteSz, Fail, [I|Acc]);
bs_split_int_1(_, _, _, _, Acc) -> Acc.
-
-%%%
-%%% Optimization of bit syntax matching: get rid
-%%% of redundant bs_restore2/2 instructions across select_val
-%%% instructions, as well as a few other simple peep-hole
-%%% optimizations.
-%%%
-
-bsm_opt(Is0, Lc0) ->
- {Is1,D0,Lc} = bsm_scan(Is0, [], Lc0, []),
- Is2 = case D0 of
- [] ->
- %% No bit syntax matching in this function.
- Is1;
- [_|_] ->
- %% Optimize the bit syntax matching.
- D = gb_trees:from_orddict(orddict:from_list(D0)),
- bsm_reroute(Is1, D, none, [])
- end,
- Is = beam_clean:bs_clean_saves(Is2),
- {bsm_opt_2(Is, []),Lc}.
-
-bsm_scan([{label,L}=Lbl,{bs_restore2,_,Save}=R|Is], D0, Lc, Acc0) ->
- D = [{{L,Save},Lc}|D0],
- Acc = [{label,Lc},R,Lbl|Acc0],
- bsm_scan(Is, D, Lc+1, Acc);
-bsm_scan([I|Is], D, Lc, Acc) ->
- bsm_scan(Is, D, Lc, [I|Acc]);
-bsm_scan([], D, Lc, Acc) ->
- {reverse(Acc),D,Lc}.
-
-bsm_reroute([{bs_save2,Reg,Save}=I|Is], D, _, Acc) ->
- bsm_reroute(Is, D, {Reg,Save}, [I|Acc]);
-bsm_reroute([{bs_restore2,Reg,Save}=I|Is], D, _, Acc) ->
- bsm_reroute(Is, D, {Reg,Save}, [I|Acc]);
-bsm_reroute([{label,_}=I|Is], D, S, Acc) ->
- bsm_reroute(Is, D, S, [I|Acc]);
-bsm_reroute([{select,select_val,Reg,F0,Lbls0}|Is], D, {_,Save}=S, Acc0) ->
- [F|Lbls] = bsm_subst_labels([F0|Lbls0], Save, D),
- Acc = [{select,select_val,Reg,F,Lbls}|Acc0],
- bsm_reroute(Is, D, S, Acc);
-bsm_reroute([{test,TestOp,F0,TestArgs}=I|Is], D, {_,Save}=S, Acc0) ->
- F = bsm_subst_label(F0, Save, D),
- Acc = [{test,TestOp,F,TestArgs}|Acc0],
- case bsm_not_bs_test(I) of
- true ->
- %% The test instruction will not update the bit offset for
- %% the binary being matched. Therefore the save position
- %% can be kept.
- bsm_reroute(Is, D, S, Acc);
- false ->
- %% The test instruction might update the bit offset. Kill
- %% our remembered Save position.
- bsm_reroute(Is, D, none, Acc)
- end;
-bsm_reroute([{test,TestOp,F0,Live,TestArgs,Dst}|Is], D, {_,Save}, Acc0) ->
- F = bsm_subst_label(F0, Save, D),
- Acc = [{test,TestOp,F,Live,TestArgs,Dst}|Acc0],
- %% The test instruction will update the bit offset. Kill our
- %% remembered Save position.
- bsm_reroute(Is, D, none, Acc);
-bsm_reroute([{block,[{set,[],[],{alloc,_,_}}]}=Bl,
- {bs_context_to_binary,_}=I|Is], D, S, Acc) ->
- %% To help further bit syntax optimizations.
- bsm_reroute([I,Bl|Is], D, S, Acc);
-bsm_reroute([I|Is], D, _, Acc) ->
- bsm_reroute(Is, D, none, [I|Acc]);
-bsm_reroute([], _, _, Acc) -> reverse(Acc).
-
-bsm_opt_2([{test,bs_test_tail2,F,[Ctx,Bits]}|Is],
- [{test,bs_skip_bits2,F,[Ctx,{integer,I},Unit,_Flags]}|Acc]) ->
- bsm_opt_2(Is, [{test,bs_test_tail2,F,[Ctx,Bits+I*Unit]}|Acc]);
-bsm_opt_2([{test,bs_skip_bits2,F,[Ctx,{integer,I1},Unit1,_]}|Is],
- [{test,bs_skip_bits2,F,[Ctx,{integer,I2},Unit2,Flags]}|Acc]) ->
- bsm_opt_2(Is, [{test,bs_skip_bits2,F,
- [Ctx,{integer,I1*Unit1+I2*Unit2},1,Flags]}|Acc]);
-bsm_opt_2([I|Is], Acc) ->
- bsm_opt_2(Is, [I|Acc]);
-bsm_opt_2([], Acc) -> reverse(Acc).
-
-%% bsm_not_bs_test({test,Name,_,Operands}) -> true|false.
-%% Test whether is the test is a "safe", i.e. does not move the
-%% bit offset for a binary.
-%%
-%% 'true' means that the test is safe, 'false' that we don't know or
-%% that the test moves the offset (e.g. bs_get_integer2).
-
-bsm_not_bs_test({test,bs_test_tail2,_,[_,_]}) -> true;
-bsm_not_bs_test(Test) -> beam_utils:is_pure_test(Test).
-
-bsm_subst_labels(Fs, Save, D) ->
- bsm_subst_labels_1(Fs, Save, D, []).
-
-bsm_subst_labels_1([F|Fs], Save, D, Acc) ->
- bsm_subst_labels_1(Fs, Save, D, [bsm_subst_label(F, Save, D)|Acc]);
-bsm_subst_labels_1([], _, _, Acc) ->
- reverse(Acc).
-
-bsm_subst_label({f,Lbl0}=F, Save, D) ->
- case gb_trees:lookup({Lbl0,Save}, D) of
- {value,Lbl} -> {f,Lbl};
- none -> F
- end;
-bsm_subst_label(Other, _, _) -> Other.
diff --git a/lib/compiler/src/beam_clean.erl b/lib/compiler/src/beam_clean.erl
index 207f1c4deb..f5f0ac2218 100644
--- a/lib/compiler/src/beam_clean.erl
+++ b/lib/compiler/src/beam_clean.erl
@@ -22,9 +22,8 @@
-module(beam_clean).
-export([module/2]).
--export([bs_clean_saves/1]).
-export([clean_labels/1]).
--import(lists, [foldl/3,reverse/1]).
+-import(lists, [foldl/3]).
-spec module(beam_utils:module_code(), [compile:option()]) ->
{'ok',beam_utils:module_code()}.
@@ -37,19 +36,9 @@ module({Mod,Exp,Attr,Fs0,_}, Opts) ->
Used = find_all_used(WorkList, All, sets:from_list(WorkList)),
Fs1 = remove_unused(Order, Used, All),
{Fs2,Lc} = clean_labels(Fs1),
- Fs3 = bs_fix(Fs2),
- Fs = maybe_remove_lines(Fs3, Opts),
+ Fs = maybe_remove_lines(Fs2, Opts),
{ok,{Mod,Exp,Attr,Fs,Lc}}.
-%% Remove all bs_save2/2 instructions not referenced by a bs_restore2/2.
-
--spec bs_clean_saves([beam_utils:instruction()]) ->
- [beam_utils:instruction()].
-
-bs_clean_saves(Is) ->
- Needed = bs_restores(Is, []),
- bs_clean_saves_1(Is, gb_sets:from_list(Needed), []).
-
%% Determine the rootset, i.e. exported functions and
%% the on_load function (if any).
@@ -97,12 +86,8 @@ add_to_work_list(F, {Fs,Used}=Sets) ->
%%%
%%% Coalesce adjacent labels. Renumber all labels to eliminate gaps.
-%%% This cleanup will slightly reduce file size and slightly speed up loading.
-%%%
-%%% We also expand is_record/3 to a sequence of instructions. It is done
-%%% here merely because this module will always be called even if optimization
-%%% is turned off. We don't want to do the expansion in beam_asm because we
-%%% want to see the expanded code in a .S file.
+%%% This cleanup will slightly reduce file size and slightly speed up
+%%% loading.
%%%
-type label() :: beam_asm:label().
@@ -127,45 +112,6 @@ function_renumber([{function,Name,Arity,_Entry,Asm0}|Fs], St0, Acc) ->
function_renumber(Fs, St, [{function,Name,Arity,St#st.entry,Asm}|Acc]);
function_renumber([], St, Acc) -> {Acc,St}.
-renumber_labels([{bif,is_record,{f,_},
- [Term,{atom,Tag}=TagAtom,{integer,Arity}],Dst}|Is0], Acc, St) ->
- ContLabel = 900000000+2*St#st.lc,
- FailLabel = ContLabel+1,
- Fail = {f,FailLabel},
- Tmp = Dst,
- Is = case is_record_tuple(Term, Tag, Arity) of
- yes ->
- [{move,{atom,true},Dst}|Is0];
- no ->
- [{move,{atom,false},Dst}|Is0];
- maybe ->
- [{test,is_tuple,Fail,[Term]},
- {test,test_arity,Fail,[Term,Arity]},
- {get_tuple_element,Term,0,Tmp},
- {test,is_eq_exact,Fail,[Tmp,TagAtom]},
- {move,{atom,true},Dst},
- {jump,{f,ContLabel}},
- {label,FailLabel},
- {move,{atom,false},Dst},
- {jump,{f,ContLabel}}, %Improves optimization by beam_dead.
- {label,ContLabel}|Is0]
- end,
- renumber_labels(Is, Acc, St);
-renumber_labels([{test,is_record,{f,_}=Fail,
- [Term,{atom,Tag}=TagAtom,{integer,Arity}]}|Is0], Acc, St) ->
- Tmp = {x,1022},
- Is = case is_record_tuple(Term, Tag, Arity) of
- yes ->
- Is0;
- no ->
- [{jump,Fail}|Is0];
- maybe ->
- [{test,is_tuple,Fail,[Term]},
- {test,test_arity,Fail,[Term,Arity]},
- {get_tuple_element,Term,0,Tmp},
- {test,is_eq_exact,Fail,[Tmp,TagAtom]}|Is0]
- end,
- renumber_labels(Is, Acc, St);
renumber_labels([{label,Old}|Is], [{label,New}|_]=Acc, #st{lmap=D0}=St) ->
D = [{Old,New}|D0],
renumber_labels(Is, Acc, St#st{lmap=D});
@@ -179,12 +125,6 @@ renumber_labels([I|Is], Acc, St0) ->
renumber_labels(Is, [I|Acc], St0);
renumber_labels([], Acc, St) -> {Acc,St}.
-is_record_tuple({x,_}, _, _) -> maybe;
-is_record_tuple({y,_}, _, _) -> maybe;
-is_record_tuple({literal,Tuple}, Tag, Arity)
- when element(1, Tuple) =:= Tag, tuple_size(Tuple) =:= Arity -> yes;
-is_record_tuple(_, _, _) -> no.
-
function_replace([{function,Name,Arity,Entry,Asm0}|Fs], Dict, Acc) ->
Asm = try
Fb = fun(Old) -> throw({error,{undefined_label,Old}}) end,
@@ -199,100 +139,6 @@ function_replace([{function,Name,Arity,Entry,Asm0}|Fs], Dict, Acc) ->
function_replace([], _, Acc) -> Acc.
%%%
-%%% Final fixup of bs_start_match2/5,bs_save2/bs_restore2 instructions for
-%%% new bit syntax matching (introduced in R11B).
-%%%
-%%% Pass 1: Scan the code, looking for bs_restore2/2 instructions.
-%%%
-%%% Pass 2: Update bs_save2/2 and bs_restore/2 instructions. Remove
-%%% any bs_save2/2 instruction whose save position are never referenced
-%%% by any bs_restore2/2 instruction.
-%%%
-%%% Note this module can be invoked several times, so we must be careful
-%%% not to touch instructions that have already been fixed up.
-%%%
-
-bs_fix(Fs) ->
- bs_fix(Fs, []).
-
-bs_fix([{function,Name,Arity,Entry,Asm0}|Fs], Acc) ->
- Asm = bs_function(Asm0),
- bs_fix(Fs, [{function,Name,Arity,Entry,Asm}|Acc]);
-bs_fix([], Acc) -> reverse(Acc).
-
-bs_function(Is) ->
- Dict0 = bs_restores(Is, []),
- S0 = sofs:relation(Dict0, [{context,save_point}]),
- S1 = sofs:relation_to_family(S0),
- S = sofs:to_external(S1),
- Dict = make_save_point_dict(S, []),
- bs_replace(Is, Dict, []).
-
-make_save_point_dict([{Ctx,Pts}|T], Acc0) ->
- Acc = make_save_point_dict_1(Pts, Ctx, 0, Acc0),
- make_save_point_dict(T, Acc);
-make_save_point_dict([], Acc) ->
- gb_trees:from_orddict(ordsets:from_list(Acc)).
-
-make_save_point_dict_1([H|T], Ctx, I, Acc) ->
- make_save_point_dict_1(T, Ctx, I+1, [{{Ctx,H},I}|Acc]);
-make_save_point_dict_1([], Ctx, I, Acc) ->
- [{Ctx,I}|Acc].
-
-%% Pass 1.
-bs_restores([{bs_restore2,_,{Same,Same}}|Is], Dict) ->
- %% This save point is special. No explicit save is needed.
- bs_restores(Is, Dict);
-bs_restores([{bs_restore2,_,{atom,start}}|Is], Dict) ->
- %% This instruction can occur if "compilation"
- %% started from a .S file.
- bs_restores(Is, Dict);
-bs_restores([{bs_restore2,_,{_,_}=SavePoint}|Is], Dict) ->
- bs_restores(Is, [SavePoint|Dict]);
-bs_restores([_|Is], Dict) ->
- bs_restores(Is, Dict);
-bs_restores([], Dict) -> Dict.
-
-%% Pass 2.
-bs_replace([{test,bs_start_match2,F,Live,[Src,{context,Ctx}],CtxR}|T], Dict, Acc) ->
- Slots = case gb_trees:lookup(Ctx, Dict) of
- {value,Slots0} -> Slots0;
- none -> 0
- end,
- I = {test,bs_start_match2,F,Live,[Src,Slots],CtxR},
- bs_replace(T, Dict, [I|Acc]);
-bs_replace([{bs_save2,CtxR,{_,_}=SavePoint}|T], Dict, Acc) ->
- case gb_trees:lookup(SavePoint, Dict) of
- {value,N} ->
- bs_replace(T, Dict, [{bs_save2,CtxR,N}|Acc]);
- none ->
- bs_replace(T, Dict, Acc)
- end;
-bs_replace([{bs_restore2,_,{atom,start}}=I|T], Dict, Acc) ->
- %% This instruction can occur if "compilation"
- %% started from a .S file.
- bs_replace(T, Dict, [I|Acc]);
-bs_replace([{bs_restore2,CtxR,{Same,Same}}|T], Dict, Acc) ->
- %% This save point refers to the point in the binary where the match
- %% started. It has a special name.
- bs_replace(T, Dict, [{bs_restore2,CtxR,{atom,start}}|Acc]);
-bs_replace([{bs_restore2,CtxR,{_,_}=SavePoint}|T], Dict, Acc) ->
- N = gb_trees:get(SavePoint, Dict),
- bs_replace(T, Dict, [{bs_restore2,CtxR,N}|Acc]);
-bs_replace([I|Is], Dict, Acc) ->
- bs_replace(Is, Dict, [I|Acc]);
-bs_replace([], _, Acc) -> reverse(Acc).
-
-bs_clean_saves_1([{bs_save2,_,{_,_}=SavePoint}=I|Is], Needed, Acc) ->
- case gb_sets:is_member(SavePoint, Needed) of
- false -> bs_clean_saves_1(Is, Needed, Acc);
- true -> bs_clean_saves_1(Is, Needed, [I|Acc])
- end;
-bs_clean_saves_1([I|Is], Needed, Acc) ->
- bs_clean_saves_1(Is, Needed, [I|Acc]);
-bs_clean_saves_1([], _, Acc) -> reverse(Acc).
-
-%%%
%%% Remove line instructions if requested.
%%%
diff --git a/lib/compiler/src/beam_dead.erl b/lib/compiler/src/beam_dead.erl
deleted file mode 100644
index efad082152..0000000000
--- a/lib/compiler/src/beam_dead.erl
+++ /dev/null
@@ -1,971 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2002-2018. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
--module(beam_dead).
-
--export([module/2]).
-
-%%% Dead code is code that is executed but has no effect. This
-%%% optimization pass either removes dead code or jumps around it,
-%%% potentially making it unreachable and a target for the
-%%% the beam_jump pass.
-
--import(lists, [mapfoldl/3,reverse/1]).
-
-
--spec module(beam_utils:module_code(), [compile:option()]) ->
- {'ok',beam_utils:module_code()}.
-
-module({Mod,Exp,Attr,Fs0,_}, _Opts) ->
- {Fs1,Lc1} = beam_clean:clean_labels(Fs0),
- {Fs,Lc} = mapfoldl(fun function/2, Lc1, Fs1),
- %%{Fs,Lc} = {Fs1,Lc1},
- {ok,{Mod,Exp,Attr,Fs,Lc}}.
-
-function({function,Name,Arity,CLabel,Is0}, Lc0) ->
- try
- Is1 = beam_jump:remove_unused_labels(Is0),
-
- %% Initialize label information with the code
- %% for the func_info label. Without it, a register
- %% may seem to be live when it is not.
- [{label,L}|FiIs] = Is1,
- D0 = beam_utils:empty_label_index(),
- D = beam_utils:index_label(L, FiIs, D0),
-
- %% Optimize away dead code.
- {Is2,Lc} = forward(Is1, Lc0),
- Is3 = backward(Is2, D),
- Is = move_move_into_block(Is3, []),
- {{function,Name,Arity,CLabel,Is},Lc}
- catch
- Class:Error:Stack ->
- io:fwrite("Function: ~w/~w\n", [Name,Arity]),
- erlang:raise(Class, Error, Stack)
- end.
-
-%% 'move' instructions outside of blocks may thwart the jump optimizer.
-%% Move them back into the block.
-
-move_move_into_block([{block,Bl0},{move,S,D}|Is], Acc) ->
- Bl = Bl0 ++ [{set,[D],[S],move}],
- move_move_into_block([{block,Bl}|Is], Acc);
-move_move_into_block([{move,S,D}|Is], Acc) ->
- Bl = [{set,[D],[S],move}],
- move_move_into_block([{block,Bl}|Is], Acc);
-move_move_into_block([I|Is], Acc) ->
- move_move_into_block(Is, [I|Acc]);
-move_move_into_block([], Acc) -> reverse(Acc).
-
-%%%
-%%% Scan instructions in execution order and remove redundant 'move'
-%%% instructions. 'move' instructions are redundant if we know that
-%%% the register already contains the value being assigned, as in the
-%%% following code:
-%%%
-%%% test is_eq_exact SomeLabel Src Dst
-%%% move Src Dst
-%%%
-%%% or in:
-%%%
-%%% test is_nil SomeLabel Dst
-%%% move nil Dst
-%%%
-%%% or in:
-%%%
-%%% select_val Register FailLabel [... Literal => L1...]
-%%% .
-%%% .
-%%% .
-%%% L1: move Literal Register
-%%%
-%%% Also add extra labels to help the second backward pass.
-%%%
-
-forward(Is, Lc) ->
- forward(Is, #{}, Lc, []).
-
-forward([{move,_,_}=Move|[{label,L}|_]=Is], D, Lc, Acc) ->
- %% move/2 followed by jump/1 is optimized by backward/3.
- forward([Move,{jump,{f,L}}|Is], D, Lc, Acc);
-forward([{bif,_,_,_,_}=Bif|[{label,L}|_]=Is], D, Lc, Acc) ->
- %% bif/4 followed by jump/1 is optimized by backward/3.
- forward([Bif,{jump,{f,L}}|Is], D, Lc, Acc);
-forward([{block,[]}|Is], D, Lc, Acc) ->
- %% Empty blocks can prevent optimizations.
- forward(Is, D, Lc, Acc);
-forward([{select,select_val,Reg,_,List}=I|Is], D0, Lc, Acc) ->
- D = update_value_dict(List, Reg, D0),
- forward(Is, D, Lc, [I|Acc]);
-forward([{label,Lbl}=LblI,{block,[{set,[Dst],[Lit],move}|BlkIs]}=Blk|Is], D, Lc, Acc) ->
- %% Assumption: The target labels in a select_val/3 instruction
- %% cannot be reached in any other way than through the select_val/3
- %% instruction (i.e. there can be no fallthrough to such label and
- %% it cannot be referenced by, for example, a jump/1 instruction).
- Key = {Lbl,Dst},
- Block = case D of
- #{Key := Lit} -> {block,BlkIs}; %Safe to remove move instruction.
- _ -> Blk %Must keep move instruction.
- end,
- forward([Block|Is], D, Lc, [LblI|Acc]);
-forward([{label,Lbl}=LblI|[{move,Lit,Dst}|Is1]=Is0], D, Lc, Acc) ->
- %% Assumption: The target labels in a select_val/3 instruction
- %% cannot be reached in any other way than through the select_val/3
- %% instruction (i.e. there can be no fallthrough to such label and
- %% it cannot be referenced by, for example, a jump/1 instruction).
- Is = case maps:find({Lbl,Dst}, D) of
- {ok,Lit} -> Is1; %Safe to remove move instruction.
- _ -> Is0 %Keep move instruction.
- end,
- forward(Is, D, Lc, [LblI|Acc]);
-forward([{test,is_eq_exact,_,[Same,Same]}|Is], D, Lc, Acc) ->
- forward(Is, D, Lc, Acc);
-forward([{test,is_eq_exact,_,[Dst,Src]}=I,
- {block,[{set,[Dst],[Src],move}|Bl]}|Is], D, Lc, Acc) ->
- forward([I,{block,Bl}|Is], D, Lc, Acc);
-forward([{test,is_nil,_,[Dst]}=I,
- {block,[{set,[Dst],[nil],move}|Bl]}|Is], D, Lc, Acc) ->
- forward([I,{block,Bl}|Is], D, Lc, Acc);
-forward([{test,is_eq_exact,_,[Dst,Src]}=I,{move,Src,Dst}|Is], D, Lc, Acc) ->
- forward([I|Is], D, Lc, Acc);
-forward([{test,is_nil,_,[Dst]}=I,{move,nil,Dst}|Is], D, Lc, Acc) ->
- forward([I|Is], D, Lc, Acc);
-forward([{test,_,_,_}=I|Is]=Is0, D, Lc, Acc) ->
- %% Help the second, backward pass to by inserting labels after
- %% relational operators so that they can be skipped if they are
- %% known to be true.
- case useful_to_insert_label(Is0) of
- false -> forward(Is, D, Lc, [I|Acc]);
- true -> forward(Is, D, Lc+1, [{label,Lc},I|Acc])
- end;
-forward([I|Is], D, Lc, Acc) ->
- forward(Is, D, Lc, [I|Acc]);
-forward([], _, Lc, Acc) -> {Acc,Lc}.
-
-update_value_dict([Lit,{f,Lbl}|T], Reg, D0) ->
- Key = {Lbl,Reg},
- D = case D0 of
- #{Key := inconsistent} -> D0;
- #{Key := _} -> D0#{Key := inconsistent};
- _ -> D0#{Key => Lit}
- end,
- update_value_dict(T, Reg, D);
-update_value_dict([], _, D) -> D.
-
-useful_to_insert_label([_,{label,_}|_]) ->
- false;
-useful_to_insert_label([{test,Op,_,_}|_]) ->
- case Op of
- is_lt -> true;
- is_ge -> true;
- is_eq_exact -> true;
- is_ne_exact -> true;
- _ -> false
- end.
-
-%%%
-%%% Scan instructions in reverse execution order and try to
-%%% shortcut branch instructions.
-%%%
-%%% For example, in this code:
-%%%
-%%% move Literal Register
-%%% jump L1
-%%% .
-%%% .
-%%% .
-%%% L1: test is_{integer,atom} FailLabel Register
-%%% select_val {x,0} FailLabel [... Literal => L2...]
-%%% .
-%%% .
-%%% .
-%%% L2: ...
-%%%
-%%% the 'selectval' instruction will always transfer control to L2,
-%%% so we can just as well jump to L2 directly by rewriting the
-%%% first part of the sequence like this:
-%%%
-%%% move Literal Register
-%%% jump L2
-%%%
-%%% If register Register is killed at label L2, we can remove the
-%%% 'move' instruction, leaving just the 'jump' instruction:
-%%%
-%%% jump L2
-%%%
-%%% These transformations may leave parts of the code unreachable.
-%%% The beam_jump pass will remove the unreachable code.
-
-backward(Is, D) ->
- backward(Is, D, []).
-
-backward([{test,is_eq_exact,Fail,[Dst,{integer,Arity}]}=I|
- [{bif,tuple_size,Fail,[Reg],Dst}|Is]=Is0], D, Acc) ->
- %% Provided that Dst is killed following this sequence,
- %% we can rewrite the instructions like this:
- %%
- %% bif tuple_size Fail Reg Dst ==> is_tuple Fail Reg
- %% is_eq_exact Fail Dst Integer test_arity Fail Reg Integer
- %%
- %% (still two instructions, but they they will be combined to
- %% one by the loader).
- case beam_utils:is_killed(Dst, Acc, D) andalso (Arity bsr 32) =:= 0 of
- false ->
- %% Not safe because the register Dst is not killed
- %% (probably cannot not happen in practice) or the arity
- %% does not fit in 32 bits (the loader will fail to load
- %% the module). We must move the first instruction to the
- %% accumulator to avoid an infinite loop.
- backward(Is0, D, [I|Acc]);
- true ->
- %% Safe.
- backward([{test,test_arity,Fail,[Reg,Arity]},
- {test,is_tuple,Fail,[Reg]}|Is], D, Acc)
- end;
-backward([{label,Lbl}=L|Is], D, Acc) ->
- backward(Is, beam_utils:index_label(Lbl, Acc, D), [L|Acc]);
-backward([{select,select_val,Reg,{f,Fail0},List0}|Is], D, Acc) ->
- List1 = shortcut_select_list(List0, Reg, D, []),
- Fail1 = shortcut_label(Fail0, D),
- Fail = shortcut_bs_test(Fail1, Is, D),
- List = prune_redundant(List1, Fail),
- case List of
- [] ->
- Jump = {jump,{f,Fail}},
- backward([Jump|Is], D, Acc);
- [V,F] ->
- Test = {test,is_eq_exact,{f,Fail},[Reg,V]},
- Jump = {jump,F},
- backward([Jump,Test|Is], D, Acc);
- [{atom,B1},F,{atom,B2},F] when B1 =:= not B2 ->
- Test = {test,is_boolean,{f,Fail},[Reg]},
- Jump = {jump,F},
- backward([Jump,Test|Is], D, Acc);
- [_|_] ->
- Sel = {select,select_val,Reg,{f,Fail},List},
- backward(Is, D, [Sel|Acc])
- end;
-backward([{jump,{f,To0}},{move,Src,Reg}=Move|Is], D, Acc) ->
- To = shortcut_select_label(To0, Reg, Src, D),
- Jump = {jump,{f,To}},
- case is_killed_at(Reg, To, D) of
- false -> backward([Move|Is], D, [Jump|Acc]);
- true -> backward([Jump|Is], D, Acc)
- end;
-backward([{jump,{f,To}}=J|[{bif,Op,{f,BifFail},Ops,Reg}|Is]=Is0], D, Acc) ->
- try replace_comp_op(To, Reg, Op, Ops, D) of
- {Test,Jump} ->
- backward([Jump,Test|Is], D, Acc)
- catch
- throw:not_possible ->
- case To =:= BifFail of
- true ->
- %% The bif instruction is redundant. See the comment
- %% in the next clause for why there is no need to
- %% test for liveness of Reg at label To.
- backward([J|Is], D, Acc);
- false ->
- backward(Is0, D, [J|Acc])
- end
- end;
-backward([{jump,{f,To}}=J|[{gc_bif,_,{f,To},_,_,_Dst}|Is]], D, Acc) ->
- %% The gc_bif instruction is redundant, since either the gc_bif
- %% instruction itself or the jump instruction will transfer control
- %% to label To. Note that a gc_bif instruction does not assign its
- %% destination register if the failure branch is taken; therefore,
- %% the code at label To is not allowed to assume that the destination
- %% register is initialized, and it is therefore no need to test
- %% for liveness of the destination register at label To.
- backward([J|Is], D, Acc);
-backward([{test,bs_start_match2,F,Live,[Src,_]=Args,Ctxt}|Is], D, Acc0) ->
- {f,To0} = F,
- case test_bs_literal(F, Ctxt, D, Acc0) of
- {none,Acc} ->
- %% Ctxt killed immediately after bs_start_match2.
- To = shortcut_bs_context_to_binary(To0, Src, D),
- I = {test,is_bitstr,{f,To},[Src]},
- backward(Is, D, [I|Acc]);
- {Literal,Acc} ->
- %% Ctxt killed after matching a literal.
- To = shortcut_bs_context_to_binary(To0, Src, D),
- Eq = {test,is_eq_exact,{f,To},[Src,{literal,Literal}]},
- backward(Is, D, [Eq|Acc]);
- not_killed ->
- %% Ctxt not killed. Not much to do.
- To = shortcut_bs_start_match(To0, Src, D),
- I = {test,bs_start_match2,{f,To},Live,Args,Ctxt},
- backward(Is, D, [I|Acc0])
- end;
-backward([{test,Op,{f,To0},Ops0}|Is], D, Acc) ->
- To1 = shortcut_bs_test(To0, Is, D),
- To2 = shortcut_label(To1, D),
- To3 = shortcut_rel_op(To2, Op, Ops0, D),
-
- %% Try to shortcut a repeated test:
- %%
- %% test Op {f,Fail1} Operands test Op {f,Fail2} Operands
- %% . . . ==> ...
- %% Fail1: test Op {f,Fail2} Operands Fail1: test Op {f,Fail2} Operands
- %%
- To = case beam_utils:code_at(To3, D) of
- [{test,Op,{f,To4},Ops}|_] ->
- case equal_ops(Ops0, Ops) of
- true -> To4;
- false -> To3
- end;
- _Code ->
- To3
- end,
- I = case Op of
- is_eq_exact -> combine_eqs(To, Ops0, D, Acc);
- _ -> {test,Op,{f,To},Ops0}
- end,
- case {I,Acc} of
- {{test,is_atom,Fail,Ops0},[{test,is_boolean,Fail,Ops0}|_]} ->
- %% An is_atom test before an is_boolean test (with the
- %% same failure label) is redundant.
- backward(Is, D, Acc);
- {{test,is_atom,Fail,[R]},
- [{test,is_eq_exact,Fail,[R,{atom,_}]}|_]} ->
- %% An is_atom test before a comparison with an atom (with
- %% the same failure label) is redundant.
- backward(Is, D, Acc);
- {{test,is_integer,Fail,[R]},
- [{test,is_eq_exact,Fail,[R,{integer,_}]}|_]} ->
- %% An is_integer test before a comparison with an integer
- %% (with the same failure label) is redundant.
- backward(Is, D, Acc);
- {{test,_,_,_},_} ->
- %% Still a test instruction. Done.
- backward(Is, D, [I|Acc]);
- {_,_} ->
- %% Rewritten to a select_val. Rescan.
- backward([I|Is], D, Acc)
- end;
-backward([{test,Op,{f,To0},Live,Ops0,Dst}|Is], D, Acc) ->
- To1 = shortcut_bs_test(To0, Is, D),
- To2 = shortcut_label(To1, D),
- %% Try to shortcut a repeated test:
- %%
- %% test Op {f,Fail1} _ Ops _ test Op {f,Fail2} _ Ops _
- %% . . . ==> ...
- %% Fail1: test Op {f,Fail2} _ Ops _ Fail1: test Op {f,Fail2} _ Ops _
- %%
- To = case beam_utils:code_at(To2, D) of
- [{test,Op,{f,To3},_,Ops,_}|_] ->
- case equal_ops(Ops0, Ops) of
- true -> To3;
- false -> To2
- end;
- _Code ->
- To2
- end,
- I = {test,Op,{f,To},Live,Ops0,Dst},
- backward(Is, D, [I|Acc]);
-backward([{kill,_}=I|Is], D, [{line,_},Exit|_]=Acc) ->
- case beam_jump:is_exit_instruction(Exit) of
- false -> backward(Is, D, [I|Acc]);
- true -> backward(Is, D, Acc)
- end;
-backward([{bif,'or',{f,To0},[Dst,{atom,false}],Dst}=I|Is], D,
- [{test,is_eq_exact,{f,To},[Dst,{atom,true}]}|_]=Acc) ->
- case shortcut_label(To0, D) of
- To ->
- backward(Is, D, Acc);
- _ ->
- backward(Is, D, [I|Acc])
- end;
-backward([{bif,map_get,{f,FF},[Key,Map],_}=I0,
- {test,has_map_fields,{f,FT}=F,[Map|Keys0]}=I1|Is], D, Acc) when FF =/= 0 ->
- case shortcut_label(FF, D) of
- FT ->
- case lists:delete(Key, Keys0) of
- [] ->
- backward([I0|Is], D, Acc);
- Keys ->
- Test = {test,has_map_fields,F,[Map|Keys]},
- backward([Test|Is], D, [I0|Acc])
- end;
- _ ->
- backward([I1|Is], D, [I0|Acc])
- end;
-backward([{bif,map_get,{f,FF},[_,Map],_}=I0,
- {test,is_map,{f,FT},[Map]}=I1|Is], D, Acc) when FF =/= 0 ->
- case shortcut_label(FF, D) of
- FT -> backward([I0|Is], D, Acc);
- _ -> backward([I1|Is], D, [I0|Acc])
- end;
-backward([I|Is], D, Acc) ->
- backward(Is, D, [I|Acc]);
-backward([], _D, Acc) -> Acc.
-
-equal_ops([{field_flags,FlA0}|T0], [{field_flags,FlB0}|T1]) ->
- FlA = lists:keydelete(anno, 1, FlA0),
- FlB = lists:keydelete(anno, 1, FlB0),
- FlA =:= FlB andalso equal_ops(T0, T1);
-equal_ops([Op|T0], [Op|T1]) ->
- equal_ops(T0, T1);
-equal_ops([], []) -> true;
-equal_ops(_, _) -> false.
-
-shortcut_select_list([Lit,{f,To0}|T], Reg, D, Acc) ->
- To = shortcut_select_label(To0, Reg, Lit, D),
- shortcut_select_list(T, Reg, D, [{f,To},Lit|Acc]);
-shortcut_select_list([], _, _, Acc) -> reverse(Acc).
-
-shortcut_label(0, _) ->
- 0;
-shortcut_label(To0, D) ->
- case beam_utils:code_at(To0, D) of
- [{jump,{f,To}}|_] -> shortcut_label(To, D);
- _ -> To0
- end.
-
-shortcut_select_label(To, Reg, Lit, D) ->
- shortcut_rel_op(To, is_ne_exact, [Reg,Lit], D).
-
-prune_redundant([_,{f,Fail}|T], Fail) ->
- prune_redundant(T, Fail);
-prune_redundant([V,F|T], Fail) ->
- [V,F|prune_redundant(T, Fail)];
-prune_redundant([], _) -> [].
-
-%% Replace a comparison operator with a test instruction and a jump.
-%% For example, if we have this code:
-%%
-%% bif '=:=' Fail Src1 Src2 {x,0}
-%% jump L1
-%% .
-%% .
-%% .
-%% L1: select_val {x,0} FailLabel [... true => L2..., ...false => L3...]
-%%
-%% the first two instructions can be replaced with
-%%
-%% test is_eq_exact L3 Src1 Src2
-%% jump L2
-%%
-%% provided that {x,0} is killed at both L2 and L3.
-
-replace_comp_op(To, Reg, Op, Ops, D) ->
- False = comp_op_find_shortcut(To, Reg, {atom,false}, D),
- True = comp_op_find_shortcut(To, Reg, {atom,true}, D),
- {bif_to_test(Op, Ops, False),{jump,{f,True}}}.
-
-comp_op_find_shortcut(To0, Reg, Val, D) ->
- case shortcut_select_label(To0, Reg, Val, D) of
- To0 ->
- not_possible();
- To ->
- case is_killed_at(Reg, To, D) of
- false -> not_possible();
- true -> To
- end
- end.
-
-bif_to_test(Name, Args, Fail) ->
- try
- beam_utils:bif_to_test(Name, Args, {f,Fail})
- catch
- error:_ -> not_possible()
- end.
-
-not_possible() -> throw(not_possible).
-
-%% combine_eqs(To, Operands, Acc) -> Instruction.
-%% Combine two is_eq_exact instructions or (an is_eq_exact
-%% instruction and a select_val instruction) to a select_val
-%% instruction if possible.
-%%
-%% Example:
-%%
-%% is_eq_exact F1 Reg Lit1 select_val Reg F2 [ Lit1 L1
-%% L1: . Lit2 L2 ]
-%% .
-%% . ==>
-%% .
-%% F1: is_eq_exact F2 Reg Lit2 F1: is_eq_exact F2 Reg Lit2
-%% L2: .... L2:
-%%
-combine_eqs(To, [Reg,{Type,_}=Lit1]=Ops, D, Acc)
- when Type =:= atom; Type =:= integer ->
- Next = case Acc of
- [{label,Lbl}|_] -> Lbl;
- [{jump,{f,Lbl}}|_] -> Lbl
- end,
- case beam_utils:code_at(To, D) of
- [{test,is_eq_exact,{f,F2},[Reg,{Type,_}=Lit2]},
- {label,L2}|_] when Lit1 =/= Lit2 ->
- {select,select_val,Reg,{f,F2},[Lit1,{f,Next},Lit2,{f,L2}]};
- [{test,is_eq_exact,{f,F2},[Reg,{Type,_}=Lit2]},
- {jump,{f,L2}}|_] when Lit1 =/= Lit2 ->
- {select,select_val,Reg,{f,F2},[Lit1,{f,Next},Lit2,{f,L2}]};
- [{select,select_val,Reg,{f,F2},[{Type,_}|_]=List0}|_] ->
- List = remove_from_list(Lit1, List0),
- {select,select_val,Reg,{f,F2},[Lit1,{f,Next}|List]};
- _Is ->
- {test,is_eq_exact,{f,To},Ops}
- end;
-combine_eqs(To, Ops, _D, _Acc) ->
- {test,is_eq_exact,{f,To},Ops}.
-
-remove_from_list(Lit, [Lit,{f,_}|T]) ->
- T;
-remove_from_list(Lit, [Val,{f,_}=Fail|T]) ->
- [Val,Fail|remove_from_list(Lit, T)];
-remove_from_list(_, []) -> [].
-
-
-test_bs_literal(F, Ctxt, D,
- [{test,bs_match_string,F,[Ctxt,Bs]},
- {test,bs_test_tail2,F,[Ctxt,0]}|Acc]) ->
- test_bs_literal_1(Ctxt, Acc, D, Bs);
-test_bs_literal(F, Ctxt, D, [{test,bs_test_tail2,F,[Ctxt,0]}|Acc]) ->
- test_bs_literal_1(Ctxt, Acc, D, <<>>);
-test_bs_literal(_, Ctxt, D, Acc) ->
- test_bs_literal_1(Ctxt, Acc, D, none).
-
-test_bs_literal_1(Ctxt, Is, D, Literal) ->
- case beam_utils:is_killed(Ctxt, Is, D) of
- true -> {Literal,Is};
- false -> not_killed
- end.
-
-%% shortcut_bs_test(TargetLabel, ReversedInstructions, D) -> TargetLabel'
-%% Try to shortcut the failure label for bit syntax matching.
-
-shortcut_bs_test(To, Is, D) ->
- shortcut_bs_test_1(beam_utils:code_at(To, D), Is, To, D).
-
-shortcut_bs_test_1([{bs_restore2,Reg,SavePoint},
- {label,_},
- {test,bs_test_tail2,{f,To},[_,TailBits]}|_],
- PrevIs, To0, D) ->
- case count_bits_matched(PrevIs, {Reg,SavePoint}, 0) of
- Bits when Bits > TailBits ->
- %% This instruction will fail. We know because a restore has been
- %% done from the previous point SavePoint in the binary, and we
- %% also know that the binary contains at least Bits bits from
- %% SavePoint.
- %%
- %% Since we will skip a bs_restore2 if we shortcut to label To,
- %% we must now make sure that code at To does not depend on
- %% the position in the context in any way.
- case shortcut_bs_pos_used(To, Reg, D) of
- false -> To;
- true -> To0
- end;
- _Bits ->
- To0
- end;
-shortcut_bs_test_1([_|_], _, To, _) -> To.
-
-%% counts_bits_matched(ReversedInstructions, SavePoint, Bits) -> Bits'
-%% Given a reversed instruction stream, determine the minimum number
-%% of bits that will be matched by bit syntax instructions up to the
-%% given save point.
-
-count_bits_matched([{test,bs_get_utf8,{f,_},_,_,_}|Is], SavePoint, Bits) ->
- count_bits_matched(Is, SavePoint, Bits+8);
-count_bits_matched([{test,bs_get_utf16,{f,_},_,_,_}|Is], SavePoint, Bits) ->
- count_bits_matched(Is, SavePoint, Bits+16);
-count_bits_matched([{test,bs_get_utf32,{f,_},_,_,_}|Is], SavePoint, Bits) ->
- count_bits_matched(Is, SavePoint, Bits+32);
-count_bits_matched([{test,_,_,_,[_,Sz,U,{field_flags,_}],_}|Is], SavePoint, Bits) ->
- case Sz of
- {integer,N} -> count_bits_matched(Is, SavePoint, Bits+N*U);
- _ -> count_bits_matched(Is, SavePoint, Bits)
- end;
-count_bits_matched([{test,bs_match_string,_,[_,Bs]}|Is], SavePoint, Bits) ->
- count_bits_matched(Is, SavePoint, Bits+bit_size(Bs));
-count_bits_matched([{test,_,_,_}|Is], SavePoint, Bits) ->
- count_bits_matched(Is, SavePoint, Bits);
-count_bits_matched([{bs_save2,Reg,SavePoint}|_], {Reg,SavePoint}, Bits) ->
- %% The save point we are looking for - we are done.
- Bits;
-count_bits_matched([_|_], _, Bits) -> Bits.
-
-shortcut_bs_pos_used(To, Reg, D) ->
- shortcut_bs_pos_used_1(beam_utils:code_at(To, D), Reg, D).
-
-shortcut_bs_pos_used_1([{bs_context_to_binary,Reg}|_], Reg, _) ->
- false;
-shortcut_bs_pos_used_1(Is, Reg, D) ->
- not beam_utils:is_killed(Reg, Is, D).
-
-%% shortcut_bs_start_match(TargetLabel, Reg) -> TargetLabel
-%% A failing bs_start_match2 instruction means that the source (Reg)
-%% cannot be a binary. That means that it is safe to skip
-%% bs_context_to_binary instructions operating on Reg, and
-%% bs_start_match2 instructions operating on Reg.
-
-shortcut_bs_start_match(To, Reg, D) ->
- shortcut_bs_start_match_1(beam_utils:code_at(To, D), Reg, To, D).
-
-shortcut_bs_start_match_1([{bs_context_to_binary,Reg}|Is], Reg, To, D) ->
- shortcut_bs_start_match_1(Is, Reg, To, D);
-shortcut_bs_start_match_1([{jump,{f,To}}|_], Reg, _, D) ->
- Code = beam_utils:code_at(To, D),
- shortcut_bs_start_match_1(Code, Reg, To, D);
-shortcut_bs_start_match_1([{test,bs_start_match2,{f,To},_,[Reg|_],_}|_],
- Reg, _, D) ->
- Code = beam_utils:code_at(To, D),
- shortcut_bs_start_match_1(Code, Reg, To, D);
-shortcut_bs_start_match_1(_, _, To, _) ->
- To.
-
-%% shortcut_bs_context_to_binary(TargetLabel, Reg) -> TargetLabel
-%% If a bs_start_match2 instruction has been eliminated, the
-%% bs_context_to_binary instruction can be eliminated too.
-
-shortcut_bs_context_to_binary(To, Reg, D) ->
- shortcut_bs_ctb_1(beam_utils:code_at(To, D), Reg, To, D).
-
-shortcut_bs_ctb_1([{bs_context_to_binary,Reg}|Is], Reg, To, D) ->
- shortcut_bs_ctb_1(Is, Reg, To, D);
-shortcut_bs_ctb_1([{jump,{f,To}}|_], Reg, _, D) ->
- Code = beam_utils:code_at(To, D),
- shortcut_bs_ctb_1(Code, Reg, To, D);
-shortcut_bs_ctb_1(_, _, To, _) ->
- To.
-
-%% shortcut_rel_op(FailLabel, Operator, [Operand], D) -> FailLabel'
-%% Try to shortcut the given test instruction. Example:
-%%
-%% is_ge L1 {x,0} 48
-%% .
-%% .
-%% .
-%% L1: is_ge L2 {x,0} 65
-%%
-%% The first test instruction can be rewritten to "is_ge L2 {x,0} 48"
-%% since the instruction at L1 will also fail.
-%%
-%% If there are instructions between L1 and the other test instruction
-%% it may still be possible to do the shortcut. For example:
-%%
-%% L1: is_eq_exact L3 {x,0} 92
-%% is_ge L2 {x,0} 65
-%%
-%% Since the first test instruction failed, we know that {x,0} must
-%% be less than 48; therefore, we know that {x,0} cannot be equal to
-%% 92 and the jump to L3 cannot happen.
-
-shortcut_rel_op(To, Op, Ops, D) ->
- case normalize_op({test,Op,{f,To},Ops}) of
- {{NormOp,A,B},_} ->
- Normalized = {negate_op(NormOp),A,B},
- shortcut_rel_op_fp(To, Normalized, D);
- {_,_} ->
- To;
- error ->
- To
- end.
-
-shortcut_rel_op_fp(To0, Normalized, D) ->
- Code = beam_utils:code_at(To0, D),
- case shortcut_any_label(Code, Normalized) of
- error ->
- To0;
- To ->
- shortcut_rel_op_fp(To, Normalized, D)
- end.
-
-%% shortcut_any_label([Instruction], PrevCondition) -> FailLabel | error
-%% Using PrevCondition (a previous condition known to be true),
-%% try to shortcut to another failure label.
-
-shortcut_any_label([{jump,{f,Lbl}}|_], _Prev) ->
- Lbl;
-shortcut_any_label([{label,Lbl}|_], _Prev) ->
- Lbl;
-shortcut_any_label([{select,select_val,R,{f,Fail},L}|_], Prev) ->
- shortcut_selectval(L, R, Fail, Prev);
-shortcut_any_label([I|Is], Prev) ->
- case normalize_op(I) of
- error ->
- error;
- {Normalized,Fail} ->
- %% We have a relational operator.
- case will_succeed(Prev, Normalized) of
- no ->
- %% This test instruction will always branch
- %% to Fail.
- Fail;
- yes ->
- %% This test instruction will never branch,
- %% so we will look at the next instruction.
- shortcut_any_label(Is, Prev);
- maybe ->
- %% May or may not branch. From now on, we can only
- %% shortcut to the this specific failure label
- %% Fail.
- shortcut_specific_label(Is, Fail, Prev)
- end
- end.
-
-%% shortcut_specific_label([Instruction], FailLabel, PrevCondition) ->
-%% FailLabel | error
-%% We have previously encountered a test instruction that may or
-%% may not branch to FailLabel. Therefore we are only allowed
-%% to do the shortcut to the same fail label (FailLabel).
-
-shortcut_specific_label([{label,_}|Is], Fail, Prev) ->
- shortcut_specific_label(Is, Fail, Prev);
-shortcut_specific_label([{select,select_val,R,{f,F},L}|_], Fail, Prev) ->
- case shortcut_selectval(L, R, F, Prev) of
- Fail -> Fail;
- _ -> error
- end;
-shortcut_specific_label([I|Is], Fail, Prev) ->
- case normalize_op(I) of
- error ->
- error;
- {Normalized,Fail} ->
- case will_succeed(Prev, Normalized) of
- no ->
- %% Will branch to FailLabel.
- Fail;
- yes ->
- %% Will definitely never branch.
- shortcut_specific_label(Is, Fail, Prev);
- maybe ->
- %% May branch, but still OK since it will branch
- %% to FailLabel.
- shortcut_specific_label(Is, Fail, Prev)
- end;
- {Normalized,_} ->
- %% This test instruction will branch to a different
- %% fail label, if it branches at all.
- case will_succeed(Prev, Normalized) of
- yes ->
- %% Still OK, since the branch will never be
- %% taken.
- shortcut_specific_label(Is, Fail, Prev);
- no ->
- %% Give up. The branch will definitely be taken
- %% to a different fail label.
- error;
- maybe ->
- %% Give up. If the branch is taken, it will be
- %% to a different fail label.
- error
- end
- end.
-
-
-%% shortcut_selectval(List, Reg, Fail, PrevCond) -> FailLabel | error
-%% Try to shortcut a selectval instruction. A selectval instruction
-%% is equivalent to the following instruction sequence:
-%%
-%% is_ne_exact L1 Reg Value1
-%% .
-%% .
-%% .
-%% is_ne_exact LN Reg ValueN
-%% jump DefaultFailLabel
-%%
-shortcut_selectval([Val,{f,Lbl}|T], R, Fail, Prev) ->
- case will_succeed(Prev, {'=/=',R,get_literal(Val)}) of
- yes -> shortcut_selectval(T, R, Fail, Prev);
- no -> Lbl;
- maybe -> error
- end;
-shortcut_selectval([], _, Fail, _) -> Fail.
-
-%% will_succeed(PrevCondition, Condition) -> yes | no | maybe
-%% PrevCondition is a condition known to be true. This function
-%% will tell whether Condition will succeed.
-
-will_succeed({Op1,Reg,A}, {Op2,Reg,B}) ->
- will_succeed_1(Op1, A, Op2, B);
-will_succeed({'=:=',Reg,{literal,A}}, {TypeTest,Reg}) ->
- case erlang:TypeTest(A) of
- false -> no;
- true -> yes
- end;
-will_succeed({_,_,_}, maybe) ->
- maybe;
-will_succeed({_,_,_}, Test) when is_tuple(Test) ->
- maybe.
-
-will_succeed_1('=:=', A, '<', B) ->
- if
- B =< A -> no;
- true -> yes
- end;
-will_succeed_1('=:=', A, '=<', B) ->
- if
- B < A -> no;
- true -> yes
- end;
-will_succeed_1('=:=', A, '=:=', B) ->
- if
- A =:= B -> yes;
- true -> no
- end;
-will_succeed_1('=:=', A, '=/=', B) ->
- if
- A =:= B -> no;
- true -> yes
- end;
-will_succeed_1('=:=', A, '>=', B) ->
- if
- B > A -> no;
- true -> yes
- end;
-will_succeed_1('=:=', A, '>', B) ->
- if
- B >= A -> no;
- true -> yes
- end;
-
-will_succeed_1('=/=', A, '=/=', B) when A =:= B -> yes;
-will_succeed_1('=/=', A, '=:=', B) when A =:= B -> no;
-
-will_succeed_1('<', A, '=:=', B) when B >= A -> no;
-will_succeed_1('<', A, '=/=', B) when B >= A -> yes;
-will_succeed_1('<', A, '<', B) when B >= A -> yes;
-will_succeed_1('<', A, '=<', B) when B > A -> yes;
-will_succeed_1('<', A, '>=', B) when B > A -> no;
-will_succeed_1('<', A, '>', B) when B >= A -> no;
-
-will_succeed_1('=<', A, '=:=', B) when B > A -> no;
-will_succeed_1('=<', A, '=/=', B) when B > A -> yes;
-will_succeed_1('=<', A, '<', B) when B > A -> yes;
-will_succeed_1('=<', A, '=<', B) when B >= A -> yes;
-will_succeed_1('=<', A, '>=', B) when B > A -> no;
-will_succeed_1('=<', A, '>', B) when B >= A -> no;
-
-will_succeed_1('>=', A, '=:=', B) when B < A -> no;
-will_succeed_1('>=', A, '=/=', B) when B < A -> yes;
-will_succeed_1('>=', A, '<', B) when B =< A -> no;
-will_succeed_1('>=', A, '=<', B) when B < A -> no;
-will_succeed_1('>=', A, '>=', B) when B =< A -> yes;
-will_succeed_1('>=', A, '>', B) when B < A -> yes;
-
-will_succeed_1('>', A, '=:=', B) when B =< A -> no;
-will_succeed_1('>', A, '=/=', B) when B =< A -> yes;
-will_succeed_1('>', A, '<', B) when B =< A -> no;
-will_succeed_1('>', A, '=<', B) when B < A -> no;
-will_succeed_1('>', A, '>=', B) when B =< A -> yes;
-will_succeed_1('>', A, '>', B) when B < A -> yes;
-
-will_succeed_1(_, _, _, _) -> maybe.
-
-%% normalize_op(Instruction) -> {Normalized,FailLabel} | error
-%% Normalized = {Operator,Register,Literal} |
-%% {TypeTest,Register} |
-%% maybe
-%% Operation = '<' | '=<' | '=:=' | '=/=' | '>=' | '>'
-%% TypeTest = is_atom | is_integer ...
-%% Literal = {literal,Term}
-%%
-%% Normalize a relational operator to facilitate further
-%% comparisons between operators. Always make the register
-%% operand the first operand. Thus the following instruction:
-%%
-%% {test,is_ge,{f,99},{integer,13},{x,0}}
-%%
-%% will be normalized to:
-%%
-%% {'=<',{x,0},{literal,13}}
-%%
-%% NOTE: Bit syntax test instructions are scary. They may change the
-%% state of match contexts and update registers, so we don't dare
-%% mess with them.
-
-normalize_op({test,is_ge,{f,Fail},Ops}) ->
- normalize_op_1('>=', Ops, Fail);
-normalize_op({test,is_lt,{f,Fail},Ops}) ->
- normalize_op_1('<', Ops, Fail);
-normalize_op({test,is_eq_exact,{f,Fail},Ops}) ->
- normalize_op_1('=:=', Ops, Fail);
-normalize_op({test,is_ne_exact,{f,Fail},Ops}) ->
- normalize_op_1('=/=', Ops, Fail);
-normalize_op({test,is_nil,{f,Fail},[R]}) ->
- normalize_op_1('=:=', [R,nil], Fail);
-normalize_op({test,Op,{f,Fail},[R]}) ->
- case erl_internal:new_type_test(Op, 1) of
- true -> {{Op,R},Fail};
- false -> {maybe,Fail}
- end;
-normalize_op({test,_,{f,Fail},_}=I) ->
- case beam_utils:is_pure_test(I) of
- true -> {maybe,Fail};
- false -> error
- end;
-normalize_op(_) ->
- error.
-
-normalize_op_1(Op, [Op1,Op2], Fail) ->
- case {get_literal(Op1),get_literal(Op2)} of
- {error,error} ->
- %% Both operands are registers.
- {maybe,Fail};
- {error,Lit} ->
- {{Op,Op1,Lit},Fail};
- {Lit,error} ->
- {{turn_op(Op),Op2,Lit},Fail};
- {_,_} ->
- %% Both operands are literals. Can probably only
- %% happen if the Core Erlang optimizations passes were
- %% turned off, so don't bother trying to do something
- %% smart here.
- {maybe,Fail}
- end.
-
-turn_op('<') -> '>';
-turn_op('>=') -> '=<';
-turn_op('=:='=Op) -> Op;
-turn_op('=/='=Op) -> Op.
-
-negate_op('>=') -> '<';
-negate_op('<') -> '>=';
-negate_op('=<') -> '>';
-negate_op('>') -> '=<';
-negate_op('=:=') -> '=/=';
-negate_op('=/=') -> '=:='.
-
-get_literal({atom,Val}) ->
- {literal,Val};
-get_literal({integer,Val}) ->
- {literal,Val};
-get_literal({float,Val}) ->
- {literal,Val};
-get_literal(nil) ->
- {literal,[]};
-get_literal({literal,_}=Lit) ->
- Lit;
-get_literal({_,_}) -> error.
-
-
-%%%
-%%% Removing stores to Y registers is not always safe
-%%% if there is an instruction that causes an exception
-%%% within a catch. In practice, there are few or no
-%%% opportunities for removing stores to Y registers anyway
-%%% if sys_core_fold has been run.
-%%%
-
-is_killed_at({x,_}=Reg, Lbl, D) ->
- beam_utils:is_killed_at(Reg, Lbl, D);
-is_killed_at({y,_}, _, _) ->
- false.
diff --git a/lib/compiler/src/beam_disasm.erl b/lib/compiler/src/beam_disasm.erl
index 6cee9acae4..d0be39f520 100644
--- a/lib/compiler/src/beam_disasm.erl
+++ b/lib/compiler/src/beam_disasm.erl
@@ -373,6 +373,8 @@ disasm_instr(B, Bs, Atoms, Literals) ->
disasm_map_inst(get_map_elements, Arity, Bs, Atoms, Literals);
has_map_fields ->
disasm_map_inst(has_map_fields, Arity, Bs, Atoms, Literals);
+ put_tuple2 ->
+ disasm_put_tuple2(Bs, Atoms, Literals);
_ ->
try decode_n_args(Arity, Bs, Atoms, Literals) of
{Args, RestBs} ->
@@ -413,6 +415,14 @@ disasm_map_inst(Inst, Arity, Bs0, Atoms, Literals) ->
{List, RestBs} = decode_n_args(Len, Bs2, Atoms, Literals),
{{Inst, Args ++ [{Z,U,List}]}, RestBs}.
+disasm_put_tuple2(Bs, Atoms, Literals) ->
+ {X, Bs1} = decode_arg(Bs, Atoms, Literals),
+ {Z, Bs2} = decode_arg(Bs1, Atoms, Literals),
+ {U, Bs3} = decode_arg(Bs2, Atoms, Literals),
+ {u, Len} = U,
+ {List, RestBs} = decode_n_args(Len, Bs3, Atoms, Literals),
+ {{put_tuple2, [X,{Z,U,List}]}, RestBs}.
+
%%-----------------------------------------------------------------------
%% decode_arg([Byte]) -> {Arg, [Byte]}
%%
@@ -1096,6 +1106,13 @@ resolve_inst({get_tl,[Src,Dst]},_,_,_) ->
{get_tl,Src,Dst};
%%
+%% OTP 22.
+%%
+resolve_inst({put_tuple2,[Dst,{{z,1},{u,_},List0}]},_,_,_) ->
+ List = resolve_args(List0),
+ {put_tuple2,Dst,{list,List}};
+
+%%
%% Catches instructions that are not yet handled.
%%
resolve_inst(X,_,_,_) -> ?exit({resolve_inst,X}).
diff --git a/lib/compiler/src/beam_except.erl b/lib/compiler/src/beam_except.erl
index 05c0f4fbc7..98831d87a7 100644
--- a/lib/compiler/src/beam_except.erl
+++ b/lib/compiler/src/beam_except.erl
@@ -31,7 +31,7 @@
%%% erlang:error(function_clause, Args) => jump FuncInfoLabel
%%%
--import(lists, [reverse/1]).
+-import(lists, [reverse/1,seq/2]).
-spec module(beam_utils:module_code(), [compile:option()]) ->
{'ok',beam_utils:module_code()}.
@@ -113,14 +113,7 @@ dig_out_block([{set,[{x,0}],[{atom,if_clause}],move}]) ->
{yes,if_end,[]};
dig_out_block([{set,[{x,0}],[{literal,{Exc,Value}}],move}|Is]) ->
translate_exception(Exc, {literal,Value}, Is, 0);
-dig_out_block([{set,[{x,0}],[Tuple],move},
- {set,[],[Value],put},
- {set,[],[{atom,Exc}],put},
- {set,[Tuple],[],{put_tuple,2}}|Is]) ->
- translate_exception(Exc, Value, Is, 3);
-dig_out_block([{set,[],[Value],put},
- {set,[],[{atom,Exc}],put},
- {set,[{x,0}],[],{put_tuple,2}}|Is]) ->
+dig_out_block([{set,[{x,0}],[{atom,Exc},Value],put_tuple2}|Is]) ->
translate_exception(Exc, Value, Is, 3);
dig_out_block(_) -> no.
@@ -138,23 +131,46 @@ fix_block(Is, Words) ->
reverse(fix_block_1(Is, Words)).
fix_block_1([{set,[],[],{alloc,Live,{F1,F2,Needed0,F3}}}|Is], Words) ->
- Needed = Needed0 - Words,
- true = Needed >= 0, %Assertion.
- [{set,[],[],{alloc,Live,{F1,F2,Needed,F3}}}|Is];
+ case Needed0 - Words of
+ 0 ->
+ Is;
+ Needed ->
+ true = Needed >= 0, %Assertion.
+ [{set,[],[],{alloc,Live,{F1,F2,Needed,F3}}}|Is]
+ end;
fix_block_1([I|Is], Words) ->
[I|fix_block_1(Is, Words)].
dig_out_block_fc([{set,[],[],{alloc,Live,_}}|Bl]) ->
- case dig_out_fc(Bl, Live-1, nil) of
- no ->
- no;
- yes ->
- {yes,{function_clause,Live}}
- end;
+ Regs = maps:from_list([{{x,X},{arg,X}} || X <- seq(0, Live-1)]),
+ dig_out_fc(Bl, Regs);
dig_out_block_fc(_) -> no.
-dig_out_fc([{set,[Dst],[{x,Reg},Dst0],put_list}|Is], Reg, Dst0) ->
- dig_out_fc(Is, Reg-1, Dst);
-dig_out_fc([{set,[{x,0}],[{atom,function_clause}],move}], -1, {x,1}) ->
- yes;
-dig_out_fc(_, _, _) -> no.
+dig_out_fc([{set,[Dst],[Hd,Tl],put_list}|Is], Regs0) ->
+ Regs = Regs0#{Dst=>{cons,get_reg(Hd, Regs0),get_reg(Tl, Regs0)}},
+ dig_out_fc(Is, Regs);
+dig_out_fc([{set,[Dst],[Src],move}|Is], Regs0) ->
+ Regs = Regs0#{Dst=>get_reg(Src, Regs0)},
+ dig_out_fc(Is, Regs);
+dig_out_fc([{set,_,_,_}|_], _Regs) ->
+ %% Unknown instruction. It is not a function_clause error.
+ no;
+dig_out_fc([], Regs) ->
+ case Regs of
+ #{{x,0}:={atom,function_clause},{x,1}:=Args} ->
+ dig_out_fc_1(Args, 0);
+ #{} ->
+ no
+ end.
+
+dig_out_fc_1({cons,{arg,I},T}, I) ->
+ dig_out_fc_1(T, I+1);
+dig_out_fc_1(nil, I) ->
+ {yes,{function_clause,I}};
+dig_out_fc_1(_, _) -> no.
+
+get_reg(R, Regs) ->
+ case Regs of
+ #{R:=Val} -> Val;
+ #{} -> R
+ end.
diff --git a/lib/compiler/src/beam_flatten.erl b/lib/compiler/src/beam_flatten.erl
index 20bd23a912..973d16a1bc 100644
--- a/lib/compiler/src/beam_flatten.erl
+++ b/lib/compiler/src/beam_flatten.erl
@@ -43,13 +43,15 @@ block([{block,Is0}|Is1], Acc) -> block(Is1, norm_block(Is0, Acc));
block([I|Is], Acc) -> block(Is, [I|Acc]);
block([], Acc) -> reverse(Acc).
-norm_block([{set,[],[],{alloc,R,Alloc}}|Is], Acc0) ->
+norm_block([{set,[],[],{alloc,R,{_,nostack,_,_}=Alloc}}|Is], Acc0) ->
case insert_alloc_in_bs_init(Acc0, Alloc) of
impossible ->
norm_block(Is, reverse(norm_allocate(Alloc, R), Acc0));
Acc ->
norm_block(Is, Acc)
end;
+norm_block([{set,[],[],{alloc,R,Alloc}}|Is], Acc0) ->
+ norm_block(Is, reverse(norm_allocate(Alloc, R), Acc0));
norm_block([{set,[D1],[S],get_hd},{set,[D2],[S],get_tl}|Is], Acc) ->
I = {get_list,S,D1,D2},
norm_block(Is, [I|Acc]);
@@ -63,6 +65,7 @@ norm({set,[D],[S],move}) -> {move,S,D};
norm({set,[D],[S],fmove}) -> {fmove,S,D};
norm({set,[D],[S],fconv}) -> {fconv,S,D};
norm({set,[D],[S1,S2],put_list}) -> {put_list,S1,S2,D};
+norm({set,[D],Els,put_tuple2}) -> {put_tuple2,D,{list,Els}};
norm({set,[D],[],{put_tuple,A}}) -> {put_tuple,A,D};
norm({set,[],[S],put}) -> {put,S};
norm({set,[D],[S],{get_tuple_element,I}}) -> {get_tuple_element,S,I,D};
diff --git a/lib/compiler/src/beam_jump.erl b/lib/compiler/src/beam_jump.erl
index 43084ad588..6d0a8db2dc 100644
--- a/lib/compiler/src/beam_jump.erl
+++ b/lib/compiler/src/beam_jump.erl
@@ -22,7 +22,7 @@
-module(beam_jump).
-export([module/2,
- is_unreachable_after/1,is_exit_instruction/1,
+ is_exit_instruction/1,
remove_unused_labels/1]).
%%% The following optimisations are done:
@@ -128,27 +128,123 @@
%%% on the program state.
%%%
--import(lists, [reverse/1,reverse/2,foldl/3]).
+-import(lists, [foldl/3,mapfoldl/3,reverse/1,reverse/2]).
-type instruction() :: beam_utils:instruction().
-spec module(beam_utils:module_code(), [compile:option()]) ->
{'ok',beam_utils:module_code()}.
-module({Mod,Exp,Attr,Fs0,Lc}, _Opt) ->
- Fs = [function(F) || F <- Fs0],
+module({Mod,Exp,Attr,Fs0,Lc0}, _Opt) ->
+ {Fs,Lc} = mapfoldl(fun function/2, Lc0, Fs0),
{ok,{Mod,Exp,Attr,Fs,Lc}}.
%% function(Function) -> Function'
%% Optimize jumps and branches.
%%
%% NOTE: This function assumes that there are no labels inside blocks.
-function({function,Name,Arity,CLabel,Asm0}) ->
- Asm1 = share(Asm0),
- Asm2 = move(Asm1),
- Asm3 = opt(Asm2, CLabel),
- Asm = remove_unused_labels(Asm3),
- {function,Name,Arity,CLabel,Asm}.
+function({function,Name,Arity,CLabel,Asm0}, Lc0) ->
+ Asm1 = eliminate_moves(Asm0),
+ {Asm2,Lc} = insert_labels(Asm1, Lc0, []),
+ Asm3 = share(Asm2),
+ Asm4 = move(Asm3),
+ Asm5 = opt(Asm4, CLabel),
+ Asm = remove_unused_labels(Asm5),
+ {{function,Name,Arity,CLabel,Asm},Lc}.
+
+%%%
+%%% Scan instructions in execution order and remove redundant 'move'
+%%% instructions. 'move' instructions are redundant if we know that
+%%% the register already contains the value being assigned, as in the
+%%% following code:
+%%%
+%%% select_val Register FailLabel [... Literal => L1...]
+%%% .
+%%% .
+%%% .
+%%% L1: move Literal Register
+%%%
+
+eliminate_moves(Is) ->
+ eliminate_moves(Is, #{}, []).
+
+eliminate_moves([{select,select_val,Reg,_,List}=I|Is], D0, Acc) ->
+ D = update_value_dict(List, Reg, D0),
+ eliminate_moves(Is, D, [I|Acc]);
+eliminate_moves([{label,Lbl},{block,[{set,[Dst],[Lit],move}|BlkIs]}=Blk0|Is],
+ D, Acc0) ->
+ Acc = [{label,Lbl}|Acc0],
+ case already_has_value(Lit, Lbl, Dst, D) andalso
+ no_fallthrough(Acc0) of
+ true ->
+ %% Remove redundant 'move' instruction.
+ Blk = {block,BlkIs},
+ eliminate_moves([Blk|Is], D, Acc);
+ false ->
+ %% Keep 'move' instruction.
+ eliminate_moves([Blk0|Is], D, Acc)
+ end;
+eliminate_moves([{block,[]}|Is], D, Acc) ->
+ %% Empty blocks can prevent further jump optimizations.
+ eliminate_moves(Is, D, Acc);
+eliminate_moves([I|Is], D0, Acc) ->
+ D = update_unsafe_labels(I, D0),
+ eliminate_moves(Is, D, [I|Acc]);
+eliminate_moves([], _, Acc) -> reverse(Acc).
+
+no_fallthrough([I|_]) ->
+ is_unreachable_after(I).
+
+already_has_value(Lit, Lbl, Reg, D) ->
+ Key = {Lbl,Reg},
+ case D of
+ #{Lbl:=unsafe} ->
+ false;
+ #{Key:=Lit} ->
+ true;
+ #{} ->
+ false
+ end.
+
+update_value_dict([Lit,{f,Lbl}|T], Reg, D0) ->
+ Key = {Lbl,Reg},
+ D = case D0 of
+ #{Key := inconsistent} -> D0;
+ #{Key := _} -> D0#{Key := inconsistent};
+ _ -> D0#{Key => Lit}
+ end,
+ update_value_dict(T, Reg, D);
+update_value_dict([], _, D) -> D.
+
+update_unsafe_labels(I, D) ->
+ Ls = instr_labels(I),
+ update_unsafe_labels_1(Ls, D).
+
+update_unsafe_labels_1([L|Ls], D) ->
+ update_unsafe_labels_1(Ls, D#{L=>unsafe});
+update_unsafe_labels_1([], D) -> D.
+
+%%%
+%%% It seems to be useful to insert extra labels after certain
+%%% test instructions. This used to be done by beam_dead.
+%%%
+
+insert_labels([{test,Op,_,_}=I|Is], Lc, Acc) ->
+ Useful = case Op of
+ is_lt -> true;
+ is_ge -> true;
+ is_eq_exact -> true;
+ is_ne_exact -> true;
+ _ -> false
+ end,
+ case Useful of
+ false -> insert_labels(Is, Lc, [I|Acc]);
+ true -> insert_labels(Is, Lc+1, [{label,Lc},I|Acc])
+ end;
+insert_labels([I|Is], Lc, Acc) ->
+ insert_labels(Is, Lc, [I|Acc]);
+insert_labels([], Lc, Acc) ->
+ {reverse(Acc),Lc}.
%%%
%%% (1) We try to share the code for identical code segments by replacing all
@@ -571,52 +667,76 @@ drop_upto_label([{label,_}|_]=Is) -> Is;
drop_upto_label([_|Is]) -> drop_upto_label(Is);
drop_upto_label([]) -> [].
-%% ulbl(Instruction, UsedGbSet) -> UsedGbSet'
-%% Update the gb_set UsedGbSet with any function-local labels
+%% ulbl(Instruction, UsedCerlSet) -> UsedCerlSet'
+%% Update the cerl_set UsedCerlSet with any function-local labels
%% (i.e. not with labels in call instructions) referenced by
%% the instruction Instruction.
%%
%% NOTE: This function does NOT look for labels inside blocks.
-ulbl({test,_,Fail,_}, Used) ->
- mark_used(Fail, Used);
-ulbl({test,_,Fail,_,_,_}, Used) ->
- mark_used(Fail, Used);
-ulbl({select,_,_,Fail,Vls}, Used) ->
- mark_used_list(Vls, mark_used(Fail, Used));
-ulbl({'try',_,Lbl}, Used) ->
- mark_used(Lbl, Used);
-ulbl({'catch',_,Lbl}, Used) ->
- mark_used(Lbl, Used);
-ulbl({jump,Lbl}, Used) ->
- mark_used(Lbl, Used);
-ulbl({loop_rec,Lbl,_}, Used) ->
- mark_used(Lbl, Used);
-ulbl({loop_rec_end,Lbl}, Used) ->
- mark_used(Lbl, Used);
-ulbl({wait,Lbl}, Used) ->
- mark_used(Lbl, Used);
-ulbl({wait_timeout,Lbl,_To}, Used) ->
- mark_used(Lbl, Used);
-ulbl({bif,_Name,Lbl,_As,_R}, Used) ->
- mark_used(Lbl, Used);
-ulbl({gc_bif,_Name,Lbl,_Live,_As,_R}, Used) ->
- mark_used(Lbl, Used);
-ulbl({bs_init,Lbl,_,_,_,_}, Used) ->
- mark_used(Lbl, Used);
-ulbl({bs_put,Lbl,_,_}, Used) ->
- mark_used(Lbl, Used);
-ulbl({put_map,Lbl,_Op,_Src,_Dst,_Live,_List}, Used) ->
- mark_used(Lbl, Used);
-ulbl({get_map_elements,Lbl,_Src,_List}, Used) ->
- mark_used(Lbl, Used);
-ulbl(_, Used) -> Used.
-
-mark_used({f,0}, Used) -> Used;
-mark_used({f,L}, Used) -> cerl_sets:add_element(L, Used).
-
-mark_used_list([{f,L}|T], Used) ->
- mark_used_list(T, cerl_sets:add_element(L, Used));
-mark_used_list([_|T], Used) ->
- mark_used_list(T, Used);
-mark_used_list([], Used) -> Used.
+ulbl(I, Used) ->
+ case instr_labels(I) of
+ [] ->
+ Used;
+ [Lbl] ->
+ cerl_sets:add_element(Lbl, Used);
+ [_|_]=L ->
+ ulbl_list(L, Used)
+ end.
+
+ulbl_list([L|Ls], Used) ->
+ ulbl_list(Ls, cerl_sets:add_element(L, Used));
+ulbl_list([], Used) -> Used.
+
+-spec instr_labels(Instruction) -> Labels when
+ Instruction :: instruction(),
+ Labels :: [beam_asm:label()].
+
+instr_labels({test,_,Fail,_}) ->
+ do_instr_labels(Fail);
+instr_labels({test,_,Fail,_,_,_}) ->
+ do_instr_labels(Fail);
+instr_labels({select,_,_,Fail,Vls}) ->
+ do_instr_labels_list(Vls, do_instr_labels(Fail));
+instr_labels({'try',_,Lbl}) ->
+ do_instr_labels(Lbl);
+instr_labels({'catch',_,Lbl}) ->
+ do_instr_labels(Lbl);
+instr_labels({jump,Lbl}) ->
+ do_instr_labels(Lbl);
+instr_labels({loop_rec,Lbl,_}) ->
+ do_instr_labels(Lbl);
+instr_labels({loop_rec_end,Lbl}) ->
+ do_instr_labels(Lbl);
+instr_labels({wait,Lbl}) ->
+ do_instr_labels(Lbl);
+instr_labels({wait_timeout,Lbl,_To}) ->
+ do_instr_labels(Lbl);
+instr_labels({bif,_Name,Lbl,_As,_R}) ->
+ do_instr_labels(Lbl);
+instr_labels({gc_bif,_Name,Lbl,_Live,_As,_R}) ->
+ do_instr_labels(Lbl);
+instr_labels({bs_init,Lbl,_,_,_,_}) ->
+ do_instr_labels(Lbl);
+instr_labels({bs_put,Lbl,_,_}) ->
+ do_instr_labels(Lbl);
+instr_labels({put_map,Lbl,_Op,_Src,_Dst,_Live,_List}) ->
+ do_instr_labels(Lbl);
+instr_labels({get_map_elements,Lbl,_Src,_List}) ->
+ do_instr_labels(Lbl);
+instr_labels({recv_mark,Lbl}) ->
+ do_instr_labels(Lbl);
+instr_labels({recv_set,Lbl}) ->
+ do_instr_labels(Lbl);
+instr_labels({fcheckerror,Lbl}) ->
+ do_instr_labels(Lbl);
+instr_labels(_) -> [].
+
+do_instr_labels({f,0}) -> [];
+do_instr_labels({f,F}) -> [F].
+
+do_instr_labels_list([{f,F}|T], Acc) ->
+ do_instr_labels_list(T, [F|Acc]);
+do_instr_labels_list([_|T], Acc) ->
+ do_instr_labels_list(T, Acc);
+do_instr_labels_list([], Acc) -> Acc.
diff --git a/lib/compiler/src/beam_kernel_to_ssa.erl b/lib/compiler/src/beam_kernel_to_ssa.erl
new file mode 100644
index 0000000000..c55a57ab32
--- /dev/null
+++ b/lib/compiler/src/beam_kernel_to_ssa.erl
@@ -0,0 +1,1330 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+%% Purpose: Convert the Kernel Erlang format to the SSA format.
+
+-module(beam_kernel_to_ssa).
+
+%% The main interface.
+-export([module/2]).
+
+-import(lists, [append/1,duplicate/2,flatmap/2,foldl/3,
+ keysort/2,mapfoldl/3,map/2,member/2,
+ reverse/1,reverse/2,sort/1]).
+
+-include("v3_kernel.hrl").
+-include("beam_ssa.hrl").
+
+-type label() :: beam_ssa:label().
+
+%% Main codegen structure.
+-record(cg, {lcount=1 :: label(), %Label counter
+ bfail=1 :: label(),
+ catch_label=none :: 'none' | label(),
+ vars=#{} :: map(), %Defined variables.
+ break=0 :: label(), %Break label
+ recv=0 :: label(), %Receive label
+ ultimate_failure=0 :: label() %Label for ultimate match failure.
+ }).
+
+%% Internal records.
+-record(cg_break, {args :: [beam_ssa:value()],
+ phi :: label()
+ }).
+-record(cg_phi, {vars :: [beam_ssa:b_var()]
+ }).
+-record(cg_unreachable, {}).
+
+-spec module(#k_mdef{}, [compile:option()]) -> {'ok',#b_module{}}.
+
+module(#k_mdef{name=Mod,exports=Es,attributes=Attr,body=Forms}, _Opts) ->
+ Body = functions(Forms, Mod),
+ Module = #b_module{name=Mod,exports=Es,attributes=Attr,body=Body},
+ {ok,Module}.
+
+functions(Forms, Mod) ->
+ [function(F, Mod) || F <- Forms].
+
+function(#k_fdef{anno=Anno0,func=Name,arity=Arity,
+ vars=As0,body=Kb}, Mod) ->
+ try
+ #k_match{} = Kb, %Assertion.
+
+ %% Generate the SSA form immediate format.
+ St0 = #cg{},
+ {As,St1} = new_ssa_vars(As0, St0),
+ {Asm,St} = cg_fun(Kb, St1),
+ Anno1 = line_anno(Anno0),
+ Anno = Anno1#{func_info=>{Mod,Name,Arity}},
+ #b_function{anno=Anno,args=As,bs=Asm,cnt=St#cg.lcount}
+ catch
+ Class:Error:Stack ->
+ io:fwrite("Function: ~w/~w\n", [Name,Arity]),
+ erlang:raise(Class, Error, Stack)
+ end.
+
+%% cg_fun([Lkexpr], [HeadVar], State) -> {[Ainstr],State}
+
+cg_fun(Ke, St0) ->
+ {UltimateFail,FailIs,St1} = make_failure(badarg, St0),
+ St2 = St1#cg{bfail=UltimateFail,ultimate_failure=UltimateFail},
+ {B,St} = cg(Ke, St2),
+ Asm = [{label,0}|B++FailIs],
+ finalize(Asm, St).
+
+make_failure(Reason, St0) ->
+ {Lbl,St1} = new_label(St0),
+ {Dst,St} = new_ssa_var('@ssa_ret', St1),
+ Is = [{label,Lbl},
+ #b_set{op=call,dst=Dst,
+ args=[#b_remote{mod=#b_literal{val=erlang},
+ name=#b_literal{val=error},
+ arity=1},
+ #b_literal{val=Reason}]},
+ #b_ret{arg=Dst}],
+ {Lbl,Is,St}.
+
+%% cg(Lkexpr, State) -> {[Ainstr],State}.
+%% Generate code for a kexpr.
+
+cg(#k_match{body=M,ret=Rs}, St) ->
+ do_match_cg(M, Rs, St);
+cg(#k_guard_match{body=M,ret=Rs}, St) ->
+ do_match_cg(M, Rs, St);
+cg(#k_seq{arg=Arg,body=Body}, St0) ->
+ {ArgIs,St1} = cg(Arg, St0),
+ {BodyIs,St} = cg(Body, St1),
+ {ArgIs++BodyIs,St};
+cg(#k_call{anno=Le,op=Func,args=As,ret=Rs}, St) ->
+ call_cg(Func, As, Rs, Le, St);
+cg(#k_enter{anno=Le,op=Func,args=As}, St) ->
+ enter_cg(Func, As, Le, St);
+cg(#k_bif{anno=Le}=Bif, St) ->
+ bif_cg(Bif, Le, St);
+cg(#k_try{arg=Ta,vars=Vs,body=Tb,evars=Evs,handler=Th,ret=Rs}, St) ->
+ try_cg(Ta, Vs, Tb, Evs, Th, Rs, St);
+cg(#k_try_enter{arg=Ta,vars=Vs,body=Tb,evars=Evs,handler=Th}, St) ->
+ try_enter_cg(Ta, Vs, Tb, Evs, Th, St);
+cg(#k_catch{body=Cb,ret=[R]}, St) ->
+ do_catch_cg(Cb, R, St);
+cg(#k_receive{anno=Le,timeout=Te,var=Rvar,body=Rm,action=Tes,ret=Rs}, St) ->
+ recv_loop_cg(Te, Rvar, Rm, Tes, Rs, Le, St);
+cg(#k_receive_next{}, #cg{recv=Recv}=St) ->
+ Is = [#b_set{op=recv_next},make_uncond_branch(Recv)],
+ {Is,St};
+cg(#k_receive_accept{}, St) ->
+ Remove = #b_set{op=remove_message},
+ {[Remove],St};
+cg(#k_put{anno=Le,arg=Con,ret=Var}, St) ->
+ put_cg(Var, Con, Le, St);
+cg(#k_return{args=[Ret0]}, St) ->
+ Ret = ssa_arg(Ret0, St),
+ {[#b_ret{arg=Ret}],St};
+cg(#k_break{args=Bs}, #cg{break=Br}=St) ->
+ Args = ssa_args(Bs, St),
+ {[#cg_break{args=Args,phi=Br}],St};
+cg(#k_guard_break{args=Bs}, St) ->
+ cg(#k_break{args=Bs}, St).
+
+%% match_cg(Matc, [Ret], State) -> {[Ainstr],State}.
+%% Generate code for a match.
+
+do_match_cg(M, Rs, St0) ->
+ {B,St1} = new_label(St0),
+ {Mis,St2} = match_cg(M, St1#cg.bfail, St1#cg{break=B}),
+ {BreakVars,St} = new_ssa_vars(Rs, St2),
+ {Mis ++ [{label,B},#cg_phi{vars=BreakVars}],
+ St#cg{bfail=St0#cg.bfail,break=St1#cg.break}}.
+
+%% match_cg(Match, Fail, State) -> {[Ainstr],State}.
+%% Generate code for a match tree.
+
+match_cg(#k_alt{first=F,then=S}, Fail, St0) ->
+ {Tf,St1} = new_label(St0),
+ {Fis,St2} = match_cg(F, Tf, St1),
+ {Sis,St3} = match_cg(S, Fail, St2),
+ {Fis ++ [{label,Tf}] ++ Sis,St3};
+match_cg(#k_select{var=#k_var{}=V,types=Scs}, Fail, St) ->
+ match_fmf(fun (S, F, Sta) ->
+ select_cg(S, V, F, Fail, Sta)
+ end, Fail, St, Scs);
+match_cg(#k_guard{clauses=Gcs}, Fail, St) ->
+ match_fmf(fun (G, F, Sta) ->
+ guard_clause_cg(G, F, Sta)
+ end, Fail, St, Gcs);
+match_cg(Ke, _Fail, St0) ->
+ cg(Ke, St0).
+
+%% select_cg(Sclause, V, TypeFail, ValueFail, State) -> {Is,State}.
+%% Selecting type and value needs two failure labels, TypeFail is the
+%% label to jump to of the next type test when this type fails, and
+%% ValueFail is the label when this type is correct but the value is
+%% wrong. These are different as in the second case there is no need
+%% to try the next type, it will always fail.
+
+select_cg(#k_type_clause{type=k_binary,values=[S]}, Var, Tf, Vf, St) ->
+ select_binary(S, Var, Tf, Vf, St);
+select_cg(#k_type_clause{type=k_bin_seg,values=Vs}, Var, Tf, _Vf, St) ->
+ select_bin_segs(Vs, Var, Tf, St);
+select_cg(#k_type_clause{type=k_bin_int,values=Vs}, Var, Tf, _Vf, St) ->
+ select_bin_segs(Vs, Var, Tf, St);
+select_cg(#k_type_clause{type=k_bin_end,values=[S]}, Var, Tf, _Vf, St) ->
+ select_bin_end(S, Var, Tf, St);
+select_cg(#k_type_clause{type=k_map,values=Vs}, Var, Tf, Vf, St) ->
+ select_map(Vs, Var, Tf, Vf, St);
+select_cg(#k_type_clause{type=k_cons,values=[S]}, Var, Tf, Vf, St) ->
+ select_cons(S, Var, Tf, Vf, St);
+select_cg(#k_type_clause{type=k_nil,values=[S]}, Var, Tf, Vf, St) ->
+ select_nil(S, Var, Tf, Vf, St);
+select_cg(#k_type_clause{type=k_literal,values=Vs}, Var, Tf, Vf, St) ->
+ select_literal(Vs, Var, Tf, Vf, St);
+select_cg(#k_type_clause{type=Type,values=Scs}, Var, Tf, Vf, St0) ->
+ {Vis,St1} =
+ mapfoldl(fun (S, Sta) ->
+ {Val,Is,Stb} = select_val(S, Var, Vf, Sta),
+ {{Is,[Val]},Stb}
+ end, St0, Scs),
+ OptVls = combine(lists:sort(combine(Vis))),
+ {Vls,Sis,St2} = select_labels(OptVls, St1, [], []),
+ Arg = ssa_arg(Var, St2),
+ {Is,St} = select_val_cg(Type, Arg, Vls, Tf, Vf, Sis, St2),
+ {Is,St}.
+
+select_val_cg(k_tuple, Tuple, Vls, Tf, Vf, Sis, St0) ->
+ {Is0,St1} = make_cond_branch({bif,is_tuple}, [Tuple], Tf, St0),
+ {Arity,St2} = new_ssa_var('@ssa_arity', St1),
+ GetArity = #b_set{op={bif,tuple_size},dst=Arity,args=[Tuple]},
+ {Is,St} = select_val_cg(k_int, Arity, Vls, Vf, Vf, Sis, St2),
+ {Is0++[GetArity]++Is,St};
+select_val_cg(Type, R, Vls, Tf, Vf, Sis, St0) ->
+ {TypeIs,St1} = if
+ Tf =:= Vf ->
+ %% The type and value failure labels are the same;
+ %% we don't need a type test.
+ {[],St0};
+ true ->
+ %% Different labels for type failure and
+ %% label failure; we need a type test.
+ Test = select_type_test(Type),
+ make_cond_branch(Test, [R], Tf, St0)
+ end,
+ case Vls of
+ [{Val,Succ}] ->
+ {Is,St} = make_cond({bif,'=:='}, [R,Val], Vf, Succ, St1),
+ {TypeIs++Is++Sis,St};
+ [_|_] ->
+ {TypeIs++[#b_switch{arg=R,fail=Vf,list=Vls}|Sis],St1}
+ end.
+
+select_type_test(k_int) -> {bif,is_integer};
+select_type_test(k_atom) -> {bif,is_atom};
+select_type_test(k_float) -> {bif,is_float}.
+
+combine([{Is,Vs1},{Is,Vs2}|Vis]) -> combine([{Is,Vs1 ++ Vs2}|Vis]);
+combine([V|Vis]) -> [V|combine(Vis)];
+combine([]) -> [].
+
+select_labels([{Is,Vs}|Vis], St0, Vls, Sis) ->
+ {Lbl,St1} = new_label(St0),
+ select_labels(Vis, St1, add_vls(Vs, Lbl, Vls), [[{label,Lbl}|Is]|Sis]);
+select_labels([], St, Vls, Sis) ->
+ {Vls,append(Sis),St}.
+
+add_vls([V|Vs], Lbl, Acc) ->
+ add_vls(Vs, Lbl, [{#b_literal{val=V},Lbl}|Acc]);
+add_vls([], _, Acc) -> Acc.
+
+select_literal(S, V, Tf, Vf, St) ->
+ Src = ssa_arg(V, St),
+ F = fun(ValClause, Fail, St0) ->
+ {Val,ValIs,St1} = select_val(ValClause, V, Vf, St0),
+ Args = [Src,#b_literal{val=Val}],
+ {Is,St2} = make_cond_branch({bif,'=:='}, Args, Fail, St1),
+ {Is++ValIs,St2}
+ end,
+ match_fmf(F, Tf, St, S).
+
+select_cons(#k_val_clause{val=#k_cons{hd=Hd,tl=Tl},body=B},
+ V, Tf, Vf, St0) ->
+ Es = [Hd,Tl],
+ {Eis,St1} = select_extract_cons(V, Es, St0),
+ {Bis,St2} = match_cg(B, Vf, St1),
+ Src = ssa_arg(V, St2),
+ {Is,St} = make_cond_branch(is_nonempty_list, [Src], Tf, St2),
+ {Is ++ Eis ++ Bis,St}.
+
+select_nil(#k_val_clause{val=#k_nil{},body=B}, V, Tf, Vf, St0) ->
+ {Bis,St1} = match_cg(B, Vf, St0),
+ Src = ssa_arg(V, St1),
+ {Is,St} = make_cond_branch({bif,'=:='}, [Src,#b_literal{val=[]}], Tf, St1),
+ {Is ++ Bis,St}.
+
+select_binary(#k_val_clause{val=#k_binary{segs=#k_var{name=Ctx0}},body=B},
+ #k_var{anno=Anno0}=Src, Tf, Vf, St0) ->
+ Anno = #{reuse_for_context=>member(reuse_for_context, Anno0)},
+ {Ctx,St1} = new_ssa_var(Ctx0, St0),
+ {Bis0,St2} = match_cg(B, Vf, St1),
+ {TestIs,St} = make_cond_branch(succeeded, [Ctx], Tf, St2),
+ Bis1 = [#b_set{anno=Anno,op=bs_start_match,dst=Ctx,
+ args=[ssa_arg(Src, St)]}] ++ TestIs ++ Bis0,
+ Bis = finish_bs_matching(Bis1),
+ {Bis,St}.
+
+finish_bs_matching([#b_set{op=bs_match,
+ args=[#b_literal{val=string},Ctx,#b_literal{val=BinList}]}=Set|Is])
+ when is_list(BinList) ->
+ I = Set#b_set{args=[#b_literal{val=string},Ctx,
+ #b_literal{val=list_to_bitstring(BinList)}]},
+ finish_bs_matching([I|Is]);
+finish_bs_matching([I|Is]) ->
+ [I|finish_bs_matching(Is)];
+finish_bs_matching([]) -> [].
+
+make_cond(Cond, Args, Fail, Succ, St0) ->
+ {Bool,St} = new_ssa_var('@ssa_bool', St0),
+ Bif = #b_set{op=Cond,dst=Bool,args=Args},
+ Br = #b_br{bool=Bool,succ=Succ,fail=Fail},
+ {[Bif,Br],St}.
+
+make_cond_branch(Cond, Args, Fail, St0) ->
+ {Bool,St1} = new_ssa_var('@ssa_bool', St0),
+ {Succ,St} = new_label(St1),
+ Bif = #b_set{op=Cond,dst=Bool,args=Args},
+ Br = #b_br{bool=Bool,succ=Succ,fail=Fail},
+ {[Bif,Br,{label,Succ}],St}.
+
+make_uncond_branch(Fail) ->
+ #b_br{bool=#b_literal{val=true},succ=Fail,fail=Fail}.
+
+%% Instructions for selection of binary segments.
+
+select_bin_segs(Scs, Ivar, Tf, St) ->
+ match_fmf(fun(S, Fail, Sta) ->
+ select_bin_seg(S, Ivar, Fail, Sta)
+ end, Tf, St, Scs).
+
+select_bin_seg(#k_val_clause{val=#k_bin_seg{size=Size,unit=U,type=T,
+ seg=Seg,flags=Fs,next=Next},
+ body=B,anno=Anno},
+ #k_var{}=Src, Fail, St0) ->
+ LineAnno = line_anno(Anno),
+ Ctx = get_context(Src, St0),
+ {Mis,St1} = select_extract_bin(Next, Size, U, T, Fs, Fail,
+ Ctx, LineAnno, St0),
+ {Extracted,St2} = new_ssa_var(Seg#k_var.name, St1),
+ {Bis,St} = bin_match_cg(Size, B, Fail, St2),
+ BsGet = #b_set{op=bs_extract,dst=Extracted,args=[ssa_arg(Next, St)]},
+ Is = Mis ++ [BsGet] ++ Bis,
+ {Is,St};
+select_bin_seg(#k_val_clause{val=#k_bin_int{size=Sz,unit=U,flags=Fs,
+ val=Val,next=Next},
+ body=B},
+ #k_var{}=Src, Fail, St0) ->
+ Ctx = get_context(Src, St0),
+ {Mis,St1} = select_extract_int(Next, Val, Sz, U, Fs, Fail,
+ Ctx, St0),
+ {Bis,St} = match_cg(B, Fail, St1),
+ Is = case Mis ++ Bis of
+ [#b_set{op=bs_match,args=[#b_literal{val=string},OtherCtx1,Bin1]},
+ #b_set{op=succeeded,dst=Bool1},
+ #b_br{bool=Bool1,succ=Succ,fail=Fail},
+ {label,Succ},
+ #b_set{op=bs_match,dst=Dst,args=[#b_literal{val=string},_OtherCtx2,Bin2]}|
+ [#b_set{op=succeeded,dst=Bool2},
+ #b_br{bool=Bool2,fail=Fail}|_]=Is0] ->
+ %% We used to do this optimization later, but it
+ %% turns out that in huge functions with many
+ %% string matching instructions, it's a huge win
+ %% to do the combination now. To avoid copying the
+ %% binary data again and again, we'll combine bitstrings
+ %% in a list and convert all of it to a bitstring later.
+ {#b_literal{val=B1},#b_literal{val=B2}} = {Bin1,Bin2},
+ Bin = #b_literal{val=[B1,B2]},
+ Set = #b_set{op=bs_match,dst=Dst,args=[#b_literal{val=string},OtherCtx1,Bin]},
+ [Set|Is0];
+ Is0 ->
+ Is0
+ end,
+ {Is,St}.
+
+bin_match_cg(#k_atom{val=all}, B0, Fail, St) ->
+ #k_select{types=Types} = B0,
+ [#k_type_clause{type=k_bin_end,values=Values}] = Types,
+ [#k_val_clause{val=#k_bin_end{},body=B}] = Values,
+ match_cg(B, Fail, St);
+bin_match_cg(_, B, Fail, St) ->
+ match_cg(B, Fail, St).
+
+get_context(#k_var{}=Var, St) ->
+ ssa_arg(Var, St).
+
+select_bin_end(#k_val_clause{val=#k_bin_end{},body=B}, Src, Tf, St0) ->
+ Ctx = get_context(Src, St0),
+ {Bis,St1} = match_cg(B, Tf, St0),
+ {TestIs,St} = make_cond_branch(bs_test_tail, [Ctx,#b_literal{val=0}], Tf, St1),
+ Is = TestIs++Bis,
+ {Is,St}.
+
+select_extract_bin(#k_var{name=Hd}, Size0, Unit, Type, Flags, Vf,
+ Ctx, Anno, St0) ->
+ {Dst,St1} = new_ssa_var(Hd, St0),
+ Size = ssa_arg(Size0, St0),
+ build_bs_instr(Anno, Type, Vf, Ctx, Size, Unit, Flags, Dst, St1).
+
+select_extract_int(#k_var{name=Tl}, 0, #k_int{val=0}, _U, _Fs, _Vf,
+ Ctx, St0) ->
+ St = set_ssa_var(Tl, Ctx, St0),
+ {[],St};
+select_extract_int(#k_var{name=Tl}, Val, #k_int{val=Sz}, U, Fs, Vf,
+ Ctx, St0) ->
+ {Dst,St1} = new_ssa_var(Tl, St0),
+ Bits = U*Sz,
+ Bin = case member(big, Fs) of
+ true ->
+ <<Val:Bits>>;
+ false ->
+ true = member(little, Fs), %Assertion.
+ <<Val:Bits/little>>
+ end,
+ Bits = bit_size(Bin), %Assertion.
+ {TestIs,St} = make_cond_branch(succeeded, [Dst], Vf, St1),
+ Set = #b_set{op=bs_match,dst=Dst,
+ args=[#b_literal{val=string},Ctx,#b_literal{val=Bin}]},
+ {[Set|TestIs],St}.
+
+build_bs_instr(Anno, Type, Fail, Ctx, Size, Unit0, Flags0, Dst, St0) ->
+ Unit = #b_literal{val=Unit0},
+ Flags = #b_literal{val=Flags0},
+ NeedSize = bs_need_size(Type),
+ TypeArg = #b_literal{val=Type},
+ Get = case NeedSize of
+ true ->
+ #b_set{anno=Anno,op=bs_match,dst=Dst,
+ args=[TypeArg,Ctx,Flags,Size,Unit]};
+ false ->
+ #b_set{anno=Anno,op=bs_match,dst=Dst,
+ args=[TypeArg,Ctx,Flags]}
+ end,
+ {Is,St} = make_cond_branch(succeeded, [Dst], Fail, St0),
+ {[Get|Is],St}.
+
+select_val(#k_val_clause{val=#k_tuple{es=Es},body=B}, V, Vf, St0) ->
+ #k{us=Used} = k_get_anno(B),
+ {Eis,St1} = select_extract_tuple(V, Es, Used, St0),
+ {Bis,St2} = match_cg(B, Vf, St1),
+ {length(Es),Eis ++ Bis,St2};
+select_val(#k_val_clause{val=Val0,body=B}, _V, Vf, St0) ->
+ Val = case Val0 of
+ #k_atom{val=Lit} -> Lit;
+ #k_float{val=Lit} -> Lit;
+ #k_int{val=Lit} -> Lit;
+ #k_literal{val=Lit} -> Lit
+ end,
+ {Bis,St1} = match_cg(B, Vf, St0),
+ {Val,Bis,St1}.
+
+%% select_extract_tuple(Src, [V], State) -> {[E],State}.
+%% Extract tuple elements, but only if they are actually used.
+%%
+%% Not extracting tuple elements that are not used is an
+%% optimization for compile time and memory use during compilation.
+%% It is probably worthwhile because it is common to extract only a
+%% few elements from a huge record.
+
+select_extract_tuple(Src, Vs, Used, St0) ->
+ Tuple = ssa_arg(Src, St0),
+ F = fun (#k_var{name=V}, {Elem,S0}) ->
+ case member(V, Used) of
+ true ->
+ Args = [Tuple,#b_literal{val=Elem}],
+ {Dst,S} = new_ssa_var(V, S0),
+ Get = #b_set{op=get_tuple_element,dst=Dst,args=Args},
+ {[Get],{Elem+1,S}};
+ false ->
+ {[],{Elem+1,S0}}
+ end
+ end,
+ {Es,{_,St}} = flatmapfoldl(F, {0,St0}, Vs),
+ {Es,St}.
+
+select_map(Scs, V, Tf, Vf, St0) ->
+ MapSrc = ssa_arg(V, St0),
+ {Is,St1} =
+ match_fmf(fun(#k_val_clause{val=#k_map{op=exact,es=Es},
+ body=B}, Fail, St1) ->
+ select_map_val(V, Es, B, Fail, St1)
+ end, Vf, St0, Scs),
+ {TestIs,St} = make_cond_branch({bif,is_map}, [MapSrc], Tf, St1),
+ {TestIs++Is,St}.
+
+select_map_val(V, Es, B, Fail, St0) ->
+ {Eis,St1} = select_extract_map(Es, V, Fail, St0),
+ {Bis,St2} = match_cg(B, Fail, St1),
+ {Eis++Bis,St2}.
+
+select_extract_map([P|Ps], Src, Fail, St0) ->
+ MapSrc = ssa_arg(Src, St0),
+ #k_map_pair{key=Key0,val=#k_var{name=Dst0}} = P,
+ Key = ssa_arg(Key0, St0),
+ {Dst,St1} = new_ssa_var(Dst0, St0),
+ Set = #b_set{op=get_map_element,dst=Dst,args=[MapSrc,Key]},
+ {TestIs,St2} = make_cond_branch(succeeded, [Dst], Fail, St1),
+ {Is,St} = select_extract_map(Ps, Src, Fail, St2),
+ {[Set|TestIs]++Is,St};
+select_extract_map([], _, _, St) ->
+ {[],St}.
+
+select_extract_cons(Src0, [#k_var{name=Hd},#k_var{name=Tl}], St0) ->
+ Src = ssa_arg(Src0, St0),
+ {HdDst,St1} = new_ssa_var(Hd, St0),
+ {TlDst,St2} = new_ssa_var(Tl, St1),
+ GetHd = #b_set{op=get_hd,dst=HdDst,args=[Src]},
+ GetTl = #b_set{op=get_tl,dst=TlDst,args=[Src]},
+ {[GetHd,GetTl],St2}.
+
+guard_clause_cg(#k_guard_clause{guard=G,body=B}, Fail, St0) ->
+ {Gis,St1} = guard_cg(G, Fail, St0),
+ {Bis,St} = match_cg(B, Fail, St1),
+ {Gis ++ Bis,St}.
+
+%% guard_cg(Guard, Fail, State) -> {[Ainstr],State}.
+%% A guard is a boolean expression of tests. Tests return true or
+%% false. A fault in a test causes the test to return false. Tests
+%% never return the boolean, instead we generate jump code to go to
+%% the correct exit point. Primops and tests all go to the next
+%% instruction on success or jump to a failure label.
+
+guard_cg(#k_protected{arg=Ts,ret=Rs,inner=Inner}, Fail, St) ->
+ protected_cg(Ts, Rs, Inner, Fail, St);
+guard_cg(#k_test{op=Test0,args=As,inverted=Inverted}, Fail, St0) ->
+ #k_remote{mod=#k_atom{val=erlang},name=#k_atom{val=Test}} = Test0,
+ test_cg(Test, Inverted, As, Fail, St0);
+guard_cg(#k_seq{arg=Arg,body=Body}, Fail, St0) ->
+ {ArgIs,St1} = guard_cg(Arg, Fail, St0),
+ {BodyIs,St} = guard_cg(Body, Fail, St1),
+ {ArgIs++BodyIs,St};
+guard_cg(G, _Fail, St) ->
+ cg(G, St).
+
+test_cg('=/=', Inverted, As, Fail, St) ->
+ test_cg('=:=', not Inverted, As, Fail, St);
+test_cg('/=', Inverted, As, Fail, St) ->
+ test_cg('==', not Inverted, As, Fail, St);
+test_cg(Test, Inverted, As0, Fail, St0) ->
+ As = ssa_args(As0, St0),
+ case {Test,ssa_args(As0, St0)} of
+ {is_record,[Tuple,#b_literal{val=Atom}=Tag,#b_literal{val=Int}=Arity]}
+ when is_atom(Atom), is_integer(Int) ->
+ test_is_record_cg(Inverted, Fail, Tuple, Tag, Arity, St0);
+ {_,As} ->
+ {Bool,St1} = new_ssa_var('@ssa_bool', St0),
+ {Succ,St} = new_label(St1),
+ Bif = #b_set{op={bif,Test},dst=Bool,args=As},
+ Br = case Inverted of
+ false -> #b_br{bool=Bool,succ=Succ,fail=Fail};
+ true -> #b_br{bool=Bool,succ=Fail,fail=Succ}
+ end,
+ {[Bif,Br,{label,Succ}],St}
+ end.
+
+test_is_record_cg(false, Fail, Tuple, TagVal, ArityVal, St0) ->
+ {Arity,St1} = new_ssa_var('@ssa_arity', St0),
+ {Tag,St2} = new_ssa_var('@ssa_tag', St1),
+ {Is0,St3} = make_cond_branch({bif,is_tuple}, [Tuple], Fail, St2),
+ GetArity = #b_set{op={bif,tuple_size},dst=Arity,args=[Tuple]},
+ {Is1,St4} = make_cond_branch({bif,'=:='}, [Arity,ArityVal], Fail, St3),
+ GetTag = #b_set{op=get_tuple_element,dst=Tag,
+ args=[Tuple,#b_literal{val=0}]},
+ {Is2,St} = make_cond_branch({bif,'=:='}, [Tag,TagVal], Fail, St4),
+ Is = Is0 ++ [GetArity] ++ Is1 ++ [GetTag] ++ Is2,
+ {Is,St};
+test_is_record_cg(true, Fail, Tuple, TagVal, ArityVal, St0) ->
+ {Succ,St1} = new_label(St0),
+ {Arity,St2} = new_ssa_var('@ssa_arity', St1),
+ {Tag,St3} = new_ssa_var('@ssa_tag', St2),
+ {Is0,St4} = make_cond_branch({bif,is_tuple}, [Tuple], Succ, St3),
+ GetArity = #b_set{op={bif,tuple_size},dst=Arity,args=[Tuple]},
+ {Is1,St5} = make_cond_branch({bif,'=:='}, [Arity,ArityVal], Succ, St4),
+ GetTag = #b_set{op=get_tuple_element,dst=Tag,
+ args=[Tuple,#b_literal{val=0}]},
+ {Is2,St} = make_cond_branch({bif,'=:='}, [Tag,TagVal], Succ, St5),
+ Is3 = [make_uncond_branch(Fail),{label,Succ}],
+ Is = Is0 ++ [GetArity] ++ Is1 ++ [GetTag] ++ Is2 ++ Is3,
+ {Is,St}.
+
+%% protected_cg([Kexpr], [Ret], Fail, St) -> {[Ainstr],St}.
+%% Do a protected. Protecteds without return values are just done
+%% for effect, the return value is not checked, success passes on to
+%% the next instruction and failure jumps to Fail. If there are
+%% return values then these must be set to 'false' on failure,
+%% control always passes to the next instruction.
+
+protected_cg(Ts, [], _, Fail, St0) ->
+ %% Protect these calls, revert when done.
+ {Tis,St1} = guard_cg(Ts, Fail, St0#cg{bfail=Fail}),
+ {Tis,St1#cg{bfail=St0#cg.bfail}};
+protected_cg(Ts, Rs, Inner0, _Fail, St0) ->
+ {Pfail,St1} = new_label(St0),
+ {Br,St2} = new_label(St1),
+ Prot = duplicate(length(Rs), #b_literal{val=false}),
+ {Tis,St3} = guard_cg(Ts, Pfail, St2#cg{break=Pfail,bfail=Pfail}),
+ Inner = ssa_args(Inner0, St3),
+ {BreakVars,St} = new_ssa_vars(Rs, St3),
+ Is = Tis ++ [#cg_break{args=Inner,phi=Br},
+ {label,Pfail},#cg_break{args=Prot,phi=Br},
+ {label,Br},#cg_phi{vars=BreakVars}],
+ {Is,St#cg{break=St0#cg.break,bfail=St0#cg.bfail}}.
+
+%% match_fmf(Fun, LastFail, State, [Clause]) -> {Is,State}.
+%% This is a special flatmapfoldl for match code gen where we
+%% generate a "failure" label for each clause. The last clause uses
+%% an externally generated failure label, LastFail. N.B. We do not
+%% know or care how the failure labels are used.
+
+match_fmf(F, LastFail, St, [H]) ->
+ F(H, LastFail, St);
+match_fmf(F, LastFail, St0, [H|T]) ->
+ {Fail,St1} = new_label(St0),
+ {R,St2} = F(H, Fail, St1),
+ {Rs,St3} = match_fmf(F, LastFail, St2, T),
+ {R ++ [{label,Fail}] ++ Rs,St3}.
+
+%% fail_label(State) -> {Where,FailureLabel}.
+%% Where = guard | no_catch | in_catch
+%% Return an indication of which part of a function code is
+%% being generated for and the appropriate failure label to
+%% use.
+%%
+%% Where has the following meaning:
+%%
+%% guard - Inside a guard.
+%% no_catch - In a function body, not in the scope of
+%% a try/catch or catch.
+%% in_catch - In the scope of a try/catch or catch.
+
+fail_label(#cg{catch_label=Catch,bfail=Fail,ultimate_failure=Ult}) ->
+ if
+ Fail =/= Ult ->
+ {guard,Fail};
+ Catch =:= none ->
+ {no_catch,Fail};
+ is_integer(Catch) ->
+ {in_catch,Catch}
+ end.
+
+%% bif_fail_label(State) -> FailureLabel.
+%% Return the appropriate failure label for a guard BIF call or
+%% primop that fails.
+
+bif_fail_label(St) ->
+ {_,Fail} = fail_label(St),
+ Fail.
+
+%% call_cg(Func, [Arg], [Ret], Le, State) ->
+%% {[Ainstr],State}.
+%% enter_cg(Func, [Arg], Le, St) -> {[Ainstr],St}.
+%% Generate code for call and enter.
+
+call_cg(Func, As, [], Le, St) ->
+ call_cg(Func, As, [#k_var{name='@ssa_ignored'}], Le, St);
+call_cg(Func0, As, [#k_var{name=R}|MoreRs]=Rs, Le, St0) ->
+ case fail_label(St0) of
+ {guard,Fail} ->
+ %% Inside a guard. The only allowed function call is to
+ %% erlang:error/1,2. We will generate a branch to the
+ %% failure branch.
+ #k_remote{mod=#k_atom{val=erlang},
+ name=#k_atom{val=error}} = Func0, %Assertion.
+ [#k_var{name=DestVar}] = Rs,
+ St = set_ssa_var(DestVar, #b_literal{val=unused}, St0),
+ {[make_uncond_branch(Fail),#cg_unreachable{}],St};
+ {Catch,Fail} ->
+ %% Ordinary function call in a function body.
+ Args = ssa_args(As, St0),
+ {Ret,St1} = new_ssa_var(R, St0),
+ Func = call_target(Func0, Args, St0),
+ Call = #b_set{anno=line_anno(Le),op=call,dst=Ret,args=[Func|Args]},
+
+ %% If this is a call to erlang:error(), MoreRs could be a
+ %% nonempty list of variables that each need a value.
+ St2 = foldl(fun(#k_var{name=Dummy}, S) ->
+ set_ssa_var(Dummy, #b_literal{val=unused}, S)
+ end, St1, MoreRs),
+ case Catch of
+ no_catch ->
+ {[Call],St2};
+ in_catch ->
+ {TestIs,St} = make_cond_branch(succeeded, [Ret], Fail, St2),
+ {[Call|TestIs],St}
+ end
+ end.
+
+enter_cg(Func0, As0, Le, St0) ->
+ Anno = line_anno(Le),
+ Func = call_target(Func0, As0, St0),
+ As = ssa_args(As0, St0),
+ {Ret,St} = new_ssa_var('@ssa_ret', St0),
+ Call = #b_set{anno=Anno,op=call,dst=Ret,args=[Func|As]},
+ {[Call,#b_ret{arg=Ret}],St}.
+
+call_target(Func, As, St) ->
+ Arity = length(As),
+ case Func of
+ #k_remote{mod=Mod0,name=Name0} ->
+ Mod = ssa_arg(Mod0, St),
+ Name = ssa_arg(Name0, St),
+ #b_remote{mod=Mod,name=Name,arity=Arity};
+ #k_local{name=Name} when is_atom(Name) ->
+ #b_local{name=#b_literal{val=Name},arity=Arity};
+ #k_var{}=Var ->
+ ssa_arg(Var, St)
+ end.
+
+%% bif_cg(#k_bif{}, Le,State) -> {[Ainstr],State}.
+%% Generate code for a guard BIF or primop.
+
+bif_cg(#k_bif{op=#k_internal{name=Name},args=As,ret=Rs}, Le, St) ->
+ internal_cg(Name, As, Rs, Le, St);
+bif_cg(#k_bif{op=#k_remote{mod=#k_atom{val=erlang},name=#k_atom{val=Name}},
+ args=As,ret=Rs}, Le, St) ->
+ bif_cg(Name, As, Rs, Le, St).
+
+%% internal_cg(Bif, [Arg], [Ret], Le, State) ->
+%% {[Ainstr],State}.
+
+internal_cg(bs_context_to_binary, [Src0], [], _Le, St) ->
+ Src = ssa_arg(Src0, St),
+ Set = #b_set{op=context_to_binary,args=[Src]},
+ {[Set],St};
+internal_cg(dsetelement, [Index0,Tuple0,New0], _Rs, _Le, St) ->
+ [New,Tuple,#b_literal{val=Index1}] = ssa_args([New0,Tuple0,Index0], St),
+ Index = #b_literal{val=Index1-1},
+ Set = #b_set{op=set_tuple_element,args=[New,Tuple,Index]},
+ {[Set],St};
+internal_cg(make_fun, [Name0,Arity0|As], Rs, _Le, St0) ->
+ #k_atom{val=Name} = Name0,
+ #k_int{val=Arity} = Arity0,
+ [#k_var{name=Dst0}] = Rs,
+ {Dst,St} = new_ssa_var(Dst0, St0),
+ Args = ssa_args(As, St),
+ Local = #b_local{name=#b_literal{val=Name},arity=Arity},
+ MakeFun = #b_set{op=make_fun,dst=Dst,args=[Local|Args]},
+ {[MakeFun],St};
+internal_cg(bs_init_writable=I, As, [#k_var{name=Dst0}], _Le, St0) ->
+ %% This behaves like a function call.
+ {Dst,St} = new_ssa_var(Dst0, St0),
+ Args = ssa_args(As, St),
+ Set = #b_set{op=I,dst=Dst,args=Args},
+ {[Set],St};
+internal_cg(build_stacktrace=I, As, [#k_var{name=Dst0}], _Le, St0) ->
+ {Dst,St} = new_ssa_var(Dst0, St0),
+ Args = ssa_args(As, St),
+ Set = #b_set{op=I,dst=Dst,args=Args},
+ {[Set],St};
+internal_cg(raise, As, [#k_var{name=Dst0}], _Le, St0) ->
+ Args = ssa_args(As, St0),
+ {Dst,St} = new_ssa_var(Dst0, St0),
+ Resume = #b_set{op=resume,dst=Dst,args=Args},
+ case St of
+ #cg{catch_label=none} ->
+ {[Resume],St};
+ #cg{catch_label=Catch} when is_integer(Catch) ->
+ Is = [Resume,make_uncond_branch(Catch),#cg_unreachable{}],
+ {Is,St}
+ end;
+internal_cg(raw_raise=I, As, [#k_var{name=Dst0}], _Le, St0) ->
+ %% This behaves like a function call.
+ {Dst,St} = new_ssa_var(Dst0, St0),
+ Args = ssa_args(As, St),
+ Set = #b_set{op=I,dst=Dst,args=Args},
+ {[Set],St}.
+
+bif_cg(Bif, As0, [#k_var{name=Dst0}], Le, St0) ->
+ {Dst,St1} = new_ssa_var(Dst0, St0),
+ case {Bif,ssa_args(As0, St0)} of
+ {is_record,[Tuple,#b_literal{val=Atom}=Tag,
+ #b_literal{val=Int}=Arity]}
+ when is_atom(Atom), is_integer(Int) ->
+ bif_is_record_cg(Dst, Tuple, Tag, Arity, St1);
+ {_,As} ->
+ I = #b_set{anno=line_anno(Le),op={bif,Bif},dst=Dst,args=As},
+ case erl_bifs:is_safe(erlang, Bif, length(As)) of
+ false ->
+ Fail = bif_fail_label(St1),
+ {Is,St} = make_cond_branch(succeeded, [Dst], Fail, St1),
+ {[I|Is],St};
+ true->
+ {[I],St1}
+ end
+ end.
+
+bif_is_record_cg(Dst, Tuple, TagVal, ArityVal, St0) ->
+ {Arity,St1} = new_ssa_var('@ssa_arity', St0),
+ {Tag,St2} = new_ssa_var('@ssa_tag', St1),
+ {Phi,St3} = new_label(St2),
+ {False,St4} = new_label(St3),
+ {Is0,St5} = make_cond_branch({bif,is_tuple}, [Tuple], False, St4),
+ GetArity = #b_set{op={bif,tuple_size},dst=Arity,args=[Tuple]},
+ {Is1,St6} = make_cond_branch({bif,'=:='}, [Arity,ArityVal], False, St5),
+ GetTag = #b_set{op=get_tuple_element,dst=Tag,
+ args=[Tuple,#b_literal{val=0}]},
+ {Is2,St} = make_cond_branch({bif,'=:='}, [Tag,TagVal], False, St6),
+ Is3 = [#cg_break{args=[#b_literal{val=true}],phi=Phi},
+ {label,False},
+ #cg_break{args=[#b_literal{val=false}],phi=Phi},
+ {label,Phi},
+ #cg_phi{vars=[Dst]}],
+ Is = Is0 ++ [GetArity] ++ Is1 ++ [GetTag] ++ Is2 ++ Is3,
+ {Is,St}.
+
+%% recv_loop_cg(TimeOut, ReceiveVar, ReceiveMatch, TimeOutExprs,
+%% [Ret], Le, St) -> {[Ainstr],St}.
+
+recv_loop_cg(Te, Rvar, Rm, Tes, Rs, Le, St0) ->
+ %% Get labels.
+ {Rl,St1} = new_label(St0),
+ {Tl,St2} = new_label(St1),
+ {Bl,St3} = new_label(St2),
+ St4 = St3#cg{break=Bl,recv=Rl},
+ {Ris,St5} = cg_recv_mesg(Rvar, Rm, Tl, Le, St4),
+ {Wis,St6} = cg_recv_wait(Te, Tes, St5),
+ {BreakVars,St} = new_ssa_vars(Rs, St6),
+ {Ris ++ [{label,Tl}] ++ Wis ++
+ [{label,Bl},#cg_phi{vars=BreakVars}],
+ St#cg{break=St0#cg.break,recv=St0#cg.recv}}.
+
+%% cg_recv_mesg( ) -> {[Ainstr],St}.
+
+cg_recv_mesg(#k_var{name=R}, Rm, Tl, Le, St0) ->
+ {Dst,St1} = new_ssa_var(R, St0),
+ {Mis,St2} = match_cg(Rm, none, St1),
+ RecvLbl = St1#cg.recv,
+ {TestIs,St} = make_cond_branch(succeeded, [Dst], Tl, St2),
+ Is = [#b_br{anno=line_anno(Le),bool=#b_literal{val=true},
+ succ=RecvLbl,fail=RecvLbl},
+ {label,RecvLbl},
+ #b_set{op=peek_message,dst=Dst}|TestIs],
+ {Is++Mis,St}.
+
+%% cg_recv_wait(Te, Tes, St) -> {[Ainstr],St}.
+
+cg_recv_wait(#k_int{val=0}, Es, St0) ->
+ {Tis,St} = cg(Es, St0),
+ {[#b_set{op=timeout}|Tis],St};
+cg_recv_wait(Te, Es, St0) ->
+ {Tis,St1} = cg(Es, St0),
+ Args = [ssa_arg(Te, St1)],
+ {WaitDst,St2} = new_ssa_var('@ssa_wait', St1),
+ {WaitIs,St} = make_cond_branch(succeeded, [WaitDst], St1#cg.recv, St2),
+ %% Infinite timeout will be optimized later.
+ Is = [#b_set{op=wait_timeout,dst=WaitDst,args=Args}] ++ WaitIs ++
+ [#b_set{op=timeout}] ++ Tis,
+ {Is,St}.
+
+%% try_cg(TryBlock, [BodyVar], TryBody, [ExcpVar], TryHandler, [Ret], St) ->
+%% {[Ainstr],St}.
+
+try_cg(Ta, Vs, Tb, Evs, Th, Rs, St0) ->
+ {B,St1} = new_label(St0), %Body label
+ {H,St2} = new_label(St1), %Handler label
+ {E,St3} = new_label(St2), %End label
+ {Next,St4} = new_label(St3),
+ {TryTag,St5} = new_ssa_var('@ssa_catch_tag', St4),
+ {SsaVs,St6} = new_ssa_vars(Vs, St5),
+ {SsaEvs,St7} = new_ssa_vars(Evs, St6),
+ {Ais,St8} = cg(Ta, St7#cg{break=B,catch_label=H}),
+ St9 = St8#cg{break=E,catch_label=St7#cg.catch_label},
+ {Bis,St10} = cg(Tb, St9),
+ {His,St11} = cg(Th, St10),
+ {BreakVars,St12} = new_ssa_vars(Rs, St11),
+ {CatchedAgg,St} = new_ssa_var('@ssa_agg', St12),
+ ExtractVs = extract_vars(SsaEvs, CatchedAgg, 0),
+ KillTryTag = #b_set{op=kill_try_tag,args=[TryTag]},
+ Args = [#b_literal{val='try'},TryTag],
+ Handler = [{label,H},
+ #b_set{op=landingpad,dst=CatchedAgg,args=Args}] ++
+ ExtractVs ++ [KillTryTag],
+ {[#b_set{op=new_try_tag,dst=TryTag,args=[#b_literal{val='try'}]},
+ #b_br{bool=TryTag,succ=Next,fail=H},
+ {label,Next}] ++ Ais ++
+ [{label,B},#cg_phi{vars=SsaVs},KillTryTag] ++ Bis ++
+ Handler ++ His ++
+ [{label,E},#cg_phi{vars=BreakVars}],
+ St#cg{break=St0#cg.break}}.
+
+try_enter_cg(Ta, Vs, Tb, Evs, Th, St0) ->
+ {B,St1} = new_label(St0), %Body label
+ {H,St2} = new_label(St1), %Handler label
+ {Next,St3} = new_label(St2),
+ {TryTag,St4} = new_ssa_var('@ssa_catch_tag', St3),
+ {SsaVs,St5} = new_ssa_vars(Vs, St4),
+ {SsaEvs,St6} = new_ssa_vars(Evs, St5),
+ {Ais,St7} = cg(Ta, St6#cg{break=B,catch_label=H}),
+ St8 = St7#cg{catch_label=St6#cg.catch_label},
+ {Bis,St9} = cg(Tb, St8),
+ {His,St10} = cg(Th, St9),
+ {CatchedAgg,St} = new_ssa_var('@ssa_agg', St10),
+ ExtractVs = extract_vars(SsaEvs, CatchedAgg, 0),
+ KillTryTag = #b_set{op=kill_try_tag,args=[TryTag]},
+ Args = [#b_literal{val='try'},TryTag],
+ Handler = [{label,H},
+ #b_set{op=landingpad,dst=CatchedAgg,args=Args}] ++
+ ExtractVs ++ [KillTryTag],
+ {[#b_set{op=new_try_tag,dst=TryTag,args=[#b_literal{val='try'}]},
+ #b_br{bool=TryTag,succ=Next,fail=H},
+ {label,Next}] ++ Ais ++
+ [{label,B},#cg_phi{vars=SsaVs},KillTryTag] ++ Bis ++
+ Handler ++ His,
+ St#cg{break=St0#cg.break}}.
+
+extract_vars([V|Vs], Agg, N) ->
+ I = #b_set{op=extract,dst=V,args=[Agg,#b_literal{val=N}]},
+ [I|extract_vars(Vs, Agg, N+1)];
+extract_vars([], _, _) -> [].
+
+%% do_catch_cg(CatchBlock, Ret, St) -> {[Ainstr],St}.
+
+do_catch_cg(Block, #k_var{name=R}, St0) ->
+ {B,St1} = new_label(St0),
+ {Next,St2} = new_label(St1),
+ {H,St3} = new_label(St2),
+ {CatchReg,St4} = new_ssa_var('@ssa_catch_tag', St3),
+ {Dst,St5} = new_ssa_var(R, St4),
+ {Succ,St6} = new_label(St5),
+ {Cis,St7} = cg(Block, St6#cg{break=Succ,catch_label=H}),
+ {CatchedVal,St8} = new_ssa_var('@catched_val', St7),
+ {SuccVal,St9} = new_ssa_var('@success_val', St8),
+ {CatchedAgg,St10} = new_ssa_var('@ssa_agg', St9),
+ {CatchEndVal,St} = new_ssa_var('@catch_end_val', St10),
+ Args = [#b_literal{val='catch'},CatchReg],
+ {[#b_set{op=new_try_tag,dst=CatchReg,args=[#b_literal{val='catch'}]},
+ #b_br{bool=CatchReg,succ=Next,fail=H},
+ {label,Next}] ++ Cis ++
+ [{label,H},
+ #b_set{op=landingpad,dst=CatchedAgg,args=Args},
+ #b_set{op=extract,dst=CatchedVal,
+ args=[CatchedAgg,#b_literal{val=0}]},
+ #cg_break{args=[CatchedVal],phi=B},
+ {label,Succ},
+ #cg_phi{vars=[SuccVal]},
+ #cg_break{args=[SuccVal],phi=B},
+ {label,B},#cg_phi{vars=[CatchEndVal]},
+ #b_set{op=catch_end,dst=Dst,args=[CatchReg,CatchEndVal]}],
+ St#cg{break=St1#cg.break,catch_label=St1#cg.catch_label}}.
+
+%% put_cg([Var], Constr, Le, Vdb, Bef, St) -> {[Ainstr],St}.
+%% Generate code for constructing terms.
+
+put_cg([#k_var{name=R}], #k_cons{hd=Hd,tl=Tl}, _Le, St0) ->
+ Args = ssa_args([Hd,Tl], St0),
+ {Dst,St} = new_ssa_var(R, St0),
+ PutList = #b_set{op=put_list,dst=Dst,args=Args},
+ {[PutList],St};
+put_cg([#k_var{name=R}], #k_tuple{es=Es}, _Le, St0) ->
+ {Ret,St} = new_ssa_var(R, St0),
+ Args = ssa_args(Es, St),
+ PutTuple = #b_set{op=put_tuple,dst=Ret,args=Args},
+ {[PutTuple],St};
+put_cg([#k_var{name=R}], #k_binary{segs=Segs}, Le, St0) ->
+ Fail = bif_fail_label(St0),
+ {Dst,St1} = new_ssa_var(R, St0),
+ cg_binary(Dst, Segs, Fail, Le, St1);
+put_cg([#k_var{name=R}], #k_map{op=Op,var=Map,
+ es=[#k_map_pair{key=#k_var{}=K,val=V}]},
+ Le, St0) ->
+ %% Map: single variable key.
+ SrcMap = ssa_arg(Map, St0),
+ LineAnno = line_anno(Le),
+ List = [ssa_arg(K, St0),ssa_arg(V, St0)],
+ {Dst,St1} = new_ssa_var(R, St0),
+ {Is,St} = put_cg_map(LineAnno, Op, SrcMap, Dst, List, St1),
+ {Is,St};
+put_cg([#k_var{name=R}], #k_map{op=Op,var=Map,es=Es}, Le, St0) ->
+ %% Map: one or more literal keys.
+ [] = [Var || #k_map_pair{key=#k_var{}=Var} <- Es], %Assertion
+ SrcMap = ssa_arg(Map, St0),
+ LineAnno = line_anno(Le),
+ List = flatmap(fun(#k_map_pair{key=K,val=V}) ->
+ [ssa_arg(K, St0),ssa_arg(V, St0)]
+ end, Es),
+ {Dst,St1} = new_ssa_var(R, St0),
+ {Is,St} = put_cg_map(LineAnno, Op, SrcMap, Dst, List, St1),
+ {Is,St};
+put_cg([#k_var{name=R}], Con0, _Le, St0) ->
+ %% Create an alias for a variable or literal.
+ Con = ssa_arg(Con0, St0),
+ St = set_ssa_var(R, Con, St0),
+ {[],St}.
+
+put_cg_map(LineAnno, Op, SrcMap, Dst, List, St0) ->
+ Fail = bif_fail_label(St0),
+ Args = [#b_literal{val=Op},SrcMap|List],
+ PutMap = #b_set{anno=LineAnno,op=put_map,dst=Dst,args=Args},
+ if
+ Op =:= assoc ->
+ {[PutMap],St0};
+ true ->
+ {Is,St} = make_cond_branch(succeeded, [Dst], Fail, St0),
+ {[PutMap|Is],St}
+ end.
+
+%%%
+%%% Code generation for constructing binaries.
+%%%
+
+cg_binary(Dst, Segs0, Fail, Le, St0) ->
+ {PutCode0,SzCalc0,St1} = cg_bin_put(Segs0, Fail, St0),
+ LineAnno = line_anno(Le),
+ Anno = Le#k.a,
+ case PutCode0 of
+ [#b_set{op=bs_put,dst=Bool,args=[_,_,Src,#b_literal{val=all}|_]},
+ #b_br{bool=Bool},
+ {label,_}|_] ->
+ #k_bin_seg{unit=Unit0,next=Segs} = Segs0,
+ Unit = #b_literal{val=Unit0},
+ {PutCode,SzCalc1,St2} = cg_bin_put(Segs, Fail, St1),
+ {_,SzVar,SzCode0,St3} = cg_size_calc(1, SzCalc1, Fail, St2),
+ SzCode = cg_bin_anno(SzCode0, LineAnno),
+ Args = case member(single_use, Anno) of
+ true ->
+ [#b_literal{val=private_append},Src,SzVar,Unit];
+ false ->
+ [#b_literal{val=append},Src,SzVar,Unit]
+ end,
+ BsInit = #b_set{anno=LineAnno,op=bs_init,dst=Dst,args=Args},
+ {TestIs,St} = make_cond_branch(succeeded, [Dst], Fail, St3),
+ {SzCode ++ [BsInit] ++ TestIs ++ PutCode,St};
+ [#b_set{op=bs_put}|_] ->
+ {Unit,SzVar,SzCode0,St2} = cg_size_calc(8, SzCalc0, Fail, St1),
+ SzCode = cg_bin_anno(SzCode0, LineAnno),
+ Args = [#b_literal{val=new},SzVar,Unit],
+ BsInit = #b_set{anno=LineAnno,op=bs_init,dst=Dst,args=Args},
+ {TestIs,St} = make_cond_branch(succeeded, [Dst], Fail, St2),
+ {SzCode ++ [BsInit] ++ TestIs ++ PutCode0,St}
+ end.
+
+cg_bin_anno([Set|Sets], Anno) ->
+ [Set#b_set{anno=Anno}|Sets];
+cg_bin_anno([], _) -> [].
+
+%% cg_size_calc(PreferredUnit, SzCalc, Fail, St0) ->
+%% {ActualUnit,SizeVariable,SizeCode,St}.
+%% Generate size calculation code.
+
+cg_size_calc(Unit, error, _Fail, St) ->
+ {#b_literal{val=Unit},#b_literal{val=badarg},[],St};
+cg_size_calc(8, [{1,_}|_]=SzCalc, Fail, St) ->
+ cg_size_calc(1, SzCalc, Fail, St);
+cg_size_calc(8, SzCalc, Fail, St0) ->
+ {Var,Pre,St} = cg_size_calc_1(SzCalc, Fail, St0),
+ {#b_literal{val=8},Var,Pre,St};
+cg_size_calc(1, SzCalc0, Fail, St0) ->
+ SzCalc = map(fun({8,#b_literal{val=Size}}) ->
+ {1,#b_literal{val=8*Size}};
+ ({8,{{bif,byte_size},Src}}) ->
+ {1,{{bif,bit_size},Src}};
+ ({8,{_,_}=UtfCalc}) ->
+ {1,{'*',#b_literal{val=8},UtfCalc}};
+ ({_,_}=Pair) ->
+ Pair
+ end, SzCalc0),
+ {Var,Pre,St} = cg_size_calc_1(SzCalc, Fail, St0),
+ {#b_literal{val=1},Var,Pre,St}.
+
+cg_size_calc_1(SzCalc, Fail, St0) ->
+ cg_size_calc_2(SzCalc, #b_literal{val=0}, Fail, St0).
+
+cg_size_calc_2([{_,{'*',Unit,{_,_}=Bif}}|T], Sum0, Fail, St0) ->
+ {Sum1,Pre0,St1} = cg_size_calc_2(T, Sum0, Fail, St0),
+ {BifDst,Pre1,St2} = cg_size_bif(Bif, Fail, St1),
+ {Sum,Pre2,St} = cg_size_add(Sum1, BifDst, Unit, Fail, St2),
+ {Sum,Pre0++Pre1++Pre2,St};
+cg_size_calc_2([{_,#b_literal{}=Sz}|T], Sum0, Fail, St0) ->
+ {Sum1,Pre0,St1} = cg_size_calc_2(T, Sum0, Fail, St0),
+ {Sum,Pre,St} = cg_size_add(Sum1, Sz, #b_literal{val=1}, Fail, St1),
+ {Sum,Pre0++Pre,St};
+cg_size_calc_2([{_,#b_var{}=Sz}|T], Sum0, Fail, St0) ->
+ {Sum1,Pre0,St1} = cg_size_calc_2(T, Sum0, Fail, St0),
+ {Sum,Pre,St} = cg_size_add(Sum1, Sz, #b_literal{val=1}, Fail, St1),
+ {Sum,Pre0++Pre,St};
+cg_size_calc_2([{_,{_,_}=Bif}|T], Sum0, Fail, St0) ->
+ {Sum1,Pre0,St1} = cg_size_calc_2(T, Sum0, Fail, St0),
+ {BifDst,Pre1,St2} = cg_size_bif(Bif, Fail, St1),
+ {Sum,Pre2,St} = cg_size_add(Sum1, BifDst, #b_literal{val=1}, Fail, St2),
+ {Sum,Pre0++Pre1++Pre2,St};
+cg_size_calc_2([], Sum, _Fail, St) ->
+ {Sum,[],St}.
+
+cg_size_bif(#b_var{}=Var, _Fail, St) ->
+ {Var,[],St};
+cg_size_bif({Name,Src}, Fail, St0) ->
+ {Dst,St1} = new_ssa_var('@ssa_bif', St0),
+ Bif = #b_set{op=Name,dst=Dst,args=[Src]},
+ {TestIs,St} = make_cond_branch(succeeded, [Dst], Fail, St1),
+ {Dst,[Bif|TestIs],St}.
+
+cg_size_add(#b_literal{val=0}, Val, #b_literal{val=1}, _Fail, St) ->
+ {Val,[],St};
+cg_size_add(A, B, Unit, Fail, St0) ->
+ {Dst,St1} = new_ssa_var('@ssa_sum', St0),
+ {TestIs,St} = make_cond_branch(succeeded, [Dst], Fail, St1),
+ BsAdd = #b_set{op=bs_add,dst=Dst,args=[A,B,Unit]},
+ {Dst,[BsAdd|TestIs],St}.
+
+cg_bin_put(Seg, Fail, St) ->
+ cg_bin_put_1(Seg, Fail, [], [], St).
+
+cg_bin_put_1(#k_bin_seg{size=Size0,unit=U,type=T,flags=Fs,seg=Src0,next=Next},
+ Fail, Acc, SzCalcAcc, St0) ->
+ [Src,Size] = ssa_args([Src0,Size0], St0),
+ NeedSize = bs_need_size(T),
+ TypeArg = #b_literal{val=T},
+ Flags = #b_literal{val=Fs},
+ Unit = #b_literal{val=U},
+ Args = case NeedSize of
+ true -> [TypeArg,Flags,Src,Size,Unit];
+ false -> [TypeArg,Flags,Src]
+ end,
+ {Is,St} = make_cond_branch(bs_put, Args, Fail, St0),
+ SzCalc = bin_size_calc(T, Src, Size, U),
+ cg_bin_put_1(Next, Fail, reverse(Is, Acc), [SzCalc|SzCalcAcc], St);
+cg_bin_put_1(#k_bin_end{}, _, Acc, SzCalcAcc, St) ->
+ SzCalc = fold_size_calc(SzCalcAcc, 0, []),
+ {reverse(Acc),SzCalc,St}.
+
+bs_need_size(utf8) -> false;
+bs_need_size(utf16) -> false;
+bs_need_size(utf32) -> false;
+bs_need_size(_) -> true.
+
+bin_size_calc(utf8, Src, _Size, _Unit) ->
+ {8,{bs_utf8_size,Src}};
+bin_size_calc(utf16, Src, _Size, _Unit) ->
+ {8,{bs_utf16_size,Src}};
+bin_size_calc(utf32, _Src, _Size, _Unit) ->
+ {8,#b_literal{val=4}};
+bin_size_calc(binary, Src, #b_literal{val=all}, Unit) ->
+ case Unit rem 8 of
+ 0 -> {8,{{bif,byte_size},Src}};
+ _ -> {1,{{bif,bit_size},Src}}
+ end;
+bin_size_calc(_Type, _Src, Size, Unit) ->
+ {Unit,Size}.
+
+fold_size_calc([{Unit,#b_literal{val=Size}}|T], Bits, Acc) ->
+ if
+ is_integer(Size) ->
+ fold_size_calc(T, Bits + Unit*Size, Acc);
+ true ->
+ error
+ end;
+fold_size_calc([{U,#b_var{}}=H|T], Bits, Acc) when U =:= 1; U =:= 8 ->
+ fold_size_calc(T, Bits, [H|Acc]);
+fold_size_calc([{U,#b_var{}=Var}|T], Bits, Acc) ->
+ fold_size_calc(T, Bits, [{1,{'*',#b_literal{val=U},Var}}|Acc]);
+fold_size_calc([{_,_}=H|T], Bits, Acc) ->
+ fold_size_calc(T, Bits, [H|Acc]);
+fold_size_calc([], Bits, Acc) ->
+ Bytes = Bits div 8,
+ RemBits = Bits rem 8,
+ Sizes = sort([{1,#b_literal{val=RemBits}},{8,#b_literal{val=Bytes}}|Acc]),
+ [Pair || {_,Sz}=Pair <- Sizes, Sz =/= #b_literal{val=0}].
+
+%%%
+%%% Utilities for creating the SSA types.
+%%%
+
+ssa_args(As, St) ->
+ [ssa_arg(A, St) || A <- As].
+
+ssa_arg(#k_var{name=V}, #cg{vars=Vars}) -> maps:get(V, Vars);
+ssa_arg(#k_literal{val=V}, _) -> #b_literal{val=V};
+ssa_arg(#k_atom{val=V}, _) -> #b_literal{val=V};
+ssa_arg(#k_float{val=V}, _) -> #b_literal{val=V};
+ssa_arg(#k_int{val=V}, _) -> #b_literal{val=V};
+ssa_arg(#k_nil{}, _) -> #b_literal{val=[]}.
+
+new_ssa_vars(Vs, St) ->
+ mapfoldl(fun(#k_var{name=V}, S) ->
+ new_ssa_var(V, S)
+ end, St, Vs).
+
+new_ssa_var(VarBase, #cg{lcount=Uniq,vars=Vars}=St0)
+ when is_atom(VarBase); is_integer(VarBase) ->
+ case Vars of
+ #{VarBase:=_} ->
+ Var = #b_var{name={VarBase,Uniq}},
+ St = St0#cg{lcount=Uniq+1,vars=Vars#{VarBase=>Var}},
+ {Var,St};
+ #{} ->
+ Var = #b_var{name=VarBase},
+ St = St0#cg{vars=Vars#{VarBase=>Var}},
+ {Var,St}
+ end.
+
+set_ssa_var(VarBase, Val, #cg{vars=Vars}=St)
+ when is_atom(VarBase); is_integer(VarBase) ->
+ St#cg{vars=Vars#{VarBase=>Val}}.
+
+%% new_label(St) -> {L,St}.
+
+new_label(#cg{lcount=Next}=St) ->
+ {Next,St#cg{lcount=Next+1}}.
+
+%% line_anno(Le) -> #{} | #{location:={File,Line}}.
+%% Create a location annotation, containing information about the
+%% current filename and line number. The annotation should be
+%% included in any operation that could cause an exception.
+
+line_anno(#k{a=Anno}) ->
+ line_anno_1(Anno).
+
+line_anno_1([Line,{file,Name}]) when is_integer(Line) ->
+ line_anno_2(Name, Line);
+line_anno_1([_|_]=A) ->
+ {Name,Line} = find_loc(A, no_file, 0),
+ line_anno_2(Name, Line);
+line_anno_1([]) ->
+ #{}.
+
+line_anno_2(no_file, _) ->
+ #{};
+line_anno_2(_, 0) ->
+ %% Missing line number or line number 0.
+ #{};
+line_anno_2(Name, Line) ->
+ #{location=>{Name,Line}}.
+
+find_loc([Line|T], File, _) when is_integer(Line) ->
+ find_loc(T, File, Line);
+find_loc([{file,File}|T], _, Line) ->
+ find_loc(T, File, Line);
+find_loc([_|T], File, Line) ->
+ find_loc(T, File, Line);
+find_loc([], File, Line) -> {File,Line}.
+
+flatmapfoldl(F, Accu0, [Hd|Tail]) ->
+ {R,Accu1} = F(Hd, Accu0),
+ {Rs,Accu2} = flatmapfoldl(F, Accu1, Tail),
+ {R++Rs,Accu2};
+flatmapfoldl(_, Accu, []) -> {[],Accu}.
+
+%%%
+%%% Finalize the code.
+%%%
+
+finalize(Asm0, St0) ->
+ Asm1 = fix_phis(Asm0),
+ {Asm,St} = fix_sets(Asm1, [], St0),
+ {build_map(Asm),St}.
+
+fix_phis(Is) ->
+ fix_phis_1(Is, none, #{}).
+
+fix_phis_1([{label,L},#cg_phi{vars=[]}=Phi|Is0], _Lbl, Map0) ->
+ case maps:is_key(L, Map0) of
+ false ->
+ %% No #cg_break{} references this label. Nothing else can
+ %% reference it, so it can be safely be removed.
+ {Is,Map} = drop_upto_label(Is0, Map0),
+ fix_phis_1(Is, none, Map);
+ true ->
+ %% There is a break referencing this label; probably caused
+ %% by a try/catch whose return value is ignored.
+ [{label,L}|fix_phis_1([Phi|Is0], L, Map0)]
+ end;
+fix_phis_1([{label,L}=I|Is], _Lbl, Map) ->
+ [I|fix_phis_1(Is, L, Map)];
+fix_phis_1([#cg_unreachable{}|Is0], _Lbl, Map0) ->
+ {Is,Map} = drop_upto_label(Is0, Map0),
+ fix_phis_1(Is, none, Map);
+fix_phis_1([#cg_break{args=Args,phi=Target}|Is], Lbl, Map) when is_integer(Lbl) ->
+ Pairs1 = case Map of
+ #{Target:=Pairs0} -> Pairs0;
+ #{} -> []
+ end,
+ Pairs = [[{Arg,Lbl} || Arg <- Args]|Pairs1],
+ I = make_uncond_branch(Target),
+ [I|fix_phis_1(Is, none, Map#{Target=>Pairs})];
+fix_phis_1([#cg_phi{vars=Vars}|Is0], Lbl, Map0) ->
+ Pairs = maps:get(Lbl, Map0),
+ Map1 = maps:remove(Lbl, Map0),
+ case gen_phis(Vars, Pairs) of
+ [#b_set{op=phi,args=[]}] ->
+ {Is,Map} = drop_upto_label(Is0, Map1),
+ Ret = #b_ret{arg=#b_literal{val=unreachable}},
+ [Ret|fix_phis_1(Is, none, Map)];
+ Phis ->
+ Phis ++ fix_phis_1(Is0, Lbl, Map1)
+ end;
+fix_phis_1([I|Is], Lbl, Map) ->
+ [I|fix_phis_1(Is, Lbl, Map)];
+fix_phis_1([], _, Map) ->
+ [] = maps:to_list(Map), %Assertion.
+ [].
+
+gen_phis([V|Vs], Preds0) ->
+ {Pairs,Preds} = collect_preds(Preds0, [], []),
+ [#b_set{op=phi,dst=V,args=Pairs}|gen_phis(Vs, Preds)];
+gen_phis([], _) -> [].
+
+collect_preds([[First|Rest]|T], ColAcc, RestAcc) ->
+ collect_preds(T, [First|ColAcc], [Rest|RestAcc]);
+collect_preds([], ColAcc, RestAcc) ->
+ {keysort(2, ColAcc),RestAcc}.
+
+fix_sets([#b_set{dst=none}=Set|Is], Acc, St0) ->
+ {Dst,St} = new_ssa_var('@ssa_ignored', St0),
+ I = Set#b_set{dst=Dst},
+ fix_sets(Is, [I|Acc], St);
+fix_sets([I|Is], Acc, St) ->
+ fix_sets(Is, [I|Acc], St);
+fix_sets([], Acc, St) ->
+ {reverse(Acc),St}.
+
+build_map(Is) ->
+ Blocks = build_graph_1(Is, [], []),
+ maps:from_list(Blocks).
+
+build_graph_1([{label,L}|Is], Lbls, []) ->
+ build_graph_1(Is, [L|Lbls], []);
+build_graph_1([{label,L}|Is], Lbls, [_|_]=BlockAcc) ->
+ make_blocks(Lbls, BlockAcc) ++ build_graph_1(Is, [L], []);
+build_graph_1([I|Is], Lbls, BlockAcc) ->
+ build_graph_1(Is, Lbls, [I|BlockAcc]);
+build_graph_1([], Lbls, BlockAcc) ->
+ make_blocks(Lbls, BlockAcc).
+
+make_blocks(Lbls, [Last|Is0]) ->
+ Is = reverse(Is0),
+ Block = #b_blk{is=Is,last=Last},
+ [{L,Block} || L <- Lbls].
+
+drop_upto_label([{label,_}|_]=Is, Map) ->
+ {Is,Map};
+drop_upto_label([#cg_break{phi=Target}|Is], Map) ->
+ Pairs = case Map of
+ #{Target:=Pairs0} -> Pairs0;
+ #{} -> []
+ end,
+ drop_upto_label(Is, Map#{Target=>Pairs});
+drop_upto_label([_|Is], Map) ->
+ drop_upto_label(Is, Map).
+
+k_get_anno(Thing) -> element(2, Thing).
diff --git a/lib/compiler/src/beam_listing.erl b/lib/compiler/src/beam_listing.erl
index 518b958794..8a0ce5b50a 100644
--- a/lib/compiler/src/beam_listing.erl
+++ b/lib/compiler/src/beam_listing.erl
@@ -23,6 +23,7 @@
-include("core_parse.hrl").
-include("v3_kernel.hrl").
+-include("beam_ssa.hrl").
-include("beam_disasm.hrl").
-import(lists, [foreach/2]).
@@ -41,6 +42,12 @@ module(File, #k_mdef{}=Kern) ->
%% This is a kernel module.
io:put_chars(File, v3_kernel_pp:format(Kern));
%%io:put_chars(File, io_lib:format("~p~n", [Kern]));
+module(File, #b_module{name=Mod,exports=Exp,attributes=Attr,body=Fs}) ->
+ io:format(File, "module ~p.\n", [Mod]),
+ io:format(File, "exports ~p.\n", [Exp]),
+ io:format(File, "attributes ~p.\n\n", [Attr]),
+ PP = [beam_ssa_pp:format_function(F) || F <- Fs],
+ io:put_chars(File, lists:join($\n, PP));
module(Stream, {Mod,Exp,Attr,Code,NumLabels}) ->
%% This is output from v3_codegen.
io:format(Stream, "{module, ~p}. %% version = ~w\n",
diff --git a/lib/compiler/src/beam_peep.erl b/lib/compiler/src/beam_peep.erl
index 2b8dd40e29..2323a439e9 100644
--- a/lib/compiler/src/beam_peep.erl
+++ b/lib/compiler/src/beam_peep.erl
@@ -101,31 +101,40 @@ peep([{select,Op,R,F,Vls0}|Is], SeenTests0, Acc0) ->
I = {jump,F},
peep([I|Is], gb_sets:empty(), Acc0);
[{atom,_}=Value,Lbl] when Op =:= select_val ->
- %% Single value left. Convert to regular test and pop redundant tests.
+ %% Single value left. Convert to regular test.
Is1 = [{test,is_eq_exact,F,[R,Value]},{jump,Lbl}|Is],
- case Acc0 of
- [{test,is_atom,F,[R]}|Acc] ->
- peep(Is1, SeenTests0, Acc);
- _ ->
- peep(Is1, SeenTests0, Acc0)
- end;
+ peep(Is1, SeenTests0, Acc0);
[{integer,_}=Value,Lbl] when Op =:= select_val ->
- %% Single value left. Convert to regular test and pop redundant tests.
+ %% Single value left. Convert to regular test.
Is1 = [{test,is_eq_exact,F,[R,Value]},{jump,Lbl}|Is],
- case Acc0 of
- [{test,is_integer,F,[R]}|Acc] ->
- peep(Is1, SeenTests0, Acc);
- _ ->
- peep(Is1, SeenTests0, Acc0)
- end;
+ peep(Is1, SeenTests0, Acc0);
[Arity,Lbl] when Op =:= select_tuple_arity ->
%% Single value left. Convert to regular test
Is1 = [{test,test_arity,F,[R,Arity]},{jump,Lbl}|Is],
peep(Is1, SeenTests0, Acc0);
+ [{atom,B1},Lbl,{atom,B2},Lbl] when B1 =:= not B2 ->
+ %% Replace with is_boolean test.
+ Is1 = [{test,is_boolean,F,[R]},{jump,Lbl}|Is],
+ peep(Is1, SeenTests0, Acc0);
[_|_]=Vls ->
I = {select,Op,R,F,Vls},
peep(Is, gb_sets:empty(), [I|Acc0])
end;
+peep([{get_map_elements,Fail,Src,List}=I|Is], _SeenTests, Acc0) ->
+ SeenTests = gb_sets:empty(),
+ case simplify_get_map_elements(Fail, Src, List, Acc0) of
+ {ok,Acc} ->
+ peep(Is, SeenTests, Acc);
+ error ->
+ peep(Is, SeenTests, [I|Acc0])
+ end;
+peep([{test,has_map_fields,Fail,Ops}=I|Is], SeenTests, Acc0) ->
+ case simplify_has_map_fields(Fail, Ops, Acc0) of
+ {ok,Acc} ->
+ peep(Is, SeenTests, Acc);
+ error ->
+ peep(Is, SeenTests, [I|Acc0])
+ end;
peep([{test,Op,_,Ops}=I|Is], SeenTests0, Acc) ->
case beam_utils:is_pure_test(I) of
false ->
@@ -176,3 +185,39 @@ prune_redundant_values([_Val,F|Vls], F) ->
prune_redundant_values([Val,Lbl|Vls], F) ->
[Val,Lbl|prune_redundant_values(Vls, F)];
prune_redundant_values([], _) -> [].
+
+simplify_get_map_elements(Fail, Src, {list,[Key,Dst]},
+ [{get_map_elements,Fail,Src,{list,List1}}|Acc]) ->
+ case are_keys_literals([Key]) andalso are_keys_literals(List1) of
+ true ->
+ case member(Key, List1) of
+ true ->
+ %% The key is already in the other list. That is
+ %% very unusual, because there are optimizations to get
+ %% rid of duplicate keys. Therefore, don't try to
+ %% do anything smart here; just keep the
+ %% get_map_elements instructions separate.
+ error;
+ false ->
+ List = [Key,Dst|List1],
+ {ok,[{get_map_elements,Fail,Src,{list,List}}|Acc]}
+ end;
+ false ->
+ error
+ end;
+simplify_get_map_elements(_, _, _, _) -> error.
+
+simplify_has_map_fields(Fail, [Src|Keys0],
+ [{test,has_map_fields,Fail,[Src|Keys1]}|Acc]) ->
+ case are_keys_literals(Keys0) andalso are_keys_literals(Keys1) of
+ true ->
+ Keys = Keys0 ++ Keys1,
+ {ok,[{test,has_map_fields,Fail,[Src|Keys]}|Acc]};
+ false ->
+ error
+ end;
+simplify_has_map_fields(_, _, _) -> error.
+
+are_keys_literals([{x,_}|_]) -> false;
+are_keys_literals([{y,_}|_]) -> false;
+are_keys_literals([_|_]) -> true.
diff --git a/lib/compiler/src/beam_receive.erl b/lib/compiler/src/beam_receive.erl
deleted file mode 100644
index ddbe67605a..0000000000
--- a/lib/compiler/src/beam_receive.erl
+++ /dev/null
@@ -1,416 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
--module(beam_receive).
--export([module/2]).
--import(lists, [foldl/3,reverse/1,reverse/2]).
-
-%%%
-%%% In code such as:
-%%%
-%%% Ref = make_ref(), %Or erlang:monitor(process, Pid)
-%%% .
-%%% .
-%%% .
-%%% receive
-%%% {Ref,Reply} -> Reply
-%%% end.
-%%%
-%%% we know that none of the messages that exist in the message queue
-%%% before the call to make_ref/0 can be matched out in the receive
-%%% statement. Therefore we can avoid going through the entire message
-%%% queue if we introduce two new instructions (here written as
-%%% BIFs in pseudo-Erlang):
-%%%
-%%% recv_mark(SomeUniqInteger),
-%%% Ref = make_ref(),
-%%% .
-%%% .
-%%% .
-%%% recv_set(SomeUniqInteger),
-%%% receive
-%%% {Ref,Reply} -> Reply
-%%% end.
-%%%
-%%% The recv_mark/1 instruction will save the current position and
-%%% SomeUniqInteger in the process context. The recv_set
-%%% instruction will verify that SomeUniqInteger is still stored
-%%% in the process context. If it is, it will set the current pointer
-%%% for the message queue (the next message to be read out) to the
-%%% position that was saved by recv_mark/1.
-%%%
-%%% The remove_message instruction must be modified to invalidate
-%%% the information stored by the previous recv_mark/1, in case there
-%%% is another receive executed between the calls to recv_mark/1 and
-%%% recv_set/1.
-%%%
-%%% We use a reference to a label (i.e. a position in the loaded code)
-%%% as the SomeUniqInteger.
-%%%
-
--spec module(beam_utils:module_code(), [compile:option()]) ->
- {'ok',beam_utils:module_code()}.
-
-module({Mod,Exp,Attr,Fs0,Lc}, _Opts) ->
- Fs = [function(F) || F <- Fs0],
- Code = {Mod,Exp,Attr,Fs,Lc},
- {ok,Code}.
-
-%%%
-%%% Local functions.
-%%%
-
-function({function,Name,Arity,Entry,Is}) ->
- try
- D = beam_utils:index_labels(Is),
- {function,Name,Arity,Entry,opt(Is, D, [])}
- catch
- Class:Error:Stack ->
- io:fwrite("Function: ~w/~w\n", [Name,Arity]),
- erlang:raise(Class, Error, Stack)
- end.
-
-opt([{call_ext,A,{extfunc,erlang,spawn_monitor,A}}=I0|Is0], D, Acc)
- when A =:= 1; A =:= 3 ->
- case ref_in_tuple(Is0) of
- no ->
- opt(Is0, D, [I0|Acc]);
- {yes,Regs,Is1,MatchReversed} ->
- %% The call creates a brand new reference. Now
- %% search for a receive statement in the same
- %% function that will match against the reference.
- case opt_recv(Is1, Regs, D) of
- no ->
- opt(Is0, D, [I0|Acc]);
- {yes,Is,Lbl} ->
- opt(Is, D, MatchReversed++[I0,{recv_mark,{f,Lbl}}|Acc])
- end
- end;
-opt([{call_ext,Arity,{extfunc,erlang,Name,Arity}}=I|Is0], D, Acc) ->
- case creates_new_ref(Name, Arity) of
- true ->
- %% The call creates a brand new reference. Now
- %% search for a receive statement in the same
- %% function that will match against the reference.
- case opt_recv(Is0, regs_init_x0(), D) of
- no ->
- opt(Is0, D, [I|Acc]);
- {yes,Is,Lbl} ->
- opt(Is, D, [I,{recv_mark,{f,Lbl}}|Acc])
- end;
- false ->
- opt(Is0, D, [I|Acc])
- end;
-opt([I|Is], D, Acc) ->
- opt(Is, D, [I|Acc]);
-opt([], _, Acc) ->
- reverse(Acc).
-
-ref_in_tuple([{test,is_tuple,_,[{x,0}]}=I1,
- {test,test_arity,_,[{x,0},2]}=I2,
- {block,[{set,[_],[{x,0}],{get_tuple_element,0}},
- {set,[Dst],[{x,0}],{get_tuple_element,1}}|Bl]}=I3|Is]) ->
- ref_in_tuple_1(Bl, Dst, Is, [I3,I2,I1]);
-ref_in_tuple([{test,is_tuple,_,[{x,0}]}=I1,
- {test,test_arity,_,[{x,0},2]}=I2,
- {block,[{set,[Dst],[{x,0}],{get_tuple_element,1}}|Bl]}=I3|Is]) ->
- ref_in_tuple_1(Bl, Dst, Is, [I3,I2,I1]);
-ref_in_tuple(_) -> no.
-
-ref_in_tuple_1(Bl, Dst, Is, MatchReversed) ->
- Regs0 = regs_init_singleton(Dst),
- Regs = opt_update_regs_bl(Bl, Regs0),
- {yes,Regs,Is,MatchReversed}.
-
-%% creates_new_ref(Name, Arity) -> true|false.
-%% Return 'true' if the BIF Name/Arity will create a new reference.
-creates_new_ref(monitor, 2) -> true;
-creates_new_ref(make_ref, 0) -> true;
-creates_new_ref(_, _) -> false.
-
-%% opt_recv([Instruction], Regs, LabelIndex) -> no|{yes,[Instruction]}
-%% Search for a receive statement that will only retrieve messages
-%% that contain the newly created reference (which is currently in {x,0}).
-opt_recv(Is, Regs, D) ->
- L = gb_sets:empty(),
- opt_recv(Is, D, Regs, L, []).
-
-opt_recv([{label,L}=Lbl,{loop_rec,{f,Fail},_}=Loop|Is], D, R0, _, Acc) ->
- R = regs_kill_not_live(0, R0),
- case regs_empty(R) of
- false ->
- %% We now have the new reference in Y registers
- %% and the current instruction is the beginning of a
- %% receive statement. We must now verify that only messages
- %% that contain the reference will be matched.
- case opt_ref_used(Is, R, Fail, D) of
- false ->
- no;
- true ->
- RecvSet = {recv_set,{f,L}},
- {yes,reverse(Acc, [RecvSet,Lbl,Loop|Is]),L}
- end;
- true ->
- no
- end;
-opt_recv([I|Is], D, R0, L0, Acc) ->
- {R,L} = opt_update_regs(I, R0, L0),
- case regs_empty(R) of
- true ->
- %% The reference is no longer alive. There is no
- %% point in continuing the search.
- no;
- false ->
- opt_recv(Is, D, R, L, [I|Acc])
- end;
-opt_recv([], _, _, _, _) -> no.
-
-opt_update_regs({block,Bl}, R, L) ->
- {opt_update_regs_bl(Bl, R),L};
-opt_update_regs({call,_,_}, R, L) ->
- {regs_kill_not_live(0, R),L};
-opt_update_regs({call_ext,_,_}, R, L) ->
- {regs_kill_not_live(0, R),L};
-opt_update_regs({call_fun,_}, R, L) ->
- {regs_kill_not_live(0, R),L};
-opt_update_regs({kill,Y}, R, L) ->
- {regs_kill([Y], R),L};
-opt_update_regs({'catch',_,{f,Lbl}}, R, L) ->
- {R,gb_sets:add(Lbl, L)};
-opt_update_regs({catch_end,_}, R, L) ->
- {R,L};
-opt_update_regs({label,Lbl}, R, L) ->
- case gb_sets:is_member(Lbl, L) of
- false ->
- %% We can't allow arbitrary labels (since the receive
- %% could be entered without first creating the reference).
- {regs_init(),L};
- true ->
- %% A catch label for a previously seen catch instruction is OK.
- {R,L}
- end;
-opt_update_regs({'try',_,{f,Lbl}}, R, L) ->
- {R,gb_sets:add(Lbl, L)};
-opt_update_regs({try_end,_}, R, L) ->
- {R,L};
-opt_update_regs({line,_}, R, L) ->
- {R,L};
-opt_update_regs(_I, _R, L) ->
- %% Unrecognized instruction. Abort the search.
- {regs_init(),L}.
-
-opt_update_regs_bl([{set,Ds,_,{alloc,Live,_}}|Is], Regs0) ->
- Regs1 = regs_kill_not_live(Live, Regs0),
- Regs = regs_kill(Ds, Regs1),
- opt_update_regs_bl(Is, Regs);
-opt_update_regs_bl([{set,[Dst]=Ds,[Src],move}|Is], Regs0) ->
- Regs1 = regs_kill(Ds, Regs0),
- Regs = case regs_is_member(Src, Regs1) of
- false -> Regs1;
- true -> regs_add(Dst, Regs1)
- end,
- opt_update_regs_bl(Is, Regs);
-opt_update_regs_bl([{set,Ds,_,_}|Is], Regs0) ->
- Regs = regs_kill(Ds, Regs0),
- opt_update_regs_bl(Is, Regs);
-opt_update_regs_bl([], Regs) -> Regs.
-
-%% opt_ref_used([Instruction], RefRegs, FailLabel, LabelIndex) -> true|false
-%% Return 'true' if it is certain that only messages that contain the same
-%% reference as in RefRegs can be matched out. Otherwise return 'false'.
-%%
-%% Basically, we follow all possible paths through the receive statement.
-%% If all paths are safe, we return 'true'.
-%%
-%% A branch to FailLabel is safe, because it exits the receive statement
-%% and no further message may be matched out.
-%%
-%% If a path hits an comparision between RefRegs and part of the message,
-%% that path is safe (any messages that may be matched further down the
-%% path is guaranteed to contain the reference).
-%%
-%% Otherwise, if we hit a 'remove_message' instruction, we give up
-%% and return 'false' (the optimization is definitely unsafe). If
-%% we hit an unrecognized instruction, we also give up and return
-%% 'false' (the optimization may be unsafe).
-
-opt_ref_used(Is, RefRegs, Fail, D) ->
- Done = gb_sets:singleton(Fail),
- Regs = regs_init_x0(),
- try
- _ = opt_ref_used_1(Is, RefRegs, D, Done, Regs),
- true
- catch
- throw:not_used ->
- false
- end.
-
-%% This functions only returns if all paths through the receive
-%% statement are safe, and throws an 'not_used' term otherwise.
-opt_ref_used_1([{block,Bl}|Is], RefRegs, D, Done, Regs0) ->
- Regs = opt_ref_used_bl(Bl, Regs0),
- opt_ref_used_1(Is, RefRegs, D, Done, Regs);
-opt_ref_used_1([{test,is_eq_exact,{f,Fail},Args}|Is],
- RefRegs, D, Done0, Regs) ->
- Done = opt_ref_used_at(Fail, RefRegs, D, Done0, Regs),
- case is_ref_msg_comparison(Args, RefRegs, Regs) of
- false ->
- opt_ref_used_1(Is, RefRegs, D, Done, Regs);
- true ->
- %% The instructions that follow (Is) can only be executed
- %% if the message contains the same reference as in RefRegs.
- Done
- end;
-opt_ref_used_1([{test,is_ne_exact,{f,Fail},Args}|Is],
- RefRegs, D, Done0, Regs) ->
- Done = opt_ref_used_1(Is, RefRegs, D, Done0, Regs),
- case is_ref_msg_comparison(Args, RefRegs, Regs) of
- false ->
- opt_ref_used_at(Fail, RefRegs, D, Done, Regs);
- true ->
- Done
- end;
-opt_ref_used_1([{test,_,{f,Fail},_}|Is], RefRegs, D, Done0, Regs) ->
- Done = opt_ref_used_at(Fail, RefRegs, D, Done0, Regs),
- opt_ref_used_1(Is, RefRegs, D, Done, Regs);
-opt_ref_used_1([{select,_,_,{f,Fail},List}|_], RefRegs, D, Done, Regs) ->
- Lbls = [F || {f,F} <- List] ++ [Fail],
- opt_ref_used_in_all(Lbls, RefRegs, D, Done, Regs);
-opt_ref_used_1([{label,Lbl}|Is], RefRegs, D, Done, Regs) ->
- case gb_sets:is_member(Lbl, Done) of
- true -> Done;
- false -> opt_ref_used_1(Is, RefRegs, D, Done, Regs)
- end;
-opt_ref_used_1([{loop_rec_end,_}|_], _, _, Done, _) ->
- Done;
-opt_ref_used_1([_I|_], _RefReg, _D, _Done, _Regs) ->
- %% The optimization may be unsafe.
- throw(not_used).
-
-%% is_ref_msg_comparison(Args, RefRegs, RegisterSet) -> true|false.
-%% Return 'true' if Args denotes a comparison between the
-%% reference and message or part of the message.
-is_ref_msg_comparison([R1,R2], RefRegs, Regs) ->
- (regs_is_member(R2, RefRegs) andalso regs_is_member(R1, Regs)) orelse
- (regs_is_member(R1, RefRegs) andalso regs_is_member(R2, Regs)).
-
-opt_ref_used_in_all([L|Ls], RefRegs, D, Done0, Regs) ->
- Done = opt_ref_used_at(L, RefRegs, D, Done0, Regs),
- opt_ref_used_in_all(Ls, RefRegs, D, Done, Regs);
-opt_ref_used_in_all([], _, _, Done, _) -> Done.
-
-opt_ref_used_at(Fail, RefRegs, D, Done0, Regs) ->
- case gb_sets:is_member(Fail, Done0) of
- true ->
- Done0;
- false ->
- Is = beam_utils:code_at(Fail, D),
- Done = opt_ref_used_1(Is, RefRegs, D, Done0, Regs),
- gb_sets:add(Fail, Done)
- end.
-
-opt_ref_used_bl([{set,[],[],remove_message}|_], _) ->
- %% We have proved that a message that does not depend on the
- %% reference can be matched out.
- throw(not_used);
-opt_ref_used_bl([{set,Ds,Ss,_}|Is], Regs0) ->
- case regs_all_members(Ss, Regs0) of
- false ->
- %% The destination registers may be assigned values that
- %% are not dependent on the message being matched.
- Regs = regs_kill(Ds, Regs0),
- opt_ref_used_bl(Is, Regs);
- true ->
- %% All the sources depend on the message directly or
- %% indirectly.
- Regs = regs_add_list(Ds, Regs0),
- opt_ref_used_bl(Is, Regs)
- end;
-opt_ref_used_bl([], Regs) -> Regs.
-
-%%%
-%%% Functions for keeping track of a set of registers.
-%%%
-
-%% regs_init() -> RegisterSet
-%% Return an empty set of registers.
-
-regs_init() ->
- {0,0}.
-
-%% regs_init_singleton(Register) -> RegisterSet
-%% Return a set that only contains one register.
-
-regs_init_singleton(Reg) ->
- regs_add(Reg, regs_init()).
-
-%% regs_init_x0() -> RegisterSet
-%% Return a set that only contains the {x,0} register.
-
-regs_init_x0() ->
- {1 bsl 0,0}.
-
-%% regs_empty(Register) -> true|false
-%% Test whether the register set is empty.
-
-regs_empty(R) ->
- R =:= {0,0}.
-
-%% regs_kill_not_live(Live, RegisterSet) -> RegisterSet'
-%% Kill all registers indicated not live by Live.
-
-regs_kill_not_live(Live, {Xregs,Yregs}) ->
- {Xregs band ((1 bsl Live)-1),Yregs}.
-
-%% regs_kill([Register], RegisterSet) -> RegisterSet'
-%% Kill all registers mentioned in the list of registers.
-
-regs_kill([{x,N}|Rs], {Xregs,Yregs}) ->
- regs_kill(Rs, {Xregs band (bnot (1 bsl N)),Yregs});
-regs_kill([{y,N}|Rs], {Xregs,Yregs}) ->
- regs_kill(Rs, {Xregs,Yregs band (bnot (1 bsl N))});
-regs_kill([{fr,_}|Rs], Regs) ->
- regs_kill(Rs, Regs);
-regs_kill([], Regs) -> Regs.
-
-regs_add_list(List, Regs) ->
- foldl(fun(R, A) -> regs_add(R, A) end, Regs, List).
-
-%% regs_add(Register, RegisterSet) -> RegisterSet'
-%% Add a new register to the set of registers.
-
-regs_add({x,N}, {Xregs,Yregs}) ->
- {Xregs bor (1 bsl N),Yregs};
-regs_add({y,N}, {Xregs,Yregs}) ->
- {Xregs,Yregs bor (1 bsl N)}.
-
-%% regs_all_members([Register], RegisterSet) -> true|false
-%% Test whether all of the registers are part of the register set.
-
-regs_all_members([R|Rs], Regs) ->
- regs_is_member(R, Regs) andalso regs_all_members(Rs, Regs);
-regs_all_members([], _) -> true.
-
-%% regs_is_member(Register, RegisterSet) -> true|false
-%% Test whether Register is part of the register set.
-
-regs_is_member({x,N}, {Regs,_}) -> Regs band (1 bsl N) =/= 0;
-regs_is_member({y,N}, {_,Regs}) -> Regs band (1 bsl N) =/= 0;
-regs_is_member(_, _) -> false.
diff --git a/lib/compiler/src/beam_record.erl b/lib/compiler/src/beam_record.erl
deleted file mode 100644
index 58a6de6775..0000000000
--- a/lib/compiler/src/beam_record.erl
+++ /dev/null
@@ -1,131 +0,0 @@
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2014-2017. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%% Rewrite the instruction stream on tagged tuple tests.
-%% Tagged tuples means a tuple of any arity with an atom as its
-%% first element, such as records and error tuples.
-%%
-%% From:
-%% ...
-%% {test,is_tuple,Fail,[Src]}.
-%% {test,test_arity,Fail,[Src,Sz]}.
-%% ...
-%% {get_tuple_element,Src,0,Dst}.
-%% ...
-%% {test,is_eq_exact,Fail,[Dst,Atom]}.
-%% ...
-%% To:
-%% ...
-%% {test,is_tagged_tuple,Fail,[Src,Sz,Atom]}.
-%% ...
-%%
-
--module(beam_record).
--export([module/2]).
-
--import(lists, [reverse/1,reverse/2]).
-
--spec module(beam_utils:module_code(), [compile:option()]) ->
- {'ok',beam_utils:module_code()}.
-
-module({Mod,Exp,Attr,Fs0,Lc}, _Opt) ->
- Fs = [function(F) || F <- Fs0],
- {ok,{Mod,Exp,Attr,Fs,Lc}}.
-
-function({function,Name,Arity,CLabel,Is0}) ->
- try
- Is1 = beam_utils:anno_defs(Is0),
- Idx = beam_utils:index_labels(Is1),
- Is = rewrite(reverse(Is1), Idx),
- {function,Name,Arity,CLabel,Is}
- catch
- Class:Error:Stack ->
- io:fwrite("Function: ~w/~w\n", [Name,Arity]),
- erlang:raise(Class, Error, Stack)
- end.
-
-rewrite(Is, Idx) ->
- rewrite(Is, Idx, 0, []).
-
-rewrite([{test,test_arity,Fail,[Src,N]}=TA,
- {test,is_tuple,Fail,[Src]}=TT|Is], Idx, Def, Acc0) ->
- case is_tagged_tuple(Acc0, Def, Fail, Src, Idx) of
- no ->
- rewrite(Is, Idx, 0, [TT,TA|Acc0]);
- {yes,Atom,Acc} ->
- I = {test,is_tagged_tuple,Fail,[Src,N,Atom]},
- rewrite(Is, Idx, Def, [I|Acc])
- end;
-rewrite([{block,[{'%anno',{def,Def}}|Bl]}|Is], Idx, _Def, Acc) ->
- rewrite(Is, Idx, Def, [{block,Bl}|Acc]);
-rewrite([{label,L}=I|Is], Idx0, Def, Acc) ->
- Idx = beam_utils:index_label(L, Acc, Idx0),
- rewrite(Is, Idx, Def, [I|Acc]);
-rewrite([I|Is], Idx, Def, Acc) ->
- rewrite(Is, Idx, Def, [I|Acc]);
-rewrite([], _, _, Acc) -> Acc.
-
-is_tagged_tuple([{block,Bl},
- {test,is_eq_exact,Fail,[Dst,{atom,_}=Atom]}|Is],
- Def, Fail, Src, Idx) ->
- case is_tagged_tuple_1(Bl, Is, Fail, Src, Dst, Idx, Def, []) of
- no ->
- no;
- {yes,[]} ->
- {yes,Atom,Is};
- {yes,[_|_]=Block} ->
- {yes,Atom,[{block,Block}|Is]}
- end;
-is_tagged_tuple(_, _, _, _, _) ->
- no.
-
-is_tagged_tuple_1([{set,[Dst],[Src],{get_tuple_element,0}}=I|Bl],
- Is, Fail, Src, Dst, Idx, Def, Acc) ->
- %% Check usage of Dst to find out whether the get_tuple_element
- %% is needed.
- case usage(Dst, Is, Fail, Idx) of
- killed ->
- %% Safe to remove the get_tuple_element instruction.
- {yes,reverse(Acc, Bl)};
- used ->
- %% Actively used. Must keep instruction.
- {yes,reverse(Acc, [I|Bl])};
- not_used ->
- %% Not actually used (but must be initialized).
- case is_defined(Dst, Def) of
- false ->
- %% Dst must be initialized, but the
- %% actual value does not matter.
- Kill = {set,[Dst],[nil],move},
- {yes,reverse(Acc, [Kill|Bl])};
- true ->
- %% The register is previously initialized.
- %% We can remove the instruction.
- {yes,reverse(Acc, Bl)}
- end
- end;
-is_tagged_tuple_1([I|Bl], Is, Fail, Src, Dst, Idx, Def, Acc) ->
- is_tagged_tuple_1(Bl, Is, Fail, Src, Dst, Idx, Def, [I|Acc]);
-is_tagged_tuple_1(_, _, _, _, _, _, _, _) ->
- no.
-
-usage(Dst, Is, Fail, Idx) ->
- beam_utils:usage(Dst, [{test,is_number,Fail,[nil]}|Is], Idx).
-
-is_defined({x,X}, Def) ->
- (Def bsr X) band 1 =:= 1.
diff --git a/lib/compiler/src/beam_reorder.erl b/lib/compiler/src/beam_reorder.erl
deleted file mode 100644
index 8d2ef5a431..0000000000
--- a/lib/compiler/src/beam_reorder.erl
+++ /dev/null
@@ -1,150 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
--module(beam_reorder).
-
--export([module/2]).
--import(lists, [member/2,reverse/1]).
-
--spec module(beam_utils:module_code(), [compile:option()]) ->
- {'ok',beam_utils:module_code()}.
-
-module({Mod,Exp,Attr,Fs0,Lc}, _Opt) ->
- Fs = [function(F) || F <- Fs0],
- {ok,{Mod,Exp,Attr,Fs,Lc}}.
-
-function({function,Name,Arity,CLabel,Is0}) ->
- try
- Is = reorder(Is0),
- {function,Name,Arity,CLabel,Is}
- catch
- Class:Error:Stack ->
- io:fwrite("Function: ~w/~w\n", [Name,Arity]),
- erlang:raise(Class, Error, Stack)
- end.
-
-%% reorder(Instructions0) -> Instructions
-%% Reorder instructions before the beam_block pass, because reordering
-%% will be more cumbersome when the blocks are in place.
-%%
-%% Execution of get_tuple_element instructions can be delayed until
-%% they are actually needed. Consider the sequence:
-%%
-%% get_tuple_element Tuple Pos Dst
-%% test Test Fail Operands
-%%
-%% If Dst is killed at label Fail (and not referenced in Operands),
-%% we can can swap the instructions:
-%%
-%% test Test Fail Operands
-%% get_tuple_element Tuple Pos Dst
-%%
-%% That can be beneficial in two ways: Firstly, if the branch is taken
-%% we have avoided execution of the get_tuple_element instruction.
-%% Secondly, even if the branch is not taken, subsequent optimization
-%% (opt_blocks/1) may be able to change Dst to the final destination
-%% register and eliminate a 'move' instruction.
-
-reorder(Is) ->
- D = beam_utils:index_labels(Is),
- reorder_1(Is, D, []).
-
-reorder_1([{Op,_,_}=TryCatch|[I|Is]=Is0], D, Acc)
- when Op =:= 'catch'; Op =:= 'try' ->
- %% Don't allow 'try' or 'catch' instructions to split blocks if
- %% it can be avoided.
- case is_safe(I) of
- false ->
- reorder_1(Is0, D, [TryCatch|Acc]);
- true ->
- reorder_1([TryCatch|Is], D, [I|Acc])
- end;
-reorder_1([{label,L}=I|_], D, Acc) ->
- Is = beam_utils:code_at(L, D),
- reorder_1(Is, D, [I|Acc]);
-reorder_1([{test,is_nonempty_list,_,_}=I|Is], D, Acc) ->
- %% The run-time system may combine the is_nonempty_list test with
- %% the following get_list instruction.
- reorder_1(Is, D, [I|Acc]);
-reorder_1([{test,_,_,_}=I,
- {select,_,_,_,_}=S|Is], D, Acc) ->
- %% There is nothing to gain by inserting a get_tuple_element
- %% instruction between the test instruction and the select
- %% instruction.
- reorder_1(Is, D, [S,I|Acc]);
-reorder_1([{test,_,{f,_},[Src|_]}=I|Is], D,
- [{get_tuple_element,Src,_,_}|_]=Acc) ->
- %% We want to avoid code that can confuse beam_validator such as:
- %% is_tuple Fail Src
- %% test_arity Fail Src Arity
- %% is_map Fail Src
- %% get_tuple_element Src Pos Dst
- %% Therefore, don't reorder the instructions in such cases.
- reorder_1(Is, D, [I|Acc]);
-reorder_1([{test,_,{f,L},Ss}=I|Is0], D0,
- [{get_tuple_element,_,_,El}=G|Acc0]=Acc) ->
- case member(El, Ss) of
- true ->
- reorder_1(Is0, D0, [I|Acc]);
- false ->
- case beam_utils:is_killed_at(El, L, D0) of
- true ->
- Is = [I,G|Is0],
- reorder_1(Is, D0, Acc0);
- false ->
- case beam_utils:is_killed(El, Is0, D0) of
- true ->
- Code0 = beam_utils:code_at(L, D0),
- Code = [G|Code0],
- D = beam_utils:index_label(L, Code, D0),
- Is = [I|Is0],
- reorder_1(Is, D, Acc0);
- false ->
- reorder_1(Is0, D0, [I|Acc])
- end
- end
- end;
-reorder_1([{allocate_zero,N,Live}=I0|Is], D,
- [{get_tuple_element,{x,Tup},_,{x,Dst}}=G|Acc]=Acc0) ->
- case Tup < Dst andalso Dst+1 =:= Live of
- true ->
- %% Move allocation instruction upwards past
- %% get_tuple_element instructions to create more
- %% opportunities for moving get_tuple_element
- %% instructions.
- I = {allocate_zero,N,Dst},
- reorder_1([I,G|Is], D, Acc);
- false ->
- reorder_1(Is, D, [I0|Acc0])
- end;
-reorder_1([I|Is], D, Acc) ->
- reorder_1(Is, D, [I|Acc]);
-reorder_1([], _, Acc) -> reverse(Acc).
-
-%% is_safe(Instruction) -> true|false
-%% Test whether an instruction is safe (cannot cause an exception).
-
-is_safe({kill,_}) -> true;
-is_safe({move,_,_}) -> true;
-is_safe({put,_}) -> true;
-is_safe({put_list,_,_,_}) -> true;
-is_safe({put_tuple,_,_}) -> true;
-is_safe({test_heap,_,_}) -> true;
-is_safe(_) -> false.
diff --git a/lib/compiler/src/beam_split.erl b/lib/compiler/src/beam_split.erl
deleted file mode 100644
index 809e49b3d0..0000000000
--- a/lib/compiler/src/beam_split.erl
+++ /dev/null
@@ -1,94 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2011-2018. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
--module(beam_split).
--export([module/2]).
-
--import(lists, [reverse/1]).
-
--spec module(beam_utils:module_code(), [compile:option()]) ->
- {'ok',beam_utils:module_code()}.
-
-module({Mod,Exp,Attr,Fs0,Lc}, _Opts) ->
- Fs = [split_blocks(F) || F <- Fs0],
- {ok,{Mod,Exp,Attr,Fs,Lc}}.
-
-%% We must split the basic block when we encounter instructions with labels,
-%% such as catches and BIFs. All labels must be visible outside the blocks.
-
-split_blocks({function,Name,Arity,CLabel,Is0}) ->
- Is = split_blocks(Is0, []),
- {function,Name,Arity,CLabel,Is}.
-
-split_blocks([{block,Bl}|Is], Acc0) ->
- Acc = split_block(Bl, [], Acc0),
- split_blocks(Is, Acc);
-split_blocks([I|Is], Acc) ->
- split_blocks(Is, [I|Acc]);
-split_blocks([], Acc) -> reverse(Acc).
-
-split_block([{set,[R],[_,_,_]=As,{bif,is_record,{f,Lbl}}}|Is], Bl, Acc) ->
- %% is_record/3 must be translated by beam_clean; therefore,
- %% it must be outside of any block.
- split_block(Is, [], [{bif,is_record,{f,Lbl},As,R}|make_block(Bl, Acc)]);
-split_block([{set,[R],As,{bif,N,{f,Lbl}=Fail}}|Is], Bl, Acc) when Lbl =/= 0 ->
- split_block(Is, [], [{bif,N,Fail,As,R}|make_block(Bl, Acc)]);
-split_block([{set,[],[],{line,_}=Line},
- {set,[R],As,{bif,raise,{f,_}=Fail}}|Is], Bl, Acc) ->
- split_block(Is, [], [{bif,raise,Fail,As,R},Line|make_block(Bl, Acc)]);
-split_block([{set,[R],As,{alloc,Live,{gc_bif,N,{f,Lbl}=Fail}}}|Is], Bl, Acc)
- when Lbl =/= 0 ->
- split_block(Is, [], [{gc_bif,N,Fail,Live,As,R}|make_block(Bl, Acc)]);
-split_block([{set,[D],[S|Puts],{alloc,R,{put_map,Op,{f,Lbl}=Fail}}}|Is],
- Bl, Acc) when Lbl =/= 0 ->
- split_block(Is, [], [{put_map,Fail,Op,S,D,R,{list,Puts}}|
- make_block(Bl, Acc)]);
-split_block([{set,[R],[],{try_catch,Op,L}}|Is], Bl, Acc) ->
- split_block(Is, [], [{Op,R,L}|make_block(Bl, Acc)]);
-split_block([I|Is], Bl, Acc) ->
- split_block(Is, [I|Bl], Acc);
-split_block([], Bl, Acc) -> make_block(Bl, Acc).
-
-make_block([], Acc) -> Acc;
-make_block([{set,[D],Ss,{bif,Op,Fail}}|Bl]=Bl0, Acc) ->
- %% If the last instruction in the block is a comparison or boolean operator
- %% (such as '=:='), move it out of the block to facilitate further
- %% optimizations.
- Arity = length(Ss),
- case erl_internal:comp_op(Op, Arity) orelse
- erl_internal:new_type_test(Op, Arity) orelse
- erl_internal:bool_op(Op, Arity) of
- false ->
- [{block,reverse(Bl0)}|Acc];
- true ->
- I = {bif,Op,Fail,Ss,D},
- case Bl =:= [] of
- true -> [I|Acc];
- false -> [I,{block,reverse(Bl)}|Acc]
- end
- end;
-make_block([{set,[Dst],[Src],move}|Bl], Acc) ->
- %% Make optimization of {move,Src,Dst}, {jump,...} possible.
- I = {move,Src,Dst},
- case Bl =:= [] of
- true -> [I|Acc];
- false -> [I,{block,reverse(Bl)}|Acc]
- end;
-make_block(Bl, Acc) -> [{block,reverse(Bl)}|Acc].
diff --git a/lib/compiler/src/beam_ssa.erl b/lib/compiler/src/beam_ssa.erl
new file mode 100644
index 0000000000..9d10d4aec3
--- /dev/null
+++ b/lib/compiler/src/beam_ssa.erl
@@ -0,0 +1,771 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+%% Purpose: Type definitions and utilities for the SSA format.
+
+-module(beam_ssa).
+-export([add_anno/3,get_anno/2,
+ clobbers_xregs/1,def/2,def_used/2,dominators/1,
+ flatmapfold_instrs_rpo/4,
+ fold_po/3,fold_po/4,fold_rpo/3,fold_rpo/4,
+ fold_instrs_rpo/4,
+ linearize/1,
+ mapfold_instrs_rpo/4,
+ normalize/1,
+ no_side_effect/1,
+ predecessors/1,
+ rename_vars/3,
+ rpo/1,rpo/2,
+ split_blocks/3,
+ successors/1,successors/2,
+ trim_unreachable/1,
+ update_phi_labels/4,used/1]).
+
+-export_type([b_module/0,b_function/0,b_blk/0,b_set/0,
+ b_ret/0,b_br/0,b_switch/0,terminator/0,
+ b_var/0,b_literal/0,b_remote/0,b_local/0,
+ value/0,argument/0,label/0,
+ var_name/0,var_base/0,literal_value/0,
+ op/0,anno/0,block_map/0]).
+
+-include("beam_ssa.hrl").
+
+-type b_module() :: #b_module{}.
+-type b_function() :: #b_function{}.
+-type b_blk() :: #b_blk{}.
+-type b_set() :: #b_set{}.
+
+-type b_br() :: #b_br{}.
+-type b_ret() :: #b_ret{}.
+-type b_switch() :: #b_switch{}.
+-type terminator() :: b_br() | b_ret() | b_switch().
+
+-type b_var() :: #b_var{}.
+-type b_literal() :: #b_literal{}.
+-type b_remote() :: #b_remote{}.
+-type b_local() :: #b_local{}.
+
+-type value() :: b_var() | b_literal().
+-type phi_value() :: {value(),label()}.
+-type argument() :: value() | b_remote() | b_local() | phi_value().
+-type label() :: non_neg_integer().
+
+-type var_name() :: var_base() | {var_base(),non_neg_integer()}.
+-type var_base() :: atom() | non_neg_integer().
+
+-type literal_value() :: atom() | integer() | float() | list() |
+ nil() | tuple() | map() | binary().
+
+-type op() :: {'bif',atom()} | {'float',float_op()} | prim_op() | cg_prim_op().
+-type anno() :: #{atom() := any()}.
+
+-type block_map() :: #{label():=b_blk()}.
+
+%% Note: By default, dialyzer will collapse this type to atom().
+%% To avoid the collapsing, change the value of SET_LIMIT to 50 in the
+%% file erl_types.erl in the hipe application.
+
+-type prim_op() :: 'bs_add' | 'bs_extract' | 'bs_init' | 'bs_init_writable' |
+ 'bs_match' | 'bs_put' | 'bs_start_match' | 'bs_test_tail' |
+ 'bs_utf16_size' | 'bs_utf8_size' | 'build_stacktrace' |
+ 'call' | 'catch_end' | 'context_to_binary' |
+ 'extract' |
+ 'get_hd' | 'get_map_element' | 'get_tl' | 'get_tuple_element' |
+ 'has_map_field' |
+ 'is_nonempty_list' | 'is_tagged_tuple' |
+ 'kill_try_tag' |
+ 'landingpad' |
+ 'make_fun' | 'new_try_tag' |
+ 'peek_message' | 'phi' | 'put_list' | 'put_map' | 'put_tuple' |
+ 'raw_raise' | 'recv_next' | 'remove_message' | 'resume' |
+ 'set_tuple_element' | 'succeeded' |
+ 'timeout' |
+ 'wait' | 'wait_timeout'.
+
+-type float_op() :: 'checkerror' | 'clearerror' | 'convert' | 'get' | 'put' |
+ '+' | '-' | '*' | '/'.
+
+%% Primops only used internally during code generation.
+-type cg_prim_op() :: 'bs_get' | 'bs_match_string' | 'bs_restore' | 'bs_skip' |
+'copy' | 'put_tuple_arity' | 'put_tuple_element'.
+
+-import(lists, [foldl/3,keyfind/3,mapfoldl/3,member/2,reverse/1]).
+
+-spec add_anno(Key, Value, Construct) -> Construct when
+ Key :: atom(),
+ Value :: any(),
+ Construct :: b_function() | b_blk() | b_set() | terminator().
+
+add_anno(Key, Val, #b_function{anno=Anno}=Bl) ->
+ Bl#b_function{anno=Anno#{Key=>Val}};
+add_anno(Key, Val, #b_blk{anno=Anno}=Bl) ->
+ Bl#b_blk{anno=Anno#{Key=>Val}};
+add_anno(Key, Val, #b_set{anno=Anno}=Bl) ->
+ Bl#b_set{anno=Anno#{Key=>Val}};
+add_anno(Key, Val, #b_br{anno=Anno}=Bl) ->
+ Bl#b_br{anno=Anno#{Key=>Val}};
+add_anno(Key, Val, #b_ret{anno=Anno}=Bl) ->
+ Bl#b_ret{anno=Anno#{Key=>Val}};
+add_anno(Key, Val, #b_switch{anno=Anno}=Bl) ->
+ Bl#b_switch{anno=Anno#{Key=>Val}}.
+
+-spec get_anno(atom(), b_blk()|b_set()|terminator()) -> any().
+
+get_anno(Key, Construct) ->
+ maps:get(Key, get_anno(Construct)).
+
+get_anno(#b_blk{anno=Anno}) -> Anno;
+get_anno(#b_set{anno=Anno}) -> Anno;
+get_anno(#b_br{anno=Anno}) -> Anno;
+get_anno(#b_ret{anno=Anno}) -> Anno;
+get_anno(#b_switch{anno=Anno}) -> Anno.
+
+%% clobbers_xregs(#b_set{}) -> true|false.
+%% Test whether the instruction invalidates all X registers.
+
+-spec clobbers_xregs(b_set()) -> boolean().
+
+clobbers_xregs(#b_set{op=Op}) ->
+ case Op of
+ bs_init_writable -> true;
+ build_stacktrace -> true;
+ call -> true;
+ landingpad -> true;
+ make_fun -> true;
+ peek_message -> true;
+ raw_raise -> true;
+ _ -> false
+ end.
+
+%% no_side_effect(#b_set{}) -> true|false.
+%% Test whether this instruction has no side effect and thus is safe
+%% not to execute if its value is not used. Note that even if `true`
+%% is returned, the instruction could still be impure (e.g. bif:get).
+
+-spec no_side_effect(b_set()) -> boolean().
+
+no_side_effect(#b_set{op=Op}) ->
+ case Op of
+ {bif,_} -> true;
+ {float,get} -> true;
+ bs_init -> true;
+ bs_extract -> true;
+ bs_match -> true;
+ bs_start_match -> true;
+ bs_test_tail -> true;
+ bs_put -> true;
+ extract -> true;
+ get_hd -> true;
+ get_tl -> true;
+ get_tuple_element -> true;
+ has_map_field -> true;
+ is_nonempty_list -> true;
+ is_tagged_tuple -> true;
+ put_map -> true;
+ put_list -> true;
+ put_tuple -> true;
+ succeeded -> true;
+ _ -> false
+ end.
+
+-spec predecessors(Blocks) -> #{BlockNumber:=[Predecessor]} when
+ Blocks :: block_map(),
+ BlockNumber :: label(),
+ Predecessor :: label().
+
+predecessors(Blocks) ->
+ P0 = [{S,L} || {L,Blk} <- maps:to_list(Blocks),
+ S <- successors(Blk)],
+ P1 = sofs:relation(P0),
+ P2 = sofs:rel2fam(P1),
+ P3 = sofs:to_external(P2),
+ P = [{0,[]}|P3],
+ maps:from_list(P).
+
+-spec successors(b_blk()) -> [label()].
+
+successors(#b_blk{last=Terminator}) ->
+ case Terminator of
+ #b_br{bool=#b_literal{val=true},succ=Succ} ->
+ [Succ];
+ #b_br{bool=#b_literal{val=false},fail=Fail} ->
+ [Fail];
+ #b_br{succ=Succ,fail=Fail} ->
+ [Fail,Succ];
+ #b_switch{fail=Fail,list=List} ->
+ [Fail|[L || {_,L} <- List]];
+ #b_ret{} ->
+ []
+ end.
+
+%% normalize(Instr0) -> Instr.
+%% Normalize instructions to help optimizations.
+%%
+%% For commutative operators (such as '+' and 'or'), always
+%% place a variable operand before a literal operand.
+%%
+%% Normalize #b_br{} to one of the following forms:
+%%
+%% #b_br{b_literal{val=true},succ=Label,fail=Label}
+%% #b_br{b_var{},succ=Label1,fail=Label2} where Label1 =/= Label2
+%%
+%% Simplify a #b_switch{} with a literal argument to a #b_br{}.
+%%
+%% Simplify a #b_switch{} with a variable argument and an empty
+%% switch list to a #b_br{}.
+
+-spec normalize(b_set() | terminator()) ->
+ b_set() | terminator().
+
+normalize(#b_set{op={bif,Bif},args=Args}=Set) ->
+ case {is_commutative(Bif),Args} of
+ {false,_} ->
+ Set;
+ {true,[#b_literal{}=Lit,#b_var{}=Var]} ->
+ Set#b_set{args=[Var,Lit]};
+ {true,_} ->
+ Set
+ end;
+normalize(#b_set{}=Set) ->
+ Set;
+normalize(#b_br{}=Br) ->
+ case Br of
+ #b_br{bool=Bool,succ=Same,fail=Same} ->
+ case Bool of
+ #b_literal{val=true} ->
+ Br;
+ _ ->
+ Br#b_br{bool=#b_literal{val=true}}
+ end;
+ #b_br{bool=#b_literal{val=true},succ=Succ} ->
+ Br#b_br{fail=Succ};
+ #b_br{bool=#b_literal{val=false},fail=Fail} ->
+ Br#b_br{bool=#b_literal{val=true},succ=Fail};
+ #b_br{} ->
+ Br
+ end;
+normalize(#b_switch{arg=Arg,fail=Fail,list=List}=Sw) ->
+ case Arg of
+ #b_literal{} ->
+ case keyfind(Arg, 1, List) of
+ false ->
+ #b_br{bool=#b_literal{val=true},succ=Fail,fail=Fail};
+ {Arg,L} ->
+ #b_br{bool=#b_literal{val=true},succ=L,fail=L}
+ end;
+ #b_var{} when List =:= [] ->
+ #b_br{bool=#b_literal{val=true},succ=Fail,fail=Fail};
+ #b_var{} ->
+ Sw
+ end;
+normalize(#b_ret{}=Ret) ->
+ Ret.
+
+-spec successors(label(), block_map()) -> [label()].
+
+successors(L, Blocks) ->
+ successors(maps:get(L, Blocks)).
+
+-spec def(Ls, Blocks) -> Def when
+ Ls :: [label()],
+ Blocks :: block_map(),
+ Def :: ordsets:ordset(var_name()).
+
+def(Ls, Blocks) ->
+ Top = rpo(Ls, Blocks),
+ Blks = [maps:get(L, Blocks) || L <- Top],
+ def_1(Blks, []).
+
+-spec def_used(Ls, Blocks) -> {Def,Used} when
+ Ls :: [label()],
+ Blocks :: block_map(),
+ Def :: ordsets:ordset(var_name()),
+ Used :: ordsets:ordset(var_name()).
+
+def_used(Ls, Blocks) ->
+ Top = rpo(Ls, Blocks),
+ Blks = [maps:get(L, Blocks) || L <- Top],
+ Preds = gb_sets:from_list(Top),
+ def_used_1(Blks, Preds, [], gb_sets:empty()).
+
+-spec dominators(Blocks) -> Result when
+ Blocks :: block_map(),
+ Result :: #{label():=ordsets:ordset(label())}.
+
+dominators(Blocks) ->
+ Preds = predecessors(Blocks),
+ Top0 = rpo(Blocks),
+ Top = [{L,maps:get(L, Preds)} || L <- Top0],
+
+ %% The flow graph for an Erlang function is reducible, and
+ %% therefore one traversal in reverse postorder is sufficient.
+ iter_dominators(Top, #{}).
+
+-spec fold_instrs_rpo(Fun, From, Acc0, Blocks) -> any() when
+ Fun :: fun((b_blk()|terminator(), any()) -> any()),
+ From :: [label()],
+ Acc0 :: any(),
+ Blocks :: block_map().
+
+fold_instrs_rpo(Fun, From, Acc0, Blocks) ->
+ Top = rpo(From, Blocks),
+ fold_instrs_rpo_1(Top, Fun, Blocks, Acc0).
+
+-spec mapfold_instrs_rpo(Fun, From, Acc0, Blocks0) -> {Blocks,Acc} when
+ Fun :: fun((b_blk()|terminator(), any()) -> any()),
+ From :: [label()],
+ Acc0 :: any(),
+ Acc :: any(),
+ Blocks0 :: block_map(),
+ Blocks :: block_map().
+
+mapfold_instrs_rpo(Fun, From, Acc0, Blocks) ->
+ Top = rpo(From, Blocks),
+ mapfold_instrs_rpo_1(Top, Fun, Blocks, Acc0).
+
+-spec flatmapfold_instrs_rpo(Fun, From, Acc0, Blocks0) -> {Blocks,Acc} when
+ Fun :: fun((b_blk()|terminator(), any()) -> any()),
+ From :: [label()],
+ Acc0 :: any(),
+ Acc :: any(),
+ Blocks0 :: block_map(),
+ Blocks :: block_map().
+
+flatmapfold_instrs_rpo(Fun, From, Acc0, Blocks) ->
+ Top = rpo(From, Blocks),
+ flatmapfold_instrs_rpo_1(Top, Fun, Blocks, Acc0).
+
+-type fold_fun() :: fun((label(), b_blk(), any()) -> any()).
+
+%% fold_rpo(Fun, [Label], Acc0, Blocks) -> Acc.
+%% Fold over all blocks a reverse postorder traversal of the block
+%% graph; that is, first visit a block, then visit its successors.
+
+-spec fold_rpo(Fun, Acc0, Blocks) -> any() when
+ Fun :: fold_fun(),
+ Acc0 :: any(),
+ Blocks :: #{label():=b_blk()}.
+
+fold_rpo(Fun, Acc0, Blocks) ->
+ fold_rpo(Fun, [0], Acc0, Blocks).
+
+%% fold_rpo(Fun, [Label], Acc0, Blocks) -> Acc. Fold over all blocks
+%% reachable from a given set of labels in a reverse postorder
+%% traversal of the block graph; that is, first visit a block, then
+%% visit its successors.
+
+-spec fold_rpo(Fun, Labels, Acc0, Blocks) -> any() when
+ Fun :: fold_fun(),
+ Labels :: [label()],
+ Acc0 :: any(),
+ Blocks :: #{label():=b_blk()}.
+
+fold_rpo(Fun, From, Acc0, Blocks) ->
+ Top = rpo(From, Blocks),
+ fold_rpo_1(Top, Fun, Blocks, Acc0).
+
+%% fold_po(Fun, Acc0, Blocks) -> Acc.
+%% Fold over all blocks in a postorder traversal of the block graph;
+%% that is, first visit all successors of block, then the block
+%% itself.
+
+-spec fold_po(Fun, Acc0, Blocks) -> any() when
+ Fun :: fold_fun(),
+ Acc0 :: any(),
+ Blocks :: #{label():=b_blk()}.
+
+%% fold_po(Fun, From, Acc0, Blocks) -> Acc.
+%% Fold over the blocks reachable from the block numbers given
+%% by From in a postorder traversal of the block graph.
+
+fold_po(Fun, Acc0, Blocks) ->
+ fold_po(Fun, [0], Acc0, Blocks).
+
+-spec fold_po(Fun, Labels, Acc0, Blocks) -> any() when
+ Fun :: fold_fun(),
+ Labels :: [label()],
+ Acc0 :: any(),
+ Blocks :: block_map().
+
+fold_po(Fun, From, Acc0, Blocks) ->
+ Top = reverse(rpo(From, Blocks)),
+ fold_rpo_1(Top, Fun, Blocks, Acc0).
+
+%% linearize(Blocks) -> [{BlockLabel,#b_blk{}}].
+%% Linearize the intermediate representation of the code.
+%% Unreachable blocks will be discarded, and phi nodes will
+%% be adjusted so that they no longer refers to discarded
+%% blocks or to blocks that no longer are predecessors of
+%% the phi node block.
+
+-spec linearize(Blocks) -> Linear when
+ Blocks :: block_map(),
+ Linear :: [{label(),b_blk()}].
+
+linearize(Blocks) ->
+ Seen = cerl_sets:new(),
+ {Linear0,_} = linearize_1([0], Blocks, Seen, []),
+ Linear = fix_phis(Linear0, #{}),
+ Linear.
+
+-spec rpo(Blocks) -> [Label] when
+ Blocks :: block_map(),
+ Label :: label().
+
+rpo(Blocks) ->
+ rpo([0], Blocks).
+
+-spec rpo(From, Blocks) -> Labels when
+ From :: [label()],
+ Blocks :: block_map(),
+ Labels :: [label()].
+
+rpo(From, Blocks) ->
+ Seen = cerl_sets:new(),
+ {Ls,_} = rpo_1(From, Blocks, Seen, []),
+ Ls.
+
+-spec rename_vars(Rename, [label()], block_map()) -> block_map() when
+ Rename :: [{var_name(),value()}] | #{var_name():=value()}.
+
+rename_vars(Rename, From, Blocks) when is_list(Rename) ->
+ rename_vars(maps:from_list(Rename), From, Blocks);
+rename_vars(Rename, From, Blocks) when is_map(Rename)->
+ Top = rpo(From, Blocks),
+ Preds = cerl_sets:from_list(Top),
+ F = fun(#b_set{op=phi,args=Args0}=Set) ->
+ Args = rename_phi_vars(Args0, Preds, Rename),
+ Set#b_set{args=Args};
+ (#b_set{args=Args0}=Set) ->
+ Args = [rename_var(A, Rename) || A <- Args0],
+ Set#b_set{args=Args};
+ (#b_switch{arg=Bool}=Sw) ->
+ Sw#b_switch{arg=rename_var(Bool, Rename)};
+ (#b_br{bool=Bool}=Br) ->
+ Br#b_br{bool=rename_var(Bool, Rename)};
+ (#b_ret{arg=Arg}=Ret) ->
+ Ret#b_ret{arg=rename_var(Arg, Rename)}
+ end,
+ map_instrs_1(Top, F, Blocks).
+
+%% split_blocks(Predicate, Blocks0, Count0) -> {Blocks,Count}.
+%% Call Predicate(Instruction) for each instruction in all
+%% blocks. If Predicate/1 returns true, split the block
+%% before this instruction.
+
+-spec split_blocks(Pred, Blocks0, Count0) -> {Blocks,Count} when
+ Pred :: fun((b_set()) -> boolean()),
+ Blocks :: block_map(),
+ Count0 :: beam_ssa:label(),
+ Blocks0 :: block_map(),
+ Blocks :: block_map(),
+ Count :: beam_ssa:label().
+
+split_blocks(P, Blocks, Count) ->
+ Ls = beam_ssa:rpo(Blocks),
+ split_blocks_1(Ls, P, Blocks, Count).
+
+-spec trim_unreachable(Blocks0) -> Blocks when
+ Blocks0 :: block_map(),
+ Blocks :: block_map().
+
+%% trim_unreachable(Blocks0) -> Blocks.
+%% Remove all unreachable blocks. Adjust all phi nodes so
+%% they don't refer to blocks that has been removed or no
+%% no longer branch to the phi node in question.
+
+trim_unreachable(Blocks) ->
+ %% Could perhaps be optimized if there is any need.
+ maps:from_list(linearize(Blocks)).
+
+%% update_phi_labels([BlockLabel], Old, New, Blocks0) -> Blocks.
+%% In the given blocks, replace label Old in with New in all
+%% phi nodes. This is useful after merging or splitting
+%% blocks.
+
+-spec update_phi_labels(From, Old, New, Blocks0) -> Blocks when
+ From :: [label()],
+ Old :: label(),
+ New :: label(),
+ Blocks0 :: block_map(),
+ Blocks :: block_map().
+
+update_phi_labels([L|Ls], Old, New, Blocks0) ->
+ case Blocks0 of
+ #{L:=#b_blk{is=[#b_set{op=phi}|_]=Is0}=Blk0} ->
+ Is = update_phi_labels_is(Is0, Old, New),
+ Blk = Blk0#b_blk{is=Is},
+ Blocks = Blocks0#{L:=Blk},
+ update_phi_labels(Ls, Old, New, Blocks);
+ #{L:=#b_blk{}} ->
+ %% No phi nodes in this block.
+ update_phi_labels(Ls, Old, New, Blocks0)
+ end;
+update_phi_labels([], _, _, Blocks) -> Blocks.
+
+-spec used(b_blk() | b_set() | terminator()) -> [var_name()].
+
+used(#b_blk{is=Is,last=Last}) ->
+ used_1([Last|Is], ordsets:new());
+used(#b_br{bool=#b_var{}=V}) ->
+ [V];
+used(#b_ret{arg=#b_var{}=V}) ->
+ [V];
+used(#b_set{op=phi,args=Args}) ->
+ ordsets:from_list([V || {#b_var{}=V,_} <- Args]);
+used(#b_set{args=Args}) ->
+ ordsets:from_list(used_args(Args));
+used(#b_switch{arg=#b_var{}=V}) ->
+ [V];
+used(_) -> [].
+
+%%%
+%%% Internal functions.
+%%%
+
+is_commutative('and') -> true;
+is_commutative('or') -> true;
+is_commutative('xor') -> true;
+is_commutative('band') -> true;
+is_commutative('bor') -> true;
+is_commutative('bxor') -> true;
+is_commutative('+') -> true;
+is_commutative('*') -> true;
+is_commutative('=:=') -> true;
+is_commutative('==') -> true;
+is_commutative('=/=') -> true;
+is_commutative('/=') -> true;
+is_commutative(_) -> false.
+
+def_used_1([#b_blk{is=Is,last=Last}|Bs], Preds, Def0, Used0) ->
+ {Def,Used1} = def_used_is(Is, Preds, Def0, Used0),
+ Used = gb_sets:union(gb_sets:from_list(used(Last)), Used1),
+ def_used_1(Bs, Preds, Def, Used);
+def_used_1([], _Preds, Def, Used) ->
+ {ordsets:from_list(Def),gb_sets:to_list(Used)}.
+
+def_used_is([#b_set{op=phi,dst=Dst,args=Args}|Is],
+ Preds, Def0, Used0) ->
+ Def = [Dst|Def0],
+ %% We must be careful to only include variables that will
+ %% be used when arriving from one of the predecessor blocks
+ %% in Preds.
+ Used1 = [V || {#b_var{}=V,L} <- Args, gb_sets:is_member(L, Preds)],
+ Used = gb_sets:union(gb_sets:from_list(Used1), Used0),
+ def_used_is(Is, Preds, Def, Used);
+def_used_is([#b_set{dst=Dst}=I|Is], Preds, Def0, Used0) ->
+ Def = [Dst|Def0],
+ Used = gb_sets:union(gb_sets:from_list(used(I)), Used0),
+ def_used_is(Is, Preds, Def, Used);
+def_used_is([], _Preds, Def, Used) ->
+ {Def,Used}.
+
+def_1([#b_blk{is=Is}|Bs], Def0) ->
+ Def = def_is(Is, Def0),
+ def_1(Bs, Def);
+def_1([], Def) ->
+ ordsets:from_list(Def).
+
+def_is([#b_set{dst=Dst}|Is], Def) ->
+ def_is(Is, [Dst|Def]);
+def_is([], Def) -> Def.
+
+iter_dominators([{0,[]}|Ls], _Doms) ->
+ Dom = [0],
+ iter_dominators(Ls, #{0=>Dom});
+iter_dominators([{L,Preds}|Ls], Doms) ->
+ DomPreds = [maps:get(P, Doms) || P <- Preds, maps:is_key(P, Doms)],
+ Dom = ordsets:add_element(L, ordsets:intersection(DomPreds)),
+ iter_dominators(Ls, Doms#{L=>Dom});
+iter_dominators([], Doms) -> Doms.
+
+fold_rpo_1([L|Ls], Fun, Blocks, Acc0) ->
+ Block = maps:get(L, Blocks),
+ Acc = Fun(L, Block, Acc0),
+ fold_rpo_1(Ls, Fun, Blocks, Acc);
+fold_rpo_1([], _, _, Acc) -> Acc.
+
+fold_instrs_rpo_1([L|Ls], Fun, Blocks, Acc0) ->
+ #b_blk{is=Is,last=Last} = maps:get(L, Blocks),
+ Acc1 = foldl(Fun, Acc0, Is),
+ Acc = Fun(Last, Acc1),
+ fold_instrs_rpo_1(Ls, Fun, Blocks, Acc);
+fold_instrs_rpo_1([], _, _, Acc) -> Acc.
+
+mapfold_instrs_rpo_1([L|Ls], Fun, Blocks0, Acc0) ->
+ #b_blk{is=Is0,last=Last0} = Block0 = maps:get(L, Blocks0),
+ {Is,Acc1} = mapfoldl(Fun, Acc0, Is0),
+ {Last,Acc} = Fun(Last0, Acc1),
+ Block = Block0#b_blk{is=Is,last=Last},
+ Blocks = maps:put(L, Block, Blocks0),
+ mapfold_instrs_rpo_1(Ls, Fun, Blocks, Acc);
+mapfold_instrs_rpo_1([], _, Blocks, Acc) ->
+ {Blocks,Acc}.
+
+flatmapfold_instrs_rpo_1([L|Ls], Fun, Blocks0, Acc0) ->
+ #b_blk{is=Is0,last=Last0} = Block0 = maps:get(L, Blocks0),
+ {Is,Acc1} = flatmapfoldl(Fun, Acc0, Is0),
+ {[Last],Acc} = Fun(Last0, Acc1),
+ Block = Block0#b_blk{is=Is,last=Last},
+ Blocks = maps:put(L, Block, Blocks0),
+ flatmapfold_instrs_rpo_1(Ls, Fun, Blocks, Acc);
+flatmapfold_instrs_rpo_1([], _, Blocks, Acc) ->
+ {Blocks,Acc}.
+
+linearize_1([L|Ls], Blocks, Seen0, Acc0) ->
+ case cerl_sets:is_element(L, Seen0) of
+ true ->
+ linearize_1(Ls, Blocks, Seen0, Acc0);
+ false ->
+ Seen1 = cerl_sets:add_element(L, Seen0),
+ Block = maps:get(L, Blocks),
+ Successors = successors(Block),
+ {Acc,Seen} = linearize_1(Successors, Blocks, Seen1, Acc0),
+ linearize_1(Ls, Blocks, Seen, [{L,Block}|Acc])
+ end;
+linearize_1([], _, Seen, Acc) ->
+ {Acc,Seen}.
+
+fix_phis([{L,Blk0}|Bs], S) ->
+ Blk = case Blk0 of
+ #b_blk{is=[#b_set{op=phi}|_]=Is0} ->
+ Is = fix_phis_1(Is0, L, S),
+ Blk0#b_blk{is=Is};
+ #b_blk{} ->
+ Blk0
+ end,
+ Successors = successors(Blk),
+ [{L,Blk}|fix_phis(Bs, S#{L=>Successors})];
+fix_phis([], _) -> [].
+
+fix_phis_1([#b_set{op=phi,args=Args0}=I|Is], L, S) ->
+ Args = [{Val,Pred} || {Val,Pred} <- Args0,
+ is_successor(L, Pred, S)],
+ [I#b_set{args=Args}|fix_phis_1(Is, L, S)];
+fix_phis_1(Is, _, _) -> Is.
+
+is_successor(L, Pred, S) ->
+ case S of
+ #{Pred:=Successors} ->
+ member(L, Successors);
+ #{} ->
+ %% This block has been removed.
+ false
+ end.
+
+rpo_1([L|Ls], Blocks, Seen0, Acc0) ->
+ case cerl_sets:is_element(L, Seen0) of
+ true ->
+ rpo_1(Ls, Blocks, Seen0, Acc0);
+ false ->
+ Block = maps:get(L, Blocks),
+ Seen1 = cerl_sets:add_element(L, Seen0),
+ Successors = successors(Block),
+ {Acc,Seen} = rpo_1(Successors, Blocks, Seen1, Acc0),
+ rpo_1(Ls, Blocks, Seen, [L|Acc])
+ end;
+rpo_1([], _, Seen, Acc) ->
+ {Acc,Seen}.
+
+rename_var(#b_var{}=Old, Rename) ->
+ case Rename of
+ #{Old:=New} -> New;
+ #{} -> Old
+ end;
+rename_var(#b_remote{mod=Mod0,name=Name0}=Remote, Rename) ->
+ Mod = rename_var(Mod0, Rename),
+ Name = rename_var(Name0, Rename),
+ Remote#b_remote{mod=Mod,name=Name};
+rename_var(Old, _) -> Old.
+
+rename_phi_vars([{Var,L}|As], Preds, Ren) ->
+ case cerl_sets:is_element(L, Preds) of
+ true ->
+ [{rename_var(Var, Ren),L}|rename_phi_vars(As, Preds, Ren)];
+ false ->
+ [{Var,L}|rename_phi_vars(As, Preds, Ren)]
+ end;
+rename_phi_vars([], _, _) -> [].
+
+map_instrs_1([L|Ls], Fun, Blocks0) ->
+ #b_blk{is=Is0,last=Last0} = Blk0 = maps:get(L, Blocks0),
+ Is = [Fun(I) || I <- Is0],
+ Last = Fun(Last0),
+ Blk = Blk0#b_blk{is=Is,last=Last},
+ Blocks = maps:put(L, Blk, Blocks0),
+ map_instrs_1(Ls, Fun, Blocks);
+map_instrs_1([], _, Blocks) -> Blocks.
+
+flatmapfoldl(F, Accu0, [Hd|Tail]) ->
+ {R,Accu1} = F(Hd, Accu0),
+ {Rs,Accu2} = flatmapfoldl(F, Accu1, Tail),
+ {R++Rs,Accu2};
+flatmapfoldl(_, Accu, []) -> {[],Accu}.
+
+split_blocks_1([L|Ls], P, Blocks0, Count0) ->
+ #b_blk{is=Is0} = Blk = maps:get(L, Blocks0),
+ case split_blocks_is(Is0, P, []) of
+ {yes,Bef,Aft} ->
+ NewLbl = Count0,
+ Count = Count0 + 1,
+ Br = #b_br{bool=#b_literal{val=true},succ=NewLbl,fail=NewLbl},
+ BefBlk = Blk#b_blk{is=Bef,last=Br},
+ NewBlk = Blk#b_blk{is=Aft},
+ Blocks1 = Blocks0#{L:=BefBlk,NewLbl=>NewBlk},
+ Successors = beam_ssa:successors(NewBlk),
+ Blocks = beam_ssa:update_phi_labels(Successors, L, NewLbl, Blocks1),
+ split_blocks_1([NewLbl|Ls], P, Blocks, Count);
+ no ->
+ split_blocks_1(Ls, P, Blocks0, Count0)
+ end;
+split_blocks_1([], _, Blocks, Count) ->
+ {Blocks,Count}.
+
+split_blocks_is([I|Is], P, []) ->
+ split_blocks_is(Is, P, [I]);
+split_blocks_is([I|Is], P, Acc) ->
+ case P(I) of
+ true ->
+ {yes,reverse(Acc),[I|Is]};
+ false ->
+ split_blocks_is(Is, P, [I|Acc])
+ end;
+split_blocks_is([], _, _) -> no.
+
+update_phi_labels_is([#b_set{op=phi,args=Args0}=I0|Is], Old, New) ->
+ Args = [{Arg,rename_label(Lbl, Old, New)} || {Arg,Lbl} <- Args0],
+ I = I0#b_set{args=Args},
+ [I|update_phi_labels_is(Is, Old, New)];
+update_phi_labels_is(Is, _, _) -> Is.
+
+rename_label(Old, Old, New) -> New;
+rename_label(Lbl, _Old, _New) -> Lbl.
+
+used_args([#b_var{}=V|As]) ->
+ [V|used_args(As)];
+used_args([#b_remote{mod=Mod,name=Name}|As]) ->
+ used_args([Mod,Name|As]);
+used_args([_|As]) ->
+ used_args(As);
+used_args([]) -> [].
+
+used_1([H|T], Used0) ->
+ Used = ordsets:union(used(H), Used0),
+ used_1(T, Used);
+used_1([], Used) -> Used.
diff --git a/lib/compiler/src/beam_ssa.hrl b/lib/compiler/src/beam_ssa.hrl
new file mode 100644
index 0000000000..fa76b08453
--- /dev/null
+++ b/lib/compiler/src/beam_ssa.hrl
@@ -0,0 +1,66 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-record(b_module, {anno=#{} :: beam_ssa:anno(),
+ name :: module(),
+ exports :: [{atom(),arity()}],
+ attributes :: list(),
+ body :: [beam_ssa:b_function()]}).
+-record(b_function, {anno=#{} :: beam_ssa:anno(),
+ args :: [beam_ssa:b_var()],
+ bs :: #{beam_ssa:label():=beam_ssa:b_blk()},
+ cnt :: beam_ssa:label()}).
+
+-record(b_blk, {anno=#{} :: beam_ssa:anno(),
+ is :: [beam_ssa:b_set()],
+ last :: beam_ssa:terminator()}).
+-record(b_set, {anno=#{} :: beam_ssa:anno(),
+ dst=none :: 'none'|beam_ssa:b_var(),
+ op :: beam_ssa:op(),
+ args=[] :: [beam_ssa:argument()]}).
+
+%% Terminators.
+-record(b_ret, {anno=#{} :: beam_ssa:anno(),
+ arg :: beam_ssa:value()}).
+
+-record(b_br, {anno=#{},
+ bool :: beam_ssa:value(),
+ succ :: beam_ssa:label(),
+ fail :: beam_ssa:label()}).
+
+-record(b_switch, {anno=#{} :: beam_ssa:anno(),
+ arg :: beam_ssa:value(),
+ fail :: beam_ssa:label(),
+ list :: [{beam_ssa:b_literal(),beam_ssa:label()}]}).
+
+%% Values.
+-record(b_var, {name :: beam_ssa:var_name()}).
+
+-record(b_literal, {val :: beam_ssa:literal_value()}).
+
+-record(b_remote, {mod :: beam_ssa:value(),
+ name :: beam_ssa:value(),
+ arity :: non_neg_integer()}).
+
+-record(b_local, {name :: beam_ssa:b_literal(),
+ arity :: non_neg_integer()}).
+
+%% If this block exists, it calls erlang:error(badarg).
+-define(BADARG_BLOCK, 1).
diff --git a/lib/compiler/src/beam_ssa_codegen.erl b/lib/compiler/src/beam_ssa_codegen.erl
new file mode 100644
index 0000000000..5085c950b5
--- /dev/null
+++ b/lib/compiler/src/beam_ssa_codegen.erl
@@ -0,0 +1,1850 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+%% Purpose: Generate BEAM assembly code from the SSA format.
+
+-module(beam_ssa_codegen).
+
+-export([module/2]).
+-export([classify_heap_need/2]). %Called from beam_ssa_pre_codegen.
+
+-export_type([ssa_register/0]).
+
+-include("beam_ssa.hrl").
+
+-import(lists, [foldl/3,keymember/3,keysort/2,last/1,map/2,mapfoldl/3,
+ reverse/1,reverse/2,sort/1,splitwith/2,takewhile/2]).
+
+-record(cg, {lcount=1 :: beam_label(), %Label counter
+ functable=#{} :: #{fa()=>beam_label()},
+ labels=#{} :: #{ssa_label()=>0|beam_label()},
+ used_labels=gb_sets:empty() :: gb_sets:set(ssa_label()),
+ regs=#{} :: #{beam_ssa:var_name()=>ssa_register()},
+ ultimate_fail=1 :: beam_label(),
+ catches=gb_sets:empty() :: gb_sets:set(ssa_label())
+ }).
+
+-spec module(beam_ssa:b_module(), [compile:option()]) ->
+ {'ok',beam_asm:module_code()}.
+
+module(#b_module{name=Mod,exports=Es,attributes=Attrs,body=Fs}, _Opts) ->
+ {Asm,St} = functions(Fs, {atom,Mod}),
+ {ok,{Mod,Es,Attrs,Asm,St#cg.lcount}}.
+
+-record(need, {h=0 :: non_neg_integer(),
+ f=0 :: non_neg_integer()}).
+
+-record(cg_blk, {anno=#{} :: anno(),
+ is=[] :: [instruction()],
+ last :: terminator()}).
+
+-record(cg_set, {anno=#{} :: anno(),
+ dst :: b_var(),
+ op :: beam_ssa:op(),
+ args :: [beam_ssa:argument() | xreg()]}).
+
+-record(cg_alloc, {anno=#{} :: anno(),
+ stack=none :: 'none' | pos_integer(),
+ words=#need{} :: #need{},
+ live :: 'undefined' | pos_integer(),
+ def_yregs=[] :: [yreg()]
+ }).
+
+-record(cg_br, {bool :: beam_ssa:value(),
+ succ :: ssa_label(),
+ fail :: ssa_label()
+ }).
+-record(cg_ret, {arg :: cg_value(),
+ dealloc=none :: 'none' | pos_integer()
+ }).
+-record(cg_switch, {arg :: cg_value(),
+ fail :: ssa_label(),
+ list :: [sw_list_item()]
+ }).
+
+-type fa() :: {beam_asm:function_name(),arity()}.
+-type ssa_label() :: beam_ssa:label().
+-type beam_label() :: beam_asm:label().
+
+-type anno() :: beam_ssa:anno().
+
+-type b_var() :: beam_ssa:b_var().
+-type b_literal() :: beam_ssa:b_literal().
+
+-type cg_value() :: beam_ssa:value() | xreg().
+
+-type cg_set() :: #cg_set{}.
+-type cg_alloc() :: #cg_alloc{}.
+
+-type instruction() :: cg_set() | cg_alloc().
+
+-type cg_br() :: #cg_br{}.
+-type cg_ret() :: #cg_ret{}.
+-type cg_switch() :: #cg_switch{}.
+-type terminator() :: cg_br() | cg_ret() | cg_switch().
+
+-type sw_list_item() :: {b_literal(),ssa_label()}.
+
+-type reg_num() :: beam_asm:reg_num().
+-type xreg() :: {'x',reg_num()}.
+-type yreg() :: {'y',reg_num()}.
+
+-type ssa_register() :: xreg() | yreg() | {'fr',reg_num()} | {'z',reg_num()}.
+
+functions(Forms, AtomMod) ->
+ mapfoldl(fun (F, St) -> function(F, AtomMod, St) end, #cg{lcount=1}, Forms).
+
+function(#b_function{anno=Anno,bs=Blocks}, AtomMod, St0) ->
+ #{func_info:={_,Name,Arity}} = Anno,
+ try
+ assert_badarg_block(Blocks), %Assertion.
+ Regs = maps:get(registers, Anno),
+ St1 = St0#cg{labels=#{},used_labels=gb_sets:empty(),
+ regs=Regs},
+ {Fi,St2} = new_label(St1), %FuncInfo label
+ {Entry,St3} = local_func_label(Name, Arity, St2),
+ {Ult,St4} = new_label(St3), %Ultimate failure
+ Labels = (St4#cg.labels)#{0=>Entry,?BADARG_BLOCK=>0},
+ St5 = St4#cg{labels=Labels,used_labels=gb_sets:singleton(Entry),
+ ultimate_fail=Ult},
+ {Body,St} = cg_fun(Blocks, St5),
+ Asm = [{label,Fi},line(Anno),
+ {func_info,AtomMod,{atom,Name},Arity}] ++ Body ++
+ [{label,Ult},if_end],
+ Func = {function,Name,Arity,Entry,Asm},
+ {Func,St}
+ catch
+ Class:Error:Stack ->
+ io:fwrite("Function: ~w/~w\n", [Name,Arity]),
+ erlang:raise(Class, Error, Stack)
+ end.
+
+assert_badarg_block(Blocks) ->
+ %% Assertion: ?BADARG_BLOCK must be the call erlang:error(badarg).
+ case Blocks of
+ #{?BADARG_BLOCK:=Blk} ->
+ #b_blk{is=[#b_set{op=call,dst=Ret,
+ args=[#b_remote{mod=#b_literal{val=erlang},
+ name=#b_literal{val=error}},
+ #b_literal{val=badarg}]}],
+ last=#b_ret{arg=Ret}} = Blk,
+ ok;
+ #{} ->
+ %% ?BADARG_BLOCK has been removed because it was never used.
+ ok
+ end.
+
+cg_fun(Blocks, St0) ->
+ Linear0 = linearize(Blocks),
+ St = collect_catch_labels(Linear0, St0),
+ Linear1 = need_heap(Linear0),
+ Linear2 = prefer_xregs(Linear1, St),
+ Linear3 = liveness(Linear2, St),
+ Linear4 = defined(Linear3, St),
+ Linear = opt_allocate(Linear4, St),
+ cg_linear(Linear, St).
+
+%% collect_catch_labels(Linear, St) -> St.
+%% Collect all catch labels (labels for blocks that begin
+%% with 'landingpad' instructions) for later use.
+
+collect_catch_labels(Linear, St) ->
+ Labels = collect_catch_labels_1(Linear),
+ St#cg{catches=gb_sets:from_list(Labels)}.
+
+collect_catch_labels_1([{L,#cg_blk{is=[#cg_set{op=landingpad}|_]}}|Bs]) ->
+ [L|collect_catch_labels_1(Bs)];
+collect_catch_labels_1([_|Bs]) ->
+ collect_catch_labels_1(Bs);
+collect_catch_labels_1([]) -> [].
+
+%% need_heap([{BlockLabel,Block]) -> [{BlockLabel,Block}].
+%% Insert need_heap instructions in the instruction list. Try to be smart and
+%% collect them together as much as possible.
+
+need_heap(Bs0) ->
+ Bs1 = need_heap_allocs(Bs0, #{}),
+ {Bs,#need{h=0,f=0}} = need_heap_blks(reverse(Bs1), #need{}, []),
+ Bs.
+
+need_heap_allocs([{L,#cg_blk{is=Is0,last=Terminator}=Blk0}|Bs], Counts0) ->
+ Next = next_block(Bs),
+ Successors = successors(Terminator),
+ Counts = foldl(fun(S, Cnts) ->
+ case Cnts of
+ #{S:=C} -> Cnts#{S:=C+1};
+ #{} when S =:= Next -> Cnts#{S=>1};
+ #{} -> Cnts#{S=>42}
+ end
+ end, Counts0, Successors),
+ case Counts of
+ #{L:=1} ->
+ [{L,Blk0}|need_heap_allocs(Bs, Counts)];
+ #{L:=_} ->
+ %% This block has multiple predecessors. Force an allocation
+ %% in this block so that the predecessors don't need to do
+ %% an allocation on behalf of this block.
+ Is = case need_heap_never(Is0) of
+ true -> Is0;
+ false -> [#cg_alloc{}|Is0]
+ end,
+ Blk = Blk0#cg_blk{is=Is},
+ [{L,Blk}|need_heap_allocs(Bs, Counts)];
+ #{} ->
+ [{L,Blk0}|need_heap_allocs(Bs, Counts)]
+ end;
+need_heap_allocs([], _) -> [].
+
+need_heap_never([#cg_alloc{}|_]) -> true;
+need_heap_never([#cg_set{op=recv_next}|_]) -> true;
+need_heap_never([#cg_set{op=wait}|_]) -> true;
+need_heap_never(_) -> false.
+
+need_heap_blks([{L,#cg_blk{is=Is0}=Blk0}|Bs], H0, Acc) ->
+ {Is1,H1} = need_heap_is(reverse(Is0), H0, []),
+ {Ns,H} = need_heap_terminator(Bs, H1),
+ Is = Ns ++ Is1,
+ Blk = Blk0#cg_blk{is=Is},
+ need_heap_blks(Bs, H, [{L,Blk}|Acc]);
+need_heap_blks([], H, Acc) ->
+ {Acc,H}.
+
+need_heap_is([#cg_alloc{words=Words}=Alloc0|Is], N, Acc) ->
+ Alloc = Alloc0#cg_alloc{words=add_heap_words(N, Words)},
+ need_heap_is(Is, #need{}, [Alloc|Acc]);
+need_heap_is([#cg_set{op=Op,args=Args}=I|Is], N, Acc) ->
+ case classify_heap_need(Op, Args) of
+ {put,Words} ->
+ %% Pass through adding to needed heap.
+ need_heap_is(Is, add_heap_words(N, Words), [I|Acc]);
+ put_float ->
+ need_heap_is(Is, add_heap_float(N), [I|Acc]);
+ neutral ->
+ need_heap_is(Is, N, [I|Acc]);
+ gc ->
+ need_heap_is(Is, #need{}, [I]++need_heap_need(N)++Acc)
+ end;
+need_heap_is([], N, Acc) ->
+ {Acc,N}.
+
+need_heap_terminator([{_,#cg_blk{last=#cg_br{succ=Same,fail=Same}}}|_], N) ->
+ {[],N};
+need_heap_terminator([{_,#cg_blk{}}|_], N) ->
+ {need_heap_need(N),#need{}};
+need_heap_terminator([], H) ->
+ {need_heap_need(H),#need{}}.
+
+need_heap_need(#need{h=0,f=0}) -> [];
+need_heap_need(#need{}=N) -> [#cg_alloc{words=N}].
+
+add_heap_words(#need{h=H1,f=F1}, #need{h=H2,f=F2}) ->
+ #need{h=H1+H2,f=F1+F2};
+add_heap_words(#need{h=Heap}=N, Words) when is_integer(Words) ->
+ N#need{h=Heap+Words}.
+
+add_heap_float(#need{f=F}=N) ->
+ N#need{f=F+1}.
+
+%% classify_heap_need(Operation, Arguments) ->
+%% gc | neutral | {put,Words} | put_float.
+%% Classify the heap need for this instruction. The return
+%% values have the following meaning.
+%%
+%% {put,Words} means that the instruction will use Words words to build
+%% something on the heap.
+%%
+%% 'put_float' means that the instruction will build one floating point
+%% number on the heap.
+%%
+%% 'gc' means that that the instruction can potentially do a GC or throw an
+%% exception. That means that an allocation instruction for any building
+%% must be placed after this instruction.
+%%
+%% 'neutral' means that the instruction does nothing to disturb the heap.
+
+-spec classify_heap_need(beam_ssa:op(), [beam_ssa:value()]) ->
+ 'gc' | 'neutral' |
+ {'put',non_neg_integer()} | 'put_float'.
+
+classify_heap_need(put_list, _) ->
+ {put,2};
+classify_heap_need(put_tuple_arity, [#b_literal{val=Words}]) ->
+ {put,Words+1};
+classify_heap_need(put_tuple, Elements) ->
+ {put,length(Elements)+1};
+classify_heap_need({bif,Name}, Args) ->
+ case is_gc_bif(Name, Args) of
+ false -> neutral;
+ true -> gc
+ end;
+classify_heap_need({float,Op}, _Args) ->
+ case Op of
+ get -> put_float;
+ _ -> neutral
+ end;
+classify_heap_need(Name, _Args) ->
+ classify_heap_need(Name).
+
+%% classify_heap_need(Operation) -> gc | neutral.
+%% Return either 'gc' or 'neutral'.
+%%
+%% 'gc' means that that the instruction can potentially do a GC or throw an
+%% exception. That means that an allocation instruction for any building
+%% must be placed after this instruction.
+%%
+%% 'neutral' means that the instruction does nothing to disturb the heap.
+%%
+%% Note: Only handle operations in this function that are not handled
+%% by classify_heap_need/2.
+
+classify_heap_need(bs_add) -> gc;
+classify_heap_need(bs_get) -> gc;
+classify_heap_need(bs_init) -> gc;
+classify_heap_need(bs_init_writable) -> gc;
+classify_heap_need(bs_match_string) -> gc;
+classify_heap_need(bs_put) -> neutral;
+classify_heap_need(bs_restore) -> neutral;
+classify_heap_need(bs_save) -> neutral;
+classify_heap_need(bs_skip) -> gc;
+classify_heap_need(bs_start_match) -> neutral;
+classify_heap_need(bs_test_tail) -> neutral;
+classify_heap_need(bs_utf16_size) -> neutral;
+classify_heap_need(bs_utf8_size) -> neutral;
+classify_heap_need(build_stacktrace) -> gc;
+classify_heap_need(call) -> gc;
+classify_heap_need(catch_end) -> gc;
+classify_heap_need(context_to_binary) -> gc;
+classify_heap_need(copy) -> neutral;
+classify_heap_need(extract) -> gc;
+classify_heap_need(get_hd) -> neutral;
+classify_heap_need(get_map_element) -> neutral;
+classify_heap_need(get_tl) -> neutral;
+classify_heap_need(get_tuple_element) -> neutral;
+classify_heap_need(has_map_field) -> neutral;
+classify_heap_need(is_nonempty_list) -> neutral;
+classify_heap_need(is_tagged_tuple) -> neutral;
+classify_heap_need(kill_try_tag) -> gc;
+classify_heap_need(landingpad) -> gc;
+classify_heap_need(make_fun) -> gc;
+classify_heap_need(new_try_tag) -> gc;
+classify_heap_need(peek_message) -> gc;
+classify_heap_need(put_map) -> gc;
+classify_heap_need(put_tuple_elements) -> neutral;
+classify_heap_need(raw_raise) -> gc;
+classify_heap_need(recv_next) -> gc;
+classify_heap_need(remove_message) -> neutral;
+classify_heap_need(resume) -> gc;
+classify_heap_need(set_tuple_element) -> gc;
+classify_heap_need(succeeded) -> neutral;
+classify_heap_need(timeout) -> gc;
+classify_heap_need(wait) -> gc;
+classify_heap_need(wait_timeout) -> gc.
+
+%%%
+%%% Because beam_ssa_pre_codegen has inserted 'copy' instructions to copy
+%%% variables that must be saved on the stack, a value can for some time
+%%% be in both an X register and a Y register.
+%%%
+%%% Here we will keep track of variables that have the same value and
+%%% rewrite instructions to use the variable that refers to the X
+%%% register instead of the Y register. That could improve performance,
+%%% since the BEAM interpreter have more optimized instructions
+%%% operating on X registers than on Y registers.
+%%%
+%%% 'call' and 'make_fun' are handled somewhat specially. If a value
+%%% already is in the correct X register, the X register will always
+%%% be used instead of the Y register. However, if there are one or more
+%%% values in the wrong X registers, the X registers variables will be
+%%% used only if that does not cause more 'move' instructions to be
+%%% be emitted than if the Y register variables were used.
+%%%
+%%% Here are some examples. The first example shows how a 'move' from
+%%% an Y register is eliminated:
+%%%
+%%% move x0 y1
+%%% move y1 x0 %%Will be eliminated.
+%%%
+%%% call f/1
+%%%
+%%% Here is an example when x0 and x1 must be swapped to load the argument
+%%% registers. Here the 'call' instruction will use the Y registers to
+%%% avoid introducing an extra 'move' insruction:
+%%%
+%%% move x0 y0
+%%% move x1 y1
+%%%
+%%% move y0 x1
+%%% move y1 x0
+%%%
+%%% call f/2
+%%%
+%%% Using the X register to load the argument registers would need
+%%% an extra 'move' instruction like this:
+%%%
+%%% move x0 y0
+%%% move x1 y1
+%%%
+%%% move x1 x2
+%%% move x0 x1
+%%% move x2 x0
+%%%
+%%% call f/2
+%%%
+
+prefer_xregs(Linear, St) ->
+ prefer_xregs(Linear, St, #{0=>#{}}).
+
+prefer_xregs([{L,#cg_blk{is=Is0,last=Last0}=Blk0}|Bs], St, Map0) ->
+ Copies0 = maps:get(L, Map0),
+ {Is,Copies} = prefer_xregs_is(Is0, St, Copies0, []),
+ Last = prefer_xregs_terminator(Last0, Copies, St),
+ Blk = Blk0#cg_blk{is=Is,last=Last},
+ Successors = successors(Last),
+ Map = prefer_xregs_successors(Successors, Copies, Map0),
+ [{L,Blk}|prefer_xregs(Bs, St, Map)];
+prefer_xregs([], _St, _Map) -> [].
+
+prefer_xregs_successors([L|Ls], Copies0, Map0) ->
+ case Map0 of
+ #{L:=Copies1} ->
+ Copies = merge_copies(Copies0, Copies1),
+ Map = Map0#{L:=Copies},
+ prefer_xregs_successors(Ls, Copies0, Map);
+ #{} ->
+ Map = Map0#{L=>Copies0},
+ prefer_xregs_successors(Ls, Copies0, Map)
+ end;
+prefer_xregs_successors([], _, Map) -> Map.
+
+prefer_xregs_is([#cg_alloc{}=I|Is], St, Copies0, Acc) ->
+ Copies = case I of
+ #cg_alloc{stack=none,words=#need{h=0,f=0}} ->
+ Copies0;
+ #cg_alloc{} ->
+ #{}
+ end,
+ prefer_xregs_is(Is, St, Copies, [I|Acc]);
+prefer_xregs_is([#cg_set{op=copy,dst=Dst,args=[Src]}=I|Is], St, Copies0, Acc) ->
+ Copies1 = prefer_xregs_prune(I, Copies0, St),
+ Copies = case beam_args([Src,Dst], St) of
+ [Same,Same] -> Copies1;
+ [_,_] -> Copies1#{Dst=>Src}
+ end,
+ prefer_xregs_is(Is, St, Copies, [I|Acc]);
+prefer_xregs_is([#cg_set{op=call,dst=Dst}=I0|Is], St, Copies, Acc) ->
+ I = prefer_xregs_call(I0, Copies, St),
+ prefer_xregs_is(Is, St, #{Dst=>{x,0}}, [I|Acc]);
+prefer_xregs_is([#cg_set{op=make_fun,dst=Dst}=I0|Is], St, Copies, Acc) ->
+ I = prefer_xregs_call(I0, Copies, St),
+ prefer_xregs_is(Is, St, #{Dst=>{x,0}}, [I|Acc]);
+prefer_xregs_is([#cg_set{op=set_tuple_element}=I|Is], St, Copies, Acc) ->
+ %% FIXME: HiPE translates the following code segment incorrectly:
+ %% {call_ext,3,{extfunc,erlang,setelement,3}}.
+ %% {move,{x,0},{y,3}}.
+ %% {set_tuple_element,{y,1},{y,3},1}.
+ %% Therefore, skip the translation of the arguments for set_tuple_element.
+ prefer_xregs_is(Is, St, Copies, [I|Acc]);
+prefer_xregs_is([#cg_set{args=Args0}=I0|Is], St, Copies0, Acc) ->
+ Args = [do_prefer_xreg(A, Copies0, St) || A <- Args0],
+ I = I0#cg_set{args=Args},
+ Copies = prefer_xregs_prune(I, Copies0, St),
+ prefer_xregs_is(Is, St, Copies, [I|Acc]);
+prefer_xregs_is([], _St, Copies, Acc) ->
+ {reverse(Acc),Copies}.
+
+prefer_xregs_terminator(#cg_br{bool=Arg0}=I, Copies, St) ->
+ Arg = do_prefer_xreg(Arg0, Copies, St),
+ I#cg_br{bool=Arg};
+prefer_xregs_terminator(#cg_ret{arg=Arg0}=I, Copies, St) ->
+ Arg = do_prefer_xreg(Arg0, Copies, St),
+ I#cg_ret{arg=Arg};
+prefer_xregs_terminator(#cg_switch{arg=Arg0}=I, Copies, St) ->
+ Arg = do_prefer_xreg(Arg0, Copies, St),
+ I#cg_switch{arg=Arg}.
+
+prefer_xregs_prune(#cg_set{anno=#{clobbers:=true}}, _, _) ->
+ #{};
+prefer_xregs_prune(#cg_set{dst=Dst}, Copies, St) ->
+ DstReg = beam_arg(Dst, St),
+ F = fun(_, Alias) ->
+ beam_arg(Alias, St) =/= DstReg
+ end,
+ maps:filter(F, Copies).
+
+%% prefer_xregs_call(Instruction, Copies, St) -> Instruction.
+%% Given a 'call' or 'make_fun' instruction, minimize the number
+%% of 'move' instructions to set up the argument registers.
+%% Prefer using X registers over Y registers, unless that will
+%% result in more 'move' instructions.
+
+prefer_xregs_call(#cg_set{args=[_]}=I, _Copies, _St) ->
+ I;
+prefer_xregs_call(#cg_set{args=[F|Args0]}=I, Copies, St) ->
+ case Args0 of
+ [A0] ->
+ %% Only one argument. Always prefer the X register
+ %% if available.
+ A = do_prefer_xreg(A0, Copies, St),
+ I#cg_set{args=[F,A]};
+ [_|_] ->
+ %% Two or more arguments. Try rewriting arguments in
+ %% two ways and see which way produces the least
+ %% number of 'move' instructions.
+ Args1 = prefer_xregs_call_1(Args0, Copies, 0, St),
+ Args2 = [do_prefer_xreg(A, Copies, St) || A <- Args0],
+ case {count_moves(Args1, St),count_moves(Args2, St)} of
+ {N1,N2} when N1 < N2 ->
+ %% There will be fewer 'move' instructions if
+ %% we keep using Y registers.
+ I#cg_set{args=[F|Args1]};
+ {_,_} ->
+ %% Always use the values in X registers.
+ I#cg_set{args=[F|Args2]}
+ end
+ end.
+
+count_moves(Args, St) ->
+ length(setup_args(beam_args(Args, St))).
+
+prefer_xregs_call_1([#b_var{}=A|As], Copies, X, St) ->
+ case {beam_arg(A, St),Copies} of
+ {{y,_},#{A:=Other}} ->
+ case beam_arg(Other, St) of
+ {x,X} ->
+ %% This value is already in the correct X register.
+ %% It is always benefical to use the X register variable.
+ [Other|prefer_xregs_call_1(As, Copies, X+1, St)];
+ _ ->
+ %% This value is another X register. Keep using
+ %% the Y register variable.
+ [A|prefer_xregs_call_1(As, Copies, X+1, St)]
+ end;
+ {_,_} ->
+ %% The value is not available in an X register.
+ [A|prefer_xregs_call_1(As, Copies, X+1, St)]
+ end;
+prefer_xregs_call_1([A|As], Copies, X, St) ->
+ [A|prefer_xregs_call_1(As, Copies, X+1, St)];
+prefer_xregs_call_1([], _, _, _) -> [].
+
+do_prefer_xreg(#b_var{}=A, Copies, St) ->
+ case {beam_arg(A, St),Copies} of
+ {{y,_},#{A:=Copy}} ->
+ Copy;
+ {_,_} ->
+ A
+ end;
+do_prefer_xreg(A, _, _) -> A.
+
+merge_copies(Copies0, Copies1) when map_size(Copies0) =< map_size(Copies1) ->
+ maps:filter(fun(K, V) ->
+ case Copies1 of
+ #{K:=V} -> true;
+ #{} -> false
+ end
+ end, Copies0);
+merge_copies(Copies0, Copies1) ->
+ merge_copies(Copies1, Copies0).
+
+
+%%%
+%%% Add annotations for the number of live registers.
+%%%
+
+liveness(Linear, #cg{regs=Regs}) ->
+ liveness(reverse(Linear), #{}, Regs, []).
+
+liveness([{L,#cg_blk{is=Is0,last=Last0}=Blk0}|Bs], LiveMap0, Regs, Acc) ->
+ Successors = liveness_successors(Last0),
+ Live0 = ordsets:union([liveness_get(S, LiveMap0) || S <- Successors]),
+ Live1 = liveness_terminator(Last0, Live0),
+ {Is,Live} = liveness_is(reverse(Is0), Regs, Live1, []),
+ LiveMap = LiveMap0#{L=>Live},
+ Blk = Blk0#cg_blk{is=Is},
+ liveness(Bs, LiveMap, Regs, [{L,Blk}|Acc]);
+liveness([], _LiveMap, _Regs, Acc) -> Acc.
+
+liveness_get(S, LiveMap) ->
+ case LiveMap of
+ #{S:=Live} -> Live;
+ #{} -> []
+ end.
+
+liveness_successors(Terminator) ->
+ successors(Terminator) -- [?BADARG_BLOCK].
+
+liveness_is([#cg_alloc{}=I0|Is], Regs, Live, Acc) ->
+ I = I0#cg_alloc{live=num_live(Live, Regs)},
+ liveness_is(Is, Regs, Live, [I|Acc]);
+liveness_is([#cg_set{dst=Dst,args=Args}=I0|Is], Regs, Live0, Acc) ->
+ Live1 = liveness_clobber(I0, Live0, Regs),
+ I1 = liveness_yregs_anno(I0, Live1, Regs),
+ Live2 = liveness_args(Args, Live1),
+ Live = ordsets:del_element(Dst, Live2),
+ I = liveness_anno(I1, Live, Regs),
+ liveness_is(Is, Regs, Live, [I|Acc]);
+liveness_is([], _, Live, Acc) ->
+ {Acc,Live}.
+
+liveness_terminator(#cg_br{bool=Arg}, Live) ->
+ liveness_terminator_1(Arg, Live);
+liveness_terminator(#cg_switch{arg=Arg}, Live) ->
+ liveness_terminator_1(Arg, Live);
+liveness_terminator(#cg_ret{arg=Arg}, Live) ->
+ liveness_terminator_1(Arg, Live).
+
+liveness_terminator_1(#b_var{}=V, Live) ->
+ ordsets:add_element(V, Live);
+liveness_terminator_1(#b_literal{}, Live) ->
+ Live;
+liveness_terminator_1(Reg, Live) ->
+ _ = verify_beam_register(Reg),
+ ordsets:add_element(Reg, Live).
+
+liveness_args([#b_var{}=V|As], Live) ->
+ liveness_args(As, ordsets:add_element(V, Live));
+liveness_args([#b_remote{mod=Mod,name=Name}|As], Live) ->
+ liveness_args([Mod,Name|As], Live);
+liveness_args([A|As], Live) ->
+ case is_beam_register(A) of
+ true ->
+ liveness_args(As, ordsets:add_element(A, Live));
+ false ->
+ liveness_args(As, Live)
+ end;
+liveness_args([], Live) -> Live.
+
+liveness_anno(#cg_set{op=Op}=I, Live, Regs) ->
+ case need_live_anno(Op) of
+ true ->
+ NumLive = num_live(Live, Regs),
+ Anno = (I#cg_set.anno)#{live=>NumLive},
+ I#cg_set{anno=Anno};
+ false ->
+ I
+ end.
+
+liveness_yregs_anno(#cg_set{op=Op,dst=Dst}=I, Live0, Regs) ->
+ case need_live_anno(Op) of
+ true ->
+ Live = ordsets:del_element(Dst, Live0),
+ LiveYregs = [V || V <- Live, is_yreg(V, Regs)],
+ Anno = (I#cg_set.anno)#{live_yregs=>LiveYregs},
+ I#cg_set{anno=Anno};
+ false ->
+ I
+ end.
+
+liveness_clobber(#cg_set{anno=Anno}, Live, Regs) ->
+ case Anno of
+ #{clobbers:=true} ->
+ [R || R <- Live, is_yreg(R, Regs)];
+ _ ->
+ Live
+ end.
+
+is_yreg(R, Regs) ->
+ case Regs of
+ #{R:={y,_}} -> true;
+ #{} -> false
+ end.
+
+num_live(Live, Regs) ->
+ Rs = ordsets:from_list([get_register(V, Regs) || V <- Live]),
+ num_live_1(Rs, 0).
+
+num_live_1([{x,X}|T], X) ->
+ num_live_1(T, X+1);
+num_live_1([{x,_}|_]=T, X) ->
+ %% error({hole,{x,X},expected,Next});
+ num_live_1(T, X+1);
+num_live_1([{y,_}|_], X) ->
+ X;
+num_live_1([{z,_}|_], X) ->
+ X;
+num_live_1([{fr,_}|T], X) ->
+ num_live_1(T, X);
+num_live_1([], X) ->
+ X.
+
+get_live(#cg_set{anno=#{live:=Live}}) ->
+ Live.
+
+%% need_live_anno(Operation) -> true|false.
+%% Return 'true' if the instruction needs a 'live' annotation with
+%% the number live X registers, or 'false' otherwise.
+
+need_live_anno(Op) ->
+ case Op of
+ {bif,_} -> true;
+ bs_get -> true;
+ bs_init -> true;
+ bs_start_match -> true;
+ bs_skip -> true;
+ call -> true;
+ put_map -> true;
+ _ -> false
+ end.
+
+%%%
+%%% Add annotations for defined Y registers.
+%%%
+
+defined(Linear, #cg{regs=Regs}) ->
+ def(Linear, #{}, Regs).
+
+def([{L,#cg_blk{is=Is0,last=Last}=Blk0}|Bs], DefMap0, Regs) ->
+ Def0 = def_get(L, DefMap0),
+ {Is,Def} = def_is(Is0, Regs, Def0, []),
+ Successors = successors(Last),
+ DefMap = def_successors(Successors, Def, DefMap0),
+ Blk = Blk0#cg_blk{is=Is},
+ [{L,Blk}|def(Bs, DefMap, Regs)];
+def([], _, _) -> [].
+
+def_get(L, DefMap) ->
+ case DefMap of
+ #{L:=Def} -> Def;
+ #{} -> []
+ end.
+
+def_is([#cg_alloc{anno=Anno0}=I0|Is], Regs, Def, Acc) ->
+ I = I0#cg_alloc{anno=Anno0#{def_yregs=>Def}},
+ def_is(Is, Regs, Def, [I|Acc]);
+def_is([#cg_set{op=kill_try_tag,args=[#b_var{}=Tag]}=I|Is], Regs, Def0, Acc) ->
+ Def = ordsets:del_element(Tag, Def0),
+ def_is(Is, Regs, Def, [I|Acc]);
+def_is([#cg_set{op=catch_end,args=[#b_var{}=Tag|_]}=I|Is], Regs, Def0, Acc) ->
+ Def = ordsets:del_element(Tag, Def0),
+ def_is(Is, Regs, Def, [I|Acc]);
+def_is([#cg_set{anno=Anno0,op=call,dst=Dst}=I0|Is],
+ Regs, Def0, Acc) ->
+ #{live_yregs:=LiveYregVars} = Anno0,
+ LiveRegs = gb_sets:from_list([maps:get(V, Regs) || V <- LiveYregVars]),
+ Kill0 = ordsets:subtract(Def0, LiveYregVars),
+
+ %% Kill0 is the set of variables that have just died. However, the registers
+ %% used for killed variables may have been reused, so we must check that the
+ %% registers to be killed are not used by other variables.
+ Kill = [K || K <- Kill0, not gb_sets:is_element(maps:get(K, Regs), LiveRegs)],
+ Anno = Anno0#{def_yregs=>Def0,kill_yregs=>Kill},
+ I = I0#cg_set{anno=Anno},
+ Def1 = ordsets:subtract(Def0, Kill),
+ Def = def_add_yreg(Dst, Def1, Regs),
+ def_is(Is, Regs, Def, [I|Acc]);
+def_is([#cg_set{anno=Anno0,op={bif,Bif},dst=Dst,args=Args}=I0|Is],
+ Regs, Def0, Acc) ->
+ Arity = length(Args),
+ I = case is_gc_bif(Bif, Args) orelse not erl_bifs:is_safe(erlang, Bif, Arity) of
+ true ->
+ I0#cg_set{anno=Anno0#{def_yregs=>Def0}};
+ false ->
+ I0
+ end,
+ Def = def_add_yreg(Dst, Def0, Regs),
+ def_is(Is, Regs, Def, [I|Acc]);
+def_is([#cg_set{anno=Anno0,dst=Dst}=I0|Is], Regs, Def0, Acc) ->
+ I = case need_y_init(I0) of
+ true ->
+ I0#cg_set{anno=Anno0#{def_yregs=>Def0}};
+ false ->
+ I0
+ end,
+ Def = def_add_yreg(Dst, Def0, Regs),
+ def_is(Is, Regs, Def, [I|Acc]);
+def_is([], _, Def, Acc) ->
+ {reverse(Acc),Def}.
+
+def_add_yreg(Dst, Def, Regs) ->
+ case is_yreg(Dst, Regs) of
+ true -> ordsets:add_element(Dst, Def);
+ false -> Def
+ end.
+
+def_successors([S|Ss], Def0, DefMap) ->
+ case DefMap of
+ #{S:=Def1} ->
+ Def = ordsets:intersection(Def0, Def1),
+ def_successors(Ss, Def0, DefMap#{S:=Def});
+ #{} ->
+ def_successors(Ss, Def0, DefMap#{S=>Def0})
+ end;
+def_successors([], _, DefMap) -> DefMap.
+
+%% need_y_init(#cg_set{}) -> true|false.
+%% Return true if this instructions needs initialized Y registers
+%% (because the instruction may do a GC or cause an exception
+%% so that the stack will be scanned), or false otherwise.
+
+need_y_init(#cg_set{anno=#{clobbers:=Clobbers}}) -> Clobbers;
+need_y_init(#cg_set{op=bs_get}) -> true;
+need_y_init(#cg_set{op=bs_init}) -> true;
+need_y_init(#cg_set{op=bs_skip,args=[#b_literal{val=Type}|_]}) ->
+ case Type of
+ utf8 -> true;
+ utf16 -> true;
+ utf32 -> true;
+ _ -> false
+ end;
+need_y_init(#cg_set{op=bs_start_match}) -> true;
+need_y_init(#cg_set{op=put_map}) -> true;
+need_y_init(#cg_set{}) -> false.
+
+%% opt_allocate([{BlockLabel,Block}], #st{}) -> [BeamInstruction].
+%% Update the def_yregs field of each #cg_alloc{} that allocates
+%% a stack frame. #cg_alloc.def_yregs will list all Y registers
+%% that will be initialized by the subsequent code (thus, the
+%% listed Y registers don't require init/1 instructions).
+
+opt_allocate(Linear, #cg{regs=Regs}) ->
+ opt_allocate_1(Linear, Regs).
+
+opt_allocate_1([{L,#cg_blk{is=[#cg_alloc{stack=Stk}=I0|Is]}=Blk0}|Bs]=Bs0, Regs)
+ when is_integer(Stk) ->
+ Yregs = opt_alloc_def(Bs0, gb_sets:singleton(L), []),
+ I = I0#cg_alloc{def_yregs=Yregs},
+ [{L,Blk0#cg_blk{is=[I|Is]}}|opt_allocate_1(Bs, Regs)];
+opt_allocate_1([B|Bs], Regs) ->
+ [B|opt_allocate_1(Bs, Regs)];
+opt_allocate_1([], _) -> [].
+
+opt_alloc_def([{L,#cg_blk{is=Is,last=Last}}|Bs], Ws0, Def0) ->
+ case gb_sets:is_member(L, Ws0) of
+ false ->
+ opt_alloc_def(Bs, Ws0, Def0);
+ true ->
+ case opt_allocate_is(Is) of
+ none ->
+ Succ = successors(Last),
+ Ws = gb_sets:union(Ws0, gb_sets:from_list(Succ)),
+ opt_alloc_def(Bs, Ws, Def0);
+ Def1 when is_list(Def1) ->
+ Def = [Def1|Def0],
+ opt_alloc_def(Bs, Ws0, Def)
+ end
+ end;
+opt_alloc_def([], _, Def) ->
+ ordsets:intersection(Def).
+
+opt_allocate_is([#cg_set{anno=Anno}|Is]) ->
+ case Anno of
+ #{def_yregs:=Yregs} ->
+ Yregs;
+ #{} ->
+ opt_allocate_is(Is)
+ end;
+opt_allocate_is([#cg_alloc{anno=#{def_yregs:=Yregs},stack=none}|_]) ->
+ Yregs;
+opt_allocate_is([#cg_alloc{}|Is]) ->
+ opt_allocate_is(Is);
+opt_allocate_is([]) -> none.
+
+%%%
+%%% Here follows the main code generation functions.
+%%%
+
+%% cg_linear([{BlockLabel,Block}]) -> [BeamInstruction].
+%% Generate BEAM instructions.
+
+cg_linear([{L,#cg_blk{anno=#{recv_set:=L}=Anno0}=B0}|Bs], St0) ->
+ Anno = maps:remove(recv_set, Anno0),
+ B = B0#cg_blk{anno=Anno},
+ {Is,St1} = cg_linear([{L,B}|Bs], St0),
+ {Fail,St} = use_block_label(L, St1),
+ {[{recv_set,Fail}|Is],St};
+cg_linear([{L,#cg_blk{is=Is0,last=Last}}|Bs], St0) ->
+ Next = next_block(Bs),
+ St1 = new_block_label(L, St0),
+ {Is1,St2} = cg_block(Is0, Last, Next, St1),
+ {Is2,St} = cg_linear(Bs, St2),
+ {def_block_label(L, St)++Is1++Is2,St};
+cg_linear([], St) -> {[],St}.
+
+cg_block([#cg_set{op=recv_next}], #cg_br{succ=Lr0}, _Next, St0) ->
+ {Lr,St} = use_block_label(Lr0, St0),
+ {[{loop_rec_end,Lr}],St};
+cg_block([#cg_set{op=wait}], #cg_br{succ=Lr0}, _Next, St0) ->
+ {Lr,St} = use_block_label(Lr0, St0),
+ {[{wait,Lr}],St};
+cg_block(Is0, Last, Next, St0) ->
+ case Last of
+ #cg_br{succ=Next,fail=Next} ->
+ cg_block(Is0, none, St0);
+ #cg_br{succ=Same,fail=Same} ->
+ {Fail,St1} = use_block_label(Same, St0),
+ {Is,St} = cg_block(Is0, none, St1),
+ {Is++[jump(Fail)],St};
+ #cg_br{bool=Bool,succ=Next,fail=Fail0} ->
+ {Fail,St1} = use_block_label(Fail0, St0),
+ {Is,St} = cg_block(Is0, {Bool,Fail}, St1),
+ {Is,St};
+ #cg_br{bool=Bool,succ=Succ0,fail=Fail0} ->
+ {[Succ,Fail],St1} = use_block_labels([Succ0,Fail0], St0),
+ {Is,St} = cg_block(Is0, {Bool,Fail}, St1),
+ {Is++[jump(Succ)],St};
+ #cg_ret{arg=Src0,dealloc=N} ->
+ Src = beam_arg(Src0, St0),
+ cg_block(Is0, {return,Src,N}, St0);
+ #cg_switch{} ->
+ cg_switch(Is0, Last, St0)
+ end.
+
+cg_switch(Is0, Last, St0) ->
+ #cg_switch{arg=Src0,fail=Fail0,list=List0} = Last,
+ Src = beam_arg(Src0, St0),
+ {Fail1,St1} = use_block_label(Fail0, St0),
+ Fail = ensure_label(Fail1, St1),
+ {List1,St2} =
+ flatmapfoldl(fun({V,L}, S0) ->
+ {Lbl,S} = use_block_label(L, S0),
+ {[beam_arg(V, S),Lbl],S}
+ end, St1, List0),
+ {Is1,St} = cg_block(Is0, none, St2),
+ case reverse(Is1) of
+ [{bif,tuple_size,_,[Tuple],{z,_}=Src}|More] ->
+ List = map(fun({integer,Arity}) -> Arity;
+ ({f,_}=F) -> F
+ end, List1),
+ Is = reverse(More, [{select_tuple_arity,Tuple,Fail,{list,List}}]),
+ {Is,St};
+ _ ->
+ SelectVal = {select_val,Src,Fail,{list,List1}},
+ {Is1 ++ [SelectVal],St}
+ end.
+
+jump({f,_}=Fail) ->
+ {jump,Fail};
+jump({catch_tag,Fail}) ->
+ {jump,Fail}.
+
+bif_fail({f,_}=Fail) -> Fail;
+bif_fail({catch_tag,_}) -> {f,0}.
+
+next_block([]) -> none;
+next_block([{Next,_}|_]) -> Next.
+
+ensure_label(Fail0, #cg{ultimate_fail=Lbl}) ->
+ case bif_fail(Fail0) of
+ {f,0} -> {f,Lbl};
+ {f,_}=Fail -> Fail
+ end.
+
+cg_block([#cg_set{anno=#{recv_mark:=L}=Anno0}=I0|T], Context, St0) ->
+ Anno = maps:remove(recv_mark, Anno0),
+ I = I0#cg_set{anno=Anno},
+ {Is,St1} = cg_block([I|T], Context, St0),
+ {Fail,St} = use_block_label(L, St1),
+ {[{recv_mark,Fail}|Is],St};
+cg_block([#cg_set{op=new_try_tag,dst=Tag,args=Args}], {Tag,Fail0}, St) ->
+ {catch_tag,Fail} = Fail0,
+ [Reg,{atom,Kind}] = beam_args([Tag|Args], St),
+ {[{Kind,Reg,Fail}],St};
+cg_block([#cg_set{anno=Anno,op={bif,Name},dst=Dst0,args=Args0}=I,
+ #cg_set{op=succeeded,dst=Bool}], {Bool,Fail0}, St) ->
+ [Dst|Args] = beam_args([Dst0|Args0], St),
+ Line0 = call_line(body, {extfunc,erlang,Name,length(Args)}, Anno),
+ Fail = bif_fail(Fail0),
+ Line = case Fail of
+ {f,0} -> Line0;
+ {f,_} -> []
+ end,
+ case is_gc_bif(Name, Args) of
+ true ->
+ Live = get_live(I),
+ Kill = kill_yregs(Anno, St),
+ {Kill++Line++[{gc_bif,Name,Fail,Live,Args,Dst}],St};
+ false ->
+ {Line++[{bif,Name,Fail,Args,Dst}],St}
+ end;
+cg_block([#cg_set{op={bif,tuple_size},dst=Arity0,args=[Tuple0]},
+ #cg_set{op={bif,'=:='},dst=Bool,args=[Arity0,#b_literal{val=Ar}]}=Eq],
+ {Bool,Fail}=Context, St0) ->
+ Tuple = beam_arg(Tuple0, St0),
+ case beam_arg(Arity0, St0) of
+ {z,_} ->
+ %% The size will only be used once. Combine to a test_arity instruction.
+ Test = {test,test_arity,ensure_label(Fail, St0),[Tuple,Ar]},
+ {[Test],St0};
+ Arity ->
+ %% The size will be used more than once. Must do an explicit
+ %% BIF call followed by the '==' test.
+ TupleSize = {bif,tuple_size,{f,0},[Tuple],Arity},
+ {Is,St} = cg_block([Eq], Context, St0),
+ {[TupleSize|Is],St}
+ end;
+cg_block([#cg_set{op={bif,Name},dst=Dst0,args=Args0}]=Is0, {Dst0,Fail}, St0) ->
+ [Dst|Args] = beam_args([Dst0|Args0], St0),
+ case Dst of
+ {z,_} ->
+ %% The result of the BIF call will only be used once. Convert to
+ %% a test instruction.
+ Test = bif_to_test(Name, Args, ensure_label(Fail, St0)),
+ {Test,St0};
+ _ ->
+ %% Must explicitly call the BIF since the result will be used
+ %% more than once.
+ {Is1,St1} = cg_block(Is0, none, St0),
+ {Is2,St} = cg_block([], {Dst0,Fail}, St1),
+ {Is1++Is2,St}
+ end;
+cg_block([#cg_set{anno=Anno,op={bif,Name},dst=Dst0,args=Args0}=I|T],
+ Context, St0) ->
+ [Dst|Args] = beam_args([Dst0|Args0], St0),
+ {Is0,St} = cg_block(T, Context, St0),
+ case is_gc_bif(Name, Args) of
+ true ->
+ Line = call_line(body, {extfunc,erlang,Name,length(Args)}, Anno),
+ Live = get_live(I),
+ Kill = kill_yregs(Anno, St),
+ Is = Kill++Line++[{gc_bif,Name,{f,0},Live,Args,Dst}|Is0],
+ {Is,St};
+ false ->
+ Is = [{bif,Name,{f,0},Args,Dst}|Is0],
+ {Is,St}
+ end;
+cg_block([#cg_set{op=bs_init,dst=Dst0,args=Args0,anno=Anno}=I,
+ #cg_set{op=succeeded,dst=Bool}], {Bool,Fail0}, St) ->
+ Fail = bif_fail(Fail0),
+ Line = line(Anno),
+ [#b_literal{val=Kind}|Args1] = Args0,
+ case Kind of
+ new ->
+ [Dst,Size,{integer,Unit}] = beam_args([Dst0|Args1], St),
+ Live = get_live(I),
+ {[Line|cg_bs_init(Dst, Size, Unit, Live, Fail)],St};
+ private_append ->
+ [Dst,Src,Bits,{integer,Unit}] = beam_args([Dst0|Args1], St),
+ Flags = {field_flags,[]},
+ Is = [Line,{bs_private_append,Fail,Bits,Unit,Src,Flags,Dst}],
+ {Is,St};
+ append ->
+ [Dst,Src,Bits,{integer,Unit}] = beam_args([Dst0|Args1], St),
+ Flags = {field_flags,[]},
+ Live = get_live(I),
+ Is = [Line,{bs_append,Fail,Bits,0,Live,Unit,Src,Flags,Dst}],
+ {Is,St}
+ end;
+cg_block([#cg_set{anno=Anno,op=bs_start_match,dst=Ctx0,args=[Bin0]}=I,
+ #cg_set{op=succeeded,dst=Bool}], {Bool,Fail}, St) ->
+ #{num_slots:=Slots} = Anno,
+ [Dst,Bin1] = beam_args([Ctx0,Bin0], St),
+ {Bin,Pre} = force_reg(Bin1, Dst),
+ Live = get_live(I),
+ Is = Pre ++ [{test,bs_start_match2,Fail,Live,[Bin,Slots],Dst}],
+ {Is,St};
+cg_block([#cg_set{op=bs_get}=Set,
+ #cg_set{op=succeeded,dst=Bool}], {Bool,Fail}, St) ->
+ {cg_bs_get(Fail, Set, St),St};
+cg_block([#cg_set{op=bs_match_string,args=[CtxVar,#b_literal{val=String}]},
+ #cg_set{op=succeeded,dst=Bool}], {Bool,Fail}, St) ->
+ CtxReg = beam_arg(CtxVar, St),
+ Is = [{test,bs_match_string,Fail,[CtxReg,String]}],
+ {Is,St};
+cg_block([#cg_set{dst=Dst0,op=landingpad,args=Args0}|T], Context, St0) ->
+ [Dst,{atom,Kind},Tag] = beam_args([Dst0|Args0], St0),
+ case Kind of
+ 'catch' ->
+ cg_catch(Dst, T, Context, St0);
+ 'try' ->
+ cg_try(Dst, Tag, T, Context, St0)
+ end;
+cg_block([#cg_set{op=kill_try_tag,args=Args0}|Is], Context, St0) ->
+ [Reg] = beam_args(Args0, St0),
+ {Is0,St} = cg_block(Is, Context, St0),
+ {[{try_end,Reg}|Is0],St};
+cg_block([#cg_set{op=catch_end,dst=Dst0,args=Args0}|Is], Context, St0) ->
+ [Dst,Reg,{x,0}] = beam_args([Dst0|Args0], St0),
+ {Is0,St} = cg_block(Is, Context, St0),
+ {[{catch_end,Reg}|copy({x,0}, Dst)++Is0],St};
+cg_block([#cg_set{op=call}=I,
+ #cg_set{op=succeeded,dst=Bool}], {Bool,_Fail}, St) ->
+ %% A call in try/catch block.
+ cg_block([I], none, St);
+cg_block([#cg_set{op=Op,dst=Dst0,args=Args0}=I,
+ #cg_set{op=succeeded,dst=Bool}], {Bool,Fail}, St) ->
+ [Dst|Args] = beam_args([Dst0|Args0], St),
+ {cg_test(Op, bif_fail(Fail), Args, Dst, I),St};
+cg_block([#cg_set{op=bs_put,dst=Bool,args=Args0}], {Bool,Fail}, St) ->
+ Args = beam_args(Args0, St),
+ {cg_bs_put(bif_fail(Fail), Args),St};
+cg_block([#cg_set{op=bs_test_tail,dst=Bool,args=Args0}], {Bool,Fail}, St) ->
+ [Ctx,{integer,Bits}] = beam_args(Args0, St),
+ {[{test,bs_test_tail2,bif_fail(Fail),[Ctx,Bits]}],St};
+cg_block([#cg_set{op={float,checkerror},dst=Bool}], {Bool,Fail}, St) ->
+ {[{fcheckerror,bif_fail(Fail)}],St};
+cg_block([#cg_set{op=is_tagged_tuple,dst=Bool,args=Args0}], {Bool,Fail}, St) ->
+ [Src,{integer,Arity},Tag] = beam_args(Args0, St),
+ {[{test,is_tagged_tuple,ensure_label(Fail, St),[Src,Arity,Tag]}],St};
+cg_block([#cg_set{op=is_nonempty_list,dst=Bool,args=Args0}], {Bool,Fail}, St) ->
+ Args = beam_args(Args0, St),
+ {[{test,is_nonempty_list,ensure_label(Fail, St),Args}],St};
+cg_block([#cg_set{op=has_map_field,dst=Bool,args=Args0}], {Bool,Fail}, St) ->
+ [Src,Key] = beam_args(Args0, St),
+ {[{test,has_map_fields,Fail,Src,{list,[Key]}}],St};
+cg_block([#cg_set{op=call}=Call], {_Bool,_Fail}=Context, St0) ->
+ {Is0,St1} = cg_call(Call, body, none, St0),
+ {Is1,St} = cg_block([], Context, St1),
+ {Is0++Is1,St};
+cg_block([#cg_set{op=call,dst=Dst0}=Call], Context, St) ->
+ Dst = beam_arg(Dst0, St),
+ case Context of
+ {return,Dst,_} ->
+ cg_call(Call, tail, Context, St);
+ _ ->
+ cg_call(Call, body, Context, St)
+ end;
+cg_block([#cg_set{op=call}=Call|T], Context, St0) ->
+ {Is0,St1} = cg_call(Call, body, none, St0),
+ {Is1,St} = cg_block(T, Context, St1),
+ {Is0++Is1,St};
+cg_block([#cg_set{op=make_fun,dst=Dst0,args=[Local|Args0]}|T],
+ Context, St0) ->
+ #b_local{name=#b_literal{val=Func},arity=Arity} = Local,
+ [Dst|Args] = beam_args([Dst0|Args0], St0),
+ {FuncLbl,St1} = local_func_label(Func, Arity, St0),
+ Is0 = setup_args(Args) ++
+ [{make_fun2,{f,FuncLbl},0,0,length(Args)}|copy({x,0}, Dst)],
+ {Is1,St} = cg_block(T, Context, St1),
+ {Is0++Is1,St};
+cg_block([#cg_set{op=copy}|_]=T0, Context, St0) ->
+ {Is0,T} = cg_copy(T0, St0),
+ {Is1,St} = cg_block(T, Context, St0),
+ Is = Is0 ++ Is1,
+ case is_call(T) of
+ {yes,Arity} ->
+ {opt_call_moves(Is, Arity),St};
+ no ->
+ {Is,St}
+ end;
+cg_block([#cg_set{op=Op,dst=Dst0,args=Args0}=Set], none, St) ->
+ [Dst|Args] = beam_args([Dst0|Args0], St),
+ Is = cg_instr(Op, Args, Dst, Set),
+ {Is,St};
+cg_block([#cg_set{op=Op,dst=Dst0,args=Args0}=Set|T], Context, St0) ->
+ [Dst|Args] = beam_args([Dst0|Args0], St0),
+ Is0 = cg_instr(Op, Args, Dst, Set),
+ {Is1,St} = cg_block(T, Context, St0),
+ {Is0++Is1,St};
+cg_block([#cg_alloc{}=Alloc|T], Context, St0) ->
+ Is0 = cg_alloc(Alloc, St0),
+ {Is1,St} = cg_block(T, Context, St0),
+ {Is0++Is1,St};
+cg_block([], {return,Arg,none}, St) ->
+ Is = copy(Arg, {x,0}) ++ [return],
+ {Is,St};
+cg_block([], {return,Arg,N}, St) ->
+ Is = copy(Arg, {x,0}) ++ [{deallocate,N},return],
+ {Is,St};
+cg_block([], none, St) ->
+ {[],St};
+cg_block([], {Bool0,Fail}, St) ->
+ [Bool] = beam_args([Bool0], St),
+ {[{test,is_eq_exact,Fail,[Bool,{atom,true}]}],St}.
+
+cg_copy(T0, St) ->
+ {Copies,T} = splitwith(fun(#cg_set{op=copy}) -> true;
+ (_) -> false
+ end, T0),
+ Moves0 = cg_copy_1(Copies, St),
+ Moves1 = [Move || {move,Src,Dst}=Move <- Moves0, Src =/= Dst],
+ Scratch = {x,1022},
+ Moves = order_moves(Moves1, Scratch),
+ {Moves,T}.
+
+cg_copy_1([#cg_set{dst=Dst0,args=Args}|T], St) ->
+ [Dst,Src] = beam_args([Dst0|Args], St),
+ Copies = cg_copy_1(T, St),
+ case keymember(Dst, 3, Copies) of
+ true ->
+ %% Will be overwritten. Don't generate a move instruction.
+ Copies;
+ false ->
+ [{move,Src,Dst}|Copies]
+ end;
+cg_copy_1([], _St) -> [].
+
+bif_to_test('and', [V1,V2], Fail) ->
+ [{test,is_eq_exact,Fail,[V1,{atom,true}]},
+ {test,is_eq_exact,Fail,[V2,{atom,true}]}];
+bif_to_test('or', [V1,V2], {f,Lbl}=Fail) when Lbl =/= 0 ->
+ %% Labels are spaced 2 apart. We can create a new
+ %% label by incrementing the Fail label.
+ SuccLabel = Lbl + 1,
+ [{test,is_eq_exact,{f,SuccLabel},[V1,{atom,false}]},
+ {test,is_eq_exact,Fail,[V2,{atom,true}]},
+ {label,SuccLabel}];
+bif_to_test('not', [Var], Fail) ->
+ [{test,is_eq_exact,Fail,[Var,{atom,false}]}];
+bif_to_test(Name, Args, Fail) ->
+ [beam_utils:bif_to_test(Name, Args, Fail)].
+
+opt_call_moves(Is0, Arity) ->
+ {Moves0,Is} = splitwith(fun({move,_,_}) -> true;
+ (_) -> false
+ end, Is0),
+ Moves = opt_call_moves_1(Moves0, Arity),
+ Moves ++ Is.
+
+opt_call_moves_1([{move,Src,{x,_}=Tmp}=M1,{move,Tmp,Dst}=M2|Is], Arity) ->
+ case is_killed(Tmp, Is, Arity) of
+ true ->
+ %% The X register Tmp is never used again. We can collapse
+ %% the two move instruction into one.
+ [{move,Src,Dst}|opt_call_moves_1(Is, Arity)];
+ false ->
+ [M1|opt_call_moves_1([M2|Is], Arity)]
+ end;
+opt_call_moves_1([M|Ms], Arity) ->
+ [M|opt_call_moves_1(Ms, Arity)];
+opt_call_moves_1([], _Arity) -> [].
+
+is_killed(R, [{move,R,_}|_], _) ->
+ false;
+is_killed(R, [{move,_,R}|_], _) ->
+ true;
+is_killed(R, [{move,_,_}|Is], Arity) ->
+ is_killed(R, Is, Arity);
+is_killed({x,X}, [], Arity) ->
+ X >= Arity.
+
+cg_alloc(#cg_alloc{stack=none,words=#need{h=0,f=0}}, _St) ->
+ [];
+cg_alloc(#cg_alloc{stack=none,words=Need,live=Live}, _St) ->
+ [{test_heap,alloc(Need),Live}];
+cg_alloc(#cg_alloc{stack=Stk,words=Need,live=Live,def_yregs=DefYregs},
+ #cg{regs=Regs}) when is_integer(Stk) ->
+ Alloc = alloc(Need),
+ All = [{y,Y} || Y <- lists:seq(0, Stk-1)],
+ Def = ordsets:from_list([maps:get(V, Regs) || V <- DefYregs]),
+ NeedInit = ordsets:subtract(All, Def),
+ NoZero = length(Def)*2 > Stk,
+ I = case {NoZero,Alloc} of
+ {true,0} -> {allocate,Stk,Live};
+ {true,_} -> {allocate_heap,Stk,Alloc,Live};
+ {false,0} -> {allocate_zero,Stk,Live};
+ {false,_} -> {allocate_heap_zero,Stk,Alloc,Live}
+ end,
+ [I|case NoZero of
+ true -> [{init,Y} || Y <- NeedInit];
+ false -> []
+ end].
+
+alloc(#need{h=Words,f=0}) ->
+ Words;
+alloc(#need{h=Words,f=Floats}) ->
+ {alloc,[{words,Words},{floats,Floats}]}.
+
+is_call([#cg_set{op=call,args=[#b_var{}|Args]}|_]) ->
+ {yes,1+length(Args)};
+is_call([#cg_set{op=call,args=[_|Args]}|_]) ->
+ {yes,length(Args)};
+is_call([#cg_set{op=make_fun,args=[_|Args]}|_]) ->
+ {yes,length(Args)};
+is_call(_) ->
+ no.
+
+cg_call(#cg_set{anno=Anno,op=call,dst=Dst0,args=[#b_local{}=Func0|Args0]},
+ Where, Context, St0) ->
+ [Dst|Args] = beam_args([Dst0|Args0], St0),
+ #b_local{name=Name0,arity=Arity} = Func0,
+ {atom,Name} = beam_arg(Name0, St0),
+ {FuncLbl,St} = local_func_label(Name, Arity, St0),
+ Line = call_line(Where, local, Anno),
+ Call = build_call(call, Arity, {f,FuncLbl}, Context, Dst),
+ Is = setup_args(Args, Anno, Context, St) ++ Line ++ Call,
+ {Is,St};
+cg_call(#cg_set{anno=Anno0,op=call,dst=Dst0,args=[#b_remote{}=Func0|Args0]},
+ Where, Context, St) ->
+ [Dst|Args] = beam_args([Dst0|Args0], St),
+ #b_remote{mod=Mod0,name=Name0,arity=Arity} = Func0,
+ case {beam_arg(Mod0, St),beam_arg(Name0, St)} of
+ {{atom,Mod},{atom,Name}} ->
+ Func = {extfunc,Mod,Name,Arity},
+ Line = call_line(Where, Func, Anno0),
+ Call = build_call(call_ext, Arity, Func, Context, Dst),
+ Anno = case erl_bifs:is_exit_bif(Mod, Name, Arity) of
+ true ->
+ %% There is no need to kill Y registers
+ %% before calling an exit BIF.
+ maps:remove(kill_yregs, Anno0);
+ false ->
+ Anno0
+ end,
+ Is = setup_args(Args, Anno, Context, St) ++ Line ++ Call,
+ {Is,St};
+ {Mod,Name} ->
+ Apply = build_apply(Arity, Context, Dst),
+ Is = setup_args(Args++[Mod,Name], Anno0, Context, St) ++
+ [line(Anno0)] ++ Apply,
+ {Is,St}
+ end;
+cg_call(#cg_set{anno=Anno,op=call,dst=Dst0,args=Args0},
+ Where, Context, St) ->
+ [Dst,Func|Args] = beam_args([Dst0|Args0], St),
+ Line = call_line(Where, Func, Anno),
+ Arity = length(Args),
+ Call = build_call(call_fun, Arity, Func, Context, Dst),
+ Is = setup_args(Args++[Func], Anno, Context, St) ++ Line ++ Call,
+ {Is,St}.
+
+build_call(call_fun, Arity, _Func, none, Dst) ->
+ [{call_fun,Arity}|copy({x,0}, Dst)];
+build_call(call_fun, Arity, _Func, {return,Dst,N}, Dst) when is_integer(N) ->
+ [{call_fun,Arity},{deallocate,N},return];
+build_call(call_fun, Arity, _Func, {return,Val,N}, _Dst) when is_integer(N) ->
+ [{call_fun,Arity},{move,Val,{x,0}},{deallocate,N},return];
+build_call(call_ext, 2, {extfunc,erlang,'!',2}, none, Dst) ->
+ [send|copy({x,0}, Dst)];
+build_call(call_ext, 2, {extfunc,erlang,'!',2}, {return,Dst,N}, Dst)
+ when is_integer(N) ->
+ [send,{deallocate,N},return];
+build_call(Prefix, Arity, Func, {return,Dst,none}, Dst) ->
+ I = case Prefix of
+ call -> call_only;
+ call_ext -> call_ext_only
+ end,
+ [{I,Arity,Func}];
+build_call(call_ext, Arity, {extfunc,Mod,Name,Arity}=Func, {return,_,none}, _Dst) ->
+ true = erl_bifs:is_exit_bif(Mod, Name, Arity), %Assertion.
+ [{call_ext_only,Arity,Func}];
+build_call(Prefix, Arity, Func, {return,Dst,N}, Dst) when is_integer(N) ->
+ I = case Prefix of
+ call -> call_last;
+ call_ext -> call_ext_last
+ end,
+ [{I,Arity,Func,N}];
+build_call(I, Arity, Func, {return,Val,N}, _Dst) when is_integer(N) ->
+ [{I,Arity,Func}|copy(Val, {x,0})++[{deallocate,N},return]];
+build_call(I, Arity, Func, none, Dst) ->
+ [{I,Arity,Func}|copy({x,0}, Dst)].
+
+build_apply(Arity, {return,Dst,N}, Dst) when is_integer(N) ->
+ [{apply_last,Arity,N}];
+build_apply(Arity, {return,Val,N}, _Dst) when is_integer(N) ->
+ [{apply,Arity}|copy(Val, {x,0})++[{deallocate,N},return]];
+build_apply(Arity, none, Dst) ->
+ [{apply,Arity}|copy({x,0}, Dst)].
+
+cg_instr(put_map, [{atom,assoc},SrcMap|Ss], Dst, Set) ->
+ Live = get_live(Set),
+ [{put_map_assoc,{f,0},SrcMap,Dst,Live,{list,Ss}}];
+cg_instr(Op, Args, Dst, _Set) ->
+ cg_instr(Op, Args, Dst).
+
+cg_instr(bs_init_writable, Args, Dst) ->
+ setup_args(Args) ++ [bs_init_writable|copy({x,0}, Dst)];
+cg_instr(bs_restore, [Ctx,Slot], _Dst) ->
+ case Slot of
+ {integer,N} ->
+ [{bs_restore2,Ctx,N}];
+ {atom,start} ->
+ [{bs_restore2,Ctx,Slot}]
+ end;
+cg_instr(bs_save, [Ctx,Slot], _Dst) ->
+ {integer,N} = Slot,
+ [{bs_save2,Ctx,N}];
+cg_instr(build_stacktrace, Args, Dst) ->
+ setup_args(Args) ++ [build_stacktrace|copy({x,0}, Dst)];
+cg_instr(context_to_binary, [Src], _Dst) ->
+ [{bs_context_to_binary,Src}];
+cg_instr(set_tuple_element=Op, [New,Tuple,{integer,Index}], _Dst) ->
+ [{Op,New,Tuple,Index}];
+cg_instr({float,clearerror}, [], _Dst) ->
+ [fclearerror];
+cg_instr({float,get}, [Src], Dst) ->
+ [{fmove,Src,Dst}];
+cg_instr({float,put}, [Src], Dst) ->
+ [{fmove,Src,Dst}];
+cg_instr(get_hd=Op, [Src], Dst) ->
+ [{Op,Src,Dst}];
+cg_instr(get_tl=Op, [Src], Dst) ->
+ [{Op,Src,Dst}];
+cg_instr(get_tuple_element=Op, [Src,{integer,N}], Dst) ->
+ [{Op,Src,N,Dst}];
+cg_instr(put_list=Op, [Hd,Tl], Dst) ->
+ [{Op,Hd,Tl,Dst}];
+cg_instr(put_tuple, Elements, Dst) ->
+ [{put_tuple2,Dst,{list,Elements}}];
+cg_instr(put_tuple_arity, [{integer,Arity}], Dst) ->
+ [{put_tuple,Arity,Dst}];
+cg_instr(put_tuple_elements, Elements, _Dst) ->
+ [{put,E} || E <- Elements];
+cg_instr(raw_raise, Args, Dst) ->
+ setup_args(Args) ++ [raw_raise|copy({x,0}, Dst)];
+cg_instr(remove_message, [], _Dst) ->
+ [remove_message];
+cg_instr(resume, [A,B], _Dst) ->
+ [{bif,raise,{f,0},[A,B],{x,0}}];
+cg_instr(timeout, [], _Dst) ->
+ [timeout].
+
+cg_test(bs_add=Op, Fail, [Src1,Src2,{integer,Unit}], Dst, _I) ->
+ [{Op,Fail,[Src1,Src2,Unit],Dst}];
+cg_test(bs_skip, Fail, Args, _Dst, I) ->
+ cg_bs_skip(Fail, Args, I);
+cg_test(bs_utf8_size=Op, Fail, [Src], Dst, _I) ->
+ [{Op,Fail,Src,Dst}];
+cg_test(bs_utf16_size=Op, Fail, [Src], Dst, _I) ->
+ [{Op,Fail,Src,Dst}];
+cg_test({float,convert}, Fail, [Src], Dst, _I) ->
+ {f,0} = Fail, %Assertion.
+ [{fconv,Src,Dst}];
+cg_test({float,Op0}, Fail, Args, Dst, #cg_set{anno=Anno}) ->
+ Op = case Op0 of
+ '+' -> fadd;
+ '-' when length(Args) =:= 2 -> fsub;
+ '-' -> fnegate;
+ '*' -> fmul;
+ '/' -> fdiv
+ end,
+ [line(Anno),{bif,Op,Fail,Args,Dst}];
+cg_test(get_map_element, Fail, [Map,Key], Dst, _I) ->
+ [{get_map_elements,Fail,Map,{list,[Key,Dst]}}];
+cg_test(peek_message, Fail, [], Dst, _I) ->
+ [{loop_rec,Fail,{x,0}}|copy({x,0}, Dst)];
+cg_test(put_map, Fail, [{atom,exact},SrcMap|Ss], Dst, Set) ->
+ Live = get_live(Set),
+ [{put_map_exact,Fail,SrcMap,Dst,Live,{list,Ss}}];
+cg_test(wait_timeout, Fail, [Timeout], _Dst, _) ->
+ case Timeout of
+ {atom,infinity} ->
+ [{wait,Fail}];
+ _ ->
+ [{wait_timeout,Fail,Timeout}]
+ end.
+
+cg_bs_get(Fail, #cg_set{dst=Dst0,args=[#b_literal{val=Type}|Ss0]}=Set, St) ->
+ Op = case Type of
+ integer -> bs_get_integer2;
+ float -> bs_get_float2;
+ binary -> bs_get_binary2;
+ utf8 -> bs_get_utf8;
+ utf16 -> bs_get_utf16;
+ utf32 -> bs_get_utf32
+ end,
+ [Dst|Ss1] = beam_args([Dst0|Ss0], St),
+ Ss = case Ss1 of
+ [Ctx,{literal,Flags},Size,{integer,Unit}] ->
+ %% Plain integer/float/binary.
+ [Ctx,Size,Unit,field_flags(Flags, Set)];
+ [Ctx,{literal,Flags}] ->
+ %% Utf8/16/32.
+ [Ctx,field_flags(Flags, Set)]
+ end,
+ Live = get_live(Set),
+ [{test,Op,Fail,Live,Ss,Dst}].
+
+cg_bs_skip(Fail, [{atom,Type}|Ss0], Set) ->
+ Op = case Type of
+ utf8 -> bs_skip_utf8;
+ utf16 -> bs_skip_utf16;
+ utf32 -> bs_skip_utf32;
+ _ -> bs_skip_bits2
+ end,
+ Live = get_live(Set),
+ Ss = case Ss0 of
+ [Ctx,{literal,Flags},Size,{integer,Unit}] ->
+ %% Plain integer/float/binary.
+ [Ctx,Size,Unit,field_flags(Flags, Set)];
+ [Ctx,{literal,Flags}] ->
+ %% Utf8/16/32.
+ [Ctx,Live,field_flags(Flags, Set)]
+ end,
+ case {Type,Ss} of
+ {binary,[_,{atom,all},1,_]} ->
+ [];
+ {binary,[R,{atom,all},U,_]} ->
+ [{test,bs_test_unit,Fail,[R,U]}];
+ {_,_} ->
+ [{test,Op,Fail,Ss}]
+ end.
+
+field_flags(Flags, #cg_set{anno=#{location:={File,Line}}}) ->
+ {field_flags,[{anno,[Line,{file,File}]}|Flags]};
+field_flags(Flags, _) ->
+ {field_flags,Flags}.
+
+cg_bs_put(Fail, [{atom,Type},{literal,Flags}|Args]) ->
+ Op = case Type of
+ integer -> bs_put_integer;
+ float -> bs_put_float;
+ binary -> bs_put_binary;
+ utf8 -> bs_put_utf8;
+ utf16 -> bs_put_utf16;
+ utf32 -> bs_put_utf32
+ end,
+ case Args of
+ [Src,Size,{integer,Unit}] ->
+ [{Op,Fail,Size,Unit,{field_flags,Flags},Src}];
+ [Src] ->
+ [{Op,Fail,{field_flags,Flags},Src}]
+ end.
+
+cg_bs_init(Dst, Size0, Unit, Live, Fail) ->
+ Op = case Unit of
+ 1 -> bs_init_bits;
+ 8 -> bs_init2
+ end,
+ Size = cg_bs_init_size(Size0),
+ [{Op,Fail,Size,0,Live,{field_flags,[]},Dst}].
+
+cg_bs_init_size({x,_}=R) -> R;
+cg_bs_init_size({y,_}=R) -> R;
+cg_bs_init_size({integer,Int}) -> Int.
+
+cg_catch(Agg, T0, Context, St0) ->
+ {Moves,T1} = cg_extract(T0, Agg, St0),
+ {T,St} = cg_block(T1, Context, St0),
+ {Moves++T,St}.
+
+cg_try(Agg, Tag, T0, Context, St0) ->
+ {Moves0,T1} = cg_extract(T0, Agg, St0),
+ Moves = order_moves(Moves0, {x,3}),
+ [#cg_set{op=kill_try_tag}|T2] = T1,
+ {T,St} = cg_block(T2, Context, St0),
+ {[{try_case,Tag}|Moves++T],St}.
+
+cg_extract([#cg_set{op=extract,dst=Dst0,args=Args0}|Is0], Agg, St) ->
+ [Dst,Agg,{integer,X}] = beam_args([Dst0|Args0], St),
+ {Ds,Is} = cg_extract(Is0, Agg, St),
+ case keymember(Dst, 3, Ds) of
+ true ->
+ %% This destination will be overwritten.
+ {Ds,Is};
+ false ->
+ {copy({x,X}, Dst)++Ds,Is}
+ end;
+cg_extract(Is, _, _) ->
+ {[],Is}.
+
+copy(Src, Src) -> [];
+copy(Src, Dst) -> [{move,Src,Dst}].
+
+force_reg({literal,_}=Lit, Reg) ->
+ {Reg,[{move,Lit,Reg}]};
+force_reg({Kind,_}=R, _) when Kind =:= x; Kind =:= y ->
+ {R,[]}.
+
+%% successors(Terminator) -> [Successor].
+%% Return an ordset of all successors for the given terminator.
+
+successors(#cg_br{succ=Succ,fail=Fail}) ->
+ ordsets:from_list([Succ,Fail]);
+successors(#cg_switch{fail=Fail,list=List}) ->
+ ordsets:from_list([Fail|[Lbl || {_,Lbl} <- List]]);
+successors(#cg_ret{}) -> [].
+
+%% linearize(Blocks) -> [{BlockLabel,#cg_blk{}}].
+%% Linearize the intermediate representation of the code. Also
+%% translate blocks from the SSA records to internal record types
+%% used only in this module.
+
+linearize(Blocks) ->
+ Linear = beam_ssa:linearize(Blocks),
+ linearize_1(Linear, Blocks).
+
+linearize_1([{?BADARG_BLOCK,_}|Ls], Blocks) ->
+ linearize_1(Ls, Blocks);
+linearize_1([{L,Block0}|Ls], Blocks) ->
+ Block = translate_block(L, Block0, Blocks),
+ [{L,Block}|linearize_1(Ls, Blocks)];
+linearize_1([], _Blocks) -> [].
+
+%% translate_block(BlockLabel, #b_blk{}, Blocks) -> #cg_blk{}.
+%% Translate a block to the internal records used in this module.
+%% Also eliminate phi nodes, replacing them with 'copy' instructions
+%% in the predecessor blocks.
+
+translate_block(L, #b_blk{anno=Anno,is=Is0,last=Last0}, Blocks) ->
+ Last = translate_terminator(Last0),
+ PhiCopies = translate_phis(L, Last, Blocks),
+ Is1 = translate_is(Is0, PhiCopies),
+ Is = case Anno of
+ #{frame_size:=Size} ->
+ Alloc = #cg_alloc{stack=Size},
+ [Alloc|Is1];
+ #{} -> Is1
+ end,
+ #cg_blk{anno=Anno,is=Is,last=Last}.
+
+translate_is([#b_set{op=phi}|Is], Tail) ->
+ translate_is(Is, Tail);
+translate_is([#b_set{anno=Anno0,op=Op,dst=Dst,args=Args}=I|Is], Tail) ->
+ Anno = case beam_ssa:clobbers_xregs(I) of
+ true -> Anno0#{clobbers=>true};
+ false -> Anno0
+ end,
+ [#cg_set{anno=Anno,op=Op,dst=Dst,args=Args}|translate_is(Is, Tail)];
+translate_is([], Tail) -> Tail.
+
+translate_terminator(#b_ret{anno=Anno,arg=Arg}) ->
+ Dealloc = case Anno of
+ #{deallocate:=N} -> N;
+ #{} -> none
+ end,
+ #cg_ret{arg=Arg,dealloc=Dealloc};
+translate_terminator(#b_br{bool=#b_literal{val=true},succ=Succ}) ->
+ #cg_br{bool=#b_literal{val=true},succ=Succ,fail=Succ};
+translate_terminator(#b_br{bool=#b_literal{val=false},fail=Fail}) ->
+ #cg_br{bool=#b_literal{val=true},succ=Fail,fail=Fail};
+translate_terminator(#b_br{bool=Bool,succ=Succ,fail=Fail}) ->
+ #cg_br{bool=Bool,succ=Succ,fail=Fail};
+translate_terminator(#b_switch{arg=Bool,fail=Fail,list=List}) ->
+ #cg_switch{arg=Bool,fail=Fail,list=List}.
+
+translate_phis(L, #cg_br{succ=Target,fail=Target}, Blocks) ->
+ #b_blk{is=Is} = maps:get(Target, Blocks),
+ Phis = takewhile(fun(#b_set{op=phi}) -> true;
+ (#b_set{}) -> false
+ end, Is),
+ phi_copies(Phis, L);
+translate_phis(_, _, _) -> [].
+
+phi_copies([#b_set{dst=Dst,args=PhiArgs}|Sets], L) ->
+ CopyArgs = [V || {V,Target} <- PhiArgs, Target =:= L],
+ [#cg_set{op=copy,dst=Dst,args=CopyArgs}|phi_copies(Sets, L)];
+phi_copies([], _) -> [].
+
+%% setup_args(Args, Anno, Context) -> [Instruction].
+%% setup_args(Args) -> [Instruction].
+%% Set up X registers for a call.
+
+setup_args(Args, Anno, none, St) ->
+ setup_args(Args) ++ kill_yregs(Anno, St);
+setup_args(Args, _, _, _) ->
+ setup_args(Args).
+
+setup_args([]) ->
+ [];
+setup_args([_|_]=Args) ->
+ Moves = gen_moves(Args, 0, []),
+ Scratch = {x,1+last(sort([length(Args)-1|[X || {x,X} <- Args]]))},
+ order_moves(Moves, Scratch).
+
+%% kill_yregs(Anno, #cg{}) -> [{kill,{y,Y}}].
+%% Kill Y registers that will not be used again.
+
+kill_yregs(#{kill_yregs:=Kill}, #cg{regs=Regs}) ->
+ ordsets:from_list([{kill,maps:get(V, Regs)} || V <- Kill]);
+kill_yregs(#{}, #cg{}) -> [].
+
+%% gen_moves(As, I, Acc)
+%% Generate the basic move instruction to move the arguments
+%% to their proper registers. The list will be sorted on
+%% destinations. (I.e. the move to {x,0} will be first --
+%% see the comment to order_moves/2.)
+
+gen_moves([A|As], I, Acc) ->
+ gen_moves(As, I+1, copy(A, {x,I}) ++ Acc);
+gen_moves([], _, Acc) ->
+ keysort(3, Acc).
+
+%% order_moves([Move], ScratchReg) -> [Move]
+%% Orders move instruction so that source registers are not
+%% destroyed before they are used. If there are cycles
+%% (such as {move,{x,0},{x,1}}, {move,{x,1},{x,1}}),
+%% the scratch register is used to break up the cycle.
+%% If possible, the first move of the input list is placed
+%% last in the result list (to make the move to {x,0} occur
+%% just before the call to allow the Beam loader to coalesce
+%% the instructions).
+
+order_moves(Ms, Scr) -> order_moves(Ms, Scr, []).
+
+order_moves([{move,_,_}=M|Ms0], ScrReg, Acc0) ->
+ {Chain,Ms} = collect_chain(Ms0, [M], ScrReg),
+ Acc = reverse(Chain, Acc0),
+ order_moves(Ms, ScrReg, Acc);
+order_moves([], _, Acc) -> Acc.
+
+collect_chain(Ms, Path, ScrReg) ->
+ collect_chain(Ms, Path, [], ScrReg).
+
+collect_chain([{move,Src,Same}=M|Ms0], [{move,Same,_}|_]=Path, Others, ScrReg) ->
+ case keymember(Src, 3, Path) of
+ false ->
+ collect_chain(reverse(Others, Ms0), [M|Path], [], ScrReg);
+ true ->
+ %% There is a cycle, which we must break up.
+ {break_up_cycle(M, Path, ScrReg),reverse(Others, Ms0)}
+ end;
+collect_chain([M|Ms], Path, Others, ScrReg) ->
+ collect_chain(Ms, Path, [M|Others], ScrReg);
+collect_chain([], Path, Others, _) ->
+ {Path,Others}.
+
+break_up_cycle({move,Src,_}=M, Path, ScrReg) ->
+ [{move,ScrReg,Src},M|break_up_cycle1(Src, Path, ScrReg)].
+
+break_up_cycle1(Dst, [{move,Src,Dst}|Path], ScrReg) ->
+ [{move,Src,ScrReg}|Path];
+break_up_cycle1(Dst, [M|Path], LastMove) ->
+ [M|break_up_cycle1(Dst, Path, LastMove)].
+
+%%%
+%%% General utility functions.
+%%%
+
+verify_beam_register({x,_}=Reg) -> Reg.
+
+is_beam_register({x,_}) -> true;
+is_beam_register(_) -> false.
+
+get_register(V, Regs) ->
+ case is_beam_register(V) of
+ true -> V;
+ false -> maps:get(V, Regs)
+ end.
+
+beam_args(As, St) ->
+ [beam_arg(A, St) || A <- As].
+
+beam_arg(#b_var{}=Name, #cg{regs=Regs}) ->
+ maps:get(Name, Regs);
+beam_arg(#b_literal{val=Val}, _) ->
+ if
+ is_atom(Val) -> {atom,Val};
+ is_float(Val) -> {float,Val};
+ is_integer(Val) -> {integer,Val};
+ Val =:= [] -> nil;
+ true -> {literal,Val}
+ end;
+beam_arg(Reg, _) ->
+ verify_beam_register(Reg).
+
+new_block_label(L, St0) ->
+ {_Lbl,St} = label_for_block(L, St0),
+ St.
+
+def_block_label(L, #cg{labels=Labels,used_labels=Used}) ->
+ Lbl = maps:get(L, Labels),
+ case gb_sets:is_member(Lbl, Used) of
+ false -> [];
+ true -> [{label,Lbl}]
+ end.
+
+use_block_labels(Ls, St) ->
+ mapfoldl(fun use_block_label/2, St, Ls).
+
+use_block_label(L, #cg{used_labels=Used,catches=Catches}=St0) ->
+ {Lbl,St} = label_for_block(L, St0),
+ case gb_sets:is_member(L, Catches) of
+ true ->
+ {{catch_tag,{f,Lbl}},
+ St#cg{used_labels=gb_sets:add(Lbl, Used)}};
+ false ->
+ {{f,Lbl},St#cg{used_labels=gb_sets:add(Lbl, Used)}}
+ end.
+
+label_for_block(L, #cg{labels=Labels0}=St0) ->
+ case Labels0 of
+ #{L:=Lbl} ->
+ {Lbl,St0};
+ #{} ->
+ {Lbl,St} = new_label(St0),
+ Labels = Labels0#{L=>Lbl},
+ {Lbl,St#cg{labels=Labels}}
+ end.
+
+%% local_func_label(Name, Arity, State) -> {Label,State'}
+%% local_func_label({Name,Arity}, State) -> {Label,State'}
+%% Get the function entry label for a local function.
+
+local_func_label(Name, Arity, St) ->
+ local_func_label({Name,Arity}, St).
+
+local_func_label(Key, #cg{functable=Map}=St0) ->
+ case Map of
+ #{Key := Label} ->
+ {Label,St0};
+ _ ->
+ {Label,St} = new_label(St0),
+ {Label,St#cg{functable=Map#{Key => Label}}}
+ end.
+
+%% is_gc_bif(Name, Args) -> true|false.
+%% Determines whether the BIF Name/Arity might do a GC.
+
+-spec is_gc_bif(atom(), [beam_ssa:value()]) -> boolean().
+
+is_gc_bif(hd, [_]) -> false;
+is_gc_bif(tl, [_]) -> false;
+is_gc_bif(self, []) -> false;
+is_gc_bif(node, []) -> false;
+is_gc_bif(node, [_]) -> false;
+is_gc_bif(element, [_,_]) -> false;
+is_gc_bif(get, [_]) -> false;
+is_gc_bif(is_map_key, [_,_]) -> false;
+is_gc_bif(map_get, [_,_]) -> false;
+is_gc_bif(tuple_size, [_]) -> false;
+is_gc_bif(Bif, Args) ->
+ Arity = length(Args),
+ not (erl_internal:bool_op(Bif, Arity) orelse
+ erl_internal:new_type_test(Bif, Arity) orelse
+ erl_internal:comp_op(Bif, Arity)).
+
+%% new_label(St) -> {L,St}.
+
+new_label(#cg{lcount=Next}=St) ->
+ %% Advance the label counter by 2 to allow us to create
+ %% a label for 'or' by incrementing an existing label.
+ {Next,St#cg{lcount=Next+2}}.
+
+%% call_line(tail|body, Func, Anno) -> [] | [{line,...}].
+%% Produce a line instruction if it will be needed by the
+%% call to Func.
+
+call_line(_Context, {extfunc,Mod,Name,Arity}, Anno) ->
+ case erl_bifs:is_safe(Mod, Name, Arity) of
+ false ->
+ %% The call could be to a BIF.
+ %% We'll need a line instruction in case the
+ %% BIF call fails.
+ [line(Anno)];
+ true ->
+ %% Call to a safe BIF. Since it cannot fail,
+ %% we don't need any line instruction here.
+ []
+ end;
+call_line(body, _, Anno) ->
+ [line(Anno)];
+call_line(tail, local, _) ->
+ %% Tail-recursive call to a local function. A line
+ %% instruction will not be useful.
+ [];
+call_line(tail, _, Anno) ->
+ %% Call to a fun.
+ [line(Anno)].
+
+%% line(Le) -> {line,[] | {location,File,Line}}
+%% Create a line instruction, containing information about
+%% the current filename and line number. A line information
+%% instruction should be placed before any operation that could
+%% cause an exception.
+
+line(#{location:={File,Line}}) ->
+ {line,[{location,File,Line}]};
+line(#{}) ->
+ {line,[]}.
+
+flatmapfoldl(F, Accu0, [Hd|Tail]) ->
+ {R,Accu1} = F(Hd, Accu0),
+ {Rs,Accu2} = flatmapfoldl(F, Accu1, Tail),
+ {R++Rs,Accu2};
+flatmapfoldl(_, Accu, []) -> {[],Accu}.
diff --git a/lib/compiler/src/beam_ssa_dead.erl b/lib/compiler/src/beam_ssa_dead.erl
new file mode 100644
index 0000000000..c20652580d
--- /dev/null
+++ b/lib/compiler/src/beam_ssa_dead.erl
@@ -0,0 +1,1001 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+%% Dead code is code that is executed but has no effect. This
+%% optimization pass either removes dead code or jumps around it,
+%% potentially making it unreachable so that it can be dropped
+%% the next time beam_ssa:linearize/1 is called.
+%%
+
+-module(beam_ssa_dead).
+-export([opt/1]).
+
+-include("beam_ssa.hrl").
+-import(lists, [append/1,last/1,member/2,takewhile/2,reverse/1]).
+
+-type used_vars() :: #{beam_ssa:label():=ordsets:ordset(beam_ssa:var_name())}.
+
+-type basic_type_test() :: atom() | {'is_tagged_tuple',pos_integer(),atom()}.
+-type type_test() :: basic_type_test() | {'not',basic_type_test()}.
+-type op_name() :: atom().
+-type basic_rel_op() :: {op_name(),beam_ssa:b_var(),beam_ssa:value()} |
+ {basic_type_test(),beam_ssa:value()}.
+-type rel_op() :: {op_name(),beam_ssa:b_var(),beam_ssa:value()} |
+ {type_test(),beam_ssa:value()}.
+
+-record(st,
+ {bs :: beam_ssa:block_map(),
+ us :: used_vars(),
+ skippable :: #{beam_ssa:label():='true'},
+ rel_op=none :: 'none' | rel_op(),
+ target=any :: 'any' | 'one_way' | beam_ssa:label()
+ }).
+
+-spec opt([{Label0,Block0}]) -> [{Label,Block}] when
+ Label0 :: beam_ssa:label(),
+ Block0 :: beam_ssa:b_blk(),
+ Label :: beam_ssa:label(),
+ Block :: beam_ssa:b_blk().
+
+opt(Linear) ->
+ {Used,Skippable} = used_vars(Linear),
+ Blocks0 = maps:from_list(Linear),
+ St0 = #st{bs=Blocks0,us=Used,skippable=Skippable},
+ St = shortcut_opt(St0),
+ #st{bs=Blocks} = combine_eqs(St),
+ beam_ssa:linearize(Blocks).
+
+%%%
+%%% Shortcut br/switch targets.
+%%%
+%%% A br/switch may branch to another br/switch that in turn always
+%%% branches to another target. Rewrite br/switch to refer to the
+%%% ultimate targets directly. That will save execution time, but
+%%% could also reduce the size of the code if some of the original
+%%% targets become unreachable and be deleted.
+%%%
+%%% When rewriting branches, we must be careful not to skip instructions
+%%% that have side effects or that bind variables that will be used
+%%% at the new target.
+%%%
+%%% We must also avoid branching to phi nodes. The reason is
+%%% twofold. First, we might create a critical edge which is strictly
+%%% forbidden. Second, there will be a branch from a block that is not
+%%% listed in the list of predecessors in the phi node. Those
+%%% limitations could probably be overcome, but it is not clear how
+%%% much that would improve the code.
+%%%
+
+shortcut_opt(#st{bs=Blocks}=St) ->
+ %% Processing the blocks in reverse post order seems to give more
+ %% opportunities for optimizations compared to post order. (Based on
+ %% running scripts/diffable with both PO and RPO and looking at
+ %% the diff.)
+ Ls = beam_ssa:rpo(Blocks),
+ shortcut_opt(Ls, #{from=>0}, St).
+
+shortcut_opt([L|Ls], Bs0, #st{bs=Blocks0}=St) ->
+ #b_blk{is=Is,last=Last0} = Blk0 = get_block(L, St),
+ Bs = Bs0#{from:=L},
+ case shortcut_terminator(Last0, Is, Bs, St) of
+ Last0 ->
+ %% No change. No need to update the block.
+ shortcut_opt(Ls, Bs, St);
+ Last ->
+ %% The terminator was simplified in some way.
+ %% Update the block.
+ Blk = Blk0#b_blk{last=Last},
+ Blocks = Blocks0#{L=>Blk},
+ shortcut_opt(Ls, Bs, St#st{bs=Blocks})
+ end;
+shortcut_opt([], _, St) -> St.
+
+shortcut_terminator(#b_br{bool=#b_literal{val=true},succ=Succ0},
+ _Is, Bs, St0) ->
+ St = St0#st{rel_op=none},
+ shortcut(Succ0, Bs, St);
+shortcut_terminator(#b_br{bool=#b_var{}=Bool,succ=Succ0,fail=Fail0}=Br,
+ Is, Bs, St0) ->
+ St = St0#st{target=one_way},
+ RelOp = get_rel_op(Bool, Is),
+ SuccBs = bind_var(Bool, #b_literal{val=true}, Bs),
+ BrSucc = shortcut(Succ0, SuccBs, St#st{rel_op=RelOp}),
+ FailBs = bind_var(Bool, #b_literal{val=false}, Bs),
+ BrFail = shortcut(Fail0, FailBs, St#st{rel_op=invert_op(RelOp)}),
+ case {BrSucc,BrFail} of
+ {#b_br{bool=#b_literal{val=true},succ=Succ},
+ #b_br{bool=#b_literal{val=true},succ=Fail}}
+ when Succ =/= Succ0; Fail =/= Fail0 ->
+ %% One or both of the targets were cut short.
+ beam_ssa:normalize(Br#b_br{succ=Succ,fail=Fail});
+ {_,_} ->
+ %% No change.
+ Br
+ end;
+shortcut_terminator(#b_switch{arg=Bool,list=List0}=Sw, _Is, Bs, St) ->
+ List = shortcut_switch(List0, Bool, Bs, St),
+ beam_ssa:normalize(Sw#b_switch{list=List});
+shortcut_terminator(Last, _Is, _Bs, _St) ->
+ Last.
+
+shortcut_switch([{Lit,L0}|T], Bool, Bs, St0) ->
+ St = St0#st{rel_op=normalize_op({bif,'=:='}, [Bool,Lit])},
+ #b_br{bool=#b_literal{val=true},succ=L} =
+ shortcut(L0, bind_var(Bool, Lit, Bs), St#st{target=one_way}),
+ [{Lit,L}|shortcut_switch(T, Bool, Bs, St0)];
+shortcut_switch([], _, _, _) -> [].
+
+shortcut(L, Bs, St) ->
+ shortcut_1(L, Bs, ordsets:new(), St).
+
+shortcut_1(L, Bs0, UnsetVars0, St) ->
+ case shortcut_2(L, Bs0, UnsetVars0, St) of
+ none ->
+ %% No more shortcuts found. Package up the previous
+ %% label in an unconditional branch.
+ #b_br{bool=#b_literal{val=true},succ=L,fail=L};
+ {#b_br{bool=#b_var{}}=Br,_,_} ->
+ %% This is a two-way branch. We can't do any better.
+ Br;
+ {#b_br{bool=#b_literal{val=true},succ=Succ},Bs,UnsetVars} ->
+ %% This is a safe `br`, but try to find a better one.
+ shortcut_1(Succ, Bs#{from:=L}, UnsetVars, St)
+ end.
+
+%% Try to shortcut this block, branching to a successor.
+shortcut_2(L, Bs0, UnsetVars0, St) ->
+ #b_blk{is=Is,last=Last} = get_block(L, St),
+ case eval_is(Is, Bs0, St) of
+ none ->
+ %% It is not safe to avoid this block because it
+ %% has instructions with potential side effects.
+ none;
+ Bs ->
+ %% The instructions in the block (if any) don't
+ %% have any side effects and can be skipped.
+ %% Evaluate the terminator.
+ case eval_terminator(Last, Bs, St) of
+ none ->
+ %% The terminator is not suitable (could be
+ %% because it is a switch that can't be simplified
+ %% or it is a ret instruction).
+ none;
+ #b_br{}=Br ->
+ %% We have a potentially suitable br.
+ %% Now update the set of variables that will never
+ %% be set if this block will be skipped.
+ UnsetVars1 = [V || #b_set{dst=V} <- Is],
+ UnsetVars = ordsets:union(UnsetVars0,
+ ordsets:from_list(UnsetVars1)),
+
+ %% Continue checking whether this br is suitable.
+ shortcut_3(Br, Bs#{from:=L}, UnsetVars, St)
+ end
+ end.
+
+shortcut_3(Br, Bs, UnsetVars, #st{target=Target}=St) ->
+ case is_br_safe(UnsetVars, Br, St) of
+ false ->
+ %% Branching using this `br` is unsafe, either because it
+ %% is an unconditional branch to a phi node, or because
+ %% one or more of the variables that are not set will be
+ %% used. Try to follow branches of this `br`, to find a
+ %% safe `br`.
+ case Br of
+ #b_br{bool=#b_literal{val=true},succ=L} ->
+ case Target of
+ L ->
+ %% We have reached the forced target, and it
+ %% is unsafe. Give up.
+ none;
+ _ ->
+ %% Try following this branch to see whether it
+ %% leads to a safe `br`.
+ shortcut_2(L, Bs, UnsetVars, St)
+ end;
+ #b_br{bool=#b_var{},succ=Succ,fail=Fail} ->
+ case {Succ,Fail} of
+ {L,Target} ->
+ %% The failure label is the forced target.
+ %% Try following the success label to see
+ %% whether it also ultimately ends up at the
+ %% forced target.
+ shortcut_2(L, Bs, UnsetVars, St);
+ {Target,L} ->
+ %% The success label is the forced target.
+ %% Try following the failure label to see
+ %% whether it also ultimately ends up at the
+ %% forced target.
+ shortcut_2(L, Bs, UnsetVars, St);
+ {_,_} ->
+ case Target of
+ any ->
+ %% This two-way branch is unsafe. Try reducing
+ %% it to a one-way branch.
+ shortcut_two_way(Br, Bs, UnsetVars, St);
+ one_way ->
+ %% This two-way branch is unsafe. Try reducing
+ %% it to a one-way branch.
+ shortcut_two_way(Br, Bs, UnsetVars, St);
+ _ when is_integer(Target) ->
+ %% This two-way branch is unsafe, and
+ %% there already is a forced target.
+ %% Give up.
+ none
+ end
+ end
+ end;
+ true ->
+ %% This `br` instruction is safe. It does not
+ %% branch to a phi node, and all variables that
+ %% will be used are guaranteed to be defined.
+ case Br of
+ #b_br{bool=#b_literal{val=true},succ=L} ->
+ %% This is a one-way branch.
+ case Target of
+ any ->
+ %% No forced target. Success!
+ {Br,Bs,UnsetVars};
+ one_way ->
+ %% The target must be a one-way branch, which this
+ %% `br` is. Success!
+ {Br,Bs,UnsetVars};
+ L when is_integer(Target) ->
+ %% The forced target is L. Success!
+ {Br,Bs,UnsetVars};
+ _ when is_integer(Target) ->
+ %% Wrong forced target. Try following this branch
+ %% to see if it ultimately ends up at the forced
+ %% target.
+ shortcut_2(L, Bs, UnsetVars, St)
+ end;
+ #b_br{bool=#b_var{}} ->
+ %% This is a two-way branch.
+ if
+ Target =:= any; Target =:= one_way ->
+ %% No specific forced target. Try to reduce the
+ %% two-way branch to an one-way branch.
+ case shortcut_two_way(Br, Bs, UnsetVars, St) of
+ none when Target =:= any ->
+ %% This `br` can't be reduced to a one-way
+ %% branch. Return the `br` as-is.
+ {Br,Bs,UnsetVars};
+ none when Target =:= one_way ->
+ %% This `br` can't be reduced to a one-way
+ %% branch. The caller wants a one-way branch.
+ %% Give up.
+ none;
+ {_,_,_}=Res ->
+ %% This `br` was successfully reduced to a
+ %% one-way branch.
+ Res
+ end;
+ is_integer(Target) ->
+ %% There is a forced target, which can't
+ %% be reached because this `br` is a two-way
+ %% branch. Give up.
+ none
+ end
+ end
+ end.
+
+shortcut_two_way(#b_br{succ=Succ,fail=Fail}, Bs0, UnsetVars0, St) ->
+ case shortcut_2(Succ, Bs0, UnsetVars0, St#st{target=Fail}) of
+ {#b_br{bool=#b_literal{},succ=Fail},_,_}=Res ->
+ Res;
+ none ->
+ case shortcut_2(Fail, Bs0, UnsetVars0, St#st{target=Succ}) of
+ {#b_br{bool=#b_literal{},succ=Succ},_,_}=Res ->
+ Res;
+ none ->
+ none
+ end
+ end.
+
+get_block(L, St) ->
+ #st{bs=#{L:=Blk}} = St,
+ Blk.
+
+is_br_safe(UnsetVars, Br, #st{us=Us}=St) ->
+ %% Check that none of the unset variables will be used.
+ case Br of
+ #b_br{bool=#b_var{}=V,succ=Succ,fail=Fail} ->
+ #{Succ:=Used0,Fail:=Used1} = Us,
+
+ %% A two-way branch never branches to a phi node, so there
+ %% is no need to check for phi nodes here.
+ not member(V, UnsetVars) andalso
+ ordsets:is_disjoint(Used0, UnsetVars) andalso
+ ordsets:is_disjoint(Used1, UnsetVars);
+ #b_br{succ=Same,fail=Same} ->
+ %% An unconditional branch must not jump to
+ %% a phi node.
+ not is_forbidden(Same, St) andalso
+ ordsets:is_disjoint(map_get(Same, Us), UnsetVars)
+ end.
+
+is_forbidden(L, St) ->
+ case get_block(L, St) of
+ #b_blk{is=[#b_set{op=phi}|_]} -> true;
+ #b_blk{is=[#b_set{op=peek_message}|_]} -> true;
+ #b_blk{} -> false
+ end.
+
+
+%% Evaluate the instructions in the block.
+%% Return the updated bindings, or 'none' if there is
+%% any instruction with potential side effects.
+
+eval_is([#b_set{op=phi,dst=Dst,args=Args}|Is], Bs0, St) ->
+ From = maps:get(from, Bs0),
+ [Val] = [Val || {Val,Pred} <- Args, Pred =:= From],
+ Bs = bind_var(Dst, Val, Bs0),
+ eval_is(Is, Bs, St);
+eval_is([#b_set{op={bif,_},dst=Dst}=I0|Is], Bs, St) ->
+ I = sub(I0, Bs),
+ case eval_bif(I, St) of
+ #b_literal{}=Val ->
+ eval_is(Is, bind_var(Dst, Val, Bs), St);
+ none ->
+ eval_is(Is, Bs, St)
+ end;
+eval_is([#b_set{op=Op,dst=Dst}=I|Is], Bs, St)
+ when Op =:= is_tagged_tuple; Op =:= is_nonempty_list ->
+ #b_set{args=Args} = sub(I, Bs),
+ case eval_rel_op(Op, Args, St) of
+ #b_literal{}=Val ->
+ eval_is(Is, bind_var(Dst, Val, Bs), St);
+ none ->
+ eval_is(Is, Bs, St)
+ end;
+eval_is([#b_set{}=I|Is], Bs, St) ->
+ case beam_ssa:no_side_effect(I) of
+ true ->
+ %% This instruction has no side effects. It can
+ %% safely be omitted.
+ eval_is(Is, Bs, St);
+ false ->
+ %% This instruction may have some side effect.
+ %% It is not safe to avoid this instruction.
+ none
+ end;
+eval_is([], Bs, _St) -> Bs.
+
+eval_terminator(#b_br{bool=#b_var{}=Bool}=Br, Bs, _St) ->
+ Val = get_value(Bool, Bs),
+ beam_ssa:normalize(Br#b_br{bool=Val});
+eval_terminator(#b_br{bool=#b_literal{}}=Br, _Bs, _St) ->
+ beam_ssa:normalize(Br);
+eval_terminator(#b_switch{arg=Arg,fail=Fail,list=List}=Sw, Bs, St) ->
+ case get_value(Arg, Bs) of
+ #b_literal{}=Val ->
+ %% Literal argument. Simplify to a `br`.
+ beam_ssa:normalize(Sw#b_switch{arg=Val});
+ #b_var{} ->
+ case St of
+ #st{rel_op=none} ->
+ %% No previous relational operator is stored.
+ %% Give up.
+ none;
+ #st{} ->
+ %% There is a previous relational operator stored.
+ %% Try optimizing the switch.
+ case eval_switch(List, Arg, St, Fail) of
+ none ->
+ none;
+ To when is_integer(To) ->
+ %% Either one of the values in the switch
+ %% matched a previous value in a '=:=' test, or
+ %% none of the values matched a previous test.
+ #b_br{bool=#b_literal{val=true},succ=To,fail=To}
+ end
+ end
+ end;
+eval_terminator(#b_ret{}, _Bs, _St) ->
+ none.
+
+eval_switch([{Lit,Lbl}|T], Arg, St, Fail) ->
+ case eval_rel_op({bif,'=:='}, [Arg,Lit], St) of
+ none ->
+ %% This label could be reached.
+ eval_switch(T, Arg, St, none);
+ #b_literal{val=false} ->
+ %% This branch will never be taken.
+ eval_switch(T, Arg, St, Fail);
+ #b_literal{val=true} ->
+ %% Success. This branch will always be taken.
+ Lbl
+ end;
+eval_switch([], _Arg, _St, Fail) ->
+ %% Fail is now either the failure label or 'none'.
+ Fail.
+
+bind_var(Var, Val0, Bs) ->
+ Val = get_value(Val0, Bs),
+ Bs#{Var=>Val}.
+
+get_value(#b_var{}=Var, Bs) ->
+ case Bs of
+ #{Var:=Val} -> get_value(Val, Bs);
+ #{} -> Var
+ end;
+get_value(#b_literal{}=Lit, _Bs) -> Lit.
+
+eval_bif(#b_set{op={bif,Bif},args=Args}, St) ->
+ Arity = length(Args),
+ case erl_bifs:is_pure(erlang, Bif, Arity) of
+ false ->
+ none;
+ true ->
+ case [Lit || #b_literal{val=Lit} <- Args] of
+ LitArgs when length(LitArgs) =:= Arity ->
+ try apply(erlang, Bif, LitArgs) of
+ Val -> #b_literal{val=Val}
+ catch
+ error:_ -> none
+ end;
+ _ ->
+ %% Not literal arguments. Try to evaluate
+ %% it based on a previous relational operator.
+ eval_rel_op({bif,Bif}, Args, St)
+ end
+ end.
+
+%%%
+%%% Handling of relational operators.
+%%%
+
+get_rel_op(Bool, [_|_]=Is) ->
+ case last(Is) of
+ #b_set{op=Op,dst=Bool,args=Args} ->
+ normalize_op(Op, Args);
+ #b_set{} ->
+ none
+ end;
+get_rel_op(_, []) -> none.
+
+%% normalize_op(Instruction) -> {Normalized,FailLabel} | error
+%% Normalized = {Operator,Variable,Variable|Literal} |
+%% {TypeTest,Variable}
+%% Operation = '<' | '=<' | '=:=' | '=/=' | '>=' | '>'
+%% TypeTest = is_atom | is_integer ...
+%% Variable = #b_var{}
+%% Literal = #b_literal{}
+%%
+%% Normalize a relational operator to facilitate further
+%% comparisons between operators. Always make the register
+%% operand the first operand. If there are two registers,
+%% order the registers in lexical order.
+%%
+%% For example, this instruction:
+%%
+%% #b_set{op={bif,=<},args=[#b_literal{}, #b_var{}}
+%%
+%% will be normalized to:
+%%
+%% {'=<',#b_var{},#b_literal{}}
+
+-spec normalize_op(Op, Args) -> NormalizedOp | 'none' when
+ Op :: beam_ssa:op(),
+ Args :: [beam_ssa:value()],
+ NormalizedOp :: basic_rel_op().
+
+normalize_op(is_tagged_tuple, [Arg,#b_literal{val=Size},#b_literal{val=Tag}])
+ when is_integer(Size), is_atom(Tag) ->
+ {{is_tagged_tuple,Size,Tag},Arg};
+normalize_op(is_nonempty_list, [Arg]) ->
+ {is_nonempty_list,Arg};
+normalize_op({bif,Bif}, [Arg]) ->
+ case erl_internal:new_type_test(Bif, 1) of
+ true -> {Bif,Arg};
+ false -> none
+ end;
+normalize_op({bif,Bif}, [_,_]=Args) ->
+ case erl_internal:comp_op(Bif, 2) of
+ true ->
+ normalize_op_1(Bif, Args);
+ false ->
+ none
+ end;
+normalize_op(_, _) -> none.
+
+normalize_op_1(Bif, Args) ->
+ case Args of
+ [#b_literal{}=Arg1,#b_var{}=Arg2] ->
+ {turn_op(Bif),Arg2,Arg1};
+ [#b_var{}=Arg1,#b_literal{}=Arg2] ->
+ {Bif,Arg1,Arg2};
+ [#b_var{}=A,#b_var{}=B] ->
+ if A < B -> {Bif,A,B};
+ true -> {turn_op(Bif),B,A}
+ end;
+ [#b_literal{},#b_literal{}] ->
+ none
+ end.
+
+-spec invert_op(basic_rel_op() | 'none') -> rel_op() | 'none'.
+
+invert_op({Op,Arg1,Arg2}) ->
+ {invert_op_1(Op),Arg1,Arg2};
+invert_op({TypeTest,Arg}) ->
+ {{'not',TypeTest},Arg};
+invert_op(none) -> none.
+
+invert_op_1('>=') -> '<';
+invert_op_1('<') -> '>=';
+invert_op_1('=<') -> '>';
+invert_op_1('>') -> '=<';
+invert_op_1('=:=') -> '=/=';
+invert_op_1('=/=') -> '=:=';
+invert_op_1('==') -> '/=';
+invert_op_1('/=') -> '=='.
+
+turn_op('<') -> '>';
+turn_op('=<') -> '>=';
+turn_op('>') -> '<';
+turn_op('>=') -> '=<';
+turn_op('=:='=Op) -> Op;
+turn_op('=/='=Op) -> Op;
+turn_op('=='=Op) -> Op;
+turn_op('/='=Op) -> Op.
+
+eval_rel_op(_Bif, _Args, #st{rel_op=none}) ->
+ none;
+eval_rel_op(Bif, Args, #st{rel_op=Prev}) ->
+ case normalize_op(Bif, Args) of
+ none ->
+ none;
+ RelOp ->
+ case will_succeed(Prev, RelOp) of
+ yes -> #b_literal{val=true};
+ no -> #b_literal{val=false};
+ maybe -> none
+ end
+ end.
+
+%% will_succeed(PrevCondition, Condition) -> yes | no | maybe
+%% PrevCondition is a condition known to be true. This function
+%% will tell whether Condition will succeed.
+
+will_succeed({_Op,_Var,_Value}=Same, {_Op,_Var,_Value}=Same) ->
+ %% Repeated test.
+ yes;
+will_succeed({Op1,Var,#b_literal{val=A}}, {Op2,Var,#b_literal{val=B}}) ->
+ will_succeed_1(Op1, A, Op2, B);
+will_succeed({Op1,Var,#b_var{}=A}, {Op2,Var,#b_var{}=B}) ->
+ will_succeed_vars(Op1, A, Op2, B);
+will_succeed({'=:=',Var,#b_literal{val=A}}, {TypeTest,Var}) ->
+ eval_type_test(TypeTest, A);
+will_succeed({_,_}=Same, {_,_}=Same) ->
+ %% Repeated type test.
+ yes;
+will_succeed({Test1,Var}, {Test2,Var}) ->
+ will_succeed_test(Test1, Test2);
+will_succeed({_,_}, {_,_}) ->
+ maybe;
+will_succeed({_,_}, {_,_,_}) ->
+ maybe;
+will_succeed({_,_,_}, {_,_}) ->
+ maybe;
+will_succeed({_,_,_}, {_,_,_}) ->
+ maybe.
+
+will_succeed_test({'not',Test1}, Test2) ->
+ case Test1 =:= Test2 of
+ true -> no;
+ false -> maybe
+ end;
+will_succeed_test(is_tuple, {is_tagged_tuple,_,_}) ->
+ maybe;
+will_succeed_test({is_tagged_tuple,_,_}, is_tuple) ->
+ yes;
+will_succeed_test(is_list, is_nonempty_list) ->
+ maybe;
+will_succeed_test(is_nonempty_list, is_list) ->
+ yes;
+will_succeed_test(T1, T2) ->
+ case is_numeric_test(T1) andalso is_numeric_test(T2) of
+ true -> maybe;
+ false -> no
+ end.
+
+will_succeed_1('=:=', A, '<', B) ->
+ if
+ B =< A -> no;
+ true -> yes
+ end;
+will_succeed_1('=:=', A, '=<', B) ->
+ if
+ B < A -> no;
+ true -> yes
+ end;
+will_succeed_1('=:=', A, '=:=', B) when A =/= B ->
+ no;
+will_succeed_1('=:=', A, '=/=', B) ->
+ if
+ A =:= B -> no;
+ true -> yes
+ end;
+will_succeed_1('=:=', A, '>=', B) ->
+ if
+ B > A -> no;
+ true -> yes
+ end;
+will_succeed_1('=:=', A, '>', B) ->
+ if
+ B >= A -> no;
+ true -> yes
+ end;
+
+will_succeed_1('=/=', A, '=:=', B) when A =:= B -> no;
+
+will_succeed_1('<', A, '=:=', B) when B >= A -> no;
+will_succeed_1('<', A, '=/=', B) when B >= A -> yes;
+will_succeed_1('<', A, '<', B) when B >= A -> yes;
+will_succeed_1('<', A, '=<', B) when B > A -> yes;
+will_succeed_1('<', A, '>=', B) when B > A -> no;
+will_succeed_1('<', A, '>', B) when B >= A -> no;
+
+will_succeed_1('=<', A, '=:=', B) when B > A -> no;
+will_succeed_1('=<', A, '=/=', B) when B > A -> yes;
+will_succeed_1('=<', A, '<', B) when B > A -> yes;
+will_succeed_1('=<', A, '=<', B) when B >= A -> yes;
+will_succeed_1('=<', A, '>=', B) when B > A -> no;
+will_succeed_1('=<', A, '>', B) when B >= A -> no;
+
+will_succeed_1('>=', A, '=:=', B) when B < A -> no;
+will_succeed_1('>=', A, '=/=', B) when B < A -> yes;
+will_succeed_1('>=', A, '<', B) when B =< A -> no;
+will_succeed_1('>=', A, '=<', B) when B < A -> no;
+will_succeed_1('>=', A, '>=', B) when B =< A -> yes;
+will_succeed_1('>=', A, '>', B) when B < A -> yes;
+
+will_succeed_1('>', A, '=:=', B) when B =< A -> no;
+will_succeed_1('>', A, '=/=', B) when B =< A -> yes;
+will_succeed_1('>', A, '<', B) when B =< A -> no;
+will_succeed_1('>', A, '=<', B) when B < A -> no;
+will_succeed_1('>', A, '>=', B) when B =< A -> yes;
+will_succeed_1('>', A, '>', B) when B < A -> yes;
+
+will_succeed_1('==', A, '==', B) ->
+ if
+ A == B -> yes;
+ true -> no
+ end;
+will_succeed_1('==', A, '/=', B) ->
+ if
+ A == B -> no;
+ true -> yes
+ end;
+will_succeed_1('/=', A, '/=', B) when A == B -> yes;
+will_succeed_1('/=', A, '==', B) when A == B -> no;
+
+will_succeed_1(_, _, _, _) -> maybe.
+
+will_succeed_vars('=/=', Val, '=:=', Val) -> no;
+will_succeed_vars('=:=', Val, '=/=', Val) -> no;
+will_succeed_vars('=:=', Val, '>=', Val) -> yes;
+will_succeed_vars('=:=', Val, '=<', Val) -> yes;
+
+will_succeed_vars('/=', Val1, '==', Val2) when Val1 == Val2 -> no;
+will_succeed_vars('==', Val1, '/=', Val2) when Val1 == Val2 -> no;
+
+will_succeed_vars(_, _, _, _) -> maybe.
+
+is_numeric_test(is_float) -> true;
+is_numeric_test(is_integer) -> true;
+is_numeric_test(is_number) -> true;
+is_numeric_test(_) -> false.
+
+eval_type_test(Test, Arg) ->
+ case eval_type_test_1(Test, Arg) of
+ true -> yes;
+ false -> no
+ end.
+
+eval_type_test_1(is_nonempty_list, Arg) ->
+ case Arg of
+ [_|_] -> true;
+ _ -> false
+ end;
+eval_type_test_1({is_tagged_tuple,Sz,Tag}, Arg) ->
+ if
+ tuple_size(Arg) =:= Sz, element(1, Arg) =:= Tag ->
+ true;
+ true ->
+ false
+ end;
+eval_type_test_1(Test, Arg) ->
+ erlang:Test(Arg).
+
+%%%
+%%% Combine bif:'=:=' and switch instructions
+%%% to switch instructions.
+%%%
+%%% Consider this code:
+%%%
+%%% 0:
+%%% @ssa_bool = bif:'=:=' Var, literal 1
+%%% br @ssa_bool, label 2, label 3
+%%%
+%%% 2:
+%%% ret literal a
+%%%
+%%% 3:
+%%% @ssa_bool:7 = bif:'=:=' Var, literal 2
+%%% br @ssa_bool:7, label 4, label 999
+%%%
+%%% 4:
+%%% ret literal b
+%%%
+%%% 999:
+%%% .
+%%% .
+%%% .
+%%%
+%%% The two bif:'=:=' instructions can be combined
+%%% to a switch:
+%%%
+%%% 0:
+%%% switch Var, label 999, [ { literal 1, label 2 },
+%%% { literal 2, label 3 } ]
+%%%
+%%% 2:
+%%% ret literal a
+%%%
+%%% 4:
+%%% ret literal b
+%%%
+%%% 999:
+%%% .
+%%% .
+%%% .
+%%%
+
+combine_eqs(#st{bs=Blocks}=St) ->
+ Ls = reverse(beam_ssa:rpo(Blocks)),
+ combine_eqs_1(Ls, St).
+
+combine_eqs_1([L|Ls], #st{bs=Blocks0}=St0) ->
+ case comb_get_sw(L, St0) of
+ none ->
+ combine_eqs_1(Ls, St0);
+ {_,Arg,_,Fail0,List0} ->
+ case comb_get_sw(Fail0, St0) of
+ {true,Arg,Fail1,Fail,List1} ->
+ %% Another switch/br with the same arguments was
+ %% found. Try combining them.
+ case combine_lists(Fail1, List0, List1, Blocks0) of
+ none ->
+ %% Different types of literals in the lists,
+ %% or the success cases in the first switch
+ %% could branch to the second switch
+ %% (increasing code size and repeating tests).
+ combine_eqs_1(Ls, St0);
+ List ->
+ %% Everything OK! Combine the lists.
+ Sw0 = #b_switch{arg=Arg,fail=Fail,list=List},
+ Sw = beam_ssa:normalize(Sw0),
+ Blk0 = maps:get(L, Blocks0),
+ Blk = Blk0#b_blk{last=Sw},
+ Blocks = Blocks0#{L:=Blk},
+ St = St0#st{bs=Blocks},
+ combine_eqs_1(Ls, St)
+ end;
+ {true,_OtherArg,_,_,_} ->
+ %% The other switch/br uses a different Arg.
+ combine_eqs_1(Ls, St0);
+ {false,_,_,_,_} ->
+ %% Not safe: Bindings of variables that will be used
+ %% or execution of instructions with potential
+ %% side effects will be skipped.
+ combine_eqs_1(Ls, St0);
+ none ->
+ %% No switch/br at this label.
+ combine_eqs_1(Ls, St0)
+ end
+ end;
+combine_eqs_1([], St) -> St.
+
+comb_get_sw(L, Blocks) ->
+ comb_get_sw(L, true, Blocks).
+
+comb_get_sw(L, Safe0, #st{bs=Blocks,skippable=Skippable}=St) ->
+ #b_blk{is=Is,last=Last} = maps:get(L, Blocks),
+ Safe1 = Safe0 andalso is_map_key(L, Skippable),
+ case Last of
+ #b_ret{} ->
+ none;
+ #b_br{bool=#b_var{}=Bool,succ=Succ,fail=Fail} ->
+ case comb_is(Is, Bool, Safe1) of
+ {none,_} ->
+ none;
+ {#b_set{op={bif,'=:='},args=[#b_var{}=Arg,#b_literal{}=Lit]},Safe} ->
+ {Safe,Arg,L,Fail,[{Lit,Succ}]};
+ {#b_set{},_} ->
+ none
+ end;
+ #b_br{bool=#b_literal{val=true},succ=Succ} ->
+ comb_get_sw(Succ, Safe1, St);
+ #b_switch{arg=#b_var{}=Arg,fail=Fail,list=List} ->
+ {none,Safe} = comb_is(Is, none, Safe1),
+ {Safe,Arg,L,Fail,List}
+ end.
+
+comb_is([#b_set{dst=#b_var{}=Bool}=I], Bool, Safe) ->
+ {I,Safe};
+comb_is([#b_set{}=I|Is], Bool, Safe0) ->
+ Safe = Safe0 andalso beam_ssa:no_side_effect(I),
+ comb_is(Is, Bool, Safe);
+comb_is([], _Bool, Safe) ->
+ {none,Safe}.
+
+%% combine_list(Fail, List1, List2, Blocks) -> List|none.
+%% Try to combine two switch lists, returning the combined
+%% list or 'none' if not possible.
+%%
+%% The values in the two lists must be all of the same type.
+%%
+%% The code reached from the labels in the first list must
+%% not reach the failure label (if they do, tests could
+%% be repeated).
+%%
+
+combine_lists(Fail, L1, L2, Blocks) ->
+ Ls = beam_ssa:rpo([Lbl || {_,Lbl} <- L1], Blocks),
+ case member(Fail, Ls) of
+ true ->
+ %% One or more of labels in the first list
+ %% could reach the failure label. That
+ %% means that the second switch/br instruction
+ %% will be retained, increasing code size and
+ %% potentially also execution time.
+ none;
+ false ->
+ %% The combined switch will replace both original
+ %% br/switch instructions, leading to a reduction in code
+ %% size and potentially also in execution time.
+ combine_lists_1(L1, L2)
+ end.
+
+combine_lists_1(List0, List1) ->
+ case are_lists_compatible(List0, List1) of
+ true ->
+ First = maps:from_list(List0),
+ List0 ++ [{Val,Lbl} || {Val,Lbl} <- List1,
+ not is_map_key(Val, First)];
+ false ->
+ none
+ end.
+
+are_lists_compatible([{#b_literal{val=Val1},_}|_],
+ [{#b_literal{val=Val2},_}|_]) ->
+ case lit_type(Val1) of
+ none -> false;
+ Type -> Type =:= lit_type(Val2)
+ end.
+
+lit_type(Val) ->
+ if
+ is_atom(Val) -> atom;
+ is_float(Val) -> float;
+ is_integer(Val) -> integer;
+ true -> none
+ end.
+
+%%%
+%%% Calculate used variables for each block.
+%%%
+
+used_vars(Linear) ->
+ used_vars(reverse(Linear), #{}, #{}).
+
+used_vars([{L,#b_blk{is=Is}=Blk}|Bs], UsedVars0, Skip0) ->
+ %% Calculate the variables used by each block and its
+ %% successors. This information is used by
+ %% shortcut_opt/1.
+
+ Successors = beam_ssa:successors(Blk),
+ Used0 = used_vars_succ(Successors, L, UsedVars0),
+ Used = used_vars_blk(Blk, Used0),
+ UsedVars = used_vars_phis(Is, L, Used, UsedVars0),
+
+ %% combine_eqs/1 needs different variable usage
+ %% information than shortcut_opt/1. The Skip
+ %% map will have an entry for each block that
+ %% can be skipped (does not bind any variable used
+ %% in successor).
+
+ Defined0 = [Def || #b_set{dst=Def} <- Is],
+ Defined = ordsets:from_list(Defined0),
+ MaySkip = ordsets:is_disjoint(Defined, Used0),
+ case MaySkip of
+ true ->
+ Skip = Skip0#{L=>true},
+ used_vars(Bs, UsedVars, Skip);
+ false ->
+ used_vars(Bs, UsedVars, Skip0)
+ end;
+used_vars([], UsedVars, Skip) ->
+ {UsedVars,Skip}.
+
+used_vars_succ([S|Ss], L, UsedVars) ->
+ Live0 = used_vars_succ(Ss, L, UsedVars),
+ Key = {S,L},
+ case UsedVars of
+ #{Key:=Live} ->
+ ordsets:union(Live, Live0);
+ #{S:=Live} ->
+ ordsets:union(Live, Live0);
+ #{} ->
+ Live0
+ end;
+used_vars_succ([], _, _) ->
+ ordsets:new().
+
+used_vars_phis(Is, L, Live0, UsedVars0) ->
+ UsedVars = UsedVars0#{L=>Live0},
+ Phis = takewhile(fun(#b_set{op=Op}) -> Op =:= phi end, Is),
+ case Phis of
+ [] ->
+ UsedVars;
+ [_|_] ->
+ PhiArgs = append([Args || #b_set{args=Args} <- Phis]),
+ case [{P,V} || {#b_var{}=V,P} <- PhiArgs] of
+ [_|_]=PhiVars ->
+ PhiLive0 = rel2fam(PhiVars),
+ PhiLive = [{{L,P},ordsets:union(ordsets:from_list(Vs), Live0)} ||
+ {P,Vs} <- PhiLive0],
+ maps:merge(UsedVars, maps:from_list(PhiLive));
+ [] ->
+ %% There were only literals in the phi node(s).
+ UsedVars
+ end
+ end.
+
+used_vars_blk(#b_blk{is=Is,last=Last}, Used0) ->
+ Used = ordsets:union(Used0, beam_ssa:used(Last)),
+ used_vars_is(reverse(Is), Used).
+
+used_vars_is([#b_set{op=phi}|Is], Used) ->
+ used_vars_is(Is, Used);
+used_vars_is([#b_set{dst=Dst}=I|Is], Used0) ->
+ Used1 = ordsets:union(Used0, beam_ssa:used(I)),
+ Used = ordsets:del_element(Dst, Used1),
+ used_vars_is(Is, Used);
+used_vars_is([], Used) ->
+ Used.
+
+%%%
+%%% Common utilities.
+%%%
+
+sub(#b_set{args=Args}=I, Sub) ->
+ I#b_set{args=[sub_arg(A, Sub) || A <- Args]}.
+
+sub_arg(Old, Sub) ->
+ case Sub of
+ #{Old:=New} -> New;
+ #{} -> Old
+ end.
+
+rel2fam(S0) ->
+ S1 = sofs:relation(S0),
+ S = sofs:rel2fam(S1),
+ sofs:to_external(S).
diff --git a/lib/compiler/src/beam_ssa_lint.erl b/lib/compiler/src/beam_ssa_lint.erl
new file mode 100644
index 0000000000..a003607dab
--- /dev/null
+++ b/lib/compiler/src/beam_ssa_lint.erl
@@ -0,0 +1,349 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+%% Purpose: Internal consistency checks for the beam_ssa format.
+
+-module(beam_ssa_lint).
+
+-export([module/2, format_error/1]).
+
+-import(lists, [append/1, foldl/3, foreach/2]).
+
+-include("beam_ssa.hrl").
+
+-spec module(#b_module{}, [compile:option()]) ->
+ {'ok',#b_module{}} | {'error',list()}.
+module(#b_module{body=Fs,name=Name}=Mod0, _Options) ->
+ Es0 = append([validate_function(F) || F <- Fs]),
+ case [{?MODULE,E} || E <- Es0] of
+ [] ->
+ {ok, Mod0};
+ [_|_]=Es ->
+ {error,[{atom_to_list(Name), Es}]}
+ end.
+
+-spec format_error(term()) -> iolist().
+format_error({{_M,F,A},{redefined_variable, Name, Old, I}}) ->
+ io_lib:format("~p/~p: Variable ~ts (~ts) redefined by ~ts",
+ [F, A, format_var(Name), format_instr(Old), format_instr(I)]);
+format_error({{_M,F,A},{missing_phi_paths, Paths, I}}) ->
+ io_lib:format("~p/~p: Phi node ~ts doesn't define a value for these "
+ "branches: ~w",
+ [F, A, format_instr(I), Paths]);
+format_error({{_M,F,A},{garbage_phi_paths, Paths, I}}) ->
+ io_lib:format("~p/~p: Phi node ~ts defines a value for these unreachable "
+ "or non-existent branches: ~w",
+ [F, A, format_instr(I), Paths]);
+format_error({{_M,F,A},{unknown_phi_variable, Name, {From, _To}, I}}) ->
+ io_lib:format("~p/~p: Variable ~ts used in phi node ~ts is undefined on "
+ "branch ~w",
+ [F, A, format_var(Name), format_instr(I), From]);
+format_error({{_M,F,A},{unknown_block, Label, I}}) ->
+ io_lib:format("~p/~p: Unknown block ~p referenced in ~ts",
+ [F, A, Label, I]);
+format_error({{_M,F,A},{unknown_variable, Name, I}}) ->
+ io_lib:format("~p/~p: Unbound variable ~ts used in ~ts",
+ [F, A, format_var(Name), format_instr(I)]);
+format_error({{_M,F,A},{phi_inside_block, Name, Id}}) ->
+ io_lib:format("~p/~p: Phi node defining ~ts is not at start of block ~p",
+ [F, A, format_var(Name), Id]);
+format_error({{_M,F,A},{undefined_label_in_phi, Label, I}}) ->
+ io_lib:format("~p/~p: Unknown block label ~p in phi node ~ts",
+ [F, A, Label, format_instr(I)]).
+
+format_instr(I) ->
+ [$',beam_ssa_pp:format_instr(I),$'].
+
+format_var(V) ->
+ beam_ssa_pp:format_var(#b_var{name=V}).
+
+validate_function(F) ->
+ try
+ validate_variables(F),
+ []
+ catch
+ throw:Reason ->
+ #{func_info:=MFA} = F#b_function.anno,
+ [{MFA,Reason}];
+ Class:Error:Stack ->
+ io:fwrite("Function: ~p\n", [F#b_function.anno]),
+ erlang:raise(Class, Error, Stack)
+ end.
+
+-type defined_vars() :: gb_sets:set(beam_ssa:var_name()).
+
+-record(vvars,
+ {blocks :: #{ beam_ssa:label() => beam_ssa:b_blk() },
+ branch_def_vars :: #{
+ %% Describes the variable state at the time of this exact branch (phi
+ %% node validation).
+ {From :: beam_ssa:label(), To :: beam_ssa:label()} => defined_vars(),
+ %% Describes the variable state common to all branches leading to this
+ %% label (un/redefined variable validation).
+ beam_ssa:label() => defined_vars() },
+ defined_vars :: defined_vars()}).
+
+-spec validate_variables(beam_ssa:b_function()) -> ok.
+validate_variables(#b_function{ args = Args, bs = Blocks }) ->
+ %% Prefill the mapping with function arguments.
+ ArgNames = vvars_get_varnames(Args),
+ DefVars = gb_sets:from_list(ArgNames),
+ Entry = 0,
+
+ State = #vvars{blocks = Blocks,
+ branch_def_vars = #{ Entry => DefVars },
+ defined_vars = DefVars},
+ ok = vvars_assert_unique(Blocks, ArgNames),
+ vvars_phi_nodes(vvars_block(Entry, State)).
+
+%% Checks the uniqueness of all variables across all blocks.
+-spec vvars_assert_unique(Blocks, [beam_ssa:var_name()]) -> ok when
+ Blocks :: #{ beam_ssa:label() => beam_ssa:b_blk() }.
+vvars_assert_unique(Blocks, Args) ->
+ BlockIs = [Is || #b_blk{is=Is} <- maps:values(Blocks)],
+ Defined0 = maps:from_list([{V,argument} || V <- Args]),
+ _ = foldl(fun(Is, Defined) ->
+ vvars_assert_unique_1(Is, Defined)
+ end, Defined0, BlockIs),
+ ok.
+
+-spec vvars_assert_unique_1(Is, Defined) -> ok when
+ Is :: list(beam_ssa:b_set()),
+ Defined :: #{ beam_ssa:var_name() => beam_ssa:b_set() }.
+vvars_assert_unique_1([#b_set{dst=#b_var{name=DstName}}=I|Is], Defined) ->
+ case Defined of
+ #{DstName:=Old} -> throw({redefined_variable, DstName, Old, I});
+ _ -> vvars_assert_unique_1(Is, Defined#{DstName=>I})
+ end;
+vvars_assert_unique_1([], Defined) ->
+ Defined.
+
+-spec vvars_phi_nodes(State :: #vvars{}) -> ok.
+vvars_phi_nodes(#vvars{ blocks = Blocks }=State) ->
+ _ = [vvars_phi_nodes_1(Is, Id, State) ||
+ {Id, #b_blk{ is = Is }} <- maps:to_list(Blocks)],
+ ok.
+
+-spec vvars_phi_nodes_1(Is, Id, State) -> ok when
+ Is :: list(beam_ssa:b_set()),
+ Id :: beam_ssa:label(),
+ State :: #vvars{}.
+vvars_phi_nodes_1([#b_set{ op = phi, args = Phis }=I | Is], Id, State) ->
+ ok = vvars_assert_phi_paths(Phis, I, Id, State),
+ ok = vvars_assert_phi_vars(Phis, I, Id, State),
+ vvars_phi_nodes_1(Is, Id, State);
+vvars_phi_nodes_1([_ | Is], Id, _State) ->
+ case [Dst || #b_set{op=phi,dst=#b_var{name=Dst}} <- Is] of
+ [Name|_] ->
+ throw({phi_inside_block, Name, Id});
+ [] ->
+ ok
+ end;
+vvars_phi_nodes_1([], _Id, _State) ->
+ ok.
+
+%% Checks whether all paths leading to this phi node are represented, and that
+%% it doesn't reference any non-existent paths.
+-spec vvars_assert_phi_paths(Phis, I, Id, State) -> ok when
+ Phis :: list({beam_ssa:argument(), beam_ssa:label()}),
+ Id :: beam_ssa:label(),
+ I :: beam_ssa:b_set(),
+ State :: #vvars{}.
+vvars_assert_phi_paths(Phis, I, Id, State) ->
+ BranchKeys = maps:keys(State#vvars.branch_def_vars),
+ RequiredPaths = ordsets:from_list([From || {From, To} <- BranchKeys, To =:= Id]),
+ ProvidedPaths = ordsets:from_list([From || {_Value, From} <- Phis]),
+ case ordsets:subtract(RequiredPaths, ProvidedPaths) of
+ [_|_]=MissingPaths -> throw({missing_phi_paths, MissingPaths, I});
+ [] -> ok
+ end.
+ %% %% The following test is sometimes useful to find missing optimizations.
+ %% %% It is commented out, though, because it can be triggered by
+ %% %% by weird but legal code.
+ %% case ordsets:subtract(ProvidedPaths, RequiredPaths) of
+ %% [_|_]=GarbagePaths -> throw({garbage_phi_paths, GarbagePaths, I});
+ %% [] -> ok
+ %% end.
+
+%% Checks whether all variables used in this phi node are defined in the branch
+%% they arrived on.
+-spec vvars_assert_phi_vars(Phis, I, Id, State) -> ok when
+ Phis :: list({beam_ssa:argument(), beam_ssa:label()}),
+ Id :: beam_ssa:label(),
+ I :: beam_ssa:b_set(),
+ State :: #vvars{}.
+vvars_assert_phi_vars(Phis, I, Id, #vvars{blocks=Blocks,
+ branch_def_vars=BranchDefVars}) ->
+ Vars = [{Var, From} || {#b_var{}=Var, From} <- Phis],
+ foreach(fun({#b_var{name=VarName}, From}) ->
+ BranchKey = {From, Id},
+ case BranchDefVars of
+ #{BranchKey:=DefVars} ->
+ case gb_sets:is_member(VarName, DefVars) of
+ true -> ok;
+ false -> throw({unknown_variable, VarName, I})
+ end;
+ #{} ->
+ throw({unknown_phi_variable, VarName, BranchKey, I})
+ end
+ end, Vars),
+ Labels = [From || {#b_literal{},From} <- Phis],
+ foreach(fun(Label) ->
+ case Blocks of
+ #{Label:=_} ->
+ ok;
+ #{} ->
+ throw({undefined_label_in_phi, Label, I})
+ end
+ end, Labels).
+
+-spec vvars_block(Id, State) -> #vvars{} when
+ Id :: beam_ssa:label(),
+ State :: #vvars{}.
+vvars_block(Id, State0) ->
+ #{ Id := #b_blk{ is = Is, last = Terminator} } = State0#vvars.blocks,
+ #{ Id := DefVars } = State0#vvars.branch_def_vars,
+ State = State0#vvars{ defined_vars = DefVars },
+ vvars_terminator(Terminator, Id, vvars_block_1(Is, State)).
+
+-spec vvars_block_1(Blocks, State) -> #vvars{} when
+ Blocks :: list(beam_ssa:b_blk()),
+ State :: #vvars{}.
+vvars_block_1([], State) ->
+ State;
+vvars_block_1([#b_set{ dst = #b_var{ name = DstName }, op = phi } | Is], State0) ->
+ %% We don't check phi node arguments at this point since we may not have
+ %% visited their definition yet. They'll be handled later on in
+ %% vvars_phi_nodes/1 after all blocks are processed.
+ vvars_block_1(Is, vvars_save_var(DstName, State0));
+vvars_block_1([#b_set{ dst = #b_var{ name = DstName }, args = Args }=I | Is], State0) ->
+ ok = vvars_assert_args(Args, I, State0),
+ vvars_block_1(Is, vvars_save_var(DstName, State0)).
+
+-spec vvars_terminator(Terminator, From, State) -> #vvars{} when
+ Terminator :: beam_ssa:terminator(),
+ From :: beam_ssa:label(),
+ State :: #vvars{}.
+vvars_terminator(#b_ret{ arg = Arg }=I, _From, State) ->
+ ok = vvars_assert_args([Arg], I, State),
+ State;
+vvars_terminator(#b_switch{arg=Arg,fail=Fail,list=Switch}=I, From, State) ->
+ ok = vvars_assert_args([Arg], I, State),
+ ok = vvars_assert_args([A || {A,_Lbl} <- Switch], I, State),
+ Labels = [Fail | [Lbl || {_Arg, Lbl} <- Switch]],
+ ok = vvars_assert_labels(Labels, I, State),
+ vvars_terminator_1(Labels, From, State);
+vvars_terminator(#b_br{bool=#b_literal{val=true},succ=Succ}=I, From, State) ->
+ Labels = [Succ],
+ ok = vvars_assert_labels(Labels, I, State),
+ vvars_terminator_1(Labels, From, State);
+vvars_terminator(#b_br{bool=#b_literal{val=false},fail=Fail}=I, From, State) ->
+ Labels = [Fail],
+ ok = vvars_assert_labels(Labels, I, State),
+ vvars_terminator_1(Labels, From, State);
+vvars_terminator(#b_br{ bool = Arg, succ = Succ, fail = Fail }=I, From, State) ->
+ ok = vvars_assert_args([Arg], I, State),
+ Labels = [Fail, Succ],
+ ok = vvars_assert_labels(Labels, I, State),
+ vvars_terminator_1(Labels, From, State).
+
+-spec vvars_terminator_1(Labels, From, State) -> #vvars{} when
+ Labels :: list(beam_ssa:label()),
+ From :: beam_ssa:label(),
+ State :: #vvars{}.
+vvars_terminator_1(Labels0, From, State0) ->
+ %% Filter out all branches that have already been taken. This should result
+ %% in either all of Labels0 or an empty list.
+ Labels = [To || To <- Labels0,
+ not maps:is_key({From, To}, State0#vvars.branch_def_vars)],
+ true = Labels =:= Labels0 orelse Labels =:= [], %Assertion
+ State1 = foldl(fun(To, State) ->
+ vvars_save_branch(From, To, State)
+ end, State0, Labels),
+ foldl(fun(To, State) ->
+ vvars_block(To, State)
+ end, State1, Labels).
+
+%% Gets all variable names in args, ignoring literals etc
+-spec vvars_get_varnames(Args) -> list(beam_ssa:var_name()) when
+ Args :: list(beam_ssa:argument()).
+vvars_get_varnames(Args) ->
+ [Name || #b_var{ name = Name } <- Args].
+
+%% Checks that all variables in Args are defined in all paths leading to the
+%% current State.
+-spec vvars_assert_args(Args, I, State) -> ok when
+ Args :: list(beam_ssa:argument()),
+ I :: beam_ssa:terminator() | beam_ssa:b_set(),
+ State :: #vvars{}.
+vvars_assert_args(Args, I, #vvars{defined_vars=DefVars}=State) ->
+ foreach(fun(#b_remote{mod=Mod,name=Name}) ->
+ vvars_assert_args([Mod,Name], I, State);
+ (#b_var{name=Name}) ->
+ case gb_sets:is_member(Name, DefVars) of
+ true -> ok;
+ false -> throw({unknown_variable,Name,I})
+ end;
+ (_) -> ok
+ end, Args).
+
+%% Checks that all given labels are defined in State.
+-spec vvars_assert_labels(Labels, I, State) -> ok when
+ Labels :: list(beam_ssa:label()),
+ I :: beam_ssa:terminator(),
+ State :: #vvars{}.
+vvars_assert_labels(Labels, I, #vvars{blocks=Blocks}) ->
+ foreach(fun(Label) ->
+ case maps:is_key(Label, Blocks) of
+ false -> throw({unknown_block, Label, I});
+ true -> ok
+ end
+ end, Labels).
+
+-spec vvars_save_branch(From, To, State) -> #vvars{} when
+ From :: beam_ssa:label(),
+ To :: beam_ssa:label(),
+ State :: #vvars{}.
+vvars_save_branch(From, To, State) ->
+ DefVars = State#vvars.defined_vars,
+ Branches0 = State#vvars.branch_def_vars,
+ case Branches0 of
+ #{ To := LblDefVars } ->
+ MergedVars = vvars_merge_branches(DefVars, LblDefVars),
+
+ Branches = Branches0#{ To => MergedVars, {From, To} => DefVars },
+ State#vvars { branch_def_vars = Branches };
+ _ ->
+ Branches = Branches0#{ To => DefVars, {From, To} => DefVars },
+ State#vvars { branch_def_vars = Branches }
+ end.
+
+-spec vvars_merge_branches(New, Existing) -> defined_vars() when
+ New :: defined_vars(),
+ Existing :: defined_vars().
+vvars_merge_branches(New, Existing) ->
+ gb_sets:intersection(New, Existing).
+
+-spec vvars_save_var(VarName, State) -> #vvars{} when
+ VarName :: beam_ssa:var_name(),
+ State :: #vvars{}.
+vvars_save_var(VarName, State0) ->
+ %% vvars_assert_unique guarantees that variables are never set twice.
+ DefVars = gb_sets:insert(VarName, State0#vvars.defined_vars),
+ State0#vvars{ defined_vars = DefVars }.
diff --git a/lib/compiler/src/beam_ssa_opt.erl b/lib/compiler/src/beam_ssa_opt.erl
new file mode 100644
index 0000000000..89cfbd7a84
--- /dev/null
+++ b/lib/compiler/src/beam_ssa_opt.erl
@@ -0,0 +1,1650 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(beam_ssa_opt).
+-export([module/2]).
+
+-include("beam_ssa.hrl").
+-import(lists, [all/2,append/1,foldl/3,keyfind/3,member/2,reverse/1,reverse/2,
+ splitwith/2,takewhile/2,unzip/1]).
+
+-spec module(beam_ssa:b_module(), [compile:option()]) ->
+ {'ok',beam_ssa:b_module()}.
+
+module(#b_module{body=Fs0}=Module, Opts) ->
+ Ps = passes(Opts),
+ Fs = functions(Fs0, Ps),
+ {ok,Module#b_module{body=Fs}}.
+
+functions([F|Fs], Ps) ->
+ [function(F, Ps)|functions(Fs, Ps)];
+functions([], _Ps) -> [].
+
+-type b_blk() :: beam_ssa:b_blk().
+-type b_var() :: beam_ssa:b_var().
+-type label() :: beam_ssa:label().
+
+-record(st, {ssa :: beam_ssa:block_map() | [{label(),b_blk()}],
+ args :: [b_var()],
+ cnt :: label()}).
+-define(PASS(N), {N,fun N/1}).
+
+passes(Opts0) ->
+ Ps = [?PASS(ssa_opt_split_blocks),
+ ?PASS(ssa_opt_coalesce_phis),
+ ?PASS(ssa_opt_element),
+ ?PASS(ssa_opt_linearize),
+ ?PASS(ssa_opt_record),
+
+ %% Run ssa_opt_cse twice, because it will help ssa_opt_dead,
+ %% and ssa_opt_dead will help ssa_opt_cse. Run ssa_opt_live
+ %% twice, because it will help ssa_opt_dead and ssa_opt_dead
+ %% will help ssa_opt_live.
+ ?PASS(ssa_opt_cse),
+ ?PASS(ssa_opt_type),
+ ?PASS(ssa_opt_live),
+ ?PASS(ssa_opt_dead),
+ ?PASS(ssa_opt_cse), %Second time.
+ ?PASS(ssa_opt_float),
+ ?PASS(ssa_opt_live), %Second time.
+
+ ?PASS(ssa_opt_bsm),
+ ?PASS(ssa_opt_bsm_shortcut),
+ ?PASS(ssa_opt_misc),
+ ?PASS(ssa_opt_tuple_size),
+ ?PASS(ssa_opt_sw),
+ ?PASS(ssa_opt_blockify),
+ ?PASS(ssa_opt_sink),
+ ?PASS(ssa_opt_merge_blocks)],
+ Negations = [{list_to_atom("no_"++atom_to_list(N)),N} ||
+ {N,_} <- Ps],
+ Opts = proplists:substitute_negations(Negations, Opts0),
+ [case proplists:get_value(Name, Opts, true) of
+ true ->
+ P;
+ false ->
+ {NoName,Name} = keyfind(Name, 2, Negations),
+ {NoName,fun(S) -> S end}
+ end || {Name,_}=P <- Ps].
+
+function(#b_function{anno=Anno,bs=Blocks0,args=Args,cnt=Count0}=F, Ps) ->
+ try
+ St = #st{ssa=Blocks0,args=Args,cnt=Count0},
+ #st{ssa=Blocks,cnt=Count} = compile:run_sub_passes(Ps, St),
+ F#b_function{bs=Blocks,cnt=Count}
+ catch
+ Class:Error:Stack ->
+ #{func_info:={_,Name,Arity}} = Anno,
+ io:fwrite("Function: ~w/~w\n", [Name,Arity]),
+ erlang:raise(Class, Error, Stack)
+ end.
+
+%%%
+%%% Trivial sub passes.
+%%%
+
+ssa_opt_dead(#st{ssa=Linear}=St) ->
+ St#st{ssa=beam_ssa_dead:opt(Linear)}.
+
+ssa_opt_linearize(#st{ssa=Blocks}=St) ->
+ St#st{ssa=beam_ssa:linearize(Blocks)}.
+
+ssa_opt_type(#st{ssa=Linear,args=Args}=St) ->
+ St#st{ssa=beam_ssa_type:opt(Linear, Args)}.
+
+ssa_opt_blockify(#st{ssa=Linear}=St) ->
+ St#st{ssa=maps:from_list(Linear)}.
+
+%%%
+%%% Split blocks before certain instructions to enable more optimizations.
+%%%
+%%% Splitting before element/2 enables the optimization that swaps
+%%% element/2 instructions.
+%%%
+%%% Splitting before call and make_fun instructions gives more opportunities
+%%% for sinking get_tuple_element instructions.
+%%%
+
+ssa_opt_split_blocks(#st{ssa=Blocks0,cnt=Count0}=St) ->
+ P = fun(#b_set{op={bif,element}}) -> true;
+ (#b_set{op=call}) -> true;
+ (#b_set{op=make_fun}) -> true;
+ (_) -> false
+ end,
+ {Blocks,Count} = beam_ssa:split_blocks(P, Blocks0, Count0),
+ St#st{ssa=Blocks,cnt=Count}.
+
+%%%
+%%% Coalesce phi nodes.
+%%%
+%%% Nested cases can led to code such as this:
+%%%
+%%% 10:
+%%% _1 = phi {literal value1, label 8}, {Var, label 9}
+%%% br 11
+%%%
+%%% 11:
+%%% _2 = phi {_1, label 10}, {literal false, label 3}
+%%%
+%%% The phi nodes can be coalesced like this:
+%%%
+%%% 11:
+%%% _2 = phi {literal value1, label 8}, {Var, label 9}, {literal false, label 3}
+%%%
+%%% Coalescing can help other optimizations, and can in some cases reduce register
+%%% shuffling (if the phi variables for two phi nodes happens to be allocated to
+%%% different registers).
+%%%
+
+ssa_opt_coalesce_phis(#st{ssa=Blocks0}=St) ->
+ Ls = beam_ssa:rpo(Blocks0),
+ Blocks = c_phis_1(Ls, Blocks0),
+ St#st{ssa=Blocks}.
+
+c_phis_1([L|Ls], Blocks0) ->
+ case maps:get(L, Blocks0) of
+ #b_blk{is=[#b_set{op=phi}|_]}=Blk ->
+ Blocks = c_phis_2(L, Blk, Blocks0),
+ c_phis_1(Ls, Blocks);
+ #b_blk{} ->
+ c_phis_1(Ls, Blocks0)
+ end;
+c_phis_1([], Blocks) -> Blocks.
+
+c_phis_2(L, #b_blk{is=Is0}=Blk0, Blocks0) ->
+ case c_phis_args(Is0, Blocks0) of
+ none ->
+ Blocks0;
+ {_,_,Preds}=Info ->
+ Is = c_rewrite_phis(Is0, Info),
+ Blk = Blk0#b_blk{is=Is},
+ Blocks = Blocks0#{L:=Blk},
+ c_fix_branches(Preds, L, Blocks)
+ end.
+
+c_phis_args([#b_set{op=phi,args=Args0}|Is], Blocks) ->
+ case c_phis_args_1(Args0, Blocks) of
+ none ->
+ c_phis_args(Is, Blocks);
+ Res ->
+ Res
+ end;
+c_phis_args(_, _Blocks) -> none.
+
+c_phis_args_1([{Var,Pred}|As], Blocks) ->
+ case c_get_pred_vars(Var, Pred, Blocks) of
+ none ->
+ c_phis_args_1(As, Blocks);
+ Result ->
+ Result
+ end;
+c_phis_args_1([], _Blocks) -> none.
+
+c_get_pred_vars(Var, Pred, Blocks) ->
+ case maps:get(Pred, Blocks) of
+ #b_blk{is=[#b_set{op=phi,dst=Var,args=Args}]} ->
+ {Var,Pred,Args};
+ #b_blk{} ->
+ none
+ end.
+
+c_rewrite_phis([#b_set{op=phi,args=Args0}=I|Is], Info) ->
+ Args = c_rewrite_phi(Args0, Info),
+ [I#b_set{args=Args}|c_rewrite_phis(Is, Info)];
+c_rewrite_phis(Is, _Info) -> Is.
+
+c_rewrite_phi([{Var,Pred}|As], {Var,Pred,Values}) ->
+ Values ++ As;
+c_rewrite_phi([{Value,Pred}|As], {_,Pred,Values}) ->
+ [{Value,P} || {_,P} <- Values] ++ As;
+c_rewrite_phi([A|As], Info) ->
+ [A|c_rewrite_phi(As, Info)];
+c_rewrite_phi([], _Info) -> [].
+
+c_fix_branches([{_,Pred}|As], L, Blocks0) ->
+ #b_blk{last=Last0} = Blk0 = maps:get(Pred, Blocks0),
+ #b_br{bool=#b_literal{val=true}} = Last0, %Assertion.
+ Last = Last0#b_br{bool=#b_literal{val=true},succ=L,fail=L},
+ Blk = Blk0#b_blk{last=Last},
+ Blocks = Blocks0#{Pred:=Blk},
+ c_fix_branches(As, L, Blocks);
+c_fix_branches([], _, Blocks) -> Blocks.
+
+%%%
+%%% Order element/2 calls.
+%%%
+%%% Order an unbroken chain of element/2 calls for the same tuple
+%%% with the same failure label so that the highest element is
+%%% retrieved first. That will allow the other element/2 calls to
+%%% be replaced with get_tuple_element/3 instructions.
+%%%
+
+ssa_opt_element(#st{ssa=Blocks}=St) ->
+ %% Collect the information about element instructions in this
+ %% function.
+ GetEls = collect_element_calls(beam_ssa:linearize(Blocks)),
+
+ %% Collect the element instructions into chains. The
+ %% element calls in each chain are ordered in reverse
+ %% execution order.
+ Chains = collect_chains(GetEls, []),
+
+ %% For each chain, swap the first element call with the
+ %% element call with the highest index.
+ St#st{ssa=swap_element_calls(Chains, Blocks)}.
+
+collect_element_calls([{L,#b_blk{is=Is0,last=Last}}|Bs]) ->
+ case {Is0,Last} of
+ {[#b_set{op={bif,element},dst=Element,
+ args=[#b_literal{val=N},#b_var{}=Tuple]},
+ #b_set{op=succeeded,dst=Bool,args=[Element]}],
+ #b_br{bool=Bool,succ=Succ,fail=Fail}} ->
+ Info = {L,Succ,{Tuple,Fail},N},
+ [Info|collect_element_calls(Bs)];
+ {_,_} ->
+ collect_element_calls(Bs)
+ end;
+collect_element_calls([]) -> [].
+
+collect_chains([{This,_,V,_}=El|Els], [{_,This,V,_}|_]=Chain) ->
+ %% Add to the previous chain.
+ collect_chains(Els, [El|Chain]);
+collect_chains([El|Els], [_,_|_]=Chain) ->
+ %% Save the previous chain and start a new chain.
+ [Chain|collect_chains(Els, [El])];
+collect_chains([El|Els], _Chain) ->
+ %% The previous chain is too short; discard it and start a new.
+ collect_chains(Els, [El]);
+collect_chains([], [_,_|_]=Chain) ->
+ %% Save the last chain.
+ [Chain];
+collect_chains([], _) -> [].
+
+swap_element_calls([[{L,_,_,N}|_]=Chain|Chains], Blocks0) ->
+ Blocks = swap_element_calls_1(Chain, {N,L}, Blocks0),
+ swap_element_calls(Chains, Blocks);
+swap_element_calls([], Blocks) -> Blocks.
+
+swap_element_calls_1([{L1,_,_,N1}], {N2,L2}, Blocks) when N2 > N1 ->
+ %% We have reached the end of the chain, and the first
+ %% element instrution to be executed. Its index is lower
+ %% than the maximum index found while traversing the chain,
+ %% so we will need to swap the instructions.
+ #{L1:=Blk1,L2:=Blk2} = Blocks,
+ [#b_set{dst=Dst1}=GetEl1,Succ1] = Blk1#b_blk.is,
+ [#b_set{dst=Dst2}=GetEl2,Succ2] = Blk2#b_blk.is,
+ Is1 = [GetEl2,Succ1#b_set{args=[Dst2]}],
+ Is2 = [GetEl1,Succ2#b_set{args=[Dst1]}],
+ Blocks#{L1:=Blk1#b_blk{is=Is1},L2:=Blk2#b_blk{is=Is2}};
+swap_element_calls_1([{L,_,_,N1}|Els], {N2,_}, Blocks) when N1 > N2 ->
+ swap_element_calls_1(Els, {N2,L}, Blocks);
+swap_element_calls_1([_|Els], Highest, Blocks) ->
+ swap_element_calls_1(Els, Highest, Blocks);
+swap_element_calls_1([], _, Blocks) ->
+ %% Nothing to do. The element call with highest index
+ %% is already the first one to be executed.
+ Blocks.
+
+%%%
+%%% Record optimization.
+%%%
+%%% Replace tuple matching with an is_tagged_tuple instruction
+%%% when applicable.
+%%%
+
+ssa_opt_record(#st{ssa=Linear}=St) ->
+ Blocks = maps:from_list(Linear),
+ St#st{ssa=record_opt(Linear, Blocks)}.
+
+record_opt([{L,#b_blk{is=Is0,last=Last}=Blk0}|Bs], Blocks) ->
+ Is = record_opt_is(Is0, Last, Blocks),
+ Blk = Blk0#b_blk{is=Is},
+ [{L,Blk}|record_opt(Bs, Blocks)];
+record_opt([], _Blocks) -> [].
+
+record_opt_is([#b_set{op={bif,is_tuple},dst=Bool,args=[Tuple]}=Set],
+ Last, Blocks) ->
+ case is_tagged_tuple(Tuple, Bool, Last, Blocks) of
+ {yes,Size,Tag} ->
+ Args = [Tuple,Size,Tag],
+ [Set#b_set{op=is_tagged_tuple,args=Args}];
+ no ->
+ [Set]
+ end;
+record_opt_is([I|Is], Last, Blocks) ->
+ [I|record_opt_is(Is, Last, Blocks)];
+record_opt_is([], _Last, _Blocks) -> [].
+
+is_tagged_tuple(#b_var{}=Tuple, Bool,
+ #b_br{bool=Bool,succ=Succ,fail=Fail},
+ Blocks) ->
+ SuccBlk = maps:get(Succ, Blocks),
+ is_tagged_tuple_1(SuccBlk, Tuple, Fail, Blocks);
+is_tagged_tuple(_, _, _, _) -> no.
+
+is_tagged_tuple_1(#b_blk{is=Is,last=Last}, Tuple, Fail, Blocks) ->
+ case Is of
+ [#b_set{op={bif,tuple_size},dst=ArityVar,
+ args=[#b_var{}=Tuple]},
+ #b_set{op={bif,'=:='},
+ dst=Bool,
+ args=[ArityVar, #b_literal{val=ArityVal}=Arity]}]
+ when is_integer(ArityVal) ->
+ case Last of
+ #b_br{bool=Bool,succ=Succ,fail=Fail} ->
+ SuccBlk = maps:get(Succ, Blocks),
+ case is_tagged_tuple_2(SuccBlk, Tuple, Fail) of
+ no ->
+ no;
+ {yes,Tag} ->
+ {yes,Arity,Tag}
+ end;
+ _ ->
+ no
+ end;
+ _ ->
+ no
+ end.
+
+is_tagged_tuple_2(#b_blk{is=Is,
+ last=#b_br{bool=#b_var{}=Bool,fail=Fail}},
+ Tuple, Fail) ->
+ is_tagged_tuple_3(Is, Bool, Tuple);
+is_tagged_tuple_2(#b_blk{}, _, _) -> no.
+
+is_tagged_tuple_3([#b_set{op=get_tuple_element,
+ dst=TagVar,
+ args=[#b_var{}=Tuple,#b_literal{val=0}]}|Is],
+ Bool, Tuple) ->
+ is_tagged_tuple_4(Is, Bool, TagVar);
+is_tagged_tuple_3([_|Is], Bool, Tuple) ->
+ is_tagged_tuple_3(Is, Bool, Tuple);
+is_tagged_tuple_3([], _, _) -> no.
+
+is_tagged_tuple_4([#b_set{op={bif,'=:='},dst=Bool,
+ args=[#b_var{}=TagVar,
+ #b_literal{val=TagVal}=Tag]}],
+ Bool, TagVar) when is_atom(TagVal) ->
+ {yes,Tag};
+is_tagged_tuple_4([_|Is], Bool, TagVar) ->
+ is_tagged_tuple_4(Is, Bool, TagVar);
+is_tagged_tuple_4([], _, _) -> no.
+
+%%%
+%%% Common subexpression elimination (CSE).
+%%%
+%%% Eliminate repeated evaluation of identical expressions. To avoid
+%%% increasing the size of the stack frame, we don't eliminate
+%%% subexpressions across instructions that clobber the X registers.
+%%%
+
+ssa_opt_cse(#st{ssa=Linear}=St) ->
+ M = #{0=>#{}},
+ St#st{ssa=cse(Linear, #{}, M)}.
+
+cse([{L,#b_blk{is=Is0,last=Last0}=Blk}|Bs], Sub0, M0) ->
+ Es0 = maps:get(L, M0),
+ {Is1,Es,Sub} = cse_is(Is0, Es0, Sub0, []),
+ Last = sub(Last0, Sub),
+ M = cse_successors(Is1, Blk, Es, M0),
+ Is = reverse(Is1),
+ [{L,Blk#b_blk{is=Is,last=Last}}|cse(Bs, Sub, M)];
+cse([], _, _) -> [].
+
+cse_successors([#b_set{op=succeeded,args=[Src]},Bif|_], Blk, EsSucc, M0) ->
+ case cse_suitable(Bif) of
+ true ->
+ %% The previous instruction only has a valid value at the success branch.
+ %% We must remove the substitution for Src from the failure branch.
+ #b_blk{last=#b_br{succ=Succ,fail=Fail}} = Blk,
+ M = cse_successors_1([Succ], EsSucc, M0),
+ EsFail = maps:filter(fun(_, Val) -> Val =/= Src end, EsSucc),
+ cse_successors_1([Fail], EsFail, M);
+ false ->
+ %% There can't be any replacement for Src in EsSucc. No need for
+ %% any special handling.
+ cse_successors_1(beam_ssa:successors(Blk), EsSucc, M0)
+ end;
+cse_successors(_Is, Blk, Es, M) ->
+ cse_successors_1(beam_ssa:successors(Blk), Es, M).
+
+cse_successors_1([L|Ls], Es0, M) ->
+ case M of
+ #{L:=Es1} when map_size(Es1) =:= 0 ->
+ %% The map is already empty. No need to do anything
+ %% since the intersection will be empty.
+ cse_successors_1(Ls, Es0, M);
+ #{L:=Es1} ->
+ %% Calculate the intersection of the two maps.
+ %% Both keys and values must match.
+ Es = maps:filter(fun(Key, Value) ->
+ case Es1 of
+ #{Key:=Value} -> true;
+ #{} -> false
+ end
+ end, Es0),
+ cse_successors_1(Ls, Es0, M#{L:=Es});
+ #{} ->
+ cse_successors_1(Ls, Es0, M#{L=>Es0})
+ end;
+cse_successors_1([], _, M) -> M.
+
+cse_is([#b_set{op=succeeded,dst=Bool,args=[Src]}=I0|Is], Es, Sub0, Acc) ->
+ I = sub(I0, Sub0),
+ case I of
+ #b_set{args=[Src]} ->
+ cse_is(Is, Es, Sub0, [I|Acc]);
+ #b_set{} ->
+ %% The previous instruction has been eliminated. Eliminate the
+ %% 'succeeded' instruction too.
+ Sub = Sub0#{Bool=>#b_literal{val=true}},
+ cse_is(Is, Es, Sub, Acc)
+ end;
+cse_is([#b_set{dst=Dst}=I0|Is], Es0, Sub0, Acc) ->
+ I = sub(I0, Sub0),
+ case beam_ssa:clobbers_xregs(I) of
+ true ->
+ %% Retaining the expressions map across calls and other
+ %% clobbering instructions would work, but it would cause
+ %% the common subexpressions to be saved to Y registers,
+ %% which would probably increase the size of the stack
+ %% frame.
+ cse_is(Is, #{}, Sub0, [I|Acc]);
+ false ->
+ case cse_expr(I) of
+ none ->
+ %% Not suitable for CSE.
+ cse_is(Is, Es0, Sub0, [I|Acc]);
+ {ok,ExprKey} ->
+ case Es0 of
+ #{ExprKey:=Src} ->
+ Sub = Sub0#{Dst=>Src},
+ cse_is(Is, Es0, Sub, Acc);
+ #{} ->
+ Es = Es0#{ExprKey=>Dst},
+ cse_is(Is, Es, Sub0, [I|Acc])
+ end
+ end
+ end;
+cse_is([], Es, Sub, Acc) ->
+ {Acc,Es,Sub}.
+
+cse_expr(#b_set{op=Op,args=Args}=I) ->
+ case cse_suitable(I) of
+ true -> {ok,{Op,Args}};
+ false -> none
+ end.
+
+cse_suitable(#b_set{op=get_hd}) -> true;
+cse_suitable(#b_set{op=get_tl}) -> true;
+cse_suitable(#b_set{op=put_list}) -> true;
+cse_suitable(#b_set{op=put_tuple}) -> true;
+cse_suitable(#b_set{op={bif,tuple_size}}) ->
+ %% Doing CSE for tuple_size/1 can prevent the
+ %% creation of test_arity and select_tuple_arity
+ %% instructions. That could decrease performance
+ %% and beam_validator could fail to understand
+ %% that tuple operations that follow are safe.
+ false;
+cse_suitable(#b_set{anno=Anno,op={bif,Name},args=Args}) ->
+ %% Doing CSE for floating point operators is unsafe.
+ %% Doing CSE for comparison operators would prevent
+ %% creation of 'test' instructions.
+ Arity = length(Args),
+ not (is_map_key(float_op, Anno) orelse
+ erl_internal:new_type_test(Name, Arity) orelse
+ erl_internal:comp_op(Name, Arity) orelse
+ erl_internal:bool_op(Name, Arity));
+cse_suitable(#b_set{}) -> false.
+
+%%%
+%%% Using floating point instructions.
+%%%
+%%% Use the special floating points version of arithmetic
+%%% instructions, if the operands are known to be floats or the result
+%%% of the operation will be a float.
+%%%
+%%% The float instructions were never used in guards before, so we
+%%% will take special care to keep not using them in guards. Using
+%%% them in guards would require a new version of the 'fconv'
+%%% instruction that would take a failure label. Since it is unlikely
+%%% that using float instructions in guards would be benefical, why
+%%% bother implementing a new instruction? Also, implementing float
+%%% instructions in guards in HiPE could turn out to be a lot of work.
+%%%
+
+-record(fs,
+ {s=undefined :: 'undefined' | 'cleared',
+ regs=#{} :: #{beam_ssa:b_var():=beam_ssa:b_var()},
+ fail=none :: 'none' | beam_ssa:label(),
+ non_guards :: gb_sets:set(beam_ssa:label()),
+ bs :: beam_ssa:block_map()
+ }).
+
+ssa_opt_float(#st{ssa=Linear0,cnt=Count0}=St) ->
+ NonGuards0 = float_non_guards(Linear0),
+ NonGuards = gb_sets:from_list(NonGuards0),
+ Blocks = maps:from_list(Linear0),
+ Fs = #fs{non_guards=NonGuards,bs=Blocks},
+ {Linear,Count} = float_opt(Linear0, Count0, Fs),
+ St#st{ssa=Linear,cnt=Count}.
+
+float_non_guards([{L,#b_blk{is=Is}}|Bs]) ->
+ case Is of
+ [#b_set{op=landingpad}|_] ->
+ [L|float_non_guards(Bs)];
+ _ ->
+ float_non_guards(Bs)
+ end;
+float_non_guards([]) -> [?BADARG_BLOCK].
+
+float_opt([{L,#b_blk{last=#b_br{fail=F}}=Blk}|Bs0],
+ Count0, #fs{non_guards=NonGuards}=Fs) ->
+ case gb_sets:is_member(F, NonGuards) of
+ true ->
+ %% This block is not inside a guard.
+ %% We can do the optimization.
+ float_opt_1(L, Blk, Bs0, Count0, Fs);
+ false ->
+ %% This block is inside a guard. Don't do
+ %% any floating point optimizations.
+ {Bs,Count} = float_opt(Bs0, Count0, Fs),
+ {[{L,Blk}|Bs],Count}
+ end;
+float_opt([{L,Blk}|Bs], Count, Fs) ->
+ float_opt_1(L, Blk, Bs, Count, Fs);
+float_opt([], Count, _Fs) ->
+ {[],Count}.
+
+float_opt_1(L, #b_blk{is=Is0}=Blk0, Bs0, Count0, Fs0) ->
+ case float_opt_is(Is0, Fs0, Count0, []) of
+ {Is1,Fs1,Count1} ->
+ Fs2 = float_fail_label(Blk0, Fs1),
+ Fail = Fs2#fs.fail,
+ {Flush,Blk,Fs,Count2} = float_maybe_flush(Blk0, Fs2, Count1),
+ Split = float_split_conv(Is1, Blk),
+ {Blks0,Count3} = float_number(Split, L, Count2),
+ {Blks,Count4} = float_conv(Blks0, Fail, Count3),
+ {Bs,Count} = float_opt(Bs0, Count4, Fs),
+ {Blks++Flush++Bs,Count};
+ none ->
+ {Bs,Count} = float_opt(Bs0, Count0, Fs0),
+ {[{L,Blk0}|Bs],Count}
+ end.
+
+%% Split {float,convert} instructions into individual blocks.
+float_split_conv(Is0, Blk) ->
+ Br = #b_br{bool=#b_literal{val=true},succ=0,fail=0},
+ case splitwith(fun(#b_set{op=Op}) ->
+ Op =/= {float,convert}
+ end, Is0) of
+ {Is,[]} ->
+ [Blk#b_blk{is=Is}];
+ {[_|_]=Is1,[#b_set{op={float,convert}}=Conv|Is2]} ->
+ [#b_blk{is=Is1,last=Br},
+ #b_blk{is=[Conv],last=Br}|float_split_conv(Is2, Blk)];
+ {[],[#b_set{op={float,convert}}=Conv|Is1]} ->
+ [#b_blk{is=[Conv],last=Br}|float_split_conv(Is1, Blk)]
+ end.
+
+%% Number the blocks that were split.
+float_number([B|Bs0], FirstL, Count0) ->
+ {Bs,Count} = float_number(Bs0, Count0),
+ {[{FirstL,B}|Bs],Count}.
+
+float_number([B|Bs0], Count0) ->
+ {Bs,Count} = float_number(Bs0, Count0+1),
+ {[{Count0,B}|Bs],Count};
+float_number([], Count) ->
+ {[],Count}.
+
+%% Insert 'succeeded' instructions after each {float,convert}
+%% instruction.
+float_conv([{L,#b_blk{is=Is0}=Blk0}|Bs0], Fail, Count0) ->
+ case Is0 of
+ [#b_set{op={float,convert}}=Conv] ->
+ {Bool0,Count1} = new_reg('@ssa_bool', Count0),
+ Bool = #b_var{name=Bool0},
+ Succeeded = #b_set{op=succeeded,dst=Bool,
+ args=[Conv#b_set.dst]},
+ Is = [Conv,Succeeded],
+ [{NextL,_}|_] = Bs0,
+ Br = #b_br{bool=Bool,succ=NextL,fail=Fail},
+ Blk = Blk0#b_blk{is=Is,last=Br},
+ {Bs,Count} = float_conv(Bs0, Fail, Count1),
+ {[{L,Blk}|Bs],Count};
+ [_|_] ->
+ case Bs0 of
+ [{NextL,_}|_] ->
+ Br = #b_br{bool=#b_literal{val=true},
+ succ=NextL,fail=NextL},
+ Blk = Blk0#b_blk{last=Br},
+ {Bs,Count} = float_conv(Bs0, Fail, Count0),
+ {[{L,Blk}|Bs],Count};
+ [] ->
+ {[{L,Blk0}],Count0}
+ end
+ end.
+
+float_maybe_flush(Blk0, #fs{s=cleared,fail=Fail,bs=Blocks}=Fs0, Count0) ->
+ #b_blk{last=#b_br{bool=#b_var{},succ=Succ}=Br} = Blk0,
+ #b_blk{is=Is} = maps:get(Succ, Blocks),
+ case Is of
+ [#b_set{anno=#{float_op:=_}}|_] ->
+ %% The next operation is also a floating point operation.
+ %% No flush needed.
+ {[],Blk0,Fs0,Count0};
+ _ ->
+ %% Flush needed.
+ {Bool0,Count1} = new_reg('@ssa_bool', Count0),
+ Bool = #b_var{name=Bool0},
+
+ %% Allocate block numbers.
+ CheckL = Count1, %For checkerror.
+ FlushL = Count1 + 1, %For flushing of float regs.
+ Count = Count1 + 2,
+ Blk = Blk0#b_blk{last=Br#b_br{succ=CheckL}},
+
+ %% Build the block with the checkerror instruction.
+ CheckIs = [#b_set{op={float,checkerror},dst=Bool}],
+ CheckBr = #b_br{bool=Bool,succ=FlushL,fail=Fail},
+ CheckBlk = #b_blk{is=CheckIs,last=CheckBr},
+
+ %% Build the block that flushes all registers.
+ FlushIs = float_flush_regs(Fs0),
+ FlushBr = #b_br{bool=#b_literal{val=true},succ=Succ,fail=Succ},
+ FlushBlk = #b_blk{is=FlushIs,last=FlushBr},
+
+ %% Update state and blocks.
+ Fs = Fs0#fs{s=undefined,regs=#{},fail=none},
+ FlushBs = [{CheckL,CheckBlk},{FlushL,FlushBlk}],
+ {FlushBs,Blk,Fs,Count}
+ end;
+float_maybe_flush(Blk, Fs, Count) ->
+ {[],Blk,Fs,Count}.
+
+float_opt_is([#b_set{op=succeeded,args=[Src]}=I0],
+ #fs{regs=Rs}=Fs, Count, Acc) ->
+ case Rs of
+ #{Src:=Fr} ->
+ I = I0#b_set{args=[Fr]},
+ {reverse(Acc, [I]),Fs,Count};
+ #{} ->
+ {reverse(Acc, [I0]),Fs,Count}
+ end;
+float_opt_is([#b_set{anno=Anno0}=I0|Is0], Fs0, Count0, Acc) ->
+ case Anno0 of
+ #{float_op:=FTypes} ->
+ Anno = maps:remove(float_op, Anno0),
+ I1 = I0#b_set{anno=Anno},
+ {Is,Fs,Count} = float_make_op(I1, FTypes, Fs0, Count0),
+ float_opt_is(Is0, Fs, Count, reverse(Is, Acc));
+ #{} ->
+ float_opt_is(Is0, Fs0#fs{regs=#{}}, Count0, [I0|Acc])
+ end;
+float_opt_is([], Fs, _Count, _Acc) ->
+ #fs{s=undefined} = Fs, %Assertion.
+ none.
+
+float_make_op(#b_set{op={bif,Op},dst=Dst,args=As0}=I0,
+ Ts, #fs{s=S,regs=Rs0}=Fs, Count0) ->
+ {As1,Rs1,Count1} = float_load(As0, Ts, Rs0, Count0, []),
+ {As,Is0} = unzip(As1),
+ {Fr,Count2} = new_reg('@fr', Count1),
+ FrDst = #b_var{name=Fr},
+ I = I0#b_set{op={float,Op},dst=FrDst,args=As},
+ Rs = Rs1#{Dst=>FrDst},
+ Is = append(Is0) ++ [I],
+ case S of
+ undefined ->
+ {Ignore,Count} = new_reg('@ssa_ignore', Count2),
+ C = #b_set{op={float,clearerror},dst=#b_var{name=Ignore}},
+ {[C|Is],Fs#fs{s=cleared,regs=Rs},Count};
+ cleared ->
+ {Is,Fs#fs{regs=Rs},Count2}
+ end.
+
+float_load([A|As], [T|Ts], Rs0, Count0, Acc) ->
+ {Load,Rs,Count} = float_reg_arg(A, T, Rs0, Count0),
+ float_load(As, Ts, Rs, Count, [Load|Acc]);
+float_load([], [], Rs, Count, Acc) ->
+ {reverse(Acc),Rs,Count}.
+
+float_reg_arg(A, T, Rs, Count0) ->
+ case Rs of
+ #{A:=Fr} ->
+ {{Fr,[]},Rs,Count0};
+ #{} ->
+ {Fr,Count} = new_float_copy_reg(Count0),
+ Dst = #b_var{name=Fr},
+ I = float_load_reg(T, A, Dst),
+ {{Dst,[I]},Rs#{A=>Dst},Count}
+ end.
+
+float_load_reg(convert, #b_var{}=Src, Dst) ->
+ #b_set{op={float,convert},dst=Dst,args=[Src]};
+float_load_reg(convert, #b_literal{val=Val}=Src, Dst) ->
+ try float(Val) of
+ F ->
+ #b_set{op={float,put},dst=Dst,args=[#b_literal{val=F}]}
+ catch
+ error:_ ->
+ %% Let the exception happen at runtime.
+ #b_set{op={float,convert},dst=Dst,args=[Src]}
+ end;
+float_load_reg(float, Src, Dst) ->
+ #b_set{op={float,put},dst=Dst,args=[Src]}.
+
+new_float_copy_reg(Count) ->
+ new_reg('@fr_copy', Count).
+
+new_reg(Base, Count) ->
+ Fr = {Base,Count},
+ {Fr,Count+1}.
+
+float_fail_label(#b_blk{last=Last}, Fs) ->
+ case Last of
+ #b_br{bool=#b_var{},fail=Fail} ->
+ Fs#fs{fail=Fail};
+ _ ->
+ Fs
+ end.
+
+float_flush_regs(#fs{regs=Rs}) ->
+ maps:fold(fun(_, #b_var{name={'@fr_copy',_}}, Acc) ->
+ Acc;
+ (Dst, Fr, Acc) ->
+ [#b_set{op={float,get},dst=Dst,args=[Fr]}|Acc]
+ end, [], Rs).
+
+%%%
+%%% Live optimization.
+%%%
+%%% Optimize instructions whose values are not used. They could be
+%%% removed if they have no side effects, or in a few cases replaced
+%%% with a cheaper instructions
+%%%
+
+ssa_opt_live(#st{ssa=Linear}=St) ->
+ St#st{ssa=live_opt(reverse(Linear), #{}, [])}.
+
+live_opt([{L,Blk0}|Bs], LiveMap0, Acc) ->
+ Successors = beam_ssa:successors(Blk0),
+ Live0 = live_opt_succ(Successors, L, LiveMap0),
+ {Blk,Live} = live_opt_blk(Blk0, Live0),
+ LiveMap = live_opt_phis(Blk#b_blk.is, L, Live, LiveMap0),
+ live_opt(Bs, LiveMap, [{L,Blk}|Acc]);
+live_opt([], _, Acc) -> Acc.
+
+live_opt_succ([S|Ss], L, LiveMap) ->
+ Live0 = live_opt_succ(Ss, L, LiveMap),
+ Key = {S,L},
+ case LiveMap of
+ #{Key:=Live} ->
+ gb_sets:union(Live, Live0);
+ #{S:=Live} ->
+ gb_sets:union(Live, Live0);
+ #{} ->
+ Live0
+ end;
+live_opt_succ([], _, _) ->
+ gb_sets:empty().
+
+live_opt_phis(Is, L, Live0, LiveMap0) ->
+ LiveMap = LiveMap0#{L=>Live0},
+ Phis = takewhile(fun(#b_set{op=Op}) -> Op =:= phi end, Is),
+ case Phis of
+ [] ->
+ LiveMap;
+ [_|_] ->
+ PhiArgs = append([Args || #b_set{args=Args} <- Phis]),
+ case [{P,V} || {#b_var{}=V,P} <- PhiArgs] of
+ [_|_]=PhiVars ->
+ PhiLive0 = rel2fam(PhiVars),
+ PhiLive = [{{L,P},gb_sets:union(gb_sets:from_list(Vs), Live0)} ||
+ {P,Vs} <- PhiLive0],
+ maps:merge(LiveMap, maps:from_list(PhiLive));
+ [] ->
+ %% There were only literals in the phi node(s).
+ LiveMap
+ end
+ end.
+
+live_opt_blk(#b_blk{is=Is0,last=Last}=Blk, Live0) ->
+ Live1 = gb_sets:union(Live0, gb_sets:from_ordset(beam_ssa:used(Last))),
+ {Is,Live} = live_opt_is(reverse(Is0), Live1, []),
+ {Blk#b_blk{is=Is},Live}.
+
+live_opt_is([#b_set{op=phi,dst=Dst}=I|Is], Live, Acc) ->
+ case gb_sets:is_member(Dst, Live) of
+ true ->
+ live_opt_is(Is, Live, [I|Acc]);
+ false ->
+ live_opt_is(Is, Live, Acc)
+ end;
+live_opt_is([#b_set{op=succeeded,dst=SuccDst=SuccDstVar,
+ args=[Dst]}=SuccI,
+ #b_set{dst=Dst}=I|Is], Live0, Acc) ->
+ case gb_sets:is_member(Dst, Live0) of
+ true ->
+ case gb_sets:is_member(SuccDst, Live0) of
+ true ->
+ Live1 = gb_sets:add(Dst, Live0),
+ Live = gb_sets:delete_any(SuccDst, Live1),
+ live_opt_is([I|Is], Live, [SuccI|Acc]);
+ false ->
+ live_opt_is([I|Is], Live0, Acc)
+ end;
+ false ->
+ case live_opt_unused(I) of
+ {replace,NewI0} ->
+ NewI = NewI0#b_set{dst=SuccDstVar},
+ live_opt_is([NewI|Is], Live0, Acc);
+ keep ->
+ case gb_sets:is_member(SuccDst, Live0) of
+ true ->
+ Live1 = gb_sets:add(Dst, Live0),
+ Live = gb_sets:delete_any(SuccDst, Live1),
+ live_opt_is([I|Is], Live, [SuccI|Acc]);
+ false ->
+ live_opt_is([I|Is], Live0, Acc)
+ end
+ end
+ end;
+live_opt_is([#b_set{dst=Dst}=I|Is], Live0, Acc) ->
+ case gb_sets:is_member(Dst, Live0) of
+ true ->
+ Live1 = gb_sets:union(Live0, gb_sets:from_ordset(beam_ssa:used(I))),
+ Live = gb_sets:delete_any(Dst, Live1),
+ live_opt_is(Is, Live, [I|Acc]);
+ false ->
+ case beam_ssa:no_side_effect(I) of
+ true ->
+ live_opt_is(Is, Live0, Acc);
+ false ->
+ Live = gb_sets:union(Live0, gb_sets:from_ordset(beam_ssa:used(I))),
+ live_opt_is(Is, Live, [I|Acc])
+ end
+ end;
+live_opt_is([], Live, Acc) ->
+ {Acc,Live}.
+
+live_opt_unused(#b_set{op=get_map_element}=Set) ->
+ {replace,Set#b_set{op=has_map_field}};
+live_opt_unused(_) -> keep.
+
+%%%
+%%% Optimize binary matching instructions.
+%%%
+
+ssa_opt_bsm(#st{ssa=Linear}=St) ->
+ Extracted0 = bsm_extracted(Linear),
+ Extracted = cerl_sets:from_list(Extracted0),
+ St#st{ssa=bsm_skip(Linear, Extracted)}.
+
+bsm_skip([{L,#b_blk{is=Is0}=Blk}|Bs], Extracted) ->
+ Is = bsm_skip_is(Is0, Extracted),
+ [{L,Blk#b_blk{is=Is}}|bsm_skip(Bs, Extracted)];
+bsm_skip([], _) -> [].
+
+bsm_skip_is([I0|Is], Extracted) ->
+ case I0 of
+ #b_set{op=bs_match,args=[#b_literal{val=string}|_]} ->
+ [I0|bsm_skip_is(Is, Extracted)];
+ #b_set{op=bs_match,dst=Ctx,args=[Type,PrevCtx|Args0]} ->
+ I = case cerl_sets:is_element(Ctx, Extracted) of
+ true ->
+ I0;
+ false ->
+ %% The value is never extracted.
+ Args = [#b_literal{val=skip},PrevCtx,Type|Args0],
+ I0#b_set{args=Args}
+ end,
+ [I|Is];
+ #b_set{} ->
+ [I0|bsm_skip_is(Is, Extracted)]
+ end;
+bsm_skip_is([], _) -> [].
+
+bsm_extracted([{_,#b_blk{is=Is}}|Bs]) ->
+ case Is of
+ [#b_set{op=bs_extract,args=[Ctx]}|_] ->
+ [Ctx|bsm_extracted(Bs)];
+ _ ->
+ bsm_extracted(Bs)
+ end;
+bsm_extracted([]) -> [].
+
+%%%
+%%% Short-cutting binary matching instructions.
+%%%
+
+ssa_opt_bsm_shortcut(#st{ssa=Linear}=St) ->
+ Positions = bsm_positions(Linear, #{}),
+ case map_size(Positions) of
+ 0 ->
+ %% No binary matching instructions.
+ St;
+ _ ->
+ St#st{ssa=bsm_shortcut(Linear, Positions)}
+ end.
+
+bsm_positions([{L,#b_blk{is=Is,last=Last}}|Bs], PosMap0) ->
+ PosMap = bsm_positions_is(Is, PosMap0),
+ case {Is,Last} of
+ {[#b_set{op=bs_test_tail,dst=Bool,args=[Ctx,#b_literal{val=Bits0}]}],
+ #b_br{bool=Bool,fail=Fail}} ->
+ Bits = Bits0 + maps:get(Ctx, PosMap0),
+ bsm_positions(Bs, PosMap#{L=>{Bits,Fail}});
+ {_,_} ->
+ bsm_positions(Bs, PosMap)
+ end;
+bsm_positions([], PosMap) -> PosMap.
+
+bsm_positions_is([#b_set{op=bs_start_match,dst=New}|Is], PosMap0) ->
+ PosMap = PosMap0#{New=>0},
+ bsm_positions_is(Is, PosMap);
+bsm_positions_is([#b_set{op=bs_match,dst=New,args=Args}|Is], PosMap0) ->
+ [_,Old|_] = Args,
+ #{Old:=Bits0} = PosMap0,
+ Bits = bsm_update_bits(Args, Bits0),
+ PosMap = PosMap0#{New=>Bits},
+ bsm_positions_is(Is, PosMap);
+bsm_positions_is([_|Is], PosMap) ->
+ bsm_positions_is(Is, PosMap);
+bsm_positions_is([], PosMap) -> PosMap.
+
+bsm_update_bits([#b_literal{val=string},_,#b_literal{val=String}], Bits) ->
+ Bits + bit_size(String);
+bsm_update_bits([#b_literal{val=utf8}|_], Bits) ->
+ Bits + 8;
+bsm_update_bits([#b_literal{val=utf16}|_], Bits) ->
+ Bits + 16;
+bsm_update_bits([#b_literal{val=utf32}|_], Bits) ->
+ Bits + 32;
+bsm_update_bits([_,_,_,#b_literal{val=Sz},#b_literal{val=U}], Bits)
+ when is_integer(Sz) ->
+ Bits + Sz*U;
+bsm_update_bits(_, Bits) -> Bits.
+
+bsm_shortcut([{L,#b_blk{is=Is,last=Last0}=Blk}|Bs], PosMap) ->
+ case {Is,Last0} of
+ {[#b_set{op=bs_match,dst=New,args=[_,Old|_]},
+ #b_set{op=succeeded,dst=Bool,args=[New]}],
+ #b_br{bool=Bool,fail=Fail}} ->
+ case PosMap of
+ #{Old:=Bits,Fail:={TailBits,NextFail}} when Bits > TailBits ->
+ Last = Last0#b_br{fail=NextFail},
+ [{L,Blk#b_blk{last=Last}}|bsm_shortcut(Bs, PosMap)];
+ #{} ->
+ [{L,Blk}|bsm_shortcut(Bs, PosMap)]
+ end;
+ {_,_} ->
+ [{L,Blk}|bsm_shortcut(Bs, PosMap)]
+ end;
+bsm_shortcut([], _PosMap) -> [].
+
+%%%
+%%% Miscellanous optimizations in execution order.
+%%%
+
+ssa_opt_misc(#st{ssa=Linear}=St) ->
+ St#st{ssa=misc_opt(Linear, #{})}.
+
+misc_opt([{L,#b_blk{is=Is0,last=Last0}=Blk0}|Bs], Sub0) ->
+ {Is,Sub} = misc_opt_is(Is0, Sub0, []),
+ Last = sub(Last0, Sub),
+ Blk = Blk0#b_blk{is=Is,last=Last},
+ [{L,Blk}|misc_opt(Bs, Sub)];
+misc_opt([], _) -> [].
+
+misc_opt_is([#b_set{op=phi}=I0|Is], Sub0, Acc) ->
+ #b_set{dst=Dst,args=Args} = I = sub(I0, Sub0),
+ case all_same(Args) of
+ true ->
+ %% Eliminate the phi node if there is just one source
+ %% value or if the values are identical.
+ [{Val,_}|_] = Args,
+ Sub = Sub0#{Dst=>Val},
+ misc_opt_is(Is, Sub, Acc);
+ false ->
+ misc_opt_is(Is, Sub0, [I|Acc])
+ end;
+misc_opt_is([#b_set{op={bif,'and'}}=I0], Sub, Acc) ->
+ #b_set{dst=Dst,args=Args} = I = sub(I0, Sub),
+ case eval_and(Args) of
+ error ->
+ misc_opt_is([], Sub, [I|Acc]);
+ Val ->
+ misc_opt_is([], Sub#{Dst=>Val}, Acc)
+ end;
+misc_opt_is([#b_set{op={bif,'or'}}=I0], Sub, Acc) ->
+ #b_set{dst=Dst,args=Args} = I = sub(I0, Sub),
+ case eval_or(Args) of
+ error ->
+ misc_opt_is([], Sub, [I|Acc]);
+ Val ->
+ misc_opt_is([], Sub#{Dst=>Val}, Acc)
+ end;
+misc_opt_is([#b_set{}=I0|Is], Sub, Acc) ->
+ #b_set{op=Op,dst=Dst,args=Args} = I = sub(I0, Sub),
+ case make_literal(Op, Args) of
+ #b_literal{}=Literal ->
+ misc_opt_is(Is, Sub#{Dst=>Literal}, Acc);
+ error ->
+ misc_opt_is(Is, Sub, [I|Acc])
+ end;
+misc_opt_is([], Sub, Acc) ->
+ {reverse(Acc),Sub}.
+
+all_same([{H,_}|T]) ->
+ all(fun({E,_}) -> E =:= H end, T).
+
+make_literal(put_tuple, Args) ->
+ case make_literal_list(Args, []) of
+ error ->
+ error;
+ List ->
+ #b_literal{val=list_to_tuple(List)}
+ end;
+make_literal(put_list, [#b_literal{val=H},#b_literal{val=T}]) ->
+ #b_literal{val=[H|T]};
+make_literal(_, _) -> error.
+
+make_literal_list([#b_literal{val=H}|T], Acc) ->
+ make_literal_list(T, [H|Acc]);
+make_literal_list([_|_], _) ->
+ error;
+make_literal_list([], Acc) ->
+ reverse(Acc).
+
+eval_and(Args) ->
+ case Args of
+ [_,#b_literal{val=false}=Res] -> Res;
+ [Res,#b_literal{val=true}] -> Res;
+ [_,_] -> error
+ end.
+
+eval_or(Args) ->
+ case Args of
+ [Res,#b_literal{val=false}] -> Res;
+ [_,#b_literal{val=true}=Res] -> Res;
+ [_,_] -> error
+ end.
+
+%%%
+%%% Optimize expressions such as "tuple_size(Var) =:= 2".
+%%%
+%%% Consider this code:
+%%%
+%%% 0:
+%%% .
+%%% .
+%%% .
+%%% Size = bif:tuple_size Var
+%%% BoolVar1 = succeeded Size
+%%% br BoolVar1, label 4, label 3
+%%%
+%%% 4:
+%%% BoolVar2 = bif:'=:=' Size, literal 2
+%%% br BoolVar2, label 6, label 3
+%%%
+%%% 6: ... %% OK
+%%%
+%%% 3: ... %% Not a tuple of size 2
+%%%
+%%% The BEAM code will look this:
+%%%
+%%% {bif,tuple_size,{f,3},[{x,0}],{x,0}}.
+%%% {test,is_eq_exact,{f,3},[{x,0},{integer,2}]}.
+%%%
+%%% Better BEAM code will be produced if we transform the
+%%% code like this:
+%%%
+%%% 0:
+%%% .
+%%% .
+%%% .
+%%% br label 10
+%%%
+%%% 10:
+%%% NewBoolVar = bif:is_tuple Var
+%%% br NewBoolVar, label 11, label 3
+%%%
+%%% 11:
+%%% Size = bif:tuple_size Var
+%%% br label 4
+%%%
+%%% 4:
+%%% BoolVar2 = bif:'=:=' Size, literal 2
+%%% br BoolVar2, label 6, label 3
+%%%
+%%% (The key part of the transformation is the removal of
+%%% the 'succeeded' instruction to signal to the code generator
+%%% that the call to tuple_size/1 can't fail.)
+%%%
+%%% The BEAM code will look like:
+%%%
+%%% {test,is_tuple,{f,3},[{x,0}]}.
+%%% {test_arity,{f,3},[{x,0},2]}.
+%%%
+%%% Those two instructions will be combined into a single
+%%% is_tuple_of_arity instruction by the loader.
+%%%
+
+ssa_opt_tuple_size(#st{ssa=Linear0,cnt=Count0}=St) ->
+ {Linear,Count} = opt_tup_size(Linear0, Count0, []),
+ St#st{ssa=Linear,cnt=Count}.
+
+opt_tup_size([{L,#b_blk{is=Is,last=Last}=Blk}|Bs], Count0, Acc0) ->
+ case {Is,Last} of
+ {[#b_set{op={bif,'=:='},dst=Bool,args=[#b_var{}=Tup,#b_literal{val=Arity}]}],
+ #b_br{bool=Bool}} when is_integer(Arity), Arity >= 0 ->
+ {Acc,Count} = opt_tup_size_1(Tup, L, Count0, Acc0),
+ opt_tup_size(Bs, Count, [{L,Blk}|Acc]);
+ {_,_} ->
+ opt_tup_size(Bs, Count0, [{L,Blk}|Acc0])
+ end;
+opt_tup_size([], Count, Acc) ->
+ {reverse(Acc),Count}.
+
+opt_tup_size_1(Size, EqL, Count0, [{L,Blk0}|Acc]) ->
+ case Blk0 of
+ #b_blk{is=Is0,last=#b_br{bool=Bool,succ=EqL,fail=Fail}} ->
+ case opt_tup_size_is(Is0, Bool, Size, []) of
+ none ->
+ {[{L,Blk0}|Acc],Count0};
+ {PreIs,TupleSizeIs,Tuple} ->
+ opt_tup_size_2(PreIs, TupleSizeIs, L, EqL,
+ Tuple, Fail, Count0, Acc)
+ end;
+ #b_blk{} ->
+ {[{L,Blk0}|Acc],Count0}
+ end;
+opt_tup_size_1(_, _, Count, Acc) ->
+ {Acc,Count}.
+
+opt_tup_size_2(PreIs, TupleSizeIs, PreL, EqL, Tuple, Fail, Count0, Acc) ->
+ IsTupleL = Count0,
+ TupleSizeL = Count0 + 1,
+ Bool = #b_var{name={'@ssa_bool',Count0+2}},
+ Count = Count0 + 3,
+
+ True = #b_literal{val=true},
+ PreBr = #b_br{bool=True,succ=IsTupleL,fail=IsTupleL},
+ PreBlk = #b_blk{is=PreIs,last=PreBr},
+
+ IsTupleIs = [#b_set{op={bif,is_tuple},dst=Bool,args=[Tuple]}],
+ IsTupleBr = #b_br{bool=Bool,succ=TupleSizeL,fail=Fail},
+ IsTupleBlk = #b_blk{is=IsTupleIs,last=IsTupleBr},
+
+ TupleSizeBr = #b_br{bool=True,succ=EqL,fail=EqL},
+ TupleSizeBlk = #b_blk{is=TupleSizeIs,last=TupleSizeBr},
+ {[{TupleSizeL,TupleSizeBlk},
+ {IsTupleL,IsTupleBlk},
+ {PreL,PreBlk}|Acc],Count}.
+
+opt_tup_size_is([#b_set{op={bif,tuple_size},dst=Size,args=[Tuple]}=I,
+ #b_set{op=succeeded,dst=Bool,args=[Size]}],
+ Bool, Size, Acc) ->
+ {reverse(Acc),[I],Tuple};
+opt_tup_size_is([I|Is], Bool, Size, Acc) ->
+ opt_tup_size_is(Is, Bool, Size, [I|Acc]);
+opt_tup_size_is([], _, _, _Acc) -> none.
+
+%%%
+%%% Optimize #b_switch{} instructions.
+%%%
+%%% If the argument for a #b_switch{} comes from a phi node with all
+%%% literals, any values in the switch list which are not in the phi
+%%% node can be removed.
+%%%
+%%% If the values in the phi node and switch list are the same,
+%%% the failure label can't be reached and be eliminated.
+%%%
+%%% A #b_switch{} with only one value can be rewritten to
+%%% a #b_br{}. A switch that only verifies that the argument
+%%% is 'true' or 'false' can be rewritten to a is_boolean test.
+%%%
+
+ssa_opt_sw(#st{ssa=Linear0,cnt=Count0}=St) ->
+ {Linear,Count} = opt_sw(Linear0, #{}, Count0, []),
+ St#st{ssa=Linear,cnt=Count}.
+
+opt_sw([{L,#b_blk{is=Is,last=#b_switch{}=Last0}=Blk0}|Bs], Phis0, Count0, Acc) ->
+ Phis = opt_sw_phis(Is, Phis0),
+ case opt_sw_last(Last0, Phis) of
+ #b_switch{arg=Arg,fail=Fail,list=[{Lit,Lbl}]} ->
+ %% Rewrite a single value switch to a br.
+ Bool = #b_var{name={'@ssa_bool',Count0}},
+ Count = Count0 + 1,
+ IsEq = #b_set{op={bif,'=:='},dst=Bool,args=[Arg,Lit]},
+ Br = #b_br{bool=Bool,succ=Lbl,fail=Fail},
+ Blk = Blk0#b_blk{is=Is++[IsEq],last=Br},
+ opt_sw(Bs, Phis, Count, [{L,Blk}|Acc]);
+ #b_switch{arg=Arg,fail=Fail,
+ list=[{#b_literal{val=B1},Lbl},{#b_literal{val=B2},Lbl}]}
+ when B1 =:= not B2 ->
+ %% Replace with is_boolean test.
+ Bool = #b_var{name={'@ssa_bool',Count0}},
+ Count = Count0 + 1,
+ IsBool = #b_set{op={bif,is_boolean},dst=Bool,args=[Arg]},
+ Br = #b_br{bool=Bool,succ=Lbl,fail=Fail},
+ Blk = Blk0#b_blk{is=Is++[IsBool],last=Br},
+ opt_sw(Bs, Phis, Count, [{L,Blk}|Acc]);
+ Last0 ->
+ opt_sw(Bs, Phis, Count0, [{L,Blk0}|Acc]);
+ Last ->
+ Blk = Blk0#b_blk{last=Last},
+ opt_sw(Bs, Phis, Count0, [{L,Blk}|Acc])
+ end;
+opt_sw([{L,#b_blk{is=Is}=Blk}|Bs], Phis0, Count, Acc) ->
+ Phis = opt_sw_phis(Is, Phis0),
+ opt_sw(Bs, Phis, Count, [{L,Blk}|Acc]);
+opt_sw([], _Phis, Count, Acc) ->
+ {reverse(Acc),Count}.
+
+opt_sw_phis([#b_set{op=phi,dst=Dst,args=Args}|Is], Phis) ->
+ case opt_sw_literals(Args, []) of
+ error ->
+ opt_sw_phis(Is, Phis);
+ Literals ->
+ opt_sw_phis(Is, Phis#{Dst=>Literals})
+ end;
+opt_sw_phis(_, Phis) -> Phis.
+
+opt_sw_last(#b_switch{arg=Arg,fail=Fail,list=List0}=Sw0, Phis) ->
+ case Phis of
+ #{Arg:=Values0} ->
+ Values = gb_sets:from_list(Values0),
+
+ %% Prune the switch list to only contain the possible values.
+ List1 = [P || {Lit,_}=P <- List0, gb_sets:is_member(Lit, Values)],
+
+ %% Now test whether the failure label can ever be reached.
+ Sw = case gb_sets:size(Values) =:= length(List1) of
+ true ->
+ %% The switch list has the same number of values as the phi node.
+ %% The values must be the same, because the values that were not
+ %% possible were pruned from the switch list. Therefore, the
+ %% failure label can't possibly be reached, and we can choose a
+ %% a new failure label by picking a value from the list.
+ case List1 of
+ [{#b_literal{},Lbl}|List] ->
+ Sw0#b_switch{fail=Lbl,list=List};
+ [] ->
+ Sw0#b_switch{list=List1}
+ end;
+ false ->
+ %% There are some values in the phi node that are not in the
+ %% switch list; thus, the failure label can still be reached.
+ Sw0
+ end,
+ beam_ssa:normalize(Sw);
+ #{} ->
+ %% Ensure that no label in the switch list is the same
+ %% as the failure label.
+ List = [{Val,Lbl} || {Val,Lbl} <- List0, Lbl =/= Fail],
+ Sw = Sw0#b_switch{list=List},
+ beam_ssa:normalize(Sw)
+ end.
+
+opt_sw_literals([{#b_literal{}=Lit,_}|T], Acc) ->
+ opt_sw_literals(T, [Lit|Acc]);
+opt_sw_literals([_|_], _Acc) ->
+ error;
+opt_sw_literals([], Acc) -> Acc.
+
+
+%%%
+%%% Merge blocks.
+%%%
+
+ssa_opt_merge_blocks(#st{ssa=Blocks}=St) ->
+ Preds = beam_ssa:predecessors(Blocks),
+ St#st{ssa=merge_blocks_1(beam_ssa:rpo(Blocks), Preds, Blocks)}.
+
+merge_blocks_1([L|Ls], Preds0, Blocks0) ->
+ case Preds0 of
+ #{L:=[P]} ->
+ #{P:=Blk0,L:=Blk1} = Blocks0,
+ case is_merge_allowed(L, Blk0, Blk1) of
+ true ->
+ #b_blk{is=Is0} = Blk0,
+ #b_blk{is=Is1} = Blk1,
+ Is = Is0 ++ Is1,
+ Blk = Blk1#b_blk{is=Is},
+ Blocks1 = maps:remove(L, Blocks0),
+ Blocks2 = maps:put(P, Blk, Blocks1),
+ Successors = beam_ssa:successors(Blk),
+ Blocks = beam_ssa:update_phi_labels(Successors, L, P, Blocks2),
+ Preds = merge_update_preds(Successors, L, P, Preds0),
+ merge_blocks_1(Ls, Preds, Blocks);
+ false ->
+ merge_blocks_1(Ls, Preds0, Blocks0)
+ end;
+ #{} ->
+ merge_blocks_1(Ls, Preds0, Blocks0)
+ end;
+merge_blocks_1([], _Preds, Blocks) -> Blocks.
+
+merge_update_preds([L|Ls], From, To, Preds0) ->
+ Ps = [rename_label(P, From, To) || P <- maps:get(L, Preds0)],
+ Preds = maps:put(L, Ps, Preds0),
+ merge_update_preds(Ls, From, To, Preds);
+merge_update_preds([], _, _, Preds) -> Preds.
+
+rename_label(From, From, To) -> To;
+rename_label(Lbl, _, _) -> Lbl.
+
+is_merge_allowed(_, _, #b_blk{is=[#b_set{op=peek_message}|_]}) ->
+ false;
+is_merge_allowed(L, Blk0, #b_blk{}) ->
+ case beam_ssa:successors(Blk0) of
+ [L] -> true;
+ [_|_] -> false
+ end.
+
+%%%
+%%% When a tuple is matched, the pattern matching compiler generates a
+%%% get_tuple_element instruction for every tuple element that will
+%%% ever be used in the rest of the function. That often forces the
+%%% extracted tuple elements to be stored in Y registers until it's
+%%% time to use them. It could also mean that there could be execution
+%%% paths that will never use the extracted elements.
+%%%
+%%% This optimization will sink get_tuple_element instructions, that
+%%% is, move them forward in the execution stream to the last possible
+%%% block there they will still dominate all uses. That may reduce the
+%%% size of stack frames, reduce register shuffling, and avoid
+%%% extracting tuple elements on execution paths that never use the
+%%% extracted values.
+%%%
+
+ssa_opt_sink(#st{ssa=Blocks0}=St) ->
+ Linear = beam_ssa:linearize(Blocks0),
+
+ %% Create a map with all variables that define get_tuple_element
+ %% instructions. The variable name map to the block it is defined in.
+ Defs = maps:from_list(def_blocks(Linear)),
+
+ %% Now find all the blocks that use variables defined by get_tuple_element
+ %% instructions.
+ Used = used_blocks(Linear, Defs, []),
+
+ %% Calculate dominators.
+ Dom0 = beam_ssa:dominators(Blocks0),
+
+ %% It is not safe to move get_tuple_element instructions to blocks
+ %% that begin with certain instructions. It is also unsafe to move
+ %% the instructions into any part of a receive. To avoid such
+ %% unsafe moves, pretend that the unsuitable blocks are not
+ %% dominators.
+ Unsuitable = unsuitable(Linear, Blocks0),
+ Dom = case gb_sets:is_empty(Unsuitable) of
+ true ->
+ Dom0;
+ false ->
+ F = fun(_, DomBy) ->
+ [L || L <- DomBy,
+ not gb_sets:is_element(L, Unsuitable)]
+ end,
+ maps:map(F, Dom0)
+ end,
+
+ %% Calculate new positions for get_tuple_element instructions. The new
+ %% position is a block that dominates all uses of the variable.
+ DefLoc = new_def_locations(Used, Defs, Dom),
+
+ %% Now move all suitable get_tuple_element instructions to their
+ %% new blocks.
+ Blocks = foldl(fun({V,To}, A) ->
+ From = maps:get(V, Defs),
+ move_defs(V, From, To, A)
+ end, Blocks0, DefLoc),
+ St#st{ssa=Blocks}.
+
+def_blocks([{L,#b_blk{is=Is}}|Bs]) ->
+ def_blocks_is(Is, L, def_blocks(Bs));
+def_blocks([]) -> [].
+
+def_blocks_is([#b_set{op=get_tuple_element,dst=Dst}|Is], L, Acc) ->
+ def_blocks_is(Is, L, [{Dst,L}|Acc]);
+def_blocks_is([_|Is], L, Acc) ->
+ def_blocks_is(Is, L, Acc);
+def_blocks_is([], _, Acc) -> Acc.
+
+used_blocks([{L,Blk}|Bs], Def, Acc0) ->
+ Used = beam_ssa:used(Blk),
+ Acc = [{V,L} || V <- Used, maps:is_key(V, Def)] ++ Acc0,
+ used_blocks(Bs, Def, Acc);
+used_blocks([], _Def, Acc) ->
+ rel2fam(Acc).
+
+%% unsuitable(Linear, Blocks) -> Unsuitable.
+%% Return an ordset of block labels for the blocks that are not
+%% suitable for sinking of get_tuple_element instructions.
+
+unsuitable(Linear, Blocks) ->
+ Predecessors = beam_ssa:predecessors(Blocks),
+ Unsuitable0 = unsuitable_1(Linear),
+ Unsuitable1 = unsuitable_recv(Linear, Blocks, Predecessors),
+ gb_sets:from_list(Unsuitable0 ++ Unsuitable1).
+
+unsuitable_1([{L,#b_blk{is=[#b_set{op=Op}|_]}}|Bs]) ->
+ Unsuitable = case Op of
+ bs_extract -> true;
+ bs_put -> true;
+ {float,_} -> true;
+ landingpad -> true;
+ peek_message -> true;
+ wait_timeout -> true;
+ _ -> false
+ end,
+ case Unsuitable of
+ true ->
+ [L|unsuitable_1(Bs)];
+ false ->
+ unsuitable_1(Bs)
+ end;
+unsuitable_1([{_,#b_blk{}}|Bs]) ->
+ unsuitable_1(Bs);
+unsuitable_1([]) -> [].
+
+unsuitable_recv([{L,#b_blk{is=[#b_set{op=Op}|_]}}|Bs], Blocks, Predecessors) ->
+ Ls = case Op of
+ remove_message ->
+ unsuitable_loop(L, Blocks, Predecessors);
+ recv_next ->
+ unsuitable_loop(L, Blocks, Predecessors);
+ _ ->
+ []
+ end,
+ Ls ++ unsuitable_recv(Bs, Blocks, Predecessors);
+unsuitable_recv([_|Bs], Blocks, Predecessors) ->
+ unsuitable_recv(Bs, Blocks, Predecessors);
+unsuitable_recv([], _, _) -> [].
+
+unsuitable_loop(L, Blocks, Predecessors) ->
+ unsuitable_loop(L, Blocks, Predecessors, []).
+
+unsuitable_loop(L, Blocks, Predecessors, Acc) ->
+ Ps = maps:get(L, Predecessors),
+ unsuitable_loop_1(Ps, Blocks, Predecessors, Acc).
+
+unsuitable_loop_1([P|Ps], Blocks, Predecessors, Acc0) ->
+ case maps:get(P, Blocks) of
+ #b_blk{is=[#b_set{op=peek_message}|_]} ->
+ unsuitable_loop_1(Ps, Blocks, Predecessors, Acc0);
+ #b_blk{} ->
+ case ordsets:is_element(P, Acc0) of
+ false ->
+ Acc1 = ordsets:add_element(P, Acc0),
+ Acc = unsuitable_loop(P, Blocks, Predecessors, Acc1),
+ unsuitable_loop_1(Ps, Blocks, Predecessors, Acc);
+ true ->
+ unsuitable_loop_1(Ps, Blocks, Predecessors, Acc0)
+ end
+ end;
+unsuitable_loop_1([], _, _, Acc) -> Acc.
+
+%% new_def_locations([{Variable,[UsedInBlock]}|Vs], Defs, Dominators) ->
+%% [{Variable,NewDefinitionBlock}]
+%% Calculate new locations for get_tuple_element instructions. For each
+%% variable, the new location is a block that dominates all uses of
+%% variable and as near to the uses of as possible. If no such block
+%% distinct from the block where the instruction currently is, the
+%% variable will not be included in the result list.
+
+new_def_locations([{V,UsedIn}|Vs], Defs, Dom) ->
+ DefIn = maps:get(V, Defs),
+ case common_dom(UsedIn, DefIn, Dom) of
+ [] ->
+ new_def_locations(Vs, Defs, Dom);
+ [_|_]=BetterDef ->
+ L = most_dominated(BetterDef, Dom),
+ [{V,L}|new_def_locations(Vs, Defs, Dom)]
+ end;
+new_def_locations([], _, _) -> [].
+
+common_dom([L|Ls], DefIn, Dom) ->
+ DomBy0 = maps:get(L, Dom),
+ DomBy = ordsets:subtract(DomBy0, maps:get(DefIn, Dom)),
+ common_dom_1(Ls, Dom, DomBy).
+
+common_dom_1(_, _, []) ->
+ [];
+common_dom_1([L|Ls], Dom, [_|_]=DomBy0) ->
+ DomBy1 = maps:get(L, Dom),
+ DomBy = ordsets:intersection(DomBy0, DomBy1),
+ common_dom_1(Ls, Dom, DomBy);
+common_dom_1([], _, DomBy) -> DomBy.
+
+most_dominated([L|Ls], Dom) ->
+ most_dominated(Ls, L, maps:get(L, Dom), Dom).
+
+most_dominated([L|Ls], L0, DomBy, Dom) ->
+ case member(L, DomBy) of
+ true ->
+ most_dominated(Ls, L0, DomBy, Dom);
+ false ->
+ most_dominated(Ls, L, maps:get(L, Dom), Dom)
+ end;
+most_dominated([], L, _, _) -> L.
+
+
+%% Move get_tuple_element instructions to their new locations.
+
+move_defs(V, From, To, Blocks) ->
+ #{From:=FromBlk0,To:=ToBlk0} = Blocks,
+ {Def,FromBlk} = remove_def(V, FromBlk0),
+ try insert_def(V, Def, ToBlk0) of
+ ToBlk ->
+ %%io:format("~p: ~p => ~p\n", [V,From,To]),
+ Blocks#{From:=FromBlk,To:=ToBlk}
+ catch
+ throw:not_possible ->
+ Blocks
+ end.
+
+remove_def(V, #b_blk{is=Is0}=Blk) ->
+ {Def,Is} = remove_def_is(Is0, V, []),
+ {Def,Blk#b_blk{is=Is}}.
+
+remove_def_is([#b_set{dst=Dst}=Def|Is], Dst, Acc) ->
+ {Def,reverse(Acc, Is)};
+remove_def_is([I|Is], Dst, Acc) ->
+ remove_def_is(Is, Dst, [I|Acc]).
+
+insert_def(V, Def, #b_blk{is=Is0}=Blk) ->
+ Is = insert_def_is(Is0, V, Def),
+ Blk#b_blk{is=Is}.
+
+insert_def_is([#b_set{op=phi}=I|Is], V, Def) ->
+ case member(V, beam_ssa:used(I)) of
+ true ->
+ throw(not_possible);
+ false ->
+ [I|insert_def_is(Is, V, Def)]
+ end;
+insert_def_is([#b_set{op=Op}=I|Is]=Is0, V, Def) ->
+ Action0 = case Op of
+ call -> beyond;
+ 'catch_end' -> beyond;
+ set_tuple_element -> beyond;
+ timeout -> beyond;
+ _ -> here
+ end,
+ Action = case Is of
+ [#b_set{op=succeeded}|_] -> here;
+ _ -> Action0
+ end,
+ case Action of
+ beyond ->
+ case member(V, beam_ssa:used(I)) of
+ true ->
+ %% The variable is used by this instruction. We must
+ %% place the definition before this instruction.
+ [Def|Is0];
+ false ->
+ %% Place it beyond the current instruction.
+ [I|insert_def_is(Is, V, Def)]
+ end;
+ here ->
+ [Def|Is0]
+ end;
+insert_def_is([], _V, Def) ->
+ [Def].
+
+
+%%%
+%%% Common utilities.
+%%%
+
+rel2fam(S0) ->
+ S1 = sofs:relation(S0),
+ S = sofs:rel2fam(S1),
+ sofs:to_external(S).
+
+sub(I, Sub) ->
+ beam_ssa:normalize(sub_1(I, Sub)).
+
+sub_1(#b_set{op=phi,args=Args}=I, Sub) ->
+ I#b_set{args=[{sub_arg(A, Sub),P} || {A,P} <- Args]};
+sub_1(#b_set{args=Args}=I, Sub) ->
+ I#b_set{args=[sub_arg(A, Sub) || A <- Args]};
+sub_1(#b_br{bool=#b_var{}=Old}=Br, Sub) ->
+ New = sub_arg(Old, Sub),
+ Br#b_br{bool=New};
+sub_1(#b_switch{arg=#b_var{}=Old}=Sw, Sub) ->
+ New = sub_arg(Old, Sub),
+ Sw#b_switch{arg=New};
+sub_1(#b_ret{arg=#b_var{}=Old}=Ret, Sub) ->
+ New = sub_arg(Old, Sub),
+ Ret#b_ret{arg=New};
+sub_1(Last, _) -> Last.
+
+sub_arg(#b_remote{mod=Mod,name=Name}=Rem, Sub) ->
+ Rem#b_remote{mod=sub_arg(Mod, Sub),name=sub_arg(Name, Sub)};
+sub_arg(Old, Sub) ->
+ case Sub of
+ #{Old:=New} -> New;
+ #{} -> Old
+ end.
diff --git a/lib/compiler/src/beam_ssa_pp.erl b/lib/compiler/src/beam_ssa_pp.erl
new file mode 100644
index 0000000000..34ac08b32e
--- /dev/null
+++ b/lib/compiler/src/beam_ssa_pp.erl
@@ -0,0 +1,238 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(beam_ssa_pp).
+
+-export([format_function/1,format_instr/1,format_var/1]).
+
+-include("beam_ssa.hrl").
+
+-spec format_function(beam_ssa:b_function()) -> iolist().
+
+format_function(#b_function{anno=Anno0,args=Args,
+ bs=Blocks,cnt=Counter}) ->
+ #{func_info:={M,F,_}} = Anno0,
+ Anno = maps:without([func_info,location,live_intervals,registers], Anno0),
+ FuncAnno = case Anno0 of
+ #{live_intervals:=Intervals} ->
+ Anno0#{live_intervals:=maps:from_list(Intervals)};
+ #{} ->
+ Anno0
+ end,
+ ReachableBlocks = beam_ssa:rpo(Blocks),
+ All = maps:keys(Blocks),
+ Unreachable = ordsets:subtract(ordsets:from_list(All),
+ ordsets:from_list(ReachableBlocks)),
+ [case Anno0 of
+ #{location:={Filename,Line}} ->
+ io_lib:format("%% ~ts:~p\n", [Filename,Line]);
+ #{} ->
+ []
+ end,
+ io_lib:format("%% Counter = ~p\n", [Counter]),
+ [format_anno(Key, Value) ||
+ {Key,Value} <- lists:sort(maps:to_list(Anno))],
+ io_lib:format("function ~p:~p(~ts) {\n", [M,F,format_args(Args, FuncAnno)]),
+ [format_live_interval(Var, FuncAnno) || Var <- Args],
+ format_blocks(ReachableBlocks, Blocks, FuncAnno),
+ case Unreachable of
+ [] ->
+ [];
+ [_|_] ->
+ ["\n%% Unreachable blocks\n\n",
+ format_blocks(Unreachable, Blocks, FuncAnno)]
+ end,
+
+ "}\n"].
+
+
+-spec format_instr(beam_ssa:b_set()) -> iolist().
+
+format_instr(#b_set{}=I) ->
+ Cs = lists:flatten(format_instr(I#b_set{anno=#{}}, #{}, true)),
+ string:trim(Cs, leading);
+format_instr(I0) ->
+ I = setelement(2, I0, #{}),
+ Cs = lists:flatten(format_terminator(I, #{})),
+ string:trim(Cs, both).
+
+-spec format_var(beam_ssa:b_var()) -> iolist().
+
+format_var(V) ->
+ Cs = lists:flatten(format_var(V, #{})),
+ string:trim(Cs, leading).
+
+%%%
+%%% Local functions.
+%%%
+
+format_anno(Key, Map) when is_map(Map) ->
+ Sorted = lists:sort(maps:to_list(Map)),
+ [io_lib:format("%% ~s:\n", [Key]),
+ [io_lib:format("%% ~w => ~w\n", [K,V]) || {K,V} <- Sorted]];
+format_anno(Key, Value) ->
+ io_lib:format("%% ~s: ~p\n", [Key,Value]).
+
+format_blocks(Ls, Blocks, Anno) ->
+ PP = [format_block(L, Blocks, Anno) || L <- Ls],
+ lists:join($\n, PP).
+
+format_block(L, Blocks, FuncAnno) ->
+ #b_blk{anno=Anno,is=Is,last=Last} = maps:get(L, Blocks),
+ [case map_size(Anno) of
+ 0 -> [];
+ _ -> io_lib:format("%% ~p\n", [Anno])
+ end,
+ io_lib:format("~p:", [L]),
+ format_instrs(Is, FuncAnno, true),
+ $\n,
+ format_terminator(Last, FuncAnno)].
+
+format_instrs([I|Is], FuncAnno, First) ->
+ [$\n,
+ format_instr(I, FuncAnno, First),
+ format_instrs(Is, FuncAnno, false)];
+format_instrs([], _FuncAnno, _First) ->
+ [].
+
+format_instr(#b_set{anno=Anno,op=Op,dst=Dst,args=Args},
+ FuncAnno, First) ->
+ AnnoStr = format_anno(Anno),
+ LiveIntervalStr = format_live_interval(Dst, FuncAnno),
+ [if
+ First ->
+ [];
+ AnnoStr =/= []; LiveIntervalStr =/= [] ->
+ $\n;
+ true ->
+ []
+ end,
+ AnnoStr,
+ LiveIntervalStr,
+ io_lib:format(" ~s~ts = ~ts", [format_i_number(Anno),
+ format_var(Dst, FuncAnno),
+ format_op(Op)]),
+ case Args of
+ [] ->
+ [];
+ [_|_] ->
+ io_lib:format(" ~ts", [format_args(Args, FuncAnno)])
+ end].
+
+format_i_number(#{n:=N}) ->
+ io_lib:format("[~p] ", [N]);
+format_i_number(#{}) -> [].
+
+format_terminator(#b_br{anno=A,bool=#b_literal{val=true},succ=Lbl}, _) ->
+ io_lib:format(" ~sbr label ~p\n", [format_i_number(A),Lbl]);
+format_terminator(#b_br{anno=A,bool=#b_literal{val=false},fail=Lbl}, _) ->
+ io_lib:format(" ~sbr label ~p\n", [format_i_number(A),Lbl]);
+format_terminator(#b_br{anno=A,bool=Bool,succ=Succ,fail=Fail}, FuncAnno) ->
+ io_lib:format(" ~sbr ~ts, label ~p, label ~p\n",
+ [format_i_number(A),format_arg(Bool, FuncAnno),Succ,Fail]);
+format_terminator(#b_switch{anno=A,arg=Arg,fail=Fail,list=List}, FuncAnno) ->
+ io_lib:format(" ~sswitch ~ts, label ~p, ~ts\n",
+ [format_i_number(A),format_arg(Arg, FuncAnno),Fail,
+ format_list(List,FuncAnno)]);
+format_terminator(#b_ret{anno=A,arg=Arg}, FuncAnno) ->
+ io_lib:format(" ~sret ~ts\n", [format_i_number(A),format_arg(Arg, FuncAnno)]).
+
+format_op({Prefix,Name}) ->
+ io_lib:format("~p:~p", [Prefix,Name]);
+format_op(Name) ->
+ io_lib:format("~p", [Name]).
+
+format_register(#b_var{}=V, #{registers:=Regs}) ->
+ {Tag,N} = maps:get(V, Regs),
+ io_lib:format("~p~p", [Tag,N]);
+format_register(_, #{}) -> "".
+
+format_var(Var, FuncAnno) ->
+ VarString = format_var_1(Var),
+ case format_register(Var, FuncAnno) of
+ [] -> VarString;
+ [_|_]=Reg -> [Reg,$/,VarString]
+ end.
+
+format_var_1(#b_var{name={Name,Uniq}}) ->
+ if
+ is_atom(Name) ->
+ io_lib:format("~ts:~p", [Name,Uniq]);
+ is_integer(Name) ->
+ io_lib:format("_~p:~p", [Name,Uniq])
+ end;
+format_var_1(#b_var{name=Name}) when is_atom(Name) ->
+ atom_to_list(Name);
+format_var_1(#b_var{name=Name}) when is_integer(Name) ->
+ "_"++integer_to_list(Name).
+
+format_args(Args, FuncAnno) ->
+ Ss = [format_arg(Arg, FuncAnno) || Arg <- Args],
+ lists:join(", ", Ss).
+
+format_arg(#b_var{}=Arg, FuncAnno) ->
+ format_var(Arg, FuncAnno);
+format_arg(#b_literal{val=Val}, _FuncAnno) ->
+ io_lib:format("literal ~p", [Val]);
+format_arg(#b_remote{mod=Mod,name=Name,arity=Arity}, FuncAnno) ->
+ io_lib:format("remote (~ts):(~ts)/~p",
+ [format_arg(Mod, FuncAnno),format_arg(Name, FuncAnno),Arity]);
+format_arg(#b_local{name=Name,arity=Arity}, FuncAnno) ->
+ io_lib:format("local ~ts/~p", [format_arg(Name, FuncAnno),Arity]);
+format_arg({Value,Label}, FuncAnno) when is_integer(Label) ->
+ io_lib:format("{ ~ts, ~p }", [format_arg(Value, FuncAnno),Label]);
+format_arg(Other, _) ->
+ io_lib:format("*** ~p ***", [Other]).
+
+format_list(List, FuncAnno) ->
+ Ss = [io_lib:format("{ ~ts, ~ts }", [format_arg(Val, FuncAnno),format_label(L)]) ||
+ {Val,L} <- List],
+ io_lib:format("[ ~ts ]", [lists:join(", ", Ss)]).
+
+format_label(L) ->
+ ["label ",integer_to_list(L)].
+
+format_anno(#{n:=_}=Anno) ->
+ format_anno(maps:remove(n, Anno));
+format_anno(#{location:={File,Line}}=Anno0) ->
+ Anno = maps:remove(location, Anno0),
+ [io_lib:format(" %% ~ts:~p\n", [File,Line])|format_anno_1(Anno)];
+format_anno(Anno) ->
+ format_anno_1(Anno).
+
+format_anno_1(Anno) ->
+ case map_size(Anno) of
+ 0 ->
+ [];
+ _ ->
+ [io_lib:format(" %% Anno: ~p\n", [Anno])]
+ end.
+
+format_live_interval(#b_var{}=Dst, #{live_intervals:=Intervals}) ->
+ case Intervals of
+ #{Dst:=Rs0} ->
+ Rs1 = [io_lib:format("~p..~p", [Start,End]) ||
+ {Start,End} <- Rs0],
+ Rs = lists:join(" ", Rs1),
+ io_lib:format(" %% ~ts: ~s\n", [format_var_1(Dst),Rs]);
+ #{} ->
+ []
+ end;
+format_live_interval(_, _) -> [].
+
diff --git a/lib/compiler/src/beam_ssa_pre_codegen.erl b/lib/compiler/src/beam_ssa_pre_codegen.erl
new file mode 100644
index 0000000000..ca3b792ed6
--- /dev/null
+++ b/lib/compiler/src/beam_ssa_pre_codegen.erl
@@ -0,0 +1,2433 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+%% Purpose: Prepare for code generation, including register allocation.
+%%
+%% The output of this compiler pass is still in the SSA format, but
+%% it has been annotated and transformed to help the code generator.
+%%
+%% * Some instructions are translated to other instructions closer to
+%% the BEAM instructions. For example, the binary matching
+%% instructions are transformed from the optimization-friendly
+%% internal format to instruction more similar to the actual BEAM
+%% instructions.
+%%
+%% * Blocks that will need an instruction for allocating a stack frame
+%% are annotated with a {frame_size,Size} annotation.
+%%
+%% * 'copy' instructions are added for all variables that need
+%% to be saved to the stack frame. Additional 'copy' instructions
+%% can be added as an optimization to reuse y registers (see
+%% the copy_retval sub pass).
+%%
+%% * Each function is annotated with a {register,RegisterMap}
+%% annotation that maps each variable to a BEAM register. The linear
+%% scan algorithm is used to allocate registers.
+%%
+%% There are four kind of registers. x, y, fr (floating point register),
+%% and z. A variable will be allocated to a z register if it is only
+%% used by the instruction following the instruction that defines the
+%% the variable. The code generator will typically combine those
+%% instructions to a test instruction. z registers are also used for
+%% some instructions that don't have a return value.
+%%
+%% References:
+%%
+%% [1] H. Mössenböck and M. Pfeiffer. Linear scan register allocation
+%% in the context of SSA form and register constraints. In Proceedings
+%% of the International Conference on Compiler Construction, pages
+%% 229–246. LNCS 2304, Springer-Verlag, 2002.
+%%
+%% [2] C. Wimmer and H. Mössenböck. Optimized interval splitting in a
+%% linear scan register allocator. In Proceedings of the ACM/USENIX
+%% International Conference on Virtual Execution Environments, pages
+%% 132–141. ACM Press, 2005.
+%%
+%% [3] C. Wimmer and M. Franz. Linear Scan Register Allocation on SSA
+%% Form. In Proceedings of the International Symposium on Code
+%% Generation and Optimization, pages 170-179. ACM Press, 2010.
+%%
+
+-module(beam_ssa_pre_codegen).
+
+-export([module/2]).
+
+-include("beam_ssa.hrl").
+
+-import(lists, [all/2,any/2,append/1,duplicate/2,
+ foldl/3,last/1,map/2,member/2,partition/2,
+ reverse/1,reverse/2,sort/1,zip/2]).
+
+-spec module(beam_ssa:b_module(), [compile:option()]) ->
+ {'ok',beam_ssa:b_module()}.
+
+module(#b_module{body=Fs0}=Module, Opts) ->
+ FixTuples = proplists:get_bool(no_put_tuple2, Opts),
+ ExtraAnnos = proplists:get_bool(dprecg, Opts),
+ Ps = passes(FixTuples, ExtraAnnos),
+ Fs = functions(Fs0, Ps),
+ {ok,Module#b_module{body=Fs}}.
+
+functions([F|Fs], Ps) ->
+ [function(F, Ps)|functions(Fs, Ps)];
+functions([], _Ps) -> [].
+
+-type b_var() :: beam_ssa:b_var().
+-type var_name() :: beam_ssa:var_name().
+-type instr_number() :: pos_integer().
+-type range() :: {instr_number(),instr_number()}.
+-type reg_num() :: beam_asm:reg_num().
+-type xreg() :: {'x',reg_num()}.
+-type yreg() :: {'y',reg_num()}.
+-type ypool() :: {'y',beam_ssa:label()}.
+-type reservation() :: 'fr' | {'prefer',xreg()} | 'x' | {'x',xreg()} |
+ ypool() | {yreg(),ypool()} | 'z'.
+-type ssa_register() :: beam_ssa_codegen:ssa_register().
+
+-define(TC(Body), tc(fun() -> Body end, ?FILE, ?LINE)).
+-record(st, {ssa :: beam_ssa:block_map(),
+ args :: [b_var()],
+ cnt :: beam_ssa:label(),
+ frames=[] :: [beam_ssa:label()],
+ intervals=[] :: [{b_var(),[range()]}],
+ aliases=[] :: [{b_var(),b_var()}],
+ res=[] :: [{b_var(),reservation()}] | #{b_var():=reservation()},
+ regs=#{} :: #{b_var():=ssa_register()},
+ extra_annos=[] :: [{atom(),term()}]
+ }).
+-define(PASS(N), {N,fun N/1}).
+
+passes(FixTuples, ExtraAnnos) ->
+ Ps = [?PASS(assert_no_critical_edges),
+
+ %% Preliminaries.
+ ?PASS(fix_bs),
+ ?PASS(sanitize),
+ case FixTuples of
+ false -> ignore;
+ true -> ?PASS(fix_tuples)
+ end,
+ ?PASS(place_frames),
+ ?PASS(fix_receives),
+
+ %% Find and reserve Y registers.
+ ?PASS(find_yregs),
+ ?PASS(reserve_yregs),
+
+ %% Improve reuse of Y registers to potentially
+ %% reduce the size of the stack frame.
+ ?PASS(copy_retval),
+ ?PASS(opt_get_list),
+
+ %% Calculate live intervals.
+ ?PASS(number_instructions),
+ ?PASS(live_intervals),
+ ?PASS(remove_unsuitable_aliases),
+ ?PASS(reserve_regs),
+ ?PASS(merge_intervals),
+
+ %% If needed for a .precg file, save the live intervals
+ %% so they can be included in an annotation.
+ case ExtraAnnos of
+ false -> ignore;
+ true -> ?PASS(save_live_intervals)
+ end,
+
+ %% Allocate registers.
+ ?PASS(linear_scan),
+ ?PASS(fix_aliased_regs),
+ ?PASS(frame_size),
+ ?PASS(turn_yregs)],
+ [P || P <- Ps, P =/= ignore].
+
+function(#b_function{anno=Anno,args=Args,bs=Blocks0,cnt=Count0}=F0, Ps) ->
+ try
+ St0 = #st{ssa=Blocks0,args=Args,cnt=Count0},
+ St = compile:run_sub_passes(Ps, St0),
+ #st{ssa=Blocks,cnt=Count,regs=Regs,extra_annos=ExtraAnnos} = St,
+ F1 = add_extra_annos(F0, ExtraAnnos),
+ F = beam_ssa:add_anno(registers, Regs, F1),
+ F#b_function{bs=Blocks,cnt=Count}
+ catch
+ Class:Error:Stack ->
+ #{func_info:={_,Name,Arity}} = Anno,
+ io:fwrite("Function: ~w/~w\n", [Name,Arity]),
+ erlang:raise(Class, Error, Stack)
+ end.
+
+save_live_intervals(#st{intervals=Intervals}=St) ->
+ St#st{extra_annos=[{live_intervals,Intervals}]}.
+
+fix_aliased_regs(#st{aliases=Aliases,regs=Regs}=St) ->
+ St#st{regs=fix_aliased_regs(Aliases, Regs)}.
+
+fix_aliased_regs([{Alias,V}|Aliases], Regs) ->
+ #{V:=Reg} = Regs,
+ fix_aliased_regs(Aliases, Regs#{Alias=>Reg});
+fix_aliased_regs([], Regs) -> Regs.
+
+%% Add extra annotations when a .precg listing file is being produced.
+add_extra_annos(F, Annos) ->
+ foldl(fun({Name,Value}, Acc) ->
+ beam_ssa:add_anno(Name, Value, Acc)
+ end, F, Annos).
+
+%% assert_no_critical_edges(St0) -> St.
+%% The code generator will not work if there are critial edges.
+%% Abort if any critical edges are found.
+
+assert_no_critical_edges(#st{ssa=Blocks}=St) ->
+ F = fun assert_no_ces/3,
+ beam_ssa:fold_rpo(F, Blocks, Blocks),
+ St.
+
+assert_no_ces(_, #b_blk{is=[#b_set{op=phi,args=[_,_]=Phis}|_]}, Blocks) ->
+ %% This block has multiple predecessors. Make sure that none
+ %% of the precessors have more than one successor.
+ true = all(fun({_,P}) ->
+ length(beam_ssa:successors(P, Blocks)) =:= 1
+ end, Phis), %Assertion.
+ Blocks;
+assert_no_ces(_, _, Blocks) -> Blocks.
+
+%% fix_bs(St0) -> St.
+%% Fix up the binary matching instructions:
+%%
+%% * Insert bs_save and bs_restore instructions where needed.
+%%
+%% * Combine bs_match and bs_extract instructions to bs_get
+%% instructions.
+
+fix_bs(#st{ssa=Blocks,cnt=Count0}=St) ->
+ F = fun(#b_set{op=bs_start_match,dst=Dst}, A) ->
+ %% Mark the root of the match context list.
+ [{Dst,{context,Dst}}|A];
+ (#b_set{op=bs_match,dst=Dst,args=[_,ParentCtx|_]}, A) ->
+ %% Link this match context the previous match context.
+ [{Dst,ParentCtx}|A];
+ (_, A) ->
+ A
+ end,
+ case beam_ssa:fold_instrs_rpo(F, [0], [],Blocks) of
+ [] ->
+ %% No binary matching in this function.
+ St;
+ [_|_]=M ->
+ CtxChain = maps:from_list(M),
+ Linear0 = beam_ssa:linearize(Blocks),
+
+ %% Insert bs_save / bs_restore instructions where needed.
+ {Linear1,Count} = bs_save_restore(Linear0, CtxChain, Count0),
+
+ %% Rename instructions.
+ Linear = bs_instrs(Linear1, CtxChain, []),
+
+ St#st{ssa=maps:from_list(Linear),cnt=Count}
+ end.
+
+
+%% Insert bs_save and bs_restore instructions as needed.
+
+bs_save_restore(Linear0, CtxChain, Count0) ->
+ Rs0 = bs_restores(Linear0, CtxChain, #{}, #{}),
+ Rs = maps:values(Rs0),
+ S0 = sofs:relation(Rs, [{context,save_point}]),
+ S1 = sofs:relation_to_family(S0),
+ S = sofs:to_external(S1),
+ Slots = make_save_point_dict(S, []),
+ {Saves,Count1} = make_save_map(Rs, Slots, Count0, []),
+ {Restores,Count} = make_restore_map(maps:to_list(Rs0), Slots, Count1, []),
+
+ %% Now insert all saves and restores.
+ {bs_insert(Linear0, Saves, Restores, Slots),Count}.
+
+make_save_map([{Ctx,Save}=Ps|T], Slots, Count, Acc) ->
+ Ignored = #b_var{name={'@ssa_ignored',Count}},
+ case make_slot(Ps, Slots) of
+ #b_literal{val=start} ->
+ make_save_map(T, Slots, Count, Acc);
+ Slot ->
+ I = #b_set{op=bs_save,dst=Ignored,args=[Ctx,Slot]},
+ make_save_map(T, Slots, Count+1, [{Save,I}|Acc])
+ end;
+make_save_map([], _, Count, Acc) ->
+ {maps:from_list(Acc),Count}.
+
+make_restore_map([{Bef,{Ctx,_}=Ps}|T], Slots, Count, Acc) ->
+ Ignored = #b_var{name={'@ssa_ignored',Count}},
+ I = #b_set{op=bs_restore,dst=Ignored,args=[Ctx,make_slot(Ps, Slots)]},
+ make_restore_map(T, Slots, Count+1, [{Bef,I}|Acc]);
+make_restore_map([], _, Count, Acc) ->
+ {maps:from_list(Acc),Count}.
+
+make_slot({Same,Same}, _Slots) ->
+ #b_literal{val=start};
+make_slot({_,_}=Ps, Slots) ->
+ #b_literal{val=maps:get(Ps, Slots)}.
+
+make_save_point_dict([{Ctx,Pts}|T], Acc0) ->
+ Acc = make_save_point_dict_1(Pts, Ctx, 0, Acc0),
+ make_save_point_dict(T, Acc);
+make_save_point_dict([], Acc) ->
+ maps:from_list(Acc).
+
+make_save_point_dict_1([Ctx|T], Ctx, I, Acc) ->
+ %% Special {atom,start} save point. Does not need a
+ %% bs_save instruction.
+ make_save_point_dict_1(T, Ctx, I, Acc);
+make_save_point_dict_1([H|T], Ctx, I, Acc) ->
+ make_save_point_dict_1(T, Ctx, I+1, [{{Ctx,H},I}|Acc]);
+make_save_point_dict_1([], Ctx, I, Acc) ->
+ [{Ctx,I}|Acc].
+
+bs_restores([{L,#b_blk{is=Is,last=Last}}|Bs], CtxChain, D0, Rs0) ->
+ FPos = case D0 of
+ #{L:=Pos0} -> Pos0;
+ #{} -> #{}
+ end,
+ {SPos,Rs} = bs_restores_is(Is, CtxChain, FPos, Rs0),
+ D = bs_update_successors(Last, SPos, FPos, D0),
+ bs_restores(Bs, CtxChain, D, Rs);
+bs_restores([], _, _, Rs) -> Rs.
+
+bs_update_successors(#b_br{succ=Succ,fail=Fail}, SPos, FPos, D) ->
+ join_positions([{Succ,SPos},{Fail,FPos}], D);
+bs_update_successors(#b_switch{fail=Fail,list=List}, SPos, FPos, D) ->
+ SPos = FPos, %Assertion.
+ Update = [{L,SPos} || {_,L} <- List] ++ [{Fail,SPos}],
+ join_positions(Update, D);
+bs_update_successors(#b_ret{}, _, _, D) -> D.
+
+join_positions([{L,MapPos0}|T], D) ->
+ case D of
+ #{L:=MapPos0} ->
+ %% Same map.
+ join_positions(T, D);
+ #{L:=MapPos1} ->
+ %% Different maps.
+ MapPos = join_positions_1(MapPos0, MapPos1),
+ join_positions(T, D#{L:=MapPos});
+ #{} ->
+ join_positions(T, D#{L=>MapPos0})
+ end;
+join_positions([], D) -> D.
+
+join_positions_1(MapPos0, MapPos1) ->
+ MapPos2 = maps:map(fun(Start, Pos) ->
+ case MapPos0 of
+ #{Start:=Pos} -> Pos;
+ #{Start:=_} -> unknown;
+ #{} -> Pos
+ end
+ end, MapPos1),
+ maps:merge(MapPos0, MapPos2).
+
+bs_restores_is([#b_set{op=bs_start_match,dst=Start}|Is],
+ CtxChain, PosMap0, Rs) ->
+ PosMap = PosMap0#{Start=>Start},
+ bs_restores_is(Is, CtxChain, PosMap, Rs);
+bs_restores_is([#b_set{op=bs_match,dst=NewPos,args=Args}=I|Is],
+ CtxChain, PosMap0, Rs0) ->
+ Start = bs_subst_ctx(NewPos, CtxChain),
+ [_,FromPos|_] = Args,
+ case PosMap0 of
+ #{Start:=FromPos} ->
+ %% Same position, no restore needed.
+ PosMap = case bs_match_type(I) of
+ plain ->
+ %% Update position to new position.
+ PosMap0#{Start:=NewPos};
+ _ ->
+ %% Position will not change (test_unit
+ %% instruction or no instruction at
+ %% all).
+ PosMap0#{Start:=FromPos}
+ end,
+ bs_restores_is(Is, CtxChain, PosMap, Rs0);
+ #{Start:=_} ->
+ %% Different positions, might need a restore instruction.
+ case bs_match_type(I) of
+ none ->
+ %% The tail test will be optimized away.
+ %% No need to do a restore.
+ PosMap = PosMap0#{Start:=FromPos},
+ bs_restores_is(Is, CtxChain, PosMap, Rs0);
+ test_unit ->
+ %% This match instruction will be replaced by
+ %% a test_unit instruction. We will need a
+ %% restore. The new position will be the position
+ %% restored to (NOT NewPos).
+ PosMap = PosMap0#{Start:=FromPos},
+ Rs = Rs0#{NewPos=>{Start,FromPos}},
+ bs_restores_is(Is, CtxChain, PosMap, Rs);
+ plain ->
+ %% Match or skip. Position will be changed.
+ PosMap = PosMap0#{Start:=NewPos},
+ Rs = Rs0#{NewPos=>{Start,FromPos}},
+ bs_restores_is(Is, CtxChain, PosMap, Rs)
+ end
+ end;
+bs_restores_is([#b_set{op=bs_extract,args=[FromPos|_]}|Is],
+ CtxChain, PosMap, Rs) ->
+ Start = bs_subst_ctx(FromPos, CtxChain),
+ #{Start:=FromPos} = PosMap, %Assertion.
+ bs_restores_is(Is, CtxChain, PosMap, Rs);
+bs_restores_is([#b_set{op=Op,dst=Dst,args=Args}|Is],
+ CtxChain, PosMap0, Rs0)
+ when Op =:= bs_test_tail;
+ Op =:= call ->
+ {Rs,PosMap} = bs_restore_args(Args, PosMap0, CtxChain, Dst, Rs0),
+ bs_restores_is(Is, CtxChain, PosMap, Rs);
+bs_restores_is([_|Is], CtxChain, PosMap, Rs) ->
+ bs_restores_is(Is, CtxChain, PosMap, Rs);
+bs_restores_is([], _CtxChain, PosMap, Rs) ->
+ {PosMap,Rs}.
+
+
+bs_match_type(#b_set{args=[#b_literal{val=skip},_Ctx,
+ #b_literal{val=binary},_Flags,
+ #b_literal{val=all},#b_literal{val=U}]}) ->
+ case U of
+ 1 -> none;
+ _ -> test_unit
+ end;
+bs_match_type(_) ->
+ plain.
+
+bs_restore_args([#b_var{}=Arg|Args], PosMap0, CtxChain, Dst, Rs0) ->
+ Start = bs_subst_ctx(Arg, CtxChain),
+ case PosMap0 of
+ #{Start:=Arg} ->
+ %% Same position, no restore needed.
+ bs_restore_args(Args, PosMap0, CtxChain, Dst, Rs0);
+ #{Start:=_} ->
+ %% Different positions, need a restore instruction.
+ PosMap = PosMap0#{Start:=Arg},
+ Rs = Rs0#{Dst=>{Start,Arg}},
+ bs_restore_args(Args, PosMap, CtxChain, Dst, Rs);
+ #{} ->
+ %% Not a match context.
+ bs_restore_args(Args, PosMap0, CtxChain, Dst, Rs0)
+ end;
+bs_restore_args([_|Args], PosMap, CtxChain, Dst, Rs) ->
+ bs_restore_args(Args, PosMap, CtxChain, Dst, Rs);
+bs_restore_args([], PosMap, _CtxChain, _Dst, Rs) ->
+ {Rs,PosMap}.
+
+%% Insert all bs_save and bs_restore instructions.
+
+bs_insert([{L,#b_blk{is=Is0}=Blk}|Bs0], Saves, Restores, Slots) ->
+ Is = bs_insert_is_1(Is0, Restores, Slots),
+ Bs = bs_insert_saves(Is, Bs0, Saves),
+ [{L,Blk#b_blk{is=Is}}|bs_insert(Bs, Saves, Restores, Slots)];
+bs_insert([], _, _, _) -> [].
+
+bs_insert_is_1([#b_set{op=Op,dst=Dst}=I0|Is], Restores, Slots) ->
+ if
+ Op =:= bs_test_tail;
+ Op =:= bs_match;
+ Op =:= call ->
+ Rs = case Restores of
+ #{Dst:=R} -> [R];
+ #{} -> []
+ end,
+ Rs ++ [I0|bs_insert_is_1(Is, Restores, Slots)];
+ Op =:= bs_start_match ->
+ NumSlots = case Slots of
+ #{Dst:=NumSlots0} -> NumSlots0;
+ #{} -> 0
+ end,
+ I = beam_ssa:add_anno(num_slots, NumSlots, I0),
+ [I|bs_insert_is_1(Is, Restores, Slots)];
+ true ->
+ [I0|bs_insert_is_1(Is, Restores, Slots)]
+ end;
+bs_insert_is_1([], _, _) -> [].
+
+bs_insert_saves([#b_set{dst=Dst}|Is], Bs, Saves) ->
+ case Saves of
+ #{Dst:=S} ->
+ bs_insert_save(S, Bs);
+ #{} ->
+ bs_insert_saves(Is, Bs, Saves)
+ end;
+bs_insert_saves([], Bs, _) -> Bs.
+
+bs_insert_save(Save, [{L,#b_blk{is=Is0}=Blk}|Bs]) ->
+ Is = case Is0 of
+ [#b_set{op=bs_extract}=Ex|Is1] ->
+ [Ex,Save|Is1];
+ _ ->
+ [Save|Is0]
+ end,
+ [{L,Blk#b_blk{is=Is}}|Bs].
+
+%% Translate bs_match instructions to bs_get, bs_match_string,
+%% or bs_skip. Also rename match context variables to use the
+%% variable assigned to by the start_match instruction.
+
+bs_instrs([{L,#b_blk{is=Is0}=Blk}|Bs], CtxChain, Acc0) ->
+ case bs_instrs_is(Is0, CtxChain, []) of
+ [#b_set{op=bs_extract,dst=Dst,args=[Ctx]}|Is] ->
+ %% Drop this instruction. Rewrite the corresponding
+ %% bs_match instruction in the previous block to
+ %% a bs_get instruction.
+ Acc = bs_combine(Dst, Ctx, Acc0),
+ bs_instrs(Bs, CtxChain, [{L,Blk#b_blk{is=Is}}|Acc]);
+ Is ->
+ bs_instrs(Bs, CtxChain, [{L,Blk#b_blk{is=Is}}|Acc0])
+ end;
+bs_instrs([], _, Acc) ->
+ reverse(Acc).
+
+bs_instrs_is([#b_set{op=Op,args=Args0}=I0|Is], CtxChain, Acc) ->
+ Args = [bs_subst_ctx(A, CtxChain) || A <- Args0],
+ I1 = I0#b_set{args=Args},
+ I = case {Op,Args} of
+ {bs_match,[#b_literal{val=skip},Ctx,Type|As]} ->
+ I1#b_set{op=bs_skip,args=[Type,Ctx|As]};
+ {bs_match,[#b_literal{val=string},Ctx|As]} ->
+ I1#b_set{op=bs_match_string,args=[Ctx|As]};
+ {_,_} ->
+ I1
+ end,
+ bs_instrs_is(Is, CtxChain, [I|Acc]);
+bs_instrs_is([], _, Acc) ->
+ reverse(Acc).
+
+%% Combine a bs_match instruction with the destination register
+%% taken from a bs_extract instruction.
+
+bs_combine(Dst, Ctx, [{L,#b_blk{is=Is0}=Blk}|Acc]) ->
+ [#b_set{}=Succeeded,
+ #b_set{op=bs_match,args=[Type,_|As]}=BsMatch|Is1] = reverse(Is0),
+ Is = reverse(Is1, [BsMatch#b_set{op=bs_get,dst=Dst,args=[Type,Ctx|As]},
+ Succeeded#b_set{args=[Dst]}]),
+ [{L,Blk#b_blk{is=Is}}|Acc].
+
+bs_subst_ctx(#b_var{}=Var, CtxChain) ->
+ case CtxChain of
+ #{Var:={context,Ctx}} ->
+ Ctx;
+ #{Var:=ParentCtx} ->
+ bs_subst_ctx(ParentCtx, CtxChain);
+ #{} ->
+ %% Not a match context variable.
+ Var
+ end;
+bs_subst_ctx(Other, _CtxChain) ->
+ Other.
+
+%% sanitize(St0) -> St.
+%% Remove constructs that can cause problems later:
+%%
+%% * Unreachable blocks may cause problems for determination of
+%% dominators.
+%%
+%% * Some instructions (such as get_hd) don't accept literal
+%% arguments. Evaluate the instructions and remove them.
+
+sanitize(#st{ssa=Blocks0,cnt=Count0}=St) ->
+ Ls = beam_ssa:rpo(Blocks0),
+ {Blocks,Count} = sanitize(Ls, Count0, Blocks0, #{}),
+ St#st{ssa=Blocks,cnt=Count}.
+
+sanitize([L|Ls], Count0, Blocks0, Values0) ->
+ #b_blk{is=Is0} = Blk0 = maps:get(L, Blocks0),
+ case sanitize_is(Is0, Count0, Values0, false, []) of
+ no_change ->
+ sanitize(Ls, Count0, Blocks0, Values0);
+ {Is,Count,Values} ->
+ Blk = Blk0#b_blk{is=Is},
+ Blocks = Blocks0#{L:=Blk},
+ sanitize(Ls, Count, Blocks, Values)
+ end;
+sanitize([], Count, Blocks0, Values) ->
+ Blocks = if
+ map_size(Values) =:= 0 ->
+ Blocks0;
+ true ->
+ beam_ssa:rename_vars(Values, [0], Blocks0)
+ end,
+
+ %% Unreachable blocks can cause problems for the dominator calculations.
+ Ls = beam_ssa:rpo(Blocks),
+ Reachable = gb_sets:from_list(Ls),
+ {case map_size(Blocks) =:= gb_sets:size(Reachable) of
+ true -> Blocks;
+ false -> remove_unreachable(Ls, Blocks, Reachable, [])
+ end,Count}.
+
+sanitize_is([#b_set{op=get_map_element,
+ args=[#b_literal{}=Map,Key]}=I0|Is],
+ Count0, Values, _Changed, Acc) ->
+ {MapVar,Count} = new_var('@ssa_map', Count0),
+ I = I0#b_set{args=[MapVar,Key]},
+ Copy = #b_set{op=copy,dst=MapVar,args=[Map]},
+ sanitize_is(Is, Count, Values, true, [I,Copy|Acc]);
+sanitize_is([#b_set{op=Op,dst=Dst,args=Args0}=I0|Is0],
+ Count, Values, Changed, Acc) ->
+ Args = map(fun(Var) ->
+ case Values of
+ #{Var:=New} -> New;
+ #{} -> Var
+ end
+ end, Args0),
+ case sanitize_instr(Op, Args, I0) of
+ {value,Value0} ->
+ Value = #b_literal{val=Value0},
+ sanitize_is(Is0, Count, Values#{Dst=>Value}, true, Acc);
+ {ok,I} ->
+ sanitize_is(Is0, Count, Values, true, [I|Acc]);
+ ok ->
+ sanitize_is(Is0, Count, Values, Changed, [I0|Acc])
+ end;
+sanitize_is([], Count, Values, Changed, Acc) ->
+ case Changed of
+ true ->
+ {reverse(Acc),Count,Values};
+ false ->
+ no_change
+ end.
+
+sanitize_instr({bif,Bif}, [#b_literal{val=Lit}], _I) ->
+ case erl_bifs:is_pure(erlang, Bif, 1) of
+ false ->
+ ok;
+ true ->
+ try
+ {value,erlang:Bif(Lit)}
+ catch
+ error:_ ->
+ ok
+ end
+ end;
+sanitize_instr({bif,Bif}, [#b_literal{val=Lit1},#b_literal{val=Lit2}], _I) ->
+ true = erl_bifs:is_pure(erlang, Bif, 2), %Assertion.
+ try
+ {value,erlang:Bif(Lit1, Lit2)}
+ catch
+ error:_ ->
+ ok
+ end;
+sanitize_instr(get_hd, [#b_literal{val=[Hd|_]}], _I) ->
+ {value,Hd};
+sanitize_instr(get_tl, [#b_literal{val=[_|Tl]}], _I) ->
+ {value,Tl};
+sanitize_instr(get_tuple_element, [#b_literal{val=T},
+ #b_literal{val=I}], _I)
+ when I < tuple_size(T) ->
+ {value,element(I+1, T)};
+sanitize_instr(is_nonempty_list, [#b_literal{val=Lit}], _I) ->
+ {value,case Lit of
+ [_|_] -> true;
+ _ -> false
+ end};
+sanitize_instr(is_tagged_tuple, [#b_literal{val=Tuple},
+ #b_literal{val=Arity},
+ #b_literal{val=Tag}], _I)
+ when is_integer(Arity), is_atom(Tag) ->
+ if
+ tuple_size(Tuple) =:= Arity, element(1, Tuple) =:= Tag ->
+ {value,true};
+ true ->
+ {value,false}
+ end;
+sanitize_instr(bs_init, [#b_literal{val=new},#b_literal{val=Sz}|_], I0) ->
+ if
+ is_integer(Sz), Sz >= 0 -> ok;
+ true -> {ok,sanitize_badarg(I0)}
+ end;
+sanitize_instr(bs_init, [#b_literal{val=append},_,#b_literal{val=Sz}|_], I0) ->
+ if
+ is_integer(Sz), Sz >= 0 -> ok;
+ true -> {ok,sanitize_badarg(I0)}
+ end;
+sanitize_instr(succeeded, [#b_literal{}], _I) ->
+ {value,true};
+sanitize_instr(_, _, _) -> ok.
+
+sanitize_badarg(I) ->
+ Func = #b_remote{mod=#b_literal{val=erlang},
+ name=#b_literal{val=error},arity=1},
+ I#b_set{op=call,args=[Func,#b_literal{val=badarg}]}.
+
+remove_unreachable([L|Ls], Blocks, Reachable, Acc) ->
+ #b_blk{is=Is0} = Blk0 = maps:get(L, Blocks),
+ case split_phis(Is0) of
+ {[_|_]=Phis,Rest} ->
+ Is = [prune_phi(Phi, Reachable) || Phi <- Phis] ++ Rest,
+ Blk = Blk0#b_blk{is=Is},
+ remove_unreachable(Ls, Blocks, Reachable, [{L,Blk}|Acc]);
+ {[],_} ->
+ remove_unreachable(Ls, Blocks, Reachable, [{L,Blk0}|Acc])
+ end;
+remove_unreachable([], _Blocks, _, Acc) ->
+ maps:from_list(Acc).
+
+prune_phi(#b_set{args=Args0}=Phi, Reachable) ->
+ Args = [A || {_,Pred}=A <- Args0,
+ gb_sets:is_element(Pred, Reachable)],
+ Phi#b_set{args=Args}.
+
+%%%
+%%% Fix tuples.
+%%%
+
+%% fix_tuples(St0) -> St.
+%% If compatibility with a previous version of Erlang has been
+%% requested, tuple creation must be split into two instruction to
+%% mirror the the way tuples are created in BEAM prior to OTP 22.
+%% Each put_tuple instruction is split into put_tuple_arity followed
+%% by put_tuple_elements.
+
+fix_tuples(#st{ssa=Blocks0,cnt=Count0}=St) ->
+ F = fun (#b_set{op=put_tuple,args=Args}=Put, C0) ->
+ Arity = #b_literal{val=length(Args)},
+ {Ignore,C} = new_var('@ssa_ignore', C0),
+ {[Put#b_set{op=put_tuple_arity,args=[Arity]},
+ #b_set{dst=Ignore,op=put_tuple_elements,args=Args}],C};
+ (I, C) -> {[I],C}
+ end,
+ {Blocks,Count} = beam_ssa:flatmapfold_instrs_rpo(F, [0], Count0, Blocks0),
+ St#st{ssa=Blocks,cnt=Count}.
+
+%%%
+%%% Find out where frames should be placed.
+%%%
+
+%% place_frames(St0) -> St.
+%% Return a list of the labels for the blocks that need stack frame
+%% allocation instructions.
+%%
+%% This function attempts to place stack frames as tight as possible
+%% around the code, to avoid building stack frames for code paths
+%% that don't need one.
+%%
+%% Stack frames are placed in blocks that dominate all of their
+%% descendants. That guarantees that the deallocation instructions
+%% cannot be reached from other execution paths that didn't set up
+%% a stack frame or set up a stack frame with a different size.
+
+place_frames(#st{ssa=Blocks}=St) ->
+ Doms = beam_ssa:dominators(Blocks),
+ Ls = beam_ssa:rpo(Blocks),
+ Tried = gb_sets:empty(),
+ Frames0 = [],
+ {Frames,_} = place_frames_1(Ls, Blocks, Doms, Tried, Frames0),
+ St#st{frames=Frames}.
+
+place_frames_1([L|Ls], Blocks, Doms, Tried0, Frames0) ->
+ Blk = maps:get(L, Blocks),
+ case need_frame(Blk) of
+ true ->
+ %% This block needs a frame. Try to place it here.
+ {Frames,Tried} = do_place_frame(L, Blocks, Doms, Tried0, Frames0),
+
+ %% Successfully placed. Try to place more frames in descendants
+ %% that are not dominated by this block.
+ place_frames_1(Ls, Blocks, Doms, Tried, Frames);
+ false ->
+ try
+ place_frames_1(Ls, Blocks, Doms, Tried0, Frames0)
+ catch
+ throw:{need_frame,For,Tried1}=Reason ->
+ %% An descendant block needs a stack frame. Try to
+ %% place it here.
+ case is_dominated_by(For, L, Doms) of
+ true ->
+ %% Try to place a frame here.
+ {Frames,Tried} = do_place_frame(L, Blocks, Doms,
+ Tried1, Frames0),
+ place_frames_1(Ls, Blocks, Doms, Tried, Frames);
+ false ->
+ %% Wrong place. This block does not dominate
+ %% the block that needs the frame. Pass it on
+ %% to our ancestors.
+ throw(Reason)
+ end
+ end
+ end;
+place_frames_1([], _, _, Tried, Frames) ->
+ {Frames,Tried}.
+
+%% do_place_frame(Label, Blocks, Dominators, Tried0, Frames0) -> {Frames,Tried}.
+%% Try to place a frame in this block. This function returns
+%% successfully if it either succeds at placing a frame in this
+%% block, if an ancestor that dominates this block has already placed
+%% a frame, or if we have already tried to put a frame in this block.
+%%
+%% An {need_frame,Label,Tried} exception will be thrown if this block
+%% block is not suitable for having a stack frame (i.e. it does not dominate
+%% all of its descendants). The exception means that an ancestor will have to
+%% place the frame needed by this block.
+
+do_place_frame(L, Blocks, Doms, Tried0, Frames) ->
+ case gb_sets:is_element(L, Tried0) of
+ true ->
+ %% We have already tried to put a frame in this block.
+ {Frames,Tried0};
+ false ->
+ %% Try to place a frame in this block.
+ Tried = gb_sets:insert(L, Tried0),
+ case place_frame_here(L, Blocks, Doms, Frames) of
+ yes ->
+ %% We need a frame and it is safe to place it here.
+ {[L|Frames],Tried};
+ no ->
+ %% An ancestor has a frame. Not needed.
+ {Frames,Tried};
+ ancestor ->
+ %% This block does not dominate all of its
+ %% descendants. We must place the frame in
+ %% an ancestor.
+ throw({need_frame,L,Tried})
+ end
+ end.
+
+%% place_frame_here(Label, Blocks, Doms, Frames) -> no|yes|ancestor.
+%% Determine whether a frame should be placed in block Label.
+
+place_frame_here(L, Blocks, Doms, Frames) ->
+ B0 = any(fun(DomBy) ->
+ is_dominated_by(L, DomBy, Doms)
+ end, Frames),
+ case B0 of
+ true ->
+ %% This block is dominated by an ancestor block that
+ %% defines a frame. Not needed/allowed to put a frame
+ %% here.
+ no;
+ false ->
+ %% No frame in any ancestor. We need a frame.
+ %% Now check whether the frame can be placed here.
+ %% If this block dominates all of its descendants
+ %% and the predecessors of any phi nodes it can be
+ %% placed here.
+ Descendants = beam_ssa:rpo([L], Blocks),
+ PhiPredecessors = phi_predecessors(L, Blocks),
+ MustDominate = ordsets:from_list(PhiPredecessors ++ Descendants),
+ Dominates = all(fun(?BADARG_BLOCK) ->
+ %% This block defines no variables and calls
+ %% erlang:error(badarg). It does not matter
+ %% whether L dominates ?BADARG_BLOCK or not;
+ %% it is still safe to put the frame in L.
+ true;
+ (Bl) ->
+ is_dominated_by(Bl, L, Doms)
+ end, MustDominate),
+
+ %% Also, this block must not be a loop header.
+ IsLoopHeader = is_loop_header(L, Blocks),
+ case Dominates andalso not IsLoopHeader of
+ true -> yes;
+ false -> ancestor
+ end
+ end.
+
+%% phi_predecessors(Label, Blocks) ->
+%% Return all predecessors referenced in phi nodes.
+
+phi_predecessors(L, Blocks) ->
+ #b_blk{is=Is} = maps:get(L, Blocks),
+ [P || #b_set{op=phi,args=Args} <- Is, {_,P} <- Args].
+
+%% is_dominated_by(Label, DominatedBy, Dominators) -> true|false.
+%% Test whether block Label is dominated by block DominatedBy.
+
+is_dominated_by(L, DomBy, Doms) ->
+ DominatedBy = maps:get(L, Doms),
+ ordsets:is_element(DomBy, DominatedBy).
+
+%% need_frame(#b_blk{}) -> true|false.
+%% Test whether any of the instructions in the block requires a stack frame.
+
+need_frame(#b_blk{is=Is,last=#b_ret{arg=Ret}}) ->
+ need_frame_1(Is, {return,Ret});
+need_frame(#b_blk{is=Is}) ->
+ need_frame_1(Is, body).
+
+need_frame_1([#b_set{op=make_fun,dst=Fun}|Is], {return,_}=Context) ->
+ %% Since make_fun clobbers X registers, a stack frame is needed if
+ %% any of the following instructions use any other variable than
+ %% the one holding the reference to the created fun.
+ need_frame_1(Is, Context) orelse
+ case beam_ssa:used(#b_blk{is=Is,last=#b_ret{arg=Fun}}) of
+ [Fun] -> false;
+ [_|_] -> true
+ end;
+need_frame_1([#b_set{op=new_try_tag}|_], _) ->
+ true;
+need_frame_1([#b_set{op=call,dst=Val}]=Is, {return,Ret}) ->
+ if
+ Val =:= Ret -> need_frame_1(Is, tail);
+ true -> need_frame_1(Is, body)
+ end;
+need_frame_1([#b_set{op=call,args=[Func|_]}|Is], Context) ->
+ case Func of
+ #b_remote{mod=#b_literal{val=Mod},
+ name=#b_literal{val=Name},
+ arity=Arity} ->
+ case erl_bifs:is_exit_bif(Mod, Name, Arity) of
+ true ->
+ false;
+ false ->
+ Context =:= body orelse
+ Is =/= [] orelse
+ is_trap_bif(Mod, Name, Arity)
+ end;
+ #b_remote{} ->
+ %% This is an apply(), which always needs a frame.
+ true;
+ #b_var{} ->
+ %% A fun call always needs a frame.
+ true;
+ _ ->
+ Context =:= body orelse Is =/= []
+ end;
+need_frame_1([I|Is], Context) ->
+ beam_ssa:clobbers_xregs(I) orelse need_frame_1(Is, Context);
+need_frame_1([], _) -> false.
+
+%% is_trap_bif(Mod, Name, Arity) -> true|false.
+%% Test whether we need a stack frame for this BIF.
+
+is_trap_bif(erlang, '!', 2) -> true;
+is_trap_bif(erlang, link, 1) -> true;
+is_trap_bif(erlang, unlink, 1) -> true;
+is_trap_bif(erlang, monitor_node, 2) -> true;
+is_trap_bif(erlang, group_leader, 2) -> true;
+is_trap_bif(erlang, exit, 2) -> true;
+is_trap_bif(_, _, _) -> false.
+
+%%%
+%%% Fix variables used in matching in receive.
+%%%
+%%% The loop_rec/2 instruction may return a reference to a
+%%% message outside of any heap or heap fragment. If the message
+%%% does not match, it is not allowed to store any reference to
+%%% the message (or part of the message) on the stack. If we do,
+%%% the message will be corrupted if there happens to be a GC.
+%%%
+%%% Here we make sure to introduce copies of variables that are
+%%% matched out and subsequently used after the remove_message/0
+%%% instructions. That will make sure that only X registers are
+%%% used during matching.
+%%%
+%%% Depending on where variables are defined and used, they must
+%%% be handled in two different ways.
+%%%
+%%% Variables that are always defined in the receive (before branching
+%%% out into the different clauses of the receive) and used after the
+%%% receive must be handled in the following way: Before each
+%%% remove_message instruction, each such variable must be copied, and
+%%% all variables must be consolidated using a phi node in the
+%%% common exit block for the receive.
+%%%
+%%% Variables that are matched out and used in the same clause
+%%% need copy instructions before the remove_message instruction
+%%% in that clause.
+%%%
+
+fix_receives(#st{ssa=Blocks0,cnt=Count0}=St) ->
+ {Blocks,Count} = fix_receives_1(maps:to_list(Blocks0),
+ Blocks0, Count0),
+ St#st{ssa=Blocks,cnt=Count}.
+
+fix_receives_1([{L,Blk}|Ls], Blocks0, Count0) ->
+ case Blk of
+ #b_blk{is=[#b_set{op=peek_message}|_]} ->
+ Rm = find_rm_blocks(L, Blocks0),
+ LoopExit = find_loop_exit(Rm, Blocks0),
+ Defs0 = beam_ssa:def([L], Blocks0),
+ CommonUsed = recv_common(Defs0, LoopExit, Blocks0),
+ {Blocks1,Count1} = recv_fix_common(CommonUsed, LoopExit, Rm,
+ Blocks0, Count0),
+ Defs = ordsets:subtract(Defs0, CommonUsed),
+ {Blocks,Count} = fix_receive(Rm, Defs, Blocks1, Count1),
+ fix_receives_1(Ls, Blocks, Count);
+ #b_blk{} ->
+ fix_receives_1(Ls, Blocks0, Count0)
+ end;
+fix_receives_1([], Blocks, Count) ->
+ {Blocks,Count}.
+
+recv_common(_Defs, none, _Blocks) ->
+ %% There is no common exit block because receive is used
+ %% in the tail position of a function.
+ [];
+recv_common(Defs, Exit, Blocks) ->
+ {ExitDefs,ExitUsed} = beam_ssa:def_used([Exit], Blocks),
+ Def = ordsets:subtract(Defs, ExitDefs),
+ ordsets:intersection(Def, ExitUsed).
+
+%% recv_fix_common([CommonVar], LoopExit, [RemoveMessageLabel],
+%% Blocks0, Count0) -> {Blocks,Count}.
+%% Handle variables alwys defined in a receive and used
+%% in the exit block following the receive.
+
+recv_fix_common([Msg0|T], Exit, Rm, Blocks0, Count0) ->
+ {Msg,Count1} = new_var('@recv', Count0),
+ Blocks1 = beam_ssa:rename_vars(#{Msg0=>Msg}, [Exit], Blocks0),
+ N = length(Rm),
+ {MsgVars,Count} = new_vars(duplicate(N, '@recv'), Count1),
+ PhiArgs = fix_exit_phi_args(MsgVars, Rm, Exit, Blocks1),
+ Phi = #b_set{op=phi,dst=Msg,args=PhiArgs},
+ ExitBlk0 = maps:get(Exit, Blocks1),
+ ExitBlk = ExitBlk0#b_blk{is=[Phi|ExitBlk0#b_blk.is]},
+ Blocks2 = Blocks1#{Exit:=ExitBlk},
+ Blocks = recv_fix_common_1(MsgVars, Rm, Msg0, Blocks2),
+ recv_fix_common(T, Exit, Rm, Blocks, Count);
+recv_fix_common([], _, _, Blocks, Count) ->
+ {Blocks,Count}.
+
+recv_fix_common_1([V|Vs], [Rm|Rms], Msg, Blocks0) ->
+ Ren = #{Msg=>V},
+ Blocks1 = beam_ssa:rename_vars(Ren, [Rm], Blocks0),
+ #b_blk{is=Is0} = Blk0 = maps:get(Rm, Blocks1),
+ Copy = #b_set{op=copy,dst=V,args=[Msg]},
+ Is = insert_after_phis(Is0, [Copy]),
+ Blk = Blk0#b_blk{is=Is},
+ Blocks = Blocks1#{Rm:=Blk},
+ recv_fix_common_1(Vs, Rms, Msg, Blocks);
+recv_fix_common_1([], [], _Msg, Blocks) -> Blocks.
+
+fix_exit_phi_args([V|Vs], [Rm|Rms], Exit, Blocks) ->
+ Path = beam_ssa:rpo([Rm], Blocks),
+ Preds = exit_predecessors(Path, Exit, Blocks),
+ [{V,Pred} || Pred <- Preds] ++ fix_exit_phi_args(Vs, Rms, Exit, Blocks);
+fix_exit_phi_args([], [], _, _) -> [].
+
+exit_predecessors([L|Ls], Exit, Blocks) ->
+ Blk = map_get(L, Blocks),
+ case member(Exit, beam_ssa:successors(Blk)) of
+ true ->
+ [L|exit_predecessors(Ls, Exit, Blocks)];
+ false ->
+ exit_predecessors(Ls, Exit, Blocks)
+ end;
+exit_predecessors([], _Exit, _Blocks) -> [].
+
+%% fix_receive([Label], Defs, Blocks0, Count0) -> {Blocks,Count}.
+%% Add a copy instruction for all variables that are matched out and
+%% later used within a clause of the receive.
+
+fix_receive([L|Ls], Defs, Blocks0, Count0) ->
+ {RmDefs,Used0} = beam_ssa:def_used([L], Blocks0),
+ Def = ordsets:subtract(Defs, RmDefs),
+ Used = ordsets:intersection(Def, Used0),
+ {NewVars,Count} = new_vars([Base || #b_var{name=Base} <- Used], Count0),
+ Ren = zip(Used, NewVars),
+ Blocks1 = beam_ssa:rename_vars(Ren, [L], Blocks0),
+ #b_blk{is=Is0} = Blk1 = maps:get(L, Blocks1),
+ CopyIs = [#b_set{op=copy,dst=New,args=[Old]} || {Old,New} <- Ren],
+ Is = insert_after_phis(Is0, CopyIs),
+ Blk = Blk1#b_blk{is=Is},
+ Blocks = maps:put(L, Blk, Blocks1),
+ fix_receive(Ls, Defs, Blocks, Count);
+fix_receive([], _Defs, Blocks, Count) ->
+ {Blocks,Count}.
+
+%% find_loop_exit([Label], Blocks) -> Label | none.
+%% Find the block to which control is transferred when the
+%% the receive loop is exited.
+
+find_loop_exit([L1,L2|_Ls], Blocks) ->
+ Path1 = beam_ssa:rpo([L1], Blocks),
+ Path2 = beam_ssa:rpo([L2], Blocks),
+ find_loop_exit_1(reverse(Path1), reverse(Path2), none);
+find_loop_exit(_, _) -> none.
+
+find_loop_exit_1([H|T1], [H|T2], _) ->
+ find_loop_exit_1(T1, T2, H);
+find_loop_exit_1(_, _, Exit) -> Exit.
+
+%% find_rm_blocks(StartLabel, Blocks) -> [Label].
+%% Find all blocks that start with remove_message within the receive
+%% loop whose peek_message label is StartLabel.
+
+find_rm_blocks(L, Blocks) ->
+ Seen = gb_sets:singleton(L),
+ Blk = maps:get(L, Blocks),
+ Succ = beam_ssa:successors(Blk),
+ find_rm_blocks_1(Succ, Seen, Blocks).
+
+find_rm_blocks_1([L|Ls], Seen0, Blocks) ->
+ case gb_sets:is_member(L, Seen0) of
+ true ->
+ find_rm_blocks_1(Ls, Seen0, Blocks);
+ false ->
+ Seen = gb_sets:insert(L, Seen0),
+ Blk = maps:get(L, Blocks),
+ case find_rm_act(Blk#b_blk.is) of
+ prune ->
+ %% Looping back. Don't look at any successors.
+ find_rm_blocks_1(Ls, Seen, Blocks);
+ continue ->
+ %% Neutral block. Do nothing here, but look at
+ %% all successors.
+ Succ = beam_ssa:successors(Blk),
+ find_rm_blocks_1(Succ++Ls, Seen, Blocks);
+ found ->
+ %% Found remove_message instruction.
+ [L|find_rm_blocks_1(Ls, Seen, Blocks)]
+ end
+ end;
+find_rm_blocks_1([], _, _) -> [].
+
+find_rm_act([#b_set{op=Op}|Is]) ->
+ case Op of
+ remove_message -> found;
+ peek_message -> prune;
+ recv_next -> prune;
+ wait_timeout -> prune;
+ wait -> prune;
+ _ -> find_rm_act(Is)
+ end;
+find_rm_act([]) ->
+ continue.
+
+%%%
+%%% Find out which variables need to be stored in Y registers.
+%%%
+
+-record(dk, {d :: ordsets:ordset(var_name()),
+ k :: ordsets:ordset(var_name())
+ }).
+
+%% find_yregs(St0) -> St.
+%% Find all variables that must be stored in Y registers. Annotate
+%% the blocks that allocate frames with the set of Y registers
+%% used within that stack frame.
+%%
+%% Basically, we following all execution paths starting from a block
+%% that allocates a frame, keeping track of of all defined registers
+%% and all registers killed by an instruction that clobbers X
+%% registers. For every use of a variable, we check if if it is in
+%% the set of killed variables; if it is, it must be stored in an Y
+%% register.
+
+find_yregs(#st{frames=[]}=St) ->
+ St;
+find_yregs(#st{frames=[_|_]=Frames,args=Args,ssa=Blocks0}=St) ->
+ FrameDefs = find_defs(Frames, Blocks0, [V || #b_var{}=V <- Args]),
+ Blocks = find_yregs_1(FrameDefs, Blocks0),
+ St#st{ssa=Blocks}.
+
+find_yregs_1([{F,Defs}|Fs], Blocks0) ->
+ DK = #dk{d=Defs,k=[]},
+ D0 = #{F=>DK},
+ Ls = beam_ssa:rpo([F], Blocks0),
+ Yregs0 = [],
+ Yregs = find_yregs_2(Ls, Blocks0, D0, Yregs0),
+ Blk0 = maps:get(F, Blocks0),
+ Blk = beam_ssa:add_anno(yregs, Yregs, Blk0),
+ Blocks = Blocks0#{F:=Blk},
+ find_yregs_1(Fs, Blocks);
+find_yregs_1([], Blocks) -> Blocks.
+
+find_yregs_2([L|Ls], Blocks0, D0, Yregs0) ->
+ Blk0 = maps:get(L, Blocks0),
+ #b_blk{is=Is,last=Last} = Blk0,
+ Ys0 = maps:get(L, D0),
+ {Yregs1,Ys} = find_yregs_is(Is, Ys0, Yregs0),
+ Yregs = find_yregs_terminator(Last, Ys, Yregs1),
+ Successors = beam_ssa:successors(Blk0),
+ D = find_update_succ(Successors, Ys, D0),
+ find_yregs_2(Ls, Blocks0, D, Yregs);
+find_yregs_2([], _Blocks, _D, Yregs) -> Yregs.
+
+find_defs(Frames, Blocks, Defs) ->
+ Seen = gb_sets:empty(),
+ FramesSet = gb_sets:from_list(Frames),
+ {FrameDefs,_} = find_defs_1([0], Blocks, FramesSet, Seen, Defs, []),
+ FrameDefs.
+
+find_defs_1([L|Ls], Blocks, Frames, Seen0, Defs0, Acc0) ->
+ case gb_sets:is_member(L, Frames) of
+ true ->
+ OrderedDefs = ordsets:from_list(Defs0),
+ find_defs_1(Ls, Blocks, Frames, Seen0, Defs0,
+ [{L,OrderedDefs}|Acc0]);
+ false ->
+ case gb_sets:is_member(L, Seen0) of
+ true ->
+ find_defs_1(Ls, Blocks, Frames, Seen0, Defs0, Acc0);
+ false ->
+ Seen1 = gb_sets:insert(L, Seen0),
+ {Acc,Seen} = find_defs_1(Ls, Blocks, Frames, Seen1, Defs0, Acc0),
+ #b_blk{is=Is} = Blk = maps:get(L, Blocks),
+ Defs = find_defs_is(Is, Defs0),
+ Successors = beam_ssa:successors(Blk),
+ find_defs_1(Successors, Blocks, Frames, Seen, Defs, Acc)
+ end
+ end;
+find_defs_1([], _, _, Seen, _, Acc) ->
+ {Acc,Seen}.
+
+find_defs_is([#b_set{dst=Dst}|Is], Acc) ->
+ find_defs_is(Is, [Dst|Acc]);
+find_defs_is([], Acc) -> Acc.
+
+find_update_succ([S|Ss], #dk{d=Defs0,k=Killed0}=DK0, D0) ->
+ case D0 of
+ #{S:=#dk{d=Defs1,k=Killed1}} ->
+ Defs = ordsets:intersection(Defs0, Defs1),
+ Killed = ordsets:union(Killed0, Killed1),
+ DK = #dk{d=Defs,k=Killed},
+ D = maps:put(S, DK, D0),
+ find_update_succ(Ss, DK0, D);
+ #{} ->
+ D = maps:put(S, DK0, D0),
+ find_update_succ(Ss, DK0, D)
+ end;
+find_update_succ([], _, D) -> D.
+
+find_yregs_is([#b_set{dst=Dst}=I|Is], #dk{d=Defs0,k=Killed0}=Ys, Yregs0) ->
+ Used = beam_ssa:used(I),
+ Yregs1 = ordsets:intersection(Used, Killed0),
+ Yregs = ordsets:union(Yregs0, Yregs1),
+ case beam_ssa:clobbers_xregs(I) of
+ false ->
+ Defs = ordsets:add_element(Dst, Defs0),
+ find_yregs_is(Is, Ys#dk{d=Defs}, Yregs);
+ true ->
+ Killed = ordsets:union(Defs0, Killed0),
+ Defs = [Dst],
+ find_yregs_is(Is, Ys#dk{d=Defs,k=Killed}, Yregs)
+ end;
+find_yregs_is([], Ys, Yregs) -> {Yregs,Ys}.
+
+find_yregs_terminator(Terminator, #dk{k=Killed}, Yregs0) ->
+ Used = beam_ssa:used(Terminator),
+ Yregs = ordsets:intersection(Used, Killed),
+ ordsets:union(Yregs0, Yregs).
+
+%%%
+%%% Try to reduce the size of the stack frame, by adding an explicit
+%%% 'copy' instructions for return values from 'call' and 'make_fun' that
+%%% need to be saved in Y registers. Here is an example to show
+%%% how that's useful. First, here is the Erlang code:
+%%%
+%%% f(Pid) ->
+%%% Res = foo(42),
+%%% _ = node(Pid),
+%%% bar(),
+%%% Res.
+%%%
+%%% Compiled to SSA format, the main part of the code looks like this:
+%%%
+%%% 0:
+%%% Res = call local literal foo/1, literal 42
+%%% _1 = bif:node Pid
+%%% @ssa_bool = succeeded _1
+%%% br @ssa_bool, label 3, label 1
+%%% 3:
+%%% @ssa_ignored = call local literal bar/0
+%%% ret Res
+%%%
+%%% It can be seen that the variables Pid and Res must be saved in Y
+%%% registers in order to survive the function calls. A previous sub
+%%% pass has inserted a 'copy' instruction to save the value of the
+%%% variable Pid:
+%%%
+%%% 0:
+%%% Pid:4 = copy Pid
+%%% Res = call local literal foo/1, literal 42
+%%% _1 = bif:node Pid:4
+%%% @ssa_bool = succeeded _1
+%%% br @ssa_bool, label 3, label 1
+%%%
+%%% 3:
+%%% @ssa_ignored = call local literal bar/0
+%%% ret Res
+%%%
+%%% The Res and Pid:4 variables must be assigned to different Y registers
+%%% because they are live at the same time. copy_retval() inserts a
+%%% 'copy' instruction to copy Res to a new variable:
+%%%
+%%% 0:
+%%% Pid:4 = copy Pid
+%%% Res:6 = call local literal foo/1, literal 42
+%%% _1 = bif:node Pid:4
+%%% @ssa_bool = succeeded _1
+%%% br @ssa_bool, label 3, label 1
+%%%
+%%% 3:
+%%% Res = copy Res:6
+%%% @ssa_ignored = call local literal bar/0
+%%% ret Res
+%%%
+%%% The new variable Res:6 is used to capture the return value from the call.
+%%% The variables Pid:4 and Res are no longer live at the same time, so they
+%%% can be assigned to the same Y register.
+%%%
+
+copy_retval(#st{frames=Frames,ssa=Blocks0,cnt=Count0}=St) ->
+ {Blocks,Count} = copy_retval_1(Frames, Blocks0, Count0),
+ St#st{ssa=Blocks,cnt=Count}.
+
+copy_retval_1([F|Fs], Blocks0, Count0) ->
+ #b_blk{anno=#{yregs:=Yregs0},is=Is} = maps:get(F, Blocks0),
+ Yregs1 = gb_sets:from_list(Yregs0),
+ Yregs = collect_yregs(Is, Yregs1),
+ Ls = beam_ssa:rpo([F], Blocks0),
+ {Blocks,Count} = copy_retval_2(Ls, Yregs, none, Blocks0, Count0),
+ copy_retval_1(Fs, Blocks, Count);
+copy_retval_1([], Blocks, Count) ->
+ {Blocks,Count}.
+
+collect_yregs([#b_set{op=copy,dst=Y,args=[#b_var{}=X]}|Is],
+ Yregs0) ->
+ true = gb_sets:is_member(X, Yregs0), %Assertion.
+ Yregs = gb_sets:insert(Y, gb_sets:delete(X, Yregs0)),
+ collect_yregs(Is, Yregs);
+collect_yregs([#b_set{}|Is], Yregs) ->
+ collect_yregs(Is, Yregs);
+collect_yregs([], Yregs) -> Yregs.
+
+copy_retval_2([L|Ls], Yregs, Copy0, Blocks0, Count0) ->
+ #b_blk{is=Is0,last=Last} = Blk = maps:get(L, Blocks0),
+ RC = case {Last,Ls} of
+ {#b_br{succ=Succ,fail=?BADARG_BLOCK},[Succ|_]} ->
+ true;
+ {_,_} ->
+ false
+ end,
+ case copy_retval_is(Is0, RC, Yregs, Copy0, Count0, []) of
+ {Is,Count} ->
+ case Copy0 =:= none andalso Count0 =:= Count of
+ true ->
+ copy_retval_2(Ls, Yregs, none, Blocks0, Count0);
+ false ->
+ Blocks = Blocks0#{L=>Blk#b_blk{is=Is}},
+ copy_retval_2(Ls, Yregs, none, Blocks, Count)
+ end;
+ {Is,Count,Copy} ->
+ Blocks = Blocks0#{L=>Blk#b_blk{is=Is}},
+ copy_retval_2(Ls, Yregs, Copy, Blocks, Count)
+ end;
+copy_retval_2([], _Yregs, none, Blocks, Count) ->
+ {Blocks,Count}.
+
+copy_retval_is([#b_set{op=put_tuple_elements,args=Args0}=I0], false, _Yregs,
+ Copy, Count, Acc) ->
+ I = I0#b_set{args=copy_sub_args(Args0, Copy)},
+ {reverse(Acc, [I|acc_copy([], Copy)]),Count};
+copy_retval_is([#b_set{}]=Is, false, _Yregs, Copy, Count, Acc) ->
+ {reverse(Acc, acc_copy(Is, Copy)),Count};
+copy_retval_is([#b_set{},#b_set{op=succeeded}]=Is, false, _Yregs, Copy, Count, Acc) ->
+ {reverse(Acc, acc_copy(Is, Copy)),Count};
+copy_retval_is([#b_set{op=Op,dst=#b_var{name=RetName}=Dst}=I0|Is], RC, Yregs,
+ Copy0, Count0, Acc0) when Op =:= call; Op =:= make_fun ->
+ {I1,Count1,Acc} = place_retval_copy(I0, Yregs, Copy0, Count0, Acc0),
+ case gb_sets:is_member(Dst, Yregs) of
+ true ->
+ {NewVar,Count} = new_var(RetName, Count1),
+ Copy = #b_set{op=copy,dst=Dst,args=[NewVar]},
+ I = I1#b_set{dst=NewVar},
+ copy_retval_is(Is, RC, Yregs, Copy, Count, [I|Acc]);
+ false ->
+ copy_retval_is(Is, RC, Yregs, none, Count1, [I1|Acc])
+ end;
+copy_retval_is([#b_set{args=Args0}=I0|Is], RC, Yregs, Copy, Count, Acc) ->
+ I = I0#b_set{args=copy_sub_args(Args0, Copy)},
+ case beam_ssa:clobbers_xregs(I) of
+ true ->
+ copy_retval_is(Is, RC, Yregs, none, Count, [I|acc_copy(Acc, Copy)]);
+ false ->
+ copy_retval_is(Is, RC, Yregs, Copy, Count, [I|Acc])
+ end;
+copy_retval_is([], RC, _, Copy, Count, Acc) ->
+ case {Copy,RC} of
+ {none,_} ->
+ {reverse(Acc),Count};
+ {#b_set{},true} ->
+ {reverse(Acc),Count,Copy};
+ {#b_set{},false} ->
+ {reverse(Acc, [Copy]),Count}
+ end.
+
+%%
+%% Consider this code:
+%%
+%% Var = ...
+%% ...
+%% A1 = call foo/0
+%% A = copy A1
+%% B = call bar/1, Var
+%%
+%% If the Var variable is no longer used after this code, its Y register
+%% can't be reused for A. To allow the Y register to be reused
+%% we will need to insert 'copy' instructions for arguments that are
+%% in Y registers:
+%%
+%% Var = ...
+%% ...
+%% A1 = call foo/0
+%% Var1 = copy Var
+%% A = copy A1
+%% B = call bar/1, Var1
+%%
+
+place_retval_copy(I, _Yregs, none, Count, Acc) ->
+ {I,Count,Acc};
+place_retval_copy(#b_set{args=[F|Args0]}=I, Yregs, Copy, Count0, Acc0) ->
+ #b_set{dst=Avoid} = Copy,
+ {Args,Acc1,Count} = copy_func_args(Args0, Yregs, Avoid, Acc0, [], Count0),
+ Acc = [Copy|Acc1],
+ {I#b_set{args=[F|Args]},Count,Acc}.
+
+copy_func_args([#b_var{name=AName}=A|As], Yregs, Avoid, CopyAcc, Acc, Count0) ->
+ case gb_sets:is_member(A, Yregs) of
+ true when A =/= Avoid ->
+ {NewVar,Count} = new_var(AName, Count0),
+ Copy = #b_set{op=copy,dst=NewVar,args=[A]},
+ copy_func_args(As, Yregs, Avoid, [Copy|CopyAcc], [NewVar|Acc], Count);
+ _ ->
+ copy_func_args(As, Yregs, Avoid, CopyAcc, [A|Acc], Count0)
+ end;
+copy_func_args([A|As], Yregs, Avoid, CopyAcc, Acc, Count) ->
+ copy_func_args(As, Yregs, Avoid, CopyAcc, [A|Acc], Count);
+copy_func_args([], _Yregs, _Avoid, CopyAcc, Acc, Count) ->
+ {reverse(Acc),CopyAcc,Count}.
+
+acc_copy(Acc, none) -> Acc;
+acc_copy(Acc, #b_set{}=Copy) -> [Copy|Acc].
+
+copy_sub_args(Args, none) ->
+ Args;
+copy_sub_args(Args, #b_set{dst=Dst,args=[Src]}) ->
+ [sub_arg(A, Dst, Src) || A <- Args].
+
+sub_arg(Old, Old, New) -> New;
+sub_arg(Old, _, _) -> Old.
+
+%%%
+%%% Consider:
+%%%
+%%% x1/Hd = get_hd x0/Cons
+%%% y0/Tl = get_tl x0/Cons
+%%%
+%%% Register x0 can't be reused for Hd. If Hd needs to be in x0,
+%%% a 'move' instruction must be inserted.
+%%%
+%%% If we swap get_hd and get_tl when Tl is in a Y register,
+%%% x0 can be used for Hd if Cons is not used again:
+%%%
+%%% y0/Tl = get_tl x0/Cons
+%%% x0/Hd = get_hd x0/Cons
+%%%
+
+opt_get_list(#st{ssa=Blocks,res=Res}=St) ->
+ ResMap = maps:from_list(Res),
+ Ls = beam_ssa:rpo(Blocks),
+ St#st{ssa=opt_get_list_1(Ls, ResMap, Blocks)}.
+
+opt_get_list_1([L|Ls], Res, Blocks0) ->
+ #b_blk{is=Is0} = Blk = maps:get(L, Blocks0),
+ case opt_get_list_is(Is0, Res, [], false) of
+ no ->
+ opt_get_list_1(Ls, Res, Blocks0);
+ {yes,Is} ->
+ Blocks = Blocks0#{L:=Blk#b_blk{is=Is}},
+ opt_get_list_1(Ls, Res, Blocks)
+ end;
+opt_get_list_1([], _, Blocks) -> Blocks.
+
+opt_get_list_is([#b_set{op=get_hd,dst=Hd,
+ args=[Cons]}=GetHd,
+ #b_set{op=get_tl,dst=Tl,
+ args=[Cons]}=GetTl|Is],
+ Res, Acc, Changed) ->
+ %% Note that when this pass is run, only Y registers have
+ %% reservations. The absence of an entry for a variable therefore
+ %% means that the variable will be in an X register.
+ case Res of
+ #{Hd:={y,_}} ->
+ %% Hd will be in a Y register. Don't swap.
+ opt_get_list_is([GetTl|Is], Res, [GetHd|Acc], Changed);
+ #{Tl:={y,_}} ->
+ %% Tl will be in a Y register. Swap.
+ opt_get_list_is([GetHd|Is], Res, [GetTl|Acc], true);
+ #{} ->
+ %% Both are in X registers. Nothing to do.
+ opt_get_list_is([GetTl|Is], Res, [GetHd|Acc], Changed)
+ end;
+opt_get_list_is([I|Is], Res, Acc, Changed) ->
+ opt_get_list_is(Is, Res, [I|Acc], Changed);
+opt_get_list_is([], _Res, Acc, Changed) ->
+ case Changed of
+ true ->
+ {yes,reverse(Acc)};
+ false ->
+ no
+ end.
+
+%%%
+%%% Number instructions in the order they are executed.
+%%%
+
+%% number_instructions(St0) -> St.
+%% Number instructions in the order they are executed. Use a step
+%% size of 2. Don't number phi instructions. All phi variables in
+%% a block will be live one unit before the first non-phi instruction
+%% in the block.
+
+number_instructions(#st{ssa=Blocks0}=St) ->
+ Ls = beam_ssa:rpo(Blocks0),
+ St#st{ssa=number_is_1(Ls, 1, Blocks0)}.
+
+number_is_1([L|Ls], N0, Blocks0) ->
+ #b_blk{is=Is0,last=Last0} = Bl0 = maps:get(L, Blocks0),
+ {Is,N1} = number_is_2(Is0, N0, []),
+ Last = beam_ssa:add_anno(n, N1, Last0),
+ N = N1 + 2,
+ Bl = Bl0#b_blk{is=Is,last=Last},
+ Blocks = maps:put(L, Bl, Blocks0),
+ number_is_1(Ls, N, Blocks);
+number_is_1([], _, Blocks) -> Blocks.
+
+number_is_2([#b_set{op=phi}=I|Is], N, Acc) ->
+ number_is_2(Is, N, [I|Acc]);
+number_is_2([I0|Is], N, Acc) ->
+ I = beam_ssa:add_anno(n, N, I0),
+ number_is_2(Is, N+2, [I|Acc]);
+number_is_2([], N, Acc) ->
+ {reverse(Acc),N}.
+
+%%%
+%%% Calculate live intervals.
+%%%
+
+live_intervals(#st{args=Args,ssa=Blocks}=St) ->
+ Vars0 = [{V,{0,1}} || #b_var{}=V <- Args],
+ F = fun(L, _, A) -> live_interval_blk(L, Blocks, A) end,
+ LiveMap0 = #{},
+ Acc0 = {[],[],LiveMap0},
+ {Vars,Aliases,_} = beam_ssa:fold_po(F, Acc0, Blocks),
+ Intervals = merge_ranges(rel2fam(Vars0++Vars)),
+ St#st{intervals=Intervals,aliases=Aliases}.
+
+merge_ranges([{V,Rs}|T]) ->
+ [{V,merge_ranges_1(Rs)}|merge_ranges(T)];
+merge_ranges([]) -> [].
+
+merge_ranges_1([{A,N},{N,Z}|Rs]) ->
+ merge_ranges_1([{A,Z}|Rs]);
+merge_ranges_1([R|Rs]) ->
+ [R|merge_ranges_1(Rs)];
+merge_ranges_1([]) -> [].
+
+live_interval_blk(L, Blocks, {Vars0,Aliases0,LiveMap0}) ->
+ Live0 = [],
+ Successors = beam_ssa:successors(L, Blocks),
+ Live1 = update_successors(Successors, L, Blocks, LiveMap0, Live0),
+
+ %% Add ranges for all variables that are live in the successors.
+ #b_blk{is=Is,last=Last} = maps:get(L, Blocks),
+ End = beam_ssa:get_anno(n, Last),
+ Use = [{V,{use,End+1}} || V <- Live1],
+
+ %% Determine used and defined variables in this block.
+ FirstNumber = first_number(Is, Last),
+ {UseDef0,Aliases} = live_interval_blk_1([Last|reverse(Is)],
+ FirstNumber, Aliases0, Use),
+ UseDef = rel2fam(UseDef0),
+
+ %% Update what is live at the beginning of this block and
+ %% store it.
+ Used = [V || {V,[{use,_}|_]} <- UseDef],
+ Live2 = ordsets:union(Live1, Used),
+ Killed = [V || {V,[{def,_}|_]} <- UseDef],
+ Live = ordsets:subtract(Live2, Killed),
+ LiveMap = LiveMap0#{L=>Live},
+
+ %% Construct the ranges for this block.
+ Vars = make_block_ranges(UseDef, FirstNumber, Vars0),
+ {Vars,Aliases,LiveMap}.
+
+make_block_ranges([{V,[{def,Def}]}|Vs], First, Acc) ->
+ make_block_ranges(Vs, First, [{V,{Def,Def}}|Acc]);
+make_block_ranges([{V,[{def,Def}|Uses]}|Vs], First, Acc) ->
+ {use,Last} = last(Uses),
+ make_block_ranges(Vs, First, [{V,{Def,Last}}|Acc]);
+make_block_ranges([{V,[{use,_}|_]=Uses}|Vs], First, Acc) ->
+ {use,Last} = last(Uses),
+ make_block_ranges(Vs, First, [{V,{First,Last}}|Acc]);
+make_block_ranges([], _, Acc) -> Acc.
+
+live_interval_blk_1([#b_set{op=phi,dst=Dst}|Is],
+ FirstNumber, Aliases, Acc0) ->
+ Acc = [{Dst,{def,FirstNumber}}|Acc0],
+ live_interval_blk_1(Is, FirstNumber, Aliases, Acc);
+live_interval_blk_1([#b_set{op=bs_start_match}=I|Is], FirstNumber,
+ Aliases0, Acc0) ->
+ N = beam_ssa:get_anno(n, I),
+ #b_set{dst=Dst} = I,
+ Acc1 = [{Dst,{def,N}}|Acc0],
+ Aliases = case beam_ssa:get_anno(reuse_for_context, I) of
+ true ->
+ #b_set{args=[Src]} = I,
+ [{Dst,Src}|Aliases0];
+ false ->
+ Aliases0
+ end,
+ Acc = [{V,{use,N}} || V <- beam_ssa:used(I)] ++ Acc1,
+ live_interval_blk_1(Is, FirstNumber, Aliases, Acc);
+live_interval_blk_1([I|Is], FirstNumber, Aliases, Acc0) ->
+ N = beam_ssa:get_anno(n, I),
+ Acc1 = case I of
+ #b_set{dst=Dst} ->
+ [{Dst,{def,N}}|Acc0];
+ _ ->
+ Acc0
+ end,
+ Used = beam_ssa:used(I),
+ Acc = [{V,{use,N}} || V <- Used] ++ Acc1,
+ live_interval_blk_1(Is, FirstNumber, Aliases, Acc);
+live_interval_blk_1([], _FirstNumber, Aliases, Acc) ->
+ {Acc,Aliases}.
+
+%% first_number([#b_set{}]) -> InstructionNumber.
+%% Return the number for the first instruction for the block.
+%% Note that this number is one less than the first
+%% non-phi instruction in the block.
+
+first_number([#b_set{op=phi}|Is], Last) ->
+ first_number(Is, Last);
+first_number([I|_], _) ->
+ beam_ssa:get_anno(n, I) - 1;
+first_number([], Last) ->
+ beam_ssa:get_anno(n, Last) - 1.
+
+update_successors([L|Ls], Pred, Blocks, LiveMap, Live0) ->
+ Live1 = ordsets:union(Live0, get_live(L, LiveMap)),
+ #b_blk{is=Is} = maps:get(L, Blocks),
+ Live = update_live_phis(Is, Pred, Live1),
+ update_successors(Ls, Pred, Blocks, LiveMap, Live);
+update_successors([], _, _, _, Live) -> Live.
+
+get_live(L, LiveMap) ->
+ case LiveMap of
+ #{L:=Live} -> Live;
+ #{} -> []
+ end.
+
+update_live_phis([#b_set{op=phi,dst=Killed,args=Args}|Is],
+ Pred, Live0) ->
+ Used = [V || {#b_var{}=V,L} <- Args, L =:= Pred],
+ Live1 = ordsets:union(ordsets:from_list(Used), Live0),
+ Live = ordsets:del_element(Killed, Live1),
+ update_live_phis(Is, Pred, Live);
+update_live_phis(_, _, Live) -> Live.
+
+%%%
+%%% Reserve Y registers.
+%%%
+
+%% reserve_yregs(St0) -> St.
+%% In each block that allocates a stack frame, insert instructions
+%% that copy variables that must be in Y registers (given by
+%% the `yregs` annotation) to new variables.
+%%
+%% Also allocate specific Y registers for try and catch tags.
+%% The outermost try/catch tag is placed in y0, any directly
+%% nested tag in y1, and so on. Note that this is the reversed
+%% order as required by BEAM; it will be corrected later by
+%% turn_yregs().
+
+reserve_yregs(#st{frames=Frames}=St0) ->
+ foldl(fun reserve_yregs_1/2, St0, Frames).
+
+reserve_yregs_1(L, #st{ssa=Blocks0,cnt=Count0,res=Res0}=St) ->
+ Blk = maps:get(L, Blocks0),
+ Yregs = beam_ssa:get_anno(yregs, Blk),
+ {Def,Used} = beam_ssa:def_used([L], Blocks0),
+ UsedYregs = ordsets:intersection(Yregs, Used),
+ DefBefore = ordsets:subtract(UsedYregs, Def),
+ {BeforeVars,Blocks,Count} = rename_vars(DefBefore, L, Blocks0, Count0),
+ InsideVars = ordsets:subtract(UsedYregs, DefBefore),
+ ResTryTags0 = reserve_try_tags(L, Blocks),
+ ResTryTags = [{V,{Reg,Count}} || {V,Reg} <- ResTryTags0],
+ Vars = BeforeVars ++ InsideVars,
+ Res = [{V,{y,Count}} || V <- Vars] ++ ResTryTags ++ Res0,
+ St#st{res=Res,ssa=Blocks,cnt=Count+1}.
+
+reserve_try_tags(L, Blocks) ->
+ Seen = gb_sets:empty(),
+ {Res0,_} = reserve_try_tags_1([L], Blocks, Seen, #{}),
+ Res1 = [maps:to_list(M) || {_,M} <- maps:to_list(Res0)],
+ Res = [{V,{y,Y}} || {V,Y} <- append(Res1)],
+ ordsets:from_list(Res).
+
+reserve_try_tags_1([L|Ls], Blocks, Seen0, ActMap0) ->
+ case gb_sets:is_element(L, Seen0) of
+ true ->
+ reserve_try_tags_1(Ls, Blocks, Seen0, ActMap0);
+ false ->
+ Seen1 = gb_sets:insert(L, Seen0),
+ #b_blk{is=Is} = Blk = maps:get(L, Blocks),
+ Active0 = get_active(L, ActMap0),
+ Active = reserve_try_tags_is(Is, Active0),
+ Successors = beam_ssa:successors(Blk),
+ ActMap1 = update_act_map(Successors, Active, ActMap0),
+ {ActMap,Seen} = reserve_try_tags_1(Ls, Blocks, Seen1, ActMap1),
+ reserve_try_tags_1(Successors, Blocks, Seen,ActMap)
+ end;
+reserve_try_tags_1([], _Blocks, Seen, ActMap) ->
+ {ActMap,Seen}.
+
+get_active(L, ActMap) ->
+ case ActMap of
+ #{L:=Active} -> Active;
+ #{} -> #{}
+ end.
+
+reserve_try_tags_is([#b_set{op=new_try_tag,dst=V}|Is], Active) ->
+ N = map_size(Active),
+ reserve_try_tags_is(Is, Active#{V=>N});
+reserve_try_tags_is([#b_set{op=kill_try_tag,args=[Tag]}|Is], Active) ->
+ reserve_try_tags_is(Is, maps:remove(Tag, Active));
+reserve_try_tags_is([_|Is], Active) ->
+ reserve_try_tags_is(Is, Active);
+reserve_try_tags_is([], Active) -> Active.
+
+update_act_map([L|Ls], Active0, ActMap0) ->
+ case ActMap0 of
+ #{L:=Active1} ->
+ ActMap = ActMap0#{L=>maps:merge(Active0, Active1)},
+ update_act_map(Ls, Active0, ActMap);
+ #{} ->
+ ActMap = ActMap0#{L=>Active0},
+ update_act_map(Ls, Active0, ActMap)
+ end;
+update_act_map([], _, ActMap) -> ActMap.
+
+rename_vars([], _, Blocks, Count) ->
+ {[],Blocks,Count};
+rename_vars(Vs, L, Blocks0, Count0) ->
+ {NewVars,Count} = new_vars([Base || #b_var{name=Base} <- Vs], Count0),
+ Ren = zip(Vs, NewVars),
+ Blocks1 = beam_ssa:rename_vars(Ren, [L], Blocks0),
+ #b_blk{is=Is0} = Blk0 = maps:get(L, Blocks1),
+ CopyIs = [#b_set{op=copy,dst=New,args=[Old]} || {Old,New} <- Ren],
+ Is = insert_after_phis(Is0, CopyIs),
+ Blk = Blk0#b_blk{is=Is},
+ Blocks = maps:put(L, Blk, Blocks1),
+ {NewVars,Blocks,Count}.
+
+insert_after_phis([#b_set{op=phi}=I|Is], InsertIs) ->
+ [I|insert_after_phis(Is, InsertIs)];
+insert_after_phis(Is, InsertIs) ->
+ InsertIs ++ Is.
+
+%% frame_size(St0) -> St.
+%% Calculate the frame size for each block that allocates a frame.
+%% Annotate the block with the frame size. Also annotate all
+%% return instructions with {deallocate,FrameSize} to simplify
+%% code generation.
+
+frame_size(#st{frames=Frames,regs=Regs,ssa=Blocks0}=St) ->
+ Blocks = foldl(fun(L, Blks) ->
+ frame_size_1(L, Regs, Blks)
+ end, Blocks0, Frames),
+ St#st{ssa=Blocks}.
+
+frame_size_1(L, Regs, Blocks0) ->
+ Def = beam_ssa:def([L], Blocks0),
+ Yregs0 = [maps:get(V, Regs) || V <- Def, is_yreg(maps:get(V, Regs))],
+ Yregs = ordsets:from_list(Yregs0),
+ FrameSize = length(ordsets:from_list(Yregs)),
+ if
+ FrameSize =/= 0 ->
+ [{y,0}|_] = Yregs, %Assertion.
+ {y,Last} = last(Yregs),
+ Last = FrameSize - 1, %Assertion.
+ ok;
+ true ->
+ ok
+ end,
+ Blk0 = maps:get(L, Blocks0),
+ Blk = beam_ssa:add_anno(frame_size, FrameSize, Blk0),
+
+ %% Insert an annotation for frame deallocation on
+ %% each #b_ret{}.
+ Blocks = maps:put(L, Blk, Blocks0),
+ Reachable = beam_ssa:rpo([L], Blocks),
+ frame_deallocate(Reachable, FrameSize, Blocks).
+
+frame_deallocate([L|Ls], Size, Blocks0) ->
+ Blk0 = maps:get(L, Blocks0),
+ Blk = case Blk0 of
+ #b_blk{last=#b_ret{}=Ret0} ->
+ Ret = beam_ssa:add_anno(deallocate, Size, Ret0),
+ Blk0#b_blk{last=Ret};
+ #b_blk{} ->
+ Blk0
+ end,
+ Blocks = maps:put(L, Blk, Blocks0),
+ frame_deallocate(Ls, Size, Blocks);
+frame_deallocate([], _, Blocks) -> Blocks.
+
+
+%% turn_yregs(St0) -> St.
+%% Renumber y registers so that {y,0} becomes {y,FrameSize-1},
+%% {y,FrameSize-1} becomes {y,0} and so on. This is to make nested
+%% catches work. The register allocator (linear_scan()) has given
+%% a lower number to the outermost catch.
+
+turn_yregs(#st{frames=Frames,regs=Regs0,ssa=Blocks}=St) ->
+ Regs1 = foldl(fun(L, A) ->
+ Blk = maps:get(L, Blocks),
+ FrameSize = beam_ssa:get_anno(frame_size, Blk),
+ Def = beam_ssa:def([L], Blocks),
+ [turn_yregs_1(Def, FrameSize, Regs0)|A]
+ end, [], Frames),
+ Regs = maps:merge(Regs0, maps:from_list(append(Regs1))),
+ St#st{regs=Regs}.
+
+turn_yregs_1(Def, FrameSize, Regs) ->
+ Yregs0 = [{maps:get(V, Regs),V} || V <- Def, is_yreg(maps:get(V, Regs))],
+ Yregs1 = rel2fam(Yregs0),
+ FrameSize = length(Yregs1),
+ Yregs2 = [{{y,FrameSize-Y-1},Vs} || {{y,Y},Vs} <- Yregs1],
+ R0 = sofs:family(Yregs2),
+ R1 = sofs:family_to_relation(R0),
+ R = sofs:converse(R1),
+ sofs:to_external(R).
+
+%%%
+%%% Reserving registers before register allocation.
+%%%
+
+%% reserve_regs(St0) -> St.
+%% Reserve registers prior to register allocation. Y registers
+%% have already been reserved. This function will reserve z,
+%% fr, and specific x registers.
+
+reserve_regs(#st{args=Args,ssa=Blocks,intervals=Intervals,res=Res0}=St) ->
+ %% Reserve x0, x1, and so on for the function arguments.
+ Res1 = reserve_arg_regs(Args, 0, Res0),
+
+ %% Reserve Z registers (dummy registers) for instructions with no
+ %% return values (e.g. remove_message) or pseudo-return values
+ %% (e.g. landingpad).
+ Res2 = reserve_zregs(Blocks, Intervals, Res1),
+
+ %% Reserve float registers.
+ Res3 = reserve_fregs(Blocks, Res2),
+
+ %% Reserve all remaining unreserved variables as X registers.
+ Res = maps:from_list(Res3),
+ St#st{res=reserve_xregs(Blocks, Res)}.
+
+reserve_arg_regs([#b_var{}=Arg|Is], N, Acc) ->
+ reserve_arg_regs(Is, N+1, [{Arg,{x,N}}|Acc]);
+reserve_arg_regs([], _, Acc) -> Acc.
+
+reserve_zregs(Blocks, Intervals, Res) ->
+ ShortLived0 = [V || {V,[{Start,End}]} <- Intervals, Start+2 =:= End],
+ ShortLived = cerl_sets:from_list(ShortLived0),
+ F = fun(_, #b_blk{is=Is,last=Last}, A) ->
+ reserve_zreg(Is, Last, ShortLived, A)
+ end,
+ beam_ssa:fold_rpo(F, [0], Res, Blocks).
+
+reserve_zreg([#b_set{op={bif,tuple_size},dst=Dst},
+ #b_set{op={bif,'=:='},args=[Dst,Val]}], _Last, ShortLived, A0) ->
+ case Val of
+ #b_literal{val=Arity} when Arity bsr 32 =:= 0 ->
+ %% These two instructions can be combined to a test_arity
+ %% instruction provided that the arity variable is short-lived.
+ reserve_zreg_1(Dst, ShortLived, A0);
+ _ ->
+ A0
+ end;
+reserve_zreg([#b_set{op={bif,tuple_size},dst=Dst}],
+ #b_switch{}, ShortLived, A) ->
+ reserve_zreg_1(Dst, ShortLived, A);
+reserve_zreg([#b_set{op=Op,dst=Dst}|Is], Last, ShortLived, A0) ->
+ IsZReg = case Op of
+ context_to_binary -> true;
+ bs_match_string -> true;
+ bs_restore -> true;
+ bs_save -> true;
+ {float,clearerror} -> true;
+ kill_try_tag -> true;
+ landingpad -> true;
+ put_tuple_elements -> true;
+ remove_message -> true;
+ set_tuple_element -> true;
+ succeeded -> true;
+ timeout -> true;
+ wait_timeout -> true;
+ _ -> false
+ end,
+ A = case IsZReg of
+ true -> [{Dst,z}|A0];
+ false -> A0
+ end,
+ reserve_zreg(Is, Last, ShortLived, A);
+reserve_zreg([], #b_br{bool=Bool}, ShortLived, A) ->
+ reserve_zreg_1(Bool, ShortLived, A);
+reserve_zreg([], _, _, A) -> A.
+
+reserve_zreg_1(#b_var{}=V, ShortLived, A) ->
+ case cerl_sets:is_element(V, ShortLived) of
+ true -> [{V,z}|A];
+ false -> A
+ end;
+reserve_zreg_1(#b_literal{}, _, A) -> A.
+
+reserve_fregs(Blocks, Res) ->
+ F = fun(_, #b_blk{is=Is}, A) ->
+ reserve_freg(Is, A)
+ end,
+ beam_ssa:fold_rpo(F, [0], Res, Blocks).
+
+reserve_freg([#b_set{op={float,Op},dst=V}|Is], Res) ->
+ case Op of
+ get ->
+ reserve_freg(Is, Res);
+ _ ->
+ reserve_freg(Is, [{V,fr}|Res])
+ end;
+reserve_freg([_|Is], Res) ->
+ reserve_freg(Is, Res);
+reserve_freg([], Res) -> Res.
+
+%% reserve_xregs(St0) -> St.
+%% Reserve all remaining variables as X registers.
+%%
+%% If a variable will need to be in a specific X register for a
+%% 'call' or 'make_fun' (and there is nothing that will kill it
+%% between the definition and use), reserve the register using a
+%% {prefer,{x,X} annotation. That annotation means that the linear
+%% scan algorithm will place the variable in the preferred register,
+%% unless that register is already occupied.
+%%
+%% All remaining variables are reserved as X registers. Linear scan
+%% will allocate the lowest free X register for the variable.
+
+reserve_xregs(Blocks, Res) ->
+ F = fun(L, #b_blk{is=Is,last=Last}, R) ->
+ {Xs0,Used0} = reserve_terminator(L, Last, Blocks, R),
+ reserve_xregs_is(reverse(Is), R, Xs0, Used0)
+ end,
+ beam_ssa:fold_po(F, Res, Blocks).
+
+reserve_xregs_is([#b_set{op=Op,dst=Dst,args=Args}=I|Is], Res0, Xs0, Used0) ->
+ Xs1 = case is_gc_safe(I) of
+ true ->
+ Xs0;
+ false ->
+ %% There may be a garbage collection after executing this
+ %% instruction. We will need prune the list of preferred
+ %% X registers.
+ res_xregs_prune(Xs0, Used0, Res0)
+ end,
+ Res = reserve_xreg(Dst, Xs1, Res0),
+ Used1 = ordsets:union(Used0, beam_ssa:used(I)),
+ Used = ordsets:del_element(Dst, Used1),
+ case Op of
+ call ->
+ Xs = reserve_call_args(tl(Args)),
+ reserve_xregs_is(Is, Res, Xs, Used);
+ make_fun ->
+ Xs = reserve_call_args(tl(Args)),
+ reserve_xregs_is(Is, Res, Xs, Used);
+ _ ->
+ reserve_xregs_is(Is, Res, Xs1, Used)
+ end;
+reserve_xregs_is([], Res, _Xs, _Used) -> Res.
+
+reserve_terminator(L, #b_br{bool=#b_literal{val=true},succ=Succ}, Blocks, Res) ->
+ case maps:get(Succ, Blocks) of
+ #b_blk{is=[],last=Last} ->
+ reserve_terminator(Succ, Last, Blocks, Res);
+ #b_blk{is=[_|_]=Is} ->
+ {res_xregs_from_phi(Is, L, Res, #{}),[]}
+ end;
+reserve_terminator(_, Last, _, _) ->
+ {#{},beam_ssa:used(Last)}.
+
+res_xregs_from_phi([#b_set{op=phi,dst=Dst,args=Args}|Is],
+ Pred, Res, Acc) ->
+ case [V || {#b_var{}=V,L} <- Args, L =:= Pred] of
+ [] ->
+ res_xregs_from_phi(Is, Pred, Res, Acc);
+ [V] ->
+ case Res of
+ #{Dst:={prefer,Reg}} ->
+ res_xregs_from_phi(Is, Pred, Res, Acc#{V=>Reg});
+ #{Dst:=_} ->
+ res_xregs_from_phi(Is, Pred, Res, Acc)
+ end
+ end;
+res_xregs_from_phi(_, _, _, Acc) -> Acc.
+
+reserve_call_args(Args) ->
+ reserve_call_args(Args, 0, #{}).
+
+reserve_call_args([#b_var{}=Var|As], X, Xs) ->
+ reserve_call_args(As, X+1, Xs#{Var=>{x,X}});
+reserve_call_args([#b_literal{}|As], X, Xs) ->
+ reserve_call_args(As, X+1, Xs);
+reserve_call_args([], _, Xs) -> Xs.
+
+reserve_xreg(V, Xs, Res) ->
+ case Res of
+ #{V:=_} ->
+ %% Already reserved.
+ Res;
+ #{} ->
+ case Xs of
+ #{V:=X} ->
+ %% Add a hint that a specific X register is
+ %% preferred, unless it is already in use.
+ Res#{V=>{prefer,X}};
+ #{} ->
+ %% Reserve as an X register in general.
+ Res#{V=>x}
+ end
+ end.
+
+is_gc_safe(#b_set{op=phi}) ->
+ false;
+is_gc_safe(#b_set{op=Op,args=Args}) ->
+ case beam_ssa_codegen:classify_heap_need(Op, Args) of
+ neutral -> true;
+ {put,_} -> true;
+ _ -> false
+ end.
+
+%% res_xregs_prune(PreferredRegs, Used, Res) -> PreferredRegs.
+%% Prune the list of preferred to only include X registers that
+%% are guaranteed to survice a garbage collection.
+
+res_xregs_prune(Xs, Used, Res) ->
+ %% The number of safe registers is the number of the X registers
+ %% used after this point. The actual number of safe registers may
+ %% be highter than this number, but this is a conservative safe
+ %% estimate.
+ NumSafe = foldl(fun(V, N) ->
+ case Res of
+ #{V:={x,_}} -> N + 1;
+ #{V:=_} -> N;
+ #{} -> N + 1
+ end
+ end, 0, Used),
+
+ %% Remove unsafe registers from the list of potential
+ %% preferred registers.
+ maps:filter(fun(_, {x,X}) -> X < NumSafe end, Xs).
+
+%%%
+%%% Remove unsuitable aliases.
+%%%
+%%% If a binary is matched more than once, we must not put the
+%%% the match context in the same register as the binary to
+%%% avoid the following situation:
+%%%
+%%% {test,bs_start_match2,{f,3},1,[{x,0},0],{x,0}}.
+%%% .
+%%% .
+%%% .
+%%% {test,bs_start_match2,{f,6},1,[{x,0},0],{x,1}}. %% ILLEGAL!
+%%%
+%%% The second instruction is illegal because a match context source
+%%% is only allowed if source and destination registers are identical.
+%%%
+
+remove_unsuitable_aliases(#st{aliases=[_|_]=Aliases0,ssa=Blocks}=St) ->
+ R = rem_unsuitable(maps:values(Blocks)),
+ Unsuitable0 = [V || {V,[_,_|_]} <- rel2fam(R)],
+ Unsuitable = gb_sets:from_list(Unsuitable0),
+ Aliases =[P || {_,V}=P <- Aliases0,
+ not gb_sets:is_member(V, Unsuitable)],
+ St#st{aliases=Aliases};
+remove_unsuitable_aliases(#st{aliases=[]}=St) -> St.
+
+rem_unsuitable([#b_blk{is=Is}|Bs]) ->
+ Vs = [{Var,Dst} ||
+ #b_set{op=bs_start_match,dst=Dst,
+ args=[#b_var{}=Var]} <- Is],
+ Vs ++ rem_unsuitable(Bs);
+rem_unsuitable([]) -> [].
+
+%%%
+%%% Merge intervals.
+%%%
+
+merge_intervals(#st{aliases=Aliases0,intervals=Intervals0,
+ res=Reserved}=St) ->
+ Aliases1 = [A || A <- Aliases0,
+ is_suitable_alias(A, Reserved)],
+ case Aliases1 of
+ [] ->
+ St#st{aliases=Aliases1};
+ [_|_] ->
+ Intervals1 = maps:from_list(Intervals0),
+ {Intervals,Aliases} =
+ merge_intervals_1(Aliases1, Intervals1, []),
+ St#st{aliases=Aliases,intervals=Intervals}
+ end.
+
+merge_intervals_1([{Alias,V}|Vs], Intervals0, Acc) ->
+ #{Alias:=Int1,V:=Int2} = Intervals0,
+ Int3 = lists:merge(Int1, Int2),
+ Int = merge_intervals_2(Int3),
+ Intervals1 = maps:remove(Alias, Intervals0),
+ Intervals = Intervals1#{V:=Int},
+ merge_intervals_1(Vs, Intervals, [{Alias,V}|Acc]);
+merge_intervals_1([], Intervals, Acc) ->
+ {maps:to_list(Intervals),Acc}.
+
+merge_intervals_2([{A1,B1},{A2,B2}|Is]) when A2 =< B1 ->
+ merge_intervals_2([{min(A1, A2),max(B1, B2)}|Is]);
+merge_intervals_2([{_A1,B1}=R|[{A2,_B2}|_]=Is]) when B1 < A2 ->
+ [R|merge_intervals_2(Is)];
+merge_intervals_2([_]=Is) -> Is.
+
+is_suitable_alias({V1,V2}, Reserved) ->
+ #{V1:=Res1,V2:=Res2} = Reserved,
+ case {Res1,Res2} of
+ {x,x} -> true;
+ {x,{x,_}} -> true;
+ {{x,_},x} -> true;
+ {_,_} -> false
+ end.
+
+%%%
+%%% Register allocation using linear scan.
+%%%
+
+-record(i,
+ {sort=1 :: instr_number(),
+ reg=none :: i_reg(),
+ pool=x :: pool_id(),
+ var=#b_var{} :: b_var(),
+ rs=[] :: [range()]
+ }).
+
+-record(l,
+ {cur=#i{} :: interval(),
+ unhandled_res=[] :: [interval()],
+ unhandled_any=[] :: [interval()],
+ active=[] :: [interval()],
+ inactive=[] :: [interval()],
+ free=#{} :: #{var_name()=>pool(),
+ {'next',pool_id()}:=reg_num()},
+ regs=[] :: [{b_var(),ssa_register()}]
+ }).
+
+-type interval() :: #i{}.
+-type i_reg() :: ssa_register() | {'prefer',xreg()} | 'none'.
+-type pool_id() :: 'fr' | 'x' | 'z' | instr_number().
+-type pool() :: ordsets:ordset(ssa_register()).
+
+linear_scan(#st{intervals=Intervals0,res=Res}=St0) ->
+ St = St0#st{intervals=[],res=[]},
+ Free = init_free(maps:to_list(Res)),
+ Intervals1 = [init_interval(Int, Res) || Int <- Intervals0],
+ Intervals = sort(Intervals1),
+ IsReserved = fun (#i{reg=Reg}) -> Reg =/= none end,
+ {UnhandledRes,Unhandled} = partition(IsReserved, Intervals),
+ L = #l{unhandled_res=UnhandledRes,
+ unhandled_any=Unhandled,free=Free},
+ #l{regs=Regs} = do_linear(L),
+ St#st{regs=maps:from_list(Regs)}.
+
+init_interval({V,[{Start,_}|_]=Rs}, Res) ->
+ Info = maps:get(V, Res),
+ Pool = case Info of
+ {prefer,{x,_}} -> x;
+ x -> x;
+ {x,_} -> x;
+ {y,Uniq} -> Uniq;
+ {{y,_},Uniq} -> Uniq;
+ z -> z;
+ fr -> fr
+ end,
+ Reg = case Info of
+ {prefer,{x,_}} -> Info;
+ {x,_} -> Info;
+ {{y,_}=Y,_} -> Y;
+ _ -> none
+ end,
+ #i{sort=Start,var=V,reg=Reg,pool=Pool,rs=Rs}.
+
+init_free(Res) ->
+ Free0 = rel2fam([{x,{x,0}}|init_free_1(Res)]),
+ #{x:=Xs0} = Free1 = maps:from_list(Free0),
+ Xs = init_xregs(Xs0),
+ Free = Free1#{x:=Xs},
+ Next = maps:fold(fun(K, V, A) -> [{{next,K},length(V)}|A] end, [], Free),
+ maps:merge(Free, maps:from_list(Next)).
+
+init_free_1([{_,{prefer,{x,_}=Reg}}|Res]) ->
+ [{x,Reg}|init_free_1(Res)];
+init_free_1([{_,{x,_}=Reg}|Res]) ->
+ [{x,Reg}|init_free_1(Res)];
+init_free_1([{_,{y,Uniq}}|Res]) ->
+ [{Uniq,{y,0}}|init_free_1(Res)];
+init_free_1([{_,{{y,_}=Reg,Uniq}}|Res]) ->
+ [{Uniq,Reg}|init_free_1(Res)];
+init_free_1([{_,z}|Res]) ->
+ [{z,{z,0}}|init_free_1(Res)];
+init_free_1([{_,fr}|Res]) ->
+ [{fr,{fr,0}}|init_free_1(Res)];
+init_free_1([{_,x}|Res]) ->
+ init_free_1(Res);
+init_free_1([]) -> [].
+
+%% Make sure that the pool of xregs is contiguous.
+init_xregs([{x,N},{x,M}|Is]) when N+1 =:= M ->
+ [{x,N}|init_xregs([{x,M}|Is])];
+init_xregs([{x,N}|[{x,_}|_]=Is]) ->
+ [{x,N}|init_xregs([{x,N+1}|Is])];
+init_xregs([{x,_}]=Is) -> Is.
+
+do_linear(L0) ->
+ case set_next_current(L0) of
+ done ->
+ L0;
+ L1 ->
+ L2 = expire_active(L1),
+ L3 = check_inactive(L2),
+ Available = collect_available(L3),
+ L4 = select_register(Available, L3),
+ L = make_cur_active(L4),
+ do_linear(L)
+ end.
+
+set_next_current(#l{unhandled_res=[Cur1|T1],
+ unhandled_any=[Cur2|T2]}=L) ->
+ case {Cur1,Cur2} of
+ {#i{sort=N1},#i{sort=N2}} when N1 < N2 ->
+ L#l{cur=Cur1,unhandled_res=T1};
+ {_,_} ->
+ L#l{cur=Cur2,unhandled_any=T2}
+ end;
+set_next_current(#l{unhandled_res=[],
+ unhandled_any=[Cur|T]}=L) ->
+ L#l{cur=Cur,unhandled_any=T};
+set_next_current(#l{unhandled_res=[Cur|T],
+ unhandled_any=[]}=L) ->
+ L#l{cur=Cur,unhandled_res=T};
+set_next_current(#l{unhandled_res=[],unhandled_any=[]}) ->
+ done.
+
+expire_active(#l{cur=#i{sort=CurBegin},active=Act0}=L0) ->
+ {Act,L} = expire_active(Act0, CurBegin, L0, []),
+ L#l{active=Act}.
+
+expire_active([#i{reg=Reg,rs=Rs0}=I|Is], CurBegin, L0, Acc) ->
+ {_,_} = Reg, %Assertion.
+ case overlap_status(Rs0, CurBegin) of
+ ends_before_cur ->
+ L = free_reg(I, L0),
+ expire_active(Is, CurBegin, L, Acc);
+ overlapping ->
+ expire_active(Is, CurBegin, L0, [I|Acc]);
+ not_overlapping ->
+ Rs = strip_before_current(Rs0, CurBegin),
+ L1 = free_reg(I, L0),
+ L = L1#l{inactive=[I#i{rs=Rs}|L1#l.inactive]},
+ expire_active(Is, CurBegin, L, Acc)
+ end;
+expire_active([], _CurBegin, L, Acc) ->
+ {Acc,L}.
+
+check_inactive(#l{cur=#i{sort=CurBegin},inactive=InAct0}=L0) ->
+ {InAct,L} = check_inactive(InAct0, CurBegin, L0, []),
+ L#l{inactive=InAct}.
+
+check_inactive([#i{rs=Rs0}=I|Is], CurBegin, L0, Acc) ->
+ case overlap_status(Rs0, CurBegin) of
+ ends_before_cur ->
+ check_inactive(Is, CurBegin, L0, Acc);
+ not_overlapping ->
+ check_inactive(Is, CurBegin, L0, [I|Acc]);
+ overlapping ->
+ Rs = strip_before_current(Rs0, CurBegin),
+ L1 = L0#l{active=[I#i{rs=Rs}|L0#l.active]},
+ L = reserve_reg(I, L1),
+ check_inactive(Is, CurBegin, L, Acc)
+ end;
+check_inactive([], _CurBegin, L, Acc) ->
+ {Acc,L}.
+
+strip_before_current([{_,E}|Rs], CurBegin) when E =< CurBegin ->
+ strip_before_current(Rs, CurBegin);
+strip_before_current(Rs, _CurBegin) -> Rs.
+
+collect_available(#l{cur=#i{reg={prefer,{_,_}=Prefer}}=I}=L) ->
+ %% Use the preferred register if it is available.
+ Avail = collect_available(L#l{cur=I#i{reg=none}}),
+ case member(Prefer, Avail) of
+ true -> [Prefer];
+ false -> Avail
+ end;
+collect_available(#l{cur=#i{reg={_,_}=ReservedReg}}) ->
+ %% Return the already reserved register.
+ [ReservedReg];
+collect_available(#l{unhandled_res=Unhandled,cur=Cur}=L) ->
+ Free = get_pool(Cur, L),
+
+ %% Note that since the live intervals are constructed from
+ %% SSA form, there cannot be any overlap of the current interval
+ %% with any inactive interval. See [3], page 175. Therefore we
+ %% only have check the unhandled intervals for overlap with
+ %% the current interval. As a further optimization, we only need
+ %% to check the intervals that have reserved registers.
+ collect_available(Unhandled, Cur, Free).
+
+collect_available([#i{pool=Pool1}|Is], #i{pool=Pool2}=Cur, Free)
+ when Pool1 =/= Pool2 ->
+ %% Wrong pool. Ignore this interval.
+ collect_available(Is, Cur, Free);
+collect_available([#i{reg={_,_}=Reg}=I|Is], Cur, Free0) ->
+ case overlaps(I, Cur) of
+ true ->
+ Free = ordsets:del_element(Reg, Free0),
+ collect_available(Is, Cur, Free);
+ false ->
+ collect_available(Is, Cur, Free0)
+ end;
+collect_available([], _, Free) -> Free.
+
+select_register([{_,_}=Reg|_], #l{cur=Cur0,regs=Regs}=L) ->
+ Cur = Cur0#i{reg=Reg},
+ reserve_reg(Cur, L#l{cur=Cur,regs=[{Cur#i.var,Reg}|Regs]});
+select_register([], #l{cur=Cur0,regs=Regs}=L0) ->
+ %% Allocate a new register in the pool.
+ {Reg,L1} = get_next_free(Cur0, L0),
+ Cur = Cur0#i{reg=Reg},
+ L = L1#l{cur=Cur,regs=[{Cur#i.var,Reg}|Regs]},
+ reserve_reg(Cur, L).
+
+make_cur_active(#l{cur=Cur,active=Act}=L) ->
+ L#l{active=[Cur|Act]}.
+
+overlaps(#i{rs=Rs1}, #i{rs=Rs2}) ->
+ are_overlapping(Rs1, Rs2).
+
+overlap_status([{S,E}], CurBegin) ->
+ if
+ E =< CurBegin -> ends_before_cur;
+ CurBegin < S -> not_overlapping;
+ true -> overlapping
+ end;
+overlap_status([{S,E}|Rs], CurBegin) ->
+ if
+ E =< CurBegin ->
+ overlap_status(Rs, CurBegin);
+ S =< CurBegin ->
+ overlapping;
+ true ->
+ not_overlapping
+ end.
+
+reserve_reg(#i{reg={_,_}=Reg}=I, L) ->
+ FreeRegs0 = get_pool(I, L),
+ FreeRegs = ordsets:del_element(Reg, FreeRegs0),
+ update_pool(I, FreeRegs, L).
+
+free_reg(#i{reg={_,_}=Reg}=I, L) ->
+ FreeRegs0 = get_pool(I, L),
+ FreeRegs = ordsets:add_element(Reg, FreeRegs0),
+ update_pool(I, FreeRegs, L).
+
+get_pool(#i{pool=Pool}, #l{free=Free}) ->
+ maps:get(Pool, Free).
+
+update_pool(#i{pool=Pool}, New, #l{free=Free0}=L) ->
+ Free = maps:put(Pool, New, Free0),
+ L#l{free=Free}.
+
+get_next_free(#i{pool=Pool}, #l{free=Free0}=L0) ->
+ K = {next,Pool},
+ N = maps:get(K, Free0),
+ Free = maps:put(K, N+1, Free0),
+ L = L0#l{free=Free},
+ if
+ is_integer(Pool) -> {{y,N},L};
+ is_atom(Pool) -> {{Pool,N},L}
+ end.
+
+%%%
+%%% Interval utilities.
+%%%
+
+are_overlapping([R|Rs1], Rs2) ->
+ case are_overlapping_1(R, Rs2) of
+ true ->
+ true;
+ false ->
+ are_overlapping(Rs1, Rs2)
+ end;
+are_overlapping([], _) -> false.
+
+are_overlapping_1({_S1,E1}, [{S2,_E2}|_]) when E1 < S2 ->
+ false;
+are_overlapping_1({S1,E1}=R, [{S2,E2}|Rs]) ->
+ (S2 < E1 andalso E2 > S1) orelse are_overlapping_1(R, Rs);
+are_overlapping_1({_,_}, []) -> false.
+
+%%%
+%%% Utilities.
+%%%
+
+%% is_loop_header(L, Blocks) -> false|true.
+%% Check whether the block is a loop header.
+
+is_loop_header(L, Blocks) ->
+ %% We KNOW that a loop header must start with a peek_message
+ %% instruction.
+ case maps:get(L, Blocks) of
+ #b_blk{is=[#b_set{op=peek_message}|_]} -> true;
+ _ -> false
+ end.
+
+rel2fam(S0) ->
+ S1 = sofs:relation(S0),
+ S = sofs:rel2fam(S1),
+ sofs:to_external(S).
+
+split_phis(Is) ->
+ partition(fun(#b_set{op=Op}) -> Op =:= phi end, Is).
+
+is_yreg({y,_}) -> true;
+is_yreg({x,_}) -> false;
+is_yreg({z,_}) -> false;
+is_yreg({fr,_}) -> false.
+
+new_vars([Base|Vs0], Count0) ->
+ {V,Count1} = new_var(Base, Count0),
+ {Vs,Count} = new_vars(Vs0, Count1),
+ {[V|Vs],Count};
+new_vars([], Count) -> {[],Count}.
+
+new_var({Base,Int}, Count) ->
+ true = is_integer(Int), %Assertion.
+ {#b_var{name={Base,Count}},Count+1};
+new_var(Base, Count) ->
+ {#b_var{name={Base,Count}},Count+1}.
diff --git a/lib/compiler/src/beam_ssa_recv.erl b/lib/compiler/src/beam_ssa_recv.erl
new file mode 100644
index 0000000000..6e49b128da
--- /dev/null
+++ b/lib/compiler/src/beam_ssa_recv.erl
@@ -0,0 +1,278 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(beam_ssa_recv).
+-export([module/2]).
+
+%%%
+%%% In code such as:
+%%%
+%%% Ref = make_ref(), %Or erlang:monitor(process, Pid)
+%%% .
+%%% .
+%%% .
+%%% receive
+%%% {Ref,Reply} -> Reply
+%%% end.
+%%%
+%%% we know that none of the messages that exist in the message queue
+%%% before the call to make_ref/0 can be matched out in the receive
+%%% statement. Therefore we can avoid going through the entire message
+%%% queue if we introduce two new instructions (here written as
+%%% BIFs in pseudo-Erlang):
+%%%
+%%% recv_mark(SomeUniqInteger),
+%%% Ref = make_ref(),
+%%% .
+%%% .
+%%% .
+%%% recv_set(SomeUniqInteger),
+%%% receive
+%%% {Ref,Reply} -> Reply
+%%% end.
+%%%
+%%% The recv_mark/1 instruction will save the current position and
+%%% SomeUniqInteger in the process context. The recv_set
+%%% instruction will verify that SomeUniqInteger is still stored
+%%% in the process context. If it is, it will set the current pointer
+%%% for the message queue (the next message to be read out) to the
+%%% position that was saved by recv_mark/1.
+%%%
+%%% The remove_message instruction must be modified to invalidate
+%%% the information stored by the previous recv_mark/1, in case there
+%%% is another receive executed between the calls to recv_mark/1 and
+%%% recv_set/1.
+%%%
+%%% We use a reference to a label (i.e. a position in the loaded code)
+%%% as the SomeUniqInteger.
+%%%
+
+-include("beam_ssa.hrl").
+-import(lists, [all/2,reverse/2]).
+
+-spec module(beam_ssa:b_module(), [compile:option()]) ->
+ {'ok',beam_ssa:b_module()}.
+
+module(#b_module{body=Fs0}=Module, _Opts) ->
+ Fs = [function(F) || F <- Fs0],
+ {ok,Module#b_module{body=Fs}}.
+
+%%%
+%%% Local functions.
+%%%
+
+function(#b_function{anno=Anno,bs=Blocks0}=F) ->
+ try
+ Blocks = opt(Blocks0),
+ F#b_function{bs=Blocks}
+ catch
+ Class:Error:Stack ->
+ #{func_info:={_,Name,Arity}} = Anno,
+ io:fwrite("Function: ~w/~w\n", [Name,Arity]),
+ erlang:raise(Class, Error, Stack)
+ end.
+
+opt(Blocks) ->
+ Linear = beam_ssa:linearize(Blocks),
+ opt(Linear, Blocks, []).
+
+opt([{L,#b_blk{is=[#b_set{op=peek_message}|_]}=Blk0}|Bs], Blocks0, Preds) ->
+ %% Search for a suitable reference creating call in one of the predecessor
+ %% blocks. Whether we find such a call or not, we always clear the
+ %% the list of predecessors to ensure that any nested receive can't
+ %% search above the current receive.
+ case recv_opt(Preds, L, Blocks0) of
+ {yes,Blocks1} ->
+ Blk = beam_ssa:add_anno(recv_set, L, Blk0),
+ Blocks = maps:put(L, Blk, Blocks1),
+ opt(Bs, Blocks, []);
+ no ->
+ opt(Bs, Blocks0, [])
+ end;
+opt([{L,_}|Bs], Blocks, Preds) ->
+ opt(Bs, Blocks, [L|Preds]);
+opt([], Blocks, _) -> Blocks.
+
+recv_opt([L|Ls], RecvLbl, Blocks) ->
+ #b_blk{is=Is0} = Blk0 = maps:get(L, Blocks),
+ case recv_opt_is(Is0, RecvLbl, Blocks, []) of
+ {yes,Is} ->
+ Blk = Blk0#b_blk{is=Is},
+ {yes,maps:put(L, Blk, Blocks)};
+ no ->
+ recv_opt(Ls, RecvLbl, Blocks)
+ end;
+recv_opt([], _, _Blocks) -> no.
+
+recv_opt_is([#b_set{op=call}=I0|Is], RecvLbl, Blocks0, Acc) ->
+ case makes_ref(I0, Blocks0) of
+ no ->
+ recv_opt_is(Is, RecvLbl, Blocks0, [I0|Acc]);
+ {yes,Ref} ->
+ case opt_ref_used(RecvLbl, Ref, Blocks0) of
+ false ->
+ recv_opt_is(Is, RecvLbl, Blocks0, [I0|Acc]);
+ true ->
+ I = beam_ssa:add_anno(recv_mark, RecvLbl, I0),
+ {yes,reverse(Acc, [I|Is])}
+ end
+ end;
+recv_opt_is([I|Is], RecvLbl, Blocks, Acc) ->
+ recv_opt_is(Is, RecvLbl, Blocks, [I|Acc]);
+recv_opt_is([], _, _, _) -> no.
+
+makes_ref(#b_set{dst=Dst,args=[Func0|_]}, Blocks) ->
+ Func = case Func0 of
+ #b_remote{mod=#b_literal{val=erlang},
+ name=#b_literal{val=Name},arity=A0} ->
+ {Name,A0};
+ _ ->
+ none
+ end,
+ case Func of
+ {make_ref,0} ->
+ {yes,Dst};
+ {monitor,2} ->
+ {yes,Dst};
+ {spawn_monitor,A} when A =:= 1; A =:= 3 ->
+ ref_in_tuple(Dst, Blocks);
+ _ ->
+ no
+ end.
+
+ref_in_tuple(Tuple, Blocks) ->
+ F = fun(#b_set{op=get_tuple_element,dst=Ref,
+ args=[#b_var{}=Tup,#b_literal{val=1}]}, no)
+ when Tup =:= Tuple -> {yes,Ref};
+ (_, A) -> A
+ end,
+ beam_ssa:fold_instrs_rpo(F, [0], no, Blocks).
+
+opt_ref_used(RecvLbl, Ref, Blocks) ->
+ Vs = #{Ref=>ref,ref=>Ref,ref_matched=>false},
+ case opt_ref_used_1(RecvLbl, Vs, Blocks) of
+ used -> true;
+ not_used -> false;
+ done -> false
+ end.
+
+opt_ref_used_1(L, Vs0, Blocks) ->
+ #b_blk{is=Is} = Blk = maps:get(L, Blocks),
+ case opt_ref_used_is(Is, Vs0) of
+ #{}=Vs ->
+ opt_ref_used_last(Blk, Vs, Blocks);
+ Result ->
+ Result
+ end.
+
+opt_ref_used_is([#b_set{op=peek_message,dst=Msg}|Is], Vs0) ->
+ Vs = Vs0#{Msg=>message},
+ opt_ref_used_is(Is, Vs);
+opt_ref_used_is([#b_set{op={bif,Bif},args=Args,dst=Dst}=I|Is],
+ Vs0) ->
+ S = case Bif of
+ '=:=' -> true;
+ '==' -> true;
+ _ -> none
+ end,
+ case S of
+ none ->
+ Vs = update_vars(I, Vs0),
+ opt_ref_used_is(Is, Vs);
+ Bool when is_boolean(Bool) ->
+ case is_ref_msg_comparison(Args, Vs0) of
+ true ->
+ Vs = Vs0#{Dst=>{is_ref,Bool}},
+ opt_ref_used_is(Is, Vs);
+ false ->
+ opt_ref_used_is(Is, Vs0)
+ end
+ end;
+opt_ref_used_is([#b_set{op=remove_message}|_], Vs) ->
+ case Vs of
+ #{ref_matched:=true} ->
+ used;
+ #{ref_matched:=false} ->
+ not_used
+ end;
+opt_ref_used_is([#b_set{op=recv_next}|_], _Vs) ->
+ done;
+opt_ref_used_is([#b_set{op=wait_timeout}|_], _Vs) ->
+ done;
+opt_ref_used_is([#b_set{op=wait}|_], _Vs) ->
+ done;
+opt_ref_used_is([#b_set{}=I|Is], Vs0) ->
+ Vs = update_vars(I, Vs0),
+ opt_ref_used_is(Is, Vs);
+opt_ref_used_is([], Vs) -> Vs.
+
+opt_ref_used_last(#b_blk{last=Last}=Blk, Vs, Blocks) ->
+ case Last of
+ #b_br{bool=#b_var{}=Bool,succ=Succ,fail=Fail} ->
+ case Vs of
+ #{Bool:={is_ref,Matched}} ->
+ ref_used_in([{Succ,Vs#{ref_matched:=Matched}},
+ {Fail,Vs#{ref_matched:=not Matched}}],
+ Blocks);
+ #{} ->
+ ref_used_in([{Succ,Vs},{Fail,Vs}], Blocks)
+ end;
+ _ ->
+ SuccVs = [{Succ,Vs} || Succ <- beam_ssa:successors(Blk)],
+ ref_used_in(SuccVs, Blocks)
+ end.
+
+ref_used_in([{L,Vs0}|Ls], Blocks) ->
+ case opt_ref_used_1(L, Vs0, Blocks) of
+ not_used ->
+ not_used;
+ used ->
+ case ref_used_in(Ls, Blocks) of
+ done -> used;
+ Result -> Result
+ end;
+ done -> ref_used_in(Ls, Blocks)
+ end;
+ref_used_in([], _) -> done.
+
+update_vars(#b_set{args=Args,dst=Dst}, Vs) ->
+ Vars = [V || #b_var{}=V <- Args],
+ All = all(fun(Var) ->
+ case Vs of
+ #{Var:=message} -> true;
+ #{} -> false
+ end
+ end, Vars),
+ case All of
+ true -> Vs#{Dst=>message};
+ false -> Vs
+ end.
+
+%% is_ref_msg_comparison(Args, Variables) -> true|false.
+%% Return 'true' if Args denotes a comparison between the
+%% reference and message or part of the message.
+
+is_ref_msg_comparison([#b_var{}=V1,#b_var{}=V2], Vs) ->
+ case Vs of
+ #{V1:=ref,V2:=message} -> true;
+ #{V1:=message,V2:=ref} -> true;
+ #{} -> false
+ end;
+is_ref_msg_comparison(_, _) -> false.
diff --git a/lib/compiler/src/beam_ssa_type.erl b/lib/compiler/src/beam_ssa_type.erl
new file mode 100644
index 0000000000..5ccc9c371b
--- /dev/null
+++ b/lib/compiler/src/beam_ssa_type.erl
@@ -0,0 +1,1193 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(beam_ssa_type).
+-export([opt/2]).
+
+-include("beam_ssa.hrl").
+-import(lists, [all/2,any/2,droplast/1,foldl/3,last/1,member/2,
+ reverse/1,sort/1]).
+
+-define(UNICODE_INT, #t_integer{elements={0,16#10FFFF}}).
+
+-record(d, {ds :: #{beam_ssa:var_name():=beam_ssa:b_set()},
+ ls :: #{beam_ssa:label():=type_db()},
+ sub :: #{beam_ssa:var_name():=beam_ssa:value()}
+ }).
+
+-define(ATOM_SET_SIZE, 5).
+
+%% Records that represent type information.
+-record(t_atom, {elements=any :: 'any' | [atom()]}).
+-record(t_integer, {elements=any :: 'any' | {integer(),integer()}}).
+-record(t_bs_match, {type :: type()}).
+-record(t_tuple, {size=0 :: integer(),
+ exact=false :: boolean(),
+ elements=[] :: [any()]
+ }).
+
+-type type() :: 'any' | 'none' |
+ #t_atom{} | #t_integer{} | #t_bs_match{} | #t_tuple{} |
+ {'binary',pos_integer()} | 'cons' | 'float' | 'list' | 'map' | 'nil' |'number'.
+-type type_db() :: #{beam_ssa:var_name():=type()}.
+
+-spec opt([{Label0,Block0}], Args) -> [{Label,Block}] when
+ Label0 :: beam_ssa:label(),
+ Block0 :: beam_ssa:b_blk(),
+ Args :: [beam_ssa:b_var()],
+ Label :: beam_ssa:label(),
+ Block :: beam_ssa:b_blk().
+
+opt(Linear, Args) ->
+ Ts = maps:from_list([{V,any} || #b_var{}=V <- Args]),
+ FakeCall = #b_set{op=call,args=[#b_remote{mod=#b_literal{val=unknown},
+ name=#b_literal{val=unknown},
+ arity=0}]},
+ Defs = maps:from_list([{Var,FakeCall#b_set{dst=Var}} ||
+ #b_var{}=Var <- Args]),
+ D = #d{ds=Defs,ls=#{0=>Ts},sub=#{}},
+ opt_1(Linear, D).
+
+opt_1([{L,Blk}|Bs], #d{ls=Ls}=D) ->
+ case Ls of
+ #{L:=Ts} ->
+ opt_2(L, Blk, Bs, Ts, D);
+ #{} ->
+ %% This block is never reached. Discard it.
+ opt_1(Bs, D)
+ end;
+opt_1([], #d{}) -> [].
+
+opt_2(L, #b_blk{is=Is0}=Blk0, Bs, Ts, #d{sub=Sub}=D0) ->
+ case Is0 of
+ [#b_set{op=call,dst=Dst,
+ args=[#b_remote{mod=#b_literal{val=Mod},
+ name=#b_literal{val=Name}}=Rem|Args0]}=I0] ->
+ case erl_bifs:is_exit_bif(Mod, Name, length(Args0)) of
+ true ->
+ %% This call will never reach the successor block.
+ %% Rewrite the terminator to a 'ret', and remove
+ %% all type information for this label. That will
+ %% simplify the phi node in the former successor.
+ Args = simplify_args(Args0, Sub, Ts),
+ I = I0#b_set{args=[Rem|Args]},
+ Ret = #b_ret{arg=Dst},
+ Blk = Blk0#b_blk{is=[I],last=Ret},
+ Ls = maps:remove(L, D0#d.ls),
+ D = D0#d{ls=Ls},
+ [{L,Blk}|opt_1(Bs, D)];
+ false ->
+ opt_3(L, Blk0, Bs, Ts, D0)
+ end;
+ _ ->
+ opt_3(L, Blk0, Bs, Ts, D0)
+ end.
+
+opt_3(L, #b_blk{is=Is0,last=Last0}=Blk0, Bs, Ts0,
+ #d{ds=Ds0,ls=Ls0,sub=Sub0}=D0) ->
+ {Is,Ts,Ds,Sub} = opt_is(Is0, Ts0, Ds0, Ls0, Sub0, []),
+ D1 = D0#d{ds=Ds,sub=Sub},
+ Last1 = simplify_terminator(Last0, Sub, Ts),
+ Last = opt_terminator(Last1, Ts, Ds),
+ D = update_successors(Last, Ts, D1),
+ Blk = Blk0#b_blk{is=Is,last=Last},
+ [{L,Blk}|opt_1(Bs, D)].
+
+simplify_terminator(#b_br{bool=Bool}=Br, Sub, Ts) ->
+ Br#b_br{bool=simplify_arg(Bool, Sub, Ts)};
+simplify_terminator(#b_switch{arg=Arg}=Sw, Sub, Ts) ->
+ Sw#b_switch{arg=simplify_arg(Arg, Sub, Ts)};
+simplify_terminator(#b_ret{arg=Arg}=Ret, Sub, Ts) ->
+ Ret#b_ret{arg=simplify_arg(Arg, Sub, Ts)}.
+
+opt_is([#b_set{op=phi,dst=Dst,args=Args0}=I0|Is],
+ Ts0, Ds0, Ls, Sub0, Acc) ->
+ %% Simplify the phi node by removing all predecessor blocks that no
+ %% longer exists or no longer branches to this block.
+ Args = [{simplify_arg(Arg, Sub0, Ts0),From} ||
+ {Arg,From} <- Args0, maps:is_key(From, Ls)],
+ case all_same(Args) of
+ true ->
+ %% Eliminate the phi node if there is just one source
+ %% value or if the values are identical.
+ [{Val,_}|_] = Args,
+ Sub = Sub0#{Dst=>Val},
+ opt_is(Is, Ts0, Ds0, Ls, Sub, Acc);
+ false ->
+ I = I0#b_set{args=Args},
+ Ts = update_types(I, Ts0, Ds0),
+ Ds = Ds0#{Dst=>I},
+ opt_is(Is, Ts, Ds, Ls, Sub0, [I|Acc])
+ end;
+opt_is([#b_set{args=Args0,dst=Dst}=I0|Is],
+ Ts0, Ds0, Ls, Sub0, Acc) ->
+ Args = simplify_args(Args0, Sub0, Ts0),
+ I1 = beam_ssa:normalize(I0#b_set{args=Args}),
+ case simplify(I1, Ts0) of
+ #b_set{}=I2 ->
+ I = beam_ssa:normalize(I2),
+ Ts = update_types(I, Ts0, Ds0),
+ Ds = Ds0#{Dst=>I},
+ opt_is(Is, Ts, Ds, Ls, Sub0, [I|Acc]);
+ #b_literal{}=Lit ->
+ Sub = Sub0#{Dst=>Lit},
+ opt_is(Is, Ts0, Ds0, Ls, Sub, Acc);
+ #b_var{}=Var ->
+ Sub = Sub0#{Dst=>Var},
+ opt_is(Is, Ts0, Ds0, Ls, Sub, Acc)
+ end;
+opt_is([], Ts, Ds, _Ls, Sub, Acc) ->
+ {reverse(Acc),Ts,Ds,Sub}.
+
+simplify(#b_set{op={bif,'and'},args=Args}=I, Ts) ->
+ case is_safe_bool_op(Args, Ts) of
+ true ->
+ case Args of
+ [_,#b_literal{val=false}=Res] -> Res;
+ [Res,#b_literal{val=true}] -> Res;
+ _ -> eval_bif(I, Ts)
+ end;
+ false ->
+ I
+ end;
+simplify(#b_set{op={bif,'or'},args=Args}=I, Ts) ->
+ case is_safe_bool_op(Args, Ts) of
+ true ->
+ case Args of
+ [Res,#b_literal{val=false}] -> Res;
+ [_,#b_literal{val=true}=Res] -> Res;
+ _ -> eval_bif(I, Ts)
+ end;
+ false ->
+ I
+ end;
+simplify(#b_set{op={bif,element},args=[#b_literal{val=Index},Tuple]}=I, Ts) ->
+ case t_tuple_size(get_type(Tuple, Ts)) of
+ {_,Size} when is_integer(Index), 1 =< Index, Index =< Size ->
+ I#b_set{op=get_tuple_element,args=[Tuple,#b_literal{val=Index-1}]};
+ _ ->
+ eval_bif(I, Ts)
+ end;
+simplify(#b_set{op={bif,hd},args=[List]}=I, Ts) ->
+ case get_type(List, Ts) of
+ cons ->
+ I#b_set{op=get_hd};
+ _ ->
+ eval_bif(I, Ts)
+ end;
+simplify(#b_set{op={bif,tl},args=[List]}=I, Ts) ->
+ case get_type(List, Ts) of
+ cons ->
+ I#b_set{op=get_tl};
+ _ ->
+ eval_bif(I, Ts)
+ end;
+simplify(#b_set{op={bif,size},args=[Term]}=I, Ts) ->
+ case get_type(Term, Ts) of
+ #t_tuple{} ->
+ simplify(I#b_set{op={bif,tuple_size}}, Ts);
+ _ ->
+ eval_bif(I, Ts)
+ end;
+simplify(#b_set{op={bif,tuple_size},args=[Term]}=I, Ts) ->
+ case get_type(Term, Ts) of
+ #t_tuple{size=Size,exact=true} ->
+ #b_literal{val=Size};
+ _ ->
+ I
+ end;
+simplify(#b_set{op={bif,'=='},args=Args}=I, Ts) ->
+ Types = get_types(Args, Ts),
+ EqEq = case {meet(Types),join(Types)} of
+ {none,any} -> true;
+ {#t_integer{},#t_integer{}} -> true;
+ {float,float} -> true;
+ {{binary,_},_} -> true;
+ {#t_atom{},_} -> true;
+ {_,_} -> false
+ end,
+ case EqEq of
+ true ->
+ simplify(I#b_set{op={bif,'=:='}}, Ts);
+ false ->
+ eval_bif(I, Ts)
+ end;
+simplify(#b_set{op={bif,'=:='},args=[Same,Same]}, _Ts) ->
+ #b_literal{val=true};
+simplify(#b_set{op={bif,'=:='},args=Args}=I, Ts) ->
+ case meet(get_types(Args, Ts)) of
+ none -> #b_literal{val=false};
+ _ -> eval_bif(I, Ts)
+ end;
+simplify(#b_set{op={bif,Op},args=Args}=I, Ts) ->
+ Types = get_types(Args, Ts),
+ case is_float_op(Op, Types) of
+ false ->
+ eval_bif(I, Ts);
+ true ->
+ AnnoArgs = [anno_float_arg(A) || A <- Types],
+ eval_bif(beam_ssa:add_anno(float_op, AnnoArgs, I), Ts)
+ end;
+simplify(#b_set{op=get_tuple_element,args=[Tuple,#b_literal{val=0}]}=I, Ts) ->
+ case get_type(Tuple, Ts) of
+ #t_tuple{elements=[First]} ->
+ #b_literal{val=First};
+ #t_tuple{} ->
+ I
+ end;
+simplify(#b_set{op=is_nonempty_list,args=[Src]}=I, Ts) ->
+ case get_type(Src, Ts) of
+ any -> I;
+ list -> I;
+ cons -> #b_literal{val=true};
+ _ -> #b_literal{val=false}
+ end;
+simplify(#b_set{op=is_tagged_tuple,
+ args=[Src,#b_literal{val=Size},#b_literal{val=Tag}]}=I, Ts) ->
+ case get_type(Src, Ts) of
+ #t_tuple{exact=true,size=Size,elements=[Tag]} ->
+ #b_literal{val=true};
+ #t_tuple{exact=true,size=ActualSize,elements=[]} ->
+ if
+ Size =/= ActualSize ->
+ #b_literal{val=false};
+ true ->
+ I
+ end;
+ #t_tuple{exact=false} ->
+ I;
+ any ->
+ I;
+ _ ->
+ #b_literal{val=false}
+ end;
+simplify(#b_set{op=put_list,args=[#b_literal{val=H},
+ #b_literal{val=T}]}, _Ts) ->
+ #b_literal{val=[H|T]};
+simplify(#b_set{op=put_tuple,args=Args}=I, _Ts) ->
+ case make_literal_list(Args) of
+ none -> I;
+ List -> #b_literal{val=list_to_tuple(List)}
+ end;
+simplify(#b_set{op=succeeded,args=[#b_literal{}]}, _Ts) ->
+ #b_literal{val=true};
+simplify(#b_set{op=wait_timeout,args=[#b_literal{val=infinity}]}=I, _Ts) ->
+ I#b_set{op=wait,args=[]};
+simplify(I, _Ts) -> I.
+
+make_literal_list(Args) ->
+ make_literal_list(Args, []).
+
+make_literal_list([#b_literal{val=H}|T], Acc) ->
+ make_literal_list(T, [H|Acc]);
+make_literal_list([_|_], _) ->
+ none;
+make_literal_list([], Acc) ->
+ reverse(Acc).
+
+is_safe_bool_op(Args, Ts) ->
+ [T1,T2] = get_types(Args, Ts),
+ t_is_boolean(T1) andalso t_is_boolean(T2).
+
+all_same([{H,_}|T]) ->
+ all(fun({E,_}) -> E =:= H end, T).
+
+eval_bif(#b_set{op={bif,Bif},args=Args}=I, Ts) ->
+ Arity = length(Args),
+ case erl_bifs:is_pure(erlang, Bif, Arity) of
+ false ->
+ I;
+ true ->
+ case make_literal_list(Args) of
+ none ->
+ case get_types(Args, Ts) of
+ [any] ->
+ I;
+ [Type] ->
+ case will_succeed(Bif, Type) of
+ yes ->
+ #b_literal{val=true};
+ no ->
+ #b_literal{val=false};
+ maybe ->
+ I
+ end;
+ _ ->
+ I
+ end;
+ LitArgs ->
+ try apply(erlang, Bif, LitArgs) of
+ Val -> #b_literal{val=Val}
+ catch
+ error:_ -> I
+ end
+
+ end
+ end.
+
+simplify_args(Args, Sub, Ts) ->
+ [simplify_arg(Arg, Sub, Ts) || Arg <- Args].
+
+simplify_arg(#b_var{}=Arg0, Sub, Ts) ->
+ case sub_arg(Arg0, Sub) of
+ #b_literal{}=LitArg ->
+ LitArg;
+ #b_var{}=Arg ->
+ Type = get_type(Arg, Ts),
+ case get_literal_from_type(Type) of
+ none -> Arg;
+ #b_literal{}=Lit -> Lit
+ end
+ end;
+simplify_arg(#b_remote{mod=Mod,name=Name}=Rem, Sub, Ts) ->
+ Rem#b_remote{mod=simplify_arg(Mod, Sub, Ts),
+ name=simplify_arg(Name, Sub, Ts)};
+simplify_arg(Arg, _Sub, _Ts) -> Arg.
+
+sub_arg(#b_var{}=Old, Sub) ->
+ case Sub of
+ #{Old:=New} -> New;
+ #{} -> Old
+ end.
+
+is_float_op('-', [float]) ->
+ true;
+is_float_op('/', [_,_]) ->
+ true;
+is_float_op(Op, [float,_Other]) ->
+ is_float_op_1(Op);
+is_float_op(Op, [_Other,float]) ->
+ is_float_op_1(Op);
+is_float_op(_, _) -> false.
+
+is_float_op_1('+') -> true;
+is_float_op_1('-') -> true;
+is_float_op_1('*') -> true;
+is_float_op_1(_) -> false.
+
+anno_float_arg(float) -> float;
+anno_float_arg(_) -> convert.
+
+opt_terminator(#b_br{bool=#b_literal{}}=Br, _Ts, _Ds) ->
+ beam_ssa:normalize(Br);
+opt_terminator(#b_br{bool=#b_var{}=V}=Br, Ts, Ds) ->
+ #{V:=Set} = Ds,
+ case Set of
+ #b_set{op={bif,'=:='},args=[Bool,#b_literal{val=true}]} ->
+ case t_is_boolean(get_type(Bool, Ts)) of
+ true ->
+ %% Bool =:= true ==> Bool
+ simplify_not(Br#b_br{bool=Bool}, Ts, Ds);
+ false ->
+ Br
+ end;
+ #b_set{} ->
+ simplify_not(Br, Ts, Ds)
+ end;
+opt_terminator(#b_switch{arg=#b_literal{}}=Sw, _Ts, _Ds) ->
+ beam_ssa:normalize(Sw);
+opt_terminator(#b_switch{arg=#b_var{}=V}=Sw0, Ts, Ds) ->
+ Type = get_type(V, Ts),
+ case Type of
+ #t_integer{elements={_,_}=Range} ->
+ simplify_switch_int(Sw0, Range);
+ _ ->
+ case t_is_boolean(Type) of
+ true ->
+ case simplify_switch_bool(Sw0, Ts, Ds) of
+ #b_br{}=Br ->
+ opt_terminator(Br, Ts, Ds);
+ Sw ->
+ beam_ssa:normalize(Sw)
+ end;
+ false ->
+ beam_ssa:normalize(Sw0)
+ end
+ end;
+opt_terminator(#b_ret{}=Ret, _Ts, _Ds) -> Ret.
+
+update_successors(#b_br{bool=#b_literal{val=true},succ=S}, Ts, D) ->
+ update_successor(S, Ts, D);
+update_successors(#b_br{bool=#b_var{}=Bool,succ=Succ,fail=Fail}, Ts, D0) ->
+ D = update_successor_bool(Bool, false, Fail, Ts, D0),
+ SuccTs = infer_types(Bool, Ts, D0),
+ update_successor_bool(Bool, true, Succ, SuccTs, D);
+update_successors(#b_switch{arg=#b_var{}=V,fail=Fail,list=List}, Ts, D0) ->
+ D = update_successor(Fail, Ts, D0),
+ foldl(fun({Val,S}, A) ->
+ T = get_type(Val, Ts),
+ update_successor(S, Ts#{V=>T}, A)
+ end, D, List);
+update_successors(#b_ret{}, _Ts, D) -> D.
+
+update_successor_bool(#b_var{}=Var, BoolValue, S, Ts, D) ->
+ case t_is_boolean(get_type(Var, Ts)) of
+ true ->
+ update_successor(S, Ts#{Var:=t_atom(BoolValue)}, D);
+ false ->
+ %% The `br` terminator is preceeded by an instruction that
+ %% does not produce a boolean value, such a `new_try_tag`.
+ update_successor(S, Ts, D)
+ end.
+
+update_successor(S, Ts0, #d{ls=Ls}=D) ->
+ case Ls of
+ #{S:=Ts1} ->
+ Ts = join_types(Ts0, Ts1),
+ D#d{ls=Ls#{S:=Ts}};
+ #{} ->
+ D#d{ls=Ls#{S=>Ts0}}
+ end.
+
+update_types(#b_set{op=Op,dst=Dst,args=Args}, Ts, Ds) ->
+ T = type(Op, Args, Ts, Ds),
+ Ts#{Dst=>T}.
+
+type(phi, Args, Ts, _Ds) ->
+ Types = [get_type(A, Ts) || {A,_} <- Args],
+ join(Types);
+type({bif,'band'}, Args, Ts, _Ds) ->
+ band_type(Args, Ts);
+type({bif,Bif}, Args, Ts, _Ds) ->
+ case bif_type(Bif, Args) of
+ number ->
+ arith_op_type(Args, Ts);
+ Type ->
+ Type
+ end;
+type(bs_init, [#b_literal{val=Type}|Args], _Ts, _Ds) ->
+ case {Type,Args} of
+ {new,[_,#b_literal{val=Unit}]} ->
+ {binary,Unit};
+ {append,[_,_,#b_literal{val=Unit}]} ->
+ {binary,Unit};
+ {private_append,[_,_,#b_literal{val=Unit}]} ->
+ {binary,Unit}
+ end;
+type(bs_extract, [Ctx], Ts, _Ds) ->
+ #t_bs_match{type=Type} = get_type(Ctx, Ts),
+ Type;
+type(bs_match, Args, _Ts, _Ds) ->
+ #t_bs_match{type=bs_match_type(Args)};
+type(call, [#b_remote{mod=#b_literal{val=Mod},
+ name=#b_literal{val=Name}}|Args], Ts, _Ds) ->
+ case {Mod,Name,Args} of
+ {erlang,setelement,[Pos,Tuple,_]} ->
+ case {get_type(Pos, Ts),get_type(Tuple, Ts)} of
+ {#t_integer{elements={MinIndex,_}},#t_tuple{}=T}
+ when MinIndex > 1 ->
+ %% First element is not updated. The result
+ %% will have the same type.
+ T;
+ {_,#t_tuple{}=T} ->
+ %% Position is 1 or unknown. May update the first
+ %% element of the tuple.
+ T#t_tuple{elements=[]};
+ {#t_integer{elements={MinIndex,_}},_} ->
+ #t_tuple{size=MinIndex};
+ {_,_} ->
+ #t_tuple{}
+ end;
+ {math,_,_} ->
+ case is_math_bif(Name, length(Args)) of
+ false -> any;
+ true -> float
+ end;
+ {_,_,_} ->
+ case erl_bifs:is_exit_bif(Mod, Name, length(Args)) of
+ true -> none;
+ false -> any
+ end
+ end;
+type(is_nonempty_list, [_], _Ts, _Ds) ->
+ t_boolean();
+type(is_tagged_tuple, [_,#b_literal{},#b_literal{}], _Ts, _Ds) ->
+ t_boolean();
+type(put_map, _Args, _Ts, _Ds) ->
+ map;
+type(put_list, _Args, _Ts, _Ds) ->
+ cons;
+type(put_tuple, Args, _Ts, _Ds) ->
+ case Args of
+ [#b_literal{val=First}|_] ->
+ #t_tuple{exact=true,size=length(Args),elements=[First]};
+ _ ->
+ #t_tuple{exact=true,size=length(Args)}
+ end;
+type(succeeded, [#b_var{}=Src], Ts, Ds) ->
+ case maps:get(Src, Ds) of
+ #b_set{op={bif,Bif},args=BifArgs} ->
+ Types = get_types(BifArgs, Ts),
+ case {Bif,Types} of
+ {BoolOp,[T1,T2]} when BoolOp =:= 'and'; BoolOp =:= 'or' ->
+ case t_is_boolean(T1) andalso t_is_boolean(T2) of
+ true -> t_atom(true);
+ false -> t_boolean()
+ end;
+ {byte_size,[{binary,_}]} ->
+ t_atom(true);
+ {bit_size,[{binary,_}]} ->
+ t_atom(true);
+ {map_size,[map]} ->
+ t_atom(true);
+ {'not',[Type]} ->
+ case t_is_boolean(Type) of
+ true -> t_atom(true);
+ false -> t_boolean()
+ end;
+ {size,[{binary,_}]} ->
+ t_atom(true);
+ {tuple_size,[#t_tuple{}]} ->
+ t_atom(true);
+ {_,_} ->
+ t_boolean()
+ end;
+ #b_set{op=get_hd} ->
+ t_atom(true);
+ #b_set{op=get_tl} ->
+ t_atom(true);
+ #b_set{op=get_tuple_element} ->
+ t_atom(true);
+ #b_set{op=wait} ->
+ t_atom(false);
+ #b_set{} ->
+ t_boolean()
+ end;
+type(_, _, _, _) -> any.
+
+arith_op_type(Args, Ts) ->
+ Types = get_types(Args, Ts),
+ foldl(fun(#t_integer{}, unknown) -> t_integer();
+ (#t_integer{}, number) -> number;
+ (#t_integer{}, float) -> float;
+ (#t_integer{}, #t_integer{}) -> t_integer();
+ (float, unknown) -> float;
+ (float, #t_integer{}) -> float;
+ (float, number) -> float;
+ (number, unknown) -> number;
+ (number, #t_integer{}) -> number;
+ (number, float) -> float;
+ (any, _) -> number;
+ (Same, Same) -> Same;
+ (_, _) -> none
+ end, unknown, Types).
+
+%% will_succeed(TestOperation, Type) -> yes|no|maybe.
+%% Test whether TestOperation applied to an argument of type Type
+%% will succeed. Return yes, no, or maybe.
+%%
+%% Type is a type as described in the comment for verified_type/1 at
+%% the very end of this file, but it will *never* be 'any'.
+
+will_succeed(is_atom, Type) ->
+ case Type of
+ #t_atom{} -> yes;
+ _ -> no
+ end;
+will_succeed(is_binary, Type) ->
+ case Type of
+ {binary,U} when U rem 8 =:= 0 -> yes;
+ {binary,_} -> maybe;
+ _ -> no
+ end;
+will_succeed(is_bitstring, Type) ->
+ case Type of
+ {binary,_} -> yes;
+ _ -> no
+ end;
+will_succeed(is_boolean, Type) ->
+ case Type of
+ #t_atom{elements=any} ->
+ maybe;
+ #t_atom{elements=Es} ->
+ case t_is_boolean(Type) of
+ true ->
+ yes;
+ false ->
+ case any(fun is_boolean/1, Es) of
+ true -> maybe;
+ false -> no
+ end
+ end;
+ _ ->
+ no
+ end;
+will_succeed(is_float, Type) ->
+ case Type of
+ float -> yes;
+ number -> maybe;
+ _ -> no
+ end;
+will_succeed(is_integer, Type) ->
+ case Type of
+ #t_integer{} -> yes;
+ number -> maybe;
+ _ -> no
+ end;
+will_succeed(is_list, Type) ->
+ case Type of
+ list -> yes;
+ cons -> yes;
+ _ -> no
+ end;
+will_succeed(is_map, Type) ->
+ case Type of
+ map -> yes;
+ _ -> no
+ end;
+will_succeed(is_number, Type) ->
+ case Type of
+ float -> yes;
+ #t_integer{} -> yes;
+ number -> yes;
+ _ -> no
+ end;
+will_succeed(is_tuple, Type) ->
+ case Type of
+ #t_tuple{} -> yes;
+ _ -> no
+ end;
+will_succeed(_, _) -> maybe.
+
+
+band_type([Other,#b_literal{val=Int}], Ts) when is_integer(Int) ->
+ band_type_1(Int, Other, Ts);
+band_type([_,_], _) -> t_integer().
+
+band_type_1(Int, OtherSrc, Ts) ->
+ Type = band_type_2(Int, 0),
+ OtherType = get_type(OtherSrc, Ts),
+ meet(Type, OtherType).
+
+band_type_2(N, Bits) when Bits < 64 ->
+ case 1 bsl Bits of
+ P when P =:= N + 1 ->
+ t_integer(0, N);
+ P when P > N + 1 ->
+ t_integer();
+ _ ->
+ band_type_2(N, Bits+1)
+ end;
+band_type_2(_, _) ->
+ %% Negative or large positive number. Give up.
+ t_integer().
+
+bs_match_type([#b_literal{val=Type}|Args]) ->
+ bs_match_type(Type, Args).
+
+bs_match_type(binary, Args) ->
+ [_,_,_,#b_literal{val=U}] = Args,
+ {binary,U};
+bs_match_type(float, _) ->
+ float;
+bs_match_type(integer, Args) ->
+ case Args of
+ [_,
+ #b_literal{val=Flags},
+ #b_literal{val=Size},
+ #b_literal{val=Unit}] when Size * Unit < 64 ->
+ NumBits = Size * Unit,
+ case member(unsigned, Flags) of
+ true ->
+ t_integer(0, (1 bsl NumBits)-1);
+ false ->
+ %% Signed integer. Don't bother.
+ t_integer()
+ end;
+ [_|_] ->
+ t_integer()
+ end;
+bs_match_type(skip, _) ->
+ any;
+bs_match_type(string, _) ->
+ any;
+bs_match_type(utf8, _) ->
+ ?UNICODE_INT;
+bs_match_type(utf16, _) ->
+ ?UNICODE_INT;
+bs_match_type(utf32, _) ->
+ ?UNICODE_INT.
+
+simplify_switch_int(#b_switch{list=List0}=Sw, {Min,Max}) ->
+ List1 = sort(List0),
+ Vs = [V || {#b_literal{val=V},_} <- List1],
+ case eq_ranges(Vs, Min, Max) of
+ true ->
+ {_,LastL} = last(List1),
+ List = droplast(List1),
+ Sw#b_switch{fail=LastL,list=List};
+ false ->
+ Sw
+ end.
+
+eq_ranges([H], H, H) -> true;
+eq_ranges([H|T], H, Max) -> eq_ranges(T, H+1, Max);
+eq_ranges(_, _, _) -> false.
+
+simplify_switch_bool(#b_switch{arg=B,list=List0}=Sw, Ts, Ds) ->
+ List = sort(List0),
+ case List of
+ [{#b_literal{val=false},Fail},{#b_literal{val=true},Succ}] ->
+ simplify_not(#b_br{bool=B,succ=Succ,fail=Fail}, Ts, Ds);
+ [_|_] ->
+ Sw
+ end.
+
+simplify_not(#b_br{bool=#b_var{}=V,succ=Succ,fail=Fail}=Br0, Ts, Ds) ->
+ case Ds of
+ #{V:=#b_set{op={bif,'not'},args=[Bool]}} ->
+ case t_is_boolean(get_type(Bool, Ts)) of
+ true ->
+ Br = Br0#b_br{bool=Bool,succ=Fail,fail=Succ},
+ beam_ssa:normalize(Br);
+ false ->
+ Br0
+ end;
+ #{} ->
+ Br0
+ end.
+
+get_types(Values, Ts) ->
+ [get_type(Val, Ts) || Val <- Values].
+-spec get_type(beam_ssa:value(), type_db()) -> type().
+
+get_type(#b_var{}=V, Ts) ->
+ #{V:=T} = Ts,
+ T;
+get_type(#b_literal{val=Val}, _Ts) ->
+ if
+ is_atom(Val) ->
+ t_atom(Val);
+ is_float(Val) ->
+ float;
+ is_integer(Val) ->
+ t_integer(Val);
+ is_list(Val), Val =/= [] ->
+ cons;
+ is_map(Val) ->
+ map;
+ Val =:= {} ->
+ #t_tuple{exact=true};
+ is_tuple(Val) ->
+ #t_tuple{exact=true,size=tuple_size(Val),
+ elements=[element(1, Val)]};
+ Val =:= [] ->
+ nil;
+ true ->
+ any
+ end.
+
+infer_types(#b_var{}=V, Ts, #d{ds=Ds}) ->
+ #{V:=#b_set{op=Op,args=Args}} = Ds,
+ Types = infer_type(Op, Args, Ds),
+ meet_types(Types, Ts).
+
+infer_type({bif,element}, [#b_literal{val=Pos},#b_var{}=Tuple], _Ds) ->
+ if
+ is_integer(Pos), 1 =< Pos ->
+ [{Tuple,#t_tuple{size=Pos}}];
+ true ->
+ []
+ end;
+infer_type({bif,'=:='}, [#b_var{}=Src,#b_literal{}=Lit], Ds) ->
+ Def = maps:get(Src, Ds),
+ Type = get_type(Lit, #{}),
+ [{Src,Type}|infer_tuple_size(Def, Lit) ++
+ infer_first_element(Def, Lit)];
+infer_type({bif,Bif}, [#b_var{}=Src]=Args, _Ds) ->
+ case inferred_bif_type(Bif, Args) of
+ any -> [];
+ T -> [{Src,T}]
+ end;
+infer_type({bif,is_map_key}, [_,#b_var{}=Src], _Ds) ->
+ [{Src,map}];
+infer_type({bif,map_get}, [_,#b_var{}=Src], _Ds) ->
+ [{Src,map}];
+infer_type(bs_start_match, [#b_var{}=Bin], _Ds) ->
+ [{Bin,{binary,1}}];
+infer_type(is_nonempty_list, [#b_var{}=Src], _Ds) ->
+ [{Src,cons}];
+infer_type(is_tagged_tuple, [#b_var{}=Src,#b_literal{val=Size},
+ #b_literal{val=Tag}], _Ds) ->
+ [{Src,#t_tuple{exact=true,size=Size,elements=[Tag]}}];
+infer_type(succeeded, [#b_var{}=Src], Ds) ->
+ #b_set{op=Op,args=Args} = maps:get(Src, Ds),
+ infer_type(Op, Args, Ds);
+infer_type(_Op, _Args, _Ds) ->
+ [].
+
+%% bif_type(Name, Args) -> Type
+%% Return the return type for the guard BIF or operator Name with
+%% arguments Args.
+%%
+%% Note that that the following BIFs are handle elsewhere:
+%%
+%% band/2
+
+bif_type(abs, [_]) -> number;
+bif_type(bit_size, [_]) -> t_integer();
+bif_type(byte_size, [_]) -> t_integer();
+bif_type(ceil, [_]) -> t_integer();
+bif_type(float, [_]) -> float;
+bif_type(floor, [_]) -> t_integer();
+bif_type(is_map_key, [_,_]) -> t_boolean();
+bif_type(length, [_]) -> t_integer();
+bif_type(map_size, [_]) -> t_integer();
+bif_type(node, []) -> #t_atom{};
+bif_type(node, [_]) -> #t_atom{};
+bif_type(round, [_]) -> t_integer();
+bif_type(size, [_]) -> t_integer();
+bif_type(trunc, [_]) -> t_integer();
+bif_type(tuple_size, [_]) -> t_integer();
+bif_type('bnot', [_]) -> t_integer();
+bif_type('bor', [_,_]) -> t_integer();
+bif_type('bsl', [_,_]) -> t_integer();
+bif_type('bsr', [_,_]) -> t_integer();
+bif_type('bxor', [_,_]) -> t_integer();
+bif_type('div', [_,_]) -> t_integer();
+bif_type('rem', [_,_]) -> t_integer();
+bif_type('/', [_,_]) -> float;
+bif_type(Name, Args) ->
+ Arity = length(Args),
+ case erl_internal:new_type_test(Name, Arity) orelse
+ erl_internal:bool_op(Name, Arity) orelse
+ erl_internal:comp_op(Name, Arity) of
+ true ->
+ t_boolean();
+ false ->
+ case erl_internal:arith_op(Name, Arity) of
+ true -> number;
+ false -> any
+ end
+ end.
+
+inferred_bif_type(is_atom, [_]) -> t_atom();
+inferred_bif_type(is_binary, [_]) -> {binary,8};
+inferred_bif_type(is_bitstring, [_]) -> {binary,1};
+inferred_bif_type(is_boolean, [_]) -> t_boolean();
+inferred_bif_type(is_float, [_]) -> float;
+inferred_bif_type(is_integer, [_]) -> t_integer();
+inferred_bif_type(is_list, [_]) -> list;
+inferred_bif_type(is_map, [_]) -> map;
+inferred_bif_type(is_number, [_]) -> number;
+inferred_bif_type(is_tuple, [_]) -> #t_tuple{};
+inferred_bif_type(abs, [_]) -> number;
+inferred_bif_type(bit_size, [_]) -> {binary,1};
+inferred_bif_type(byte_size, [_]) -> {binary,1};
+inferred_bif_type(ceil, [_]) -> number;
+inferred_bif_type(float, [_]) -> number;
+inferred_bif_type(floor, [_]) -> number;
+inferred_bif_type(hd, [_]) -> cons;
+inferred_bif_type(length, [_]) -> list;
+inferred_bif_type(map_size, [_]) -> map;
+inferred_bif_type(round, [_]) -> number;
+inferred_bif_type(trunc, [_]) -> number;
+inferred_bif_type(tl, [_]) -> cons;
+inferred_bif_type(tuple_size, [_]) -> #t_tuple{};
+inferred_bif_type(_, _) -> any.
+
+infer_tuple_size(#b_set{op={bif,tuple_size},args=[#b_var{}=Tuple]},
+ #b_literal{val=Size}) when is_integer(Size) ->
+ [{Tuple,#t_tuple{exact=true,size=Size}}];
+infer_tuple_size(_, _) -> [].
+
+infer_first_element(#b_set{op=get_tuple_element,
+ args=[#b_var{}=Tuple,#b_literal{val=0}]},
+ #b_literal{val=First}) ->
+ [{Tuple,#t_tuple{size=1,elements=[First]}}];
+infer_first_element(_, _) -> [].
+
+is_math_bif(cos, 1) -> true;
+is_math_bif(cosh, 1) -> true;
+is_math_bif(sin, 1) -> true;
+is_math_bif(sinh, 1) -> true;
+is_math_bif(tan, 1) -> true;
+is_math_bif(tanh, 1) -> true;
+is_math_bif(acos, 1) -> true;
+is_math_bif(acosh, 1) -> true;
+is_math_bif(asin, 1) -> true;
+is_math_bif(asinh, 1) -> true;
+is_math_bif(atan, 1) -> true;
+is_math_bif(atanh, 1) -> true;
+is_math_bif(erf, 1) -> true;
+is_math_bif(erfc, 1) -> true;
+is_math_bif(exp, 1) -> true;
+is_math_bif(log, 1) -> true;
+is_math_bif(log2, 1) -> true;
+is_math_bif(log10, 1) -> true;
+is_math_bif(sqrt, 1) -> true;
+is_math_bif(atan2, 2) -> true;
+is_math_bif(pow, 2) -> true;
+is_math_bif(ceil, 1) -> true;
+is_math_bif(floor, 1) -> true;
+is_math_bif(fmod, 2) -> true;
+is_math_bif(pi, 0) -> true;
+is_math_bif(_, _) -> false.
+
+join_types(Ts0, Ts1) ->
+ if
+ map_size(Ts0) < map_size(Ts1) ->
+ join_types_1(maps:keys(Ts0), Ts1, Ts0);
+ true ->
+ join_types_1(maps:keys(Ts1), Ts0, Ts1)
+ end.
+
+join_types_1([V|Vs], Ts0, Ts1) ->
+ case {Ts0,Ts1} of
+ {#{V:=Same},#{V:=Same}} ->
+ join_types_1(Vs, Ts0, Ts1);
+ {#{V:=T0},#{V:=T1}} ->
+ case join(T0, T1) of
+ T1 ->
+ join_types_1(Vs, Ts0, Ts1);
+ T ->
+ join_types_1(Vs, Ts0, Ts1#{V:=T})
+ end;
+ {#{},#{V:=_}} ->
+ join_types_1(Vs, Ts0, Ts1)
+ end;
+join_types_1([], Ts0, Ts1) ->
+ maps:merge(Ts0, Ts1).
+
+join([T1,T2|Ts]) ->
+ join([join(T1, T2)|Ts]);
+join([T]) -> T.
+
+get_literal_from_type(#t_atom{elements=[Atom]}) ->
+ #b_literal{val=Atom};
+get_literal_from_type(#t_integer{elements={Int,Int}}) ->
+ #b_literal{val=Int};
+get_literal_from_type(nil) ->
+ #b_literal{val=[]};
+get_literal_from_type(_) -> none.
+
+t_atom() ->
+ #t_atom{elements=any}.
+
+t_atom(Atom) when is_atom(Atom) ->
+ #t_atom{elements=[Atom]}.
+
+t_boolean() ->
+ #t_atom{elements=[false,true]}.
+
+t_integer() ->
+ #t_integer{elements=any}.
+
+t_integer(Int) when is_integer(Int) ->
+ #t_integer{elements={Int,Int}}.
+
+t_integer(Min, Max) when is_integer(Min), is_integer(Max) ->
+ #t_integer{elements={Min,Max}}.
+
+t_is_boolean(#t_atom{elements=[F,T]}) ->
+ F =:= false andalso T =:= true;
+t_is_boolean(#t_atom{elements=[B]}) ->
+ is_boolean(B);
+t_is_boolean(_) -> false.
+
+t_tuple_size(#t_tuple{size=Size,exact=false}) ->
+ {at_least,Size};
+t_tuple_size(#t_tuple{size=Size,exact=true}) ->
+ {exact,Size};
+t_tuple_size(_) ->
+ none.
+
+%% join(Type1, Type2) -> Type
+%% Return the "join" of Type1 and Type2. The join is a more general
+%% type than Type1 and Type2. For example:
+%%
+%% join(#t_integer{elements=any}, #t_integer=elements={0,3}}) ->
+%% #t_integer{}
+%%
+%% The join for two different types result in 'any', which is
+%% the top element for our type lattice:
+%%
+%% join(#t_integer{}, map) -> any
+
+-spec join(type(), type()) -> type().
+
+join(T, T) ->
+ verified_type(T);
+join(none, T) ->
+ verified_type(T);
+join(T, none) ->
+ verified_type(T);
+join(any, _) -> any;
+join(_, any) -> any;
+join(#t_atom{elements=[_|_]=Set1}, #t_atom{elements=[_|_]=Set2}) ->
+ Set = ordsets:union(Set1, Set2),
+ case ordsets:size(Set) of
+ Size when Size =< ?ATOM_SET_SIZE ->
+ #t_atom{elements=Set};
+ _Size ->
+ #t_atom{elements=any}
+ end;
+join(#t_atom{elements=any}=T, #t_atom{elements=[_|_]}) -> T;
+join(#t_atom{elements=[_|_]}, #t_atom{elements=any}=T) -> T;
+join({binary,U1}, {binary,U2}) ->
+ {binary,gcd(U1, U2)};
+join(#t_integer{}, #t_integer{}) -> t_integer();
+join(list, cons) -> list;
+join(cons, list) -> list;
+join(nil, cons) -> list;
+join(cons, nil) -> list;
+join(nil, list) -> list;
+join(list, nil) -> list;
+join(#t_integer{}, float) -> number;
+join(float, #t_integer{}) -> number;
+join(#t_integer{}, number) -> number;
+join(number, #t_integer{}) -> number;
+join(float, number) -> number;
+join(number, float) -> number;
+join(#t_tuple{size=Sz,exact=Exact1}, #t_tuple{size=Sz,exact=Exact2}) ->
+ Exact = Exact1 and Exact2,
+ #t_tuple{size=Sz,exact=Exact};
+join(#t_tuple{size=Sz1}, #t_tuple{size=Sz2}) ->
+ #t_tuple{size=min(Sz1, Sz2)};
+join(_T1, _T2) ->
+ %%io:format("~p ~p\n", [_T1,_T2]),
+ any.
+
+gcd(A, B) ->
+ case A rem B of
+ 0 -> B;
+ X -> gcd(B, X)
+ end.
+
+meet_types([{V,T0}|Vs], Ts) ->
+ #{V:=T1} = Ts,
+ T = meet(T0, T1),
+ meet_types(Vs, Ts#{V:=T});
+meet_types([], Ts) -> Ts.
+
+meet([T1,T2|Ts]) ->
+ meet([meet(T1, T2)|Ts]);
+meet([T]) -> T.
+
+%% meet(Type1, Type2) -> Type
+%% Return the "meet" of Type1 and Type2. The meet is a narrower
+%% type than Type1 and Type2. For example:
+%%
+%% meet(#t_integer{elements=any}, #t_integer{elements={0,3}}) ->
+%% #t_integer{elements={0,3}}
+%%
+%% The meet for two different types result in 'none', which is
+%% the bottom element for our type lattice:
+%%
+%% meet(#t_integer{}, map) -> none
+
+-spec meet(type(), type()) -> type().
+
+meet(T, T) ->
+ verified_type(T);
+meet(#t_atom{elements=[_|_]=Set1}, #t_atom{elements=[_|_]=Set2}) ->
+ case ordsets:intersection(Set1, Set2) of
+ [] ->
+ none;
+ [_|_]=Set ->
+ #t_atom{elements=Set}
+ end;
+meet(#t_atom{elements=[_|_]}=T, #t_atom{elements=any}) ->
+ T;
+meet(#t_atom{elements=any}, #t_atom{elements=[_|_]}=T) ->
+ T;
+meet(#t_integer{elements={_,_}}=T, #t_integer{elements=any}) ->
+ T;
+meet(#t_integer{elements=any}, #t_integer{elements={_,_}}=T) ->
+ T;
+meet(#t_integer{elements={Min1,Max1}},
+ #t_integer{elements={Min2,Max2}}) ->
+ #t_integer{elements={max(Min1, Min2),min(Max1, Max2)}};
+meet(#t_integer{}=T, number) -> T;
+meet(float=T, number) -> T;
+meet(number, #t_integer{}=T) -> T;
+meet(number, float=T) -> T;
+meet(list, cons) -> cons;
+meet(list, nil) -> nil;
+meet(cons, list) -> cons;
+meet(nil, list) -> nil;
+meet(#t_tuple{}=T1, #t_tuple{}=T2) ->
+ meet_tuples(T1, T2);
+meet({binary,U1}, {binary,U2}) ->
+ {binary,max(U1, U2)};
+meet(any, T) ->
+ verified_type(T);
+meet(T, any) ->
+ verified_type(T);
+meet(_, _) ->
+ %% Inconsistent types. There will be an exception at runtime.
+ none.
+
+meet_tuples(#t_tuple{elements=[E1]}, #t_tuple{elements=[E2]})
+ when E1 =/= E2 ->
+ none;
+meet_tuples(#t_tuple{size=Sz1,exact=true},
+ #t_tuple{size=Sz2,exact=true}) when Sz1 =/= Sz2 ->
+ none;
+meet_tuples(#t_tuple{size=Sz1,exact=Ex1,elements=Es1},
+ #t_tuple{size=Sz2,exact=Ex2,elements=Es2}) ->
+ Size = max(Sz1, Sz2),
+ Exact = Ex1 or Ex2,
+ Es = case {Es1,Es2} of
+ {[],[_|_]} -> Es2;
+ {[_|_],[]} -> Es1;
+ {_,_} -> Es1
+ end,
+ #t_tuple{size=Size,exact=Exact,elements=Es}.
+
+%% verified_type(Type) -> Type
+%% Returns the passed in type if it is one of the defined types.
+%% Crashes if there is anything wrong with the type.
+%%
+%% Here are all possible types:
+%%
+%% any Any Erlang term (top element for the type lattice).
+%%
+%% #t_atom{} Any atom or some specific atoms.
+%% {binary,Unit} Binary/bitstring aligned to unit Unit.
+%% float Floating point number.
+%% #t_integer{} Integer
+%% list Empty or nonempty list.
+%% map Map.
+%% nil Empty list.
+%% cons Cons (nonempty list).
+%% number A number (float or integer).
+%% #t_tuple{} Tuple.
+%%
+%% none No type (bottom element for the type lattice).
+
+-spec verified_type(T) -> T when
+ T :: type().
+
+verified_type(any=T) -> T;
+verified_type(none=T) -> T;
+verified_type(#t_atom{elements=any}=T) -> T;
+verified_type(#t_atom{elements=[_|_]}=T) -> T;
+verified_type({binary,U}=T) when is_integer(U) -> T;
+verified_type(#t_integer{elements=any}=T) -> T;
+verified_type(#t_integer{elements={Min,Max}}=T)
+ when is_integer(Min), is_integer(Max) -> T;
+verified_type(list=T) -> T;
+verified_type(map=T) -> T;
+verified_type(nil=T) -> T;
+verified_type(cons=T) -> T;
+verified_type(number=T) -> T;
+verified_type(#t_tuple{}=T) -> T;
+verified_type(float=T) -> T.
diff --git a/lib/compiler/src/beam_trim.erl b/lib/compiler/src/beam_trim.erl
index 4da0985085..1acbedd45b 100644
--- a/lib/compiler/src/beam_trim.erl
+++ b/lib/compiler/src/beam_trim.erl
@@ -288,7 +288,7 @@ frame_size([{get_map_elements,{f,L},_,_}|Is], Safe) ->
frame_size([{deallocate,N}|_], _) -> N;
frame_size([{line,_}|Is], Safe) ->
frame_size(Is, Safe);
-frame_size([_|_], _) -> throw(not_possible).
+frame_size(_, _) -> throw(not_possible).
frame_size_branch(0, Is, Safe) ->
frame_size(Is, Safe);
diff --git a/lib/compiler/src/beam_type.erl b/lib/compiler/src/beam_type.erl
deleted file mode 100644
index b5c979e529..0000000000
--- a/lib/compiler/src/beam_type.erl
+++ /dev/null
@@ -1,1117 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%% Purpose: Type-based optimisations. See the comment for verified_type/1
-%% the very end of this file for a description of the types in the
-%% type database.
-
--module(beam_type).
-
--export([module/2]).
-
--import(lists, [foldl/3,member/2,reverse/1,reverse/2,sort/1]).
-
--define(UNICODE_INT, {integer,{0,16#10FFFF}}).
-
--spec module(beam_utils:module_code(), [compile:option()]) ->
- {'ok',beam_utils:module_code()}.
-
-module({Mod,Exp,Attr,Fs0,Lc}, _Opts) ->
- Fs = [function(F) || F <- Fs0],
- {ok,{Mod,Exp,Attr,Fs,Lc}}.
-
-function({function,Name,Arity,CLabel,Asm0}) ->
- try
- Asm1 = beam_utils:live_opt(Asm0),
- Asm2 = opt(Asm1, [], tdb_new()),
- Asm3 = beam_utils:live_opt(Asm2),
- Asm = beam_utils:delete_annos(Asm3),
- {function,Name,Arity,CLabel,Asm}
- catch
- Class:Error:Stack ->
- io:fwrite("Function: ~w/~w\n", [Name,Arity]),
- erlang:raise(Class, Error, Stack)
- end.
-
-%% opt([Instruction], Accumulator, TypeDb) -> {[Instruction'],TypeDb'}
-%% Keep track of type information; try to simplify.
-
-opt([{block,Body1}|Is], [{block,Body0}|Acc], Ts0) ->
- {Body2,Ts} = simplify(Body1, Ts0),
- Body = merge_blocks(Body0, Body2),
- opt(Is, [{block,Body}|Acc], Ts);
-opt([{block,Body0}|Is], Acc, Ts0) ->
- {Body,Ts} = simplify(Body0, Ts0),
- opt(Is, [{block,Body}|Acc], Ts);
-opt([I0|Is], Acc, Ts0) ->
- case simplify_basic([I0], Ts0) of
- {[],Ts} -> opt(Is, Acc, Ts);
- {[I],Ts} -> opt(Is, [I|Acc], Ts)
- end;
-opt([], Acc, _) -> reverse(Acc).
-
-%% simplify(Instruction, TypeDb) -> NewInstruction
-%% Simplify an instruction using type information (this is
-%% technically a "strength reduction").
-
-simplify(Is0, TypeDb0) ->
- {Is,_} = BasicRes = simplify_basic(Is0, TypeDb0),
- case simplify_float(Is, TypeDb0) of
- not_possible -> BasicRes;
- {_,_}=Res -> Res
- end.
-
-%% simplify_basic([Instruction], TypeDatabase) -> {[Instruction],TypeDatabase'}
-%% Basic simplification, mostly tuples, no floating point optimizations.
-
-simplify_basic(Is, Ts) ->
- simplify_basic(Is, Ts, []).
-
-simplify_basic([I0|Is], Ts0, Acc) ->
- case simplify_instr(I0, Ts0) of
- [] ->
- simplify_basic(Is, Ts0, Acc);
- [I] ->
- Ts = update(I, Ts0),
- simplify_basic(Is, Ts, [I|Acc])
- end;
-simplify_basic([], Ts, Acc) ->
- {reverse(Acc),Ts}.
-
-%% simplify_instr(Instruction, Ts) -> [Instruction].
-
-%% Simplify a simple instruction using type information. Return an
-%% empty list if the instruction should be removed, or a list with
-%% the original or modified instruction.
-
-simplify_instr({set,[D],[{integer,Index},Reg],{bif,element,_}}=I, Ts) ->
- case max_tuple_size(Reg, Ts) of
- Sz when 0 < Index, Index =< Sz ->
- [{set,[D],[Reg],{get_tuple_element,Index-1}}];
- _ -> [I]
- end;
-simplify_instr({test,Test,Fail,[R]}=I, Ts) ->
- case tdb_find(R, Ts) of
- any ->
- [I];
- Type ->
- case will_succeed(Test, Type) of
- yes -> [];
- no -> [{jump,Fail}];
- maybe -> [I]
- end
- end;
-simplify_instr({set,[D],[TupleReg],{get_tuple_element,0}}=I, Ts) ->
- case tdb_find(TupleReg, Ts) of
- {tuple,_,_,[Contents]} ->
- [{set,[D],[Contents],move}];
- _ ->
- [I]
- end;
-simplify_instr({test,test_arity,_,[R,Arity]}=I, Ts) ->
- case tdb_find(R, Ts) of
- {tuple,exact_size,Arity,_} -> [];
- _ -> [I]
- end;
-simplify_instr({test,is_eq_exact,Fail,[R,{atom,A}=Atom]}=I, Ts) ->
- case tdb_find(R, Ts) of
- {atom,_}=Atom -> [];
- boolean when is_boolean(A) -> [I];
- any -> [I];
- _ -> [{jump,Fail}]
- end;
-simplify_instr({test,is_record,_,[R,{atom,_}=Tag,{integer,Arity}]}=I, Ts) ->
- case tdb_find(R, Ts) of
- {tuple,exact_size,Arity,[Tag]} -> [];
- _ -> [I]
- end;
-simplify_instr({select,select_val,Reg,_,_}=I, Ts) ->
- [case tdb_find(Reg, Ts) of
- {integer,Range} ->
- simplify_select_val_int(I, Range);
- boolean ->
- simplify_select_val_bool(I);
- _ ->
- I
- end];
-simplify_instr({test,bs_test_unit,_,[Src,Unit]}=I, Ts) ->
- case tdb_find(Src, Ts) of
- {binary,U} when U rem Unit =:= 0 -> [];
- _ -> [I]
- end;
-simplify_instr(I, _) -> [I].
-
-simplify_select_val_int({select,select_val,R,_,L0}=I, {Min,Max}) ->
- Vs = sort([V || {integer,V} <- L0]),
- case eq_ranges(Vs, Min, Max) of
- false -> I;
- true -> simplify_select_val_1(L0, {integer,Max}, R, [])
- end.
-
-simplify_select_val_bool({select,select_val,R,_,L}=I) ->
- Vs = sort([V || {atom,V} <- L]),
- case Vs of
- [false,true] ->
- simplify_select_val_1(L, {atom,false}, R, []);
- _ ->
- I
- end.
-
-simplify_select_val_1([Val,F|T], Val, R, Acc) ->
- L = reverse(Acc, T),
- {select,select_val,R,F,L};
-simplify_select_val_1([V,F|T], Val, R, Acc) ->
- simplify_select_val_1(T, Val, R, [F,V|Acc]).
-
-eq_ranges([H], H, H) -> true;
-eq_ranges([H|T], H, Max) -> eq_ranges(T, H+1, Max);
-eq_ranges(_, _, _) -> false.
-
-%% will_succeed(TestOperation, Type) -> yes|no|maybe.
-%% Test whether TestOperation applied to an argument of type Type
-%% will succeed. Return yes, no, or maybe.
-%%
-%% Type is a type as described in the comment for verified_type/1 at
-%% the very end of this file, but it will *never* be 'any'.
-
-will_succeed(is_atom, Type) ->
- case Type of
- {atom,_} -> yes;
- boolean -> yes;
- _ -> no
- end;
-will_succeed(is_binary, Type) ->
- case Type of
- {binary,U} when U rem 8 =:= 0 -> yes;
- {binary,_} -> maybe;
- _ -> no
- end;
-will_succeed(is_bitstr, Type) ->
- case Type of
- {binary,_} -> yes;
- _ -> no
- end;
-will_succeed(is_integer, Type) ->
- case Type of
- integer -> yes;
- {integer,_} -> yes;
- _ -> no
- end;
-will_succeed(is_map, Type) ->
- case Type of
- map -> yes;
- _ -> no
- end;
-will_succeed(is_nonempty_list, Type) ->
- case Type of
- nonempty_list -> yes;
- _ -> no
- end;
-will_succeed(is_tuple, Type) ->
- case Type of
- {tuple,_,_,_} -> yes;
- _ -> no
- end;
-will_succeed(_, _) -> maybe.
-
-%% simplify_float([Instruction], TypeDatabase) ->
-%% {[Instruction],TypeDatabase'} | not_possible
-%% Simplify floating point operations in blocks.
-%%
-simplify_float(Is0, Ts0) ->
- {Is1,Ts} = simplify_float_1(Is0, Ts0, [], []),
- Is2 = opt_fmoves(Is1, []),
- Is3 = flt_need_heap(Is2),
- try
- {flt_liveness(Is3),Ts}
- catch
- throw:not_possible -> not_possible
- end.
-
-simplify_float_1([{set,[],[],fclearerror}|Is], Ts, Rs, Acc) ->
- simplify_float_1(Is, Ts, Rs, clearerror(Acc));
-simplify_float_1([{set,[],[],fcheckerror}|Is], Ts, Rs, Acc) ->
- simplify_float_1(Is, Ts, Rs, checkerror(Acc));
-simplify_float_1([{set,[{fr,_}],_,_}=I|Is], Ts, Rs, Acc) ->
- simplify_float_1(Is, Ts, Rs, [I|Acc]);
-simplify_float_1([{set,[D0],[A0],{alloc,_,{gc_bif,'-',{f,0}}}}=I|Is]=Is0,
- Ts0, Rs0, Acc0) ->
- case tdb_find(A0, Ts0) of
- float ->
- A = coerce_to_float(A0),
- {Rs1,Acc1} = load_reg(A, Ts0, Rs0, Acc0),
- {D,Rs} = find_dest(D0, Rs1),
- Areg = fetch_reg(A, Rs),
- Acc = [{set,[D],[Areg],{bif,fnegate,{f,0}}}|clearerror(Acc1)],
- Ts = tdb_store(D0, float, Ts0),
- simplify_float_1(Is, Ts, Rs, Acc);
- _Other ->
- Ts = update(I, Ts0),
- {Rs,Acc} = flush(Rs0, Is0, Acc0),
- simplify_float_1(Is, Ts, Rs, [I|checkerror(Acc)])
- end;
-simplify_float_1([{set,[D0],[A0,B0],{alloc,_,{gc_bif,Op0,{f,0}}}}=I|Is]=Is0,
- Ts0, Rs0, Acc0) ->
- case float_op(Op0, A0, B0, Ts0) of
- no ->
- Ts = update(I, Ts0),
- {Rs,Acc} = flush(Rs0, Is0, Acc0),
- simplify_float_1(Is, Ts, Rs, [I|checkerror(Acc)]);
- {yes,Op} ->
- A = coerce_to_float(A0),
- B = coerce_to_float(B0),
- {Rs1,Acc1} = load_reg(A, Ts0, Rs0, Acc0),
- {Rs2,Acc2} = load_reg(B, Ts0, Rs1, Acc1),
- {D,Rs} = find_dest(D0, Rs2),
- Areg = fetch_reg(A, Rs),
- Breg = fetch_reg(B, Rs),
- Acc = [{set,[D],[Areg,Breg],{bif,Op,{f,0}}}|clearerror(Acc2)],
- Ts = tdb_store(D0, float, Ts0),
- simplify_float_1(Is, Ts, Rs, Acc)
- end;
-simplify_float_1([{set,_,_,{try_catch,_,_}}=I|Is]=Is0, _Ts, Rs0, Acc0) ->
- Acc = flush_all(Rs0, Is0, Acc0),
- simplify_float_1(Is, tdb_new(), Rs0, [I|Acc]);
-simplify_float_1([{set,_,_,{line,_}}=I|Is], Ts, Rs, Acc) ->
- simplify_float_1(Is, Ts, Rs, [I|Acc]);
-simplify_float_1([I|Is], Ts0, [], Acc) ->
- Ts = update(I, Ts0),
- simplify_float_1(Is, Ts, [], [I|Acc]);
-simplify_float_1([I|Is]=Is0, Ts0, Rs0, Acc0) ->
- Ts = update(I, Ts0),
- {Rs,Acc} = flush(Rs0, Is0, Acc0),
- simplify_float_1(Is, Ts, Rs, [I|checkerror(Acc)]);
-simplify_float_1([], Ts, [], Acc) ->
- Is = reverse(Acc),
- {Is,Ts}.
-
-coerce_to_float({integer,I}=Int) ->
- try float(I) of
- F ->
- {float,F}
- catch _:_ ->
- %% Let the overflow happen at run-time.
- Int
- end;
-coerce_to_float(Other) -> Other.
-
-opt_fmoves([{set,[{x,_}=R],[{fr,_}]=Src,fmove}=I1,
- {set,[_]=Dst,[{x,_}=R],move}=I2|Is], Acc) ->
- case beam_utils:is_killed_block(R, Is) of
- false -> opt_fmoves(Is, [I2,I1|Acc]);
- true -> opt_fmoves(Is, [{set,Dst,Src,fmove}|Acc])
- end;
-opt_fmoves([I|Is], Acc) ->
- opt_fmoves(Is, [I|Acc]);
-opt_fmoves([], Acc) -> reverse(Acc).
-
-clearerror(Is) ->
- clearerror(Is, Is).
-
-clearerror([{set,[],[],fclearerror}|_], OrigIs) -> OrigIs;
-clearerror([{set,[],[],fcheckerror}|_], OrigIs) -> [{set,[],[],fclearerror}|OrigIs];
-clearerror([_|Is], OrigIs) -> clearerror(Is, OrigIs);
-clearerror([], OrigIs) -> [{set,[],[],fclearerror}|OrigIs].
-
-%% merge_blocks(Block1, Block2) -> Block.
-%% Combine two blocks and eliminate any move instructions that assign
-%% to registers that are killed later in the block.
-%%
-merge_blocks(B1, [{'%anno',_}|B2]) ->
- merge_blocks_1(B1++[{set,[],[],stop_here}|B2]).
-
-merge_blocks_1([{set,[],_,stop_here}|Is]) -> Is;
-merge_blocks_1([{set,[D],_,move}=I|Is]) ->
- case beam_utils:is_killed_block(D, Is) of
- true -> merge_blocks_1(Is);
- false -> [I|merge_blocks_1(Is)]
- end;
-merge_blocks_1([I|Is]) -> [I|merge_blocks_1(Is)].
-
-%% flt_need_heap([Instruction]) -> [Instruction]
-%% Insert need heap allocation instructions in the instruction stream
-%% to properly account for both inserted floating point operations and
-%% normal term build operations (such as put_list/3).
-%%
-%% Ignore old heap allocation instructions (except if they allocate a stack
-%% frame too), as they may be in the wrong place (because gc_bif instructions
-%% could have been converted to floating point operations).
-
-flt_need_heap(Is) ->
- flt_need_heap_1(reverse(Is), 0, 0, []).
-
-flt_need_heap_1([{set,[],[],{alloc,_,Alloc}}|Is], H, Fl, Acc) ->
- case Alloc of
- {_,nostack,_,_} ->
- %% Remove any existing test_heap/2 instruction.
- flt_need_heap_1(Is, H, Fl, Acc);
- {Z,Stk,_,Inits} when is_integer(Stk) ->
- %% Keep any allocate*/2 instruction and recalculate heap need.
- I = {set,[],[],{alloc,regs,{Z,Stk,build_alloc(H, Fl),Inits}}},
- flt_need_heap_1(Is, 0, 0, [I|Acc])
- end;
-flt_need_heap_1([I|Is], H0, Fl0, Acc) ->
- {Ns,H1,Fl1} = flt_need_heap_2(I, H0, Fl0),
- flt_need_heap_1(Is, H1, Fl1, [I|Ns]++Acc);
-flt_need_heap_1([], H, Fl, Acc) ->
- flt_alloc(H, Fl) ++ Acc.
-
-%% First come all instructions that build. We pass through, while we
-%% add to the need for heap words and floats on the heap.
-flt_need_heap_2({set,[_],[{fr,_}],fmove}, H, Fl) ->
- {[],H,Fl+1};
-flt_need_heap_2({set,_,_,put_list}, H, Fl) ->
- {[],H+2,Fl};
-flt_need_heap_2({set,_,_,{put_tuple,_}}, H, Fl) ->
- {[],H+1,Fl};
-flt_need_heap_2({set,_,_,put}, H, Fl) ->
- {[],H+1,Fl};
-%% The following instructions cause the insertion of an allocation
-%% instruction if needed.
-flt_need_heap_2({set,_,_,{alloc,_,_}}, H, Fl) ->
- {flt_alloc(H, Fl),0,0};
-flt_need_heap_2({set,_,_,{set_tuple_element,_}}, H, Fl) ->
- {flt_alloc(H, Fl),0,0};
-flt_need_heap_2({'%anno',_}, H, Fl) ->
- {flt_alloc(H, Fl),0,0};
-%% All other instructions are "neutral". We just pass them.
-flt_need_heap_2(_, H, Fl) ->
- {[],H,Fl}.
-
-flt_alloc(0, 0) ->
- [];
-flt_alloc(H, 0) ->
- [{set,[],[],{alloc,regs,{nozero,nostack,H,[]}}}];
-flt_alloc(H, F) ->
- [{set,[],[],{alloc,regs,{nozero,nostack,
- build_alloc(H, F),[]}}}].
-
-build_alloc(Words, 0) -> Words;
-build_alloc(Words, Floats) -> {alloc,[{words,Words},{floats,Floats}]}.
-
-
-%% flt_liveness([Instruction]) -> [Instruction]
-%% (Re)calculate the number of live registers for each heap allocation
-%% function. We base liveness of the number of register map at the
-%% beginning of the instruction sequence.
-%%
-%% A 'not_possible' term will be thrown if the set of live registers
-%% is not continous at an allocation function (e.g. if {x,0} and {x,2}
-%% are live, but not {x,1}).
-
-flt_liveness([{'%anno',{used,Regs}}=LiveInstr|Is]) ->
- flt_liveness_1(Is, Regs, [LiveInstr]).
-
-flt_liveness_1([{set,Ds,Ss,{alloc,Live0,Alloc}}|Is], Regs0, Acc) ->
- Live = min(Live0, live_regs(Regs0)),
- I = {set,Ds,Ss,{alloc,Live,Alloc}},
- Regs1 = init_regs(Live),
- Regs = x_live(Ds, Regs1),
- flt_liveness_1(Is, Regs, [I|Acc]);
-flt_liveness_1([{set,Ds,_,_}=I|Is], Regs0, Acc) ->
- Regs = x_live(Ds, Regs0),
- flt_liveness_1(Is, Regs, [I|Acc]);
-flt_liveness_1([{'%anno',_}], _Regs, Acc) ->
- reverse(Acc).
-
-init_regs(Live) ->
- (1 bsl Live) - 1.
-
-live_regs(Regs) ->
- live_regs_1(Regs, 0).
-
-live_regs_1(0, N) -> N;
-live_regs_1(R, N) ->
- case R band 1 of
- 0 -> throw(not_possible);
- 1 -> live_regs_1(R bsr 1, N+1)
- end.
-
-x_live([{x,N}|Rs], Regs) -> x_live(Rs, Regs bor (1 bsl N));
-x_live([_|Rs], Regs) -> x_live(Rs, Regs);
-x_live([], Regs) -> Regs.
-
-%% update(Instruction, TypeDb) -> NewTypeDb
-%% Update the type database to account for executing an instruction.
-%%
-%% First the cases for instructions inside basic blocks.
-update({'%anno',_}, Ts) ->
- Ts;
-update({set,[D],[S],move}, Ts) ->
- tdb_copy(S, D, Ts);
-update({set,[D],[Index,Reg],{bif,element,_}}, Ts0) ->
- MinSize = case Index of
- {integer,I} -> I;
- _ -> 0
- end,
- Ts = tdb_meet(Reg, {tuple,min_size,MinSize,[]}, Ts0),
- tdb_store(D, any, Ts);
-update({set,[D],[_Key,Map],{bif,map_get,_}}, Ts0) ->
- Ts = tdb_meet(Map, map, Ts0),
- tdb_store(D, any, Ts);
-update({set,[D],Args,{bif,N,_}}, Ts) ->
- Ar = length(Args),
- BoolOp = erl_internal:new_type_test(N, Ar) orelse
- erl_internal:comp_op(N, Ar) orelse
- erl_internal:bool_op(N, Ar),
- Type = case BoolOp of
- true -> boolean;
- false -> unary_op_type(N)
- end,
- tdb_store(D, Type, Ts);
-update({set,[D],[S],{get_tuple_element,0}}, Ts0) ->
- if
- D =:= S ->
- tdb_store(D, any, Ts0);
- true ->
- Ts = tdb_store(D, {tuple_element,S,0}, Ts0),
- tdb_store(S, {tuple,min_size,1,[]}, Ts)
- end;
-update({set,[D],[S],{alloc,_,{gc_bif,float,{f,0}}}}, Ts0) ->
- %% Make sure we reject non-numeric literal argument.
- case possibly_numeric(S) of
- true -> tdb_store(D, float, Ts0);
- false -> Ts0
- end;
-update({set,[D],[S1,S2],{alloc,_,{gc_bif,'band',{f,0}}}}, Ts) ->
- Type = band_type(S1, S2, Ts),
- tdb_store(D, Type, Ts);
-update({set,[D],[S1,S2],{alloc,_,{gc_bif,'/',{f,0}}}}, Ts) ->
- %% Make sure we reject non-numeric literals.
- case possibly_numeric(S1) andalso possibly_numeric(S2) of
- true -> tdb_store(D, float, Ts);
- false -> Ts
- end;
-update({set,[D],[S1,S2],{alloc,_,{gc_bif,Op,{f,0}}}}, Ts0) ->
- case op_type(Op) of
- integer ->
- tdb_store(D, integer, Ts0);
- {float,_} ->
- case {tdb_find(S1, Ts0),tdb_find(S2, Ts0)} of
- {float,_} -> tdb_store(D, float, Ts0);
- {_,float} -> tdb_store(D, float, Ts0);
- {_,_} -> tdb_store(D, any, Ts0)
- end;
- Type ->
- tdb_store(D, Type, Ts0)
- end;
-update({set,[D],[_],{alloc,_,{gc_bif,Op,{f,0}}}}, Ts) ->
- tdb_store(D, unary_op_type(Op), Ts);
-update({set,[],_Src,_Op}, Ts) ->
- Ts;
-update({set,[D],_Src,_Op}, Ts) ->
- tdb_store(D, any, Ts);
-update({kill,D}, Ts) ->
- tdb_store(D, any, Ts);
-
-%% Instructions outside of blocks.
-update({test,test_arity,_Fail,[Src,Arity]}, Ts) ->
- tdb_meet(Src, {tuple,exact_size,Arity,[]}, Ts);
-update({get_map_elements,_,Src,{list,Elems0}}, Ts0) ->
- Ts1 = tdb_meet(Src, map, Ts0),
- {_Ss,Ds} = beam_utils:split_even(Elems0),
- foldl(fun(Dst, A) -> tdb_store(Dst, any, A) end, Ts1, Ds);
-update({test,is_eq_exact,_,[Reg,{atom,_}=Atom]}, Ts0) ->
- Ts = case tdb_find_source_tuple(Reg, Ts0) of
- {source_tuple,TupleReg} ->
- tdb_meet(TupleReg, {tuple,min_size,1,[Atom]}, Ts0);
- none ->
- Ts0
- end,
- tdb_meet(Reg, Atom, Ts);
-update({test,is_record,_Fail,[Src,Tag,{integer,Arity}]}, Ts) ->
- tdb_meet(Src, {tuple,exact_size,Arity,[Tag]}, Ts);
-
-%% Binaries and binary matching.
-
-update({test,bs_get_integer2,_,_,Args,Dst}, Ts) ->
- tdb_store(Dst, get_bs_integer_type(Args), Ts);
-update({test,bs_get_utf8,_,_,_,Dst}, Ts) ->
- tdb_store(Dst, ?UNICODE_INT, Ts);
-update({test,bs_get_utf16,_,_,_,Dst}, Ts) ->
- tdb_store(Dst, ?UNICODE_INT, Ts);
-update({test,bs_get_utf32,_,_,_,Dst}, Ts) ->
- tdb_store(Dst, ?UNICODE_INT, Ts);
-update({bs_init,_,{bs_init2,_,_},_,_,Dst}, Ts) ->
- tdb_store(Dst, {binary,8}, Ts);
-update({bs_init,_,_,_,_,Dst}, Ts) ->
- tdb_store(Dst, {binary,1}, Ts);
-update({bs_put,_,_,_}, Ts) ->
- Ts;
-update({bs_save2,_,_}, Ts) ->
- Ts;
-update({bs_restore2,_,_}, Ts) ->
- Ts;
-update({bs_context_to_binary,Dst}, Ts) ->
- tdb_store(Dst, any, Ts);
-update({test,bs_start_match2,_,_,[Src,_],Dst}, Ts0) ->
- Ts = tdb_meet(Src, {binary,1}, Ts0),
- tdb_copy(Src, Dst, Ts);
-update({test,bs_get_binary2,_,_,[_,_,Unit,_],Dst}, Ts) ->
- true = is_integer(Unit), %Assertion.
- tdb_store(Dst, {binary,Unit}, Ts);
-update({test,bs_get_float2,_,_,_,Dst}, Ts) ->
- tdb_store(Dst, float, Ts);
-update({test,bs_test_unit,_,[Src,Unit]}, Ts) ->
- tdb_meet(Src, {binary,Unit}, Ts);
-
-%% Other test instructions
-update({test,Test,_Fail,[Src]}, Ts) ->
- Type = case Test of
- is_binary -> {binary,8};
- is_bitstr -> {binary,1};
- is_boolean -> boolean;
- is_float -> float;
- is_integer -> integer;
- is_map -> map;
- is_nonempty_list -> nonempty_list;
- _ -> any
- end,
- tdb_meet(Src, Type, Ts);
-update({test,_Test,_Fail,_Other}, Ts) ->
- Ts;
-
-%% Calls
-
-update({call_ext,Ar,{extfunc,math,Math,Ar}}, Ts) ->
- case is_math_bif(Math, Ar) of
- true -> tdb_store({x,0}, float, Ts);
- false -> tdb_kill_xregs(Ts)
- end;
-update({call_ext,3,{extfunc,erlang,setelement,3}}, Ts0) ->
- Ts = tdb_kill_xregs(Ts0),
- case tdb_find({x,1}, Ts0) of
- {tuple,SzKind,Sz,_}=T0 ->
- T = case tdb_find({x,0}, Ts0) of
- {integer,{I,I}} when I > 1 ->
- %% First element is not changed. The result
- %% will have the same type.
- T0;
- _ ->
- %% Position is 1 or unknown. May change the
- %% first element of the tuple.
- {tuple,SzKind,Sz,[]}
- end,
- tdb_store({x,0}, T, Ts);
- _ ->
- Ts
- end;
-update({call,_Arity,_Func}, Ts) -> tdb_kill_xregs(Ts);
-update({call_ext,_Arity,_Func}, Ts) -> tdb_kill_xregs(Ts);
-update({make_fun2,_,_,_,_}, Ts) -> tdb_kill_xregs(Ts);
-update({call_fun, _}, Ts) -> tdb_kill_xregs(Ts);
-update({apply, _}, Ts) -> tdb_kill_xregs(Ts);
-
-update({line,_}, Ts) -> Ts;
-update({'%',_}, Ts) -> Ts;
-
-%% The instruction is unknown. Kill all information.
-update(_I, _Ts) -> tdb_new().
-
-band_type({integer,Int}, Other, Ts) ->
- band_type_1(Int, Other, Ts);
-band_type(Other, {integer,Int}, Ts) ->
- band_type_1(Int, Other, Ts);
-band_type(_, _, _) -> integer.
-
-band_type_1(Int, OtherSrc, Ts) ->
- Type = band_type_2(Int, 0),
- OtherType = tdb_find(OtherSrc, Ts),
- meet(Type, OtherType).
-
-band_type_2(N, Bits) when Bits < 64 ->
- case 1 bsl Bits of
- P when P =:= N + 1 ->
- {integer,{0,N}};
- P when P > N + 1 ->
- integer;
- _ ->
- band_type_2(N, Bits+1)
- end;
-band_type_2(_, _) ->
- %% Negative or large positive number. Give up.
- integer.
-
-get_bs_integer_type([_,{integer,N},U,{field_flags,Fl}])
- when N*U < 64 ->
- NumBits = N*U,
- case member(unsigned, Fl) of
- true ->
- {integer,{0,(1 bsl NumBits)-1}};
- false ->
- %% Signed integer. Don't bother.
- integer
- end;
-get_bs_integer_type(_) ->
- %% Avoid creating ranges with a huge upper limit.
- integer.
-
-is_math_bif(cos, 1) -> true;
-is_math_bif(cosh, 1) -> true;
-is_math_bif(sin, 1) -> true;
-is_math_bif(sinh, 1) -> true;
-is_math_bif(tan, 1) -> true;
-is_math_bif(tanh, 1) -> true;
-is_math_bif(acos, 1) -> true;
-is_math_bif(acosh, 1) -> true;
-is_math_bif(asin, 1) -> true;
-is_math_bif(asinh, 1) -> true;
-is_math_bif(atan, 1) -> true;
-is_math_bif(atanh, 1) -> true;
-is_math_bif(erf, 1) -> true;
-is_math_bif(erfc, 1) -> true;
-is_math_bif(exp, 1) -> true;
-is_math_bif(log, 1) -> true;
-is_math_bif(log2, 1) -> true;
-is_math_bif(log10, 1) -> true;
-is_math_bif(sqrt, 1) -> true;
-is_math_bif(atan2, 2) -> true;
-is_math_bif(pow, 2) -> true;
-is_math_bif(ceil, 1) -> true;
-is_math_bif(floor, 1) -> true;
-is_math_bif(fmod, 2) -> true;
-is_math_bif(pi, 0) -> true;
-is_math_bif(_, _) -> false.
-
-%% Reject non-numeric literals.
-possibly_numeric({x,_}) -> true;
-possibly_numeric({y,_}) -> true;
-possibly_numeric({integer,_}) -> true;
-possibly_numeric({float,_}) -> true;
-possibly_numeric(_) -> false.
-
-max_tuple_size(Reg, Ts) ->
- case tdb_find(Reg, Ts) of
- {tuple,_,Sz,_} -> Sz;
- _Other -> 0
- end.
-
-float_op('/', A, B, _) ->
- case possibly_numeric(A) andalso possibly_numeric(B) of
- true -> {yes,fdiv};
- false -> no
- end;
-float_op(Op, {float,_}, B, _) ->
- case possibly_numeric(B) of
- true -> arith_op(Op);
- false -> no
- end;
-float_op(Op, A, {float,_}, _) ->
- case possibly_numeric(A) of
- true -> arith_op(Op);
- false -> no
- end;
-float_op(Op, A, B, Ts) ->
- case {tdb_find(A, Ts),tdb_find(B, Ts)} of
- {float,_} -> arith_op(Op);
- {_,float} -> arith_op(Op);
- {_,_} -> no
- end.
-
-find_dest(V, Rs0) ->
- case find_reg(V, Rs0) of
- {ok,FR} ->
- {FR,mark(V, Rs0, dirty)};
- error ->
- Rs = put_reg(V, Rs0, dirty),
- {ok,FR} = find_reg(V, Rs),
- {FR,Rs}
- end.
-
-load_reg({float,_}=F, _, Rs0, Is0) ->
- Rs = put_reg(F, Rs0, clean),
- {ok,FR} = find_reg(F, Rs),
- Is = [{set,[FR],[F],fmove}|Is0],
- {Rs,Is};
-load_reg(V, Ts, Rs0, Is0) ->
- case find_reg(V, Rs0) of
- {ok,_FR} -> {Rs0,Is0};
- error ->
- Rs = put_reg(V, Rs0, clean),
- {ok,FR} = find_reg(V, Rs),
- Op = case tdb_find(V, Ts) of
- float -> fmove;
- _ -> fconv
- end,
- Is = [{set,[FR],[V],Op}|Is0],
- {Rs,Is}
- end.
-
-arith_op(Op) ->
- case op_type(Op) of
- {float,Instr} -> {yes,Instr};
- _ -> no
- end.
-
-op_type('+') -> {float,fadd};
-op_type('-') -> {float,fsub};
-op_type('*') -> {float,fmul};
-%% '/' and 'band' are specially handled.
-op_type('bor') -> integer;
-op_type('bxor') -> integer;
-op_type('bsl') -> integer;
-op_type('bsr') -> integer;
-op_type('div') -> integer;
-op_type(_) -> any.
-
-unary_op_type(bit_size) -> integer;
-unary_op_type(byte_size) -> integer;
-unary_op_type(length) -> integer;
-unary_op_type(map_size) -> integer;
-unary_op_type(size) -> integer;
-unary_op_type(tuple_size) -> integer;
-unary_op_type(_) -> any.
-
-flush(Rs, [{set,[_],[_,_,_],{bif,is_record,_}}|_]=Is0, Acc0) ->
- Acc = flush_all(Rs, Is0, Acc0),
- {[],Acc};
-flush(Rs, [{set,[_],[],{put_tuple,_}}|_]=Is0, Acc0) ->
- Acc = flush_all(Rs, Is0, Acc0),
- {[],Acc};
-flush(Rs0, [{set,Ds,Ss,_Op}|_], Acc0) ->
- Save = cerl_sets:from_list(Ss),
- Acc = save_regs(Rs0, Save, Acc0),
- Rs1 = foldl(fun(S, A) -> mark(S, A, clean) end, Rs0, Ss),
- Kill = cerl_sets:from_list(Ds),
- Rs = kill_regs(Rs1, Kill),
- {Rs,Acc};
-flush(Rs0, Is, Acc0) ->
- Acc = flush_all(Rs0, Is, Acc0),
- {[],Acc}.
-
-flush_all([{_,{float,_},_}|Rs], Is, Acc) ->
- flush_all(Rs, Is, Acc);
-flush_all([{I,V,dirty}|Rs], Is, Acc0) ->
- Acc = checkerror(Acc0),
- case beam_utils:is_killed_block(V, Is) of
- true -> flush_all(Rs, Is, Acc);
- false -> flush_all(Rs, Is, [{set,[V],[{fr,I}],fmove}|Acc])
- end;
-flush_all([{_,_,clean}|Rs], Is, Acc) -> flush_all(Rs, Is, Acc);
-flush_all([free|Rs], Is, Acc) -> flush_all(Rs, Is, Acc);
-flush_all([], _, Acc) -> Acc.
-
-save_regs(Rs, Save, Acc) ->
- foldl(fun(R, A) -> save_reg(R, Save, A) end, Acc, Rs).
-
-save_reg({I,V,dirty}, Save, Acc) ->
- case cerl_sets:is_element(V, Save) of
- true -> [{set,[V],[{fr,I}],fmove}|checkerror(Acc)];
- false -> Acc
- end;
-save_reg(_, _, Acc) -> Acc.
-
-kill_regs(Rs, Kill) ->
- [kill_reg(R, Kill) || R <- Rs].
-
-kill_reg({_,V,_}=R, Kill) ->
- case cerl_sets:is_element(V, Kill) of
- true -> free;
- false -> R
- end;
-kill_reg(R, _) -> R.
-
-mark(V, [{I,V,_}|Rs], Mark) -> [{I,V,Mark}|Rs];
-mark(V, [R|Rs], Mark) -> [R|mark(V, Rs, Mark)];
-mark(_, [], _) -> [].
-
-fetch_reg(V, [{I,V,_}|_]) -> {fr,I};
-fetch_reg(V, [_|SRs]) -> fetch_reg(V, SRs).
-
-find_reg(V, [{I,V,_}|_]) -> {ok,{fr,I}};
-find_reg(V, [_|SRs]) -> find_reg(V, SRs);
-find_reg(_, []) -> error.
-
-put_reg(V, Rs, Dirty) -> put_reg_1(V, Rs, Dirty, 0).
-
-put_reg_1(V, [free|Rs], Dirty, I) -> [{I,V,Dirty}|Rs];
-put_reg_1(V, [R|Rs], Dirty, I) -> [R|put_reg_1(V, Rs, Dirty, I+1)];
-put_reg_1(V, [], Dirty, I) -> [{I,V,Dirty}].
-
-checkerror(Is) ->
- checkerror_1(Is, Is).
-
-checkerror_1([{set,[],[],fcheckerror}|_], OrigIs) -> OrigIs;
-checkerror_1([{set,_,_,{bif,fadd,_}}|_], OrigIs) -> checkerror_2(OrigIs);
-checkerror_1([{set,_,_,{bif,fsub,_}}|_], OrigIs) -> checkerror_2(OrigIs);
-checkerror_1([{set,_,_,{bif,fmul,_}}|_], OrigIs) -> checkerror_2(OrigIs);
-checkerror_1([{set,_,_,{bif,fdiv,_}}|_], OrigIs) -> checkerror_2(OrigIs);
-checkerror_1([{set,_,_,{bif,fnegate,_}}|_], OrigIs) -> checkerror_2(OrigIs);
-checkerror_1([_|Is], OrigIs) -> checkerror_1(Is, OrigIs);
-checkerror_1([], OrigIs) -> OrigIs.
-
-checkerror_2(OrigIs) -> [{set,[],[],fcheckerror}|OrigIs].
-
-
-%%% Routines for maintaining a type database. The type database
-%%% associates type information with registers.
-%%%
-%%% See the comment for verified_type/1 at the end of module for
-%%% a description of the possible types.
-
-%% tdb_new() -> EmptyDataBase
-%% Creates a new, empty type database.
-
-tdb_new() -> [].
-
-%% tdb_find(Register, Db) -> Type
-%% Returns type information or the atom error if there is no type
-%% information available for Register.
-%%
-%% See the comment for verified_type/1 at the end of module for
-%% a description of the possible types.
-
-tdb_find(Reg, Ts) ->
- case tdb_find_raw(Reg, Ts) of
- {tuple_element,_,_} -> any;
- Type -> Type
- end.
-
-%% tdb_find_source_tuple(Register, Ts) -> {source_tuple,Register} | 'none'.
-%% Find the tuple whose first element was fetched to the register Register.
-
-tdb_find_source_tuple(Reg, Ts) ->
- case tdb_find_raw(Reg, Ts) of
- {tuple_element,Src,0} ->
- {source_tuple,Src};
- _ ->
- none
- end.
-
-%% tdb_copy(Source, Dest, Db) -> Db'
-%% Update the type information for Dest to have the same type
-%% as the Source.
-
-tdb_copy({Tag,_}=S, D, Ts) when Tag =:= x; Tag =:= y ->
- case tdb_find_raw(S, Ts) of
- any -> orddict:erase(D, Ts);
- Type -> orddict:store(D, Type, Ts)
- end;
-tdb_copy(Literal, D, Ts) ->
- Type = case Literal of
- {atom,_} -> Literal;
- {float,_} -> float;
- {integer,Int} -> {integer,{Int,Int}};
- {literal,[_|_]} -> nonempty_list;
- {literal,#{}} -> map;
- {literal,Tuple} when tuple_size(Tuple) >= 1 ->
- Lit = tag_literal(element(1, Tuple)),
- {tuple,exact_size,tuple_size(Tuple),[Lit]};
- _ -> any
- end,
- tdb_store(D, verified_type(Type), Ts).
-
-%% tdb_store(Register, Type, Ts0) -> Ts.
-%% Store a new type for register Register. Return the update type
-%% database. Use this function when a new value is assigned to
-%% a register.
-%%
-%% See the comment for verified_type/1 at the end of module for
-%% a description of the possible types.
-
-tdb_store(Reg, any, Ts) ->
- erase(Reg, Ts);
-tdb_store(Reg, Type, Ts) ->
- store(Reg, verified_type(Type), Ts).
-
-store(Key, New, [{K,_}|_]=Dict) when Key < K ->
- [{Key,New}|Dict];
-store(Key, New, [{K,Val}=E|Dict]) when Key > K ->
- case Val of
- {tuple_element,Key,_} -> store(Key, New, Dict);
- _ -> [E|store(Key, New, Dict)]
- end;
-store(Key, New, [{_K,Old}|Dict]) -> %Key == K
- case Old of
- {tuple,_,_,_} ->
- [{Key,New}|erase_tuple_element(Key, Dict)];
- _ ->
- [{Key,New}|Dict]
- end;
-store(Key, New, []) -> [{Key,New}].
-
-erase(Key, [{K,_}=E|Dict]) when Key < K ->
- [E|Dict];
-erase(Key, [{K,Val}=E|Dict]) when Key > K ->
- case Val of
- {tuple_element,Key,_} -> erase(Key, Dict);
- _ -> [E|erase(Key, Dict)]
- end;
-erase(Key, [{_K,Val}|Dict]) -> %Key == K
- case Val of
- {tuple,_,_,_} -> erase_tuple_element(Key, Dict);
- _ -> Dict
- end;
-erase(_, []) -> [].
-
-erase_tuple_element(Key, [{_,{tuple_element,Key,_}}|Dict]) ->
- erase_tuple_element(Key, Dict);
-erase_tuple_element(Key, [E|Dict]) ->
- [E|erase_tuple_element(Key, Dict)];
-erase_tuple_element(_Key, []) -> [].
-
-%% tdb_meet(Register, Type, Ts0) -> Ts.
-%% Update information of a register that is used as the source for an
-%% instruction. The type Type will be combined using the meet operation
-%% with the previous type information for the register, resulting in
-%% narrower (more specific) type.
-%%
-%% For example, if the previous type is {tuple,min_size,2,[]} and the
-%% the new type is {tuple,exact_size,5,[]}, the meet of the types will
-%% be {tuple,exact_size,5,[]}.
-%%
-%% See the comment for verified_type/1 at the end of module for
-%% a description of the possible types.
-
-tdb_meet(Reg, NewType, Ts) ->
- Update = fun(Type0) -> meet(Type0, NewType) end,
- orddict:update(Reg, Update, NewType, Ts).
-
-%%%
-%%% Here follows internal helper functions for accessing and
-%%% updating the type database.
-%%%
-
-tdb_find_raw({x,_}=K, Ts) -> tdb_find_raw_1(K, Ts);
-tdb_find_raw({y,_}=K, Ts) -> tdb_find_raw_1(K, Ts);
-tdb_find_raw(_, _) -> any.
-
-tdb_find_raw_1(K, Ts) ->
- case orddict:find(K, Ts) of
- {ok,Val} -> Val;
- error -> any
- end.
-
-tag_literal(A) when is_atom(A) -> {atom,A};
-tag_literal(F) when is_float(F) -> {float,F};
-tag_literal(I) when is_integer(I) -> {integer,I};
-tag_literal([]) -> nil;
-tag_literal(Lit) -> {literal,Lit}.
-
-%% tdb_kill_xregs(Db) -> NewDb
-%% Kill all information about x registers. Also kill all tuple_element
-%% dependencies from y registers to x registers.
-
-tdb_kill_xregs([{{x,_},_Type}|Db]) -> tdb_kill_xregs(Db);
-tdb_kill_xregs([{{y,_},{tuple_element,{x,_},_}}|Db]) -> tdb_kill_xregs(Db);
-tdb_kill_xregs([Any|Db]) -> [Any|tdb_kill_xregs(Db)];
-tdb_kill_xregs([]) -> [].
-
-%% meet(Type1, Type2) -> Type
-%% Returns the "meet" of Type1 and Type2. The meet is a narrower
-%% type than Type1 and Type2. For example:
-%%
-%% meet(integer, {integer,{0,3}}) -> {integer,{0,3}}
-%%
-%% The meet for two different types result in 'none', which is
-%% the bottom element for our type lattice:
-%%
-%% meet(integer, map) -> none
-
-meet(T, T) ->
- T;
-meet({integer,_}=T, integer) ->
- T;
-meet(integer, {integer,_}=T) ->
- T;
-meet({integer,{Min1,Max1}}, {integer,{Min2,Max2}}) ->
- {integer,{max(Min1, Min2),min(Max1, Max2)}};
-meet({tuple,min_size,Sz1,Same}, {tuple,min_size,Sz2,Same}=Max) when Sz1 < Sz2 ->
- Max;
-meet({tuple,min_size,Sz1,Same}=Max, {tuple,min_size,Sz2,Same}) when Sz1 > Sz2 ->
- Max;
-meet({tuple,exact_size,_,Same}=Exact, {tuple,_,_,Same}) ->
- Exact;
-meet({tuple,_,_,Same},{tuple,exact_size,_,Same}=Exact) ->
- Exact;
-meet({tuple,SzKind1,Sz1,[]}, {tuple,_SzKind2,_Sz2,First}=Tuple2) ->
- meet({tuple,SzKind1,Sz1,First}, Tuple2);
-meet({tuple,_SzKind1,_Sz1,First}=Tuple1, {tuple,SzKind2,Sz2,_}) ->
- meet(Tuple1, {tuple,SzKind2,Sz2,First});
-meet({binary,U1}, {binary,U2}) ->
- {binary,max(U1, U2)};
-meet(T1, T2) ->
- case is_any(T1) of
- true ->
- verified_type(T2);
- false ->
- case is_any(T2) of
- true ->
- verified_type(T1);
- false ->
- none %The bottom element.
- end
- end.
-
-is_any(any) -> true;
-is_any({tuple_element,_,_}) -> true;
-is_any(_) -> false.
-
-%% verified_type(Type) -> Type
-%% Returns the passed in type if it is one of the defined types.
-%% Crashes if there is anything wrong with the type.
-%%
-%% Here are all possible types:
-%%
-%% any Any Erlang term (top element for the type lattice).
-%%
-%% {atom,Atom} The specific atom Atom.
-%% {binary,Unit} Binary/bitstring aligned to unit Unit.
-%% boolean 'true' | 'false'
-%% float Floating point number.
-%% integer Integer.
-%% {integer,{Min,Max}} Integer in the inclusive range Min through Max.
-%% map Map.
-%% nonempty_list Nonempty list.
-%% {tuple,_,_,_} Tuple (see below).
-%%
-%% none No type (bottom element for the type lattice).
-%%
-%% {tuple,min_size,Size,First} means that the corresponding register
-%% contains a tuple with *at least* Size elements (conversely,
-%% {tuple,exact_size,Size,First} means that it contains a tuple with
-%% *exactly* Size elements). An tuple with unknown size is
-%% represented as {tuple,min_size,0,[]}. First is either [] (meaning
-%% that the tuple's first element is unknown) or [FirstElement] (the
-%% contents of the first element).
-%%
-%% There is also a pseudo-type called {tuple_element,_,_}:
-%%
-%% {tuple_element,SrcTuple,ElementNumber}
-%%
-%% that does not provide any information about the type of the
-%% register itself, but provides a link back to the source tuple that
-%% the register got its value from.
-%%
-%% Note that {tuple_element,_,_} will *never* be returned by tdb_find/2.
-%% Use tdb_find_source_tuple/2 to locate the source tuple for a register.
-
-verified_type(any=T) -> T;
-verified_type({atom,_}=T) -> T;
-verified_type({binary,U}=T) when is_integer(U) -> T;
-verified_type(boolean=T) -> T;
-verified_type(integer=T) -> T;
-verified_type({integer,{Min,Max}}=T)
- when is_integer(Min), is_integer(Max) -> T;
-verified_type(map=T) -> T;
-verified_type(nonempty_list=T) -> T;
-verified_type({tuple,_,Sz,[]}=T) when is_integer(Sz) -> T;
-verified_type({tuple,_,Sz,[_]}=T) when is_integer(Sz) -> T;
-verified_type({tuple_element,_,_}=T) -> T;
-verified_type(float=T) -> T.
diff --git a/lib/compiler/src/beam_utils.erl b/lib/compiler/src/beam_utils.erl
index 5580d2f123..686d314c2d 100644
--- a/lib/compiler/src/beam_utils.erl
+++ b/lib/compiler/src/beam_utils.erl
@@ -21,18 +21,16 @@
%%
-module(beam_utils).
--export([is_killed_block/2,is_killed/3,is_killed_at/3,
- is_not_used/3,usage/3,
+-export([is_killed/3,is_killed_at/3,is_not_used/3,
empty_label_index/0,index_label/3,index_labels/1,replace_labels/4,
code_at/2,bif_to_test/3,is_pure_test/1,
- live_opt/1,delete_annos/1,combine_heap_needs/2,
- anno_defs/1,
+ combine_heap_needs/2,
split_even/1
]).
-export_type([code_index/0,module_code/0,instruction/0]).
--import(lists, [flatmap/2,map/2,member/2,sort/1,reverse/1,splitwith/2]).
+-import(lists, [flatmap/2,map/2,member/2,sort/1,reverse/1]).
-define(is_const(Val), (Val =:= nil orelse
element(1, Val) =:= integer orelse
@@ -62,46 +60,6 @@
{lbl :: code_index(), %Label to code index.
res :: result_cache()}). %Result cache for each label.
-%% usage(Register, [Instruction], State) -> killed|not_used|used.
-%% Determine the usage of Register in the instruction sequence.
-%% The return value is one of:
-%%
-%% killed - The register is not used in any way.
-%% not_used - The register is referenced only by an allocating instruction
-%% (the actual value does not matter).
-%% used - The register is used (its value do matter).
-
--spec usage(beam_asm:reg(), [instruction()], code_index()) ->
- 'killed' | 'not_used' | 'used'.
-
-usage(R, Is, D) ->
- St = #live{lbl=D,res=gb_trees:empty()},
- {Usage,_} = check_liveness(R, Is, St),
- Usage.
-
-
-%% is_killed_block(Register, [Instruction]) -> true|false
-%% Determine whether a register is killed by the instruction sequence inside
-%% a block.
-%%
-%% If true is returned, it means that the register will not be
-%% referenced in ANY way (not even indirectly by an allocate instruction);
-%% i.e. it is OK to enter the instruction sequence with Register
-%% containing garbage.
-
--spec is_killed_block(beam_asm:reg(), [instruction()]) -> boolean().
-
-is_killed_block({x,X}, [{set,_,_,{alloc,Live,_}}|_]) ->
- X >= Live;
-is_killed_block(R, [{set,Ds,Ss,_Op}|Is]) ->
- not member(R, Ss) andalso (member(R, Ds) orelse is_killed_block(R, Is));
-is_killed_block(R, [{'%anno',{used,Regs}}|Is]) ->
- case R of
- {x,X} when (Regs bsr X) band 1 =:= 0 -> true;
- _ -> is_killed_block(R, Is)
- end;
-is_killed_block(_, []) -> false.
-
%% is_killed(Register, [Instruction], State) -> true|false
%% Determine whether a register is killed by the instruction sequence.
%% If true is returned, it means that the register will not be
@@ -224,23 +182,18 @@ bif_to_test('=<', [A,B], Fail) -> {test,is_ge,Fail,[B,A]};
bif_to_test('>', [A,B], Fail) -> {test,is_lt,Fail,[B,A]};
bif_to_test('<', [_,_]=Ops, Fail) -> {test,is_lt,Fail,Ops};
bif_to_test('>=', [_,_]=Ops, Fail) -> {test,is_ge,Fail,Ops};
-bif_to_test('==', [A,nil], Fail) -> {test,is_nil,Fail,[A]};
-bif_to_test('==', [nil,A], Fail) -> {test,is_nil,Fail,[A]};
bif_to_test('==', [C,A], Fail) when ?is_const(C) ->
{test,is_eq,Fail,[A,C]};
bif_to_test('==', [_,_]=Ops, Fail) -> {test,is_eq,Fail,Ops};
bif_to_test('/=', [C,A], Fail) when ?is_const(C) ->
{test,is_ne,Fail,[A,C]};
bif_to_test('/=', [_,_]=Ops, Fail) -> {test,is_ne,Fail,Ops};
-bif_to_test('=:=', [A,nil], Fail) -> {test,is_nil,Fail,[A]};
-bif_to_test('=:=', [nil,A], Fail) -> {test,is_nil,Fail,[A]};
bif_to_test('=:=', [C,A], Fail) when ?is_const(C) ->
{test,is_eq_exact,Fail,[A,C]};
bif_to_test('=:=', [_,_]=Ops, Fail) -> {test,is_eq_exact,Fail,Ops};
bif_to_test('=/=', [C,A], Fail) when ?is_const(C) ->
{test,is_ne_exact,Fail,[A,C]};
-bif_to_test('=/=', [_,_]=Ops, Fail) -> {test,is_ne_exact,Fail,Ops};
-bif_to_test(is_record, [_,_,_]=Ops, Fail) -> {test,is_record,Fail,Ops}.
+bif_to_test('=/=', [_,_]=Ops, Fail) -> {test,is_ne_exact,Fail,Ops}.
%% is_pure_test({test,Op,Fail,Ops}) -> true|false.
@@ -256,8 +209,8 @@ is_pure_test({test,is_eq_exact,_,[_,_]}) -> true;
is_pure_test({test,is_ne_exact,_,[_,_]}) -> true;
is_pure_test({test,is_ge,_,[_,_]}) -> true;
is_pure_test({test,is_lt,_,[_,_]}) -> true;
-is_pure_test({test,is_nil,_,[_]}) -> true;
is_pure_test({test,is_nonempty_list,_,[_]}) -> true;
+is_pure_test({test,is_tagged_tuple,_,[_,_,_]}) -> true;
is_pure_test({test,test_arity,_,[_,_]}) -> true;
is_pure_test({test,has_map_fields,_,[_|_]}) -> true;
is_pure_test({test,is_bitstr,_,[_]}) -> true;
@@ -265,42 +218,6 @@ is_pure_test({test,is_function2,_,[_,_]}) -> true;
is_pure_test({test,Op,_,Ops}) ->
erl_internal:new_type_test(Op, length(Ops)).
-
-%% live_opt([Instruction]) -> [Instruction].
-%% Go through the instruction sequence in reverse execution
-%% order, keep track of liveness and remove 'move' instructions
-%% whose destination is a register that will not be used.
-%% Also insert {used,Regs} annotations at the beginning
-%% and end of each block.
-
--spec live_opt([instruction()]) -> [instruction()].
-
-live_opt(Is0) ->
- {[{label,Fail}|_]=Bef,[Fi|Is]} =
- splitwith(fun({func_info,_,_,_}) -> false;
- (_) -> true
- end, Is0),
- {func_info,_,_,Live} = Fi,
- D = gb_trees:insert(Fail, live_call(Live), gb_trees:empty()),
- Bef ++ [Fi|live_opt(reverse(Is), 0, D, [])].
-
-
-%% delete_annos([Instruction]) -> [Instruction].
-%% Delete all annotations.
-
--spec delete_annos([instruction()]) -> [instruction()].
-
-delete_annos([{block,Bl0}|Is]) ->
- case delete_annos(Bl0) of
- [] -> delete_annos(Is);
- [_|_]=Bl -> [{block,Bl}|delete_annos(Is)]
- end;
-delete_annos([{'%anno',_}|Is]) ->
- delete_annos(Is);
-delete_annos([I|Is]) ->
- [I|delete_annos(Is)];
-delete_annos([]) -> [].
-
%% combine_heap_needs(HeapNeed1, HeapNeed2) -> HeapNeed
%% Combine the heap need for two allocation instructions.
@@ -314,24 +231,6 @@ combine_heap_needs(H1, H2) when is_integer(H1), is_integer(H2) ->
combine_heap_needs(H1, H2) ->
{alloc,combine_alloc_lists([H1,H2])}.
-
-%% anno_defs(Instructions) -> Instructions'
-%% Add {def,RegisterBitmap} annotations to the beginning of
-%% each block. Iff bit X is set in the the bitmap, it means
-%% that {x,X} is defined when the block is entered.
-
--spec anno_defs([instruction()]) -> [instruction()].
-
-anno_defs(Is0) ->
- {Bef,[Fi|Is1]} =
- splitwith(fun({func_info,_,_,_}) -> false;
- (_) -> true
- end, Is0),
- {func_info,_,_,Arity} = Fi,
- Regs = init_def_regs(Arity),
- Is = defs(Is1, Regs, #{}),
- Bef ++ [Fi|Is].
-
%% split_even/1
%% [1,2,3,4,5,6] -> {[1,3,5],[2,4,6]}
@@ -850,466 +749,7 @@ combine_alloc_lists(Al0) ->
%% live_opt/4.
-%% Bit syntax instructions.
-live_opt([{bs_context_to_binary,Src}=I|Is], Regs0, D, Acc) ->
- Regs = x_live([Src], Regs0),
- live_opt(Is, Regs, D, [I|Acc]);
-live_opt([{bs_init,Fail,_,none,Ss,Dst}=I|Is], Regs0, D, Acc) ->
- Regs1 = x_live(Ss, x_dead([Dst], Regs0)),
- Regs = live_join_label(Fail, D, Regs1),
- live_opt(Is, Regs, D, [I|Acc]);
-live_opt([{bs_init,Fail,Info,Live0,Ss,Dst}|Is], Regs0, D, Acc) ->
- Regs1 = x_dead([Dst], Regs0),
- Live = live_regs(Regs1),
- true = Live =< Live0, %Assertion.
- Regs2 = live_call(Live),
- Regs3 = x_live(Ss, Regs2),
- Regs = live_join_label(Fail, D, Regs3),
- I = {bs_init,Fail,Info,Live,Ss,Dst},
- live_opt(Is, Regs, D, [I|Acc]);
-live_opt([{bs_put,Fail,_,Ss}=I|Is], Regs0, D, Acc) ->
- Regs1 = x_live(Ss, Regs0),
- Regs = live_join_label(Fail, D, Regs1),
- live_opt(Is, Regs, D, [I|Acc]);
-live_opt([{bs_restore2,Src,_}=I|Is], Regs0, D, Acc) ->
- Regs = x_live([Src], Regs0),
- live_opt(Is, Regs, D, [I|Acc]);
-live_opt([{bs_save2,Src,_}=I|Is], Regs0, D, Acc) ->
- Regs = x_live([Src], Regs0),
- live_opt(Is, Regs, D, [I|Acc]);
-live_opt([{test,bs_start_match2,Fail,Live,[Src,_],_}=I|Is], _, D, Acc) ->
- Regs0 = live_call(Live),
- Regs1 = x_live([Src], Regs0),
- Regs = live_join_label(Fail, D, Regs1),
- live_opt(Is, Regs, D, [I|Acc]);
-
-%% Other instructions.
-live_opt([{block,Bl0}|Is], Regs0, D, Acc) ->
- Live0 = make_anno({used,Regs0}),
- {Bl,Regs} = live_opt_block(reverse(Bl0), Regs0, D, [Live0]),
- Live = make_anno({used,Regs}),
- live_opt(Is, Regs, D, [{block,[Live|Bl]}|Acc]);
-live_opt([build_stacktrace=I|Is], _, D, Acc) ->
- live_opt(Is, live_call(1), D, [I|Acc]);
-live_opt([raw_raise=I|Is], _, D, Acc) ->
- live_opt(Is, live_call(3), D, [I|Acc]);
-live_opt([{label,L}=I|Is], Regs, D0, Acc) ->
- D = gb_trees:insert(L, Regs, D0),
- live_opt(Is, Regs, D, [I|Acc]);
-live_opt([{jump,{f,L}}=I|Is], _, D, Acc) ->
- Regs = gb_trees:get(L, D),
- live_opt(Is, Regs, D, [I|Acc]);
-live_opt([return=I|Is], _, D, Acc) ->
- live_opt(Is, 1, D, [I|Acc]);
-live_opt([{catch_end,_}=I|Is], _, D, Acc) ->
- live_opt(Is, live_call(1), D, [I|Acc]);
-live_opt([{badmatch,Src}=I|Is], _, D, Acc) ->
- Regs = x_live([Src], 0),
- live_opt(Is, Regs, D, [I|Acc]);
-live_opt([{case_end,Src}=I|Is], _, D, Acc) ->
- Regs = x_live([Src], 0),
- live_opt(Is, Regs, D, [I|Acc]);
-live_opt([{try_case_end,Src}=I|Is], _, D, Acc) ->
- Regs = x_live([Src], 0),
- live_opt(Is, Regs, D, [I|Acc]);
-live_opt([if_end=I|Is], _, D, Acc) ->
- Regs = 0,
- live_opt(Is, Regs, D, [I|Acc]);
-live_opt([{call,Arity,_}=I|Is], _, D, Acc) ->
- live_opt(Is, live_call(Arity), D, [I|Acc]);
-live_opt([{call_ext,Arity,_}=I|Is], _, D, Acc) ->
- live_opt(Is, live_call(Arity), D, [I|Acc]);
-live_opt([{call_fun,Arity}=I|Is], _, D, Acc) ->
- live_opt(Is, live_call(Arity+1), D, [I|Acc]);
-live_opt([{apply,Arity}=I|Is], _, D, Acc) ->
- live_opt(Is, live_call(Arity+2), D, [I|Acc]);
-live_opt([{make_fun2,_,_,_,Arity}=I|Is], _, D, Acc) ->
- live_opt(Is, live_call(Arity), D, [I|Acc]);
-live_opt([{test,_,Fail,Ss}=I|Is], Regs0, D, Acc) ->
- Regs1 = x_live(Ss, Regs0),
- Regs = live_join_label(Fail, D, Regs1),
- live_opt(Is, Regs, D, [I|Acc]);
-live_opt([{test,_,Fail,Live,Ss,_}=I|Is], _, D, Acc) ->
- Regs0 = live_call(Live),
- Regs1 = x_live(Ss, Regs0),
- Regs = live_join_label(Fail, D, Regs1),
- live_opt(Is, Regs, D, [I|Acc]);
-live_opt([{select,_,Src,Fail,List}=I|Is], _, D, Acc) ->
- Regs0 = 0,
- Regs1 = x_live([Src], Regs0),
- Regs = live_join_labels([Fail|List], D, Regs1),
- live_opt(Is, Regs, D, [I|Acc]);
-live_opt([{try_case,Y}=I|Is], Regs0, D, Acc) ->
- Regs = live_call(1),
- case Regs0 of
- 0 ->
- live_opt(Is, Regs, D, [{try_end,Y}|Acc]);
- _ ->
- live_opt(Is, live_call(1), D, [I|Acc])
- end;
-live_opt([{loop_rec,_Fail,_Dst}=I|Is], _, D, Acc) ->
- live_opt(Is, 0, D, [I|Acc]);
-live_opt([timeout=I|Is], _, D, Acc) ->
- live_opt(Is, 0, D, [I|Acc]);
-live_opt([{wait,_}=I|Is], _, D, Acc) ->
- live_opt(Is, 0, D, [I|Acc]);
-live_opt([{get_map_elements,Fail,Src,{list,List}}=I|Is], Regs0, D, Acc) ->
- {Ss,Ds} = split_even(List),
- Regs1 = x_live([Src|Ss], x_dead(Ds, Regs0)),
- Regs = live_join_label(Fail, D, Regs1),
- live_opt(Is, Regs, D, [I|Acc]);
-live_opt([{gc_bif,N,F,R,As,Dst}=I|Is], Regs0, D, Acc) ->
- Bl = [{set,[Dst],As,{alloc,R,{gc_bif,N,F}}}],
- {_,Regs} = live_opt_block(Bl, Regs0, D, []),
- live_opt(Is, Regs, D, [I|Acc]);
-live_opt([{bif,N,F,As,Dst}=I|Is], Regs0, D, Acc) ->
- Bl = [{set,[Dst],As,{bif,N,F}}],
- {_,Regs} = live_opt_block(Bl, Regs0, D, []),
- live_opt(Is, Regs, D, [I|Acc]);
-live_opt([{get_tuple_element,Src,Idx,Dst}=I|Is], Regs0, D, Acc) ->
- Bl = [{set,[Dst],[Src],{get_tuple_element,Idx}}],
- {_,Regs} = live_opt_block(Bl, Regs0, D, []),
- live_opt(Is, Regs, D, [I|Acc]);
-live_opt([{move,Src,Dst}=I|Is], Regs0, D, Acc) ->
- Regs = x_live([Src], x_dead([Dst], Regs0)),
- live_opt(Is, Regs, D, [I|Acc]);
-live_opt([{put_map,F,Op,S,Dst,R,{list,Puts}}=I|Is], Regs0, D, Acc) ->
- Bl = [{set,[Dst],[S|Puts],{alloc,R,{put_map,Op,F}}}],
- {_,Regs} = live_opt_block(Bl, Regs0, D, []),
- live_opt(Is, Regs, D, [I|Acc]);
-
-%% Transparent instructions - they neither use nor modify x registers.
-live_opt([{deallocate,_}=I|Is], Regs, D, Acc) ->
- live_opt(Is, Regs, D, [I|Acc]);
-live_opt([{kill,_}=I|Is], Regs, D, Acc) ->
- live_opt(Is, Regs, D, [I|Acc]);
-live_opt([{try_end,_}=I|Is], Regs, D, Acc) ->
- live_opt(Is, Regs, D, [I|Acc]);
-live_opt([{loop_rec_end,_}=I|Is], Regs, D, Acc) ->
- live_opt(Is, Regs, D, [I|Acc]);
-live_opt([{wait_timeout,_,nil}=I|Is], Regs, D, Acc) ->
- live_opt(Is, Regs, D, [I|Acc]);
-live_opt([{wait_timeout,_,{Tag,_}}=I|Is], Regs, D, Acc) when Tag =/= x ->
- live_opt(Is, Regs, D, [I|Acc]);
-live_opt([{line,_}=I|Is], Regs, D, Acc) ->
- live_opt(Is, Regs, D, [I|Acc]);
-live_opt([{'catch',_,_}=I|Is], Regs, D, Acc) ->
- live_opt(Is, Regs, D, [I|Acc]);
-live_opt([{'try',_,_}=I|Is], Regs, D, Acc) ->
- live_opt(Is, Regs, D, [I|Acc]);
-
-%% The following instructions can occur if the "compilation" has been
-%% started from a .S file using the 'from_asm' option.
-live_opt([{trim,_,_}=I|Is], Regs, D, Acc) ->
- live_opt(Is, Regs, D, [I|Acc]);
-live_opt([{'%',_}=I|Is], Regs, D, Acc) ->
- live_opt(Is, Regs, D, [I|Acc]);
-live_opt([{recv_set,_}=I|Is], Regs, D, Acc) ->
- live_opt(Is, Regs, D, [I|Acc]);
-live_opt([{recv_mark,_}=I|Is], Regs, D, Acc) ->
- live_opt(Is, Regs, D, [I|Acc]);
-
-live_opt([], _, _, Acc) -> Acc.
-
-live_opt_block([{set,[{x,X}]=Ds,Ss,move}=I|Is], Regs0, D, Acc) ->
- Regs = x_live(Ss, x_dead(Ds, Regs0)),
- case is_live(X, Regs0) of
- true ->
- live_opt_block(Is, Regs, D, [I|Acc]);
- false ->
- %% Useless move, will never be used.
- live_opt_block(Is, Regs, D, Acc)
- end;
-live_opt_block([{set,Ds,Ss,{alloc,Live0,AllocOp}}|Is], Regs0, D, Acc) ->
- %% Calculate liveness from the point of view of the GC.
- %% There will never be a GC if the instruction fails, so we should
- %% ignore the failure branch.
- GcRegs1 = x_dead(Ds, Regs0),
- GcRegs = x_live(Ss, GcRegs1),
- Live = live_regs(GcRegs),
-
- %% The life-time analysis used by the code generator is sometimes too
- %% conservative, so it may be possible to lower the number of live
- %% registers based on the exact liveness information. The main benefit is
- %% that more optimizations that depend on liveness information (such as the
- %% beam_dead pass) may be applied.
- true = Live =< Live0, %Assertion.
- I = {set,Ds,Ss,{alloc,Live,AllocOp}},
-
- %% Calculate liveness from the point of view of the preceding instruction.
- %% The liveness is the union of live registers in the GC and the live
- %% registers at the failure label.
- Regs1 = live_call(Live),
- Regs = live_join_alloc(AllocOp, D, Regs1),
- live_opt_block(Is, Regs, D, [I|Acc]);
-live_opt_block([{set,Ds,Ss,{bif,_,Fail}}=I|Is], Regs0, D, Acc) ->
- Regs1 = x_dead(Ds, Regs0),
- Regs2 = x_live(Ss, Regs1),
- Regs = live_join_label(Fail, D, Regs2),
- live_opt_block(Is, Regs, D, [I|Acc]);
-live_opt_block([{set,Ds,Ss,_}=I|Is], Regs0, D, Acc) ->
- Regs = x_live(Ss, x_dead(Ds, Regs0)),
- live_opt_block(Is, Regs, D, [I|Acc]);
-live_opt_block([{'%anno',_}|Is], Regs, D, Acc) ->
- live_opt_block(Is, Regs, D, Acc);
-live_opt_block([], Regs, _, Acc) -> {Acc,Regs}.
-
-live_join_alloc({Kind,_Name,Fail}, D, Regs) when Kind =:= gc_bif; Kind =:= put_map ->
- live_join_label(Fail, D, Regs);
-live_join_alloc(_, _, Regs) -> Regs.
-
-live_join_labels([{f,L}|T], D, Regs0) when L =/= 0 ->
- Regs = gb_trees:get(L, D) bor Regs0,
- live_join_labels(T, D, Regs);
-live_join_labels([_|T], D, Regs) ->
- live_join_labels(T, D, Regs);
-live_join_labels([], _, Regs) -> Regs.
-
-live_join_label({f,0}, _, Regs) ->
- Regs;
-live_join_label({f,L}, D, Regs) ->
- gb_trees:get(L, D) bor Regs.
-
-live_call(Live) -> (1 bsl Live) - 1.
-
-live_regs(Regs) ->
- live_regs_1(0, Regs).
-
-live_regs_1(N, 0) -> N;
-live_regs_1(N, Regs) -> live_regs_1(N+1, Regs bsr 1).
-
-x_dead([{x,N}|Rs], Regs) -> x_dead(Rs, Regs band (bnot (1 bsl N)));
-x_dead([_|Rs], Regs) -> x_dead(Rs, Regs);
-x_dead([], Regs) -> Regs.
-
-x_live([{x,N}|Rs], Regs) -> x_live(Rs, Regs bor (1 bsl N));
-x_live([_|Rs], Regs) -> x_live(Rs, Regs);
-x_live([], Regs) -> Regs.
-
-is_live(X, Regs) -> ((Regs bsr X) band 1) =:= 1.
-
split_even([], Ss, Ds) ->
{reverse(Ss),reverse(Ds)};
split_even([S,D|Rs], Ss, Ds) ->
split_even(Rs, [S|Ss], [D|Ds]).
-
-%%%
-%%% Add annotations for defined registers.
-%%%
-%%% This analysis is done by scanning the instructions in
-%%% execution order.
-%%%
-
-defs([{apply,_}=I|Is], _Regs, D) ->
- [I|defs(Is, 1, D)];
-defs([{bif,_,{f,Fail},_Src,Dst}=I|Is], Regs0, D) ->
- Regs = def_regs([Dst], Regs0),
- [I|defs(Is, Regs, update_regs(Fail, Regs0, D))];
-defs([{block,Block0}|Is], Regs0, D0) ->
- {Block,Regs,D} = defs_list(Block0, Regs0, D0),
- [{block,[make_anno({def,Regs0})|Block]}|defs(Is, Regs, D)];
-defs([{bs_init,{f,L},_,Live,_,Dst}=I|Is], Regs0, D) ->
- Regs1 = case Live of
- none -> Regs0;
- _ -> init_def_regs(Live)
- end,
- Regs = def_regs([Dst], Regs1),
- [I|defs(Is, Regs, update_regs(L, Regs, D))];
-defs([{bs_put,{f,L},_,_}=I|Is], Regs, D) ->
- [I|defs(Is, Regs, update_regs(L, Regs, D))];
-defs([build_stacktrace=I|Is], _Regs, D) ->
- [I|defs(Is, 1, D)];
-defs([{call,_,_}=I|Is], _Regs, D) ->
- [I|defs(Is, 1, D)];
-defs([{call_ext,_,{extfunc,M,F,A}}=I|Is], _Regs, D) ->
- case erl_bifs:is_exit_bif(M, F, A) of
- false ->
- [I|defs(Is, 1, D)];
- true ->
- [I|defs_unreachable(Is, D)]
- end;
-defs([{call_ext,_,_}=I|Is], _Regs, D) ->
- [I|defs(Is, 1, D)];
-defs([{call_fun,_}=I|Is], _Regs, D) ->
- [I|defs(Is, 1, D)];
-defs([{'catch',_,{f,L}}=I|Is], Regs, D) ->
- RegsAtLabel = init_def_regs(1),
- [I|defs(Is, Regs, update_regs(L, RegsAtLabel, D))];
-defs([{catch_end,_}=I|Is], _Regs, D) ->
- Regs = init_def_regs(1),
- [I|defs(Is, Regs, D)];
-defs([{gc_bif,_,{f,Fail},Live,_Src,Dst}=I|Is], Regs0, D) ->
- true = all_defined(Live, Regs0), %Assertion.
- Regs = def_regs([Dst], init_def_regs(Live)),
- [I|defs(Is, Regs, update_regs(Fail, Regs0, D))];
-defs([{get_map_elements,{f,L},_Src,{list,DstList}}=I|Is], Regs0, D) ->
- {_,Ds} = beam_utils:split_even(DstList),
- Regs = def_regs(Ds, Regs0),
- [I|defs(Is, Regs, update_regs(L, Regs0, D))];
-defs([{get_tuple_element,_,_,Dst}=I|Is], Regs0, D) ->
- Regs = def_regs([Dst], Regs0),
- [I|defs(Is, Regs, D)];
-defs([{jump,{f,L}}=I|Is], Regs, D) ->
- [I|defs_unreachable(Is, update_regs(L, Regs, D))];
-defs([{label,L}=I|Is], Regs0, D) ->
- case D of
- #{L:=Regs1} ->
- Regs = Regs0 band Regs1,
- [I|defs(Is, Regs, D)];
- #{} ->
- [I|defs(Is, Regs0, D)]
- end;
-defs([{loop_rec,{f,L},{x,0}}=I|Is], _Regs, D0) ->
- RegsAtLabel = init_def_regs(0),
- D = update_regs(L, RegsAtLabel, D0),
- [I|defs(Is, init_def_regs(1), D)];
-defs([{loop_rec_end,_}=I|Is], _Regs, D) ->
- [I|defs_unreachable(Is, D)];
-defs([{make_fun2,_,_,_,_}=I|Is], _Regs, D) ->
- [I|defs(Is, 1, D)];
-defs([{move,_,Dst}=I|Is], Regs0, D) ->
- Regs = def_regs([Dst], Regs0),
- [I|defs(Is, Regs, D)];
-defs([{put_map,{f,Fail},_,_,Dst,_,_}=I|Is], Regs0, D) ->
- Regs = def_regs([Dst], Regs0),
- [I|defs(Is, Regs, update_regs(Fail, Regs0, D))];
-defs([raw_raise=I|Is], _Regs, D) ->
- [I|defs(Is, 1, D)];
-defs([return=I|Is], _Regs, D) ->
- [I|defs_unreachable(Is, D)];
-defs([{select,_,_Src,Fail,List}=I|Is], Regs, D0) ->
- D = update_list([Fail|List], Regs, D0),
- [I|defs_unreachable(Is, D)];
-defs([{test,_,{f,L},_}=I|Is], Regs, D) ->
- [I|defs(Is, Regs, update_regs(L, Regs, D))];
-defs([{test,_,{f,L},Live,_,Dst}=I|Is], Regs0, D) ->
- true = all_defined(Live, Regs0), %Assertion.
- Regs = def_regs([Dst], init_def_regs(Live)),
- [I|defs(Is, Regs, update_regs(L, Regs0, D))];
-defs([{'try',_,{f,L}}=I|Is], Regs, D) ->
- RegsAtLabel = init_def_regs(3),
- [I|defs(Is, Regs, update_regs(L, RegsAtLabel, D))];
-defs([{try_case,_}=I|Is], _Regs, D) ->
- [I|defs(Is, init_def_regs(3), D)];
-defs([{wait,_}=I|Is], _Regs, D) ->
- [I|defs_unreachable(Is, D)];
-defs([{wait_timeout,_,_}=I|Is], _Regs, D) ->
- [I|defs(Is, 0, D)];
-
-%% Exceptions.
-defs([{badmatch,_}=I|Is], _Regs, D) ->
- [I|defs_unreachable(Is, D)];
-defs([{case_end,_}=I|Is], _Regs, D) ->
- [I|defs_unreachable(Is, D)];
-defs([if_end=I|Is], _Regs, D) ->
- [I|defs_unreachable(Is, D)];
-defs([{try_case_end,_}=I|Is], _Regs, D) ->
- [I|defs_unreachable(Is, D)];
-
-%% Neutral instructions
-defs([{bs_context_to_binary,_}=I|Is], Regs, D) ->
- [I|defs(Is, Regs, D)];
-defs([{bs_restore2,_,_}=I|Is], Regs, D) ->
- [I|defs(Is, Regs, D)];
-defs([{bs_save2,_,_}=I|Is], Regs, D) ->
- [I|defs(Is, Regs, D)];
-defs([{deallocate,_}=I|Is], Regs, D) ->
- [I|defs(Is, Regs, D)];
-defs([{kill,_}=I|Is], Regs, D) ->
- [I|defs(Is, Regs, D)];
-defs([{line,_}=I|Is], Regs, D) ->
- [I|defs(Is, Regs, D)];
-defs([{recv_mark,_}=I|Is], Regs, D) ->
- [I|defs(Is, Regs, D)];
-defs([{recv_set,_}=I|Is], Regs, D) ->
- [I|defs(Is, Regs, D)];
-defs([timeout=I|Is], Regs, D) ->
- [I|defs(Is, Regs, D)];
-defs([{trim,_,_}=I|Is], Regs, D) ->
- [I|defs(Is, Regs, D)];
-defs([{try_end,_}=I|Is], Regs, D) ->
- [I|defs(Is, Regs, D)];
-defs([{'%',_}=I|Is], Regs, D) ->
- [I|defs(Is, Regs, D)];
-defs([], _, _) -> [].
-
-defs_unreachable([{label,L}=I|Is], D) ->
- case D of
- #{L:=Regs} ->
- [I|defs(Is, Regs, D)];
- #{} ->
- defs_unreachable(Is, D)
- end;
-defs_unreachable([_|Is], D) ->
- defs_unreachable(Is, D);
-defs_unreachable([], _D) -> [].
-
-defs_list(Is, Regs, D) ->
- defs_list(Is, Regs, D, []).
-
-defs_list([{set,Ds,_,{alloc,Live,Info}}=I|Is], Regs0, D0, Acc) ->
- true = all_defined(Live, Regs0), %Assertion.
- D = case Info of
- {gc_bif,_,{f,Fail}} ->
- update_regs(Fail, Regs0, D0);
- {put_map,_,{f,Fail}} ->
- update_regs(Fail, Regs0, D0);
- _ ->
- D0
- end,
- Regs = def_regs(Ds, init_def_regs(Live)),
- defs_list(Is, Regs, D, [I|Acc]);
-defs_list([{set,Ds,_,Info}=I|Is], Regs0, D0, Acc) ->
- D = case Info of
- {bif,_,{f,Fail}} ->
- update_regs(Fail, Regs0, D0);
- {try_catch,'catch',{f,Fail}} ->
- update_regs(Fail, init_def_regs(1), D0);
- {try_catch,'try',{f,Fail}} ->
- update_regs(Fail, init_def_regs(3), D0);
- _ ->
- D0
- end,
- Regs = def_regs(Ds, Regs0),
- defs_list(Is, Regs, D, [I|Acc]);
-defs_list([], Regs, D, Acc) ->
- {reverse(Acc),Regs,D}.
-
-init_def_regs(Arity) ->
- (1 bsl Arity) - 1.
-
-def_regs([{x,X}|T], Regs) ->
- def_regs(T, Regs bor (1 bsl X));
-def_regs([_|T], Regs) ->
- def_regs(T, Regs);
-def_regs([], Regs) -> Regs.
-
-update_list([{f,L}|T], Regs, D0) ->
- D = update_regs(L, Regs, D0),
- update_list(T, Regs, D);
-update_list([_|T], Regs, D) ->
- update_list(T, Regs, D);
-update_list([], _Regs, D) -> D.
-
-update_regs(L, Regs0, D) ->
- case D of
- #{L:=Regs1} ->
- Regs = Regs0 band Regs1,
- D#{L:=Regs};
- #{} ->
- D#{L=>Regs0}
- end.
-
-all_defined(Live, Regs) ->
- All = (1 bsl Live) - 1,
- Regs band All =:= All.
-
-%%%
-%%% Utilities.
-%%%
-
-%% make_anno(Anno) -> WrappedAnno.
-%% Wrap an annotation term.
-
-make_anno(Anno) ->
- {'%anno',Anno}.
diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl
index c09dbadd7f..8d699f2abd 100644
--- a/lib/compiler/src/beam_validator.erl
+++ b/lib/compiler/src/beam_validator.erl
@@ -27,7 +27,7 @@
%% Interface for compiler.
-export([module/2, format_error/1]).
--import(lists, [any/2,dropwhile/2,foldl/3,foreach/2,reverse/1]).
+-import(lists, [any/2,dropwhile/2,foldl/3,map/2,foreach/2,reverse/1]).
%% To be called by the compiler.
@@ -145,7 +145,9 @@ validate_0(Module, [{function,Name,Ar,Entry,Code}|Fs], Ft) ->
fls=undefined, %Floating point state.
ct=[], %List of hot catch/try labels
setelem=false, %Previous instruction was setelement/3.
- puts_left=none %put/1 instructions left.
+ puts_left=none, %put/1 instructions left.
+ defs=#{}, %Defining expression for each register.
+ aliases=#{}
}).
-type label() :: integer().
@@ -203,6 +205,12 @@ validate_fun_info_branches([], _, _) -> ok.
validate_fun_info_branches_1(Arity, {_,_,Arity}, _) -> ok;
validate_fun_info_branches_1(X, {Mod,Name,Arity}=MFA, Vst) ->
try
+ case Vst of
+ #vst{current=#st{numy=none}} ->
+ ok;
+ #vst{current=#st{numy=Size}} ->
+ error({unexpected_stack_frame,Size})
+ end,
get_term_type({x,X}, Vst)
catch Error ->
I = {func_info,{atom,Mod},{atom,Name},Arity},
@@ -304,9 +312,10 @@ valfun_1({move,{y,_}=Src,{y,_}=Dst}, Vst) ->
{trytag,_} -> error({trytag,Src});
Type -> set_type_reg(Type, Dst, Vst)
end;
-valfun_1({move,Src,Dst}, Vst) ->
- Type = get_move_term_type(Src, Vst),
- set_type_reg(Type, Dst, Vst);
+valfun_1({move,Src,Dst}, Vst0) ->
+ Type = get_move_term_type(Src, Vst0),
+ Vst = set_type_reg(Type, Dst, Vst0),
+ set_alias(Src, Dst, Vst);
valfun_1({fmove,Src,{fr,_}=Dst}, Vst) ->
assert_type(float, Src, Vst),
set_freg(Dst, Vst);
@@ -332,7 +341,7 @@ valfun_1({bif,Op,{f,_},Src,Dst}=I, Vst) ->
%% catch state).
validate_src(Src, Vst),
Type = bif_type(Op, Src, Vst),
- set_type_reg(Type, Dst, Vst)
+ set_type_reg_expr(Type, I, Dst, Vst)
end;
%% Put instructions.
valfun_1({put_list,A,B,Dst}, Vst0) ->
@@ -340,6 +349,12 @@ valfun_1({put_list,A,B,Dst}, Vst0) ->
assert_term(B, Vst0),
Vst = eat_heap(2, Vst0),
set_type_reg(cons, Dst, Vst);
+valfun_1({put_tuple2,Dst,{list,Elements}}, Vst0) ->
+ _ = [assert_term(El, Vst0) || El <- Elements],
+ Size = length(Elements),
+ Vst = eat_heap(Size+1, Vst0),
+ Type = {tuple,Size},
+ set_type_reg(Type, Dst, Vst);
valfun_1({put_tuple,Sz,Dst}, Vst0) when is_integer(Sz) ->
Vst1 = eat_heap(1, Vst0),
Vst = set_type_reg(tuple_in_progress, Dst, Vst1),
@@ -408,35 +423,27 @@ valfun_1({trim,N,Remaining}, #vst{current=#st{y=Yregs0,numy=NumY}=St}=Vst) ->
N =< NumY, N+Remaining =:= NumY ->
Yregs1 = [{Y-N,Type} || {Y,Type} <- gb_trees:to_list(Yregs0), Y >= N],
Yregs = gb_trees_from_list(Yregs1),
- Vst#vst{current=St#st{y=Yregs,numy=NumY-N}};
+ Vst#vst{current=St#st{y=Yregs,numy=NumY-N,aliases=#{}}};
true ->
error({trim,N,Remaining,allocated,NumY})
end;
%% Catch & try.
-valfun_1({'catch',Dst,{f,Fail}}, Vst0) when Fail /= none ->
- Vst = #vst{current=#st{ct=Fails}=St} =
- set_type_y({catchtag,[Fail]}, Dst, Vst0),
- Vst#vst{current=St#st{ct=[[Fail]|Fails]}};
-valfun_1({'try',Dst,{f,Fail}}, Vst0) ->
- Vst = #vst{current=#st{ct=Fails}=St} =
- set_type_y({trytag,[Fail]}, Dst, Vst0),
- Vst#vst{current=St#st{ct=[[Fail]|Fails]}};
+valfun_1({'catch',Dst,{f,Fail}}, Vst) when Fail =/= none ->
+ init_try_catch_branch(catchtag, Dst, Fail, Vst);
+valfun_1({'try',Dst,{f,Fail}}, Vst) when Fail =/= none ->
+ init_try_catch_branch(trytag, Dst, Fail, Vst);
valfun_1({catch_end,Reg}, #vst{current=#st{ct=[Fail|Fails]}}=Vst0) ->
case get_special_y_type(Reg, Vst0) of
{catchtag,Fail} ->
Vst = #vst{current=St} = set_catch_end(Reg, Vst0),
- Xs = gb_trees_from_list([{0,term}]),
- Vst#vst{current=St#st{x=Xs,ct=Fails,fls=undefined}};
+ Xregs = gb_trees:enter(0, term, St#st.x),
+ Vst#vst{current=St#st{x=Xregs,ct=Fails,fls=undefined,aliases=#{}}};
Type ->
error({bad_type,Type})
end;
-valfun_1({try_end,Reg}, #vst{current=#st{ct=[Fail|Fails]}=St0}=Vst0) ->
- case get_special_y_type(Reg, Vst0) of
+valfun_1({try_end,Reg}, #vst{current=#st{ct=[Fail|Fails]}=St0}=Vst) ->
+ case get_special_y_type(Reg, Vst) of
{trytag,Fail} ->
- Vst = case Fail of
- [FailLabel] -> branch_state(FailLabel, Vst0);
- _ -> Vst0
- end,
St = St0#st{ct=Fails,fls=undefined},
set_catch_end(Reg, Vst#vst{current=St});
Type ->
@@ -447,7 +454,7 @@ valfun_1({try_case,Reg}, #vst{current=#st{ct=[Fail|Fails]}}=Vst0) ->
{trytag,Fail} ->
Vst = #vst{current=St} = set_catch_end(Reg, Vst0),
Xs = gb_trees_from_list([{0,{atom,[]}},{1,term},{2,term}]),
- Vst#vst{current=St#st{x=Xs,ct=Fails,fls=undefined}};
+ Vst#vst{current=St#st{x=Xs,ct=Fails,fls=undefined,aliases=#{}}};
Type ->
error({bad_type,Type})
end;
@@ -464,14 +471,34 @@ valfun_1({get_tl,Src,Dst}, Vst) ->
valfun_1({get_tuple_element,Src,I,Dst}, Vst) ->
assert_type({tuple_element,I+1}, Src, Vst),
set_type_reg(term, Src, Dst, Vst);
+valfun_1({jump,{f,Lbl}}, Vst) ->
+ kill_state(branch_state(Lbl, Vst));
valfun_1(I, Vst) ->
valfun_2(I, Vst).
+init_try_catch_branch(Tag, Dst, Fail, Vst0) ->
+ Vst1 = set_type_y({Tag,[Fail]}, Dst, Vst0),
+ #vst{current=#st{ct=Fails}=St0} = Vst1,
+ CurrentSt = St0#st{ct=[[Fail]|Fails]},
+
+ %% Set the initial state at the try/catch label.
+ %% Assume that Y registers contain terms or try/catch
+ %% tags.
+ Yregs0 = map(fun({Y,uninitialized}) -> {Y,term};
+ ({Y,initialized}) -> {Y,term};
+ (E) -> E
+ end, gb_trees:to_list(CurrentSt#st.y)),
+ Yregs = gb_trees:from_orddict(Yregs0),
+ BranchSt = CurrentSt#st{y=Yregs},
+
+ Vst = branch_state(Fail, Vst1#vst{current=BranchSt}),
+ Vst#vst{current=CurrentSt}.
+
%% Update branched state if necessary and try next set of instructions.
valfun_2(I, #vst{current=#st{ct=[]}}=Vst) ->
valfun_3(I, Vst);
valfun_2(I, #vst{current=#st{ct=[[Fail]|_]}}=Vst) when is_integer(Fail) ->
- %% Update branched state
+ %% Update branched state.
valfun_3(I, branch_state(Fail, Vst));
valfun_2(_, _) ->
error(ambiguous_catch_try_state).
@@ -541,18 +568,18 @@ valfun_4({call_ext_last,_,_,_}, #vst{current=#st{numy=NumY}}) ->
valfun_4({make_fun2,_,_,_,Live}, Vst) ->
call(make_fun, Live, Vst);
%% Other BIFs
-valfun_4({bif,tuple_size,{f,Fail},[Tuple],Dst}, Vst0) ->
+valfun_4({bif,tuple_size,{f,Fail},[Tuple],Dst}=I, Vst0) ->
TupleType0 = get_term_type(Tuple, Vst0),
Vst1 = branch_state(Fail, Vst0),
TupleType = upgrade_tuple_type({tuple,[0]}, TupleType0),
Vst = set_type(TupleType, Tuple, Vst1),
- set_type_reg({integer,[]}, Dst, Vst);
+ set_type_reg_expr({integer,[]}, I, Dst, Vst);
valfun_4({bif,element,{f,Fail},[Pos,Tuple],Dst}, Vst0) ->
TupleType0 = get_term_type(Tuple, Vst0),
PosType = get_term_type(Pos, Vst0),
Vst1 = branch_state(Fail, Vst0),
TupleType = upgrade_tuple_type({tuple,[get_tuple_size(PosType)]}, TupleType0),
- Vst = set_type(TupleType, Tuple, Vst1),
+ Vst = set_aliased_type(TupleType, Tuple, Vst1),
set_type_reg(term, Tuple, Dst, Vst);
valfun_4({bif,raise,{f,0},Src,_Dst}, Vst) ->
validate_src(Src, Vst),
@@ -565,6 +592,20 @@ valfun_4({bif,map_get,{f,Fail},[_Key,Map]=Src,Dst}, Vst0) ->
Vst = set_type(map, Map, Vst1),
Type = propagate_fragility(term, Src, Vst),
set_type_reg(Type, Dst, Vst);
+valfun_4({bif,is_map_key,{f,Fail},[_Key,Map]=Src,Dst}, Vst0) ->
+ validate_src(Src, Vst0),
+ Vst1 = branch_state(Fail, Vst0),
+ Vst = set_type(map, Map, Vst1),
+ Type = propagate_fragility(bool, Src, Vst),
+ set_type_reg(Type, Dst, Vst);
+valfun_4({bif,Op,{f,Fail},[Cons]=Src,Dst}, Vst0)
+ when Op =:= hd; Op =:= tl ->
+ validate_src(Src, Vst0),
+ Vst1 = branch_state(Fail, Vst0),
+ Vst = set_type(cons, Cons, Vst1),
+ Type0 = bif_type(Op, Src, Vst),
+ Type = propagate_fragility(Type0, Src, Vst),
+ set_type_reg(Type, Dst, Vst);
valfun_4({bif,Op,{f,Fail},Src,Dst}, Vst0) ->
validate_src(Src, Vst0),
Vst = branch_state(Fail, Vst0),
@@ -577,7 +618,13 @@ valfun_4({gc_bif,Op,{f,Fail},Live,Src,Dst}, #vst{current=St0}=Vst0) ->
St = kill_heap_allocation(St0),
Vst1 = Vst0#vst{current=St},
Vst2 = branch_state(Fail, Vst1),
- Vst = prune_x_regs(Live, Vst2),
+ Vst3 = prune_x_regs(Live, Vst2),
+ Vst = case Op of
+ map_size ->
+ set_type(map, hd(Src), Vst3);
+ _ ->
+ Vst3
+ end,
validate_src(Src, Vst),
Type0 = bif_type(Op, Src, Vst),
Type = propagate_fragility(Type0, Src, Vst),
@@ -587,8 +634,6 @@ valfun_4(return, #vst{current=#st{numy=none}}=Vst) ->
kill_state(Vst);
valfun_4(return, #vst{current=#st{numy=NumY}}) ->
error({stack_frame,NumY});
-valfun_4({jump,{f,Lbl}}, Vst) ->
- kill_state(branch_state(Lbl, Vst));
valfun_4({loop_rec,{f,Fail},Dst}, Vst0) ->
Vst = branch_state(Fail, Vst0),
%% This term may not be part of the root set until
@@ -615,13 +660,20 @@ valfun_4({set_tuple_element,Src,Tuple,I}, Vst) ->
assert_type({tuple_element,I+1}, Tuple, Vst),
Vst;
%% Match instructions.
-valfun_4({select_val,Src,{f,Fail},{list,Choices}}, Vst) ->
- assert_term(Src, Vst),
- Lbls = [L || {f,L} <- Choices]++[Fail],
- kill_state(foldl(fun(L, S) -> branch_state(L, S) end, Vst, Lbls));
+valfun_4({select_val,Src,{f,Fail},{list,Choices}}, Vst0) ->
+ assert_term(Src, Vst0),
+ assert_choices(Choices),
+ Vst = branch_state(Fail, Vst0),
+ kill_state(select_val_branches(Src, Choices, Vst));
valfun_4({select_tuple_arity,Tuple,{f,Fail},{list,Choices}}, Vst) ->
assert_type(tuple, Tuple, Vst),
- kill_state(branch_arities(Choices, Tuple, branch_state(Fail, Vst)));
+ assert_arities(Choices),
+ TupleType = case get_term_type(Tuple, Vst) of
+ {fragile,TupleType0} -> TupleType0;
+ TupleType0 -> TupleType0
+ end,
+ kill_state(branch_arities(Choices, Tuple, TupleType,
+ branch_state(Fail, Vst)));
%% New bit syntax matching instructions.
valfun_4({test,bs_start_match2,{f,Fail},Live,[Ctx,NeedSlots],Ctx}, Vst0) ->
@@ -694,16 +746,19 @@ valfun_4({test,is_float,{f,Lbl},[Float]}, Vst) ->
valfun_4({test,is_tuple,{f,Lbl},[Tuple]}, Vst) ->
Type0 = get_term_type(Tuple, Vst),
Type = upgrade_tuple_type({tuple,[0]}, Type0),
- set_type(Type, Tuple, branch_state(Lbl, Vst));
+ set_aliased_type(Type, Tuple, branch_state(Lbl, Vst));
valfun_4({test,is_nonempty_list,{f,Lbl},[Cons]}, Vst) ->
assert_term(Cons, Vst),
- set_type(cons, Cons, branch_state(Lbl, Vst));
+ Type = cons,
+ set_aliased_type(Type, Cons, branch_state(Lbl, Vst));
valfun_4({test,test_arity,{f,Lbl},[Tuple,Sz]}, Vst) when is_integer(Sz) ->
assert_type(tuple, Tuple, Vst),
- set_type_reg({tuple,Sz}, Tuple, branch_state(Lbl, Vst));
+ Type = {tuple,Sz},
+ set_aliased_type(Type, Tuple, branch_state(Lbl, Vst));
valfun_4({test,is_tagged_tuple,{f,Lbl},[Src,Sz,_Atom]}, Vst) ->
validate_src([Src], Vst),
- set_type_reg({tuple, Sz}, Src, branch_state(Lbl, Vst));
+ Type = {tuple,Sz},
+ set_aliased_type(Type, Src, branch_state(Lbl, Vst));
valfun_4({test,has_map_fields,{f,Lbl},Src,{list,List}}, Vst) ->
assert_type(map, Src, Vst),
assert_unique_map_keys(List),
@@ -712,11 +767,26 @@ valfun_4({test,is_map,{f,Lbl},[Src]}, Vst0) ->
Vst = branch_state(Lbl, Vst0),
case Src of
{Tag,_} when Tag =:= x; Tag =:= y ->
- set_type_reg(map, Src, Vst);
+ Type = map,
+ set_aliased_type(Type, Src, Vst);
{literal,Map} when is_map(Map) ->
- Vst;
+ Vst0;
_ ->
- kill_state(Vst)
+ kill_state(Vst0)
+ end;
+valfun_4({test,is_eq_exact,{f,Lbl},[Src,Val]=Ss}, Vst0) ->
+ validate_src(Ss, Vst0),
+ Infer = infer_types(Src, Vst0),
+ Vst1 = Infer(Val, Vst0),
+ Vst = branch_state(Lbl, Vst1),
+ case Val of
+ {literal,Tuple} when is_tuple(Tuple) ->
+ Type0 = get_term_type(Val, Vst),
+ Type = upgrade_tuple_type({tuple,tuple_size(Tuple)},
+ Type0),
+ set_aliased_type(Type, Src, Vst);
+ _ ->
+ Vst
end;
valfun_4({test,_Op,{f,Lbl},Src}, Vst) ->
validate_src(Src, Vst),
@@ -879,21 +949,15 @@ val_dsetel({set_tuple_element,_,_,_}, #vst{current=#st{setelem=false}}) ->
error(illegal_context_for_set_tuple_element);
val_dsetel({set_tuple_element,_,_,_}, #vst{current=#st{setelem=true}}=Vst) ->
Vst;
+val_dsetel({get_tuple_element,_,_,_}, Vst) ->
+ Vst;
val_dsetel({line,_}, Vst) ->
Vst;
val_dsetel(_, #vst{current=#st{setelem=true}=St}=Vst) ->
Vst#vst{current=St#st{setelem=false}};
val_dsetel(_, Vst) -> Vst.
-kill_state(#vst{current=#st{ct=[[Fail]|_]}}=Vst) when is_integer(Fail) ->
- %% There is an active catch. Make sure that we merge the state into
- %% the catch label before clearing it, so that that we can be sure
- %% that the label gets a state.
- kill_state_1(branch_state(Fail, Vst));
kill_state(Vst) ->
- kill_state_1(Vst).
-
-kill_state_1(Vst) ->
Vst#vst{current=none}.
%% A "plain" call.
@@ -906,7 +970,7 @@ call(Name, Live, #vst{current=St}=Vst) ->
Type when Type =/= exception ->
%% Type is never 'exception' because it has been handled earlier.
Xs = gb_trees_from_list([{0,Type}]),
- Vst#vst{current=St#st{x=Xs,f=init_fregs()}}
+ Vst#vst{current=St#st{x=Xs,f=init_fregs(),aliases=#{}}}
end.
%% Tail call.
@@ -1019,13 +1083,50 @@ heap_alloc_2([{floats,Floats}|T], St0) ->
St = St0#st{hf=Floats},
heap_alloc_2(T, St);
heap_alloc_2([], St) -> St.
-
-prune_x_regs(Live, #vst{current=#st{x=Xs0}=St0}=Vst) when is_integer(Live) ->
+
+prune_x_regs(Live, #vst{current=St0}=Vst)
+ when is_integer(Live) ->
+ #st{x=Xs0,defs=Defs0,aliases=Aliases0} = St0,
Xs1 = gb_trees:to_list(Xs0),
Xs = [P || {R,_}=P <- Xs1, R < Live],
- St = St0#st{x=gb_trees:from_orddict(Xs)},
+ Defs = maps:filter(fun({x,X}, _) -> X < Live;
+ ({y,_}, _) -> true
+ end, Defs0),
+ Aliases = maps:filter(fun({x,X1}, {x,X2}) ->
+ X1 < Live andalso X2 < Live;
+ ({x,X}, _) ->
+ X < Live;
+ (_, {x,X}) ->
+ X < Live;
+ (_, _) ->
+ true
+ end, Aliases0),
+ St = St0#st{x=gb_trees:from_orddict(Xs),defs=Defs,aliases=Aliases},
Vst#vst{current=St}.
+%% All choices in a select_val list must be integers, floats, or atoms.
+%% All must be of the same type.
+assert_choices([{Tag,_},{f,_}|T]) ->
+ if
+ Tag =:= atom; Tag =:= float; Tag =:= integer ->
+ assert_choices_1(T, Tag);
+ true ->
+ error(bad_select_list)
+ end;
+assert_choices([]) -> ok.
+
+assert_choices_1([{Tag,_},{f,_}|T], Tag) ->
+ assert_choices_1(T, Tag);
+assert_choices_1([_,{f,_}|_], _Tag) ->
+ error(bad_select_list);
+assert_choices_1([], _Tag) -> ok.
+
+assert_arities([Arity,{f,_}|T]) when is_integer(Arity) ->
+ assert_arities(T);
+assert_arities([]) -> ok;
+assert_arities(_) -> error(bad_tuple_arity_list).
+
+
%%%
%%% Floating point checking.
%%%
@@ -1154,10 +1255,73 @@ bsm_restore(Reg, SavePoint, Vst) ->
_ -> error({illegal_restore,SavePoint,range})
end.
+select_val_branches(Src, Choices, Vst) ->
+ Infer = infer_types(Src, Vst),
+ select_val_branches_1(Choices, Infer, Vst).
+
+select_val_branches_1([Val,{f,L}|T], Infer, Vst0) ->
+ Vst = branch_state(L, Infer(Val, Vst0)),
+ select_val_branches_1(T, Infer, Vst);
+select_val_branches_1([], _, Vst) -> Vst.
+
+infer_types(Src, Vst) ->
+ case get_def(Src, Vst) of
+ {bif,is_map,{f,_},[Map],_} ->
+ fun({atom,true}, S) -> set_type_reg(map, Map, S);
+ (_, S) -> S
+ end;
+ {bif,tuple_size,{f,_},[Tuple],_} ->
+ fun({integer,Arity}, S) ->
+ Type0 = get_term_type(Tuple, S),
+ Type = upgrade_tuple_type({tuple,Arity}, Type0),
+ set_type(Type, Tuple, S);
+ (_, S) -> S
+ end;
+ {bif,'=:=',{f,_},[ArityReg,{integer,_}=Val],_} when ArityReg =/= Src ->
+ fun({atom,true}, S) ->
+ Infer = infer_types(ArityReg, S),
+ Infer(Val, S);
+ (_, S) -> S
+ end;
+ _ ->
+ fun(_, S) -> S end
+ end.
+
%%%
%%% Keeping track of types.
%%%
+set_alias(Reg1, Reg2, #vst{current=St0}=Vst) ->
+ case Reg1 of
+ {Kind,_} when Kind =:= x; Kind =:= y ->
+ #st{aliases=Aliases0} = St0,
+ Aliases = Aliases0#{Reg1=>Reg2,Reg2=>Reg1},
+ St = St0#st{aliases=Aliases},
+ Vst#vst{current=St};
+ _ ->
+ Vst
+ end.
+
+set_aliased_type(Type, Reg, #vst{current=#st{aliases=Aliases}}=Vst0) ->
+ Vst1 = set_type(Type, Reg, Vst0),
+ case Aliases of
+ #{Reg:=OtherReg} ->
+ Vst = set_type_reg(Type, OtherReg, Vst1),
+ #vst{current=St} = Vst,
+ Vst#vst{current=St#st{aliases=Aliases}};
+ #{} ->
+ Vst1
+ end.
+
+kill_aliases(Reg, #st{aliases=Aliases0}=St) ->
+ case Aliases0 of
+ #{Reg:=OtherReg} ->
+ Aliases = maps:without([Reg,OtherReg], Aliases0),
+ St#st{aliases=Aliases};
+ #{} ->
+ St
+ end.
+
set_type(Type, {x,_}=Reg, Vst) -> set_type_reg(Type, Reg, Vst);
set_type(Type, {y,_}=Reg, Vst) -> set_type_y(Type, Reg, Vst);
set_type(_, _, #vst{}=Vst) -> Vst.
@@ -1170,12 +1334,18 @@ set_type_reg(Type, Src, Dst, Vst) ->
set_type_reg(Type, Dst, Vst)
end.
-set_type_reg(Type, {x,_}=Reg, Vst) ->
- set_type_x(Type, Reg, Vst);
set_type_reg(Type, Reg, Vst) ->
- set_type_y(Type, Reg, Vst).
+ set_type_reg_expr(Type, none, Reg, Vst).
+
+set_type_reg_expr(Type, Expr, {x,_}=Reg, Vst) ->
+ set_type_x(Type, Expr, Reg, Vst);
+set_type_reg_expr(Type, Expr, Reg, Vst) ->
+ set_type_y(Type, Expr, Reg, Vst).
+
+set_type_y(Type, Reg, Vst) ->
+ set_type_y(Type, none, Reg, Vst).
-set_type_x(Type, {x,X}=Reg, #vst{current=#st{x=Xs0}=St}=Vst)
+set_type_x(Type, Expr, {x,X}=Reg, #vst{current=#st{x=Xs0,defs=Defs0}=St0}=Vst)
when is_integer(X), 0 =< X ->
check_limit(Reg),
Xs = case gb_trees:lookup(X, Xs0) of
@@ -1186,11 +1356,13 @@ set_type_x(Type, {x,X}=Reg, #vst{current=#st{x=Xs0}=St}=Vst)
{value,_} ->
gb_trees:update(X, Type, Xs0)
end,
- Vst#vst{current=St#st{x=Xs}};
-set_type_x(Type, Reg, #vst{}) ->
+ Defs = Defs0#{Reg=>Expr},
+ St = kill_aliases(Reg, St0),
+ Vst#vst{current=St#st{x=Xs,defs=Defs}};
+set_type_x(Type, _Expr, Reg, #vst{}) ->
error({invalid_store,Reg,Type}).
-set_type_y(Type, {y,Y}=Reg, #vst{current=#st{y=Ys0}=St}=Vst)
+set_type_y(Type, Expr, {y,Y}=Reg, #vst{current=#st{y=Ys0,defs=Defs0}=St0}=Vst)
when is_integer(Y), 0 =< Y ->
check_limit(Reg),
Ys = case gb_trees:lookup(Y, Ys0) of
@@ -1204,8 +1376,11 @@ set_type_y(Type, {y,Y}=Reg, #vst{current=#st{y=Ys0}=St}=Vst)
gb_trees:update(Y, Type, Ys0)
end,
check_try_catch_tags(Type, Y, Ys0),
- Vst#vst{current=St#st{y=Ys}};
-set_type_y(Type, Reg, #vst{}) -> error({invalid_store,Reg,Type}).
+ Defs = Defs0#{Reg=>Expr},
+ St = kill_aliases(Reg, St0),
+ Vst#vst{current=St#st{y=Ys,defs=Defs}};
+set_type_y(Type, _Expr, Reg, #vst{}) ->
+ error({invalid_store,Reg,Type}).
make_fragile({fragile,_}=Type) -> Type;
make_fragile(Type) -> {fragile,Type}.
@@ -1417,6 +1592,8 @@ get_term_type_1({atom,A}=T, _) when is_atom(A) -> T;
get_term_type_1({float,F}=T, _) when is_float(F) -> T;
get_term_type_1({integer,I}=T, _) when is_integer(I) -> T;
get_term_type_1({literal,Map}, _) when is_map(Map) -> map;
+get_term_type_1({literal,Tuple}, _) when is_tuple(Tuple) ->
+ {tuple,tuple_size(Tuple)};
get_term_type_1({literal,_}=T, _) -> T;
get_term_type_1({x,X}=Reg, #vst{current=#st{x=Xs}}) when is_integer(X) ->
case gb_trees:lookup(X, Xs) of
@@ -1431,6 +1608,11 @@ get_term_type_1({y,Y}=Reg, #vst{current=#st{y=Ys}}) when is_integer(Y) ->
end;
get_term_type_1(Src, _) -> error({bad_source,Src}).
+get_def(Src, #vst{current=#st{defs=Defs}}) ->
+ case Defs of
+ #{Src:=Def} -> Def;
+ #{} -> none
+ end.
%% get_literal(Src) -> literal_value().
get_literal(nil) -> [];
@@ -1440,13 +1622,20 @@ get_literal({integer,I}) when is_integer(I) -> I;
get_literal({literal,L}) -> L;
get_literal(T) -> error({not_literal,T}).
-
-branch_arities([], _, #vst{}=Vst) -> Vst;
-branch_arities([Sz,{f,L}|T], Tuple, #vst{current=St}=Vst0)
- when is_integer(Sz) ->
- Vst1 = set_type_reg({tuple,Sz}, Tuple, Vst0),
+branch_arities([Sz,{f,L}|T], Tuple, {tuple,[_]}=Type0, Vst0) when is_integer(Sz) ->
+ Vst1 = set_aliased_type({tuple,Sz}, Tuple, Vst0),
Vst = branch_state(L, Vst1),
- branch_arities(T, Tuple, Vst#vst{current=St}).
+ branch_arities(T, Tuple, Type0, Vst);
+branch_arities([Sz,{f,L}|T], Tuple, {tuple,Sz}=Type, Vst0) when is_integer(Sz) ->
+ %% The type is already correct. (This test is redundant.)
+ Vst = branch_state(L, Vst0),
+ branch_arities(T, Tuple, Type, Vst);
+branch_arities([Sz0,{f,_}|T], Tuple, {tuple,Sz}=Type, Vst)
+ when is_integer(Sz), Sz0 =/= Sz ->
+ %% We already have an established different exact size for the tuple.
+ %% This label can't possibly be reached.
+ branch_arities(T, Tuple, Type, Vst);
+branch_arities([], _, _, #vst{}=Vst) -> Vst.
branch_state(0, #vst{}=Vst) ->
%% If the instruction fails, the stack may be scanned
@@ -1476,13 +1665,14 @@ merge_states(L, St, Branched) when L =/= 0 ->
{value,OtherSt} -> merge_states_1(St, OtherSt)
end.
-merge_states_1(#st{x=Xs0,y=Ys0,numy=NumY0,h=H0,ct=Ct0},
- #st{x=Xs1,y=Ys1,numy=NumY1,h=H1,ct=Ct1}) ->
+merge_states_1(#st{x=Xs0,y=Ys0,numy=NumY0,h=H0,ct=Ct0,aliases=Aliases0},
+ #st{x=Xs1,y=Ys1,numy=NumY1,h=H1,ct=Ct1,aliases=Aliases1}) ->
NumY = merge_stk(NumY0, NumY1),
Xs = merge_regs(Xs0, Xs1),
Ys = merge_y_regs(Ys0, Ys1),
Ct = merge_ct(Ct0, Ct1),
- #st{x=Xs,y=Ys,numy=NumY,h=min(H0, H1),ct=Ct}.
+ Aliases = merge_aliases(Aliases0, Aliases1),
+ #st{x=Xs,y=Ys,numy=NumY,h=min(H0, H1),ct=Ct,aliases=Aliases}.
merge_stk(S, S) -> S;
merge_stk(_, _) -> undecided.
@@ -1567,6 +1757,12 @@ merge_types(bool, {atom,A}) ->
merge_bool(A);
merge_types({atom,A}, bool) ->
merge_bool(A);
+merge_types(cons, {literal,[_|_]}) ->
+ cons;
+merge_types({literal,[_|_]}, cons) ->
+ cons;
+merge_types({literal,[_|_]}, {literal,[_|_]}) ->
+ cons;
merge_types(#ms{id=Id1,valid=B1,slots=Slots1},
#ms{id=Id2,valid=B2,slots=Slots2}) ->
Id = if
@@ -1585,7 +1781,17 @@ merge_bool([]) -> {atom,[]};
merge_bool(true) -> bool;
merge_bool(false) -> bool;
merge_bool(_) -> {atom,[]}.
-
+
+merge_aliases(Al0, Al1) when map_size(Al0) =< map_size(Al1) ->
+ maps:filter(fun(K, V) ->
+ case Al1 of
+ #{K:=V} -> true;
+ #{} -> false
+ end
+ end, Al0);
+merge_aliases(Al0, Al1) ->
+ merge_aliases(Al1, Al0).
+
verify_y_init(#vst{current=#st{y=Ys}}) ->
verify_y_init_1(gb_trees:to_list(Ys)).
@@ -1752,6 +1958,12 @@ is_bif_safe(self, 0) -> true;
is_bif_safe(node, 0) -> true;
is_bif_safe(_, _) -> false.
+arith_type([A], Vst) ->
+ %% Unary '+' or '-'.
+ case get_term_type(A, Vst) of
+ {float,_} -> {float,[]};
+ _ -> number
+ end;
arith_type([A,B], Vst) ->
case {get_term_type(A, Vst),get_term_type(B, Vst)} of
{{float,_},_} -> {float,[]};
diff --git a/lib/compiler/src/beam_z.erl b/lib/compiler/src/beam_z.erl
index 1c9d762eb1..677094b3cd 100644
--- a/lib/compiler/src/beam_z.erl
+++ b/lib/compiler/src/beam_z.erl
@@ -110,6 +110,8 @@ undo_rename({test,has_map_fields,Fail,[Src|List]}) ->
{test,has_map_fields,Fail,Src,{list,List}};
undo_rename({get_map_elements,Fail,Src,{list,List}}) ->
{get_map_elements,Fail,Src,{list,List}};
+undo_rename({test,is_eq_exact,Fail,[Src,nil]}) ->
+ {test,is_nil,Fail,[Src]};
undo_rename({select,I,Reg,Fail,List}) ->
{I,Reg,Fail,{list,List}};
undo_rename(I) -> I.
diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl
index e1c1f7338e..74ad864163 100644
--- a/lib/compiler/src/compile.erl
+++ b/lib/compiler/src/compile.erl
@@ -31,6 +31,9 @@
%% Erlc interface.
-export([compile/3,compile_beam/3,compile_asm/3,compile_core/3]).
+%% Utility functions for compiler passes.
+-export([run_sub_passes/2]).
+
-export_type([option/0]).
-include("erl_compile.hrl").
@@ -39,6 +42,8 @@
-import(lists, [member/2,reverse/1,reverse/2,keyfind/3,last/1,
map/2,flatmap/2,foreach/2,foldr/3,any/2]).
+-define(SUB_PASS_TIMES, compile__sub_pass_times).
+
%%----------------------------------------------------------------------
-type abstract_code() :: [erl_parse:abstract_form()].
@@ -64,6 +69,7 @@
-type err_ret() :: 'error' | {'error', errors(), warnings()}.
-type comp_ret() :: mod_ret() | bin_ret() | err_ret().
+
%%----------------------------------------------------------------------
%%
@@ -143,6 +149,30 @@ noenv_output_generated(Opts) ->
env_compiler_options() -> env_default_opts().
+
+%%%
+%%% Run sub passes from a compiler pass.
+%%%
+
+-spec run_sub_passes([term()], term()) -> term().
+
+run_sub_passes(Ps, St) ->
+ case get(?SUB_PASS_TIMES) of
+ undefined ->
+ Runner = fun(_Name, Run, S) -> Run(S) end,
+ run_sub_passes_1(Ps, Runner, St);
+ Times when is_list(Times) ->
+ Runner = fun(Name, Run, S0) ->
+ T1 = erlang:monotonic_time(),
+ S = Run(S0),
+ T2 = erlang:monotonic_time(),
+ put(?SUB_PASS_TIMES,
+ [{Name,T2-T1}|get(?SUB_PASS_TIMES)]),
+ S
+ end,
+ run_sub_passes_1(Ps, Runner, St)
+ end.
+
%%
%% Local functions
%%
@@ -219,22 +249,24 @@ expand_opt(report, Os) ->
expand_opt(return, Os) ->
[return_errors,return_warnings|Os];
expand_opt(r16, Os) ->
- [no_get_hd_tl,no_record_opt,no_utf8_atoms|Os];
+ expand_opt_before_21(Os);
expand_opt(r17, Os) ->
- [no_get_hd_tl,no_record_opt,no_utf8_atoms|Os];
+ expand_opt_before_21(Os);
expand_opt(r18, Os) ->
- [no_get_hd_tl,no_record_opt,no_utf8_atoms|Os];
+ expand_opt_before_21(Os);
expand_opt(r19, Os) ->
- [no_get_hd_tl,no_record_opt,no_utf8_atoms|Os];
+ expand_opt_before_21(Os);
expand_opt(r20, Os) ->
- [no_get_hd_tl,no_record_opt,no_utf8_atoms|Os];
+ expand_opt_before_21(Os);
+expand_opt(r21, Os) ->
+ [no_put_tuple2|Os];
expand_opt({debug_info_key,_}=O, Os) ->
[encrypt_debug_info,O|Os];
-expand_opt(no_float_opt, Os) ->
- %%Turn off the entire type optimization pass.
- [no_topt|Os];
expand_opt(O, Os) -> [O|Os].
+expand_opt_before_21(Os) ->
+ [no_put_tuple2,no_get_hd_tl,no_ssa_opt_record,no_utf8_atoms|Os].
+
%% format_error(ErrorDescriptor) -> string()
-spec format_error(term()) -> iolist().
@@ -387,17 +419,57 @@ fold_comp([{Name,Pass}|Ps], Run, Code0, St0) ->
end;
fold_comp([], _Run, Code, St) -> {ok,Code,St}.
+run_sub_passes_1([{Name,Run}|Ps], Runner, St0)
+ when is_atom(Name), is_function(Run, 1) ->
+ try Runner(Name, Run, St0) of
+ St ->
+ run_sub_passes_1(Ps, Runner, St)
+ catch
+ C:E:Stk ->
+ io:format("Sub pass ~s\n", [Name]),
+ erlang:raise(C, E, Stk)
+ end;
+run_sub_passes_1([], _, St) -> St.
+
run_tc({Name,Fun}, Code, St) ->
+ put(?SUB_PASS_TIMES, []),
T1 = erlang:monotonic_time(),
Val = (catch Fun(Code, St)),
T2 = erlang:monotonic_time(),
- Elapsed = erlang:convert_time_unit(T2 - T1, native, millisecond),
+ Times = erase(?SUB_PASS_TIMES),
+ Elapsed = erlang:convert_time_unit(T2 - T1, native, microsecond),
Mem0 = erts_debug:flat_size(Val)*erlang:system_info(wordsize),
Mem = lists:flatten(io_lib:format("~.1f kB", [Mem0/1024])),
io:format(" ~-30s: ~10.3f s ~12s\n",
- [Name,Elapsed/1000,Mem]),
+ [Name,Elapsed/1000000,Mem]),
+ print_times(Times, Name),
Val.
+print_times(Times0, Name) ->
+ Fam0 = sofs:relation(Times0),
+ Fam1 = sofs:rel2fam(Fam0),
+ Fam2 = sofs:to_external(Fam1),
+ Fam3 = [{W,lists:sum(Times)} || {W,Times} <- Fam2],
+ Fam = reverse(lists:keysort(2, Fam3)),
+ Total = case lists:sum([T || {_,T} <- Fam]) of
+ 0 -> 1;
+ Total0 -> Total0
+ end,
+ case Fam of
+ [] ->
+ ok;
+ [_|_] ->
+ io:format(" %% Sub passes of ~s from slowest to fastest:\n", [Name]),
+ print_times_1(Fam, Total)
+ end.
+
+print_times_1([{Name,T}|Ts], Total) ->
+ Elapsed = erlang:convert_time_unit(T, native, microsecond),
+ io:format(" ~-27s: ~10.3f s ~3w %\n",
+ [Name,Elapsed/1000000,round(100*T/Total)]),
+ print_times_1(Ts, Total);
+print_times_1([], _Total) -> ok.
+
run_eprof({Name,Fun}, Code, Name, St) ->
io:format("~p: Running eprof\n", [Name]),
c:appcall(tools, eprof, start_profiling, [[self()]]),
@@ -741,8 +813,20 @@ kernel_passes() ->
?pass(v3_kernel),
{iff,dkern,{listing,"kernel"}},
{iff,'to_kernel',{done,"kernel"}},
- {pass,v3_codegen},
- {iff,dcg,{listing,"codegen"}}
+ {pass,beam_kernel_to_ssa},
+ {iff,dssa,{listing,"ssa"}},
+ {iff,ssalint,{pass,beam_ssa_lint}},
+ {unless,no_ssa_opt,{pass,beam_ssa_opt}},
+ {iff,dssaopt,{listing,"ssaopt"}},
+ {iff,ssalint,{pass,beam_ssa_lint}},
+ {unless,no_recv_opt,{pass,beam_ssa_recv}},
+ {iff,drecv,{listing,"recv"}},
+ {pass,beam_ssa_pre_codegen},
+ {iff,dprecg,{listing,"precodegen"}},
+ {iff,ssalint,{pass,beam_ssa_lint}},
+ {pass,beam_ssa_codegen},
+ {iff,dcg,{listing,"codegen"}},
+ {iff,doldcg,{listing,"codegen"}}
| asm_passes()].
asm_passes() ->
@@ -751,20 +835,12 @@ asm_passes() ->
[{pass,beam_a},
{iff,da,{listing,"a"}},
{unless,no_postopt,
- [{unless,no_reorder,{pass,beam_reorder}},
- {iff,dre,{listing,"reorder"}},
- {pass,beam_block},
+ [{pass,beam_block},
{iff,dblk,{listing,"block"}},
{unless,no_except,{pass,beam_except}},
{iff,dexcept,{listing,"except"}},
{unless,no_bs_opt,{pass,beam_bs}},
{iff,dbs,{listing,"bs"}},
- {unless,no_topt,{pass,beam_type}},
- {iff,dtype,{listing,"type"}},
- {pass,beam_split},
- {iff,dsplit,{listing,"split"}},
- {unless,no_dead,{pass,beam_dead}},
- {iff,ddead,{listing,"dead"}},
{unless,no_jopt,{pass,beam_jump}},
{iff,djmp,{listing,"jump"}},
{unless,no_peep_opt,{pass,beam_peep}},
@@ -773,12 +849,6 @@ asm_passes() ->
{iff,dclean,{listing,"clean"}},
{unless,no_bsm_opt,{pass,beam_bsm}},
{iff,dbsm,{listing,"bsm"}},
- {unless,no_recv_opt,{pass,beam_receive}},
- {iff,drecv,{listing,"recv"}},
- {unless,no_record_opt,{pass,beam_record}},
- {iff,drecord,{listing,"record"}},
- {unless,no_blk2,?pass(block2)},
- {iff,dblk2,{listing,"block2"}},
{unless,no_stack_trimming,{pass,beam_trim}},
{iff,dtrim,{listing,"trim"}},
{pass,beam_flatten}]},
@@ -1354,10 +1424,6 @@ v3_kernel(Code0, #compile{options=Opts,warnings=Ws0}=St) ->
{ok,Code,St}
end.
-block2(Code0, #compile{options=Opts}=St) ->
- {ok,Code} = beam_block:module(Code0, [no_blockify|Opts]),
- {ok,Code,St}.
-
test_old_inliner(#compile{options=Opts}) ->
%% The point of this test is to avoid loading the old inliner
%% if we know that it will not be used.
@@ -1603,7 +1669,6 @@ effects_code_generation(Option) ->
binary -> false;
verbose -> false;
{cwd,_} -> false;
- {i,_} -> false;
{outdir, _} -> false;
_ -> true
end.
@@ -1967,19 +2032,21 @@ pre_load() ->
beam_bs,
beam_bsm,
beam_clean,
- beam_dead,
beam_dict,
beam_except,
beam_flatten,
beam_jump,
+ beam_kernel_to_ssa,
beam_opcodes,
beam_peep,
- beam_receive,
- beam_record,
- beam_reorder,
- beam_split,
+ beam_ssa,
+ beam_ssa_codegen,
+ beam_ssa_dead,
+ beam_ssa_opt,
+ beam_ssa_pre_codegen,
+ beam_ssa_recv,
+ beam_ssa_type,
beam_trim,
- beam_type,
beam_utils,
beam_validator,
beam_z,
@@ -1998,7 +2065,6 @@ pre_load() ->
sys_core_bsm,
sys_core_dsetel,
sys_core_fold,
- v3_codegen,
v3_core,
v3_kernel],
_ = code:ensure_modules_loaded(L),
diff --git a/lib/compiler/src/compiler.app.src b/lib/compiler/src/compiler.app.src
index cf32fd251c..bb281376ef 100644
--- a/lib/compiler/src/compiler.app.src
+++ b/lib/compiler/src/compiler.app.src
@@ -27,21 +27,25 @@
beam_bs,
beam_bsm,
beam_clean,
- beam_dead,
beam_dict,
beam_disasm,
beam_except,
beam_flatten,
beam_jump,
+ beam_kernel_to_ssa,
beam_listing,
beam_opcodes,
beam_peep,
- beam_receive,
- beam_reorder,
- beam_record,
- beam_split,
+ beam_ssa,
+ beam_ssa_codegen,
+ beam_ssa_dead,
+ beam_ssa_lint,
+ beam_ssa_opt,
+ beam_ssa_pp,
+ beam_ssa_pre_codegen,
+ beam_ssa_recv,
+ beam_ssa_type,
beam_trim,
- beam_type,
beam_utils,
beam_validator,
beam_z,
@@ -65,7 +69,6 @@
sys_core_fold_lists,
sys_core_inline,
sys_pre_attributes,
- v3_codegen,
v3_core,
v3_kernel,
v3_kernel_pp
diff --git a/lib/compiler/src/genop.tab b/lib/compiler/src/genop.tab
index f35ae09fe7..8e34e3e291 100755
--- a/lib/compiler/src/genop.tab
+++ b/lib/compiler/src/genop.tab
@@ -573,3 +573,8 @@ BEAM_FORMAT_NUMBER=0
## @doc Get the tail (or cdr) part of a list (a cons cell) from Source and
## put it into the register Tail.
163: get_tl/2
+
+## @spec put_tuple2 Destination Elements
+## @doc Build a tuple with the elements in the list Elements and put it
+## put into register Destination.
+164: put_tuple2/2
diff --git a/lib/compiler/src/v3_codegen.erl b/lib/compiler/src/v3_codegen.erl
deleted file mode 100644
index e9152ba88f..0000000000
--- a/lib/compiler/src/v3_codegen.erl
+++ /dev/null
@@ -1,2925 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2018. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-%% Purpose : Code generator for Beam.
-
--module(v3_codegen).
-
-%% The main interface.
--export([module/2]).
-
--import(lists, [member/2,keymember/3,keysort/2,keydelete/3,
- append/1,flatmap/2,filter/2,foldl/3,foldr/3,mapfoldl/3,
- sort/1,reverse/1,reverse/2,map/2]).
--import(ordsets, [add_element/2,intersection/2,union/2]).
-
--include("v3_kernel.hrl").
-
-%% These are not defined in v3_kernel.hrl.
-get_kanno(Kthing) -> element(2, Kthing).
-set_kanno(Kthing, Anno) -> setelement(2, Kthing, Anno).
-
-%% Main codegen structure.
--record(cg, {lcount=1, %Label counter
- bfail, %Fail label for BIFs
- break, %Break label
- recv, %Receive label
- is_top_block, %Boolean: top block or not
- functable=#{}, %Map of local functions: {Name,Arity}=>Label
- in_catch=false, %Inside a catch or not.
- need_frame, %Need a stack frame.
- ultimate_failure, %Label for ultimate match failure.
- ctx %Match context.
- }).
-
-%% Stack/register state record.
--record(sr, {reg=[], %Register table
- stk=[], %Stack table
- res=[]}). %Registers to reserve
-
-%% Internal records.
--record(cg_need_heap, {anno=[] :: term(),
- h=0 :: integer()}).
--record(cg_block, {anno=[] :: term(),
- es=[] :: [term()]}).
-
--type vdb_entry() :: {atom(),non_neg_integer(),non_neg_integer()}.
-
--record(l, {i=0 :: non_neg_integer(), %Op number
- vdb=[] :: [vdb_entry()], %Variable database
- a=[] :: [term()]}). %Core annotation
-
--spec module(#k_mdef{}, [compile:option()]) -> {'ok',beam_asm:module_code()}.
-
-module(#k_mdef{name=Mod,exports=Es,attributes=Attr,body=Forms}, _Opts) ->
- {Asm,St} = functions(Forms, {atom,Mod}),
- {ok,{Mod,Es,Attr,Asm,St#cg.lcount}}.
-
-functions(Forms, AtomMod) ->
- mapfoldl(fun (F, St) -> function(F, AtomMod, St) end, #cg{lcount=1}, Forms).
-
-function(#k_fdef{anno=#k{a=Anno},func=Name,arity=Arity,
- vars=As,body=Kb}, AtomMod, St0) ->
- try
- #k_match{} = Kb, %Assertion.
-
- %% Try to suppress the stack frame unless it is
- %% really needed.
- Body0 = avoid_stack_frame(Kb),
-
- %% Annotate kernel records with variable usage.
- Vdb0 = init_vars(As),
- {Body,_,Vdb} = body(Body0, 1, Vdb0),
-
- %% Generate the BEAM assembly code.
- {Asm,EntryLabel,St} = cg_fun(Body, As, Vdb, AtomMod,
- {Name,Arity}, Anno, St0),
- Func = {function,Name,Arity,EntryLabel,Asm},
- {Func,St}
- catch
- Class:Error:Stack ->
- io:fwrite("Function: ~w/~w\n", [Name,Arity]),
- erlang:raise(Class, Error, Stack)
- end.
-
-
-%% avoid_stack_frame(Kernel) -> Kernel'
-%% If possible, avoid setting up a stack frame. Functions
-%% that only do matching, calls to guard BIFs, and tail-recursive
-%% calls don't need a stack frame.
-
-avoid_stack_frame(#k_match{body=Body}=M) ->
- try
- M#k_match{body=avoid_stack_frame_1(Body)}
- catch
- impossible ->
- M
- end.
-
-avoid_stack_frame_1(#k_alt{first=First0,then=Then0}=Alt) ->
- First = avoid_stack_frame_1(First0),
- Then = avoid_stack_frame_1(Then0),
- Alt#k_alt{first=First,then=Then};
-avoid_stack_frame_1(#k_bif{op=Op}=Bif) ->
- case Op of
- #k_internal{} ->
- %% Most internal BIFs clobber the X registers.
- throw(impossible);
- _ ->
- Bif
- end;
-avoid_stack_frame_1(#k_break{anno=Anno,args=Args}) ->
- #k_guard_break{anno=Anno,args=Args};
-avoid_stack_frame_1(#k_guard_break{}=Break) ->
- Break;
-avoid_stack_frame_1(#k_enter{}=Enter) ->
- %% Tail-recursive calls don't need a stack frame.
- Enter;
-avoid_stack_frame_1(#k_guard{clauses=Cs0}=Guard) ->
- Cs = avoid_stack_frame_list(Cs0),
- Guard#k_guard{clauses=Cs};
-avoid_stack_frame_1(#k_guard_clause{guard=G0,body=B0}=C) ->
- G = avoid_stack_frame_1(G0),
- B = avoid_stack_frame_1(B0),
- C#k_guard_clause{guard=G,body=B};
-avoid_stack_frame_1(#k_match{anno=A,vars=Vs,body=B0,ret=Ret}) ->
- %% Use #k_guard_match{} instead to avoid saving the X registers
- %% to the stack before matching.
- B = avoid_stack_frame_1(B0),
- #k_guard_match{anno=A,vars=Vs,body=B,ret=Ret};
-avoid_stack_frame_1(#k_guard_match{body=B0}=M) ->
- B = avoid_stack_frame_1(B0),
- M#k_guard_match{body=B};
-avoid_stack_frame_1(#k_protected{arg=Arg0}=Prot) ->
- Arg = avoid_stack_frame_1(Arg0),
- Prot#k_protected{arg=Arg};
-avoid_stack_frame_1(#k_put{}=Put) ->
- Put;
-avoid_stack_frame_1(#k_return{}=Ret) ->
- Ret;
-avoid_stack_frame_1(#k_select{var=#k_var{anno=Vanno},types=Types0}=Select) ->
- case member(reuse_for_context, Vanno) of
- false ->
- Types = avoid_stack_frame_list(Types0),
- Select#k_select{types=Types};
- true ->
- %% Including binary patterns that overwrite the register containing
- %% the binary with the match context may not be safe. For example,
- %% bs_match_SUITE:bin_tail_e/1 with inlining will be rejected by
- %% beam_validator.
- %%
- %% Essentially the following code is produced:
- %%
- %% bs_match {x,0} => {x,0}
- %% ...
- %% bs_match {x,0} => {x,1} %% ILLEGAL
- %%
- %% A bs_match instruction will only accept a match context as the
- %% source operand if the source and destination registers are the
- %% the same (as in the first bs_match instruction above).
- %% The second bs_match instruction is therefore illegal.
- %%
- %% This situation is avoided if there is a stack frame:
- %%
- %% move {x,0} => {y,0}
- %% bs_match {x,0} => {x,0}
- %% ...
- %% bs_match {y,0} => {x,1} %% LEGAL
- %%
- throw(impossible)
- end;
-avoid_stack_frame_1(#k_seq{arg=#k_call{anno=Anno,op=Op}=Call,
- body=#k_break{args=BrArgs0}}=Seq) ->
- case Op of
- #k_remote{mod=#k_atom{val=Mod},
- name=#k_atom{val=Name},
- arity=Arity} ->
- case erl_bifs:is_exit_bif(Mod, Name, Arity) of
- false ->
- %% Will clobber X registers. Must have a stack frame.
- throw(impossible);
- true ->
- %% The call to this BIF will never return. It is safe
- %% to suppress the stack frame.
- Bif = #k_bif{anno=Anno,
- op=#k_internal{name=guard_error,arity=1},
- args=[Call],ret=[]},
- BrArgs = lists:duplicate(length(BrArgs0), #k_nil{}),
- GB = #k_guard_break{anno=#k{us=[],ns=[],a=[]},args=BrArgs},
- Seq#k_seq{arg=Bif,body=GB}
- end;
- _ ->
- %% Will clobber X registers. Must have a stack frame.
- throw(impossible)
- end;
-avoid_stack_frame_1(#k_seq{arg=A0,body=B0}=Seq) ->
- A = avoid_stack_frame_1(A0),
- B = avoid_stack_frame_1(B0),
- Seq#k_seq{arg=A,body=B};
-avoid_stack_frame_1(#k_test{}=Test) ->
- Test;
-avoid_stack_frame_1(#k_type_clause{values=Values0}=TC) ->
- Values = avoid_stack_frame_list(Values0),
- TC#k_type_clause{values=Values};
-avoid_stack_frame_1(#k_val_clause{body=B0}=VC) ->
- B = avoid_stack_frame_1(B0),
- VC#k_val_clause{body=B};
-avoid_stack_frame_1(_Body) ->
- throw(impossible).
-
-avoid_stack_frame_list([H|T]) ->
- [avoid_stack_frame_1(H)|avoid_stack_frame_list(T)];
-avoid_stack_frame_list([]) -> [].
-
-
-%% This pass creates beam format annotated with variable lifetime
-%% information. Each thing is given an index and for each variable we
-%% store the first and last index for its occurrence. The variable
-%% database, VDB, attached to each thing is only relevant internally
-%% for that thing.
-%%
-%% For nested things like matches the numbering continues locally and
-%% the VDB for that thing refers to the variable usage within that
-%% thing. Variables which live through a such a thing are internally
-%% given a very large last index. Internally the indexes continue
-%% after the index of that thing. This creates no problems as the
-%% internal variable info never escapes and externally we only see
-%% variable which are alive both before or after.
-%%
-%% This means that variables never "escape" from a thing and the only
-%% way to get values from a thing is to "return" them, with 'break' or
-%% 'return'. Externally these values become the return values of the
-%% thing. This is no real limitation as most nested things have
-%% multiple threads so working out a common best variable usage is
-%% difficult.
-
-%% body(Kbody, I, Vdb) -> {[Expr],MaxI,Vdb}.
-%% Handle a body.
-
-body(#k_seq{arg=Ke,body=Kb}, I, Vdb0) ->
- %%ok = io:fwrite("life ~w:~p~n", [?LINE,{Ke,I,Vdb0}]),
- A = get_kanno(Ke),
- Vdb1 = use_vars(union(A#k.us, A#k.ns), I, Vdb0),
- {Es,MaxI,Vdb2} = body(Kb, I+1, Vdb1),
- E = expr(Ke, I, Vdb2),
- {[E|Es],MaxI,Vdb2};
-body(Ke, I, Vdb0) ->
- %%ok = io:fwrite("life ~w:~p~n", [?LINE,{Ke,I,Vdb0}]),
- A = get_kanno(Ke),
- Vdb1 = use_vars(union(A#k.us, A#k.ns), I, Vdb0),
- E = expr(Ke, I, Vdb1),
- {[E],I,Vdb1}.
-
-%% expr(Kexpr, I, Vdb) -> Expr.
-
-expr(#k_test{anno=A}=Test, I, _Vdb) ->
- Test#k_test{anno=#l{i=I,a=A#k.a}};
-expr(#k_call{anno=A}=Call, I, _Vdb) ->
- Call#k_call{anno=#l{i=I,a=A#k.a}};
-expr(#k_enter{anno=A}=Enter, I, _Vdb) ->
- Enter#k_enter{anno=#l{i=I,a=A#k.a}};
-expr(#k_bif{anno=A}=Bif, I, _Vdb) ->
- Bif#k_bif{anno=#l{i=I,a=A#k.a}};
-expr(#k_match{anno=A,body=Kb,ret=Rs}, I, Vdb) ->
- %% Work out imported variables which need to be locked.
- Mdb = vdb_sub(I, I+1, Vdb),
- M = match(Kb, A#k.us, I+1, Mdb),
- L = #l{i=I,vdb=use_vars(A#k.us, I+1, Mdb),a=A#k.a},
- #k_match{anno=L,body=M,ret=Rs};
-expr(#k_guard_match{anno=A,body=Kb,ret=Rs}, I, Vdb) ->
- %% Work out imported variables which need to be locked.
- Mdb = vdb_sub(I, I+1, Vdb),
- M = match(Kb, A#k.us, I+1, Mdb),
- L = #l{i=I,vdb=use_vars(A#k.us, I+1, Mdb),a=A#k.a},
- #k_guard_match{anno=L,body=M,ret=Rs};
-expr(#k_protected{}=Protected, I, Vdb) ->
- protected(Protected, I, Vdb);
-expr(#k_try{anno=A,arg=Ka,vars=Vs,body=Kb,evars=Evs,handler=Kh}=Try, I, Vdb) ->
- %% Lock variables that are alive before the catch and used afterwards.
- %% Don't lock variables that are only used inside the try.
- Tdb0 = vdb_sub(I, I+1, Vdb),
- %% This is the tricky bit. Lock variables in Arg that are used in
- %% the body and handler. Add try tag 'variable'.
- Ab = get_kanno(Kb),
- Ah = get_kanno(Kh),
- Tdb1 = use_vars(union(Ab#k.us, Ah#k.us), I+3, Tdb0),
- Tdb2 = vdb_sub(I, I+2, Tdb1),
- Vnames = fun (Kvar) -> Kvar#k_var.name end, %Get the variable names
- {Aes,_,Adb} = body(Ka, I+2, add_var({catch_tag,I+1}, I+1, locked, Tdb2)),
- {Bes,_,Bdb} = body(Kb, I+4, new_vars(sort(map(Vnames, Vs)), I+3, Tdb2)),
- {Hes,_,Hdb} = body(Kh, I+4, new_vars(sort(map(Vnames, Evs)), I+3, Tdb2)),
- L = #l{i=I,vdb=Tdb1,a=A#k.a},
- Try#k_try{anno=L,
- arg=#cg_block{es=Aes,anno=#l{i=I+1,vdb=Adb,a=[]}},
- vars=Vs,body=#cg_block{es=Bes,anno=#l{i=I+3,vdb=Bdb,a=[]}},
- evars=Evs,handler=#cg_block{es=Hes,anno=#l{i=I+3,vdb=Hdb,a=[]}}};
-expr(#k_try_enter{anno=A,arg=Ka,vars=Vs,body=Kb,evars=Evs,handler=Kh}, I, Vdb) ->
- %% Lock variables that are alive before the catch and used afterwards.
- %% Don't lock variables that are only used inside the try.
- Tdb0 = vdb_sub(I, I+1, Vdb),
- %% This is the tricky bit. Lock variables in Arg that are used in
- %% the body and handler. Add try tag 'variable'.
- Ab = get_kanno(Kb),
- Ah = get_kanno(Kh),
- Tdb1 = use_vars(union(Ab#k.us, Ah#k.us), I+3, Tdb0),
- Tdb2 = vdb_sub(I, I+2, Tdb1),
- Vnames = fun (Kvar) -> Kvar#k_var.name end, %Get the variable names
- {Aes,_,Adb} = body(Ka, I+2, add_var({catch_tag,I+1}, I+1, 1000000, Tdb2)),
- {Bes,_,Bdb} = body(Kb, I+4, new_vars(sort(map(Vnames, Vs)), I+3, Tdb2)),
- {Hes,_,Hdb} = body(Kh, I+4, new_vars(sort(map(Vnames, Evs)), I+3, Tdb2)),
- L = #l{i=I,vdb=Tdb1,a=A#k.a},
- #k_try_enter{anno=L,
- arg=#cg_block{es=Aes,anno=#l{i=I+1,vdb=Adb,a=[]}},
- vars=Vs,body=#cg_block{es=Bes,anno=#l{i=I+3,vdb=Bdb,a=[]}},
- evars=Evs,handler=#cg_block{es=Hes,anno=#l{i=I+3,vdb=Hdb,a=[]}}};
-expr(#k_catch{anno=A,body=Kb}=Catch, I, Vdb) ->
- %% Lock variables that are alive before the catch and used afterwards.
- %% Don't lock variables that are only used inside the catch.
- %% Add catch tag 'variable'.
- Cdb0 = vdb_sub(I, I+1, Vdb),
- {Es,_,Cdb1} = body(Kb, I+1, add_var({catch_tag,I}, I, locked, Cdb0)),
- L = #l{i=I,vdb=Cdb1,a=A#k.a},
- Catch#k_catch{anno=L,body=#cg_block{es=Es}};
-expr(#k_receive{anno=A,var=V,body=Kb,action=Ka}=Recv, I, Vdb) ->
- %% Work out imported variables which need to be locked.
- Rdb = vdb_sub(I, I+1, Vdb),
- M = match(Kb, add_element(V#k_var.name, A#k.us), I+1,
- new_vars([V#k_var.name], I, Rdb)),
- {Tes,_,Adb} = body(Ka, I+1, Rdb),
- Le = #l{i=I,vdb=use_vars(A#k.us, I+1, Vdb),a=A#k.a},
- Recv#k_receive{anno=Le,body=M,
- action=#cg_block{anno=#l{i=I+1,vdb=Adb,a=[]},es=Tes}};
-expr(#k_receive_accept{anno=A}, I, _Vdb) ->
- #k_receive_accept{anno=#l{i=I,a=A#k.a}};
-expr(#k_receive_next{anno=A}, I, _Vdb) ->
- #k_receive_next{anno=#l{i=I,a=A#k.a}};
-expr(#k_put{anno=A}=Put, I, _Vdb) ->
- Put#k_put{anno=#l{i=I,a=A#k.a}};
-expr(#k_break{anno=A}=Break, I, _Vdb) ->
- Break#k_break{anno=#l{i=I,a=A#k.a}};
-expr(#k_guard_break{anno=A}=Break, I, _Vdb) ->
- Break#k_guard_break{anno=#l{i=I,a=A#k.a}};
-expr(#k_return{anno=A}=Ret, I, _Vdb) ->
- Ret#k_return{anno=#l{i=I,a=A#k.a}}.
-
-%% protected(Kprotected, I, Vdb) -> Protected.
-%% Only used in guards.
-
-protected(#k_protected{anno=A,arg=Ts}=Prot, I, Vdb) ->
- %% Lock variables that are alive before try and used afterwards.
- %% Don't lock variables that are only used inside the protected
- %% expression.
- Pdb0 = vdb_sub(I, I+1, Vdb),
- {T,MaxI,Pdb1} = body(Ts, I+1, Pdb0),
- Pdb2 = use_vars(A#k.ns, MaxI+1, Pdb1), %Save "return" values
- Prot#k_protected{arg=T,anno=#l{i=I,a=A#k.a,vdb=Pdb2}}.
-
-%% match(Kexpr, [LockVar], I, Vdb) -> Expr.
-%% Convert match tree to old format.
-
-match(#k_alt{anno=A,first=Kf,then=Kt}, Ls, I, Vdb0) ->
- Vdb1 = use_vars(union(A#k.us, Ls), I, Vdb0),
- F = match(Kf, Ls, I+1, Vdb1),
- T = match(Kt, Ls, I+1, Vdb1),
- #k_alt{anno=[],first=F,then=T};
-match(#k_select{anno=A,types=Kts}=Select, Ls, I, Vdb0) ->
- Vdb1 = use_vars(union(A#k.us, Ls), I, Vdb0),
- Ts = [type_clause(Tc, Ls, I+1, Vdb1) || Tc <- Kts],
- Select#k_select{anno=[],types=Ts};
-match(#k_guard{anno=A,clauses=Kcs}, Ls, I, Vdb0) ->
- Vdb1 = use_vars(union(A#k.us, Ls), I, Vdb0),
- Cs = [guard_clause(G, Ls, I+1, Vdb1) || G <- Kcs],
- #k_guard{anno=[],clauses=Cs};
-match(Other, Ls, I, Vdb0) ->
- Vdb1 = use_vars(Ls, I, Vdb0),
- {B,_,Vdb2} = body(Other, I+1, Vdb1),
- Le = #l{i=I,vdb=Vdb2,a=[]},
- #cg_block{anno=Le,es=B}.
-
-type_clause(#k_type_clause{anno=A,type=T,values=Kvs}, Ls, I, Vdb0) ->
- %%ok = io:format("life ~w: ~p~n", [?LINE,{T,Kvs}]),
- Vdb1 = use_vars(union(A#k.us, Ls), I+1, Vdb0),
- Vs = [val_clause(Vc, Ls, I+1, Vdb1) || Vc <- Kvs],
- #k_type_clause{anno=[],type=T,values=Vs}.
-
-val_clause(#k_val_clause{anno=A,val=V,body=Kb}, Ls0, I, Vdb0) ->
- New = (get_kanno(V))#k.ns,
- Bus = (get_kanno(Kb))#k.us,
- %%ok = io:format("Ls0 = ~p, Used=~p\n New=~p, Bus=~p\n", [Ls0,Used,New,Bus]),
- Ls1 = union(intersection(New, Bus), Ls0), %Lock for safety
- Vdb1 = use_vars(union(A#k.us, Ls1), I+1, new_vars(New, I, Vdb0)),
- B = match(Kb, Ls1, I+1, Vdb1),
- Le = #l{i=I,vdb=use_vars(Bus, I+1, Vdb1),a=A#k.a},
- #k_val_clause{anno=Le,val=V,body=B}.
-
-guard_clause(#k_guard_clause{anno=A,guard=Kg,body=Kb}, Ls, I, Vdb0) ->
- Vdb1 = use_vars(union(A#k.us, Ls), I+2, Vdb0),
- Gdb = vdb_sub(I+1, I+2, Vdb1),
- G = protected(Kg, I+1, Gdb),
- B = match(Kb, Ls, I+2, Vdb1),
- Le = #l{i=I,vdb=use_vars((get_kanno(Kg))#k.us, I+2, Vdb1),a=A#k.a},
- #k_guard_clause{anno=Le,guard=G,body=B}.
-
-
-%% Here follows the code generator pass.
-%%
-%% The following assumptions have been made:
-%%
-%% 1. Matches, i.e. things with {match,M,Ret} wrappers, only return
-%% values; no variables are exported. If the match would have returned
-%% extra variables then these have been transformed to multiple return
-%% values.
-%%
-%% 2. All BIF's called in guards are gc-safe so there is no need to
-%% put thing on the stack in the guard. While this would in principle
-%% work it would be difficult to keep track of the stack depth when
-%% trimming.
-%%
-%% The code generation uses variable lifetime information added by
-%% the previous pass to save variables, allocate registers and
-%% move registers to the stack when necessary.
-%%
-%% We try to use a consistent variable name scheme throughout. The
-%% StackReg record is always called Bef,Int<n>,Aft.
-
-%% cg_fun([Lkexpr], [HeadVar], Vdb, State) -> {[Ainstr],State}
-
-cg_fun(Les, Hvs, Vdb, AtomMod, NameArity, Anno, St0) ->
- {Fi,St1} = new_label(St0), %FuncInfo label
- {Fl,St2} = local_func_label(NameArity, St1),
-
- %%
- %% The pattern matching compiler (in v3_kernel) no longer
- %% provides its own catch-all clause, because the
- %% call to erlang:exit/1 caused problem when cases were
- %% used in guards. Therefore, there may be tests that
- %% cannot fail (providing that there is not a bug in a
- %% previous optimzation pass), but still need to provide
- %% a label (there are instructions, such as is_tuple/2,
- %% that do not allow {f,0}).
- %%
- %% We will generate an ultimate failure label and put it
- %% at the end of function, followed by an 'if_end' instruction.
- %% Note that and 'if_end' instruction does not need any
- %% live x registers, so it will always be safe to jump to
- %% it. (We never ever expect the jump to be taken, and in
- %% most functions there will never be any references to
- %% the label in the first place.)
- %%
-
- {UltimateMatchFail,St3} = new_label(St2),
-
- %% Create initial stack/register state, clear unused arguments.
- Bef = clear_dead(#sr{reg=foldl(fun (#k_var{name=V}, Reg) ->
- put_reg(V, Reg)
- end, [], Hvs),
- stk=[]}, 0, Vdb),
- {B,_Aft,St} = cg_list(Les, Vdb, Bef,
- St3#cg{bfail=0,
- ultimate_failure=UltimateMatchFail,
- is_top_block=true}),
- {Name,Arity} = NameArity,
- Asm = [{label,Fi},line(Anno),{func_info,AtomMod,{atom,Name},Arity},
- {label,Fl}|B++[{label,UltimateMatchFail},if_end]],
- {Asm,Fl,St}.
-
-%% cg(Lkexpr, Vdb, StackReg, State) -> {[Ainstr],StackReg,State}.
-%% Generate code for a kexpr.
-
-cg(#cg_block{anno=Le,es=Es}, Vdb, Bef, St) ->
- block_cg(Es, Le, Vdb, Bef, St);
-cg(#k_match{anno=Le,body=M,ret=Rs}, Vdb, Bef, St) ->
- match_cg(M, Rs, Le, Vdb, Bef, St);
-cg(#k_guard_match{anno=Le,body=M,ret=Rs}, Vdb, Bef, St) ->
- guard_match_cg(M, Rs, Le, Vdb, Bef, St);
-cg(#k_call{anno=Le,op=Func,args=As,ret=Rs}, Vdb, Bef, St) ->
- call_cg(Func, As, Rs, Le, Vdb, Bef, St);
-cg(#k_enter{anno=Le,op=Func,args=As}, Vdb, Bef, St) ->
- enter_cg(Func, As, Le, Vdb, Bef, St);
-cg(#k_bif{anno=Le}=Bif, Vdb, Bef, St) ->
- bif_cg(Bif, Le, Vdb, Bef, St);
-cg(#k_receive{anno=Le,timeout=Te,var=Rvar,body=Rm,action=Tes,ret=Rs},
- Vdb, Bef, St) ->
- recv_loop_cg(Te, Rvar, Rm, Tes, Rs, Le, Vdb, Bef, St);
-cg(#k_receive_next{anno=Le}, Vdb, Bef, St) ->
- recv_next_cg(Le, Vdb, Bef, St);
-cg(#k_receive_accept{}, _Vdb, Bef, St) ->
- {[remove_message],Bef,St};
-cg(#k_try{anno=Le,arg=Ta,vars=Vs,body=Tb,evars=Evs,handler=Th,ret=Rs},
- Vdb, Bef, St) ->
- try_cg(Ta, Vs, Tb, Evs, Th, Rs, Le, Vdb, Bef, St);
-cg(#k_try_enter{anno=Le,arg=Ta,vars=Vs,body=Tb,evars=Evs,handler=Th},
- Vdb, Bef, St) ->
- try_enter_cg(Ta, Vs, Tb, Evs, Th, Le, Vdb, Bef, St);
-cg(#k_catch{anno=Le,body=Cb,ret=[R]}, Vdb, Bef, St) ->
- catch_cg(Cb, R, Le, Vdb, Bef, St);
-cg(#k_put{anno=Le,arg=Con,ret=Var}, Vdb, Bef, St) ->
- put_cg(Var, Con, Le, Vdb, Bef, St);
-cg(#k_return{anno=Le,args=Rs}, Vdb, Bef, St) ->
- return_cg(Rs, Le, Vdb, Bef, St);
-cg(#k_break{anno=Le,args=Bs}, Vdb, Bef, St) ->
- break_cg(Bs, Le, Vdb, Bef, St);
-cg(#k_guard_break{anno=Le,args=Bs}, Vdb, Bef, St) ->
- guard_break_cg(Bs, Le, Vdb, Bef, St);
-cg(#cg_need_heap{h=H}, _Vdb, Bef, St) ->
- {[{test_heap,H,max_reg(Bef#sr.reg)}],Bef,St}.
-
-%% cg_list([Kexpr], FirstI, Vdb, StackReg, St) -> {[Ainstr],StackReg,St}.
-
-cg_list(Kes, Vdb, Bef, St0) ->
- {Keis,{Aft,St1}} =
- flatmapfoldl(fun (Ke, {Inta,Sta}) ->
- {Keis,Intb,Stb} = cg(Ke, Vdb, Inta, Sta),
- {Keis,{Intb,Stb}}
- end, {Bef,St0}, need_heap(Kes)),
- {Keis,Aft,St1}.
-
-%% need_heap([Lkexpr], I, St) -> [Lkexpr].
-%% Insert need_heap instructions in Kexpr list. Try to be smart and
-%% collect them together as much as possible.
-
-need_heap(Kes0) ->
- {Kes,H} = need_heap_0(reverse(Kes0), 0, []),
-
- %% Prepend need_heap if necessary.
- need_heap_need(H) ++ Kes.
-
-need_heap_0([Ke|Kes], H0, Acc) ->
- {Ns,H} = need_heap_1(Ke, H0),
- need_heap_0(Kes, H, [Ke|Ns]++Acc);
-need_heap_0([], H, Acc) ->
- {Acc,H}.
-
-need_heap_1(#k_put{arg=#k_binary{}}, H) ->
- {need_heap_need(H),0};
-need_heap_1(#k_put{arg=#k_map{}}, H) ->
- {need_heap_need(H),0};
-need_heap_1(#k_put{arg=Val}, H) ->
- %% Just pass through adding to needed heap.
- {[],H + case Val of
- #k_cons{} -> 2;
- #k_tuple{es=Es} -> 1 + length(Es);
- _Other -> 0
- end};
-need_heap_1(#k_bif{}=Bif, H) ->
- case is_gc_bif(Bif) of
- false ->
- {[],H};
- true ->
- {need_heap_need(H),0}
- end;
-need_heap_1(_Ke, H) ->
- %% Call or call-like instruction such as set_tuple_element/3.
- {need_heap_need(H),0}.
-
-need_heap_need(0) -> [];
-need_heap_need(H) -> [#cg_need_heap{h=H}].
-
-%% is_gc_bif(#k_bif{}) -> true|false.
-%% is_gc_bif(Name, Arity) -> true|false.
-%% Determines whether the BIF Name/Arity might do a GC.
-
-is_gc_bif(#k_bif{op=#k_remote{name=#k_atom{val=Name}},args=Args}) ->
- is_gc_bif(Name, length(Args));
-is_gc_bif(#k_bif{op=#k_internal{}}) ->
- true.
-
-is_gc_bif(hd, 1) -> false;
-is_gc_bif(tl, 1) -> false;
-is_gc_bif(self, 0) -> false;
-is_gc_bif(node, 0) -> false;
-is_gc_bif(node, 1) -> false;
-is_gc_bif(element, 2) -> false;
-is_gc_bif(get, 1) -> false;
-is_gc_bif(tuple_size, 1) -> false;
-is_gc_bif(map_get, 2) -> false;
-is_gc_bif(is_map_key, 2) -> false;
-is_gc_bif(Bif, Arity) ->
- not (erl_internal:bool_op(Bif, Arity) orelse
- erl_internal:new_type_test(Bif, Arity) orelse
- erl_internal:comp_op(Bif, Arity)).
-
-%% match_cg(Matc, [Ret], Le, Vdb, StackReg, State) ->
-%% {[Ainstr],StackReg,State}.
-%% Generate code for a match. First save all variables on the stack
-%% that are to survive after the match. We leave saved variables in
-%% their registers as they might actually be in the right place.
-
-match_cg(M, Rs, Le, Vdb, Bef, St0) ->
- I = Le#l.i,
- {Sis,Int0} = adjust_stack(Bef, I, I+1, Vdb),
- {B,St1} = new_label(St0),
- {Mis,Int1,St2} = match_cg(M, St1#cg.ultimate_failure,
- Int0, St1#cg{break=B}),
- %% Put return values in registers.
- Reg = load_vars(Rs, Int1#sr.reg),
- {Sis ++ Mis ++ [{label,B}],
- clear_dead(Int1#sr{reg=Reg}, I, Vdb),
- St2#cg{break=St1#cg.break}}.
-
-guard_match_cg(M, Rs, Le, Vdb, Bef, St0) ->
- I = Le#l.i,
- {B,St1} = new_label(St0),
- Fail = case St0 of
- #cg{bfail=0,ultimate_failure=Fail0} -> Fail0;
- #cg{bfail=Fail0} -> Fail0
- end,
- {Mis,Aft,St2} = match_cg(M, Fail, Bef, St1#cg{break=B}),
- %% Update the register descriptors for the return registers.
- Reg = guard_match_regs(Aft#sr.reg, Rs),
- {Mis ++ [{label,B}],
- clear_dead(Aft#sr{reg=Reg}, I, Vdb),
- St2#cg{break=St1#cg.break}}.
-
-guard_match_regs([{I,gbreakvar}|Rs], [#k_var{name=V}|Vs]) ->
- [{I,V}|guard_match_regs(Rs, Vs)];
-guard_match_regs([R|Rs], Vs) ->
- [R|guard_match_regs(Rs, Vs)];
-guard_match_regs([], []) -> [].
-
-
-%% match_cg(Match, Fail, StackReg, State) -> {[Ainstr],StackReg,State}.
-%% Generate code for a match tree. N.B. there is no need pass Vdb
-%% down as each level which uses this takes its own internal Vdb not
-%% the outer one.
-
-match_cg(#k_alt{first=F,then=S}, Fail, Bef, St0) ->
- {Tf,St1} = new_label(St0),
- {Fis,Faft,St2} = match_cg(F, Tf, Bef, St1),
- {Sis,Saft,St3} = match_cg(S, Fail, Bef, St2),
- Aft = sr_merge(Faft, Saft),
- {Fis ++ [{label,Tf}] ++ Sis,Aft,St3};
-match_cg(#k_select{var=#k_var{anno=Vanno,name=Vname}=V,types=Scs0}, Fail, Bef, St) ->
- ReuseForContext = member(reuse_for_context, Vanno) andalso
- find_reg(Vname, Bef#sr.reg) =/= error,
- Scs = case ReuseForContext of
- false -> Scs0;
- true -> bsm_rename_ctx(Scs0, Vname)
- end,
- match_fmf(fun (S, F, Sta) ->
- select_cg(S, V, F, Fail, Bef, Sta) end,
- Fail, St, Scs);
-match_cg(#k_guard{clauses=Gcs}, Fail, Bef, St) ->
- match_fmf(fun (G, F, Sta) -> guard_clause_cg(G, F, Bef, Sta) end,
- Fail, St, Gcs);
-match_cg(#cg_block{anno=Le,es=Es}, _Fail, Bef, St) ->
- %% Must clear registers and stack of dead variables.
- Int = clear_dead(Bef, Le#l.i, Le#l.vdb),
- block_cg(Es, Le, Int, St).
-
-%% bsm_rename_ctx([Clause], Var) -> [Clause]
-%% We know from an annotation that the register for a binary can
-%% be reused for the match context because the two are not truly
-%% alive at the same time (even though the life time information
-%% says so).
-%%
-%% The easiest way to have those variables share the same register is
-%% to rename the variable with the shortest life-span (the match
-%% context) to the variable for the binary (which can have a very
-%% long life-time because it is locked during matching). We KNOW that
-%% the match state variable will only be alive during the matching.
-%%
-%% We must also remove all information about the match context
-%% variable from all life-time information databases (Vdb).
-
-bsm_rename_ctx([#k_type_clause{type=k_binary,values=Vcs}=TC|Cs], New) ->
- [#k_val_clause{val=#k_binary{segs=#k_var{name=Old}}=Bin,
- body=Ke0}=VC0] = Vcs,
- Ke = bsm_rename_ctx(Ke0, Old, New, false),
- VC = VC0#k_val_clause{val=Bin#k_binary{segs=#k_var{name=New}},
- body=Ke},
- [TC#k_type_clause{values=[VC]}|bsm_rename_ctx(Cs, New)];
-bsm_rename_ctx([C|Cs], New) ->
- [C|bsm_rename_ctx(Cs, New)];
-bsm_rename_ctx([], _) -> [].
-
-%% bsm_rename_ctx(Ke, OldName, NewName, InProt) -> Ke'
-%% Rename and clear OldName from life-time information. We must
-%% recurse into any block contained in a protected, but it would
-%% only complicatate things to recurse into blocks not in a protected
-%% (the match context variable is not live inside them).
-
-bsm_rename_ctx(#k_select{var=#k_var{name=V},types=Cs0}=Sel,
- Old, New, InProt) ->
- Cs = bsm_rename_ctx_list(Cs0, Old, New, InProt),
- Sel#k_select{var=#k_var{name=bsm_rename_var(V, Old, New)},types=Cs};
-bsm_rename_ctx(#k_type_clause{values=Cs0}=TC, Old, New, InProt) ->
- Cs = bsm_rename_ctx_list(Cs0, Old, New, InProt),
- TC#k_type_clause{values=Cs};
-bsm_rename_ctx(#k_val_clause{body=Ke0}=VC, Old, New, InProt) ->
- Ke = bsm_rename_ctx(Ke0, Old, New, InProt),
- VC#k_val_clause{body=Ke};
-bsm_rename_ctx(#k_alt{first=F0,then=S0}=Alt, Old, New, InProt) ->
- F = bsm_rename_ctx(F0, Old, New, InProt),
- S = bsm_rename_ctx(S0, Old, New, InProt),
- Alt#k_alt{first=F,then=S};
-bsm_rename_ctx(#k_guard{clauses=Gcs0}=Guard, Old, New, InProt) ->
- Gcs = bsm_rename_ctx_list(Gcs0, Old, New, InProt),
- Guard#k_guard{clauses=Gcs};
-bsm_rename_ctx(#k_guard_clause{guard=G0,body=B0}=GC, Old, New, InProt) ->
- G = bsm_rename_ctx(G0, Old, New, InProt),
- B = bsm_rename_ctx(B0, Old, New, InProt),
- %% A guard clause may cause unsaved variables to be saved on the stack.
- %% Since the match state variable Old is an alias for New (uses the
- %% same register), it is neither in the stack nor register descriptor
- %% lists and we would crash when we didn't find it unless we remove
- %% it from the database.
- bsm_forget_var(GC#k_guard_clause{guard=G,body=B}, Old);
-bsm_rename_ctx(#k_protected{arg=Ts0}=Prot, Old, New, _InProt) ->
- InProt = true,
- Ts = bsm_rename_ctx_list(Ts0, Old, New, InProt),
- bsm_forget_var(Prot#k_protected{arg=Ts}, Old);
-bsm_rename_ctx(#k_guard_match{body=Ms0}=Match, Old, New, InProt) ->
- Ms = bsm_rename_ctx(Ms0, Old, New, InProt),
- Match#k_guard_match{body=Ms};
-bsm_rename_ctx(#k_test{}=Test, _, _, _) -> Test;
-bsm_rename_ctx(#k_bif{}=Bif, _, _, _) -> Bif;
-bsm_rename_ctx(#k_put{}=Put, _, _, _) -> Put;
-bsm_rename_ctx(#k_call{}=Call, _, _, _) -> Call;
-bsm_rename_ctx(#cg_block{}=Block, Old, _, false) ->
- %% This block is not inside a protected. The match context variable cannot
- %% possibly be live inside the block.
- bsm_forget_var(Block, Old);
-bsm_rename_ctx(#cg_block{es=Es0}=Block, Old, New, true) ->
- %% A block in a protected. We must recursively rename the variable
- %% inside the block.
- Es = bsm_rename_ctx_list(Es0, Old, New, true),
- bsm_forget_var(Block#cg_block{es=Es}, Old);
-bsm_rename_ctx(#k_guard_break{}=Break, Old, _New, _InProt) ->
- bsm_forget_var(Break, Old).
-
-bsm_rename_ctx_list([C|Cs], Old, New, InProt) ->
- [bsm_rename_ctx(C, Old, New, InProt)|
- bsm_rename_ctx_list(Cs, Old, New, InProt)];
-bsm_rename_ctx_list([], _, _, _) -> [].
-
-bsm_rename_var(Old, Old, New) -> New;
-bsm_rename_var(V, _, _) -> V.
-
-%% bsm_forget_var(#l{}, Variable) -> #l{}
-%% Remove a variable from the variable life-time database.
-
-bsm_forget_var(Ke, V) ->
- #l{vdb=Vdb} = L0 = get_kanno(Ke),
- L = L0#l{vdb=keydelete(V, 1, Vdb)},
- set_kanno(Ke, L).
-
-%% block_cg([Kexpr], Le, Vdb, StackReg, St) -> {[Ainstr],StackReg,St}.
-%% block_cg([Kexpr], Le, StackReg, St) -> {[Ainstr],StackReg,St}.
-
-block_cg(Es, Le, _Vdb, Bef, St) ->
- block_cg(Es, Le, Bef, St).
-
-block_cg(Es, Le, Bef, #cg{is_top_block=false}=St) ->
- cg_block(Es, Le#l.vdb, Bef, St);
-block_cg(Es, Le, Bef, #cg{is_top_block=true}=St0) ->
- %% No stack frame has been established yet. Do we need one?
- case need_stackframe(Es) of
- true ->
- %% We need a stack frame. Generate the code and add the
- %% code for creating and deallocating the stack frame.
- {Is0,Aft,St} = cg_block(Es, Le#l.vdb, Bef,
- St0#cg{is_top_block=false,need_frame=false}),
- Is = top_level_block(Is0, Aft, max_reg(Bef#sr.reg), St),
- {Is,Aft,St#cg{is_top_block=true}};
- false ->
- %% This sequence of instructions ending in a #k_match{} (a
- %% 'case' or 'if') in the Erlang code does not need a
- %% stack frame yet. Delay the creation (if a stack frame
- %% is needed at all, it will be created inside the
- %% #k_match{}).
- cg_list(Es, Le#l.vdb, Bef, St0)
- end.
-
-%% need_stackframe([Kexpr]) -> true|false.
-%% Does this list of instructions need a stack frame?
-%%
-%% A sequence of instructions that don't clobber the X registers
-%% followed by a single #k_match{} doesn't need a stack frame.
-
-need_stackframe([H|T]) ->
- case H of
- #k_bif{op=#k_internal{}} -> true;
- #k_put{arg=#k_binary{}} -> true;
- #k_bif{} -> need_stackframe(T);
- #k_put{} -> need_stackframe(T);
- #k_guard_match{} -> need_stackframe(T);
- #k_match{} when T =:= [] -> false;
- _ -> true
- end;
-need_stackframe([]) -> false.
-
-cg_block([], _Vdb, Bef, St0) ->
- {[],Bef,St0};
-cg_block(Kes0, Vdb, Bef, St0) ->
- {Kes2,Int1,St1} =
- case basic_block(Kes0) of
- {Kes1,LastI,Args,Rest} ->
- cg_basic_block(Kes1, LastI, Args, Vdb, Bef, St0);
- {Kes1,Rest} ->
- cg_list(Kes1, Vdb, Bef, St0)
- end,
- {Kes3,Int2,St2} = cg_block(Rest, Vdb, Int1, St1),
- {Kes2 ++ Kes3,Int2,St2}.
-
-basic_block(Kes) -> basic_block(Kes, []).
-
-basic_block([Ke|Kes], Acc) ->
- case collect_block(Ke) of
- include -> basic_block(Kes, [Ke|Acc]);
- {block_end,As} ->
- case Acc of
- [] ->
- %% If the basic block does not contain any #k_put{} instructions,
- %% it serves no useful purpose to do basic block optimizations.
- {[Ke],Kes};
- _ ->
- #l{i=I} = get_kanno(Ke),
- {reverse(Acc, [Ke]),I,As,Kes}
- end;
- no_block -> {reverse(Acc, [Ke]),Kes}
- end.
-
-collect_block(#k_put{arg=Arg}) ->
- %% #k_put{} instructions that may garbage collect are not allowed
- %% in basic blocks.
- case Arg of
- #k_binary{} -> no_block;
- #k_map{} -> no_block;
- _ -> include
- end;
-collect_block(#k_call{op=Func,args=As}) ->
- {block_end,As++func_vars(Func)};
-collect_block(#k_enter{op=Func,args=As}) ->
- {block_end,As++func_vars(Func)};
-collect_block(#k_return{args=Rs}) ->
- {block_end,Rs};
-collect_block(#k_break{args=Bs}) ->
- {block_end,Bs};
-collect_block(_) -> no_block.
-
-func_vars(#k_var{}=Var) ->
- [Var];
-func_vars(#k_remote{mod=M,name=F})
- when is_record(M, k_var); is_record(F, k_var) ->
- [M,F];
-func_vars(_) -> [].
-
-%% cg_basic_block([Kexpr], FirstI, LastI, Arguments, Vdb, StackReg, State) ->
-%% {[Ainstr],StackReg,State}.
-%%
-%% Do a specialized code generation for a basic block of #put{}
-%% instructions (that don't do any garbage collection) followed by a
-%% call, break, or return.
-%%
-%% 'Arguments' is a list of the variables that must be loaded into
-%% consecutive X registers before the last instruction in the block.
-%% The point of this specialized code generation is to try put the
-%% all of the variables in 'Arguments' into the correct X register
-%% to begin with, instead of putting them into the first available
-%% X register and having to move them to the correct X register
-%% later.
-%%
-%% To achieve that, we attempt to reserve the X registers that the
-%% variables in 'Arguments' will need to be in when the block ends.
-%%
-%% To make it more likely that reservations will be successful, we
-%% will try to save variables that need to be saved to the stack as
-%% early as possible (if an X register needed by a variable in
-%% Arguments is occupied by another variable, the value in the
-%% X register can be evicted if it is saved on the stack).
-%%
-%% We will take care not to increase the size of stack frame compared
-%% to what the standard code generator would have done (that is, to
-%% save all X registers at the last possible moment). We will do that
-%% by extending the stack frame to the minimal size needed to save
-%% all that needs to be saved using extend_stack/4, and use
-%% save_carefully/4 during code generation to only save the variables
-%% that can be saved without growing the stack frame.
-
-cg_basic_block(Kes, Lf, As, Vdb, Bef, St0) ->
- Int0 = reserve_arg_regs(As, Bef),
- Int = extend_stack(Int0, Lf, Lf+1, Vdb),
- {Keis,{Aft,St1}} =
- flatmapfoldl(fun(Ke, St) -> cg_basic_block(Ke, St, Lf, Vdb) end,
- {Int,St0}, need_heap(Kes)),
- {Keis,Aft,St1}.
-
-cg_basic_block(#cg_need_heap{}=Ke, {Bef,St0}, _Lf, Vdb) ->
- {Keis,Aft,St1} = cg(Ke, Vdb, Bef, St0),
- {Keis,{Aft,St1}};
-cg_basic_block(Ke, {Bef,St0}, Lf, Vdb) ->
- #l{i=I} = get_kanno(Ke),
-
- %% Save all we can to increase the possibility that reserving
- %% registers will succeed.
- {Sis,Int0} = save_carefully(Bef, I, Lf+1, Vdb),
- Int1 = reserve(Int0),
- {Keis,Aft,St1} = cg(Ke, Vdb, Int1, St0),
- {Sis ++ Keis,{Aft,St1}}.
-
-%% reserve_arg_regs([Argument], Bef) -> Aft.
-%% Try to reserve the X registers for all arguments. All registers
-%% that we wish to reserve will be saved in Bef#sr.res.
-
-reserve_arg_regs(As, Bef) ->
- Res = reserve_arg_regs_1(As, 0),
- reserve(Bef#sr{res=Res}).
-
-reserve_arg_regs_1([#k_var{name=V}|As], I) ->
- [{I,V}|reserve_arg_regs_1(As, I+1)];
-reserve_arg_regs_1([A|As], I) ->
- [{I,A}|reserve_arg_regs_1(As, I+1)];
-reserve_arg_regs_1([], _) -> [].
-
-%% reserve(Bef) -> Aft.
-%% Try to reserve more registers. The registers we wish to reserve
-%% are found in Bef#sr.res.
-
-reserve(#sr{reg=Regs,stk=Stk,res=Res}=Sr) ->
- Sr#sr{reg=reserve_1(Res, Regs, Stk)}.
-
-reserve_1([{I,V}|Rs], [free|Regs], Stk) ->
- [{reserved,I,V}|reserve_1(Rs, Regs, Stk)];
-reserve_1([{I,V}|Rs], [{I,V}|Regs], Stk) ->
- [{I,V}|reserve_1(Rs, Regs, Stk)];
-reserve_1([{I,V}|Rs], [{I,Var}|Regs], Stk) ->
- case on_stack(Var, Stk) of
- true -> [{reserved,I,V}|reserve_1(Rs, Regs, Stk)];
- false -> [{I,Var}|reserve_1(Rs, Regs, Stk)]
- end;
-reserve_1([{I,V}|Rs], [{reserved,I,_}|Regs], Stk) ->
- [{reserved,I,V}|reserve_1(Rs, Regs, Stk)];
-reserve_1([{I,V}|Rs], [], Stk) ->
- [{reserved,I,V}|reserve_1(Rs, [], Stk)];
-reserve_1([], Regs, _) -> Regs.
-
-%% extend_stack(Bef, FirstBefore, LastFrom, Vdb) -> Aft.
-%% Extend the stack enough to fit all variables alive past LastFrom
-%% and not already on the stack.
-
-extend_stack(#sr{stk=Stk0}=Bef, Fb, Lf, Vdb) ->
- Stk1 = clear_dead_stk(Stk0, Fb, Vdb),
- New = new_not_on_stack(Stk1, Fb, Lf, Vdb),
- Stk2 = foldl(fun ({V,_,_}, Stk) -> put_stack(V, Stk) end, Stk1, New),
- Stk = Stk0 ++ lists:duplicate(length(Stk2) - length(Stk0), free),
- Bef#sr{stk=Stk}.
-
-%% save_carefully(Bef, FirstBefore, LastFrom, Vdb) -> {[SaveVar],Aft}.
-%% Save variables which are used past current point and which are not
-%% already on the stack, but only if the variables can be saved without
-%% growing the stack frame.
-
-save_carefully(#sr{stk=Stk}=Bef, Fb, Lf, Vdb) ->
- New0 = new_not_on_stack(Stk, Fb, Lf, Vdb),
- New = keysort(2, New0),
- save_carefully_1(New, Bef, []).
-
-save_carefully_1([{V,_,_}|Vs], #sr{reg=Regs,stk=Stk0}=Bef, Acc) ->
- case put_stack_carefully(V, Stk0) of
- error ->
- {reverse(Acc),Bef};
- Stk1 ->
- SrcReg = fetch_reg(V, Regs),
- Move = {move,SrcReg,fetch_stack(V, Stk1)},
- {x,_} = SrcReg, %Assertion - must be X register.
- save_carefully_1(Vs, Bef#sr{stk=Stk1}, [Move|Acc])
- end;
-save_carefully_1([], Bef, Acc) ->
- {reverse(Acc),Bef}.
-
-%% top_level_block([Instruction], Bef, MaxRegs, St) -> [Instruction].
-%% For the top-level block, allocate a stack frame a necessary,
-%% adjust Y register numbering and instructions that return
-%% from the function.
-
-top_level_block(Keis, #sr{stk=[]}, _MaxRegs, #cg{need_frame=false}) ->
- Keis;
-top_level_block(Keis, Bef, MaxRegs, _St) ->
- %% This top block needs an allocate instruction before it, and a
- %% deallocate instruction before each return.
- FrameSz = length(Bef#sr.stk),
- MaxY = FrameSz-1,
- Keis1 = flatmap(fun ({call_only,Arity,Func}) ->
- [{call_last,Arity,Func,FrameSz}];
- ({call_ext_only,Arity,Func}) ->
- [{call_ext_last,Arity,Func,FrameSz}];
- ({apply_only,Arity}) ->
- [{apply_last,Arity,FrameSz}];
- (return) ->
- [{deallocate,FrameSz},return];
- (Tuple) when is_tuple(Tuple) ->
- [turn_yregs(Tuple, MaxY)];
- (Other) ->
- [Other]
- end, Keis),
- [{allocate_zero,FrameSz,MaxRegs}|Keis1].
-
-%% turn_yregs(Size, Tuple, MaxY) -> Tuple'
-%% Renumber y register so that {y,0} becomes {y,FrameSize-1},
-%% {y,FrameSize-1} becomes {y,0} and so on. This is to make nested
-%% catches work. The code generation algorithm gives a lower register
-%% number to the outer catch, which is wrong.
-
-turn_yregs({call,_,_}=I, _MaxY) -> I;
-turn_yregs({call_ext,_,_}=I, _MaxY) -> I;
-turn_yregs({jump,_}=I, _MaxY) -> I;
-turn_yregs({label,_}=I, _MaxY) -> I;
-turn_yregs({line,_}=I, _MaxY) -> I;
-turn_yregs({test_heap,_,_}=I, _MaxY) -> I;
-turn_yregs({bif,Op,F,A,B}, MaxY) ->
- {bif,Op,F,turn_yreg(A, MaxY),turn_yreg(B, MaxY)};
-turn_yregs({gc_bif,Op,F,Live,A,B}, MaxY) when is_integer(Live) ->
- {gc_bif,Op,F,Live,turn_yreg(A, MaxY),turn_yreg(B, MaxY)};
-turn_yregs({get_tuple_element,S,N,D}, MaxY) ->
- {get_tuple_element,turn_yreg(S, MaxY),N,turn_yreg(D, MaxY)};
-turn_yregs({put_tuple,Arity,D}, MaxY) ->
- {put_tuple,Arity,turn_yreg(D, MaxY)};
-turn_yregs({select_val,R,F,L}, MaxY) ->
- {select_val,turn_yreg(R, MaxY),F,L};
-turn_yregs({test,Op,F,L}, MaxY) ->
- {test,Op,F,turn_yreg(L, MaxY)};
-turn_yregs({test,Op,F,Live,A,B}, MaxY) when is_integer(Live) ->
- {test,Op,F,Live,turn_yreg(A, MaxY),turn_yreg(B, MaxY)};
-turn_yregs({Op,A}, MaxY) ->
- {Op,turn_yreg(A, MaxY)};
-turn_yregs({Op,A,B}, MaxY) ->
- {Op,turn_yreg(A, MaxY),turn_yreg(B, MaxY)};
-turn_yregs({Op,A,B,C}, MaxY) ->
- {Op,turn_yreg(A, MaxY),turn_yreg(B, MaxY),turn_yreg(C, MaxY)};
-turn_yregs(Tuple, MaxY) ->
- turn_yregs(tuple_size(Tuple), Tuple, MaxY).
-
-turn_yregs(1, Tp, _) ->
- Tp;
-turn_yregs(N, Tp, MaxY) ->
- E = turn_yreg(element(N, Tp), MaxY),
- turn_yregs(N-1, setelement(N, Tp, E), MaxY).
-
-turn_yreg({yy,YY}, MaxY) ->
- {y,MaxY-YY};
-turn_yreg({list,Ls},MaxY) ->
- {list,turn_yreg(Ls, MaxY)};
-turn_yreg([_|_]=Ts, MaxY) ->
- [turn_yreg(T, MaxY) || T <- Ts];
-turn_yreg(Other, _MaxY) ->
- Other.
-
-%% select_cg(Sclause, V, TypeFail, ValueFail, StackReg, State) ->
-%% {Is,StackReg,State}.
-%% Selecting type and value needs two failure labels, TypeFail is the
-%% label to jump to of the next type test when this type fails, and
-%% ValueFail is the label when this type is correct but the value is
-%% wrong. These are different as in the second case there is no need
-%% to try the next type, it will always fail.
-
-select_cg(#k_type_clause{type=Type,values=Vs}, Var, Tf, Vf, Bef, St) ->
- #k_var{name=V} = Var,
- select_cg(Type, Vs, V, Tf, Vf, Bef, St).
-
-select_cg(k_cons, [S], V, Tf, Vf, Bef, St) ->
- select_cons(S, V, Tf, Vf, Bef, St);
-select_cg(k_nil, [S], V, Tf, Vf, Bef, St) ->
- select_nil(S, V, Tf, Vf, Bef, St);
-select_cg(k_binary, [S], V, Tf, Vf, Bef, St) ->
- select_binary(S, V, Tf, Vf, Bef, St);
-select_cg(k_bin_seg, S, V, Tf, _Vf, Bef, St) ->
- select_bin_segs(S, V, Tf, Bef, St);
-select_cg(k_bin_int, S, V, Tf, _Vf, Bef, St) ->
- select_bin_segs(S, V, Tf, Bef, St);
-select_cg(k_bin_end, [S], V, Tf, _Vf, Bef, St) ->
- select_bin_end(S, V, Tf, Bef, St);
-select_cg(k_map, S, V, Tf, Vf, Bef, St) ->
- select_map(S, V, Tf, Vf, Bef, St);
-select_cg(k_literal, S, V, Tf, Vf, Bef, St) ->
- select_literal(S, V, Tf, Vf, Bef, St);
-select_cg(Type, Scs, V, Tf, Vf, Bef, St0) ->
- {Vis,{Aft,St1}} =
- mapfoldl(fun (S, {Int,Sta}) ->
- {Val,Is,Inta,Stb} = select_val(S, V, Vf, Bef, Sta),
- {{Is,[Val]},{sr_merge(Int, Inta),Stb}}
- end, {void,St0}, Scs),
- OptVls = combine(lists:sort(combine(Vis))),
- {Vls,Sis,St2} = select_labels(OptVls, St1, [], []),
- {select_val_cg(Type, fetch_var(V, Bef), Vls, Tf, Vf, Sis), Aft, St2}.
-
-select_val_cg(k_tuple, R, [Arity,{f,Lbl}], Tf, Vf, [{label,Lbl}|Sis]) ->
- [{test,is_tuple,{f,Tf},[R]},{test,test_arity,{f,Vf},[R,Arity]}|Sis];
-select_val_cg(k_tuple, R, Vls, Tf, Vf, Sis) ->
- [{test,is_tuple,{f,Tf},[R]},{select_tuple_arity,R,{f,Vf},{list,Vls}}|Sis];
-select_val_cg(Type, R, [Val, {f,Lbl}], Fail, Fail, [{label,Lbl}|Sis]) ->
- [{test,is_eq_exact,{f,Fail},[R,{type(Type),Val}]}|Sis];
-select_val_cg(Type, R, [Val, {f,Lbl}], Tf, Vf, [{label,Lbl}|Sis]) ->
- [{test,select_type_test(Type),{f,Tf},[R]},
- {test,is_eq_exact,{f,Vf},[R,{type(Type),Val}]}|Sis];
-select_val_cg(Type, R, Vls0, Tf, Vf, Sis) ->
- Vls1 = [case Value of
- {f,_Lbl} -> Value;
- _ -> {type(Type),Value}
- end || Value <- Vls0],
- [{test,select_type_test(Type),{f,Tf},[R]}, {select_val,R,{f,Vf},{list,Vls1}}|Sis].
-
-type(k_atom) -> atom;
-type(k_float) -> float;
-type(k_int) -> integer.
-
-select_type_test(k_int) -> is_integer;
-select_type_test(k_atom) -> is_atom;
-select_type_test(k_float) -> is_float.
-
-combine([{Is,Vs1}, {Is,Vs2}|Vis]) -> combine([{Is,Vs1 ++ Vs2}|Vis]);
-combine([V|Vis]) -> [V|combine(Vis)];
-combine([]) -> [].
-
-select_labels([{Is,Vs}|Vis], St0, Vls, Sis) ->
- {Lbl,St1} = new_label(St0),
- select_labels(Vis, St1, add_vls(Vs, Lbl, Vls), [[{label,Lbl}|Is]|Sis]);
-select_labels([], St, Vls, Sis) ->
- {Vls,append(Sis),St}.
-
-add_vls([V|Vs], Lbl, Acc) ->
- add_vls(Vs, Lbl, [V, {f,Lbl}|Acc]);
-add_vls([], _, Acc) -> Acc.
-
-select_literal(S, V, Tf, Vf, Bef, St) ->
- Reg = fetch_var(V, Bef),
- F = fun(ValClause, Fail, St0) ->
- {Val,Is,Aft,St1} = select_val(ValClause, V, Vf, Bef, St0),
- Test = {test,is_eq_exact,{f,Fail},[Reg,{literal,Val}]},
- {[Test|Is],Aft,St1}
- end,
- match_fmf(F, Tf, St, S).
-
-select_cons(#k_val_clause{val=#k_cons{hd=Hd,tl=Tl},body=B,anno=#l{i=I,vdb=Vdb}},
- V, Tf, Vf, Bef, St0) ->
- Es = [Hd,Tl],
- {Eis,Int,St1} = select_extract_cons(V, Es, I, Vdb, Bef, St0),
- {Bis,Aft,St2} = match_cg(B, Vf, Int, St1),
- {[{test,is_nonempty_list,{f,Tf},[fetch_var(V, Bef)]}] ++ Eis ++ Bis,Aft,St2}.
-
-select_nil(#k_val_clause{val=#k_nil{},body=B}, V, Tf, Vf, Bef, St0) ->
- {Bis,Aft,St1} = match_cg(B, Vf, Bef, St0),
- {[{test,is_nil,{f,Tf},[fetch_var(V, Bef)]}] ++ Bis,Aft,St1}.
-
-select_binary(#k_val_clause{val=#k_binary{segs=#k_var{name=V}},body=B,
- anno=#l{i=I,vdb=Vdb}}, V, Tf, Vf, Bef, St0) ->
- #cg{ctx=OldCtx} = St0,
- Int0 = clear_dead(Bef#sr{reg=Bef#sr.reg}, I, Vdb),
- {Bis0,Aft,St1} = match_cg(B, Vf, Int0, St0#cg{ctx=V}),
- CtxReg = fetch_var(V, Int0),
- Live = max_reg(Bef#sr.reg),
- Bis1 = [{test,bs_start_match2,{f,Tf},Live,[CtxReg,{context,V}],CtxReg},
- {bs_save2,CtxReg,{V,V}}|Bis0],
- Bis = finish_select_binary(Bis1),
- {Bis,Aft,St1#cg{ctx=OldCtx}};
-select_binary(#k_val_clause{val=#k_binary{segs=#k_var{name=Ivar}},body=B,
- anno=#l{i=I,vdb=Vdb}}, V, Tf, Vf, Bef, St0) ->
- #cg{ctx=OldCtx} = St0,
- Regs = put_reg(Ivar, Bef#sr.reg),
- Int0 = clear_dead(Bef#sr{reg=Regs}, I, Vdb),
- {Bis0,Aft,St1} = match_cg(B, Vf, Int0, St0#cg{ctx=Ivar}),
- CtxReg = fetch_var(Ivar, Int0),
- Live = max_reg(Bef#sr.reg),
- Bis1 = [{test,bs_start_match2,{f,Tf},Live,
- [fetch_var(V, Bef),{context,Ivar}],CtxReg},
- {bs_save2,CtxReg,{Ivar,Ivar}}|Bis0],
- Bis = finish_select_binary(Bis1),
- {Bis,Aft,St1#cg{ctx=OldCtx}}.
-
-finish_select_binary([{bs_save2,R,Point}=I,{bs_restore2,R,Point}|Is]) ->
- [I|finish_select_binary(Is)];
-finish_select_binary([{bs_save2,R,Point}=I,{test,is_eq_exact,_,_}=Test,
- {bs_restore2,R,Point}|Is]) ->
- [I,Test|finish_select_binary(Is)];
-finish_select_binary([{test,bs_match_string,F,[Ctx,BinList]}|Is])
- when is_list(BinList) ->
- I = {test,bs_match_string,F,[Ctx,list_to_bitstring(BinList)]},
- [I|finish_select_binary(Is)];
-finish_select_binary([I|Is]) ->
- [I|finish_select_binary(Is)];
-finish_select_binary([]) -> [].
-
-%% New instructions for selection of binary segments.
-
-select_bin_segs(Scs, Ivar, Tf, Bef, St) ->
- match_fmf(fun(S, Fail, Sta) ->
- select_bin_seg(S, Ivar, Fail, Bef, Sta) end,
- Tf, St, Scs).
-
-select_bin_seg(#k_val_clause{val=#k_bin_seg{size=Size,unit=U,type=T,
- seg=Seg,flags=Fs0,next=Next},
- body=B,
- anno=#l{i=I,vdb=Vdb,a=A}}, Ivar, Fail, Bef, St0) ->
- Ctx = St0#cg.ctx,
- Fs = [{anno,A}|Fs0],
- Es = case Next of
- [] -> [Seg];
- _ -> [Seg,Next]
- end,
- {Mis,Int,St1} = select_extract_bin(Es, Size, U, T, Fs, Fail,
- I, Vdb, Bef, Ctx, B, St0),
- {Bis,Aft,St2} = match_cg(B, Fail, Int, St1),
- CtxReg = fetch_var(Ctx, Bef),
- Is = if
- Mis =:= [] ->
- %% No bs_restore2 instruction needed if no match instructions.
- Bis;
- true ->
- [{bs_restore2,CtxReg,{Ctx,Ivar}}|Mis++Bis]
- end,
- {Is,Aft,St2};
-select_bin_seg(#k_val_clause{val=#k_bin_int{size=Sz,unit=U,flags=Fs,
- val=Val,next=Next},
- body=B,
- anno=#l{i=I,vdb=Vdb}}, Ivar, Fail, Bef, St0) ->
- Ctx = St0#cg.ctx,
- {Mis,Int,St1} = select_extract_int(Next, Val, Sz, U, Fs, Fail,
- I, Vdb, Bef, Ctx, St0),
- {Bis,Aft,St2} = match_cg(B, Fail, Int, St1),
- CtxReg = fetch_var(Ctx, Bef),
- Is = case Mis ++ Bis of
- [{test,bs_match_string,F,[OtherCtx,Bin1]},
- {bs_save2,OtherCtx,_},
- {bs_restore2,OtherCtx,_},
- {test,bs_match_string,F,[OtherCtx,Bin2]}|Is0] ->
- %% We used to do this optimization later, but it
- %% turns out that in huge functions with many
- %% bs_match_string instructions, it's a big win
- %% to do the combination now. To avoid copying the
- %% binary data again and again, we'll combine bitstrings
- %% in a list and convert all of it to a bitstring later.
- [{test,bs_match_string,F,[OtherCtx,[Bin1,Bin2]]}|Is0];
- Is0 ->
- Is0
- end,
- {[{bs_restore2,CtxReg,{Ctx,Ivar}}|Is],Aft,St2}.
-
-select_extract_int(#k_var{name=Tl}, Val, #k_int{val=Sz}, U, Fs, Vf,
- I, Vdb, Bef, Ctx, St) ->
- Bits = U*Sz,
- Bin = case member(big, Fs) of
- true ->
- <<Val:Bits>>;
- false ->
- true = member(little, Fs), %Assertion.
- <<Val:Bits/little>>
- end,
- Bits = bit_size(Bin), %Assertion.
- CtxReg = fetch_var(Ctx, Bef),
- Is = if
- Bits =:= 0 ->
- [{bs_save2,CtxReg,{Ctx,Tl}}];
- true ->
- [{test,bs_match_string,{f,Vf},[CtxReg,Bin]},
- {bs_save2,CtxReg,{Ctx,Tl}}]
- end,
- {Is,clear_dead(Bef, I, Vdb),St}.
-
-select_extract_bin([#k_var{name=Hd},#k_var{name=Tl}], Size0, Unit, Type, Flags, Vf,
- I, Vdb, Bef, Ctx, _Body, St) ->
- SizeReg = get_bin_size_reg(Size0, Bef),
- {Es,Aft} =
- case vdb_find(Hd, Vdb) of
- {_,_,Lhd} when Lhd =< I ->
- %% The extracted value will not be used.
- CtxReg = fetch_var(Ctx, Bef),
- Live = max_reg(Bef#sr.reg),
- Skip = build_skip_instr(Type, Vf, CtxReg, Live,
- SizeReg, Unit, Flags),
- {[Skip,{bs_save2,CtxReg,{Ctx,Tl}}],Bef};
- {_,_,_} ->
- Reg = put_reg(Hd, Bef#sr.reg),
- Int1 = Bef#sr{reg=Reg},
- Rhd = fetch_reg(Hd, Reg),
- CtxReg = fetch_reg(Ctx, Reg),
- Live = max_reg(Bef#sr.reg),
- {[build_bs_instr(Type, Vf, CtxReg, Live, SizeReg,
- Unit, Flags, Rhd),
- {bs_save2,CtxReg,{Ctx,Tl}}],Int1}
- end,
- {Es,clear_dead(Aft, I, Vdb),St};
-select_extract_bin([#k_var{name=Hd}], Size, Unit, binary, Flags, Vf,
- I, Vdb, Bef, Ctx, Body, St) ->
- %% Match the last segment of a binary. We KNOW that the size
- %% must be 'all'.
- #k_atom{val=all} = Size, %Assertion.
- {Es,Aft} =
- case vdb_find(Hd, Vdb) of
- {_,_,Lhd} when Lhd =< I ->
- %% The result will not be used. Furthermore, since we
- %% we are at the end of the binary, the position will
- %% not be used again; thus, it is safe to do a cheaper
- %% test of the unit.
- CtxReg = fetch_var(Ctx, Bef),
- {case Unit of
- 1 ->
- [];
- _ ->
- [{test,bs_test_unit,{f,Vf},[CtxReg,Unit]}]
- end,Bef};
- {_,_,_} ->
- case is_context_unused(Body) of
- false ->
- Reg = put_reg(Hd, Bef#sr.reg),
- Int1 = Bef#sr{reg=Reg},
- Rhd = fetch_reg(Hd, Reg),
- CtxReg = fetch_reg(Ctx, Reg),
- Name = bs_get_binary2,
- Live = max_reg(Bef#sr.reg),
- {[{test,Name,{f,Vf},Live,
- [CtxReg,atomic(Size),Unit,{field_flags,Flags}],Rhd}],
- Int1};
- true ->
- %% Since the matching context will not be used again,
- %% we can reuse its register. Reusing the register
- %% opens some interesting optimizations in the
- %% run-time system.
-
- Reg0 = Bef#sr.reg,
- CtxReg = fetch_reg(Ctx, Reg0),
- Reg = replace_reg_contents(Ctx, Hd, Reg0),
- Int1 = Bef#sr{reg=Reg},
- Name = bs_get_binary2,
- Live = max_reg(Int1#sr.reg),
- {[{test,Name,{f,Vf},Live,
- [CtxReg,atomic(Size),Unit,{field_flags,Flags}],CtxReg}],
- Int1}
- end
- end,
- {Es,clear_dead(Aft, I, Vdb),St}.
-
-%% is_context_unused(Ke) -> true | false
-%% Simple heurististic to determine whether the code that follows
-%% will use the current matching context again. (The liveness
-%% information is too conservative to be useful for this purpose.)
-%% 'true' means that the code that follows will definitely not use
-%% the context again (because it is a block, not guard or matching
-%% code); 'false' that we are not sure (there could be more
-%% matching).
-
-is_context_unused(#k_alt{then=Then}) ->
- %% #k_alt{} can be used for different purposes. If the Then part
- %% is a block, it means that matching has finished and is used for a guard
- %% to choose between the matched clauses.
- is_context_unused(Then);
-is_context_unused(#cg_block{}) ->
- true;
-is_context_unused(_) ->
- false.
-
-select_bin_end(#k_val_clause{val=#k_bin_end{},body=B}, Ivar, Tf, Bef, St0) ->
- Ctx = St0#cg.ctx,
- {Bis,Aft,St2} = match_cg(B, Tf, Bef, St0),
- CtxReg = fetch_var(Ctx, Bef),
- {[{bs_restore2,CtxReg,{Ctx,Ivar}},
- {test,bs_test_tail2,{f,Tf},[CtxReg,0]}|Bis],Aft,St2}.
-
-get_bin_size_reg(#k_var{name=V}, Bef) ->
- fetch_var(V, Bef);
-get_bin_size_reg(Literal, _Bef) ->
- atomic(Literal).
-
-build_bs_instr(Type, Vf, CtxReg, Live, SizeReg, Unit, Flags, Rhd) ->
- {Format,Name} = case Type of
- integer -> {plain,bs_get_integer2};
- float -> {plain,bs_get_float2};
- binary -> {plain,bs_get_binary2};
- utf8 -> {utf,bs_get_utf8};
- utf16 -> {utf,bs_get_utf16};
- utf32 -> {utf,bs_get_utf32}
- end,
- case Format of
- plain ->
- {test,Name,{f,Vf},Live,
- [CtxReg,SizeReg,Unit,{field_flags,Flags}],Rhd};
- utf ->
- {test,Name,{f,Vf},Live,
- [CtxReg,{field_flags,Flags}],Rhd}
- end.
-
-build_skip_instr(Type, Vf, CtxReg, Live, SizeReg, Unit, Flags) ->
- {Format,Name} = case Type of
- utf8 -> {utf,bs_skip_utf8};
- utf16 -> {utf,bs_skip_utf16};
- utf32 -> {utf,bs_skip_utf32};
- _ -> {plain,bs_skip_bits2}
- end,
- case Format of
- plain ->
- {test,Name,{f,Vf},[CtxReg,SizeReg,Unit,{field_flags,Flags}]};
- utf ->
- {test,Name,{f,Vf},[CtxReg,Live,{field_flags,Flags}]}
- end.
-
-select_val(#k_val_clause{val=#k_tuple{es=Es},body=B,anno=#l{i=I,vdb=Vdb}},
- V, Vf, Bef, St0) ->
- {Eis,Int,St1} = select_extract_tuple(V, Es, I, Vdb, Bef, St0),
- {Bis,Aft,St2} = match_cg(B, Vf, Int, St1),
- {length(Es),Eis ++ Bis,Aft,St2};
-select_val(#k_val_clause{val=Val0,body=B}, _V, Vf, Bef, St0) ->
- Val = case Val0 of
- #k_atom{val=Lit} -> Lit;
- #k_float{val=Lit} -> Lit;
- #k_int{val=Lit} -> Lit;
- #k_literal{val=Lit} -> Lit
- end,
- {Bis,Aft,St1} = match_cg(B, Vf, Bef, St0),
- {Val,Bis,Aft,St1}.
-
-%% select_extract_tuple(Src, [V], I, Vdb, StackReg, State) ->
-%% {[E],StackReg,State}.
-%% Extract tuple elements, but only if they do not immediately die.
-
-select_extract_tuple(Src, Vs, I, Vdb, Bef, St) ->
- F = fun (#k_var{name=V}, {Int0,Elem}) ->
- case vdb_find(V, Vdb) of
- {V,_,L} when L =< I -> {[], {Int0,Elem+1}};
- _Other ->
- Reg1 = put_reg(V, Int0#sr.reg),
- Int1 = Int0#sr{reg=Reg1},
- Rsrc = fetch_var(Src, Int1),
- {[{get_tuple_element,Rsrc,Elem,fetch_reg(V, Reg1)}],
- {Int1,Elem+1}}
- end
- end,
- {Es,{Aft,_}} = flatmapfoldl(F, {Bef,0}, Vs),
- {Es,Aft,St}.
-
-select_map(Scs, V, Tf, Vf, Bef, St0) ->
- Reg = fetch_var(V, Bef),
- {Is,Aft,St1} =
- match_fmf(fun(#k_val_clause{val=#k_map{op=exact,es=Es},
- body=B,anno=#l{i=I,vdb=Vdb}}, Fail, St1) ->
- select_map_val(V, Es, B, Fail, I, Vdb, Bef, St1)
- end, Vf, St0, Scs),
- {[{test,is_map,{f,Tf},[Reg]}|Is],Aft,St1}.
-
-select_map_val(V, Es, B, Fail, I, Vdb, Bef, St0) ->
- {Eis,Int,St1} = select_extract_map(V, Es, Fail, I, Vdb, Bef, St0),
- {Bis,Aft,St2} = match_cg(B, Fail, Int, St1),
- {Eis++Bis,Aft,St2}.
-
-select_extract_map(_, [], _, _, _, Bef, St) -> {[],Bef,St};
-select_extract_map(Src, Vs, Fail, I, Vdb, Bef, St) ->
- %% First split the instruction flow
- %% We want one set of each
- %% 1) has_map_fields (no target registers)
- %% 2) get_map_elements (with target registers)
- %% Assume keys are term-sorted
- Rsrc = fetch_var(Src, Bef),
-
- {{HasKs,GetVs,HasVarKs,GetVarVs},Aft} =
- foldr(fun(#k_map_pair{key=#k_var{name=K},val=#k_var{name=V}},
- {{HasKsi,GetVsi,HasVarVsi,GetVarVsi},Int0}) ->
- case vdb_find(V, Vdb) of
- {V,_,L} when L =< I ->
- RK = fetch_var(K,Int0),
- {{HasKsi,GetVsi,[RK|HasVarVsi],GetVarVsi},Int0};
- _Other ->
- Reg1 = put_reg(V, Int0#sr.reg),
- Int1 = Int0#sr{reg=Reg1},
- RK = fetch_var(K,Int0),
- RV = fetch_reg(V,Reg1),
- {{HasKsi,GetVsi,HasVarVsi,[[RK,RV]|GetVarVsi]},Int1}
- end;
- (#k_map_pair{key=Key,val=#k_var{name=V}},
- {{HasKsi,GetVsi,HasVarVsi,GetVarVsi},Int0}) ->
- case vdb_find(V, Vdb) of
- {V,_,L} when L =< I ->
- {{[atomic(Key)|HasKsi],GetVsi,HasVarVsi,GetVarVsi},Int0};
- _Other ->
- Reg1 = put_reg(V, Int0#sr.reg),
- Int1 = Int0#sr{reg=Reg1},
- {{HasKsi,[atomic(Key),fetch_reg(V, Reg1)|GetVsi],
- HasVarVsi,GetVarVsi},Int1}
- end
- end, {{[],[],[],[]},Bef}, Vs),
-
- Code = [{test,has_map_fields,{f,Fail},Rsrc,{list,HasKs}} || HasKs =/= []] ++
- [{test,has_map_fields,{f,Fail},Rsrc,{list,[K]}} || K <- HasVarKs] ++
- [{get_map_elements, {f,Fail},Rsrc,{list,GetVs}} || GetVs =/= []] ++
- [{get_map_elements, {f,Fail},Rsrc,{list,[K,V]}} || [K,V] <- GetVarVs],
- {Code, Aft, St}.
-
-
-select_extract_cons(Src, [#k_var{name=Hd},#k_var{name=Tl}], I, Vdb, Bef, St) ->
- Rsrc = fetch_var(Src, Bef),
- Int = clear_dead(Bef, I, Vdb),
- {{_,_,Lhd},{_,_,Ltl}} = {vdb_find(Hd, Vdb),vdb_find(Tl, Vdb)},
- case {Lhd =< I, Ltl =< I} of
- {true,true} ->
- %% Both dead.
- {[],Bef,St};
- {true,false} ->
- %% Head dead.
- Reg0 = put_reg(Tl, Bef#sr.reg),
- Aft = Int#sr{reg=Reg0},
- Rtl = fetch_reg(Tl, Reg0),
- {[{get_tl,Rsrc,Rtl}],Aft,St};
- {false,true} ->
- %% Tail dead.
- Reg0 = put_reg(Hd, Bef#sr.reg),
- Aft = Int#sr{reg=Reg0},
- Rhd = fetch_reg(Hd, Reg0),
- {[{get_hd,Rsrc,Rhd}],Aft,St};
- {false,false} ->
- %% Both used.
- Reg0 = put_reg(Tl, put_reg(Hd, Bef#sr.reg)),
- Aft = Bef#sr{reg=Reg0},
- Rhd = fetch_reg(Hd, Reg0),
- Rtl = fetch_reg(Tl, Reg0),
- {[{get_hd,Rsrc,Rhd},{get_tl,Rsrc,Rtl}],Aft,St}
- end.
-
-guard_clause_cg(#k_guard_clause{anno=#l{vdb=Vdb},guard=G,body=B}, Fail, Bef, St0) ->
- {Gis,Int,St1} = guard_cg(G, Fail, Vdb, Bef, St0),
- {Bis,Aft,St} = match_cg(B, Fail, Int, St1),
- {Gis ++ Bis,Aft,St}.
-
-%% guard_cg(Guard, Fail, Vdb, StackReg, State) ->
-%% {[Ainstr],StackReg,State}.
-%% A guard is a boolean expression of tests. Tests return true or
-%% false. A fault in a test causes the test to return false. Tests
-%% never return the boolean, instead we generate jump code to go to
-%% the correct exit point. Primops and tests all go to the next
-%% instruction on success or jump to a failure label.
-
-guard_cg(#k_protected{arg=Ts,ret=Rs,anno=#l{vdb=Pdb}}, Fail, _Vdb, Bef, St) ->
- protected_cg(Ts, Rs, Fail, Pdb, Bef, St);
-guard_cg(#k_test{anno=#l{i=I},op=Test0,args=As,inverted=Inverted},
- Fail, Vdb, Bef, St0) ->
- #k_remote{mod=#k_atom{val=erlang},name=#k_atom{val=Test}} = Test0,
- case Inverted of
- false ->
- test_cg(Test, As, Fail, I, Vdb, Bef, St0);
- true ->
- {Psucc,St1} = new_label(St0),
- {Is,Aft,St2} = test_cg(Test, As, Psucc, I, Vdb, Bef, St1),
- {Is++[{jump,{f,Fail}},{label,Psucc}],Aft,St2}
- end;
-guard_cg(G, _Fail, Vdb, Bef, St) ->
- %%ok = io:fwrite("cg ~w: ~p~n", [?LINE,{G,Fail,Vdb,Bef}]),
- {Gis,Aft,St1} = cg(G, Vdb, Bef, St),
- %%ok = io:fwrite("cg ~w: ~p~n", [?LINE,{Aft}]),
- {Gis,Aft,St1}.
-
-%% guard_cg_list([Kexpr], Fail, I, Vdb, StackReg, St) ->
-%% {[Ainstr],StackReg,St}.
-
-guard_cg_list(Kes, Fail, Vdb, Bef, St0) ->
- {Keis,{Aft,St1}} =
- flatmapfoldl(fun (Ke, {Inta,Sta}) ->
- {Keis,Intb,Stb} =
- guard_cg(Ke, Fail, Vdb, Inta, Sta),
- {Keis,{Intb,Stb}}
- end, {Bef,St0}, need_heap(Kes)),
- {Keis,Aft,St1}.
-
-%% protected_cg([Kexpr], [Ret], Fail, I, Vdb, Bef, St) -> {[Ainstr],Aft,St}.
-%% Do a protected. Protecteds without return values are just done
-%% for effect, the return value is not checked, success passes on to
-%% the next instruction and failure jumps to Fail. If there are
-%% return values then these must be set to 'false' on failure,
-%% control always passes to the next instruction.
-
-protected_cg(Ts, [], Fail, Vdb, Bef, St0) ->
- %% Protect these calls, revert when done.
- {Tis,Aft,St1} = guard_cg_list(Ts, Fail, Vdb, Bef, St0#cg{bfail=Fail}),
- {Tis,Aft,St1#cg{bfail=St0#cg.bfail}};
-protected_cg(Ts, Rs, _Fail, Vdb, Bef, St0) ->
- {Pfail,St1} = new_label(St0),
- {Psucc,St2} = new_label(St1),
- {Tis,Aft,St3} = guard_cg_list(Ts, Pfail, Vdb, Bef,
- St2#cg{bfail=Pfail}),
- %%ok = io:fwrite("cg ~w: ~p~n", [?LINE,{Rs,I,Vdb,Aft}]),
- %% Set return values to false.
- Mis = [{move,{atom,false},fetch_var(V,Aft)}||#k_var{name=V} <- Rs],
- {Tis ++ [{jump,{f,Psucc}},
- {label,Pfail}] ++ Mis ++ [{label,Psucc}],
- Aft,St3#cg{bfail=St0#cg.bfail}}.
-
-%% test_cg(TestName, Args, Fail, I, Vdb, Bef, St) -> {[Ainstr],Aft,St}.
-%% Generate test instruction. Use explicit fail label here.
-
-test_cg(is_map, [A], Fail, I, Vdb, Bef, St) ->
- %% We must avoid creating code like this:
- %%
- %% move x(0) y(0)
- %% is_map Fail [x(0)]
- %% make_fun => x(0) %% Overwrite x(0)
- %% put_map_assoc y(0) ...
- %%
- %% The code is safe, but beam_validator does not understand that.
- %% Extending beam_validator to handle such (rare) code as the
- %% above would make it slower for all programs. Instead, change
- %% the code generator to always prefer the Y register for is_map()
- %% and put_map_assoc() instructions, ensuring that they use the
- %% same register.
- Arg = cg_reg_arg_prefer_y(A, Bef),
- Aft = clear_dead(Bef, I, Vdb),
- {[{test,is_map,{f,Fail},[Arg]}],Aft,St};
-test_cg(is_boolean, [#k_atom{val=Val}], Fail, I, Vdb, Bef, St) ->
- Aft = clear_dead(Bef, I, Vdb),
- Is = case is_boolean(Val) of
- true -> [];
- false -> [{jump,{f,Fail}}]
- end,
- {Is,Aft,St};
-test_cg(Test, As, Fail, I, Vdb, Bef, St) ->
- Args = cg_reg_args(As, Bef),
- Aft = clear_dead(Bef, I, Vdb),
- {[beam_utils:bif_to_test(Test, Args, {f,Fail})],Aft,St}.
-
-%% match_fmf(Fun, LastFail, State, [Clause]) -> {Is,Aft,State}.
-%% This is a special flatmapfoldl for match code gen where we
-%% generate a "failure" label for each clause. The last clause uses
-%% an externally generated failure label, LastFail. N.B. We do not
-%% know or care how the failure labels are used.
-
-match_fmf(F, LastFail, St, [H]) ->
- F(H, LastFail, St);
-match_fmf(F, LastFail, St0, [H|T]) ->
- {Fail,St1} = new_label(St0),
- {R,Aft1,St2} = F(H, Fail, St1),
- {Rs,Aft2,St3} = match_fmf(F, LastFail, St2, T),
- {R ++ [{label,Fail}] ++ Rs,sr_merge(Aft1, Aft2),St3}.
-
-%% call_cg(Func, [Arg], [Ret], Le, Vdb, StackReg, State) ->
-%% {[Ainstr],StackReg,State}.
-%% enter_cg(Func, [Arg], Le, Vdb, Bef, St) -> {[Ainstr],Aft,St}.
-%% Call and enter first put the arguments into registers and save any
-%% other registers, then clean up and compress the stack and set the
-%% frame size. Finally the actual call is made. Call then needs the
-%% return values filled in.
-
-call_cg(#k_var{}=Var, As, Rs, Le, Vdb, Bef, St0) ->
- {Sis,Int} = cg_setup_call(As++[Var], Bef, Le#l.i, Vdb),
- %% Put return values in registers.
- Reg = load_vars(Rs, clear_regs(Int#sr.reg)),
- %% Build complete code and final stack/register state.
- Arity = length(As),
- {Frees,Aft} = free_dead(clear_dead(Int#sr{reg=Reg}, Le#l.i, Vdb)),
- {Sis ++ Frees ++ [line(Le),{call_fun,Arity}],Aft,
- need_stack_frame(St0)};
-call_cg(#k_remote{mod=Mod,name=Name}, As, Rs, Le, Vdb, Bef, St0)
- when is_record(Mod, k_var); is_record(Name, k_var) ->
- {Sis,Int} = cg_setup_call(As++[Mod,Name], Bef, Le#l.i, Vdb),
- %% Put return values in registers.
- Reg = load_vars(Rs, clear_regs(Int#sr.reg)),
- %% Build complete code and final stack/register state.
- Arity = length(As),
- St = need_stack_frame(St0),
- %%{Call,St1} = build_call(Func, Arity, St0),
- {Frees,Aft} = free_dead(clear_dead(Int#sr{reg=Reg}, Le#l.i, Vdb)),
- {Sis ++ Frees ++ [line(Le),{apply,Arity}],Aft,St};
-call_cg(Func, As, Rs, Le, Vdb, Bef, St0) ->
- case St0 of
- #cg{bfail=Fail} when Fail =/= 0 ->
- %% Inside a guard. The only allowed function call is to
- %% erlang:error/1,2. We will generate the following code:
- %%
- %% move {atom,ok} DestReg
- %% jump FailureLabel
- #k_remote{mod=#k_atom{val=erlang},
- name=#k_atom{val=error}} = Func, %Assertion.
- [#k_var{name=DestVar}] = Rs,
- Int0 = clear_dead(Bef, Le#l.i, Vdb),
- Reg = put_reg(DestVar, Int0#sr.reg),
- Int = Int0#sr{reg=Reg},
- Dst = fetch_reg(DestVar, Reg),
- {[{move,{atom,ok},Dst},{jump,{f,Fail}}],
- clear_dead(Int, Le#l.i, Vdb),St0};
- #cg{} ->
- %% Ordinary function call in a function body.
- {Sis,Int} = cg_setup_call(As, Bef, Le#l.i, Vdb),
- %% Put return values in registers.
- Reg = load_vars(Rs, clear_regs(Int#sr.reg)),
- %% Build complete code and final stack/register state.
- Arity = length(As),
- {Call,St1} = build_call(Func, Arity, St0),
- {Frees,Aft} = free_dead(clear_dead(Int#sr{reg=Reg}, Le#l.i, Vdb)),
- {Sis ++ Frees ++ [line(Le)|Call],Aft,St1}
- end.
-
-build_call(#k_remote{mod=#k_atom{val=erlang},name=#k_atom{val='!'}}, 2, St0) ->
- {[send],need_stack_frame(St0)};
-build_call(#k_remote{mod=#k_atom{val=Mod},name=#k_atom{val=Name}}, Arity, St0) ->
- {[{call_ext,Arity,{extfunc,Mod,Name,Arity}}],need_stack_frame(St0)};
-build_call(#k_local{name=Name}, Arity, St0) when is_atom(Name) ->
- {Lbl,St1} = local_func_label(Name, Arity, need_stack_frame(St0)),
- {[{call,Arity,{f,Lbl}}],St1}.
-
-free_dead(#sr{stk=Stk0}=Aft) ->
- {Instr,Stk} = free_dead(Stk0, 0, [], []),
- {Instr,Aft#sr{stk=Stk}}.
-
-free_dead([dead|Stk], Y, Instr, StkAcc) ->
- %% Note: kill/1 is equivalent to init/1 (translated by beam_asm).
- %% We use kill/1 to help further optimisation passes.
- free_dead(Stk, Y+1, [{kill,{yy,Y}}|Instr], [free|StkAcc]);
-free_dead([Any|Stk], Y, Instr, StkAcc) ->
- free_dead(Stk, Y+1, Instr, [Any|StkAcc]);
-free_dead([], _, Instr, StkAcc) -> {Instr,reverse(StkAcc)}.
-
-enter_cg(#k_var{} = Var, As, Le, Vdb, Bef, St0) ->
- {Sis,Int} = cg_setup_call(As++[Var], Bef, Le#l.i, Vdb),
- %% Build complete code and final stack/register state.
- Arity = length(As),
- {Sis ++ [line(Le),{call_fun,Arity},return],
- clear_dead(Int#sr{reg=clear_regs(Int#sr.reg)}, Le#l.i, Vdb),
- need_stack_frame(St0)};
-enter_cg(#k_remote{mod=Mod,name=Name}, As, Le, Vdb, Bef, St0)
- when is_record(Mod, k_var); is_record(Name, k_var) ->
- {Sis,Int} = cg_setup_call(As++[Mod,Name], Bef, Le#l.i, Vdb),
- %% Build complete code and final stack/register state.
- Arity = length(As),
- St = need_stack_frame(St0),
- {Sis ++ [line(Le),{apply_only,Arity}],
- clear_dead(Int#sr{reg=clear_regs(Int#sr.reg)}, Le#l.i, Vdb),
- St};
-enter_cg(Func, As, Le, Vdb, Bef, St0) ->
- {Sis,Int} = cg_setup_call(As, Bef, Le#l.i, Vdb),
- %% Build complete code and final stack/register state.
- Arity = length(As),
- {Call,St1} = build_enter(Func, Arity, St0),
- Line = enter_line(Func, Arity, Le),
- {Sis ++ Line ++ Call,
- clear_dead(Int#sr{reg=clear_regs(Int#sr.reg)}, Le#l.i, Vdb),
- St1}.
-
-build_enter(#k_remote{mod=#k_atom{val=erlang},name=#k_atom{val='!'}}, 2, St0) ->
- {[send,return],need_stack_frame(St0)};
-build_enter(#k_remote{mod=#k_atom{val=Mod},name=#k_atom{val=Name}}, Arity, St0) ->
- St1 = case trap_bif(Mod, Name, Arity) of
- true -> need_stack_frame(St0);
- false -> St0
- end,
- {[{call_ext_only,Arity,{extfunc,Mod,Name,Arity}}],St1};
-build_enter(#k_local{name=Name}, Arity, St0) when is_atom(Name) ->
- {Lbl,St1} = local_func_label(Name, Arity, St0),
- {[{call_only,Arity,{f,Lbl}}],St1}.
-
-enter_line(#k_remote{mod=#k_atom{val=Mod},name=#k_atom{val=Name}}, Arity, Le) ->
- case erl_bifs:is_safe(Mod, Name, Arity) of
- false ->
- %% Tail-recursive call, possibly to a BIF.
- %% We'll need a line instruction in case the
- %% BIF call fails.
- [line(Le)];
- true ->
- %% Call to a safe BIF. Since it cannot fail,
- %% we don't need any line instruction here.
- []
- end;
-enter_line(_, _, _) ->
- %% Tail-recursive call to a local function. A line
- %% instruction will not be useful.
- [].
-
-%% local_func_label(Name, Arity, State) -> {Label,State'}
-%% local_func_label({Name,Arity}, State) -> {Label,State'}
-%% Get the function entry label for a local function.
-
-local_func_label(Name, Arity, St) ->
- local_func_label({Name,Arity}, St).
-
-local_func_label(Key, #cg{functable=Map}=St0) ->
- case Map of
- #{Key := Label} -> {Label,St0};
- _ ->
- {Label,St} = new_label(St0),
- {Label,St#cg{functable=Map#{Key => Label}}}
- end.
-
-%% need_stack_frame(State) -> State'
-%% Make a note in the state that this function will need a stack frame.
-
-need_stack_frame(#cg{need_frame=true}=St) -> St;
-need_stack_frame(St) -> St#cg{need_frame=true}.
-
-%% trap_bif(Mod, Name, Arity) -> true|false
-%% Trap bifs that need a stack frame.
-
-trap_bif(erlang, link, 1) -> true;
-trap_bif(erlang, unlink, 1) -> true;
-trap_bif(erlang, monitor_node, 2) -> true;
-trap_bif(erlang, group_leader, 2) -> true;
-trap_bif(erlang, exit, 2) -> true;
-trap_bif(_, _, _) -> false.
-
-%% bif_cg(#k_bif{}, Le, Vdb, StackReg, State) ->
-%% {[Ainstr],StackReg,State}.
-%% Generate code a BIF.
-
-bif_cg(#k_bif{op=#k_internal{name=Name},args=As,ret=Rs}, Le, Vdb, Bef, St) ->
- internal_cg(Name, As, Rs, Le, Vdb, Bef, St);
-bif_cg(#k_bif{op=#k_remote{mod=#k_atom{val=erlang},name=#k_atom{val=Name}},
- args=As,ret=Rs}, Le, Vdb, Bef, St) ->
- Ar = length(As),
- case is_gc_bif(Name, Ar) of
- false ->
- bif_cg(Name, As, Rs, Le, Vdb, Bef, St);
- true ->
- gc_bif_cg(Name, As, Rs, Le, Vdb, Bef, St)
- end.
-
-%% internal_cg(Bif, [Arg], [Ret], Le, Vdb, StackReg, State) ->
-%% {[Ainstr],StackReg,State}.
-
-internal_cg(bs_context_to_binary=Instr, [Src0], [], Le, Vdb, Bef, St0) ->
- [Src] = cg_reg_args([Src0], Bef),
- {[{Instr,Src}],clear_dead(Bef, Le#l.i, Vdb), St0};
-internal_cg(dsetelement, [Index0,Tuple0,New0], _Rs, Le, Vdb, Bef, St0) ->
- [New,Tuple,{integer,Index1}] = cg_reg_args([New0,Tuple0,Index0], Bef),
- Index = Index1-1,
- {[{set_tuple_element,New,Tuple,Index}],
- clear_dead(Bef, Le#l.i, Vdb), St0};
-internal_cg(make_fun, [Func0,Arity0|As], Rs, Le, Vdb, Bef, St0) ->
- %% This behaves more like a function call.
- #k_atom{val=Func} = Func0,
- #k_int{val=Arity} = Arity0,
- {Sis,Int} = cg_setup_call(As, Bef, Le#l.i, Vdb),
- Reg = load_vars(Rs, clear_regs(Int#sr.reg)),
- {FuncLbl,St1} = local_func_label(Func, Arity, St0),
- MakeFun = {make_fun2,{f,FuncLbl},0,0,length(As)},
- {Sis ++ [MakeFun],
- clear_dead(Int#sr{reg=Reg}, Le#l.i, Vdb),
- St1};
-internal_cg(bs_init_writable=I, As, Rs, Le, Vdb, Bef, St) ->
- %% This behaves like a function call.
- {Sis,Int} = cg_setup_call(As, Bef, Le#l.i, Vdb),
- Reg = load_vars(Rs, clear_regs(Int#sr.reg)),
- {Sis++[I],clear_dead(Int#sr{reg=Reg}, Le#l.i, Vdb),St};
-internal_cg(build_stacktrace=I, As, Rs, Le, Vdb, Bef, St) ->
- %% This behaves like a function call.
- {Sis,Int} = cg_setup_call(As, Bef, Le#l.i, Vdb),
- Reg = load_vars(Rs, clear_regs(Int#sr.reg)),
- {Sis++[I],clear_dead(Int#sr{reg=Reg}, Le#l.i, Vdb),St};
-internal_cg(raise, As, Rs, Le, Vdb, Bef, St) ->
- %% raise can be treated like a guard BIF.
- bif_cg(raise, As, Rs, Le, Vdb, Bef, St);
-internal_cg(guard_error, [ExitCall], _Rs, Le, Vdb, Bef, St) ->
- %% A call an exit BIF from inside a #k_guard_match{}.
- %% Generate a standard call, but leave the register descriptors
- %% alone, effectively pretending that there was no call.
- #k_call{op=#k_remote{mod=#k_atom{val=Mod},name=#k_atom{val=Name}},
- args=As} = ExitCall,
- Arity = length(As),
- {Ms,_} = cg_call_args(As, Bef, Le#l.i, Vdb),
- Call = {call_ext,Arity,{extfunc,Mod,Name,Arity}},
- Is = Ms++[line(Le),Call],
- {Is,Bef,St};
-internal_cg(raw_raise=I, As, Rs, Le, Vdb, Bef, St) ->
- %% This behaves like a function call.
- {Sis,Int} = cg_setup_call(As, Bef, Le#l.i, Vdb),
- Reg = load_vars(Rs, clear_regs(Int#sr.reg)),
- {Sis++[I],clear_dead(Int#sr{reg=Reg}, Le#l.i, Vdb),St}.
-
-%% bif_cg(Bif, [Arg], [Ret], Le, Vdb, StackReg, State) ->
-%% {[Ainstr],StackReg,State}.
-
-bif_cg(Bif, As, [#k_var{name=V}], Le, Vdb, Bef, St0) ->
- Ars = cg_reg_args(As, Bef),
-
- %% If we are inside a catch and in a body (not in guard) and the
- %% BIF may fail, we must save everything that will be alive after
- %% the catch (because the code after the code assumes that all
- %% variables that are live are stored on the stack).
- %%
- %% Currently, we are somewhat pessimistic in
- %% that we save any variable that will be live after this BIF call.
-
- MayFail = not erl_bifs:is_safe(erlang, Bif, length(As)),
- {Sis,Int0} =
- case MayFail of
- true ->
- maybe_adjust_stack(Bef, Le#l.i, Le#l.i+1, Vdb, St0);
- false ->
- {[],Bef}
- end,
- Int1 = clear_dead(Int0, Le#l.i, Vdb),
- Reg = put_reg(V, Int1#sr.reg),
- Int = Int1#sr{reg=Reg},
- Dst = fetch_reg(V, Reg),
- BifFail = {f,St0#cg.bfail},
- %% We need a line instructions for BIFs that may fail in a body.
- Line = case BifFail of
- {f,0} when MayFail ->
- [line(Le)];
- _ ->
- []
- end,
- {Sis++Line++[{bif,Bif,BifFail,Ars,Dst}],
- clear_dead(Int, Le#l.i, Vdb), St0}.
-
-
-%% gc_bif_cg(Bif, [Arg], [Ret], Le, Vdb, StackReg, State) ->
-%% {[Ainstr],StackReg,State}.
-
-gc_bif_cg(Bif, As, [#k_var{name=V}], Le, Vdb, Bef, St0) ->
- Ars = cg_reg_args(As, Bef),
-
- %% If we are inside a catch and in a body (not in guard) and the
- %% BIF may fail, we must save everything that will be alive after
- %% the catch (because the code after the code assumes that all
- %% variables that are live are stored on the stack).
- %%
- %% Currently, we are somewhat pessimistic in
- %% that we save any variable that will be live after this BIF call.
-
- {Sis,Int0} = maybe_adjust_stack(Bef, Le#l.i, Le#l.i+1, Vdb, St0),
-
- Int1 = clear_dead(Int0, Le#l.i, Vdb),
- Reg = put_reg(V, Int1#sr.reg),
- Int = Int1#sr{reg=Reg},
- Dst = fetch_reg(V, Reg),
- BifFail = {f,St0#cg.bfail},
- Line = case BifFail of
- {f,0} -> [line(Le)];
- {f,_} -> []
- end,
- {Sis++Line++[{gc_bif,Bif,BifFail,max_reg(Bef#sr.reg),Ars,Dst}],
- clear_dead(Int, Le#l.i, Vdb), St0}.
-
-%% recv_loop_cg(TimeOut, ReceiveVar, ReceiveMatch, TimeOutExprs,
-%% [Ret], Le, Vdb, Bef, St) -> {[Ainstr],Aft,St}.
-
-recv_loop_cg(Te, Rvar, Rm, Tes, Rs, Le, Vdb, Bef, St0) ->
- {Sis,Int0} = adjust_stack(Bef, Le#l.i, Le#l.i, Vdb),
- Int1 = Int0#sr{reg=clear_regs(Int0#sr.reg)},
- %% Get labels.
- {Rl,St1} = new_label(St0),
- {Tl,St2} = new_label(St1),
- {Bl,St3} = new_label(St2),
- St4 = St3#cg{break=Bl,recv=Rl}, %Set correct receive labels
- {Ris,Raft,St5} = cg_recv_mesg(Rvar, Rm, Tl, Int1, St4),
- {Wis,Taft,St6} = cg_recv_wait(Te, Tes, Le#l.i, Int1, St5),
- Int2 = sr_merge(Raft, Taft), %Merge stack/registers
- Reg = load_vars(Rs, Int2#sr.reg),
- {Sis ++ [line(Le)] ++ Ris ++ [{label,Tl}] ++ Wis ++ [{label,Bl}],
- clear_dead(Int2#sr{reg=Reg}, Le#l.i, Vdb),
- St6#cg{break=St0#cg.break,recv=St0#cg.recv}}.
-
-%% cg_recv_mesg( ) -> {[Ainstr],Aft,St}.
-
-cg_recv_mesg(#k_var{name=R}, Rm, Tl, Bef, St0) ->
- Int0 = Bef#sr{reg=put_reg(R, Bef#sr.reg)},
- Ret = fetch_reg(R, Int0#sr.reg),
- %% Int1 = clear_dead(Int0, I, Rm#l.vdb),
- Int1 = Int0,
- {Mis,Int2,St1} = match_cg(Rm, none, Int1, St0),
- {[{label,St1#cg.recv},{loop_rec,{f,Tl},Ret}|Mis],Int2,St1}.
-
-%% cg_recv_wait(Te, Tes, I, Vdb, Int2, St3) -> {[Ainstr],Aft,St}.
-
-cg_recv_wait(#k_atom{val=infinity}, #cg_block{anno=Le,es=Tes}, I, Bef, St0) ->
- %% We know that the 'after' body will never be executed.
- %% But to keep the stack and register information up to date,
- %% we will generate the code for the 'after' body, and then discard it.
- Int1 = clear_dead(Bef, I, Le#l.vdb),
- {_,Int2,St1} = cg_block(Tes, Le#l.vdb,
- Int1#sr{reg=clear_regs(Int1#sr.reg)}, St0),
- {[{wait,{f,St1#cg.recv}}],Int2,St1};
-cg_recv_wait(#k_int{val=0}, #cg_block{anno=Le,es=Tes}, _I, Bef, St0) ->
- {Tis,Int,St1} = cg_block(Tes, Le#l.vdb, Bef, St0),
- {[timeout|Tis],Int,St1};
-cg_recv_wait(Te, #cg_block{anno=Le,es=Tes}, I, Bef, St0) ->
- Reg = cg_reg_arg(Te, Bef),
- %% Must have empty registers here! Bug if anything in registers.
- Int0 = clear_dead(Bef, I, Le#l.vdb),
- {Tis,Int,St1} = cg_block(Tes, Le#l.vdb,
- Int0#sr{reg=clear_regs(Int0#sr.reg)}, St0),
- {[{wait_timeout,{f,St1#cg.recv},Reg},timeout] ++ Tis,Int,St1}.
-
-%% recv_next_cg(Le, Vdb, StackReg, St) -> {[Ainstr],StackReg,St}.
-%% Use adjust stack to clear stack, but only need it for Aft.
-
-recv_next_cg(Le, Vdb, Bef, St) ->
- {Sis,Aft} = adjust_stack(Bef, Le#l.i, Le#l.i+1, Vdb),
- {[{loop_rec_end,{f,St#cg.recv}}] ++ Sis,Aft,St}. %Joke
-
-%% try_cg(TryBlock, [BodyVar], TryBody, [ExcpVar], TryHandler, [Ret],
-%% Le, Vdb, StackReg, St) -> {[Ainstr],StackReg,St}.
-
-try_cg(Ta, Vs, Tb, Evs, Th, Rs, Le, Vdb, Bef, St0) ->
- {B,St1} = new_label(St0), %Body label
- {H,St2} = new_label(St1), %Handler label
- {E,St3} = new_label(St2), %End label
- #l{i=TryTag} = get_kanno(Ta),
- Int1 = Bef#sr{stk=put_catch(TryTag, Bef#sr.stk)},
- TryReg = fetch_stack({catch_tag,TryTag}, Int1#sr.stk),
- {Ais,Int2,St4} = cg(Ta, Vdb, Int1, St3#cg{break=B,in_catch=true}),
- Int3 = Int2#sr{stk=drop_catch(TryTag, Int2#sr.stk)},
- St5 = St4#cg{break=E,in_catch=St3#cg.in_catch},
- {Bis,Baft,St6} = cg(Tb, Vdb, Int3#sr{reg=load_vars(Vs, Int3#sr.reg)}, St5),
- {His,Haft,St7} = cg(Th, Vdb, Int3#sr{reg=load_vars(Evs, Int3#sr.reg)}, St6),
- Int4 = sr_merge(Baft, Haft), %Merge stack/registers
- Aft = Int4#sr{reg=load_vars(Rs, Int4#sr.reg)},
- {[{'try',TryReg,{f,H}}] ++ Ais ++
- [{label,B},{try_end,TryReg}] ++ Bis ++
- [{label,H},{try_case,TryReg}] ++ His ++
- [{label,E}],
- clear_dead(Aft, Le#l.i, Vdb),
- St7#cg{break=St0#cg.break}}.
-
-try_enter_cg(Ta, Vs, Tb, Evs, Th, Le, Vdb, Bef, St0) ->
- {B,St1} = new_label(St0), %Body label
- {H,St2} = new_label(St1), %Handler label
- #l{i=TryTag} = get_kanno(Ta),
- Int1 = Bef#sr{stk=put_catch(TryTag, Bef#sr.stk)},
- TryReg = fetch_stack({catch_tag,TryTag}, Int1#sr.stk),
- {Ais,Int2,St3} = cg(Ta, Vdb, Int1, St2#cg{break=B,in_catch=true}),
- Int3 = Int2#sr{stk=drop_catch(TryTag, Int2#sr.stk)},
- St4 = St3#cg{in_catch=St2#cg.in_catch},
- {Bis,Baft,St5} = cg(Tb, Vdb, Int3#sr{reg=load_vars(Vs, Int3#sr.reg)}, St4),
- {His,Haft,St6} = cg(Th, Vdb, Int3#sr{reg=load_vars(Evs, Int3#sr.reg)}, St5),
- Int4 = sr_merge(Baft, Haft), %Merge stack/registers
- Aft = Int4,
- {[{'try',TryReg,{f,H}}] ++ Ais ++
- [{label,B},{try_end,TryReg}] ++ Bis ++
- [{label,H},{try_case,TryReg}] ++ His,
- clear_dead(Aft, Le#l.i, Vdb),
- St6#cg{break=St0#cg.break}}.
-
-%% catch_cg(CatchBlock, Ret, Le, Vdb, Bef, St) -> {[Ainstr],Aft,St}.
-
-catch_cg(#cg_block{es=C}, #k_var{name=R}, Le, Vdb, Bef, St0) ->
- {B,St1} = new_label(St0),
- CatchTag = Le#l.i,
- Int1 = Bef#sr{stk=put_catch(CatchTag, Bef#sr.stk)},
- CatchReg = fetch_stack({catch_tag,CatchTag}, Int1#sr.stk),
- {Cis,Int2,St2} = cg_block(C, Le#l.vdb, Int1,
- St1#cg{break=B,in_catch=true}),
- [] = Int2#sr.reg, %Assertion.
- Aft = Int2#sr{reg=[{0,R}],stk=drop_catch(CatchTag, Int2#sr.stk)},
- {[{'catch',CatchReg,{f,B}}] ++ Cis ++
- [{label,B},{catch_end,CatchReg}],
- clear_dead(Aft, Le#l.i, Vdb),
- St2#cg{break=St1#cg.break,in_catch=St1#cg.in_catch}}.
-
-%% put_cg([Var], Constr, Le, Vdb, Bef, St) -> {[Ainstr],Aft,St}.
-%% We have to be careful how a 'put' works. First the structure is
-%% built, then it is filled and finally things can be cleared. The
-%% annotation must reflect this and make sure that the return
-%% variable is allocated first.
-%%
-%% put_list and put_map are atomic instructions, both of
-%% which can safely resuse one of the source registers as target.
-
-put_cg([#k_var{name=R}], #k_cons{hd=Hd,tl=Tl}, Le, Vdb, Bef, St) ->
- [S1,S2] = cg_reg_args([Hd,Tl], Bef),
- Int0 = clear_dead(Bef, Le#l.i, Vdb),
- Int1 = Int0#sr{reg=put_reg(R, Int0#sr.reg)},
- Ret = fetch_reg(R, Int1#sr.reg),
- {[{put_list,S1,S2,Ret}], Int1, St};
-put_cg([#k_var{name=R}], #k_binary{segs=Segs}, Le, Vdb, Bef,
- #cg{bfail=Bfail}=St) ->
- %% At run-time, binaries are constructed in three stages:
- %% 1) First the size of the binary is calculated.
- %% 2) Then the binary is allocated.
- %% 3) Then each field in the binary is constructed.
- %% For simplicity, we use the target register to also hold the
- %% size of the binary. Therefore the target register must *not*
- %% be one of the source registers.
-
- %% First allocate the target register.
- Int0 = Bef#sr{reg=put_reg(R, Bef#sr.reg)},
- Target = fetch_reg(R, Int0#sr.reg),
-
- %% Also allocate a scratch register for size calculations.
- Temp = find_scratch_reg(Int0#sr.reg),
-
- %% First generate the code that constructs each field.
- Fail = {f,Bfail},
- PutCode = cg_bin_put(Segs, Fail, Bef),
- {Sis,Int1} = maybe_adjust_stack(Int0, Le#l.i, Le#l.i+1, Vdb, St),
- MaxRegs = max_reg(Bef#sr.reg),
- Aft = clear_dead(Int1, Le#l.i, Vdb),
-
- %% Now generate the complete code for constructing the binary.
- Code = cg_binary(PutCode, Target, Temp, Fail, MaxRegs, Le#l.a),
- {Sis++Code,Aft,St};
-
-%% Map: single variable key.
-put_cg([#k_var{name=R}], #k_map{op=Op,var=Map,
- es=[#k_map_pair{key=#k_var{}=K,val=V}]},
- Le, Vdb, Bef, St0) ->
- {Sis,Int0} = maybe_adjust_stack(Bef, Le#l.i, Le#l.i+1, Vdb, St0),
-
- SrcReg = cg_reg_arg_prefer_y(Map, Int0),
- Line = line(Le#l.a),
-
- List = [cg_reg_arg(K,Int0),cg_reg_arg(V,Int0)],
-
- Live = max_reg(Bef#sr.reg),
-
- %% The target register can reuse one of the source registers.
- Aft0 = clear_dead(Int0, Le#l.i, Vdb),
- Aft = Aft0#sr{reg=put_reg(R, Aft0#sr.reg)},
- Target = fetch_reg(R, Aft#sr.reg),
-
- {Is,St1} = put_cg_map(Line, Op, SrcReg, Target, Live, List, St0),
- {Sis++Is,Aft,St1};
-
-%% Map: (possibly) multiple literal keys.
-put_cg([#k_var{name=R}], #k_map{op=Op,var=Map,es=Es}, Le, Vdb, Bef, St0) ->
-
- %% assert key literals
- [] = [Var || #k_map_pair{key=#k_var{}=Var} <- Es],
-
- {Sis,Int0} = maybe_adjust_stack(Bef, Le#l.i, Le#l.i+1, Vdb, St0),
- SrcReg = cg_reg_arg_prefer_y(Map, Int0),
- Line = line(Le#l.a),
-
- %% fetch registers for values to be put into the map
- List = flatmap(fun(#k_map_pair{key=K,val=V}) ->
- [atomic(K),cg_reg_arg(V, Int0)]
- end, Es),
-
- Live = max_reg(Bef#sr.reg),
-
- %% The target register can reuse one of the source registers.
- Aft0 = clear_dead(Int0, Le#l.i, Vdb),
- Aft = Aft0#sr{reg=put_reg(R, Aft0#sr.reg)},
- Target = fetch_reg(R, Aft#sr.reg),
-
- {Is,St1} = put_cg_map(Line, Op, SrcReg, Target, Live, List, St0),
- {Sis++Is,Aft,St1};
-
-%% Everything else.
-put_cg([#k_var{name=R}], Con, Le, Vdb, Bef, St) ->
- %% Find a place for the return register first.
- Int = Bef#sr{reg=put_reg(R, Bef#sr.reg)},
- Ret = fetch_reg(R, Int#sr.reg),
- Ais = case Con of
- #k_tuple{es=Es} ->
- [{put_tuple,length(Es),Ret}] ++ cg_build_args(Es, Bef);
- Other ->
- [{move,cg_reg_arg(Other, Int),Ret}]
- end,
- {Ais,clear_dead(Int, Le#l.i, Vdb),St}.
-
-
-put_cg_map(Line, Op0, SrcReg, Target, Live, List, St0) ->
- Bfail = St0#cg.bfail,
- Fail = {f,St0#cg.bfail},
- Op = case Op0 of
- assoc -> put_map_assoc;
- exact -> put_map_exact
- end,
- {OkLbl,St1} = new_label(St0),
- {BadLbl,St2} = new_label(St1),
- Is = if
- Bfail =:= 0 orelse Op =:= put_map_assoc ->
- [Line,{Op,{f,0},SrcReg,Target,Live,{list,List}}];
- true ->
- %% Ensure that Target is always set, even if
- %% the map update operation fails. That is necessary
- %% because Target may be included in a test_heap
- %% instruction.
- [Line,
- {Op,{f,BadLbl},SrcReg,Target,Live,{list,List}},
- {jump,{f,OkLbl}},
- {label,BadLbl},
- {move,{atom,ok},Target},
- {jump,Fail},
- {label,OkLbl}]
- end,
- {Is,St2}.
-
-%%%
-%%% Code generation for constructing binaries.
-%%%
-
-cg_binary([{bs_put_binary,Fail,{atom,all},U,_Flags,Src}|PutCode],
- Target, Temp, Fail, MaxRegs, Anno) ->
- Line = line(Anno),
- Live = cg_live(Target, MaxRegs),
- SzCode = cg_bitstr_size(PutCode, Target, Temp, Fail, Live),
- BinFlags = {field_flags,[]},
- Code = [Line|SzCode] ++
- [case member(single_use, Anno) of
- true ->
- {bs_private_append,Fail,Target,U,Src,BinFlags,Target};
- false ->
- {bs_append,Fail,Target,0,MaxRegs,U,Src,BinFlags,Target}
- end] ++ PutCode,
- cg_bin_opt(Code);
-cg_binary(PutCode, Target, Temp, Fail, MaxRegs, Anno) ->
- Line = line(Anno),
- Live = cg_live(Target, MaxRegs),
- {InitOp,SzCode} = cg_binary_size(PutCode, Target, Temp, Fail, Live),
-
- Code = [Line|SzCode] ++ [{InitOp,Fail,Target,0,MaxRegs,
- {field_flags,[]},Target}|PutCode],
- cg_bin_opt(Code).
-
-cg_live({x,X}, MaxRegs) when X =:= MaxRegs -> MaxRegs+1;
-cg_live({x,X}, MaxRegs) when X < MaxRegs -> MaxRegs.
-
-%% Generate code that calculate the size of the bitstr to be
-%% built in BITS.
-
-cg_bitstr_size(PutCode, Target, Temp, Fail, Live) ->
- {Bits,Es} = cg_bitstr_size_1(PutCode, 0, []),
- reverse(cg_gen_binsize(Es, Target, Temp, Fail, Live,
- [{move,{integer,Bits},Target}])).
-
-cg_bitstr_size_1([{bs_put_utf8,_,_,Src}|Next], Bits, Acc) ->
- cg_bitstr_size_1(Next, Bits, [{'*',{bs_utf8_size,Src},8}|Acc]);
-cg_bitstr_size_1([{bs_put_utf16,_,_,Src}|Next], Bits, Acc) ->
- cg_bitstr_size_1(Next, Bits, [{'*',{bs_utf16_size,Src},8}|Acc]);
-cg_bitstr_size_1([{bs_put_utf32,_,_,_}|Next], Bits, Acc) ->
- cg_bitstr_size_1(Next, Bits+32, Acc);
-cg_bitstr_size_1([{_,_,S,U,_,Src}|Next], Bits, Acc) ->
- case S of
- {integer,N} -> cg_bitstr_size_1(Next, Bits+N*U, Acc);
- {atom,all} -> cg_bitstr_size_1(Next, Bits, [{bit_size,Src}|Acc]);
- _ when U =:= 1 -> cg_bitstr_size_1(Next, Bits, [S|Acc]);
- _ -> cg_bitstr_size_1(Next, Bits, [{'*',S,U}|Acc])
- end;
-cg_bitstr_size_1([], Bits, Acc) -> {Bits,Acc}.
-
-%% Generate code that calculate the size of the bitstr to be
-%% built in BYTES or BITS (depending on what is easiest).
-
-cg_binary_size(PutCode, Target, Temp, Fail, Live) ->
- {InitInstruction,Szs} = cg_binary_size_1(PutCode, 0, []),
- SizeExpr = reverse(cg_gen_binsize(Szs, Target, Temp, Fail, Live, [{move,{integer,0},Target}])),
- {InitInstruction,SizeExpr}.
-
-cg_binary_size_1([{bs_put_utf8,_Fail,_Flags,Src}|T], Bits, Acc) ->
- cg_binary_size_1(T, Bits, [{8,{bs_utf8_size,Src}}|Acc]);
-cg_binary_size_1([{bs_put_utf16,_Fail,_Flags,Src}|T], Bits, Acc) ->
- cg_binary_size_1(T, Bits, [{8,{bs_utf16_size,Src}}|Acc]);
-cg_binary_size_1([{bs_put_utf32,_Fail,_Flags,_Src}|T], Bits, Acc) ->
- cg_binary_size_1(T, Bits+32, Acc);
-cg_binary_size_1([{_Put,_Fail,S,U,_Flags,Src}|T], Bits, Acc) ->
- cg_binary_size_2(S, U, Src, T, Bits, Acc);
-cg_binary_size_1([], Bits, Acc) ->
- Bytes = Bits div 8,
- RemBits = Bits rem 8,
- Sizes0 = sort([{1,{integer,RemBits}},{8,{integer,Bytes}}|Acc]),
- Sizes = filter(fun({_,{integer,0}}) -> false;
- (_) -> true end, Sizes0),
- case Sizes of
- [{1,_}|_] ->
- {bs_init_bits,cg_binary_bytes_to_bits(Sizes, [])};
- [{8,_}|_] ->
- {bs_init2,[E || {8,E} <- Sizes]};
- [] ->
- {bs_init_bits,[]}
- end.
-
-cg_binary_size_2({integer,N}, U, _, Next, Bits, Acc) ->
- cg_binary_size_1(Next, Bits+N*U, Acc);
-cg_binary_size_2({atom,all}, U, E, Next, Bits, Acc) ->
- if
- U rem 8 =:= 0 ->
- cg_binary_size_1(Next, Bits, [{8,{byte_size,E}}|Acc]);
- true ->
- cg_binary_size_1(Next, Bits, [{1,{bit_size,E}}|Acc])
- end;
-cg_binary_size_2(Reg, 1, _, Next, Bits, Acc) ->
- cg_binary_size_1(Next, Bits, [{1,Reg}|Acc]);
-cg_binary_size_2(Reg, 8, _, Next, Bits, Acc) ->
- cg_binary_size_1(Next, Bits, [{8,Reg}|Acc]);
-cg_binary_size_2(Reg, U, _, Next, Bits, Acc) ->
- cg_binary_size_1(Next, Bits, [{1,{'*',Reg,U}}|Acc]).
-
-cg_binary_bytes_to_bits([{8,{integer,N}}|T], Acc) ->
- cg_binary_bytes_to_bits(T, [{integer,8*N}|Acc]);
-cg_binary_bytes_to_bits([{8,{byte_size,Reg}}|T], Acc) ->
- cg_binary_bytes_to_bits(T, [{bit_size,Reg}|Acc]);
-cg_binary_bytes_to_bits([{8,Reg}|T], Acc) ->
- cg_binary_bytes_to_bits(T, [{'*',Reg,8}|Acc]);
-cg_binary_bytes_to_bits([{1,Sz}|T], Acc) ->
- cg_binary_bytes_to_bits(T, [Sz|Acc]);
-cg_binary_bytes_to_bits([], Acc) ->
- cg_binary_bytes_to_bits_1(sort(Acc)).
-
-cg_binary_bytes_to_bits_1([{integer,I},{integer,J}|T]) ->
- cg_binary_bytes_to_bits_1([{integer,I+J}|T]);
-cg_binary_bytes_to_bits_1([H|T]) ->
- [H|cg_binary_bytes_to_bits_1(T)];
-cg_binary_bytes_to_bits_1([]) -> [].
-
-cg_gen_binsize([{'*',{bs_utf8_size,Src},B}|T], Target, Temp, Fail, Live, Acc) ->
- Size = {bs_utf8_size,Fail,Src,Temp},
- Add = {bs_add,Fail,[Target,Temp,B],Target},
- cg_gen_binsize(T, Target, Temp, Fail, Live,
- [Add,Size|Acc]);
-cg_gen_binsize([{'*',{bs_utf16_size,Src},B}|T], Target, Temp, Fail, Live, Acc) ->
- Size = {bs_utf16_size,Fail,Src,Temp},
- Add = {bs_add,Fail,[Target,Temp,B],Target},
- cg_gen_binsize(T, Target, Temp, Fail, Live,
- [Add,Size|Acc]);
-cg_gen_binsize([{'*',A,B}|T], Target, Temp, Fail, Live, Acc) ->
- cg_gen_binsize(T, Target, Temp, Fail, Live,
- [{bs_add,Fail,[Target,A,B],Target}|Acc]);
-cg_gen_binsize([{bit_size,B}|T], Target, Temp, Fail, Live, Acc) ->
- cg_gen_binsize([Temp|T], Target, Temp, Fail, Live,
- [{gc_bif,bit_size,Fail,Live,[B],Temp}|Acc]);
-cg_gen_binsize([{byte_size,B}|T], Target, Temp, Fail, Live, Acc) ->
- cg_gen_binsize([Temp|T], Target, Temp, Fail, Live,
- [{gc_bif,byte_size,Fail,Live,[B],Temp}|Acc]);
-cg_gen_binsize([{bs_utf8_size,B}|T], Target, Temp, Fail, Live, Acc) ->
- cg_gen_binsize([Temp|T], Target, Temp, Fail, Live,
- [{bs_utf8_size,Fail,B,Temp}|Acc]);
-cg_gen_binsize([{bs_utf16_size,B}|T], Target, Temp, Fail, Live, Acc) ->
- cg_gen_binsize([Temp|T], Target, Temp, Fail, Live,
- [{bs_utf16_size,Fail,B,Temp}|Acc]);
-cg_gen_binsize([E0|T], Target, Temp, Fail, Live, Acc) ->
- cg_gen_binsize(T, Target, Temp, Fail, Live,
- [{bs_add,Fail,[Target,E0,1],Target}|Acc]);
-cg_gen_binsize([], _, _, _, _, Acc) -> Acc.
-
-
-%% cg_bin_opt(Code0) -> Code
-%% Optimize the size calculations for binary construction.
-
-cg_bin_opt([{move,S1,{x,X}=D},{gc_bif,Op,Fail,Live0,As,Dst}|Is]) ->
- Live = if
- X + 1 =:= Live0 -> X;
- true -> Live0
- end,
- [{gc_bif,Op,Fail,Live,As,D}|cg_bin_opt([{move,S1,Dst}|Is])];
-cg_bin_opt([{move,_,_}=I1,{Op,_,_,_}=I2|Is])
- when Op =:= bs_utf8_size orelse Op =:= bs_utf16_size ->
- [I2|cg_bin_opt([I1|Is])];
-cg_bin_opt([{bs_add,_,[{integer,0},Src,1],Dst}|Is]) ->
- cg_bin_opt_1([{move,Src,Dst}|Is]);
-cg_bin_opt([{bs_add,_,[Src,{integer,0},_],Dst}|Is]) ->
- cg_bin_opt_1([{move,Src,Dst}|Is]);
-cg_bin_opt(Is) ->
- cg_bin_opt_1(Is).
-
-cg_bin_opt_1([{move,Size,D},{bs_append,Fail,D,Extra,Regs,U,Bin,Flags,D}|Is]) ->
- [{bs_append,Fail,Size,Extra,Regs,U,Bin,Flags,D}|cg_bin_opt(Is)];
-cg_bin_opt_1([{move,Size,D},{bs_private_append,Fail,D,U,Bin,Flags,D}|Is]) ->
- [{bs_private_append,Fail,Size,U,Bin,Flags,D}|cg_bin_opt(Is)];
-cg_bin_opt_1([{move,Size,D},{Op,Fail,D,Extra,Regs,Flags,D}|Is])
- when Op =:= bs_init2; Op =:= bs_init_bits ->
- Bytes = case Size of
- {integer,Int} -> Int;
- _ -> Size
- end,
- [{Op,Fail,Bytes,Extra,Regs,Flags,D}|cg_bin_opt(Is)];
-cg_bin_opt_1([{move,S1,D},{bs_add,Fail,[D,S2,U],Dst}|Is]) ->
- cg_bin_opt([{bs_add,Fail,[S1,S2,U],Dst}|Is]);
-cg_bin_opt_1([{move,S1,D},{bs_add,Fail,[S2,D,U],Dst}|Is]) ->
- cg_bin_opt([{bs_add,Fail,[S2,S1,U],Dst}|Is]);
-cg_bin_opt_1([I|Is]) ->
- [I|cg_bin_opt(Is)];
-cg_bin_opt_1([]) ->
- [].
-
-cg_bin_put(#k_bin_seg{size=S0,unit=U,type=T,flags=Fs,seg=E0,next=Next},
- Fail, Bef) ->
- S1 = cg_reg_arg(S0, Bef),
- E1 = cg_reg_arg(E0, Bef),
- {Format,Op} = case T of
- integer -> {plain,bs_put_integer};
- utf8 -> {utf,bs_put_utf8};
- utf16 -> {utf,bs_put_utf16};
- utf32 -> {utf,bs_put_utf32};
- binary -> {plain,bs_put_binary};
- float -> {plain,bs_put_float}
- end,
- case Format of
- plain ->
- [{Op,Fail,S1,U,{field_flags,Fs},E1}|cg_bin_put(Next, Fail, Bef)];
- utf ->
- [{Op,Fail,{field_flags,Fs},E1}|cg_bin_put(Next, Fail, Bef)]
- end;
-cg_bin_put(#k_bin_end{}, _, _) -> [].
-
-cg_build_args(As, Bef) ->
- [{put,cg_reg_arg(A, Bef)} || A <- As].
-
-%% return_cg([Val], Le, Vdb, Bef, St) -> {[Ainstr],Aft,St}.
-%% break_cg([Val], Le, Vdb, Bef, St) -> {[Ainstr],Aft,St}.
-%% These are very simple, just put return/break values in registers
-%% from 0, then return/break. Use the call setup to clean up stack,
-%% but must clear registers to ensure sr_merge works correctly.
-
-return_cg(Rs, Le, Vdb, Bef, St) ->
- {Ms,Int} = cg_setup_call(Rs, Bef, Le#l.i, Vdb),
- {Ms ++ [return],Int#sr{reg=clear_regs(Int#sr.reg)},St}.
-
-break_cg(Bs, Le, Vdb, Bef, St) ->
- {Ms,Int} = cg_setup_call(Bs, Bef, Le#l.i, Vdb),
- {Ms ++ [{jump,{f,St#cg.break}}],
- Int#sr{reg=clear_regs(Int#sr.reg)},St}.
-
-guard_break_cg(Bs, #l{i=I}, Vdb, #sr{reg=Reg0}=Bef, St) ->
- #sr{reg=Reg1} = Int = clear_dead(Bef, I, Vdb),
- Reg2 = trim_free(Reg1),
- NumLocked = length(Reg2),
- Moves0 = gen_moves(Bs, Bef, NumLocked, []),
- Moves = order_moves(Moves0, find_scratch_reg(Reg0)),
- {BreakVars,_} = mapfoldl(fun(_, RegNum) ->
- {{RegNum,gbreakvar},RegNum+1}
- end, length(Reg2), Bs),
- Reg = Reg2 ++ BreakVars,
- Aft = Int#sr{reg=Reg},
- {Moves ++ [{jump,{f,St#cg.break}}],Aft,St}.
-
-%% cg_reg_arg(Arg0, Info) -> Arg
-%% cg_reg_args([Arg0], Info) -> [Arg]
-%% Convert argument[s] into registers. Literal values are returned unchanged.
-
-cg_reg_args(As, Bef) -> [cg_reg_arg(A, Bef) || A <- As].
-
-cg_reg_arg(#k_var{name=V}, Bef) -> fetch_var(V, Bef);
-cg_reg_arg(Literal, _) -> atomic(Literal).
-
-cg_reg_arg_prefer_y(#k_var{name=V}, Bef) -> fetch_var_prefer_y(V, Bef);
-cg_reg_arg_prefer_y(Literal, _) -> atomic(Literal).
-
-%% cg_setup_call([Arg], Bef, Cur, Vdb) -> {[Instr],Aft}.
-%% Do the complete setup for a call/enter.
-
-cg_setup_call(As, Bef, I, Vdb) ->
- {Ms,Int0} = cg_call_args(As, Bef, I, Vdb),
- %% Have set up arguments, can now clean up, compress and save to stack.
- Int1 = Int0#sr{stk=clear_dead_stk(Int0#sr.stk, I, Vdb),res=[]},
- {Sis,Int2} = adjust_stack(Int1, I, I+1, Vdb),
- {Ms ++ Sis,Int2}.
-
-%% cg_call_args([Arg], SrState) -> {[Instr],SrState}.
-%% Setup the arguments to a call/enter/bif. Put the arguments into
-%% consecutive registers starting at {x,0} moving any data which
-%% needs to be saved. Return a modified SrState structure with the
-%% new register contents. N.B. the resultant register info will
-%% contain non-variable values when there are non-variable values.
-%%
-%% This routine is complicated by unsaved values in x registers.
-%% We'll move away any unsaved values that are in the registers
-%% to be overwritten by the arguments.
-
-cg_call_args(As, Bef, I, Vdb) ->
- Regs0 = load_arg_regs(Bef#sr.reg, As),
- Unsaved = unsaved_registers(Regs0, Bef#sr.stk, I, I+1, Vdb),
- {UnsavedMoves,Regs} = move_unsaved(Unsaved, Bef#sr.reg, Regs0),
- Moves0 = gen_moves(As, Bef),
- Moves = order_moves(Moves0, find_scratch_reg(Regs)),
- {UnsavedMoves ++ Moves,Bef#sr{reg=Regs}}.
-
-%% load_arg_regs([Reg], Arguments) -> [Reg]
-%% Update the register descriptor to include the arguments (from {x,0}
-%% and upwards). Values in argument register are overwritten.
-%% Values in x registers above the arguments are preserved.
-
-load_arg_regs(Regs, As) -> load_arg_regs(Regs, As, 0).
-
-load_arg_regs([_|Rs], [#k_var{name=V}|As], I) -> [{I,V}|load_arg_regs(Rs, As, I+1)];
-load_arg_regs([_|Rs], [A|As], I) -> [{I,A}|load_arg_regs(Rs, As, I+1)];
-load_arg_regs([], [#k_var{name=V}|As], I) -> [{I,V}|load_arg_regs([], As, I+1)];
-load_arg_regs([], [A|As], I) -> [{I,A}|load_arg_regs([], As, I+1)];
-load_arg_regs(Rs, [], _) -> Rs.
-
-%% Returns the variables must be saved and are currently in the
-%% x registers that are about to be overwritten by the arguments.
-
-unsaved_registers(Regs, Stk, Fb, Lf, Vdb) ->
- [V || {V,F,L} <- Vdb,
- F < Fb,
- L >= Lf,
- not on_stack(V, Stk),
- not in_reg(V, Regs)].
-
-in_reg(V, Regs) -> keymember(V, 2, Regs).
-
-%% Move away unsaved variables from the registers that are to be
-%% overwritten by the arguments.
-move_unsaved(Vs, OrigRegs, NewRegs) ->
- move_unsaved(Vs, OrigRegs, NewRegs, []).
-
-move_unsaved([V|Vs], OrigRegs, NewRegs0, Acc) ->
- NewRegs = put_reg(V, NewRegs0),
- Src = fetch_reg(V, OrigRegs),
- Dst = fetch_reg(V, NewRegs),
- move_unsaved(Vs, OrigRegs, NewRegs, [{move,Src,Dst}|Acc]);
-move_unsaved([], _, Regs, Acc) -> {Acc,Regs}.
-
-%% gen_moves(As, Sr)
-%% Generate the basic move instruction to move the arguments
-%% to their proper registers. The list will be sorted on
-%% destinations. (I.e. the move to {x,0} will be first --
-%% see the comment to order_moves/2.)
-
-gen_moves(As, Sr) -> gen_moves(As, Sr, 0, []).
-
-gen_moves([#k_var{name=V}|As], Sr, I, Acc) ->
- case fetch_var(V, Sr) of
- {x,I} -> gen_moves(As, Sr, I+1, Acc);
- Reg -> gen_moves(As, Sr, I+1, [{move,Reg,{x,I}}|Acc])
- end;
-gen_moves([A0|As], Sr, I, Acc) ->
- A = atomic(A0),
- gen_moves(As, Sr, I+1, [{move,A,{x,I}}|Acc]);
-gen_moves([], _, _, Acc) -> lists:keysort(3, Acc).
-
-%% order_moves([Move], ScratchReg) -> [Move]
-%% Orders move instruction so that source registers are not
-%% destroyed before they are used. If there are cycles
-%% (such as {move,{x,0},{x,1}}, {move,{x,1},{x,1}}),
-%% the scratch register is used to break up the cycle.
-%% If possible, the first move of the input list is placed
-%% last in the result list (to make the move to {x,0} occur
-%% just before the call to allow the Beam loader to coalesce
-%% the instructions).
-
-order_moves(Ms, Scr) -> order_moves(Ms, Scr, []).
-
-order_moves([{move,_,_}=M|Ms0], ScrReg, Acc0) ->
- {Chain,Ms} = collect_chain(Ms0, [M], ScrReg),
- Acc = reverse(Chain, Acc0),
- order_moves(Ms, ScrReg, Acc);
-order_moves([], _, Acc) -> Acc.
-
-collect_chain(Ms, Path, ScrReg) ->
- collect_chain(Ms, Path, [], ScrReg).
-
-collect_chain([{move,Src,Same}=M|Ms0], [{move,Same,_}|_]=Path, Others, ScrReg) ->
- case lists:keyfind(Src, 3, Path) of
- false ->
- collect_chain(reverse(Others, Ms0), [M|Path], [], ScrReg);
- _ -> % We have a cycle.
- {break_up_cycle(M, Path, ScrReg),reverse(Others, Ms0)}
- end;
-collect_chain([M|Ms], Path, Others, ScrReg) ->
- collect_chain(Ms, Path, [M|Others], ScrReg);
-collect_chain([], Path, Others, _) ->
- {Path,Others}.
-
-break_up_cycle({move,Src,_}=M, Path, ScrReg) ->
- [{move,ScrReg,Src},M|break_up_cycle1(Src, Path, ScrReg)].
-
-break_up_cycle1(Dst, [{move,Src,Dst}|Path], ScrReg) ->
- [{move,Src,ScrReg}|Path];
-break_up_cycle1(Dst, [M|Path], LastMove) ->
- [M|break_up_cycle1(Dst, Path, LastMove)].
-
-%% clear_dead(Sr, Until, Vdb) -> Aft.
-%% Remove all variables in Sr which have died AT ALL so far.
-
-clear_dead(#sr{stk=Stk}=Sr0, Until, Vdb) ->
- Sr = Sr0#sr{reg=clear_dead_reg(Sr0, Until, Vdb),
- stk=clear_dead_stk(Stk, Until, Vdb)},
- reserve(Sr).
-
-clear_dead_reg(Sr, Until, Vdb) ->
- [case R of
- {_I,V} = IV ->
- case vdb_find(V, Vdb) of
- {V,_,L} when L > Until -> IV;
- _ -> free %Remove anything else
- end;
- {reserved,_I,_V}=Reserved -> Reserved;
- free -> free
- end || R <- Sr#sr.reg].
-
-clear_dead_stk(Stk, Until, Vdb) ->
- [case S of
- {V} = T ->
- case vdb_find(V, Vdb) of
- {V,_,L} when L > Until -> T;
- _ -> dead %Remove anything else
- end;
- free -> free;
- dead -> dead
- end || S <- Stk].
-
-
-%% sr_merge(Sr1, Sr2) -> Sr.
-%% Merge two stack/register states keeping the longest of both stack
-%% and register. Perform consistency check on both, elements must be
-%% the same. Allow frame size 'void' to make easy creation of
-%% "empty" frame.
-
-sr_merge(#sr{reg=R1,stk=S1,res=[]}, #sr{reg=R2,stk=S2,res=[]}) ->
- #sr{reg=longest(R1, R2),stk=longest(S1, S2),res=[]};
-sr_merge(void, S2) -> S2#sr{res=[]}.
-
-longest([H|T1], [H|T2]) -> [H|longest(T1, T2)];
-longest([dead|T1], [free|T2]) -> [dead|longest(T1, T2)];
-longest([free|T1], [dead|T2]) -> [dead|longest(T1, T2)];
-longest([dead|_] = L, []) -> L;
-longest([], [dead|_] = L) -> L;
-longest([free|_] = L, []) -> L;
-longest([], [free|_] = L) -> L;
-longest([], []) -> [].
-
-trim_free([R|Rs0]) ->
- case {trim_free(Rs0),R} of
- {[],free} -> [];
- {Rs,R} -> [R|Rs]
- end;
-trim_free([]) -> [].
-
-%% maybe_adjust_stack(Bef, FirstBefore, LastFrom, Vdb, St) -> {[Ainstr],Aft}.
-%% Adjust the stack, but only if the code is inside a catch and not
-%% inside a guard. Use this funtion before instructions that may
-%% cause an exception.
-
-maybe_adjust_stack(Bef, Fb, Lf, Vdb, St) ->
- case St of
- #cg{in_catch=true,bfail=0} ->
- adjust_stack(Bef, Fb, Lf, Vdb);
- #cg{} ->
- {[],Bef}
- end.
-
-%% adjust_stack(Bef, FirstBefore, LastFrom, Vdb) -> {[Ainstr],Aft}.
-%% Do complete stack adjustment by compressing stack and adding
-%% variables to be saved. Try to optimise ordering on stack by
-%% having reverse order to their lifetimes.
-%%
-%% In Beam, there is a fixed stack frame and no need to do stack compression.
-
-adjust_stack(Bef, Fb, Lf, Vdb) ->
- Stk0 = Bef#sr.stk,
- {Stk1,Saves} = save_stack(Stk0, Fb, Lf, Vdb),
- {saves(Saves, Bef#sr.reg, Stk1),
- Bef#sr{stk=Stk1}}.
-
-%% save_stack(Stack, FirstBefore, LastFrom, Vdb) -> {[SaveVar],NewStack}.
-%% Save variables which are used past current point and which are not
-%% already on the stack.
-
-save_stack(Stk0, Fb, Lf, Vdb) ->
- %% New variables that are in use but not on stack.
- New = new_not_on_stack(Stk0, Fb, Lf, Vdb),
-
- %% Add new variables that are not just dropped immediately.
- %% N.B. foldr works backwards from the end!!
- Saves = [V || {V,_,_} <- keysort(3, New)],
- Stk1 = foldr(fun (V, Stk) -> put_stack(V, Stk) end, Stk0, Saves),
- {Stk1,Saves}.
-
-%% new_not_on_stack(Stack, FirstBefore, LastFrom, Vdb) ->
-%% [{Variable,First,Last}]
-%% Return information about all variables that are used past current
-%% point and that are not already on the stack.
-
-new_not_on_stack(Stk, Fb, Lf, Vdb) ->
- [VFL || {V,F,L} = VFL <- Vdb,
- F < Fb,
- L >= Lf,
- not on_stack(V, Stk)].
-
-%% saves([SaveVar], Reg, Stk) -> [{move,Reg,Stk}].
-%% Generate move instructions to save variables onto stack. The
-%% stack/reg info used is that after the new stack has been made.
-
-saves(Ss, Reg, Stk) ->
- [{move,fetch_reg(V, Reg),fetch_stack(V, Stk)} || V <- Ss].
-
-%% fetch_var(VarName, StkReg) -> r{R} | sp{Sp}.
-%% find_var(VarName, StkReg) -> ok{r{R} | sp{Sp}} | error.
-%% Fetch/find a variable in either the registers or on the
-%% stack. Fetch KNOWS it's there.
-
-fetch_var(V, Sr) ->
- case find_reg(V, Sr#sr.reg) of
- {ok,R} -> R;
- error -> fetch_stack(V, Sr#sr.stk)
- end.
-
-fetch_var_prefer_y(V, #sr{reg=Reg,stk=Stk}) ->
- case find_stack(V, Stk) of
- {ok,R} -> R;
- error -> fetch_reg(V, Reg)
- end.
-
-load_vars(Vs, Regs) ->
- foldl(fun (#k_var{name=V}, Rs) -> put_reg(V, Rs) end, Regs, Vs).
-
-%% put_reg(Val, Regs) -> Regs.
-%% find_reg(Val, Regs) -> {ok,r{R}} | error.
-%% fetch_reg(Val, Regs) -> r{R}.
-%% Functions to interface the registers.
-
-% put_regs(Vs, Rs) -> foldl(fun put_reg/2, Rs, Vs).
-
-put_reg(V, Rs) -> put_reg_1(V, Rs, 0).
-
-put_reg_1(V, [free|Rs], I) -> [{I,V}|Rs];
-put_reg_1(V, [{reserved,I,V}|Rs], I) -> [{I,V}|Rs];
-put_reg_1(V, [R|Rs], I) -> [R|put_reg_1(V, Rs, I+1)];
-put_reg_1(V, [], I) -> [{I,V}].
-
-fetch_reg(V, [{I,V}|_]) -> {x,I};
-fetch_reg(V, [_|SRs]) -> fetch_reg(V, SRs).
-
-find_reg(V, [{I,V}|_]) -> {ok,{x,I}};
-find_reg(V, [_|SRs]) -> find_reg(V, SRs);
-find_reg(_, []) -> error.
-
-%% For the bit syntax, we need a scratch register if we are constructing
-%% a binary that will not be used.
-
-find_scratch_reg(Rs) -> find_scratch_reg(Rs, 0).
-
-find_scratch_reg([free|_], I) -> {x,I};
-find_scratch_reg([_|Rs], I) -> find_scratch_reg(Rs, I+1);
-find_scratch_reg([], I) -> {x,I}.
-
-replace_reg_contents(Old, New, [{I,Old}|Rs]) -> [{I,New}|Rs];
-replace_reg_contents(Old, New, [R|Rs]) -> [R|replace_reg_contents(Old, New, Rs)].
-
-%%clear_regs(Regs) -> map(fun (R) -> free end, Regs).
-clear_regs(_) -> [].
-
-max_reg(Regs) ->
- foldl(fun ({I,_}, _) -> I;
- (_, Max) -> Max end,
- -1, Regs) + 1.
-
-%% put_stack(Val, [{Val}]) -> [{Val}].
-%% fetch_stack(Var, Stk) -> sp{S}.
-%% find_stack(Var, Stk) -> ok{sp{S}} | error.
-%% Functions to interface the stack.
-
-put_stack(Val, []) -> [{Val}];
-put_stack(Val, [dead|Stk]) -> [{Val}|Stk];
-put_stack(Val, [free|Stk]) -> [{Val}|Stk];
-put_stack(Val, [NotFree|Stk]) -> [NotFree|put_stack(Val, Stk)].
-
-put_stack_carefully(Val, Stk0) ->
- try
- put_stack_carefully1(Val, Stk0)
- catch
- throw:error ->
- error
- end.
-
-put_stack_carefully1(_, []) -> throw(error);
-put_stack_carefully1(Val, [dead|Stk]) -> [{Val}|Stk];
-put_stack_carefully1(Val, [free|Stk]) -> [{Val}|Stk];
-put_stack_carefully1(Val, [NotFree|Stk]) ->
- [NotFree|put_stack_carefully1(Val, Stk)].
-
-fetch_stack(Var, Stk) -> fetch_stack(Var, Stk, 0).
-
-fetch_stack(V, [{V}|_], I) -> {yy,I};
-fetch_stack(V, [_|Stk], I) -> fetch_stack(V, Stk, I+1).
-
-find_stack(Var, Stk) -> find_stack(Var, Stk, 0).
-
-find_stack(V, [{V}|_], I) -> {ok,{yy,I}};
-find_stack(V, [_|Stk], I) -> find_stack(V, Stk, I+1);
-find_stack(_, [], _) -> error.
-
-on_stack(V, Stk) -> keymember(V, 1, Stk).
-
-%% put_catch(CatchTag, Stack) -> Stack'
-%% drop_catch(CatchTag, Stack) -> Stack'
-%% Special interface for putting and removing catch tags, to ensure that
-%% catches nest properly. Also used for try tags.
-
-put_catch(Tag, Stk0) -> put_catch(Tag, reverse(Stk0), []).
-
-put_catch(Tag, [], Stk) ->
- put_stack({catch_tag,Tag}, Stk);
-put_catch(Tag, [{{catch_tag,_}}|_]=RevStk, Stk) ->
- reverse(RevStk, put_stack({catch_tag,Tag}, Stk));
-put_catch(Tag, [Other|Stk], Acc) ->
- put_catch(Tag, Stk, [Other|Acc]).
-
-drop_catch(Tag, [{{catch_tag,Tag}}|Stk]) -> [free|Stk];
-drop_catch(Tag, [Other|Stk]) -> [Other|drop_catch(Tag, Stk)].
-
-%% atomic(Klit) -> Lit.
-%% atomic_list([Klit]) -> [Lit].
-
-atomic(#k_literal{val=V}) -> {literal,V};
-atomic(#k_int{val=I}) -> {integer,I};
-atomic(#k_float{val=F}) -> {float,F};
-atomic(#k_atom{val=A}) -> {atom,A};
-%%atomic(#k_char{val=C}) -> {char,C};
-atomic(#k_nil{}) -> nil.
-
-%% new_label(St) -> {L,St}.
-
-new_label(#cg{lcount=Next}=St) ->
- {Next,St#cg{lcount=Next+1}}.
-
-%% line(Le) -> {line,[] | {location,File,Line}}
-%% Create a line instruction, containing information about
-%% the current filename and line number. A line information
-%% instruction should be placed before any operation that could
-%% cause an exception.
-
-line(#l{a=Anno}) ->
- line(Anno);
-line([Line,{file,Name}]) when is_integer(Line) ->
- line_1(Name, Line);
-line([_|_]=A) ->
- {Name,Line} = find_loc(A, no_file, 0),
- line_1(Name, Line);
-line([]) ->
- {line,[]}.
-
-line_1(no_file, _) ->
- {line,[]};
-line_1(_, 0) ->
- %% Missing line number or line number 0.
- {line,[]};
-line_1(Name, Line) ->
- {line,[{location,Name,Line}]}.
-
-find_loc([Line|T], File, _) when is_integer(Line) ->
- find_loc(T, File, Line);
-find_loc([{file,File}|T], _, Line) ->
- find_loc(T, File, Line);
-find_loc([_|T], File, Line) ->
- find_loc(T, File, Line);
-find_loc([], File, Line) -> {File,Line}.
-
-flatmapfoldl(F, Accu0, [Hd|Tail]) ->
- {R,Accu1} = F(Hd, Accu0),
- {Rs,Accu2} = flatmapfoldl(F, Accu1, Tail),
- {R++Rs,Accu2};
-flatmapfoldl(_, Accu, []) -> {[],Accu}.
-
-%% Keep track of life time for variables.
-%%
-%% init_vars([{var,VarName}]) -> Vdb.
-%% new_vars([VarName], I, Vdb) -> Vdb.
-%% use_vars([VarName], I, Vdb) -> Vdb.
-%% add_var(VarName, F, L, Vdb) -> Vdb.
-%%
-%% The list of variable names for new_vars/3 and use_vars/3
-%% must be sorted.
-
-init_vars(Vs) ->
- vdb_new(Vs).
-
-new_vars([], _, Vdb) -> Vdb;
-new_vars([V], I, Vdb) -> vdb_store_new(V, {V,I,I}, Vdb);
-new_vars(Vs, I, Vdb) -> vdb_update_vars(Vs, Vdb, I).
-
-use_vars([], _, Vdb) ->
- Vdb;
-use_vars([V], I, Vdb) ->
- case vdb_find(V, Vdb) of
- {V,F,L} when I > L -> vdb_update(V, {V,F,I}, Vdb);
- {V,_,_} -> Vdb;
- error -> vdb_store_new(V, {V,I,I}, Vdb)
- end;
-use_vars(Vs, I, Vdb) -> vdb_update_vars(Vs, Vdb, I).
-
-add_var(V, F, L, Vdb) ->
- vdb_store_new(V, {V,F,L}, Vdb).
-
-%% vdb
-
-vdb_new(Vs) ->
- ordsets:from_list([{V,0,0} || #k_var{name=V} <- Vs]).
-
--type var() :: atom().
-
--spec vdb_find(var(), [vdb_entry()]) -> 'error' | vdb_entry().
-
-vdb_find(V, Vdb) ->
- case lists:keyfind(V, 1, Vdb) of
- false -> error;
- Vd -> Vd
- end.
-
-vdb_update(V, Update, [{V,_,_}|Vdb]) ->
- [Update|Vdb];
-vdb_update(V, Update, [Vd|Vdb]) ->
- [Vd|vdb_update(V, Update, Vdb)].
-
-vdb_store_new(V, New, [{V1,_,_}=Vd|Vdb]) when V > V1 ->
- [Vd|vdb_store_new(V, New, Vdb)];
-vdb_store_new(V, New, [{V1,_,_}|_]=Vdb) when V < V1 ->
- [New|Vdb];
-vdb_store_new(_, New, []) -> [New].
-
-vdb_update_vars([V|_]=Vs, [{V1,_,_}=Vd|Vdb], I) when V > V1 ->
- [Vd|vdb_update_vars(Vs, Vdb, I)];
-vdb_update_vars([V|Vs], [{V1,_,_}|_]=Vdb, I) when V < V1 ->
- %% New variable.
- [{V,I,I}|vdb_update_vars(Vs, Vdb, I)];
-vdb_update_vars([V|Vs], [{_,F,L}=Vd|Vdb], I) ->
- %% Existing variable.
- if
- I > L -> [{V,F,I}|vdb_update_vars(Vs, Vdb, I)];
- true -> [Vd|vdb_update_vars(Vs, Vdb, I)]
- end;
-vdb_update_vars([V|Vs], [], I) ->
- %% New variable.
- [{V,I,I}|vdb_update_vars(Vs, [], I)];
-vdb_update_vars([], Vdb, _) -> Vdb.
-
-%% vdb_sub(Min, Max, Vdb) -> Vdb.
-%% Extract variables which are used before and after Min. Lock
-%% variables alive after Max.
-
-vdb_sub(Min, Max, Vdb) ->
- [ if L >= Max -> {V,F,locked};
- true -> Vd
- end || {V,F,L}=Vd <- Vdb,
- F < Min,
- L >= Min ].
diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl
index 3b746ab5bf..45e0ed5088 100644
--- a/lib/compiler/src/v3_core.erl
+++ b/lib/compiler/src/v3_core.erl
@@ -228,7 +228,8 @@ function({function,_,Name,Arity,Cs0}, Ws0, File, Opts) ->
body(Cs0, Name, Arity, St0) ->
Anno = lineno_anno(element(2, hd(Cs0)), St0),
- {Args,St1} = new_vars(Anno, Arity, St0),
+ {Args0,St1} = new_vars(Anno, Arity, St0),
+ Args = reverse(Args0), %Nicer order
case clauses(Cs0, St1) of
{Cs1,[],St2} ->
{Ps,St3} = new_vars(Arity, St2), %Need new variables here
@@ -328,14 +329,16 @@ gexpr({protect,Line,Arg}, Bools0, St0) ->
Anno = lineno_anno(Line, St),
{#iprotect{anno=#a{anno=Anno},body=Eps++[E]},[],Bools0,St}
end;
-gexpr({op,L,'andalso',E1,E2}, Bools, St0) ->
+gexpr({op,_,'andalso',_,_}=E0, Bools, St0) ->
+ {op,L,'andalso',E1,E2} = right_assoc(E0, 'andalso', St0),
Anno = lineno_anno(L, St0),
{#c_var{name=V0},St} = new_var(Anno, St0),
V = {var,L,V0},
False = {atom,L,false},
E = make_bool_switch_guard(L, E1, V, E2, False),
gexpr(E, Bools, St);
-gexpr({op,L,'orelse',E1,E2}, Bools, St0) ->
+gexpr({op,_,'orelse',_,_}=E0, Bools, St0) ->
+ {op,L,'orelse',E1,E2} = right_assoc(E0, 'orelse', St0),
Anno = lineno_anno(L, St0),
{#c_var{name=V0},St} = new_var(Anno, St0),
V = {var,L,V0},
@@ -2054,6 +2057,19 @@ fail_clause(Pats, Anno, Arg) ->
body=[#iprimop{anno=#a{anno=Anno},name=#c_literal{val=match_fail},
args=[Arg]}]}.
+%% Optimization for Dialyzer.
+right_assoc(E, Op, St) ->
+ case member(dialyzer, St#core.opts) of
+ true ->
+ right_assoc2(E, Op);
+ false ->
+ E
+ end.
+
+right_assoc2({op,L1,Op,{op,L2,Op,E1,E2},E3}, Op) ->
+ right_assoc2({op,L2,Op,E1,{op,L1,Op,E2,E3}}, Op);
+right_assoc2(E, _Op) -> E.
+
annotate_tuple(A, Es, St) ->
case member(dialyzer, St#core.opts) of
true ->
diff --git a/lib/compiler/src/v3_kernel.erl b/lib/compiler/src/v3_kernel.erl
index aef0b6cc9f..fe8e252e5a 100644
--- a/lib/compiler/src/v3_kernel.erl
+++ b/lib/compiler/src/v3_kernel.erl
@@ -2043,9 +2043,6 @@ get_match(#k_cons{}, St0) ->
get_match(#k_binary{}, St0) ->
{[V]=Mes,St1} = new_vars(1, St0),
{#k_binary{segs=V},Mes,St1};
-get_match(#k_bin_seg{size=#k_atom{val=all},next={k_bin_end,[]}}=Seg, St0) ->
- {[S]=Vars,St1} = new_vars(1, St0),
- {Seg#k_bin_seg{seg=S,next=[]},Vars,St1};
get_match(#k_bin_seg{}=Seg, St0) ->
{[S,N0],St1} = new_vars(2, St0),
N = set_kanno(N0, [no_usage]),
@@ -2073,9 +2070,6 @@ new_clauses(Cs0, U, St) ->
#k_cons{hd=H,tl=T} -> [H,T|As];
#k_tuple{es=Es} -> Es ++ As;
#k_binary{segs=E} -> [E|As];
- #k_bin_seg{size=#k_atom{val=all},
- seg=S,next={k_bin_end,[]}} ->
- [S|As];
#k_bin_seg{seg=S,next=N} ->
[S,N|As];
#k_bin_int{next=N} ->
@@ -2374,9 +2368,10 @@ uexpr(#k_try{anno=A,arg=A0,vars=Vs,body=B0,evars=Evs,handler=H0},
true ->
{[#k_var{name=X}],#k_var{name=X}} = {Vs,B0}, %Assertion.
#k_atom{val=false} = H0, %Assertion.
- {A1,Bu,St1} = uexpr(A0, Br, St0),
+ {Avs,St1} = new_vars(length(Rs0), St0),
+ {A1,Bu,St} = uexpr(A0, {break,Avs}, St1),
{#k_protected{anno=#k{us=Bu,ns=lit_list_vars(Rs0),a=A},
- arg=A1,ret=Rs0},Bu,St1};
+ arg=A1,ret=Rs0,inner=Avs},Bu,St};
false ->
{Avs,St1} = new_vars(length(Vs), St0),
{A1,Au,St2} = ubody(A0, {break,Avs}, St1),
diff --git a/lib/compiler/src/v3_kernel.hrl b/lib/compiler/src/v3_kernel.hrl
index e6f0d3c1f7..e26360a6da 100644
--- a/lib/compiler/src/v3_kernel.hrl
+++ b/lib/compiler/src/v3_kernel.hrl
@@ -66,7 +66,7 @@
-record(k_receive_next, {anno=[]}).
-record(k_try, {anno=[],arg,vars,body,evars,handler,ret=[]}).
-record(k_try_enter, {anno=[],arg,vars,body,evars,handler}).
--record(k_protected, {anno=[],arg,ret=[]}).
+-record(k_protected, {anno=[],arg,ret=[],inner}).
-record(k_catch, {anno=[],body,ret=[]}).
-record(k_guard_match, {anno=[],vars,body,ret=[]}).
diff --git a/lib/compiler/test/Makefile b/lib/compiler/test/Makefile
index da5d207db9..2a5004aa4c 100644
--- a/lib/compiler/test/Makefile
+++ b/lib/compiler/test/Makefile
@@ -14,6 +14,7 @@ MODULES= \
beam_except_SUITE \
beam_jump_SUITE \
beam_reorder_SUITE \
+ beam_ssa_SUITE \
beam_type_SUITE \
beam_utils_SUITE \
bif_SUITE \
@@ -52,6 +53,7 @@ NO_OPT= \
beam_except \
beam_jump \
beam_reorder \
+ beam_ssa \
beam_type \
beam_utils \
bif \
@@ -75,6 +77,7 @@ INLINE= \
andor \
apply \
beam_block \
+ beam_ssa \
beam_utils \
bif \
bs_bincomp \
@@ -124,7 +127,7 @@ RELSYSDIR = $(RELEASE_PATH)/compiler_test
# ----------------------------------------------------
ERL_MAKE_FLAGS +=
-ERL_COMPILE_FLAGS += +clint +clint0
+ERL_COMPILE_FLAGS += +clint +clint0 +ssalint
EBIN = .
@@ -135,7 +138,8 @@ EBIN = .
make_emakefile: $(NO_OPT_ERL_FILES) $(POST_OPT_ERL_FILES) $(INLINE_ERL_FILES)
$(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES) \
> $(EMAKEFILE)
- $(ERL_TOP)/make/make_emakefile +no_copt +no_postopt $(ERL_COMPILE_FLAGS) \
+ $(ERL_TOP)/make/make_emakefile +no_copt +no_postopt \
+ +no_ssa_opt +no_recv_opt $(ERL_COMPILE_FLAGS) \
-o$(EBIN) $(NO_OPT_MODULES) >> $(EMAKEFILE)
$(ERL_TOP)/make/make_emakefile +no_copt $(ERL_COMPILE_FLAGS) \
-o$(EBIN) $(POST_OPT_MODULES) >> $(EMAKEFILE)
diff --git a/lib/compiler/test/andor_SUITE.erl b/lib/compiler/test/andor_SUITE.erl
index 721f77f0f6..5c463063c1 100644
--- a/lib/compiler/test/andor_SUITE.erl
+++ b/lib/compiler/test/andor_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/compiler/test/apply_SUITE.erl b/lib/compiler/test/apply_SUITE.erl
index be49cff9b9..0f82a56fb7 100644
--- a/lib/compiler/test/apply_SUITE.erl
+++ b/lib/compiler/test/apply_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/compiler/test/beam_except_SUITE.erl b/lib/compiler/test/beam_except_SUITE.erl
index 1eb07c8c85..2b4a780899 100644
--- a/lib/compiler/test/beam_except_SUITE.erl
+++ b/lib/compiler/test/beam_except_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2011-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2011-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/compiler/test/beam_jump_SUITE.erl b/lib/compiler/test/beam_jump_SUITE.erl
index 488c30919b..c61e4ab65c 100644
--- a/lib/compiler/test/beam_jump_SUITE.erl
+++ b/lib/compiler/test/beam_jump_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2016. All Rights Reserved.
+%% Copyright Ericsson AB 2016-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/compiler/test/beam_reorder_SUITE.erl b/lib/compiler/test/beam_reorder_SUITE.erl
index 33b27b9f9f..c8a4f9a75f 100644
--- a/lib/compiler/test/beam_reorder_SUITE.erl
+++ b/lib/compiler/test/beam_reorder_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/compiler/test/beam_ssa_SUITE.erl b/lib/compiler/test/beam_ssa_SUITE.erl
new file mode 100644
index 0000000000..5536abbdde
--- /dev/null
+++ b/lib/compiler/test/beam_ssa_SUITE.erl
@@ -0,0 +1,471 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(beam_ssa_SUITE).
+
+-export([all/0,suite/0,groups/0,init_per_suite/1,end_per_suite/1,
+ init_per_group/2,end_per_group/2,
+ calls/1,tuple_matching/1,recv/1,maps/1,
+ cover_ssa_dead/1,combine_sw/1]).
+
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [{group,p}].
+
+groups() ->
+ [{p,test_lib:parallel(),
+ [tuple_matching,
+ calls,
+ recv,
+ maps,
+ cover_ssa_dead,
+ combine_sw
+ ]}].
+
+init_per_suite(Config) ->
+ test_lib:recompile(?MODULE),
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+calls(Config) ->
+ Ret = {return,value,Config},
+ Ret = fun_call(fun(42) -> ok end, Ret),
+ Ret = apply_fun(fun(a, b) -> ok end, [a,b], Ret),
+ Ret = apply_mfa(test_lib, id, [anything], Ret),
+ {'EXIT',{badarg,_}} = (catch call_error()),
+ {'EXIT',{badarg,_}} = (catch call_error(42)),
+ 5 = start_it([erlang,length,1,2,3,4,5]),
+ ok.
+
+fun_call(Fun, X0) ->
+ X = id(X0),
+ Fun(42),
+ X.
+
+apply_fun(Fun, Args, X0) ->
+ X = id(X0),
+ apply(Fun, Args),
+ X.
+
+apply_mfa(Mod, Name, Args, X0) ->
+ X = id(X0),
+ apply(Mod, Name, Args),
+ X.
+
+call_error() ->
+ error(badarg),
+ ok.
+
+call_error(I) ->
+ <<I:(-8)>>,
+ ok.
+
+start_it([_|_]=MFA) ->
+ case MFA of
+ [M,F|Args] -> M:F(Args)
+ end.
+
+tuple_matching(_Config) ->
+ do_tuple_matching({tag,42}).
+
+do_tuple_matching(Arg) ->
+ Res = do_tuple_matching_1(Arg),
+ Res = do_tuple_matching_2(Arg),
+ Res = do_tuple_matching_3(Arg),
+ Res.
+
+do_tuple_matching_1({tag,V}) ->
+ {ok,V}.
+
+do_tuple_matching_2(Tuple) when is_tuple(Tuple) ->
+ Size = tuple_size(Tuple),
+ if
+ Size =:= 2 ->
+ {ok,element(2, Tuple)}
+ end.
+
+do_tuple_matching_3(Tuple) when is_tuple(Tuple) ->
+ Size = tuple_size(Tuple),
+ if
+ Size =:= 2 ->
+ 2 = id(Size),
+ {ok,element(2, Tuple)}
+ end.
+
+-record(reporter_state, {res,run_config}).
+-record(run_config, {report_interval=0}).
+
+recv(_Config) ->
+ Parent = self(),
+
+ %% Test sync_wait_mon/2.
+ Succ = fun() -> Parent ! {ack,self(),{result,42}} end,
+ {result,42} = sync_wait_mon(spawn_monitor(Succ), infinity),
+
+ Down = fun() -> exit(down) end,
+ {error,down} = sync_wait_mon(spawn_monitor(Down), infinity),
+
+ Exit = fun() ->
+ Self = self(),
+ spawn(fun() -> exit(Self, kill_me) end),
+ receive _ -> ok end
+ end,
+ {error,kill_me} = sync_wait_mon(spawn_monitor(Exit), infinity),
+
+ Timeout = fun() -> receive _ -> ok end end,
+ {error,timeout} = sync_wait_mon(spawn_monitor(Timeout), 0),
+
+ %% Test reporter_loop/1.
+ {a,Parent} = reporter_loop(#reporter_state{res={a,Parent},
+ run_config=#run_config{}}),
+
+ %% Test bad_sink/0.
+ bad_sink(),
+
+ %% Test tricky_recv_1/0.
+ self() ! 1,
+ a = tricky_recv_1(),
+ self() ! 2,
+ b = tricky_recv_1(),
+
+ %% Test tricky_recv_2/0.
+ self() ! 1,
+ {1,yes} = tricky_recv_2(),
+ self() ! 2,
+ {2,maybe} = tricky_recv_2(),
+
+ %% Test 'receive after infinity' in try/catch.
+ Pid = spawn(fun recv_after_inf_in_try/0),
+ exit(Pid, done),
+
+ %% Test tricky_recv_3().
+ self() ! {{self(),r0},{1,42,"name"}},
+ {Parent,r0,[<<1:32,1:8,42:8>>,"name",0]} = tricky_recv_3(),
+ self() ! {{self(),r1},{2,99,<<"data">>}},
+ {Parent,r1,<<1:32,2:8,99:8,"data">>} = tricky_recv_3(),
+
+ %% Test tricky_recv_4().
+ self() ! {[self(),r0],{1,42,"name"}},
+ {Parent,r0,[<<1:32,1:8,42:8>>,"name",0]} = tricky_recv_4(),
+ self() ! {[self(),r1],{2,99,<<"data">>}},
+ {Parent,r1,<<1:32,2:8,99:8,"data">>} = tricky_recv_4(),
+
+ ok.
+
+sync_wait_mon({Pid, Ref}, Timeout) ->
+ receive
+ {ack,Pid,Return} ->
+ erlang:demonitor(Ref, [flush]),
+ Return;
+ {'DOWN',Ref,_Type,Pid,Reason} ->
+ {error,Reason};
+ {'EXIT',Pid,Reason} ->
+ erlang:demonitor(Ref, [flush]),
+ {error,Reason}
+ after Timeout ->
+ erlang:demonitor(Ref, [flush]),
+ exit(Pid, kill),
+ {error,timeout}
+ end.
+
+reporter_loop(State) ->
+ RC = State#reporter_state.run_config,
+ receive after RC#run_config.report_interval ->
+ State#reporter_state.res
+ end.
+
+bad_sink() ->
+ {ok,Pid} = my_spawn(self()),
+ %% The get_tuple_element instruction for the matching
+ %% above was sinked into the receive loop. That will
+ %% not work (and would be bad for performance if it
+ %% would work).
+ receive
+ {ok,Pid} ->
+ ok;
+ error ->
+ exit(failed)
+ end,
+ exit(Pid, kill).
+
+my_spawn(Parent) ->
+ Pid = spawn(fun() ->
+ Parent ! {ok,self()},
+ receive _ -> ok end
+ end),
+ {ok,Pid}.
+
+tricky_recv_1() ->
+ receive
+ X=1 ->
+ id(42),
+ a;
+ X=2 ->
+ b
+ end,
+ case X of
+ 1 -> a;
+ 2 -> b
+ end.
+
+tricky_recv_2() ->
+ receive
+ X=1 ->
+ Y = case id(X) of
+ 1 -> yes;
+ _ -> no
+ end,
+ a;
+ X=2 ->
+ Y = maybe,
+ b
+ end,
+ {X,Y}.
+
+recv_after_inf_in_try() ->
+ try
+ %% Used to crash beam_kernel_to_ssa.
+ receive after infinity -> ok end
+ catch
+ _A:_B ->
+ receive after infinity -> ok end
+ end.
+
+tricky_recv_3() ->
+ {Pid, R, Request} =
+ receive
+ {{Pid0,R0}, {1, Proto0, Name0}} ->
+ {Pid0, R0,
+ [<<1:32, 1:8, Proto0:8>>,Name0,0]};
+ {{Pid1,R1}, {2, Proto1, Data1}} ->
+ {Pid1, R1,
+ <<1:32, 2:8, Proto1:8, Data1/binary>>}
+ end,
+ id({Pid,R,Request}).
+
+tricky_recv_4() ->
+ {Pid, R, Request} =
+ receive
+ {[Pid0,R0], {1, Proto0, Name0}} ->
+ {Pid0, R0,
+ [<<1:32, 1:8, Proto0:8>>,Name0,0]};
+ {[Pid1,R1], {2, Proto1, Data1}} ->
+ {Pid1, R1,
+ <<1:32, 2:8, Proto1:8, Data1/binary>>}
+ end,
+ id({Pid,R,Request}).
+
+maps(_Config) ->
+ {'EXIT',{{badmatch,#{}},_}} = (catch maps_1(any)),
+ ok.
+
+maps_1(K) ->
+ _ = id(42),
+ #{K:=V} = #{},
+ V.
+
+-record(wx_ref, {type=any_type,ref=any_ref}).
+
+cover_ssa_dead(_Config) ->
+ str = format_str(str, escapable, [], true),
+ [iolist,str] = format_str(str, escapable, iolist, true),
+ bad = format_str(str, not_escapable, [], true),
+ bad = format_str(str, not_escapable, iolist, true),
+ bad = format_str(str, escapable, [], false),
+ bad = format_str(str, escapable, [], bad),
+
+ DefWxRef = #wx_ref{},
+ {DefWxRef,77,9999,[]} = contains(#wx_ref{}, 77, 9999),
+ {DefWxRef,77.0,9999,[]} = contains(#wx_ref{}, 77.0, 9999),
+ {DefWxRef,77,9999.0,[]} = contains(#wx_ref{}, 77, 9999.0),
+ {DefWxRef,77.0,9999.0,[]} = contains(#wx_ref{}, 77.0, 9999.0),
+ {any_type,any_ref,42,43,[option]} = contains(#wx_ref{}, {42,43}, [option]),
+ {any_type,any_ref,42,43,[]} = contains(#wx_ref{}, {42,43}, []),
+ {any_type,any_ref,42.0,43,[]} = contains(#wx_ref{}, {42.0,43}, []),
+ {any_type,any_ref,42,43.0,[]} = contains(#wx_ref{}, {42,43.0}, []),
+ {any_type,any_ref,42.0,43.0,[]} = contains(#wx_ref{}, {42.0,43.0}, []),
+
+ nope = conv_alub(false, '=:='),
+ ok = conv_alub(true, '=:='),
+ ok = conv_alub(true, none),
+ error = conv_alub(false, none),
+
+ {false,false} = eval_alu(false, false, false),
+ {true,false} = eval_alu(false, false, true),
+ {false,true} = eval_alu(false, true, false),
+ {false,false} = eval_alu(false, true, true),
+ {false,true} = eval_alu(true, false, false),
+ {false,false} = eval_alu(true, false, true),
+ {true,true} = eval_alu(true, true, false),
+ {false,true} = eval_alu(true, true, true),
+
+ 100.0 = percentage(1.0, 0.0),
+ 100.0 = percentage(1, 0),
+ 0.0 = percentage(0, 0),
+ 0.0 = percentage(0.0, 0.0),
+ 40.0 = percentage(4.0, 10.0),
+ 60.0 = percentage(6, 10),
+
+ %% Cover '=:=', followed by '=/='.
+ false = 'cover__=:=__=/='(41),
+ true = 'cover__=:=__=/='(42),
+ false = 'cover__=:=__=/='(43),
+
+ %% Cover '<', followed by '=/='.
+ true = 'cover__<__=/='(41),
+ false = 'cover__<__=/='(42),
+ false = 'cover__<__=/='(43),
+
+ %% Cover '=<', followed by '=/='.
+ true = 'cover__=<__=/='(41),
+ true = 'cover__=<__=/='(42),
+ false = 'cover__=<__=/='(43),
+
+ %% Cover '>=', followed by '=/='.
+ false = 'cover__>=__=/='(41),
+ true = 'cover__>=__=/='(42),
+ true = 'cover__>=__=/='(43),
+
+ %% Cover '>', followed by '=/='.
+ false = 'cover__>__=/='(41),
+ false = 'cover__>__=/='(42),
+ true = 'cover__>__=/='(43),
+
+ ok.
+
+'cover__=:=__=/='(X) when X =:= 42 -> X =/= 43;
+'cover__=:=__=/='(_) -> false.
+
+'cover__<__=/='(X) when X < 42 -> X =/= 42;
+'cover__<__=/='(_) -> false.
+
+'cover__=<__=/='(X) when X =< 42 -> X =/= 43;
+'cover__=<__=/='(_) -> false.
+
+'cover__>=__=/='(X) when X >= 42 -> X =/= 41;
+'cover__>=__=/='(_) -> false.
+
+'cover__>__=/='(X) when X > 42 -> X =/= 42;
+'cover__>__=/='(_) -> false.
+
+format_str(Str, FormatData, IoList, EscChars) ->
+ Escapable = FormatData =:= escapable,
+ case id(Str) of
+ IoStr when Escapable, EscChars, IoList == [] ->
+ id(IoStr);
+ IoStr when Escapable, EscChars ->
+ [IoList,id(IoStr)];
+ _ ->
+ bad
+ end.
+
+contains(This, X, Y) when is_record(This, wx_ref), is_number(X), is_number(Y) ->
+ {This,X,Y,[]};
+contains(#wx_ref{type=ThisT,ref=ThisRef}, {CX,CY}, Options)
+ when is_number(CX), is_number(CY), is_list(Options) ->
+ {ThisT,ThisRef,CX,CY,Options}.
+
+conv_alub(HasDst, CmpOp) ->
+ case (not HasDst) andalso CmpOp =/= none of
+ true -> nope;
+ false ->
+ case HasDst of
+ false -> error;
+ true -> ok
+ end
+ end.
+
+eval_alu(Sign1, Sign2, N) ->
+ V = (Sign1 andalso Sign2 andalso (not N))
+ or ((not Sign1) andalso (not Sign2) andalso N),
+ C = (Sign1 andalso Sign2)
+ or ((not N) andalso (Sign1 orelse Sign2)),
+ {V,C}.
+
+percentage(Divident, Divisor) ->
+ if Divisor == 0 andalso Divident /= 0 ->
+ 100.0;
+ Divisor == 0 ->
+ 0.0;
+ true ->
+ Divident / Divisor * 100
+ end.
+
+combine_sw(_Config) ->
+ [a] = do_comb_sw_1(a),
+ [b,b] = do_comb_sw_1(b),
+ [c] = do_comb_sw_1(c),
+ [c] = do_comb_sw_1(c),
+ [] = do_comb_sw_1(z),
+
+ [a] = do_comb_sw_2(a),
+ [b2,b1] = do_comb_sw_2(b),
+ [c] = do_comb_sw_2(c),
+ [c] = do_comb_sw_2(c),
+ [] = do_comb_sw_2(z),
+
+ ok.
+
+do_comb_sw_1(X) ->
+ put(?MODULE, []),
+ if
+ X == a; X == b ->
+ put(?MODULE, [X|get(?MODULE)]);
+ true ->
+ ok
+ end,
+ if
+ X == b; X == c ->
+ put(?MODULE, [X|get(?MODULE)]);
+ true ->
+ ok
+ end,
+ erase(?MODULE).
+
+do_comb_sw_2(X) ->
+ put(?MODULE, []),
+ case X of
+ a ->
+ put(?MODULE, [a|get(?MODULE)]);
+ b ->
+ put(?MODULE, [b1|get(?MODULE)]);
+ _ ->
+ ok
+ end,
+ case X of
+ b ->
+ put(?MODULE, [b2|get(?MODULE)]);
+ c ->
+ put(?MODULE, [c|get(?MODULE)]);
+ _ ->
+ ok
+ end,
+ erase(?MODULE).
+
+%% The identity function.
+id(I) -> I.
diff --git a/lib/compiler/test/beam_type_SUITE.erl b/lib/compiler/test/beam_type_SUITE.erl
index 061076b3ff..a4459b95bf 100644
--- a/lib/compiler/test/beam_type_SUITE.erl
+++ b/lib/compiler/test/beam_type_SUITE.erl
@@ -21,9 +21,10 @@
-export([all/0,suite/0,groups/0,init_per_suite/1,end_per_suite/1,
init_per_group/2,end_per_group/2,
- integers/1,coverage/1,booleans/1,setelement/1,cons/1,
- tuple/1,record_float/1,binary_float/1,float_compare/1,
- arity_checks/1,elixir_binaries/1,find_best/1]).
+ integers/1,numbers/1,coverage/1,booleans/1,setelement/1,
+ cons/1,tuple/1,record_float/1,binary_float/1,float_compare/1,
+ arity_checks/1,elixir_binaries/1,find_best/1,
+ test_size/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -33,6 +34,7 @@ all() ->
groups() ->
[{p,[parallel],
[integers,
+ numbers,
coverage,
booleans,
setelement,
@@ -43,7 +45,8 @@ groups() ->
float_compare,
arity_checks,
elixir_binaries,
- find_best
+ find_best,
+ test_size
]}].
init_per_suite(Config) ->
@@ -123,6 +126,59 @@ do_integers_5(X0, Y0) ->
3 -> three
end.
+numbers(_Config) ->
+ Int = id(42),
+ true = is_integer(Int),
+ true = is_number(Int),
+ false = is_float(Int),
+
+ Float = id(42.0),
+ true = is_float(Float),
+ true = is_number(Float),
+ false = is_integer(Float),
+
+ Number = id(1) + id(2),
+ true = is_number(Number),
+ true = is_integer(Number),
+ false = is_float(Number),
+
+ AnotherNumber = id(99.0) + id(1),
+ true = is_float(AnotherNumber),
+ true = is_number(AnotherNumber),
+ false = is_integer(AnotherNumber),
+
+ NotNumber = id(atom),
+ true = is_atom(NotNumber),
+ false = is_number(NotNumber),
+ false = is_integer(NotNumber),
+ false = is_float(NotNumber),
+
+ true = is_number(Int),
+ true = is_number(Float),
+ true = is_number(Number),
+ true = is_number(AnotherNumber),
+
+ %% Cover beam_ssa_type:join/2.
+
+ Join1 = case id(a) of
+ a -> 3 + id(7); %Number.
+ b -> id(5) / id(2) %Float.
+ end,
+ true = is_integer(Join1),
+
+ Join2 = case id(a) of
+ a -> id(5) / 2; %Float.
+ b -> 3 + id(7) %Number.
+ end,
+ true = is_float(Join2),
+
+ %% Cover beam_ssa_type:meet/2.
+
+ Meet1 = id(0) + -10.0, %Float.
+ 10.0 = abs(Meet1), %Number.
+
+ ok.
+
coverage(Config) ->
{'EXIT',{badarith,_}} = (catch id(1) bsl 0.5),
{'EXIT',{badarith,_}} = (catch id(2.0) bsl 2),
@@ -160,10 +216,31 @@ coverage(Config) ->
ok.
booleans(_Config) ->
- {'EXIT',{{case_clause,_},_}} = (catch do_booleans(42)),
+ {'EXIT',{{case_clause,_},_}} = (catch do_booleans_1(42)),
+
+ AnyAtom = id(atom),
+ true = is_atom(AnyAtom),
+ false = is_boolean(AnyAtom),
+
+ MaybeBool = id(maybe),
+ case MaybeBool of
+ true -> ok;
+ maybe -> ok;
+ false -> ok
+ end,
+ false = is_boolean(MaybeBool),
+
+ NotBool = id(a),
+ case NotBool of
+ a -> ok;
+ b -> ok;
+ c -> ok
+ end,
+ false = is_boolean(NotBool),
+
ok.
-do_booleans(B) ->
+do_booleans_1(B) ->
case is_integer(B) of
yes -> yes;
no -> no
@@ -177,13 +254,59 @@ setelement(_Config) ->
cons(_Config) ->
[did] = cons(assigned, did),
+
+ true = cons_is_empty_list([]),
+ false = cons_is_empty_list([a]),
+
+ false = cons_not(true),
+ true = cons_not(false),
+
+ {$a,"bc"} = cons_hdtl(true),
+ {$d,"ef"} = cons_hdtl(false),
ok.
cons(assigned, Instrument) ->
[Instrument] = [did].
+cons_is_empty_list(L) ->
+ Cons = case L of
+ [] -> "true";
+ _ -> "false"
+ end,
+ id(1),
+ case Cons of
+ "true" -> true;
+ "false" -> false
+ end.
+
+cons_not(B) ->
+ Cons = case B of
+ true -> "true";
+ false -> "false"
+ end,
+ id(1),
+ case Cons of
+ "true" -> false;
+ "false" -> true
+ end.
+
+cons_hdtl(B) ->
+ Cons = case B of
+ true -> "abc";
+ false -> "def"
+ end,
+ id(1),
+ {id(hd(Cons)),id(tl(Cons))}.
+
+-record(bird, {a=a,b=id(42)}).
+
tuple(_Config) ->
{'EXIT',{{badmatch,{necessary}},_}} = (catch do_tuple()),
+
+ [] = [X || X <- [], #bird{a = a} == {r,X,foo}],
+ [] = [X || X <- [], #bird{b = b} == {bird,X}],
+ [] = [X || X <- [], 3 == X#bird.a],
+
ok.
do_tuple() ->
@@ -320,6 +443,15 @@ find_best([], <<"a">>) ->
find_best([], nil) ->
{error,<<"should not get here">>}.
+test_size(_Config) ->
+ 2 = do_test_size({a,b}),
+ 4 = do_test_size(<<42:32>>),
+ ok.
+
+do_test_size(Term) when is_tuple(Term) ->
+ size(Term);
+do_test_size(Term) when is_binary(Term) ->
+ size(Term).
id(I) ->
I.
diff --git a/lib/compiler/test/bif_SUITE.erl b/lib/compiler/test/bif_SUITE.erl
index c4c709eb3a..42ba5d5365 100644
--- a/lib/compiler/test/bif_SUITE.erl
+++ b/lib/compiler/test/bif_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2016. All Rights Reserved.
+%% Copyright Ericsson AB 2016-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/compiler/test/bs_bincomp_SUITE.erl b/lib/compiler/test/bs_bincomp_SUITE.erl
index a5d49020a9..0419b16eea 100644
--- a/lib/compiler/test/bs_bincomp_SUITE.erl
+++ b/lib/compiler/test/bs_bincomp_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/compiler/test/bs_bit_binaries_SUITE.erl b/lib/compiler/test/bs_bit_binaries_SUITE.erl
index 17faa012bc..526769f3a6 100644
--- a/lib/compiler/test/bs_bit_binaries_SUITE.erl
+++ b/lib/compiler/test/bs_bit_binaries_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl
index 7814738449..b4277f0705 100644
--- a/lib/compiler/test/bs_match_SUITE.erl
+++ b/lib/compiler/test/bs_match_SUITE.erl
@@ -248,6 +248,12 @@ bin_tail(Config) when is_list(Config) ->
ok = bin_tail_e(<<2:2,1:1,1:5,42:64>>),
error = bin_tail_e(<<3:2,1:1,1:5,42:64>>),
error = bin_tail_e(<<>>),
+
+ MD5 = erlang:md5(<<42>>),
+ <<"abc">> = bin_tail_f(<<MD5/binary,"abc">>, MD5, 3),
+ error = bin_tail_f(<<MD5/binary,"abc">>, MD5, 999),
+ {'EXIT',{_,_}} = (catch bin_tail_f(<<0:16/unit:8>>, MD5, 0)),
+
ok.
bin_tail_c(Bin, Offset) ->
@@ -304,6 +310,14 @@ bin_tail_e_var(Bin) ->
<<2:2,_:1,1:5,Tail/binary>> -> Tail;
_ -> error
end.
+
+bin_tail_f(Bin, MD5, Size) ->
+ case Bin of
+ <<MD5:16/binary, Tail:Size/binary>> ->
+ Tail;
+ <<MD5:16/binary, _/binary>> ->
+ error
+ end.
save_restore(Config) when is_list(Config) ->
0 = save_restore_1(<<0:2,42:6>>),
@@ -455,6 +469,15 @@ unit(Config) when is_list(Config) ->
127 = peek7(<<127:7>>),
100 = peek7(<<100:7,19:7>>),
fc(peek7, [<<1,2>>], catch peek7(<<1,2>>)),
+
+ 1 = unit_opt(1, -1),
+ 8 = unit_opt(8, -1),
+
+ <<1:32,"abc">> = unit_opt_2(<<1:32,"abc">>),
+ <<"def">> = unit_opt_2(<<2:32,"def">>),
+ {'EXIT',_} = (catch unit_opt_2(<<1:32,33:7>>)),
+ {'EXIT',_} = (catch unit_opt_2(<<2:32,55:7>>)),
+
ok.
peek1(<<B:8,_/bitstring>>) -> B.
@@ -465,6 +488,27 @@ peek8(<<B:8,_/binary>>) -> B.
peek16(<<B:16,_/binary-unit:16>>) -> B.
+unit_opt(U, X) ->
+ %% Cover type analysis in beam_ssa_type.
+ Bin = case U of
+ 1 -> <<X:7>>;
+ 8 -> <<X>>
+ end,
+ %% The type of Bin will be set to {binary,gcd(1, 8)}.
+ case Bin of
+ <<_/binary-unit:8>> -> 8;
+ <<_/binary-unit:1>> -> 1
+ end.
+
+unit_opt_2(<<St:32,KO/binary>> = Bin0) ->
+ Bin = if
+ St =:= 1 ->
+ Bin0;
+ St =:= 2 ->
+ <<KO/binary>>
+ end,
+ id(Bin).
+
shared_sub_bins(Config) when is_list(Config) ->
{15,[<<>>,<<5>>,<<4,5>>,<<3,4,5>>,<<2,3,4,5>>]} = sum(<<1,2,3,4,5>>, [], 0),
ok.
diff --git a/lib/compiler/test/bs_utf_SUITE.erl b/lib/compiler/test/bs_utf_SUITE.erl
index 4330677260..8ea4a849ec 100644
--- a/lib/compiler/test/bs_utf_SUITE.erl
+++ b/lib/compiler/test/bs_utf_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/compiler/test/compilation_SUITE.erl b/lib/compiler/test/compilation_SUITE.erl
index 3ba3ce7cdf..74f9dbd9b4 100644
--- a/lib/compiler/test/compilation_SUITE.erl
+++ b/lib/compiler/test/compilation_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -170,7 +170,7 @@ try_it(Module, Conf) ->
atom_to_list(Module)),
Out = proplists:get_value(priv_dir,Conf),
io:format("Compiling: ~s\n", [Src]),
- CompRc0 = compile:file(Src, [clint0,clint,{outdir,Out},report,
+ CompRc0 = compile:file(Src, [clint0,clint,ssalint,{outdir,Out},report,
bin_opt_info|OtherOpts]),
io:format("Result: ~p\n",[CompRc0]),
{ok,_Mod} = CompRc0,
@@ -189,7 +189,7 @@ try_it(Module, Conf) ->
ct:timetrap(Timetrap),
io:format("Compiling (with old inliner): ~s\n", [Src]),
- CompRc2 = compile:file(Src, [clint,
+ CompRc2 = compile:file(Src, [clint,ssalint,
{outdir,Out},report,bin_opt_info,
{inline,1000}|OtherOpts]),
io:format("Result: ~p\n",[CompRc2]),
@@ -355,7 +355,7 @@ compile_compiler(Files, OutDir, Version, InlineOpts) ->
io:format("~ts", [code:which(compile)]),
io:format("Compiling ~s into ~ts", [Version,OutDir]),
Opts = [report,
- clint0,clint,
+ clint0,clint,ssalint,
bin_opt_info,
{outdir,OutDir},
{d,'COMPILER_VSN',"\""++Version++"\""},
diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl
index 1ecae06128..38bc928f85 100644
--- a/lib/compiler/test/compile_SUITE.erl
+++ b/lib/compiler/test/compile_SUITE.erl
@@ -385,12 +385,13 @@ do_file_listings(DataDir, PrivDir, [File|Files]) ->
do_listing(Simple, TargetDir, dcbsm, ".core_bsm"),
do_listing(Simple, TargetDir, dsetel, ".dsetel"),
do_listing(Simple, TargetDir, dkern, ".kernel"),
+ do_listing(Simple, TargetDir, dssa, ".ssa"),
+ do_listing(Simple, TargetDir, dssaopt, ".ssaopt"),
+ do_listing(Simple, TargetDir, dprecg, ".precodegen"),
do_listing(Simple, TargetDir, dcg, ".codegen"),
do_listing(Simple, TargetDir, dblk, ".block"),
do_listing(Simple, TargetDir, dexcept, ".except"),
do_listing(Simple, TargetDir, dbs, ".bs"),
- do_listing(Simple, TargetDir, dtype, ".type"),
- do_listing(Simple, TargetDir, ddead, ".dead"),
do_listing(Simple, TargetDir, djmp, ".jump"),
do_listing(Simple, TargetDir, dclean, ".clean"),
do_listing(Simple, TargetDir, dpeep, ".peep"),
@@ -424,6 +425,9 @@ listings_big(Config) when is_list(Config) ->
do_listing(Big, TargetDir, 'E'),
do_listing(Big, TargetDir, 'P'),
do_listing(Big, TargetDir, dkern, ".kernel"),
+ do_listing(Big, TargetDir, dssa, ".ssa"),
+ do_listing(Big, TargetDir, dssaopt, ".ssaopt"),
+ do_listing(Big, TargetDir, dprecg, ".precodegen"),
do_listing(Big, TargetDir, to_dis, ".dis"),
TargetNoext = filename:rootname(Target, code:objfile_extension()),
@@ -920,7 +924,7 @@ do_core_pp_1(M, A, Outdir) ->
ok = file:delete(CoreFile),
%% Compile as usual (including optimizations).
- compile_forms(M, Core, [clint,from_core,binary]),
+ compile_forms(M, Core, [clint,ssalint,from_core,binary]),
%% Don't optimize to test that we are not dependent
%% on the Core Erlang optmimization passes.
@@ -929,7 +933,7 @@ do_core_pp_1(M, A, Outdir) ->
%% records; if sys_core_fold was run it would fix
%% that; if sys_core_fold was not run v3_kernel would
%% crash.)
- compile_forms(M, Core, [clint,from_core,no_copt,binary]),
+ compile_forms(M, Core, [clint,ssalint,from_core,no_copt,binary]),
ok.
@@ -1242,21 +1246,11 @@ do_opt_guards_fun([_|Is]) ->
do_opt_guards_fun(Is);
do_opt_guards_fun([]) -> [].
-is_exception(bs_match_SUITE, {matching_and_andalso_2,2}) -> true;
-is_exception(bs_match_SUITE, {matching_and_andalso_3,2}) -> true;
is_exception(guard_SUITE, {'-complex_not/1-fun-4-',1}) -> true;
is_exception(guard_SUITE, {'-complex_not/1-fun-5-',1}) -> true;
-is_exception(guard_SUITE, {basic_andalso_orelse,1}) -> true;
is_exception(guard_SUITE, {bad_guards,1}) -> true;
-is_exception(guard_SUITE, {bad_guards_2,2}) -> true;
is_exception(guard_SUITE, {bad_guards_3,2}) -> true;
-is_exception(guard_SUITE, {cqlc,4}) -> true;
-is_exception(guard_SUITE, {csemi7,3}) -> true;
-is_exception(guard_SUITE, {misc,1}) -> true;
is_exception(guard_SUITE, {nested_not_2b,4}) -> true;
-is_exception(guard_SUITE, {tricky_1,2}) -> true;
-is_exception(map_SUITE, {map_guard_update,2}) -> true;
-is_exception(map_SUITE, {map_guard_update_variables,3}) -> true;
is_exception(_, _) -> false.
sys_pre_attributes(Config) ->
@@ -1478,18 +1472,22 @@ bc_options(Config) ->
101 = highest_opcode(DataDir, small_float, [no_get_hd_tl,no_line_info]),
103 = highest_opcode(DataDir, big,
- [no_get_hd_tl,no_record_opt,
+ [no_put_tuple2,
+ no_get_hd_tl,no_ssa_opt_record,
no_line_info,no_stack_trimming]),
125 = highest_opcode(DataDir, small_float,
- [no_get_hd_tl,no_line_info,no_float_opt]),
+ [no_get_hd_tl,no_line_info,no_ssa_opt_float]),
132 = highest_opcode(DataDir, small,
- [no_get_hd_tl,no_record_opt,no_float_opt,no_line_info]),
+ [no_put_tuple2,no_get_hd_tl,no_ssa_opt_record,
+ no_ssa_opt_float,no_line_info]),
- 136 = highest_opcode(DataDir, big, [no_get_hd_tl,no_record_opt,no_line_info]),
+ 136 = highest_opcode(DataDir, big, [no_put_tuple2,no_get_hd_tl,
+ no_ssa_opt_record,no_line_info]),
- 153 = highest_opcode(DataDir, big, [no_get_hd_tl,no_record_opt]),
+ 153 = highest_opcode(DataDir, big, [no_put_tuple2,no_get_hd_tl,
+ no_ssa_opt_record]),
153 = highest_opcode(DataDir, big, [r16]),
153 = highest_opcode(DataDir, big, [r17]),
153 = highest_opcode(DataDir, big, [r18]),
@@ -1501,9 +1499,10 @@ bc_options(Config) ->
158 = highest_opcode(DataDir, small_maps, [r18]),
158 = highest_opcode(DataDir, small_maps, [r19]),
158 = highest_opcode(DataDir, small_maps, [r20]),
- 158 = highest_opcode(DataDir, small_maps, []),
+ 158 = highest_opcode(DataDir, small_maps, [r21]),
- 163 = highest_opcode(DataDir, big, []),
+ 164 = highest_opcode(DataDir, small_maps, []),
+ 164 = highest_opcode(DataDir, big, []),
ok.
diff --git a/lib/compiler/test/core_alias_SUITE.erl b/lib/compiler/test/core_alias_SUITE.erl
index 4f96576621..737b1567d4 100644
--- a/lib/compiler/test/core_alias_SUITE.erl
+++ b/lib/compiler/test/core_alias_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/compiler/test/core_fold_SUITE.erl b/lib/compiler/test/core_fold_SUITE.erl
index 30d145582a..3fca1434ae 100644
--- a/lib/compiler/test/core_fold_SUITE.erl
+++ b/lib/compiler/test/core_fold_SUITE.erl
@@ -212,9 +212,14 @@ bifs(Config) when is_list(Config) ->
{ok,#{K:=V}} = id(list_to_tuple([ok,#{K=>V}])),
ok.
--define(CMP_SAME(A0, B), (fun(A) -> true = A == B, false = A /= B end)(id(A0))).
--define(CMP_DIFF(A0, B), (fun(A) -> false = A == B, true = A /= B end)(id(A0))).
-
+-define(CMP_SAME0(A0, B), (fun(A) -> true = A == B, false = A /= B end)(id(A0))).
+-define(CMP_SAME1(A0, B), (fun(A) -> false = A /= B, true = A == B end)(id(A0))).
+-define(CMP_SAME(A0, B), (true = ?CMP_SAME0(A0, B) =:= not ?CMP_SAME1(A0, B))).
+
+-define(CMP_DIFF0(A0, B), (fun(A) -> false = A == B, true = A /= B end)(id(A0))).
+-define(CMP_DIFF1(A0, B), (fun(A) -> true = A /= B, false = A == B end)(id(A0))).
+-define(CMP_DIFF(A0, B), (true = ?CMP_DIFF0(A0, B) =:= not ?CMP_DIFF1(A0, B))).
+
eq(Config) when is_list(Config) ->
?CMP_SAME([a,b,c], [a,b,c]),
?CMP_SAME([42.0], [42.0]),
@@ -373,7 +378,7 @@ unused_multiple_values_error(Config) when is_list(Config) ->
PrivDir = proplists:get_value(priv_dir, Config),
Dir = test_lib:get_data_dir(Config),
Core = filename:join(Dir, "unused_multiple_values_error"),
- Opts = [no_copt,clint,return,from_core,{outdir,PrivDir}
+ Opts = [no_copt,clint,ssalint,return,from_core,{outdir,PrivDir}
|test_lib:opt_opts(?MODULE)],
{error,[{unused_multiple_values_error,
[{none,core_lint,{return_mismatch,{hello,1}}}]}],
diff --git a/lib/compiler/test/error_SUITE.erl b/lib/compiler/test/error_SUITE.erl
index da291bdc8b..8b9dbe4aa0 100644
--- a/lib/compiler/test/error_SUITE.erl
+++ b/lib/compiler/test/error_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/compiler/test/float_SUITE.erl b/lib/compiler/test/float_SUITE.erl
index 39867021cb..012810aba2 100644
--- a/lib/compiler/test/float_SUITE.erl
+++ b/lib/compiler/test/float_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/compiler/test/guard_SUITE.erl b/lib/compiler/test/guard_SUITE.erl
index 99dc06b525..1c05129dc4 100644
--- a/lib/compiler/test/guard_SUITE.erl
+++ b/lib/compiler/test/guard_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -35,8 +35,7 @@
basic_andalso_orelse/1,traverse_dcd/1,
check_qlc_hrl/1,andalso_semi/1,t_tuple_size/1,binary_part/1,
bad_constants/1,bad_guards/1,
- guard_in_catch/1,beam_bool_SUITE/1,
- cover_beam_dead/1]).
+ guard_in_catch/1,beam_bool_SUITE/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -54,8 +53,7 @@ groups() ->
rel_ops,rel_op_combinations,
literal_type_tests,basic_andalso_orelse,traverse_dcd,
check_qlc_hrl,andalso_semi,t_tuple_size,binary_part,
- bad_constants,bad_guards,guard_in_catch,beam_bool_SUITE,
- cover_beam_dead]}].
+ bad_constants,bad_guards,guard_in_catch,beam_bool_SUITE]}].
init_per_suite(Config) ->
test_lib:recompile(?MODULE),
@@ -1779,15 +1777,10 @@ t_tuple_size(Config) when is_list(Config) ->
error = ludicrous_tuple_size({a,b,c}),
error = ludicrous_tuple_size([a,b,c]),
- %% Test the "unsafe case" - the register assigned the tuple size is
- %% not killed.
- DataDir = test_lib:get_data_dir(Config),
- File = filename:join(DataDir, "guard_SUITE_tuple_size"),
- {ok,Mod,Code} = compile:file(File, [from_asm,binary]),
- code:load_binary(Mod, File, Code),
- 14 = Mod:t({1,2,3,4}),
- _ = code:delete(Mod),
- _ = code:purge(Mod),
+ good_ip({1,2,3,4}),
+ good_ip({1,2,3,4,5,6,7,8}),
+ error = validate_ip({42,11}),
+ error = validate_ip(atom),
ok.
@@ -1805,6 +1798,16 @@ ludicrous_tuple_size(T)
when tuple_size(T) =:= 16#FFFFFFFFFFFFFFFF -> ok;
ludicrous_tuple_size(_) -> error.
+good_ip(IP) ->
+ IP = validate_ip(IP).
+
+validate_ip(Value) when is_tuple(Value) andalso
+ ((size(Value) =:= 4) orelse (size(Value) =:= 8)) ->
+ %% size/1 (converted to tuple_size) used more than once.
+ Value;
+validate_ip(_) ->
+ error.
+
%%
%% The binary_part/2,3 guard BIFs
%%
@@ -2206,32 +2209,6 @@ maps() ->
evidence(#{0 := Charge}) when 0; #{[] => Charge} == #{[] => 42} ->
ok.
-cover_beam_dead(_Config) ->
- Mod = ?FUNCTION_NAME,
- Attr = [],
- Fs = [{function,test,1,2,
- [{label,1},
- {line,[]},
- {func_info,{atom,Mod},{atom,test},1},
- {label,2},
- %% Cover beam_dead:turn_op/1 using swapped operand order.
- {test,is_ne_exact,{f,3},[{integer,1},{x,0}]},
- {test,is_eq_exact,{f,1},[{atom,a},{x,0}]},
- {label,3},
- {move,{atom,ok},{x,0}},
- return]}],
- Exp = [{test,1}],
- Asm = {Mod,Exp,Attr,Fs,3},
- {ok,Mod,Beam} = compile:forms(Asm, [from_asm,binary,report]),
- {module,Mod} = code:load_binary(Mod, Mod, Beam),
- ok = Mod:test(1),
- ok = Mod:test(a),
- {'EXIT',_} = (catch Mod:test(other)),
- true = code:delete(Mod),
- _ = code:purge(Mod),
-
- ok.
-
%% Call this function to turn off constant propagation.
id(I) -> I.
diff --git a/lib/compiler/test/guard_SUITE_data/guard_SUITE_tuple_size.S b/lib/compiler/test/guard_SUITE_data/guard_SUITE_tuple_size.S
deleted file mode 100644
index cffb792920..0000000000
--- a/lib/compiler/test/guard_SUITE_data/guard_SUITE_tuple_size.S
+++ /dev/null
@@ -1,30 +0,0 @@
-{module, guard_SUITE_tuple_size}. %% version = 0
-
-{exports, [{t,1}]}.
-
-{attributes, []}.
-
-{labels, 5}.
-
-
-{function, t, 1, 2}.
- {label,1}.
- {func_info,{atom,guard_SUITE_tuple_size},{atom,t},1}.
- {label,2}.
- {bif,tuple_size,{f,4},[{x,0}],{x,1}}.
- {test,is_eq_exact,{f,4},[{x,1},{integer,4}]}.
- {test,is_tuple,{f,3},[{x,0}]}.
- {test,test_arity,{f,3},[{x,0},4]}.
- {get_tuple_element,{x,0},0,{x,5}}.
- {get_tuple_element,{x,0},1,{x,2}}.
- {get_tuple_element,{x,0},2,{x,3}}.
- {get_tuple_element,{x,0},3,{x,4}}.
- {gc_bif,'+',{f,0},6,[{x,1},{x,2}],{x,0}}.
- {gc_bif,'+',{f,0},6,[{x,0},{x,3}],{x,0}}.
- {gc_bif,'+',{f,0},6,[{x,0},{x,4}],{x,0}}.
- {gc_bif,'+',{f,0},6,[{x,0},{x,5}],{x,0}}.
- return.
- {label,3}.
- {badmatch,{x,0}}.
- {label,4}.
- {jump,{f,1}}.
diff --git a/lib/compiler/test/inline_SUITE.erl b/lib/compiler/test/inline_SUITE.erl
index fdf2fe88b4..69c9dcba69 100644
--- a/lib/compiler/test/inline_SUITE.erl
+++ b/lib/compiler/test/inline_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -96,7 +96,8 @@ try_inline(Mod, Config) ->
%% Normal compilation.
io:format("Compiling: ~s\n", [Src]),
- {ok,Mod} = compile:file(Src, [{outdir,Out},report,bin_opt_info,clint]),
+ {ok,Mod} = compile:file(Src, [{outdir,Out},report,
+ bin_opt_info,clint,ssalint]),
ct:timetrap({minutes,10}),
NormalResult = rpc:call(Node, ?MODULE, load_and_call, [Out,Mod]),
@@ -104,7 +105,7 @@ try_inline(Mod, Config) ->
%% Inlining.
io:format("Compiling with old inliner: ~s\n", [Src]),
{ok,Mod} = compile:file(Src, [{outdir,Out},report,bin_opt_info,
- {inline,1000},clint]),
+ {inline,1000},clint,ssalint]),
%% Run inlined code.
ct:timetrap({minutes,10}),
@@ -117,7 +118,7 @@ try_inline(Mod, Config) ->
%% Inlining.
io:format("Compiling with new inliner: ~s\n", [Src]),
{ok,Mod} = compile:file(Src, [{outdir,Out},report,
- bin_opt_info,inline,clint]),
+ bin_opt_info,inline,clint,ssalint]),
%% Run inlined code.
ct:timetrap({minutes,10}),
@@ -351,7 +352,8 @@ otp_7223_2({a}) ->
coverage(Config) when is_list(Config) ->
Mod = bsdecode,
Src = filename:join(proplists:get_value(data_dir, Config), Mod),
- {ok,Mod,_} = compile:file(Src, [binary,report,{inline,0},clint]),
+ {ok,Mod,_} = compile:file(Src, [binary,report,{inline,0},
+ clint,ssalint]),
{ok,Mod,_} = compile:file(Src, [binary,report,{inline,20},
- verbose,clint]),
+ verbose,clint,ssalint]),
ok.
diff --git a/lib/compiler/test/map_SUITE.erl b/lib/compiler/test/map_SUITE.erl
index c004dca834..3e0ab78390 100644
--- a/lib/compiler/test/map_SUITE.erl
+++ b/lib/compiler/test/map_SUITE.erl
@@ -1258,6 +1258,38 @@ t_guard_bifs(Config) when is_list(Config) ->
{'EXIT',{{badkey,k},_}} = (catch erl_699(#{})),
{'EXIT',{{badmap,not_a_map},_}} = (catch erl_699(not_a_map)),
+ %% Cover optimizations in beam_dead.
+
+ ok = beam_dead_1(#{a=>any,k=>true}),
+ error = beam_dead_1(#{a=>any,k=>false}),
+ error = beam_dead_1(#{a=>any}),
+ error = beam_dead_1(#{}),
+
+ ok = beam_dead_2(#{a=>any,k=>true}),
+ error = beam_dead_2(#{a=>any,k=>false}),
+ error = beam_dead_2(#{a=>any}),
+ error = beam_dead_2(#{}),
+
+ ok = beam_dead_3(#{k=>true}),
+ error = beam_dead_3(#{k=>false}),
+ error = beam_dead_3(#{}),
+
+ ok = beam_dead_4(#{k=>true}),
+ error = beam_dead_4(#{k=>false}),
+ error = beam_dead_4(#{}),
+ error = beam_dead_4(not_a_map),
+
+ ok = beam_dead_5(#{k=>true}),
+ error = beam_dead_5(#{k=>false}),
+ error = beam_dead_3(#{}),
+
+ %% Test is_map_key/2 followed by map update.
+
+ Used0 = map_usage(var, #{other=>value}),
+ Used0 = #{other=>value,var=>dead},
+ Used1 = map_usage(var, #{var=>live}),
+ Used1 = #{var=>live},
+
ok.
map_guard_empty() when is_map(#{}); false -> true.
@@ -1298,6 +1330,48 @@ erl_699(M) ->
%% Used to cause an internal consistency failure.
{is_map_key(k, M),maps:get(k, M)}.
+beam_dead_1(#{a:=_,k:=_}=M) when map_get(k, M) ->
+ ok;
+beam_dead_1(#{}) ->
+ error.
+
+beam_dead_2(M) ->
+ case M of
+ #{a:=_,k:=_} when map_get(k, M) ->
+ ok;
+ #{} ->
+ error
+ end.
+
+beam_dead_3(M) ->
+ case M of
+ #{k:=_} when map_get(k, M) ->
+ ok;
+ #{} ->
+ error
+ end.
+
+beam_dead_4(M) ->
+ case M of
+ #{} when map_get(k, M) ->
+ ok;
+ _ ->
+ error
+ end.
+
+beam_dead_5(#{}=M) when map_get(k, M) ->
+ ok;
+beam_dead_5(#{}) ->
+ error.
+
+%% Test is_map_key/2, followed by an update of the map.
+map_usage(Def, Used) ->
+ case is_map_key(Def, Used) of
+ true -> Used;
+ false -> Used#{Def=>dead}
+ end.
+
+
t_guard_sequence(Config) when is_list(Config) ->
{1, "a"} = map_guard_sequence_1(#{seq=>1,val=>id("a")}),
{2, "b"} = map_guard_sequence_1(#{seq=>2,val=>id("b")}),
diff --git a/lib/compiler/test/match_SUITE.erl b/lib/compiler/test/match_SUITE.erl
index e3f842b668..229c3093d7 100644
--- a/lib/compiler/test/match_SUITE.erl
+++ b/lib/compiler/test/match_SUITE.erl
@@ -254,6 +254,8 @@ non_matching_aliases(_Config) ->
none = mixed_aliases([d]),
none = mixed_aliases({a,42}),
none = mixed_aliases(42),
+ none = mixed_aliases(<<6789:16>>),
+ none = mixed_aliases(#{key=>value}),
{'EXIT',{{badmatch,42},_}} = (catch nomatch_alias(42)),
{'EXIT',{{badmatch,job},_}} = (catch entirely()),
@@ -279,6 +281,16 @@ mixed_aliases(<<X:8>> = x) -> {a,X};
mixed_aliases([b] = <<X:8>>) -> {b,X};
mixed_aliases(<<X:8>> = {a,X}) -> {c,X};
mixed_aliases([X] = <<X:8>>) -> {d,X};
+mixed_aliases(<<X:16>> = X) -> {e,X};
+mixed_aliases(X = <<X:16>>) -> {f,X};
+mixed_aliases(<<X:16,_/binary>> = X) -> {g,X};
+mixed_aliases(X = <<X:16,_/binary>>) -> {h,X};
+mixed_aliases(X = #{key:=X}) -> {i,X};
+mixed_aliases(#{key:=X} = X) -> {j,X};
+mixed_aliases([X] = #{key:=X}) -> {k,X};
+mixed_aliases(#{key:=X} = [X]) -> {l,X};
+mixed_aliases({a,X} = #{key:=X}) -> {m,X};
+mixed_aliases(#{key:=X} = {a,X}) -> {n,X};
mixed_aliases(_) -> none.
nomatch_alias(I) ->
@@ -434,6 +446,7 @@ letify_guard(A, B) ->
selectify(Config) when is_list(Config) ->
integer = sel_different_types({r,42}),
atom = sel_different_types({r,forty_two}),
+ float = sel_different_types({r,100.0}),
none = sel_different_types({r,18}),
{'EXIT',_} = (catch sel_different_types([a,b,c])),
@@ -444,12 +457,15 @@ selectify(Config) when is_list(Config) ->
integer42 = sel_same_value2(42),
integer43 = sel_same_value2(43),
error = sel_same_value2(44),
+
ok.
sel_different_types({r,_}=T) when element(2, T) =:= forty_two ->
atom;
sel_different_types({r,_}=T) when element(2, T) =:= 42 ->
integer;
+sel_different_types({r,_}=T) when element(2, T) =:= 100.0 ->
+ float;
sel_different_types({r,_}) ->
none.
diff --git a/lib/compiler/test/misc_SUITE.erl b/lib/compiler/test/misc_SUITE.erl
index a1d931b994..4c2d0116c9 100644
--- a/lib/compiler/test/misc_SUITE.erl
+++ b/lib/compiler/test/misc_SUITE.erl
@@ -171,7 +171,7 @@ silly_coverage(Config) when is_list(Config) ->
expect_error(fun() -> sys_core_dsetel:module(BadCoreErlang, []) end),
expect_error(fun() -> v3_kernel:module(BadCoreErlang, []) end),
- %% v3_codegen
+ %% beam_kernel_to_ssa
BadKernel = {k_mdef,[],?MODULE,
[{foo,0}],
[],
@@ -179,7 +179,31 @@ silly_coverage(Config) when is_list(Config) ->
{k,[],[],[]},
f,0,[],
seriously_bad_body}]},
- expect_error(fun() -> v3_codegen:module(BadKernel, []) end),
+ expect_error(fun() -> beam_kernel_to_ssa:module(BadKernel, []) end),
+
+ %% beam_ssa_lint
+ %% beam_ssa_recv
+ %% beam_ssa_pre_codegen
+ %% beam_ssa_opt
+ %% beam_ssa_codegen
+ BadSSA = {b_module,#{},a,b,c,
+ [{b_function,#{func_info=>{mod,foo,0}},args,bad_blocks,0}]},
+ expect_error(fun() -> beam_ssa_lint:module(BadSSA, []) end),
+ expect_error(fun() -> beam_ssa_recv:module(BadSSA, []) end),
+ expect_error(fun() -> beam_ssa_pre_codegen:module(BadSSA, []) end),
+ expect_error(fun() -> beam_ssa_opt:module(BadSSA, []) end),
+ expect_error(fun() -> beam_ssa_codegen:module(BadSSA, []) end),
+
+ %% beam_ssa_lint, beam_ssa_pp
+ {error,[{_,Errors}]} = beam_ssa_lint:module(bad_ssa_lint_input(), []),
+ _ = [io:put_chars(Mod:format_error(Reason)) ||
+ {Mod,Reason} <- Errors],
+
+ %% Cover printing of annotations in beam_ssa_pp
+ PPAnno = #{func_info=>{mod,foo,0},other_anno=>value,map_anno=>#{k=>v}},
+ PPBlocks = #{0=>{b_blk,#{},[],{b_ret,#{},{b_literal,42}}}},
+ PP = {b_function,PPAnno,[],PPBlocks,0},
+ io:put_chars(beam_ssa_pp:format_function(PP)),
%% beam_a
BeamAInput = {?MODULE,[{foo,0}],[],
@@ -189,14 +213,6 @@ silly_coverage(Config) when is_list(Config) ->
{label,2}|non_proper_list]}],99},
expect_error(fun() -> beam_a:module(BeamAInput, []) end),
- %% beam_reorder
- BlockInput = {?MODULE,[{foo,0}],[],
- [{function,foo,0,2,
- [{label,1},
- {func_info,{atom,?MODULE},{atom,foo},0},
- {label,2}|non_proper_list]}],99},
- expect_error(fun() -> beam_reorder:module(BlockInput, []) end),
-
%% beam_block
BlockInput = {?MODULE,[{foo,0}],[],
[{function,foo,0,2,
@@ -209,15 +225,6 @@ silly_coverage(Config) when is_list(Config) ->
BsInput = BlockInput,
expect_error(fun() -> beam_bs:module(BsInput, []) end),
- %% beam_type
- TypeInput = {?MODULE,[{foo,0}],[],
- [{function,foo,0,2,
- [{label,1},
- {line,loc},
- {func_info,{atom,?MODULE},{atom,foo},0},
- {label,2}|non_proper_list]}],99},
- expect_error(fun() -> beam_type:module(TypeInput, []) end),
-
%% beam_except
ExceptInput = {?MODULE,[{foo,0}],[],
[{function,foo,0,2,
@@ -227,16 +234,6 @@ silly_coverage(Config) when is_list(Config) ->
{label,2}|non_proper_list]}],99},
expect_error(fun() -> beam_except:module(ExceptInput, []) end),
- %% beam_dead. This is tricky. Our function must look OK to
- %% beam_utils:clean_labels/1, but must crash beam_dead.
- DeadInput = {?MODULE,[{foo,0}],[],
- [{function,foo,0,2,
- [{label,1},
- {func_info,{atom,?MODULE},{atom,foo},0},
- {label,2},
- {test,is_eq_exact,{f,1},[bad,operands]}]}],99},
- expect_error(fun() -> beam_dead:module(DeadInput, []) end),
-
%% beam_clean
CleanInput = {?MODULE,[{foo,0}],[],
[{function,foo,0,2,
@@ -268,33 +265,6 @@ silly_coverage(Config) when is_list(Config) ->
{block,[a|b]}]}],0},
expect_error(fun() -> beam_bsm:module(BsmInput, []) end),
- %% beam_receive.
- ReceiveInput = {?MODULE,[{foo,0}],[],
- [{function,foo,0,2,
- [{label,1},
- {func_info,{atom,?MODULE},{atom,foo},0},
- {label,2},
- {call_ext,0,{extfunc,erlang,make_ref,0}},
- {block,[a|b]}]}],0},
- expect_error(fun() -> beam_receive:module(ReceiveInput, []) end),
-
- %% beam_record.
- RecordInput = {?MODULE,[{foo,0}],[],
- [{function,foo,1,2,
- [{label,1},
- {func_info,{atom,?MODULE},{atom,foo},1},
- {label,2},
- {test,is_tuple,{f,1},[{x,0}]},
- {test,test_arity,{f,1},[{x,0},3]},
- {block,[{set,[{x,1}],[{x,0}],{get_tuple_element,0}}]},
- {test,is_eq_exact,{f,1},[{x,1},{atom,bar}]},
- {block,[{set,[{x,2}],[{x,0}],{get_tuple_element,1}}|a]},
- {test,is_eq_exact,{f,1},[{x,2},{integer,1}]},
- {block,[{set,[{x,0}],[{atom,ok}],move}]},
- return]}],0},
-
- expect_error(fun() -> beam_record:module(RecordInput, []) end),
-
BeamZInput = {?MODULE,[{foo,0}],[],
[{function,foo,0,2,
[{label,1},
@@ -312,6 +282,31 @@ silly_coverage(Config) when is_list(Config) ->
ok.
+bad_ssa_lint_input() ->
+ {b_module,#{},t,
+ [{foobar,1},{module_info,0},{module_info,1}],
+ [],
+ [{b_function,
+ #{func_info => {t,foobar,1},location => {"t.erl",4}},
+ [{b_var,0}],
+ #{0 => {b_blk,#{},[],{b_ret,#{},{b_var,'@undefined_var'}}}},
+ 3},
+ {b_function,
+ #{func_info => {t,module_info,0}},
+ [],
+ #{0 =>
+ {b_blk,#{},
+ [{b_set,#{},
+ {b_var,{'@ssa_ret',3}},
+ call,
+ [{b_remote,
+ {b_literal,erlang},
+ {b_literal,get_module_info},
+ 1},
+ {b_var,'@unknown_variable'}]}],
+ {b_ret,#{},{b_var,{'@ssa_ret',3}}}}},
+ 4}]}.
+
expect_error(Fun) ->
try Fun() of
Any ->
diff --git a/lib/compiler/test/overridden_bif_SUITE.erl b/lib/compiler/test/overridden_bif_SUITE.erl
index a46abe8dcf..6b8a9591c9 100644
--- a/lib/compiler/test/overridden_bif_SUITE.erl
+++ b/lib/compiler/test/overridden_bif_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/compiler/test/receive_SUITE_data/ref_opt/no_5.erl b/lib/compiler/test/receive_SUITE_data/ref_opt/no_5.erl
new file mode 100644
index 0000000000..4fbde3a83d
--- /dev/null
+++ b/lib/compiler/test/receive_SUITE_data/ref_opt/no_5.erl
@@ -0,0 +1,38 @@
+-module(no_5).
+-compile([export_all,nowarn_export_all]).
+
+?MODULE() ->
+ ok.
+
+%% Nested receives were not handled properly.
+
+confusing_recv_mark(Pid) ->
+ Ref = make_ref(),
+ %% There would be a recv_mark here.
+ MRef = erlang:monitor(process, Pid),
+ receive
+ Ref ->
+ %% And a recv_set here.
+ receive
+ MRef -> gurka
+ end;
+ MRef ->
+ gaffel
+ end.
+
+%% The optimization could potentially be improved to
+%% handle matching of multiple refs, like this:
+
+proper_recv_mark(Pid) ->
+ %% Place the recv_mark before the creation of both refs.
+ Ref = make_ref(),
+ MRef = erlang:monitor(process, Pid),
+ %% Place the recv_set here.
+ receive
+ Ref ->
+ receive
+ MRef -> gurka
+ end;
+ MRef ->
+ gaffel
+ end.
diff --git a/lib/compiler/test/receive_SUITE_data/ref_opt/yes_14.S b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_14.S
deleted file mode 100644
index fd14228135..0000000000
--- a/lib/compiler/test/receive_SUITE_data/ref_opt/yes_14.S
+++ /dev/null
@@ -1,71 +0,0 @@
-{module, yes_14}. %% version = 0
-
-{exports, [{f,2},{module_info,0},{module_info,1},{yes_14,0}]}.
-
-{attributes, []}.
-
-{labels, 12}.
-
-
-{function, yes_14, 0, 2}.
- {label,1}.
- {func_info,{atom,yes_14},{atom,yes_14},0}.
- {label,2}.
- {move,{atom,ok},{x,0}}.
- return.
-
-
-{function, f, 2, 4}.
- {label,3}.
- {func_info,{atom,yes_14},{atom,f},2}.
- {label,4}.
- {allocate_heap,2,3,2}.
- {move,{x,0},{y,1}}.
- {put_tuple,2,{y,0}}.
- {put,{atom,data}}.
- {put,{x,1}}.
- {call_ext,0,{extfunc,erlang,make_ref,0}}. % Ref in [x0]
- {test_heap,4,1}.
- {put_tuple,3,{x,1}}.
- {put,{atom,request}}.
- {put,{x,0}}.
- {put,{y,0}}.
- {move,{x,0},{y,0}}. % Ref in [x0,y0]
- {move,{y,1},{x,0}}. % Ref in [y0]
- {kill,{y,1}}.
- send.
- {move,{y,0},{x,0}}. % Ref in [x0,y0]
- {move,{x,0},{y,1}}. % Ref in [x0,y0,y1]
- {label,5}.
- {loop_rec,{f,7},{x,0}}. % Ref in [y0,y1]
- {test,is_tuple,{f,6},[{x,0}]}.
- {test,test_arity,{f,6},[{x,0},2]}.
- {get_tuple_element,{x,0},0,{x,1}}.
- {get_tuple_element,{x,0},1,{x,2}}.
- {test,is_eq_exact,{f,6},[{x,1},{atom,reply}]}.
- {test,is_eq_exact,{f,6},[{x,2},{y,1}]}.
- remove_message.
- {move,{atom,ok},{x,0}}.
- {deallocate,2}.
- return.
- {label,6}.
- {loop_rec_end,{f,5}}.
- {label,7}.
- {wait,{f,5}}.
-
-
-{function, module_info, 0, 9}.
- {label,8}.
- {func_info,{atom,yes_14},{atom,module_info},0}.
- {label,9}.
- {move,{atom,yes_14},{x,0}}.
- {call_ext_only,1,{extfunc,erlang,get_module_info,1}}.
-
-
-{function, module_info, 1, 11}.
- {label,10}.
- {func_info,{atom,yes_14},{atom,module_info},1}.
- {label,11}.
- {move,{x,0},{x,1}}.
- {move,{atom,yes_14},{x,0}}.
- {call_ext_only,2,{extfunc,erlang,get_module_info,2}}.
diff --git a/lib/compiler/test/receive_SUITE_data/ref_opt/yes_14.erl b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_14.erl
new file mode 100644
index 0000000000..aa47c02af9
--- /dev/null
+++ b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_14.erl
@@ -0,0 +1,27 @@
+-module(yes_14).
+-compile(export_all).
+
+?MODULE() ->
+ ok.
+
+do_call(Process, Request) ->
+ Mref = erlang:monitor(process, Process),
+ Process ! Request,
+ Local = case node(Process) of
+ Node when Node =:= node() -> true;
+ _Node -> false
+ end,
+ id(Local),
+ receive
+ {X,Y,Z} when Mref =/= X, Z =:= 42, Mref =:= Y ->
+ error;
+ {X,Y,_} when Mref =/= X, Mref =:= Y ->
+ error;
+ {Mref, Reply} ->
+ erlang:demonitor(Mref, [flush]),
+ {ok, Reply};
+ {'DOWN', Mref, _, _, _} ->
+ error
+ end.
+
+id(I) -> I.
diff --git a/lib/compiler/test/record_SUITE.erl b/lib/compiler/test/record_SUITE.erl
index 118e0a241c..4ed7f39780 100644
--- a/lib/compiler/test/record_SUITE.erl
+++ b/lib/compiler/test/record_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/compiler/test/regressions_SUITE.erl b/lib/compiler/test/regressions_SUITE.erl
index f448d54933..9b0b9b0c38 100644
--- a/lib/compiler/test/regressions_SUITE.erl
+++ b/lib/compiler/test/regressions_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/compiler/test/test_lib.erl b/lib/compiler/test/test_lib.erl
index 8954a9f5fb..c6baa611ec 100644
--- a/lib/compiler/test/test_lib.erl
+++ b/lib/compiler/test/test_lib.erl
@@ -72,11 +72,9 @@ opt_opts(Mod) ->
{options,Opts} = lists:keyfind(options, 1, Comp),
lists:filter(fun(no_copt) -> true;
(no_postopt) -> true;
- (no_float_opt) -> true;
- (no_new_funs) -> true;
- (no_new_binaries) -> true;
- (no_new_apply) -> true;
- (no_gc_bifs) -> true;
+ (no_ssa_opt) -> true;
+ (no_recv_opt) -> true;
+ (no_ssa_float) -> true;
(no_stack_trimming) -> true;
(debug_info) -> true;
(inline) -> true;
diff --git a/lib/compiler/test/warnings_SUITE.erl b/lib/compiler/test/warnings_SUITE.erl
index 42ff4f6133..33d55996ad 100644
--- a/lib/compiler/test/warnings_SUITE.erl
+++ b/lib/compiler/test/warnings_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/compiler/vsn.mk b/lib/compiler/vsn.mk
index 355113a94d..c7e7fb6754 100644
--- a/lib/compiler/vsn.mk
+++ b/lib/compiler/vsn.mk
@@ -1 +1 @@
-COMPILER_VSN = 7.2.3
+COMPILER_VSN = 7.2.5
diff --git a/lib/configure.in.src b/lib/configure.in.src
deleted file mode 100644
index d507a5c0dd..0000000000
--- a/lib/configure.in.src
+++ /dev/null
@@ -1,62 +0,0 @@
-dnl
-dnl %CopyrightBegin%
-dnl
-dnl Copyright Ericsson AB 1999-2016. All Rights Reserved.
-dnl
-dnl Licensed under the Apache License, Version 2.0 (the "License");
-dnl you may not use this file except in compliance with the License.
-dnl You may obtain a copy of the License at
-dnl
-dnl http://www.apache.org/licenses/LICENSE-2.0
-dnl
-dnl Unless required by applicable law or agreed to in writing, software
-dnl distributed under the License is distributed on an "AS IS" BASIS,
-dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-dnl See the License for the specific language governing permissions and
-dnl limitations under the License.
-dnl
-dnl %CopyrightEnd%
-dnl
-
-dnl Turn off caching
-define([AC_CACHE_LOAD], )dnl
-define([AC_CACHE_SAVE], )dnl
-
-dnl Process this file with autoconf to produce a configure script.
-AC_INIT
-
-dnl
-dnl This is just to run configure in all applications that need it.
-dnl
-
-if test -z "$ERL_TOP" || test ! -d $ERL_TOP ; then
- AC_MSG_ERROR(You need to set the environment variable ERL_TOP!)
-fi
-erl_top=${ERL_TOP}
-AC_CONFIG_AUX_DIRS($erl_top/erts/autoconf)
-
-AC_ARG_ENABLE(bootstrap-only,
-[ --enable-bootstrap-only enable bootstrap only configuration],
-[ if test "X$enableval" = "Xyes"; then
- bootstrap_only=yes
- else
- bootstrap_only=no
- fi
-],
-bootstrap_only=no)
-
-# Multiple versions of autoconf generates code that
-# don't work on all platforms (e.g. SunOS 5.8) if
-# sub directories are soft links. Internally at Ericsson
-# some OTP application directories are soft links.
-# An added "/." solves this problem.
-
-@BOOTSTRAP_CONFIGURE_APPS@
-
-if test $bootstrap_only = no; then
-
-@NON_BOOTSTRAP_CONFIGURE_APPS@
-
-fi
-
-AC_OUTPUT
diff --git a/lib/crypto/c_src/Makefile.in b/lib/crypto/c_src/Makefile.in
index 31124ba477..cd0e5442e9 100644
--- a/lib/crypto/c_src/Makefile.in
+++ b/lib/crypto/c_src/Makefile.in
@@ -19,7 +19,6 @@
#
include $(ERL_TOP)/make/target.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
-include $(ERL_TOP)/make/$(TARGET)/otp_ded.mk
# ----------------------------------------------------
# Application version
@@ -31,23 +30,20 @@ VSN=$(CRYPTO_VSN)
# The following variables differ between systems.
# Set by configure.
# ----------------------------------------------------
-CC = $(DED_CC)
-LD = $(DED_LD)
+CC = @DED_CC@
+LD = @DED_LD@
SHELL = /bin/sh
-LIBS = $(DED_LIBS)
-LDFLAGS += $(DED_LDFLAGS)
-CFLAGS = $(DED_CFLAGS)
+LIBS = @DED_LIBS@
+LDFLAGS += @DED_LDFLAGS@
+CFLAGS = @DED_CFLAGS@ @SSL_FLAGS@
# From erts/configure
SSL_LIBDIR = @SSL_LIBDIR@
SSL_INCLUDE = @SSL_INCLUDE@
SSL_CRYPTO_LIBNAME = @SSL_CRYPTO_LIBNAME@
SSL_SSL_LIBNAME = @SSL_SSL_LIBNAME@
-SSL_FLAGS = @SSL_FLAGS@
-
-INCLUDES = $(SSL_INCLUDE) $(DED_INCLUDES)
-CFLAGS += $(SSL_FLAGS)
+INCLUDES = $(SSL_INCLUDE) @DED_INCLUDE@
ifeq ($(TYPE),debug)
TYPEMARKER = .debug
@@ -70,6 +66,11 @@ RELSYSDIR = $(RELEASE_PATH)/lib/crypto-$(VSN)
# ----------------------------------------------------
# Misc Macros
# ----------------------------------------------------
+
+PRIVDIR = ../priv
+OBJDIR = $(PRIVDIR)/obj/$(TARGET)
+LIBDIR = $(PRIVDIR)/lib/$(TARGET)
+
CRYPTO_OBJS = $(OBJDIR)/crypto$(TYPEMARKER).o
CALLBACK_OBJS = $(OBJDIR)/crypto_callback$(TYPEMARKER).o
NIF_MAKEFILE = $(PRIVDIR)/Makefile
@@ -80,19 +81,10 @@ NIF_ARCHIVE = $(LIBDIR)/crypto$(TYPEMARKER).a
TEST_ENGINE_OBJS = $(OBJDIR)/otp_test_engine$(TYPEMARKER).o
-ifeq ($(findstring win32,$(TARGET)), win32)
-NIF_LIB = $(LIBDIR)/crypto$(TYPEMARKER).dll
-CALLBACK_LIB = $(LIBDIR)/crypto_callback$(TYPEMARKER).dll
-TEST_ENGINE_LIB = $(LIBDIR)/otp_test_engine$(TYPEMARKER).dll
-else
-NIF_LIB = $(LIBDIR)/crypto$(TYPEMARKER).so
-CALLBACK_LIB = $(LIBDIR)/crypto_callback$(TYPEMARKER).so
-TEST_ENGINE_LIB = $(LIBDIR)/otp_test_engine$(TYPEMARKER).so
-endif
+NIF_LIB = $(LIBDIR)/crypto$(TYPEMARKER).@DED_EXT@
+CALLBACK_LIB = $(LIBDIR)/crypto_callback$(TYPEMARKER).@DED_EXT@
+TEST_ENGINE_LIB = $(LIBDIR)/otp_test_engine$(TYPEMARKER).@DED_EXT@
-ifeq ($(HOST_OS),)
-HOST_OS := $(shell $(ERL_TOP)/erts/autoconf/config.guess)
-endif
DYNAMIC_CRYPTO_LIB=@SSL_DYNAMIC_ONLY@
ifeq ($(DYNAMIC_CRYPTO_LIB),yes)
@@ -125,7 +117,7 @@ RANLIB=true
endif
ALL_CFLAGS = $(TYPE_FLAGS) $(EXTRA_FLAGS) $(INCLUDES)
-ALL_STATIC_CFLAGS = $(DED_STATIC_CFLAGS) $(INCLUDES)
+ALL_STATIC_CFLAGS = @DED_STATIC_CFLAGS@ $(INCLUDES)
# ----------------------------------------------------
# Targets
@@ -181,21 +173,13 @@ endif
clean:
-ifeq ($(findstring win32,$(TARGET)), win32)
- rm -f $(LIBDIR)/crypto.dll
- rm -f $(LIBDIR)/crypto.debug.dll
- rm -f $(LIBDIR)/crypto_callback.dll
- rm -f $(LIBDIR)/crypto_callback.debug.dll
- rm -f $(LIBDIR)/otp_test_engine.dll
-else
- rm -f $(LIBDIR)/crypto.so
- rm -f $(LIBDIR)/crypto.debug.so
- rm -f $(LIBDIR)/crypto.valgrind.so
- rm -f $(LIBDIR)/crypto_callback.so
- rm -f $(LIBDIR)/crypto_callback.debug.so
- rm -f $(LIBDIR)/crypto_callback.valgrind.so
- rm -f $(LIBDIR)/otp_test_engine.so
-endif
+ rm -f $(LIBDIR)/crypto.@DED_EXT@
+ rm -f $(LIBDIR)/crypto.debug.@DED_EXT@
+ rm -f $(LIBDIR)/crypto.valgrind.@DED_EXT@
+ rm -f $(LIBDIR)/crypto_callback.@DED_EXT@
+ rm -f $(LIBDIR)/crypto_callback.debug.@DED_EXT@
+ rm -f $(LIBDIR)/crypto_callback.valgrind.@DED_EXT@
+ rm -f $(LIBDIR)/otp_test_engine.@DED_EXT@
rm -f $(OBJDIR)/crypto.o
rm -f $(OBJDIR)/crypto_static.o
rm -f $(OBJDIR)/crypto.debug.o
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index 68d2c44b5e..d40d285f86 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -148,6 +148,23 @@
# define HAVE_DES_ede3_cfb_encrypt
#endif
+// SHA3:
+#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,1,1)
+// An error in beta releases of 1.1.1 fixed in production release
+# ifdef NID_sha3_224
+# define HAVE_SHA3_224
+# endif
+# ifdef NID_sha3_256
+# define HAVE_SHA3_256
+# endif
+#endif
+# ifdef NID_sha3_384
+# define HAVE_SHA3_384
+# endif
+# ifdef NID_sha3_512
+# define HAVE_SHA3_512
+# endif
+
#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION(0,9,8,'o') \
&& !defined(OPENSSL_NO_EC) \
&& !defined(OPENSSL_NO_ECDH) \
@@ -155,12 +172,11 @@
# define HAVE_EC
#endif
-// (test for == 1.1.1pre8)
-#if OPENSSL_VERSION_NUMBER == (PACKED_OPENSSL_VERSION_PLAIN(1,1,1) - 7) \
+// (test for >= 1.1.1pre8)
+#if OPENSSL_VERSION_NUMBER >= (PACKED_OPENSSL_VERSION_PLAIN(1,1,1) - 7) \
&& !defined(HAS_LIBRESSL) \
&& defined(HAVE_EC)
-// EXPERIMENTAL:
-# define HAVE_EDDH
+# define HAVE_ED_CURVE_DH
#endif
#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION(0,9,8,'c')
@@ -169,7 +185,9 @@
#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,1)
# define HAVE_EVP_AES_CTR
+# define HAVE_AEAD
# define HAVE_GCM
+# define HAVE_CCM
# define HAVE_CMAC
# if OPENSSL_VERSION_NUMBER < PACKED_OPENSSL_VERSION(1,0,1,'d')
# define HAVE_GCM_EVP_DECRYPT_BUG
@@ -178,19 +196,33 @@
#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,1,0)
# ifndef HAS_LIBRESSL
+# define HAVE_CHACHA20
# define HAVE_CHACHA20_POLY1305
# define HAVE_RSA_OAEP_MD
# endif
#endif
+// OPENSSL_VERSION_NUMBER >= 1.1.1-pre8
+#if OPENSSL_VERSION_NUMBER >= (PACKED_OPENSSL_VERSION_PLAIN(1,1,1)-7)
+# ifndef HAS_LIBRESSL
+# define HAVE_POLY1305
+# endif
+#endif
+
#if OPENSSL_VERSION_NUMBER <= PACKED_OPENSSL_VERSION(0,9,8,'l')
# define HAVE_ECB_IVEC_BUG
#endif
-#define HAVE_RSA_SSLV23_PADDING
-#if defined(HAS_LIBRESSL) \
- && LIBRESSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(2,6,1)
-# undef HAVE_RSA_SSLV23_PADDING
+#ifndef HAS_LIBRESSL
+# ifdef RSA_SSLV23_PADDING
+# define HAVE_RSA_SSLV23_PADDING
+# endif
+#endif
+
+#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)
+# ifdef RSA_PKCS1_PSS_PADDING
+# define HAVE_RSA_PKCS1_PSS_PADDING
+# endif
#endif
#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION(0,9,8,'h') \
@@ -515,14 +547,16 @@ static ERL_NIF_TERM evp_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF
static ERL_NIF_TERM rand_seed_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM aes_gcm_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM aes_gcm_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM aead_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM aead_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
#ifdef HAVE_GCM_EVP_DECRYPT_BUG
static ERL_NIF_TERM aes_gcm_decrypt_NO_EVP(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
#endif
-static ERL_NIF_TERM chacha20_poly1305_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM chacha20_poly1305_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM chacha20_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM chacha20_stream_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+
+static ERL_NIF_TERM poly1305_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM engine_by_id_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM engine_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
@@ -537,6 +571,7 @@ static ERL_NIF_TERM engine_remove_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE
static ERL_NIF_TERM engine_get_first_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM engine_get_next_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM engine_get_id_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM engine_get_name_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM engine_get_all_methods_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
/* helpers */
@@ -607,11 +642,14 @@ static ErlNifFunc nif_funcs[] = {
{"rand_seed_nif", 1, rand_seed_nif},
- {"aes_gcm_encrypt", 5, aes_gcm_encrypt},
- {"aes_gcm_decrypt", 5, aes_gcm_decrypt},
+ {"aead_encrypt", 6, aead_encrypt},
+ {"aead_decrypt", 6, aead_decrypt},
+
+ {"chacha20_stream_init", 2, chacha20_stream_init},
+ {"chacha20_stream_encrypt", 2, chacha20_stream_crypt},
+ {"chacha20_stream_decrypt", 2, chacha20_stream_crypt},
- {"chacha20_poly1305_encrypt", 4, chacha20_poly1305_encrypt},
- {"chacha20_poly1305_decrypt", 5, chacha20_poly1305_decrypt},
+ {"poly1305_nif", 2, poly1305_nif},
{"engine_by_id_nif", 1, engine_by_id_nif},
{"engine_init_nif", 1, engine_init_nif},
@@ -626,6 +664,7 @@ static ErlNifFunc nif_funcs[] = {
{"engine_get_first_nif", 0, engine_get_first_nif},
{"engine_get_next_nif", 1, engine_get_next_nif},
{"engine_get_id_nif", 1, engine_get_id_nif},
+ {"engine_get_name_nif", 1, engine_get_name_nif},
{"engine_get_all_methods_nif", 0, engine_get_all_methods_nif}
};
@@ -675,6 +714,15 @@ static ERL_NIF_TERM atom_onbasis;
static ERL_NIF_TERM atom_aes_cfb8;
static ERL_NIF_TERM atom_aes_cfb128;
+#ifdef HAVE_GCM
+static ERL_NIF_TERM atom_aes_gcm;
+#endif
+#ifdef HAVE_CCM
+static ERL_NIF_TERM atom_aes_ccm;
+#endif
+#ifdef HAVE_CHACHA20_POLY1305
+static ERL_NIF_TERM atom_chacha20_poly1305;
+#endif
#ifdef HAVE_ECB_IVEC_BUG
static ERL_NIF_TERM atom_aes_ecb;
static ERL_NIF_TERM atom_des_ecb;
@@ -685,8 +733,7 @@ static ERL_NIF_TERM atom_rsa;
static ERL_NIF_TERM atom_dss;
static ERL_NIF_TERM atom_ecdsa;
-#ifdef HAVE_EDDH
-static ERL_NIF_TERM atom_eddh;
+#ifdef HAVE_ED_CURVE_DH
static ERL_NIF_TERM atom_x25519;
static ERL_NIF_TERM atom_x448;
#endif
@@ -706,6 +753,10 @@ static ERL_NIF_TERM atom_sha224;
static ERL_NIF_TERM atom_sha256;
static ERL_NIF_TERM atom_sha384;
static ERL_NIF_TERM atom_sha512;
+static ERL_NIF_TERM atom_sha3_224;
+static ERL_NIF_TERM atom_sha3_256;
+static ERL_NIF_TERM atom_sha3_384;
+static ERL_NIF_TERM atom_sha3_512;
static ERL_NIF_TERM atom_md5;
static ERL_NIF_TERM atom_ripemd160;
@@ -791,6 +842,35 @@ static struct digest_type_t digest_types[] =
{NULL}
#endif
},
+ {{"sha3_224"},
+#ifdef HAVE_SHA3_224
+ {&EVP_sha3_224}
+#else
+ {NULL}
+#endif
+ },
+ {{"sha3_256"},
+#ifdef HAVE_SHA3_256
+ {&EVP_sha3_256}
+#else
+ {NULL}
+#endif
+ },
+ {{"sha3_384"},
+#ifdef HAVE_SHA3_384
+ {&EVP_sha3_384}
+#else
+ {NULL}
+#endif
+ },
+ {{"sha3_512"},
+#ifdef HAVE_SHA3_512
+ {&EVP_sha3_512}
+#else
+ {NULL}
+#endif
+ },
+
{{NULL}}
};
@@ -1083,6 +1163,15 @@ static int initialize(ErlNifEnv* env, ERL_NIF_TERM load_info)
#endif
atom_aes_cfb8 = enif_make_atom(env, "aes_cfb8");
atom_aes_cfb128 = enif_make_atom(env, "aes_cfb128");
+#ifdef HAVE_GCM
+ atom_aes_gcm = enif_make_atom(env, "aes_gcm");
+#endif
+#ifdef HAVE_CCM
+ atom_aes_ccm = enif_make_atom(env, "aes_ccm");
+#endif
+#ifdef HAVE_CHACHA20_POLY1305
+ atom_chacha20_poly1305 = enif_make_atom(env,"chacha20_poly1305");
+#endif
#ifdef HAVE_ECB_IVEC_BUG
atom_aes_ecb = enif_make_atom(env, "aes_ecb");
atom_des_ecb = enif_make_atom(env, "des_ecb");
@@ -1098,8 +1187,7 @@ static int initialize(ErlNifEnv* env, ERL_NIF_TERM load_info)
atom_rsa = enif_make_atom(env,"rsa");
atom_dss = enif_make_atom(env,"dss");
atom_ecdsa = enif_make_atom(env,"ecdsa");
-#ifdef HAVE_EDDH
- atom_eddh = enif_make_atom(env,"eddh");
+#ifdef HAVE_ED_CURVE_DH
atom_x25519 = enif_make_atom(env,"x25519");
atom_x448 = enif_make_atom(env,"x448");
#endif
@@ -1118,6 +1206,10 @@ static int initialize(ErlNifEnv* env, ERL_NIF_TERM load_info)
atom_sha256 = enif_make_atom(env,"sha256");
atom_sha384 = enif_make_atom(env,"sha384");
atom_sha512 = enif_make_atom(env,"sha512");
+ atom_sha3_224 = enif_make_atom(env,"sha3_224");
+ atom_sha3_256 = enif_make_atom(env,"sha3_256");
+ atom_sha3_384 = enif_make_atom(env,"sha3_384");
+ atom_sha3_512 = enif_make_atom(env,"sha3_512");
atom_md5 = enif_make_atom(env,"md5");
atom_ripemd160 = enif_make_atom(env,"ripemd160");
@@ -1238,15 +1330,17 @@ static void unload(ErlNifEnv* env, void* priv_data)
}
static int algo_hash_cnt, algo_hash_fips_cnt;
-static ERL_NIF_TERM algo_hash[8]; /* increase when extending the list */
+static ERL_NIF_TERM algo_hash[12]; /* increase when extending the list */
static int algo_pubkey_cnt, algo_pubkey_fips_cnt;
static ERL_NIF_TERM algo_pubkey[11]; /* increase when extending the list */
static int algo_cipher_cnt, algo_cipher_fips_cnt;
-static ERL_NIF_TERM algo_cipher[24]; /* increase when extending the list */
+static ERL_NIF_TERM algo_cipher[25]; /* increase when extending the list */
static int algo_mac_cnt, algo_mac_fips_cnt;
-static ERL_NIF_TERM algo_mac[2]; /* increase when extending the list */
+static ERL_NIF_TERM algo_mac[3]; /* increase when extending the list */
static int algo_curve_cnt, algo_curve_fips_cnt;
static ERL_NIF_TERM algo_curve[87]; /* increase when extending the list */
+static int algo_rsa_opts_cnt, algo_rsa_opts_fips_cnt;
+static ERL_NIF_TERM algo_rsa_opts[10]; /* increase when extending the list */
static void init_algorithms_types(ErlNifEnv* env)
{
@@ -1265,6 +1359,18 @@ static void init_algorithms_types(ErlNifEnv* env)
#ifdef HAVE_SHA512
algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha512");
#endif
+#ifdef HAVE_SHA3_224
+ algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha3_224");
+#endif
+#ifdef HAVE_SHA3_256
+ algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha3_256");
+#endif
+#ifdef HAVE_SHA3_384
+ algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha3_384");
+#endif
+#ifdef HAVE_SHA3_512
+ algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha3_512");
+#endif
// Non-validated algorithms follow
algo_hash_fips_cnt = algo_hash_cnt;
algo_hash[algo_hash_cnt++] = enif_make_atom(env, "md4");
@@ -1284,9 +1390,6 @@ static void init_algorithms_types(ErlNifEnv* env)
#endif
// Non-validated algorithms follow
algo_pubkey_fips_cnt = algo_pubkey_cnt;
-#ifdef HAVE_EDDH
- algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "eddh");
-#endif
algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "srp");
// Validated algorithms first
@@ -1309,6 +1412,9 @@ static void init_algorithms_types(ErlNifEnv* env)
#if defined(HAVE_GCM)
algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"aes_gcm");
#endif
+#if defined(HAVE_CCM)
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"aes_ccm");
+#endif
// Non-validated algorithms follow
algo_cipher_fips_cnt = algo_cipher_cnt;
#ifdef HAVE_AES_IGE
@@ -1332,13 +1438,19 @@ static void init_algorithms_types(ErlNifEnv* env)
#if defined(HAVE_CHACHA20_POLY1305)
algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"chacha20_poly1305");
#endif
-
+#if defined(HAVE_CHACHA20)
+ algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"chacha20");
+#endif
+
// Validated algorithms first
algo_mac_cnt = 0;
algo_mac[algo_mac_cnt++] = enif_make_atom(env,"hmac");
#ifdef HAVE_CMAC
algo_mac[algo_mac_cnt++] = enif_make_atom(env,"cmac");
#endif
+#ifdef HAVE_POLY1305
+ algo_mac[algo_mac_cnt++] = enif_make_atom(env,"poly1305");
+#endif
// Non-validated algorithms follow
algo_mac_fips_cnt = algo_mac_cnt;
@@ -1438,17 +1550,41 @@ static void init_algorithms_types(ErlNifEnv* env)
#endif
#endif
//--
-#ifdef HAVE_EDDH
+#ifdef HAVE_ED_CURVE_DH
algo_curve[algo_curve_cnt++] = enif_make_atom(env,"x25519");
algo_curve[algo_curve_cnt++] = enif_make_atom(env,"x448");
#endif
+ // Validated algorithms first
+ algo_rsa_opts_cnt = 0;
+#ifdef HAS_EVP_PKEY_CTX
+# ifdef HAVE_RSA_PKCS1_PSS_PADDING
+ algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_pkcs1_pss_padding");
+ algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_pss_saltlen");
+# endif
+ algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_mgf1_md");
+# ifdef HAVE_RSA_OAEP_MD
+ algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_oaep_label");
+ algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_oaep_md");
+# endif
+ algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"signature_md");
+#endif
+ algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_pkcs1_padding");
+ algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_x931_padding");
+#ifdef HAVE_RSA_SSLV23_PADDING
+ algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_sslv23_padding");
+#endif
+ algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_no_padding");
+ algo_rsa_opts_fips_cnt = algo_rsa_opts_cnt;
+
+
// Check that the max number of algos is updated
ASSERT(algo_hash_cnt <= sizeof(algo_hash)/sizeof(ERL_NIF_TERM));
ASSERT(algo_pubkey_cnt <= sizeof(algo_pubkey)/sizeof(ERL_NIF_TERM));
ASSERT(algo_cipher_cnt <= sizeof(algo_cipher)/sizeof(ERL_NIF_TERM));
ASSERT(algo_mac_cnt <= sizeof(algo_mac)/sizeof(ERL_NIF_TERM));
ASSERT(algo_curve_cnt <= sizeof(algo_curve)/sizeof(ERL_NIF_TERM));
+ ASSERT(algo_rsa_opts_cnt <= sizeof(algo_rsa_opts)/sizeof(ERL_NIF_TERM));
}
static ERL_NIF_TERM algorithms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -1460,19 +1596,22 @@ static ERL_NIF_TERM algorithms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
int cipher_cnt = fips_mode ? algo_cipher_fips_cnt : algo_cipher_cnt;
int mac_cnt = fips_mode ? algo_mac_fips_cnt : algo_mac_cnt;
int curve_cnt = fips_mode ? algo_curve_fips_cnt : algo_curve_cnt;
+ int rsa_opts_cnt = fips_mode ? algo_rsa_opts_fips_cnt : algo_rsa_opts_cnt;
#else
int hash_cnt = algo_hash_cnt;
int pubkey_cnt = algo_pubkey_cnt;
int cipher_cnt = algo_cipher_cnt;
int mac_cnt = algo_mac_cnt;
int curve_cnt = algo_curve_cnt;
+ int rsa_opts_cnt = algo_rsa_opts_cnt;
#endif
- return enif_make_tuple5(env,
+ return enif_make_tuple6(env,
enif_make_list_from_array(env, algo_hash, hash_cnt),
enif_make_list_from_array(env, algo_pubkey, pubkey_cnt),
enif_make_list_from_array(env, algo_cipher, cipher_cnt),
enif_make_list_from_array(env, algo_mac, mac_cnt),
- enif_make_list_from_array(env, algo_curve, curve_cnt)
+ enif_make_list_from_array(env, algo_curve, curve_cnt),
+ enif_make_list_from_array(env, algo_rsa_opts, rsa_opts_cnt)
);
}
@@ -2080,6 +2219,62 @@ static ERL_NIF_TERM cmac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
#endif
}
+/* For OpenSSL >= 1.1.1 the hmac_nif and cmac_nif could be integrated into poly1305 (with 'type' as parameter) */
+static ERL_NIF_TERM poly1305_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Key, Text) */
+#ifdef HAVE_POLY1305
+ ErlNifBinary key_bin, text, ret_bin;
+ ERL_NIF_TERM ret = atom_error;
+ EVP_PKEY *key = NULL;
+ EVP_MD_CTX *mctx = NULL;
+ EVP_PKEY_CTX *pctx = NULL;
+ const EVP_MD *md = NULL;
+ size_t size;
+ int type;
+
+ type = EVP_PKEY_POLY1305;
+
+ if (!enif_inspect_binary(env, argv[0], &key_bin) ||
+ !(key_bin.size == 32) ) {
+ return enif_make_badarg(env);
+ }
+
+ if (!enif_inspect_binary(env, argv[1], &text) ) {
+ return enif_make_badarg(env);
+ }
+
+ key = EVP_PKEY_new_raw_private_key(type, /*engine*/ NULL, key_bin.data, key_bin.size);
+
+ if (!key ||
+ !(mctx = EVP_MD_CTX_new()) ||
+ !EVP_DigestSignInit(mctx, &pctx, md, /*engine*/ NULL, key) ||
+ !EVP_DigestSignUpdate(mctx, text.data, text.size)) {
+ goto err;
+ }
+
+ if (!EVP_DigestSignFinal(mctx, NULL, &size) ||
+ !enif_alloc_binary(size, &ret_bin) ||
+ !EVP_DigestSignFinal(mctx, ret_bin.data, &size)) {
+ goto err;
+ }
+
+ if ((size != ret_bin.size) &&
+ !enif_realloc_binary(&ret_bin, size)) {
+ goto err;
+ }
+
+ ret = enif_make_binary(env, &ret_bin);
+
+ err:
+ EVP_MD_CTX_free(mctx);
+ EVP_PKEY_free(key);
+ return ret;
+
+#else
+ return atom_notsup;
+#endif
+}
+
static ERL_NIF_TERM block_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Type, Key, Ivec, Text, IsEncrypt) or (Type, Key, Text, IsEncrypt) */
struct cipher_type_t *cipherp = NULL;
@@ -2373,66 +2568,102 @@ static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_N
}
#endif /* !HAVE_EVP_AES_CTR */
-static ERL_NIF_TERM aes_gcm_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key,Iv,AAD,In) */
-#if defined(HAVE_GCM)
+static ERL_NIF_TERM aead_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Type,Key,Iv,AAD,In) */
+#if defined(HAVE_AEAD)
EVP_CIPHER_CTX *ctx;
const EVP_CIPHER *cipher = NULL;
ErlNifBinary key, iv, aad, in;
unsigned int tag_len;
unsigned char *outp, *tagp;
- ERL_NIF_TERM out, out_tag;
- int len;
+ ERL_NIF_TERM type, out, out_tag;
+ int len, ctx_ctrl_set_ivlen, ctx_ctrl_get_tag;
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
- || (key.size != 16 && key.size != 24 && key.size != 32)
- || !enif_inspect_binary(env, argv[1], &iv) || iv.size == 0
- || !enif_inspect_iolist_as_binary(env, argv[2], &aad)
- || !enif_inspect_iolist_as_binary(env, argv[3], &in)
- || !enif_get_uint(env, argv[4], &tag_len) || tag_len < 1 || tag_len > 16) {
+ type = argv[0];
+
+ if (!enif_is_atom(env, type)
+ || !enif_inspect_iolist_as_binary(env, argv[1], &key)
+ || !enif_inspect_binary(env, argv[2], &iv)
+ || !enif_inspect_iolist_as_binary(env, argv[3], &aad)
+ || !enif_inspect_iolist_as_binary(env, argv[4], &in)
+ || !enif_get_uint(env, argv[5], &tag_len)) {
return enif_make_badarg(env);
}
- if (key.size == 16)
- cipher = EVP_aes_128_gcm();
- else if (key.size == 24)
- cipher = EVP_aes_192_gcm();
- else if (key.size == 32)
- cipher = EVP_aes_256_gcm();
-
+ /* Use cipher_type some day. Must check block_encrypt|decrypt first */
+#if defined(HAVE_GCM)
+ if (type == atom_aes_gcm) {
+ if ((iv.size > 0)
+ && (1 <= tag_len && tag_len <= 16)) {
+ ctx_ctrl_set_ivlen = EVP_CTRL_GCM_SET_IVLEN;
+ ctx_ctrl_get_tag = EVP_CTRL_GCM_GET_TAG;
+ if (key.size == 16) cipher = EVP_aes_128_gcm();
+ else if (key.size == 24) cipher = EVP_aes_192_gcm();
+ else if (key.size == 32) cipher = EVP_aes_256_gcm();
+ else enif_make_badarg(env);
+ } else
+ enif_make_badarg(env);
+ } else
+#endif
+#if defined(HAVE_CCM)
+ if (type == atom_aes_ccm) {
+ if ((7 <= iv.size && iv.size <= 13)
+ && (4 <= tag_len && tag_len <= 16)
+ && ((tag_len & 1) == 0)
+ ) {
+ ctx_ctrl_set_ivlen = EVP_CTRL_CCM_SET_IVLEN;
+ ctx_ctrl_get_tag = EVP_CTRL_CCM_GET_TAG;
+ if (key.size == 16) cipher = EVP_aes_128_ccm();
+ else if (key.size == 24) cipher = EVP_aes_192_ccm();
+ else if (key.size == 32) cipher = EVP_aes_256_ccm();
+ else enif_make_badarg(env);
+ } else
+ enif_make_badarg(env);
+ } else
+#endif
+#if defined(HAVE_CHACHA20_POLY1305)
+ if (type == atom_chacha20_poly1305) {
+ if ((key.size == 32)
+ && (1 <= iv.size && iv.size <= 16)
+ && (tag_len == 16)
+ ) {
+ ctx_ctrl_set_ivlen = EVP_CTRL_AEAD_SET_IVLEN;
+ ctx_ctrl_get_tag = EVP_CTRL_AEAD_GET_TAG,
+ cipher = EVP_chacha20_poly1305();
+ } else enif_make_badarg(env);
+ } else
+#endif
+ return enif_raise_exception(env, atom_notsup);
+
ctx = EVP_CIPHER_CTX_new();
+ if (EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1) goto out_err;
+ if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_set_ivlen, iv.size, NULL) != 1) goto out_err;
+
+#if defined(HAVE_CCM)
+ if (type == atom_aes_ccm) {
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, tag_len, NULL) != 1) goto out_err;
+ if (EVP_EncryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1) goto out_err;
+ if (EVP_EncryptUpdate(ctx, NULL, &len, NULL, in.size) != 1) goto out_err;
+ } else
+#endif
+ if (EVP_EncryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1) goto out_err;
- if (EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1)
- goto out_err;
-
- EVP_CIPHER_CTX_set_padding(ctx, 0);
-
- if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv.size, NULL) != 1)
- goto out_err;
- if (EVP_EncryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1)
- goto out_err;
- if (EVP_EncryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1)
- goto out_err;
+ if (EVP_EncryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1) goto out_err;
outp = enif_make_new_binary(env, in.size, &out);
- if (EVP_EncryptUpdate(ctx, outp, &len, in.data, in.size) != 1)
- goto out_err;
- if (EVP_EncryptFinal_ex(ctx, outp+len, &len) != 1)
- goto out_err;
+ if (EVP_EncryptUpdate(ctx, outp, &len, in.data, in.size) != 1) goto out_err;
+ if (EVP_EncryptFinal_ex(ctx, outp/*+len*/, &len) != 1) goto out_err;
tagp = enif_make_new_binary(env, tag_len, &out_tag);
- if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, tag_len, tagp) != 1)
- goto out_err;
+ if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_get_tag, tag_len, tagp) != 1) goto out_err;
EVP_CIPHER_CTX_free(ctx);
-
CONSUME_REDS(env, in);
-
return enif_make_tuple2(env, out, out_tag);
-out_err:
+out_err:
EVP_CIPHER_CTX_free(ctx);
return atom_error;
@@ -2441,58 +2672,103 @@ out_err:
#endif
}
-static ERL_NIF_TERM aes_gcm_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key,Iv,AAD,In,Tag) */
-#if defined(HAVE_GCM_EVP_DECRYPT_BUG)
- return aes_gcm_decrypt_NO_EVP(env, argc, argv);
-#elif defined(HAVE_GCM)
+static ERL_NIF_TERM aead_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Type,Key,Iv,AAD,In,Tag) */
+#if defined(HAVE_AEAD)
EVP_CIPHER_CTX *ctx;
const EVP_CIPHER *cipher = NULL;
ErlNifBinary key, iv, aad, in, tag;
unsigned char *outp;
- ERL_NIF_TERM out;
- int len;
+ ERL_NIF_TERM type, out;
+ int len, ctx_ctrl_set_ivlen, ctx_ctrl_set_tag;
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
- || (key.size != 16 && key.size != 24 && key.size != 32)
- || !enif_inspect_binary(env, argv[1], &iv) || iv.size == 0
- || !enif_inspect_iolist_as_binary(env, argv[2], &aad)
- || !enif_inspect_iolist_as_binary(env, argv[3], &in)
- || !enif_inspect_iolist_as_binary(env, argv[4], &tag)) {
+ type = argv[0];
+#if defined(HAVE_GCM_EVP_DECRYPT_BUG)
+ if (type == atom_aes_gcm)
+ return aes_gcm_decrypt_NO_EVP(env, argc, argv);
+#endif
+
+ if (!enif_is_atom(env, type)
+ || !enif_inspect_iolist_as_binary(env, argv[1], &key)
+ || !enif_inspect_binary(env, argv[2], &iv)
+ || !enif_inspect_iolist_as_binary(env, argv[3], &aad)
+ || !enif_inspect_iolist_as_binary(env, argv[4], &in)
+ || !enif_inspect_iolist_as_binary(env, argv[5], &tag)) {
return enif_make_badarg(env);
}
- if (key.size == 16)
- cipher = EVP_aes_128_gcm();
- else if (key.size == 24)
- cipher = EVP_aes_192_gcm();
- else if (key.size == 32)
- cipher = EVP_aes_256_gcm();
+ /* Use cipher_type some day. Must check block_encrypt|decrypt first */
+#if defined(HAVE_GCM)
+ if (type == atom_aes_gcm) {
+ if (iv.size > 0) {
+ ctx_ctrl_set_ivlen = EVP_CTRL_GCM_SET_IVLEN;
+ ctx_ctrl_set_tag = EVP_CTRL_GCM_SET_TAG;
+ if (key.size == 16) cipher = EVP_aes_128_gcm();
+ else if (key.size == 24) cipher = EVP_aes_192_gcm();
+ else if (key.size == 32) cipher = EVP_aes_256_gcm();
+ else enif_make_badarg(env);
+ } else
+ enif_make_badarg(env);
+ } else
+#endif
+#if defined(HAVE_CCM)
+ if (type == atom_aes_ccm) {
+ if (iv.size > 0) {
+ ctx_ctrl_set_ivlen = EVP_CTRL_CCM_SET_IVLEN;
+ if (key.size == 16) cipher = EVP_aes_128_ccm();
+ else if (key.size == 24) cipher = EVP_aes_192_ccm();
+ else if (key.size == 32) cipher = EVP_aes_256_ccm();
+ else enif_make_badarg(env);
+ } else
+ enif_make_badarg(env);
+ } else
+#endif
+#if defined(HAVE_CHACHA20_POLY1305)
+ if (type == atom_chacha20_poly1305) {
+ if ((key.size == 32)
+ && (1 <= iv.size && iv.size <= 16)
+ && tag.size == 16
+ ) {
+ ctx_ctrl_set_ivlen = EVP_CTRL_AEAD_SET_IVLEN;
+ ctx_ctrl_set_tag = EVP_CTRL_AEAD_SET_TAG;
+ cipher = EVP_chacha20_poly1305();
+ } else enif_make_badarg(env);
+ } else
+#endif
+ return enif_raise_exception(env, atom_notsup);
+
+ outp = enif_make_new_binary(env, in.size, &out);
ctx = EVP_CIPHER_CTX_new();
+ if (EVP_DecryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1) goto out_err;
+ if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_set_ivlen, iv.size, NULL) != 1) goto out_err;
- if (EVP_DecryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1)
- goto out_err;
- if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv.size, NULL) != 1)
- goto out_err;
- if (EVP_DecryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1)
- goto out_err;
- if (EVP_DecryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1)
- goto out_err;
+#if defined(HAVE_CCM)
+ if (type == atom_aes_ccm) {
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, tag.size, tag.data) != 1) goto out_err;
+ }
+#endif
- outp = enif_make_new_binary(env, in.size, &out);
+ if (EVP_DecryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1) goto out_err;
- if (EVP_DecryptUpdate(ctx, outp, &len, in.data, in.size) != 1)
- goto out_err;
- if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, tag.size, tag.data) != 1)
- goto out_err;
- if (EVP_DecryptFinal_ex(ctx, outp+len, &len) != 1)
- goto out_err;
+#if defined(HAVE_CCM)
+ if (type == atom_aes_ccm) {
+ if (1 != EVP_DecryptUpdate(ctx, NULL, &len, NULL, in.size)) goto out_err;
+ }
+#endif
+ if (EVP_DecryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1) goto out_err;
+ if (EVP_DecryptUpdate(ctx, outp, &len, in.data, in.size) != 1) goto out_err;
+
+#if defined(HAVE_GCM) || defined(HAVE_CHACHA20_POLY1305)
+ if (type == atom_aes_gcm) {
+ if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_set_tag, tag.size, tag.data) != 1) goto out_err;
+ if (EVP_DecryptFinal_ex(ctx, outp+len, &len) != 1) goto out_err;
+ }
+#endif
EVP_CIPHER_CTX_free(ctx);
CONSUME_REDS(env, in);
-
return out;
out_err:
@@ -2505,19 +2781,19 @@ out_err:
#ifdef HAVE_GCM_EVP_DECRYPT_BUG
static ERL_NIF_TERM aes_gcm_decrypt_NO_EVP(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{
+{/* (Type,Key,Iv,AAD,In,Tag) */
GCM128_CONTEXT *ctx;
ErlNifBinary key, iv, aad, in, tag;
AES_KEY aes_key;
unsigned char *outp;
ERL_NIF_TERM out;
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key)
+ if (!enif_inspect_iolist_as_binary(env, argv[1], &key)
|| AES_set_encrypt_key(key.data, key.size*8, &aes_key) != 0
- || !enif_inspect_binary(env, argv[1], &iv) || iv.size == 0
- || !enif_inspect_iolist_as_binary(env, argv[2], &aad)
- || !enif_inspect_iolist_as_binary(env, argv[3], &in)
- || !enif_inspect_iolist_as_binary(env, argv[4], &tag)) {
+ || !enif_inspect_binary(env, argv[2], &iv) || iv.size == 0
+ || !enif_inspect_iolist_as_binary(env, argv[3], &aad)
+ || !enif_inspect_iolist_as_binary(env, argv[4], &in)
+ || !enif_inspect_iolist_as_binary(env, argv[5], &tag)) {
return enif_make_badarg(env);
}
@@ -2551,118 +2827,67 @@ out_err:
#endif /* HAVE_GCM_EVP_DECRYPT_BUG */
-static ERL_NIF_TERM chacha20_poly1305_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key,Iv,AAD,In) */
-#if defined(HAVE_CHACHA20_POLY1305)
- EVP_CIPHER_CTX *ctx;
- const EVP_CIPHER *cipher = NULL;
- ErlNifBinary key, iv, aad, in;
- unsigned char *outp, *tagp;
- ERL_NIF_TERM out, out_tag;
- int len;
+static ERL_NIF_TERM chacha20_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Key, IV) */
+#if defined(HAVE_CHACHA20)
+ ErlNifBinary key_bin, ivec_bin;
+ struct evp_cipher_ctx *ctx;
+ const EVP_CIPHER *cipher;
+ ERL_NIF_TERM ret;
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 32
- || !enif_inspect_binary(env, argv[1], &iv) || iv.size == 0 || iv.size > 16
- || !enif_inspect_iolist_as_binary(env, argv[2], &aad)
- || !enif_inspect_iolist_as_binary(env, argv[3], &in)) {
- return enif_make_badarg(env);
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
+ || !enif_inspect_binary(env, argv[1], &ivec_bin)
+ || key_bin.size != 32
+ || ivec_bin.size != 16) {
+ return enif_make_badarg(env);
}
- cipher = EVP_chacha20_poly1305();
-
- ctx = EVP_CIPHER_CTX_new();
-
- if (EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1)
- goto out_err;
-
- EVP_CIPHER_CTX_set_padding(ctx, 0);
-
- if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, iv.size, NULL) != 1)
- goto out_err;
- if (EVP_EncryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1)
- goto out_err;
- if (EVP_EncryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1)
- goto out_err;
-
- outp = enif_make_new_binary(env, in.size, &out);
-
- if (EVP_EncryptUpdate(ctx, outp, &len, in.data, in.size) != 1)
- goto out_err;
- if (EVP_EncryptFinal_ex(ctx, outp+len, &len) != 1)
- goto out_err;
+ cipher = EVP_chacha20();
- tagp = enif_make_new_binary(env, 16, &out_tag);
-
- if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, tagp) != 1)
- goto out_err;
-
- EVP_CIPHER_CTX_free(ctx);
-
- CONSUME_REDS(env, in);
+ ctx = enif_alloc_resource(evp_cipher_ctx_rtype, sizeof(struct evp_cipher_ctx));
+ ctx->ctx = EVP_CIPHER_CTX_new();
- return enif_make_tuple2(env, out, out_tag);
-out_err:
- EVP_CIPHER_CTX_free(ctx);
- return atom_error;
+ EVP_CipherInit_ex(ctx->ctx, cipher, NULL,
+ key_bin.data, ivec_bin.data, 1);
+ EVP_CIPHER_CTX_set_padding(ctx->ctx, 0);
+ ret = enif_make_resource(env, ctx);
+ enif_release_resource(ctx);
+ return ret;
#else
return enif_raise_exception(env, atom_notsup);
#endif
-}
+};
-static ERL_NIF_TERM chacha20_poly1305_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Key,Iv,AAD,In,Tag) */
-#if defined(HAVE_CHACHA20_POLY1305)
- EVP_CIPHER_CTX *ctx;
- const EVP_CIPHER *cipher = NULL;
- ErlNifBinary key, iv, aad, in, tag;
- unsigned char *outp;
- ERL_NIF_TERM out;
- int len;
+static ERL_NIF_TERM chacha20_stream_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (State, Data) */
+#if defined(HAVE_CHACHA20)
+ struct evp_cipher_ctx *ctx, *new_ctx;
+ ErlNifBinary data_bin;
+ ERL_NIF_TERM ret, cipher_term;
+ unsigned char *out;
+ int outl = 0;
- if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 32
- || !enif_inspect_binary(env, argv[1], &iv) || iv.size == 0 || iv.size > 16
- || !enif_inspect_iolist_as_binary(env, argv[2], &aad)
- || !enif_inspect_iolist_as_binary(env, argv[3], &in)
- || !enif_inspect_iolist_as_binary(env, argv[4], &tag) || tag.size != 16) {
- return enif_make_badarg(env);
+ if (!enif_get_resource(env, argv[0], evp_cipher_ctx_rtype, (void**)&ctx)
+ || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
+ return enif_make_badarg(env);
}
+ new_ctx = enif_alloc_resource(evp_cipher_ctx_rtype, sizeof(struct evp_cipher_ctx));
+ new_ctx->ctx = EVP_CIPHER_CTX_new();
+ EVP_CIPHER_CTX_copy(new_ctx->ctx, ctx->ctx);
+ out = enif_make_new_binary(env, data_bin.size, &cipher_term);
+ EVP_CipherUpdate(new_ctx->ctx, out, &outl, data_bin.data, data_bin.size);
+ ASSERT(outl == data_bin.size);
- cipher = EVP_chacha20_poly1305();
-
- ctx = EVP_CIPHER_CTX_new();
-
- if (EVP_DecryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1)
- goto out_err;
- if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, iv.size, NULL) != 1)
- goto out_err;
- if (EVP_DecryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1)
- goto out_err;
- if (EVP_DecryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1)
- goto out_err;
-
- outp = enif_make_new_binary(env, in.size, &out);
-
- if (EVP_DecryptUpdate(ctx, outp, &len, in.data, in.size) != 1)
- goto out_err;
- if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, tag.size, tag.data) != 1)
- goto out_err;
- if (EVP_DecryptFinal_ex(ctx, outp+len, &len) != 1)
- goto out_err;
-
- EVP_CIPHER_CTX_free(ctx);
-
- CONSUME_REDS(env, in);
-
- return out;
-
-out_err:
- EVP_CIPHER_CTX_free(ctx);
- return atom_error;
+ ret = enif_make_tuple2(env, enif_make_resource(env, new_ctx), cipher_term);
+ enif_release_resource(new_ctx);
+ CONSUME_REDS(env,data_bin);
+ return ret;
#else
return enif_raise_exception(env, atom_notsup);
#endif
-}
+};
+
static ERL_NIF_TERM strong_rand_bytes_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Bytes) */
@@ -3944,11 +4169,10 @@ out_err:
#endif
}
-// EXPERIMENTAL!
static ERL_NIF_TERM evp_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
/* (Curve, PeerBin, MyBin) */
{
-#ifdef HAVE_EDDH
+#ifdef HAVE_ED_CURVE_DH
int type;
EVP_PKEY_CTX *ctx;
ErlNifBinary peer_bin, my_bin, key_bin;
@@ -4000,11 +4224,10 @@ static ERL_NIF_TERM evp_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_
#endif
}
-// EXPERIMENTAL!
static ERL_NIF_TERM evp_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
/* (Curve) */
{
-#ifdef HAVE_EDDH
+#ifdef HAVE_ED_CURVE_DH
int type;
EVP_PKEY_CTX *ctx;
EVP_PKEY *pkey = NULL;
@@ -4017,22 +4240,20 @@ static ERL_NIF_TERM evp_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF
if (!(ctx = EVP_PKEY_CTX_new_id(type, NULL))) return enif_make_badarg(env);
- if (!EVP_PKEY_keygen_init(ctx)) return enif_make_atom(env,"EVP_PKEY_keygen_init failed");
- if (!EVP_PKEY_keygen(ctx, &pkey)) return enif_make_atom(env,"EVP_PKEY_keygen failed");
+ if (!EVP_PKEY_keygen_init(ctx)) return atom_error;
+ if (!EVP_PKEY_keygen(ctx, &pkey)) return atom_error;
- if (!EVP_PKEY_get_raw_public_key(pkey, NULL, &key_len))
- return enif_make_atom(env,"EVP_PKEY_get_raw_public_key 1 failed");
+ if (!EVP_PKEY_get_raw_public_key(pkey, NULL, &key_len)) return atom_error;
if (!EVP_PKEY_get_raw_public_key(pkey,
enif_make_new_binary(env, key_len, &ret_pub),
&key_len))
- return enif_make_atom(env,"EVP_PKEY_get_raw_public_key 2 failed");
+ return atom_error;
- if (!EVP_PKEY_get_raw_private_key(pkey, NULL, &key_len))
- return enif_make_atom(env,"EVP_PKEY_get_raw_private_key 1 failed");
+ if (!EVP_PKEY_get_raw_private_key(pkey, NULL, &key_len)) return atom_error;
if (!EVP_PKEY_get_raw_private_key(pkey,
enif_make_new_binary(env, key_len, &ret_prv),
&key_len))
- return enif_make_atom(env,"EVP_PKEY_get_raw_private_key 2 failed");
+ return atom_error;
return enif_make_tuple2(env, ret_pub, ret_prv);
#else
@@ -4183,7 +4404,7 @@ static int get_pkey_sign_options(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF
if (tpl_terms[1] == atom_rsa_pkcs1_padding) {
opt->rsa_padding = RSA_PKCS1_PADDING;
} else if (tpl_terms[1] == atom_rsa_pkcs1_pss_padding) {
-#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)
+#ifdef HAVE_RSA_PKCS1_PSS_PADDING
opt->rsa_padding = RSA_PKCS1_PSS_PADDING;
if (opt->rsa_mgf1_md == NULL) {
opt->rsa_mgf1_md = md;
@@ -4472,6 +4693,7 @@ printf("\r\n");
if (argv[0] == atom_rsa) {
if (EVP_PKEY_CTX_set_rsa_padding(ctx, sig_opt.rsa_padding) <= 0) goto badarg;
+#ifdef HAVE_RSA_PKCS1_PSS_PADDING
if (sig_opt.rsa_padding == RSA_PKCS1_PSS_PADDING) {
if (sig_opt.rsa_mgf1_md != NULL) {
#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,1)
@@ -4486,6 +4708,7 @@ printf("\r\n");
&& EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, sig_opt.rsa_pss_saltlen) <= 0)
goto badarg;
}
+#endif
}
if (EVP_PKEY_sign(ctx, NULL, &siglen, tbs, tbslen) <= 0) goto badarg;
@@ -4967,7 +5190,7 @@ static ERL_NIF_TERM pkey_crypt_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM
} else {
/* non-evp rsa private decrypt */
i = RSA_private_decrypt(in_bin.size, in_bin.data,
- out_bin.data, rsa, crypt_opt.rsa_padding);
+ out_bin.data, rsa, crypt_opt.rsa_padding);
if (i > 0) {
ERL_VALGRIND_MAKE_MEM_DEFINED(out_bin.data, i);
enif_realloc_binary(&out_bin, i);
@@ -4985,7 +5208,7 @@ static ERL_NIF_TERM pkey_crypt_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM
} else {
/* non-evp rsa public decrypt */
i = RSA_public_decrypt(in_bin.size, in_bin.data,
- out_bin.data, rsa, crypt_opt.rsa_padding);
+ out_bin.data, rsa, crypt_opt.rsa_padding);
if (i > 0) {
ERL_VALGRIND_MAKE_MEM_DEFINED(out_bin.data, i);
enif_realloc_binary(&out_bin, i);
@@ -5004,7 +5227,10 @@ static ERL_NIF_TERM pkey_crypt_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM
unsigned char *p;
if (rsa == NULL) goto badarg;
tmplen = RSA_size(rsa);
- if (!enif_alloc_binary(tmplen, &tmp_bin)) goto badarg;
+ if (!enif_alloc_binary(tmplen, &tmp_bin)) {
+ RSA_free(rsa);
+ goto badarg;
+ }
p = out_bin.data;
p++;
i = RSA_padding_check_SSLv23(tmp_bin.data, tmplen, p, out_bin.size - 1, tmplen);
@@ -5015,6 +5241,7 @@ static ERL_NIF_TERM pkey_crypt_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM
tmp_bin = in_bin;
i = 1;
}
+ RSA_free(rsa);
}
#endif
}
@@ -5103,7 +5330,7 @@ static ERL_NIF_TERM privkey_to_pubkey_nif(ErlNifEnv* env, int argc, const ERL_NI
/ * Example of result:
{
Curve = {Field, Prime, Point, Order, CoFactor} =
- {
+ {
Field = {prime_field,<<255,...,255>>},
Prime = {<<255,...,252>>,
<<90,...,75>>,
@@ -5116,9 +5343,9 @@ static ERL_NIF_TERM privkey_to_pubkey_nif(ErlNifEnv* env, int argc, const ERL_NI
Key = <<151,...,62>>
}
or
- {
+ {
Curve =
- {characteristic_two_field,
+ {characteristic_two_field,
M,
Basis = {tpbasis, _}
| {ppbasis, k1, k2, k3}
@@ -5131,7 +5358,7 @@ static ERL_NIF_TERM privkey_to_pubkey_nif(ErlNifEnv* env, int argc, const ERL_NI
*/
#endif
}
-
+
if (pkey) EVP_PKEY_free(pkey);
return enif_make_badarg(env);
}
@@ -5312,7 +5539,7 @@ static ERL_NIF_TERM engine_ctrl_cmd_strings_nif(ErlNifEnv* env, int argc, const
error:
for(i = 0; cmds != NULL && cmds[i] != NULL; i++)
- enif_free(cmds[i]);
+ enif_free(cmds[i]);
enif_free(cmds);
return ret;
#else
@@ -5630,7 +5857,7 @@ static ERL_NIF_TERM engine_get_id_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE
if (!engine_id) {
enif_alloc_binary(0, &engine_id_bin);
engine_id_bin.size = 0;
- return enif_make_tuple2(env, atom_ok, enif_make_binary(env, &engine_id_bin));
+ return enif_make_binary(env, &engine_id_bin);
}
size = strlen(engine_id);
@@ -5638,7 +5865,39 @@ static ERL_NIF_TERM engine_get_id_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE
engine_id_bin.size = size;
memcpy(engine_id_bin.data, engine_id, size);
- return enif_make_tuple2(env, atom_ok, enif_make_binary(env, &engine_id_bin));
+ return enif_make_binary(env, &engine_id_bin);
+#else
+ return atom_notsup;
+#endif
+}
+
+static ERL_NIF_TERM engine_get_name_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Engine) */
+#ifdef HAS_ENGINE_SUPPORT
+ ErlNifBinary engine_name_bin;
+ const char *engine_name;
+ int size;
+ struct engine_ctx *ctx;
+
+ // Get Engine
+ if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) {
+ PRINTF_ERR0("engine_get_id_nif Leaved: Parameter not an engine resource object");
+ return enif_make_badarg(env);
+ }
+
+ engine_name = ENGINE_get_name(ctx->engine);
+ if (!engine_name) {
+ enif_alloc_binary(0, &engine_name_bin);
+ engine_name_bin.size = 0;
+ return enif_make_binary(env, &engine_name_bin);
+ }
+
+ size = strlen(engine_name);
+ enif_alloc_binary(size, &engine_name_bin);
+ engine_name_bin.size = size;
+ memcpy(engine_name_bin.data, engine_name, size);
+
+ return enif_make_binary(env, &engine_name_bin);
#else
return atom_notsup;
#endif
diff --git a/lib/crypto/c_src/otp_test_engine.c b/lib/crypto/c_src/otp_test_engine.c
index b6c9067964..34c825059f 100644
--- a/lib/crypto/c_src/otp_test_engine.c
+++ b/lib/crypto/c_src/otp_test_engine.c
@@ -64,7 +64,8 @@ static int test_init(ENGINE *e) {
printf("OTP Test Engine Initializatzion!\r\n");
/* Load all digest and cipher algorithms. Needed for password protected private keys */
- OpenSSL_add_all_algorithms();
+ OpenSSL_add_all_ciphers();
+ OpenSSL_add_all_digests();
return 111;
}
diff --git a/lib/crypto/configure.in b/lib/crypto/configure.in
new file mode 100644
index 0000000000..a3b6673f29
--- /dev/null
+++ b/lib/crypto/configure.in
@@ -0,0 +1,775 @@
+dnl Process this file with autoconf to produce a configure script. -*-m4-*-
+dnl
+dnl %CopyrightBegin%
+dnl
+dnl Copyright Ericsson AB 2018. All Rights Reserved.
+dnl
+dnl Licensed under the Apache License, Version 2.0 (the "License");
+dnl you may not use this file except in compliance with the License.
+dnl You may obtain a copy of the License at
+dnl
+dnl http://www.apache.org/licenses/LICENSE-2.0
+dnl
+dnl Unless required by applicable law or agreed to in writing, software
+dnl distributed under the License is distributed on an "AS IS" BASIS,
+dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+dnl See the License for the specific language governing permissions and
+dnl limitations under the License.
+dnl
+dnl %CopyrightEnd%
+dnl
+
+dnl define([AC_CACHE_LOAD], )dnl
+dnl define([AC_CACHE_SAVE], )dnl
+
+
+AC_INIT(vsn.mk)
+
+if test -z "$ERL_TOP" || test ! -d "$ERL_TOP" ; then
+ AC_CONFIG_AUX_DIRS(autoconf)
+else
+ erl_top=${ERL_TOP}
+ AC_CONFIG_AUX_DIRS($erl_top/erts/autoconf)
+fi
+
+if test "X$host" != "Xfree_source" -a "X$host" != "Xwin32"; then
+ AC_CANONICAL_HOST
+else
+ host_os=win32
+fi
+
+LM_PRECIOUS_VARS
+
+if test "$cross_compiling" = "yes"; then
+ CROSS_COMPILING=yes
+else
+ CROSS_COMPILING=no
+fi
+AC_SUBST(CROSS_COMPILING)
+
+ERL_XCOMP_SYSROOT_INIT
+
+AC_PROG_CC
+LM_WINDOWS_ENVIRONMENT
+
+ERL_DED
+
+dnl
+dnl SSL, SSH and CRYPTO need the OpenSSL libraries
+dnl
+dnl Check flags --with-ssl, --without-ssl --with-ssl=PATH.
+dnl If no option is given or --with-ssl is set without a path then we
+dnl search for OpenSSL libraries and header files in the standard locations.
+dnl If set to --without-ssl we disable the use of SSL, SSH and CRYPTO.
+dnl If set to --with-ssl=PATH we use that path as the prefix, i.e. we
+dnl use "PATH/include" and "PATH/lib".
+
+AC_CHECK_SIZEOF(void *)
+
+std_ssl_locations="/usr/local /usr/sfw /usr /opt/local /usr/pkg /usr/local/openssl /usr/lib/openssl /usr/openssl /usr/local/ssl /usr/lib/ssl /usr/ssl /"
+
+AC_ARG_WITH(ssl-zlib,
+AS_HELP_STRING([--with-ssl-zlib=PATH],
+ [specify location of ZLib to be used by OpenSSL])
+AS_HELP_STRING([--with-ssl-zlib],
+ [link SSL with Zlib (default if found)])
+AS_HELP_STRING([--without-ssl-zlib],
+ [don't link SSL with ZLib]))
+
+if test "x$with_ssl_zlib" = "xno"; then
+ SSL_LINK_WITH_ZLIB=no
+ STATIC_ZLIB_LIBS=
+elif test "x$with_ssl_zlib" = "xyes" || test "x$with_ssl_zlib" = "x"; then
+ if test $erl_xcomp_without_sysroot = yes; then
+ AC_MSG_WARN([Cannot search for zlib; missing cross system root (erl_xcomp_sysroot).])
+ SSL_LINK_WITH_ZLIB=no
+ STATIC_ZLIB_LIBS=
+ elif test "x$MIXED_CYGWIN" = "xyes" -o "x$MIXED_MSYS" = "xyes"; then
+ SSL_LINK_WITH_ZLIB=no
+ STATIC_ZLIB_LIBS=
+ else
+ SSL_LINK_WITH_ZLIB=no
+ STATIC_ZLIB_LIBS=
+ AC_MSG_CHECKING(for static ZLib to be used by SSL in standard locations)
+ for rdir in $std_ssl_locations; do
+ dir="$erl_xcomp_sysroot$rdir"
+ if test "x$ac_cv_sizeof_void_p" = "x8"; then
+ if test -f "$dir/lib64/libz.a"; then
+ SSL_LINK_WITH_ZLIB=yes
+ STATIC_ZLIB_LIBS="$dir/lib64/libz.a"
+ break
+ elif test -f "$dir/lib/64/libz.a"; then
+ SSL_LINK_WITH_ZLIB=yes
+ STATIC_ZLIB_LIBS="$dir/lib/64/libz.a"
+ break
+ fi
+ fi
+ if test -f "$dir/lib/libz.a"; then
+ SSL_LINK_WITH_ZLIB=yes
+ STATIC_ZLIB_LIBS="$dir/lib/libz.a"
+ break
+ fi
+ done
+ if test "x$SSL_LINK_WITH_ZLIB" = "xno"; then
+ AC_MSG_RESULT([no])
+ else
+ AC_MSG_RESULT([$STATIC_ZLIB_LIBS])
+ fi
+ fi
+else
+ SSL_LINK_WITH_ZLIB=no
+ STATIC_ZLIB_LIBS=
+ if test -f "$with_ssl_zlib/libz.a"; then
+ SSL_LINK_WITH_ZLIB=yes
+ STATIC_ZLIB_LIBS=$with_ssl_zlib/libz.a
+ elif test -f "$with_ssl_zlib/lib/libz.a"; then
+ SSL_LINK_WITH_ZLIB=yes
+ STATIC_ZLIB_LIBS=$with_ssl_zlib/lib/libz.a
+ fi
+ if test "x$ac_cv_sizeof_void_p" = "x8"; then
+ if test -f "$with_ssl_zlib/lib64/libz.a"; then
+ SSL_LINK_WITH_ZLIB=yes
+ STATIC_ZLIB_LIBS=$with_ssl_zlib/lib64/libz.a
+ elif test -f "$with_ssl_zlib/lib/64/libz.a"; then
+ SSL_LINK_WITH_ZLIB=yes
+ STATIC_ZLIB_LIBS=$with_ssl_zlib/lib/64/libz.a
+ fi
+ fi
+ if test "x$SSL_LINK_WITH_ZLIB" = "xno"; then
+ AC_MSG_ERROR(Invalid path to option --with-ssl-zlib=PATH)
+ fi
+fi
+
+
+AC_ARG_WITH(ssl,
+AS_HELP_STRING([--with-ssl=PATH], [specify location of OpenSSL include and lib])
+AS_HELP_STRING([--with-ssl], [use SSL (default)])
+AS_HELP_STRING([--without-ssl], [don't use SSL]))
+
+AC_ARG_WITH(ssl-incl,
+AS_HELP_STRING([--with-ssl-incl=PATH], [location of OpenSSL include dir, if different than specified by --with-ssl=PATH]),
+[
+case X$with_ssl in
+ X | Xyes | Xno) AC_MSG_ERROR([--with-ssl-incl=PATH set without --with-ssl=PATH]);;
+esac
+],
+[with_ssl_incl=$with_ssl]) #default
+
+AC_ARG_WITH(ssl-rpath,
+AS_HELP_STRING([--with-ssl-rpath=yes|no|PATHS],
+ [runtime library path for OpenSSL. Default is "yes", which equates to a
+ number of standard locations. If "no", then no runtime
+ library paths will be used. Anything else should be a
+ comma separated list of paths.]),
+[
+case X$with_ssl in
+ Xno) AC_MSG_ERROR([--with-ssl-rpath set without --with-ssl]);;
+esac
+],
+[with_ssl_rpath=yes]) #default
+
+
+AC_ARG_ENABLE(dynamic-ssl-lib,
+AS_HELP_STRING([--disable-dynamic-ssl-lib],
+ [disable using dynamic openssl libraries]),
+[ case "$enableval" in
+ no) enable_dynamic_ssl=no ;;
+ *) enable_dynamic_ssl=yes ;;
+ esac ], enable_dynamic_ssl=yes)
+
+#----------------------------------------------------------------------
+# We actually might do the SSL tests twice due to late discovery of
+# kerberos problems with static linking, in case we redo it all trying
+# dynamic SSL libraries instead.
+#----------------------------------------------------------------------
+
+ssl_done=no
+
+while test "x$ssl_done" != "xyes"; do
+
+ssl_done=yes # Default only one run
+
+# Remove all SKIP files from previous runs
+for a in ssl crypto ssh; do
+ rm -f "$ERL_TOP/lib/$a/SKIP"
+done
+
+SSL_DYNAMIC_ONLY=$enable_dynamic_ssl
+SSL_STATIC_ONLY=no
+
+case "$erl_xcomp_without_sysroot-$with_ssl" in
+ yes-* | no-no)
+ SSL_APP=
+ CRYPTO_APP=
+ SSH_APP=
+ if test "$with_ssl" = "no"; then
+ skip="User gave --without-ssl option"
+ else
+ skip="Cannot search for ssl; missing cross system root (erl_xcomp_sysroot)."
+ fi
+ for a in ssl crypto ssh; do
+ echo "$skip" > $ERL_TOP/lib/$a/SKIP
+ done
+ ;;
+ no-yes | no- )
+ # On windows, we could try to find the installation
+ # of Shining Light OpenSSL, which can be found by poking in
+ # the uninstall section in the registry, it's worth a try...
+ extra_dir=""
+ if test "x$MIXED_CYGWIN" = "xyes"; then
+ AC_CHECK_PROG(REGTOOL, regtool, regtool, false)
+ if test "$ac_cv_prog_REGTOOL" != false; then
+ wrp="/machine/software/microsoft/windows/currentversion/"
+ if test "x$ac_cv_sizeof_void_p" = "x8"; then
+ urp="uninstall/openssl (64-bit)_is1/inno setup: app path"
+ regtool_subsystem=-w
+ else
+ urp="uninstall/openssl (32-bit)_is1/inno setup: app path"
+ regtool_subsystem=-W
+ fi
+ rp="$wrp$urp"
+ if regtool -q $regtool_subsystem get "$rp" > /dev/null; then
+ true
+ else
+ # Fallback to unspecified wordlength
+ urp="uninstall/openssl_is1/inno setup: app path"
+ rp="$wrp$urp"
+ fi
+ if regtool -q $regtool_subsystem get "$rp" > /dev/null; then
+ ssl_install_dir=`regtool -q $regtool_subsystem get "$rp"`
+ # Try hard to get rid of spaces...
+ if cygpath -d "$ssl_install_dir" > /dev/null 2>&1; then
+ ssl_install_dir=`cygpath -d "$ssl_install_dir"`
+ fi
+ extra_dir=`cygpath $ssl_install_dir`
+ fi
+ fi
+ elif test "x$MIXED_MSYS" = "xyes"; then
+ AC_CHECK_PROG(REGTOOL, reg_query.sh, reg_query.sh, false)
+ if test "$ac_cv_prog_REGTOOL" != false; then
+ if test "x$ac_cv_sizeof_void_p" = "x8"; then
+ rp="HKLM/SOFTWARE/Microsoft/Windows/CurrentVersion/Uninstall/OpenSSL (64-bit)_is1"
+ else
+ rp="HKLM/SOFTWARE/Microsoft/Windows/CurrentVersion/Uninstall/OpenSSL_is1"
+ fi
+ key="Inno Setup: App Path"
+ if "$ac_cv_prog_REGTOOL" "$rp" "$key" > /dev/null; then
+ ssl_install_dir=`"$ac_cv_prog_REGTOOL" "$rp" "$key"`
+ extra_dir=`win2msys_path.sh "$ssl_install_dir"`
+ fi
+ fi
+ fi
+ # We search for OpenSSL in the common OS standard locations.
+ SSL_APP=ssl
+ CRYPTO_APP=crypto
+ SSH_APP=ssh
+
+ SSL_CRYPTO_LIBNAME=crypto
+ SSL_SSL_LIBNAME=ssl
+
+ if test "x$MIXED_CYGWIN" = "xyes" -o "x$MIXED_MSYS" = "xyes"; then
+ if test "x$ac_cv_sizeof_void_p" = "x8"; then
+ std_win_ssl_locations="/cygdrive/c/OpenSSL-Win64 /c/OpenSSL-Win64 /opt/local64/pgm/OpenSSL"
+ else
+ std_win_ssl_locations="/cygdrive/c/OpenSSL-Win32 /c/OpenSSL-Win32 /cygdrive/c/OpenSSL /c/OpenSSL /opt/local/pgm/OpenSSL"
+ fi
+ else
+ std_win_ssl_locations=""
+ fi
+
+
+ AC_MSG_CHECKING(for OpenSSL >= 0.9.8c in standard locations)
+ for rdir in $extra_dir $std_win_ssl_locations $std_ssl_locations; do
+ dir="$erl_xcomp_sysroot$rdir"
+ if test -f "$erl_xcomp_isysroot$rdir/include/openssl/opensslv.h"; then
+ is_real_ssl=yes
+ SSL_INCDIR="$dir"
+ if test "x$MIXED_CYGWIN" = "xyes" -o "x$MIXED_MSYS" = "xyes"; then
+ if test -f "$dir/lib/VC/libeay32.lib"; then
+ SSL_RUNTIME_LIBDIR="$rdir/lib/VC"
+ SSL_LIBDIR="$dir/lib/VC"
+ SSL_CRYPTO_LIBNAME=libeay32
+ SSL_SSL_LIBNAME=ssleay32
+ elif test -f "$dir/lib/VC/openssl.lib"; then
+ SSL_RUNTIME_LIBDIR="$rdir/lib/VC"
+ SSL_LIBDIR="$dir/lib/VC"
+ elif test -f $dir/lib/VC/libeay32MD.lib; then
+ SSL_CRYPTO_LIBNAME=libeay32MD
+ SSL_SSL_LIBNAME=ssleay32MD
+ if test "x$enable_dynamic_ssl" = "xno" && \
+ test -f $dir/lib/VC/static/libeay32MD.lib; then
+ SSL_RUNTIME_LIBDIR="$rdir/lib/VC/static"
+ SSL_LIBDIR="$dir/lib/VC/static"
+ else
+ SSL_RUNTIME_LIBDIR="$rdir/lib/VC"
+ SSL_LIBDIR="$dir/lib/VC"
+ fi
+ elif test -f "$dir/lib/libeay32.lib"; then
+ SSL_RUNTIME_LIBDIR="$rdir/lib"
+ SSL_LIBDIR="$dir/lib"
+ SSL_CRYPTO_LIBNAME=libeay32
+ SSL_SSL_LIBNAME=ssleay32
+ elif test -f "$dir/lib/openssl.lib"; then
+ SSL_RUNTIME_LIBDIR="$rdir/lib"
+ SSL_LIBDIR="$dir/lib"
+ else
+ is_real_ssl=no
+ fi
+ elif test -f "$dir/lib/powerpc/libsslcrypto.a"; then
+ SSL_CRYPTO_LIBNAME=sslcrypto
+ SSL_LIBDIR="$dir/lib/powerpc/"
+ SSL_RUNTIME_LIBDIR="$rdir/lib/powerpc/"
+ else
+ if test "x$ac_cv_sizeof_void_p" = "x8"; then
+ if test -f "$dir/lib64/libcrypto.a"; then
+ SSL_RUNTIME_LIBDIR="$rdir/lib64"
+ SSL_LIBDIR="$dir/lib64"
+ elif test -f "$dir/lib/64/libcrypto.a"; then
+ SSL_RUNTIME_LIBDIR="$rdir/lib/64"
+ SSL_LIBDIR="$dir/lib/64"
+ elif test -f "$dir/lib64/libcrypto.so"; then
+ SSL_RUNTIME_LIBDIR="$rdir/lib64"
+ SSL_LIBDIR="$dir/lib64"
+ elif test -f "$dir/lib/64/libcrypto.so"; then
+ SSL_RUNTIME_LIBDIR="$rdir/lib/64"
+ SSL_LIBDIR="$dir/lib/64"
+ else
+ SSL_RUNTIME_LIBDIR="$rdir/lib"
+ SSL_LIBDIR="$dir/lib"
+ fi
+ else
+ SSL_RUNTIME_LIBDIR="$rdir/lib"
+ SSL_LIBDIR="$dir/lib"
+ fi
+ fi
+ if test '!' -f "$SSL_LIBDIR/lib${SSL_CRYPTO_LIBNAME}.a"; then
+ SSL_DYNAMIC_ONLY=yes
+ elif test '!' -f "$SSL_LIBDIR/lib${SSL_CRYPTO_LIBNAME}.so" -a '!' -f "$SSL_LIBDIR/lib${SSL_CRYPTO_LIBNAME}.dylib"; then
+ SSL_STATIC_ONLY=yes
+ fi
+ SSL_BINDIR="$rdir/bin"
+ if test "x$is_real_ssl" = "xyes" ; then
+ SSL_INCLUDE="-I$dir/include"
+ old_CPPFLAGS=$CPPFLAGS
+ CPPFLAGS=$SSL_INCLUDE
+ AC_EGREP_CPP(^yes$,[
+#include <openssl/opensslv.h>
+#if OPENSSL_VERSION_NUMBER >= 0x0090803fL
+yes
+#endif
+ ],[
+ ssl_found=yes
+ ],[
+ SSL_APP=
+ ssl_found=no
+ ])
+ CPPFLAGS=$old_CPPFLAGS
+ if test "x$ssl_found" = "xyes"; then
+ if test "x$MIXED_CYGWIN" = "xyes" -o "x$MIXED_MSYS" = "xyes"; then
+ ssl_linkable=yes
+ elif test "x${SSL_CRYPTO_LIBNAME}" = "xsslcrypto"; then
+ # This should only be triggered seen OSE
+ ssl_linkable=yes
+ else
+ saveCFLAGS="$CFLAGS"
+ saveLDFLAGS="$LDFLAGS"
+ saveLIBS="$LIBS"
+ CFLAGS="$CFLAGS $SSL_INCLUDE"
+ if test "x$SSL_STATIC_ONLY" = "xyes"; then
+ LIBS="${SSL_LIBDIR}/lib${SSL_CRYPTO_LIBNAME}.a"
+ else
+ LDFLAGS="$LDFLAGS -L$SSL_LIBDIR"
+ LIBS="$LIBS -l${SSL_CRYPTO_LIBNAME}"
+ fi
+ AC_TRY_LINK([
+ #include <stdio.h>
+ #include <openssl/hmac.h>],
+ [
+ HMAC(0, 0, 0, 0, 0, 0, 0);
+ ],
+ [ssl_linkable=yes],
+ [ssl_linkable=no])
+ CFLAGS="$saveCFLAGS"
+ LDFLAGS="$saveLDFLAGS"
+ LIBS="$saveLIBS"
+ fi
+ fi
+ if test "x$ssl_found" = "xyes" && test "x$ssl_linkable" = "xyes"; then
+ AC_MSG_RESULT([$dir])
+ break;
+ fi
+ fi
+ fi
+ done
+
+ if test "x$ssl_found" != "xyes" ; then
+ dnl
+ dnl If no SSL found above, check whether we are running on OpenBSD.
+ dnl
+ case $host_os in
+ openbsd*)
+ if test -f "$erl_xcomp_isysroot/usr/include/openssl/opensslv.h"; then
+ # Trust OpenBSD to have everything the in the correct locations.
+ ssl_found=yes
+ ssl_linkable=yes
+ SSL_INCDIR="$erl_xcomp_sysroot/usr"
+ AC_MSG_RESULT([$SSL_INCDIR])
+ SSL_RUNTIME_LIB="/usr/lib"
+ SSL_LIB="$erl_xcomp_sysroot/usr/lib"
+ SSL_BINDIR="/usr/sbin"
+ dnl OpenBSD requires us to link with -L and -l
+ SSL_DYNAMIC_ONLY="yes"
+ fi
+ ;;
+ esac
+ fi
+dnl Now, certain linuxes have a 64bit libcrypto
+dnl that cannot build shared libraries (i.e. not PIC)
+dnl One could argue that this is wrong, but
+dnl so it is - be adoptable
+ if test "$ssl_found" = "yes" && test "$ssl_linkable" = "yes" && test "$SSL_DYNAMIC_ONLY" != "yes"; then
+ case $host_os in
+ linux*)
+ saveCFLAGS="$CFLAGS"
+ saveLDFLAGS="$LDFLAGS"
+ saveLIBS="$LIBS"
+ CFLAGS="$DED_CFLAGS $SSL_INCLUDE"
+ LDFLAGS="$DED_LDFLAGS"
+ LIBS="$SSL_LIBDIR/libcrypto.a $STATIC_ZLIB_LIBS"
+ AC_TRY_LINK([
+ #include <stdio.h>
+ #include <openssl/hmac.h>],
+ [
+ HMAC(0, 0, 0, 0, 0, 0, 0);
+ ],
+ [ssl_dyn_linkable=yes],
+ [ssl_dyn_linkable=no])
+ CFLAGS="$saveCFLAGS"
+ LDFLAGS="$saveLDFLAGS"
+ LIBS="$saveLIBS"
+ if test "x$ssl_dyn_linkable" != "xyes"; then
+ SSL_DYNAMIC_ONLY=yes
+ AC_MSG_WARN([SSL will be linked against dynamic lib as static lib is not purely relocatable])
+ fi
+ ;;
+ esac
+ fi
+
+
+
+
+ if test "x$ssl_found" != "xyes" || test "x$ssl_linkable" != "xyes"; then
+ if test "x$ssl_found" = "xyes"; then
+ AC_MSG_RESULT([found; but not usable])
+ else
+ AC_MSG_RESULT([no])
+ fi
+ SSL_APP=
+ CRYPTO_APP=
+ SSH_APP=
+ AC_MSG_WARN([No (usable) OpenSSL found, skipping ssl, ssh and crypto applications])
+
+ for a in ssl crypto ssh; do
+ echo "No usable OpenSSL found" > $ERL_TOP/lib/$a/SKIP
+ done
+ fi
+ ;;
+ *)
+ # Option given with PATH to package
+ if test ! -d "$with_ssl" ; then
+ AC_MSG_ERROR(Invalid path to option --with-ssl=PATH)
+ fi
+ if test ! -d "$with_ssl_incl" ; then
+ AC_MSG_ERROR(Invalid path to option --with-ssl-incl=PATH)
+ fi
+ SSL_INCDIR="$with_ssl_incl"
+ SSL_CRYPTO_LIBNAME=crypto
+ SSL_SSL_LIBNAME=ssl
+ if test "x$MIXED_CYGWIN" = "xyes" -o "x$MIXED_MSYS" = "xyes" && test -d "$with_ssl/lib/VC"; then
+ if test -f "$with_ssl/lib/VC/libeay32.lib"; then
+ SSL_LIBDIR="$with_ssl/lib/VC"
+ SSL_CRYPTO_LIBNAME=libeay32
+ SSL_SSL_LIBNAME=ssleay32
+ elif test -f "$with_ssl/lib/VC/openssl.lib"; then
+ SSL_LIBDIR="$with_ssl/lib/VC"
+ elif test -f $with_ssl/lib/VC/libeay32MD.lib; then
+ SSL_CRYPTO_LIBNAME=libeay32MD
+ SSL_SSL_LIBNAME=ssleay32MD
+ if test "x$enable_dynamic_ssl" = "xno" && \
+ test -f $with_ssl/lib/VC/static/libeay32MD.lib; then
+ SSL_LIBDIR="$with_ssl/lib/VC/static"
+ else
+ SSL_LIBDIR="$with_ssl/lib/VC"
+ fi
+ elif test -f "$with_ssl/lib/libeay32.lib"; then
+ SSL_LIBDIR="$with_ssl/lib"
+ SSL_CRYPTO_LIBNAME=libeay32
+ SSL_SSL_LIBNAME=ssleay32
+ else
+ # This probably wont work, but that's what the user said, so...
+ SSL_LIBDIR="$with_ssl/lib"
+ fi
+ elif test -f "$dir/lib/powerpc/libsslcrypto.a"; then
+ SSL_CRYPTO_LIBNAME=sslcrypto
+ SSL_LIBDIR="$with_ssl/lib/powerpc/"
+ elif test "x$ac_cv_sizeof_void_p" = "x8"; then
+ if test -f "$with_ssl/lib64/libcrypto.a"; then
+ SSL_LIBDIR="$with_ssl/lib64"
+ elif test -f "$with_ssl/lib/64/libcrypto.a"; then
+ SSL_LIBDIR="$with_ssl/lib/64"
+ elif test -f "$with_ssl/lib64/libcrypto.so"; then
+ SSL_LIBDIR="$with_ssl/lib64"
+ elif test -f "$with_ssl/lib/64/libcrypto.so"; then
+ SSL_LIBDIR="$with_ssl/lib/64"
+ else
+ SSL_LIBDIR="$with_ssl/lib"
+ fi
+ else
+ SSL_LIBDIR="$with_ssl/lib"
+ fi
+ if test '!' -f "${SSL_LIBDIR}/lib${SSL_CRYPTO_LIBNAME}.a"; then
+ SSL_DYNAMIC_ONLY=yes
+ elif test '!' -f ${SSL_LIBDIR}/lib${SSL_CRYPTO_LIBNAME}.so -a '!' -f "$SSL_LIBDIR/lib${SSL_CRYPTO_LIBNAME}.dylib"; then
+ SSL_STATIC_ONLY=yes
+ fi
+ SSL_INCLUDE="-I$with_ssl_incl/include"
+ SSL_APP=ssl
+ CRYPTO_APP=crypto
+ SSH_APP=ssh
+ if test "$cross_compiling" = "yes"; then
+ SSL_RUNTIME_LIBDIR=`echo "$SSL_LIBDIR" | sed -n "s|^$erl_xcomp_sysroot\(/*\)\(.*\)\$|/\2|p"`
+ else
+ SSL_RUNTIME_LIBDIR="$SSL_LIBDIR"
+ fi
+esac
+
+if test "x$SSL_APP" != "x" ; then
+ dnl We found openssl, now check if we use kerberos 5 support
+ dnl FIXME: Do we still support platforms that have Kerberos?
+ AC_MSG_CHECKING(for OpenSSL kerberos 5 support)
+ old_CPPFLAGS=$CPPFLAGS
+ CPPFLAGS=$SSL_INCLUDE
+ AC_EGREP_CPP(^yes$,[
+#include <openssl/opensslv.h>
+#include <openssl/opensslconf.h>
+#if OPENSSL_VERSION_NUMBER < 0x1010000fL && !defined(OPENSSL_NO_KRB5)
+yes
+#endif
+ ],[
+ AC_MSG_RESULT([yes])
+ ssl_krb5_enabled=yes
+ if test "x$SSL_DYNAMIC_ONLY" != "xyes"; then
+ if test -f "$SSL_LIBDIR/libkrb5.a"; then
+ SSL_LINK_WITH_KERBEROS=yes
+ STATIC_KERBEROS_LIBS="$SSL_LIBDIR/libkrb5.a"
+ if test -f "$SSL_LIBDIR/libkrb5support.a"; then
+ STATIC_KERBEROS_LIBS="$STATIC_KERBEROS_LIBS $SSL_LIBDIR/libkrb5support.a"
+ fi
+ if test -f "$SSL_LIBDIR/libk5crypto.a"; then
+ STATIC_KERBEROS_LIBS="$STATIC_KERBEROS_LIBS $SSL_LIBDIR/libk5crypto.a"
+ fi
+ if test -f "$SSL_LIBDIR/libresolv.a"; then
+ STATIC_KERBEROS_LIBS="$STATIC_KERBEROS_LIBS $SSL_LIBDIR/libresolv.a"
+ fi
+ if test -f "$SSL_LIBDIR/libcom_err.a"; then
+ STATIC_KERBEROS_LIBS="$STATIC_KERBEROS_LIBS $SSL_LIBDIR/libcom_err.a"
+ fi
+ else
+ AC_MSG_WARN([Kerberos needed but no kerberos static libraries found])
+ AC_MSG_WARN([Rescanning for dynamic SSL libraries])
+ enable_dynamic_ssl=yes
+ ssl_done=no
+ SSL_LINK_WITH_KERBEROS=no
+ STATIC_KERBEROS_LIBS=""
+ ssl_krb5_enabled=no
+ SSL_WITH_KERBEROS=no
+ fi
+ else
+ SSL_LINK_WITH_KERBEROS=no
+ STATIC_KERBEROS_LIBS=""
+ fi
+ ],[
+ AC_MSG_RESULT([no])
+ ssl_krb5_enabled=no
+ SSL_WITH_KERBEROS=no
+ ])
+ CPPFLAGS=$old_CPPFLAGS
+ SSL_KRB5_INCLUDE=
+ if test "x$ssl_krb5_enabled" = "xyes" ; then
+ AC_MSG_CHECKING(for krb5.h in standard locations)
+ for dir in $extra_dir "$SSL_INCDIR/include" "$SSL_INCDIR/include/openssl" \
+ "$SSL_INCDIR/include/kerberos" \
+ "$erl_xcomp_isysroot/cygdrive/c/kerberos/include" \
+ "$erl_xcomp_isysroot/usr/local/kerberos/include" \
+ "$erl_xcomp_isysroot/usr/kerberos/include" \
+ "$erl_xcomp_isysroot/usr/include"
+ do
+ if test -f "$dir/krb5.h" ; then
+ SSL_KRB5_INCLUDE="$dir"
+ break
+ fi
+ done
+ if test "x$SSL_KRB5_INCLUDE" = "x" ; then
+ AC_MSG_RESULT([not found])
+ SSL_APP=
+ CRYPTO_APP=
+ SSH_APP=
+ AC_MSG_WARN([OpenSSL is configured for kerberos but no krb5.h found])
+ for a in ssl crypto ssh ; do
+ echo "OpenSSL is configured for kerberos but no krb5.h found" > $ERL_TOP/lib/$a/SKIP
+ done
+ else
+ AC_MSG_RESULT([found in $SSL_KRB5_INCLUDE])
+ SSL_INCLUDE="$SSL_INCLUDE -I$SSL_KRB5_INCLUDE"
+ fi
+ fi
+fi
+
+done # while test ssl_done != yes
+
+SSL_DED_LD_RUNTIME_LIBRARY_PATH=
+ded_ld_rflg="$DED_LD_FLAG_RUNTIME_LIBRARY_PATH"
+
+
+case "$with_ssl_rpath" in
+
+yes) # Use standard lib locations for ssl runtime library path
+
+ if test "$SSL_APP" != "" && test "$SSL_DYNAMIC_ONLY" = "yes" && test "$ded_ld_rflg" != ""; then
+
+ AC_MSG_CHECKING(for ssl runtime library path to use)
+
+ libdirs="/lib"
+
+ if test "$ac_cv_sizeof_void_p" = "8"; then
+ dir_lib64=no
+ dir_lib_64=no
+
+ case "$SSL_RUNTIME_LIBDIR" in
+ */lib/64 | */lib/64/ ) dir_lib_64=yes;;
+ */lib64 | */lib64/ ) dir_lib64=yes;;
+ *) ;;
+ esac
+
+ for dir in $std_ssl_locations; do
+ test $dir_lib_64 = no &&
+ test -d "$erl_xcomp_sysroot$dir/lib/64" &&
+ dir_lib_64=yes
+ test $dir_lib64 = no &&
+ test -d "$erl_xcomp_sysroot$dir/lib64" &&
+ dir_lib64=yes
+ done
+
+ test $dir_lib_64 = yes && libdirs="/lib/64 $libdirs"
+ test $dir_lib64 = yes && libdirs="/lib64 $libdirs"
+ fi
+
+ for type in std x_std curr; do
+
+ ded_ld_rpath="$ded_ld_rflg$SSL_RUNTIME_LIBDIR"
+ rpath="$SSL_RUNTIME_LIBDIR"
+
+ if test $type != curr; then
+ for ldir in $libdirs; do
+ for dir in $std_ssl_locations; do
+ test "$SSL_LIBDIR" != "$dir$ldir" || continue
+ test $type != x_std || test -d "$dir$ldir" || continue
+ if test "$dir" = "/"; then
+ libdir="$ldir"
+ else
+ libdir="$dir$ldir"
+ fi
+ ded_ld_rpath="$ded_ld_rpath $ded_ld_rflg$libdir"
+ rpath="$rpath:$libdir"
+ done
+ done
+ fi
+
+ saveCFLAGS="$CFLAGS"
+ saveLDFLAGS="$LDFLAGS"
+ saveLIBS="$LIBS"
+ CFLAGS="$CFLAGS $SSL_INCLUDE"
+ LDFLAGS="$LDFLAGS $ld_rpath -L$SSL_LIBDIR"
+ LIBS="-lcrypto"
+ AC_TRY_LINK([
+ #include <stdio.h>
+ #include <openssl/hmac.h>
+ ],
+ [
+ HMAC(0, 0, 0, 0, 0, 0, 0);
+ ],
+ [rpath_success=yes],
+ [rpath_success=no])
+ CFLAGS="$saveCFLAGS"
+ LDFLAGS="$saveLDFLAGS"
+ LIBS="$saveLIBS"
+
+ test "$rpath_success" = "yes" && break
+ done
+
+ test "$rpath_success" = "yes" || { ded_ld_rpath=; rpath=; }
+
+ SSL_DED_LD_RUNTIME_LIBRARY_PATH="$ded_ld_rpath"
+
+ AC_MSG_RESULT([$rpath])
+ test "$rpath" != "" || AC_MSG_WARN([Cannot set run path during linking])
+ fi
+ ;;
+
+no) # Use no ssl runtime library path
+ SSL_DED_LD_RUNTIME_LIBRARY_PATH=
+ ;;
+
+*) # Use ssl runtime library paths set by --with-ssl-rpath (without any check)
+ ded_ld_rpath=
+ delimit=
+ for dir in `echo $with_ssl_rpath | sed "s/,/ /g"`; do
+ ded_ld_rpath="$ded_ld_rpath$delimit$ded_ld_rflg$dir"
+ delimit=" "
+ done
+ SSL_DED_LD_RUNTIME_LIBRARY_PATH="$ded_ld_rpath"
+ ;;
+
+esac
+
+
+AC_ARG_ENABLE(fips,
+AS_HELP_STRING([--enable-fips], [enable OpenSSL FIPS mode support])
+AS_HELP_STRING([--disable-fips], [disable OpenSSL FIPS mode support (default)]),
+[ case "$enableval" in
+ yes) enable_fips_support=yes ;;
+ *) enable_fips_support=no ;;
+ esac ], enable_fips_support=no)
+
+if test "x$enable_fips_support" = "xyes" && test "$CRYPTO_APP" != ""; then
+ saveCFLAGS="$CFLAGS"
+ saveLDFLAGS="$LDFLAGS"
+ saveLIBS="$LIBS"
+ CFLAGS="$CFLAGS $SSL_INCLUDE"
+ LDFLAGS="$LDFLAGS $ded_ld_rpath -L$SSL_LIBDIR"
+ LIBS="-lcrypto"
+ AC_CHECK_FUNC([FIPS_mode_set],
+ [SSL_FLAGS="-DFIPS_SUPPORT"],
+ [SSL_FLAGS=])
+ CFLAGS="$saveCFLAGS"
+ LDFLAGS="$saveLDFLAGS"
+ LIBS="$saveLIBS"
+else
+ SSL_FLAGS=
+fi
+
+AC_SUBST(SSL_INCLUDE)
+AC_SUBST(SSL_INCDIR)
+AC_SUBST(SSL_LIBDIR)
+AC_SUBST(SSL_FLAGS)
+AC_SUBST(SSL_CRYPTO_LIBNAME)
+AC_SUBST(SSL_SSL_LIBNAME)
+AC_SUBST(SSL_DED_LD_RUNTIME_LIBRARY_PATH)
+AC_SUBST(SSL_DYNAMIC_ONLY)
+AC_SUBST(SSL_LINK_WITH_KERBEROS)
+AC_SUBST(STATIC_KERBEROS_LIBS)
+AC_SUBST(SSL_LINK_WITH_ZLIB)
+AC_SUBST(STATIC_ZLIB_LIBS)
+
+AC_OUTPUT(c_src/$host/Makefile:c_src/Makefile.in)
+
diff --git a/lib/crypto/doc/specs/.gitignore b/lib/crypto/doc/specs/.gitignore
new file mode 100644
index 0000000000..322eebcb06
--- /dev/null
+++ b/lib/crypto/doc/specs/.gitignore
@@ -0,0 +1 @@
+specs_*.xml
diff --git a/lib/crypto/doc/src/Makefile b/lib/crypto/doc/src/Makefile
index 2148062e78..cbcafb7375 100644
--- a/lib/crypto/doc/src/Makefile
+++ b/lib/crypto/doc/src/Makefile
@@ -39,7 +39,7 @@ XML_REF3_FILES = crypto.xml
XML_REF6_FILES = crypto_app.xml
XML_PART_FILES = usersguide.xml
-XML_CHAPTER_FILES = notes.xml licenses.xml fips.xml engine_load.xml engine_keys.xml
+XML_CHAPTER_FILES = notes.xml licenses.xml fips.xml engine_load.xml engine_keys.xml algorithm_details.xml
BOOK_FILES = book.xml
@@ -62,11 +62,17 @@ HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
+SPECS_FILES = $(XML_REF3_FILES:%.xml=$(SPECDIR)/specs_%.xml)
+
+TOP_SPECS_FILE = specs.xml
+
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
XML_FLAGS +=
+#in ssh it looks like this: SPECS_FLAGS = -I../../../public_key/include -I../../../public_key/src -I../../..
+
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
@@ -93,6 +99,7 @@ clean clean_docs clean_tex:
rm -f $(MAN3DIR)/*
rm -f $(MAN6DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
+ rm -f $(SPECS_FILES)
rm -f errs core *~
# ----------------------------------------------------
diff --git a/lib/crypto/doc/src/algorithm_details.xml b/lib/crypto/doc/src/algorithm_details.xml
new file mode 100644
index 0000000000..68ad264df7
--- /dev/null
+++ b/lib/crypto/doc/src/algorithm_details.xml
@@ -0,0 +1,297 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>2014</year><year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ The contents of this file are subject to the Erlang Public License,
+ Version 1.1, (the "License"); you may not use this file except in
+ compliance with the License. You should have received a copy of the
+ Erlang Public License along with this software. If not, it can be
+ retrieved online at http://www.erlang.org/.
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and limitations
+ under the License.
+
+ </legalnotice>
+
+ <title>Algorithm Details</title>
+ <prepared>Hans Nilsson</prepared>
+ <docno></docno>
+ <date>2018-08-22</date>
+ <rev>A</rev>
+ <file>algorithm_details.xml</file>
+ </header>
+ <p>
+ This chapter describes details of algorithms in the crypto application.
+ </p>
+ <p>The tables only documents the supported cryptos and key lengths. The user should not draw any conclusion
+ on security from the supplied tables.
+ </p>
+
+ <section>
+ <title>Ciphers</title>
+ <section>
+ <title>Block Ciphers</title>
+ <p>To be used in
+ <seealso marker="crypto#block_encrypt-3">block_encrypt/3</seealso>,
+ <seealso marker="crypto#block_encrypt-4">block_encrypt/4</seealso>,
+ <seealso marker="crypto#block_decrypt-3">block_decrypt/3</seealso> and
+ <seealso marker="crypto#block_decrypt-4">block_decrypt/4</seealso>.
+ </p>
+ <p>Available in all OpenSSL compatible with Erlang CRYPTO if not disabled by configuration.
+ </p>
+ <p>To dynamically check availability, check that the name in the <i>Cipher and Mode</i> column is present in the
+ list with the <c>cipher</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ <table>
+ <row><cell><strong>Cipher and Mode</strong></cell><cell><strong>Key length</strong><br/><strong>[bytes]</strong></cell><cell><strong>IV length</strong><br/><strong>[bytes]</strong></cell><cell><strong>Block size</strong><br/><strong>[bytes]</strong></cell></row>
+ <row><cell><c>aes_cbc</c></cell> <cell>16, 24, 32</cell><cell>16</cell><cell>16</cell></row>
+ <row><cell><c>aes_cbc128</c></cell><cell>16</cell><cell>16</cell><cell>16</cell></row>
+ <row><cell><c>aes_cbc256</c></cell><cell>32</cell><cell>16</cell><cell>16</cell></row>
+
+ <row><cell><c>aes_cfb8</c></cell> <cell>16, 24, 32</cell><cell>16</cell><cell>any</cell></row>
+
+ <row><cell><c>aes_ecb</c></cell><cell>16, 24, 32</cell><cell> </cell><cell>16</cell></row>
+
+ <row><cell><c>aes_ige256</c></cell><cell>16</cell><cell>32</cell><cell>16</cell></row>
+ <row><cell><c>blowfish_cbc</c></cell> <cell>4-56</cell> <cell>8</cell> <cell>8</cell></row>
+ <row><cell><c>blowfish_cfb64</c></cell> <cell>1-</cell> <cell>8</cell> <cell>any</cell></row>
+ <row><cell><c>blowfish_ecb</c></cell><cell>1-</cell><cell> </cell><cell>8</cell></row>
+ <row><cell><c>blowfish_ofb64</c></cell><cell>1-</cell><cell>8</cell><cell>any</cell></row>
+
+ <row><cell><c>des3_cbc</c><br/><i>(=DES EDE3 CBC)</i></cell><cell>[8,8,8]</cell><cell>8</cell><cell>8</cell></row>
+ <row><cell><c>des3_cfb</c><br/><i>(=DES EDE3 CFB)</i></cell><cell>[8,8,8]</cell><cell>8</cell><cell>any</cell></row>
+
+ <row><cell><c>des_cbc</c></cell><cell>8</cell><cell>8</cell> <cell>8</cell></row>
+ <row><cell><c>des_cfb</c></cell><cell>8</cell><cell>8</cell><cell>any</cell></row>
+ <row><cell><c>des_ecb</c></cell><cell>8</cell><cell> </cell><cell>8</cell></row>
+ <row><cell><c>des_ede3</c><br/><i>(=DES EDE3 CBC)</i></cell><cell>[8,8,8]</cell><cell>8</cell><cell>8</cell></row>
+ <row><cell><c>rc2_cbc</c></cell><cell>1-</cell><cell>8</cell><cell>8</cell></row>
+ <tcaption>Block cipher key lengths</tcaption>
+ </table>
+ </section>
+
+ <section>
+ <title>AEAD Ciphers</title>
+ <p>To be used in <seealso marker="crypto#block_encrypt-4">block_encrypt/4</seealso> and
+ <seealso marker="crypto#block_decrypt-4">block_decrypt/4</seealso>.
+ </p>
+ <p>To dynamically check availability, check that the name in the <i>Cipher and Mode</i> column is present in the
+ list with the <c>cipher</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ <table>
+ <row><cell><strong>Cipher and Mode</strong></cell><cell><strong>Key length</strong><br/><strong>[bytes]</strong></cell><cell><strong>IV length</strong><br/><strong>[bytes]</strong></cell><cell><strong>AAD length</strong><br/><strong>[bytes]</strong></cell><cell><strong>Tag length</strong><br/><strong>[bytes]</strong></cell><cell><strong>Block size</strong><br/><strong>[bytes]</strong></cell><cell><strong>Supported with</strong><br/><strong>OpenSSL versions</strong></cell></row>
+ <row><cell><c>aes_ccm</c></cell> <cell>16,24,32</cell> <cell>7-13</cell> <cell>any</cell> <cell>even 4-16<br/>default: 12</cell> <cell>any</cell><cell>1.1.0 -</cell></row>
+ <row><cell><c>aes_gcm</c></cell> <cell>16,24,32</cell> <cell>1-</cell> <cell>any</cell> <cell>1-16<br/>default: 16</cell> <cell>any</cell><cell>1.1.0 -</cell></row>
+ <row><cell><c>chacha20_poly1305</c></cell><cell>32</cell> <cell>1-16</cell> <cell>any</cell> <cell>16</cell> <cell>any</cell><cell>1.1.0 -</cell></row>
+ <tcaption>AEAD cipher key lengths</tcaption>
+ </table>
+ </section>
+
+ <section>
+ <title>Stream Ciphers</title>
+ <p>To be used in <seealso marker="crypto#stream_init-2">stream_init/2</seealso> and
+ <seealso marker="crypto#stream_init/3">stream_init/3</seealso>.
+ </p>
+ <p>To dynamically check availability, check that the name in the <i>Cipher and Mode</i> column is present in the
+ list with the <c>cipher</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ <table>
+ <row><cell><strong>Cipher and Mode</strong></cell><cell><strong>Key length</strong><br/><strong>[bytes]</strong></cell><cell><strong>IV length</strong><br/><strong>[bytes]</strong></cell><cell><strong>Supported with</strong><br/><strong>OpenSSL versions</strong></cell></row>
+ <row><cell><c>aes_ctr</c></cell><cell>16, 24, 32</cell><cell>16</cell><cell>1.0.1 -</cell></row>
+ <row><cell><c>rc4</c></cell><cell>1-</cell><cell> </cell> <cell>all</cell></row>
+ <tcaption>Stream cipher key lengths</tcaption>
+ </table>
+ </section>
+ </section>
+
+ <section>
+ <title>Message Authentication Codes (MACs)</title>
+
+ <section>
+ <title>CMAC</title>
+ <p>To be used in <seealso marker="crypto#cmac-3">cmac/3</seealso> and
+ <seealso marker="crypto#cmac-3">cmac/4</seealso>.
+ </p>
+ <p>CMAC with the following ciphers are available with OpenSSL 1.0.1 or later if not disabled by configuration.
+ </p>
+
+ <p>To dynamically check availability, check that the name <c>cmac</c> is present in the
+ list with the <c>macs</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ Also check that the name in the <i>Cipher and Mode</i> column is present in the
+ list with the <c>cipher</c> tag in the return value.
+ </p>
+ <table>
+ <row><cell><strong>Cipher and Mode</strong></cell><cell><strong>Key length</strong><br/><strong>[bytes]</strong></cell><cell><strong>Max Mac Length</strong><br/><strong>[bytes]</strong></cell></row>
+ <row><cell><c>aes_cbc</c></cell> <cell>16, 24, 32</cell><cell>16</cell></row>
+ <row><cell><c>aes_cbc128</c></cell><cell>16</cell><cell>16</cell></row>
+ <row><cell><c>aes_cbc256</c></cell><cell>32</cell><cell>16</cell></row>
+
+ <row><cell><c>aes_cfb8</c></cell> <cell>16</cell><cell>1</cell></row>
+
+ <row><cell><c>blowfish_cbc</c></cell> <cell>4-56</cell> <cell>8</cell></row>
+ <row><cell><c>blowfish_cfb64</c></cell> <cell>1-</cell> <cell>1</cell></row>
+ <row><cell><c>blowfish_ecb</c></cell><cell>1-</cell> <cell>8</cell></row>
+ <row><cell><c>blowfish_ofb64</c></cell><cell>1-</cell> <cell>1</cell></row>
+
+ <row><cell><c>des3_cbc</c><br/><i>(=DES EDE3 CBC)</i></cell><cell>[8,8,8]</cell><cell>8</cell></row>
+ <row><cell><c>des3_cfb</c><br/><i>(=DES EDE3 CFB)</i></cell><cell>[8,8,8]</cell><cell>1</cell></row>
+
+ <row><cell><c>des_cbc</c></cell><cell>8</cell><cell>8</cell></row>
+
+ <row><cell><c>des_cfb</c></cell><cell>8</cell><cell>1</cell></row>
+ <row><cell><c>des_ecb</c></cell><cell>8</cell><cell>1</cell></row>
+ <row><cell><c>rc2_cbc</c></cell><cell>1-</cell><cell>8</cell></row>
+ <tcaption>CMAC cipher key lengths</tcaption>
+ </table>
+ </section>
+
+ <section>
+ <title>HMAC</title>
+ <p>Available in all OpenSSL compatible with Erlang CRYPTO if not disabled by configuration.
+ </p>
+ <p>To dynamically check availability, check that the name <c>hmac</c> is present in the
+ list with the <c>macs</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ </section>
+
+ <section>
+ <title>POLY1305</title>
+ <p>POLY1305 is available with OpenSSL 1.1.1 or later if not disabled by configuration.
+ </p>
+ <p>To dynamically check availability, check that the name <c>poly1305</c> is present in the
+ list with the <c>macs</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ </section>
+
+ </section>
+
+ <section>
+ <title>Hash</title>
+
+ <p>To dynamically check availability, check that the wanted name in the <i>Names</i> column is present in the
+ list with the <c>hashs</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+
+
+ <table>
+ <row><cell><strong>Type</strong></cell>
+ <cell><strong>Names</strong></cell>
+ <cell><strong>Supported with</strong><br/><strong>OpenSSL versions</strong></cell>
+ </row>
+ <row><cell>SHA1</cell><cell>sha</cell><cell>all</cell></row>
+ <row><cell>SHA2</cell><cell>sha224, sha256, sha384, sha512</cell><cell>all</cell></row>
+ <row><cell>SHA3</cell><cell>sha3_224, sha3_256, sha3_384, sha3_512</cell><cell>1.1.1 -</cell></row>
+ <row><cell>MD4</cell><cell>md4</cell><cell>all</cell></row>
+ <row><cell>MD5</cell><cell>md5</cell><cell>all</cell></row>
+ <row><cell>RIPEMD</cell><cell>ripemd160</cell><cell>all</cell></row>
+ <tcaption></tcaption>
+ </table>
+ </section>
+
+ <section>
+ <title>Public Key Cryptography</title>
+
+ <section>
+ <title>RSA</title>
+ <p>RSA is available with all OpenSSL versions compatible with Erlang CRYPTO if not disabled by configuration.
+ To dynamically check availability, check that the atom <c>rsa</c> is present in the
+ list with the <c>public_keys</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ <warning>
+ <!-- In RefMan rsa_opt(), rsa_sign_verify_opt() and User's man RSA -->
+ <p>The RSA options are experimental.
+ </p>
+ <p>The exact set of options and there syntax <em>may</em> be changed
+ without prior notice.</p>
+ </warning>
+ <table>
+ <row><cell><strong>Option</strong></cell> <cell><strong>sign/verify</strong></cell> <cell><strong>encrypt/decrypt</strong></cell> <cell><strong>Supported with</strong><br/><strong>OpenSSL versions</strong></cell> </row>
+ <row><cell>{rsa_mgf1_md,atom()}</cell> <cell>x</cell> <cell>x</cell> <cell>1.0.1</cell></row>
+ <row><cell>{rsa_oaep_label, binary()}</cell> <cell> </cell> <cell>x</cell> <cell></cell></row>
+ <row><cell>{rsa_oaep_md, atom()}</cell> <cell> </cell> <cell>x</cell> <cell></cell></row>
+ <row><cell>{rsa_padding,rsa_pkcs1_pss_padding}</cell> <cell>x</cell> <cell> </cell> <cell>1.0.0</cell></row>
+ <row><cell>{rsa_pss_saltlen, -2..}</cell> <cell>x</cell> <cell> </cell> <cell>1.0.0</cell></row>
+ <row><cell>{rsa_padding,rsa_no_padding}</cell> <cell>x</cell> <cell>x</cell> <cell></cell></row>
+ <row><cell>{rsa_padding,rsa_pkcs1_padding}</cell> <cell>x</cell> <cell>x</cell> <cell></cell></row>
+ <row><cell>{rsa_padding,rsa_sslv23_padding}</cell> <cell> </cell> <cell>x</cell> <cell></cell></row>
+ <row><cell>{rsa_padding,rsa_x931_padding}</cell> <cell>x</cell> <cell> </cell> <cell></cell></row>
+ <tcaption></tcaption>
+ </table>
+ </section>
+
+ <section>
+ <title>DSS</title>
+ <p>DSS is available with OpenSSL versions compatible with Erlang CRYPTO if not disabled by configuration.
+ To dynamically check availability, check that the atom <c>dss</c> is present in the
+ list with the <c>public_keys</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ </section>
+
+ <section>
+ <title>ECDSA</title>
+ <p>ECDSA is available with OpenSSL 0.9.8o or later if not disabled by configuration.
+ To dynamically check availability, check that the atom <c>ecdsa</c> is present in the
+ list with the <c>public_keys</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ If the atom <c>ec_gf2m</c> characteristic two field curves are available.
+ </p>
+ <p>The actual supported named curves could be checked by examining the list with the
+ <c>curves</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ </section>
+
+ <section>
+ <title>Diffie-Hellman</title>
+ <p>Diffie-Hellman computations are available with OpenSSL versions compatible with Erlang CRYPTO
+ if not disabled by configuration.
+ To dynamically check availability, check that the atom <c>dh</c> is present in the
+ list with the <c>public_keys</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ </section>
+
+ <section>
+ <title>Elliptic Curve Diffie-Hellman</title>
+ <p>Elliptic Curve Diffie-Hellman is available with OpenSSL 0.9.8o or later if not disabled by configuration.
+ To dynamically check availability, check that the atom <c>ecdh</c> is present in the
+ list with the <c>public_keys</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+
+ <p>The Edward curves <c>x25519</c> and <c>x448</c> are supported with OpenSSL 1.1.1 or later
+ if not disabled by configuration.
+ </p>
+
+ <p>The actual supported named curves could be checked by examining the list with the
+ <c>curves</c> tag in the return value of
+ <seealso marker="crypto#supports-0">crypto:supports()</seealso>.
+ </p>
+ </section>
+
+ </section>
+
+
+</chapter>
+
+
+
+
+
diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
index 85d5ccaa34..b8ec41bea8 100644
--- a/lib/crypto/doc/src/crypto.xml
+++ b/lib/crypto/doc/src/crypto.xml
@@ -1,4 +1,3 @@
-<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE erlref SYSTEM "erlref.dtd">
<erlref>
@@ -28,226 +27,528 @@
<description>
<p>This module provides a set of cryptographic functions.
</p>
- <list type="bulleted">
- <item>
- <p>Hash functions -
- <url href="http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf"> Secure Hash Standard</url>,
- <url href="http://www.ietf.org/rfc/rfc1321.txt"> The MD5 Message Digest Algorithm (RFC 1321)</url> and
- <url href="http://www.ietf.org/rfc/rfc1320.txt">The MD4 Message Digest Algorithm (RFC 1320)</url>
- </p>
- </item>
- <item>
- <p>Hmac functions - <url href="http://www.ietf.org/rfc/rfc2104.txt"> Keyed-Hashing for Message Authentication (RFC 2104) </url></p>
- </item>
- <item>
- <p>Cmac functions - <url href="http://www.ietf.org/rfc/rfc4493.txt">The AES-CMAC Algorithm (RFC 4493)</url></p>
- </item>
- <item>
- <p>Block ciphers - <url href="http://csrc.nist.gov/groups/ST/toolkit/block_ciphers.html"> </url> DES and AES in
- Block Cipher Modes - <url href="http://csrc.nist.gov/groups/ST/toolkit/BCM/index.html"> ECB, CBC, CFB, OFB, CTR and GCM </url></p>
- </item>
- <item>
- <p><url href="http://www.ietf.org/rfc/rfc1321.txt"> RSA encryption RFC 1321 </url> </p>
- </item>
- <item>
- <p>Digital signatures <url href="http://csrc.nist.gov/publications/drafts/fips186-3/fips_186-3.pdf">Digital Signature Standard (DSS)</url> and<url href="http://csrc.nist.gov/groups/STM/cavp/documents/dss2/ecdsa2vs.pdf"> Elliptic Curve Digital
- Signature Algorithm (ECDSA) </url> </p>
- </item>
- <item>
- <p><url href="http://www.ietf.org/rfc/rfc2945.txt"> Secure Remote Password Protocol (SRP - RFC 2945) </url></p>
- </item>
- <item>
- <p>gcm: Dworkin, M., "Recommendation for Block Cipher Modes of
- Operation: Galois/Counter Mode (GCM) and GMAC",
- National Institute of Standards and Technology SP 800-
- 38D, November 2007.</p>
- </item>
- </list>
- </description>
-
- <section>
- <title>DATA TYPES </title>
+ <taglist>
+ <tag>Hash functions</tag>
+ <item>
+ <p></p>
+ <taglist>
+ <tag>SHA1, SHA2</tag>
+ <item>
+ <url href="https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf">
+ Secure Hash Standard [FIPS PUB 180-4]
+ </url>
+ </item>
+ <tag>SHA3</tag>
+ <item>
+ <url href="https://www.nist.gov/publications/sha-3-standard-permutation-based-hash-and-extendable-output-functions?pub_id=919061">
+ SHA-3 Standard: Permutation-Based Hash and Extendable-Output Functions [FIPS PUB 202]
+ </url>
+ </item>
+ <tag>MD5</tag>
+ <item>
+ <url href="http://www.ietf.org/rfc/rfc1321.txt">The MD5 Message Digest Algorithm [RFC 1321]</url>
+ </item>
+ <tag>MD4</tag>
+ <item>
+ <url href="http://www.ietf.org/rfc/rfc1320.txt">The MD4 Message Digest Algorithm [RFC 1320]</url>
+ </item>
+ </taglist>
+ <p></p>
+ </item>
+
+ <tag>MACs - Message Authentication Codes</tag>
+ <item>
+ <p></p>
+ <taglist>
+ <tag>Hmac functions</tag>
+ <item>
+ <url href="http://www.ietf.org/rfc/rfc2104.txt">
+ Keyed-Hashing for Message Authentication [RFC 2104]
+ </url>
+ </item>
+ <tag>Cmac functions</tag>
+ <item>
+ <url href="http://www.ietf.org/rfc/rfc4493.txt">
+ The AES-CMAC Algorithm [RFC 4493]
+ </url>
+ </item>
+ <tag>POLY1305</tag>
+ <item>
+ <url href="http://www.ietf.org/rfc/rfc7539.txt">
+ ChaCha20 and Poly1305 for IETF Protocols [RFC 7539]
+ </url>
+ </item>
+ </taglist>
+ <p></p>
+ </item>
+
+ <tag>Symmetric Ciphers</tag>
+ <item>
+ <p></p>
+ <taglist>
+ <tag>DES, 3DES and AES</tag>
+ <item>
+ <url href="https://csrc.nist.gov/projects/block-cipher-techniques">Block Cipher Techniques [NIST]</url>
+ </item>
+ <tag>Blowfish</tag>
+ <item>
+ <url href="https://www.schneier.com/academic/archives/1994/09/description_of_a_new.html">
+ Fast Software Encryption, Cambridge Security Workshop Proceedings (December 1993), Springer-Verlag, 1994, pp. 191-204.
+ </url>
+ </item>
+ <tag>Chacha20</tag>
+ <item>
+ <url href="http://www.ietf.org/rfc/rfc7539.txt">
+ ChaCha20 and Poly1305 for IETF Protocols [RFC 7539]
+ </url>
+ </item>
+ <tag>Chacha20_poly1305</tag>
+ <item>
+ <url href="http://www.ietf.org/rfc/rfc7539.txt">
+ ChaCha20 and Poly1305 for IETF Protocols [RFC 7539]
+ </url>
+ </item>
+ </taglist>
+ <p></p>
+ </item>
+
+ <tag>Modes</tag>
+ <item>
+ <p></p>
+ <taglist>
+ <tag>ECB, CBC, CFB, OFB and CTR</tag>
+ <item>
+ <url href="https://csrc.nist.gov/publications/detail/sp/800-38a/final">
+ Recommendation for Block Cipher Modes of Operation: Methods and Techniques [NIST SP 800-38A]
+ </url>
+ </item>
+ <tag>GCM</tag>
+ <item>
+ <url href="https://csrc.nist.gov/publications/detail/sp/800-38d/final">
+ Recommendation for Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC [NIST SP 800-38D]
+ </url>
+ </item>
+ <tag>CCM</tag>
+ <item>
+ <url href="https://nvlpubs.nist.gov/nistpubs/legacy/sp/nistspecialpublication800-38c.pdf">
+ Recommendation for Block Cipher Modes of Operation:
+ The CCM Mode for Authentication and Confidentiality [NIST SP 800-38C]
+ </url>
+ </item>
+ </taglist>
+ <p></p>
+ </item>
+
+ <tag>Asymetric Ciphers - Public Key Techniques</tag>
+ <item>
+ <p></p>
+ <taglist>
+ <tag>RSA</tag>
+ <item>
+ <url href="http://www.ietf.org/rfc/rfc3447.txt">
+ PKCS #1: RSA Cryptography Specifications [RFC 3447]
+ </url>
+ </item>
+ <tag>DSS</tag>
+ <item>
+ <url href="https://csrc.nist.gov/publications/detail/fips/186/4/final">
+ Digital Signature Standard (DSS) [FIPS 186-4]
+ </url>
+ </item>
+ <tag>ECDSA</tag>
+ <item>
+ <url href="http://csrc.nist.gov/groups/STM/cavp/documents/dss2/ecdsa2vs.pdf">
+ Elliptic Curve Digital Signature Algorithm [ECDSA]
+ </url>
+ </item>
+ <tag>SRP</tag>
+ <item>
+ <url href="http://www.ietf.org/rfc/rfc2945.txt">
+ The SRP Authentication and Key Exchange System [RFC 2945]
+ </url>
+ </item>
+ </taglist>
+ <p></p>
+ </item>
+ </taglist>
+
+ <note>
+ <p>The actual supported algorithms and features depends on their availability in the actual libcrypto used.
+ See the <seealso marker="crypto:crypto_app">crypto (App)</seealso> about dependencies.
+ </p>
+ <p>Enabling FIPS mode will also disable algorithms and features.
+ </p>
+ </note>
- <code>key_value() = integer() | binary() </code>
- <p>Always <c>binary()</c> when used as return value</p>
+ <p>The <seealso marker="users_guide">CRYPTO User's Guide</seealso> has more information on
+ FIPS, Engines and Algorithm Details like key lengths.
+ </p>
+ </description>
- <code>rsa_public() = [key_value()] = [E, N] </code>
- <p> Where E is the public exponent and N is public modulus. </p>
+ <datatypes>
+ <datatype_title>Ciphers</datatype_title>
+ <datatype>
+ <name name="stream_cipher"/>
+ <desc>
+ <p>Stream ciphers for
+ <seealso marker="#stream_encrypt-2">stream_encrypt/2</seealso> and
+ <seealso marker="#stream_decrypt-2">stream_decrypt/2</seealso> .
+ </p>
+ </desc>
+ </datatype>
- <code>rsa_private() = [key_value()] = [E, N, D] | [E, N, D, P1, P2, E1, E2, C] </code>
- <p>Where E is the public exponent, N is public modulus and D is
- the private exponent. The longer key format contains redundant
- information that will make the calculation faster. P1,P2 are first
- and second prime factors. E1,E2 are first and second exponents. C
- is the CRT coefficient. Terminology is taken from <url href="http://www.ietf.org/rfc/rfc3477.txt"> RFC 3447</url>.</p>
+ <datatype>
+ <name name="block_cipher_with_iv"/>
+ <name name="cbc_cipher"/>
+ <name name="cfb_cipher"/>
+ <desc>
+ <p>Block ciphers with initialization vector for
+ <seealso marker="#block_encrypt-4">block_encrypt/4</seealso> and
+ <seealso marker="#block_decrypt-4">block_decrypt/4</seealso> .
+ </p>
+ </desc>
+ </datatype>
- <code>dss_public() = [key_value()] = [P, Q, G, Y] </code>
- <p>Where P, Q and G are the dss parameters and Y is the public key.</p>
+ <datatype>
+ <name name="block_cipher_without_iv"/>
+ <name name="ecb_cipher"/>
+ <desc>
+ <p>Block ciphers without initialization vector for
+ <seealso marker="#block_encrypt-3">block_encrypt/3</seealso> and
+ <seealso marker="#block_decrypt-3">block_decrypt/3</seealso> .
+ </p>
+ </desc>
+ </datatype>
- <code>dss_private() = [key_value()] = [P, Q, G, X] </code>
- <p>Where P, Q and G are the dss parameters and X is the private key.</p>
+ <datatype>
+ <name name="aead_cipher"/>
+ <desc>
+ <p>Ciphers with simultaneous MAC-calculation or MAC-checking.
+ <seealso marker="#block_encrypt-4">block_encrypt/4</seealso> and
+ <seealso marker="#block_decrypt-4">block_decrypt/4</seealso> .
+ </p>
+ </desc>
+ </datatype>
- <code>srp_public() = key_value() </code>
- <p>Where is <c>A</c> or <c>B</c> from <url href="http://srp.stanford.edu/design.html">SRP design</url></p>
+ <datatype_title>Digests</datatype_title>
+ <datatype>
+ <name name="sha1"/>
+ <name name="sha2"/>
+ <name name="sha3"/>
+ <desc>
+ </desc>
+ </datatype>
- <code>srp_private() = key_value() </code>
- <p>Where is <c>a</c> or <c>b</c> from <url href="http://srp.stanford.edu/design.html">SRP design</url></p>
+ <datatype>
+ <name name="compatibility_only_hash"/>
+ <desc>
+ <p>The <c>compatibility_only_hash()</c> algorithms are recommended only for compatibility with existing applications.</p>
+ </desc>
+ </datatype>
- <p>Where Verifier is <c>v</c>, Generator is <c>g</c> and Prime is<c> N</c>, DerivedKey is <c>X</c>, and Scrambler is
- <c>u</c> (optional will be generated if not provided) from <url href="http://srp.stanford.edu/design.html">SRP design</url>
- Version = '3' | '6' | '6a'
- </p>
+ <datatype>
+ <name name="rsa_digest_type"/>
+ <desc>
+ </desc>
+ </datatype>
- <code>dh_public() = key_value() </code>
+ <datatype>
+ <name name="dss_digest_type"/>
+ <desc>
+ </desc>
+ </datatype>
- <code>dh_private() = key_value() </code>
+ <datatype>
+ <name name="ecdsa_digest_type"/>
+ <desc>
+ </desc>
+ </datatype>
- <code>dh_params() = [key_value()] = [P, G] | [P, G, PrivateKeyBitLength]</code>
+ <datatype_title>Elliptic Curves</datatype_title>
+ <datatype>
+ <name name="ec_named_curve"/>
+ <name name="edwards_curve"/>
+ <desc>
+ <p>Note that some curves are disabled if FIPS is enabled.</p>
+ </desc>
+ </datatype>
- <code>ecdh_public() = key_value() </code>
+ <datatype>
+ <name name="ec_explicit_curve"/>
+ <name name="ec_field"/>
+ <name name="ec_curve"/>
+ <desc>
+ <p>Parametric curve definition.</p>
+ </desc>
+ </datatype>
- <code>ecdh_private() = key_value() </code>
+ <datatype>
+ <name name="ec_prime_field"/>
+ <name name="ec_characteristic_two_field"/>
+ <name name="ec_basis"/>
+ <desc>
+ <p>Curve definition details.</p>
+ </desc>
+ </datatype>
- <code>ecdh_params() = ec_named_curve() | ec_explicit_curve()</code>
+ <datatype_title>Keys</datatype_title>
+ <datatype>
+ <name name="key"/>
+ <name name="des3_key"/>
+ <desc>
+ <p>For keylengths, iv-sizes and blocksizes see the
+ <seealso marker="crypto:algorithm_details#ciphers">User's Guide</seealso>.
+ </p>
+ <p>A key for des3 is a list of three iolists</p>
+ </desc>
+ </datatype>
- <code>ec_explicit_curve() =
- {ec_field(), Prime :: key_value(), Point :: key_value(), Order :: integer(),
- CoFactor :: none | integer()} </code>
+ <datatype>
+ <name name="key_integer"/>
+ <desc>
+ <p>Always <c>binary()</c> when used as return value</p>
+ </desc>
+ </datatype>
- <code>ec_field() = {prime_field, Prime :: integer()} |
- {characteristic_two_field, M :: integer(), Basis :: ec_basis()}</code>
+ <datatype_title>Public/Private Keys</datatype_title>
+ <datatype>
+ <name name="rsa_public"/>
+ <name name="rsa_private"/>
+ <name name="rsa_params"/>
+ <desc>
+ <code>rsa_public() = [E, N]</code>
+ <code>rsa_private() = [E, N, D] | [E, N, D, P1, P2, E1, E2, C]</code>
+ <p>Where E is the public exponent, N is public modulus and D is
+ the private exponent. The longer key format contains redundant
+ information that will make the calculation faster. P1,P2 are first
+ and second prime factors. E1,E2 are first and second exponents. C
+ is the CRT coefficient. Terminology is taken from <url href="http://www.ietf.org/rfc/rfc3477.txt"> RFC 3447</url>.</p>
+ </desc>
+ </datatype>
- <code>ec_basis() = {tpbasis, K :: non_neg_integer()} |
- {ppbasis, K1 :: non_neg_integer(), K2 :: non_neg_integer(), K3 :: non_neg_integer()} |
- onbasis</code>
+ <datatype>
+ <name name="dss_public"/>
+ <name name="dss_private"/>
+ <desc>
+ <code>dss_public() = [P, Q, G, Y] </code>
+ <p>Where P, Q and G are the dss parameters and Y is the public key.</p>
- <code>ec_named_curve() ->
- sect571r1| sect571k1| sect409r1| sect409k1| secp521r1| secp384r1| secp224r1| secp224k1|
- secp192k1| secp160r2| secp128r2| secp128r1| sect233r1| sect233k1| sect193r2| sect193r1|
- sect131r2| sect131r1| sect283r1| sect283k1| sect163r2| secp256k1| secp160k1| secp160r1|
- secp112r2| secp112r1| sect113r2| sect113r1| sect239k1| sect163r1| sect163k1| secp256r1|
- secp192r1|
- brainpoolP160r1| brainpoolP160t1| brainpoolP192r1| brainpoolP192t1| brainpoolP224r1|
- brainpoolP224t1| brainpoolP256r1| brainpoolP256t1| brainpoolP320r1| brainpoolP320t1|
- brainpoolP384r1| brainpoolP384t1| brainpoolP512r1| brainpoolP512t1
- </code>
- <p>Note that the <em>sect</em> curves are GF2m (characteristic two) curves and are only supported if the
- underlying OpenSSL has support for them.
- See also <seealso marker="#supports-0">crypto:supports/0</seealso>
- </p>
+ <code>dss_private() = [P, Q, G, X] </code>
+ <p>Where P, Q and G are the dss parameters and X is the private key.</p>
+ </desc>
+ </datatype>
- <marker id="type-engine_key_ref"/>
- <marker id="engine_key_ref_type"/>
- <code>engine_key_ref() = #{engine := engine_ref(),
- key_id := key_id(),
- password => password()}</code>
+ <datatype>
+ <name name="ecdsa_public"/>
+ <name name="ecdsa_private"/>
+ <name name="ecdsa_params"/>
+ <desc>
+ </desc>
+ </datatype>
- <code>engine_ref() = term()</code>
- <p>The result of a call to <seealso marker="#engine_load-3">engine_load/3</seealso>.
- </p>
+ <datatype>
+ <name name="srp_public"/>
+ <name name="srp_private"/>
+ <desc>
+ <code>srp_public() = key_integer() </code>
+ <p>Where is <c>A</c> or <c>B</c> from <url href="http://srp.stanford.edu/design.html">SRP design</url></p>
+
+ <code>srp_private() = key_integer() </code>
+ <p>Where is <c>a</c> or <c>b</c> from <url href="http://srp.stanford.edu/design.html">SRP design</url></p>
+ </desc>
+ </datatype>
- <code>key_id() = string() | binary()</code>
- <p>Identifies the key to be used. The format depends on the loaded engine. It is passed to
- the <c>ENGINE_load_(private|public)_key</c> functions in libcrypto.
- </p>
+ <datatype>
+ <name name="srp_gen_params"/>
+ <name name="srp_comp_params"/>
+ <desc>
+ <marker id="type-srp_user_gen_params"/>
+ <code>srp_user_gen_params() = [DerivedKey::binary(), Prime::binary(), Generator::binary(), Version::atom()]</code>
+ <marker id="type-srp_host_gen_params"/>
+ <code>srp_host_gen_params() = [Verifier::binary(), Prime::binary(), Version::atom() ]</code>
+ <marker id="type-srp_user_comp_params"/>
+ <code>srp_user_comp_params() = [DerivedKey::binary(), Prime::binary(), Generator::binary(), Version::atom() | ScramblerArg::list()]</code>
+ <marker id="type-srp_host_comp_params"/>
+ <code>srp_host_comp_params() = [Verifier::binary(), Prime::binary(), Version::atom() | ScramblerArg::list()]</code>
+ <p>Where Verifier is <c>v</c>, Generator is <c>g</c> and Prime is<c> N</c>, DerivedKey is <c>X</c>, and Scrambler is
+ <c>u</c> (optional will be generated if not provided) from <url href="http://srp.stanford.edu/design.html">SRP design</url>
+ Version = '3' | '6' | '6a'
+ </p>
+ </desc>
+ </datatype>
- <code>password() = string() | binary()</code>
- <p>The key's password
- </p>
+ <datatype_title>Public Key Ciphers</datatype_title>
- <code>stream_cipher() = rc4 | aes_ctr </code>
+ <datatype>
+ <name name="pk_encrypt_decrypt_algs"/>
+ <desc>
+ <p>Algorithms for public key encrypt/decrypt. Only RSA is supported.</p>
+ </desc>
+ </datatype>
- <code>block_cipher() = aes_cbc | aes_cfb8 | aes_cfb128 | aes_ige256 | blowfish_cbc |
- blowfish_cfb64 | des_cbc | des_cfb | des3_cbc | des3_cfb | des_ede3 | rc2_cbc </code>
+ <datatype>
+ <name name="pk_encrypt_decrypt_opts"/>
+ <name name="rsa_opt"/>
+ <name name="rsa_padding"/>
+ <desc>
+ <p>Options for public key encrypt/decrypt. Only RSA is supported.</p>
+ <warning>
+ <!-- In RefMan rsa_opt(), rsa_sign_verify_opt() and User's man RSA -->
+ <p>The RSA options are experimental.
+ </p>
+ <p>The exact set of options and there syntax <em>may</em> be changed
+ without prior notice.</p>
+ </warning>
+ </desc>
+ </datatype>
- <code>aead_cipher() = aes_gcm | chacha20_poly1305 </code>
+ <datatype>
+ <name name="rsa_compat_opts"/>
+ <desc>
+ <p>Those option forms are kept only for compatibility and should not be used in new code.</p>
+ </desc>
+ </datatype>
- <code>stream_key() = aes_key() | rc4_key() </code>
+ <datatype_title>Public Key Sign and Verify</datatype_title>
- <code>block_key() = aes_key() | blowfish_key() | des_key()| des3_key() </code>
+ <datatype>
+ <name name="pk_sign_verify_algs"/>
+ <desc>
+ <p>Algorithms for sign and verify.</p>
+ </desc>
+ </datatype>
- <code>aes_key() = iodata() </code> <p>Key length is 128, 192 or 256 bits</p>
+ <datatype>
+ <name name="pk_sign_verify_opts"/>
+ <name name="rsa_sign_verify_opt"/>
+ <name name="rsa_sign_verify_padding"/>
+ <desc>
+ <p>Options for sign and verify.</p>
+ <warning>
+ <!-- In RefMan rsa_opt(), rsa_sign_verify_opt() and User's man RSA -->
+ <p>The RSA options are experimental.
+ </p>
+ <p>The exact set of options and there syntax <em>may</em> be changed
+ without prior notice.</p>
+ </warning>
+ </desc>
+ </datatype>
- <code>rc4_key() = iodata() </code> <p>Variable key length from 8 bits up to 2048 bits (usually between 40 and 256)</p>
+ <datatype_title>Diffie-Hellman Keys and parameters</datatype_title>
+ <datatype>
+ <name name="dh_public"/>
+ <name name="dh_private"/>
+ <desc>
+ </desc>
+ </datatype>
- <code>blowfish_key() = iodata() </code> <p>Variable key length from 32 bits up to 448 bits</p>
+ <datatype>
+ <name name="dh_params"/>
+ <desc>
+ <code>dh_params() = [P, G] | [P, G, PrivateKeyBitLength]</code>
+ </desc>
+ </datatype>
- <code>des_key() = iodata() </code> <p>Key length is 64 bits (in CBC mode only 8 bits are used)</p>
+ <datatype>
+ <name name="ecdh_public"/>
+ <name name="ecdh_private"/>
+ <name name="ecdh_params"/>
+ <desc>
+ </desc>
+ </datatype>
- <code>des3_key() = [binary(), binary(), binary()] </code> <p>Each key part is 64 bits (in CBC mode only 8 bits are used)</p>
+ <datatype_title>Types for Engines</datatype_title>
- <code>digest_type() = md5 | sha | sha224 | sha256 | sha384 | sha512</code>
+ <datatype>
+ <name name="engine_key_ref"/>
+ <name name="engine_ref"/>
+ <desc>
+ <p>The result of a call to <seealso marker="#engine_load-3">engine_load/3</seealso>.
+ </p>
+ </desc>
+ </datatype>
- <code>rsa_digest_type() = md5 | ripemd160 | sha | sha224 | sha256 | sha384 | sha512</code>
+ <datatype>
+ <name name="key_id"/>
+ <desc>
+ <p>Identifies the key to be used. The format depends on the loaded engine. It is passed to
+ the <c>ENGINE_load_(private|public)_key</c> functions in libcrypto.
+ </p>
+ </desc>
+ </datatype>
- <code>dss_digest_type() = sha | sha224 | sha256 | sha384 | sha512</code> <p>Note that the actual supported
- dss_digest_type depends on the underlying crypto library. In OpenSSL version >= 1.0.1 the listed digest are supported, while in 1.0.0 only sha, sha224 and sha256 are supported. In version 0.9.8 only sha is supported.</p>
+ <datatype>
+ <name name="password"/>
+ <desc>
+ <p>The password of the key stored in an engine.
+ </p>
+ </desc>
+ </datatype>
- <code>ecdsa_digest_type() = sha | sha224 | sha256 | sha384 | sha512</code>
+ <datatype>
+ <name name="engine_method_type"/>
+ </datatype>
- <code>sign_options() = [{rsa_pad, rsa_sign_padding()} | {rsa_pss_saltlen, integer()}]</code>
+ <datatype>
+ <name name="engine_cmnd"/>
+ <desc>
+ <p>Pre and Post commands for <seealso marker="#engine_load-3">engine_load/3 and /4</seealso>.
+ </p>
+ </desc>
+ </datatype>
- <code>rsa_sign_padding() = rsa_pkcs1_padding | rsa_pkcs1_pss_padding</code>
+ <datatype_title>Internal data types</datatype_title>
- <code> hash_algorithms() = md5 | ripemd160 | sha | sha224 | sha256 | sha384 | sha512 </code> <p>md4 is also supported for hash_init/1 and hash/2.
- Note that both md4 and md5 are recommended only for compatibility with existing applications.
- </p>
- <code> cipher_algorithms() = aes_cbc | aes_cfb8 | aes_cfb128 | aes_ctr | aes_gcm |
- aes_ige256 | blowfish_cbc | blowfish_cfb64 | chacha20_poly1305 | des_cbc |
- des_cfb | des3_cbc | des3_cfb | des_ede3 | rc2_cbc | rc4 </code>
- <code> mac_algorithms() = hmac | cmac</code>
- <code> public_key_algorithms() = rsa |dss | ecdsa | dh | ecdh | ec_gf2m</code>
- <p>Note that ec_gf2m is not strictly a public key algorithm, but a restriction on what curves are supported
- with ecdsa and ecdh.
- </p>
- <code>engine_method_type() = engine_method_rsa | engine_method_dsa | engine_method_dh |
- engine_method_rand | engine_method_ecdh | engine_method_ecdsa |
- engine_method_ciphers | engine_method_digests | engine_method_store |
- engine_method_pkey_meths | engine_method_pkey_asn1_meths</code>
+ <datatype>
+ <name name="stream_state"/>
+ <name name="hmac_state"/>
+ <name name="hash_state"/>
+ <desc>
+ <p>Contexts with an internal state that should not be manipulated but passed between function calls.
+ </p>
+ </desc>
+ </datatype>
- </section>
+ </datatypes>
+ <!--================ FUNCTIONS ================-->
<funcs>
<func>
- <name>block_encrypt(Type, Key, PlainText) -> CipherText</name>
+ <name name="block_encrypt" arity="3"/>
<fsummary>Encrypt <c>PlainText</c> according to <c>Type</c> block cipher</fsummary>
- <type>
- <v>Type = des_ecb | blowfish_ecb | aes_ecb </v>
- <v>Key = block_key() </v>
- <v>PlainText = iodata() </v>
- </type>
<desc>
- <p>Encrypt <c>PlainText</c> according to <c>Type</c> block cipher.</p>
- <p>May throw exception <c>notsup</c> in case the chosen <c>Type</c>
- is not supported by the underlying OpenSSL implementation.</p>
+ <p>Encrypt <c>PlainText</c> according to <c>Type</c> block cipher.</p>
+ <p>May raise exception <c>error:notsup</c> in case the chosen <c>Type</c>
+ is not supported by the underlying libcrypto implementation.</p>
+ <p>For keylengths and blocksizes see the
+ <seealso marker="crypto:algorithm_details#ciphers">User's Guide</seealso>.
+ </p>
</desc>
</func>
<func>
- <name>block_decrypt(Type, Key, CipherText) -> PlainText</name>
+ <name name="block_decrypt" arity="3"/>
<fsummary>Decrypt <c>CipherText</c> according to <c>Type</c> block cipher</fsummary>
- <type>
- <v>Type = des_ecb | blowfish_ecb | aes_ecb </v>
- <v>Key = block_key() </v>
- <v>PlainText = iodata() </v>
- </type>
<desc>
<p>Decrypt <c>CipherText</c> according to <c>Type</c> block cipher.</p>
- <p>May throw exception <c>notsup</c> in case the chosen <c>Type</c>
- is not supported by the underlying OpenSSL implementation.</p>
+ <p>May raise exception <c>error:notsup</c> in case the chosen <c>Type</c>
+ is not supported by the underlying libcrypto implementation.</p>
+ <p>For keylengths and blocksizes see the
+ <seealso marker="crypto:algorithm_details#ciphers">User's Guide</seealso>.
+ </p>
</desc>
</func>
<func>
<name>block_encrypt(Type, Key, Ivec, PlainText) -> CipherText</name>
<name>block_encrypt(AeadType, Key, Ivec, {AAD, PlainText}) -> {CipherText, CipherTag}</name>
- <name>block_encrypt(aes_gcm, Key, Ivec, {AAD, PlainText, TagLength}) -> {CipherText, CipherTag}</name>
+ <name>block_encrypt(aes_gcm | aes_ccm, Key, Ivec, {AAD, PlainText, TagLength}) -> {CipherText, CipherTag}</name>
<fsummary>Encrypt <c>PlainText</c> according to <c>Type</c> block cipher</fsummary>
<type>
- <v>Type = block_cipher() </v>
- <v>AeadType = aead_cipher() </v>
- <v>Key = block_key() </v>
- <v>PlainText = iodata() </v>
+ <v>Type = <seealso marker="#type-block_cipher_with_iv">block_cipher_with_iv()</seealso></v>
+ <v>AeadType = <seealso marker="#type-aead_cipher">aead_cipher()</seealso></v>
+ <v>Key = <seealso marker="#type-key">key()</seealso> | <seealso marker="#type-des3_key">des3_key()</seealso></v>
+ <v>PlainText = iodata()</v>
<v>AAD = IVec = CipherText = CipherTag = binary()</v>
<v>TagLength = 1..16</v>
</type>
@@ -257,8 +558,11 @@
<p>In AEAD (Authenticated Encryption with Associated Data) mode, encrypt
<c>PlainText</c>according to <c>Type</c> block cipher and calculate
<c>CipherTag</c> that also authenticates the <c>AAD</c> (Associated Authenticated Data).</p>
- <p>May throw exception <c>notsup</c> in case the chosen <c>Type</c>
- is not supported by the underlying OpenSSL implementation.</p>
+ <p>May raise exception <c>error:notsup</c> in case the chosen <c>Type</c>
+ is not supported by the underlying libcrypto implementation.</p>
+ <p>For keylengths, iv-sizes and blocksizes see the
+ <seealso marker="crypto:algorithm_details#ciphers">User's Guide</seealso>.
+ </p>
</desc>
</func>
@@ -267,10 +571,10 @@
<name>block_decrypt(AeadType, Key, Ivec, {AAD, CipherText, CipherTag}) -> PlainText | error</name>
<fsummary>Decrypt <c>CipherText</c> according to <c>Type</c> block cipher</fsummary>
<type>
- <v>Type = block_cipher() </v>
- <v>AeadType = aead_cipher() </v>
- <v>Key = block_key() </v>
- <v>PlainText = iodata() </v>
+ <v>Type = <seealso marker="#type-block_cipher_with_iv">block_cipher_with_iv()</seealso></v>
+ <v>AeadType = <seealso marker="#type-aead_cipher">aead_cipher()</seealso></v>
+ <v>Key = <seealso marker="#type-key">key()</seealso> | <seealso marker="#type-des3_key">des3_key()</seealso></v>
+ <v>PlainText = iodata()</v>
<v>AAD = IVec = CipherText = CipherTag = binary()</v>
</type>
<desc>
@@ -280,19 +584,17 @@
<c>CipherText</c>according to <c>Type</c> block cipher and check the authenticity
the <c>PlainText</c> and <c>AAD</c> (Associated Authenticated Data) using the
<c>CipherTag</c>. May return <c>error</c> if the decryption or validation fail's</p>
- <p>May throw exception <c>notsup</c> in case the chosen <c>Type</c>
- is not supported by the underlying OpenSSL implementation.</p>
+ <p>May raise exception <c>error:notsup</c> in case the chosen <c>Type</c>
+ is not supported by the underlying libcrypto implementation.</p>
+ <p>For keylengths, iv-sizes and blocksizes see the
+ <seealso marker="crypto:algorithm_details#ciphers">User's Guide</seealso>.
+ </p>
</desc>
</func>
<func>
- <name>bytes_to_integer(Bin) -> Integer </name>
+ <name name="bytes_to_integer" arity="1"/>
<fsummary>Convert binary representation, of an integer, to an Erlang integer.</fsummary>
- <type>
- <v>Bin = binary() - as returned by crypto functions</v>
-
- <v>Integer = integer() </v>
- </type>
<desc>
<p>Convert binary representation, of an integer, to an Erlang integer.
</p>
@@ -300,17 +602,8 @@
</func>
<func>
- <name>compute_key(Type, OthersPublicKey, MyKey, Params) -> SharedSecret</name>
+ <name name="compute_key" arity="4"/>
<fsummary>Computes the shared secret</fsummary>
- <type>
- <v> Type = dh | ecdh | srp </v>
- <v>OthersPublicKey = dh_public() | ecdh_public() | srp_public() </v>
- <v>MyKey = dh_private() | ecdh_private() | {srp_public(),srp_private()}</v>
- <v>Params = dh_params() | ecdh_params() | SrpUserParams | SrpHostParams</v>
- <v>SrpUserParams = {user, [DerivedKey::binary(), Prime::binary(), Generator::binary(), Version::atom() | [Scrambler:binary()]]} </v>
- <v>SrpHostParams = {host, [Verifier::binary(), Prime::binary(), Version::atom() | [Scrambler::binary]]} </v>
- <v>SharedSecret = binary()</v>
- </type>
<desc>
<p>Computes the shared secret from the private key and the other party's public key.
See also <seealso marker="public_key:public_key#compute_key-2">public_key:compute_key/2</seealso>
@@ -319,85 +612,61 @@
</func>
<func>
- <name>exor(Data1, Data2) -> Result</name>
+ <name name="exor" arity="2"/>
<fsummary>XOR data</fsummary>
- <type>
- <v>Data1, Data2 = iodata()</v>
- <v>Result = binary()</v>
- </type>
<desc>
<p>Performs bit-wise XOR (exclusive or) on the data supplied.</p>
</desc>
</func>
- <func>
- <name>generate_key(Type, Params) -> {PublicKey, PrivKeyOut} </name>
- <name>generate_key(Type, Params, PrivKeyIn) -> {PublicKey, PrivKeyOut} </name>
+
+ <func>
+ <name name="generate_key" arity="2"/>
+ <name name="generate_key" arity="3"/>
<fsummary>Generates a public key of type <c>Type</c></fsummary>
- <type>
- <v> Type = dh | ecdh | rsa | srp </v>
- <v>Params = dh_params() | ecdh_params() | RsaParams | SrpUserParams | SrpHostParams </v>
- <v>RsaParams = {ModulusSizeInBits::integer(), PublicExponent::key_value()}</v>
- <v>SrpUserParams = {user, [Generator::binary(), Prime::binary(), Version::atom()]}</v>
- <v>SrpHostParams = {host, [Verifier::binary(), Generator::binary(), Prime::binary(), Version::atom()]}</v>
- <v>PublicKey = dh_public() | ecdh_public() | rsa_public() | srp_public() </v>
- <v>PrivKeyIn = undefined | dh_private() | ecdh_private() | srp_private() </v>
- <v>PrivKeyOut = dh_private() | ecdh_private() | rsa_private() | srp_private() </v>
- </type>
<desc>
<p>Generates a public key of type <c>Type</c>.
See also <seealso marker="public_key:public_key#generate_key-1">public_key:generate_key/1</seealso>.
- May throw exception an exception of class <c>error</c>:
+ May raise exception:
</p>
<list type="bulleted">
- <item><c>badarg</c>: an argument is of wrong type or has an illegal value,</item>
- <item><c>low_entropy</c>: the random generator failed due to lack of secure "randomness",</item>
- <item><c>computation_failed</c>: the computation fails of another reason than <c>low_entropy</c>.</item>
+ <item><c>error:badarg</c>: an argument is of wrong type or has an illegal value,</item>
+ <item><c>error:low_entropy</c>: the random generator failed due to lack of secure "randomness",</item>
+ <item><c>error:computation_failed</c>: the computation fails of another reason than <c>low_entropy</c>.</item>
</list>
<note>
<p>RSA key generation is only available if the runtime was
built with dirty scheduler support. Otherwise, attempting to
- generate an RSA key will throw exception <c>error:notsup</c>.</p>
+ generate an RSA key will raise exception <c>error:notsup</c>.</p>
</note>
</desc>
</func>
<func>
- <name>hash(Type, Data) -> Digest</name>
+ <name name="hash" arity="2"/>
<fsummary></fsummary>
- <type>
- <v>Type = md4 | hash_algorithms()</v>
- <v>Data = iodata()</v>
- <v>Digest = binary()</v>
- </type>
<desc>
<p>Computes a message digest of type <c>Type</c> from <c>Data</c>.</p>
- <p>May throw exception <c>notsup</c> in case the chosen <c>Type</c>
- is not supported by the underlying OpenSSL implementation.</p>
+ <p>May raise exception <c>error:notsup</c> in case the chosen <c>Type</c>
+ is not supported by the underlying libcrypto implementation.</p>
</desc>
</func>
<func>
- <name>hash_init(Type) -> Context</name>
+ <name name="hash_init" arity="1"/>
<fsummary></fsummary>
- <type>
- <v>Type = md4 | hash_algorithms()</v>
- </type>
<desc>
<p>Initializes the context for streaming hash operations. <c>Type</c> determines
which digest to use. The returned context should be used as argument
to <seealso marker="#hash_update-2">hash_update</seealso>.</p>
- <p>May throw exception <c>notsup</c> in case the chosen <c>Type</c>
- is not supported by the underlying OpenSSL implementation.</p>
+ <p>May raise exception <c>error:notsup</c> in case the chosen <c>Type</c>
+ is not supported by the underlying libcrypto implementation.</p>
</desc>
</func>
<func>
- <name>hash_update(Context, Data) -> NewContext</name>
+ <name name="hash_update" arity="2"/>
<fsummary></fsummary>
- <type>
- <v>Data = iodata()</v>
- </type>
<desc>
<p>Updates the digest represented by <c>Context</c> using the given <c>Data</c>. <c>Context</c>
must have been generated using <seealso marker="#hash_init-1">hash_init</seealso>
@@ -406,12 +675,10 @@
or <seealso marker="#hash_final-1">hash_final</seealso>.</p>
</desc>
</func>
+
<func>
- <name>hash_final(Context) -> Digest</name>
+ <name name="hash_final" arity="1"/>
<fsummary></fsummary>
- <type>
- <v>Digest = binary()</v>
- </type>
<desc>
<p>Finalizes the hash operation referenced by <c>Context</c> returned
from a previous call to <seealso marker="#hash_update-2">hash_update</seealso>.
@@ -421,16 +688,9 @@
</func>
<func>
- <name>hmac(Type, Key, Data) -> Mac</name>
- <name>hmac(Type, Key, Data, MacLength) -> Mac</name>
+ <name name="hmac" arity="3"/>
+ <name name="hmac" arity="4"/>
<fsummary></fsummary>
- <type>
- <v>Type = hash_algorithms() - except ripemd160</v>
- <v>Key = iodata()</v>
- <v>Data = iodata()</v>
- <v>MacLength = integer()</v>
- <v>Mac = binary()</v>
- </type>
<desc>
<p>Computes a HMAC of type <c>Type</c> from <c>Data</c> using
<c>Key</c> as the authentication key.</p> <p><c>MacLength</c>
@@ -439,13 +699,8 @@
</func>
<func>
- <name>hmac_init(Type, Key) -> Context</name>
+ <name name="hmac_init" arity="2"/>
<fsummary></fsummary>
- <type>
- <v>Type = hash_algorithms() - except ripemd160</v>
- <v>Key = iodata()</v>
- <v>Context = binary()</v>
- </type>
<desc>
<p>Initializes the context for streaming HMAC operations. <c>Type</c> determines
which hash function to use in the HMAC operation. <c>Key</c> is the authentication
@@ -454,12 +709,8 @@
</func>
<func>
- <name>hmac_update(Context, Data) -> NewContext</name>
+ <name name="hmac_update" arity="2"/>
<fsummary></fsummary>
- <type>
- <v>Context = NewContext = binary()</v>
- <v>Data = iodata()</v>
- </type>
<desc>
<p>Updates the HMAC represented by <c>Context</c> using the given <c>Data</c>. <c>Context</c>
must have been generated using an HMAC init function (such as
@@ -472,16 +723,13 @@
call to hmac_update or hmac_final. The semantics of reusing old contexts
in any way is undefined and could even crash the VM in earlier releases.
The reason for this limitation is a lack of support in the underlying
- OpenSSL API.</p></warning>
+ libcrypto API.</p></warning>
</desc>
</func>
<func>
- <name>hmac_final(Context) -> Mac</name>
+ <name name="hmac_final" arity="1"/>
<fsummary></fsummary>
- <type>
- <v>Context = Mac = binary()</v>
- </type>
<desc>
<p>Finalizes the HMAC operation referenced by <c>Context</c>. The size of the resultant MAC is
determined by the type of hash function used to generate it.</p>
@@ -489,12 +737,8 @@
</func>
<func>
- <name>hmac_final_n(Context, HashLen) -> Mac</name>
+ <name name="hmac_final_n" arity="2"/>
<fsummary></fsummary>
- <type>
- <v>Context = Mac = binary()</v>
- <v>HashLen = non_neg_integer()</v>
- </type>
<desc>
<p>Finalizes the HMAC operation referenced by <c>Context</c>. <c>HashLen</c> must be greater than
zero. <c>Mac</c> will be a binary with at most <c>HashLen</c> bytes. Note that if HashLen is greater than the actual number of bytes returned from the underlying hash, the returned hash will have fewer than <c>HashLen</c> bytes.</p>
@@ -502,16 +746,9 @@
</func>
<func>
- <name>cmac(Type, Key, Data) -> Mac</name>
- <name>cmac(Type, Key, Data, MacLength) -> Mac</name>
+ <name name="cmac" arity="3"/>
+ <name name="cmac" arity="4"/>
<fsummary>Calculates the Cipher-based Message Authentication Code.</fsummary>
- <type>
- <v>Type = block_cipher()</v>
- <v>Key = iodata()</v>
- <v>Data = iodata()</v>
- <v>MacLength = integer()</v>
- <v>Mac = binary()</v>
- </type>
<desc>
<p>Computes a CMAC of type <c>Type</c> from <c>Data</c> using
<c>Key</c> as the authentication key.</p> <p><c>MacLength</c>
@@ -520,20 +757,21 @@
</func>
<func>
- <name>info_fips() -> Status</name>
+ <name name="info_fips" arity="0"/>
<fsummary>Provides information about the FIPS operating status.</fsummary>
- <type>
- <v>Status = enabled | not_enabled | not_supported</v>
- </type>
<desc>
<p>Provides information about the FIPS operating status of
- crypto and the underlying OpenSSL library. If crypto was built
+ crypto and the underlying libcrypto library. If crypto was built
with FIPS support this can be either <c>enabled</c> (when
running in FIPS mode) or <c>not_enabled</c>. For other builds
- this value is always <c>not_supported</c>.</p>
+ this value is always <c>not_supported</c>.
+ </p>
+ <p>See <seealso marker="#enable_fips_mode-1">enable_fips_mode/1</seealso> about how to enable
+ FIPS mode.
+ </p>
<warning>
<p>In FIPS mode all non-FIPS compliant algorithms are
- disabled and throw exception <c>not_supported</c>. Check
+ disabled and raise exception <c>error:notsup</c>. Check
<seealso marker="#supports-0">supports</seealso> that in
FIPS mode returns the restricted list of available
algorithms.</p>
@@ -542,13 +780,23 @@
</func>
<func>
- <name>info_lib() -> [{Name,VerNum,VerStr}]</name>
+ <name name="enable_fips_mode" arity="1"/>
+ <fsummary>Change FIPS mode.</fsummary>
+ <desc>
+ <p>Enables (<c>Enable = true</c>) or disables (<c>Enable = false</c>) FIPS mode. Returns <c>true</c> if
+ the operation was successful or <c>false</c> otherwise.
+ </p>
+ <p>Note that to enable FIPS mode succesfully, OTP must be built with the configure option <c>--enable-fips</c>,
+ and the underlying libcrypto must also support FIPS.
+ </p>
+ <p>See also <seealso marker="#info_fips-0">info_fips/0</seealso>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="info_lib" arity="0"/>
<fsummary>Provides information about the libraries used by crypto.</fsummary>
- <type>
- <v>Name = binary()</v>
- <v>VerNum = integer()</v>
- <v>VerStr = binary()</v>
- </type>
<desc>
<p>Provides the name and version of the libraries used by crypto.</p>
<p><c>Name</c> is the name of the library. <c>VerNum</c> is
@@ -561,52 +809,45 @@
<note><p>
From OTP R16 the <em>numeric version</em> represents the version of the OpenSSL
<em>header files</em> (<c>openssl/opensslv.h</c>) used when crypto was compiled.
- The text variant represents the OpenSSL library used at runtime.
+ The text variant represents the libcrypto library used at runtime.
In earlier OTP versions both numeric and text was taken from the library.
</p></note>
</desc>
</func>
<func>
- <name>mod_pow(N, P, M) -> Result</name>
+ <name name="mod_pow" arity="3"/>
<fsummary>Computes the function: N^P mod M</fsummary>
- <type>
- <v>N, P, M = binary() | integer()</v>
- <v>Result = binary() | error</v>
- </type>
<desc>
<p>Computes the function <c>N^P mod M</c>.</p>
</desc>
</func>
<func>
- <name>next_iv(Type, Data) -> NextIVec</name>
- <name>next_iv(Type, Data, IVec) -> NextIVec</name>
- <fsummary></fsummary>
- <type>
- <v>Type = des_cbc | des3_cbc | aes_cbc | des_cfb</v>
- <v>Data = iodata()</v>
- <v>IVec = NextIVec = binary()</v>
- </type>
- <desc>
- <p>Returns the initialization vector to be used in the next
- iteration of encrypt/decrypt of type <c>Type</c>. <c>Data</c> is the
- encrypted data from the previous iteration step. The <c>IVec</c>
- argument is only needed for <c>des_cfb</c> as the vector used
- in the previous iteration step.</p>
- </desc>
+ <name name="next_iv" arity="2"/>
+ <name name="next_iv" arity="3"/>
+ <fsummary></fsummary>
+ <desc>
+ <p>Returns the initialization vector to be used in the next
+ iteration of encrypt/decrypt of type <c>Type</c>. <c>Data</c> is the
+ encrypted data from the previous iteration step. The <c>IVec</c>
+ argument is only needed for <c>des_cfb</c> as the vector used
+ in the previous iteration step.</p>
+ </desc>
</func>
<func>
- <name>private_decrypt(Type, CipherText, PrivateKey, Padding) -> PlainText</name>
+ <name name="poly1305" arity="2"/>
+ <fsummary></fsummary>
+ <desc>
+ <p>Computes a POLY1305 message authentication code (<c>Mac</c>) from <c>Data</c> using
+ <c>Key</c> as the authentication key.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="private_decrypt" arity="4"/>
<fsummary>Decrypts CipherText using the private Key.</fsummary>
- <type>
- <v>Type = rsa</v>
- <v>CipherText = binary()</v>
- <v>PrivateKey = rsa_private() | engine_key_ref()</v>
- <v>Padding = rsa_pkcs1_padding | rsa_pkcs1_oaep_padding | rsa_no_padding</v>
- <v>PlainText = binary()</v>
- </type>
<desc>
<p>Decrypts the <c>CipherText</c>, encrypted with
<seealso marker="#public_encrypt-4">public_encrypt/4</seealso> (or equivalent function)
@@ -619,34 +860,8 @@
</func>
<func>
- <name>privkey_to_pubkey(Type, EnginePrivateKeyRef) -> PublicKey</name>
- <fsummary>Fetches a public key from an Engine stored private key.</fsummary>
- <type>
- <v>Type = rsa | dss</v>
- <v>EnginePrivateKeyRef = engine_key_ref()</v>
- <v>PublicKey = rsa_public() | dss_public()</v>
- </type>
- <desc>
- <p>Fetches the corresponding public key from a private key stored in an Engine.
- The key must be of the type indicated by the Type parameter.
- </p>
- </desc>
- </func>
-
- <func>
- <name>private_encrypt(Type, PlainText, PrivateKey, Padding) -> CipherText</name>
+ <name name="private_encrypt" arity="4"/>
<fsummary>Encrypts PlainText using the private Key.</fsummary>
- <type>
- <v>Type = rsa</v>
- <v>PlainText = binary()</v>
- <d> The size of the <c>PlainText</c> must be less
- than <c>byte_size(N)-11</c> if <c>rsa_pkcs1_padding</c> is
- used, and <c>byte_size(N)</c> if <c>rsa_no_padding</c> is
- used, where N is public modulus of the RSA key.</d>
- <v>PrivateKey = rsa_private() | engine_key_ref()</v>
- <v>Padding = rsa_pkcs1_padding | rsa_no_padding</v>
- <v>CipherText = binary()</v>
- </type>
<desc>
<p>Encrypts the <c>PlainText</c> using the <c>PrivateKey</c>
and returns the ciphertext. This is a low level signature operation
@@ -656,16 +871,10 @@
</p>
</desc>
</func>
+
<func>
- <name>public_decrypt(Type, CipherText, PublicKey, Padding) -> PlainText</name>
+ <name name="public_decrypt" arity="4"/>
<fsummary>Decrypts CipherText using the public Key.</fsummary>
- <type>
- <v>Type = rsa</v>
- <v>CipherText = binary()</v>
- <v>PublicKey = rsa_public() | engine_key_ref()</v>
- <v>Padding = rsa_pkcs1_padding | rsa_no_padding</v>
- <v>PlainText = binary()</v>
- </type>
<desc>
<p>Decrypts the <c>CipherText</c>, encrypted with
<seealso marker="#private_encrypt-4">private_encrypt/4</seealso>(or equivalent function)
@@ -678,19 +887,8 @@
</func>
<func>
- <name>public_encrypt(Type, PlainText, PublicKey, Padding) -> CipherText</name>
+ <name name="public_encrypt" arity="4"/>
<fsummary>Encrypts PlainText using the public Key.</fsummary>
- <type>
- <v>Type = rsa</v>
- <v>PlainText = binary()</v>
- <d> The size of the <c>PlainText</c> must be less
- than <c>byte_size(N)-11</c> if <c>rsa_pkcs1_padding</c> is
- used, and <c>byte_size(N)</c> if <c>rsa_no_padding</c> is
- used, where N is public modulus of the RSA key.</d>
- <v>PublicKey = rsa_public() | engine_key_ref()</v>
- <v>Padding = rsa_pkcs1_padding | rsa_pkcs1_oaep_padding | rsa_no_padding</v>
- <v>CipherText = binary()</v>
- </type>
<desc>
<p>Encrypts the <c>PlainText</c> (message digest) using the <c>PublicKey</c>
and returns the <c>CipherText</c>. This is a low level signature operation
@@ -701,18 +899,15 @@
</func>
<func>
- <name>rand_seed(Seed) -> ok</name>
+ <name name="rand_seed" arity="1"/>
<fsummary>Set the seed for random bytes generation</fsummary>
- <type>
- <v>Seed = binary()</v>
- </type>
<desc>
<p>Set the seed for PRNG to the given binary. This calls the
RAND_seed function from openssl. Only use this if the system
you are running on does not have enough "randomness" built in.
Normally this is when
<seealso marker="#strong_rand_bytes/1">strong_rand_bytes/1</seealso>
- throws <c>low_entropy</c></p>
+ raises <c>error:low_entropy</c></p>
</desc>
</func>
@@ -730,36 +925,15 @@
</func>
<func>
- <name>sign(Algorithm, DigestType, Msg, Key) -> binary()</name>
- <name>sign(Algorithm, DigestType, Msg, Key, Options) -> binary()</name>
- <fsummary> Create digital signature.</fsummary>
- <type>
- <v>Algorithm = rsa | dss | ecdsa </v>
- <v>Msg = binary() | {digest,binary()}</v>
- <d>The msg is either the binary "cleartext" data to be
- signed or it is the hashed value of "cleartext" i.e. the
- digest (plaintext).</d>
- <v>DigestType = rsa_digest_type() | dss_digest_type() | ecdsa_digest_type()</v>
- <v>Key = rsa_private() | dss_private() | [ecdh_private(),ecdh_params()] | engine_key_ref()</v>
- <v>Options = sign_options()</v>
- </type>
- <desc>
- <p>Creates a digital signature.</p>
- <p>Algorithm <c>dss</c> can only be used together with digest type
- <c>sha</c>.</p>
- <p>See also <seealso marker="public_key:public_key#sign-3">public_key:sign/3</seealso>.</p>
- </desc>
- </func>
-
- <func>
- <name>start() -> ok</name>
+ <name name="start" arity="0"/>
<fsummary> Equivalent to application:start(crypto). </fsummary>
<desc>
<p> Equivalent to application:start(crypto).</p>
</desc>
</func>
+
<func>
- <name>stop() -> ok</name>
+ <name name="stop" arity="0"/>
<fsummary> Equivalent to application:stop(crypto).</fsummary>
<desc>
<p> Equivalent to application:stop(crypto).</p>
@@ -767,23 +941,20 @@
</func>
<func>
- <name>strong_rand_bytes(N) -> binary()</name>
+ <name name="strong_rand_bytes" arity="1"/>
<fsummary>Generate a binary of random bytes</fsummary>
- <type>
- <v>N = integer()</v>
- </type>
<desc>
<p>Generates N bytes randomly uniform 0..255, and returns the
result in a binary. Uses a cryptographically secure prng seeded and
periodically mixed with operating system provided entropy. By default
this is the <c>RAND_bytes</c> method from OpenSSL.</p>
- <p>May throw exception <c>low_entropy</c> in case the random generator
+ <p>May raise exception <c>error:low_entropy</c> in case the random generator
failed due to lack of secure "randomness".</p>
</desc>
</func>
<func>
- <name>rand_seed() -> rand:state()</name>
+ <name name="rand_seed" arity="0"/>
<fsummary>Strong random number generation plugin state</fsummary>
<desc>
<p>
@@ -799,7 +970,7 @@
<p>
When using the state object from this function the
<seealso marker="stdlib:rand">rand</seealso> functions using it
- may throw exception <c>low_entropy</c> in case the random generator
+ may raise exception <c>error:low_entropy</c> in case the random generator
failed due to lack of secure "randomness".
</p>
<p><em>Example</em></p>
@@ -811,7 +982,7 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</func>
<func>
- <name>rand_seed_s() -> rand:state()</name>
+ <name name="rand_seed_s" arity="0"/>
<fsummary>Strong random number generation plugin state</fsummary>
<desc>
<p>
@@ -825,7 +996,7 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
<p>
When using the state object from this function the
<seealso marker="stdlib:rand">rand</seealso> functions using it
- may throw exception <c>low_entropy</c> in case the random generator
+ may raise exception <c>error:low_entropy</c> in case the random generator
failed due to lack of secure "randomness".
</p>
<note>
@@ -856,7 +1027,8 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
<p>
Creates state object for
<seealso marker="stdlib:rand">random number generation</seealso>,
- in order to generate cryptographically strong random numbers.
+ in order to generate cryptographically strong random numbers,
+ and saves it in the process dictionary before returning it as well.
See also
<seealso marker="stdlib:rand#seed-1">rand:seed/1</seealso> and
<seealso marker="#rand_seed_alg_s-1">rand_seed_alg_s/1</seealso>.
@@ -864,15 +1036,9 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
<p>
When using the state object from this function the
<seealso marker="stdlib:rand">rand</seealso> functions using it
- may throw exception <c>low_entropy</c> in case the random generator
+ may raise exception <c>error:low_entropy</c> in case the random generator
failed due to lack of secure "randomness".
</p>
- <p>
- The cache size can be changed from its default value using the
- <seealso marker="crypto_app">
- crypto app's
- </seealso> configuration parameter <c>rand_cache_size</c>.
- </p>
<p><em>Example</em></p>
<pre>
_ = crypto:rand_seed_alg(crypto_cache),
@@ -882,6 +1048,34 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</func>
<func>
+ <name>rand_seed_alg(Alg, Seed) -> rand:state()</name>
+ <fsummary>Strong random number generation plugin state</fsummary>
+ <type>
+ <v>Alg = crypto_aes</v>
+ </type>
+ <desc>
+ <marker id="rand_seed_alg-2" />
+ <p>
+ Creates a state object for
+ <seealso marker="stdlib:rand">random number generation</seealso>,
+ in order to generate cryptographically unpredictable random numbers,
+ and saves it in the process dictionary before returning it as well.
+ See also
+ <seealso marker="#rand_seed_alg_s-2">rand_seed_alg_s/2</seealso>.
+ </p>
+ <p><em>Example</em></p>
+ <pre>
+_ = crypto:rand_seed_alg(crypto_aes, "my seed"),
+IntegerValue = rand:uniform(42), % [1; 42]
+FloatValue = rand:uniform(), % [0.0; 1.0[
+_ = crypto:rand_seed_alg(crypto_aes, "my seed"),
+IntegerValue = rand:uniform(42), % Same values
+FloatValue = rand:uniform(). % again
+ </pre>
+ </desc>
+ </func>
+
+ <func>
<name>rand_seed_alg_s(Alg) -> rand:state()</name>
<fsummary>Strong random number generation plugin state</fsummary>
<type>
@@ -909,7 +1103,7 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
<p>
When using the state object from this function the
<seealso marker="stdlib:rand">rand</seealso> functions using it
- may throw exception <c>low_entropy</c> in case the random generator
+ may raise exception <c>error:low_entropy</c> in case the random generator
failed due to lack of secure "randomness".
</p>
<p>
@@ -918,6 +1112,12 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
crypto app's
</seealso> configuration parameter <c>rand_cache_size</c>.
</p>
+ <p>
+ When using the state object from this function the
+ <seealso marker="stdlib:rand">rand</seealso> functions using it
+ may throw exception <c>low_entropy</c> in case the random generator
+ failed due to lack of secure "randomness".
+ </p>
<note>
<p>
The state returned from this function cannot be used
@@ -940,45 +1140,102 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</func>
<func>
- <name>stream_init(Type, Key) -> State</name>
- <fsummary></fsummary>
+ <name>rand_seed_alg_s(Alg, Seed) -> rand:state()</name>
+ <fsummary>Strong random number generation plugin state</fsummary>
<type>
- <v>Type = rc4 </v>
- <v>State = opaque() </v>
- <v>Key = iodata()</v>
+ <v>Alg = crypto_aes</v>
</type>
<desc>
+ <marker id="rand_seed_alg_s-2" />
+ <p>
+ Creates a state object for
+ <seealso marker="stdlib:rand">random number generation</seealso>,
+ in order to generate cryptographically unpredictable random numbers.
+ See also
+ <seealso marker="#rand_seed_alg-1">rand_seed_alg/1</seealso>.
+ </p>
+ <p>
+ To get a long period the Xoroshiro928 generator from the
+ <seealso marker="stdlib:rand">rand</seealso>
+ module is used as a counter (with period 2^928 - 1)
+ and the generator states are scrambled through AES
+ to create 58-bit pseudo random values.
+ </p>
+ <p>
+ The result should be statistically completely unpredictable
+ random values, since the scrambling is cryptographically strong
+ and the period is ridiculously long. But the generated numbers
+ are not to be regarded as cryptographically strong since
+ there is no re-keying schedule.
+ </p>
+ <list type="bulleted">
+ <item>
+ <p>
+ If you need cryptographically strong random numbers use
+ <seealso marker="#rand_seed_alg_s-1">rand_seed_alg_s/1</seealso>
+ with <c>Alg =:= crypto</c> or <c>Alg =:= crypto_cache</c>.
+ </p>
+ </item>
+ <item>
+ <p>
+ If you need to be able to repeat the sequence use this function.
+ </p>
+ </item>
+ <item>
+ <p>
+ If you do not need the statistical quality of this function,
+ there are faster algorithms in the
+ <seealso marker="stdlib:rand">rand</seealso>
+ module.
+ </p>
+ </item>
+ </list>
+ <p>
+ Thanks to the used generator the state object supports the
+ <seealso marker="stdlib:rand#jump-0"><c>rand:jump/0,1</c></seealso>
+ function with distance 2^512.
+ </p>
+ <p>
+ Numbers are generated in batches and cached for speed reasons.
+ The cache size can be changed from its default value using the
+ <seealso marker="crypto_app">
+ crypto app's
+ </seealso> configuration parameter <c>rand_cache_size</c>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="stream_init" arity="2"/>
+ <fsummary></fsummary>
+ <desc>
<p>Initializes the state for use in RC4 stream encryption
<seealso marker="#stream_encrypt-2">stream_encrypt</seealso> and
<seealso marker="#stream_decrypt-2">stream_decrypt</seealso></p>
+ <p>For keylengths see the
+ <seealso marker="crypto:algorithm_details#stream-ciphers">User's Guide</seealso>.
+ </p>
</desc>
</func>
<func>
- <name>stream_init(Type, Key, IVec) -> State</name>
+ <name name="stream_init" arity="3"/>
<fsummary></fsummary>
- <type>
- <v>Type = aes_ctr </v>
- <v>State = opaque() </v>
- <v>Key = iodata()</v>
- <v>IVec = binary()</v>
- </type>
<desc>
<p>Initializes the state for use in streaming AES encryption using Counter mode (CTR).
<c>Key</c> is the AES key and must be either 128, 192, or 256 bits long. <c>IVec</c> is
an arbitrary initializing vector of 128 bits (16 bytes). This state is for use with
<seealso marker="#stream_encrypt-2">stream_encrypt</seealso> and
<seealso marker="#stream_decrypt-2">stream_decrypt</seealso>.</p>
+ <p>For keylengths and iv-sizes see the
+ <seealso marker="crypto:algorithm_details#stream-ciphers">User's Guide</seealso>.
+ </p>
</desc>
</func>
<func>
- <name>stream_encrypt(State, PlainText) -> { NewState, CipherText}</name>
+ <name name="stream_encrypt" arity="2"/>
<fsummary></fsummary>
- <type>
- <v>Text = iodata()</v>
- <v>CipherText = binary()</v>
- </type>
<desc>
<p>Encrypts <c>PlainText</c> according to the stream cipher <c>Type</c> specified in stream_init/3.
<c>Text</c> can be any number of bytes. The initial <c>State</c> is created using
@@ -988,12 +1245,8 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</func>
<func>
- <name>stream_decrypt(State, CipherText) -> { NewState, PlainText }</name>
+ <name name="stream_decrypt" arity="2"/>
<fsummary></fsummary>
- <type>
- <v>CipherText = iodata()</v>
- <v>PlainText = binary()</v>
- </type>
<desc>
<p>Decrypts <c>CipherText</c> according to the stream cipher <c>Type</c> specified in stream_init/3.
<c>PlainText</c> can be any number of bytes. The initial <c>State</c> is created using
@@ -1003,60 +1256,57 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</func>
<func>
- <name>supports() -> AlgorithmList </name>
+ <name name="supports" arity="0"/>
<fsummary>Provide a list of available crypto algorithms.</fsummary>
- <type>
- <v> AlgorithmList = [{hashs, [hash_algorithms()]},
- {ciphers, [cipher_algorithms()]},
- {public_keys, [public_key_algorithms()]},
- {macs, [mac_algorithms()]}]
- </v>
- </type>
<desc>
<p> Can be used to determine which crypto algorithms that are supported
- by the underlying OpenSSL library</p>
+ by the underlying libcrypto library</p>
+ <p>Note: the <c>rsa_opts</c> entry is in an experimental state and may change or be removed without notice.
+ No guarantee for the accuarcy of the rsa option's value list should be assumed.
+ </p>
</desc>
</func>
<func>
- <name>ec_curves() -> EllipticCurveList </name>
+ <name name="ec_curves" arity="0"/>
<fsummary>Provide a list of available named elliptic curves.</fsummary>
- <type>
- <v>EllipticCurveList = [ec_named_curve()]</v>
- </type>
<desc>
<p>Can be used to determine which named elliptic curves are supported.</p>
</desc>
</func>
<func>
- <name>ec_curve(NamedCurve) -> EllipticCurve </name>
+ <name name="ec_curve" arity="1"/>
<fsummary>Get the defining parameters of a elliptic curve.</fsummary>
- <type>
- <v>NamedCurve = ec_named_curve()</v>
- <v>EllipticCurve = ec_explicit_curve()</v>
- </type>
<desc>
<p>Return the defining parameters of a elliptic curve.</p>
</desc>
</func>
- <func>
- <name>verify(Algorithm, DigestType, Msg, Signature, Key) -> boolean()</name>
- <name>verify(Algorithm, DigestType, Msg, Signature, Key, Options) -> boolean()</name>
+ <func>
+ <name name="sign" arity="4"/>
+ <name name="sign" arity="5"/>
+ <fsummary> Create digital signature.</fsummary>
+ <desc>
+ <p>Creates a digital signature.</p>
+ <p>The msg is either the binary "cleartext" data to be
+ signed or it is the hashed value of "cleartext" i.e. the
+ digest (plaintext).</p>
+ <p>Algorithm <c>dss</c> can only be used together with digest type
+ <c>sha</c>.</p>
+ <p>See also <seealso marker="public_key:public_key#sign-3">public_key:sign/3</seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="verify" arity="5"/>
+ <name name="verify" arity="6"/>
<fsummary>Verifies a digital signature.</fsummary>
- <type>
- <v> Algorithm = rsa | dss | ecdsa </v>
- <v>Msg = binary() | {digest,binary()}</v>
- <d>The msg is either the binary "cleartext" data
- or it is the hashed value of "cleartext" i.e. the digest (plaintext).</d>
- <v>DigestType = rsa_digest_type() | dss_digest_type() | ecdsa_digest_type()</v>
- <v>Signature = binary()</v>
- <v>Key = rsa_public() | dss_public() | [ecdh_public(),ecdh_params()] | engine_key_ref()</v>
- <v>Options = sign_options()</v>
- </type>
<desc>
<p>Verifies a digital signature</p>
+ <p>The msg is either the binary "cleartext" data to be
+ signed or it is the hashed value of "cleartext" i.e. the
+ digest (plaintext).</p>
<p>Algorithm <c>dss</c> can only be used together with digest type
<c>sha</c>.</p>
@@ -1066,17 +1316,24 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
<!-- Engine functions -->
<func>
- <name>engine_get_all_methods() -> Result</name>
+ <name name="privkey_to_pubkey" arity="2"/>
+ <fsummary>Fetches a public key from an Engine stored private key.</fsummary>
+ <desc>
+ <p>Fetches the corresponding public key from a private key stored in an Engine.
+ The key must be of the type indicated by the Type parameter.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="engine_get_all_methods" arity="0"/>
<fsummary>Return list of all possible engine methods</fsummary>
- <type>
- <v>Result = [EngineMethod::atom()]</v>
- </type>
<desc>
<p>
Returns a list of all possible engine methods.
</p>
- <p>
- May throw exception notsup in case there is
+ <p>
+ May raise exception <c>error:notsup</c> in case there is
no engine support in the underlying OpenSSL implementation.
</p>
<p>
@@ -1087,23 +1344,18 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</func>
<func>
- <name>engine_load(EngineId, PreCmds, PostCmds) -> Result</name>
+ <name name="engine_load" arity="3"/>
<fsummary>Dynamical load an encryption engine</fsummary>
- <type>
- <v>EngineId = unicode:chardata()</v>
- <v>PreCmds, PostCmds = [{unicode:chardata(), unicode:chardata()}]</v>
- <v>Result = {ok, Engine::term()} | {error, Reason::term()}</v>
- </type>
<desc>
<p>
Loads the OpenSSL engine given by <c>EngineId</c> if it is available and then returns ok and
- an engine handle. This function is the same as calling <c>engine_load/4</c> with
- <c>EngineMethods</c> set to a list of all the possible methods. An error tuple is
+ an engine handle. This function is the same as calling <c>engine_load/4</c> with
+ <c>EngineMethods</c> set to a list of all the possible methods. An error tuple is
returned if the engine can't be loaded.
</p>
<p>
- The function throws a badarg if the parameters are in wrong format.
- It may also throw the exception notsup in case there is
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
no engine support in the underlying OpenSSL implementation.
</p>
<p>
@@ -1114,22 +1366,16 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</func>
<func>
- <name>engine_load(EngineId, PreCmds, PostCmds, EngineMethods) -> Result</name>
+ <name name="engine_load" arity="4"/>
<fsummary>Dynamical load an encryption engine</fsummary>
- <type>
- <v>EngineId = unicode:chardata()</v>
- <v>PreCmds, PostCmds = [{unicode:chardata(), unicode:chardata()}]</v>
- <v>EngineMethods = [engine_method_type()]</v>
- <v>Result = {ok, Engine::term()} | {error, Reason::term()}</v>
- </type>
<desc>
<p>
Loads the OpenSSL engine given by <c>EngineId</c> if it is available and then returns ok and
an engine handle. An error tuple is returned if the engine can't be loaded.
</p>
<p>
- The function throws a badarg if the parameters are in wrong format.
- It may also throw the exception notsup in case there is
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
no engine support in the underlying OpenSSL implementation.
</p>
<p>
@@ -1140,20 +1386,16 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</func>
<func>
- <name>engine_unload(Engine) -> Result</name>
+ <name name="engine_unload" arity="1"/>
<fsummary>Dynamical load an encryption engine</fsummary>
- <type>
- <v>Engine = term()</v>
- <v>Result = ok | {error, Reason::term()}</v>
- </type>
<desc>
<p>
- Unloads the OpenSSL engine given by <c>EngineId</c>.
+ Unloads the OpenSSL engine given by <c>Engine</c>.
An error tuple is returned if the engine can't be unloaded.
</p>
<p>
- The function throws a badarg if the parameter is in wrong format.
- It may also throw the exception notsup in case there is
+ The function raises a <c>error:badarg</c> if the parameter is in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
no engine support in the underlying OpenSSL implementation.
</p>
<p>
@@ -1164,146 +1406,225 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</func>
<func>
- <name>engine_list() -> Result</name>
- <fsummary>List the known engine ids</fsummary>
- <type>
- <v>Result = [EngineId::unicode:chardata()]</v>
- </type>
+ <name name="engine_by_id" arity="1"/>
+ <fsummary>Get a reference to an already loaded engine</fsummary>
<desc>
- <p>List the id's of all engines in OpenSSL's internal list.</p>
<p>
- It may also throw the exception notsup in case there is
+ Get a reference to an already loaded engine with <c>EngineId</c>.
+ An error tuple is returned if the engine can't be unloaded.
+ </p>
+ <p>
+ The function raises a <c>error:badarg</c> if the parameter is in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
no engine support in the underlying OpenSSL implementation.
</p>
<p>
- See also the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
+ See also the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
in the User's Guide.
</p>
</desc>
</func>
<func>
- <name>engine_ctrl_cmd_string(Engine, CmdName, CmdArg) -> Result</name>
+ <name name="engine_ctrl_cmd_string" arity="3"/>
<fsummary>Sends ctrl commands to an OpenSSL engine</fsummary>
- <type>
- <v>Engine = term()</v>
- <v>CmdName = unicode:chardata()</v>
- <v>CmdArg = unicode:chardata()</v>
- <v>Result = ok | {error, Reason::term()}</v>
- </type>
<desc>
<p>
Sends ctrl commands to the OpenSSL engine given by <c>Engine</c>.
- This function is the same as calling <c>engine_ctrl_cmd_string/4</c> with
+ This function is the same as calling <c>engine_ctrl_cmd_string/4</c> with
<c>Optional</c> set to <c>false</c>.
</p>
<p>
- The function throws a badarg if the parameters are in wrong format.
- It may also throw the exception notsup in case there is
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
no engine support in the underlying OpenSSL implementation.
</p>
</desc>
</func>
<func>
- <name>engine_ctrl_cmd_string(Engine, CmdName, CmdArg, Optional) -> Result</name>
+ <name name="engine_ctrl_cmd_string" arity="4"/>
<fsummary>Sends ctrl commands to an OpenSSL engine</fsummary>
- <type>
- <v>Engine = term()</v>
- <v>CmdName = unicode:chardata()</v>
- <v>CmdArg = unicode:chardata()</v>
- <v>Optional = boolean()</v>
- <v>Result = ok | {error, Reason::term()}</v>
- </type>
<desc>
<p>
Sends ctrl commands to the OpenSSL engine given by <c>Engine</c>.
- <c>Optional</c> is a boolean argument that can relax the semantics of the function.
- If set to <c>true</c> it will only return failure if the ENGINE supported the given
- command name but failed while executing it, if the ENGINE doesn't support the command
- name it will simply return success without doing anything. In this case we assume
+ <c>Optional</c> is a boolean argument that can relax the semantics of the function.
+ If set to <c>true</c> it will only return failure if the ENGINE supported the given
+ command name but failed while executing it, if the ENGINE doesn't support the command
+ name it will simply return success without doing anything. In this case we assume
the user is only supplying commands specific to the given ENGINE so we set this to
<c>false</c>.
</p>
<p>
- The function throws a badarg if the parameters are in wrong format.
- It may also throw the exception notsup in case there is
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="engine_add" arity="1"/>
+ <fsummary>Add engine to OpenSSL internal list</fsummary>
+ <desc>
+ <p>Add the engine to OpenSSL's internal list.</p>
+ <p>
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="engine_remove" arity="1"/>
+ <fsummary>Remove engine to OpenSSL internal list</fsummary>
+ <desc>
+ <p>Remove the engine from OpenSSL's internal list.</p>
+ <p>
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="engine_get_id" arity="1"/>
+ <fsummary>Fetch engine ID</fsummary>
+ <desc>
+ <p>Return the ID for the engine, or an empty binary if there is no id set.</p>
+ <p>
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="engine_get_name" arity="1"/>
+ <fsummary>Fetch engine name</fsummary>
+ <desc>
+ <p>Return the name (eg a description) for the engine, or an empty binary if there is no name set.</p>
+ <p>
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="engine_list" arity="0"/>
+ <fsummary>List the known engine ids</fsummary>
+ <desc>
+ <p>List the id's of all engines in OpenSSL's internal list.</p>
+ <p>
+ It may also raise the exception <c>error:notsup</c> in case there is
no engine support in the underlying OpenSSL implementation.
</p>
+ <p>
+ See also the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
+ in the User's Guide.
+ </p>
+ <p>
+ May raise exception <c>error:notsup</c> in case engine functionality is not supported by the underlying
+ OpenSSL implementation.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="ensure_engine_loaded" arity="2"/>
+ <fsummary>Ensure encryption engine just loaded once</fsummary>
+ <desc>
+ <p>
+ Loads the OpenSSL engine given by <c>EngineId</c> and the path to the dynamic library
+ implementing the engine. This function is the same as calling <c>ensure_engine_loaded/3</c> with
+ <c>EngineMethods</c> set to a list of all the possible methods. An error tuple is
+ returned if the engine can't be loaded.
+ </p>
+ <p>
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ <p>
+ See also the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
+ in the User's Guide.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="ensure_engine_loaded" arity="3"/>
+ <fsummary>Ensure encryption engine just loaded once</fsummary>
+ <desc>
+ <p>
+ Loads the OpenSSL engine given by <c>EngineId</c> and the path to the dynamic library
+ implementing the engine. This function differs from the normal engine_load in that sense it
+ also add the engine id to the internal list in OpenSSL. Then in the following calls to the function
+ it just fetch the reference to the engine instead of loading it again.
+ An error tuple is returned if the engine can't be loaded.
+ </p>
+ <p>
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ <p>
+ See also the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
+ in the User's Guide.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="ensure_engine_unloaded" arity="1"/>
+ <fsummary>Unload an engine loaded with the ensure function</fsummary>
+ <desc>
+ <p>
+ Unloads an engine loaded with the <c>ensure_engine_loaded</c> function.
+ It both removes the label from the OpenSSL internal engine list and unloads the engine.
+ This function is the same as calling <c>ensure_engine_unloaded/2</c> with
+ <c>EngineMethods</c> set to a list of all the possible methods. An error tuple is
+ returned if the engine can't be unloaded.
+ </p>
+ <p>
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ <p>
+ See also the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
+ in the User's Guide.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="ensure_engine_unloaded" arity="2"/>
+ <fsummary>Unload an engine loaded with the ensure function</fsummary>
+ <desc>
+ <p>
+ Unloads an engine loaded with the <c>ensure_engine_loaded</c> function.
+ It both removes the label from the OpenSSL internal engine list and unloads the engine.
+ An error tuple is returned if the engine can't be unloaded.
+ </p>
+ <p>
+ The function raises a <c>error:badarg</c> if the parameters are in wrong format.
+ It may also raise the exception <c>error:notsup</c> in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ <p>
+ See also the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
+ in the User's Guide.
+ </p>
</desc>
</func>
</funcs>
- <!-- Maybe put this in the users guide -->
- <!-- <section> -->
- <!-- <title>DES in CBC mode</title> -->
- <!-- <p>The Data Encryption Standard (DES) defines an algorithm for -->
- <!-- encrypting and decrypting an 8 byte quantity using an 8 byte key -->
- <!-- (actually only 56 bits of the key is used). -->
- <!-- </p> -->
- <!-- <p>When it comes to encrypting and decrypting blocks that are -->
- <!-- multiples of 8 bytes various modes are defined (NIST SP -->
- <!-- 800-38A). One of those modes is the Cipher Block Chaining (CBC) -->
- <!-- mode, where the encryption of an 8 byte segment depend not only -->
- <!-- of the contents of the segment itself, but also on the result of -->
- <!-- encrypting the previous segment: the encryption of the previous -->
- <!-- segment becomes the initializing vector of the encryption of the -->
- <!-- current segment. -->
- <!-- </p> -->
- <!-- <p>Thus the encryption of every segment depends on the encryption -->
- <!-- key (which is secret) and the encryption of the previous -->
- <!-- segment, except the first segment which has to be provided with -->
- <!-- an initial initializing vector. That vector could be chosen at -->
- <!-- random, or be a counter of some kind. It does not have to be -->
- <!-- secret. -->
- <!-- </p> -->
- <!-- <p>The following example is drawn from the old FIPS 81 standard -->
- <!-- (replaced by NIST SP 800-38A), where both the plain text and the -->
- <!-- resulting cipher text is settled. The following code fragment -->
- <!-- returns `true'. -->
- <!-- </p> -->
- <!-- <pre><![CDATA[ -->
-
- <!-- Key = <<16#01,16#23,16#45,16#67,16#89,16#ab,16#cd,16#ef>>, -->
- <!-- IVec = <<16#12,16#34,16#56,16#78,16#90,16#ab,16#cd,16#ef>>, -->
- <!-- P = "Now is the time for all ", -->
- <!-- C = crypto:des_cbc_encrypt(Key, IVec, P), -->
- <!-- % Which is the same as -->
- <!-- P1 = "Now is t", P2 = "he time ", P3 = "for all ", -->
- <!-- C1 = crypto:des_cbc_encrypt(Key, IVec, P1), -->
- <!-- C2 = crypto:des_cbc_encrypt(Key, C1, P2), -->
- <!-- C3 = crypto:des_cbc_encrypt(Key, C2, P3), -->
-
- <!-- C = <<C1/binary, C2/binary, C3/binary>>, -->
- <!-- C = <<16#e5,16#c7,16#cd,16#de,16#87,16#2b,16#f2,16#7c, -->
- <!-- 16#43,16#e9,16#34,16#00,16#8c,16#38,16#9c,16#0f, -->
- <!-- 16#68,16#37,16#88,16#49,16#9a,16#7c,16#05,16#f6>>, -->
- <!-- <<"Now is the time for all ">> == -->
- <!-- crypto:des_cbc_decrypt(Key, IVec, C). -->
- <!-- ]]></pre> -->
- <!-- <p>The following is true for the DES CBC mode. For all -->
- <!-- decompositions <c>P1 ++ P2 = P</c> of a plain text message -->
- <!-- <c>P</c> (where the length of all quantities are multiples of 8 -->
- <!-- bytes), the encryption <c>C</c> of <c>P</c> is equal to <c>C1 ++ -->
- <!-- C2</c>, where <c>C1</c> is obtained by encrypting <c>P1</c> with -->
- <!-- <c>Key</c> and the initializing vector <c>IVec</c>, and where -->
- <!-- <c>C2</c> is obtained by encrypting <c>P2</c> with <c>Key</c> -->
- <!-- and the initializing vector <c>last8(C1)</c>, -->
- <!-- where <c>last(Binary)</c> denotes the last 8 bytes of the -->
- <!-- binary <c>Binary</c>. -->
- <!-- </p> -->
- <!-- <p>Similarly, for all decompositions <c>C1 ++ C2 = C</c> of a -->
- <!-- cipher text message <c>C</c> (where the length of all quantities -->
- <!-- are multiples of 8 bytes), the decryption <c>P</c> of <c>C</c> -->
- <!-- is equal to <c>P1 ++ P2</c>, where <c>P1</c> is obtained by -->
- <!-- decrypting <c>C1</c> with <c>Key</c> and the initializing vector -->
- <!-- <c>IVec</c>, and where <c>P2</c> is obtained by decrypting -->
- <!-- <c>C2</c> with <c>Key</c> and the initializing vector -->
- <!-- <c>last8(C1)</c>, where <c>last8(Binary)</c> is as above. -->
- <!-- </p> -->
- <!-- <p>For DES3 (which uses three 64 bit keys) the situation is the -->
- <!-- same. -->
- <!-- </p> -->
- <!-- </section> -->
+
</erlref>
diff --git a/lib/crypto/doc/src/engine_keys.xml b/lib/crypto/doc/src/engine_keys.xml
index 80d811c47e..b28606fb4e 100644
--- a/lib/crypto/doc/src/engine_keys.xml
+++ b/lib/crypto/doc/src/engine_keys.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2017</year><year>2017</year>
+ <year>2017</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -62,7 +62,7 @@
on the Engine loaded
</item>
<item>an Erlang map is constructed with the Engine reference, the key reference and possibly a key passphrase if
- needed by the Engine. See the <seealso marker="crypto:crypto#engine_key_ref_type">Reference Manual</seealso> for
+ needed by the Engine. See the <seealso marker="crypto:crypto#type-engine_key_ref">Reference Manual</seealso> for
details of the map.
</item>
</list>
diff --git a/lib/crypto/doc/src/engine_load.xml b/lib/crypto/doc/src/engine_load.xml
index e5c3f5d561..5f7ccc784b 100644
--- a/lib/crypto/doc/src/engine_load.xml
+++ b/lib/crypto/doc/src/engine_load.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2017</year><year>2017</year>
+ <year>2017</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -42,6 +42,9 @@
operations. The hardware implementation usually offers improved performance over its
software-based counterpart, which is known as cryptographic acceleration.
</p>
+ <note>
+ <p>The file name requirement on the engine dynamic library can differ between SSL versions.</p>
+ </note>
</section>
<section>
@@ -54,9 +57,6 @@
<code>
1> {ok, Engine} = crypto:engine_load(&lt;&lt;"otp_test_engine">>, [], []).
{ok, #Ref}</code>
- <note>
- <p>The file name requirement on the engine dynamic library can differ between SSL versions.</p>
- </note>
</section>
<section>
@@ -72,9 +72,6 @@
&lt;&lt;"LOAD">>],
[]).
{ok, #Ref}</code>
- <note>
- <p>The dynamic engine is not supported in LibreSSL from version 2.2.1</p>
- </note>
</section>
<section>
@@ -100,6 +97,28 @@ engine_method_pkey_meths, engine_method_pkey_asn1_meths].
</section>
<section>
+ <title>Load with the ensure loaded function</title>
+ <p>
+ This function makes sure the engine is loaded just once and the ID is added to the internal
+ engine list of OpenSSL. The following calls to the function will check if the ID is loaded
+ and then just get a new reference to the engine.
+ </p>
+ <code>
+ 5> {ok, Engine} = crypto:ensure_engine_loaded(&lt;&lt;"MD5">>,
+ &lt;&lt;"/some/path/otp_test_engine.so">>).
+ {ok, #Ref}</code>
+ <p>
+ To unload it use crypto:ensure_engine_unloaded/1 which removes the ID from the internal list
+ before unloading the engine.
+ </p>
+ <code>
+ 6> crypto:ensure_engine_unloaded(&lt;&lt;"MD5">>).
+ ok</code>
+ </section>
+
+
+
+ <section>
<title>List all engines currently loaded</title>
<code>
5> crypto:engine_list().
diff --git a/lib/crypto/doc/src/notes.xml b/lib/crypto/doc/src/notes.xml
index 5e0851f6b8..d81a8ddd87 100644
--- a/lib/crypto/doc/src/notes.xml
+++ b/lib/crypto/doc/src/notes.xml
@@ -31,6 +31,148 @@
</header>
<p>This document describes the changes made to the Crypto application.</p>
+<section><title>Crypto 4.3.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The RSA options <c>rsa_mgf1_md</c>, <c>rsa_oaep_md</c>,
+ and <c>rsa_oaep_label</c> were always disabled. They will
+ now be enabled when a suitable cryptolib is used.</p>
+ <p>
+ They are still experimental and may change without prior
+ notice.</p>
+ <p>
+ Own Id: OTP-15212 Aux Id: ERL-675, PR1899, PR838 </p>
+ </item>
+ <item>
+ <p>
+ The ciphers <c>aes_ige256</c> and <c>blowfish_cbc</c> had
+ naming issues in <c>crypto:next_iv/2</c>.</p>
+ <p>
+ Own Id: OTP-15283</p>
+ </item>
+ <item>
+ <p>
+ the <c>RSA_SSLV23_PADDING</c> is disabled if LibreSSL is
+ used as cryptlib. This is due to compilation problems.</p>
+ <p>
+ This will be investigated further in the future.</p>
+ <p>
+ Own Id: OTP-15303</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The supported named elliptic curves are now reported in
+ <c>crypto:supports/0</c> in a new entry tagged by
+ <c>'curves'</c>.</p>
+ <p>
+ The function <c>crypto:ec_curves/0</c> is kept for
+ compatibility.</p>
+ <p>
+ Own Id: OTP-14717 Aux Id: OTP-15244 </p>
+ </item>
+ <item>
+ <p>
+ The typing in the CRYPTO and PUBLIC_KEY applications are
+ reworked and a few mistakes are corrected.</p>
+ <p>
+ The documentation is now generated from the typing and
+ some clarifications are made.</p>
+ <p>
+ A new chapter on Algorithm Details such as key sizes and
+ availability is added to the CRYPTO User's Guide.</p>
+ <p>
+ Own Id: OTP-15134</p>
+ </item>
+ <item>
+ <p>
+ Support for SHA3 both as a separate hash and in HMAC is
+ now available if OpenSSL 1.1.1 or higher is used as
+ cryptolib.</p>
+ <p>
+ Available lengths are reported in the <c>'hashs'</c>
+ entry in <c>crypto:supports/0</c> as <c>sha3_*</c>.</p>
+ <p>
+ Own Id: OTP-15153</p>
+ </item>
+ <item>
+ <p>
+ The mac algorithm <c>poly1305</c> and the cipher
+ algorithm <c>chacha20</c> are now supported if OpenSSL
+ 1.1.1 or higher is used as cryptolib.</p>
+ <p>
+ Own Id: OTP-15164 Aux Id: OTP-15209 </p>
+ </item>
+ <item>
+ <p>
+ The key exchange Edward curves <c>x25519</c> and
+ <c>x448</c> are now supported if OpenSSL 1.1.1 or higher
+ is used as cryptolib.</p>
+ <p>
+ Own Id: OTP-15240 Aux Id: OTP-15133 </p>
+ </item>
+ <item>
+ <p>
+ The supported RSA options for sign/verify and
+ encrypt/decrypt are now reported in
+ <c>crypto:supports/0</c> in a new entry tagged by
+ '<c>rsa_opts</c>'.</p>
+ <p>
+ The exakt set is still experimental and may change
+ without prior notice.</p>
+ <p>
+ Own Id: OTP-15260</p>
+ </item>
+ <item>
+ <p>
+ The cipher <c>aes_ccm</c> is added.</p>
+ <p>
+ Own Id: OTP-15286</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Crypto 4.3.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Update the crypto engine functions to handle multiple
+ loads of an engine. </p> <p><c>engine_load/3/4</c> is
+ updated so it doesn't add the engine ID to OpenSSLs
+ internal list of engines which makes it possible to run
+ the engine_load more than once if it doesn't contain
+ global data.</p> <p>Added <c>ensure_engine_loaded/2/3</c>
+ which guarantees that the engine just is loaded once and
+ the following calls just returns a reference to it. This
+ is done by add the ID to the internal OpenSSL list and
+ check if it is already registered when the function is
+ called.</p> <p>Added <c>ensure_engine_unloaded/1/2</c> to
+ unload engines loaded with ensure_engine_loaded.</p>
+ <p>Then some more utility functions are added.</p>
+ <p><c>engine_add/1</c>, adds the engine to OpenSSL
+ internal list</p> <p><c>engine_remove/1</c>, remove the
+ engine from OpenSSL internal list</p>
+ <p><c>engine_get_id/1</c>, fetch the engines id</p>
+ <p><c>engine_get_name/1</c>, fetch the engine name</p>
+ <p>
+ Own Id: OTP-15233</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Crypto 4.3.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/crypto/doc/src/specs.xml b/lib/crypto/doc/src/specs.xml
new file mode 100644
index 0000000000..66c79a906b
--- /dev/null
+++ b/lib/crypto/doc/src/specs.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<specs xmlns:xi="http://www.w3.org/2001/XInclude">
+ <xi:include href="../specs/specs_crypto.xml"/>
+</specs>
diff --git a/lib/crypto/doc/src/usersguide.xml b/lib/crypto/doc/src/usersguide.xml
index 0124121433..2dfc966609 100644
--- a/lib/crypto/doc/src/usersguide.xml
+++ b/lib/crypto/doc/src/usersguide.xml
@@ -50,4 +50,5 @@
<xi:include href="fips.xml"/>
<xi:include href="engine_load.xml"/>
<xi:include href="engine_keys.xml"/>
+ <xi:include href="algorithm_details.xml"/>
</part>
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index 835cadce47..68c0bcef5e 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -29,10 +29,12 @@
-export([generate_key/2, generate_key/3, compute_key/4]).
-export([hmac/3, hmac/4, hmac_init/2, hmac_update/2, hmac_final/1, hmac_final_n/2]).
-export([cmac/3, cmac/4]).
+-export([poly1305/2]).
-export([exor/2, strong_rand_bytes/1, mod_pow/3]).
--export([rand_seed/0, rand_seed_alg/1]).
--export([rand_seed_s/0, rand_seed_alg_s/1]).
+-export([rand_seed/0, rand_seed_alg/1, rand_seed_alg/2]).
+-export([rand_seed_s/0, rand_seed_alg_s/1, rand_seed_alg_s/2]).
-export([rand_plugin_next/1]).
+-export([rand_plugin_aes_next/1, rand_plugin_aes_jump/1]).
-export([rand_plugin_uniform/1]).
-export([rand_plugin_uniform/2]).
-export([rand_cache_plugin_next/1]).
@@ -51,19 +53,49 @@
engine_load/3,
engine_load/4,
engine_unload/1,
+ engine_by_id/1,
engine_list/0,
engine_ctrl_cmd_string/3,
- engine_ctrl_cmd_string/4
+ engine_ctrl_cmd_string/4,
+ engine_add/1,
+ engine_remove/1,
+ engine_get_id/1,
+ engine_get_name/1,
+ ensure_engine_loaded/2,
+ ensure_engine_loaded/3,
+ ensure_engine_unloaded/1,
+ ensure_engine_unloaded/2
]).
+-export_type([ %% A minimum exported: only what public_key needs.
+ dh_private/0,
+ dh_public/0,
+ dss_digest_type/0,
+ ec_named_curve/0,
+ ecdsa_digest_type/0,
+ pk_encrypt_decrypt_opts/0,
+ pk_sign_verify_opts/0,
+ rsa_digest_type/0,
+ sha1/0,
+ sha2/0
+ ]).
+
-export_type([engine_ref/0,
key_id/0,
password/0
]).
-
+%%% Opaque types must be exported :(
+-export_type([
+ stream_state/0,
+ hmac_state/0,
+ hash_state/0
+ ]).
+
%% Private. For tests.
--export([packed_openssl_version/4, engine_methods_convert_to_bitmask/2, get_test_engine/0]).
+-export([packed_openssl_version/4, engine_methods_convert_to_bitmask/2,
+ get_test_engine/0]).
+-export([rand_plugin_aes_jump_2pow20/1]).
-deprecated({rand_uniform, 2, next_major_release}).
@@ -73,16 +105,187 @@
%% Used by strong_rand_float/0
-define(HALF_DBL_EPSILON, 1.1102230246251565e-16). % math:pow(2, -53)
-%%-type ecdsa_digest_type() :: 'md5' | 'sha' | 'sha256' | 'sha384' | 'sha512'.
+
+%%% ===== BEGIN NEW TYPING ====
+
+%%% Basic
+-type key_integer() :: integer() | binary(). % Always binary() when used as return value
+
+%%% Keys
+-type rsa_public() :: [key_integer()] . % [E, N]
+-type rsa_private() :: [key_integer()] . % [E, N, D] | [E, N, D, P1, P2, E1, E2, C]
+-type rsa_params() :: {ModulusSizeInBits::integer(), PublicExponent::key_integer()} .
+
+-type dss_public() :: [key_integer()] . % [P, Q, G, Y]
+-type dss_private() :: [key_integer()] . % [P, Q, G, X]
+
+-type ecdsa_public() :: key_integer() .
+-type ecdsa_private() :: key_integer() .
+-type ecdsa_params() :: ec_named_curve() | edwards_curve() | ec_explicit_curve() .
+
+-type srp_public() :: key_integer() .
+-type srp_private() :: key_integer() .
+-type srp_gen_params() :: {user,srp_user_gen_params()} | {host,srp_host_gen_params()}.
+-type srp_comp_params() :: {user,srp_user_comp_params()} | {host,srp_host_comp_params()}.
+-type srp_user_gen_params() :: list(binary() | atom() | list()) .
+-type srp_host_gen_params() :: list(binary() | atom() | list()) .
+-type srp_user_comp_params() :: list(binary() | atom()) .
+-type srp_host_comp_params() :: list(binary() | atom()) .
+
+-type dh_public() :: key_integer() .
+-type dh_private() :: key_integer() .
+-type dh_params() :: [key_integer()] . % [P, G] | [P, G, PrivateKeyBitLength]
+
+-type ecdh_public() :: key_integer() .
+-type ecdh_private() :: key_integer() .
+-type ecdh_params() :: ec_named_curve() | edwards_curve() | ec_explicit_curve() .
+
+
+%%% Curves
+
+-type ec_explicit_curve() :: {Field :: ec_field(),
+ Curve :: ec_curve(),
+ BasePoint :: binary(),
+ Order :: binary(),
+ CoFactor :: none | % FIXME: Really?
+ binary()
+ } .
+
+-type ec_curve() :: {A :: binary(),
+ B :: binary(),
+ Seed :: none | binary()
+ } .
+
+-type ec_field() :: ec_prime_field() | ec_characteristic_two_field() .
+
+-type ec_prime_field() :: {prime_field, Prime :: integer()} .
+-type ec_characteristic_two_field() :: {characteristic_two_field, M :: integer(), Basis :: ec_basis()} .
+
+-type ec_basis() :: {tpbasis, K :: non_neg_integer()}
+ | {ppbasis, K1 :: non_neg_integer(), K2 :: non_neg_integer(), K3 :: non_neg_integer()}
+ | onbasis .
+
+-type ec_named_curve() :: brainpoolP160r1
+ | brainpoolP160t1
+ | brainpoolP192r1
+ | brainpoolP192t1
+ | brainpoolP224r1
+ | brainpoolP224t1
+ | brainpoolP256r1
+ | brainpoolP256t1
+ | brainpoolP320r1
+ | brainpoolP320t1
+ | brainpoolP384r1
+ | brainpoolP384t1
+ | brainpoolP512r1
+ | brainpoolP512t1
+ | c2pnb163v1
+ | c2pnb163v2
+ | c2pnb163v3
+ | c2pnb176v1
+ | c2pnb208w1
+ | c2pnb272w1
+ | c2pnb304w1
+ | c2pnb368w1
+ | c2tnb191v1
+ | c2tnb191v2
+ | c2tnb191v3
+ | c2tnb239v1
+ | c2tnb239v2
+ | c2tnb239v3
+ | c2tnb359v1
+ | c2tnb431r1
+ | ipsec3
+ | ipsec4
+ | prime192v1
+ | prime192v2
+ | prime192v3
+ | prime239v1
+ | prime239v2
+ | prime239v3
+ | prime256v1
+ | secp112r1
+ | secp112r2
+ | secp128r1
+ | secp128r2
+ | secp160k1
+ | secp160r1
+ | secp160r2
+ | secp192k1
+ | secp192r1
+ | secp224k1
+ | secp224r1
+ | secp256k1
+ | secp256r1
+ | secp384r1
+ | secp521r1
+ | sect113r1
+ | sect113r2
+ | sect131r1
+ | sect131r2
+ | sect163k1
+ | sect163r1
+ | sect163r2
+ | sect193r1
+ | sect193r2
+ | sect233k1
+ | sect233r1
+ | sect239k1
+ | sect283k1
+ | sect283r1
+ | sect409k1
+ | sect409r1
+ | sect571k1
+ | sect571r1
+ | wtls1
+ | wtls10
+ | wtls11
+ | wtls12
+ | wtls3
+ | wtls4
+ | wtls5
+ | wtls6
+ | wtls7
+ | wtls8
+ | wtls9
+ .
+
+-type edwards_curve() :: x25519
+ | x448 .
+
+%%%
+-type block_cipher_with_iv() :: cbc_cipher()
+ | cfb_cipher()
+ | aes_cbc128
+ | aes_cbc256
+ | aes_ige256
+ | blowfish_ofb64
+ | des3_cbf % cfb misspelled
+ | des_ede3
+ | rc2_cbc .
+
+-type cbc_cipher() :: des_cbc | des3_cbc | aes_cbc | blowfish_cbc .
+-type aead_cipher() :: aes_gcm | aes_ccm | chacha20_poly1305 .
+-type cfb_cipher() :: aes_cfb128 | aes_cfb8 | blowfish_cfb64 | des3_cfb | des_cfb .
+
+-type block_cipher_without_iv() :: ecb_cipher() .
+-type ecb_cipher() :: des_ecb | blowfish_ecb | aes_ecb .
+
+-type key() :: iodata().
+-type des3_key() :: [key()].
+
+%%%
+-type rsa_digest_type() :: sha1() | sha2() | md5 | ripemd160 .
+-type dss_digest_type() :: sha1() | sha2() .
+-type ecdsa_digest_type() :: sha1() | sha2() .
+
+-type sha1() :: sha .
+-type sha2() :: sha224 | sha256 | sha384 | sha512 .
+-type sha3() :: sha3_224 | sha3_256 | sha3_384 | sha3_512 .
+
+-type compatibility_only_hash() :: md5 | md4 .
+
-type crypto_integer() :: binary() | integer().
-%%-type ec_named_curve() :: atom().
-%%-type ec_point() :: crypto_integer().
-%%-type ec_basis() :: {tpbasis, K :: non_neg_integer()} | {ppbasis, K1 :: non_neg_integer(), K2 :: non_neg_integer(), K3 :: non_neg_integer()} | onbasis.
-%%-type ec_field() :: {prime_field, Prime :: integer()} | {characteristic_two_field, M :: integer(), Basis :: ec_basis()}.
-%%-type ec_prime() :: {A :: crypto_integer(), B :: crypto_integer(), Seed :: binary() | none}.
-%%-type ec_curve_spec() :: {Field :: ec_field(), Prime :: ec_prime(), Point :: crypto_integer(), Order :: integer(), CoFactor :: none | integer()}.
-%%-type ec_curve() :: ec_named_curve() | ec_curve_spec().
-%%-type ec_key() :: {Curve :: ec_curve(), PrivKey :: binary() | undefined, PubKey :: ec_point() | undefined}.
-compile(no_native).
-on_load(on_load/0).
@@ -98,144 +301,240 @@ nif_stub_error(Line) ->
%% Crypto app version history:
%% (no version): Driver implementation
%% 2.0 : NIF implementation, requires OTP R14
+
+%% When generating documentation from crypto.erl, the macro ?CRYPTO_VSN is not defined.
+%% That causes the doc generation to stop...
+-ifndef(CRYPTO_VSN).
+-define(CRYPTO_VSN, "??").
+-endif.
version() -> ?CRYPTO_VSN.
+-spec start() -> ok | {error, Reason::term()}.
start() ->
application:start(crypto).
+-spec stop() -> ok | {error, Reason::term()}.
stop() ->
application:stop(crypto).
+-spec supports() -> [Support]
+ when Support :: {hashs, Hashs}
+ | {ciphers, Ciphers}
+ | {public_keys, PKs}
+ | {macs, Macs}
+ | {curves, Curves}
+ | {rsa_opts, RSAopts},
+ Hashs :: [sha1() | sha2() | sha3() | ripemd160 | compatibility_only_hash()],
+ Ciphers :: [stream_cipher()
+ | block_cipher_with_iv() | block_cipher_without_iv()
+ | aead_cipher()
+ ],
+ PKs :: [rsa | dss | ecdsa | dh | ecdh | ec_gf2m],
+ Macs :: [hmac | cmac | poly1305],
+ Curves :: [ec_named_curve() | edwards_curve()],
+ RSAopts :: [rsa_sign_verify_opt() | rsa_opt()] .
supports()->
- {Hashs, PubKeys, Ciphers, Macs, Curves} = algorithms(),
+ {Hashs, PubKeys, Ciphers, Macs, Curves, RsaOpts} = algorithms(),
[{hashs, Hashs},
{ciphers, Ciphers},
{public_keys, PubKeys},
{macs, Macs},
- {curves, Curves}
+ {curves, Curves},
+ {rsa_opts, RsaOpts}
].
+-spec info_lib() -> [{Name,VerNum,VerStr}] when Name :: binary(),
+ VerNum :: integer(),
+ VerStr :: binary() .
info_lib() -> ?nif_stub.
-spec info_fips() -> not_supported | not_enabled | enabled.
info_fips() -> ?nif_stub.
--spec enable_fips_mode(boolean()) -> boolean().
-
+-spec enable_fips_mode(Enable) -> Result when Enable :: boolean(),
+ Result :: boolean().
enable_fips_mode(_) -> ?nif_stub.
--spec hash(_, iodata()) -> binary().
+%%%================================================================
+%%%
+%%% Hashing
+%%%
+%%%================================================================
-hash(Hash, Data0) ->
- Data = iolist_to_binary(Data0),
- MaxBytes = max_bytes(),
- hash(Hash, Data, erlang:byte_size(Data), MaxBytes).
+-define(HASH_HASH_ALGORITHM, sha1() | sha2() | sha3() | ripemd160 | compatibility_only_hash() ).
--spec hash_init('md5'|'md4'|'ripemd160'|
- 'sha'|'sha224'|'sha256'|'sha384'|'sha512') -> any().
+-spec hash(Type, Data) -> Digest when Type :: ?HASH_HASH_ALGORITHM,
+ Data :: iodata(),
+ Digest :: binary().
+hash(Type, Data) ->
+ Data1 = iolist_to_binary(Data),
+ MaxBytes = max_bytes(),
+ hash(Type, Data1, erlang:byte_size(Data1), MaxBytes).
-hash_init(Hash) ->
- notsup_to_error(hash_init_nif(Hash)).
+-opaque hash_state() :: reference().
--spec hash_update(_, iodata()) -> any().
+-spec hash_init(Type) -> State when Type :: ?HASH_HASH_ALGORITHM,
+ State :: hash_state().
+hash_init(Type) ->
+ notsup_to_error(hash_init_nif(Type)).
-hash_update(State, Data0) ->
- Data = iolist_to_binary(Data0),
+-spec hash_update(State, Data) -> NewState when State :: hash_state(),
+ NewState :: hash_state(),
+ Data :: iodata() .
+hash_update(Context, Data) ->
+ Data1 = iolist_to_binary(Data),
MaxBytes = max_bytes(),
- hash_update(State, Data, erlang:byte_size(Data), MaxBytes).
+ hash_update(Context, Data1, erlang:byte_size(Data1), MaxBytes).
--spec hash_final(_) -> binary().
+-spec hash_final(State) -> Digest when State :: hash_state(),
+ Digest :: binary().
+hash_final(Context) ->
+ notsup_to_error(hash_final_nif(Context)).
-hash_final(State) ->
- notsup_to_error(hash_final_nif(State)).
+%%%================================================================
+%%%
+%%% MACs (Message Authentication Codes)
+%%%
+%%%================================================================
+%%%---- HMAC
--spec hmac(_, iodata(), iodata()) -> binary().
--spec hmac(_, iodata(), iodata(), integer()) -> binary().
--spec hmac_init(atom(), iodata()) -> binary().
--spec hmac_update(binary(), iodata()) -> binary().
--spec hmac_final(binary()) -> binary().
--spec hmac_final_n(binary(), integer()) -> binary().
+-define(HMAC_HASH_ALGORITHM, sha1() | sha2() | sha3() | compatibility_only_hash()).
-hmac(Type, Key, Data0) ->
- Data = iolist_to_binary(Data0),
- hmac(Type, Key, Data, undefined, erlang:byte_size(Data), max_bytes()).
-hmac(Type, Key, Data0, MacSize) ->
- Data = iolist_to_binary(Data0),
- hmac(Type, Key, Data, MacSize, erlang:byte_size(Data), max_bytes()).
+%%%---- hmac/3,4
+
+-spec hmac(Type, Key, Data) ->
+ Mac when Type :: ?HMAC_HASH_ALGORITHM,
+ Key :: iodata(),
+ Data :: iodata(),
+ Mac :: binary() .
+hmac(Type, Key, Data) ->
+ Data1 = iolist_to_binary(Data),
+ hmac(Type, Key, Data1, undefined, erlang:byte_size(Data1), max_bytes()).
+
+-spec hmac(Type, Key, Data, MacLength) ->
+ Mac when Type :: ?HMAC_HASH_ALGORITHM,
+ Key :: iodata(),
+ Data :: iodata(),
+ MacLength :: integer(),
+ Mac :: binary() .
+hmac(Type, Key, Data, MacLength) ->
+ Data1 = iolist_to_binary(Data),
+ hmac(Type, Key, Data1, MacLength, erlang:byte_size(Data1), max_bytes()).
+
+%%%---- hmac_init, hamc_update, hmac_final
+
+-opaque hmac_state() :: binary().
+
+-spec hmac_init(Type, Key) ->
+ State when Type :: ?HMAC_HASH_ALGORITHM,
+ Key :: iodata(),
+ State :: hmac_state() .
hmac_init(Type, Key) ->
notsup_to_error(hmac_init_nif(Type, Key)).
+%%%---- hmac_update
+
+-spec hmac_update(State, Data) -> NewState when Data :: iodata(),
+ State :: hmac_state(),
+ NewState :: hmac_state().
hmac_update(State, Data0) ->
Data = iolist_to_binary(Data0),
hmac_update(State, Data, erlang:byte_size(Data), max_bytes()).
+%%%---- hmac_final
+
+-spec hmac_final(State) -> Mac when State :: hmac_state(),
+ Mac :: binary().
hmac_final(Context) ->
notsup_to_error(hmac_final_nif(Context)).
+
+-spec hmac_final_n(State, HashLen) -> Mac when State :: hmac_state(),
+ HashLen :: integer(),
+ Mac :: binary().
hmac_final_n(Context, HashLen) ->
notsup_to_error(hmac_final_nif(Context, HashLen)).
--spec cmac(_, iodata(), iodata()) -> binary().
--spec cmac(_, iodata(), iodata(), integer()) -> binary().
+%%%---- CMAC
+
+-define(CMAC_CIPHER_ALGORITHM, cbc_cipher() | cfb_cipher() | blowfish_cbc | des_ede3 | rc2_cbc ).
+-spec cmac(Type, Key, Data) ->
+ Mac when Type :: ?CMAC_CIPHER_ALGORITHM,
+ Key :: iodata(),
+ Data :: iodata(),
+ Mac :: binary().
cmac(Type, Key, Data) ->
notsup_to_error(cmac_nif(Type, Key, Data)).
-cmac(Type, Key, Data, MacSize) ->
- erlang:binary_part(cmac(Type, Key, Data), 0, MacSize).
-
-%% Ecrypt/decrypt %%%
-
--spec block_encrypt(des_cbc | des_cfb |
- des3_cbc | des3_cbf | des3_cfb | des_ede3 |
- blowfish_cbc | blowfish_cfb64 | blowfish_ofb64 |
- aes_cbc128 | aes_cfb8 | aes_cfb128 | aes_cbc256 | aes_ige256 |
- aes_cbc |
- rc2_cbc,
- Key::iodata(), Ivec::binary(), Data::iodata()) -> binary();
- (aes_gcm | chacha20_poly1305, Key::iodata(), Ivec::binary(), {AAD::binary(), Data::iodata()}) -> {binary(), binary()};
- (aes_gcm, Key::iodata(), Ivec::binary(), {AAD::binary(), Data::iodata(), TagLength::1..16}) -> {binary(), binary()}.
-
-block_encrypt(Type, Key, Ivec, Data) when Type =:= des_cbc;
- Type =:= des_cfb;
- Type =:= blowfish_cbc;
- Type =:= blowfish_cfb64;
- Type =:= blowfish_ofb64;
- Type =:= aes_cbc128;
- Type =:= aes_cfb8;
- Type =:= aes_cfb128;
- Type =:= aes_cbc256;
- Type =:= aes_cbc;
- Type =:= rc2_cbc ->
- block_crypt_nif(Type, Key, Ivec, Data, true);
-block_encrypt(Type, Key0, Ivec, Data) when Type =:= des3_cbc;
- Type =:= des_ede3 ->
+
+-spec cmac(Type, Key, Data, MacLength) ->
+ Mac when Type :: ?CMAC_CIPHER_ALGORITHM,
+ Key :: iodata(),
+ Data :: iodata(),
+ MacLength :: integer(),
+ Mac :: binary().
+cmac(Type, Key, Data, MacLength) ->
+ erlang:binary_part(cmac(Type, Key, Data), 0, MacLength).
+
+%%%---- POLY1305
+
+-spec poly1305(iodata(), iodata()) -> Mac when Mac :: binary().
+
+poly1305(Key, Data) ->
+ poly1305_nif(Key, Data).
+
+%%%================================================================
+%%%
+%%% Encrypt/decrypt
+%%%
+%%%================================================================
+
+%%%---- Block ciphers
+
+-spec block_encrypt(Type::block_cipher_with_iv(), Key::key()|des3_key(), Ivec::binary(), PlainText::iodata()) -> binary();
+ (Type::aead_cipher(), Key::iodata(), Ivec::binary(), {AAD::binary(), PlainText::iodata()}) ->
+ {binary(), binary()};
+ (aes_gcm | aes_ccm, Key::iodata(), Ivec::binary(), {AAD::binary(), PlainText::iodata(), TagLength::1..16}) ->
+ {binary(), binary()}.
+
+block_encrypt(Type, Key, Ivec, PlainText) when Type =:= des_cbc;
+ Type =:= des_cfb;
+ Type =:= blowfish_cbc;
+ Type =:= blowfish_cfb64;
+ Type =:= blowfish_ofb64;
+ Type =:= aes_cbc128;
+ Type =:= aes_cfb8;
+ Type =:= aes_cfb128;
+ Type =:= aes_cbc256;
+ Type =:= aes_cbc;
+ Type =:= rc2_cbc ->
+ block_crypt_nif(Type, Key, Ivec, PlainText, true);
+block_encrypt(Type, Key0, Ivec, PlainText) when Type =:= des3_cbc;
+ Type =:= des_ede3 ->
Key = check_des3_key(Key0),
- block_crypt_nif(des_ede3_cbc, Key, Ivec, Data, true);
-block_encrypt(des3_cbf, Key0, Ivec, Data) ->
+ block_crypt_nif(des_ede3_cbc, Key, Ivec, PlainText, true);
+block_encrypt(des3_cbf, Key0, Ivec, PlainText) -> % cfb misspelled
Key = check_des3_key(Key0),
- block_crypt_nif(des_ede3_cbf, Key, Ivec, Data, true);
-block_encrypt(des3_cfb, Key0, Ivec, Data) ->
+ block_crypt_nif(des_ede3_cbf, Key, Ivec, PlainText, true);
+block_encrypt(des3_cfb, Key0, Ivec, PlainText) ->
Key = check_des3_key(Key0),
- block_crypt_nif(des_ede3_cfb, Key, Ivec, Data, true);
-block_encrypt(aes_ige256, Key, Ivec, Data) ->
- notsup_to_error(aes_ige_crypt_nif(Key, Ivec, Data, true));
-block_encrypt(aes_gcm, Key, Ivec, {AAD, Data}) ->
- aes_gcm_encrypt(Key, Ivec, AAD, Data);
-block_encrypt(aes_gcm, Key, Ivec, {AAD, Data, TagLength}) ->
- aes_gcm_encrypt(Key, Ivec, AAD, Data, TagLength);
-block_encrypt(chacha20_poly1305, Key, Ivec, {AAD, Data}) ->
- chacha20_poly1305_encrypt(Key, Ivec, AAD, Data).
-
--spec block_decrypt(des_cbc | des_cfb |
- des3_cbc | des3_cbf | des3_cfb | des_ede3 |
- blowfish_cbc | blowfish_cfb64 | blowfish_ofb64 |
- aes_cbc128 | aes_cfb8 | aes_cfb128 | aes_cbc256 | aes_ige256 |
- aes_cbc |
- rc2_cbc,
- Key::iodata(), Ivec::binary(), Data::iodata()) -> binary();
- (aes_gcm | chacha20_poly1305, Key::iodata(), Ivec::binary(),
+ block_crypt_nif(des_ede3_cfb, Key, Ivec, PlainText, true);
+block_encrypt(aes_ige256, Key, Ivec, PlainText) ->
+ notsup_to_error(aes_ige_crypt_nif(Key, Ivec, PlainText, true));
+block_encrypt(Type, Key, Ivec, {AAD, PlainText}) when Type =:= aes_gcm;
+ Type =:= aes_ccm ->
+ aead_encrypt(Type, Key, Ivec, AAD, PlainText);
+block_encrypt(Type, Key, Ivec, {AAD, PlainText, TagLength}) when Type =:= aes_gcm;
+ Type =:= aes_ccm ->
+ aead_encrypt(Type, Key, Ivec, AAD, PlainText, TagLength);
+block_encrypt(chacha20_poly1305=Type, Key, Ivec, {AAD, PlainText}) ->
+ aead_encrypt(Type, Key, Ivec, AAD, PlainText, 16).
+
+
+-spec block_decrypt(Type::block_cipher_with_iv(), Key::key()|des3_key(), Ivec::binary(), Data::iodata()) -> binary();
+ (Type::aead_cipher(), Key::iodata(), Ivec::binary(),
{AAD::binary(), Data::iodata(), Tag::binary()}) -> binary() | error.
block_decrypt(Type, Key, Ivec, Data) when Type =:= des_cbc;
Type =:= des_cfb;
@@ -253,7 +552,7 @@ block_decrypt(Type, Key0, Ivec, Data) when Type =:= des3_cbc;
Type =:= des_ede3 ->
Key = check_des3_key(Key0),
block_crypt_nif(des_ede3_cbc, Key, Ivec, Data, false);
-block_decrypt(des3_cbf, Key0, Ivec, Data) ->
+block_decrypt(des3_cbf, Key0, Ivec, Data) -> % cfb misspelled
Key = check_des3_key(Key0),
block_crypt_nif(des_ede3_cbf, Key, Ivec, Data, false);
block_decrypt(des3_cfb, Key0, Ivec, Data) ->
@@ -261,23 +560,27 @@ block_decrypt(des3_cfb, Key0, Ivec, Data) ->
block_crypt_nif(des_ede3_cfb, Key, Ivec, Data, false);
block_decrypt(aes_ige256, Key, Ivec, Data) ->
notsup_to_error(aes_ige_crypt_nif(Key, Ivec, Data, false));
-block_decrypt(aes_gcm, Key, Ivec, {AAD, Data, Tag}) ->
- aes_gcm_decrypt(Key, Ivec, AAD, Data, Tag);
-block_decrypt(chacha20_poly1305, Key, Ivec, {AAD, Data, Tag}) ->
- chacha20_poly1305_decrypt(Key, Ivec, AAD, Data, Tag).
+block_decrypt(Type, Key, Ivec, {AAD, Data, Tag}) when Type =:= aes_gcm;
+ Type =:= aes_ccm;
+ Type =:= chacha20_poly1305 ->
+ aead_decrypt(Type, Key, Ivec, AAD, Data, Tag).
+
+
+-spec block_encrypt(Type::block_cipher_without_iv(), Key::key(), PlainText::iodata()) -> binary().
--spec block_encrypt(des_ecb | blowfish_ecb | aes_ecb, Key::iodata(), Data::iodata()) -> binary().
+block_encrypt(Type, Key, PlainText) ->
+ block_crypt_nif(Type, Key, PlainText, true).
-block_encrypt(Type, Key, Data) ->
- block_crypt_nif(Type, Key, Data, true).
--spec block_decrypt(des_ecb | blowfish_ecb | aes_ecb, Key::iodata(), Data::iodata()) -> binary().
+-spec block_decrypt(Type::block_cipher_without_iv(), Key::key(), Data::iodata()) -> binary().
block_decrypt(Type, Key, Data) ->
block_crypt_nif(Type, Key, Data, false).
--spec next_iv(des_cbc | des3_cbc | aes_cbc | aes_ige, Data::iodata()) -> binary().
+-spec next_iv(Type:: cbc_cipher(), Data) -> NextIVec when % Type :: cbc_cipher(), %des_cbc | des3_cbc | aes_cbc | aes_ige,
+ Data :: iodata(),
+ NextIVec :: binary().
next_iv(Type, Data) when is_binary(Data) ->
IVecSize = case Type of
des_cbc -> 8;
@@ -290,7 +593,9 @@ next_iv(Type, Data) when is_binary(Data) ->
next_iv(Type, Data) when is_list(Data) ->
next_iv(Type, list_to_binary(Data)).
--spec next_iv(des_cfb, Data::iodata(), Ivec::binary()) -> binary().
+-spec next_iv(des_cfb, Data, IVec) -> NextIVec when Data :: iodata(),
+ IVec :: binary(),
+ NextIVec :: binary().
next_iv(des_cfb, Data, IVec) ->
IVecAndData = list_to_binary([IVec, Data]),
@@ -299,38 +604,57 @@ next_iv(des_cfb, Data, IVec) ->
next_iv(Type, Data, _Ivec) ->
next_iv(Type, Data).
+%%%---- Stream ciphers
+
+-opaque stream_state() :: {stream_cipher(), reference()}.
+
+-type stream_cipher() :: rc4 | aes_ctr | chacha20 .
+
+-spec stream_init(Type, Key, IVec) -> State when Type :: aes_ctr | chacha20,
+ Key :: iodata(),
+ IVec :: binary(),
+ State :: stream_state() .
stream_init(aes_ctr, Key, Ivec) ->
- {aes_ctr, aes_ctr_stream_init(Key, Ivec)}.
+ {aes_ctr, aes_ctr_stream_init(Key, Ivec)};
+stream_init(chacha20, Key, Ivec) ->
+ {chacha20, chacha20_stream_init(Key,Ivec)}.
+
+-spec stream_init(Type, Key) -> State when Type :: rc4,
+ Key :: iodata(),
+ State :: stream_state() .
stream_init(rc4, Key) ->
{rc4, notsup_to_error(rc4_set_key(Key))}.
+-spec stream_encrypt(State, PlainText) -> {NewState, CipherText}
+ when State :: stream_state(),
+ PlainText :: iodata(),
+ NewState :: stream_state(),
+ CipherText :: iodata() .
stream_encrypt(State, Data0) ->
Data = iolist_to_binary(Data0),
MaxByts = max_bytes(),
stream_crypt(fun do_stream_encrypt/2, State, Data, erlang:byte_size(Data), MaxByts, []).
+-spec stream_decrypt(State, CipherText) -> {NewState, PlainText}
+ when State :: stream_state(),
+ CipherText :: iodata(),
+ NewState :: stream_state(),
+ PlainText :: iodata() .
stream_decrypt(State, Data0) ->
Data = iolist_to_binary(Data0),
MaxByts = max_bytes(),
stream_crypt(fun do_stream_decrypt/2, State, Data, erlang:byte_size(Data), MaxByts, []).
-%%
-%% RAND - pseudo random numbers using RN_ and BN_ functions in crypto lib
-%%
+
+%%%================================================================
+%%%
+%%% RAND - pseudo random numbers using RN_ and BN_ functions in crypto lib
+%%%
+%%%================================================================
-type rand_cache_seed() ::
nonempty_improper_list(non_neg_integer(), binary()).
--spec strong_rand_bytes(non_neg_integer()) -> binary().
--spec rand_seed() -> rand:state().
--spec rand_seed_s() -> rand:state().
--spec rand_seed_alg(Alg :: atom()) ->
- {rand:alg_handler(),
- atom() | rand_cache_seed()}.
--spec rand_seed_alg_s(Alg :: atom()) ->
- {rand:alg_handler(),
- atom() | rand_cache_seed()}.
--spec rand_uniform(crypto_integer(), crypto_integer()) ->
- crypto_integer().
+-spec strong_rand_bytes(N::non_neg_integer()) -> binary().
strong_rand_bytes(Bytes) ->
case strong_rand_bytes_nif(Bytes) of
false -> erlang:error(low_entropy);
@@ -339,40 +663,87 @@ strong_rand_bytes(Bytes) ->
strong_rand_bytes_nif(_Bytes) -> ?nif_stub.
+-spec rand_seed() -> rand:state().
rand_seed() ->
rand:seed(rand_seed_s()).
+-spec rand_seed_s() -> rand:state().
rand_seed_s() ->
rand_seed_alg_s(?MODULE).
+-spec rand_seed_alg(Alg :: atom()) ->
+ {rand:alg_handler(),
+ atom() | rand_cache_seed()}.
rand_seed_alg(Alg) ->
rand:seed(rand_seed_alg_s(Alg)).
+-spec rand_seed_alg(Alg :: atom(), Seed :: term()) ->
+ {rand:alg_handler(),
+ atom() | rand_cache_seed()}.
+rand_seed_alg(Alg, Seed) ->
+ rand:seed(rand_seed_alg_s(Alg, Seed)).
+
-define(CRYPTO_CACHE_BITS, 56).
-rand_seed_alg_s(?MODULE) ->
- {#{ type => ?MODULE,
- bits => 64,
- next => fun ?MODULE:rand_plugin_next/1,
- uniform => fun ?MODULE:rand_plugin_uniform/1,
- uniform_n => fun ?MODULE:rand_plugin_uniform/2},
- no_seed};
-rand_seed_alg_s(crypto_cache) ->
+-define(CRYPTO_AES_BITS, 58).
+
+-spec rand_seed_alg_s(Alg :: atom()) ->
+ {rand:alg_handler(),
+ atom() | rand_cache_seed()}.
+rand_seed_alg_s({AlgHandler, _AlgState} = State) when is_map(AlgHandler) ->
+ State;
+rand_seed_alg_s({Alg, AlgState}) when is_atom(Alg) ->
+ {mk_alg_handler(Alg),AlgState};
+ rand_seed_alg_s(Alg) when is_atom(Alg) ->
+ {mk_alg_handler(Alg),mk_alg_state(Alg)}.
+%%
+-spec rand_seed_alg_s(Alg :: atom(), Seed :: term()) ->
+ {rand:alg_handler(),
+ atom() | rand_cache_seed()}.
+rand_seed_alg_s(Alg, Seed) when is_atom(Alg) ->
+ {mk_alg_handler(Alg),mk_alg_state({Alg,Seed})}.
+
+mk_alg_handler(?MODULE = Alg) ->
+ #{ type => Alg,
+ bits => 64,
+ next => fun ?MODULE:rand_plugin_next/1,
+ uniform => fun ?MODULE:rand_plugin_uniform/1,
+ uniform_n => fun ?MODULE:rand_plugin_uniform/2};
+mk_alg_handler(crypto_cache = Alg) ->
+ #{ type => Alg,
+ bits => ?CRYPTO_CACHE_BITS,
+ next => fun ?MODULE:rand_cache_plugin_next/1};
+mk_alg_handler(crypto_aes = Alg) ->
+ #{ type => Alg,
+ bits => ?CRYPTO_AES_BITS,
+ next => fun ?MODULE:rand_plugin_aes_next/1,
+ jump => fun ?MODULE:rand_plugin_aes_jump/1}.
+
+mk_alg_state(?MODULE) ->
+ no_seed;
+mk_alg_state(crypto_cache) ->
CacheBits = ?CRYPTO_CACHE_BITS,
- EnvCacheSize =
- application:get_env(
- crypto, rand_cache_size, CacheBits * 16), % Cache 16 * 8 words
- Bytes = (CacheBits + 7) div 8,
+ BytesPerWord = (CacheBits + 7) div 8,
+ GenBytes =
+ ((rand_cache_size() + (2*BytesPerWord - 1)) div BytesPerWord)
+ * BytesPerWord,
+ {CacheBits, GenBytes, <<>>};
+mk_alg_state({crypto_aes,Seed}) ->
+ %% 16 byte words (128 bit crypto blocks)
+ GenWords = (rand_cache_size() + 31) div 16,
+ Key = crypto:hash(sha256, Seed),
+ {F,Count} = longcount_seed(Seed),
+ {Key,GenWords,F,Count}.
+
+rand_cache_size() ->
+ DefaultCacheSize = 1024,
CacheSize =
- case ((EnvCacheSize + (Bytes - 1)) div Bytes) * Bytes of
- Sz when is_integer(Sz), Bytes =< Sz ->
- Sz;
- _ ->
- Bytes
- end,
- {#{ type => crypto_cache,
- bits => CacheBits,
- next => fun ?MODULE:rand_cache_plugin_next/1},
- {CacheBits, CacheSize, <<>>}}.
+ application:get_env(crypto, rand_cache_size, DefaultCacheSize),
+ if
+ is_integer(CacheSize), 0 =< CacheSize ->
+ CacheSize;
+ true ->
+ DefaultCacheSize
+ end.
rand_plugin_next(Seed) ->
{bytes_to_integer(strong_rand_range(1 bsl 64)), Seed}.
@@ -383,12 +754,97 @@ rand_plugin_uniform(State) ->
rand_plugin_uniform(Max, State) ->
{bytes_to_integer(strong_rand_range(Max)) + 1, State}.
-rand_cache_plugin_next({CacheBits, CacheSize, <<>>}) ->
+
+rand_cache_plugin_next({CacheBits, GenBytes, <<>>}) ->
rand_cache_plugin_next(
- {CacheBits, CacheSize, strong_rand_bytes(CacheSize)});
-rand_cache_plugin_next({CacheBits, CacheSize, Cache}) ->
+ {CacheBits, GenBytes, strong_rand_bytes(GenBytes)});
+rand_cache_plugin_next({CacheBits, GenBytes, Cache}) ->
<<I:CacheBits, NewCache/binary>> = Cache,
- {I, {CacheBits, CacheSize, NewCache}}.
+ {I, {CacheBits, GenBytes, NewCache}}.
+
+
+%% Encrypt 128 bit counter values and use the 58 lowest
+%% encrypted bits as random numbers.
+%%
+%% The 128 bit counter is handled as 4 32 bit words
+%% to avoid bignums. Generate a bunch of numbers
+%% at the time and cache them.
+%%
+-dialyzer({no_improper_lists, rand_plugin_aes_next/1}).
+rand_plugin_aes_next([V|Cache]) ->
+ {V,Cache};
+rand_plugin_aes_next({Key,GenWords,F,Count}) ->
+ rand_plugin_aes_next(Key, GenWords, F, Count);
+rand_plugin_aes_next({Key,GenWords,F,_JumpBase,Count}) ->
+ rand_plugin_aes_next(Key, GenWords, F, Count).
+%%
+rand_plugin_aes_next(Key, GenWords, F, Count) ->
+ {Cleartext,NewCount} = aes_cleartext(<<>>, F, Count, GenWords),
+ Encrypted = crypto:block_encrypt(aes_ecb, Key, Cleartext),
+ [V|Cache] = aes_cache(Encrypted, {Key,GenWords,F,Count,NewCount}),
+ {V,Cache}.
+
+%% A jump advances the counter 2^512 steps; the jump function
+%% is applied to the jump base and then the number of used
+%% numbers from the cache has to be wasted for the jump to be correct
+%%
+rand_plugin_aes_jump({#{type := crypto_aes} = Alg, Cache}) ->
+ {Alg,rand_plugin_aes_jump(fun longcount_jump/1, 0, Cache)}.
+%% Count cached words and subtract their number from jump
+-dialyzer({no_improper_lists, rand_plugin_aes_jump/3}).
+rand_plugin_aes_jump(Jump, J, [_|Cache]) ->
+ rand_plugin_aes_jump(Jump, J + 1, Cache);
+rand_plugin_aes_jump(Jump, J, {Key,GenWords,F,JumpBase, _Count}) ->
+ rand_plugin_aes_jump(Jump, GenWords - J, Key, GenWords, F, JumpBase);
+rand_plugin_aes_jump(Jump, 0, {Key,GenWords,F,JumpBase}) ->
+ rand_plugin_aes_jump(Jump, 0, Key, GenWords, F, JumpBase).
+%%
+rand_plugin_aes_jump(Jump, Skip, Key, GenWords, F, JumpBase) ->
+ Count = longcount_next_count(Skip, Jump(JumpBase)),
+ {Key,GenWords,F,Count}.
+
+rand_plugin_aes_jump_2pow20(Cache) ->
+ rand_plugin_aes_jump(fun longcount_jump_2pow20/1, 0, Cache).
+
+
+longcount_seed(Seed) ->
+ <<X:64, _:6, F:12, S2:58, S1:58, S0:58>> =
+ crypto:hash(sha256, [Seed,<<"Xoroshiro928">>]),
+ {F,rand:exro928_seed([S0,S1,S2|rand:seed58(13, X)])}.
+
+longcount_next_count(0, Count) ->
+ Count;
+longcount_next_count(N, Count) ->
+ longcount_next_count(N - 1, rand:exro928_next_state(Count)).
+
+longcount_next(Count) ->
+ rand:exro928_next(Count).
+
+longcount_jump(Count) ->
+ rand:exro928_jump_2pow512(Count).
+
+longcount_jump_2pow20(Count) ->
+ rand:exro928_jump_2pow20(Count).
+
+
+%% Build binary with counter values to cache
+aes_cleartext(Cleartext, _F, Count, 0) ->
+ {Cleartext,Count};
+aes_cleartext(Cleartext, F, Count, GenWords) ->
+ {{S0,S1}, NewCount} = longcount_next(Count),
+ aes_cleartext(
+ <<Cleartext/binary, F:12, S1:58, S0:58>>,
+ F, NewCount, GenWords - 1).
+
+%% Parse and cache encrypted counter values aka random numbers
+-dialyzer({no_improper_lists, aes_cache/2}).
+aes_cache(<<>>, Cache) ->
+ Cache;
+aes_cache(
+ <<_:(128 - ?CRYPTO_AES_BITS), V:?CRYPTO_AES_BITS, Encrypted/binary>>,
+ Cache) ->
+ [V|aes_cache(Encrypted, Cache)].
+
strong_rand_range(Range) when is_integer(Range), Range > 0 ->
BinRange = int_to_bin(Range),
@@ -406,7 +862,9 @@ strong_rand_float() ->
WholeRange = strong_rand_range(1 bsl 53),
?HALF_DBL_EPSILON * bytes_to_integer(WholeRange).
-rand_uniform(From,To) when is_binary(From), is_binary(To) ->
+-spec rand_uniform(crypto_integer(), crypto_integer()) ->
+ crypto_integer().
+rand_uniform(From, To) when is_binary(From), is_binary(To) ->
case rand_uniform_nif(From,To) of
<<Len:32/integer, MSB, Rest/binary>> when MSB > 127 ->
<<(Len + 1):32/integer, 0, MSB, Rest/binary>>;
@@ -441,116 +899,228 @@ rand_seed(Seed) when is_binary(Seed) ->
rand_seed_nif(_Seed) -> ?nif_stub.
--spec mod_pow(binary()|integer(), binary()|integer(), binary()|integer()) -> binary() | error.
-mod_pow(Base, Exponent, Prime) ->
- case mod_exp_nif(ensure_int_as_bin(Base), ensure_int_as_bin(Exponent), ensure_int_as_bin(Prime), 0) of
- <<0>> -> error;
- R -> R
- end.
+%%%================================================================
+%%%
+%%% Sign/verify
+%%%
+%%%================================================================
+-type pk_sign_verify_algs() :: rsa | dss | ecdsa .
-verify(Algorithm, Type, Data, Signature, Key) ->
- verify(Algorithm, Type, Data, Signature, Key, []).
+-type pk_sign_verify_opts() :: [ rsa_sign_verify_opt() ] .
-%% Backwards compatible
-verify(Algorithm = dss, none, Digest, Signature, Key, Options) ->
- verify(Algorithm, sha, {digest, Digest}, Signature, Key, Options);
-verify(Algorithm, Type, Data, Signature, Key, Options) ->
- case pkey_verify_nif(Algorithm, Type, Data, Signature, format_pkey(Algorithm, Key), Options) of
- notsup -> erlang:error(notsup);
- Boolean -> Boolean
- end.
+-type rsa_sign_verify_opt() :: {rsa_padding, rsa_sign_verify_padding()}
+ | {rsa_pss_saltlen, integer()} .
+
+-type rsa_sign_verify_padding() :: rsa_pkcs1_padding | rsa_pkcs1_pss_padding
+ | rsa_x931_padding | rsa_no_padding
+ .
+%%%----------------------------------------------------------------
+%%% Sign
+
+-spec sign(Algorithm, DigestType, Msg, Key)
+ -> Signature
+ when Algorithm :: pk_sign_verify_algs(),
+ DigestType :: rsa_digest_type()
+ | dss_digest_type()
+ | ecdsa_digest_type(),
+ Msg :: binary() | {digest,binary()},
+ Key :: rsa_private()
+ | dss_private()
+ | [ecdsa_private()|ecdsa_params()]
+ | engine_key_ref(),
+ Signature :: binary() .
+
sign(Algorithm, Type, Data, Key) ->
sign(Algorithm, Type, Data, Key, []).
-%% Backwards compatible
-sign(Algorithm = dss, none, Digest, Key, Options) ->
- sign(Algorithm, sha, {digest, Digest}, Key, Options);
-sign(Algorithm, Type, Data, Key, Options) ->
+
+-spec sign(Algorithm, DigestType, Msg, Key, Options)
+ -> Signature
+ when Algorithm :: pk_sign_verify_algs(),
+ DigestType :: rsa_digest_type()
+ | dss_digest_type()
+ | ecdsa_digest_type()
+ | none,
+ Msg :: binary() | {digest,binary()},
+ Key :: rsa_private()
+ | dss_private()
+ | [ecdsa_private() | ecdsa_params()]
+ | engine_key_ref(),
+ Options :: pk_sign_verify_opts(),
+ Signature :: binary() .
+
+sign(Algorithm0, Type0, Data, Key, Options) ->
+ {Algorithm, Type} = sign_verify_compatibility(Algorithm0, Type0, Data),
case pkey_sign_nif(Algorithm, Type, Data, format_pkey(Algorithm, Key), Options) of
error -> erlang:error(badkey, [Algorithm, Type, Data, Key, Options]);
notsup -> erlang:error(notsup);
Signature -> Signature
end.
+pkey_sign_nif(_Algorithm, _Type, _Digest, _Key, _Options) -> ?nif_stub.
+%%%----------------------------------------------------------------
+%%% Verify
+
+-spec verify(Algorithm, DigestType, Msg, Signature, Key)
+ -> Result
+ when Algorithm :: pk_sign_verify_algs(),
+ DigestType :: rsa_digest_type()
+ | dss_digest_type()
+ | ecdsa_digest_type(),
+ Msg :: binary() | {digest,binary()},
+ Signature :: binary(),
+ Key :: rsa_private()
+ | dss_private()
+ | [ecdsa_private() | ecdsa_params()]
+ | engine_key_ref(),
+ Result :: boolean().
--type key_id() :: string() | binary() .
--type password() :: string() | binary() .
-
--type engine_key_ref() :: #{engine := engine_ref(),
- key_id := key_id(),
- password => password(),
- term() => term()
- }.
-
--type pk_algs() :: rsa | ecdsa | dss .
--type pk_key() :: engine_key_ref() | [integer() | binary()] .
--type pk_opt() :: list() | rsa_padding() .
-
--spec public_encrypt(pk_algs(), binary(), pk_key(), pk_opt()) -> binary().
--spec public_decrypt(pk_algs(), binary(), pk_key(), pk_opt()) -> binary().
--spec private_encrypt(pk_algs(), binary(), pk_key(), pk_opt()) -> binary().
--spec private_decrypt(pk_algs(), binary(), pk_key(), pk_opt()) -> binary().
+verify(Algorithm, Type, Data, Signature, Key) ->
+ verify(Algorithm, Type, Data, Signature, Key, []).
-public_encrypt(Algorithm, In, Key, Options) when is_list(Options) ->
- case pkey_crypt_nif(Algorithm, In, format_pkey(Algorithm, Key), Options, false, true) of
- error -> erlang:error(encrypt_failed, [Algorithm, In, Key, Options]);
+-spec verify(Algorithm, DigestType, Msg, Signature, Key, Options)
+ -> Result
+ when Algorithm :: pk_sign_verify_algs(),
+ DigestType :: rsa_digest_type()
+ | dss_digest_type()
+ | ecdsa_digest_type(),
+ Msg :: binary() | {digest,binary()},
+ Signature :: binary(),
+ Key :: rsa_public()
+ | dss_public()
+ | [ecdsa_public() | ecdsa_params()]
+ | engine_key_ref(),
+ Options :: pk_sign_verify_opts(),
+ Result :: boolean().
+
+verify(Algorithm0, Type0, Data, Signature, Key, Options) ->
+ {Algorithm, Type} = sign_verify_compatibility(Algorithm0, Type0, Data),
+ case pkey_verify_nif(Algorithm, Type, Data, Signature, format_pkey(Algorithm, Key), Options) of
notsup -> erlang:error(notsup);
- Out -> Out
- end;
-%% Backwards compatible
-public_encrypt(Algorithm = rsa, In, Key, Padding) when is_atom(Padding) ->
- public_encrypt(Algorithm, In, Key, [{rsa_padding, Padding}]).
+ Boolean -> Boolean
+ end.
-private_decrypt(Algorithm, In, Key, Options) when is_list(Options) ->
- case pkey_crypt_nif(Algorithm, In, format_pkey(Algorithm, Key), Options, true, false) of
- error -> erlang:error(decrypt_failed, [Algorithm, In, Key, Options]);
- notsup -> erlang:error(notsup);
- Out -> Out
- end;
-%% Backwards compatible
-private_decrypt(Algorithm = rsa, In, Key, Padding) when is_atom(Padding) ->
- private_decrypt(Algorithm, In, Key, [{rsa_padding, Padding}]).
+pkey_verify_nif(_Algorithm, _Type, _Data, _Signature, _Key, _Options) -> ?nif_stub.
-private_encrypt(Algorithm, In, Key, Options) when is_list(Options) ->
- case pkey_crypt_nif(Algorithm, In, format_pkey(Algorithm, Key), Options, true, true) of
- error -> erlang:error(encrypt_failed, [Algorithm, In, Key, Options]);
- notsup -> erlang:error(notsup);
- Out -> Out
- end;
-%% Backwards compatible
-private_encrypt(Algorithm = rsa, In, Key, Padding) when is_atom(Padding) ->
- private_encrypt(Algorithm, In, Key, [{rsa_padding, Padding}]).
+%% Backwards compatible:
+sign_verify_compatibility(dss, none, Digest) ->
+ {sha, {digest, Digest}};
+sign_verify_compatibility(Algorithm0, Type0, _Digest) ->
+ {Algorithm0, Type0}.
-public_decrypt(Algorithm, In, Key, Options) when is_list(Options) ->
- case pkey_crypt_nif(Algorithm, In, format_pkey(Algorithm, Key), Options, false, false) of
- error -> erlang:error(decrypt_failed, [Algorithm, In, Key, Options]);
+%%%================================================================
+%%%
+%%% Public/private encrypt/decrypt
+%%%
+%%% Only rsa works so far (although ecdsa | dss should do it)
+%%%================================================================
+-type pk_encrypt_decrypt_algs() :: rsa .
+
+-type pk_encrypt_decrypt_opts() :: [rsa_opt()] | rsa_compat_opts().
+
+-type rsa_compat_opts() :: [{rsa_pad, rsa_padding()}]
+ | rsa_padding() .
+
+-type rsa_padding() :: rsa_pkcs1_padding
+ | rsa_pkcs1_oaep_padding
+ | rsa_sslv23_padding
+ | rsa_x931_padding
+ | rsa_no_padding.
+
+-type rsa_opt() :: {rsa_padding, rsa_padding()}
+ | {signature_md, atom()}
+ | {rsa_mgf1_md, sha}
+ | {rsa_oaep_label, binary()}
+ | {rsa_oaep_md, sha} .
+
+%%%---- Encrypt with public key
+
+-spec public_encrypt(Algorithm, PlainText, PublicKey, Options) ->
+ CipherText when Algorithm :: pk_encrypt_decrypt_algs(),
+ PlainText :: binary(),
+ PublicKey :: rsa_public() | engine_key_ref(),
+ Options :: pk_encrypt_decrypt_opts(),
+ CipherText :: binary().
+public_encrypt(Algorithm, PlainText, PublicKey, Options) ->
+ pkey_crypt(Algorithm, PlainText, PublicKey, Options, false, true).
+
+%%%---- Decrypt with private key
+
+-spec private_decrypt(Algorithm, CipherText, PrivateKey, Options) ->
+ PlainText when Algorithm :: pk_encrypt_decrypt_algs(),
+ CipherText :: binary(),
+ PrivateKey :: rsa_private() | engine_key_ref(),
+ Options :: pk_encrypt_decrypt_opts(),
+ PlainText :: binary() .
+private_decrypt(Algorithm, CipherText, PrivateKey, Options) ->
+ pkey_crypt(Algorithm, CipherText, PrivateKey, Options, true, false).
+
+%%%---- Encrypt with private key
+
+-spec private_encrypt(Algorithm, PlainText, PrivateKey, Options) ->
+ CipherText when Algorithm :: pk_encrypt_decrypt_algs(),
+ PlainText :: binary(),
+ PrivateKey :: rsa_private() | engine_key_ref(),
+ Options :: pk_encrypt_decrypt_opts(),
+ CipherText :: binary().
+private_encrypt(Algorithm, PlainText, PrivateKey, Options) ->
+ pkey_crypt(Algorithm, PlainText, PrivateKey, Options, true, true).
+
+%%%---- Decrypt with public key
+
+-spec public_decrypt(Algorithm, CipherText, PublicKey, Options) ->
+ PlainText when Algorithm :: pk_encrypt_decrypt_algs(),
+ CipherText :: binary(),
+ PublicKey :: rsa_public() | engine_key_ref(),
+ Options :: pk_encrypt_decrypt_opts(),
+ PlainText :: binary() .
+public_decrypt(Algorithm, CipherText, PublicKey, Options) ->
+ pkey_crypt(Algorithm, CipherText, PublicKey, Options, false, false).
+
+%%%---- Call the nif, but fix a compatibility issue first
+
+%% Backwards compatible (rsa_pad -> rsa_padding is handled by the pkey_crypt_nif):
+pkey_crypt(rsa, Text, Key, Padding, PubPriv, EncDec) when is_atom(Padding) ->
+ pkey_crypt(rsa, Text, Key, [{rsa_padding, Padding}], PubPriv, EncDec);
+
+pkey_crypt(Alg, Text, Key, Options, PubPriv, EncDec) ->
+ case pkey_crypt_nif(Alg, Text, format_pkey(Alg,Key), Options, PubPriv, EncDec) of
+ error when EncDec==true -> erlang:error(encrypt_failed, [Alg, Text, Key, Options]);
+ error when EncDec==false -> erlang:error(decrypt_failed, [Alg, Text, Key, Options]);
notsup -> erlang:error(notsup);
Out -> Out
- end;
-%% Backwards compatible
-public_decrypt(Algorithm = rsa, In, Key, Padding) when is_atom(Padding) ->
- public_decrypt(Algorithm, In, Key, [{rsa_padding, Padding}]).
-
-
-%%
-%% XOR - xor to iolists and return a binary
-%% NB doesn't check that they are the same size, just concatenates
-%% them and sends them to the driver
-%%
--spec exor(iodata(), iodata()) -> binary().
+ end.
-exor(Bin1, Bin2) ->
- Data1 = iolist_to_binary(Bin1),
- Data2 = iolist_to_binary(Bin2),
- MaxBytes = max_bytes(),
- exor(Data1, Data2, erlang:byte_size(Data1), MaxBytes, []).
+pkey_crypt_nif(_Algorithm, _In, _Key, _Options, _IsPrivate, _IsEncrypt) -> ?nif_stub.
+%%%================================================================
+%%%
+%%%
+%%%
+%%%================================================================
+
+-spec generate_key(Type, Params)
+ -> {PublicKey, PrivKeyOut}
+ when Type :: dh | ecdh | rsa | srp,
+ PublicKey :: dh_public() | ecdh_public() | rsa_public() | srp_public(),
+ PrivKeyOut :: dh_private() | ecdh_private() | rsa_private() | {srp_public(),srp_private()},
+ Params :: dh_params() | ecdh_params() | rsa_params() | srp_gen_params()
+ .
generate_key(Type, Params) ->
generate_key(Type, Params, undefined).
+-spec generate_key(Type, Params, PrivKeyIn)
+ -> {PublicKey, PrivKeyOut}
+ when Type :: dh | ecdh | rsa | srp,
+ PublicKey :: dh_public() | ecdh_public() | rsa_public() | srp_public(),
+ PrivKeyIn :: undefined | dh_private() | ecdh_private() | rsa_private() | {srp_public(),srp_private()},
+ PrivKeyOut :: dh_private() | ecdh_private() | rsa_private() | {srp_public(),srp_private()},
+ Params :: dh_params() | ecdh_params() | rsa_params() | srp_comp_params()
+ .
+
generate_key(dh, DHParameters0, PrivateKey) ->
{DHParameters, Len} =
case DHParameters0 of
@@ -597,6 +1167,14 @@ generate_key(ecdh, Curve, PrivKey) ->
evp_generate_key_nif(_Curve) -> ?nif_stub.
+-spec compute_key(Type, OthersPublicKey, MyPrivateKey, Params)
+ -> SharedSecret
+ when Type :: dh | ecdh | srp,
+ SharedSecret :: binary(),
+ OthersPublicKey :: dh_public() | ecdh_public() | srp_public(),
+ MyPrivateKey :: dh_private() | ecdh_private() | {srp_public(),srp_private()},
+ Params :: dh_params() | ecdh_params() | srp_comp_params()
+ .
compute_key(dh, OthersPublicKey, MyPrivateKey, DHParameters) ->
case dh_compute_key_nif(ensure_int_as_bin(OthersPublicKey),
@@ -649,71 +1227,121 @@ compute_key(ecdh, Others, My, Curve) ->
evp_compute_key_nif(_Curve, _OthersBin, _MyBin) -> ?nif_stub.
-%%======================================================================
-%% Engine functions
-%%======================================================================
+
+%%%================================================================
+%%%
+%%% XOR - xor to iolists and return a binary
+%%% NB doesn't check that they are the same size, just concatenates
+%%% them and sends them to the driver
+%%%
+%%%================================================================
+
+-spec exor(iodata(), iodata()) -> binary().
+
+exor(Bin1, Bin2) ->
+ Data1 = iolist_to_binary(Bin1),
+ Data2 = iolist_to_binary(Bin2),
+ MaxBytes = max_bytes(),
+ exor(Data1, Data2, erlang:byte_size(Data1), MaxBytes, []).
+
+
+%%%================================================================
+%%%
+%%% Exponentiation modulo
+%%%
+%%%================================================================
+
+-spec mod_pow(N, P, M) -> Result when N :: binary() | integer(),
+ P :: binary() | integer(),
+ M :: binary() | integer(),
+ Result :: binary() | error .
+mod_pow(Base, Exponent, Prime) ->
+ case mod_exp_nif(ensure_int_as_bin(Base), ensure_int_as_bin(Exponent), ensure_int_as_bin(Prime), 0) of
+ <<0>> -> error;
+ R -> R
+ end.
+
+%%%======================================================================
+%%%
+%%% Engine functions
+%%%
+%%%======================================================================
+
+%%%---- Refering to keys stored in an engine:
+-type key_id() :: string() | binary() .
+-type password() :: string() | binary() .
+
+-type engine_key_ref() :: #{engine := engine_ref(),
+ key_id := key_id(),
+ password => password(),
+ term() => term()
+ }.
+
+%%%---- Commands:
+-type engine_cmnd() :: {unicode:chardata(), unicode:chardata()}.
+
%%----------------------------------------------------------------------
%% Function: engine_get_all_methods/0
%%----------------------------------------------------------------------
-type engine_method_type() :: engine_method_rsa | engine_method_dsa | engine_method_dh |
engine_method_rand | engine_method_ecdh | engine_method_ecdsa |
engine_method_ciphers | engine_method_digests | engine_method_store |
- engine_method_pkey_meths | engine_method_pkey_asn1_meths |
+ engine_method_pkey_meths | engine_method_pkey_asn1_meths |
engine_method_ec.
-type engine_ref() :: term().
--spec engine_get_all_methods() ->
- [engine_method_type()].
+-spec engine_get_all_methods() -> Result when Result :: [engine_method_type()].
engine_get_all_methods() ->
notsup_to_error(engine_get_all_methods_nif()).
%%----------------------------------------------------------------------
%% Function: engine_load/3
%%----------------------------------------------------------------------
--spec engine_load(EngineId::unicode:chardata(),
- PreCmds::[{unicode:chardata(), unicode:chardata()}],
- PostCmds::[{unicode:chardata(), unicode:chardata()}]) ->
- {ok, Engine::engine_ref()} | {error, Reason::term()}.
-engine_load(EngineId, PreCmds, PostCmds) when is_list(PreCmds), is_list(PostCmds) ->
+-spec engine_load(EngineId, PreCmds, PostCmds) ->
+ Result when EngineId::unicode:chardata(),
+ PreCmds::[engine_cmnd()],
+ PostCmds::[engine_cmnd()],
+ Result :: {ok, Engine::engine_ref()} | {error, Reason::term()}.
+engine_load(EngineId, PreCmds, PostCmds) when is_list(PreCmds),
+ is_list(PostCmds) ->
engine_load(EngineId, PreCmds, PostCmds, engine_get_all_methods()).
%%----------------------------------------------------------------------
%% Function: engine_load/4
%%----------------------------------------------------------------------
--spec engine_load(EngineId::unicode:chardata(),
- PreCmds::[{unicode:chardata(), unicode:chardata()}],
- PostCmds::[{unicode:chardata(), unicode:chardata()}],
- EngineMethods::[engine_method_type()]) ->
- {ok, Engine::term()} | {error, Reason::term()}.
+-spec engine_load(EngineId, PreCmds, PostCmds, EngineMethods) ->
+ Result when EngineId::unicode:chardata(),
+ PreCmds::[engine_cmnd()],
+ PostCmds::[engine_cmnd()],
+ EngineMethods::[engine_method_type()],
+ Result :: {ok, Engine::engine_ref()} | {error, Reason::term()}.
engine_load(EngineId, PreCmds, PostCmds, EngineMethods) when is_list(PreCmds),
is_list(PostCmds) ->
try
ok = notsup_to_error(engine_load_dynamic_nif()),
case notsup_to_error(engine_by_id_nif(ensure_bin_chardata(EngineId))) of
{ok, Engine} ->
- ok = engine_load_1(Engine, PreCmds, PostCmds, EngineMethods),
- {ok, Engine};
+ engine_load_1(Engine, PreCmds, PostCmds, EngineMethods);
{error, Error1} ->
{error, Error1}
end
catch
- throw:Error2 ->
- Error2
+ throw:Error2 ->
+ Error2
end.
engine_load_1(Engine, PreCmds, PostCmds, EngineMethods) ->
try
ok = engine_nif_wrapper(engine_ctrl_cmd_strings_nif(Engine, ensure_bin_cmds(PreCmds), 0)),
- ok = engine_nif_wrapper(engine_add_nif(Engine)),
ok = engine_nif_wrapper(engine_init_nif(Engine)),
engine_load_2(Engine, PostCmds, EngineMethods),
- ok
+ {ok, Engine}
catch
- throw:Error ->
- %% The engine couldn't initialise, release the structural reference
- ok = engine_free_nif(Engine),
- throw(Error)
+ throw:Error ->
+ %% The engine couldn't initialise, release the structural reference
+ ok = engine_free_nif(Engine),
+ throw(Error)
end.
engine_load_2(Engine, PostCmds, EngineMethods) ->
@@ -732,18 +1360,18 @@ engine_load_2(Engine, PostCmds, EngineMethods) ->
%%----------------------------------------------------------------------
%% Function: engine_unload/1
%%----------------------------------------------------------------------
--spec engine_unload(Engine::term()) ->
- ok | {error, Reason::term()}.
+-spec engine_unload(Engine) -> Result when Engine :: engine_ref(),
+ Result :: ok | {error, Reason::term()}.
engine_unload(Engine) ->
engine_unload(Engine, engine_get_all_methods()).
--spec engine_unload(Engine::term(), EngineMethods::[engine_method_type()]) ->
- ok | {error, Reason::term()}.
+-spec engine_unload(Engine, EngineMethods) -> Result when Engine :: engine_ref(),
+ EngineMethods :: [engine_method_type()],
+ Result :: ok | {error, Reason::term()}.
engine_unload(Engine, EngineMethods) ->
try
[ok = engine_nif_wrapper(engine_unregister_nif(Engine, engine_method_atom_to_int(Method))) ||
Method <- EngineMethods],
- ok = engine_nif_wrapper(engine_remove_nif(Engine)),
%% Release the functional reference from engine_init_nif
ok = engine_nif_wrapper(engine_finish_nif(Engine)),
%% Release the structural reference from engine_by_id_nif
@@ -754,19 +1382,63 @@ engine_unload(Engine, EngineMethods) ->
end.
%%----------------------------------------------------------------------
+%% Function: engine_by_id/1
+%%----------------------------------------------------------------------
+-spec engine_by_id(EngineId) -> Result when EngineId :: unicode:chardata(),
+ Result :: {ok, Engine::engine_ref()} | {error, Reason::term()} .
+engine_by_id(EngineId) ->
+ try
+ notsup_to_error(engine_by_id_nif(ensure_bin_chardata(EngineId)))
+ catch
+ throw:Error ->
+ Error
+ end.
+
+%%----------------------------------------------------------------------
+%% Function: engine_add/1
+%%----------------------------------------------------------------------
+-spec engine_add(Engine) -> Result when Engine :: engine_ref(),
+ Result :: ok | {error, Reason::term()} .
+engine_add(Engine) ->
+ notsup_to_error(engine_add_nif(Engine)).
+
+%%----------------------------------------------------------------------
+%% Function: engine_remove/1
+%%----------------------------------------------------------------------
+-spec engine_remove(Engine) -> Result when Engine :: engine_ref(),
+ Result :: ok | {error, Reason::term()} .
+engine_remove(Engine) ->
+ notsup_to_error(engine_remove_nif(Engine)).
+
+%%----------------------------------------------------------------------
+%% Function: engine_get_id/1
+%%----------------------------------------------------------------------
+-spec engine_get_id(Engine) -> EngineId when Engine :: engine_ref(),
+ EngineId :: unicode:chardata().
+engine_get_id(Engine) ->
+ notsup_to_error(engine_get_id_nif(Engine)).
+
+%%----------------------------------------------------------------------
+%% Function: engine_get_name/1
+%%----------------------------------------------------------------------
+-spec engine_get_name(Engine) -> EngineName when Engine :: engine_ref(),
+ EngineName :: unicode:chardata().
+engine_get_name(Engine) ->
+ notsup_to_error(engine_get_name_nif(Engine)).
+
+%%----------------------------------------------------------------------
%% Function: engine_list/0
%%----------------------------------------------------------------------
--spec engine_list() ->
- [EngineId::binary()].
+-spec engine_list() -> Result when Result :: [EngineId::unicode:chardata()].
engine_list() ->
case notsup_to_error(engine_get_first_nif()) of
{ok, <<>>} ->
[];
{ok, Engine} ->
case notsup_to_error(engine_get_id_nif(Engine)) of
- {ok, <<>>} ->
+ <<>> ->
engine_list(Engine, []);
- {ok, EngineId} ->
+ EngineId ->
engine_list(Engine, [EngineId])
end
end.
@@ -777,9 +1449,9 @@ engine_list(Engine0, IdList) ->
lists:reverse(IdList);
{ok, Engine1} ->
case notsup_to_error(engine_get_id_nif(Engine1)) of
- {ok, <<>>} ->
+ <<>> ->
engine_list(Engine1, IdList);
- {ok, EngineId} ->
+ EngineId ->
engine_list(Engine1, [EngineId |IdList])
end
end.
@@ -787,24 +1459,26 @@ engine_list(Engine0, IdList) ->
%%----------------------------------------------------------------------
%% Function: engine_ctrl_cmd_string/3
%%----------------------------------------------------------------------
--spec engine_ctrl_cmd_string(Engine::term(),
- CmdName::unicode:chardata(),
- CmdArg::unicode:chardata()) ->
- ok | {error, Reason::term()}.
+-spec engine_ctrl_cmd_string(Engine, CmdName, CmdArg) ->
+ Result when Engine::term(),
+ CmdName::unicode:chardata(),
+ CmdArg::unicode:chardata(),
+ Result :: ok | {error, Reason::term()}.
engine_ctrl_cmd_string(Engine, CmdName, CmdArg) ->
engine_ctrl_cmd_string(Engine, CmdName, CmdArg, false).
%%----------------------------------------------------------------------
%% Function: engine_ctrl_cmd_string/4
%%----------------------------------------------------------------------
--spec engine_ctrl_cmd_string(Engine::term(),
- CmdName::unicode:chardata(),
- CmdArg::unicode:chardata(),
- Optional::boolean()) ->
- ok | {error, Reason::term()}.
+-spec engine_ctrl_cmd_string(Engine, CmdName, CmdArg, Optional) ->
+ Result when Engine::term(),
+ CmdName::unicode:chardata(),
+ CmdArg::unicode:chardata(),
+ Optional::boolean(),
+ Result :: ok | {error, Reason::term()}.
engine_ctrl_cmd_string(Engine, CmdName, CmdArg, Optional) ->
- case engine_ctrl_cmd_strings_nif(Engine,
- ensure_bin_cmds([{CmdName, CmdArg}]),
+ case engine_ctrl_cmd_strings_nif(Engine,
+ ensure_bin_cmds([{CmdName, CmdArg}]),
bool_to_int(Optional)) of
ok ->
ok;
@@ -814,6 +1488,97 @@ engine_ctrl_cmd_string(Engine, CmdName, CmdArg, Optional) ->
{error, Error}
end.
+%%----------------------------------------------------------------------
+%% Function: ensure_engine_loaded/2
+%% Special version of load that only uses dynamic engine to load
+%%----------------------------------------------------------------------
+-spec ensure_engine_loaded(EngineId, LibPath) ->
+ Result when EngineId :: unicode:chardata(),
+ LibPath :: unicode:chardata(),
+ Result :: {ok, Engine::engine_ref()} | {error, Reason::term()}.
+ensure_engine_loaded(EngineId, LibPath) ->
+ ensure_engine_loaded(EngineId, LibPath, engine_get_all_methods()).
+
+%%----------------------------------------------------------------------
+%% Function: ensure_engine_loaded/3
+%% Special version of load that only uses dynamic engine to load
+%%----------------------------------------------------------------------
+-spec ensure_engine_loaded(EngineId, LibPath, EngineMethods) ->
+ Result when EngineId :: unicode:chardata(),
+ LibPath :: unicode:chardata(),
+ EngineMethods :: [engine_method_type()],
+ Result :: {ok, Engine::engine_ref()} | {error, Reason::term()}.
+ensure_engine_loaded(EngineId, LibPath, EngineMethods) ->
+ try
+ List = crypto:engine_list(),
+ case lists:member(EngineId, List) of
+ true ->
+ notsup_to_error(engine_by_id_nif(ensure_bin_chardata(EngineId)));
+ false ->
+ ok = notsup_to_error(engine_load_dynamic_nif()),
+ case notsup_to_error(engine_by_id_nif(ensure_bin_chardata(<<"dynamic">>))) of
+ {ok, Engine} ->
+ PreCommands = [{<<"SO_PATH">>, ensure_bin_chardata(LibPath)},
+ {<<"ID">>, ensure_bin_chardata(EngineId)},
+ <<"LOAD">>],
+ ensure_engine_loaded_1(Engine, PreCommands, EngineMethods);
+ {error, Error1} ->
+ {error, Error1}
+ end
+ end
+ catch
+ throw:Error2 ->
+ Error2
+ end.
+
+ensure_engine_loaded_1(Engine, PreCmds, Methods) ->
+ try
+ ok = engine_nif_wrapper(engine_ctrl_cmd_strings_nif(Engine, ensure_bin_cmds(PreCmds), 0)),
+ ok = engine_nif_wrapper(engine_add_nif(Engine)),
+ ok = engine_nif_wrapper(engine_init_nif(Engine)),
+ ensure_engine_loaded_2(Engine, Methods),
+ {ok, Engine}
+ catch
+ throw:Error ->
+ %% The engine couldn't initialise, release the structural reference
+ ok = engine_free_nif(Engine),
+ throw(Error)
+ end.
+
+ensure_engine_loaded_2(Engine, Methods) ->
+ try
+ [ok = engine_nif_wrapper(engine_register_nif(Engine, engine_method_atom_to_int(Method))) ||
+ Method <- Methods],
+ ok
+ catch
+ throw:Error ->
+ %% The engine registration failed, release the functional reference
+ ok = engine_finish_nif(Engine),
+ throw(Error)
+ end.
+%%----------------------------------------------------------------------
+%% Function: ensure_engine_unloaded/1
+%%----------------------------------------------------------------------
+-spec ensure_engine_unloaded(Engine) -> Result when Engine :: engine_ref(),
+ Result :: ok | {error, Reason::term()}.
+ensure_engine_unloaded(Engine) ->
+ ensure_engine_unloaded(Engine, engine_get_all_methods()).
+
+%%----------------------------------------------------------------------
+%% Function: ensure_engine_unloaded/2
+%%----------------------------------------------------------------------
+-spec ensure_engine_unloaded(Engine, EngineMethods) ->
+ Result when Engine :: engine_ref(),
+ EngineMethods :: [engine_method_type()],
+ Result :: ok | {error, Reason::term()}.
+ensure_engine_unloaded(Engine, EngineMethods) ->
+ case engine_remove(Engine) of
+ ok ->
+ engine_unload(Engine, EngineMethods);
+ {error, E} ->
+ {error, E}
+ end.
+
%%--------------------------------------------------------------------
%%% On load
%%--------------------------------------------------------------------
@@ -880,13 +1645,17 @@ path2bin(Path) when is_list(Path) ->
Bin
end.
-%%--------------------------------------------------------------------
+%%%================================================================
+%%%================================================================
+%%%
%%% Internal functions
-%%--------------------------------------------------------------------
+%%%
+%%%================================================================
+
max_bytes() ->
?MAX_BYTES_TO_NIF.
-notsup_to_error(notsup) ->
+notsup_to_error(notsup) ->
erlang:error(notsup);
notsup_to_error(Other) ->
Other.
@@ -942,9 +1711,12 @@ hmac_final_nif(_Context) -> ?nif_stub.
hmac_final_nif(_Context, _MacSize) -> ?nif_stub.
%% CMAC
-
cmac_nif(_Type, _Key, _Data) -> ?nif_stub.
+%% POLY1305
+poly1305_nif(_Key, _Data) -> ?nif_stub.
+
+
%% CIPHERS --------------------------------------------------------------------
block_crypt_nif(_Type, _Key, _Ivec, _Text, _IsEncrypt) -> ?nif_stub.
@@ -964,16 +1736,11 @@ check_des3_key(Key) ->
%% AES - in Galois/Counter Mode (GCM)
%%
%% The default tag length is EVP_GCM_TLS_TAG_LEN(16),
-aes_gcm_encrypt(Key, Ivec, AAD, In) ->
- aes_gcm_encrypt(Key, Ivec, AAD, In, 16).
-aes_gcm_encrypt(_Key, _Ivec, _AAD, _In, _TagLength) -> ?nif_stub.
-aes_gcm_decrypt(_Key, _Ivec, _AAD, _In, _Tag) -> ?nif_stub.
+aead_encrypt(Type=aes_ccm, Key, Ivec, AAD, In) -> aead_encrypt(Type, Key, Ivec, AAD, In, 12);
+aead_encrypt(Type=aes_gcm, Key, Ivec, AAD, In) -> aead_encrypt(Type, Key, Ivec, AAD, In, 16).
-%%
-%% Chacha20/Ppoly1305
-%%
-chacha20_poly1305_encrypt(_Key, _Ivec, _AAD, _In) -> ?nif_stub.
-chacha20_poly1305_decrypt(_Key, _Ivec, _AAD, _In, _Tag) -> ?nif_stub.
+aead_encrypt(_Type, _Key, _Ivec, _AAD, _In, _TagLength) -> ?nif_stub.
+aead_decrypt(_Type, _Key, _Ivec, _AAD, _In, _Tag) -> ?nif_stub.
%%
%% AES - with 256 bit key in infinite garble extension mode (IGE)
@@ -999,27 +1766,25 @@ do_stream_encrypt({aes_ctr, State0}, Data) ->
{{aes_ctr, State}, Cipher};
do_stream_encrypt({rc4, State0}, Data) ->
{State, Cipher} = rc4_encrypt_with_state(State0, Data),
- {{rc4, State}, Cipher}.
+ {{rc4, State}, Cipher};
+do_stream_encrypt({chacha20, State0}, Data) ->
+ {State, Cipher} = chacha20_stream_encrypt(State0, Data),
+ {{chacha20, State}, Cipher}.
do_stream_decrypt({aes_ctr, State0}, Data) ->
{State, Text} = aes_ctr_stream_decrypt(State0, Data),
{{aes_ctr, State}, Text};
do_stream_decrypt({rc4, State0}, Data) ->
{State, Text} = rc4_encrypt_with_state(State0, Data),
- {{rc4, State}, Text}.
+ {{rc4, State}, Text};
+do_stream_decrypt({chacha20, State0}, Data) ->
+ {State, Cipher} = chacha20_stream_decrypt(State0, Data),
+ {{chacha20, State}, Cipher}.
%%
%% AES - in counter mode (CTR) with state maintained for multi-call streaming
%%
--type ctr_state() :: { iodata(), binary(), binary(), integer() } | binary().
-
--spec aes_ctr_stream_init(iodata(), binary()) -> ctr_state().
--spec aes_ctr_stream_encrypt(ctr_state(), binary()) ->
- { ctr_state(), binary() }.
--spec aes_ctr_stream_decrypt(ctr_state(), binary()) ->
- { ctr_state(), binary() }.
-
aes_ctr_stream_init(_Key, _IVec) -> ?nif_stub.
aes_ctr_stream_encrypt(_State, _Data) -> ?nif_stub.
aes_ctr_stream_decrypt(_State, _Cipher) -> ?nif_stub.
@@ -1030,6 +1795,13 @@ aes_ctr_stream_decrypt(_State, _Cipher) -> ?nif_stub.
rc4_set_key(_Key) -> ?nif_stub.
rc4_encrypt_with_state(_State, _Data) -> ?nif_stub.
+%%
+%% CHACHA20 - stream cipher
+%%
+chacha20_stream_init(_Key, _IVec) -> ?nif_stub.
+chacha20_stream_encrypt(_State, _Data) -> ?nif_stub.
+chacha20_stream_decrypt(_State, _Data) -> ?nif_stub.
+
%% Secure remote password -------------------------------------------------------------------
user_srp_gen_key(Private, Generator, Prime) ->
@@ -1096,11 +1868,6 @@ srp_user_secret_nif(_A, _U, _B, _Multiplier, _Generator, _Exponent, _Prime) -> ?
srp_value_B_nif(_Multiplier, _Verifier, _Generator, _Exponent, _Prime) -> ?nif_stub.
-%% Digital signatures --------------------------------------------------------------------
-
-pkey_sign_nif(_Algorithm, _Type, _Digest, _Key, _Options) -> ?nif_stub.
-pkey_verify_nif(_Algorithm, _Type, _Data, _Signature, _Key, _Options) -> ?nif_stub.
-
%% Public Keys --------------------------------------------------------------------
%% RSA Rivest-Shamir-Adleman functions
%%
@@ -1122,13 +1889,20 @@ ec_key_generate(_Curve, _Key) -> ?nif_stub.
ecdh_compute_key_nif(_Others, _Curve, _My) -> ?nif_stub.
+-spec ec_curves() -> [EllipticCurve] when EllipticCurve :: ec_named_curve() | edwards_curve() .
+
ec_curves() ->
crypto_ec_curves:curves().
+-spec ec_curve(CurveName) -> ExplicitCurve when CurveName :: ec_named_curve(),
+ ExplicitCurve :: ec_explicit_curve() .
ec_curve(X) ->
crypto_ec_curves:curve(X).
+-spec privkey_to_pubkey(Type, EnginePrivateKeyRef) -> PublicKey when Type :: rsa | dss,
+ EnginePrivateKeyRef :: engine_key_ref(),
+ PublicKey :: rsa_public() | dss_public() .
privkey_to_pubkey(Alg, EngineMap) when Alg == rsa; Alg == dss; Alg == ecdsa ->
try privkey_to_pubkey_nif(Alg, format_pkey(Alg,EngineMap))
of
@@ -1142,7 +1916,7 @@ privkey_to_pubkey(Alg, EngineMap) when Alg == rsa; Alg == dss; Alg == ecdsa ->
error:notsup ->
{error, notsup}
end.
-
+
privkey_to_pubkey_nif(_Alg, _EngineMap) -> ?nif_stub.
@@ -1154,10 +1928,16 @@ term_to_nif_prime({prime_field, Prime}) ->
{prime_field, ensure_int_as_bin(Prime)};
term_to_nif_prime(PrimeField) ->
PrimeField.
+
term_to_nif_curve({A, B, Seed}) ->
{ensure_int_as_bin(A), ensure_int_as_bin(B), Seed}.
+
nif_curve_params({PrimeField, Curve, BasePoint, Order, CoFactor}) ->
- {term_to_nif_prime(PrimeField), term_to_nif_curve(Curve), ensure_int_as_bin(BasePoint), ensure_int_as_bin(Order), ensure_int_as_bin(CoFactor)};
+ {term_to_nif_prime(PrimeField),
+ term_to_nif_curve(Curve),
+ ensure_int_as_bin(BasePoint),
+ ensure_int_as_bin(Order),
+ ensure_int_as_bin(CoFactor)};
nif_curve_params(Curve) when is_atom(Curve) ->
%% named curve
case Curve of
@@ -1197,6 +1977,7 @@ int_to_bin_neg(-1, Ds=[MSB|_]) when MSB >= 16#80 ->
int_to_bin_neg(X,Ds) ->
int_to_bin_neg(X bsr 8, [(X band 255)|Ds]).
+-spec bytes_to_integer(binary()) -> integer() .
bytes_to_integer(Bin) ->
bin_to_int(Bin).
@@ -1244,9 +2025,6 @@ format_pwd(M) -> M.
%%--------------------------------------------------------------------
%%
--type rsa_padding() :: 'rsa_pkcs1_padding' | 'rsa_pkcs1_oaep_padding' | 'rsa_no_padding'.
-
-pkey_crypt_nif(_Algorithm, _In, _Key, _Options, _IsPrivate, _IsEncrypt) -> ?nif_stub.
%% large integer in a binary with 32bit length
%% MP representaion (SSH2)
@@ -1308,6 +2086,7 @@ engine_unregister_nif(_Engine, _EngineMethod) -> ?nif_stub.
engine_get_first_nif() -> ?nif_stub.
engine_get_next_nif(_Engine) -> ?nif_stub.
engine_get_id_nif(_Engine) -> ?nif_stub.
+engine_get_name_nif(_Engine) -> ?nif_stub.
engine_get_all_methods_nif() -> ?nif_stub.
%%--------------------------------------------------------------------
@@ -1365,7 +2144,7 @@ get_test_engine() ->
Type = erlang:system_info(system_architecture),
LibDir = filename:join([code:priv_dir(crypto), "lib"]),
ArchDir = filename:join([LibDir, Type]),
- case filelib:is_dir(ArchDir) of
+ case filelib:is_dir(ArchDir) of
true -> check_otp_test_engine(ArchDir);
false -> check_otp_test_engine(LibDir)
end.
@@ -1383,4 +2162,3 @@ check_otp_test_engine(LibDir) ->
{error, notexist}
end
end.
-
diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl
index 1027a8d945..ba3901e5fc 100644
--- a/lib/crypto/test/crypto_SUITE.erl
+++ b/lib/crypto/test/crypto_SUITE.erl
@@ -51,6 +51,10 @@ groups() ->
{group, sha256},
{group, sha384},
{group, sha512},
+ {group, sha3_224},
+ {group, sha3_256},
+ {group, sha3_384},
+ {group, sha3_512},
{group, rsa},
{group, dss},
{group, ecdsa},
@@ -75,8 +79,11 @@ groups() ->
{group, rc2_cbc},
{group, rc4},
{group, aes_ctr},
+ {group, aes_ccm},
{group, aes_gcm},
{group, chacha20_poly1305},
+ {group, chacha20},
+ {group, poly1305},
{group, aes_cbc}]},
{fips, [], [{group, no_md4},
{group, no_md5},
@@ -110,8 +117,10 @@ groups() ->
{group, no_rc2_cbc},
{group, no_rc4},
{group, aes_ctr},
+ {group, aes_ccm},
{group, aes_gcm},
{group, no_chacha20_poly1305},
+ {group, no_chacha20},
{group, aes_cbc}]},
{md4, [], [hash]},
{md5, [], [hash, hmac]},
@@ -121,6 +130,10 @@ groups() ->
{sha256, [], [hash, hmac]},
{sha384, [], [hash, hmac]},
{sha512, [], [hash, hmac]},
+ {sha3_224, [], [hash, hmac]},
+ {sha3_256, [], [hash, hmac]},
+ {sha3_384, [], [hash, hmac]},
+ {sha3_512, [], [hash, hmac]},
{rsa, [], [sign_verify,
public_encrypt,
private_encrypt,
@@ -155,8 +168,11 @@ groups() ->
{blowfish_ofb64,[], [block]},
{rc4, [], [stream]},
{aes_ctr, [], [stream]},
+ {aes_ccm, [], [aead]},
{aes_gcm, [], [aead]},
{chacha20_poly1305, [], [aead]},
+ {chacha20, [], [stream]},
+ {poly1305, [], [poly1305]},
{aes_cbc, [], [block]},
{no_md4, [], [no_support, no_hash]},
{no_md5, [], [no_support, no_hash, no_hmac]},
@@ -170,6 +186,7 @@ groups() ->
{no_blowfish_ofb64, [], [no_support, no_block]},
{no_aes_ige256, [], [no_support, no_block]},
{no_chacha20_poly1305, [], [no_support, no_aead]},
+ {no_chacha20, [], [no_support, no_stream_ivec]},
{no_rc2_cbc, [], [no_support, no_block]},
{no_rc4, [], [no_support, no_stream]},
{api_errors, [], [api_errors_ecdh]}
@@ -356,6 +373,20 @@ cmac(Config) when is_list(Config) ->
lists:foreach(fun cmac_check/1, Pairs),
lists:foreach(fun cmac_check/1, cmac_iolistify(Pairs)).
%%--------------------------------------------------------------------
+poly1305() ->
+ [{doc, "Test poly1305 function"}].
+poly1305(Config) ->
+ lists:foreach(
+ fun({Key, Txt, Expect}) ->
+ case crypto:poly1305(Key,Txt) of
+ Expect ->
+ ok;
+ Other ->
+ ct:fail({{crypto, poly1305, [Key, Txt]}, {expected, Expect}, {got, Other}})
+ end
+ end, proplists:get_value(poly1305, Config)).
+
+%%--------------------------------------------------------------------
block() ->
[{doc, "Test block ciphers"}].
block(Config) when is_list(Config) ->
@@ -397,12 +428,18 @@ no_block(Config) when is_list(Config) ->
no_aead() ->
[{doc, "Test disabled aead ciphers"}].
no_aead(Config) when is_list(Config) ->
- [{Type, Key, PlainText, Nonce, AAD, CipherText, CipherTag} | _] =
- lazy_eval(proplists:get_value(aead, Config)),
- EncryptArgs = [Type, Key, Nonce, {AAD, PlainText}],
+ EncArg4 =
+ case lazy_eval(proplists:get_value(aead, Config)) of
+ [{Type, Key, PlainText, Nonce, AAD, CipherText, CipherTag, TagLen, _Info} | _] ->
+ {AAD, PlainText, TagLen};
+ [{Type, Key, PlainText, Nonce, AAD, CipherText, CipherTag, _Info} | _] ->
+ {AAD, PlainText}
+ end,
+ EncryptArgs = [Type, Key, Nonce, EncArg4],
DecryptArgs = [Type, Key, Nonce, {AAD, CipherText, CipherTag}],
notsup(fun crypto:block_encrypt/4, EncryptArgs),
notsup(fun crypto:block_decrypt/4, DecryptArgs).
+
%%--------------------------------------------------------------------
stream() ->
[{doc, "Test stream ciphers"}].
@@ -420,6 +457,13 @@ no_stream(Config) when is_list(Config) ->
notsup(fun crypto:stream_init/2, [Type, <<"Key">>]).
%%--------------------------------------------------------------------
+no_stream_ivec() ->
+ [{doc, "Test disabled stream ciphers that uses ivec"}].
+no_stream_ivec(Config) when is_list(Config) ->
+ Type = ?config(type, Config),
+ notsup(fun crypto:stream_init/3, [Type, <<"Key">>, <<"Ivec">>]).
+
+%%--------------------------------------------------------------------
aead() ->
[{doc, "Test AEAD ciphers"}].
aead(Config) when is_list(Config) ->
@@ -470,7 +514,7 @@ generate_compute(Config) when is_list(Config) ->
%%--------------------------------------------------------------------
compute_bug() ->
[{doc, "Test that it works even if the Secret is smaller than expected"}].
-compute_bug(Config) ->
+compute_bug(_Config) ->
ExpectedSecret = <<118,89,171,16,156,18,156,103,189,134,130,49,28,144,111,241,247,82,79,32,228,11,209,141,119,176,251,80,105,143,235,251,203,121,223,211,129,3,233,133,45,2,31,157,24,111,5,75,153,66,135,185,128,115,229,178,216,39,73,52,80,151,8,241,34,52,226,71,137,167,53,48,59,224,175,154,89,110,76,83,24,117,149,21,72,6,186,78,149,74,188,56,98,244,30,77,108,248,88,194,195,237,23,51,20,242,254,123,21,12,209,74,217,168,230,65,7,60,211,139,128,239,234,153,22,229,180,59,159,121,41,156,121,200,177,130,163,162,54,224,93,1,94,11,177,254,118,28,156,26,116,10,207,145,219,166,214,189,214,230,221,170,228,15,69,88,31,68,94,255,113,58,49,82,86,192,248,176,131,133,39,186,194,172,206,84,184,16,66,68,153,128,178,227,27,118,52,130,122,92,24,222,102,195,221,207,255,13,152,175,65,32,167,84,54,244,243,109,244,18,234,16,159,224,188,2,106,123,27,17,131,171,226,34,111,251,62,119,155,124,221,124,254,62,97,167,1,105,116,98,98,19,197,30,72,180,79,221,100,134,120,117,124,85,73,132,224,223,222,41,155,137,218,130,238,237,157,161,134,150,69,206,91,141,17,89,120,218,235,229,37,150,76,197,7,157,56,144,42,203,137,100,200,72,141,194,239,1,67,236,238,183,48,214,75,76,108,235,3,237,67,40,137,45,182,236,246,37,116,103,144,237,142,211,88,233,11,24,21,218,41,245,250,51,130,250,104,74,189,17,69,145,70,50,50,215,253,155,10,128,41,114,185,211,82,164,72,92,17,145,104,66,6,140,226,80,43,62,1,166,216,153,118,96,15,147,126,137,118,191,192,75,149,241,206,18,92,17,154,215,219,18,6,139,190,103,210,156,184,29,224,213,157,60,112,189,104,220,125,40,186,50,119,17,143,136,149,38,74,107,21,192,59,61,59,42,231,144,59,175,3,176,87,23,16,122,54,31,82,34,230,211,44,81,41,47,86,37,228,175,130,148,88,136,131,254,241,202,99,199,175,1,141,215,124,155,120,43,141,89,11,140,120,141,29,35,82,219,155,204,75,12,66,241,253,33,250,84,24,85,68,13,80,85,142,227,34,139,26,146,24>>,
OthersPublicKey = 635619632099733175381667940709387641100492974601603060984753028943194386334921787463327680809776598322996634648015962954045728174069768874873236397421720142610982770302060309928552098274817978606093380781524199673890631795310930242601197479471368910519338301177304682162189801040921618559902948819107531088646753320486728060005223263561551402855338732899079439899705951063999951507319258050864346087428042978411873495523439615429804957374639092580169417598963105885529553632847023899713490485619763926900318508906706745060947269748612049634207985438016935262521715769812475329234748426647554362991758104620357149045960316987533503707855364806010494793980069245562784050236811004893018183726397041999426883788660276453352521120006817370050691205529335316794439089316232980047277245051173281601960196573681285904611182521967067911862467395705665888521948321299521549941618586026714676885890192323289343756440666276226084448279082483536164085883288884231665240707495770544705648564889889198060417915693315346959170105413290799314390963124178046425737828369059171472978294050322371452255088799865552038756937873388385970088906560408959959429398326288750834357514847891423941047433478384621074116184703014798814515161475596555032391555842,
MyPrivateKey = 387759582879975726965038486537011291913744975764132199838375902680222019267527675651273586836110220500657652661706223760165097275862806031329642160439090779625708664007910974206651834216043397115514725827856461492311499129200688538220719685637154290305617686974719521885238198226075381217068175824097878445476010193039590876624464274744156624589136789060427283492343902761765833713520850870233407503430180028104167029073459918756981323130062648615262139444306321256382009848217866984408901761817655567071716275177768316006340055589170095799943481591033461616307776069027985761229636731465482676467627154100912586936231051371168178564599296638350391246393336702334311781595616786107810962134407697848002331639021101685320844880636050048769216986088652236979636019052557155807310341483407890060105599892252118584570558049301477535792498672552850760356632076013402382600669875697284264329434950712239302528367835155163504374877787288116104285944993818319105835423479332617802010952731990182088670508346704423006877514817882782443833997288652405892920173712497948376815825396272381214976859009518623799156300136570204539240675245115597412280078940442452936425561984312708387584800789375684525365060589104566195610526570099527133097201479,
@@ -602,31 +646,29 @@ hash_increment(State0, [Increment | Rest]) ->
hmac(_, [],[],[]) ->
ok;
hmac(sha = Type, [Key | Keys], [ <<"Test With Truncation">> = Data| Rest], [Expected | Expects]) ->
- case crypto:hmac(Type, Key, Data, 20) of
- Expected ->
- ok;
- Other ->
- ct:fail({{crypto, hmac, [Type, Key, Data]}, {expected, Expected}, {got, Other}})
- end,
+ call_crypto_hmac([Type, Key, Data, 20], Type, Expected),
hmac(Type, Keys, Rest, Expects);
-
hmac(Type, [Key | Keys], [ <<"Test With Truncation">> = Data| Rest], [Expected | Expects]) ->
- case crypto:hmac(Type, Key, Data, 16) of
- Expected ->
- ok;
- Other ->
- ct:fail({{crypto, hmac, [Type, Key, Data]}, {expected, Expected}, {got, Other}})
- end,
+ call_crypto_hmac([Type, Key, Data, 16], Type, Expected),
hmac(Type, Keys, Rest, Expects);
-
hmac(Type, [Key | Keys], [Data| Rest], [Expected | Expects]) ->
- case crypto:hmac(Type, Key, Data) of
+ call_crypto_hmac([Type, Key, Data], Type, Expected),
+ hmac(Type, Keys, Rest, Expects).
+
+call_crypto_hmac(Args, Type, Expected) ->
+ try apply(crypto, hmac, Args)
+ of
Expected ->
ok;
Other ->
- ct:fail({{crypto, hmac, [Type, Key, Data]}, {expected, Expected}, {got, Other}})
- end,
- hmac(Type, Keys, Rest, Expects).
+ ct:fail({{crypto,hmac,Args}, {expected,Expected}, {got,Other}})
+ catch
+ error:notsup ->
+ ct:fail("HMAC ~p not supported", [Type]);
+ Class:Cause ->
+ ct:fail({{crypto,hmac,Args}, {expected,Expected}, {got,{Class,Cause}}})
+ end.
+
hmac_increment(Type) ->
Key = hmac_key(Type),
@@ -757,16 +799,33 @@ stream_cipher({Type, Key, IV, PlainText}) ->
ok;
Other ->
ct:fail({{crypto, stream_decrypt, [State, CipherText]}, {expected, PlainText}, {got, Other}})
+ end;
+stream_cipher({Type, Key, IV, PlainText, CipherText}) ->
+ Plain = iolist_to_binary(PlainText),
+ State = crypto:stream_init(Type, Key, IV),
+ case crypto:stream_encrypt(State, PlainText) of
+ {_, CipherText} ->
+ ok;
+ {_, Other0} ->
+ ct:fail({{crypto, stream_encrypt, [State, Type, Key, IV, Plain]}, {expected, CipherText}, {got, Other0}})
+ end,
+ case crypto:stream_decrypt(State, CipherText) of
+ {_, Plain} ->
+ ok;
+ Other1 ->
+ ct:fail({{crypto, stream_decrypt, [State, CipherText]}, {expected, PlainText}, {got, Other1}})
end.
stream_cipher_incment({Type, Key, PlainTexts}) ->
State = crypto:stream_init(Type, Key),
- stream_cipher_incment(State, State, PlainTexts, [], iolist_to_binary(PlainTexts));
+ stream_cipher_incment_loop(State, State, PlainTexts, [], iolist_to_binary(PlainTexts));
stream_cipher_incment({Type, Key, IV, PlainTexts}) ->
State = crypto:stream_init(Type, Key, IV),
- stream_cipher_incment(State, State, PlainTexts, [], iolist_to_binary(PlainTexts)).
+ stream_cipher_incment_loop(State, State, PlainTexts, [], iolist_to_binary(PlainTexts));
+stream_cipher_incment({Type, Key, IV, PlainTexts, _CipherText}) ->
+ stream_cipher_incment({Type, Key, IV, PlainTexts}).
-stream_cipher_incment(_State, OrigState, [], Acc, Plain) ->
+stream_cipher_incment_loop(_State, OrigState, [], Acc, Plain) ->
CipherText = iolist_to_binary(lists:reverse(Acc)),
case crypto:stream_decrypt(OrigState, CipherText) of
{_, Plain} ->
@@ -774,38 +833,55 @@ stream_cipher_incment(_State, OrigState, [], Acc, Plain) ->
Other ->
ct:fail({{crypto, stream_decrypt, [OrigState, CipherText]}, {expected, Plain}, {got, Other}})
end;
-stream_cipher_incment(State0, OrigState, [PlainText | PlainTexts], Acc, Plain) ->
+stream_cipher_incment_loop(State0, OrigState, [PlainText | PlainTexts], Acc, Plain) ->
{State, CipherText} = crypto:stream_encrypt(State0, PlainText),
- stream_cipher_incment(State, OrigState, PlainTexts, [CipherText | Acc], Plain).
+ stream_cipher_incment_loop(State, OrigState, PlainTexts, [CipherText | Acc], Plain).
-aead_cipher({Type, Key, PlainText, IV, AAD, CipherText, CipherTag}) ->
+aead_cipher({Type, Key, PlainText, IV, AAD, CipherText, CipherTag, Info}) ->
Plain = iolist_to_binary(PlainText),
case crypto:block_encrypt(Type, Key, IV, {AAD, Plain}) of
{CipherText, CipherTag} ->
ok;
Other0 ->
- ct:fail({{crypto, block_encrypt, [Plain, PlainText]}, {expected, {CipherText, CipherTag}}, {got, Other0}})
+ ct:fail({{crypto,
+ block_encrypt,
+ [{info,Info}, {key,Key}, {pt,PlainText}, {iv,IV}, {aad,AAD}, {ct,CipherText}, {tag,CipherTag}]},
+ {expected, {CipherText, CipherTag}},
+ {got, Other0}})
end,
case crypto:block_decrypt(Type, Key, IV, {AAD, CipherText, CipherTag}) of
Plain ->
ok;
Other1 ->
- ct:fail({{crypto, block_decrypt, [CipherText]}, {expected, Plain}, {got, Other1}})
+ ct:fail({{crypto,
+ block_decrypt,
+ [{info,Info}, {key,Key}, {pt,PlainText}, {iv,IV}, {aad,AAD}, {ct,CipherText}, {tag,CipherTag}]},
+ {expected, Plain},
+ {got, Other1}})
end;
-aead_cipher({Type, Key, PlainText, IV, AAD, CipherText, CipherTag, TagLen}) ->
+aead_cipher({Type, Key, PlainText, IV, AAD, CipherText, CipherTag, TagLen, Info}) ->
<<TruncatedCipherTag:TagLen/binary, _/binary>> = CipherTag,
Plain = iolist_to_binary(PlainText),
case crypto:block_encrypt(Type, Key, IV, {AAD, Plain, TagLen}) of
{CipherText, TruncatedCipherTag} ->
ok;
Other0 ->
- ct:fail({{crypto, block_encrypt, [Plain, PlainText]}, {expected, {CipherText, TruncatedCipherTag}}, {got, Other0}})
+ ct:fail({{crypto,
+ block_encrypt,
+ [{info,Info}, {key,Key}, {pt,PlainText}, {iv,IV}, {aad,AAD}, {ct,CipherText}, {tag,CipherTag}, {taglen,TagLen}]},
+ {expected, {CipherText, TruncatedCipherTag}},
+ {got, Other0}})
end,
case crypto:block_decrypt(Type, Key, IV, {AAD, CipherText, TruncatedCipherTag}) of
Plain ->
ok;
Other1 ->
- ct:fail({{crypto, block_decrypt, [CipherText]}, {expected, Plain}, {got, Other1}})
+ ct:fail({{crypto,
+ block_decrypt,
+ [{info,Info}, {key,Key}, {pt,PlainText}, {iv,IV}, {aad,AAD}, {ct,CipherText}, {tag,CipherTag},
+ {truncated,TruncatedCipherTag}]},
+ {expected, Plain},
+ {got, Other1}})
end.
do_sign_verify({Type, Hash, Public, Private, Msg}) ->
@@ -998,6 +1074,8 @@ hexstr2bin(S) when is_binary(S) ->
hexstr2bin(S) ->
list_to_binary(hexstr2list(S)).
+hexstr2list([$ |T]) ->
+ hexstr2list(T);
hexstr2list([X,Y|T]) ->
[mkint(X)*16 + mkint(Y) | hexstr2list(T)];
hexstr2list([]) ->
@@ -1009,6 +1087,14 @@ mkint(C) when $A =< C, C =< $F ->
mkint(C) when $a =< C, C =< $f ->
C - $a + 10.
+bin2hexstr(B) when is_binary(B) ->
+ io_lib:format("~.16b",[crypto:bytes_to_integer(B)]).
+
+decstr2int(S) when is_binary(S) ->
+ list_to_integer(binary:bin_to_list(S));
+decstr2int(S) ->
+ list_to_integer(S).
+
is_supported(Group) ->
lists:member(Group, lists:append([Algo || {_, Algo} <- crypto:supports()])).
@@ -1027,7 +1113,9 @@ do_cmac_iolistify({Type, Key, Text, Size, CMac}) ->
do_stream_iolistify({Type, Key, PlainText}) ->
{Type, iolistify(Key), iolistify(PlainText)};
do_stream_iolistify({Type, Key, IV, PlainText}) ->
- {Type, iolistify(Key), IV, iolistify(PlainText)}.
+ {Type, iolistify(Key), IV, iolistify(PlainText)};
+do_stream_iolistify({Type, Key, IV, PlainText, CipherText}) ->
+ {Type, iolistify(Key), IV, iolistify(PlainText), CipherText}.
do_block_iolistify({des_cbc = Type, Key, IV, PlainText}) ->
{Type, Key, IV, des_iolistify(PlainText)};
@@ -1273,7 +1361,7 @@ group_config(sha224 = Type, Config) ->
Keys = rfc_4231_keys(),
Data = rfc_4231_msgs(),
Hmac = rfc4231_hmac_sha224(),
- [{hash, {Type, Msgs, Digests}}, {hmac, {Type, Keys, Data, Hmac}} | Config];
+ [{hash, {Type, Msgs, Digests}}, {hmac, {Type, Keys, Data, Hmac}} | Config];
group_config(sha256 = Type, Config) ->
Msgs = [rfc_4634_test1(), rfc_4634_test2_1(), long_msg()],
Digests = rfc_4634_sha256_digests() ++ [long_sha256_digest()],
@@ -1295,6 +1383,18 @@ group_config(sha512 = Type, Config) ->
Data = rfc_4231_msgs() ++ [long_msg()],
Hmac = rfc4231_hmac_sha512() ++ [long_hmac(sha512)],
[{hash, {Type, Msgs, Digests}}, {hmac, {Type, Keys, Data, Hmac}} | Config];
+group_config(sha3_224 = Type, Config) ->
+ {Msgs,Digests} = sha3_test_vectors(Type),
+ [{hash, {Type, Msgs, Digests}}, {hmac, hmac_sha3(Type)} | Config];
+group_config(sha3_256 = Type, Config) ->
+ {Msgs,Digests} = sha3_test_vectors(Type),
+ [{hash, {Type, Msgs, Digests}}, {hmac, hmac_sha3(Type)} | Config];
+group_config(sha3_384 = Type, Config) ->
+ {Msgs,Digests} = sha3_test_vectors(Type),
+ [{hash, {Type, Msgs, Digests}}, {hmac, hmac_sha3(Type)} | Config];
+group_config(sha3_512 = Type, Config) ->
+ {Msgs,Digests} = sha3_test_vectors(Type),
+ [{hash, {Type, Msgs, Digests}}, {hmac, hmac_sha3(Type)} | Config];
group_config(rsa = Type, Config) ->
Msg = rsa_plain(),
Public = rsa_public(),
@@ -1319,8 +1419,8 @@ group_config(rsa = Type, Config) ->
{rsa, PublicS, PrivateS, MsgPubEnc, [{rsa_padding, rsa_sslv23_padding}]},
{rsa, PublicS, PrivateS, MsgPubEnc, [{rsa_padding, rsa_x931_padding}]},
rsa_oaep(),
- rsa_oaep_label(),
- rsa_oaep256(),
+ %% rsa_oaep_label(),
+ %% rsa_oaep256(),
no_padding()
],
Generate = [{rsa, 1024, 3}, {rsa, 2048, 17}, {rsa, 3072, 65537}],
@@ -1426,12 +1526,27 @@ group_config(rc4, Config) ->
group_config(aes_ctr, Config) ->
Stream = aes_ctr(),
[{stream, Stream} | Config];
+group_config(aes_ccm, Config) ->
+ AEAD = fun() -> aes_ccm(Config) end,
+ [{aead, AEAD} | Config];
group_config(aes_gcm, Config) ->
AEAD = fun() -> aes_gcm(Config) end,
[{aead, AEAD} | Config];
group_config(chacha20_poly1305, Config) ->
AEAD = chacha20_poly1305(),
[{aead, AEAD} | Config];
+group_config(chacha20, Config) ->
+ Stream = chacha20(),
+ [{stream, Stream} | Config];
+group_config(poly1305, Config) ->
+ V = [%% {Key, Txt, Expect}
+ {%% RFC7539 2.5.2
+ crypto_SUITE:hexstr2bin("85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b"),
+ <<"Cryptographic Forum Research Group">>,
+ crypto_SUITE:hexstr2bin("a8061dc1305136c6c22b8baf0c0127a9")
+ }
+ ],
+ [{poly1305,V} | Config];
group_config(aes_cbc, Config) ->
Block = aes_cbc(Config),
[{block, Block} | Config];
@@ -1500,6 +1615,160 @@ rfc_1321_md5_digests() ->
hexstr2bin("d174ab98d277d9f5a5611c2c9f419d9f"),
hexstr2bin("57edf4a22be3c955ac49da2e2107b67a")].
+%%% https://www.di-mgt.com.au/sha_testvectors.html
+sha3_msgs() ->
+ ["abc",
+ "",
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", % length 448 bits
+ "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", % length 896 bits
+ lists:duplicate(1000000,$a)
+ ].
+
+sha3_test_vectors(sha3_224) ->
+ {sha3_msgs(),
+ [hexstr2bin("e642824c3f8cf24a d09234ee7d3c766f c9a3a5168d0c94ad 73b46fdf"),
+ hexstr2bin("6b4e03423667dbb7 3b6e15454f0eb1ab d4597f9a1b078e3f 5b5a6bc7"),
+ hexstr2bin("8a24108b154ada21 c9fd5574494479ba 5c7e7ab76ef264ea d0fcce33"),
+ hexstr2bin("543e6868e1666c1a 643630df77367ae5 a62a85070a51c14c bf665cbc"),
+ hexstr2bin("d69335b93325192e 516a912e6d19a15c b51c6ed5c15243e7 a7fd653c")
+ ]
+ };
+sha3_test_vectors(sha3_256) ->
+ {sha3_msgs(),
+ [hexstr2bin("3a985da74fe225b2 045c172d6bd390bd 855f086e3e9d525b 46bfe24511431532"),
+ hexstr2bin("a7ffc6f8bf1ed766 51c14756a061d662 f580ff4de43b49fa 82d80a4b80f8434a"),
+ hexstr2bin("41c0dba2a9d62408 49100376a8235e2c 82e1b9998a999e21 db32dd97496d3376"),
+ hexstr2bin("916f6061fe879741 ca6469b43971dfdb 28b1a32dc36cb325 4e812be27aad1d18"),
+ hexstr2bin("5c8875ae474a3634 ba4fd55ec85bffd6 61f32aca75c6d699 d0cdcb6c115891c1")
+ ]
+ };
+sha3_test_vectors(sha3_384) ->
+ {sha3_msgs(),
+ [hexstr2bin("ec01498288516fc9 26459f58e2c6ad8d f9b473cb0fc08c25 96da7cf0e49be4b2 98d88cea927ac7f5 39f1edf228376d25"),
+ hexstr2bin("0c63a75b845e4f7d 01107d852e4c2485 c51a50aaaa94fc61 995e71bbee983a2a c3713831264adb47 fb6bd1e058d5f004"),
+ hexstr2bin("991c665755eb3a4b 6bbdfb75c78a492e 8c56a22c5c4d7e42 9bfdbc32b9d4ad5a a04a1f076e62fea1 9eef51acd0657c22"),
+ hexstr2bin("79407d3b5916b59c 3e30b09822974791 c313fb9ecc849e40 6f23592d04f625dc 8c709b98b43b3852 b337216179aa7fc7"),
+ hexstr2bin("eee9e24d78c18553 37983451df97c8ad 9eedf256c6334f8e 948d252d5e0e7684 7aa0774ddb90a842 190d2c558b4b8340")
+ ]
+ };
+sha3_test_vectors(sha3_512) ->
+ {sha3_msgs(),
+ [hexstr2bin("b751850b1a57168a 5693cd924b6b096e 08f621827444f70d 884f5d0240d2712e 10e116e9192af3c9 1a7ec57647e39340 57340b4cf408d5a5 6592f8274eec53f0"),
+ hexstr2bin("a69f73cca23a9ac5 c8b567dc185a756e 97c982164fe25859 e0d1dcc1475c80a6 15b2123af1f5f94c 11e3e9402c3ac558 f500199d95b6d3e3 01758586281dcd26"),
+ hexstr2bin("04a371e84ecfb5b8 b77cb48610fca818 2dd457ce6f326a0f d3d7ec2f1e91636d ee691fbe0c985302 ba1b0d8dc78c0863 46b533b49c030d99 a27daf1139d6e75e"),
+ hexstr2bin("afebb2ef542e6579 c50cad06d2e578f9 f8dd6881d7dc824d 26360feebf18a4fa 73e3261122948efc fd492e74e82e2189 ed0fb440d187f382 270cb455f21dd185"),
+ hexstr2bin("3c3a876da14034ab 60627c077bb98f7e 120a2a5370212dff b3385a18d4f38859 ed311d0a9d5141ce 9cc5c66ee689b266 a8aa18ace8282a0e 0db596c90b0a7b87")
+ ]
+ }.
+
+
+
+%%% http://www.wolfgang-ehrhardt.de/hmac-sha3-testvectors.html
+
+hmac_sha3(Type) ->
+ N = case Type of
+ sha3_224 -> 1;
+ sha3_256 -> 2;
+ sha3_384 -> 3;
+ sha3_512 -> 4
+ end,
+ {Keys, Datas, Hmacs} =
+ lists:unzip3(
+ [{hexstr2bin(Key), hexstr2bin(Data), hexstr2bin(element(N,Hmacs))}
+ || {Key,Data,Hmacs} <- hmac_sha3_data()]),
+ {Type, Keys, Datas, Hmacs}.
+
+
+hmac_sha3_data() ->
+ [
+ {"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b 0b0b0b0b",
+ "4869205468657265",
+ {"3b16546bbc7be2706a031dcafd56373d 9884367641d8c59af3c860f7",
+ "ba85192310dffa96e2a3a40e69774351 140bb7185e1202cdcc917589f95e16bb",
+ "68d2dcf7fd4ddd0a2240c8a437305f61 fb7334cfb5d0226e1bc27dc10a2e723a 20d370b47743130e26ac7e3d532886bd",
+ "eb3fbd4b2eaab8f5c504bd3a41465aac ec15770a7cabac531e482f860b5ec7ba 47ccb2c6f2afce8f88d22b6dc61380f2 3a668fd3888bb80537c0a0b86407689e"
+ }},
+
+ {"4a656665",
+ "7768617420646f2079612077616e7420 666f72206e6f7468696e673f",
+ {"7fdb8dd88bd2f60d1b798634ad386811 c2cfc85bfaf5d52bbace5e66",
+ "c7d4072e788877ae3596bbb0da73b887 c9171f93095b294ae857fbe2645e1ba5",
+ "f1101f8cbf9766fd6764d2ed61903f21 ca9b18f57cf3e1a23ca13508a93243ce 48c045dc007f26a21b3f5e0e9df4c20a",
+ "5a4bfeab6166427c7a3647b747292b83 84537cdb89afb3bf5665e4c5e709350b 287baec921fd7ca0ee7a0c31d022a95e 1fc92ba9d77df883960275beb4e62024"
+ }},
+
+ {"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaa",
+ "dddddddddddddddddddddddddddddddd dddddddddddddddddddddddddddddddd dddddddddddddddddddddddddddddddd dddd",
+ {"676cfc7d16153638780390692be142d2 df7ce924b909c0c08dbfdc1a",
+ "84ec79124a27107865cedd8bd82da996 5e5ed8c37b0ac98005a7f39ed58a4207",
+ "275cd0e661bb8b151c64d288f1f782fb 91a8abd56858d72babb2d476f0458373 b41b6ab5bf174bec422e53fc3135ac6e",
+ "309e99f9ec075ec6c6d475eda1180687 fcf1531195802a99b5677449a8625182 851cb332afb6a89c411325fbcbcd42af cb7b6e5aab7ea42c660f97fd8584bf03"
+ }},
+
+ {"0102030405060708090a0b0c0d0e0f10 111213141516171819",
+ "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd cdcd",
+ {"a9d7685a19c4e0dbd9df2556cc8a7d2a 7733b67625ce594c78270eeb",
+ "57366a45e2305321a4bc5aa5fe2ef8a9 21f6af8273d7fe7be6cfedb3f0aea6d7",
+ "3a5d7a879702c086bc96d1dd8aa15d9c 46446b95521311c606fdc4e308f4b984 da2d0f9449b3ba8425ec7fb8c31bc136",
+ "b27eab1d6e8d87461c29f7f5739dd58e 98aa35f8e823ad38c5492a2088fa0281 993bbfff9a0e9c6bf121ae9ec9bb09d8 4a5ebac817182ea974673fb133ca0d1d"
+ }},
+
+ %% {"0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c 0c0c0c0c",
+ %% "546573742057697468205472756e6361 74696f6e",
+ %% {"49fdd3abd005ebb8ae63fea946d1883c",
+ %% "6e02c64537fb118057abb7fb66a23b3c",
+ %% "47c51ace1ffacffd7494724682615783",
+ %% "0fa7475948f43f48ca0516671e18978c"
+ %% }},
+
+ {"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaa",
+ "54657374205573696e67204c61726765 72205468616e20426c6f636b2d53697a 65204b6579202d2048617368204b6579 204669727374",
+ {"b4a1f04c00287a9b7f6075b313d279b8 33bc8f75124352d05fb9995f",
+ "ed73a374b96c005235f948032f09674a 58c0ce555cfc1f223b02356560312c3b",
+ "0fc19513bf6bd878037016706a0e57bc 528139836b9a42c3d419e498e0e1fb96 16fd669138d33a1105e07c72b6953bcc",
+ "00f751a9e50695b090ed6911a4b65524 951cdc15a73a5d58bb55215ea2cd839a c79d2b44a39bafab27e83fde9e11f634 0b11d991b1b91bf2eee7fc872426c3a4"
+ }},
+
+ {"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaa",
+ "54657374205573696e67204c61726765 72205468616e20426c6f636b2d53697a 65204b6579202d2048617368204b6579 204669727374",
+ {
+ "b96d730c148c2daad8649d83defaa371 9738d34775397b7571c38515",
+ "a6072f86de52b38bb349fe84cd6d97fb 6a37c4c0f62aae93981193a7229d3467",
+ "713dff0302c85086ec5ad0768dd65a13 ddd79068d8d4c6212b712e4164944911 1480230044185a99103ed82004ddbfcc",
+ "b14835c819a290efb010ace6d8568dc6 b84de60bc49b004c3b13eda763589451 e5dd74292884d1bdce64e6b919dd61dc 9c56a282a81c0bd14f1f365b49b83a5b"
+ }},
+
+ {"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaa",
+ "54686973206973206120746573742075 73696e672061206c6172676572207468 616e20626c6f636b2d73697a65206b65 7920616e642061206c61726765722074 68616e20626c6f636b2d73697a652064 6174612e20546865206b6579206e6565 647320746f2062652068617368656420 6265666f7265206265696e6720757365 642062792074686520484d414320616c 676f726974686d2e",
+ {
+ "05d8cd6d00faea8d1eb68ade28730bbd 3cbab6929f0a086b29cd62a0",
+ "65c5b06d4c3de32a7aef8763261e49ad b6e2293ec8e7c61e8de61701fc63e123",
+ "026fdf6b50741e373899c9f7d5406d4e b09fc6665636fc1a530029ddf5cf3ca5 a900edce01f5f61e2f408cdf2fd3e7e8",
+ "38a456a004bd10d32c9ab83366841128 62c3db61adcca31829355eaf46fd5c73 d06a1f0d13fec9a652fb3811b577b1b1 d1b9789f97ae5b83c6f44dfcf1d67eba"
+ }},
+
+ {"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaa",
+ "54686973206973206120746573742075 73696e672061206c6172676572207468 616e20626c6f636b2d73697a65206b65 7920616e642061206c61726765722074 68616e20626c6f636b2d73697a652064 6174612e20546865206b6579206e6565 647320746f2062652068617368656420 6265666f7265206265696e6720757365 642062792074686520484d414320616c 676f726974686d2e",
+ {
+ "c79c9b093424e588a9878bbcb089e018 270096e9b4b1a9e8220c866a",
+ "e6a36d9b915f86a093cac7d110e9e04c f1d6100d30475509c2475f571b758b5a",
+ "cad18a8ff6c4cc3ad487b95f9769e9b6 1c062aefd6952569e6e6421897054cfc 70b5fdc6605c18457112fc6aaad45585",
+ "dc030ee7887034f32cf402df34622f31 1f3e6cf04860c6bbd7fa488674782b46 59fdbdf3fd877852885cfe6e22185fe7 b2ee952043629bc9d5f3298a41d02c66"
+ }}
+ %%,
+
+ %% {"4a656665",
+ %% "'11001' or LSB 13 or MSB c8",
+ %% {
+ %% "5f8c0ea7fafecd0c3463aad09742cece b142fe0ab6f4539438c59de8",
+ %% "ec8222773fac68b3d3dcb182aec8b050 7ace4448d20a1147e682118da4e3f44c",
+ %% "21fbd3bf3ebba3cfc9ef64c0591c92c5 acb265e92d8761d1f91a52a103a6c796 94cfd67a9a2ac1324f02fea63b81effc",
+ %% "27f9388c1567ef4ef200602a6cf871d6 8a6fb048d4737ac4418a2f021289d13d 1fd1120fecb9cf964c5b117ab5b11c61 4b2da39dadd51f2f5e22aaccec7d576e"
+ %% }}
+ ].
+
+
+
rfc_4634_test1() ->
<<"abc">>.
rfc_4634_test2_1() ->
@@ -2069,6 +2338,13 @@ aes_gcm(Config) ->
"gcmEncryptExtIV192.rsp",
"gcmEncryptExtIV256.rsp"]).
+aes_ccm(Config) ->
+ read_rsp(Config, aes_ccm,
+ ["VADT128.rsp", "VADT192.rsp", "VADT256.rsp",
+ "VNT128.rsp", "VNT192.rsp", "VNT256.rsp",
+ "VPT128.rsp", "VPT192.rsp", "VPT256.rsp"
+ ]).
+
%% https://tools.ietf.org/html/rfc7539#appendix-A.5
chacha20_poly1305() ->
[
@@ -2111,9 +2387,108 @@ chacha20_poly1305() ->
"49e617d91d361094fa68f0ff77987130"
"305beaba2eda04df997b714d6c6f2c29"
"a6ad5cb4022b02709b"),
- hexstr2bin("eead9d67890cbb22392336fea1851f38")} %% CipherTag
+ hexstr2bin("eead9d67890cbb22392336fea1851f38"), %% CipherTag
+ no_info
+ }
].
+
+chacha20() ->
+%%% chacha20 (no mode) test vectors from RFC 7539 A.2
+ [
+ %% Test Vector #1:
+ {chacha20,
+ hexstr2bin("00000000000000000000000000000000"
+ "00000000000000000000000000000000"), %% Key
+ hexstr2bin("00000000" % Initial counter = 0, little-endian
+ "000000000000000000000000"), %% IV
+ hexstr2bin("00000000000000000000000000000000" %% PlainText
+ "00000000000000000000000000000000"
+ "00000000000000000000000000000000"
+ "00000000000000000000000000000000"),
+ hexstr2bin("76b8e0ada0f13d90405d6ae55386bd28" %% CipherText
+ "bdd219b8a08ded1aa836efcc8b770dc7"
+ "da41597c5157488d7724e03fb8d84a37"
+ "6a43b8f41518a11cc387b669b2ee6586")},
+ %% Test Vector #2:
+ {chacha20,
+ hexstr2bin("00000000000000000000000000000000"
+ "00000000000000000000000000000001"), %% Key
+ hexstr2bin("01000000" % Initial counter = 1, little-endian
+ "000000000000000000000002"), %% IV
+ hexstr2bin("416e79207375626d697373696f6e2074" %% PlainText
+ "6f20746865204945544620696e74656e"
+ "6465642062792074686520436f6e7472"
+ "696275746f7220666f72207075626c69"
+ "636174696f6e20617320616c6c206f72"
+ "2070617274206f6620616e2049455446"
+ "20496e7465726e65742d447261667420"
+ "6f722052464320616e6420616e792073"
+ "746174656d656e74206d616465207769"
+ "7468696e2074686520636f6e74657874"
+ "206f6620616e20494554462061637469"
+ "7669747920697320636f6e7369646572"
+ "656420616e20224945544620436f6e74"
+ "7269627574696f6e222e205375636820"
+ "73746174656d656e747320696e636c75"
+ "6465206f72616c2073746174656d656e"
+ "747320696e2049455446207365737369"
+ "6f6e732c2061732077656c6c20617320"
+ "7772697474656e20616e6420656c6563"
+ "74726f6e696320636f6d6d756e696361"
+ "74696f6e73206d61646520617420616e"
+ "792074696d65206f7220706c6163652c"
+ "20776869636820617265206164647265"
+ "7373656420746f"),
+ hexstr2bin("a3fbf07df3fa2fde4f376ca23e827370" %% CipherText
+ "41605d9f4f4f57bd8cff2c1d4b7955ec"
+ "2a97948bd3722915c8f3d337f7d37005"
+ "0e9e96d647b7c39f56e031ca5eb6250d"
+ "4042e02785ececfa4b4bb5e8ead0440e"
+ "20b6e8db09d881a7c6132f420e527950"
+ "42bdfa7773d8a9051447b3291ce1411c"
+ "680465552aa6c405b7764d5e87bea85a"
+ "d00f8449ed8f72d0d662ab052691ca66"
+ "424bc86d2df80ea41f43abf937d3259d"
+ "c4b2d0dfb48a6c9139ddd7f76966e928"
+ "e635553ba76c5c879d7b35d49eb2e62b"
+ "0871cdac638939e25e8a1e0ef9d5280f"
+ "a8ca328b351c3c765989cbcf3daa8b6c"
+ "cc3aaf9f3979c92b3720fc88dc95ed84"
+ "a1be059c6499b9fda236e7e818b04b0b"
+ "c39c1e876b193bfe5569753f88128cc0"
+ "8aaa9b63d1a16f80ef2554d7189c411f"
+ "5869ca52c5b83fa36ff216b9c1d30062"
+ "bebcfd2dc5bce0911934fda79a86f6e6"
+ "98ced759c3ff9b6477338f3da4f9cd85"
+ "14ea9982ccafb341b2384dd902f3d1ab"
+ "7ac61dd29c6f21ba5b862f3730e37cfd"
+ "c4fd806c22f221")},
+ %%Test Vector #3:
+ {chacha20,
+ hexstr2bin("1c9240a5eb55d38af333888604f6b5f0"
+ "473917c1402b80099dca5cbc207075c0"), %% Key
+ hexstr2bin("2a000000" % Initial counter = 42 (decimal), little-endian
+ "000000000000000000000002"), %% IV
+ hexstr2bin("2754776173206272696c6c69672c2061" %% PlainText
+ "6e642074686520736c6974687920746f"
+ "7665730a446964206779726520616e64"
+ "2067696d626c6520696e207468652077"
+ "6162653a0a416c6c206d696d73792077"
+ "6572652074686520626f726f676f7665"
+ "732c0a416e6420746865206d6f6d6520"
+ "7261746873206f757467726162652e"),
+ hexstr2bin("62e6347f95ed87a45ffae7426f27a1df" %% CipherText
+ "5fb69110044c0d73118effa95b01e5cf"
+ "166d3df2d721caf9b21e5fb14c616871"
+ "fd84c54f9d65b283196c7fe4f60553eb"
+ "f39c6402c42234e32a356b3e764312a6"
+ "1a5532055716ead6962568f87d3f3f77"
+ "04c6a8d1bcd1bf4d50d6154b6da731b1"
+ "87b58dfd728afa36757a797ac188d1")}
+ ].
+
+
rsa_plain() ->
<<"7896345786348756234 Hejsan Svejsan, erlang crypto debugger"
"09812312908312378623487263487623412039812 huagasd">>.
@@ -2309,7 +2684,9 @@ srp(ClientPrivate, Generator, Prime, Version, Verifier, ServerPublic, ServerPriv
SessionKey}.
ecdh() ->
%% http://csrc.nist.gov/groups/STM/cavp/
- Curves = crypto:ec_curves(),
+ Curves = crypto:ec_curves() ++
+ [X || X <- proplists:get_value(curves, crypto:supports(), []),
+ lists:member(X, [x25519,x448])],
TestCases =
[{ecdh, hexstr2point("42ea6dd9969dd2a61fea1aac7f8e98edcc896c6e55857cc0", "dfbe5d7c61fac88b11811bde328e8a0d12bf01a9d204b523"),
hexstr2bin("f17d3fea367b74d340851ca4270dcb24c271f445bed9d527"),
@@ -2392,7 +2769,32 @@ ecdh() ->
"2FDC313095BCDD5FB3A91636F07A959C8E86B5636A1E930E8396049CB481961D365CC11453A06C719835475B12CB52FC3C383BCE35E27EF194512B71876285FA"),
hexstr2bin("16302FF0DBBB5A8D733DAB7141C1B45ACBC8715939677F6A56850A38BD87BD59B09E80279609FF333EB9D4C061231FB26F92EEB04982A5F1D1764CAD57665422"),
brainpoolP512r1,
- hexstr2bin("A7927098655F1F9976FA50A9D566865DC530331846381C87256BAF3226244B76D36403C024D7BBF0AA0803EAFF405D3D24F11A9B5C0BEF679FE1454B21C4CD1F")}],
+ hexstr2bin("A7927098655F1F9976FA50A9D566865DC530331846381C87256BAF3226244B76D36403C024D7BBF0AA0803EAFF405D3D24F11A9B5C0BEF679FE1454B21C4CD1F")},
+
+ %% RFC 7748, 6.1
+ {ecdh,
+ 16#8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a,
+ 16#5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb,
+ x25519,
+ hexstr2bin("4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742")},
+ {ecdh,
+ 16#de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f,
+ 16#77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a,
+ x25519,
+ hexstr2bin("4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742")},
+
+ %% RFC 7748, 6.2
+ {ecdh,
+ 16#9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0,
+ 16#1c306a7ac2a0e2e0990b294470cba339e6453772b075811d8fad0d1d6927c120bb5ee8972b0d3e21374c9c921b09d1b0366f10b65173992d,
+ x448,
+ hexstr2bin("07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b56fd2464c335543936521c24403085d59a449a5037514a879d")},
+ {ecdh,
+ 16#3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b43027d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609,
+ 16#9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b,
+ x448,
+ hexstr2bin("07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b56fd2464c335543936521c24403085d59a449a5037514a879d")}
+ ],
lists:filter(fun ({_Type, _Pub, _Priv, Curve, _SharedSecret}) ->
lists:member(Curve, Curves)
end,
@@ -2523,29 +2925,36 @@ read_rsp(Config, Type, Files) ->
Tests =
lists:foldl(
fun(FileName, Acc) ->
- read_rsp_file(filename:join(datadir(Config), FileName),
- Type, Acc)
+ NewAcc = read_rsp_file(filename:join(datadir(Config), FileName),
+ Type, Acc),
+ ct:log("~p: ~p tests read.~n",[FileName,length(NewAcc)-length(Acc)]),
+ NewAcc
end, [], Files),
log_rsp_size(Type, Tests),
Tests.
read_rsp_file(FileName, Type, Acc) ->
- {ok, Raw} = file:read_file(FileName),
- Split = binary:split(Raw, [<<"\r">>, <<"\n">>], [global, trim_all]),
- parse_rsp(Type, Split, Acc).
+ case file:read_file(FileName) of
+ {ok, Raw} ->
+ Split = binary:split(Raw, [<<"\r">>, <<"\n">>], [global, trim_all]),
+ parse_rsp(Type, Split, #{file => FileName}, Acc);
+ Other ->
+ ct:fail("~p ~p",[FileName, Other])
+ end.
-parse_rsp(_Type, [], Acc) ->
+parse_rsp(_Type, [], _State, Acc) ->
Acc;
-parse_rsp(_Type, [<<"DECRYPT">>|_], Acc) ->
+parse_rsp(_Type, [<<"DECRYPT">>|_], _State, Acc) ->
Acc;
%% AES format
parse_rsp(Type, [<<"COUNT = ", _/binary>>,
<<"KEY = ", Key/binary>>,
<<"IV = ", IV/binary>>,
<<"PLAINTEXT = ", PlainText/binary>>,
- <<"CIPHERTEXT = ", CipherText/binary>>|Next], Acc) ->
- parse_rsp(Type, Next, [{Type, hexstr2bin(Key), hexstr2bin(IV),
- hexstr2bin(PlainText), hexstr2bin(CipherText)}|Acc]);
+ <<"CIPHERTEXT = ", CipherText/binary>>|Next], State, Acc) ->
+ parse_rsp(Type, Next, State,
+ [{Type, hexstr2bin(Key), hexstr2bin(IV),
+ hexstr2bin(PlainText), hexstr2bin(CipherText)}|Acc]);
%% CMAC format
parse_rsp(Type, [<<"Count = ", _/binary>>,
<<"Klen = ", _/binary>>,
@@ -2553,23 +2962,23 @@ parse_rsp(Type, [<<"Count = ", _/binary>>,
<<"Tlen = ", Tlen/binary>>,
<<"Key = ", Key/binary>>,
<<"Msg = ", Msg/binary>>,
- <<"Mac = ", MAC/binary>>|Rest], Acc) ->
+ <<"Mac = ", MAC/binary>>|Rest], State, Acc) ->
case Rest of
[<<"Result = P">>|Next] ->
- parse_rsp_cmac(Type, Key, Msg, Mlen, Tlen, MAC, Next, Acc);
+ parse_rsp_cmac(Type, Key, Msg, Mlen, Tlen, MAC, Next, State, Acc);
[<<"Result = ", _/binary>>|Next] ->
- parse_rsp(Type, Next, Acc);
+ parse_rsp(Type, Next, State, Acc);
_ ->
- parse_rsp_cmac(Type, Key, Msg, Mlen, Tlen, MAC, Rest, Acc)
+ parse_rsp_cmac(Type, Key, Msg, Mlen, Tlen, MAC, Rest, State, Acc)
end;
%% GCM format decode format
-parse_rsp(Type, [<<"Count = ", _/binary>>,
+parse_rsp(Type, [<<"Count = ", Count/binary>>,
<<"Key = ", Key/binary>>,
<<"IV = ", IV/binary>>,
<<"CT = ", CipherText/binary>>,
<<"AAD = ", AAD/binary>>,
<<"Tag = ", CipherTag0/binary>>,
- <<"PT = ", PlainText/binary>>|Next], Acc) ->
+ <<"PT = ", PlainText/binary>>|Next], #{file:=File}=State, Acc) ->
CipherTag = hexstr2bin(CipherTag0),
TestCase = {Type,
hexstr2bin(Key),
@@ -2578,16 +2987,17 @@ parse_rsp(Type, [<<"Count = ", _/binary>>,
hexstr2bin(AAD),
hexstr2bin(CipherText),
CipherTag,
- size(CipherTag)},
- parse_rsp(Type, Next, [TestCase|Acc]);
+ size(CipherTag),
+ {File,decstr2int(Count)}},
+ parse_rsp(Type, Next, State, [TestCase|Acc]);
%% GCM format encode format
-parse_rsp(Type, [<<"Count = ", _/binary>>,
+parse_rsp(Type, [<<"Count = ", Count/binary>>,
<<"Key = ", Key/binary>>,
<<"IV = ", IV/binary>>,
<<"PT = ", PlainText/binary>>,
<<"AAD = ", AAD/binary>>,
<<"CT = ", CipherText/binary>>,
- <<"Tag = ", CipherTag0/binary>>|Next], Acc) ->
+ <<"Tag = ", CipherTag0/binary>>|Next], #{file:=File}=State, Acc) ->
CipherTag = hexstr2bin(CipherTag0),
TestCase = {Type,
hexstr2bin(Key),
@@ -2596,13 +3006,88 @@ parse_rsp(Type, [<<"Count = ", _/binary>>,
hexstr2bin(AAD),
hexstr2bin(CipherText),
CipherTag,
- size(CipherTag)},
- parse_rsp(Type, Next, [TestCase|Acc]);
+ size(CipherTag),
+ {File,decstr2int(Count)}},
+ parse_rsp(Type, Next, State, [TestCase|Acc]);
+%% CCM-VADT format
+parse_rsp(Type, [<<"[Alen = ", AlenB0/binary>>|Next], State0, Acc) ->
+ AlenSize = size(AlenB0) - 1, % remove closing ']'
+ Alen = decstr2int(<<AlenB0:AlenSize/binary>>),
+ State = State0#{alen => Alen},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type, [<<"[Nlen = ", NlenB0/binary>>|Next], State0, Acc) ->
+ NlenSize = size(NlenB0) - 1, % remove closing ']'
+ Nlen = decstr2int(<<NlenB0:NlenSize/binary>>),
+ State = State0#{nlen => Nlen},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type, [<<"[Plen = ", PlenB0/binary>>|Next], State0, Acc) ->
+ PlenSize = size(PlenB0) - 1, % remove closing ']'
+ Plen = decstr2int(<<PlenB0:PlenSize/binary>>),
+ State = State0#{plen => Plen},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type, [<<"[Tlen = ", TlenB0/binary>>|Next], State0, Acc) ->
+ TlenSize = size(TlenB0) - 1, % remove closing ']'
+ Tlen = decstr2int(<<TlenB0:TlenSize/binary>>),
+ State = State0#{tlen => Tlen},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type, [<<"Alen = ", B/binary>>|Next], State0, Acc) ->
+ State = State0#{alen => decstr2int(B)},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type, [<<"Plen = ", B/binary>>|Next], State0, Acc) ->
+ State = State0#{plen => decstr2int(B)},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type, [<<"Count = ", B/binary>>|Next], State0, Acc) ->
+ State = State0#{count => B},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type, [<<"Nlen = ", B/binary>>|Next], State0, Acc) ->
+ State = State0#{nlen => decstr2int(B)},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type, [<<"Tlen = ", B/binary>>|Next], State0, Acc) ->
+ State = State0#{tlen => decstr2int(B)},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type, [<<"Key = ",Key/binary>>|Next], State0, Acc) ->
+ State = State0#{key => hexstr2bin(Key)},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type, [<<"Nonce = ",Nonce/binary>>|Next], State0, Acc) ->
+ State = State0#{nonce => hexstr2bin(Nonce)},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type, [<<"Adata = ",Adata/binary>>|Next], State0, Acc) ->
+ State = State0#{adata => hexstr2bin(Adata)},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type, [<<"Payload = ",Payload/binary>>|Next], State0, Acc) ->
+ State = State0#{payload => hexstr2bin(Payload)},
+ parse_rsp(Type, Next, State, Acc);
+parse_rsp(Type,
+ [<<"CT = ", CT/binary>>|Next],
+ #{count := Count,
+ file := File,
+ alen := Alen,
+ plen := Plen,
+ nlen := Nlen,
+ tlen := Tlen,
+ key := Key,
+ nonce := IV,
+ adata := Adata,
+ payload := Payload
+ } = State, Acc) ->
+ AAD = <<Adata:Alen/binary>>,
+ PlainText = <<Payload:Plen/binary>>,
+ <<CipherText:Plen/binary, CipherTag:Tlen/binary>> = hexstr2bin(CT),
+ TestCase = {Type,
+ Key,
+ PlainText,
+ IV,
+ AAD,
+ CipherText,
+ CipherTag,
+ Tlen,
+ {File,decstr2int(Count)}},
+ parse_rsp(Type, Next, State, [TestCase|Acc]);
+parse_rsp(Type, [_|Next], State, Acc) ->
+ parse_rsp(Type, Next, State, Acc).
-parse_rsp(Type, [_|Next], Acc) ->
- parse_rsp(Type, Next, Acc).
-parse_rsp_cmac(Type, Key0, Msg0, Mlen0, Tlen, MAC0, Next, Acc) ->
+parse_rsp_cmac(Type, Key0, Msg0, Mlen0, Tlen, MAC0, Next, State, Acc) ->
Key = hexstr2bin(Key0),
Mlen = binary_to_integer(Mlen0),
<<Msg:Mlen/bytes, _/binary>> = hexstr2bin(Msg0),
@@ -2610,9 +3095,9 @@ parse_rsp_cmac(Type, Key0, Msg0, Mlen0, Tlen, MAC0, Next, Acc) ->
case binary_to_integer(Tlen) of
0 ->
- parse_rsp(Type, Next, [{Type, Key, Msg, MAC}|Acc]);
+ parse_rsp(Type, Next, State, [{Type, Key, Msg, MAC}|Acc]);
I ->
- parse_rsp(Type, Next, [{Type, Key, Msg, I, MAC}|Acc])
+ parse_rsp(Type, Next, State, [{Type, Key, Msg, I, MAC}|Acc])
end.
api_errors_ecdh(Config) when is_list(Config) ->
diff --git a/lib/crypto/test/crypto_SUITE_data/VADT128.rsp b/lib/crypto/test/crypto_SUITE_data/VADT128.rsp
new file mode 100644
index 0000000000..a4fe9130a0
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/VADT128.rsp
@@ -0,0 +1,1823 @@
+# CAVS 11.0
+# "CCM-VADT" information
+# AES Keylen: 128
+# Generated on Tue Mar 15 08:09:24 2011
+
+Plen = 24
+Nlen = 13
+Tlen = 16
+
+[Alen = 0]
+
+Key = d24a3d3dde8c84830280cb87abad0bb3
+Nonce = f1100035bb24a8d26004e0e24b
+
+Count = 0
+Adata = 00
+Payload = 7c86135ed9c2a515aaae0e9a208133897269220f30870006
+CT = 1faeb0ee2ca2cd52f0aa3966578344f24e69b742c4ab37ab1123301219c70599b7c373ad4b3ad67b
+
+Count = 1
+Adata = 00
+Payload = 48df73208cdc63d716752df7794807b1b2a80794a2433455
+CT = 2bf7d09079bc0b904c711a0b0e4a70ca8ea892d9566f03f8b77a140819f39ef045103e785e1df8c2
+
+Count = 2
+Adata = 00
+Payload = b99de8168e8c13ea4aef66bdb93133dff5d57e9837ff6ccb
+CT = dab54ba67bec7bad10eb5141ce3344a4c9d5ebd5c3d35b664b01098842a618390619b86e00850b2e
+
+Count = 3
+Adata = 00
+Payload = 09fc21ac4a1f43de29621cacf3ad84e055c6b220721af7ce
+CT = 6ad4821cbf7f2b9973662b5084aff39b69c6276d8636c0638bd518724ab84fb814fe7b5570769f7f
+
+Count = 4
+Adata = 00
+Payload = cb43320d7488dfd6eed9efd88f440ea3f6f77a0df09d0727
+CT = a86b91bd81e8b791b4ddd824f84679d8caf7ef4004b1308a7229cbcecef221570cee8345b38cd6ec
+
+Count = 5
+Adata = 00
+Payload = a350ed58c04473e113b9088b1fb9dad92807f6b63b0d690c
+CT = c0784ee835241ba649bd3f7768bbada2140763fbcf215ea1fee47fec27d7764e5e2819c850088bac
+
+Count = 6
+Adata = 00
+Payload = 0709e691faf41383fab5d1848a8eee77101d1c99e526a264
+CT = 642145210f947bc4a0b1e678fd8c990c2c1d89d4110a95c954d610bc1ab4bc9a8a28c7306f7c539e
+
+Count = 7
+Adata = 00
+Payload = e7b913c2f0630562eb1c16b3b1ed84090c011a15c09e5471
+CT = 8491b07205036d25b118214fc6eff37230018f5834b263dc2e31657ecc51f5ec8590482fc053230d
+
+Count = 8
+Adata = 00
+Payload = 6b909697074900d41ce8c7d559b229af11fb3cec334784d4
+CT = 08b83527f229689346ecf0292eb05ed42dfba9a1c76bb379d500827f2081b00397102f90fc9ccd88
+
+Count = 9
+Adata = 00
+Payload = 495ff03335bcb39a317b9ea3f8bb6306fa771f3c55adebce
+CT = 2a775383c0dcdbdd6b7fa95f8fb9147dc6778a71a181dc63e2e7997803029476598c0e8d4fc63857
+
+[Alen = 1]
+
+Key = 08b0da255d2083808a1b4d367090bacc
+Nonce = 777828b13679a9e2ca89568233
+
+Count = 10
+Adata = dd
+Payload = 1b156d7e2bf7c9a25ad91cff7b0b02161cb78ff9162286b0
+CT = e8b80af4960d5417c15726406e345c5c46831192b03432eed16b6282283e16602331bcca9d51ce76
+
+Count = 11
+Adata = c5
+Payload = 032fee9dbffccc751e6a1ee6d07bb218b3a7ec6bf5740ead
+CT = f0828917020651c085e42459c544ec52e99372005362baf308ebeed45f67ef8733737c9c6f82daad
+
+Count = 12
+Adata = 68
+Payload = 9c4cd65b92070bc382fd18146611defb4204acddfdf6b276
+CT = 6fe1b1d12ffd9676197322ab732e80b1183032b65be00628f9b477e3a23bfdfdb619c7bc531fbcce
+
+Count = 13
+Adata = be
+Payload = 2ff93ef2fc5fe2c297ace05f3f7585aed75ef90ade3acf89
+CT = dc54597841a57f770c22dae02a4adbe48d6a6761782c7bd7aa82130f5a86c0cd0433585e5c208cf7
+
+Count = 14
+Adata = 7a
+Payload = 62766e9acd41285eeed9b4007340dbb611699624274ad117
+CT = 91db091070bbb5eb75578ebf667f85fc4b5d084f815c65499d60012a2f25463e036ceecea57b3c97
+
+Count = 15
+Adata = 13
+Payload = ea689c268a04912d0527b16d9d9406df38302fb11cb64a99
+CT = 19c5fbac37fe0c989ea98bd288ab58956204b1dabaa0fec7e337897c90eb260729a729aed1c8a244
+
+Count = 16
+Adata = e5
+Payload = f31e35953beb211efcce487ba8c0cd1a8446343d5851b9fd
+CT = 00b3521f8611bcab674072c4bdff9350de72aa56fe470da373dc2911c75b37cd995481d42b04524a
+
+Count = 17
+Adata = e3
+Payload = c4ac3c645387584c2a95b1f16b8317730592924dd831a388
+CT = 37015beeee7dc5f9b11b8b4e7ebc49395fa60c267e2717d684f76ecf3dc5f3307ce982f185321248
+
+Count = 18
+Adata = d5
+Payload = 81af394c2ea3a85e1ea954596e3772f01635d007794c0b19
+CT = 72025ec6935935eb85276ee67b082cba4c014e6cdf5abf472c38d0fe4e4eba054c1420c39a3dcc61
+
+Count = 19
+Adata = ed
+Payload = e013a2edd5b86bab8df5c9940d0a0c864478c1ad42668304
+CT = 13bec5676842f61e167bf32b183552cc1e4c5fc6e470375a7cfa6c9945f5aee3c799eee37b0605db
+
+[Alen = 2]
+
+Key = 1538cc03b60880bf3e7d388e29f27739
+Nonce = 9e734de325026b5d7128193973
+
+Count = 20
+Adata = c93c
+Payload = e7b819a853ffe79baaa72097ff0d04f02640ae62bcfd3da5
+CT = 1d8f42f9730424fa27240bd6277f4882604f440324b11b003ca01d874439b4e1f79a26d8c6dc433a
+
+Count = 21
+Adata = 4cf9
+Payload = dc6cf325ed6d968efba9f57e48a58f4578cc3540fe121ba2
+CT = 265ba874cd9655ef762ade3f90d7c3373ec3df21665e3d07b40653cd23afc7cc7a31fa13ba8f4e49
+
+Count = 22
+Adata = b469
+Payload = 22ab6a0daf953165dda864cceeeb782e275c0b072aedd284
+CT = d89c315c8f6ef204502b4f8d3699345c6153e166b2a1f421c8c10aaf90b1116be216f912c82ca96a
+
+Count = 23
+Adata = cf6b
+Payload = a35f62a431fee63468dc02fdf7bef78d3a5937de56151939
+CT = 596839f511052555e55f29bc2fccbbff7c56ddbfce593f9c2f568ef41324189fb3644edcd76dc19c
+
+Count = 24
+Adata = af7c
+Payload = 548840cb0400824af809fb68447500b77e977128200d3b81
+CT = aebf1b9a24fb412b758ad0299c074cc538989b49b8411d242548c244a875d3681d715db3da19962f
+
+Count = 25
+Adata = 61dc
+Payload = 440b6095c77495e73fff54c785b7ceb5eb358731c213ffcd
+CT = be3c3bc4e78f5686b27c7f865dc582c7ad3a6d505a5fd968b599bc8927ad8d43067807f4b858f854
+
+Count = 26
+Adata = b97e
+Payload = 50c59ca54eb64575b82b13c6dac96488af369e9f5f86cdf2
+CT = aaf2c7f46e4d861435a8388702bb28fae93974fec7caeb577454774ee78f76e555cf743df340381e
+
+Count = 27
+Adata = 57ab
+Payload = 21b8eb1f0bda26ca36167ce7bc2e796818bf11fc8c192885
+CT = db8fb04e2b21e5abbb9557a6645c351a5eb0fb9d14550e20e0a22a5ee031978271c7dd2a0d4e7018
+
+Count = 28
+Adata = 5f9c
+Payload = b4d84fb1e81e18c89391a7a59fc05fedaf160e0d0d027a7c
+CT = 4eef14e0c8e5dba91e128ce447b2139fe919e46c954e5cd99a242ebae5c6da57ee38e5c227c46b32
+
+Count = 29
+Adata = e0c4
+Payload = 54dc5a0e1b67577cda4e7dbd48b769c120c1d13dd567cfad
+CT = aeeb015f3b9c941d57cd56fc90c525b366ce3b5c4d2be908a5f8a92f4201c4658289307167cee810
+
+[Alen = 3]
+
+Key = f149e41d848f59276cfddd743bafa9a9
+Nonce = 14b756d66fc51134e203d1c6f9
+
+Count = 30
+Adata = f5827e
+Payload = 9759e6f21f5a588010f57e6d6eae178d8b20ab59cda66f42
+CT = f634bf00f1f9f1f93f41049d7f3797b05e805f0b14850f4e78e2a23411147a6187da6818506232ee
+
+Count = 31
+Adata = e9699b
+Payload = 1555bc87d6c688fd221a2c75cd1e4dd1c1693207ac421d24
+CT = 7438e575386521840dae5685dc87cdec14c9c65575617d28f10835db9897b7528e3204fe3a81424f
+
+Count = 32
+Adata = 972896
+Payload = b72b2a080d92f3f3bb7d96222982de82a28c9eebaddba247
+CT = d64673fae3315a8a94c9ecd2381b5ebf772c6ab974f8c24b3efa05ba4a73ec2234461d459f54acd2
+
+Count = 33
+Adata = 3053f3
+Payload = b5417ed6933ffe2b57ea601d77e97eb12fa1fb8fdc06c86f
+CT = d42c27247d9c5752785e1aed6670fe8cfa010fdd0525a863b557537c6525e827750917a1ed49602f
+
+Count = 34
+Adata = 24db75
+Payload = 4e7f42666035a00e62783283c54b027603917685d27326bc
+CT = 2f121b948e9609774dcc4873d4d2824bd63182d70b5046b0dfd06b037e9094f120eb3d8649d48918
+
+Count = 35
+Adata = ff27a4
+Payload = 7bf180699c294421ad9565cacc27227a4b3a7cf9637290c6
+CT = 1a9cd99b728aed5882211f3addbea2479e9a88abba51f0cabfa8cfabbd79b3e3210482e6f3822fee
+
+Count = 36
+Adata = 77ec24
+Payload = 3d47071c13f994cb42fb2887e5c6e53a542be7ddad9779e0
+CT = 5c2a5eeefd5a3db26d4f5277f45f6507818b138f74b419ec3b9575e347051e98d0c8646ad46318e6
+
+Count = 37
+Adata = 6d7748
+Payload = 317d5da0a2ec12c3b96c83dd61cc955242a9c1c640e2b92f
+CT = 501004524c4fbbba96d8f92d7055156f9709359499c1d92378e7af65eb0388ae7a52f58f6ba32109
+
+Count = 38
+Adata = 029674
+Payload = c9bb21306ee1b4a6c4fa5443af2e181716993cbb374e177c
+CT = a8d678c280421ddfeb4e2eb3beb7982ac339c8e9ee6d77708019fa97ff70d4d21c0bd83caa434b3a
+
+Count = 39
+Adata = 60dfe8
+Payload = 44eb7edd6bee501ad97873aa7ecbf7ed8b613760d7c95e15
+CT = 2586272f854df963f6cc095a6f5277d05ec1c3320eea3e191814ed48a21d97ea02e86d7e6e8834cb
+
+[Alen = 4]
+
+Key = 9a57a22c7f26feff8ca6cceff214e4c2
+Nonce = 88f30fd2b04fb8ddbce8fc26e6
+
+Count = 40
+Adata = a95bdff6
+Payload = 035c516776c706a7dd5f181fa6aa891b04dd423042ea0667
+CT = b92f7ec2ebecebdbd2977b3874e61bf496a382153b2529fc9b6443a35f329b2068916fb6ab8227eb
+
+Count = 41
+Adata = d2672cbb
+Payload = 3ba306bcec94615c347f990b62841a16df7b321f113f1714
+CT = 81d0291971bf8c203bb7fa2cb0c888f94d05f23a68f0388f19e2aa492ce9ddfb6de0ab7a447f5351
+
+Count = 42
+Adata = 737f4d00
+Payload = 68313a29ace3efe521c3ca1e5bac8e98d6b4434c80a7dc74
+CT = d242158c31c802992e0ba93989e01c7744ca8369f968f3ef2bf683b1209f104e82ba39f7c62cd666
+
+Count = 43
+Adata = 3610b1ae
+Payload = 963bfe556138317bebe3936b18a2c1dd100dc73be6fde556
+CT = 2c48d1f0fc13dc07e42bf04ccaee53328273071e9f32cacd4fc7d5cac043f182edbe5c2658f73092
+
+Count = 44
+Adata = f1aa7f72
+Payload = 52d5c53ee4f23cb050a95db54112b44033c34ac31de96be8
+CT = e8a6ea9b79d9d1cc5f613e92935e26afa1bd8ae664264473b8234f3fbaca3dc2c497418219151b05
+
+Count = 45
+Adata = 6b1013aa
+Payload = a302aebc0f8fd61badc8371991beacf5933de46effacb8ce
+CT = 1971811992a43b67a200543e43f23e1a0143244b866397558fa5f9539e0500f139016e4a4337d86b
+
+Count = 46
+Adata = 33028129
+Payload = f7d653c23254875625b20e1ef60ae92847046d84bb4ce857
+CT = 4da57c67af7f6a2a2a7a6d3924467bc7d57aada1c283c7ccfa2379fde155e64b5b84e336056445c3
+
+Count = 47
+Adata = 2cab4a09
+Payload = 872a3f7230e626abff519e5aeecc93897249405daeaffc98
+CT = 3d5910d7adcdcbd7f099fd7d3c800166e0378078d760d30358208335cb81e4fb10923fca4ddb9ff9
+
+Count = 48
+Adata = 73142ba7
+Payload = 766f94e7d9b1ce74bbaf2c99d215350f060122767fc1953f
+CT = cc1cbb42449a2308b4674fbe0059a7e0947fe253060ebaa42d6ecfb49ac8983415503efef1e21950
+
+Count = 49
+Adata = bc9f967e
+Payload = 5f089ed9267363bc23c6c7b8f73208a36f61fa8ea8084ff7
+CT = e57bb17cbb588ec02c0ea49f257e9a4cfd1f3aabd1c7606c1978a62d15430fc20b87940292b49641
+
+[Alen = 5]
+
+Key = 54caf96ef6d448734700aadab50faf7a
+Nonce = a3803e752ae849c910d8da36af
+
+Count = 50
+Adata = 5f476348dd
+Payload = c69f7c5a50f3e72123371bbfd6bdf532b99ef78500508dfe
+CT = 20c43ad83610880249f1632dd418ec9a5ed333b50e996d1a4e5a32fbe7961b832b722bc07a18595b
+
+Count = 51
+Adata = 07db8aada5
+Payload = 9cf8b638f2b295b85cf782fabab11153dc091b4afcd761a9
+CT = 7aa3f0ba9451fa9b3631fa68b81408fb3b44df7af21e814d401a2222443696021b5faa520129b563
+
+Count = 52
+Adata = 31ef6561ff
+Payload = 62b8263dc015ef873cd16272e4da89799b910f2b04204420
+CT = 84e360bfa6f680a456171ae0e67f90d17cdccb1b0ae9a4c4f842681d2e90da5718234ed893197662
+
+Count = 53
+Adata = e97dfcbafb
+Payload = 810bed3a2bc0f9d75389155b7a39d9d014c08646814f9718
+CT = 6750abb84d2396f4394f6dc9789cc078f38d42768f8677fc33a08eb30ee154f71279682ab02eff27
+
+Count = 54
+Adata = 4981c51fcc
+Payload = 063d23fc3ec344c1ba3486802e01e55617455d5cfbfb5279
+CT = e066657e58202be2d0f2fe122ca4fcfef008996cf532b29d8d3071c79f0cf86fe4148cb5e8ace0ce
+
+Count = 55
+Adata = c8437dba76
+Payload = 41db5b245ea0fab985b93e7fc0a00cd3cca5bdbb642b7ebf
+CT = a7801da63843959aef7f46edc205157b2be8798b6ae29e5b842700619dc1599603f3f3f6cfdf5e0b
+
+Count = 56
+Adata = 6f65a24344
+Payload = b0e36734b2ba871d59df0b029c7f32af68e003a689ac4911
+CT = 56b821b6d459e83e331973909eda2b078fadc7968765a9f539a0cd8d8bbf211b907f34411f868c79
+
+Count = 57
+Adata = cd62d6d203
+Payload = 747e53e627eabde0cd77d78d1bd720bea518f8a2f76e57a2
+CT = 922515644109d2c3a7b1af1f1972391642553c92f9a7b746c4a90e5fc11266bab77eea1d24fbdbb9
+
+Count = 58
+Adata = 9663b3c8e6
+Payload = c70c92ec4c518802662fa4c41a6a33a22599f79f8f7264b3
+CT = 2157d46e2ab2e7210ce9dc5618cf2a0ac2d433af81bb8457b3c1246f7dd6462ce757db82db45f36e
+
+Count = 59
+Adata = 35c4720d3c
+Payload = a26835605b66fc08abdbb5dc77e39783d60b8e8f2314e95f
+CT = 443373e23d85932bc11dcd4e75468e2b31464abf2ddd09bbd472c06a5f4c04f97d06ec401d3e7fd9
+
+[Alen = 6]
+
+Key = cc0c084d7de011e2f031616a302e7a31
+Nonce = f0b4522847f6f8336fe534a4e7
+
+Count = 60
+Adata = da853a27aee2
+Payload = 15b369889699b6de1fa3ee73e5fe19814e46f129074c965b
+CT = f39755d160a64611368a8eccf6fcbc45ef7f1f56240eb19a2e3ca4ec3c776ab58843f617d605fd72
+
+Count = 61
+Adata = d4ed4584678e
+Payload = a18c0460b56a5bcd5bf6842cec6ed44d90b2bfa968a6a7e7
+CT = 47a838394355ab0272dfe493ff6c7189318b51d64be48026327804c44c8f17a4446a3d5ba85f9c7f
+
+Count = 62
+Adata = 590a27721a36
+Payload = 41cee0ecaf9c65cef740440af37954ef49a585779d2abbca
+CT = a7eadcb559a39501de6924b5e07bf12be89c6b08be689c0bbcd00e9cb726d75e4283820ee81d933a
+
+Count = 63
+Adata = 58830fb0b1f3
+Payload = dce983e4e3734a9bd8848dba0d744d07bbeba602f4006025
+CT = 3acdbfbd154cba54f1aded051e76e8c31ad2487dd74247e4d5d71a1f0f1b6518c35f0632a30931fd
+
+Count = 64
+Adata = eedd0d767a25
+Payload = 4653b3e879ab18b65c5c3706a5139698262cb830a22d943b
+CT = a0778fb18f94e879757557b9b611335c8715564f816fb3fa3ad112899e9ba442660eb5dfe33b2f96
+
+Count = 65
+Adata = 618bcf2e3e79
+Payload = 8586383281925363ac15fb19c26d64c639c75920c792dc2c
+CT = 63a2046b77ada3ac853c9ba6d16fc10298feb75fe4d0fbed54fba446028919342b2fe86ee67efcc7
+
+Count = 66
+Adata = 549c9b84c7f7
+Payload = 95c25ae4445cd8c4d267df82687484667e309992fcf1e737
+CT = 73e666bdb263280bfb4ebf3d7b7621a2df0977eddfb3c0f69fc23013142f62881ccfa3037067e1ef
+
+Count = 67
+Adata = 92d7fa6a8135
+Payload = e58034bbb0e6f5e724e32ee56896dadae25c2a3efb8c6f2f
+CT = 03a408e246d905280dca4e5a7b947f1e4365c441d8ce48ee8263568d56fae8bf35b2f2cdecbffe0a
+
+Count = 68
+Adata = f43e126c0f83
+Payload = d98f0dddfe9cb3cae1336970d5efb55316a65e2c51e316f4
+CT = 3fab318408a34305c81a09cfc6ed1097b79fb05372a13135de2c2fbfdddc7dd6672714af174c5121
+
+Count = 69
+Adata = f02074812dde
+Payload = 548747b1669c6383b793054d93957f9e99d605761c6c23b5
+CT = b2a37be890a3934c9eba65f28097da5a38efeb093f2e04743704560ff23ce0000fba8812c45940ad
+
+[Alen = 7]
+
+Key = d7572ed0e37261efa02f8c83e695efdc
+Nonce = f4f96d7b4384a3930b3d830f82
+
+Count = 70
+Adata = 922340ec94861f
+Payload = 1edef80c57d17f969f8bde10ab38a1a8811a124de72c526e
+CT = de14558cc686e1836f1f121ea1b941a9ebd4f0fb916dc870fd541b988a801cb5751c7faaf5b0c164
+
+Count = 71
+Adata = 4eb379f21b1531
+Payload = ddd5282a207c1dcb03c1c3bbc9eb12a7bd28534118db2735
+CT = 1d1f85aab12b83def3550fb5c36af2a6d7e6b1f76e9abd2bc068bd1b1c309dfbd52d9a24be07c630
+
+Count = 72
+Adata = 7fa89e9d6e3fec
+Payload = c5b7c462eb166f48bb59c8102ee7b3dc67a28e5de7570c51
+CT = 057d69e27a41f15d4bcd041e246653dd0d6c6ceb9116964f2d114d6ab082738d05d60acca8e8ccfb
+
+Count = 73
+Adata = fda8665f87c618
+Payload = af793815e147e3180f5146aa6a582e343dc479f26b4226b2
+CT = 6fb3959570107d0dffc58aa460d9ce35570a9b441d03bcac1cc84bd77fe00e1a13433f2c10e3b799
+
+Count = 74
+Adata = 46bde207491ebd
+Payload = 47c76a0bbd5b1616b278089d41a050c509c7a1c280574bf7
+CT = 870dc78b2c0c880342ecc4934b21b0c463094374f616d1e9990c81f1bae32c953bf02ddbde047632
+
+Count = 75
+Adata = a799f5f895fd7a
+Payload = d554806ffc3900a0952a3c094c745808950697a6e5d62c1d
+CT = 159e2def6d6e9eb565bef00746f5b809ffc875109397b6031af19f1f080dd1dd2da799059755e49f
+
+Count = 76
+Adata = 20225831a9ee06
+Payload = ba45e1859efae362a44a0116a14e488ba369da6c76c3913b
+CT = 7a8f4c050fad7d7754decd18abcfa88ac9a738da00820b2523d3b9a0060834ac4860dae0eac570ef
+
+Count = 77
+Adata = 785360916464eb
+Payload = 57bc338946ff78cf76adf5021e2e44e34e687fb68ad703f3
+CT = 97769e09d7a8e6da8639390c14afa4e224a69d00fc9699edff96e7cf841a66c50bbb6fb2bac7ef51
+
+Count = 78
+Adata = 57b946369226db
+Payload = 9ac5be9929c4fe5a9992749a38dc69874866db3d4747da97
+CT = 5a0f1319b893604f6906b894325d898622a8398b3106408986e1c33a45f9d52755c374650635bef6
+
+Count = 79
+Adata = 73e4da8973c1e3
+Payload = 5a05410aa3a71f5f1a253b8576eba269c06a4c30591144cc
+CT = 9acfec8a32f0814aeab1f78b7c6a4268aaa4ae862f50ded2d78592c2d89c15edc5bb7486aa93f896
+
+[Alen = 8]
+
+Key = 98a42d7a0c5917deaf3b4de3f0cbe0a1
+Nonce = 03d33ab0c2df7bfce88b5ee4c4
+
+Count = 80
+Adata = 2d5438b728b950d9
+Payload = 9aa9c8358117564371366beeec923051ef433252197aaad5
+CT = 9ff942baa60f440c17a78e9581216b9a947a67f04d54911feecfff971fdfaa856310b014aa59c978
+
+Count = 81
+Adata = 6e430b497a16e7f5
+Payload = 5758a500978c71a9b90f6e5beae9d96ef05a41486b10ea2e
+CT = 52082f8fb09463e6df9e8b20875a82a58b6314ea3f3ed1e46a4d7b4b4df6c831ee32116ee4dad98c
+
+Count = 82
+Adata = e12f98507d6514c3
+Payload = 49efe18c76a8355127d914a3a830c1c6ff2a163d728526e1
+CT = 4cbf6b0351b0271e4148f1d8c5839a0d8413439f26ab1d2b3243fc75cd1624e152f451678edcac87
+
+Count = 83
+Adata = eecf8d641ee0bee9
+Payload = 49ae2309fbe6ce4e9421516b8f79ae64b1316cb849eaf638
+CT = 4cfea986dcfedc01f2b0b410e2caf5afca08391a1dc4cdf2dd6d8ca57da1880e1baff43736b3da34
+
+Count = 84
+Adata = 9066367c784de0a4
+Payload = b1bda5fa4242aa6aad0f5a5b1d31d86b8d4a97588b3e315d
+CT = b4ed2f75655ab825cb9ebf20708283a0f673c2fadf100a97f05439a661001513a96b896de46b7081
+
+Count = 85
+Adata = edf848b2510f7803
+Payload = eaa8608f6763d968576a7e89056b9828a1686c8441b06377
+CT = eff8ea00407bcb2731fb9bf268d8c3e3da513926159e58bdcf20709b2dc2ff9946094190b5ea09d1
+
+Count = 86
+Adata = 0f49cae81c8628d2
+Payload = f32029cf51609f0df9832ad1b283ea94a5356f70112c1328
+CT = f670a34076788d429f12cfaadf30b15fde0c3ad2450228e2a5bb6b4f87b9b198665203e4fdf9e7f7
+
+Count = 87
+Adata = b0c47e9cce46a276
+Payload = 7a550ef9254a8da6e4fee290a76ea838ffb61d3533d4d31f
+CT = 7f05847602529fe9826f07ebcaddf3f3848f489767fae8d529f416f89f1a34bbbf2ce40d943c6d8b
+
+Count = 88
+Adata = a6fe7c9ce2d49f85
+Payload = e67c486dd7ba9a9061844b9354f55890321ae626efaa28cc
+CT = e32cc2e2f0a288df0715aee83946035b4923b384bb8413067eb95550b91b955d5c2d72d5c189b704
+
+Count = 89
+Adata = eb1d11cc4876f58f
+Payload = 35f2c810091e930a52e4a3f28c9c8184967f1554c2675eb5
+CT = 30a2429f2e06814534754689e12fda4fed4640f69649657f0e8e8a5a7e0ea6860bab4a4320f03ae5
+
+[Alen = 9]
+
+Key = 2a68e3fe746f593c1b97cb637079c3e5
+Nonce = cd62d0f27b7f4864dc7c343acd
+
+Count = 90
+Adata = abe4f1d3812bfe3ccf
+Payload = 13b4a874888db0e5d8fd814b5e7e04f7fdfbc1601ccc02bc
+CT = 032835a3dbf688d09cf2a32a92b101959d33ff47500f92f4fd49840440f866d1a22b0854996111d8
+
+Count = 91
+Adata = 2e21f466814d3d6340
+Payload = 08b5c773364cded74d7b308984313c17ff90eed496a27a2b
+CT = 18295aa46537e6e2097412e848fe39759f58d0f3da61ea63de2f5c335df537fbbc6ae59cd562732f
+
+Count = 92
+Adata = dba22aabcea0e694fc
+Payload = bbac1790abb7aafe272ec472c897e6363e335b3c4126c762
+CT = ab308a47f8cc92cb6321e6130458e3545efb651b0de5572acc5ed6e4a907ff4742ab6c835a427f92
+
+Count = 93
+Adata = 97e9d16bd757395ec1
+Payload = 7249612dc09809bbca9dd311e720f7da2cb54ce33e3eb9c3
+CT = 62d5fcfa93e3318e8e92f1702beff2b84c7d72c472fd298b1714b5a3df454f3bc35869da75adc882
+
+Count = 94
+Adata = 866cf710470cac74d3
+Payload = 060ae0ab9857324a3b2ac79f3b6e6f90f5de884ce9c7b930
+CT = 16967d7ccb2c0a7f7f25e5fef7a16af29516b66ba5042978aa33dffe2596832f98a9c8413bd898b9
+
+Count = 95
+Adata = 2dd7a7f832b29ccce2
+Payload = f77a9fd5363836deefd34e1bea0882484a7ab746b4495d59
+CT = e7e6020265430eebabdc6c7a26c7872a2ab28961f88acd11dd5049f7c53d6a7fe5d7f959689ee960
+
+Count = 96
+Adata = 502349a60e897356b5
+Payload = 96118dbfe53434d8aed88769a535eb0c8b5849dca1c81c34
+CT = 868d1068b64f0cedead7a50869faee6eeb9077fbed0b8c7ced9c3a0d0de8788471c5f6c2f9638b7c
+
+Count = 97
+Adata = debed45c9acf129268
+Payload = df5a47d3eb5c0b6cabb6711a45400602d205b82ecae9e849
+CT = cfc6da04b8273359efb9537b898f0360b2cd8609862a7801d49b4b9bead1b7de2021cff280d6f93b
+
+Count = 98
+Adata = 2726702dd62a6e5344
+Payload = 5a7649cb001fbb6f653cbca17756c5c1a078c2e240d92085
+CT = 4aead41c5364835a21339ec0bb99c0a3c0b0fcc50c1ab0cd69df31aba209d87ee22bd6a1dcadb168
+
+Count = 99
+Adata = e8006cfb0536696ac7
+Payload = 95186d41f927cdbef42157f21d966e88061b6558b5ec932f
+CT = 8584f096aa5cf58bb02e7593d1596bea66d35b7ff92f03677cc5b60c881fe834a789d28447d8fb54
+
+[Alen = 10]
+
+Key = 46b067cf9b1a28cf187002e90b14e130
+Nonce = bad8c03292bf01cfd8d34f860c
+
+Count = 100
+Adata = 8d65880eddb9fd96d276
+Payload = cc0915194218d4536e467433cd6d79ff1d9eb9ff160ab684
+CT = bd56edc015692c6ab9bec493a9893863598414a3d11a6a0f27ecdcb257d0d30491e5bf1aa8f90958
+
+Count = 101
+Adata = 8a65cde13149d9d54a5b
+Payload = 28257133b1d8b0b2be4faecd6e819ac783707a5c5f50c302
+CT = 597a89eae6a9488b69b71e6d0a65db5bc76ad70098401f89b10f9fc201e4128696dcd899dd2e24ea
+
+Count = 102
+Adata = e999ec3e1bfb25b5877c
+Payload = 96ab0cfc204bafc4f5851d6c682d631d0c5ad03ac925a943
+CT = e7f4f425773a57fd227dadcc0cc9228148407d660e3575c8c522e5ba5adbc6a639cbd06f103ebc9e
+
+Count = 103
+Adata = a8554441e073d6065dce
+Payload = 50925853a84a33ff392154e4e737efc18dcfc98f4d5235a9
+CT = 21cda08aff3bcbc6eed9e44483d3ae5dc9d564d38a42e922e1a4e0f7ebc3cff3915d27971cce7e91
+
+Count = 104
+Adata = 838f0be8d04d28d77549
+Payload = d0700658d5f4010ff21091f3d119c99645e339198029c3a9
+CT = a12ffe818285f93625e82153b5fd880a01f9944547391f22c215c88d80bffc881aff10ba40f11976
+
+Count = 105
+Adata = 20f014d928d5b25fbaf4
+Payload = 4bdf28748a0c281dd49c7294ae8e55fe7a52d45ff6384db3
+CT = 3a80d0addd7dd0240364c234ca6a14623e487903312891382cc9391bc06aa6ca9d486a4e2a218c54
+
+Count = 106
+Adata = 56c026b8a71974ff7ecd
+Payload = f75db057f0276fff85014f54ecdec8f90b96a2a982db14cb
+CT = 8602488ea75697c652f9fff4883a89654f8c0ff545cbc840778b05c6c582a0bb7d1d9dcf6a46b9f6
+
+Count = 107
+Adata = 75c3b9e52648a4f9aca9
+Payload = c15c554169dbb9b08494afaa44819a10dc9ddad54199ab54
+CT = b003ad983eaa4189536c1f0a2065db8c98877789868977dff47d9ebbd3cff14623b10cecc94b53d6
+
+Count = 108
+Adata = 1c76c3014a14b7fa1ca8
+Payload = 19eef6f798fc68086aad1cda6d7976cdcfe6b8af74598032
+CT = 68b10e2ecf8d9031bd55ac7a099d37518bfc15f3b3495cb9d2b74b84dc170c00dce85b56e346a976
+
+Count = 109
+Adata = a4eb60d4eb7ead1bd0e6
+Payload = e06e5dba5ac35cfd07949e5cc12ad70507d4a86a952ecca3
+CT = 9131a5630db2a4c4d06c2efca5ce969943ce0536523e1028d92e19fd8b5c1fcbff36adaa5e47ae84
+
+[Alen = 11]
+
+Key = e94dac9c90984790a7c0c867536615ff
+Nonce = c19f06f91e645d4199365f18c0
+
+Count = 110
+Adata = 537038b5357e358a930bd6
+Payload = 4d64461c55eb16bf7b9120f22be349598f2f394da8460dc6
+CT = e9fc5004c2359724e1e4411ae6f834ef6bea046d549753c88790c1648f461a31c84e62ea8592a074
+
+Count = 111
+Adata = 7e3d7b3eada988668f3784
+Payload = eab7d5dbd91d4cbbac8d79fadd70b5dcb3baadac5cb713a3
+CT = 4e2fc3c34ec3cd2036f81812106bc86a577f908ca0664dadacb1d1c9231d2c22ecfeed622792dfd0
+
+Count = 112
+Adata = 78b107b29c4878ff18f749
+Payload = 3c6ae2e2578875a1f5611582528e058aece2ddc33a4dde3d
+CT = 98f2f4fac056f43a6f14746a9f95783c0827e0e3c69c8033fffe60299768f048e7098033cde046b0
+
+Count = 113
+Adata = d293908bb516c5f3a411b9
+Payload = d7a46e726ed43f1580eb52141a93390982cc809dc833e3f0
+CT = 733c786af90abe8e1a9e33fcd78844bf6609bdbd34e2bdfe4ee6ebc0d90a0de05b428495c93e1801
+
+Count = 114
+Adata = 33ef208faad4d2948c9e67
+Payload = b1fe5d9d34157193fc0608cd8ecb872e17720f5f6814a466
+CT = 15664b85a3cbf0086673692543d0fa98f3b7327f94c5fa687e7e64cc0fcd6a92c79ceb6ce2abd8ee
+
+Count = 115
+Adata = b7f7ed9ccac3c2b4fbfee0
+Payload = de6bb539fb7a9c87414f62a7cf25a4cfca176509e991af41
+CT = 7af3a3216ca41d1cdb3a034f023ed9792ed258291540f14fb02b53bc779e0976b634b0d1b88fc0a9
+
+Count = 116
+Adata = a6e287383927f76e4927af
+Payload = 8719d20c20c8959068b8adcd65e6f6bc7b3693828f0735a0
+CT = 2381c414b716140bf2cdcc25a8fd8b0a9ff3aea273d66bae3c37fa936243b393f07fcccb0fc13e41
+
+Count = 117
+Adata = 70828be6dd93954f4e7b6b
+Payload = 30b39426831f61c8ba5f2ef5b71f0c4b2f916e3b5a578110
+CT = 942b823e14c1e053202a4f1d7a0471fdcb54531ba686df1e0d7534a489e6d242966ebea4455f8f79
+
+Count = 118
+Adata = 506015fc2831df293f4da0
+Payload = 818d5d810f678629f078723f5c6c3657271077533bfb7c29
+CT = 25154b9998b907b26a0d13d791774be1c3d54a73c72a2227ccbf64f04e95b180d09e843847d22104
+
+Count = 119
+Adata = e9394b0245b379e68e3dea
+Payload = f0613205a7a0822849df9e8a3cf6caf281f3adfa966c5507
+CT = 54f9241d307e03b3d3aaff62f1edb744653690da6abd0b0927b546ef8cd717073832584fb25a0645
+
+[Alen = 12]
+
+Key = f6bb5d59b0fa9de0828b115303bf94aa
+Nonce = 05358f33e1fc6a53ab5a5c98ce
+
+Count = 120
+Adata = 040b25771239cc2a39446e3c
+Payload = 011fc50329bfd63a85ebd4f7693363602f1a4147371270b7
+CT = 4432d7eb42980734d34f19c50cf8abf71ac1b19ed75a727854e5d050a405f755047d09cb0f49546a
+
+Count = 121
+Adata = 50a1d37fa2f3462bd304631b
+Payload = c90e40540d372ab1eb00ea5d5b8de5bf7c94ce4e376d6949
+CT = 8c2352bc6610fbbfbda4276f3e462d28494f3e97d7256b862abee8547ee3f24cfa677468ecc1d121
+
+Count = 122
+Adata = ac3bb872a41df35e415d2b0c
+Payload = 9e7be78c0ab9e6a4c6c257e77c63681bea35d951f168b0c5
+CT = db56f564619e37aa90669ad519a8a08cdfee29881120b20a61cef865ce4080e7c7abfc43f62c03a3
+
+Count = 123
+Adata = e3106ae6456153dd922640a1
+Payload = 00df0c5a5d3eceb2bd293066529799544f846672a9a1d31b
+CT = 45f21eb236191fbceb8dfd54375c51c37a5f96ab49e9d1d4e1d19c321a1e0852adba939b447220ab
+
+Count = 124
+Adata = 297b4498bf5427e6341aa927
+Payload = 14967a0476dbaea03b07fa8d40d344eabaf479be2443243a
+CT = 51bb68ec1dfc7fae6da337bf25188c7d8f2f8967c40b26f579ea5fb65018abdcde1a39f6859ecb56
+
+Count = 125
+Adata = 5de60dc0e3b5bda0b33a9520
+Payload = 2da3716d76d10b6766a1f9cbf9f420316fd5f396e7b9a2ba
+CT = 688e63851df6da69300534f99c3fe8a65a0e034f07f1a075c2629ff871ee15745fd8c1ddbdae4c29
+
+Count = 126
+Adata = 1c9b8541943ad50b4243c179
+Payload = 8c1b3ba18d1f5cff74a457aadd6b3e7d093d06ad2622e6a0
+CT = c9362949e6388df122009a98b8a0f6ea3ce6f674c66ae46f04e198ad16ad1106d3ba6172f4a13a8f
+
+Count = 127
+Adata = 51e926d2542ac8faef61465a
+Payload = 88936e97db070c0ec2aa58d1c6f5b34df3d32ddf7db34a8b
+CT = cdbe7c7fb020dd00940e95e3a33e7bdac608dd069dfb484475981131e3934ec6d41e00d502729799
+
+Count = 128
+Adata = ebefbac97b363e6f32526aac
+Payload = c20742e4b410c5b661da373a905fb0ed55b20e0e879eff5c
+CT = 872a500cdf3714b8377efa08f594787a6069fed767d6fd93e2c005b5bebe07ff578b1b4bc51971cd
+
+Count = 129
+Adata = 1ef059ac7d648e9e32d9b1f2
+Payload = 65c55ca21a89a8325365bf2be861d700559de2eabb41b37f
+CT = 20e84e4a71ae793c05c172198daa1f97604612335b09b1b021a25f15b5b4229a872a9199972c85b3
+
+[Alen = 13]
+
+Key = d1da2e961e78063af8de41865b226873
+Nonce = 03739f5474857006340cce554d
+
+Count = 130
+Adata = e3afd091d2b588465872a6300f
+Payload = 8e5fa1a6662a8378cda15697e926841594f2f394fa5a34ab
+CT = ca0d95e3ff186ad6b88d45fc4079e6b7b4a615e7e8dd5f4742d522cc9dc19c47a4fa0b1528069cf8
+
+Count = 131
+Adata = ce3186bb737753b59ee76b748c
+Payload = 311ebc5ff2f625944562ea699b2690df3e6e64a17c62bd3a
+CT = 754c881a6bc4cc3a304ef9023279f27d1e3a82d26ee5d6d659b26510b8f25610799e011d7c850ecd
+
+Count = 132
+Adata = bfd636989dfbcb0edc9f014cc8
+Payload = c96cee5ba7b799f16254a17b1870cdb85fe0ef3f42110c13
+CT = 8d3eda1e3e85705f1778b210b12faf1a7fb4094c509667ff52942aa0d39649f3d9ed535bebc2b603
+
+Count = 133
+Adata = 4812b092aa59d57451bfd812c3
+Payload = 13b1b4404dc5735655139414fcbd02c5327ae9fb148bd324
+CT = 57e38005d4f79af8203f877f55e26067122e0f88060cb8c8c1e61efb9c1d84ddac2d24f43531f569
+
+Count = 134
+Adata = f6ef9ac4f4c9ce1e4309c64fa8
+Payload = 6c5b59319e2710f5d63407f85b424d1860425ef8ce0cfe53
+CT = 28096d740715f95ba3181493f21d2fba4016b88bdc8b95bf13350de0ef34df12fb945b0ae0a0d9bd
+
+Count = 135
+Adata = 9bf12168bb3d79ebd25262f2b4
+Payload = 968e1d78008da78611e82985c4028e86770858cfe61c3723
+CT = d2dc293d99bf4e2864c43aee6d5dec24575cbebcf49b5ccfa0734563638598d8c4bf1fcd94009925
+
+Count = 136
+Adata = 7d870d7e52d3053c65eefad477
+Payload = 6a1306d911434cc7400d2f9a95e36aedceddca2b3d583f51
+CT = 2e41329c8871a56935213cf13cbc084fee892c582fdf54bda1f5fc53b08aca82bccfba6fbcb27e69
+
+Count = 137
+Adata = e95099f04371e445e5eaa1d80e
+Payload = b9197eb50c8168d16b8a12bd261d553ffcc521d979b26fee
+CT = fd4b4af095b3817f1ea601d68f42379ddc91c7aa6b3504027d1a922953facbd630d7fea6b63594ec
+
+Count = 138
+Adata = 3e80eb03db6545204ef4241ad6
+Payload = 95f59e36eac8eb3b51709d635b07fa2da0976ea20e25807f
+CT = d1a7aa7373fa0295245c8e08f258988f80c388d11ca2eb9383fa000d10078256b71249d9d1f1846c
+
+Count = 139
+Adata = 9748798c0f3cc766795c8ce0e4
+Payload = a48db9add9ecdeb49e51d3ab7bb2075202ed2aa50c0195b1
+CT = e0df8de840de371aeb7dc0c0d2ed65f022b9ccd61e86fe5d2773c2f55b752477c489facee812c614
+
+[Alen = 14]
+
+Key = 1eee667267ef10b03624cf9c341e3f75
+Nonce = 0630a3eae27e505c61c56e6560
+
+Count = 140
+Adata = d24651ef0561282d3e20e834960c
+Payload = 798e31cce0a83702a95171fb1162a17b9ce00ec3592ce262
+CT = f3c3e52f1a1ff528a8d3783ee4e75f114e3e6416334815d2d9236d5c5c9319092078411b72c51ba8
+
+Count = 141
+Adata = c527d309ab29ee91c5fc53117e71
+Payload = d79cd4c8891ec4ce2c51136712d23b32266b2b73768aeb1e
+CT = 5dd1002b73a906e42dd31aa2e757c558f4b541a61cee1caed8ad2a48cb734e3f93e602c15c7c775e
+
+Count = 142
+Adata = a93dfc3944514ddfc5acdd89fab7
+Payload = d7fa81c949f1f2af29dbd56529b307e3b348e996d0936455
+CT = 5db7552ab34630852859dca0dc36f98961968343baf793e5f34b297f3f106a9cdae255f7634fbd0f
+
+Count = 143
+Adata = e502abe21c7b22120693a08ef3e6
+Payload = 6330caaeddf0473d564d175b9408c6f12e6d3cd4ee2c423f
+CT = e97d1e4d2747851757cf1e9e618d389bfcb356018448b58f4f5d9c3dbfe3e2fe03a002e55039ebe6
+
+Count = 144
+Adata = a49b34dfad43333fb2ffd701a2d6
+Payload = 45671482c390e65f75de15ca91b93596e9bf3d6fc9178bcb
+CT = cf2ac06139272475745c1c0f643ccbfc3b6157baa3737c7b6f7bb0749c99d75740f2d193fef36c60
+
+Count = 145
+Adata = 9e4d8aa3dbdc4d4b4b8d72734f52
+Payload = c8f34bea8bdc403a48d8ed9268429141cd03c29558050ef4
+CT = 42be9f09716b8210495ae4579dc76f2b1fdda8403261f944ceec82fc674da9efa6926e8641729ed8
+
+Count = 146
+Adata = 052327ad59cc791259817fd0ed96
+Payload = d8d1c57b16c23894b66023c29f8648ce4a6074647e1f5f69
+CT = 529c1198ec75fabeb7e22a076a03b6a498be1eb1147ba8d92ff19e93f60c8f3a511300fddc38ee59
+
+Count = 147
+Adata = 14bc3c44c001ccb261a2a0526523
+Payload = 71c14a7031033db15bfe23b75fed9daf8886dd11392a0b78
+CT = fb8c9e93cbb4ff9b5a7c2a72aa6863c55a58b7c4534efcc87fa00fb244eda0d77cf6c05c8fd590af
+
+Count = 148
+Adata = 3477384c396a9e9efb3e169722cb
+Payload = afa795f836763a1210bb36fef167864f73ba3b6abc593537
+CT = 25ea411bccc1f83811393f3b04e27825a16451bfd63dc287bae19612657c87d3bb73cfb8cee7c8a8
+
+Count = 149
+Adata = 0c3b9a6924ad506038cb2d6590c9
+Payload = ca4a186f116a179579e3d327aec3f5be358bc7094f853bc3
+CT = 4007cc8cebddd5bf7861dae25b460bd4e755addc25e1cc733d9713d2e916c23ac3039de34c295fc4
+
+[Alen = 15]
+
+Key = dbbd26f5d9e970e4e384b2273961be5a
+Nonce = 0b1eabe504ef4822542e397fec
+
+Count = 150
+Adata = 477937301c83ba02d50760b603e0ea
+Payload = 553714e17a208a2eceb847a4a2d95088388b1ac8d8ca43e0
+CT = 1c80213268bad5402c4dc9b5d836ab7499810d0d8a974716df9a0e986ab2890736423bb3772cec3e
+
+Count = 151
+Adata = c91eb5a07ff19c044023e5cf339203
+Payload = c94d0b9e728413c58202cb3f6b82dba7aa9e3ca0a72c40c7
+CT = 80fa3e4d601e4cab60f7452e116d205b0b942b65f571443139f907a92cb01215e3cda84ae13af48b
+
+Count = 152
+Adata = 38c71a8e9b279c605c7f0418a0afc1
+Payload = b4e8c4fd5ad98a1be8b5a11677c57ca1c1694e3528092aa9
+CT = fd5ff12e4843d5750a402f070d2a875d606359f07a542e5f3dbd8dbf7485106cdf9ea0e7088a5650
+
+Count = 153
+Adata = f2c76ef617fa2bfc8a4d6bcbb15fe8
+Payload = 578ce26cdb5ba2e8798e23588e5cd04ef782820b80e49a42
+CT = 1e3bd7bfc9c1fd869b7bad49f4b32bb2568895ced2b99eb4853fde6f4dca88ff11bbce20ed9e5012
+
+Count = 154
+Adata = 36004342dd74e7966692a848b2c11e
+Payload = 78733c635d4d4e8b0729732f1e174dfcec4e020a7ac3870d
+CT = 31c409b04fd711e5e5dcfd3e64f8b6004d4415cf289e83fbd94e979108fcecbd32f6bdf72f0ccb4d
+
+Count = 155
+Adata = db92bc3fe5d4141aeb39baea6f114c
+Payload = c7aafe7760945e45703c1e19f1032dfd56ddc216c3b03826
+CT = 8e1dcba4720e012b92c990088becd601f7d7d5d391ed3cd0229c8f9d4e39fc16cbdb44236ef125c7
+
+Count = 156
+Adata = 34ec2d5b6f0d950509b47a0637d74c
+Payload = 2345e36a63be0b78df95e60907c78da0e48e61e70685a1f3
+CT = 6af2d6b9712454163d6068187d28765c4584762254d8a5051c9ab7cb0a779c3fa78c9ee12603802b
+
+Count = 157
+Adata = 6ab658d177c2dd87c9b8787cd70182
+Payload = b0725f735543eb0c0ec88ae69b140f5787d28ef4a2e36d57
+CT = f9c56aa047d9b462ec3d04f7e1fbf4ab26d89931f0be69a1648c6307ec5ea304045a7cdc93f36b9d
+
+Count = 158
+Adata = 483f135c61250fa610b4d14b99ecf0
+Payload = 315a947bf5291278d446d332ee5ca0def7655d5c957a8fb4
+CT = 78eda1a8e7b34d1636b35d2394b35b22566f4a99c7278b42364ff3b1ad915347b1c7f062b10d3da4
+
+Count = 159
+Adata = bb022aed60819ef84ae83ce27db9d0
+Payload = f78d00755bcb45e6822121fe7cb03c8e627c9f548ccd7e7c
+CT = be3a35a649511a8860d4afef065fc772c3768891de907a8a7569808dab58d42181543b2e2d05992c
+
+[Alen = 16]
+
+Key = 10a7720f2e18f739c26924925af6b670
+Nonce = 8c4e7813ab9bce9dafee01c628
+
+Count = 160
+Adata = a209941fab710fda38d11c68b13d930f
+Payload = e59782a9aea45f467b90e51a0fdf166baba05663def2d8b6
+CT = e357b1ccdaca6f3506dc45279c2e4c59f5307a5fd6a99cd72341ea8c0785569973f90ee9ee645acc
+
+Count = 161
+Adata = 2e2f6f9755a492ee54df77b2ecab9808
+Payload = 042a072f6ebf11f79fcb4f5a64f7946dc837d9d2355785ea
+CT = 02ea344a1ad12184e287ef67f706ce5f96a7f5ee3d0cc18b703eb81224cdb1fd2e1cfb2fbfe1e402
+
+Count = 162
+Adata = 99e98c9983c85d1f49ae43ebad67a652
+Payload = 5db6bda27910e7b8b61ac476c6532570b71b3932bd6a698c
+CT = 5b768ec70d7ed7cbcb56644b55a27f42e98b150eb5312ded64c4aea7f17f18f068897557c93ffaaa
+
+Count = 163
+Adata = 37a837d73fa15793f6f823fb99c2ea74
+Payload = 8cac261a461c3ddd2642b8e4e5c3389e491fcb2ff8356412
+CT = 8a6c157f32720dae5b0e18d9763262ac178fe713f06e20736f3b2e70e6e2dc7acc74a823a7f49722
+
+Count = 164
+Adata = 11119a4e779cfb64c736d425e4ff554d
+Payload = 3429f9b088b501d7944c462694d0799568282e7ce07d3e61
+CT = 32e9cad5fcdb31a4e900e61b072123a736b80240e8267a000dc3b57096f0df1d4eb5328c416921bc
+
+Count = 165
+Adata = 962d7d4305f23d1692747b504960c0a4
+Payload = a46ae4c71d4c9eb72fabfa76b8074aa02e07653eca10eef5
+CT = a2aad7a26922aec452e75a4b2bf6109270974902c24baa94f62ed804e9f2ac0f7001d0f35ea9f3c1
+
+Count = 166
+Adata = bbb1fdfefcf3657ba6cd93ff341a04e1
+Payload = 92f5e3083f57c77ac9553a2024a66489698bd2261f05d415
+CT = 9435d06d4b39f709b4199a1db7573ebb371bfe1a175e9074907dcd7ac1e0bb248d46c3036c39fb02
+
+Count = 167
+Adata = 74be126f7c596642dafa8fe3da904e69
+Payload = 41ecc3aae5cfebfad7921a47a0684601ffe73816380f8716
+CT = 472cf0cf91a1db89aadeba7a33991c33a177142a3054c37787cbb80fd21127feca7e76fd6947d5b7
+
+Count = 168
+Adata = d72cc521c90a468522af8966c24799f3
+Payload = 8850bdda4bd0271e333db344a47b837183eb48269c3dc0b6
+CT = 8e908ebf3fbe176d4e711379378ad943dd7b641a946684d7cdb5d1243b6e73b8e380d8ca041647db
+
+Count = 169
+Adata = 28f427fba8d0bb0380bbe5072ccfa519
+Payload = fdd3ca2f193f93f5a349b50357d26748b767cde6ab5cbfe7
+CT = fb13f94a6d51a386de05153ec4233d7ae9f7e1daa307fb864a0ae8604b103f882f17db893ed5c576
+
+[Alen = 17]
+
+Key = 6bffab1f4f4c1ff66b4a669b515b2f8d
+Nonce = ddb34d5e0140fb96d690e1a2b7
+
+Count = 170
+Adata = 5cbba9ea778e01af00afb2a934f28c7211
+Payload = d91b12e8655dd92b1332fc1d71c391c96a17111562d90ba3
+CT = d302e5b2d5d90433186b804cd7717e2db2f22cdc34fb2942ab30780a2c4f12af8f35350d65284c59
+
+Count = 171
+Adata = 1583138aa307401dddc40804ac0f414d33
+Payload = eeafb08d4a4819f5682a01d44371e34cc5729079e74e73a6
+CT = e4b647d7faccc4ed63737d85e5c30ca81d97adb0b16c514746577901b7f6feb88b8e2b8562f9cb5f
+
+Count = 172
+Adata = 23931c258c84086500c6a3b6eda457e6b5
+Payload = b8737d5bbfc976c2d8d9786148dea664dd83cee98df537b5
+CT = b26a8a010f4dabdad3800430ee6c49800566f320dbd715548735a59390ba7a892741694f3a89b0bf
+
+Count = 173
+Adata = e12f98507d6514c3b551d240595346bc9e
+Payload = eb021b63c61c0b194bd44870608d7ef0b932b6104412d7a9
+CT = e11bec397698d601408d3421c63f911461d78bd91230f548f4f81ed18cc1820375a7bec2318cde1e
+
+Count = 174
+Adata = e14b87d49d231c0199eec627fd7f1b5332
+Payload = 93b42584c4956078359d77e80aef52281b9228a1f66aa36b
+CT = 99add2de7411bd603ec40bb9ac5dbdccc3771568a048818a187b430caa60d98dc3e2aeefe6249b44
+
+Count = 175
+Adata = ca095aec96a8b093e62b10f0950ce35ce7
+Payload = 6a788d8238c7b313b8eba27b210a71c36819d719115b9b76
+CT = 60617ad888436e0bb3b2de2a87b89e27b0fcead04779b9970a77372b727408e1bf5a70790b9eba3a
+
+Count = 176
+Adata = d1cac02b34ad33c0e77a5bda2c3baf5e5d
+Payload = 3bc1ee54d0094603dfc68eee118e547d031fb36e464e776d
+CT = 31d8190e608d9b1bd49ff2bfb73cbb99dbfa8ea7106c558cdc1f5cb4d4fa2204e82eedcb3784443d
+
+Count = 177
+Adata = 065c06b49a49898e20bb679e35edbb1f76
+Payload = 8a12adb8b746216baa8a418725e608e4377f13816a036a10
+CT = 800b5ae207c2fc73a1d33dd68354e700ef9a2e483c2148f12413f9496592a75a1d6e42ee3a258607
+
+Count = 178
+Adata = 98a42d7a0c5917deaf3b4de3f0cbe0a191
+Payload = 30a226c07401d0ae24c73d682e3a6e7e377ec1613bafba17
+CT = 3abbd19ac4850db62f9e41398888819aef9bfca86d8d98f6b571a3150887df1ac5f813676b2eb24f
+
+Count = 179
+Adata = e245a7528931841b52a5f59d861d98d7b7
+Payload = 3d17bcdf30445ebd8a9b6aa2fe11d443c1161bb1ee69ced0
+CT = 370e4b8580c083a581c216f358a33ba719f32678b84bec3131aa5e4657c92e31c69ab18d447d3578
+
+[Alen = 18]
+
+Key = ae6136df9ab43631ef143515dacedbe7
+Nonce = c5c445792208a50c8e93d64aa3
+
+Count = 180
+Adata = e04006b68c83a5dd4ceac3cde238e48895ae
+Payload = 6a493c5ef3769ccc4101dbb2eb36e1e5bbc577a057ce0731
+CT = c7584c0203c2535c5702c6ae93b7cbfb066f4a055c627a180d6d676d11fce907b5c93fa1ed7bff2b
+
+Count = 181
+Adata = 5da64e368f45153ea5b7ddca966b6c5b699a
+Payload = 15e0c672c6764f3699d9d3e7120f8ce5daab166f08fdd074
+CT = b8f1b62e36c280a68fdacefb6a8ea6fb67012bca0351ad5d2cd45f211b1a1364c91ad07959bf0ee5
+
+Count = 182
+Adata = 1b315d024bb5d1e03d7510e61f37d8adb10a
+Payload = de907d58cd8f5a72acaa1d329b937dfbbfed65a4e45eb029
+CT = 73810d043d3b95e2baa9002ee31257e502475801eff2cd0018f021a98b2edfb0b7500363099c2a1a
+
+Count = 183
+Adata = 8691ba4f9232ca86f919fe72ddb39c91d707
+Payload = c7fa314d27be79f9d3e2d1e188c1785b0c970f91b8ed4290
+CT = 6aeb4111d70ab669c5e1ccfdf0405245b13d3234b3413fb92ac9aeb018c48f3902276ac759710b6d
+
+Count = 184
+Adata = ff0baf1cbb5884a9290ea7b5ee49915efb4b
+Payload = 33b05b20f3c849fac091a5028cbfa0bc9a1c32514136fee3
+CT = 9ea12b7c037c866ad692b81ef43e8aa227b60ff44a9a83ca7dac49f606dadb9f7034e0a1860d519b
+
+Count = 185
+Adata = 2d118cda20700bc2748ea1753fbca6f74933
+Payload = f43832e420e2eccd5d80502bea2ba1804e17d4433318fc86
+CT = 592942b8d056235d4b834d3792aa8b9ef3bde9e638b481af623ccbab19c1442806e21c5a820945da
+
+Count = 186
+Adata = 0c7a5fd2010c999a8a0efa81f89ff5bfefe0
+Payload = ceb203c842a962183f22e602644fc66e4290b3d5be445fb4
+CT = 63a37394b21dad882921fb1e1cceec70ff3a8e70b5e8229ddbcd18947ac1800856c9c92eb0388c70
+
+Count = 187
+Adata = 73fdddb9e0a64f5671fd70c4ea8443507789
+Payload = d6015b6bd5f5eabb2a649129f8f727c06a3ad59499f21caf
+CT = 7b102b372541252b3c678c3580760dded790e831925e618639c29ea73b0c5aa130d8b14f7b9926a9
+
+Count = 188
+Adata = 82c4484e3a6e18b6bbfd78b69b00c40b30c5
+Payload = c288b810fb533441bd549d02c0b28d5b834293683eaacda2
+CT = 6f99c84c0be7fbd1ab57801eb833a7453ee8aecd3506b08bf0a0f148ae138c2ea02538c8fd7ac76c
+
+Count = 189
+Adata = 267d8385b14721eded743cffd69e4d595f7e
+Payload = 667cc47d13c34923be2441300066a6c150b24d66c947ca7b
+CT = cb6db421e37786b3a8275c2c78e78cdfed1870c3c2ebb75285eb537e7583f04e040a0ddc41106213
+
+[Alen = 19]
+
+Key = f1908328edf2996ebfc9655472ca5ad0
+Nonce = 4c693364546930b6c5250e2699
+
+Count = 190
+Adata = 4a3634e5028df97fbe00eb016e8ea4f1918faa
+Payload = eede01b08f9a303cdf14c99d7a45732972c6eff2a1db06eb
+CT = 90c850790b0b380f5aeb2488fdf43c9d5ef1759861e86f6e52570e769629dcc2e568737ba53a1195
+
+Count = 191
+Adata = 041b93e3fc059fa44aa755e88df277b9b6e499
+Payload = e61ca7310172eec16745a73e34516f65844eecd0dbc5566a
+CT = 980af6f885e3e6f2e2ba4a2bb3e020d1a87976ba1bf63feff1d82ec19a2e3ec43bbdb34e10999d90
+
+Count = 192
+Adata = d1be393376cb5d23cf8139da0fd92f3d520ae9
+Payload = ea887edee68ad5fa6bae928aa480dda898037f820700ec52
+CT = 949e2f17621bddc9ee517f9f2331921cb434e5e8c73385d7f2abb0ce4de9eeb5e8af9cdf3391d3cc
+
+Count = 193
+Adata = f3e551b34d2db1286a9f41085e4dda95ec3f75
+Payload = 71fe1ba5d299495d2a56039c64032ec6263d437f55e3f5be
+CT = 0fe84a6c5608416eafa9ee89e3b261720a0ad91595d09c3b239c73b01ba49a8498b5ff4833851069
+
+Count = 194
+Adata = a69ddc66e63a3415f21009d53adcf26bc1a9a5
+Payload = bd04d854216740a6ceb9827cbddd83761d19feb2a21d78ef
+CT = c312899da5f648954b466f693a6cccc2312e64d8622e116a2248dacd3903c26a2dc5ae649566ad67
+
+Count = 195
+Adata = 5735d6f5882d8f27155eb4cc285a65138ad64a
+Payload = 33b44873a7a1e5b0fdbb7e7347623e4fa1ccd937feb26fda
+CT = 4da219ba2330ed8378449366c0d371fb8dfb435d3e81065fd4156cf7d97b2e744351b6960a807cf8
+
+Count = 196
+Adata = 5d94ed976ab2063512690ae704c3b115519742
+Payload = d3909d577a4e89642227cc6fc146b61bc18392175e342898
+CT = ad86cc9efedf8157a7d8217a46f7f9afedb4087d9e07411d5a50086b6711ac72533c3c5717f6892c
+
+Count = 197
+Adata = db20b384620ab8691aed2fed14a745188d94c0
+Payload = ba0716355fffb8ef947d2a15eb58375a1ff1084c56699029
+CT = c41147fcdb6eb0dc1182c7006ce978ee33c69226965af9ac54fb74ecb9a5163b01b9dbf97ff2f999
+
+Count = 198
+Adata = 94897cdd04e0c8480b2ef7b5201dda37558ba9
+Payload = 5f4b4f97b6aa48adb3336c451aac377fde4adf47897fd9cc
+CT = 215d1e5e323b409e36cc81509d1d78cbf27d452d494cb049d2a81702f665ff5c54f586defd268c94
+
+Count = 199
+Adata = 95c44e1e5ad256b3ce1cc1d87137a1e09f1fd4
+Payload = 598e91d39c414496fd5e69f2cf80826b4e7d59ba28e0a0d8
+CT = 2798c01a18d04ca578a184e74831cddf624ac3d0e8d3c95dfa641889723e163825ab65727e8a5343
+
+[Alen = 20]
+
+Key = 61cb8eb792e95d099a1455fb789d8d16
+Nonce = 1f37b3e59137f2a60dc09d16ac
+
+Count = 200
+Adata = 09db3efac9473f713da630ae92c2c8604c61c51e
+Payload = 6ad541695a37c32d73ff6d5f870abd5b0f362a8968c4fce0
+CT = e65fcc975865c1499b088b58ba163283085d8ca68dc3b235d89756e5d78753ef22c012ae34b39a20
+
+Count = 201
+Adata = b6d07035aed9c141c713cc3bce60f7ba8ac2545f
+Payload = 9cce4c82fe9d38ef64ac8abdf0619f201a25ce6903675627
+CT = 1044c17cfccf3a8b8c5b6cbacd7d10f81d4e6846e66018f2fc78ebae9c143a7283b0641e1f83f5a0
+
+Count = 202
+Adata = 80a5ab693378af29cd5a33555cb3579f9ae540aa
+Payload = 7295a7aed3e987baef19ad68c33ba5a5dcbff27875ff5236
+CT = fe1f2a50d1bb85de07ee4b6ffe272a7ddbd4545790f81ce35a7e44348d2b3085348f787128a4e96a
+
+Count = 203
+Adata = 220817144a15a0a654fc1beaabce60270aa72df8
+Payload = eb21fe20fc4f92452b261eac0d7b70016f7469afdff7a3f5
+CT = 67ab73defe1d9021c3d1f8ab3067ffd9681fcf803af0ed2024dfc096cd8a09d2d81f6146fb54082a
+
+Count = 204
+Adata = 5a2423c2ff2d642c80ac1ca27dd779321f3e9c01
+Payload = 23bf80f51dfd83f63986910e69d54a315c2bfb43f432b7de
+CT = af350d0b1faf8192d171770954c9c5e95b405d6c1135f90b5da82204f4dd8f535cb2fec2f133d882
+
+Count = 205
+Adata = f2c76ef617fa2bfc8a4d6bcbb15fe88436fdc216
+Payload = fc3a50cc8a68778327923ea697f5388da4c814381e29c5e4
+CT = 70b0dd32883a75e7cf65d8a1aae9b755a3a3b217fb2e8b31108630135498ba409f4b6c8caee8a85b
+
+Count = 206
+Adata = b40c8c1d2cee490653105ca2443356cdb63e4fd0
+Payload = 465e41c69928d08c33e063ea119595a04d0de6bffd17bba5
+CT = cad4cc389b7ad2e8db1785ed2c891a784a6640901810f570f89c515837d129ba41f9c24b0229ddcf
+
+Count = 207
+Adata = 6ebfa1e8f80b3cdb1bedf2e3c7e74f30f55c38e1
+Payload = 3f98ee3922f8f1086e3135ae66c5465426b13c8794954880
+CT = b31263c720aaf36c86c6d3a95bd9c98c21da9aa871920655a352fa6b9c4e40733ddcd3fcdaf9ae63
+
+Count = 208
+Adata = 6d0159861031c1a5f01aab35927fe2ab28154d19
+Payload = 5b43067a5ab3a9f9e633fdc084c44ffa7f11edd12ea5873d
+CT = d7c98b8458e1ab9d0ec41bc7b9d8c022787a4bfecba2c9e82c1aa13f062c0f1f5008e27ff2191942
+
+Count = 209
+Adata = 15e5ade017b30ab41878a2747e93aa91c61c2908
+Payload = e40b7e9e46e339e64891526e730b3bf6562fa37acefce307
+CT = 6881f36044b13b82a066b4694e17b42e514405552bfbadd2e149dd02bc7face0c4dfe4e501c2ac2a
+
+[Alen = 21]
+
+Key = be1ed49e2cb0caf6b6a0940c58453b93
+Nonce = b78ad129457681fa7346435b97
+
+Count = 210
+Adata = 161d92c7df1ebb0924719e066e08b95eb4914a5eda
+Payload = a9eec383f63892521e4616fcbadc5485942ffaf4669c43a7
+CT = 949be340720c4fdc4adc05cb777dd81a2549628d33fba07e62d2b338a7b34ebd9d85c244c952d681
+
+Count = 211
+Adata = 6b1d94bc0c6e45fc905c509ea667853e4b2c5a8848
+Payload = 7b44a093162bfc8b4d65f1031d890a6b08a3705b142c0c26
+CT = 46318050921f210519ffe234d02886f4b9c5e822414befff8a4defafeb3d61dad8c007b68d8fb9b3
+
+Count = 212
+Adata = 868dd3e241f60f097a7a2fe571307ee5eb961218ca
+Payload = 28c4d6de3e2ce51b849b135d9cfd3084f0e3155447cad9d5
+CT = 15b1f61dba183895d001006a515cbc1b41858d2d12ad3a0c57cbab553b511d68a4f41db211d0a2fc
+
+Count = 213
+Adata = 3776f37fbf8803bdfd246ffaff2e59658a6c3f0ebb
+Payload = 16d345606a315ad2406abbcb43cd8cabe948107ba6d17a72
+CT = 2ba665a3ee05875c14f0a8fc8e6c0034582e8802f3b699ab0290fd7dbf0afa3e597274e3c9fe170b
+
+Count = 214
+Adata = d0f2769eba9b8e618f00eed6b34c261c59322a253b
+Payload = fcbbcdd9599a86e7c8ccb9347065789a9728ca1220fa51ca
+CT = c1ceed1addae5b699c56aa03bdc4f405264e526b759db2139c7dec3960e6aba3174d793b4e08f449
+
+Count = 215
+Adata = 2be180892faed0bb75887668d187807666d3c66c68
+Payload = 8d145b1f792cc31a2e5b86216609bb018e7aea3012ff70a5
+CT = b0617bdcfd181e947ac19516aba8379e3f1c72494798937c7057b9e2d844e86ee5c3ecfb3270804e
+
+Count = 216
+Adata = 52859849a5b7c1d432c3bfb35271cd8141db2ec774
+Payload = 741db990b43ef34993c33d1c4953b67b128b9299dfe86d74
+CT = 49689953300a2ec7c7592e2b84f23ae4a3ed0ae08a8f8ead1150fa899152eef7a30ae0f20986818e
+
+Count = 217
+Adata = aa192759625f4e42d1d1fa73dc0f62199142155615
+Payload = 51dca5c0f8e5d49596f32d3eb87437bcae866640310ce1e3
+CT = 6ca985037cd1091bc2693e0975d5bb231fe0fe39646b023aba7ff9203608089558698ec29472dda7
+
+Count = 218
+Adata = 6de564226884188ec7bea3894535a875cff2a42fdb
+Payload = dfaa7aa8b28626210d5c24e2ddfe516189be05aabe26f3b2
+CT = e2df5a6b36b2fbaf59c637d5105fddfe38d89dd3eb41106b85bd0a5074ef852575baf5f12c22663e
+
+Count = 219
+Adata = f245f2ee23755df863dee55d7ef0c3c09a0b6f0b0c
+Payload = eedf00aab5edefdd6549d37ed44358e11c588c24f141dc57
+CT = d3aa206931d9325331d3c04919e2d47ead3e145da4263f8e9eb617436bae012331daf020fce24e47
+
+[Alen = 22]
+
+Key = 34ab6fd7f54a2e0276fcb7cf1e203aba
+Nonce = 6091afb62c1a8eed4da5624dd7
+
+Count = 220
+Adata = 1ab5cc3d7b01dc74e6cf838bb565fea3187d33d552a2
+Payload = 8d164f598ea141082b1069776fccd87baf6a2563cbdbc9d1
+CT = 0d30ab07153b5153637969e6bd3539448c541e42b3d432fd7ef14622a9b621d1721b944c60f7fd67
+
+Count = 221
+Adata = 1f1ac4674b272bc7a4ee9f4eae33e969b16fa90a69ba
+Payload = 14e99a2ef0de650adbd785c692342cdb765e6d20d5fca09a
+CT = 94cf7e706b44755193be855740cdcde455605601adf35bb6dfa4ec2c92671c64ee07946527be67f0
+
+Count = 222
+Adata = 43ee77f12ea42e82a02275a68aa95cbd1bb440442bcf
+Payload = 383242c709fe5f2ce782bf8c83b645d171f2bd238abc655d
+CT = b814a69992644f77afebbf1d514fa4ee52cc8602f2b39e71173572fbf3d9495760aae4347397b110
+
+Count = 223
+Adata = ae2ff288199be25bf640811541394ad7e1dd0dc0d24d
+Payload = 9c16a5b638c35c97c5c981c1b8dbcba11aec30e72e45a936
+CT = 1c3041e8a3594ccc8da081506a222a9e39d20bc6564a521a4d2327956e030b9df753e063b5b71201
+
+Count = 224
+Adata = 4ccfb4281852b5ca7e787723d689384a68ff9437db31
+Payload = ec9d8edff25645520801b6e8d14a2fc3b193db70d5e5e878
+CT = 6cbb6a8169cc55094068b67903b3cefc92ade051adea1354e4dac0c9130f5641afd035dd884b6271
+
+Count = 225
+Adata = d3a2fffc798fd9cc2f409471faf18caa2ff3dcf4e652
+Payload = 0db33eda4188a9165147e24e40f79fee1985eb68d5162728
+CT = 8d95da84da12b94d192ee2df920e7ed13abbd049ad19dc0448807dd50a9cf41651083c49c7493ceb
+
+Count = 226
+Adata = 7b5121aa4d1e314f209ffe3e92cd26ee4f74d91e27f2
+Payload = e0d3ea4308376423c4322503f56e427a64e2e6d8b4f5e668
+CT = 60f50e1d93ad74788c5b25922797a34547dcddf9ccfa1d448ea0da53046733f522ded40a09c6d7a6
+
+Count = 227
+Adata = 6e12c112720ef346bbbe7d1c19483721b1c52c438dad
+Payload = 491f2bca585d6b5fdf38d18890e4d1bc923fe26930b3d2f1
+CT = c939cf94c3c77b049751d119421d3083b101d94848bc29dd345cb5a968f39654b994686699d532c2
+
+Count = 228
+Adata = 20433402a2d869c95ac4a070c7a3da838c928a385f89
+Payload = f45908d691ddaf89c0bc129ffada94c3ceda5f47d63ef76a
+CT = 747fec880a47bfd288d5120e282375fcede46466ae310c46cce85eb55339b886b7121b306fccc0b2
+
+Count = 229
+Adata = 42f944c21cc221beaacb288115ac628346b8a1d94bd5
+Payload = e300fc7a5b96806382c35af5b2c2e8e26382751b59010d4b
+CT = 63261824c00c9038caaa5a64603b09dd40bc4e3a210ef667a37ca5ce12aa6f0659467642deb8bfcd
+
+[Alen = 23]
+
+Key = ea96f90fbae12a857f5c97e0cba57943
+Nonce = 21cc46d9ced1539b0ad946e600
+
+Count = 230
+Adata = 105258d2f25f62675aee975cfdb668aff833f05b61eb2a
+Payload = 49db80f22bc267a70e5636dfbc8a21c83d9691fe4b9c3051
+CT = d2fcc8b7809b5fc07e44083e437d8180157f1782a9ce9f65c7fa9ee2e7cdc1b755258f2212a8a8f4
+
+Count = 231
+Adata = 0f5938540651fa4ca03867e67518eb2b73f60dd8750fa0
+Payload = 26618e21099a79d6c517335389551323065ad89c8848ea12
+CT = bd46c664a2c341b1b5050db276a2b36b2eb35ee06a1a4526bfdb9bfcd3b969fb2e41221eb92b0147
+
+Count = 232
+Adata = d6b228960fcbcf07c7bede616139db62b3808718a5b511
+Payload = 4de1d6d57144896ddea1c30f49afecd27bdf4840ed9928b5
+CT = d6c69e90da1db10aaeb3fdeeb6584c9a5336ce3c0fcb8781f8beea22cba93203c912209c78c03aa1
+
+Count = 233
+Adata = 75f8f071e229355e286882917ce5dd4f1db591fee51b6c
+Payload = 785359b1dc754a1e1b6d8731bd2d917ce3e91507401310e8
+CT = e37411f4772c72796b7fb9d042da3134cb00937ba241bfdc69a2e3ea4a40f7c491912c1a0778ebde
+
+Count = 234
+Adata = 4afb62aa8648ac7474dd16fcc376f8909c69e1ce36e6d1
+Payload = ab627aac1496d011ed2edcb2fc6b2afbcc394654f56124f6
+CT = 304532e9bfcfe8769d3ce253039c8ab3e4d0c02817338bc2a75c7ba2a769c27903e99b72639b0841
+
+Count = 235
+Adata = 736fdf94db820a2efe89e7fc9dcfe7c23d5754ac2bcc7c
+Payload = 40722cffb37f1455c2618408e777ed0f4b1bd039952730cc
+CT = db5564ba18262c32b273bae918804d4763f2564577759ff8f84f4ca4a69fde75d7207e50494819b6
+
+Count = 236
+Adata = 8a9a0367137c28db4c4e78d9cd9a68cde0d1b4583532ae
+Payload = dcaabf7a061502618541c09ea59dbbbd52b2692fd0064747
+CT = 478df73fad4c3a06f553fe7f5a6a1bf57a5bef533254e873a0c34a24d3ee0946034c71fba4dbb333
+
+Count = 237
+Adata = 34dbbff560ef04ea731b8979aef2ae50972f4db3efe14a
+Payload = dd641a893b16e0e173ea2eda20638bb01849ac11e64e8ddb
+CT = 464352cc904fd88603f8103bdf942bf830a02a6d041c22ef0f5e24a435a39a716c39f43dabdc4281
+
+Count = 238
+Adata = f3d1fcd912252431db9d8ccfc3e203d5b34d537468b4c6
+Payload = 9aa3e8ad92777dfeb121a646ce2e918d1e12b30754bc0947
+CT = 0184a0e8392e4599c13398a731d931c536fb357bb6eea673f623d59f66764d859a772bb50ec91fc3
+
+Count = 239
+Adata = 513b4cdc551c203ed5f1e659813584862023911590b672
+Payload = c8f44ae4b02fffdbce0df773c24075f877945fc7a86be460
+CT = 53d302a11b76c7bcbe1fc9923db7d5b05f7dd9bb4a394b543b6549eb16fba96318afb3df51f4675f
+
+[Alen = 24]
+
+Key = 35b403a15212097085d6e2b77ec3d4f2
+Nonce = daa423bf9256c3fcc347a293aa
+
+Count = 240
+Adata = d3c0ed74e5f25e4c1e479e1a51182bb018698ec267269149
+Payload = 7dd7396db6613eb80909a3b8c0029b624912aabedda0659b
+CT = 5b00cf8a66baa7fe22502ed6f4861af71fa64b550d643f95eee82c19ecba34280604b58d92dacd3f
+
+Count = 241
+Adata = 62f4fe53e99a9b0c51e9561d910d7e2ffe19a5176c9dec06
+Payload = 897f0dfd90213f64a9277a0eda4f134f303fa89f56ca54fb
+CT = afa8fb1a40faa622827ef760eecb92da668b4974860e0ef5ab4999e9689d52b8afeb87923efa3b48
+
+Count = 242
+Adata = 191c4dfa653c20292657f7694c6b6a4a410c49a879abd217
+Payload = 2b7cf9e6e2d6abcd7775f8a6eb6294e822041c4c45f09c3c
+CT = 0dab0f01320d328b5c2c75c8dfe6157d74b0fda79534c632cdc71e556c34fd4e1b5ebc50d38da8b3
+
+Count = 243
+Adata = ba34741f8edb51470eb20f891869aabeab562d92571ac943
+Payload = dccb9a4625512496b372a2b8b768f75741d8c2e30e57d638
+CT = fa1c6ca1f58abdd0982b2fd683ec76c2176c2308de938c3646223d381090661c2ee2370d29a572a9
+
+Count = 244
+Adata = 8b922aca6125722ec490b134a45864397f4e2c281d6e2089
+Payload = e0e452c990665465160b02cad6367ca89723613488d8efbf
+CT = c633a42e40bdcd233d528fa4e2b2fd3dc19780df581cb5b1f78af50466646b7c7e652f787afe5357
+
+Count = 245
+Adata = afb9fd78e3f8eaf4e8c91da62b2da534508e54f7dfa214fc
+Payload = b536fdb8839f87080ae65ec35da347e792622ffe18a61d46
+CT = 93e10b5f53441e4e21bfd3ad6927c672c4d6ce15c8624748cc9d9a1270f78648a6b66cb8c0f2471b
+
+Count = 246
+Adata = ecf942ccee7396cb3ee177eadd4d96a4af1d90afdce97376
+Payload = c81233826e5125e1f31fe275184ccba8f1a743e58e146e4d
+CT = eec5c565be8abca7d8466f1b2cc84a3da713a20e5ed03443b17d3d6f1fc4f530841b749d9f3a0a7a
+
+Count = 247
+Adata = 16fea92ffcaad563792aa924bffe7ef690edc90ea4e29cc0
+Payload = 24ab253b5b06552665c3c810254c0ed15e68a783180d7eee
+CT = 027cd3dc8bddcc604e9a457e11c88f4408dc4668c8c924e05852ed48cf88d9ab2326aa46b6541b60
+
+Count = 248
+Adata = 76f110eecd369d79e21fb208058359d3a2f37581d1f7f691
+Payload = 7f596bc7a815d103ed9f6dc428b60e72aeadcb9382ccde4a
+CT = 598e9d2078ce4845c6c6e0aa1c328fe7f8192a7852088444c62dff6bcade5ac2edb8ec9797ce433e
+
+Count = 249
+Adata = 8834c776a3237f060ae0ab9857324a3b2ac79f3b6e6f90f5
+Payload = 11cbfb3d348c7abef99f562607e289de34a2bb379a5dfe50
+CT = 371c0ddae457e3f8d2c6db483366084b62165adc4a99a45eb936ac4764575f85352c24ab23209d42
+
+[Alen = 25]
+
+Key = 7a459aadb48f1a528edae71fcf698b84
+Nonce = fa4616b715ea898772b0e89dd4
+
+Count = 250
+Adata = 0c0b4a45df5c3919c1e1669c5af5d398d9545e44307d95c481
+Payload = 0b3d947de8632dc8ff752f619ba7c84716fac7a23e101641
+CT = 7db9f3f7dc26fc2adf58d4525d26d5601e977de5a7c33911a1138cff7b624f9908b5b4d7e90a824a
+
+Count = 251
+Adata = aa27a28a36b5a2cee57ffeca0233feb4bdd4eacb2cae28e98f
+Payload = e6dedce2c278c44e5678d13e7d5b5d3501d61bb0bb6b5558
+CT = 905abb68f63d15ac76552a0dbbda401209bba1f722b87a08e23f92b598f7a248a894e6b8f5691bee
+
+Count = 252
+Adata = 66220aa9b40a1772caba7749a544bff938e804dbc6e556498f
+Payload = a276b0922fbd5094bf89b9329d07341e039d6204397b81c0
+CT = d4f2d7181bf881769fa442015b8629390bf0d843a0a8ae90e94043c0d80fd651469232fe9d47a81f
+
+Count = 253
+Adata = 3d765d20e03a4cebfda50316c4b7d8b6c55078d5b3e9cbc567
+Payload = b99afbc2dbb377350cc58d4bfe8e954cef25d7b27b82fad4
+CT = cf1e9c48eff6a6d72ce87678380f886be7486df5e251d58425088b522fc0731097e729448236b317
+
+Count = 254
+Adata = e91b6265879153e1692b00a112b4205111c8eb1a7b7f2c6898
+Payload = 56114cc783b80ca2dd2881387b6d92a59a237dfc8e976d8b
+CT = 20952b4db7fddd40fd057a0bbdec8f82924ec7bb174442db2208cf07574cc4f3f83ed6301b904404
+
+Count = 255
+Adata = 340b16f352817babb4fb70e9e6e18784b3e67bdd449872158c
+Payload = eb21fe20fc4f92452b261eac0d7b70016f7469afdff7a3f5
+CT = 9da599aac80a43a70b0be59fcbfa6d266719d3e846248ca514b0a900068e55cd24c92bbb78c521ad
+
+Count = 256
+Adata = 5a2423c2ff2d642c80ac1ca27dd779321f3e9c01445be684dc
+Payload = b15083a73607c9d7e197a8cc884ad3be98ac343f6493df67
+CT = c7d4e42d02421835c1ba53ff4ecbce9990c18e78fd40f0373f8ba66d74321c80c057f010078d2f28
+
+Count = 257
+Adata = 5fe8bb27a59a5f4e370adbba96484c2365fc0d8c6e58d7d3e6
+Payload = 07542d18e8f2d3e199fca0f90cabb78b169525fdce81666a
+CT = 71d04a92dcb70203b9d15bcaca2aaaac1ef89fba5752493a0a189319e4f06d53c1405d37b06cc8eb
+
+Count = 258
+Adata = 23e5422e8d7560a9e65642b5e723a47536c16791f3a0cf918d
+Payload = cd574ed56bdfd1408f7831e0b24b4345ee979ac906a7aa22
+CT = bbd3295f5f9a00a2af55cad374ca5e62e6fa208e9f748572dd72f48ae03670249d74f8460b63b1ae
+
+Count = 259
+Adata = fcc9422ba5023a9997baa9c4ee6cb196ffe96e08eb9c2b8a75
+Payload = 8c9abe94beed4c9bd46adb1d04fbfe7016dd50d324525abb
+CT = fa1ed91e8aa89d79f447202ec27ae3571eb0ea94bd8175eb1717c00c93d36a77141b723d573c8c65
+
+[Alen = 26]
+
+Key = ca748225057f735f712ecc64791367f0
+Nonce = 1341a6998eb1f50d4b710a13ac
+
+Count = 260
+Adata = 5fb96b045f494808c02014f06074bd45b8a8ad12b4cb448ec162
+Payload = e92cd0cb97afe4fb00c4f12e9b9abe1d08db98f49a27f461
+CT = 82b666694232e86e82295beae66ae67d56aceb5d6b1484ceb4a6843ec16078038c10afedc41f5362
+
+Count = 261
+Adata = 87db0d9d69bc0cf69cabeb92570e482bbc8ff3e1ba72f12f3225
+Payload = a6dbad96ad23ff61479df39b99f0673a09f2a7eaebbd34b9
+CT = cd411b3478bef3f4c570595fe4003f5a5785d4431a8e4416a7c6566d0b8ff97f946d7c7773a845f2
+
+Count = 262
+Adata = a061a09024f1e03b223695d4703ee202e90e07156b95859a22e3
+Payload = b1dd81cc3b2b0efe540a3194d6fe304cd2de53db7929ebe1
+CT = da47376eeeb6026bd6e79b50ab0e682c8ca92072881a9b4ee1d66a4728b67b42602e23c8500b0115
+
+Count = 263
+Adata = 0dd513c5d8d62b723ab8b0a3aaa477e843d9149dc8a2f878e585
+Payload = fb30c2e98f3d7e4ed7431da285711d3d287884db13a474e7
+CT = 90aa744b5aa072db55aeb766f881455d760ff772e297044803c51e8c59ed13b3e5d9b489d4ea2ccf
+
+Count = 264
+Adata = 3ff59c40bd796048e586eccc23a82e4d09fc5e779f38eb4afbed
+Payload = 886f9f91a6566ceb99c39462ab675a3ae3be98f68787626f
+CT = e3f5293373cb607e1b2e3ea6d697025abdc9eb5f76b412c0f1ec270b43fc5a9811b56ccf033789c6
+
+Count = 265
+Adata = 0df7ef91f7124da867e992bcbc6fb38232ff6d5205f38768da72
+Payload = ed370d1c2d6dc03e4fae4deb9343a7d4339562cffd427587
+CT = 86adbbbef8f0ccabcd43e72feeb3ffb46de211660c710528bb4ed25940d58cba64271fe1d2e8013d
+
+Count = 266
+Adata = 6777de159c34d005b94f67c33ae4a35ebab09d9cb9c56b4c9c81
+Payload = 2f77c2eb07db14bd713c5af10c0760ea3a6ca5ff8d046d36
+CT = 44ed7449d2461828f3d1f03571f7388a641bd6567c371d99392636a5e373c1354ea9b969abb4932a
+
+Count = 267
+Adata = 75559898f4ba03c55afc25ea91aa61a93c2f8270a5fa51b6f6dc
+Payload = 360fb89429dc9b48358097d930c8561b2bd18dc0a470d1d6
+CT = 5d950e36fc4197ddb76d3d1d4d380e7b75a6fe695543a17959a7e8bc0570f19159f91fc14ac6532a
+
+Count = 268
+Adata = 5e03fc430473c5de96d68907fa506f9da353ae48a965445e1f24
+Payload = f2d8d67b9f291c3edc264893922622b2693f3e7231137eba
+CT = 994260d94ab410ab5ecbe257efd67ad237484ddbc0200e1507e559568c27a30b5676f98cc66f57d6
+
+Count = 269
+Adata = 7eee4869e77f6db12c91d1f647cad2340d33a3defaeb362d311d
+Payload = 7fd6fb81c36e44b150af10e04683b1ec9b5dda87c71ff939
+CT = 144c4d2316f34824d242ba243b73e98cc52aa92e362c89964910615920f6f3c3421a9c2bec1bec7e
+
+[Alen = 27]
+
+Key = fdf2b2c7fcb3789b4e90abe607dca2af
+Nonce = a69ddc66e63a3415f21009d53a
+
+Count = 270
+Adata = c76846da496ed87b9c0f65c6266c9a822224acde9775efb186a4a5
+Payload = d7aa4efa5d75195a400018bd38f7d8cd53fdffe88df1837f
+CT = 150d9a8b78d9c04239d66207a1f95021bbb1b7c70d7c354825d05e5a2e76a90f6fe489fd74cab2a3
+
+Count = 271
+Adata = 4efbd225553b541c3f53cabe8a1ac03845b0e846c8616b3ea2cc7d
+Payload = 5f94a2e48d348a1d56c55a659306e319c3d2ad78b9fe43a7
+CT = 9d337695a89853052f1320df0a086bf52b9ee5573973f590be6af49ce97d5e0e77c7fd5d9cc6d932
+
+Count = 272
+Adata = 7631cf7822a545daefa16a5ec43c877d475a82d5aa2d51cec7fbb4
+Payload = a44b010fc1c659eac9241a58b11a73d7ce33156ddfc54c3c
+CT = 66ecd57ee46a80f2b0f260e22814fb3b267f5d425f48fa0b924b268cab915f999aea3e1cc3a88ccd
+
+Count = 273
+Adata = e4da34663edc44370bfd8aa8315945471a893a1cc069628a071ee0
+Payload = 28d157f5741f1be057d5219711414c0638b47d165a905a6a
+CT = ea76838451b3c2f82e035b2d884fc4ead0f83539da1dec5dc368f5af8e311e67209e02dfa2613377
+
+Count = 274
+Adata = 077509eae1dc367540f87832c5780f6c5b29e180bc6c1fee38e826
+Payload = ba7432a8e34bfaa91b35c8dfd822d86850be39e63150257f
+CT = 78d3e6d9c6e723b162e3b265412c5084b8f271c9b1dd9348ad175fcad35d29396380b79a28784cff
+
+Count = 275
+Adata = a513d750ca1e8bf6cb7b8cea5204e064c15c2dc40d742b31cf5459
+Payload = 3f5830b0ce8849a660af7d58a60c19a9824a3033bb5fed43
+CT = fdffe4c1eb2490be197907e23f0291456a06781c3bd25b7493b4b3e33d325359c9c651290ce73bed
+
+Count = 276
+Adata = e439db829c1291df49fc42c2fa1a92118c2665f11e13f28dc6f11a
+Payload = e69b2a243340df5dc70b2cb05be12e5992ee36f7d9f4ca84
+CT = 243cfe5516ec0645bedd560ac2efa6b57aa27ed859797cb371f88ca5857c6d801e726a01c621a0c3
+
+Count = 277
+Adata = a12c690568114fd7a677f49d74e84fc1a6b7f7d2a08693266c0a91
+Payload = 9de35b840a69a84701ffae1b1d2bf13c34b42a57d14c524d
+CT = 5f448ff52fc5715f7829d4a1842579d0dcf8627851c1e47a0592d360fc6a46aa18c4ce5d74fa4532
+
+Count = 278
+Adata = 1813bf176a1127f4d508d7663ae750f9c4bcb84a6e26811ac60d46
+Payload = 9e2fa20bf76768a5a1467d90a048bb503a2c33bbbaa71653
+CT = 5c88767ad2cbb1bdd890072a394633bcd2607b943a2aa0648b772cef893495cf0a94e8ebf06e920b
+
+Count = 279
+Adata = cc6e9cc2699d3ba0e624e715599480d6b7dbc6eeea0d12a9236444
+Payload = 6681b1cbeceea57a828324831407280b00f4917ed52a10df
+CT = a42665bac9427c62fb555e398d09a0e7e8b8d95155a7a6e8b1851d571a1ef8aed565b784dcaaac4e
+
+[Alen = 28]
+
+Key = 7d870d7e52d3053c65eefad47764cfeb
+Nonce = 37d888f4aa452d7bf217f5a529
+
+Count = 280
+Adata = 9610949f6d23d5b1f3989b2f4e524fab4f297a5bec8ddad4f16cb616
+Payload = 109317556c21c969eda65a94176d7a11462c9ae18a865b6d
+CT = 4e6b967b1571c6d7b9e118b112b7ac949a4a175650316a242dd579cb0d201d22c86bbc7fbe47bd0d
+
+Count = 281
+Adata = 96118dbfe53434d8aed88769a535eb0c8b5849dca1c81c34626ac9b9
+Payload = 3e6c914a196e175079315b1c92b2b8a844deb472e249e3d3
+CT = 60941064603e18ee2d76193997686e2d98b839c538fed29af0dd7aef4a609f3587652173446ebd82
+
+Count = 282
+Adata = 21fc96f73975298207f818909088295d6d6861677130ca258c2174f6
+Payload = e0014147d5771b4380dc0192d45f36f7d60776d1ba47374d
+CT = bef9c069ac2714fdd49b43b7d185e0720a61fb6660f0060463e4405d45caf4836467edbf35089d87
+
+Count = 283
+Adata = 72a5151abcb55933ff7c9314f3235eba2a400121454144c2670e8359
+Payload = 0f1c6dffeda98f7a159f9cc61820bfb29910d8eaa41b751a
+CT = 51e4ecd194f980c441d8dee31dfa69374576555d7eac44537441c813e90fac775eddb7290df059d9
+
+Count = 284
+Adata = dbbf192914b1ad73666e9f5e9c22c08ca398f7524af62b1046a863bd
+Payload = c1ddd14e380cc91324cf2a381df1da1ccffd90ae436a373a
+CT = 9f255060415cc6ad7088681d182b0c99139b1d1999dd067334d9316f1f1c3142c1c9b26e5c220a32
+
+Count = 285
+Adata = 28e4b88fbf04e9897057ff5bfde7eb04fa480256817a50fa281030b4
+Payload = d4dae9c4cae92afb80f9a5c99383ff16e23a2ec942eed4d2
+CT = 8a2268eab3b92545d4bee7ec965929933e5ca37e9859e59bc0b188e33bfab29b237d6c6920ce3418
+
+Count = 286
+Adata = d9ebc1cbfab9034317132a72e0f11c341331146a59e7a2f26bf4f3d7
+Payload = 8a188d40a6e6fbb06a9f06304349a7a808b092cc2fc10b9e
+CT = d4e00c6edfb6f40e3ed844154693712dd4d61f7bf5763ad7fdde04d21b876468bd9184101b5f32d0
+
+Count = 287
+Adata = 34ad69f192ae4dcab771aeeacf01bbd32609bcbbea8ff9df31ded719
+Payload = 590c1aac30ab166b1caff748452fc146765c372e226ffc26
+CT = 07f49b8249fb19d548e8b56d40f517c3aa3aba99f8d8cd6f068c65e9d0e5f1b81c86393900e64c19
+
+Count = 288
+Adata = f5e50ce1f99ed5e9f2baa54b96ae7039234b1131e734ec190695d28d
+Payload = 16d0522b2e691e42bd80ce95e00c8a7a1fc738169e904bdb
+CT = 4828d305573911fce9c78cb0e5d65cffc3a1b5a144277a9206ab3b72c56c8df4a12dba89a2f21276
+
+Count = 289
+Adata = 9b1e7e52ea1a12444d884866e11dcf367b70b816460936fdaebba36d
+Payload = 0bddf342121b82f906368b0d7b04df1c682ecd4c2b2b43df
+CT = 5525726c6b4b8d475271c9287ede0999b44840fbf19c72960170ca7b16d23537eeb3034105334699
+
+[Alen = 29]
+
+Key = 8fcac40527c0e7ca8eaff265ca12c053
+Nonce = ae9f012fd9af60a400e20b1690
+
+Count = 290
+Adata = 9ce65598cd1f86afc9aaaf172809570cc306333c25523f863c6d0e0154
+Payload = 78d1e96af8cebdcc7e7e2a4ddcfa34f6cf9a24fb85672ad7
+CT = 9adb9a95a9379ad795d8d3ffd4e37a045160d6d727f974a6cb3b5151f327e65447e52c7525562c91
+
+Count = 291
+Adata = e7c78ef4c4b959ee00cb1a09d71221a43892ef8ad705edd27ed85d03a3
+Payload = bc59f18c8473941abc681a92741ab5ee13679829f542b8f4
+CT = 5e538273d58ab30157cee3207c03fb1c8d9d6a0557dce68534e5b08e27d8f5eeef0f064ff620652a
+
+Count = 292
+Adata = f1bce6f2a4bdd3a07ebf5f8d47f931d27e7e63389d70e1059f701216be
+Payload = 5575d950312c14c89ac609dfb0b2fd1af732bb6aae5e8651
+CT = b77faaaf60d533d37160f06db8abb3e869c849460cc0d82044c0a96baae318f4714f0206812516b5
+
+Count = 293
+Adata = 3da3bb091016e54477dae88af1c84c1a51b59c1bb49a05deb6f32064e6
+Payload = df5947d8c6094ccc25816639ec42214b28731bfd7b8312dc
+CT = 3d53342797f06bd7ce279f8be45b6fb9b689e9d1d91d4cad4e7bdce2dc6aae24178aab6984f31028
+
+Count = 294
+Adata = c4cd183071c37a8157c6930a7d4d530cf4b7eb021682327810bd48209e
+Payload = 2fbb6dc235761875411ef59ae06110df8f15f66b721b0fd6
+CT = cdb11e3d648f3f6eaab80c28e8785e2d11ef0447d08551a7f18ece8260bd56ecdee768022d0dd8d1
+
+Count = 295
+Adata = 0e0fece7b6b659b642668e8ba3dca330523e70279155f485f3f6f8041e
+Payload = cd149d17dba7ec50000b8c5390d114697fafb61025301f4e
+CT = 2f1eeee88a5ecb4bebad75e198c85a9be155443c87ae413f6f0fb3b7440b84ddc3cc53819c2e93be
+
+Count = 296
+Adata = a35c6f70f637a9a5e6f215c694fdf65b6fd85f794ed3eaa1bc19abe592
+Payload = 030390adb572f2bd2a6a4454fd68236cd1d465574328aa00
+CT = e109e352e48bd5a6c1ccbde6f5716d9e4f2e977be1b6f47129ca778c51f9320f121dd803ece8d5da
+
+Count = 297
+Adata = c2992096828325820e2d7acaa17ac789b6830ec3128dd7f904398afbec
+Payload = f2d9cf953c8d3a051d9b3eae4307a3cb4fffaa2435b49586
+CT = 10d3bc6a6d741d1ef63dc71c4b1eed39d1055808972acbf79c223a5ad65120bfca4a5992e5ebc6fc
+
+Count = 298
+Adata = c023763a285ea934bc5bc7ddfc2aefe2b3f9eafe7b87c61383dcc07990
+Payload = 4b92e8d2ffaa4af8f3e0ac037a900bd18e195f490a3d71e1
+CT = a9989b2dae536de3184655b17289452310e3ad65a8a32f905c3bc4f618ffb3a159f4e2d0622cea6e
+
+Count = 299
+Adata = 0a39ec0163c7aeb1b4fbe7cb4fa5b0592fade70f430e23730a23ed4160
+Payload = 7c0e6a0d35f8ac854c7245ebc73693731bbbc3e6fab64446
+CT = 9e0419f264018b9ea7d4bc59cf2fdd81854131ca58281a376f099dce6e18435fba4d26c1e93bda0c
+
+[Alen = 30]
+
+Key = ddf9f150cc3f1c15e8e773663c5b061c
+Nonce = 98c5036b7d54da9a1177105600
+
+Count = 300
+Adata = 20c5ab290e6d97f53c74121951f39ba865b3acc465fa3f0fb8a591622277
+Payload = 79d8841ab83279724ce35e1a8abd4e158168dcf388ab4c3d
+CT = d00d29396ffa9e691290d746527777bf96a851f306d4da0b1816df1e0e82bb7bc8105930ad6a2232
+
+Count = 301
+Adata = 0e205a4dc5d5ead0d9ff7f182dc140fc49511c01b0fdbc7e6d6cb5fdf027
+Payload = 88b2572fbe7cf2b46df04db476ffedb41778ae2eb3c3aae4
+CT = 2167fa0c69b415af3383c4e8ae35d41e00b8232e3dbc3cd2df823c8ccd466807f2bd1c4032f0cfeb
+
+Count = 302
+Adata = 48043560d60381e83c11d4bc9d997d3ee2add6b0524b779c62dfaa73ce0a
+Payload = d44bf28b010e076b45db1b053af03db718b60748da51db1f
+CT = 7d9e5fa8d6c6e0701ba89259e23a041d0f768a48542e4d2931f5be8c9965345c760c72cc1b7908d1
+
+Count = 303
+Adata = f0729a8a2fd073699ab87b521cbe0420b43529556a505f5f87874d1a053c
+Payload = eab8cffb512eabe267cd64353552513defe97c2d10f35503
+CT = 436d62d886e64cf939beed69ed986897f829f12d9e8cc335381d94a828a95872ebdfda8a4c6a196b
+
+Count = 304
+Adata = fc2cd69bb61223f713e33a5071d09bf2783640c307c22d836dd94952dd37
+Payload = 001056926546c261fbbdf92b94498e038c2bcfd0b6345497
+CT = a9c5fbb1b28e257aa5ce70774c83b7a99beb42d0384bc2a163931808533f4f70d7a78242ced110eb
+
+Count = 305
+Adata = 8f653c5c003c807d16d17f833eebb97c9c2f0e5aae3780a52ce53a6c33f7
+Payload = 29ffaef9415fd300127ffd26ef324083a9d90e0f60e2ab4f
+CT = 802a03da9697341b4c0c747a37f87929be19830fee9d3d79f34553198f8e40fde6473f9cf04f1de6
+
+Count = 306
+Adata = 8d05e7d3077151c6d9378cb08e049e4d7c28a908f7f7c079c46ff92cd01b
+Payload = 9874dc5ca1b541f7b21c7b3860fa6b0c3ab1b712ab0fca98
+CT = 31a1717f767da6ecec6ff264b83052a62d713a1225705cae0fac20e8d45d2b0771d140b5e4a47c87
+
+Count = 307
+Adata = d4feb3ea76ac2945651f557406f3f38a2d7e9232ed55ff4eaf1201dd8255
+Payload = 1e01c7128c821fb9c971a27fc7c6f9bb902fa735de583b8a
+CT = b7d46a315b4af8a297022b231f0cc01187ef2a355027adbcd3cacfe4281e52d79e60eeb38319bc3a
+
+Count = 308
+Adata = 7cbb4ae995a3367a256cafd11cd6c6cab5bf3252fa97f27a8a1434ca9a27
+Payload = 51cd306fac7d20e3c7043eae3a6dfec046c5c24a666a0723
+CT = f8189d4c7bb5c7f89977b7f2e2a7c76a51054f4ae81591158f0d7646a799b14288bb2f354b5d8847
+
+Count = 309
+Adata = bd40b06a4beded2be3d176266b10772c7fa2949f0a9b20d613af90c2daf5
+Payload = fc5b26befc633a3e8ace011aa7a42bd0258a9f3dc14fc1c8
+CT = 558e8b9d2babdd25d4bd88467f6e127a324a123d4f3057fefd7f95e1d331e700aa9ef83f09b689fd
+
+[Alen = 31]
+
+Key = b1dc81d116d94f5eced526b37c004b95
+Nonce = 97c8f69fb91b17299461fd8d63
+
+Count = 310
+Adata = f8b08aa83bed09ca342249b2cf9e2b45a89dcfb8711a120395e455921af481
+Payload = 54390715b6e7c7bd51a234db059a51ba030cf22ee00b7277
+CT = cb629994c3418a662a8cde1b5f4d99aa7df66e24c53dc6df11297930fd44c63675b7cca70671ef4d
+
+Count = 311
+Adata = 0351c969dd38eeaa4b9b0000e346eeb1a2cd462033c59d9e6e3331822045cd
+Payload = 65b5e856a8cf35dffd42c5ba105cba4c434aa1c2a0390352
+CT = faee76d7dd697804866c2f7a4a8b725c3db03dc8850fb7fa7e77f5566ca2fd9293835bceb461dbaa
+
+Count = 312
+Adata = 5db8b6bc16740680f78fba917733a6899cdba5e4c10a8058963d1265681eaa
+Payload = 9a7685e3daac43ccf22cad0df900ba8acddc5d420846118d
+CT = 052d1b62af0a0e17890247cda3d7729ab326c1482d70a525ec2cf9f5d35521c1c000685e49d2ed42
+
+Count = 313
+Adata = e7d6024611210da0cfb90a9955195aa0a0539280a3a7c792a1540930daae2d
+Payload = c18d9e7971e2ae5fc128777086338fbe194443324e2d2cd1
+CT = 5ed600f80444e384ba069db0dce447ae67bedf386b1b987966f33dfb44ae413283b238616c6b99fb
+
+Count = 314
+Adata = 77a878c9c76f3e6a4ddd330d1d8828949d08e0fedffe0d8e2e557b29e7c78c
+Payload = fcf8982f7342f1b953658453cd5ea413700eff00f1ee7d6f
+CT = 63a306ae06e4bc62284b6e9397896c030ef4630ad4d8c9c731df6fc6b4cf0b6332936ed7cfe9455e
+
+Count = 315
+Adata = aa540554ee80dbffa475f702d862d6b60e0a4090792420a26d02926517723e
+Payload = 0d5690d2a7083ad6daf22b308314b8f5363aca77ca72835e
+CT = 920d0e53d2ae770da1dcc1f0d9c370e548c0567def4437f67c8162a815f2809601ad02595e2e0ff4
+
+Count = 316
+Adata = fae86f95dd06fb7fbae63a646615555aec8153dc328bdf79da5d4cc9677ed6
+Payload = f6e313cc35e8f8812b10a44f8ad00b6893f8084d942effe0
+CT = 69b88d4d404eb55a503e4e8fd007c378ed029447b1184b487fcaa11bdeab86f60f9cd0a2b45cee1a
+
+Count = 317
+Adata = fd525302d2fb246a47cf4e3a27808bda89d8488cf450f1a1c7df6eedd810ee
+Payload = 91e961ea2eb750577c5137c609602dbfcc4c07955ba429ec
+CT = 0eb2ff6b5b111d8c077fdd0653b7e5afb2b69b9f7e929d440a86a810881bd969744ad80f579400f1
+
+Count = 318
+Adata = 767b1bdf9793a512d3a84e99ef77b43011a3bcb8de4cd375dfe47a79293e01
+Payload = 98438c4411bead6f30c89ead762a12bf39391d3652b78b7a
+CT = 071812c56418e0b44be6746d2cfddaaf47c3813c77813fd2250ca00d3231819ecdf501ad39c864f3
+
+Count = 319
+Adata = aac7014f606df6feec415a75e29015891007f07518c955875fbf5619262ff2
+Payload = 540cb00c0eface3d1b2d632d80a642f53c78ff672a1ff6ff
+CT = cb572e8d7b5c83e6600389edda718ae54282636d0f2942571224d1d0294d46981d7dc39114a693d2
+
+[Alen = 32]
+
+Key = 5a33980e71e7d67fd6cf171454dc96e5
+Nonce = 33ae68ebb8010c6b3da6b9cb29
+
+Count = 320
+Adata = eca622a37570df619e10ebb18bebadb2f2b49c4d2b2ff715873bb672e30fc0ff
+Payload = a34dfa24847c365291ce1b54bcf8d9a75d861e5133cc3a74
+CT = 7a60fa7ee8859e283cce378fb6b95522ab8b70efcdb0265f7c4b4fa597666b86dd1353e400f28864
+
+Count = 321
+Adata = 55a62968c222a8501d1ae56a9a815667f8a9554607b7c56e6753f8fa92a4d054
+Payload = 764dbefb42644d18d23e5e4568685d14dbacfa418d36c4ef
+CT = af60bea12e9de5627f3e729e6229d1912da194ff734ad8c4423862a715dda2f63a4197f894515803
+
+Count = 322
+Adata = f8436e35b7a1c810ac6aabe8e2d48a3678d19e1e96337dada514ee5fc075fce4
+Payload = cecef24b62676a5623bedae8087b9b05d7e22b41a14dd2d5
+CT = 17e3f2110e9ec22c8ebef633023a178021ef45ff5f31cefec200f190bd700f6108f9959f6d12f0f0
+
+Count = 323
+Adata = 548e2152f3a15b8fb81dc01062d99f7b4fc8f074e5cbdc1030c97f8ccc02ec3f
+Payload = 53c164a4990c6e0637267ff2556c1542712fc584f6ff7458
+CT = 8aec64fef5f5c67c9a2653295f2d99c78722ab3a088368733a66ebc4e0777a6fc140a51e04a10f86
+
+Count = 324
+Adata = d100f1d08ef1e3eda4aef22cd970c2b785c4ff9b523c401b4064324aecf7f2d9
+Payload = 15681d2121ac56a63b9d0a38b9c4eccf84fdb746d32c14b4
+CT = cc451d7b4d55fedc969d26e3b385604a72f0d9f82d50089fb810cdc08db0a9966dffeb43ba26446e
+
+Count = 325
+Adata = eece934a807c9f21487cd810f15fd55d7bb4421882333ff2c43b0353de7fc5a6
+Payload = 412a8ef924ca156de860f147575e5731825f0a3759688928
+CT = 98078ea34833bd174560dd9c5d1fdbb474526489a7149503cfc5b397578f8d02a0b936ffac29b99a
+
+Count = 326
+Adata = 86311ff444d9be90459b6ee3652e1705ed0b5cdac3d27293ddea3378fb686ee5
+Payload = 54ba8a020d0876fa369dc32e8627f565ba3dda862ea0bcfe
+CT = 8d978a5861f1de809b9deff58c6679e04c30b438d0dca0d52c3fcd6d618c260d51724126f257534a
+
+Count = 327
+Adata = ab6efbc44a8906d5c067eaed71af467e130aaf170827a58beb03c55069674125
+Payload = 7a15506fd1dae444d77b2a3ae7b57a8d5b4f10e25a9f78e2
+CT = a3385035bd234c3e7a7b06e1edf4f608ad427e5ca4e364c9bf8b2821920640b992b00cd1c9618025
+
+Count = 328
+Adata = ddb640923d083725587aced81ae1d7409983d1f1e3ccc8dcf94376dc1bbcae8b
+Payload = b18a61a89cd698f32e059b7a2a9f62a46be2c248790a9915
+CT = 68a761f2f02f30898305b7a120deee219defacf68776853e4cd52d41a968284af8907ccbb4588cc0
+
+Count = 329
+Adata = d95ec4a6f594be1ba39fa1aa933dc0a5dafff5ce44509577ebb3a3e8084c4401
+Payload = 16ee3bc9ec8b4448e292b8973618e02a99da1c348539d5c7
+CT = cfc33b938072ec324f92944c3c596caf6fd7728a7b45c9ec47449a5cb4943ff2846c589b7c98ef49
diff --git a/lib/crypto/test/crypto_SUITE_data/VADT192.rsp b/lib/crypto/test/crypto_SUITE_data/VADT192.rsp
new file mode 100644
index 0000000000..1a7a5875fe
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/VADT192.rsp
@@ -0,0 +1,1823 @@
+# CAVS 11.0
+# "CCM-VADT" information
+# AES Keylen: 192
+# Generated on Tue Mar 15 08:09:25 2011
+
+Plen = 24
+Nlen = 13
+Tlen = 16
+
+[Alen = 0]
+
+Key = 26511fb51fcfa75cb4b44da75a6e5a0eb8d9c8f3b906f886
+Nonce = 15b369889699b6de1fa3ee73e5
+
+Count = 0
+Adata = 00
+Payload = 39f08a2af1d8da6212550639b91fb2573e39a8eb5d801de8
+CT = 6342b8700edec97a960eb16e7cb1eb4412fb4e263ddd2206b090155d34a76c8324e5550c3ef426ed
+
+Count = 1
+Adata = 00
+Payload = 296fbda0017351491c2187273fbde2c3a427170e430a703c
+CT = 73dd8ffafe754251987a3070fa13bbd088e5f1c323574fd2167ee33e75d05023a7d63c770cfef2ea
+
+Count = 2
+Adata = 00
+Payload = eb61c284fe009921039ef6a9ce50e702823e44b35357923f
+CT = b1d3f0de01068a3987c541fe0bfebe11aefca27e330aadd170647420f79c0d91cbbd69b806fe96a5
+
+Count = 3
+Adata = 00
+Payload = ffeccc6460d23fdcc387c697e75dbb959b78013a8282eaa4
+CT = a55efe3e9fd42cc447dc71c022f3e286b7bae7f7e2dfd54a8a3ef2324754539ac774872282534386
+
+Count = 4
+Adata = 00
+Payload = 90958d7f458d98c48cbb464c74bf495a49846dd468c514e9
+CT = ca27bf25ba8b8bdc08e0f11bb111104965468b1908982b07e292cd0e32535a848e327bc53cdae94c
+
+Count = 5
+Adata = 00
+Payload = a4fad5205d38206e25097075687ca86032b95b3fe7e82a07
+CT = fe48e77aa23e3376a152c722add2f1731e7bbdf287b515e9bb21701af36936be5f62d02b84df87c3
+
+Count = 6
+Adata = 00
+Payload = b37114c65372b052cbeecf83d05a5da44f7b5bbff7d986b5
+CT = e9c3269cac74a34a4fb578d415f404b763b9bd729784b95b7da7f975367be24341e4af51b8bb156a
+
+Count = 7
+Adata = 00
+Payload = 9c0f0426f171ff18b2a4392f61fb4ee4a44c476fe03dc930
+CT = c6bd367c0e77ec0036ff8e78a45517f7888ea1a28060f6de360c6d50a96f316eda0b216cbb6380ef
+
+Count = 8
+Adata = 00
+Payload = 7b6e0a480a40585545b0e940e8d97c9ec987bd3c0e9c16a8
+CT = 21dc3812f5464b4dc1eb5e172d77258de5455bf16ec1294634cd1bd98e8137b578a174e39efe09b8
+
+Count = 9
+Adata = 00
+Payload = 34dac6dbc28be62332a6935efc122e37b26ee100eb4033f8
+CT = 6e68f4813d8df53bb6fd240939bc77249eac07cd8b1d0c16909a895a3b08b63d7a2a1e75d25e7861
+
+[Alen = 1]
+
+Key = 9748798c0f3cc766795c8ce0e4c979c1930dfe7faefea84a
+Nonce = cdf4ba655acfe8e2134fa0542f
+
+Count = 10
+Adata = 67
+Payload = 100fa71462277d76ca81f2cfdb3d39d3894b0ca28074a0f0
+CT = 36e2415b4f888a6072f260d7e786d803be16f8b9cbee112d7ff74e3b05b7d7c13284573bd3e7e481
+
+Count = 11
+Adata = 17
+Payload = 0217eb6778691f8dfe2d0e5241f05fcbcf97b9171f4de3f0
+CT = 24fa0d2855c6e89b465e9c4a7d4bbe1bf8ca4d0c54d7522d3ee7ce845f85dfc770d96dee9ca54ccd
+
+Count = 12
+Adata = dc
+Payload = a78b7bc6c1a7250c5fc236f2a8343725a9a7bd3ca81b53e4
+CT = 81669d89ec08d21ae7b1a4ea948fd6f59efa4927e381e239dc14ddd8ae0aa5d810040a8d1d4da1e9
+
+Count = 13
+Adata = 0c
+Payload = 390c808d998582793bb10ee60568eb8d975c51d68b4e4da9
+CT = 1fe166c2b42a756f83c29cfe39d30a5da001a5cdc0d4fc746b40dec7e647720f1f5e8474bf570c2f
+
+Count = 14
+Adata = 3e
+Payload = bcd9747fb54184b61b2e9e049caa75e22006e250f3722c0e
+CT = 9a34923098ee73a0a35d0c1ca0119432175b164bb8e89dd3c10c4aac45d90119cce490cc8681a49f
+
+Count = 15
+Adata = 7e
+Payload = d0342e3cd2c1142b642da7297ee3b9978cec405e6810f12f
+CT = f6d9c873ff6ee33ddc5e353142585847bbb1b445238a40f2f9a95091d2cab7d3d9fa3e10d3e67ac9
+
+Count = 16
+Adata = e3
+Payload = 7fab91d1aa072947d22f0dc322355a022fe7f0747f4a184b
+CT = 5946779e87a8de516a5c9fdb1e8ebbd218ba046f34d0a996180f7818c373e89f7ff3003f53260060
+
+Count = 17
+Adata = 3e
+Payload = e487143dc4d98dcc6a2dfe6ee0f85d565d1f46bb0fafe62a
+CT = c26af272e9767adad25e6c76dc43bc866a42b2a0443557f71905f581585e59e3c8c038b5bf966559
+
+Count = 18
+Adata = 3b
+Payload = 976b489244ed6789a34251500057d1d4a3229367a42b9066
+CT = b186aedd6942909f1b31c3483cec3004947f677cefb121bbea56569c34f8d9eea23e85fec18cfc51
+
+Count = 19
+Adata = a5
+Payload = 71efa75961dfd60ad533082a8cfe111214eb02573adc4591
+CT = 570241164c70211c6d409a32b045f0c223b6f64c7146f44c212da23548f2ca4e9a8a07962be6422c
+
+[Alen = 2]
+
+Key = 393dcac5a28d77297946d7ab471ae03bd303ba3499e2ce26
+Nonce = fe7329f343f6e726a90b11ae37
+
+Count = 20
+Adata = 1c8b
+Payload = 262f4ac988812500cb437f52f0c182148e85a0bec67a2736
+CT = e6d43f822ad168aa9c2e29c07f4592d7bbeb0203f418f3020ecdbc200be353112faf20e2be711908
+
+Count = 21
+Adata = 9db5
+Payload = d5982c462ad40458660cd7b120ce07fce9afe812caedcebd
+CT = 1563590d888449f231618123af4a173fdcc14aaff88f1a89015e5cd97b7dd3d981321ae0b2d99e1a
+
+Count = 22
+Adata = 69cf
+Payload = 1a95f06b821879df3fd3ac52fc99a7c1d3e9775263b7d036
+CT = da6e85202048347568befac0731db702e687d5ef51d50402bf3e75863c7acd2699caba3cc301f4b2
+
+Count = 23
+Adata = 6c6e
+Payload = 373c157e59b934a1afb57d4c5dd9ca7fb736b206a6210bef
+CT = f7c76035fbe9790bf8d82bded25ddabc825810bb9443dfdb5d6a8f7a9f52a8038aa9dc1bdc9ed876
+
+Count = 24
+Adata = dafa
+Payload = 26e10a2ed8cc883a6552aee162c5542ff8bb8e758a1975f8
+CT = e61a7f657a9cc590323ff873ed4144eccdd52cc8b87ba1cc8a15603f10cbfdb041f8b2b12cc8f037
+
+Count = 25
+Adata = c8b1
+Payload = dd235b05c15479dfe0326ba206ac784eca50038bbeb35d32
+CT = 1dd82e4e63043475b75f3d308928688dff3ea1368cd189061278bf62ba6a4819513d49fdcdb45480
+
+Count = 26
+Adata = af48
+Payload = a0818342a5cae4a90ef281d3d1289d83f273f418a545fcbf
+CT = 607af609079aa903599fd7415eac8d40c71d56a59727288b8b4d00309b50f9ea72f8105c94475b52
+
+Count = 27
+Adata = b1cd
+Payload = 33c0d06b6583bb4d15b4a07364c4be70ac6e72795c3dae0f
+CT = f33ba520c7d3f6e742d9f6e1eb40aeb39900d0c46e5f7a3b220ba58e97936612c4183ba86705b2f9
+
+Count = 28
+Adata = 649a
+Payload = 3ba11282d61fe36e38cab7b559c2fd9cbe8bf7eb5863bde9
+CT = fb5a67c9744faec46fa7e127d646ed5f8be555566a0169dd87d602dc85bb260fb3df1221e2fbd10c
+
+Count = 29
+Adata = 593c
+Payload = a97faefcae36732fcfe47736c2334ea7d411bf7638b0c019
+CT = 6984dbb70c663e85988921a44db75e64e17f1dcb0ad2142deb3835b7eecad6dac9785ad1d370ede4
+
+[Alen = 3]
+
+Key = a74abc4347e4be0acb0a73bb8f7d25c35bae13b77f80233a
+Nonce = 6a850e94940da8781159ba97ef
+
+Count = 30
+Adata = a4490e
+Payload = 6372824bf416cd072a7ad0ae5f9f596c6127520c1b688ab4
+CT = b14a07bdc119d87611342c4c6935c5786ff1f9ae2eb49e6191c88a3cb4fbafcb8a4a157d587d7e39
+
+Count = 31
+Adata = 5cad2e
+Payload = 295f4f3417a77fcf0bbda17b0fd629ad57a6086573c87eb1
+CT = fb67cac222a86abe30f35d99397cb5b95970a3c746146a64235c34d1390bba5b008c3fb29c2df958
+
+Count = 32
+Adata = ebdf4c
+Payload = 86f354a505de941d34cd98e3af3706d56a938ab9a2797182
+CT = 54cbd15330d1816c0f836401999d9ac16445211b97a565575a733bba0a6992d0664dc77d2b5d194c
+
+Count = 33
+Adata = 7c0d70
+Payload = 88c3bfb546abe2f6bfc92a7c56c627e24ab92a8a87a6b43c
+CT = 5afb3a4373a4f7878487d69e606cbbf6446f8128b27aa0e90902a31b15eed99c2dc4ed1bf11cad96
+
+Count = 34
+Adata = 8fa501
+Payload = 75d4216bad77943bfe82be216157843b0da0fd16eeee8471
+CT = a7eca49d9878814ac5cc42c357fd182f037656b4db3290a42f25595ae00103d4eb20288158132e7d
+
+Count = 35
+Adata = b7aca7
+Payload = bf1401e8dcf6f681ed6dd74c7e23b7e54b384608b0e5ec52
+CT = 6d2c841ee9f9e3f0d6232bae48892bf145eeedaa8539f88760e67693b509ea4795b7da32c5c5d17f
+
+Count = 36
+Adata = 1f283f
+Payload = 7e623e7ef7d0a678b5d22a8402d89220f4f1bf759e3084dd
+CT = ac5abb88c2dfb3098e9cd66634720e34fa2714d7abec900880ef8ea380a1a0a38b2c20288e637a9f
+
+Count = 37
+Adata = e93f31
+Payload = 14f80e7a6298d85d31fb80376a394a8f88b0ae47f00450c7
+CT = c6c08b8c5797cd2c0ab57cd55c93d69b866605e5c5d84412d553aafe8536385d34c412c14d3a1563
+
+Count = 38
+Adata = 27e9a5
+Payload = 3330df12249639961f562a74b34f60b0a8bc7c783f6572fd
+CT = e1085ae411992ce72418d69685e5fca4a66ad7da0ab96628f594d366c8fc826ce58309e9053c27f7
+
+Count = 39
+Adata = 72d566
+Payload = 1a1860ac8c11c5d262f8141738cae8ff91ca05906dc98bb4
+CT = c820e55ab91ed0a359b6e8f50e6074eb9f1cae3258159f61cdd6ac6c42cd3d11e0344a9c1001e253
+
+[Alen = 4]
+
+Key = df052e95aea3769a433ce4e4e800b8418649bbe8c6297eb0
+Nonce = ba356d392c3f700f4f2706a4ca
+
+Count = 40
+Adata = 8ffc0e3d
+Payload = e8c1a89228d8212f75c136bab7923a89f9fea18e781cb836
+CT = 66b5d782323925e1bd0a8413a9a5a881356453d5df2cbeb199b2e1e803550dcdde55fd66ecb45edd
+
+Count = 41
+Adata = 2b4f9cfc
+Payload = a12c6324e022affd61b7e0d8cccbeb23e2e6c65355c1d586
+CT = 2f581c34fac3ab33a97c5271d2fc792b2e7c3408f2f1d3019e8fbc507244ba234a0581dc69962a66
+
+Count = 42
+Adata = b4de3039
+Payload = 7cccb26f1dd227bc77458b99fd9e00f8e801adaece7bfcd1
+CT = f2b8cd7f07332372bf8e3930e3a992f0249b5ff5694bfa5628a2857099af20a4ae08e687bdb02c75
+
+Count = 43
+Adata = bc59f18c
+Payload = 692b53c1355475c71ceff0b0952a8b3541b2938270247d44
+CT = e75f2cd12fb57109d42442198b1d193d8d2861d9d7147bc3e33a6416e387d9e571a1954471ec9cc7
+
+Count = 44
+Adata = 4fd9fd39
+Payload = 7e3e755e25bbe78d4a7770f9356ab9f4ff1bbfdba46383f5
+CT = f04a0a4e3f5ae34382bcc2502b5d2bfc33814d8003538572180f9735f994c8335e593f30b331a920
+
+Count = 45
+Adata = 296cd04c
+Payload = 997b712cd9295dc43cc19b40679f218c27af3e8c638d2e5d
+CT = 170f0e3cc3c8590af40a29e979a8b384eb35ccd7c4bd28da91990fa537d2657d01f66872ba9af22f
+
+Count = 46
+Adata = 88037d3e
+Payload = 577981ccb6c893dfe6405075fcb41507de7f9bfda860791f
+CT = d90dfedcac2997112e8be2dce283870f12e569a60f507f984915cb93e84028c7aedce1a2dadbb6bb
+
+Count = 47
+Adata = fc4bb852
+Payload = 37ba9f57ec230675ce060ba3d388095adf15907aa0b0673d
+CT = b9cee047f6c202bb06cdb90acdbf9b52138f6221078061ba25baa6385af8d7b807a2d2ab19aa4999
+
+Count = 48
+Adata = f40ec14f
+Payload = 401e0cdc132a9e4a9b5ceeed3c181f67e5203ea69508deff
+CT = ce6a73cc09cb9a8453975c44222f8d6f29baccfd3238d8786adcdb44870e1105b7318d8bad0af957
+
+Count = 49
+Adata = 90e2c63b
+Payload = 0234dae5bd7ae66c67ff0c1a3f1a191a0d7bceb451bc2b7d
+CT = 8c40a5f5a79be2a2af34beb3212d8b12c1e13ceff68c2dfa8b079fb71d45bd985bffd343c3362653
+
+[Alen = 5]
+
+Key = 16d345606a315ad2406abbcb43cd8cabe948107ba6d17a72
+Nonce = d4ef3e9e04f1b7f20ffc5a022e
+
+Count = 50
+Adata = a468f08d07
+Payload = d3bef460223c81e4579c9d1d463ac5e0881685de1420a411
+CT = abb85db49a9b1c8724ecbc734cc8373bd20083cfa4007b1cfe4d3a3bb25f89f692884be230c6035c
+
+Count = 51
+Adata = 4497649a54
+Payload = 81ad3f386bedcbf656ff535c63580d1f87e3c72326461ee1
+CT = f9ab96ecd34a5695258f723269aaffc4ddf5c1329666c1ecd05ae56511a230627e02d066c52a919e
+
+Count = 52
+Adata = c30ddd994e
+Payload = 84b88264afec06b370dfcebf5e1d3e2c1f005faf248b3215
+CT = fcbe2bb0174b9bd003afefd154efccf7451659be94abed188ef92fc17dca026f1ac1eaf78a05017c
+
+Count = 53
+Adata = 9573270f7e
+Payload = 9e4c8aa9b58a8eabc5586892f5541000b43f17d9a051a040
+CT = e64a237d0d2d13c8b62849fcffa6e2dbee2911c810717f4d38eddff1e60e2d9ae74a936364b8df21
+
+Count = 54
+Adata = 40336790fc
+Payload = 260f67122dfbe03365bc9e35e9d4ac4b2eb150eddb30857d
+CT = 5e09cec6955c7d5016ccbf5be3265e9074a756fc6b105a70aa3d464ad89cae59b474d019a5a7605c
+
+Count = 55
+Adata = 0b310c8529
+Payload = 1d55e7352bd895c4ef77389a7225c664f72b38c8de778d57
+CT = 65534ee1937f08a79c0719f478d734bfad3d3ed96e57525abeab0c520e64939c6950c0fa406eafb1
+
+Count = 56
+Adata = 5756b2c681
+Payload = fbd315e1f5bd0f0e60ee6684c88f3543452c62ea0701d11d
+CT = 83d5bc354d1a926d139e47eac27dc7981f3a64fbb7210e10d22d339c382343bf39c239fd64c2a64f
+
+Count = 57
+Adata = 3b919e3665
+Payload = d68d6556c5a5b1f5a123389b3ce966d5837cb8fcf5accfff
+CT = ae8bcc827d022c96d25319f5361b940ed96abeed458c10f2fcd6b562a1b6aa10be92a81f99ed540c
+
+Count = 58
+Adata = 58749b643f
+Payload = 062cb6962fa5b3a6239b95f3a51b478a1f32b081dc538a80
+CT = 7e2a1f4297022ec550ebb49dafe9b5514524b6906c73558d4b853022237d94d253b375bf2150e699
+
+Count = 59
+Adata = a5d50c008b
+Payload = 08c62ff9bd7bcf189f530d5065f8764532d2692f69858483
+CT = 70c0862d05dc527bec232c3e6f0a849e68c46f3ed9a55b8ee7aee0d403b2cf6f8b993eebd6b93615
+
+[Alen = 6]
+
+Key = 1c476cfd7dd300d961fd3f24a6fe0e80742b00851676ca63
+Nonce = e300fc7a5b96806382c35af5b2
+
+Count = 60
+Adata = 28130f938c45
+Payload = 6f3938932b5c1280311e892280d8a822a828a0be7fdb1bcd
+CT = df48662fe134e75a85abc2cece2c3b6236c88a70fa792e9beadc9601adf9fbdf4e3e94b395b0a332
+
+Count = 61
+Adata = f600024a7bf9
+Payload = 0af7345e71f4e8886503395ade0b0296a5856e086638b06a
+CT = ba866ae2bb9c1d52d1b672b690ff91d63b6544c6e39a853c0692a40a6aba8d7c5addae21de90fea9
+
+Count = 62
+Adata = 4eef510d1f48
+Payload = 37f57772f056f45a5ce9f46d27be1858980c8935b9c839b7
+CT = 878429ce3a3e0180e85cbf81694a8b1806eca3fb3c6a0ce122f64becb581070411957e632e19bb8f
+
+Count = 63
+Adata = 4c9c76b6fad5
+Payload = 8bb10c82bcabb7fb2b169252ab443b01df217cf908b8c241
+CT = 3bc0523e76c342219fa3d9bee5b0a84141c156378d1af71708c59f83aa97d069b6d83d9387051f43
+
+Count = 64
+Adata = 5572ecfc7e53
+Payload = d1ccb4654a22b1afe32f3d3035fdccd87e9cbed83c679007
+CT = 61bdead9804a4475579a76dc7b095f98e07c9416b9c5a551f04686ee1d7b985d903f1de6cf78f8f4
+
+Count = 65
+Adata = bffdf9d20d74
+Payload = f990a8f6ba14065d48665db36eb470c49f38e2b6376a9bde
+CT = 49e1f64a707cf387fcd3165f2040e38401d8c878b2c8ae88f8118f1b9f39b51965ae9ef1bdb40111
+
+Count = 66
+Adata = 3f27e678c580
+Payload = f8c7d89639ab742a8bcfffe776e868d671e1fbdd55807a8a
+CT = 48b6862af3c381f03f7ab40b381cfb96ef01d113d0224fdca3236d02f33f49759f281315e449bfef
+
+Count = 67
+Adata = 1294cb9db5f5
+Payload = 8601cfd7d935e8a8487b9c39d55ca27096255f2eb9e009e3
+CT = 3670916b135d1d72fcced7d59ba8313008c575e03c423cb5e74770a07c242c3854ceb242dadc1976
+
+Count = 68
+Adata = cec271332b75
+Payload = 77c85b8022f58337b364142a2474fe5cfddb31cfca48af46
+CT = c7b9053ce89d76ed07d15fc66a806d1c633b1b014fea9a10d6c65f19175cfa49898655ccdddb864a
+
+Count = 69
+Adata = da06bd140502
+Payload = b0f2db802475fa70af02057373844f637a3244cda4b4f93d
+CT = 0083853cee1d0faa1bb74e9f3d70dc23e4d26e032116cc6b458822e49e69031431b3eea872a72eb7
+
+[Alen = 7]
+
+Key = 79d1e38a70df1cf239be168833dcd0570bc8f37b3aa26c37
+Nonce = 8229d6d7e9e21fdc789bff5dcf
+
+Count = 70
+Adata = 076887d2abe900
+Payload = 83c24f3a77b83b4ef45277ba90225f3ba1722312f52b1a07
+CT = 19d880f1d959a68f162de243d4a45747ace704613359b27218d1531a066de60a95d2924a6910e990
+
+Count = 71
+Adata = 7535bcc6fbd1a0
+Payload = 24f85ef683cc521387f484bc0b2ad9172f61884c09a9718c
+CT = bee2913d2d2dcfd2658b11454facd16b22f4af3fcfdbd9f96dbf58406020e6df7b312b6825127f9a
+
+Count = 72
+Adata = f4f96d7b4384a3
+Payload = 212bedfa06b5e1a2c3a2f31f6f791dd9df8ef26077821c0a
+CT = bb312231a8547c6321dd66e62bff15a5d21bd513b1f0b47f64dd755177efc87f8b1daf1fd88e51a6
+
+Count = 73
+Adata = 3b7e3d9c1a7fa2
+Payload = 8b9036914bb0f440c8dbcfde9b9547be5e5ef1f56492c75e
+CT = 118af95ae55169812aa45a27df134fc253cbd686a2e06f2b0be31cab31f1a20805d5c07dc516d707
+
+Count = 74
+Adata = a8c35fae8912d6
+Payload = 50f3f3a91bf6fd9573d5ef54b9bb5805205b2f9865d81fd7
+CT = cae93c62b517605491aa7aadfd3d50792dce08eba3aab7a2399df9a45ad153c0dfb3fec3b9d6f7c5
+
+Count = 75
+Adata = db636541f2429d
+Payload = 6fbda8d435555e735443f1e6bc09e96065092efd89edd64a
+CT = f5a7671f9bb4c3b2b63c641ff88fe11c689c098e4f9f7e3fe20b7da94eac8c7ef8478671165e0d82
+
+Count = 76
+Adata = a8de55170c6dc0
+Payload = 640ef4c246a2c6e16ddc49072a5aeef70319149ffba071ef
+CT = fe143b09e8435b208fa3dcfe6edce68b0e8c33ec3dd2d99a4979c35bdbf9538666b6fa57f0f915d8
+
+Count = 77
+Adata = f8d64ce2aa66e6
+Payload = a14e3910766f31594a28ad2c3678c31d0c3aee88484ca6d6
+CT = 3b54f6dbd88eac98a85738d572fecb6101afc9fb8e3e0ea3752824a691da2e99374ae6c031d74ffb
+
+Count = 78
+Adata = b3c340afdc53a8
+Payload = 1b8e0a09e6364020b4cac704dc19bfa79455295604cf9c9a
+CT = 8194c5c248d7dde156b552fd989fb7db99c00e25c2bd34ef04159a68706faa2e8c3376b4dbeb423a
+
+Count = 79
+Adata = 73824034001519
+Payload = 52c84a0735eea6c5c230644075ebfc5db0c3128056e7a8f4
+CT = c8d285cc9b0f3b04204ff1b9316df421bd5635f390950081e5adc7564721ead2af75cb98e61148b4
+
+[Alen = 8]
+
+Key = 72e6cebdaf88205c4e74428664bc0d7eb4687a272217b7ca
+Nonce = 3820db475c7cb04a0f74d8e449
+
+Count = 80
+Adata = f427c47e10c45bb3
+Payload = 54bc7e3c227df4e83252a5848fea12dfdb2d14b9e67c1629
+CT = 91e7baff2b42af63e26c87ce6991af22422c1f82906858b1721961de5c768f4d19bd3034f44f08d2
+
+Count = 81
+Adata = ca25504f3f5559aa
+Payload = ff4493fea916f49fbb3cae2838bc84e293531092cc0904ab
+CT = 3a1f573da029af146b028c62dec7391f0a521ba9ba1d4a3342968c638ecb8a2b358e8eaefd931efb
+
+Count = 82
+Adata = 8215753d9efc5132
+Payload = af16ab8558269a93d8e8c9e38f12a8768947d8b69be0e259
+CT = 6a4d6f465119c11808d6eba96969158b1046d38dedf4acc1f8ac11752fe51e354f3f8a68815539aa
+
+Count = 83
+Adata = 9e7cdbc6202e6492
+Payload = 744a167ae31a8ca20df82290766429de9ef0b7dfe199a78d
+CT = b111d2b9ea25d729ddc600da901f942307f1bce4978de915489de8e241dcab16bdcbf1a1ff4d8d10
+
+Count = 84
+Adata = b8d511d0ab86a07f
+Payload = eeb39de1fe21b5aba654da45fe1481decb22365fa4cbe49d
+CT = 2be85922f71eee20766af80f186f3c2352233d64d2dfaa053fab212a1b6dc7b953e2bc211be194ae
+
+Count = 85
+Adata = c74a5d4265f9f3d5
+Payload = e95c20e80153bae3fde3c3d82b6b33b35fc1959fa31a5d11
+CT = 2c07e42b086ce1682ddde192cd108e4ec6c09ea4d50e138973918ab70fe048d6c5b63a01725eddfb
+
+Count = 86
+Adata = fd849d3ada03181a
+Payload = 6d00606c72cea3deaea5b51ae09e61924355e167058ef42c
+CT = a85ba4af7bf1f8557e9b975006e5dc6fda54ea5c739abab487089bc20867f474c1127aa1320f0000
+
+Count = 87
+Adata = 56825a68681f498c
+Payload = c47705d897a6c7e7aed710b96e2d8532c23b82090e21b114
+CT = 012cc11b9e999c6c7ee932f3885638cf5b3a89327835ff8c34a23b0b6ac4d297dd7832a5e2102272
+
+Count = 88
+Adata = 72e4da839913a26e
+Payload = c822a1ee581cf85b0482c821473385bd3f28528e5e5760d9
+CT = 0d79652d5123a3d0d4bcea6ba1483840a62959b528432e41dd665766c7af21ff890bd40178f1c660
+
+Count = 89
+Adata = 138457571ee8dafd
+Payload = 3ffb82a83308da66e95ac63ae92931b09ffe0e42afbb4979
+CT = faa0466b3a3781ed3964e4700f528c4d06ff0579d9af07e16a6a58bb772c79481dc26861ffbd68c6
+
+[Alen = 9]
+
+Key = 39c03a0c8634047b1635348f284d3dc1e752ab40548eb337
+Nonce = 9e2ea8eb7f56087ee506925648
+
+Count = 90
+Adata = 28d157f09a71da80dd
+Payload = 0662e63c88e963d3e0cf2c4653515ae4474a2c78ab0394c0
+CT = 01dcd4dd3b8c1369518136ce45e8bb9df565b0ad231a887b02ada34addf0aa2f4744ed2e07995491
+
+Count = 91
+Adata = c17d311362c41d442b
+Payload = d6df8b60c697093987b3d89a3667b36504b6ddddf12b0900
+CT = d161b98175f2798336fdc21220de521cb6994108793215bb38a27466b8741bffce44ef04b23af321
+
+Count = 92
+Adata = 006669ef1a11b65b1d
+Payload = 49ad29ef5e82b08752ac5a50dd982e4bcb700005454ade6c
+CT = 4e131b0eede7c03de3e240d8cb21cf32795f9cd0cd53c2d77d11372fb0dab1c99b159e5fe9f91118
+
+Count = 93
+Adata = 8eafce9ba466fd53eb
+Payload = 385f9fb139dbf88561b7a500b0c7b835fe57e2698c6d9f76
+CT = 3fe1ad508abe883fd0f9bf88a67e594c4c787ebc047483cd09e4898a4046f6ec9f40e412915007e4
+
+Count = 94
+Adata = 796e55fbe7bed46d02
+Payload = 4ebb149b01cbacba32d11168ca61928ea149dcf2ee2c1001
+CT = 4905267ab2aedc00839f0be0dcd873f71366402766350cba5d40a9902481bfac7ff33d08fb4b3d31
+
+Count = 95
+Adata = 8f958d796be0566512
+Payload = 0d974e5621caa1d86eaaee689ccbca57843373fcf20db407
+CT = 0a297cb792afd162dfe4f4e08a722b2e361cef297a14a8bcd972d09a17172161eb68a30b593b1bd6
+
+Count = 96
+Adata = cc879ff2d583a7288c
+Payload = f8e0dac6a691dfb231411b5c5f70a0daff83cc637b0c7bb3
+CT = ff5ee82715f4af08800f01d449c941a34dac50b6f3156708119cc26a80c152c253fbc36cb886e0fc
+
+Count = 97
+Adata = 4765d696d19dec58bc
+Payload = 096a36396ccfa260f28fb0919157a5076b53506c51a2a4ef
+CT = 0ed404d8dfaad2da43c1aa1987ee447ed97cccb9d9bbb8549de06cc5c3bc4ad75076c774576843fb
+
+Count = 98
+Adata = a004f283afc3309c31
+Payload = 5b943269be41e2758a4ea6a3cc621b711a8ba6002783aa72
+CT = 5c2a00880d2492cf3b00bc2bdadbfa08a8a43ad5af9ab6c9135493b44f79a5774df6b2943b0bec67
+
+Count = 99
+Adata = cdd5d8aefe49a315ad
+Payload = 5f27867109e74862ce0dbc9ba73c420b93067bdede17ae51
+CT = 5899b490ba8238d87f43a613b185a3722129e70b560eb2ea7a5da4a29a9012d78b6de6f1b3e8c9ed
+
+[Alen = 10]
+
+Key = e2a92ffbb0b5eb68cb82687f12449fae5167d375131b0b10
+Nonce = 441ad5e1382e083a95224f395d
+
+Count = 100
+Adata = 2352648299b0413cb2ce
+Payload = 048c9ba4597c3bb595bfd5048e5e9a1296f30e5c0118b177
+CT = 25247a258e4ac0a988d8def60cc174a9d4578cd5346fb5150c96e8ab8774baa421f39c64a386c418
+
+Count = 101
+Adata = ce003c836a6f5f066053
+Payload = 02ea8e7e488c863584f828df13dfeb68433294d11d9ca9d7
+CT = 23426fff9fba7d29999f232d914005d30196165828ebadb5d453036cdc6bad0c5e770a6249a52e74
+
+Count = 102
+Adata = d11be73a104ccc6346d5
+Payload = 6d5573c9279897d7d1602d8a95c04bb5ca3fad2dbe89a024
+CT = 4cfd9248f0ae6ccbcc072678175fa50e889b2fa48bfea4464627ad75bbfe17f3f5ddfd3dbc1045f3
+
+Count = 103
+Adata = 6a7b80b6738ff0a23ad5
+Payload = 97a813e75d95d25c2edb1c705c4ffe4d7c08c756761fbc0b
+CT = b600f2668aa3294033bc1782ded010f63eac45df4368b869af8943f74706cc3394a170fd49f7011a
+
+Count = 104
+Adata = a391acdb3a06dae4a671
+Payload = a78981ac244307451e4d3fd7f654b70cc4e6518aa47a3c18
+CT = 8621602df375fc59032a342574cb59b78642d303910d387af22597f63074ca3533bb5e107860481f
+
+Count = 105
+Adata = 0b9f28f2d3215785f569
+Payload = 5d649d79ff0e304e164a383c74f13d7ffab145d00cb0ec2c
+CT = 7ccc7cf82838cb520b2d33cef66ed3c4b815c75939c7e84e905b5609f593c6ea9281f66cd2e646dd
+
+Count = 106
+Adata = 7928b1091cbfb2eef0fe
+Payload = 83a273687dced7b94d569f81d75508595cde668f06406183
+CT = a20a92e9aaf82ca55031947355cae6e21e7ae406333765e1428195355618ea0cf87260ad20b6d7b9
+
+Count = 107
+Adata = 3b74afb81f54a93c79d5
+Payload = b4dc3c059cf7b47dd0bb7f165a63fc80b5c6b5f3ca7eeb73
+CT = 9574dd844bc14f61cddc74e4d8fc123bf762377aff09ef1155019659f41a5f0430695b4ada9d8b8d
+
+Count = 108
+Adata = a46ae4c71d4c9eb72fab
+Payload = 7e919581c5105d98717d0613e1ca869c6516506ea482d5c2
+CT = 5f3974001226a6846c1a0de16355682727b2d2e791f5d1a01514b252f33dc870c42260e48c4fa9fd
+
+Count = 109
+Adata = a1ace61711f0a09ac17d
+Payload = 3a4558b55214f21cbd2ae2eda5a2321cfc2f102e059b744a
+CT = 1bedb93485220900a04de91f273ddca7be8b92a730ec7028c263c667d7ed58907452c092905d0b31
+
+[Alen = 11]
+
+Key = ef1ad3eb0bde7d4728389da2255d1f8a66ecb72e6f2f1ac4
+Nonce = 8e7d8a44244daa7df2b340993e
+
+Count = 110
+Adata = 521583c25eb4a3b2e46120
+Payload = 9f580cc6c62a05ce125c6bec109a48ca527ee26a64b14b68
+CT = ff0ff95bcb0bccd5e4aadd77ac6770f5013654eb3c6386fded2c87135861b43a99f258b6938f66e3
+
+Count = 111
+Adata = 31adb39e947f8883fa4b69
+Payload = f16bba081bddda83546eabc9a55c81a439720dd8562ce964
+CT = 913c4f9516fc1398a2981d5219a1b99b6a3abb590efe24f132b87476d66a1bd405f484ef9ac8ab7e
+
+Count = 112
+Adata = f05f39eb0a3d6460076aa8
+Payload = 6baf784f63cf45a1836fa8f3609fff7870ce8cbd1e91268c
+CT = 0bf88dd26eee8cba75991e68dc62c74723863a3c4643eb19a120b455b366cb104fd8b6dc2c80471e
+
+Count = 113
+Adata = 74c7a633ff73ff507009c5
+Payload = d8176a6de1c15a14c8b8b58725c179dc84c9308268d718d5
+CT = b8409ff0ece0930f3e4e031c993c41e3d78186033005d5400c8ca09f4bf06b1c27e75abf15112e49
+
+Count = 114
+Adata = ab322a88cf44b9ca774415
+Payload = 3706e4d8ff748574f382e5f9b0a3b6258f1f360fd87001b0
+CT = 57511145f2554c6f057453620c5e8e1adc57808e80a2cc25b3159274a7de3550baf759f7fae53dbc
+
+Count = 115
+Adata = d6fe6e17221d4e06ed3ab9
+Payload = e02217394772deffe218c405e40f2a3a56ca01d55d6d3330
+CT = 8075e2a44a5317e414ee729e58f212050582b75405bffea516fba8d193e133e6f78daa39681cb262
+
+Count = 116
+Adata = 2739d2cdfcbe7d5cd7d28c
+Payload = bb713f74a884bd1a994adba87561d637853c6181290ef5e8
+CT = db26cae9a5a574016fbc6d33c99cee08d674d70071dc387d65f92db3b3d1c2de04c69c5d06b0e001
+
+Count = 117
+Adata = 5841571299cd064a6262b7
+Payload = 9641dedd50d80ac0abf7591436065fa2e23e4687abbb86e4
+CT = f6162b405df9c3db5d01ef8f8afb679db176f006f3694b716e4d20ab5ffad6f71155f6839dfdbb25
+
+Count = 118
+Adata = dc5d7fd97bb3243ba585fa
+Payload = aefda8501193edacb8abb94fff875529a537a462c4b9b69c
+CT = ceaa5dcd1cb224b74e5d0fd4437a6d16f67f12e39c6b7b090ebc3af2de52b8bee3d130fa973f716b
+
+Count = 119
+Adata = 8789e0b3e0dc13d9725b37
+Payload = 65e53f549b62aca03f21ab2a494b93805e02cfecf4f12aa4
+CT = 05b2cac9964365bbc9d71db1f5b6abbf0d4a796dac23e731b5cd5a004a0ef28e30383bdaed8f93c7
+
+[Alen = 12]
+
+Key = 44cba20b7204ed85327c9c71c6fea00b47ce7bdde9dea490
+Nonce = f3329154d8908f4e4a5b079992
+
+Count = 120
+Adata = f1e0af185180d2eb63e50e37
+Payload = 6333bde218b784ccd8370492f7c8c722f8ef143af66d71d7
+CT = b9401a4927b34dc15e9193db00212f85f0c319781ec90e3b4484d93cb422cb564acc63d3d18e169c
+
+Count = 121
+Adata = ea74231e49e667ca1c21d46d
+Payload = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e
+CT = e67d8fbeec794d42fc64d7f36a87d2ac22aafa440021ea72c4c151d9927e6a9f19d47ff7d79ca6f6
+
+Count = 122
+Adata = 7f5871a8300471dc325f8289
+Payload = c642c9722d84d708682350dc70bdaa9a1181a415a9e72b93
+CT = 1c316ed912801e05ee85c7958754423d19ada9574143547f959eee29be1415ab03444de0fa42707d
+
+Count = 123
+Adata = ee7e6075ba52846de5d62549
+Payload = 2286a1eddd80737a724ca941217e9f0232870b6c2f20d29c
+CT = f8f50646e284ba77f4ea3e08d69777a53aab062ec784ad70ce97c1c8aea70de04580d7b37f8c014d
+
+Count = 124
+Adata = a30f2fd445820cdf80014554
+Payload = 92577d5db20391110309d490f52acecdfc18382f368bbe42
+CT = 4824daf68d07581c85af43d902c3266af434356dde2fc1ae23b536f993381e525a14599dd5c02e80
+
+Count = 125
+Adata = 0cfec933831644b468724e80
+Payload = 6803dc3f7c06568ca78ee5aa2e9b1b354a4f1e067ff6a25b
+CT = b2707b9443029f81212872e3d972f392426313449752ddb7d6ea722fdd82ede2c7b8832dde3cbe80
+
+Count = 126
+Adata = 6bd14e3bf91dc7fd6be07647
+Payload = 5580672e52aacb9d714a34c31c33fc221e13e8f90849adba
+CT = 8ff3c0856dae0290f7eca38aebda1485163fe5bbe0edd2565c2994b2b469ad977564d83db1ebfe38
+
+Count = 127
+Adata = 6c6ad35e97d023217018162f
+Payload = 1bd1bcc6766d251144376d91ff93ef83033d0e0ee546266f
+CT = c1a21b6d4969ec1cc291fad8087a07240b11034c0de25983ac31ebf9e255eecf3c69ddf198760556
+
+Count = 128
+Adata = 52c35db85cc34b6efed180ee
+Payload = 28f71a2fe498f89203a5d23e8f8fa64b124aea6459fe721d
+CT = f284bd84db9c319f8503457778664eec1a66e726b15a0df13424079e3de87fa59c3d10fd62380a90
+
+Count = 129
+Adata = a96e4776270683ee7d0c9b6e
+Payload = 5be078ead1926074afca81f9a97dc93dcb954c955e4343e4
+CT = 8193df41ee96a979296c16b05e94219ac3b941d7b6e73c082258e1f3fc3eb7e976c86c8a21bd6569
+
+[Alen = 13]
+
+Key = b5f43f3ae38a6165f0f990abe9ee50cd9ad7e847a0a51731
+Nonce = 13501aebda19a9bf1b5ffaa42a
+
+Count = 130
+Adata = ead4c45ff9db54f9902a6de181
+Payload = 3726c1aaf85ee8099a7ebd3268700e07d4b3f292c65bba34
+CT = fd80e88f07dad09eed5569a4f9bb65c42ef426dda40450119503d811701642143013f28ce384d912
+
+Count = 131
+Adata = e63b89e95df8338ecdcc885c3b
+Payload = 37f86aa62b1e31e9ded3e1a38a7e1a8a638d619ac109694f
+CT = fd5e4383d49a097ea9f835351bb5714999cab5d5a356836ac6d3f9c7b9f25e09ce164a11370b8b05
+
+Count = 132
+Adata = a2161536e263459e0b0a29a225
+Payload = 1749f5977197359a5d318d5fea38aba95b3603f1d7011e66
+CT = ddefdcb28e130d0d2a1a59c97bf3c06aa171d7beb55ef443e02b848b006c28803303fd97bdc35476
+
+Count = 133
+Adata = 8ac95a6ae0bce0fb07f85368ab
+Payload = 0842bfb8b38283257c2ea58b29c8350775f1dbf15f73c905
+CT = c2e4969d4c06bbb20b05711db8035ec48fb60fbe3d2c2320431de2bc45b2b726bfda92939a11f68b
+
+Count = 134
+Adata = 44cc9b2510680c4d73f1938c77
+Payload = 68d09fce5e89e4ef6d453b8ee326090cedb97b75b886c7b3
+CT = a276b6eba10ddc781a6eef1872ed62cf17feaf3adad92d96786add8c2619f0782ca12312a1d64266
+
+Count = 135
+Adata = d8a662ab8449bd037da0346a24
+Payload = 45245de4ac6a6196a0b15b77c622a21bb50627379ddb4256
+CT = 8f8274c153ee5901d79a8fe157e9c9d84f41f378ff84a873b6bd4a09f9b4aa2864d39ff1a03e0ff7
+
+Count = 136
+Adata = 8ed39da1d9179e77156eb909f3
+Payload = e928e37dbe8389a53c650edc86f83cd3589a53dc8e45adfd
+CT = 238eca584107b1324b4eda4a17335710a2dd8793ec1a47d819b6935778ffbc0953974de0a9d87a31
+
+Count = 137
+Adata = 423515f7bd592d6a7a2408661a
+Payload = 4c3bdc6186297896097b3297ba90bcde78dc8a9efe3bd8b1
+CT = 869df54479ad40017e50e6012b5bd71d829b5ed19c64329400a3da0d3ce34a272b51582a998f461e
+
+Count = 138
+Adata = 5a6bc2cd6890a473d478a582b4
+Payload = 1c5ebaeb7b926a39b8aaf65a4c484b113d6f2caafadc33ea
+CT = d6f893ce841652aecf8122ccdd8320d2c728f8e59883d9cf4ef28c338f497a40f550f2945734ad1a
+
+Count = 139
+Adata = 7bdc26b5b4df58af539d91eb2e
+Payload = be5c9fee6babf569c66e6a0d0f3c4dc314f40c0aeca493f7
+CT = 74fab6cb942fcdfeb145be9b9ef72600eeb3d8458efb79d2e07f1998e57ba9b611568632dc5cb9fe
+
+[Alen = 14]
+
+Key = 13f179aa2a23bc90a85660306394940e9bb226ce3885ec01
+Nonce = aaa52c63ca1f74a203d08c2078
+
+Count = 140
+Adata = 5cc924222692979a8e28ab1e0018
+Payload = d3b36c6289ad6ae7c5d885fe83d62a76270689ce05fa3b48
+CT = bc4fcef401c2e1d1c335734ff23ea52c3474d2e6f31648a7f58649400ac9e825b038d67f0c2a6f1c
+
+Count = 141
+Adata = 21fb9cdd9b110bbbc6832275dfa7
+Payload = a7742dd9c3e8bbad08157fbd01ebfb94e1639117c4b4eb5d
+CT = c8888f4f4b87309b0ef8890c700374cef211ca3f325898b23fa5ad4142e0b4650fa5cc8f7ef70d62
+
+Count = 142
+Adata = 9919ddb6ee6c330646cd15953d39
+Payload = 297b4498bf5427e6341aa9275c1f62e3b0c9b150a195ae72
+CT = 4687e60e373bacd032f75f962df7edb9a3bbea785779dd9dfec551d11b8647432cc4320173939600
+
+Count = 143
+Adata = f94cfd1f8c7902a57784c10b9a5a
+Payload = 2218868033e17220655f0196dab6193c58293ca105d467d9
+CT = 4de42416bb8ef91663b2f727ab5e96664b5b6789f3381436a79a075ec2cacee1482b8328b697a3b2
+
+Count = 144
+Adata = 63f3fe58c348dc6bcbb44c3c370f
+Payload = 4a9bc26fb10000a57b9e73a8a3d30f66ef9de8782201ffa8
+CT = 256760f9396f8b937d738519d23b803cfcefb350d4ed8c4739cbe17b4edd64a3dcd2b8ae3352c04a
+
+Count = 145
+Adata = dec0ce763833305aa9c9efdc2c65
+Payload = 1b61b3ff3e4847a17f55f7565826b0e2ccc1368f4de32022
+CT = 749d1169b627cc9779b801e729ce3fb8dfb36da7bb0f53cdf54665c476d0741164685b0d81caca31
+
+Count = 146
+Adata = 592ef6784ee839a049e0d96257fa
+Payload = 32e5998b37987a38800f5bfe3132979ca1447314570aaef7
+CT = 5d193b1dbff7f10e86e2ad4f40da18c6b236283ca1e6dd18500d93b11fecc8b4560320878ba53550
+
+Count = 147
+Adata = 4a47a82b999a2a739959f153a091
+Payload = 84acfb6cf10b301558e5acbf41bbbe0b145dc66dc600f4df
+CT = eb5059fa7964bb235e085a0e30533151072f9d4530ec87303c2a41443578adaf31483bbb6b9f10b0
+
+Count = 148
+Adata = 4ceba98cc0ff5de1a7d580cf23d2
+Payload = d7c73d77a286df38aad116843620911c92e11486be5fcb0c
+CT = b83b9fe12ae9540eac3ce03547c81e4681934fae48b3b8e32232a856c07999e99a4701988b486ef2
+
+Count = 149
+Adata = 15e3b3c5794fececd703ac58ccb2
+Payload = 140882c5d3534bb0861e7ba9423e67439a02ee6f0b0b00f3
+CT = 7bf420535b3cc08680f38d1833d6e8198970b547fde7731cb3a6d50a92f3183c0c5090edc3c7f822
+
+[Alen = 15]
+
+Key = c1dfc48273d406a3a7b9176f80b2dc4e9a7f68134bab66d2
+Nonce = 1ac53ba965cdaeeef7326a37e4
+
+Count = 150
+Adata = 39ba54a410a58a5d11615a2163cc3b
+Payload = 67d9728a88f1fac3af43ed6d634ba902896bd226858697d9
+CT = 360f0fc714994e3b59448b50cdd61d511b4f09e0e5fb5ac826a51fe5b9b598a17eb3da10f936813b
+
+Count = 151
+Adata = 38b0cca09d69320105d24ee3f96684
+Payload = a8365ba9fcfff060b28895f7a2d786c5991a8f7758962caa
+CT = f9e026e460974498448ff3ca0c4a32960b3e54b138ebe1bbba673a94f4280e84724f4a2510165e9a
+
+Count = 152
+Adata = 76718dfb9c68acdd82592d96def39a
+Payload = 497be597dd695cb159d8a64f44049c3b549ac927837b1b90
+CT = 18ad98da4101e849afdfc072ea992868c6be12e1e306d68118865ab37be6f015316e0d177b6c2e91
+
+Count = 153
+Adata = dd719ba1710916a546233c1494a7a7
+Payload = ca452c21383ebc3fb584f0d59a227374854983f243a3f460
+CT = 9b93516ca45608c7438396e834bfc727176d583423de39713d903f67ad0d72fb8ffea2035216b769
+
+Count = 154
+Adata = d893fa2bd7c70e21a5934dc2e99037
+Payload = 3dd118ed65453d3d7844d8de78d7a43587ac5e9305b11464
+CT = 6c0765a0f92d89c58e43bee3d64a10661588855565ccd9750b885e3e054f519d0355db1bd589bb35
+
+Count = 155
+Adata = 97c60265a3a6993b97ac1b375a79b8
+Payload = a7375ba32251af0138bd9fd8fcd56a7c43ab2ca9a7fc0117
+CT = f6e126eebe391bf9cebaf9e55248de2fd18ff76fc781cc064a950e4bed4137e38787839e39924821
+
+Count = 156
+Adata = acfdf302ed116ac4755069d1704423
+Payload = d39d188f28521e4fb0a0c5e48e6d6efe4383c95b2535ea8d
+CT = 824b65c2b43aaab746a7a3d920f0daadd1a7129d4548279cca94dd97fd2a5d50eb7dd6234b40c525
+
+Count = 157
+Adata = d449f97164aae9a3046624e98810bc
+Payload = 758102470e221e30d87d2807b5f8b793a7a56c83eecf32a4
+CT = 24577f0a924aaac82e7a4e3a1b6503c03581b7458eb2ffb596f11450d5d2ba55ffb4a6cf7eab847a
+
+Count = 158
+Adata = 3e6c914a196e175079315b1c92b2b8
+Payload = 1db875c4b4f9dd4926dfb5604d6c4d21aba7d905aed9d1b0
+CT = 4c6e0889289169b1d0d8d35de3f1f972398302c3cea41ca164894e9218ecacd143fb62df69a13d33
+
+Count = 159
+Adata = e2b7b00d0cfbdfcc24f1819ae1869f
+Payload = d7a75bc621addccbbe162b86d536d69c887c278384af54e7
+CT = 8671268bbdc5683348114dbb7bab62cf1a58fc45e4d299f685a7c19bc9c2f8e36ed95015ebb679ae
+
+[Alen = 16]
+
+Key = d8a662ab8449bd037da0346a24565683a3bbbbd1800e3c1c
+Nonce = 166fb8d0e110124c09013e0568
+
+Count = 160
+Adata = 1c1c082eeb5b8548283d50cc2ace1c35
+Payload = 61fdd10938557080191d13dd6c3002dd445d9af988029199
+CT = 23c05927502a4ee6e61e4e10552d49b020643eab476eeacc867601fe79a122a7817819655183283e
+
+Count = 161
+Adata = cae884fa25adedd883ef4e7c855def19
+Payload = 8c7ae2c3c503e9072d6e04e44c2ea78fd24994503567a136
+CT = ce476aedad7cd761d26d59297533ece2b6703002fa0bda63160bb976ab072aec8fcea8eab3dc5aff
+
+Count = 162
+Adata = a350ed58c04473e113b9088b1fb9dad9
+Payload = 863f9a26182f131c594972398b52b3a01a9d314fd9390bf4
+CT = c402120870502d7aa64a2ff4b24ff8cd7ea4951d165570a1291b2c13a3f5e49ce35b9047ee1e8627
+
+Count = 163
+Adata = cb7090f7a465782f680fd44cbc558107
+Payload = bd94c9ad6253c25dc417f87b6e52e03621ccf4b3bff5b402
+CT = ffa941830a2cfc3b3b14a5b6574fab5b45f550e17099cf57fdd9fd1d469a9042b80e6458d25292b4
+
+Count = 164
+Adata = 914cf55a3fc739b5f87ac7518cc4171b
+Payload = c313bd213dc29c00691e25ce028884192e21a820003aece4
+CT = 812e350f55bda266961d78033b95cf744a180c72cf5697b1a8b8e82175ff30c69ea71d2cfb814ada
+
+Count = 165
+Adata = adc8b69d84ef7ae62f9ca9f371d3488e
+Payload = 85e4e053b976e06a64dfa8523130cdd802d3e7c3d6d797c2
+CT = c7d9687dd109de0c9bdcf59f082d86b566ea439119bbec9776fa36db27b2f84d1b8ab55e2fc89ab8
+
+Count = 166
+Adata = 29ed477994dd231d3a71157eb56d219d
+Payload = c77aae5fd09dc9bceee7428e0734d4b0556528396a58f909
+CT = 85472671b8e2f7da11e41f433e299fdd315c8c6ba534825c0e32058ea939036805a735198934a072
+
+Count = 167
+Adata = 494c8f931029a4919e2dcbc16512a8bf
+Payload = 1f47273103f265f963e498878361c06c01a5ffcfb630a161
+CT = 5d7aaf1f6b8d5b9f9ce7c54aba7c8b01659c5b9d795cda3437098c81475f8a1d8f3b0e63d499d387
+
+Count = 168
+Adata = 53200bc5d1f1fb0eeff02d2bc42f7d54
+Payload = a38231af405dc7b70c8dbc8cb84e6be8a0dc2e95fddc2ce8
+CT = e1bfb9812822f9d1f38ee14181532085c4e58ac732b057bd9d7317973878957e8fc1fa57a025a3e9
+
+Count = 169
+Adata = 61e0e28bf344a9a1b04b15156e06498e
+Payload = a0d3a94ba6bb3bedf38220d1cba7e91273ad19f9a1c436c0
+CT = e2ee2165cec4058b0c817d1cf2baa27f1794bdab6ea84d95b0aa1befae96e71b9d221673844b1cb7
+
+[Alen = 17]
+
+Key = 116f4855121d6aa53e8b8b43a2e23d468c8568c744f49de5
+Nonce = 924322a3ef0c64412f460a91b2
+
+Count = 170
+Adata = 03c2d22a3bb08bbb96b2811ce4b1110a83
+Payload = 1bd3b5db392402790be16e8d0a715453928f17f3384c13a7
+CT = ad736402626df0f9393fe4491eb812725ad39d6facf20b5b2f9340b0d48a17ae1cc71d7515e61ee9
+
+Count = 171
+Adata = f390387610741d560325b5d2010d8cd4a0
+Payload = c93aaa04279e451b6880ed7b7fdb3ca9e80ab76180434937
+CT = 7f9a7bdd7cd7b79b5a5e67bf6b127a8820563dfd14fd51cb717bae4c040561bcfcf80fd842ae8dd8
+
+Count = 172
+Adata = 891d7988a56415a7b433f463b1e80eaa62
+Payload = 2611612ccb5ffefaa73195509bb52c641472bca0dfd09d49
+CT = 90b1b0f590160c7a95ef1f948f7c6a45dc2e363c4b6e85b5bc9fb15d874feccb6b5f581fa470734f
+
+Count = 173
+Adata = 831c0fed5e600dd82d7d55669262a9a17d
+Payload = 08136e946e306cde0544ddc2f3f4a529c89c7b77a5e635c1
+CT = beb3bf4d35799e5e379a5706e73de30800c0f1eb31582d3da72589ee50d23f925f7998ab3ccac37f
+
+Count = 174
+Adata = 32ca9d412d4ef0e89928496e96c9de7f2e
+Payload = 695aaac402942de7d899cc3f741c7fb2b2d8247a7676cf29
+CT = dffa7b1d59dddf67ea4746fb60d539937a84aee6e2c8d7d555c0b608f331dca47c65f5c879f2d532
+
+Count = 175
+Adata = 0746b2e6149c7f55854e9ca3e6861bf0e9
+Payload = 8f958d796be0566512f0512dcebd2e12f3160b05b72ae955
+CT = 39355ca030a9a4e5202edbe9da7468333b4a81992394f1a9b039bd916e923e2fc1f7c60eb59916fd
+
+Count = 176
+Adata = 0e4cbd1c574d656112bf6e70a8f23347f0
+Payload = 367ecd1b71dfb96a84e2369f28705dfaebf0c73ed35d5364
+CT = 80de1cc22a964beab63cbc5b3cb91bdb23ac4da247e34b98ac07f2c0847069fe5be26e623033f532
+
+Count = 177
+Adata = 1a05ff12412bf728497536534c234901ce
+Payload = a9ccee975feb10f635d548a8502f7c8b6adbd2be74117257
+CT = 1f6c3f4e04a2e276070bc26c44e63aaaa2875822e0af6aabf4e66a2b210e5a03bb10ff2926ed8a48
+
+Count = 178
+Adata = 3bd063a51c71fab5aeb47e7f8f958d796b
+Payload = 7df6220599d6235eb450989b6f0cd6c96db62b0d13afc4f4
+CT = cb56f3dcc29fd1de868e125f7bc590e8a5eaa1918711dc08ec90169d0c5c11fff8f255fedb13a99a
+
+Count = 179
+Adata = f0d334e0a27c3d00d56b15c2ee426e6347
+Payload = 6f65a24344c32debaf9f8c3fa426fe0b139e8ad1c8b1fbbb
+CT = d9c5739a1f8adf6b9d4106fbb0efb82adbc2004d5c0fe347170141cf3f207c4f0fc1b0238477cfad
+
+[Alen = 18]
+
+Key = e67f3ba11282d61fe36e38cab7b559c2fd9cbe8bf7eb5863
+Nonce = a727ed373886dd872859b92ccd
+
+Count = 180
+Adata = 68d199e8fced02b7aeba31aa94068a25d27a
+Payload = d7a954dae563b93385c02c82e0143b6c17ce3067d8b54120
+CT = c6cfaa1f54d041089bd81f89197e57a53b2880cefc3f9d877e30b2bcc3f1ea9ec2b8f28bf0af4ecf
+
+Count = 181
+Adata = fc4bbe329a86089ebe2a2f3320dad55a9bda
+Payload = a206a1eb70a9d24bb5e72f314e7d91de074f59055653bdd2
+CT = b3605f2ec11a2a70abff1c3ab717fd172ba9e9ac72d961753a6e6844102d6bb86986c030765d3393
+
+Count = 182
+Adata = d8741e540330692d83cc806a8ac1c4742be6
+Payload = 56ef76dbec6b8b46f5b7b4e311c0baaa6fcf54c69c0b9c3b
+CT = 4789881e5dd8737debaf87e8e8aad6634329e46fb881409c3f92a80b1d82f8c1dc32bfe64adca12a
+
+Count = 183
+Adata = c8b1992dfba55b4ab86b480546c861655e1a
+Payload = 2729636112f2abe2c76ea5e52a3f80b0f882f0f3b6f7c806
+CT = 364f9da4a34153d9d97696eed355ec79d464405a927d14a12fb48ad162b0c0678674d79d26a6b5ef
+
+Count = 184
+Adata = 347e12eec56e95aafcc7d25bf10fc756b4e4
+Payload = dd433eb7422c7c4dccee57a1679633ced3b5f08df763d457
+CT = cc25c072f39f8476d2f664aa9efc5f07ff534024d3e908f081c7cd81c974d985bf24b7fe9542141a
+
+Count = 185
+Adata = 45b35a04d6e2645e9a5aef206ed4e36199c9
+Payload = 70523bc397417e09d791a4976960e02636ca7144a5681cf7
+CT = 6134c50626f28632c989979c900a8cef1a2cc1ed81e2c050a7f6a5c04e59896074e1594706ab27e9
+
+Count = 186
+Adata = 378b48531fe34f55125b2f14f59715dd6ef0
+Payload = 514cb462dd4b117f26cac22062fcbeb353650c71649a7b3d
+CT = 402a4aa76cf8e94438d2f12b9b96d27a7f83bcd84010a79aa9d16c3ab79276cff345444511940a9d
+
+Count = 187
+Adata = 73ed686d6fecdc031cd97653137f269d6537
+Payload = 7f0c2b261db3f3de0ce3a733f4b8c446c374567d96d00379
+CT = 6e6ad5e3ac000be512fb94380dd2a88fef92e6d4b25adfdef92bf8aa6facbe6f9607ea02b54a1bf0
+
+Count = 188
+Adata = 5b0441107e5560be94f030a41cedbdb116d9
+Payload = ebb3e2ad7803508ba46e81e220b1cff33ea8381504110e9f
+CT = fad51c68c9b0a8b0ba76b2e9d9dba33a124e88bc209bd238e4936ee93b5c7a302913292df33c1700
+
+Count = 189
+Adata = feedcc5f8524fe7d49bcd178415b9f4c450a
+Payload = 3216dce3b8b1ce0e79e40fffcac728ab191aaaf319d971d3
+CT = 237022260902363567fc3cf433ad446235fc1a5a3d53ad7493426b6193afe765a76b3dec00266e69
+
+[Alen = 19]
+
+Key = e0a29a2c7840cf9b41de49780b9ee92d646a4bfc5b9da74a
+Nonce = fc9fd876b1edded09f70b18824
+
+Count = 190
+Adata = 36e15baafa0002efbb4bb26503b7e3b79f6c68
+Payload = 344dc8b6bd66a1fbbe330a95af5dd2a8783dc264d6a9267d
+CT = 43b3b96aa5a54378f3bb573ffda3e154aa7f425fc3008175b60a77b9d38740356b544b1c0f259086
+
+Count = 191
+Adata = 712b788f0276e2b5a58be80f9114a12ab2a268
+Payload = 6d0546d4e95d1cfcb37a8f88a62064f5d95791311511535b
+CT = 1afb3708f19efe7ffef2d222f4de57090b15110a00b8f4535f750bb4cd42db3038e2c1622b72cea8
+
+Count = 192
+Adata = 07f77f114d7264a122a7e9db4fc8d091334a03
+Payload = 05024ce13b9057dd2c509db7dbcbd5585e4e64a1e2e380ff
+CT = 72fc3d3d2353b55e61d8c01d8935e6a48c0ce49af74a27f761e77b59ef7eeeae35bb53bb9543b64a
+
+Count = 193
+Adata = 899b036138cee77cd28382ba27984d858a6351
+Payload = 77b8e735b13b10e45e411ab94c6fe1a9eb89f0a7af40ff1a
+CT = 004696e9a9f8f26713c947131e91d25539cb709cbae9581244a60fdb473098a11b2176d37b2c4643
+
+Count = 194
+Adata = 4b000440a8484a5201cd54aec058919769772e
+Payload = 6b21800ae599a15254bb33f0bb080788fb6e9fa054bfd8b2
+CT = 1cdff1d6fd5a43d119336e5ae9f63474292c1f9b41167fba58d4afc30a7f672ea34e05ec1843d848
+
+Count = 195
+Adata = 73a222e681ed1ca47d92a6dd90625d895fbf29
+Payload = bfa9d9af6e1f32b6626a1cd89b1c32513b5b50a18ddab028
+CT = c857a87376dcd0352fe24172c9e201ade919d09a987317204ef270e0f3b5e3ca0b8440af65c76e85
+
+Count = 196
+Adata = 7109a3a36b286059bc1a1abb2767c92f884e3f
+Payload = c68b1bc0050e19780ab53efbea175634f70a7245d966966e
+CT = b1756a1c1dcdfbfb473d6351b8e965c82548f27ecccf3166ffb66991b38a0345fbbff5f2362f87de
+
+Count = 197
+Adata = cd15973753b94b77bb4b778de8b3b0cabbde85
+Payload = 4256f1c9b64390fe2120df9fd38e497c2903c2ca5679ab75
+CT = 35a88015ae80727d6ca8823581707a80fb4142f143d00c7dd033a087c44c2e44adbeb333aa9ded10
+
+Count = 198
+Adata = 6e5e0793855f7145e13a5872f563e5ec61cfd2
+Payload = bb0036b34b0c20094d335a8c74f6b3dea42eeccf4145192e
+CT = ccfe476f53cfc28a00bb072626088022766c6cf454ecbe26ff9c8713422fe38d5bbf2dedccbffe10
+
+Count = 199
+Adata = f844684f5404e7d8eedfa20394b40b4f5d910a
+Payload = 86afa9cdd743916563ebfd3adbdd56e015ea3a4ebc61cfe2
+CT = f151d811cf8073e62e63a0908923651cc7a8ba75a9c868eae75de56eabcf8e02c1a27705adef2732
+
+[Alen = 20]
+
+Key = 26d0a3a8509d97f81379d21981fe1a02c579121ab7356ca0
+Nonce = 8015c0f07a7acd4b1cbdd21b54
+
+Count = 200
+Adata = 093ed26ada5628cfb8cfc1391526b3bcc4af97d9
+Payload = 37ab2a0b7b69942278e21032fc83eba6cdc34f5285a8b711
+CT = a3a60b422eb070b499cf6da0a404b13a05cedda549c6b93e6ca0e07e04674f21a46df2659a5905fb
+
+Count = 201
+Adata = 7df13c9d2247aa40af7bbe2da98bd366d8b47b43
+Payload = 93925579b6367ff592ecbd59495fdeccb50f31ea4fa390bc
+CT = 079f7430e3ef9b6373c1c0cb11d884507d02a31d83cd9e93836597806f5da1d176c745d95c4fa46a
+
+Count = 202
+Adata = 7f369bbc99b6f08049eeb43566269a174829d4dd
+Payload = 8363aef9c7c34e1f8149de46c97d5ac79d38c6ed31ab1d12
+CT = 176e8fb0921aaa896064a3d491fa005b5535541afdc5133df826dda99111691993027628c70ff6ae
+
+Count = 203
+Adata = 04aa8442179f62babad0c006e36af0c21105f27a
+Payload = 17281acb525b13653000ab45d86e70106c10a93c99b18f76
+CT = 83253b820782f7f3d12dd6d780e92a8ca41d3bcb55df8159d074b018143a7ea1b5369b7f80eae20d
+
+Count = 204
+Adata = 997e646014f19a53beab8877ca6022bef23016f1
+Payload = 5d48a71557608736eded309027a80349a18e9ce5dee2bc6a
+CT = c945865c02b963a00cc04d027f2f59d569830e12128cb2455db17d3f75214c3cf39858617cfee57a
+
+Count = 205
+Adata = 60ffcb23d6b88e485b920af81d1083f6291d06ac
+Payload = 6c9d11cfb64d96bfab61c04a25d9e19294fb7330fb4847c8
+CT = f8903086e39472294a4cbdd87d5ebb0e5cf6e1c7372649e79550998376e61e11a5a69e9f8fe1c329
+
+Count = 206
+Adata = d574632658bf456dfbb11c2653602ed0f4dae777
+Payload = 7d41688c86d5e3bc53966810f2299fdd732e3471fb0a88f9
+CT = e94c49c5d30c072ab2bb1582aaaec541bb23a686376486d6a1b0d05a7ebc657c3235479893bf7e5d
+
+Count = 207
+Adata = d896ed60128f4bb0277d3af94c5138cf91697aa9
+Payload = 8c7ae2c3c503e9072d6e04e44c2ea78fd24994503567a136
+CT = 1877c38a90da0d91cc43797614a9fd131a4406a7f909af1980c98c8959c158ce209aebcbd554f250
+
+Count = 208
+Adata = a350ed58c04473e113b9088b1fb9dad92807f6b6
+Payload = 49bc9d3bcf3c22daa8cf55c1b59d4bffddc2412d60518e98
+CT = ddb1bc729ae5c64c49e22853ed1a116315cfd3daac3f80b7573175f9105cd16ee384465ebb232200
+
+Count = 209
+Adata = 1db5887001204194e8b5dcee92c8af8fa5f7321f
+Payload = 25f3788e0d3dd8f5821faa4e45a9d6b3995fd881f927135c
+CT = b1fe59c758e43c636332d7dc1d2e8c2f51524a7635491d732b67e993384f2e7229d1838efd040d99
+
+[Alen = 21]
+
+Key = aac60835c309d837aacc635931af95702a4784c214283ebb
+Nonce = 0e20602d4dc38baa1ebf94ded5
+
+Count = 210
+Adata = 796e55fbe7bed46d025599c258964a99574c523f6a
+Payload = e8610756528f75607b83926597ef515f4b32a8386437e6d4
+CT = e0a3d5f43e688ce104f4ae1a4fcd85500aa6b8fdbcd1b8d3003c0c3b7369e79339433e1754c0937f
+
+Count = 211
+Adata = 5170836711fcb1a350b087907d8a17c7637aa1595b
+Payload = c61b0c1845fa9b2e0013b3fa9a8cb4f4fbbc6846f63ed180
+CT = ced9deba291d62af7f648f8542ae60fbba2878832ed88f87120a7f18d021833b167bf330c4858239
+
+Count = 212
+Adata = 2a68e3fe746f593c1b97cb637079c3e5ee352c107a
+Payload = 10c654c78a9e3c0628f004b061e28c39a3c23e7250f53615
+CT = 18048665e679c587578738cfb9c05836e2562eb788136812ca9698d9a88e892c364e57dd35c2f17a
+
+Count = 213
+Adata = bf38ca0e89b8f5ccd29387f7f193ab5a967caa715b
+Payload = fa3a959fdff853c39f76da626094a1ea6dbc78bd2f091a79
+CT = f2f8473db31faa42e001e61db8b675e52c286878f7ef447ef3839d6f7e20a2e343f4c4da9eb9be13
+
+Count = 214
+Adata = bee00f2f75a4415ce993d2d14a6d8e01d1d59a48f6
+Payload = 76d12e3c4c5d990bf563c60aa4999e52998d887f97477f6d
+CT = 7e13fc9e20ba608a8a14fa757cbb4a5dd81998ba4fa1216a6630bfb7a2a2441e020efdf36274b72f
+
+Count = 215
+Adata = d5b614e4e8f72a5d8b1ec2b375da5dac64c2cc30b1
+Payload = 693fae7af84aa397f0b2baaed9b3c7953f75e7424c49b634
+CT = 61fd7cd894ad5a168fc586d10191139a7ee1f78794afe833866bcee343ec5aae61f9effa19b99d3b
+
+Count = 216
+Adata = 33f11aa36d8ab0fc53486839a576b31ee915dbd769
+Payload = 56ce9a09f38127b14dbbdcaa59f363c92a3b9843ad20e2b7
+CT = 5e0c48ab9f66de3032cce0d581d1b7c66baf888675c6bcb00331b60eb252f744a06b4a95aa9f4e7c
+
+Count = 217
+Adata = f40bce1a6817b29b9e8b56f214fcca7dfde17e7ee6
+Payload = 5cd8986e974d09ede34ba68fd81d6109a64092e7fbbaf87d
+CT = 541a4accfbaaf06c9c3c9af0003fb506e7d48222235ca67a4153778a644cb2469cef3ad125e257bc
+
+Count = 218
+Adata = 53c457d8d4d4ab95ba116c28b82c16743cb09de9fe
+Payload = 9c3c610f204d98702dd91ea28e0cc14830b26bb5e2ee0349
+CT = 94feb3ad4caa61f152ae22dd562e154771267b703a085d4e7013e1c34dbc5efc7bcd4f8e52797644
+
+Count = 219
+Adata = c7acf1b17609dc336df1006ffac6497777cdfd497c
+Payload = 90c5dd9db0316dac89db18f70491bdf0a06a6a7f72b77d9a
+CT = 98070f3fdcd6942df6ac2488dcb369ffe1fe7abaaa51239d66aed667c761b7dea44822e30cff671f
+
+[Alen = 22]
+
+Key = 671544bf2988056f7f9ccd526861391a27233793a23f811f
+Nonce = 0a259148a1d081e0df381ecd0c
+
+Count = 220
+Adata = 61dafc237cb52f83ab773ba8a885462b6f77d4924611
+Payload = 576b069ae2713f53d2924c1fd68f786cb2eec68892f9e1be
+CT = ce06b3d09b02921f290544032a081a7766612940048867281bb089af0245792c16e6320cf5ffa19e
+
+Count = 221
+Adata = 87e49b8164e7052becfa0c966991637b38df833fc5f7
+Payload = d7eb0d7dd737805cd3b8dbf451aeea2fa1f6a96eb58cb428
+CT = 4e86b837ae442d10282fd3e8ad298834757946a623fd32be3cec29bd5df92363d6bb75456f5cd32b
+
+Count = 222
+Adata = d302a518d7c625756d3e4c8cc2b1d973a19107c945fc
+Payload = 77d8c9e6321314524afd05b7ad599c29f4eedda9e9f0763f
+CT = eeb57cac4b60b91eb16a0dab51defe32206132617f81f0a901ca82cddb78a2fe3904d1d8bf6fe5b2
+
+Count = 223
+Adata = 6566bb616a94bb03df5c26b722bcd38d516285c5f6c1
+Payload = abbf28b3ae164051648293d0b94e11f5af8468450005c7c0
+CT = 32d29df9d765ed1d9f159bcc45c973ee7b0b878d96744156d095ad121f0f76f07b715cad996def52
+
+Count = 224
+Adata = 141be3601e38185a9fa1596d2ee406415c9673af32f5
+Payload = b67d50110f844b36a00d352123012a1123c7c3cba959dc48
+CT = 2f10e55b76f7e67a5b9a3d3ddf86480af7482c033f285ade8529ec8f477462dc2409482c3479756d
+
+Count = 225
+Adata = a2969243b0955402ab45a430fef2ef9e0c025006732b
+Payload = 2a63f7b09b43fee65738e8115bd8419b3ef3e8f86eca707f
+CT = b30e42fae23053aaacafe00da75f2380ea7c0730f8bbf6e9b14fe8dbb3c361ea61d7b44e689a1c48
+
+Count = 226
+Adata = 87faef55c54250c30232ccaf5efa1ff41b6243b2a5bc
+Payload = 59dad755af92c29522da4348ab9b3037fe87004f5fa1394a
+CT = c0b7621fd6e16fd9d94d4b54571c522c2a08ef87c9d0bfdc54f0659fae291f943f2f3b33688602cb
+
+Count = 227
+Adata = 5d895fb949344e603ce5de029842b20d2bb614ecbbb8
+Payload = 64d8bd3c646f76dc6ce89defd40777fe17316729e22ba90f
+CT = fdb508761d1cdb90977f95f3288015e5c3be88e1745a2f993af4e3a7a20390a8da264299712a34e3
+
+Count = 228
+Adata = 74cc8da150b0bacdefa8943900b4ea047611d96be70a
+Payload = 0c3c9a634a000f00be003846eac7482e303a5bef3a70fe75
+CT = 95512f293373a24c4597305a16402a35e4b5b427ac0178e3a7f79d2b5a9bde5bd453bc8a03e971d8
+
+Count = 229
+Adata = 65f6adbaaa803dbad5ba9cb6d231314d55147cc61399
+Payload = 712c788928c8a1562bc1f3f0eb1286e15c3405f6a6fa0443
+CT = e841cdc351bb0c1ad056fbec1795e4fa88bbea3e308b82d5ffccebfb8c833833db40e98a1950fb70
+
+[Alen = 23]
+
+Key = 90e2c63b6e5394b1aeec03f95a9d13a01a7d4e9d58610786
+Nonce = dada5465eb9b7229807a39e557
+
+Count = 230
+Adata = f5629ca0eea589f6cf963d875a7d2efb656983f2dd2231
+Payload = 44dd098b1f869d670a8a841900c4bef023a1946a0c278354
+CT = 6b38ca85450e05e7b9362ed7e6e291a130ff233b5a561cdef7ec84dd992fdf98514f845dac8f656e
+
+Count = 231
+Adata = d43d7753530a7280b76221906dca85d396b6cf05125018
+Payload = cea19562328bd1fea889f575db6a28a14b7d06fb9f9c98bb
+CT = e144566c6803497e1b355fbb3d4c07f05823b1aac9ed07313613ed15d527d9dc58ab6893e723db58
+
+Count = 232
+Adata = 75650ce366757618af20205b69af7e5d4e82c398c00101
+Payload = f0641f595b791edd860977fcf699688587a354e053e9c7fe
+CT = df81dc5701f1865d35b5dd3210bf47d494fde3b105985874ef8728d1bf3a2d93db3266bafadb7c26
+
+Count = 233
+Adata = c00f1b8066677c63e898fddfb8a1b482b536963da0628d
+Payload = c7486a084f8475e6f5138e8d6e9f42a1de90f05aa88a362d
+CT = e8ada906150ced6646af244388b96df0cdce470bfefba9a7a5bce94d7564d297fe87730f1a36acf4
+
+Count = 234
+Adata = 5a89ab6b26b2ca78f98a8f8409fe8008b97ba9ef185d41
+Payload = 091ef698e16dc43a11d3ea005d5a5cdb7f1bdb5665a6c81e
+CT = 26fb3596bbe55cbaa26f40cebb7c738a6c456c0733d75794cd971b07fc14c512b8df6dd964b129d0
+
+Count = 235
+Adata = 5d24d80f22afe713c4076c200c1bab36917907fde7b6d3
+Payload = 62f204394b367c4410746001e02dfd171858396568fdd43b
+CT = 4d17c73711bee4c4a3c8cacf060bd2460b068e343e8c4bb1a192b781dc94448d4a0f6a439a716339
+
+Count = 236
+Adata = 4a47a82b999a2a739959f153a091a65c4d7387646da66b
+Payload = ac1cd5ba4997af91dbd74aee7730f9ee92cf8a360ca96a8a
+CT = 83f916b4131f3711686be0209116d6bf81913d675ad8f500cade9533b272e0a3edeba68362b057b4
+
+Count = 237
+Adata = d9fc295082e8f48569eb073ac1b9566246728fc62ccaab
+Payload = d0a249a97b5f1486721a50d4c4ab3f5d674a0e29925d5bf2
+CT = ff478aa721d78c06c1a6fa1a228d100c7414b978c42cc4785d68df8ff28345be4d83541a72071059
+
+Count = 238
+Adata = 720a9dc3e33ac080775a06f67f4a6591c37d0e101944a0
+Payload = 77fb98f24172f5d5edadbf466ee910855a71d46090b789ee
+CT = 581e5bfc1bfa6d555e11158888cf3fd4492f6331c6c61664caa7ec8892be6a18458c663665495035
+
+Count = 239
+Adata = 13cdaaa4f5721c6d7e709cc048063cfb8b9d92e6425903
+Payload = 77fb98f24172f5d5edadbf466ee910855a71d46090b789ee
+CT = 581e5bfc1bfa6d555e11158888cf3fd4492f6331c6c61664862fda880e45e891a3a50da7e14344c8
+
+[Alen = 24]
+
+Key = 13cdaaa4f5721c6d7e709cc048063cfb8b9d92e6425903e6
+Nonce = f97b532259babac5322e9d9a79
+
+Count = 240
+Adata = ad6622279832502839a82348486d42e9b38626e8f06317c4
+Payload = d7c837971b973f5f651102bf8d032e7dcd10e306739a0d6c
+CT = 4709600418f2839841e6d126359f6982bdb53acc7ff209635623d15b24184481eadc63bb8c878fc4
+
+Count = 241
+Adata = ad4833aa53218949cfd724814a43889a74a2114bbef4cf37
+Payload = 7d672bccd0fb01ce79320ed61779146aa432038daa13cb41
+CT = eda67c5fd39ebd095dc5dd4fafe55395d497da47a67bcf4e614c3e546273f0aeef207bd3f4d32fca
+
+Count = 242
+Adata = 54a723826086c7175e8fdc854b62d780de6ac1f90b57dd3a
+Payload = 0e1b73df74982f535a5fb08bc13d22515ee10969efe033bb
+CT = 9eda244c77fd93947ea8631279a165ae2e44d0a3e38837b413c6395ce9aee2e22ac0606beb140185
+
+Count = 243
+Adata = bec02d7df4cc3deefdd7e7d3ea82d381c870ad46bc06d64f
+Payload = 9a55aff269b180118ff0ea99e851c7474d19d23e641f16a9
+CT = 0a94f8616ad43cd6ab07390050cd80b83dbc0bf4687712a661e4f02150bedd86dfa49f52b214239d
+
+Count = 244
+Adata = 1b8090d712e0ec95a01bc3aeb6f5230c67c355e0ed68043a
+Payload = ff19294e8faed8353dbcab0b146e2ef928dd2680833424bd
+CT = 6fd87edd8ccb64f2194b7892acf269065878ff4a8f5c20b2f0e82b9f04bfc0cc0ba432b5135450c2
+
+Count = 245
+Adata = 5ed0b9f25d07b26717cdcb2507bef9d681ecd9389831ac15
+Payload = db1eba6ac4a79aa1d97838d263c7c4ffa7d354770e762805
+CT = 4bdfedf9c7c22666fd8feb4bdb5b8300d7768dbd021e2c0a2e64c82b60880c5c7506321a1060a481
+
+Count = 246
+Adata = 55f16fefaf2168aebc61b5e01d9e1f7bfe215eaaef118974
+Payload = 012d45168505ca9fde5aed123875639a207d473b993dc7b8
+CT = 91ec128586607658faad3e8b80e9246550d89ef19555c3b77152f64dc993b36ad9d5d12bb52b1ad5
+
+Count = 247
+Adata = 9893bf14fd3a86c418a35c5667e642d5998507e396596c50
+Payload = b205f26d6c8a8d6085ab28d595703cae046f96d82093082b
+CT = 22c4a5fe6fef31a7a15cfb4c2dec7b5174ca4f122cfb0c243e5c69256b6326ebb7ee6e677d396765
+
+Count = 248
+Adata = 244b840085bda9576c8424bb05a925a6b09cad2d0528ab8d
+Payload = 549ba26a299391538b56ce4bd71dbbfd96995836f8915ca5
+CT = c45af5f92af62d94afa11dd26f81fc02e63c81fcf4f958aa2083dac565c7a63908f0022e2867bb68
+
+Count = 249
+Adata = 9e8d492c304cf6ad59102bca0e0b23620338c15fc9ecd1e9
+Payload = 9e9dbd78a1066800ae33253be6104015158a0187e4f38116
+CT = 0e5ceaeba263d4c78ac4f6a25e8c07ea652fd84de89b851968242fe32958ea32e670ae1b3543974f
+
+[Alen = 25]
+
+Key = 90851933d4d3257137984cdb9cba2ca737322dac4dbd64bc
+Nonce = be02df3a840322df8d448c600c
+
+Count = 250
+Adata = 69a9dd9ac8be489c3a3f7f070bdaca10699171f66ab3da9351
+Payload = ba1785a149cb8b69a4e011c11a3ff06f6d7218f525ac81b5
+CT = 89ab2efefa8406336d9e2245199fbc9454f0ef650b9ed0f446c7246bd3130803bf8d703ef5bdf15c
+
+Count = 251
+Adata = 0c39a72f0f38d2713c164b0f870646fc65b9838a322ecfddd0
+Payload = 263dc4fb5cd8798ce0f183a816e51fafba167533dde1bf96
+CT = 15816fa4ef97f4d6298fb02c15455354839482a3f3d3eed7096a6a4422e582c5d02973952ac80e5f
+
+Count = 252
+Adata = 911d9f5c4c34c2f4b69be1e253d43fe729e2ab2622130394b1
+Payload = 7b5da2c283116713f3d80c7907114270964541e03ab80d50
+CT = 48e1099d305eea493aa63ffd04b10e8bafc7b670148a5c115965f6df4332fe7a2cdc4d1b80e28a34
+
+Count = 253
+Adata = 8a961df9c23f6d5ecdafa94c61164a22f460a1bf7415258d39
+Payload = 541a2b3ee25022c92fdc6783a6cbde90680ad3dc41868e5f
+CT = 67a68061511faf93e6a25407a56b926b5188244c6fb4df1e18bed174081b2170ffc6ab53b54c9ddb
+
+Count = 254
+Adata = cac7a248a4d4e96a9733627e247234995d6aa57e491498118a
+Payload = ebb2e893da9f32c363f98bc76fd14eda59e7cc620070f6d3
+CT = d80e43cc69d0bf99aa87b8436c71022160653bf22e42a792bac3d3a2b9ef6d4c8715f9a5c6fe8245
+
+Count = 255
+Adata = 41eacf70d05a6d0cdbdd38f197a52987def8fde37f332eebd9
+Payload = 199cca0d0e1c70ec405d6816cbddc69f8ada624f2c168891
+CT = 2a206152bd53fdb689235b92c87d8a64b35895df0224d9d07f9610c82fe9a7c78e8f1980e886b446
+
+Count = 256
+Adata = 78b6ed20ed85337c969618bd41917cd85c37e7c35c3a12e25f
+Payload = ca481f557306f9ce386edd0cfde375a550cb5b574be524f7
+CT = f9f4b40ac0497494f110ee88fe43395e6949acc765d775b6aab366637ec41d0bf557f578be424a8b
+
+Count = 257
+Adata = 87faef55c54250c30232ccaf5efa1ff41b6243b2a5bc93e7cf
+Payload = 6f1b4ff66d3aec7b0c0d9e202acc52722e15bca0983291e0
+CT = 5ca7e4a9de756121c573ada4296c1e8917974b30b600c0a1e57a5b3ae26469d229425f887ad5a2a1
+
+Count = 258
+Adata = 7f19ac3e53a629a2df1cb56d68fde0c80a46be40a996830e2a
+Payload = 7533c88ce55c2243b64b6c5bd01aed4dd6ac8bb9fd333e06
+CT = 468f63d35613af197f355fdfd3baa1b6ef2e7c29d3016f476ce4fe492062f74bff4c3c0e9ea849a4
+
+Count = 259
+Adata = 0516a69bfd8785ad001367b51e5410b75c11b761be08b9eea5
+Payload = 19ea09a9bfd10db2a74e398859d8f4831fa5749767773acf
+CT = 2a56a2f60c9e80e86e300a0c5a78b8782627830749456b8ead47ffc17b871f530f62b9f9aec98509
+
+[Alen = 26]
+
+Key = 5c5d02c93faa74a848e5046fc52f236049e28cd8096dcac6
+Nonce = 54cbf2889437673b8875a0f567
+
+Count = 260
+Adata = 09fc21ac4a1f43de29621cacf3ad84e055c6b220721af7ce33bb
+Payload = b4da43ebfe9396b68f4689fba8837c68d0064841c6ddd4a7
+CT = d40725397229021a18f3481e3a85f70445557bb2a85e4ae8101a34c777e918e16186fda05a386572
+
+Count = 261
+Adata = 10f0c45d06a138a964fb11b2d450620a2977bcd2952afe371cad
+Payload = 7b628930d44e22907277db057395601b82b65479fbd59613
+CT = 1bbfefe258f4b63ce5c21ae0e193eb7717e5678a9556085cc1e79234882846d916dabae40b1bd055
+
+Count = 262
+Adata = 64dbb170a037b36beed28a2637c87830e2b23f8eea6cd9a7331c
+Payload = 9db30b669fc5d25f05e0dc708d597da6ddce2dacc85ae99c
+CT = fd6e6db4137f46f392551d951f5ff6ca489d1e5fa6d977d3e35499e3c09dc384eb41344ee8be3769
+
+Count = 263
+Adata = c47de6608546a02c6eebd6628c9123f6936c0154d3df52a367e5
+Payload = 62036cbed3666d85624d3dc9c1f437454b9ab5c03ce0de92
+CT = 02de0a6c5fdcf929f5f8fc2c53f2bc29dec98633526340ddd605189608ce40b237dde7bed6fde487
+
+Count = 264
+Adata = bab7e36098d59d3a31d7784d549aebfc6938bbd0612c85c0edb7
+Payload = 5c9bc739f6b6fe4214f3c6aad307d1f208892d79de010e37
+CT = 3c46a1eb7a0c6aee8346074f41015a9e9dda1e8ab0829078c31f69c847440be20bd08cfef330002f
+
+Count = 265
+Adata = 8a9716135fa38c250e249f6712f7cb3ad9210d7278b53d599df9
+Payload = 0df109298083d3896214b84ff6edb11e9cfdbd88f5702839
+CT = 6d2c6ffb0c394725f5a179aa64eb3a7209ae8e7b9bf3b676ca83622b127fa50fc9637998c0ddd44d
+
+Count = 266
+Adata = 2d52447d1244d2ebc28650e7b05654bad35b3a68eedc7f851530
+Payload = 518f651f6d82f670b63767ad8476ed8fc24df12a45110611
+CT = 315203cde13862dc2182a648167066e3571ec2d92b92985e81e738b9e4b0dc7b7a39eb7d03adc64a
+
+Count = 267
+Adata = 3cba0fd2bb16ae1d997cbe659a2dd101885c97f2322b0172b5d6
+Payload = e91a694bea2d351928b6098660d49f382c087f6777de159c
+CT = 89c70f996697a1b5bf03c863f2d21454b95b4c94195d8bd3d298c05b1d2e597f44f8621ecd11ed16
+
+Count = 268
+Adata = c7f93152016bba584dadc6002ec493a46305726068886d2340da
+Payload = 2d14792ed349a878b2b879e7fa5f438a50e36947ce827e73
+CT = 4dc91ffc5ff33cd4250db8026859c8e6c5b05ab4a001e03c5fd5221fceecbf0dc7211a1aec06793a
+
+Count = 269
+Adata = 799cac048eaccded37ca6a70dd89595e1ee04606212da5572679
+Payload = 315b8d95938d304015bbc94ea03c21f6dc25c90f991ba680
+CT = 5186eb471f37a4ec820e08ab323aaa9a4976fafcf79838cf5c25f00b862b49fcfe8447949f39787c
+
+[Alen = 27]
+
+Key = 0234dae5bd7ae66c67ff0c1a3f1a191a0d7bceb451bc2b7d
+Nonce = 16d345606a315ad2406abbcb43
+
+Count = 270
+Adata = c37fdf7449fd7e943595d75e977089c623be0a3926e63fdbbfdf4a
+Payload = 0f960a89a7e806f8709047cb7a2e7c4211ad724692c88a05
+CT = 3907880d25f910eab12dd14e704d1b33ea7c453634d54da2a461f44dac1112ae3f9c65671a931d3e
+
+Count = 271
+Adata = 85f647d940a6d1acb6b7851912f807063515631eaabaa019dcfb99
+Payload = ab40a4baa39b0e568bf2193fecbc36b84c76bb50523b2912
+CT = 9dd1263e218a18444a4f8fbae6df51c9b7a78c20f426eeb5ed15db6e142ee07b59eb5b0ad3a59194
+
+Count = 272
+Adata = 79ae14843b2e7ccf0fd85218184f7844fbb35e934476841b056b3a
+Payload = b74c06d9077c568762796d5be14f3563e7205a6e9bc65bcb
+CT = 81dd845d856d4095a3c4fbdeeb2c52121cf16d1e3ddb9c6c203f11f66b74366caeca8dbded2bf17a
+
+Count = 273
+Adata = 542d86fd7ff591f97e6926a090553538bc3b8a6bcd45f2e29c7d9f
+Payload = f2179beb5635a6d8a8340acea0ffcf4428e5de1306a8c12b
+CT = c486196fd424b0ca69899c4baa9ca835d334e963a0b5068ced925fb9a4cf6b6bf17f72ab044653d1
+
+Count = 274
+Adata = 4392c3043287dd096b43b4a37ea7f5dc1d298b0623ccbf4fd650a4
+Payload = d1a9e4593bc3d02c407e84a1736e587c1819c72195a07d57
+CT = e73866ddb9d2c63e81c31224790d3f0de3c8f05133bdbaf0d1f677deca1bfda83c1b9223aaaedbfc
+
+Count = 275
+Adata = 966954582e78e99ba68d6ffaf794b55a82325834ec4f373b2bd227
+Payload = 15b94910853a8f23dfb8b31c0262b8461f777075cc0937e9
+CT = 2328cb94072b99311e0525990801df37e4a647056a14f04e12937871932a7ca3e1e27a90a7f73694
+
+Count = 276
+Adata = b7aca715dcc402565cb711b001f21e8e95ec54c4afab2e2dcc8a2f
+Payload = fd1681cc306518bf77766f55226afac3eb21e31ed897075c
+CT = cb870348b2740eadb6cbf9d028099db210f0d46e7e8ac0fba0464ff4ddeccbd523a5ed3b32337f7c
+
+Count = 277
+Adata = 290a36f7daeeeafca4431446b396dbec0bea0a1f6f081418811656
+Payload = 0804fa48fc76f98bb021e3501bef8875b64a3b508adf8594
+CT = 3e9578cc7e67ef99719c75d5118cef044d9b0c202cc242332f68ed5e44a71c5ba8bade07b7bf5495
+
+Count = 278
+Adata = f0739a855422310a21ed863376bce9d75dc7c687b9b535cb7a05cc
+Payload = 4f5c6d80a3955f12f4d2594e02a045c42fabb11d90817fff
+CT = 79cdef0421844900356fcfcb08c322b5d47a866d369cb8583b5dc1fbe32743e257b7c1c9d624adc8
+
+Count = 279
+Adata = ffac0edb0b62977bb5040e4128a48deaf711f5e6a84d8f677341f3
+Payload = 5c29c458212d010a0d9c5a547aba1138eb4ce94742fef01e
+CT = 6ab846dca33c1718cc21ccd170d97649109dde37e4e337b9e53b654de1976294897cae0476ac6248
+
+[Alen = 28]
+
+Key = 6351a67fd6daabd2fd49ee944dd41dd37301f958dd17fcc3
+Nonce = b8d517b033754058128d13d11a
+
+Count = 280
+Adata = 511c6924fa96db716f6b053b7a48aebdc1504145a56cd02d6be2590d
+Payload = 0c0663dd69ccbffbbd0c8c2e9473d0354451ae7a20fa3695
+CT = 19f2745df5007619c79c84d174e4521b942776478a0601d982c560fede4741e2fd3b54b3a48f3e38
+
+Count = 281
+Adata = d9ccd93317441e9d6ccc358f31e7e2ccef8c921b23d742993eff9d53
+Payload = 34a882834172924d39d2df5d637d9d273a99a9222971701c
+CT = 215c9503ddbe5baf4342d7a283ea1f09eaef711f838d4750ee82d927a2aa678e792acdeb615409f8
+
+Count = 282
+Adata = c268d65f7a7b30d3d198b2045fc8d1db7adda56604fa567d8855d1a5
+Payload = 5b7450b73d68de079e92bba56c7860f11126b8fdedd3334d
+CT = 4e804737a1a417e5e402b35a8cefe2dfc15060c0472f04017a48226389d24ed3ec3da2da1a9bdf7c
+
+Count = 283
+Adata = 4c2b6815156f0643b4573825e28b9f2a668a4976e3342884f48bc310
+Payload = 140c6933248f052e05bd4a36aec185ee86730108cc2989b6
+CT = 01f87eb3b843cccc7f2d42c94e5607c05605d93566d5befa16fe6bd83993ccbdd50e1ca061f4845f
+
+Count = 284
+Adata = f11c873354b3c0cff2c8f8010e9e364582b9c05c62efdefbdcc2e1c0
+Payload = 2a083de317380d94dd991349a7b8761c7c98013b1b0227e0
+CT = 3ffc2a638bf4c476a7091bb6472ff432aceed906b1fe10ac577c5893cb3896400012e48f5b190b73
+
+Count = 285
+Adata = d0a056754098d7f7ef2f639d61ea3d2b9cc936c48a1b2c5a9e96d169
+Payload = 02769283d5a06c363c2cc66c09b1ac954134e3ec7df773f2
+CT = 17828503496ca5d446bcce93e9262ebb91423bd1d70b44be80c80101fdfe6dc4cfce080bf921582e
+
+Count = 286
+Adata = 56de0e55653b9a04a3ded71c31f8807c3c8dd96bc82892e4acccef30
+Payload = 4890404bc5b24822b4cf7a2fe28abc52fbefb919ae0629ec
+CT = 5d6457cb597e81c0ce5f72d0021d3e7c2b99612404fa1ea0122dfc20e3088dcd33b6706a0c1fdfa8
+
+Count = 287
+Adata = 794a86f5b20d344ad86fd5523d08f1864737be57731440c29aa6b425
+Payload = 161f8501f59338f72026815c77cad6d8d581859192cd5644
+CT = 03eb9281695ff1155ab689a3975d54f605f75dac3831610828f0a78ce798448529afe26eec875aa6
+
+Count = 288
+Adata = b1eafc03ea2fa3e9e3842a09a225e83055de8a1f412badd6fc9ead12
+Payload = b3f38aedbf08dd7ead9d402c5aaa1ec9279c7e4bfd4a2967
+CT = a6079d6d23c4149cd70d48d3ba3d9ce7f7eaa67657b61e2ba48856a266c0d404474316f418f8f4e4
+
+Count = 289
+Adata = 8fec99f1be0e69267620c0b934bf984d60c1437f74c6ac19610fe188
+Payload = 5c09e2a6a055fe9c21e06e5519cf56b8e2e7fb44094e79f9
+CT = 49fdf5263c99377e5b7066aaf958d49632912379a3b24eb56412292d8015285efaa6f1154580eb57
+
+[Alen = 29]
+
+Key = 9a5a9560baed3b8e0e90b92655d4e5f33889e5d7253d9f6c
+Nonce = c0049382cdd8646756d4e6bff5
+
+Count = 290
+Adata = c95a86d52088a8b0107cc5b437a8938b2c9e74e46e2e03bb9bceecdbe3
+Payload = 5bbe9c1fb2563e3e82999fe097b28da4dc6ff2e020f3b4f3
+CT = 6d5401db42b5c48b79203b6ad82806d7460ac4c82ad0809b811020480e834f6fe55900a162a4e61a
+
+Count = 291
+Adata = 1dd56442fa09a42890b1b4274b950770ea8beea2e048193dfa755a5943
+Payload = 8a85a9b32a323c6af156a3fa2f1448b6387cc3660aa8a0f4
+CT = bc6f3477dad1c6df0aef0770608ec3c5a219f54e008b949cba9827513c7f1de970d316b6f81c109d
+
+Count = 292
+Adata = c834096e059ea73ddc90b0c982f9a3a31bfc6b1b81a03f9d41c9c741e7
+Payload = 1e02c13104937fe084b18eba1ea8951dcc5e75b692937dea
+CT = 28e85cf5f47085557f082a3051321e6e563b439e98b04982c9d79dd3255a8323f8229ac1c6d76ae4
+
+Count = 293
+Adata = 9249022bdead3d86ef5bd03acf053132d08663ba1f2426e19c126b22e9
+Payload = 3225570fb15ae13a13c71e364ae9a9fef03d1c9a7fa5dfa0
+CT = 04cfcacb41b91b8fe87ebabc0573228d6a582ab27586ebc8425dc81f93257ae8399fc2d48b4a7685
+
+Count = 294
+Adata = 3c3a92c4ece49fb9f84243d7c1bc91f595fce118305a758c83985c34b4
+Payload = fa0a458174537ddba25708b8d0c22d5517d57b122517b0c9
+CT = cce0d84584b0876e59eeac329f58a6268db04d3a2f3484a1b595003c58e69600c2a3b9ec45c0e15a
+
+Count = 295
+Adata = b49b845ccf76acf508f9db8543c73375d530d91f3b0e4ed70decfd2c2d
+Payload = b7fbdaeaa3ee1d0bbf5ec47898b069ec4ba6a140a3e83996
+CT = 8111472e530de7be44e760f2d72ae29fd1c39768a9cb0dfe0da009261c43c6640303696655e2981f
+
+Count = 296
+Adata = 3aabdf589eeb1709bb3d60b08bc71eaa3ffeba4e2903a5dbd8339aae85
+Payload = 9aea86b9fbd9bd4504ee2e25054942b33d3cdbd84215db7e
+CT = ac001b7d0b3a47f0ff578aaf4ad3c9c0a759edf04836ef16dfdcdbd4ad711c493d3176f032a02af0
+
+Count = 297
+Adata = 6a79879cd62bd1dbf9609897d2ebf2dc4dda43cc15fcb241aaa0deb4b3
+Payload = 3a861638ccd6591e51e2a525be59447e4a28bab32e36a5f3
+CT = 0c6c8bfc3c35a3abaa5b01aff1c3cf0dd04d8c9b2415919bfd59b45c05873c670f5f8bb47732d59f
+
+Count = 298
+Adata = c5b6ca474eb251817ae4d2f47c0632c381e222aae3b6f585a0dcae120a
+Payload = c7da4e9ba6e5758be726e6e227d7bddb0332228f7e3ecb6b
+CT = f130d35f56068f3e1c9f4268684d36a8995714a7741dff031572a24bc00b40a6b4b172b3648142e7
+
+Count = 299
+Adata = 64a96d191f1d5f95f5fed6259e33e7206adc07b0279e16cb453a9c6438
+Payload = 2b9347d3e195152dce22afdb92acd179eb484872285704c3
+CT = 1d79da171176ef98359b0b51dd365a0a712d7e5a227430ab828bc33396179ac39ce0027a1d62e0fe
+
+[Alen = 30]
+
+Key = 3e61094c80df0053e86d43fccf4e1d3ee2cdb862d3237b0a
+Nonce = 63f00b2488809fdc49ca5f05d5
+
+Count = 300
+Adata = a08763ca936abdeece06467bef8c3c47c3a473636a039d4db540c867d3e3
+Payload = 1fada8f4c7daea0d1c370184c169485b80a278708ed41451
+CT = 680dd22f16a1290bde42c9792dfa997aed24d5bd2265b6e095aa6b99d3f894d3790c2aa2dae1ba2c
+
+Count = 301
+Adata = 19508a6c83b992c660a1a28597e07c729ea2ed39401aadbf9d7586b5720d
+Payload = e9f1f2cf0b8d563e2d20f39f9f464a808b136dba364a6446
+CT = 9e518814daf69538ef553b6273d59ba1e695c0779afbc6f72d9d77109f4597e9c4c8cf7023dc5f3b
+
+Count = 302
+Adata = e5929c3b5d68a4c9fcf1168ea35bf8c0bf3043cb1ed54ff301578b3b7266
+Payload = 07a74c3b874849ecbf013713b80a84337c90b690cea0b837
+CT = 700736e056338aea7d74ffee5499551211161b5d62111a86b2544ecc3c7d5accd22ac075e7b44d5a
+
+Count = 303
+Adata = caa5cc5d0d87680eafc29429bac55c9e33167d485789c7c124b5c57a1ba8
+Payload = 4255f2cf90f0d15e9bead4be799165c57f7225980713d609
+CT = 35f58814418b1258599f1c439502b4e412f48855aba274b8f1a8a1db25de0fab7cabb11a18497584
+
+Count = 304
+Adata = f61cf7ae23a66777bd3fabc3d542feed2b00c6d4f46a772fda11b5214551
+Payload = 70b1e2e4cf260b108f5a52d0d8234838ffd6ffe7b4acd78d
+CT = 0711983f1e5dc8164d2f9a2d34b099199250522a181d753c5a9718ed0257a50e38de86154054fc3a
+
+Count = 305
+Adata = 85f647d940a6d1acb6b7851912f807063515631eaabaa019dcfb993e86f4
+Payload = af4be10b3a59ea99dadc75fbe5651f6f7630852bb556aa39
+CT = d8eb9bd0eb22299f18a9bd0609f6ce4e1bb628e619e70888550d1acca34c28ba8a3b890bb0542b23
+
+Count = 306
+Adata = 296cd04c4d9ab493def7aeb6841a45309e777028868efe45166235c56b2d
+Payload = 72d5663727592f1bfc9c65be83f4d3508126fecc4e34ae72
+CT = 05751cecf622ec1d3ee9ad436f670271eca05301e2850cc3a268dc1596a7855639c63fa76ad8479b
+
+Count = 307
+Adata = f380ca0a26a94adcf2c1ce26d226d3bf520268c72412e58a71acd9a66d00
+Payload = 3e2ccce03c10ce1527ef8e002adb265edba5779fbd4fcaf6
+CT = 498cb63bed6b0d13e59a46fdc648f77fb623da5211fe6847e3416c75fc28924a21cc123e62a7894c
+
+Count = 308
+Adata = 8825532a31680cb3b5bdb027802d2d8718755e135367e0c8c88e21288311
+Payload = a18dfe7f2d7bbaf316366f67445170afcbe18e2a1de1e947
+CT = d62d84a4fc0079f5d443a79aa8c2a18ea66723e7b1504bf6ff1a47f23d08485951aab18b393584ef
+
+Count = 309
+Adata = f768375589b687fb17c56673af4263626da69eb991007d94d4f5a163fd05
+Payload = 17ca72a440c944fefd6c08ecc3a8ecb54d96b9cad9d2aa4c
+CT = 606a087f91b287f83f19c0112f3b3d9420101407756308fd7d024456bcb69a4f77008773a3f48805
+
+[Alen = 31]
+
+Key = b5664dd6ed435df006052f6ded74bb7ce9482ca9229886f7
+Nonce = 7a1649896f3e030c18f0205599
+
+Count = 310
+Adata = c5f1a26351e53e6509c8bbbed03c42c23ad81c65fccec7ffa1cb494c7f1fc4
+Payload = 0b6de49b530703affc94010c2b793ddc6de0c44d48037ff2
+CT = 56b02fea595cc24e798691ae905be3d466ca68ca744005dba260b5ea3b047020b73b5bafa17e5084
+
+Count = 311
+Adata = 89899be18b4c389afa769b11ecd22e9fad8f38fd614ea5f8eb7a066c0ed8d8
+Payload = 2f1821aa57e5278ffd33c17d46615b77363149dbc9847041
+CT = 72c5eadb5dbee66e782151dffd43857f3d1be55cf5c70a685e4bd97b9dc83134867c00c2acea0aaf
+
+Count = 312
+Adata = d43b841f174335f1347834590b0984a2cb35f7a00a0ee993157d2d4f848748
+Payload = c7da4e95cb38342c6d5bf0c381d5a192adc3bfc1cda3a1d7
+CT = 9a0785e4c163f5cde84960613af77f9aa6e91346f1e0dbfe55202ba34bb9918fe915776de65947c0
+
+Count = 313
+Adata = c1093518efd80245e3c42371f220b21f2034e6738fe02ef43e828190f01aef
+Payload = 414a70aba5a219dbd41cdc46b84812b28cc4f7399218004d
+CT = 1c97bbdaaff9d83a510e4ce4036accba87ee5bbeae5b7a642fdf807b5a6880f2d4c36d558b40eb90
+
+Count = 314
+Adata = 90f627d5b939625bc76fe1bd4643b39edc11d3dc7f4bfe16e61bc26c3d49d8
+Payload = 58b260d3f645a35bad7a3842440bc03608248bd46e725e60
+CT = 056faba2fc1e62ba2868a8e0ff291e3e030e2753523124495a9307ca4239380a45bb7f87e41c4cf7
+
+Count = 315
+Adata = 2f360a4715074e942244ab7f9b6db127b0442df9af2efa2e78db1a94312905
+Payload = 5505caa97218957e90247fde60275bdafce4b16bcb36c263
+CT = 08d801d87843549f1536ef7cdb0585d2f7ce1decf775b84af3aeadff9dd60468aef2a8e2c56dda7d
+
+Count = 316
+Adata = 7db564811f14bc5c2098d5635655c3671fbd8288ea14944af925eaec653408
+Payload = b93e40f556a786e39126b8834a6ecacd2dc9f0f528bab135
+CT = e4e38b845cfc470214342821f14c14c526e35c7214f9cb1c8335f2e31a0468b830c5009cd02dbd5f
+
+Count = 317
+Adata = 36be91854d3d02a5d62503bb9047ef4354280510f7576c4272fd757240b621
+Payload = 543a070fdb3a855dd7d83fbc5f983671ad9e905f307148e4
+CT = 09e7cc7ed16144bc52caaf1ee4bae879a6b43cd80c3232cd5d772a599e91504e022b9dbfb124b71a
+
+Count = 318
+Adata = 6aa6ea668df60b0db85592d0a819c9df9e1099916272aafb8813ccc2f2dd96
+Payload = 86ef67572cb339c6706eb5909b96848aba5246a196972a1e
+CT = db32ac2626e8f827f57c253220b45a82b178ea26aad450379846cd12430f7adc910d1f0c51d80636
+
+Count = 319
+Adata = 3a64414c3588d7c26871d7d054ac6c8420d4917e3baad4a343685916265321
+Payload = cecef24b62676a5623bedae8087b9b05d7e22b41a14dd2d5
+CT = 9313393a683cabb7a6ac4a4ab359450ddcc887c69d0ea8fcd9ee65ac3a8fae1b00a4f1dfe2577293
+
+[Alen = 32]
+
+Key = 50925853a84a33ff392154e4e737efc18dcfc98f4d5235a9
+Nonce = 809343e986f6ff47f54d4cac22
+
+Count = 320
+Adata = d70aef3532bdc5293a3ebb11589ac1f801c9f93ea0d656e1d04068facf9f768b
+Payload = 718f061e8b972a3adcf465d66c5b28e8661f080127f6722f
+CT = bad3b0e6772e9c4c9c631c095e259d99692292932efb72b8966e91a19617bb748f3495aa433585bb
+
+Count = 321
+Adata = 1ee0eb409398bc252175cb460ef9a2da4c9beab2ef6d8206e4fcce74df785246
+Payload = 72e6cebdaf88205c4e74428664bc0d7eb4687a272217b7ca
+CT = b9ba78455331962a0ee33b5956c2b80fbb55e0b52b1ab75dc8f70aa565a12ca3545e68110968040f
+
+Count = 322
+Adata = 3820db475c7cb04a0f74d8e449f026ec951fa59667738698b0ed5c8cb09a8c96
+Payload = d959dd38a458039e2400d21d27b9a2faee8fe23683330cb5
+CT = 12056bc058e1b5e86497abc215c7178be1b278a48a3e0c22daf38076c810e14a7843444a02f010e0
+
+Count = 323
+Adata = f555216840a1f40b411d44128e567617e2694caf16216ea74c604a8d6ec01e72
+Payload = 337f12e8ebc0544b82fcdd3c4a0dab0e5e75c9f433a27d66
+CT = f823a4101779e23dc26ba4e378731e7f514853663aaf7df1594aebf9b8318877bdec2900a22df858
+
+Count = 324
+Adata = 2311a6fe1feeda3a1f16310d635496c0dd662024f0b0f1de79325e030cb850e5
+Payload = 463c65fa7becae5605af80d1feca59075ee88c0abfc72cb4
+CT = 8d60d302875518204538f90eccb4ec7651d51698b6ca2c231d9872d1c10a6594b5c349b84f710d64
+
+Count = 325
+Adata = b2c633e3181ae5fe7828707ed5b70e0460088a84465eadeecdbcfa0e9ff19bb1
+Payload = 23c1732959c4bf85bc707e45cc964b6227acd3a8fc73e675
+CT = e89dc5d1a57d09f3fce7079afee8fe132891493af57ee6e2a9db7c4bcaf6087e158c1a5d4eb1c2cc
+
+Count = 326
+Adata = 791f23252094b9b99fafe7fac1d8ff3ba09305c476041e75afb245ac438b4069
+Payload = 02f60f967e7fbcf957313619882407ea8a03fc943062296c
+CT = c9aab96e82c60a8f17a64fc6ba5ab29b853e6606396f29fb5e1c87d9e1c1f3b7d30fdc2f0ccac783
+
+Count = 327
+Adata = 22197f9ad14591e7a6d5f8b18c969a553de9a85309757fa5d319cc505c24f438
+Payload = 6c1aa088d1a6086d0e72636744a6840c80ab8223409c61b7
+CT = a74616702d1fbe1b4ee51ab876d8317d8f9618b1499161201514b449a741e07f9287f7e9090fa54b
+
+Count = 328
+Adata = 0bb18f7280a30767cd769cb5ffd3edd1c18914b92d1b2192e27ac88f57135616
+Payload = 57275bc3b4d63b9b01b0b0760235c9785d45761cace23f1e
+CT = 9c7bed3b486f8ded4127c9a9304b7c095278ec8ea5ef3f892c889b610157e16e9f31558c669298a7
+
+Count = 329
+Adata = 3e5f0f32e27be18ca6f84de11e6e9c25fc0c4cb0cf83633eea1f033aa1373f3c
+Payload = eba27a27f0d4604a5296a41b3fe995c50c66bcba302d0447
+CT = 20feccdf0c6dd63c1201ddc40d9720b4035b2628392004d0fbe19321dc22c748a17aa5eda29d8cf3
diff --git a/lib/crypto/test/crypto_SUITE_data/VADT256.rsp b/lib/crypto/test/crypto_SUITE_data/VADT256.rsp
new file mode 100644
index 0000000000..af4f5c1df7
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/VADT256.rsp
@@ -0,0 +1,1823 @@
+# CAVS 11.0
+# "CCM-VADT" information
+# AES Keylen: 256
+# Generated on Tue Mar 15 08:09:25 2011
+
+Plen = 24
+Nlen = 13
+Tlen = 16
+
+[Alen = 0]
+
+Key = 26511fb51fcfa75cb4b44da75a6e5a0eb8d9c8f3b906f886df3ba3e6da3a1389
+Nonce = 72a60f345a1978fb40f28a2fa4
+
+Count = 0
+Adata = 00
+Payload = 30d56ff2a25b83fee791110fcaea48e41db7c7f098a81000
+CT = 55f068c0bbba8b598013dd1841fd740fda2902322148ab5e935753e601b79db4ae730b6ae3500731
+
+Count = 1
+Adata = 00
+Payload = e44b4307234281209bd41f89dbe2cc3fbf68e14df2f7fce4
+CT = 816e44353aa38987fc56d39e50f5f0d478f6248f4b1747ba003abc6a4b020625adc8b6cd7bafbd42
+
+Count = 2
+Adata = 00
+Payload = 8db7a73856bcb4007346bb3e00096f69e75e97c0bb960f3b
+CT = e892a00a4f5dbca714c477298b1e538220c052020276b465e7cfa7a208a8b3e6b6377236045df17d
+
+Count = 3
+Adata = 00
+Payload = 48f3ceda4fd390a7eb38f7f5bcd14310af6b5a557e676d44
+CT = 2dd6c9e8563298008cba3be237c67ffb68f59f97c787d61a81b39a0c55822e32042b4f8981021090
+
+Count = 4
+Adata = 00
+Payload = 7cdb2c9b167b3ae811289acf7dc1814bbe241f553447699f
+CT = 19fe2ba90f9a324f76aa56d8f6d6bda079bada978da7d2c1091117e2ad77db510d902038743b5a98
+
+Count = 5
+Adata = 00
+Payload = 41eacf70d05a6d0cdbdd38f197a52987def8fde37f332eeb
+CT = 24cfc842c9bb65abbc5ff4e61cb2156c19663821c6d395b5ac7379b8e51592b98e4874f4592278a8
+
+Count = 6
+Adata = 00
+Payload = bde9e3eb9f0c57302c9185b1cb912ef76d88f2f9c3b51e9a
+CT = d8cce4d986ed5f974b1349a64086121caa16373b7a55a5c4d08c1c902c4c2f078452dd6943b85028
+
+Count = 7
+Adata = 00
+Payload = 6f9ccc033c6bfbdfad4719ad033c927e2175727a9a021dc6
+CT = 0ab9cb31258af378cac5d5ba882bae95e6ebb7b823e2a69832fefb87445f1ca42811899acc0cdf68
+
+Count = 8
+Adata = 00
+Payload = cc67bc3b7afd625b2610226d3b30e111e6aa47a3254f711a
+CT = a942bb09631c6afc4192ee7ab027ddfa213482619cafca4481d605a1019c8e9778b8928b4636053e
+
+Count = 9
+Adata = 00
+Payload = a10c81725f49ab9075fbf4d96be030a2d881d8501b115d61
+CT = c429864046a8a337127938cee0f70c491f1f1d92a2f1e63f96a82e8411e5b04426dc608298c6408d
+
+[Alen = 1]
+
+Key = a4490ed6ab51dbfccd6f3702a857575dad44da3a27eaf31178abc97da60d1e4b
+Nonce = 26ceaf6e3b28190a17c4f0c378
+
+Count = 10
+Adata = 9e
+Payload = 1b5cc6b1651dec4bbbf5130343852e971c7ff1774100d9be
+CT = 789bce069a725a96c484e64a9e54dcb7a7c268c85df47815a462ff2dd8ba44a381e1f6edab12b5a9
+
+Count = 11
+Adata = 4e
+Payload = e7ab98901c0cb1d7d76e125d8ac8e86edf6f469fa937bc10
+CT = 846c9027e363070aa81fe71457191a4e64d2df20b5c31dbb6b0789c5866b7e3312ad992e228d6d20
+
+Count = 12
+Adata = cc
+Payload = 53bc7e3648d0b389b887b065e9e8f79685beb2eb36e2eb95
+CT = 307b7681b7bf0554c7f6452c343905b63e032b542a164a3e39b1b1a480fdd268c1c75b131cde798b
+
+Count = 13
+Adata = 45
+Payload = 6d7262476da95db63b322c5193ea05030923c3cbf0f8e8b1
+CT = 0eb56af092c6eb6b4443d9184e3bf723b29e5a74ec0c491a32060fea35c3e9528fd18994fae9fce8
+
+Count = 14
+Adata = 2c
+Payload = 8246bf7b81b287411777df7ecb53a1795e54b150ff3dd584
+CT = e181b7cc7edd319c68062a3716825359e5e928efe3c9742fb4e0a604ab30a764e8c98a9cafbca8d4
+
+Count = 15
+Adata = a9
+Payload = 2596ca8772bc69b50bcbf33088c6efbab614b691ed836f92
+CT = 4651c2308dd3df6874ba067955171d9a0da92f2ef177ce397ca72f1acf6dfd078b6f4eb82fa01e9b
+
+Count = 16
+Adata = 85
+Payload = 703065d701f4fcadee20d64300b3082c0c76490eb2dc4ba7
+CT = 13f76d60fe9b4a709151230add62fa0cb7cbd0b1ae28ea0c2a85c9252ee62612dc29cffa7289b2ca
+
+Count = 17
+Adata = dc
+Payload = a1aeda4b4cb8dd2943675181561bac48ba07e8de5b327837
+CT = c269d2fcb3d76bf43c16a4c88bca5e6801ba716147c6d99c9fbdac729413152c089d3939e30b8602
+
+Count = 18
+Adata = ce
+Payload = aa17341f4cead054d41c171dd34c459f7052da225c6c365d
+CT = c9d03ca8b3856689ab6de2540e9db7bfcbef439d409897f6f86266c273f8184e901b50c04845b8ab
+
+Count = 19
+Adata = a6
+Payload = 448cdd9cbbf863eb666fda36b825f3798827da3c1349611f
+CT = 274bd52b4497d536191e2f7f65f40159339a43830fbdc0b4ddd02d5c9ae2bbac47a7a076edb1d207
+
+[Alen = 2]
+
+Key = df594db94ef8eca56a417afe946085eaed444c7cc648d07d58132e6cb5bc2bc3
+Nonce = c1ad812bf2bbb2cdaee4636ee7
+
+Count = 20
+Adata = c0c3
+Payload = f4d7978fad36223623ccb5bb18a7373cba8a6e3b1c921259
+CT = bea778540a90033b2c0d087e3cc447711ea25f7eea96855506ec97f23bd6ea97834f92f7263c3195
+
+Count = 21
+Adata = 34b9
+Payload = f6c043c70136585d012ae0df6f42b25584e374649d0116c5
+CT = bcb0ac1ca69079500eeb5d1a4b21c21820cb45216b0581c9f3230df0b52b5cb7ac907dcadcb662ca
+
+Count = 22
+Adata = d4ab
+Payload = dec0c896b04490816409da1783478ef2510231d0a28c5b39
+CT = 94b0274d17e2b18c6bc867d2a724febff52a00955488cc35a99c3165ce83102891ef3885088ed6eb
+
+Count = 23
+Adata = 2a3a
+Payload = cbfd94fc31785d30214271dab2264134805fee6e52aa0b5c
+CT = 818d7b2796de7c3d2e83cc1f964531792477df2ba4ae9c50c9d8078607994ae5dff0de6526fb53d1
+
+Count = 24
+Adata = 4eb1
+Payload = 134d2d9726400d09dd3521326f96fbef993ddc0c40887700
+CT = 593dc24c81e62c04d2f49cf74bf58ba23d15ed49b68ce00c7e84da7d2564533e7ad55390ec3a6ff9
+
+Count = 25
+Adata = 0a79
+Payload = 1ccdcf789d42caba80d7893feaf26d3853fbcaf7d964df0b
+CT = 56bd20a33ae4ebb78f1634face911d75f7d3fbb22f604807520849295a56191367a696999ffef8e9
+
+Count = 26
+Adata = 865f
+Payload = 4042dbe148db3e6dc542b25d57a5787af535d38e8c34c71b
+CT = 0a32343aef7d1f60ca830f9873c60837511de2cb7a305017bc4aceed1a10309b6402b9e9420b33a3
+
+Count = 27
+Adata = f4ae
+Payload = 85b6894fec36294aa934cdc3523fd95c90ad56cbd18545dd
+CT = cfc666944b900847a6f57006765ca9113485678e2781d2d176c180d2e299ccf0b8781ba6de8a72ce
+
+Count = 28
+Adata = 10bf
+Payload = 0f27f4fc8538a676a763b3e5db845a1bfb20d5fab340dee3
+CT = 45571b27229e877ba8a20e20ffe72a565f08e4bf454449ef98d91c68d94873a5d6557611a5402a0a
+
+Count = 29
+Adata = b92e
+Payload = 1b5ec0cb03810a12fc6a0a1ff565afb001405d2a45a1f18a
+CT = 512e2f10a4272b1ff3abb7dad106dffda5686c6fb3a566865321cedf1122354636e130acbd69718b
+
+[Alen = 3]
+
+Key = d98193ab2a465e3fcd85651aaeca18b8e91489b73b7c7e93b518c4b5b81fc6ac
+Nonce = 2247dc7e2674e9e0a63fe70613
+
+Count = 30
+Adata = 4dc2f4
+Payload = edba7d6312144e90ec9eaace7576045a46e553dcb8ee5a98
+CT = 44b9ea727c847336fd739ad11f4b906b292edb810462f06ef59626ad5cdac2e4d4cb07b538a1fd8f
+
+Count = 31
+Adata = 2f3bf0
+Payload = 52a9626f5279c11e17e96f5dc5e1c1f58c1e913020d8499b
+CT = fbaaf57e3ce9fcb806045f42afdc55c4e3d5196d9c54e36ded0d53402253453e494ad350994ca77a
+
+Count = 32
+Adata = 95d2cf
+Payload = 87b6447d97a74d0b315031078aa06fffc7b9f246bfa5f147
+CT = 2eb5d36cf93770ad20bd0118e09dfbcea8727a1b03295bb196dbc3bff865a1d94b164df23d708e8e
+
+Count = 33
+Adata = 0caba9
+Payload = 1852848046706f2e274ba381a2bee1422df4f61d93219af7
+CT = b151139128e0528836a6939ec8837573423f7e402fad3001791b4469fe50d45f8efb81217cd68580
+
+Count = 34
+Adata = f8d459
+Payload = 99aac82fa66a15e4f76b76cf4590150999d5cf8468df7f42
+CT = 30a95f3ec8fa2842e68646d02fad8138f61e47d9d453d5b4587106da25012f92f01cc2db8d11ac29
+
+Count = 35
+Adata = e883dd
+Payload = 4e2f0f91990b855a00d27fbb2e8db7184cd82909de361b52
+CT = e72c9880f79bb8fc113f4fa444b023292313a15462bab1a464148536847290e4fdda7966fe6d5e3b
+
+Count = 36
+Adata = e45da4
+Payload = e558be3fd246170b294d18ffa708842242681890baf8bed9
+CT = 4c5b292ebcd62aad38a028e0cd3510132da390cd0674142fcc4cb33472825363940e2b26424b7802
+
+Count = 37
+Adata = 3b6fc8
+Payload = f8b284c2d851289275973fcd807fac5d8e5e3b6a75ba2ace
+CT = 51b113d3b6c11534647a0fd2ea42386ce195b337c9368038a99dd8dbe89b3ecf663eda1b0f92be7f
+
+Count = 38
+Adata = 043d68
+Payload = 8edf1eb90f0ad33be8a7c6446899e06addc10b3badc4ea25
+CT = 27dc89a8619aee9df94af65b02a4745bb20a8366114840d3dc4894c8fa0a1e1aa760acf9360042f5
+
+Count = 39
+Adata = e89257
+Payload = 8fe9a6bd82462c97f436d382d1ff971c95406b1a6c847d81
+CT = 26ea31acecd61131e5dbe39dbbc2032dfa8be347d008d777cdad1590fd8bf2d7ea919e60d0316566
+
+[Alen = 4]
+
+Key = 45c8afd7373cb0f6b092af3a633d9fd97c4ca378e19d75f9b74d089429726c29
+Nonce = fdb1fa230ae0b172ff98fc7496
+
+Count = 40
+Adata = 270981af
+Payload = 0b92adbb251dc29a67f0bb97f8e7160862b6c4e843d07fd9
+CT = 274e2faea3271ea6fa0494c1951f115b5491a893056c3ee4c76fc350e585277e373e9119bf9595cb
+
+Count = 41
+Adata = 633f3efa
+Payload = 1f88dfd4f5c52c22b1db47f9f4fb6e2f8bcd78d593061369
+CT = 33545dc173fff01e2c2f68af9903697cbdea14aed5ba52540fa7e55dc54e80488a05ee7f1fc96e9d
+
+Count = 42
+Adata = aad86fb5
+Payload = b2b4cb5e90ebf4bd265093b7f5efd4d62dc60e29737aa496
+CT = 9e68494b16d12881bba4bce19817d3851be1625235c6e5ab18151c17d9e3f97244000a3b2d3c2f95
+
+Count = 43
+Adata = ed42941a
+Payload = f312b47d05f8eb5a29943b41347cb1983c75cb7a458a3868
+CT = dfce366883c23766b46014175984b6cb0a52a7010336795562d521c4b5c7a6f2c5ac65f2fd15b066
+
+Count = 44
+Adata = e5b085d8
+Payload = e9fb86938ea7f04cc230296859e7c96fcc352f968c9473e4
+CT = c5270486089d2c705fc4063e341fce3cfa1243edca2832d9e491a31218f688744098851672a09a64
+
+Count = 45
+Adata = 3776f37f
+Payload = 8af6b7540f997954812e38dbd99ccfaedd5c69963c353a4e
+CT = a62a354189a3a5681cda178db464c8fdeb7b05ed7a897b730ece28347d7ebf8291d7eb66b7651b4e
+
+Count = 46
+Adata = 4eb08c9e
+Payload = b90cfd9dd58e320d98510483b1d939bdb5f3b81666ecee59
+CT = 95d07f8853b4ee3105a52bd5dc213eee83d4d46d2050af64cbd25fb40480d15c039878b5d2f25afb
+
+Count = 47
+Adata = c7f93152
+Payload = 02caabc6ed0641681e7148c10cf3159fe35e44013252071e
+CT = 2e1629d36b3c9d5483856797610b12ccd579287a74ee4623fbfd98c8567b78d4b9c3a49a4641908e
+
+Count = 48
+Adata = 57957630
+Payload = 2f29882fdf1418d04f0b9d44272995a56973c4369c687a99
+CT = 03f50a3a592ec4ecd2ffb2124ad192f65f54a84ddad43ba4655c1abcb3ed1a175f12721a407c5d00
+
+Count = 49
+Adata = 19da955d
+Payload = 4e427130be9e94639320529ec135715e65da1117b5ba3c76
+CT = 629ef32538a4485f0ed47dc8accd760d53fd7d6cf3067d4b90621a5e5683df421a0dc52341485d1b
+
+[Alen = 5]
+
+Key = a2e6bf39efd1ceddc92b4333ed92d65efeea6c031ca345adb93a7770a8039bcd
+Nonce = 693cbb46bc8366086ec7cd7776
+
+Count = 50
+Adata = 3ba11282d6
+Payload = d822f84b023f12ea9e3ce16b904278e4aaab5e11c2c23f3f
+CT = 9f91fd2f6472e33b02b1eabb9d6655729d44c44dad6b3883fe0667bcc5806b225224b04ade8b21c1
+
+Count = 51
+Adata = 3f3a4718ea
+Payload = af87b347b59e37a424004a00907dcbcf6a554e6782a9be12
+CT = e834b623d3d3c675b88d41d09d59e6595dbad43bed00b9aea6750fffa5a487540ce65770cd836e99
+
+Count = 52
+Adata = ff79ca8965
+Payload = 82b7cd168b6a82cb2d837f41ceda0c27adc5f5b28030454b
+CT = c504c872ed27731ab10e7491c3fe21b19a2a6feeef9942f7e7cfafe32bd71ea9813607c5df446c9d
+
+Count = 53
+Adata = 0021be18ed
+Payload = 1c1a0f144df76781e7c85ab178ed9b1ce8c6dc3f15c59149
+CT = 5ba90a702bba96507b45516175c9b68adf2946637a6c96f576716fe674c33ad3b9d3e54cc86bfccf
+
+Count = 54
+Adata = 9ae7996547
+Payload = d9bb71ad90152d5c1af358c8501fa89ebd4b17bf4ff43841
+CT = 9e0874c9f658dc8d867e53185d3b85088aa48de3205d3ffdab55dbee34f1bab555bbb196095fb5fd
+
+Count = 55
+Adata = fa292d1958
+Payload = fc7d028a1aa05c74b7ffe333ba6f676913b0f9f1ffa050b8
+CT = bbce07ee7cedada52b72e8e3b74b4aff245f63ad9009570476a4e9e759d5bb79c187a157099e3d12
+
+Count = 56
+Adata = 88800df7b6
+Payload = c9ea772e61742a6706da3ab3e81df14b31506ae58b063ece
+CT = 8e59724a0739dbb69a573163e539dcdd06bff0b9e4af39729f0f3699c9743ad6c9f09dc00ea10487
+
+Count = 57
+Adata = 715041afd4
+Payload = 70d2b8d64121ceccf1961444e8d33b7b7f998aeb58d3d270
+CT = 3761bdb2276c3f1d6d1b1f94e5f716ed487610b7377ad5cc560d78cba6d9f50e9c2677a710f92155
+
+Count = 58
+Adata = 14682301a9
+Payload = 1013946815001a2c08acca4196e0d6668ffbb3883cf111e7
+CT = 57a0910c734debfd9421c1919bc4fbf0b81429d45358165b95ffb6e29172a283d47e4478e2e1f7c4
+
+Count = 59
+Adata = e44c3c21c1
+Payload = f40dc834067bd163e0004d0ec5dd4b96e2a1ea31ea431c98
+CT = b3becd50603620b27c8d46dec8f96600d54e706d85ea1b24ccf233caf0bad9f68f71d78ee58512ec
+
+[Alen = 6]
+
+Key = c5a850167a5bfdf56636ce9e56e2952855504e35cc4f5d24ee5e168853be82d8
+Nonce = c45b165477e8bfa9ca3a1cd3ca
+
+Count = 60
+Adata = 4759557e9bab
+Payload = e758796d7db73bccb1697c42df691ac57974b40ca9186a43
+CT = 93ad58bd5f4f77ac4f92b0ae16c62489e4074c7f152e2ed8a88179e0d32f4928eff13b4ce2873338
+
+Count = 61
+Adata = 2ea07d393a0a
+Payload = ce60ddbe40b70bd55a9147036ad079dec1558ef4c2c625b3
+CT = ba95fc6e624f47b5a46a8befa37f47925c2676877ef06128b7d812c4d69f1f53ee9158382e56625b
+
+Count = 62
+Adata = aa6667faedc1
+Payload = 89eb3056770a6157f06921bc153834447c4b6d862d10d185
+CT = fd1e118655f22d370e92ed50dc970a08e13895f59126951e26fdbed62b228db008a1b14bd7942e12
+
+Count = 63
+Adata = 9e2127d92311
+Payload = 132f3e19e12f462a7463226b716c41a05a59c76f0e1a2f72
+CT = 67da1fc9c3d70a4a8a98ee87b8c37fecc72a3f1cb22c6be9124e1eb78de01b8af83b684baf3e43ad
+
+Count = 64
+Adata = 2f191bc9cff6
+Payload = b8611cbb9a3667b9458ca57eb636eb1dc580e7dbb5701692
+CT = cc943d6bb8ce2bd9bb7769927f99d55158f31fa809465209cb0f79736d1a810d06a776094f9fb67f
+
+Count = 65
+Adata = ad739d5f4736
+Payload = 112f89ccbdadc2433008d3ede2290f9ce81e5c736abf42a8
+CT = 65daa81c9f558e23cef31f012b8631d0756da400d6890633bfba2348f629471c232c9ff7e5f6f85a
+
+Count = 66
+Adata = 01acc909b7d3
+Payload = d47f2ff745de39a9055ad002de6334971fde480bef268b33
+CT = a08a0e27672675c9fba11cee17cc0adb82adb0785310cfa8c0f694d03ffed043787343827ea2603f
+
+Count = 67
+Adata = ce003c836a6f
+Payload = 13be365884b8a91a284ca24f70011e48794b51be275153b9
+CT = 674b1788a640e57ad6b76ea3b9ae2004e438a9cd9b671722279b553998a6fee0a86e177a448573a4
+
+Count = 68
+Adata = 6a759a4efd00
+Payload = d5c87c649579da3f632ba95cb0a07c924095e4bdd4e0376e
+CT = a13d5db4b781965f9dd065b0790f42dedde61cce68d673f54eeb434cca3ea719827417e94d6ed564
+
+Count = 69
+Adata = 02b84a26c773
+Payload = b7bc1580c68fd5d06c1bf75c31dad7a3e26d636d7eee20b9
+CT = c3493450e47799b092e03bb0f875e9ef7f1e9b1ec2d86422a74b5e4e2edb91fbbe722bfaf1500db4
+
+[Alen = 7]
+
+Key = ae8f93c3efe38e2af07e256961dd33028faa0716e5320a7ab319a10d2f4c5548
+Nonce = 6333bde218b784ccd8370492f7
+
+Count = 70
+Adata = 0b1fabdf2a4107
+Payload = bc9ca92a9c9919e39095d3e53fb148694620ae61227e0069
+CT = 45811b0c8f754bf03950e520cd4afc81c2e3eb8a11f4fd386d5a6e4b1fbee15d35939c721004502e
+
+Count = 71
+Adata = 2fc7f5c0ce052f
+Payload = f25a4ca20bbf4969bed6b93c1c77e3d7415f60fe3784216b
+CT = 0b47fe8418531b7a17138ff9ee8c573fc59c2515040edc3a24a68f98716190fb55f743a8bf62a085
+
+Count = 72
+Adata = 8a74412da3034b
+Payload = 3237bf953989d17c65a0fafd2bb1e32c237f98f55389e8f8
+CT = cb2a0db32a65836fcc65cc38d94a57c4a7bcdd1e600315a923afef7b4955d7d1e8f1abef9933bf9f
+
+Count = 73
+Adata = 7139f3c1d6cc36
+Payload = 55d86dc0423cfc2616ef996a3316e776707f8d25c985884a
+CT = acc5dfe651d0ae35bf2aafafc1ed539ef4bcc8cefa0f751b8e824c62632dff5cbc103d3060fbd174
+
+Count = 74
+Adata = af7a380f079aa1
+Payload = ac48398adb10292314973946f261ec39397442ca09b98dd8
+CT = 55558bacc8fc7b30bd520f83009a58d1bdb707213a33708980202d518ca871c9544f4a8c55fd8d20
+
+Count = 75
+Adata = e602abe8f72964
+Payload = 2fb78654e4395df8c37f260d74def234a3a4e3d2b1fe8614
+CT = d6aa3472f7d50feb6aba10c8862546dc2767a63982747b454b33ea6e4344033f74f513d1e41b82ae
+
+Count = 76
+Adata = 82741c5fd6e1df
+Payload = d488bdda400932de56a9f105f0e74ee79c2ed869faaadc31
+CT = 2d950ffc53e560cdff6cc7c0021cfa0f18ed9d82c920216073ccf18c7ea7dce79d0be1204c593234
+
+Count = 77
+Adata = 78f0cc22535402
+Payload = b22aba8d3e9f4b4bf006e26062de15daf94597731a600912
+CT = 4b3708ab2d73195859c3d4a59025a1327d86d29829eaf443b81b8af57b85093778690266e20e2fbb
+
+Count = 78
+Adata = 18e468139dd16f
+Payload = bd864f7b8efd6ed2b068f425482d449bf53a203ea88e1ca1
+CT = 449bfd5d9d113cc119adc2e0bad6f07371f965d59b04e1f09b94a857e7a0423ef6c9cbebde1f9c40
+
+Count = 79
+Adata = a6dab47c0fbfe1
+Payload = 47d9d18b6addc5f88986f0457b666faae59aba4fa3a02abb
+CT = bec463ad793197eb2043c680899ddb426159ffa4902ad7ea64718820065a739fbd3ba560a416895c
+
+[Alen = 8]
+
+Key = 548c2d1eb7d91e003633d4d9ff199e4a8447180edd89ac7867d25a1db288b5ce
+Nonce = 23b205bd6ff8ed0bab0c98999c
+
+Count = 80
+Adata = a6601111cd92c943
+Payload = 49fd5cbe4aff89dc3b8718f9ce545d612cbbebb289ecbf42
+CT = 3cfc6211e359ae322802fc9566f377b0dfe17d1dfe0878ebf2a9047e37cc0be1fab0006af8db8dc4
+
+Count = 81
+Adata = 96f0b7cd7439721d
+Payload = 94a95e945f660d1571b4d7d22709b000b45ff98b2129a4ae
+CT = e1a8603bf6c02afb623133be8fae9ad147056f2456cd6307106a430b04938e97f2e4cda81108ad3e
+
+Count = 82
+Adata = 2ee135dc2ddd9501
+Payload = aeed3aea01755c912213c8c276a2b75dad24f888a611efa3
+CT = dbec0445a8d37b7f31962caede059d8c5e7e6e27d1f5280ab2ab219c6c4952d52505cd9f904b0e04
+
+Count = 83
+Adata = 10c361934fd6ff77
+Payload = be1fcebea4c22a1d71e08047b028d7f4ccab0a6b8085d344
+CT = cb1ef0110d640df36265642b188ffd253ff19cc4f76114edfc1f7b2fe314faea28ab0dae349feb9c
+
+Count = 84
+Adata = 3f6c8a69917f7776
+Payload = 87680ac26fe1511e0f1f745aa4c2a5b9f6c0117dcf08feaa
+CT = f269346dc64776f01c9a90360c658f68059a87d2b8ec390308e529d64e786a29661cccddc0366f3b
+
+Count = 85
+Adata = 0f7a1426ff3b5ee1
+Payload = 9e004b072a27b085e59ca201c157c7d3c906a2c3b455c56e
+CT = eb0175a88381976bf619466d69f0ed023a5c346cc3b102c797c6510b85dfd097f3eac276aff00ba2
+
+Count = 86
+Adata = faa5bed84dcf168e
+Payload = a1bf47b15cd66e43daff420edf014a14b11994b97ada4030
+CT = d4be791ef57049adc97aa66277a660c5424302160d3e87998e522b6f13f99ecb553b6de845940907
+
+Count = 87
+Adata = 2851dae3cb3fcb1c
+Payload = 2d15734871adc63ff32d7002ab40c4a235a4d5fad223953f
+CT = 58144de7d80be1d1e0a8946e03e7ee73c6fe4355a5c752967a9ca39566189ee96c86462bfea78af5
+
+Count = 88
+Adata = 35a29c1bcbe2182f
+Payload = 5a84c4fdd47510fb7aebc0f79d7b625ccd0a96575740b8e6
+CT = 2f85fa527dd33715696e249b35dc488d3e5000f820a47f4fa613b5fbbe73a2df6c630a00ff4b1b92
+
+Count = 89
+Adata = 45820ae66c3e8e77
+Payload = 2052a94e1392dc1db0e89be19ea8f7379ee4cb607a914c89
+CT = 555397e1ba34fbf3a36d7f8d360fdde66dbe5dcf0d758b20d19feb067e9f6225376da21b4899d296
+
+[Alen = 9]
+
+Key = aab793e377a12484dbdd74c9b3a85c74c286e1cc498663fbd7c718b5633bb91a
+Nonce = 10022cddb323e88b3c08f95a0f
+
+Count = 90
+Adata = 82b8c736037ce2f2e8
+Payload = 7c0889854658d3408c5d8043aad2f4ae4a89449a36f8a3b8
+CT = 1044250f58857c69f72b5d3454d43949e5c02b3822970b280de1a3f7fc5d06cc30f06075f5504ed7
+
+Count = 91
+Adata = 8f2777ec4930f7e349
+Payload = bd845561f099500a6ff3fd09964dc3820f7ab48ba4ed04d5
+CT = d1c8f9ebee44ff231485207e684b0e65a033db29b082ac45835840df6fa96f5c972ac09d94148cbc
+
+Count = 92
+Adata = 5cab3b846870709569
+Payload = a6e09404fe60badfc63dc228057485e6f563ba82acdabd7c
+CT = caac388ee0bd15f6bd4b1f5ffb7248015a2ad520b8b515ec2f83ef84b299cfdb61d2b5039d536c3f
+
+Count = 93
+Adata = 0938f2e2ebb64f8af8
+Payload = 33404d7e0e620c1030b91020e33619c5f53d8b210fa86489
+CT = 5f0ce1f410bfa3394bcfcd571d30d4225a74e4831bc7cc19db04e655cbe22b9ea508d2a03757b97c
+
+Count = 94
+Adata = 82f78ca0e0da2b2d3a
+Payload = 617868ae91f705c6b583b5fd7e1e4086a1bb9f087a50bf50
+CT = 0d34c4248f2aaaefcef5688a80188d610ef2f0aa6e3f17c04bd88dc6985f819004c2b634c5303ed8
+
+Count = 95
+Adata = 401191aa3fd34abe87
+Payload = 949cdd7c2973d7519e7bca98b2c5947e6d8e91c90e632319
+CT = f8d071f637ae7878e50d17ef4cc35999c2c7fe6b1a0c8b894ff3572e4ebf78473760d8cb4b0366b4
+
+Count = 96
+Adata = 4df4377596d8987671
+Payload = f6720a0bd8705c70e0f923338965e810b3ea939bad652327
+CT = 9a3ea681c6adf3599b8ffe44776325f71ca3fc39b90a8bb7de95ec3eee17753e60fb3c0661bdd098
+
+Count = 97
+Adata = 6593194b9970545c5a
+Payload = de9b0556661e726f3e6e34515ff7196420fe61b4f38419f2
+CT = b2d7a9dc78c3dd464518e926a1f1d4838fb70e16e7ebb162b8590ff04f967e51fbd1be84f01b4dcb
+
+Count = 98
+Adata = ab2d432058b540ac72
+Payload = 6cad7f3b9f196839bbc5a7f755c09aa8e17c83d9cb8b3954
+CT = 00e1d3b181c4c710c0b37a80abc6574f4e35ec7bdfe491c471d67b75b2da855a12ffb24ddd64a048
+
+Count = 99
+Adata = 5dc631eeeacb5a0b0b
+Payload = 70a55aec1144357377612fd0bbc2c817f33465a656219957
+CT = 1ce9f6660f999a5a0c17f2a745c405f05c7d0a04424e31c71fc798dd16c1fadef607a9297cbfbfef
+
+[Alen = 10]
+
+Key = 06ac39896073a44283611a66ccab067e2dd2faa8da82ff9a45bb29e54d2e6e77
+Nonce = 6c7942c9819cf69b817bfcdb0a
+
+Count = 100
+Adata = 215e2a6c24325340fdec
+Payload = 3216dce3b8b1ce0e79e40fffcac728ab191aaaf319d971d3
+CT = c5b3b50ed8a7b7b96b02ba9464b6a2ff80e90548605699a63d70e6dffb31a376a1eb7f94526dca48
+
+Count = 101
+Adata = e0a29a2c7840cf9b41de
+Payload = 7e5e5710a693ebfa36335cf7965574740880acdddd13fb1a
+CT = 89fb3efdc685924d24d5e99c3824fe2091730366a49c136fcbf516608fe20e06bbff931e84683545
+
+Count = 102
+Adata = b8026fbada6339d84802
+Payload = 08c342a50aa23362622934dfab55d9b22c22c249ad08138c
+CT = ff662b486ab44ad570cf81b4052453e6b5d16df2d487fbf9d70eb14f3fa0229906b9e0360be3d3f9
+
+Count = 103
+Adata = 65f4b3a00c1c1ef39445
+Payload = e085aba85882c75d5e41559167731496cf17d3907894352a
+CT = 1720c2453894beea4ca7e0fac9029ec256e47c2b011bdd5f4184771199a427861bf17cd8401e794e
+
+Count = 104
+Adata = 96118dbfe53434d8aed8
+Payload = 710f890be2b8da77c1eff429ede9cc931d50f059748cbcb6
+CT = 86aae0e682aea3c0d3094142439846c784a35fe20d0354c34e20b2db52fde68f88bfb886fdcb2c47
+
+Count = 105
+Adata = cdf4b485d2e04709cf8f
+Payload = cda96efee4e188ab3048bc1904ac2c36ab018f2ab7602682
+CT = 3a0c071384f7f11c22ae0972aadda66232f22091ceefcef782ee3df38ddea8e269eb47e39900345e
+
+Count = 106
+Adata = 50e57e57cf8e49e3a4e6
+Payload = 3dc596d52e520779a50bcba3049388b340dbf6d0f2eb94cf
+CT = ca60ff384e447eceb7ed7ec8aae202e7d928596b8b647cba44aaac4ed86f687cfc031f22827725f1
+
+Count = 107
+Adata = 48c670f11ff7f74e7003
+Payload = a33105c0dccf8e3b687212a870af9f710462756705fe09b3
+CT = 54946c2dbcd9f78c7a94a7c3dede15259d91dadc7c71e1c6d75255006ac037d6a4d048f1fc338012
+
+Count = 108
+Adata = 465e3be6113a2fb2ee20
+Payload = 573ac2436158eb7dd9be981e3cfbe75d3a188ea9cf2b1ee2
+CT = a09fabae014e92cacb582d75928a6d09a3eb2112b6a4f6976c1da33a80bc8157cece1acf9400b2bb
+
+Count = 109
+Adata = ee4e10574faeae85e9b6
+Payload = ca35bdb54e73eac5a5200a296b3aba5f37c87349746102d4
+CT = 3d90d4582e659372b7c6bf42c54b300bae3bdcf20deeeaa165c1cb98da4a1a920ca1ed9a7b6ec514
+
+[Alen = 11]
+
+Key = 50412c6444bcf9829506ab019e98234af1541061557412740bc120b456052763
+Nonce = 85684f94c3702c5d870310166d
+
+Count = 110
+Adata = f706a3e09df95d3e21d2e0
+Payload = 6cdbd63f6d591f59776f828533b28e2453a214d1d0dd8a39
+CT = 8c8b4ae854a5d5c265b25e3b54bded9444cc454b3e0e6a24d6c05eaf406a5ebd578e19edd5227380
+
+Count = 111
+Adata = e46b25b9a41a858e87900a
+Payload = 100132c315bfc9c4fb93023f5d3500d7208a68acb4d2c630
+CT = f051ae142c43035fe94ede813a3a636737e439365a01262d5088446e42591c0ede68e82334d97cfa
+
+Count = 112
+Adata = 28d34b29afe6586fd9bf0e
+Payload = d5460c1db0d24dedc63c4c78ce6d1f0b2d46f3b01934525c
+CT = 351690ca892e8776d4e190c6a9627cbb3a28a22af7e7b2413eaaef2823f5ac3f313f560bd774d10e
+
+Count = 113
+Adata = 2852d4fd68a3e9e47d44a7
+Payload = d2d73b62e3b1c9ab75f3544ff8616741e0adbae84b8cf9d0
+CT = 3287a7b5da4d0330672e88f19f6e04f1f7c3eb72a55f19cd62d30d99bb7dadec34e2891c156a1f5d
+
+Count = 114
+Adata = ec1c17b2ab13d7c8ac874f
+Payload = 74796d78d6ad03634ed80800af530212baa7e5093651cedf
+CT = 9429f1afef51c9f85c05d4bec85c61a2adc9b493d8822ec241c9a05ebf9ed27792bbced83b5dc582
+
+Count = 115
+Adata = 4f1ab5ddb1c199e9a5daab
+Payload = fb432488b5d08d576a90f085181ad883407a6ce9ea29950a
+CT = 1b13b85f8c2c47cc784d2c3b7f15bb3357143d7304fa75171ffc24020e86b1314724104e6b57b3ce
+
+Count = 116
+Adata = 864e0e728aea856fae6c6d
+Payload = 2b82d96ed1778412378abe4e09c633acf3359b9709ae3dcb
+CT = cbd245b9e88b4e89255762f06ec9501ce45bca0de77dddd6539bbb0af8ecf77b4508533247b3501a
+
+Count = 117
+Adata = 21ee21a5ed0d75d0380a28
+Payload = 85143071241bb65261fe7afcc102416e59b9e46ee0c90073
+CT = 6544aca61de77cc97323a642a60d22de4ed7b5f40e1ae06ef8981ec6ce7c4687b178f2103fa8c8be
+
+Count = 118
+Adata = 2b63f7b676f13f45d103dd
+Payload = 185577b48237acbdaa3590b8057fe374f875ce829b62c98f
+CT = f805eb63bbcb6626b8e84c06627080c4ef1b9f1875b1299265d9d899c6b71c0ab3049ea1dbfaf6a9
+
+Count = 119
+Adata = a33e86d813c2c4ff3bab20
+Payload = f051beb936e60fd4f3bca31964f1ad3e6fa16dd27b65a6db
+CT = 1001226e0f1ac54fe1617fa703fece8e78cf3c4895b646c6b246474c4e79822f5fd55f2fb0067a40
+
+[Alen = 12]
+
+Key = 8a56588fe5e125237b6cdc30f940b8d88b2863ec501a0cb00b1abade1b5ce0ed
+Nonce = d80210b9f9776ea36dc0e0a787
+
+Count = 120
+Adata = e4296d1c8cf4ffc4b2635135
+Payload = c825952293e434ea866db558aaf486ef09a92bf366988f71
+CT = b8b3b15fdf6a4a0b5abc313afc769e4e8413bd887552583ede3ed995d1b70561c8e28a7b1a7e3dc8
+
+Count = 121
+Adata = d18bfcc1584eeb8695388ebe
+Payload = a1e0248355bfd1d881fb1a4798cda2f6f6ad513c69c5f9b4
+CT = d17600fe1931af395d2a9e25ce4fba577b17c7477a0f2efb561575f6743c5759494be59afa0c3e11
+
+Count = 122
+Adata = 14682301a99bf680805d1ffe
+Payload = ded135fcbf62219bfba2cba40c2d2cbe4815ddaac1342231
+CT = ae471181f3ec5f7a27734fc65aaf341fc5af4bd1d2fef57e34f689367228cbaf3cd76fb407109cf6
+
+Count = 123
+Adata = 8853aa2dfea9c4d370678bb6
+Payload = 12d3900c6c01968b8344762e0e883e5e219f42b052dc6215
+CT = 6245b471208fe86a5f95f24c580a26ffac25d4cb4116b55a2cacb7fc3856abcf759feb8dc0998ab1
+
+Count = 124
+Adata = c5d3b9c593c3185fe4b6d1bc
+Payload = 8c3c1193fe1a1ebad7e01a1eed1a32c08a0091b1c948e184
+CT = fcaa35eeb294605b0b319e7cbb982a6107ba07cada8236cb42a740cd3262424a2c3d77849ead6149
+
+Count = 125
+Adata = dfb9e8149b51f89b1ec00a8e
+Payload = 8219618b7728ac89237705ecf84012cc7c80293c4cf171d8
+CT = f28f45f63ba6d268ffa6818eaec20a6df13abf475f3ba69747d4dbe0f9415d40843070e1e93059eb
+
+Count = 126
+Adata = 08a4590d262e4dbcb7e23ffc
+Payload = b344b7dc239617fa51b9ea10a349e940c3163779f5284c9c
+CT = c3d293a16f18691b8d686e72f5cbf1e14eaca102e6e29bd31215b3dccba4ca5de64be7fab8a7a22c
+
+Count = 127
+Adata = 74aab7b5b96238710637c6e5
+Payload = 740d4b25ca7221d0826057701a6bfd66c50a82f010a57be8
+CT = 049b6f5886fc5f315eb1d3124ce9e5c748b0148b036faca734e09945ee44c95c7923d8b9249ade7b
+
+Count = 128
+Adata = 420aac47a3f212fffca40549
+Payload = 5d9000489186abdf4f0a2794f0222fcaa156fe6309c10f79
+CT = 2d062435dd08d53e93dba3f6a6a0376b2cec68181a0bd8360a568dd779526a0058d522af1dafde30
+
+Count = 129
+Adata = 6e80dd7f1badf3a1c9ab25c7
+Payload = ac2c44263363810bec3a309aa618b303e05099dfdbeb5c16
+CT = dcba605b7fedffea30ebb4f8f09aaba26dea0fa4c8218b59279442c88d612ed1a39ae0005f88155d
+
+[Alen = 13]
+
+Key = a4cc7e1c90f8684e6a5f95e6898ab4e3c194cb46e196d8228062b9f3fa744930
+Nonce = cdc2712e51c7f333d6bad78eee
+
+Count = 130
+Adata = 569c56b27268d3db54e728aac0
+Payload = 10d4cff95ef490923c9e0906880729d4d05412e7675cce76
+CT = be3ce3e9dc72499839a98ae52abb17415e8547687e8a3c7b8aaaac20d4c9276f2851cbba2b04d185
+
+Count = 131
+Adata = d75635b6450e43285fba966835
+Payload = c9db03e2efbab713b0b640421018d3971ffe2abd70fe8fa1
+CT = 67332ff26d3c6e19b581c3a1b2a4ed02912f7f3269287dacc121ff83891335dd1214ea6fc25f6a68
+
+Count = 132
+Adata = 70750acea6a05f8b7b425d262b
+Payload = add631ce5846ce71434aad4998f8e429aed430e7d38bdbb2
+CT = 033e1ddedac0177b467d2eaa3a44dabc20056568ca5d29bf549e71ec517cd65150f42b3cb53f936e
+
+Count = 133
+Adata = 2a567c7ec7edaa5a438ae3bb35
+Payload = a514d170422feb1d87bb7725a9e77cc6fc8afb45c2af6d90
+CT = 0bfcfd60c0a93217828cf4c60b5b4253725baecadb799f9d0e432ec394ddbb65205dc40a5a8e90a4
+
+Count = 134
+Adata = 0f8795385b805246a0a2573afc
+Payload = 79d8841ab83279724ce35e1a8abd4e158168dcf388ab4c3d
+CT = d730a80a3ab4a07849d4ddf9280170800fb9897c917dbe30926b0d977107a3918717f79b63f36b0a
+
+Count = 135
+Adata = 111d224c102b136159fbeb44a7
+Payload = 2edd498e54b23aab6f4fd7b3f22c4c787e3a4f1fb06c9ec7
+CT = 8035659ed634e3a16a785450509072edf0eb1a90a9ba6ccac2cd61599bb93db3dd3dabc12aa90932
+
+Count = 136
+Adata = df0821c9ea6ab329c626d11b4b
+Payload = 6e3e25db29da2c787bb37755ee770e2402fb8208da23389d
+CT = c0d609cbab5cf5727e84f4b64ccb30b18c2ad787c3f5ca90bd027ecd00cc6dc5ffd5d746d92281e9
+
+Count = 137
+Adata = aacaf4839c35338d6e2b47ac45
+Payload = d4ed4584678e982ace8664e77d0e55be356be558cead3755
+CT = 7a056994e5084120cbb1e704dfb26b2bbbbab0d7d77bc5583c01354a450eda2588be7578530e38c0
+
+Count = 138
+Adata = dc6eed3f8bd1b5563c1eeb9afa
+Payload = 4ebf00eadaf70711f630f5badf0214d8518a200afb0e5765
+CT = e0572cfa5871de1bf30776597dbe2a4ddf5b7585e2d8a5688d7a1d546e25ba026cd46556eb2c4b7e
+
+Count = 139
+Adata = fbfe7e910f242a78dd6e69a2ec
+Payload = 2729636112f2abe2c76ea5e52a3f80b0f882f0f3b6f7c806
+CT = 89c14f71907472e8c25926068883be257653a57caf213a0b0e951aee790239e7067ef37f497b4bf4
+
+[Alen = 14]
+
+Key = 347e12eec56e95aafcc7d25bf10fc756b4e42bc2e43da7f97df24331f27f1f5c
+Nonce = b8d517b033754058128d13d11a
+
+Count = 140
+Adata = 511c6924fa96db716f6b053b7a48
+Payload = ca88dddfc876a12f45f19562bc9ca250f43267ab251a7f34
+CT = eeedcfa8f5b5b48c1d7e277526eecb7294213b9f5785167ae949b93003dfe63c95c1d49edfb4de3f
+
+Count = 141
+Adata = 10c26d5939618189a9503623f55f
+Payload = de0c0d17c3950e7f8985b56d60623cbd010cd765da4df5ab
+CT = fa691f60fe561bdcd10a077afa10559f611f8b51a8d29ce585c32a90d77fed97eb0ac164ed616e1c
+
+Count = 142
+Adata = bc09c59d20e55a9e184d70af2c7c
+Payload = 2f35102d78a32fcde1cfb563ea8d310ecb83c146ab8de362
+CT = 0b50025a45603a6eb940077470ff582cab909d72d9128a2c180fdf5f63045f326057cf74fd4cee6b
+
+Count = 143
+Adata = b75887f13d6e8c4b35b27b965693
+Payload = a3fcce3420effdd6edb37271735a0d30c10c65233aee173f
+CT = 8799dc431d2ce875b53cc066e9286412a11f391748717e7134959a180fc2cf2ba99af21cc1bc8e5c
+
+Count = 144
+Adata = 603401a9b8ecde4d5c86b6107363
+Payload = 4ac918727e41b8c536484e3781c403e260c278712853508d
+CT = 6eac0a054382ad666ec7fc201bb66ac000d124455acc39c32ca2e5195dbd44f0a119538c95788510
+
+Count = 145
+Adata = 7206b06f306124ca3a302e84c5a6
+Payload = 97d770cbb2c42a552e450cc4e35e5668b2ff89cec735cc91
+CT = b3b262bc8f073ff676cabed3792c3f4ad2ecd5fab5aaa5df74a4e1198878a76291594b9826d4b563
+
+Count = 146
+Adata = b15efed90a5d1d62f545ac22af6e
+Payload = 86bb2ae50e36c72936240a74502172625cbca210cf285077
+CT = a2de389233f5d28a6eabb863ca531b403caffe24bdb73939ff5f993dcfbd048274da7439c0f9ef5a
+
+Count = 147
+Adata = c9eb714ed9858a8dc11a26ee3f00
+Payload = 0dc79993047fd6e7260aac4d847fdb4d16483f28b13b5f17
+CT = 29a28be439bcc3447e851e5a1e0db26f765b631cc3a436590e87710559a375ece6ef2953b6aa2542
+
+Count = 148
+Adata = 07ca22271e95cb48a872046822b7
+Payload = f950e96d65a55efb3be3a55daffb421afad1d5625e3440a1
+CT = dd35fb1a58664b58636c174a35892b389ac289562cab29ef998035c81716e2d1ed4b4d56ff18af5d
+
+Count = 149
+Adata = b65f6773516124317cfb4b1fcdf5
+Payload = e160e28e601a49d16db18f25410756b330b036c42e615fd6
+CT = c505f0f95dd95c72353e3d32db753f9150a36af05cfe36981ae73a9b6896d8fc1b8c0d772d632983
+
+[Alen = 15]
+
+Key = 520902aa27c16dee112812b2e685aa203aeb8b8633bd1bfc99728a482d96c1fe
+Nonce = ddf50502f414c1bf24888f1328
+
+Count = 150
+Adata = 22b4f8f1aac02a9b2ef785d0ff6f93
+Payload = 533fee7d2c7740db55770e48cb1b541d990ea3f8f08ed1a6
+CT = fc867b319e0e4ab45ec518a1b5dcec4f29982173f3abfd4d8a8f8d14d2bdac84c3737cfbd75b7c0b
+
+Count = 151
+Adata = d0a43de391d492746ecf322acd6e5b
+Payload = cced20b59a6b2c3c45ea6c87802440c9c47b1015e83d86c3
+CT = 6354b5f9281226534e587a6efee3f89b74ed929eeb18aa28fce59f5e6e3cee284b4cc747ff5ee13f
+
+Count = 152
+Adata = 3a789c06f87f05933c34a1cf9834a8
+Payload = 90939a4530181ad6900664f66bfc2ce0289432a0afe9babe
+CT = 3f2a0f09826110b99bb4721f153b94b29802b02baccc9655ddaef56d8255125f7c316c6c59ce779f
+
+Count = 153
+Adata = 785260973f112c56d9f891160c4c11
+Payload = 86cd926b9565b76a88fde73c31e9ac908ffd1e6ca30b59ce
+CT = 29740727271cbd05834ff1d54f2e14c23f6b9ce7a02e752555810cbcdf48f05d0a7808673c82d08d
+
+Count = 154
+Adata = bf6a144591c0ea7b10274fbd3345a1
+Payload = 6ecd1c1acc6290672f9cf639ed0cebcb21ed0c56f35a5ce3
+CT = c17489567e1b9a08242ee0d093cb5399917b8eddf07f700849e41e5d34a698ae1d96f16bc68da944
+
+Count = 155
+Adata = 7d9488b500d89a27f367f34a448a87
+Payload = b01e3f4fb5ee7501e8c2f4ccefb542ae20d7fd61a2c41c8b
+CT = 1fa7aa0307977f6ee370e2259172fafc90417feaa1e130601bc54e546d1a6fcf6187169feb1ea533
+
+Count = 156
+Adata = 060fc718e994edc7bac9962ca7f28d
+Payload = 22ab6a0daf953165dda864cceeeb782e275c0b072aedd284
+CT = 8d12ff411dec3b0ad61a7225902cc07c97ca898c29c8fe6ff2eb6c0ab42acf42985c721bfd576e71
+
+Count = 157
+Adata = cb6f96dd06015967279ade310a7401
+Payload = f96ed20b23c784015ff58f5f040798ca75e3b98045deca8e
+CT = 56d7474791be8e6e544799b67ac02098c5753b0b46fbe665ac502b8e65cc1329b6895afdd354f5db
+
+Count = 158
+Adata = 9aa6d501455019b4ef4c7fb789d22f
+Payload = 648a84813ca97aef4ab7e143ee29acb946388660f18eb671
+CT = cb3311cd8ed070804105f7aa90ee14ebf6ae04ebf2ab9a9a87e5f8a8148f21adf721477c36bd99ca
+
+Count = 159
+Adata = ebd1d12bbd14176a0d4080aa1edb89
+Payload = 32d71e59634126ac6c6156a80a0dfa0175b29e9f40a31696
+CT = 9d6e8b15d1382cc367d3404174ca4253c5241c1443863a7dda9ea0427522dbeaa509a11755434760
+
+[Alen = 16]
+
+Key = 57da1c2704219ed59abfdf04743a9a93c87a63d471818de0f1564b2db6421562
+Nonce = 4b60a47b7e90f622fa0bf803e1
+
+Count = 160
+Adata = 0ae8c012ff39753510df3ee80707e4e2
+Payload = ddc3c1aa73fb6de92bb4db138e26f3c2e0543ab4f5924871
+CT = daa8256d4753fdf9cfef876295badaba89b45cc497f54d220ec2c6fb687753bca4580adc6aa2f296
+
+Count = 161
+Adata = d5b22e7697ba70e00c7ef32709563f01
+Payload = 34270576724083e9989764d08a0d5c1b4738f34927a1e436
+CT = 334ce1b146e813f97ccc38a1919175632ed8953945c6e1658f30b9c8e380c98bb939a4e8a85af758
+
+Count = 162
+Adata = 6b4edef415763aabcef01863e8197aec
+Payload = 904fe88e7a8e76447a64b488ef84184d0f1ab1b67f0c5a7d
+CT = 97240c494e26e6549e3fe8f9f418313566fad7c61d6b5f2e53e80d8ccc687fd303f4cdef44b6e8b9
+
+Count = 163
+Adata = 4c099809061024c010a77e9621fc2bcf
+Payload = 51fe7bac8f3255f17f64fb9322210fb7d8da8e762498b233
+CT = 56959f6bbb9ac5e19b3fa7e239bd26cfb13ae80646ffb7600c635dac5b70338dac3f33ce16a99145
+
+Count = 164
+Adata = 9d329439588164d5a96675a85c07a039
+Payload = eab6dbc13bb92df36b1882df2b8f34c3cefa41f95717fbd7
+CT = eddd3f060f11bde38f43deae30131dbba71a27893570fe84f996e8163affb1494bb3c12eeadf16b6
+
+Count = 165
+Adata = b768fc3daf29ff9e8bd575072d986e99
+Payload = c44c9c287d3eac7c30570d9c4adf2e4857c598f7c54cd126
+CT = c32778ef49963c6cd40c51ed514307303e25fe87a72bd47598b4206a9622d5631751a497dfb1f662
+
+Count = 166
+Adata = 3efc7cc2d16bf82d2bcfbc559a09b2c9
+Payload = c11b9c9d7607f387359c0038d3e8ec4d527562ce63c3384c
+CT = c670785a42af6397d1c75c49c874c5353b9504be01a43d1f7dd300167d267ad700dea37fb475ecdd
+
+Count = 167
+Adata = 0ff89eff92a530b66684cd75a39481e7
+Payload = cc17904b166f28df82f57889f391159a4a308e752d714ee5
+CT = cb7c748c22c7b8cf66ae24f8e80d3ce223d0e8054f164bb6303e9c9bd0d8e4aac42894ca03d6ab06
+
+Count = 168
+Adata = fbd11bc75759f0461e796f6917aeb42b
+Payload = 6f97e595ea2f40612ea84a2097b974d235055fe1dae59403
+CT = 68fc0152de87d071caf316518c255daa5ce53991b88291500953f46e0e9cf1369e9eb018a4df3c09
+
+Count = 169
+Adata = b79940952f42537484aa2907c72dffa9
+Payload = a48cbf933b88c0ec5ddcdd8fcad186391c2cbef308607de5
+CT = a3e75b540f2050fcb98781fed14daf4175ccd8836a0778b68a1702dfa0cd9c290c5ff9c35cc83705
+
+[Alen = 17]
+
+Key = 9267ebc99ccf648b146cba3c251187e24a9947d806ceb0ced6894211641a1e0d
+Nonce = 9b7298950280e8762ecdc9bbe4
+
+Count = 170
+Adata = 5824689453bc406bf891b85e4576e38fe8
+Payload = 967daf12f16f166b7b5038f83a1cf0b980f5abf4c7746f2a
+CT = 7cfe2a7a54306eb8d8a63d3d1ae86794f9a2c22198b2cb4f10ca926f1a430c08c12e23db3d913e93
+
+Count = 171
+Adata = cd15973753b94b77bb4b778de8b3b0cabb
+Payload = c4a756f6024a9dceabf6e264fffff9c719217fb418141ac5
+CT = 2e24d39ea715e51d0800e7a1df0b6eea6076166147d2bea05d5b674fd15410cc235dba6d8c8d82a8
+
+Count = 172
+Adata = ed8540f7ce451c522c1ff5d2d1030d7b3f
+Payload = e0d5de7d1eace211c0e70859ff315ff485d1200c6dd13f93
+CT = 0a565b15bbf39ac263110d9cdfc5c8d9fc8649d932179bf688750b5f36c86e7eda9015e960a7471a
+
+Count = 173
+Adata = cbbecf92551a15f5cf00a5be4a50b0eb17
+Payload = 05a4a4ba28fe8876f9bcfa5ec60651fd3fd4732f22049bd5
+CT = ef2721d28da1f0a55a4aff9be6f2c6d046831afa7dc23fb0d5fa842209dbbc04c87965f78500fec1
+
+Count = 174
+Adata = 873ba7f8b71517ec50297b21cf94cdb7a5
+Payload = 9cdebaeee8690b68751070691f49593668a6de12d3a948b3
+CT = 765d3f864d3673bbd6e675ac3fbdce1b11f1b7c78c6fecd67d147edbe114bfdb3f3b9b37d5719ef5
+
+Count = 175
+Adata = ac087420feb1e1e8c2546c2a8b8a5af0d0
+Payload = 5672e61cf664d73918dc1ca84df1fce82db0e305a61d57b9
+CT = bcf16374533bafeabb2a196d6d056bc554e78ad0f9dbf3dc57b4c2bbc377937d15b3b89543e29d0e
+
+Count = 176
+Adata = a12c690568114fd7a677f49d74e84fc1a6
+Payload = 0f5452e6b51540cf219998590995cd7f8785fa40b4f217fc
+CT = e5d7d78e104a381c826f9d9c29615a52fed29395eb34b3992e6ca774074b47b59adabeaf8835582d
+
+Count = 177
+Adata = 7a78ddfe5afb2dc90ee4a600c2fc014b0f
+Payload = 9ad338cbfd1b52e6ae4178f05e00062274f8b0b25eae72f7
+CT = 7050bda358442a350db77d357ef4910f0dafd9670168d692bd320f48a7221537e3cbed5ac4154a56
+
+Count = 178
+Adata = 6053e466ed1f647a3cd88c4d2052ec00cb
+Payload = d17b8d556e83190c84d4a812957c64ffa7f336298f4e2c72
+CT = 3bf8083dcbdc61df2722add7b588f3d2dea45ffcd088881740574e201f9a26932a87c8d822505814
+
+Count = 179
+Adata = f7673e3beb526834d6507058fe62e34987
+Payload = 2eaef86b0f602364f86510eabc58bc9ad1e6f0a6f6df0b83
+CT = c42d7d03aa3f5bb75b93152f9cac2bb7a8b19973a919afe6837dfa3fdef2f012b6609de2ac5dd9d6
+
+[Alen = 18]
+
+Key = 7a855e1690ee638de01db43b37401dcd569c1ae03dc73dd0a917d0cadb5abc29
+Nonce = 8f160a873a1166c8b32bccbba7
+
+Count = 180
+Adata = 72674aca7eba2fc0eeafbd143c2c4d8aa6c8
+Payload = 33ae68ebb8010c6b3da6b9cb29fe9f8bd09b59ec39f4ce4b
+CT = b22afdf4f12c43ec23e01ac1215a3f5286059211207e957057e9a9203da74387a9468f8af5e27547
+
+Count = 181
+Adata = f7da3f100b80e2ade812f1700aab6b72f746
+Payload = dbb29817b86cb80e0d008742cedfbf52b236f15ee8cad50e
+CT = 5a360d08f141f78913462448c67b1f8be4a83aa3f1408e35a3985f12a49eac424a35c94645917e91
+
+Count = 182
+Adata = 4b05eaadf98505d0806c233b2cdcaf4254e8
+Payload = 145aa8cfd544a2f46bae1aa83cbdb3d21c3d1350078a3af4
+CT = 95de3dd09c69ed7375e8b9a23419130b4aa3d8ad1e0061cf4ab089a8724b87a1167180963d44ec65
+
+Count = 183
+Adata = 05a3aaa08b9a6aaeb84704431425d0e45a14
+Payload = 6b32e8906dc89194a69410b79cd041b62eb01afb28a3e10a
+CT = eab67d8f24e5de13b8d2b3bd9474e16f782ed1063129ba310a7d1520141892e140448292185c41c7
+
+Count = 184
+Adata = 74db01edc26a2d2044cb8eaad8b907b78863
+Payload = 545ed03588fd85a8bbfeee66d2082ae6f8e2f3c9dbd8725f
+CT = d5da452ac1d0ca2fa5b84d6cdaac8a3fae7c3834c252296472d3eee219d94bd788f62df4add5ec40
+
+Count = 185
+Adata = 5f2c6ddf5a2403e04dac8b2813c060b67e76
+Payload = 66dd5fd8611c551973a3d0c078ec2b4d39ad163d9168de3c
+CT = e759cac728311a9e6de573ca70488b946f33ddc088e28507c600496f4f8b1b7da118ee36d8cd57f8
+
+Count = 186
+Adata = a650a2a5e3c6f7c95614570aaefd0cdd9a42
+Payload = 6f364b3f778376cbf3f4b0b0c5350a8fa278f9d8c25faad6
+CT = eeb2de203eae394cedb213bacd91aa56f4e63225dbd5f1ed4710004d06ce7a7efbd19da4e3ce3cf7
+
+Count = 187
+Adata = 477c2484cf5c56b813313927be8387b1024f
+Payload = 3de4798d8ad84c460b92abc10b7f5e7c9fae46a1dd353687
+CT = bc60ec92c3f503c115d408cb03dbfea5c9308d5cc4bf6dbc304099641c4ec3dc2c54fdf4f48dbef2
+
+Count = 188
+Adata = 564e1df74aa2d7ee33b66cfeda810774e16c
+Payload = 7769b45fea11f530fb9a67f1b5b1964a34cfa32bbb03f4b1
+CT = f6ed2140a33cbab7e5dcc4fbbd153693625168d6a289af8a905c1b05e8945685f8688faea777eb43
+
+Count = 189
+Adata = d5e66502529b0045883d935e05acd242baa8
+Payload = 0c0a502b42f81b51806c7080a8155280f493f2922cdc7df8
+CT = 8d8ec5340bd554d69e2ad38aa0b1f259a20d396f355626c3ea5a3b6a8bafde4006b993cfb3b13557
+
+[Alen = 19]
+
+Key = 0ebdc6ddb4c502725dd6ee8da95d56a0d1044b4694d6ba8475a4434f23a8474f
+Nonce = fb717a8c82114477253acc14f6
+
+Count = 190
+Adata = 41e9d65632f74f449a6842d5e6c4a86ef83791
+Payload = c7360282c85484a5a33ab1c68dd70873ab4e74ffd4a62cd5
+CT = 2e961b3a2fa1609a4e6fd04bff6ac5e306ae2638706f997b42be2e2ba05c54b619850db5c9d684fe
+
+Count = 191
+Adata = 555304659bde926cb2553b8a4605251fcddd92
+Payload = 1332314d1cf783b9f64e0fa2d42d43d225da9fd5165b5f0a
+CT = fa9228f5fb0267861b1b6e2fa6908e42883acd12b292eaa4bbdee2605bc69601b1e83d1e7a0b400d
+
+Count = 192
+Adata = 69ea953dbb910ec589372d797c7379d3f3b9e9
+Payload = f264da8606ea429e0e25da3f2efafe28beaff05b42097369
+CT = 1bc4c33ee11fa6a1e370bbb25c4733b8134fa29ce6c0c6c7304611baf530932da7954f714514d228
+
+Count = 193
+Adata = d7186a67061319b44eedc0677ebf5d932d5bce
+Payload = c9ee6482144dc61c43041324a2c18ede370011cb4882b0c5
+CT = 204e7d3af3b82223ae5172a9d07c434e9ae0430cec4b056b6d1d44e26404b7324767f0b3f7486f8b
+
+Count = 194
+Adata = 38f37d5e2da017f1953ff3701be0b38809ba80
+Payload = 40524a4d32a711e7d5a59809878c318f42b6e2375b77b8a7
+CT = a9f253f5d552f5d838f0f984f531fc1fef56b0f0ffbe0d095453724d2db19f606c85d00e49b0bb38
+
+Count = 195
+Adata = b3b2d249cd3517555fa692bbe9116f069e7405
+Payload = 961c15bd7dc34cd5409c9e8869988676ec6845ecb0ee85fd
+CT = 7fbc0c059a36a8eaadc9ff051b254be64188172b142730536db1e4112fcd650e8c0f0f6fbf2d07e1
+
+Count = 196
+Adata = f5b5bcc38efaff01f69bd3a106dcfca3cc6414
+Payload = 879568ab9ebdea768a5459ced1d3181d822536c3d1ba38c3
+CT = 6e35711379480e4967013843a36ed58d2fc5640475738d6d1cedb29e68322e47ff9997f859257d98
+
+Count = 197
+Adata = a2098e3e23826e01f31107a208202f710eff00
+Payload = 47cb57599686716c75d7ecef5541d20fb908e6d98c39925a
+CT = ae6b4ee17173955398828d6227fc1f9f14e8b41e28f027f41c12bf2a3571ed672592b27e986e9058
+
+Count = 198
+Adata = 20a3d53e77201599540344c4e746c3ae3a5f84
+Payload = 4a8667b5ee09d3d4a6dca9a95f4ad406f1da94b846dcc6b8
+CT = a3267e0d09fc37eb4b89c8242df719965c3ac67fe2157316f12b2be8f5966d96602111c28f87b104
+
+Count = 199
+Adata = 92c592ead4b3f193cc36687593d4f0f412a5d5
+Payload = 1dc9e32ac4176f64bd78a6edd651ebeea3ba85dfcd8298a8
+CT = f469fa9223e28b5b502dc760a4ec267e0e5ad718694b2d06776df0a0cf048892e65bd8ad77cb2255
+
+[Alen = 20]
+
+Key = 2ff64bbec197a63315c2f328dcb4837d0cdc21a5d6f89ff1d97cb51195330cd8
+Nonce = a235f8ee3de9896b71910ac02c
+
+Count = 200
+Adata = 2b411bea57b51d10a4d2fb17ef0f204aa53cf112
+Payload = 4a17522da707b4b2587a0ae367a2cd2831bb593a18ef442a
+CT = 1bf122798bd8ee8e73391d589bd046a294d1615794e69cb9e6f3ba30143acbc3a1c1c6ec74333107
+
+Count = 201
+Adata = 0248359f8071143c3cc1d61882a3547a0b3d2175
+Payload = 4a6a7151465c2abd7e7fa1fd13019ad098b6ebcd190e96f7
+CT = 1b8c01056a837081553cb646ef73115a3ddcd3a095074e6436cb510c13a039f4df8cc26a942f9911
+
+Count = 202
+Adata = cca77bc4cf6c0abd3393dac3fbe90fbc8a1154f7
+Payload = a94f5ede43929d48d2c5a58c3262d9127d2ac3cb2fbd5768
+CT = f8a92e8a6f4dc774f986b237ce105298d840fba6a3b48ffb7fe0dedc2899dff81a251cff16bf5897
+
+Count = 203
+Adata = 9c082a84646c070bb11b7d6b92b62f06ee5b5b71
+Payload = 7303bd41cf47289a3111366d08e8e21548baf293052029eb
+CT = 22e5cd15e39872a61a5221d6f49a699fedd0cafe8929f17886c43ac23800de60a1fd2caef0f03261
+
+Count = 204
+Adata = 1c3ede1982a807a410ae1e21947bf430f8db7027
+Payload = fa9743a67978c20316cb91801d7789e350079aae3aadbd43
+CT = ab7133f255a7983f3d88863be1050269f56da2c3b6a465d026f7907e235c09d3322c4092d2e88f88
+
+Count = 205
+Adata = deb05a30a026ff66ce71e98afa62f0255aef84f5
+Payload = 99599b4042dcdb685350cdecfdf24992fd5b165670025d0c
+CT = c8bfeb146e0381547813da570180c21858312e3bfc0b859f6bb44a28c145d49f49f2821d4044e4b6
+
+Count = 206
+Adata = 93dd9b00a3353e5331338dcfcb7ca7e0bb873a4e
+Payload = 451101250ec6f26652249d59dc974b7361d571a8101cdfd3
+CT = 14f771712219a85a79678ae220e5c0f9c4bf49c59c1507400f7d20aa3d792d6a3ebc5ee0df2fd89c
+
+Count = 207
+Adata = 0855263860043207543c8c34648d53ec51c4f47e
+Payload = b2db87b7787531968d603098cb20ca7c438b4af72623fea9
+CT = e33df7e354aa6baaa6232723375241f6e6e1729aaa2a263a7ca4733f0208668b0a7879305e861d71
+
+Count = 208
+Adata = ee2d3a66deb3ebca867a902bb9202226ed516ded
+Payload = ca18ce38086223e63b4f0b616d110010f9e45eac42f2ba46
+CT = 9bfebe6c24bd79da100c1cda91638b9a5c8e66c1cefb62d5d76b482ff20429da8f60f0f863e1af50
+
+Count = 209
+Adata = 8e531aaea849addab6a83497cbc504f489505952
+Payload = 5717ed5da5b8aa806a18bfe979502bab6632c9428d3a7725
+CT = 06f19d098967f0bc415ba8528522a021c358f12f0133afb6aab66e1ac2346ef97850a4985c64b737
+
+[Alen = 21]
+
+Key = 24e9f08a9a007f9976919e10dc432002e2e078a339677f00105c72ed35633a3f
+Nonce = 15977424eeec0ec7f647e6c798
+
+Count = 210
+Adata = 2d838eb51a4bc69a001a18adf2084a680f02a3c5fc
+Payload = d3416a81b4246eb0bf8119a72a886bbc0ac9449c69f71d2f
+CT = e001a8fae390dc5d672cdd18f86a1f728158ec83a002050def9af5679edbcbb7db20ab6af30698db
+
+Count = 211
+Adata = d83ee7ce22fd1a2882d8d552346e4d7b3efdd67da4
+Payload = 22b6f10b482448626f6c7bebb14f1497896d071738133b4d
+CT = 11f633701f90fa8fb7c1bf5463ad605902fcaf08f1e6236fd435a5a38f84387f63b13407f65ec86c
+
+Count = 212
+Adata = 2d5537b24d0b0f7a45703c1e131656ec9edc12cdf7
+Payload = d60edc830be8207ffd9e9f646d3b4343b10b3d56acb89d44
+CT = e54e1ef85c5c929225335bdbbfd9378d3a9a9549654d85662ede8a705f8c988f55459542bd631b1c
+
+Count = 213
+Adata = 1a750eb326923412d94ccb35f5acd0f87415268178
+Payload = 716d3132f449a9def383978102ae50ed3ccae0cb346ba1df
+CT = 422df349a3fd1b332b2e533ed04c2423b75b48d4fd9eb9fd986de774a612230ce6c71449d26732ce
+
+Count = 214
+Adata = b10fc523bc4562d44edfe5956f93c15c4ab38bba3c
+Payload = 063c2ae2a15f26f979bf90657d20643e3184f1a9f75a3aad
+CT = 357ce899f6eb9414a11254daafc210f0ba1559b63eaf228fe710431005264fa7d3fc04bac50fc1ec
+
+Count = 215
+Adata = fe4f60ce9634e7dbc5e56204c4bf8aa9be577027ec
+Payload = bdc513e56a5bb70c02abc041af04d6e45e735d10cc88357f
+CT = 8e85d19e3def05e1da0604fe7de6a22ad5e2f50f057d2d5d5c13bea6ad0cad724e6cd02c89517ffc
+
+Count = 216
+Adata = 48f3ceda4fd390a7eb38f7f5bcd14310af6b5a557e
+Payload = 7dc5d8cd90ce2faf76bbd0d52e5ae11b310fc2b0051c4377
+CT = 4e851ab6c77a9d42ae16146afcb895d5ba9e6aafcce95b55d2a5531655aae01e249f213e0e04af0d
+
+Count = 217
+Adata = 199ec321d1d24d5408076912d6bb2b6f192d6b347f
+Payload = 66c2696edec26ba3d07bd3f485a0d6ce8a1b0a85b20083e7
+CT = 5582ab158976d94e08d6174b5742a200018aa29a7bf59bc52a127ef341345f9641b26e91265e1482
+
+Count = 218
+Adata = 8b013f5782d5d1af8dbd451a4202866095dac975fc
+Payload = f4da8ac3e8fe5ec6a5b6a2f27b68396e850b46a024d441f0
+CT = c79a48b8bf4aec2b7d1b664da98a4da00e9aeebfed2159d2a005ca13c4bf715c3b7b2782f799b23a
+
+Count = 219
+Adata = e320df32b71cc530e8493b12b9afbeabc255c5eb44
+Payload = 244891cb4af66cc8e99a3784a2e82475e51bd5c7fde67cf5
+CT = 170853b01d42de253137f33b700a50bb6e8a7dd8341364d704642aff9cb9288d49f0e567dd837e05
+
+[Alen = 22]
+
+Key = 0ec1b22b8df05dc92135d2dfbefed8ea81458f5ea1b801e8a218faf6cbdf1a79
+Nonce = 97ebcb8575bb58260208d5c227
+
+Count = 220
+Adata = a2f6337f86dd00d1a58448851e95d8c9bace4a5c8710
+Payload = 2f59d94d4ab8eeb84c2a6fefb7fb0a3ac059c1e1a65ae34a
+CT = 7ca0b1dbe34b0391e524b868b0af08b3e096917664d6aa2cabc1f9d0132394149c9062b74b82f04b
+
+Count = 221
+Adata = abf26b05558252c8e38c52b1ace087bbd1eb3d561239
+Payload = c25381853f73a3dc4195fdcbc45dfa1a40eb8324749adb2e
+CT = 91aae91396804ef5e89b2a4cc309f8936024d3b3b61692486d7df57c6a792f6f6b24cb5f87e92123
+
+Count = 222
+Adata = a13ade56b47803897666e42ef2ef88be0e779ac86c28
+Payload = 8dc5226a2a13088c87f4bf94262e0c0413f06b35d2fda79b
+CT = de3c4afc83e0e5a52efa6813217a0e8d333f3ba21071eefd4ac19b0b74cd9d5e100598b96c9f1f2e
+
+Count = 223
+Adata = 3c5b68b65edf62755b7e064bd26c843816bf6c1cd481
+Payload = ee4b23039cd512cfab8c7a2d0f2c78d66764520bc88759e1
+CT = bdb24b953526ffe60282adaa08787a5f47ab029c0a0b1087a77a27eabfc79f192c0ac491280af8d0
+
+Count = 224
+Adata = 0213fe13c49083d7c00335e1864dc139c9e7123162d1
+Payload = 30b48d4021838090fbd5251069ff8c631452daee5ef899db
+CT = 634de5d688706db952dbf2976eab8eea349d8a799c74d0bd39935f91c1e29fc1e4c5c5427ca9da79
+
+Count = 225
+Adata = a32291746b151be8134e183798aa82bef210343feaf6
+Payload = 2286a1eddd80737a724ca941217e9f0232870b6c2f20d29c
+CT = 717fc97b74739e53db427ec6262a9d8b12485bfbedac9bfaaeaec90ada2a1ffef64c3873af645a40
+
+Count = 226
+Adata = a30f2fd445820cdf800145540602c877da0e4c311272
+Payload = fe703ca0901e4a706ce1393c7d8ce18a03eb2caadbfa7b8e
+CT = ad89543639eda759c5efeebb7ad8e30323247c3d197632e87932952831d0ba25c77c18fe154d8ed8
+
+Count = 227
+Adata = ed438e393e0e37629cb25044ae89de9fd0d42d60c1a3
+Payload = 7043c67726870bb5816da925925bc2722478311c8a606cca
+CT = 23baaee18f74e69c28637ea2950fc0fb04b7618b48ec25ac234fd0241d00f3890a23ccd0bf16dcbf
+
+Count = 228
+Adata = 1013946815001a2c08acca4196e0d6668ffbb3883cf1
+Payload = 695e9712dbbf883e9bf8af9188bd01fc631968928258168d
+CT = 3aa7ff84724c651732f678168fe9037543d6380540d45febaf43498b0c3f70c119f82d5812db940f
+
+Count = 229
+Adata = 44cc9b2510680c4d73f1938c77de21242c8ee790ed7f
+Payload = 67ba90d22c6bb5f649bc0c505c5ed23a299882559a3bf520
+CT = 3443f844859858dfe0b2dbd75b0ad0b30957d2c258b7bc46db66dbb03a4c943ac089ed11eb214bbb
+
+[Alen = 23]
+
+Key = 0875020959ed969cfb38636d1d5aabce9658b00171a7614ea9e5395331c7659c
+Nonce = 451101250ec6f26652249d59dc
+
+Count = 230
+Adata = 7cc9c51b69f98a06391ab32742fb6365e15106c811fe8a
+Payload = 065ef9eeafbe077c1c7049f43eb0d8999708e8609f214d5c
+CT = 990065322a438e136860f7b019807e9feff52a642bf3d44a9163fa7a867f04cab6f52dc250070f31
+
+Count = 231
+Adata = 7bb1bc069a783d45d51d8ecd0a53ab7a386fa1f5ef12a1
+Payload = 69b2b056f2265e707d3e31e68bff6a060544c8a737b2a9b9
+CT = f6ec2c8a77dbd71f092e8fa2accfcc007db90aa3836030affd33dd9155619fb040dcd6038c7b7367
+
+Count = 232
+Adata = 0dd220919d0eeee3b7cec36c47e376b778583b38bf61c8
+Payload = b98d79aaa4c04171398c7f1189497acaa7546ef068bc7a3f
+CT = 26d3e576213dc81e4d9cc155ae79dcccdfa9acf4dc6ee3294fcba5a886b1f33cf1cf44618d28f01f
+
+Count = 233
+Adata = 1c1915fab09348b9a5536495c70d1a040305708c112479
+Payload = eeaeb773ade5fb2d27b50bb892916333e0b123c6e3ae5bdb
+CT = 71f02baf2818724253a5b5fcb5a1c535984ce1c2577cc2cdeafe2c670eac203d5e90b9d520e7a618
+
+Count = 234
+Adata = 614b0ac4611b6c6d3b4ed089510dcd2215567bc3789f85
+Payload = f2198e1f91fde2672a1ef60403c0d175f366b6780ee9f1c2
+CT = 6d4712c314006b085e0e484024f077738b9b747cba3b68d4f0388746438e83b731b5588fef53f1f3
+
+Count = 235
+Adata = 866fea4483d4e903566844e31c24283571832dfae32c74
+Payload = ba37617342b4eefd4bdce8fad30c4751b206d47814973b3a
+CT = 2569fdafc74967923fcc56bef43ce157cafb167ca045a22cfca81f8b36d16698a600fd701f2c6424
+
+Count = 236
+Adata = 9d7546f7e8b949c539d21a357f81d0151e278d0bf2c5a5
+Payload = 69adcae8a1e9a3f2fe9e62591f7b4c5b19d3b50e769521f6
+CT = f6f3563424142a9d8a8edc1d384bea5d612e770ac247b8e04c15a6d292c7ed2f31cf9512435ec7d2
+
+Count = 237
+Adata = 42b692048c8b3cce1b5e83f4f33232a7d7d0bc20695e7e
+Payload = e0753d4248643642c7a96404de8d76c9d80527b659ec6d31
+CT = 7f2ba19ecd99bf2db3b9da40f9bdd0cfa0f8e5b2ed3ef427a2ad73179d0314b5fe52dd7217518cb8
+
+Count = 238
+Adata = f1dfb6fdb31cb423226f181c0988a52ee4015aef4536f4
+Payload = 79ba959c7221b293e2115f538d9394c64284c756563c04b0
+CT = e6e40940f7dc3bfc9601e117aaa332c03a790552e2ee9da69ccc5ba1caf933b80bfc6f281109688f
+
+Count = 239
+Adata = 8eafce9ba466fd53eb87f499d7c76bd486db0e90a3d281
+Payload = e1590206717a708cad9cca7d23a3b8ee5f7fb7786aa3be47
+CT = 7e079edaf487f9e3d98c743904931ee82782757cde71275173271ec36d92fff34609169f579c8f1d
+
+[Alen = 24]
+
+Key = ef4c1d2314e671f666cc6667660f1438a293208c7cc29b412d81277f0a635c91
+Nonce = 50b23b052922366c25dd40e348
+
+Count = 240
+Adata = cd0522ebe1fed82465277d1c10ae9316a98b4469be63b180
+Payload = c99c3e79125b6fd95e737326a842424eb6c6ecea4c0475c4
+CT = 76df4be4ec8373864399acda11294b220b9f7c3a7d2b3660b25764e40ac6a171e7e6bab4fdee4288
+
+Count = 241
+Adata = ce5bf070678cb07e963263b1562ff79311144addb6e4de4f
+Payload = eede01b08f9a303cdf14c99d7a45732972c6eff2a1db06eb
+CT = 519d742d71422c63c2fe1661c32e7a45cf9f7f2290f4454ffca49758d17f2073066b82667eae6ce3
+
+Count = 242
+Adata = 07175be2475cc735c9a3c1140895277378debf8fb1c87c24
+Payload = 6d5579aaaf8737b01620424f3ddeaf538f10dfad094e5ec4
+CT = d2160c37515f2bef0bca9db384b5a63f32494f7d38611d607c1d64d7e9de47a6ad7878283da9d870
+
+Count = 243
+Adata = c821a8d4bab9d993c20dd206955304a55968e6db5ab6480d
+Payload = d0628b2027f06c246497977d05f211b2c2e302d5b82700b5
+CT = 6f21febdd928707b797d4881bc9918de7fba920589084311adc2bb471862d25cfe25e66fedb8e28c
+
+Count = 244
+Adata = 68439bc9d176feeeb4119d00ed5449dfefb72b5a582bfd97
+Payload = 6cc9749f48c61050e421afa3a10ad3dd3aa02cc3f8586915
+CT = d38a0102b61e0c0ff9cb705f1861dab187f9bc13c9772ab1319a493abc947945f1312395ea98d937
+
+Count = 245
+Adata = adb262c924942e4e1964e9d97c6a8c159fbf9bfedc5ff296
+Payload = 92d50736466e64e6225962e76bd90da824f716a3301a1a90
+CT = 2d9672abb8b678b93fb3bd1bd2b204c499ae86730135593421d0602d29447ba6b24a67509eaee1e8
+
+Count = 246
+Adata = fc7b08707d3c3dac7689ec18088ee6502ef08d3ffbff38ed
+Payload = 87c7ac031fd63e4c83280dce6b68a92dfafb6ea19388fa9f
+CT = 3884d99ee10e22139ec2d232d203a04147a2fe71a2a7b93be52a2eeacb1f023e849161b6306b6cfa
+
+Count = 247
+Adata = fd43dfb66041b117f2ac54c94f7b6e2677860864d9494175
+Payload = 6b53c46266b2f4284d8fe7f0549c98977344d67e178e9a8e
+CT = d410b1ff986ae8775065380cedf791fbce1d46ae26a1d92a0d8c5b1e96b21460e0b5414639abeb0b
+
+Count = 248
+Adata = ef1ad3eb0bde7d4728389da2255d1f8a66ecb72e6f2f1ac4
+Payload = 8e7d8a44244daa7df2b340993e32dac50e05d7b2e103be98
+CT = 313effd9da95b622ef599f658759d3a9b35c4762d02cfd3c1c97260d20797d374c595cbc2ff080bc
+
+Count = 249
+Adata = 9895b24d12b004b215583eac70a95f4fba7442164f35c57b
+Payload = cec07df916ffb7a453d0eb588b7462096f22874bd5abf814
+CT = 71830864e827abfb4e3a34a4321f6b65d27b179be484bbb06cd287afcbdbc5531f11246080b22677
+
+[Alen = 25]
+
+Key = 8544808e8fbf8c3a5e1d4ca751d4b603af9fe119eabc6923205815e0e748b7e7
+Nonce = b44a58724596b4d8dea827c1a0
+
+Count = 250
+Adata = f5b2c88f5232c37273b1e66aa31cfa7201e33c21d60054d025
+Payload = 617d54fc6a23601c79e3984f93bfc2d151fde420863206b3
+CT = 57b3414db48982c6567265e1e0173bf38fdfaffe4461fbebc1411af83237c0f9eb0bfe8ed914da66
+
+Count = 251
+Adata = 8fabe14dcb3aa2fd28281147c326e98ad699ca7997f03a105d
+Payload = 337290d0b4ce1e87afc3cf01d6c98f8c17a4603120dcfcd1
+CT = 05bc85616a64fc5d805232afa56176aec9862befe28f01897ed6e23720b60ffe54bbb9f7ff371008
+
+Count = 252
+Adata = cf193eb3d755cb8e06c5be2334b5c8b7a22b6524d46d547ba3
+Payload = 01ef7ac6470aa02ccd8c1712827e52699d05751b78e4c5a6
+CT = 37216f7799a042f6e21deabcf1d6ab4b43273ec5bab738feb6aa6b284e7720acbd027a50317f816a
+
+Count = 253
+Adata = b4cadb5f9cb66415c3a3b71421b926f147566a174160a0bcc0
+Payload = 64fb9322210fb7d8da8e762498b233b0eb172c91231c50cb
+CT = 52358693ffa55502f51f8b8aeb1aca923535674fe14fad937058e9c0164ca079668097fde19e5302
+
+Count = 254
+Adata = 48400d76ff882d6d5129c8674acc71f445356c9db9c91f8256
+Payload = 291aa463c4babc76b4a6faf2e27e9401586b1ac83e4b06a4
+CT = 1fd4b1d21a105eac9b37075c91d66d2386495116fc18fbfcf988611d5ce0f65b217bb4787bf59bbc
+
+Count = 255
+Adata = 749d369d837002ad33feb8aa22c3f68705eb4872e1b8f85a7f
+Payload = 141cdd7f964a78815be144a785c6a2a298c54230e73039e2
+CT = 22d2c8ce48e09a5b7470b909f66e5b8046e709ee2563c4bad6251a5fd375a48583a6d0f8eb75cbb4
+
+Count = 256
+Adata = 80214108b16d030feff6e056c9a07a00a1d5e3ebb07abd3f4a
+Payload = fa2441cb7f9d072b8a3f1a496b2be6728a38b94a4f44c9be
+CT = ccea547aa137e5f1a5aee7e718831f50541af2948d1734e6af1dab0f105414293cb130bea285fd6a
+
+Count = 257
+Adata = 8b9fabe29718a8f297c9bf6f199c80bbc71f94eb3034a11ecb
+Payload = c8ce88ab40b62229223d46cc44f21bb39cfef27aa9fdccad
+CT = fe009d1a9e1cc0f30dacbb62375ae29142dcb9a46bae31f51cc3f7640a42460be877fb7059a3ed61
+
+Count = 258
+Adata = 8812f28a0cd5fdaa226fdd44ed857241007377057be3bea577
+Payload = cf59f75ca4d6d216cf8862b44b5192c382c140f862def117
+CT = f997e2ed7a7c30cce0199f1a38f96be15ce30b26a08d0c4fbbe0ddd2e7f4aa2024b3fec9281b6cac
+
+Count = 259
+Adata = c8f05e96d703a4850bae1421ae9ff3aec7531baf9b899dfd75
+Payload = 4eed58f381e500902ba5c56864f6249d191e14d1b1fad3dd
+CT = 78234d425f4fe24a043438c6175eddbfc73c5f0f73a92e85e5df1e5e96bb84f730fcb253d468278f
+
+[Alen = 26]
+
+Key = e19eaddd9f1574447e7e6525f7fd67e3b42807e44fbb60e75d8c3e98abc18361
+Nonce = a8c459ce0223358826fb1ec0f0
+
+Count = 260
+Adata = ef88f4393d6c1e7b7be55a12144209ee051bb779e440432721ef
+Payload = b3b0de10b7c0996662f1b064e04e528b7d85ca1166985d33
+CT = d63e6082c95c6c5ff2bc0771321a4f883ef61cff7b99e0ea8a20a1abe7c842ebc08c8c81a2743c81
+
+Count = 261
+Adata = a4c891c9dd1fcc982c35bc74cfe71651bae424602519672b466d
+Payload = 4f0b40913f07269550b7b06ab9027a4d9331f8ef98a45dca
+CT = 2a85fe03419bd3acc0fa077f6b56674ed0422e0185a5e013845e2d6de83ab729dd200a21088a1ec3
+
+Count = 262
+Adata = 4db5730cb9794f3b1facc9d6738115d02ba9f27ba02330fbb856
+Payload = 841e032773d58bc72a3237bc9b24c61b9efdd850fc2ea605
+CT = e190bdb50d497efeba7f80a94970db18dd8e0ebee12f1bdc10ed272c732247a696a608ef67510f9c
+
+Count = 263
+Adata = 471a900ee49f2cfa1d3eb37c951d810c349364d4cc3b5b64fc47
+Payload = b4db42e523e65557157b93dc0281601f7997e6731543a914
+CT = d155fc775d7aa06e853624c9d0d57d1c3ae4309d084214cd15f0df52e392c37ec15f7458469dae84
+
+Count = 264
+Adata = 7b40b3443d00a0348a060db109e8882157612c43084ac5c3e9c5
+Payload = 73e0ed35c0e847188e607cde46586eb9e237fbdc5d59163c
+CT = 166e53a7be74b2211e2dcbcb940c73baa1442d324058abe5421433dafea2b5484ba87b5050e1fb49
+
+Count = 265
+Adata = d563f5c048a1b45265182b99ca7b9004fdc73a9cb07806dd44fc
+Payload = 4f7669caaedee961dbba6bde9d09fee1a20eee55baaf98f5
+CT = 2af8d758d0421c584bf7dccb4f5de3e2e17d38bba7ae252cdf91749fe3cd52a9431d9a847a8c2a9a
+
+Count = 266
+Adata = d301a61eb17366d4e70942ab69b4f4bcf8ff6a97f5972ee5780a
+Payload = 154454fb74e9565c56775a8e4654f75a38b954dd28c4e939
+CT = 70caea690a75a365c63aed9b9400ea597bca823335c554e07563d37846f5185bb44d71be1ea6a73c
+
+Count = 267
+Adata = f74b48d168f77fbd3429728c0b168ecbd854264eaef70b74fffb
+Payload = 716b371857e68a17b20ea06651cdcfd4560a741830ca8a13
+CT = 14e5898a297a7f2e224317738399d2d71579a2f62dcb37ca55e93bc2d3f05d7016747690fb920e12
+
+Count = 268
+Adata = 3a257ce3592a8f88162f0bb4ecd5db3bb79b54ab17b0bbc61506
+Payload = cfdb7363985aa01af6f8e8237dbfb7871eb39303b4135269
+CT = aa55cdf1e6c6552366b55f36afebaa845dc045eda912efb01c46822f839f09c41b7aa6dc06035c93
+
+Count = 269
+Adata = 21916ebeca9e66b77cf55d1cac80a4c85d8b6b014f268ffa73ca
+Payload = b4b67ac551d1966caa20d951351387f384c2e5d81a76a92c
+CT = d138c4572f4d63553a6d6e44e7479af0c7b13336077714f54f8e77600c5bbc6d028fa25ba61a1719
+
+[Alen = 27]
+
+Key = 9498f02e50487cfbda1ce6459e241233bd4c4cb10281dcb51915dbc7fb6545c0
+Nonce = e3bd4bc3a60cddd26c20aa8636
+
+Count = 270
+Adata = 70cfcb828d483216b46c3cd22e2f9ee879e9e3059b566179b6e16c
+Payload = 0d16cc69caa9f19b88b05e151b3d26accd018ca4a5786a80
+CT = f1c4bedb8d6f91676881daa37656a7e6402f472735b04a0f1f8332f4236437737438e7aa1b5100c7
+
+Count = 271
+Adata = e7e5779282db80f424dc050b2c1e7754b2a5d3a8beae77beb74e34
+Payload = 148de640f3c11591a6f8c5c48632c5fb79d3b7e1cef9159c
+CT = e85f94f2b407756d46c94172eb5944b1f4fd7c625e3135138be2f6f356c2eb401468be15104e7763
+
+Count = 272
+Adata = d17e8189a94a559b07be9549f73d653172740e8e978f5b0a38ad43
+Payload = 00a23b25bca7c206edd051814d81083db1cd00048ce8ead5
+CT = fc704997fb61a2fa0de1d53720ea89773ce3cb871c20ca5a9646f2b6c2455603f1a6f20ea5a4611a
+
+Count = 273
+Adata = fda37ff136895de7ebeaf81e701e5751245201baed2e13d7e1b591
+Payload = a89409b0977f60a029dc4c1560ba6dbe7c65b068633acf74
+CT = 54467b02d0b9005cc9edc8a30dd1ecf4f14b7bebf3f2effb303fa5d8321241b1c9e18a5909d6e428
+
+Count = 274
+Adata = 9c179fd0d6277a5e073e77dd6abb4cba00ad9c9932e6c002b951c7
+Payload = e16c69861efc206e85aab1255e69d6d33c52cf058dec9d0b
+CT = 1dbe1b34593a4092659b359333025799b17c04861d24bd849e8cb01db1da077502814db1610662ce
+
+Count = 275
+Adata = cf5703228e615428d3d3805e428e754961d205c5aa0297ecdea71d
+Payload = 62036cbed3666d85624d3dc9c1f437454b9ab5c03ce0de92
+CT = 9ed11e0c94a00d79827cb97fac9fb60fc6b47e43ac28fe1d40a02a49857d7b280330b8105efac854
+
+Count = 276
+Adata = bab7e36098d59d3a31d7784d549aebfc6938bbd0612c85c0edb796
+Payload = 790ac86c5e9d8ce8cbec1dfb7e4fc4dca3d0b1039adfe585
+CT = 85d8bade195bec142bdd994d132445962efe7a800a17c50a5ecfa9dd03e2db70aa212ee7dcb573fd
+
+Count = 277
+Adata = 96f0b7cd7439721d4c9cc4f69585f8c90a95bed8fea22150efffba
+Payload = 3cfacd61ea3398de20ca6bdb00e81af482320614bdfb8642
+CT = c028bfd3adf5f822c0fbef6d6d839bbe0f1ccd972d33a6cde17a7a0cd162945a3616892e101e3e93
+
+Count = 278
+Adata = ee71e53d0b4eef82575c2bd38d7bd21b41fabe58c6f571954fe159
+Payload = d75c153e34ae1c6d1fcf5b1052190d8882041e1f9c5490e2
+CT = 2b8e678c73687c91fffedfa63f728cc20f2ad59c0c9cb06d15fadc2d79841d230cd55c04379f22b4
+
+Count = 279
+Adata = 18a4aa894861c7720ddb43809c3d2ed2af2f1bfe8f9fd4f872c14c
+Payload = 0e728056c7c64214be8f1f1727408d8cca8c42e2ac7bf67e
+CT = f2a0f2e4800022e85ebe9ba14a2b0cc647a289613cb3d6f1b229b9bae4634eea6b723f432e19ae55
+
+[Alen = 28]
+
+Key = 3ac7d5bc4698c021e49a685cd71057e09821633957d1d59c3c30cbc3f2d1dbf8
+Nonce = 54c8ff5459702aac058bb3be04
+
+Count = 280
+Adata = ecbd7091732e49c0f4bda2e63235ea43bbf8c8730f955f9c049dd1ec
+Payload = 89198d3acc39b950f0d411119c478c60b2422ffe7e26e00b
+CT = 7717b8e4447afcea1eeebf3e39ffdab2f52828e7931ef27e475acd27900478f09fec1f479ab3a7c8
+
+Count = 281
+Adata = 9a04820205234795ecd540b6a0b2fbd0b19f18106c42f374a2b98425
+Payload = c0f61950f98110db4226e269cf197c7e2794c5b87ad68cf9
+CT = 3ef82c8e71c25561ac1c4c466aa12aac60fec2a197ee9e8cf7b7ed6e8ede6ef5a73b484bf13b3424
+
+Count = 282
+Adata = 0e4dbd167da0240298f4795102ef18ff9a8772c6fd73b3374cdfa30a
+Payload = 7960dbc9136880e2eea7956c3271adfe2aba7dca53da917d
+CT = 876eee179b2bc558009d3b4397c9fb2c6dd07ad3bee28308e47d08ea0788f7ca0ecd846689c8027a
+
+Count = 283
+Adata = 2de4291068a5d290b599a73c6a8ecff4f9fd6c9cc48f14c233e18581
+Payload = 0c5d7055bbfbd2bc213cfbbafa763b71b1fde6f4de96fa59
+CT = f253458b33b89706cf0655955fce6da3f697e1ed33aee82cd081f66b1c7b70718dc50367c3da6792
+
+Count = 284
+Adata = dedeb714f555575fcedbd9de8171484090e6466dd4fba3c6b7c42eae
+Payload = b5654edcc8f09e4f80d0258c9376d7c53fb68f78d333b18b
+CT = 4b6b7b0240b3dbf56eea8ba336ce811778dc88613e0ba3fece672883438da186741e6c542b3f805d
+
+Count = 285
+Adata = 03d340904ace1cd52d4b72a96d96afd77aee68ac3936415005ed0d56
+Payload = d796f3409a7eeb896c3d4ebef46e9c6e553aab28b1cc4a90
+CT = 2998c69e123dae338207e09151d6cabc1250ac315cf458e5cf58d4a5552bc8ed1b1dda46703a256e
+
+Count = 286
+Adata = c67f9aa8cf1be3b4377c30c175d33ab2af390982c6a015d99209acdd
+Payload = e4dd279a79a381c68de777df941a4779e50a1381c8aa9122
+CT = 1ad31244f1e0c47c63ddd9f031a211aba260149825928357f95cf2b57e06de4d01bbb6c0e39f37e1
+
+Count = 287
+Adata = fef1b2ccd661b9fac85ba005addebdf8317ab104920549d3a490a21a
+Payload = bbf0c267d952aeb6f810601b9cf1962a92dcaba7273e6902
+CT = 45fef7b95111eb0c162ace343949c0f8d5b6acbeca067b777589cd12984286af98908db88920323c
+
+Count = 288
+Adata = 693fae7af84aa397f0b2baaed9b3c7953f75e7424c49b6349c2fc20f
+Payload = e8b13a263e0c4fb5645e500e88ab8074ab7d92e5a8dac6aa
+CT = 16bf0ff8b64f0a0f8a64fe212d13d6a6ec1795fc45e2d4dfee8fc441da990dd92c0caeac9d956699
+
+Count = 289
+Adata = 85e5df4ddec99f0bea14b3338b2eb190ab6584f5253c6c2ee3064637
+Payload = 067de2869333ed22c7b63ed7eeba1301bbac69b0d430adb5
+CT = f873d7581b70a898298c90f84b0245d3fcc66ea93908bfc0d502f5434bea8c3c13ad5422ff90e218
+
+[Alen = 29]
+
+Key = 948882c3667caa81c9b900996e3d591e6fcb3d08333eeb29911e9c6338710c17
+Nonce = 43b0aca2f0a9030f90559fa6d3
+
+Count = 290
+Adata = a516ca8405e5c8854e667921b5c5e1968bdd052915b55ac9984b7eefb3
+Payload = 8b9130b0c3c15366831bbb19f377e3209a8dbf7619cd09bd
+CT = 4646b2acdeb11174171da23999cd54e297daa32bbc13d30512e57c576b315f48c11877178389aaa0
+
+Count = 291
+Adata = db3121ea71294983b185207a9d8de3e484a66c0431bf07c962eb82977c
+Payload = 7f369bbc99b6f08049eeb43566269a174829d4dddb05cb9b
+CT = b2e119a084c6b292dde8ad150c9c2dd5457ec8807edb112366775e693f93af6575dccc7903538065
+
+Count = 292
+Adata = 1651cf38fd9b2da65ebb4922b97dcb861128eeefa060d6c1c94b25eb4e
+Payload = fd0900b5fa72e2fba43d611bad25de40a3507a5cc5d186c7
+CT = 30de82a9e702a0e9303b783bc79f6982ae076601600f5c7fb70d8de40c2068de96a274d3b5086b5a
+
+Count = 293
+Adata = af87b347b59e37a424004a00907dcbcf6a554e6782a9be12cb3047625e
+Payload = 36318d80c02a1da41ef1652d9a752e155526b5f597fba226
+CT = fbe60f9cdd5a5fb68af77c0df0cf99d75871a9a83225789ee7da096d2fb28f20f64a000fe93e96e2
+
+Count = 294
+Adata = 0680d5bacefa2ab14aa12b0e517a1432862d4215dc72dc4d5ac6b96c1c
+Payload = 7a29aa2994d11215ab3ef3382b3db6ed581164a235c4b1d1
+CT = b7fe283589a150073f38ea184187012f554678ff901a6b69b88748a2de31261534cdb2237565bf8a
+
+Count = 295
+Adata = 9af701f0a9de52309267289bd170fb97c03c131c0a169d736137ff3d74
+Payload = 3542fbe0f59a6d5f3abf619b7d58b199f7caff0205093f8b
+CT = f89579fce8ea2f4daeb978bb17e2065bfa9de35fa0d7e5330c003eb65ceedc98ae4e38ef341ee47d
+
+Count = 296
+Adata = dab7845fb7ead205569475753c7e26540c09d3a74312f2de25181511f8
+Payload = 83c15520d9541c86b3dd809ede42de22bbb2b75ff18a023b
+CT = 4e16d73cc4245e9427db99beb4f869e0b6e5ab025454d8835c2fb596d8ff6a863604cd224fa3be42
+
+Count = 297
+Adata = a844d6dbd05545ecc736994dc9fc2260c5ab63ed6ffdc40b915f8744a1
+Payload = 793a188fa3efa32f41d6e4c5b42353b95024117d546c79ca
+CT = b4ed9a93be9fe13dd5d0fde5de99e47b5d730d20f1b2a3722ac782e2cd8ecb06172eef2cb9b0e331
+
+Count = 298
+Adata = f9112503884615c0e8a1d8414724b0d19298988f393a27c436b2b6734c
+Payload = 6b237444fb0e1f4150701546c4cb24021c5edad30d9b31dd
+CT = a6f4f658e67e5d53c4760c66ae7193c01109c68ea845eb65f814492b42571033f4dffc0282ea2f51
+
+Count = 299
+Adata = d633a5a3defdde6a68f959ef39a91c6ea6e13ef1a7859d2c2c94d3a5b4
+Payload = 6342312e8a72f71f2e5afe04cfcde4d60a41556111752103
+CT = ae95b3329702b50dba5ce724a57753140716493cb4abfbbb75999099df2de6e436bd99f0341423f4
+
+[Alen = 30]
+
+Key = 3bf52cc5ee86b9a0190f390a5c0366a560b557000dbe5115fd9ee11630a62769
+Nonce = f9fbd02f28ecc929d369182752
+
+Count = 300
+Adata = ebf0b3e3199a5c3773c761c725c7600add5f9d8321c9f8e5e5fd1c7a5d2f
+Payload = 094b538110495e938b08cf748a6bcf3e0c80ff9c66570237
+CT = 4d8b53016fc8bc9677184c0fa15bbd3d671b9366d82ecb67f8562eadcdcbcdbad1299bea1523f5d2
+
+Count = 301
+Adata = a865b88d512e485ab3f2844c29e6dde0cf1151efa9ad3b3021d06fffb74b
+Payload = 23edddd8732cdbf03af08162f0e4a24c9222bdbb4549c663
+CT = 672ddd580cad39f5c6e00219dbd4d04ff9b9d141fb300f3359ff77cf0962455b3539dbf91f3077cc
+
+Count = 302
+Adata = 16918dbc785d94a8f1720c5ad234dde860219874c9fb076a5c290903f85b
+Payload = 1798286c37c1504fc0d7402681f6f70711ef506dcc3e29d0
+CT = 535828ec4840b24a3cc7c35daac685047a743c977247e0806dbed76d94c90595b49d50c84c3efc76
+
+Count = 303
+Adata = a2969243b0955402ab45a430fef2ef9e0c025006732bf8e592e3d3884918
+Payload = 0d02778f90a164a4f9ada9dc7fd24eeb941069621418ef32
+CT = 49c2770fef2086a105bd2aa754e23ce8ff8b0598aa61266248fbe60c146056e5cb01268403e4b9f5
+
+Count = 304
+Adata = 2de5222a0609f058f60e9e581b6e4f0ddebed84fc8302c8e985d17b89241
+Payload = b0c3858231e284af6d231f043b95772f5e7b16a34ffcd2ec
+CT = f40385024e6366aa91339c7f10a5052c35e07a59f1851bbcacff35df1ec942b43eef5aef980cb038
+
+Count = 305
+Adata = 3fc7453df038a92829dc103d44b63ad097d7cd7f9ae7996547012090c7c4
+Payload = 319f396cc02834f8e69d65f77496d0eb31ce1a7b7e324820
+CT = 755f39ecbfa9d6fd1a8de68c5fa6a2e85a557681c04b817091a93f5fc28e5f4f351cfb888da763dc
+
+Count = 306
+Adata = 18f1e92bd3c4a597ed970911d03a78ff9a6790147c9bb0ca5f23b70cce7a
+Payload = 25550c03f8fa02b3781330f96e0fdc58681b0c0bc5e83fe9
+CT = 61950c83877be0b68403b382453fae5b038060f17b91f6b92c6a90ef2e9a969ec0576fae1d126a85
+
+Count = 307
+Adata = 09ecb2406054716418ff3600c3c5cacb0845a377a2d80542abc36ec81bb1
+Payload = 210ff7975e08388b9a46eb732230e3a3856a497549b5eb49
+CT = 65cff7172189da8e66566808090091a0eef1258ff7cc221959fd6aeb047200907911621e8756b45f
+
+Count = 308
+Adata = 62d515bb0525b565a6a3613ae20343c8da7424c8368e8cad6a862b7d37a5
+Payload = 5d867265965bb2aafebb0691de9e157a24066d06fe3cbd7c
+CT = 194672e5e9da50af02ab85eaf5ae67794f9d01fc4045742cc4db6d5fd910c83fd77aefba3f7665d8
+
+Count = 309
+Adata = 00617ca141e55b045a188e4934caf6db63d4577f634db92c22010e1cbf1e
+Payload = 396b27afd16a1081f37bbc1f742b549f5f68df799b93083f
+CT = 7dab272faeebf2840f6b3f645f1b269c34f3b38325eac16fdf5f21f32cbe5d272004f1c104cbcae9
+
+[Alen = 31]
+
+Key = e45bb1730d0d539aab3805350ac986540de9f0f6c239ee70395c291397b70309
+Nonce = d5c7824af715bb7822b6b340fe
+
+Count = 310
+Adata = 860f4a09ad8b3d345c2aa18ffb803f0bc3b734a4d047a1437701a5e3d95288
+Payload = bc8b3bc48c7a88c9fafde258b6ccaa9d4f0d018703d63871
+CT = 95f083ad6bbaee6ab540fe023858f8baf25e333fd3e89c00e678a392d228b210dc5c991905dacf3f
+
+Count = 311
+Adata = 8a84b57915bdbe7bf5a1c1a426512b3c178d883251cc46c95a8bbc8ed9e56b
+Payload = 9499ea48edab9bc21b91dd614f04934ca20db8630622f481
+CT = bde252210a6bfd61542cc13bc190c16b1f5e8adbd61c50f010fbdd3b305522dae6b652322d89d9ac
+
+Count = 312
+Adata = ed8540f7ce451c522c1ff5d2d1030d7b3fbd1219a21aaa84044c4f23c08f5d
+Payload = 73843a4e9e7937fed24bb1fae15822213b1aa86c07f1b5d1
+CT = 5aff822779b9515d9df6ada06fcc700686499ad4d7cf11a08b6b08548e794eaf85ad9f5de80b1c00
+
+Count = 313
+Adata = 61bb196b212feab645f05a8aa1986f6210a384c15bc749245d840b3565fb36
+Payload = a8e24266e5981b2ed14213a29f961cbbf7f02f63a33c987e
+CT = 8199fa0f02587d8d9eff0ff811024e9c4aa31ddb73023c0fcc73643a7ee9291e15137d7046a92f3f
+
+Count = 314
+Adata = a49c2df94ba65107f375ce1c53b72406143f6bcd270945de5b7811682fe361
+Payload = 3e3c402caeca41687d12897102e04312edf7b8c7d8567a22
+CT = 1747f845490a27cb32af952b8c74113550a48a7f0868de53204438662ea82f423a69c6e4e3c0623a
+
+Count = 315
+Adata = 7c48480e9bc87ba299e03899698b2259eef150ee0f2efff40a5583b80ab484
+Payload = cfa9292b9052ac6bb863205d3c0dc2d9e20d2ba6a680d2ed
+CT = e6d291427792cac8f7de3c07b29990fe5f5e191e76be769c6ea00b9cd881e3f4b1e838dfa31f6560
+
+Count = 316
+Adata = 5cf9744090366d828b477dc890eab8ebebd44f6aeaa5b101291bf67d12867e
+Payload = e0fe4e139ab0deb4fdf2145b719f35c50b869e6cb20608b5
+CT = c985f67a7d70b817b24f0801ff0b67e2b6d5acd46238acc4c59b3b87d722a58cd1de58f3963d12b3
+
+Count = 317
+Adata = 761d74be5fae170a1bdfa16081b44c1e49972e15ce0818df1390bf7204f619
+Payload = 665fdcdf55a1231e9912562eaa5a5011d69f6948e29e3f8f
+CT = 4f2464b6b26145bdd6af4a7424ce02366bcc5bf032a09bfe158759886124f1f0ce8147c94f4e7114
+
+Count = 318
+Adata = 9815353b69d0b4effa52cefff13703fa71a6296f9cca0f02568661be4b64cb
+Payload = 7b2d52a5186d912cf6b83ace7740ceda3f5f443530c5a49f
+CT = 5256eaccffadf78fb9052694f9d49cfd820c768de0fb00ee6310a79c9932456dbc00515b264f3168
+
+Count = 319
+Adata = 69dd1a050c8d79dafbbe3403af4dc1f070b9b2b980888aa796e6cff68d9060
+Payload = 3cea5ff50167c5641066852fd00061df35b1f66bedb894b7
+CT = 1591e79ce6a7a3c75fdb99755e9433f888e2c4d33d8630c6da7e97f9984a7db3b93aefb4316d9acb
+
+[Alen = 32]
+
+Key = 2e6e34070caf1b8820ed39edfa83459abe1c15a1827f1c39f7ac316c4c27910f
+Nonce = c49ccef869bb86d21932cb443b
+
+Count = 320
+Adata = d37e35d7cdccd9824a1ae4c787819735e4af798a3beb49d4705336d6496853ad
+Payload = 771a7baa9cf83aa253349f6475d5e74dba4525307b022ba7
+CT = eebac2475004970071dfa2cfb855c4e78b1add8dcbccfc0bd6b14027324b657a56263df148665393
+
+Count = 321
+Adata = ab22bc22bf2628b0e0ab245c3db2fc5128d13a011c2cc9b9fea05a79a3410704
+Payload = dad95a4b4d3754613f0542caa62cfe4e375dfbdd369ec32e
+CT = 4379e3a681cbf9c31dee7f616bacdde40602036086501482a8c810b6944815fd2e434193520b1d5b
+
+Count = 322
+Adata = c48c5aacf701137fc40fd0d3649641aaa5be427ceee702cf7ddf6408f458a581
+Payload = 3f28df9263e473be648fabad163aa4142b633388b16d8392
+CT = a688667faf18de1c46649606dbba87be1a3ccb3501a3543e8aa447b79284c588bef50b423de97908
+
+Count = 323
+Adata = 477c2484cf5c56b813313927be8387b1024f995e98fc87f1029091c01424bdc2
+Payload = f83107b50a1f192ed45cc43fa80e6b519bfd859173ea9ee9
+CT = 6191be58c6e3b48cf6b7f994658e48fbaaa27d2cc3244945d4f4a413eb3ac2c474134995d4db9a16
+
+Count = 324
+Adata = 143bc037f1d0bd4ec16825c58cb3796bf8989200d27bda9beabbbc49247f59f7
+Payload = dfeb324ba459ec4a5c54d2534e98002412e67db19cfc66bb
+CT = 464b8ba668a541e87ebfeff88318238e23b9850c2c32b11756a3fb2e06734b28fbd57942a609d914
+
+Count = 325
+Adata = ffc416f1dae4e43c1a01339a604c44d6a0f25ab9ca3978c6aacb6d270d510ee6
+Payload = 0765949e6f22c422ebd47dc1ed73f1b849d7a058a1656fc2
+CT = 9ec52d73a3de6980c93f406a20f3d212788858e511abb86edb94280d3c4a1cd8cb00705f60ae36f2
+
+Count = 326
+Adata = 6090b596b4082ec6926576137f6561cf13916860ad1cfc43650d1b5142a12041
+Payload = 6db320cbe76bc5b8cee9ef89aca11765571c6c501993195a
+CT = f41399262b97681aec02d222612134cf664394eda95dcef612caca26cc3bbb289da3be0616b3445f
+
+Count = 327
+Adata = 178ba75adb7c5bea6769270bb3b4f6ce208d4a786913d3ced7bb4090b5f65544
+Payload = 0875020959ed969cfb38636d1d5aabce9658b00171a7614e
+CT = 91d5bbe495113b3ed9d35ec6d0da8864a70748bcc169b6e26cc8c665289d907628eb0e299c2d411e
+
+Count = 328
+Adata = 90f0474dca998916075b1b1428df14d90be05491bb8d5d88e32e65ec890ba9d3
+Payload = 4f89ca6ad371f86a6e073ec12fb1b928bb10d6639233b918
+CT = d62973871f8d55c84cec036ae2319a828a4f2ede22fd6eb4f7e481607a2a0529f9cda1d5903325b7
+
+Count = 329
+Adata = 5ad8dd40ecdce52d5b30424ca0bccb666f34f66b0c9a4c1260051ac04ca06aab
+Payload = fe2009d0a4a1711b83057b948cd0b174a3a042fd97579ab8
+CT = 6780b03d685ddcb9a1ee463f415092de92ffba4027994d140a1b9ba2bfe5bf778b859f0ff0c29a67
diff --git a/lib/crypto/test/crypto_SUITE_data/VNT128.rsp b/lib/crypto/test/crypto_SUITE_data/VNT128.rsp
new file mode 100644
index 0000000000..b796541cf5
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/VNT128.rsp
@@ -0,0 +1,456 @@
+# CAVS 11.0
+# "CCM-VNT" information
+# AES Keylen: 128
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Plen = 24
+Tlen = 16
+
+[Nlen = 7]
+
+Key = c0425ed20cd28fda67a2bcc0ab342a49
+
+Count = 0
+Nonce = 37667f334dce90
+Adata = 0b3e8d9785c74c8f41ea257d4d87495ffbbb335542b12e0d62bb177ec7a164d9
+Payload = 4f065a23eeca6b18d118e1de4d7e5ca1a7c0e556d786d407
+CT = 768fccdf4898bca099e33c3d40565497dec22dd6e33dcf4384d71be8565c21a455db45816da8158c
+
+Count = 1
+Nonce = f7a5098b2a4d92
+Adata = bc498326755503ff25d02805eb3517221b54eb4fd79af0fcdf9312b2a9ad95f7
+Payload = 3e2144e2a381b718962a77e167778bf579957a8fae29612c
+CT = 98ce91033fabaa8fe853d347be6cbe5de102fdccf042e7be697b41c9a69acaf8386140ee6e36f406
+
+Count = 2
+Nonce = 732d2dd64b4a25
+Adata = 495b03df82e317e4f351c5323d17c673f4c77856983179d7c7cb75c2b0573c72
+Payload = 4bb0d170bdcc70fd18f19605cf9c6181082c4367f1e6fbce
+CT = 9bd9304259962448fa8487bc15d950303621213afd88f1e32d442ff663242fa269c4a742a220edc5
+
+Count = 3
+Nonce = fefd3ac595428f
+Adata = 91ffb6be8e129cef9189f7e0fec8e937afcfc6083b6a79a778a724bb3e8d0794
+Payload = 9e8c4f1292e8d7e5179b34ae5d2ba2491d7754acc54bb91d
+CT = a5d012b3062cc93b831860d76539169c88854b85550c67fc564a2f1cb7d77e0223287740d5ff9003
+
+Count = 4
+Nonce = e14d81ee3b873a
+Adata = ecdc5249ceb48e8d5a4483043921c00c1acb1843fae00155a28f3a127150b1c4
+Payload = f99e23288e6b5ae85c14610994d90d5fcbcab62b4ed1333e
+CT = cc4ee711d0202deb58664e00cf0cf70b737f48ddadcefd6cd217fb611daeb66fa2d8e1bd43cb2131
+
+Count = 5
+Nonce = 2cbeaba94dbbd1
+Adata = d129674c6c91c1c89f4408139afe187026b8114893d0f172f16469b183fee97e
+Payload = 1b42cb685bd462fbd40e0273a81c767aa81cb43f17d3c0c9
+CT = 1a1b1c7130aa63098dea17ffbb2216d1d276cb10145b0762a45116736e95d823e579d73dc31dc487
+
+Count = 6
+Nonce = 8a961df9c23f6d
+Adata = 07185502bf6d275c84e3ac4f5f77c3d4b30d8e106603be84410c11849a3c18ea
+Payload = 434e182d04ecda519a6119fbaa4c45e8c9803a9a3eb51dae
+CT = 3f603939c6226d8208b2b0e675b82557609ceaeeee4032c7837ed517dbd7e6fe34ea42b01c69d370
+
+Count = 7
+Nonce = d3604d390faab3
+Adata = c95e7329d36145664da69d25f24b301d334e1bca2baa74b2d5c325ed7d04fae4
+Payload = ee104be898a225eb1da99163bbf768d8ae6d5850af6f8767
+CT = 3e6a7683d9d804f791f77d2b69996102ba82477ec4557747ef2e0b322f51abb366a1e8e37f4fe4ee
+
+Count = 8
+Nonce = db5004a1cdae8e
+Adata = 1370fc9d5bf1ad2d071be5a28b235402a85270f536b5601c221519a3b329c71a
+Payload = 59bee7d18fd4ba573f3e4f61076f5b9f6a3487e47d98c729
+CT = 6db54d6f5c3f3efa6da67aea1234d46e8b679a5c257c66d82e4ef944778281ed186b4a8099b47fff
+
+Count = 9
+Nonce = 783477f981ef05
+Adata = 04bbf2a826bdf3d55069b1936c4f8e8e08189f54066a035c950c7347604b1b65
+Payload = 6150f132b25727ebbaed9f16bd91ebce00c68e5b39bc0ef9
+CT = 36f78cef22cacaf9f3d4464821737f7fbacd79be517b4727bc5c098625c51ac7fdd15da2cc9ef4b6
+
+[Nlen = 8]
+
+Key = 0b6256bd328a4cda2510d527c0f73ed4
+
+Count = 10
+Nonce = 21fd9011d6d9484a
+Adata = 66ff35c4f86ad7755b149e14e299034763023e7384f4af8c35277d2c7e1a7de2
+Payload = 78a292662b8e05abc2d44fbefd0840795e7493028015d9f2
+CT = 5a0be834c57b59d47a4590d8d19a1206d3c06e937a9b57f74034d9fdb43c3f48932aa72177b23bf6
+
+Count = 11
+Nonce = 97f940d7c1230bd8
+Adata = 78337ddfe38be7897372b0f805603a9a9e55598452285764641c3bb7aeb54a3c
+Payload = 772aeff60eb3adf5a9589ad54dda0401cc9765589609dbd3
+CT = ef5c408dc6d0b501925a47def54d8deb9880a07a3e6380bca20a3995cf25c5a7b9477d8916adff73
+
+Count = 12
+Nonce = acfdf302ed116ac4
+Adata = fe9d9989bffae3c9e6161eb0aa9d54ee8f5051f0dcabb5a750c5478c11798ce1
+Payload = 99ffe16de323a9b65fe60305a2d062cae490ccca6d9fe9da
+CT = 1bbc2c7877d845591660636cb6ccf4edcd4c156996a26a707d0e2fe322f203c08f44d7f9bd7258c3
+
+Count = 13
+Nonce = c8d36e13b7459c47
+Adata = 3f3c3a4c26dba18f385274ac5ac3df73282686488d91bc8190b7f61071b07f62
+Payload = 316ee95430329f706348886b8ac7779e3056809e25da0a03
+CT = fd2db9611a26a3e90f4861467df60edcc595f442332b089905fdd72307c3355b19ea66d4a16ef17d
+
+Count = 14
+Nonce = 5822755a3e47c27d
+Adata = 1d72d6b371e85ca359483761704f80b3360f4d6610e6d5e490b0d509f73c3233
+Payload = af4ae8f19cf6cbd199677fe033859f56906f1979b1b5926d
+CT = d5ed6f8d5c42f4f3ea527094173b278724a2ba787e416ad759124db19ab1373a5376f46ec7095ef4
+
+Count = 15
+Nonce = 6c1c94c2e71b865b
+Adata = 298cac1e4684182786f386ef3de79c11e30b2dab7579b8ca18d0312200860403
+Payload = 6e4d992d7541e02a4aa167e56c7e47206abc25fea6c5125d
+CT = 560cd43a502a6e8b1af478a3b640a68937d1a83057110d38eaa52d69ab9790edc384b9a5d8c91dbf
+
+Count = 16
+Nonce = ce7ec65cfeda31da
+Adata = 13c1298cbf7fe6a9ab378f86d3c2207944cc2a232f9383513ceb3b202086d365
+Payload = 196c80d02b663bdd89fdaa31e329b5a8f7c596236ee8dd80
+CT = 00174dd83a7f8edc71afbe5da095160336be9184f693db3db1f45de395e021c6fb1b2991c91bd643
+
+Count = 17
+Nonce = ddb739acda6c56ec
+Adata = 7f89bbe513b9a7ebe9be3f6eb88782080593c83e8cbe47fbe15bdc3e5782090f
+Payload = e95e142217c838d1f998a52e342e4f2d80b1cfd35cf6b73d
+CT = 819d73dadaf095652cf39729b2e2cad7fc7783887a5acc15713d941b845d96a5bf65e9f80ae7f923
+
+Count = 18
+Nonce = d9bb71ad90152d5c
+Adata = 20bfcba120cdbeb07c5f4d70338ffce493822d78a03c9e80b5b934e16e39f70e
+Payload = f1fe98b50ea2f9f088f6f93910757cf744d5aabf3081966d
+CT = 36decda8ade6ab104a201c6d370412b907a559738eef59665e99761cb1ac77d772b9cce9345d9a75
+
+Count = 19
+Nonce = 2c9ec9f1f1358c50
+Adata = 96f0b1edec4ad14407dcaf30ed68942b46c48d58b2dd63af60fccd5bdd48e560
+Payload = d74badb8ad7f2c2bcdf67e497151d35a4fc2a3c4c871868a
+CT = 0e9066270da6e03cb4307c43adc71b4b596213a63fc8032085ce60506ac3bd97327904ad2e072a6a
+
+[Nlen = 9]
+
+Key = afdccc84f257cb768b7ad735edbd1990
+
+Count = 20
+Nonce = b7776aa998f4d1189b
+Adata = 9f9ac464de508b98e789243fdb32db458538f8a291ed93ddf8aeaacfbfc371aa
+Payload = 56d0942490e546798f30d3c60ad4e3e110fc04f5b1c1fa83
+CT = 96f124c74fd737819008ddef440320f4a3733d0062c83c893e259aecf12ba08f2a2e966a3341d6d4
+
+Count = 21
+Nonce = 278cf1f09b13f467fe
+Adata = af9627922758a9f7792345716782e8837ca78e8f9db16e3fe12a7124a3d4e99d
+Payload = aa9b9e80cef47b6db3816b1d665f233e696337e21bb8333a
+CT = 5eba7e3b3ecab78121b0d56acb9dbfc6756c1255b42f145d11751638ed36c1fd3c7268b71633c1cf
+
+Count = 22
+Nonce = 4ae701103c63deca5b
+Adata = 5872a1507c833c581ac2750b2b54add4b92be14e45d72db7679f8fa2b4d1eeeb
+Payload = e832b053854fbd40c0d8b6d6b8fd5de2da0c173f5fe594ef
+CT = 3b2b964c3a90d51c0ace186db79818b4d0f7b81236d36017d3635aa1d8167087600b01643b0a5ce5
+
+Count = 23
+Nonce = cfb5b12928e1c36849
+Adata = febe755bb8e4475d8d12f5e96269abd0d4e40d73cb966e2c523343e9a6d2d71a
+Payload = f46d6970dcc37d32d93ff062e68034c1906ee487fd28eefa
+CT = 0d5332a42fc583f4f81744b899cdf2a64cad1e78d577112fee6f8c4b252e10b42fbaf8c7af1e9f3e
+
+Count = 24
+Nonce = 68d5863cafc69e6ceb
+Adata = 048ba28abb191ded5449dfe9dc7d19f9b132a2a9fd779aab7da44d2887485954
+Payload = dd4438d7ba3edc73872e42dbbf78cf300fe4bf0eac9e16b6
+CT = 874d3ef7f916db2c2799b6892ef4bfbeb4729ecbf26ac4983a8639f21f8548fae45dc76de57bcee0
+
+Count = 25
+Nonce = ea09fbe5da0fa4fe91
+Adata = 63ee18eb720b21ee4c157dafcb8c7bcc6817f54d5c1b8dd7058c37228a03f8ad
+Payload = c1811d613bf0789beeef693611ef733cd173da703b66ab3c
+CT = cbe5c799952b28fadf414607a6cf8194e9f41194abace4541d3853a52971b0ab46cc0a3eded435c1
+
+Count = 26
+Nonce = 0021be18ed76b3a34c
+Adata = bb5eded483f0ae1106fd08c5e2b91cf06d3a7a73518ad4c479fb05e631ba5399
+Payload = 2d5531d1c51c6ea100b028596bf9f24dd90be14eab58f07b
+CT = 7af0449f7359b7f3e5f6c1e7bc264c7724037f4f16077fd0a2a8e3cfb827c7e6edabb34f7bbafd01
+
+Count = 27
+Nonce = 449b51ee0760179e35
+Adata = e99bdf783070a3a48431704e90277ca65a9704c12eeae2e2d70b62f816115267
+Payload = c4896d58442877c986e4f862a9f3a3179f0e9b96316a90d8
+CT = af7531c073df01077fd5c8ea9a5530c2fe1688d529e5c2f24aa8feae6a500919a336dbba1d9fb7e9
+
+Count = 28
+Nonce = 232114642e0c6b55b5
+Adata = da288d2014616f16a2abf5923dea49aded1748592adbcd97415c33ebfa57150d
+Payload = 11fd3f94b5a5ce94f2740a27a0771aeeac77f3155d2bc12c
+CT = f0c174a7927da0bb88e92917af8ae1df4ffc3527004e9e2d0b25cea7ed6e4fe9069a2ce49875230d
+
+Count = 29
+Nonce = 660cb6d654afcbdab4
+Adata = bd96c3c225099fc58cc1f97779304606b11efe9712fba13abf74fc1d7d44a900
+Payload = 793c0bc3deb6e0bec4c1d1fc17e455eb1aa5e9e25cada861
+CT = fa4b14a381ee41fec7b7279e58f0d06a3beec26d645f81336218635754d5563f2cd48bdbb267e5ca
+
+[Nlen = 10]
+
+Key = 6ccb68d3838d4ddf660b9cd904cad40f
+
+Count = 30
+Nonce = c4fb7519a19f13d9d1fc
+Adata = 092e64fef08b5655a86cdb8de63ffaa7772e8730844e9016141af8bad2216246
+Payload = 5ea35c082e2b190e9d98e6b2daad8672f587b4f2968072fc
+CT = cda5fe3d15d00150b99120c7f206b88a4c2c4a39ca9143425603ab284a73a38cc916f8b653c92ab4
+
+Count = 31
+Nonce = 45927852550961f1ae9e
+Adata = 53ae030474795ffda4d9ac0fc3c45afb592ddd761f7b5335c13a6747e21075a7
+Payload = 6c5f468077536b4c9a94ea4a6fe3cf621083a210daee45b6
+CT = 694847b6429cbc3902d9cb7049625aef1e97b569e1e3169035bb811491d142cf1b26350f8451bd14
+
+Count = 32
+Nonce = d8c54463dfcf02d0e327
+Adata = ff95c0ed0da32d1b5f57570b815a50592ecdc9c1c4e727e0f6dfd93fc10ce88d
+Payload = 7321a6de8d694ea05623206f5df438c5c2cdd6b1eccab4d8
+CT = 9cf8ef119aa5cf3d6305d50b2b520a0b10bcd240e27276749c68e8e641b0120f7dd66e8f0cfa4205
+
+Count = 33
+Nonce = f690f3a996928275050b
+Adata = 41c05fda535770699ed22cef253753b658437f833afe65c9c393581d835f0fea
+Payload = 56520a4bfd7b73a471e0446f9524a407e81c2681b7329e35
+CT = 14aa15f9f64c4c64f6e88094e012ecb24193249f044c033dda44a62f97c0fead3f65b28928bfbcc3
+
+Count = 34
+Nonce = 26eb9ef25be62148fa61
+Adata = 8f45608a07521de86ed5a84a851e629b579b51d7bf4cc7202a773e0f9e9d8748
+Payload = c68094c26c7f017b79f126dc26b3bbcb95f97535ca412da5
+CT = 7ba8a0c2fe2b230768d1c1874085ddff8926931961bc4558f0d5444466bcc631bef8e58fe5818af7
+
+Count = 35
+Nonce = fad21bc27dabafe7a4ae
+Adata = dc5d7fd97bb3243ba585fa0d71a07191667af418e30a6b76bedd05b32c673403
+Payload = c247fa8d8091cd3f299cdacba7fb7af93549e9e3160f9cf8
+CT = 3097d2ec0f8bf00b22504ab03a75e740d3e59c269c3ee3f00b5419293a67eb008aef0f9f675201df
+
+Count = 36
+Nonce = c911348848fe67406dea
+Adata = 50d50a0b5ed4d6904ec3045263af0255a6494b7a7e2e95ea806c4bb788423dc1
+Payload = d846c170ae0111348362901503b26d58f5efc17b6d296aba
+CT = 5d72562f7dfb47bf34b90ee4ea11ff9f726c915b07f4d843dec5a554f4bbecbf6943ffdab8d8a26a
+
+Count = 37
+Nonce = bb921b46a16d20ae4046
+Adata = 7d17f8f60ad1e61a168b5b0e7fbbc90cee79b612b6d6c0d7ff6ede042341e8a1
+Payload = 71bb6ae84262646c9be95e0f4289ffeab7555ec6746c6ae9
+CT = bac123320888b553666249756e6d63b3498760791cbe9e34e5b1162b7489a59a50c0f0f3618e6c2e
+
+Count = 38
+Nonce = 61a8b8cbfc9bdbadb2a3
+Adata = 51cf2a8949e13eaa087a34c9ec4d7fd92b862efd6a0b1fef8b016fa2c6933426
+Payload = 362f9a46aab59fb6213c83d791b2129b34367ac2de2048fb
+CT = b8a57e8714d8789f4ef2af29e0efec21b1ef67fdabc7cdf0ed5505f1f0ff77723771338585c456b7
+
+Count = 39
+Nonce = 6bc4cd23c32a913998a7
+Adata = 92fbc970b5e64198ce2a138de92767edff8d82f12f8832444b346d159657356b
+Payload = fa442383da234cf8f0c5fb667218bc3bea0c091b3a8e6b77
+CT = cdfe3e83aba43a9804c5a1832e0e47a9a153359cc32db907714025f485c7f40256049f16f859b859
+
+[Nlen = 11]
+
+Key = e6ab9e70a4fb51b01c2e262233e64c0d
+
+Count = 40
+Nonce = 74e689eb5af9441dd690a6
+Adata = 42f6518ee0fbe42f28e13b4bb2eb60517b37c9744394d9143393a879c3e107c7
+Payload = ba15916733550d7aa82b2f6b117cd3f54c83ddc16cd0288a
+CT = dcc151443288f35d39ed8fae6f0ce1d1eb656f4f7fd65c0b16f322ce85d7c54e71ac560fd4da9651
+
+Count = 41
+Nonce = eb118fb41284bfcb1bc338
+Adata = b5a6067fbac46578cfc8d3fe04108588c9de077eb009249374f205553bba9d02
+Payload = 863da00c7accf45418d47c1eda72338734dcc49cd599f328
+CT = d64de7a56146b971e21bf5784d67bab32dd837cfb81591da4a0177883346dc896eb39e8a32bc1393
+
+Count = 42
+Nonce = caba2716d07e95de83855e
+Adata = 0e0ff2c73ea5fa8f8726a3514cf906ce1610a1a6dc19b22682f9e4619f762d82
+Payload = 2af6d5636ab65db2058b2ba16df257369fc4e8aef8b9481c
+CT = 3c9e006c7d8eff5f448b0cc9c27c964713241aa7fed3665d775ea25fb272981de8b8aa0a637498fb
+
+Count = 43
+Nonce = 314c136999e41d137bd7ba
+Adata = 366c659bc45d0a88acd54ef7eeaa3e140e1cafb1b01474a065a9d460c5e83bfd
+Payload = 217b19ea6a431a1f66bd9d02b718e8507a08ab8e6f603e3f
+CT = 33d7b672b23e8b03a39ff3fd1e7b0f2be67163e3e3bae072f2aaa211dec623947a50b1252bc5aad3
+
+Count = 44
+Nonce = 6fe51f5013f53d4e4fd907
+Adata = ff182f2e179d790e827cbfd0bd8b9297ecae57ffcef9e25ef114474a22e4ec5b
+Payload = c6bf582b49dd4ab6cb33f3f88e8a4d14fe32b308ee3b4682
+CT = 26cd5dc5eac2acda283ca03354260ad57af79e20c5e92f5775ed171bb0fbaa6f431c5411cf9b536d
+
+Count = 45
+Nonce = 24bc8dc1e2354667b79ba4
+Adata = d0d48d01fc79685c6bee04d45e40d06cdf1f4607542b1ece556fc2d1bb2b03f1
+Payload = 90f52ebb1bd5439386faeaa194623285f750672a7baae64b
+CT = a7f43f56c50705a1a101044b954414fdfbe32b518e934d38f391749ea3acd624c01e4583ab1506b7
+
+Count = 46
+Nonce = 89ce46b3de3afaf2518d41
+Adata = 5767202c913584d653f37d926a0c5ac1c67db3efd1dc58fbff998778a6856254
+Payload = b2ab379a0dd15baf91415eee3a4e56e7eca54d4c1c3094f8
+CT = 9f530e455a54b86835eacd8801b34c884a3b2ac819ba38f894e43a6b1cf73cb2d6a1dd8331549520
+
+Count = 47
+Nonce = d3208eb695e84c7a925037
+Adata = 91d8fa65a6885f162a795afe2898f391990a8b3a87c11f94734dcbddf5f58da8
+Payload = f15e39f0e4eaa5bf81359d8e30186522f1a1a415436668cf
+CT = 7f1d9fcd9e5cce3a81e3495bfecec817fd7180d8bbfe0abab27fb6425fcc3537ce471425a5b17dcf
+
+Count = 48
+Nonce = 067de2869333ed22c7b63e
+Adata = c31e441fd551b3fdfbe23ceec5ec1f838f31a5300f6055ad2a936a9d0c1c856e
+Payload = 1536d9c9a09302d142c85638202f5bbf0c287f68115d51d8
+CT = b1a5c7a7fd23228dc7ea26885802daa0719f6a23681e1d65dfb879c21b46f3307ef22f1da579303f
+
+Count = 49
+Nonce = 15f61b4526d19bceae1093
+Adata = b97b122af73e928e617e98684f845be4cb80566345739b7a884c6a3eec5102bf
+Payload = 37c81988c07a5b01e2b40ff9f9ada5f50ca764efb717ff9e
+CT = 0d93a5c77482d573b7f1b8c5e283f2571efc9f54216a4c01900504a73c8817ff2b55618b2602bf38
+
+[Nlen = 12]
+
+Key = 005e8f4d8e0cbf4e1ceeb5d87a275848
+
+Count = 50
+Nonce = 0ec3ac452b547b9062aac8fa
+Adata = 2f1821aa57e5278ffd33c17d46615b77363149dbc98470413f6543a6b749f2ca
+Payload = b6f345204526439daf84998f380dcfb4b4167c959c04ff65
+CT = 9575e16f35da3c88a19c26a7b762044f4d7bbbafeff05d754829e2a7752fa3a14890972884b511d8
+
+Count = 51
+Nonce = 472711261a9262bef077c0b7
+Adata = 17c87889a2652636bcf712d111c86b9d68d64d18d531928030a5ec97c59931a4
+Payload = 9d63df773b3799e361c5328d44bbb12f4154747ecf7cc667
+CT = 53323b82d7a754d82cebf0d4bc930ef06d11e162c5c027c4715a641834bbb75bb6572ca5a45c3183
+
+Count = 52
+Nonce = 6a7b80b6738ff0a23ad58fb2
+Adata = 26c12e5cdfe225a5be56d7a8aaf9fd4eb327d2f29c2ebc7396022f884f33ce54
+Payload = ba1978d58492c7f827cafef87d00f1a137f3f05a2dedb14d
+CT = aa1d9eacabdcdd0f54681653ac44042a3dd47e338d15604e86a0e926daf21d17b359253d0d5d5d00
+
+Count = 53
+Nonce = d8e133e7ff8e0a0ec6c4096e
+Adata = ef9e432c15d8c93a4b5c0666608e61c824cd466d7940d642acd3dc33057c0395
+Payload = 2836de99c0f641cd55e89f5af76638947b8227377ef88bfb
+CT = 5edb056d85dafeaaf74bdf4caa47339d6a75bf1ee998565e9f9cdf6ab825f6e026f5be2ad895033e
+
+Count = 54
+Nonce = 2fa8120398d1a946f391367c
+Adata = 377cd407ad28dc02bd3835a31d92f8295c9dbe597f56662ceda112c588dc73a5
+Payload = 7a37255b682766a0bfecf78e5162528885a339174c2a4932
+CT = 701f5f506fc7e9ea4a27a4db5cb890f7be3b4f6bcb20f97ed3021f6ad620648b8196ab1693710398
+
+Count = 55
+Nonce = 8d638ef43f56dece910139e9
+Adata = 87ea7b095388de70ac0ed23e86f502400910028a8ab5e3bbb91d05821c0d2d61
+Payload = 7370d9b453936955b9c9d336f4b283237986232de007bf41
+CT = be2f03f6ce1731418a5f53b6f6e467b73992a0c8102d8ffc2d236162688096d80b8733d2afbcd244
+
+Count = 56
+Nonce = f479ea8812b6b2f6ac78fe9d
+Adata = 20c2b8f5d3a65a66ba8a25e2ee339a779a32d45f5db91077efae6cf308feef50
+Payload = 59ff9f7581a781808d36fed378080963f35c00ea5a6e3932
+CT = d127c956349c16e2186f55b72254c677f03c61f1c4ada9e661bb9415b32d6a58f5f7647ed41de685
+
+Count = 57
+Nonce = 423515f7bd592d6a7a240866
+Adata = 19eef6f798fc68086aad1cda6d7976cdcfe6b8af74598032972c939db300d8c1
+Payload = 3c379f90b11c622a765756a15efc8fc3ca7b08b3281945f5
+CT = 15792e01fc17f5294c3405484291082c00a8f46dd9af8ca230ba95c4058501234a1b97543c998e9d
+
+Count = 58
+Nonce = c3f3da69e13c5733039744b1
+Adata = eedf00aab5edefdd6549d37ed44358e11c588c24f141dc5731303fe0bd56b11e
+Payload = 9db6fe9adb8c0fee87cac9a7f01a7ed8a84f0512d09b1834
+CT = 9b6b829ca1dc4e90d4402188632ea3377cbec2ba60f0f072afca1b08b6dd589a17a32d49b6f7135b
+
+Count = 59
+Nonce = 0a57d59f21ead5b6d80cd2ce
+Adata = de5f2d413c98c6ea2a5640a7b1c424aebe75cbc78b06710b5bff8bec6afb5a76
+Payload = 0b5f6389f7c20f4ba326e8f05d373ca27b7ebe59e6d729f0
+CT = 0b704e14bc7d2977d89e0b2e7ed7fe3c9e0f2ea80d2d6165f344f2f1b2218d9b4283fe640a6d315b
+
+[Nlen = 13]
+
+Key = ac87fef3b76e725d66d905625a387e82
+
+Count = 60
+Nonce = 61bf06b9fa5a450d094f3ddcb5
+Adata = 0245484bcd987787fe97fda6c8ffb6e7058d7b8f7064f27514afaac4048767fd
+Payload = 959403e0771c21a416bd03f3898390e90d0a0899f69f9552
+CT = cabf8aa613d5357aa3e70173d43f1f202b628a61d18e8b572eb66bb8213a515aa61e5f0945cd57f4
+
+Count = 61
+Nonce = 2a27257bfaadf23a87df082c57
+Adata = 0001dc666c9daf3560daeaf514270db0b5075d295068e6caf231c1de0e1a9300
+Payload = 6cbbfa6d736fbcc4cf73ab4d7be537420e0e574ee1f2d1b5
+CT = 72d525e6bb312bf2c20b91f41108779789c25720797ebffa4cd9d735f51430275387c565cf1a69bc
+
+Count = 62
+Nonce = b94ac8ed14895c80a91fda8367
+Adata = e1eaf35fb266f243a3fa407cd41815ae6432ad79877bfa59d8f196cbf19bfbb2
+Payload = e6ec561496ce18d96b26d594a47ffad02d68ef25d2d2edb9
+CT = c63500445239bbdf71a8dfe3f8c01061d659cfeb038b825dc89fb5f507f5aeefaa9365f0b18dcb3c
+
+Count = 63
+Nonce = bbae10aa491ac9c668a3ba8d7a
+Adata = 981fc31e64fbad244ba1ef0303ba1e4beef5bacca74f60ffdb9142a25a1ad5a3
+Payload = b9bec3e2adc83620772048d6cbfb6f78e4fad74d754ffbbb
+CT = 9c629c375f014e162895cfc25a972c29839f97407e7c7cca83d0a61d453d596fbc5c2e315d9780bf
+
+Count = 64
+Nonce = e0b10e78e9fb41ee970143e9e3
+Adata = 399b71ecb41f4590abda79045cdf6495f27daaa559c1b34f513b5c4ac105ec10
+Payload = 4b81804d777a59b6a107cf3c99c9d1a35bd8e4ed36596789
+CT = 867799b30558697d6efb4afcfe458cfad8da21139a0b43128e8f8e13b7896b244d0c9aa52ed31a95
+
+Count = 65
+Nonce = 17b61109f5e37754e4e92a28d7
+Adata = 0bc2fdd890c19882640f8d4188b88b9db99cc1934cc3e98a5df08589287968a6
+Payload = 347c1eb4aff917bc0012f005e74caadc93f4f18f2b614ece
+CT = ee19f3120991b67b2389e6f36543d99590f2e6d785c9c8ecc40eb85585cc3b7520a940a4e993327d
+
+Count = 66
+Nonce = db3ca9e80ab761804349379961
+Adata = ce01369d08d37dcda2c899c9fc0d11ccf94a0051b2816a1d6c3ad07fc8dd02d7
+Payload = f0e1af1276d2918be91a191814660bfe735463d3983de1ed
+CT = 0f1b1228729b181772d7cf55ad257fbcb19cd46f7b31a885401358c7b44aea27617b429583103a1a
+
+Count = 67
+Nonce = 1f57959cecbd377374477e33b3
+Adata = de1c7c83ac61e1f99ae99b198f4af5d24f8de60ea98fe637f3a801fab38b2a4b
+Payload = 42a42b84df098ceb43519c4cb86c14c2fafca39346159e13
+CT = 12425453de653d0fe8103013fde1ebf4a8fe18f76f0c9d60e93525fe8048c3b2147a149f12eaecd3
+
+Count = 68
+Nonce = c9db03e2efbab713b0b6404210
+Adata = a2969243b0955402ab45a430fef2ef9e0c025006732bf8e592e3d3884918696a
+Payload = d633a5a3defdde6a68f959ef39a91c6ea6e13ef1a7859d2c
+CT = 5cdc183c32b4c1878eb83e8473a17c55c88e2ad6b944ab1f64ddee42614aa737231207636c114575
+
+Count = 69
+Nonce = 89ed296a3ac03fbfb71422b921
+Adata = 1ffbe1aff0a1e7fa3e68be31a74612a1519b59397e7007ef61fc015f316d55b5
+Payload = bff42516e30c92ed46710013c656600406a48a84c1fa32ce
+CT = e08c1ab4ae7edb5184c30ffb3e74689ea855f50b0e890392f26b130720f75c422fdf66fb174383b5
diff --git a/lib/crypto/test/crypto_SUITE_data/VNT192.rsp b/lib/crypto/test/crypto_SUITE_data/VNT192.rsp
new file mode 100644
index 0000000000..06e9ff5655
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/VNT192.rsp
@@ -0,0 +1,456 @@
+# CAVS 11.0
+# "CCM-VNT" information
+# AES Keylen: 192
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Plen = 24
+Tlen = 16
+
+[Nlen = 7]
+
+Key = ceb009aea4454451feadf0e6b36f45555dd04723baa448e8
+
+Count = 0
+Nonce = 764043c49460b7
+Adata = 6e80dd7f1badf3a1c9ab25c75f10bde78c23fa0eb8f9aaa53adefbf4cbf78fe4
+Payload = c8d275f919e17d7fe69c2a1f58939dfe4d403791b5df1310
+CT = 8a0f3d8229e48e7487fd95a28ad392c80b3681d4fbc7bbfd2dd6ef1c45d4ccb723dc074414db506d
+
+Count = 1
+Nonce = 026a0b8b17be95
+Adata = 44caa8ecfaf38e5e773cb0366e1b04aa0b9fac5c34a362310f471960c4a1e1c9
+Payload = 0e52a384cedcdf7f179348de6e7336aa86f8855fbd903cfa
+CT = 3417044bad5fddd9455579123dda4fd342c273a57ff6333dfedf191496d88cbe17c6271b65096e66
+
+Count = 2
+Nonce = ea09fbe5da0fa4
+Adata = 1d9799f2bb0f7ab57fe3de27949ff64066131c81bfee172b308f9bb0b3171067
+Payload = 469ff9698cfc96b581d7115c822e4363d7355ec5daed2eae
+CT = 1dae7cc16f1b469290902cfad47b959784b4d6f48a79e690d47e30b635d10d1663477d61d7ffb55d
+
+Count = 3
+Nonce = 8d27bcbf9ebfd3
+Adata = a7070b85b7add9193c9dcd2e6c03f6e7ecc52ffe9e099866baf7472f20c03aab
+Payload = 225651d072dc9d93762dd79691ac2b6ddba00ec1252d69eb
+CT = 5da819adefbf794612eb458519debcd524c283763eb3d7252eca8766bdf0db6bb2dcc793e1749c21
+
+Count = 4
+Nonce = 13f560187b6077
+Adata = c4ab4244db75f8256e55c5b613a07b11c963c3cc24f66128aad4ba8b7ca99331
+Payload = a38231af405dc7b70c8dbc8cb84e6be8a0dc2e95fddc2ce8
+CT = 3aedcf8347aa23fd3325ce08b6b00462536baed69968a753feab6761c55431bb5668e1f5b7505e89
+
+Count = 5
+Nonce = 61e0e28bf344a9
+Adata = 5f998952de70449ad46428f2ff8a01c5af43c0107a1bcc6930f19d4112598666
+Payload = db21b37e875d7709a02239ce6ea529cf37255d5b617c153d
+CT = b8f5fed39c723d7643d6dcf2efd3bbd1ba0da1ec901305fd64b2302ace4f66216ca8b4d776197692
+
+Count = 6
+Nonce = f6be4aad63d33a
+Adata = 18339be863fb8a887d04ae9ff3b4a7db095075cd5d113a9ec87b41fe85ea405e
+Payload = e53101e6eabcda32c13d7b1dd1d88e7c2ca3ddc2064f64c6
+CT = b758858ab60e1630a0883d4d330119a593729a3015c42525effb985b9c2dd9ec954bd25d9c464c67
+
+Count = 7
+Nonce = 2c1c59aa0d8eff
+Adata = d44af86b89fda8448a9b2fcae20ea156dd8738c8251699c02b785811c830bf72
+Payload = 1fd7188a43dee7b059420e8634d71d2c0658f6d0d308dc73
+CT = d046f845a67800a5a58f461e5a8641e8fc9b4c53b32e61d172adafffbacb297d67f6b5c02b982e04
+
+Count = 8
+Nonce = 48e4598edd191e
+Adata = 61588bdc980ea2310e87dec4c651e9a55c27e3858b6505cbf3bf85e51931badc
+Payload = c25868f390af5e59c035cb5830e018c62c5b96bd35b764f1
+CT = 0ece161bd77b7f969b3b20c818769a98c178d84524544664500ff4cfe66ade1832babc019778acc3
+
+Count = 9
+Nonce = 6d576ce3c5fcb5
+Adata = 92c598cb5ca2926c11f67c3b3cf25493d77606fa60d7290430e0e975091644a6
+Payload = bcd97479db934357a163a9e5f5a85999ca987f8243d8017b
+CT = bee185e11b3d42bac846b9d92c70a078aebfa630ab763840391031b3a22b2adeb9791ee35765c8cc
+
+[Nlen = 8]
+
+Key = 1dd56442fa09a42890b1b4274b950770ea8beea2e048193d
+
+Count = 10
+Nonce = ad749d596d88a4b4
+Adata = c67219909828adef64422286008e1e306867a1c0b3da95444507a68b45c953e4
+Payload = bd92d6744cde446fc8621625658fc4bc00dcb97f06195ad7
+CT = 076cffd0ca978fe2bad411ced45a090abafb22a99896f6a75a1969276aa2b0cdb37ccaf2845dbf6e
+
+Count = 11
+Nonce = b1dc81d116d94f5e
+Adata = aa4b71906b6642f10f66c2391ec157c7cde97eb322db10045af4c5248807f691
+Payload = 9aa6dbe1cd3eb98d330c937d31ef93bee8938b6c5cfd38de
+CT = 720f6876ac91665f20147483f0655fdbe21963a01e36f1daa67e36d7cc8d54cfec0762514475127b
+
+Count = 12
+Nonce = e758738df5c89af3
+Adata = 5715fa238f432c926e62dd93708d0e3145428e0ed45e1efa8148d2c4ab6cba50
+Payload = ce80b99039a16e69018d1e3c239dd1bf06e94a78b0b1df37
+CT = acdf7ba3edca1563727ed85cabf085c2f0c8f27556c3c064ef50d85bc3ade6a773d956b2660ac367
+
+Count = 13
+Nonce = d586c4c67d535476
+Adata = 1e8dc63c6c54a540b6b02067ba7c719221cf289fa3897299722c9a2bd6eed05b
+Payload = 2f88305117f9a5d807d54b7e95ecfeb7327e52d9acac352f
+CT = e42b86e619be1a38973c934babeb4688243a9012c85d643d81e024aaf0a62b353f9bed36681288d2
+
+Count = 14
+Nonce = 77e83758f68d272b
+Adata = 25c80edef3d5bd8b049fa731215b80ca2ee9ee6fb051326e8c6d0b9e11e3d7ef
+Payload = 92e47b82b728d639777d5d5843de2a5c364956cb4b21cabd
+CT = 1b9177f5b76403cb8c690b39c3dd22b55da35cebccb9b64e05fe32f796f0b4a75a459fce6c7d740c
+
+Count = 15
+Nonce = 311dc245549206cd
+Adata = 87767f13bb4904d0df0d64eb22c9ddb65e81b5739baad86ad5e2c239ffde9f6c
+Payload = 8691c0301a216a5f3ed9123886d100309bd85630d6b845f5
+CT = f39fe3620a03b37a4bf457909e0770447b498ad2a2f0f9d7b75f9e4239e43bbf93066897e60f6fbe
+
+Count = 16
+Nonce = 2a17b70f10e120c0
+Adata = 981fc31e64fbad244ba1ef0303ba1e4beef5bacca74f60ffdb9142a25a1ad5a3
+Payload = b9bec3e2adc83620772048d6cbfb6f78e4fad74d754ffbbb
+CT = 92187955ee1ae702ef01a385537119b2bd4545402e8b2384a0c069a2439a2d8843302c6a9999e658
+
+Count = 17
+Nonce = e0b10e78e9fb41ee
+Adata = 9d072b8a3f1a496b2be6728a38b94a4f44c9be40c8793b69afd81d01696a6b4a
+Payload = cea28e7cd0eff0c5eafeec908d4aa8ba303e72ada33db087
+CT = c605e48f2e66e8e0a92471e466981ae5e31db3e4ad80b09f5005b06d15f63f2f015cfe447828da09
+
+Count = 18
+Nonce = 02d72dde23f9772c
+Adata = 2dc44c39940e2d9c94d2dbe40bbf5cca5efb4d4b250a31aa24f208b87e9c2453
+Payload = 809343e986f6ff47f54d4cac22ed39babd12271d4c7edb58
+CT = 0bb59581f22f6b15de76c0066645495a5c19e44381c349263ed92ebb789c314a89c83542b15ed694
+
+Count = 19
+Nonce = 28c4d6de3e2ce51b
+Adata = 913a8eda924589d3206ce0a951fef93668c6c0c454824b217997bff6b3026d54
+Payload = a19f65ffdafd6ad5ee43570f7e168f94a8b4a7b7402ac80b
+CT = f0c91a29f1222b906550ef5c7c0944c5c4236cb6c31122cfada8e796f2ce7f9449f42de504873868
+
+[Nlen = 9]
+
+Key = 8cc622645065c72d0d2aca75802cf1bbbd81096721627c08
+
+Count = 20
+Nonce = cd84acbe9abb6a990a
+Adata = 447b6f36acdad2d1cfd6e9a92f4055ad90142e61f4a19927caea9dbe634d3208
+Payload = 597b3614ff9cd567afd1aad4e5f52cc3fa4ca32b9b213c55
+CT = 2d7fb83e6621eed9073e0386d032c6941bef37b2cf36a4c6c5e36222d17c6fb0631c3f560a3ce4a4
+
+Count = 21
+Nonce = 1fc7a43ed124745d04
+Adata = c892b095173076a40e24522297be27fd3a765c8d417f24c71a9f03b3fe3d8e20
+Payload = 415cd8312dd20a1c26f4b90d98104cdfbe06739466fc0aa5
+CT = 7bebd6f55f15ae57ab73f92f7be6ff37ddd99740e988f01a7a2a13c22df4a156e6d6063235452c85
+
+Count = 22
+Nonce = 19ff5e7c1f2c594abc
+Adata = effcea4e4dbc57410426b39fcf51c9daecd9d310888590d77827973a29c4ebff
+Payload = 97fd2c259a4e672e9555a9a5b98f4c0ec8c4c49c7ade26a4
+CT = a460674c2f358762e97dfc958d90973e1e419dbc6a832e987579b2c4a6bcf0356f48cf8959cfa54a
+
+Count = 23
+Nonce = 64d9bd368ac2357cf2
+Adata = 62c5a16f946b4312517f67c80afe2614c822e3a01b87dc81538c00bbf3fc0108
+Payload = b6ada12f7a28211e9d2c07cbb3d39fa77aadc077b34c46f9
+CT = 8fb5e0954388b9b58519482962487e9b0768f0cee08afe9a92be2b06a0ecd2d00877abded7d9634c
+
+Count = 24
+Nonce = b4aaf2cd93efc0ce93
+Adata = 79d8841ab83279724ce35e1a8abd4e158168dcf388ab4c3d1ae70413e4e43d14
+Payload = dd42449da4c95e858b796085b6b5b3b5eef484dbf3c2bc8b
+CT = 893f86e29972928c1f3c3e25c73947c8d677814bca7fff2cf8d301ceace678f9bf91fc361dff5812
+
+Count = 25
+Nonce = 132f3e19e12f462a74
+Adata = 176cc5a280f6171d00e247edacc81f05c1b9faa87fc831163ac9d76aae59a6c3
+Payload = 8ea05a5033ab8b009664fa2800c24e217488ce6888cad147
+CT = 4771d210ea678dbfab96e320e9c44b68f47cb05b01826ccf42ca4f4ccf986eb6a6b85b99db2fcd93
+
+Count = 26
+Nonce = de709ba64cb75704c0
+Adata = 0cf8e9ab95766b6fa85e88d86e4f349a17c0d90509939e343eede988e7462255
+Payload = 51dd9fda9549f25dd868245a6a54b8d59346d2f336adf9af
+CT = fccc3e44afa6bd2fbcfc5c834db63dc9d152c04c0dc0b43d393162252ae91ca46fb8e8338cbeb75d
+
+Count = 27
+Nonce = b11b4c1b7a26387265
+Adata = 14ed867cc909c0619f366918a7d5ae25279fb137e1dee7fd98ddbe3bd19d841d
+Payload = e35ea4a16e274fcab457fd4dc7886c3d81fc668c19e0f374
+CT = dcca8aa2eab8ac3f5db9cd9560ae0758d7df40d7d868d1f71f498ea6ec8251a6d149c7ca38b25fe4
+
+Count = 28
+Nonce = 20d03227a7fcaef1ce
+Adata = c5c15245e641687d0ca9e913406acd2de3f21fbaf2dc5e4e8963222da61d02a6
+Payload = 6775e5faffd0b13e78da70a789042245d5ef31eab5245380
+CT = 4bb8ed2207f36f40f62d3a2c90f8e3bd8f589059b69037118ce3ab864545ea81943ef0ea9489d223
+
+Count = 29
+Nonce = 267f76b9ec0f5e7c6f
+Adata = 2b421be47d07dcb12a0706f7490d05024fce8f433079e18ec78f4c8678f5f155
+Payload = 9330bb23428ab45f573923e977db74882282cbe1371da68e
+CT = c6ae24f82ac5cf9c18a2d98e610027eb2566a1ccfcf99945655e14c7bc8be97ea47388cb7b18bcf0
+
+[Nlen = 10]
+
+Key = ab72eef2aba30205c986e2052d6e2c67881d24ae5fceaa8f
+
+Count = 30
+Nonce = d7a46e726ed43f1580eb
+Adata = baa86f14271b2be7dbb37ddc7c95ce4857e57aa94624d594d7bd6ceeaada8d5f
+Payload = 2a794b84fc9e4a7e6d70a82b5141fd132177a86b4e8fc13a
+CT = 2d7f76464417613bb61d3657481346b74fc9d6abc6a3babd39365dce86859cd82395d11bfc8cf188
+
+Count = 31
+Nonce = d0afcbc1b2524a4a4553
+Adata = 7c267223047af946b06f6a45ffde4a5ec49c28b81ca22da4a36bf523e89e9da8
+Payload = bfc5ce1316ccdbcd8ac62484e7656c87947ff98cbba8e1e9
+CT = 4772c121367d0e8d3edade883342395f3ea065fe7dd7be8c8355b915ca2633fd557ca7ed41e00926
+
+Count = 32
+Nonce = 6eecffd227e8d5349523
+Adata = df7736560b1a13aa8e536500ea6cdb9a6757309aadf25a6a9189055a309c3f8b
+Payload = 19eef017100dc82f26ed0815c55c122e0b1587302894c391
+CT = e2864c6e12ac089daaa1e94af4b2ed04060d7ef65d2f72f0e7d017514d498f1f3c07d650afde8293
+
+Count = 33
+Nonce = a67c0675753f725a8fd4
+Adata = 7dd546397a9a0129861fb6815d419a307f90d259d55f3503961754126cd1b776
+Payload = 80f1f1ea46c92d28f2d60eab39ce056a4aefe63fa688538e
+CT = 882c687c03eaaad9d7f591649e736f0c1c78f95e40d40cd77499a8544bc2a8fe95f55fefc7316f8d
+
+Count = 34
+Nonce = eb83928f0d5f7aa3a74f
+Adata = 060cd3e4aecdb03837dfa9f544318c0a16cdc37fa2a3135be7888ac67e7eb26b
+Payload = 81e9174e9472777b6b184707108c01d6ea6b5d108ec3c6c8
+CT = 243cfa0a0a36a4c20333968910e6f52acc04c6f74e704180623f3a13fc13db958cbac49f7421d6af
+
+Count = 35
+Nonce = 5757abe01f7a1183fdcf
+Adata = 744629263041f0eccfce4a1ebcc18c4c984010f9241d35966263a8b2f72ee26b
+Payload = 991049f26b529af8b0bee0cc83989cf817d248254182f332
+CT = b20469b5f33f0996e8de869ad10ce09924a0bdd7b67a89a09c447a3132fbe5213133650000d50b06
+
+Count = 36
+Nonce = d9adfc5b44ad7aa94b05
+Adata = aa6a5448c6ec87be75eca35725ad2e902dbccf840d25b2bdf7e62e4a8fa4a511
+Payload = 14682301a99bf680805d1ffe62e1506d48cee8c51ef1d255
+CT = 9b44efa185b0c10325bb4c3c0815e6a6e46eea366b9a416b5ae554cb440eadd875657fd5cecc214a
+
+Count = 37
+Nonce = dc3ca30782c9c0a7fe89
+Adata = e788c98ae85b11b3ae884eed6f3b8f5bcf5ab1b7b20ad3f44f760b2287cc5793
+Payload = f9cb86f24536931a1b095b426a07e4621c000cf09b472bf8
+CT = 463f9124d1cc387a0f8b971d1e2da448f0efffc3956ebb2af8312986315522081f0989838ef0429b
+
+Count = 38
+Nonce = 9523f53f92b6e4ba86e5
+Adata = c3b123ccc916d26a2e6a8b5e30041ad69a944217e9b402b7acc0170c31e8c2e4
+Payload = b9bdcac80f64175836ab51bb1a1bee5ffe3a6b9b71afe3ef
+CT = c356b5a78cebd123808fb740754dc47a8ec7c9448bfacf39768e94f062e86129cc9210dfcd3e6128
+
+Count = 39
+Nonce = 16bdf18c09d60f3a2a32
+Adata = eedd0796f23612749e9fd282c864f3118d0683409d3bef1fda352e1422273c7e
+Payload = cc96133e473d197be1bafdfc1a21d58e57d0d89b2ba1c3ff
+CT = f9d78e9e3a41b3bcbfe756385a3715776eb84bb7d8d15432978757883f07802b25e9a5b15c43b451
+
+[Nlen = 11]
+
+Key = af84c6f302c59aeee6d5728ed5da2e3c64a5a781c52c4d1b
+
+Count = 40
+Nonce = df990c42a268950677c433
+Adata = a6ab5d78427f297a4b7e21f1091ff3a5b20caa3fe1cbcb09459d9df596a6c8e1
+Payload = 6db41aeb5f7c24df8929dbc30483b3c7934b3bd1cdce5bb9
+CT = 8c9328258bf71970d33e23a3ff81cc1c9cbe196a1294264bfd6a7255e4801963bb30a63de3fc5b82
+
+Count = 41
+Nonce = b7ea72641bbe2dca6d85e7
+Adata = 4e0f2ddf183281ec131693bdcea3fc9743733c07a486a42d5737735b3f6e3fdf
+Payload = 726844e41b1e4d883024b32fee0dcea38c889cb328885b7c
+CT = 9a133e4582c2ebc445862a9c6f2f4e39223c84081e322c8f262de30da6ef505fe640c53d765f672c
+
+Count = 42
+Nonce = 446fee1e75e79c0dfc9ddc
+Adata = 42b598eaee271e06d9e98dd94152b28ef10f506d65bd660b2fb8b1be9a2d7254
+Payload = 0cdcf348ecc9c3588001802c2106fb64be9c301adcc66e73
+CT = 0c2657b0482b6ca92e1b1c8fdf75eae3b0cd3af205e9bca396ecb1e46beb16000d585e1d9559ee22
+
+Count = 43
+Nonce = 2e6e34070caf1b8820ed39
+Adata = 8bd1ef3a1831fcc8919d736fb23111ca3ef4cccaf20264fab8eb3b071e56667f
+Payload = ca0860cc1e96506c2beb25b53d2947fbab634f0372afc8ba
+CT = 19e4774030e43e6853ab5bf176ba9c4b59f29f285977e3c15198cbe3e34c884c3f56a732974aa1d6
+
+Count = 44
+Nonce = 428542ecfb94a745980aa6
+Adata = 8efe01716b9018084e2ea7616f85b7333d945c0c970f8cdd400130b98db67cda
+Payload = bc6b59120ba2845b0e41f65a55e2ef1c45a81485c926c14c
+CT = cb48b0af6fad251d409d14ce0fbfae9cd9c40bf4a0c1e2b7e7cec415030997e1ac5db974b617b5a7
+
+Count = 45
+Nonce = eff703e6d72ddd23ff52d9
+Adata = d7fc74035e66709d2590b7bb3276245dd43824c9896fbd801ec1d07018b39b6b
+Payload = 1a5432e8085511ddac1be91be3e2945f85f0cdcc3a1c9f8d
+CT = c0a00cbaec65b7ca525fb26e80ee0cd18c7ef47c39c704833e59bfecf263bfdb24686627fd95e120
+
+Count = 46
+Nonce = 6a652ce21334a40a259dcf
+Adata = 5d24d80f22afe713c4076c200c1bab36917907fde7b6d34e141066f543526db6
+Payload = eb8f1988cb405041bf48d138ad41da7ef364d4ac59a9e324
+CT = d4f23166c09a15466c7e0e2b30627ee5a84f22d7e6135b4a0652b67d559a84b4a915ca6a420fd300
+
+Count = 47
+Nonce = 9382e12d447c0ca23cc9c3
+Adata = 239129eb760f8a770410c160e4e13a6b9497077c3e463b65397393fcd3cb5c70
+Payload = b40e80564263c7f450c53ef84df67247d72e8a04dbb284bc
+CT = 6de2ba26caa80874814816154784912c55e3d6da83488e7250f5a52f82211542b4e2661cf870c80c
+
+Count = 48
+Nonce = 2c3a4148cbb02504a2483f
+Adata = 33c3bdbf185b580353de79e51e675b03b31e195f19ba1f063d44def0441dc528
+Payload = 60a31736d99c3dcf25b349f6110e1c152b93506e85a01e67
+CT = 4d5e705d08f3ed1ca6f1caa74b46e4b1eee18a0783686f207de16aaa41d06bc071657dacf14da754
+
+Count = 49
+Nonce = 691cdf6fe9ecc2154d0101
+Adata = dc096596644c4e09c44078b86e5e0887c45094042eb0d74a6a13aa2524463076
+Payload = 77e6441ee017a93dd876ff2c7980540c77ee15edb0f23933
+CT = 24cecc81c8ac7ca9906372dc5263f2220b4dd162f1e08283f07f23e65475a20fd96e45c6c695cd83
+
+[Nlen = 12]
+
+Key = d49b255aed8be1c02eb6d8ae2bac6dcd7901f1f61df3bbf5
+
+Count = 50
+Nonce = 1af29e721c98e81fb6286370
+Adata = 64f8a0eee5487a4958a489ed35f1327e2096542c1bdb2134fb942ca91804c274
+Payload = 062eafb0cd09d26e65108c0f56fcc7a305f31c34e0f3a24c
+CT = 721344e2fd05d2ee50713531052d75e4071103ab0436f65f0af2a663da51bac626c9f4128ba5ec0b
+
+Count = 51
+Nonce = ca650ed993c4010c1b0bd1f2
+Adata = 4efbd225553b541c3f53cabe8a1ac03845b0e846c8616b3ea2cc7d50d344340c
+Payload = fc375d984fa13af4a5a7516f3434365cd9473cd316e8964c
+CT = 5b300c718d5a64f537f6cbb4d212d0f903b547ab4b21af56ef7662525021c5777c2d74ea239a4c44
+
+Count = 52
+Nonce = 318adeb8d8df47878ca59117
+Adata = feccf08d8c3a9be9a2c0f93f888e486b0076e2e9e2fd068c04b2db735cbeb23a
+Payload = 610a52216f47a544ec562117e0741e5f8b2e02bc9bc9122e
+CT = 83f14f6ba09a6e6b50f0d94d7d79376561f891f9a6162d0f8925c37cc35c1c8530b0be4817814a8e
+
+Count = 53
+Nonce = b4cadb5f9cb66415c3a3b714
+Adata = c4384069e09a3d4de2c94e7e6055d8a00394e268398d6ea32914097aec37a1f4
+Payload = 22bade59214fa4b933cb5e3dc5f096e239af4c2f44f582b0
+CT = 2296e3f8a2245224d274f1b90ed1287cbeeb464c70a89ee475ecb546efb8872a3f8b0281b3901752
+
+Count = 54
+Nonce = 72e6cebdaf88205c4e744286
+Adata = feaf010f462ad40a38eefb788b648e1cc292cd4bb08ebeff3c39182862296042
+Payload = 30655a6b5a5965db992e7248d24141055e988d726abb8e72
+CT = 69b27f2bbaa61c4f24e1c25e0779147fef79ec1582486b4651cffa571570618e2ada3376bd9f3e5f
+
+Count = 55
+Nonce = d8030fb31eca2c43f3f5eb88
+Adata = 66704365ddd0145febeb33f68b228a3f09e1e5a4b68149e6e06d886301841295
+Payload = 9d014a02507a6f266bd1ace21b55ab8b73983ff503bb9adb
+CT = 233a883650538ab8c0da30b90527f880fcad5b16bd435e762beeeea7a638c717e63764b3a5118a0c
+
+Count = 56
+Nonce = 58038cc35ad3dcd75195e125
+Adata = 3da7a757e942409a3b39ccdc0669ce6401f7e133c07c4c42e366d70a8e9bdd49
+Payload = eccfd817fa5e3a0146967fae13fc2471ee3944cee37969f4
+CT = 415a36872a04f5b4b5372f63394ab9fb353e0eb9b430450133a87fa29e5fbfa9bc0430b0cac00b7e
+
+Count = 57
+Nonce = acd82ae31bfcabd90af5af45
+Adata = ce22126f01bde16249c47102b4da68ad3edebcd4a16c24a16ea7ccdd5d364d10
+Payload = 9d2126d34963d3ba12cd841bd321036cb82cfb78f2a6535f
+CT = 88a5b889e6fd74fc15336e23374b430988416c7e6b6e7248b336cbbeb64fbebf2e7076a98ecf5bbe
+
+Count = 58
+Nonce = d24457d567fd0a65fdabf219
+Adata = 0091d39f3478d2c59bf874b96db9ce0f7e8b85a9b805e07dc96b219819d51663
+Payload = 6da3ac85505e93c4f391ea367a9e15fa9b388ef7ae2693c1
+CT = 7039a8a49cfa6402b4ba3b840e69200c13ac4a3eb1c709a30ea909047af4998c660afbaf346ed65b
+
+Count = 59
+Nonce = 50c59ca54eb64575b82b13c6
+Adata = 5e4e42cbf172853c351d597c7d6d38b1a9cbb7ac92c00863a80ac4a2d9f0e7fd
+Payload = 25b2ba0a937b71f3ee68e7172cf2c4524b662efcd08ce2b3
+CT = e95fc44287ce39c5ad6b91c88582563fa68a9e304094deb8b193dd767f17783f0b51ac0fb7323301
+
+[Nlen = 13]
+
+Key = 36ad1e3fb630d1b1fbccfd685f44edd8984427b78deae7a9
+
+Count = 60
+Nonce = 3af625df8be9d7685a842f260e
+Adata = 308443033ecd4a814475672b814b7c6d813d0ec2a0caeecbcaba18a2840cdb6c
+Payload = 8b9db1c8f9b4892a5654c85467bcffa2e15e28392c938952
+CT = 6bc6890fee299c712fb8d9df9c141f24ee1572b8f15112c2f8c99ccf2d82788cf613a61d60dae458
+
+Count = 61
+Nonce = 24eaeaa437649e61b706942b8d
+Adata = fff75462f96157d9554bddb6aac156fefd88fd4a90a8536dfc28cc577f19c83a
+Payload = 49ff4ff85f7407ca383cfa4fd7177adb4dab26e642c8186d
+CT = 3647fae50c588d792442f43a20125e77ab5db3c469391d24d0a421bbbc002eb9ac9ad01f625f824b
+
+Count = 62
+Nonce = 7325932d6694aaf61a8204c172
+Adata = be20ceb8ca14e9bef7158b280a26bcac763da79cd0eba9b1833ea808c5e7a66a
+Payload = 2861494eb40b9d964d339797c1b6aac63c6674187768957c
+CT = 286dc74001e2a6000a23db164f4b2912de4afcf1df8c3aa5ee32a7ffd4e7bc303d3482fbac431828
+
+Count = 63
+Nonce = 61c9949df5853e42599e5ee0c7
+Adata = 243d09ceb16755cb58d62065df84890b840ad9b7eec1132c6427cd7c3d843fcc
+Payload = 943a49073db6ae94a88844ed895f8fd99ed25c3f42a2f78c
+CT = d3c56bd265a2cb0811dd218f248800ceade4f02b5403b9635eb30cbec49cbb51c41cd5032b7fd759
+
+Count = 64
+Nonce = 07b6c18dd3b0fd9e8ff026a436
+Adata = e85f141c3d1af7727fcdb00f8e2c34e42a436d04ac5b8ca9f321a178a2056806
+Payload = a18b0a4618063c0519818d113b8e5435aaf153f664058f1b
+CT = 69f933a2a5e774e8d013cbf78c6ab0b73e6ca323d0c52691acb5cf2631987d3d963349b035324aac
+
+Count = 65
+Nonce = 0c075df70630dec2fe81834945
+Adata = f3f5c5ffbfe8247bc0c33c793652f749fe91b6dd141cf0db56e71cef8a2fd266
+Payload = ddc4bac4115e8cb06d29d22e400674dbc615a667f933603d
+CT = 26bdd25c9f204fc7520d26c161464c28fb35e395b295b3db4e239d33283d18415b54c2aad4bde354
+
+Count = 66
+Nonce = 0c2d20375057fcd4241d290f6a
+Adata = 70ff1b9ff8ec08fdb18b0e7dbe01127ed0cfe0b0a449ca2ace4992b7b6248b71
+Payload = dacbdf1979e000d52b573e74800761b30acc26681f372acd
+CT = 6a642c389433a3464fc64783ae6a14a9a45f0998b56a5b9162d7e0320dc930df3640a786d7ea9ae4
+
+Count = 67
+Nonce = ea0801cb3dab853750a922dd25
+Adata = d83360d0896e022bf014bd33710ab212ddedda6d95a54996f33db304e5f12f01
+Payload = 46cc5653bbd8300dfb0df6d0af3fb7c7639a830bdc9f68c7
+CT = f1b0728920351d9edfdbe7df360b21f6cc5b628dcf43a3f10d06b4a545609a2128a95d4d73471559
+
+Count = 68
+Nonce = 97e6de379c90fccf3fa8f27013
+Adata = 539f8eb802bfecaa4fb5b19debbf3d4847db9c4e0473a308ab3f3c859e68fecf
+Payload = 8b013f52a828905013f250fb9c006a173f6c66a64b5ba317
+CT = 556a439bc979dac1cfea8c5b64aa78547f52a62896c19893f3512baf72cd79ba9301194be204bcc0
+
+Count = 69
+Nonce = e832b6330d3e5e190598cb9c61
+Adata = 093be516277e8b197ba5e9c85a831529befff0f3971510ab611dfe0dfb50a2ad
+Payload = 635d2d7894bb816f154210946a369df37ea492993ba23af9
+CT = d8e19c67e5aa7f14a16ecaaac414a2b15a15bb5f966932e6b0bfe9a5857fd36df94aeadda7f83a79
diff --git a/lib/crypto/test/crypto_SUITE_data/VNT256.rsp b/lib/crypto/test/crypto_SUITE_data/VNT256.rsp
new file mode 100644
index 0000000000..2817684910
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/VNT256.rsp
@@ -0,0 +1,456 @@
+# CAVS 11.0
+# "CCM-VNT" information
+# AES Keylen: 256
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Plen = 24
+Tlen = 16
+
+[Nlen = 7]
+
+Key = 553521a765ab0c3fd203654e9916330e189bdf951feee9b44b10da208fee7acf
+
+Count = 0
+Nonce = aaa23f101647d8
+Adata = a355d4c611812e5f9258d7188b3df8851477094ffc2af2cf0c8670db903fbbe0
+Payload = 644eb34b9a126e437b5e015eea141ca1a88020f2d5d6cc2c
+CT = 27ed90668174ebf8241a3c74b35e1246b6617e4123578f153bdb67062a13ef4e986f5bb3d0bb4307
+
+Count = 1
+Nonce = 195c0b84baacc8
+Adata = c7d9557b2ed415652ce6faa8cff5217ac803530ec902890b31eaaf3eeb0aa98b
+Payload = fe012718481b2c4e1d7f9a7685e3daac43ccf22cad0df900
+CT = 893af0f130f1317de9f217234274b0c04fcc202cea9a0df882c00b5b463654adbf82888099a7d258
+
+Count = 2
+Nonce = 363e0e921c6f11
+Adata = 805678936d4e94746ab4818dc5f50c41e32cf32e7a8aafb300fb91af6406108c
+Payload = 7e7e33e1a07d4e8fde2f33304f21cb564d146860ccfeb49f
+CT = 645cdd11a1c232815ce1e07ca3ea83f372eba46cedafddd980adf2762a1617adfd4d8356bb48aa8a
+
+Count = 3
+Nonce = e323cc866af462
+Adata = 163c747f3ba4ffd68af87f2475f48f2714659a2ec43b9ed115e02fe0e3c8be99
+Payload = 2bfc76f3b108ba3118b07433c4d3d5f41564d22547c12822
+CT = 0db04c6b068e73e3c4d71059bdeee3d27622f99dfd07d868fb9c02753c57fec7e1a5fa8f3860501b
+
+Count = 4
+Nonce = 03ae777078b95d
+Adata = f1dacf9062dff9a6a3d0498f9d058782f891475684196bf2d8e7e905393acff7
+Payload = 38c4275a5f605fd1d99517e13deebf0c9794ef586070fa9a
+CT = df8f524872b5f06f3f219ba76524990b466409894930d7e0d104990e598eabd88cc8342ac16424b5
+
+Count = 5
+Nonce = 1c6c351d4fe9be
+Adata = 14285e97cc3cae452e1a52e2fa0bbe24df96abf2faf6b9779acc59764612eadd
+Payload = 9e2220f3c17532e1ce0d6f562b049fcef35bcaf9a7e196be
+CT = c274b28228a6b13b670c325080f88d188d40d78d385481eae004894b1861db5d2d8ae98ed8926c1e
+
+Count = 6
+Nonce = a121dc27479397
+Adata = 359421e9f78cc4a31f4f019977d7fd29780524e20288798c50002a682a6368b9
+Payload = d42b16b32e77637724144eaddb21ca8d7db4e7f73acbf707
+CT = 56e3e3e59e978161355e7d8573dc0657db400ca0b083dae8ed2ac2cb63e1b9d7dc598634198fe4fc
+
+Count = 7
+Nonce = b1f0e26b60bf1d
+Adata = 2ab4239fffd13762fb5391f5a4760d12d96ea12666a793b4d651e9f4891c22c1
+Payload = 9a2851083ad4e7b915bb0526bb4054e4c0b4adf8626edc90
+CT = 5b2e0215523ff37f0df46e84f996fc9fc779986c766fa51595b8a23ee377d5c2850f4ed95a385253
+
+Count = 8
+Nonce = 50412c6444bcf9
+Adata = 09cdcaa87ddf8bbe6db8411d14bb9064e4a121286cc8a6e97fce1844935f436b
+Payload = b28a5bc814e7f71ae94586b58281ff05a71191c92e45db74
+CT = 05cbc32a6ca797684636dedd16ce65a1eed69bcab1b1bdbd514ef5cbf9991a919fb4974d55506ce1
+
+Count = 9
+Nonce = 225557b0faca3d
+Adata = 21611da060fa90cf7fd68b721caf303307a56e56453326495b628c7dc93cd175
+Payload = e831b739e8eb9f787f63c0bb071ddcc9f44cab8d5b447d23
+CT = a97e0879407eb3b7f93118ca73f17eb34e9f4baf43b07be2e8a3f7b848054cb235e1b58d6a12c5cb
+
+[Nlen = 8]
+
+Key = 472bf7946bce1d3c6f168f4475e5bb3a67d5df2fa01e64bce8bb6e43a6c8b177
+
+Count = 10
+Nonce = 790134a8db83f2da
+Adata = a7a86a4407b7ecebc89434baa65ef173e88bd2dad9899b717ca578867c2d916f
+Payload = 59eb45bbbeb054b0b97334d53580ce03f699ac2a7e490143
+CT = db4961070f528ccd1a5a0681ee4d0ce3515fb890bccedc2dbc00b1d8b2bc393a8d09e87af7811f55
+
+Count = 11
+Nonce = fb2441d1594a488a
+Adata = 0875020959ed969cfb38636d1d5aabce9658b00171a7614ea9e5395331c7659c
+Payload = 451101250ec6f26652249d59dc974b7361d571a8101cdfd3
+CT = 1bca7b0d35a68c0ffc568ffc8221cca738b67b95e3ab26efee21c5738d1f7fddf3030d004a702704
+
+Count = 12
+Nonce = 0855263860043207
+Adata = c7fc24863c33f7e8cf97b337918495d52d864ac570c99cbb09d151758d6b504e
+Payload = 61fcd7ef9bf151b9d8a81dc1ba4f82c45e9c2e4784627acd
+CT = 9b939b6b188e1d0fe016f366fb01eb79a99ef7b1b57c6f7ab223454c57c714d96681cd4d55615afd
+
+Count = 13
+Nonce = 415cd251a5e36943
+Adata = 1a393c7e85fb286709f4eb50f09640e1d65ec1135cb4443820136b3cec69772a
+Payload = 66ae08d494dc9df9b7f8f53199fa37d0c88885458b168c57
+CT = 1731e260ae31b8068ad1099313b167d9e6cbe49f471da61a9af96d3ce4ea94213b60cb69d92050e6
+
+Count = 14
+Nonce = d95bd65242bb2265
+Adata = d0e20e1358be5cc1c45c1cf02c82d0a6d0824cfcb65774cf95f047b9f2cc1d3f
+Payload = 312c3791c64d79205a11eebfc14b2d7a6b00391793c9559b
+CT = c3fbe558ff9ea83ed86b7d66503ee38eee94e4a41fd53f0f627a352d056712e0d44404c61712e2ab
+
+Count = 15
+Nonce = 3f0bf0141dd3ace0
+Adata = 9dd4ed18209dd6cdf19cc76fee443827e7331aaf020960c15d7bbed0f6a3b1f7
+Payload = 08354480047eee3beeb5ab165da17d23f2f1a4ad98720611
+CT = 2db9d2c54134d37ebefcecb9e2076034b975677fde58ef6032645a322fa9bc8aace600f942a84db4
+
+Count = 16
+Nonce = 3fd8b3a3ff563a42
+Adata = e58327efebad3276a7cd1b1ccb56db0caddd02a303cd9fc7ea5c607a2ebefaae
+Payload = d1abd89351384e1a3c3366f77c3175f6390801554d7cd783
+CT = be284dcb357ae99ada7cc891730320ebb32ca627eb8c80623957a2a5b6164218fc83e12c42d5c532
+
+Count = 17
+Nonce = 14db1ffc1c87117f
+Adata = 6c2b091433833a0ed915354dcb70d982095b614dc51a95a22cec417184d8e786
+Payload = 0594307491f157821e63f50c94034f9284f095d5b897153c
+CT = a114c84a10071e359bba2b2ba4ea67f893e27e6ea880aa4b2cf16ce68a93f8839245baebb2278300
+
+Count = 18
+Nonce = 40b0f74ff27a3fc8
+Adata = 3b9e1f4e9b57a6dfb5e0ca7ef601fc6af30a1f8650228e51e0dc61180d0bec6b
+Payload = fc8b7dbceef6b0ffcbade789e09303044042cd671607e819
+CT = d00ef56074a8213740af8b8f974f778db560ac365d6ce916b8d191130e864bcfcd1dec94a1aaeaef
+
+Count = 19
+Nonce = 96cbe9cd19351359
+Adata = cf498fd042f9a07503e490cec4873d4df91162cfde60bd2cbb2b710c6681a9fd
+Payload = 315e81c9ce556dcf97a5b68503fd2228a7a6a174a15cd618
+CT = 7383c2de08bce3f0b7e504dc03d062f44396bcedd2180fd954e6ec9f6ae1e0976ecf04dbee6463c2
+
+[Nlen = 9]
+
+Key = 58ae7965a508e8dd2eda69b5d888a28a1cb3783bad55d59d5b0da87137b72e93
+
+Count = 20
+Nonce = caa3d928d2bf2b7f2c
+Adata = 304678b3ffd3200e33a8912bcb556b3cfec53ca17f70ecba00d359f9f51d3e3b
+Payload = e61bad17640ecff926d0b0238271ee4c9f8e801dd7243e9e
+CT = 7bb1137c14cb4d324a4a8f1115c619ebf74927f0bed60a8d5a9140ff50dc4da375c7d2de80de097f
+
+Count = 21
+Nonce = cf09ca67659a583bb1
+Adata = 5507c4c3107cb446d19975f91207dbf3e2a51d1dcfd7da2f082159dbc3f41547
+Payload = 1887bb0c02500093a30a44b99e137483704b06615d308c6b
+CT = 834d3b2e5f0915c2348c706b4d2ff2717983ab4490edcc63971f02b7122d1e4f78de9c3376520f5a
+
+Count = 22
+Nonce = 97f940d7c1230bd8d2
+Adata = 56be2c9e09b555373d58f6fe2a0ca9b4ddba899addddf12b0fda860ad791773a
+Payload = 5ac67c9bec9b95c54e187a4a6812f5d701c4ac8f847c005b
+CT = 9f372ba1c87a115847cd708aaf5b8a143b6981ffc2c61cefd30ece13481609809b218de04c4e5ed0
+
+Count = 23
+Nonce = 147c7ebb6c92245054
+Adata = f95d64a513a9f3e6c95c9ed27b22fafd7dd10da52636029523142149116aff53
+Payload = 08f199a8d7e3ea821dd3106e8947cd2e9d485342b25a6471
+CT = c438aa6d187643d030dfe4d6b5b578f84838f4dc5c396d700c0986ecd7dab44e5e97db37392a485a
+
+Count = 24
+Nonce = b9bad794d49cdac9b3
+Adata = de9ff2a43f49cdc502cd17a373989bafd13fa6ccff6660557ce05b6295186d47
+Payload = 40d1cd4063750184356a1d7cae1cf1824f552c5d59a62dc1
+CT = 9952b25f4f4f375440cd958456184fe61610381ba92ca48f38dd977042c4d97da84e4effa650799a
+
+Count = 25
+Nonce = bbe054fbef86db3ce7
+Adata = dcec76181e3b872a5a6e79f070354e38866c7f67fc428fbca29ae6d929b1dd7f
+Payload = 5f29808ba74b672a0f82b3b7581dc32478c6e790e2b8c61c
+CT = 4d176f48b09b772dde8adbdaef720aba128a8d38a902847ebf22c81a5d824b4916660be6f9b513e6
+
+Count = 26
+Nonce = 6a35e1a4307f6efc6d
+Adata = af28120505a84a75b0f6b18cc9d8c75c661bf143be29c11d8ede78b9bb98c98a
+Payload = 5e2f601395ec406fcf96785f768162e849f867dca77667ab
+CT = 4e305e26d34711c6aa775f490939cc6560d3cb6905f5b0f5588ace6fc303600abc8e5825cbaedc7c
+
+Count = 27
+Nonce = f6c237fb3cfe95ec84
+Adata = 038f8ed89444784417a9c23bf11e9b436174e6c10959e00faa1704ce2f7f2c7e
+Payload = dfd9cacbf7d73d688447ebab13d2e13f3613652379b386f6
+CT = fb16c17a6b22a8658f446203ad46a48b34808083b271cabb015a1f78abc287bd2a63381ead07c558
+
+Count = 28
+Nonce = 50d024a3e7455d7249
+Adata = 8513365786b7988b208984e11022c15573f978bbdc29e8a7a4745c8a81885a1d
+Payload = 400317786b7df63373ffe541efcee6318cfc95bb673aad3e
+CT = d33b3141fea3a9ebdeb80d1da32dae42680be78471fb3023721f714120162514555b60560afa4256
+
+Count = 29
+Nonce = 02769283d5a06c363c
+Adata = 292c0be3713c6c588cb4e29a1c43b3e6353e33556194e568e800e4e44e8281e0
+Payload = 12ba8eddff1c2a03ddd25bb924ff065a93fd712b2c4f61eb
+CT = b15b1789c323a68568f86f35483bd7e204beff8f318ae14351f5e62b3b923a937e6c307af202fab3
+
+[Nlen = 10]
+
+Key = aecc5e18088bf9fd7b17f089bdd5607b69903b04b726361f8a81e221b1c91891
+
+Count = 30
+Nonce = c527d309ab29ee91c5fc
+Adata = 8f9a73e7bc1c11e2919020ba3a404cbddf861e9e78477218e3be2cd4337b278d
+Payload = d4291c99901345afe29f58912a414a7498f37b44362bdf3c
+CT = 392784a9e0b14bcd37639ec5409d6ead3e75f855e5a92c33ffc040ef3977e0035ce6ea6d157c18d3
+
+Count = 31
+Nonce = eebc31a5813b4fb93b63
+Adata = 9c87ad77953bf8a811e001ddb946eefafbfaa598150e85f0701853fa307d77d6
+Payload = ebcfd71120b0f9a2cccb898e6dfa082998cbe10032de3e61
+CT = e38eaad1e2df77e85e7129a8ce0f82cfc32b0aef79ab651bade65aa17e4dfb0aafe18cf71a72b180
+
+Count = 32
+Nonce = 231b33dc406c9210f59a
+Adata = 38be46d271bf868c198052391f8a2147c663700d9bb25a0caaa36974f18dacea
+Payload = 9032f910347daf661092b5c1f15b5ffed1369b194d9e12f0
+CT = 868b85288828501cf1d06610fec25e8b8a4b437e2e4f5563b7f3b898a2356909784598f8a8916f5a
+
+Count = 33
+Nonce = f2a88c3ebc74e62f24c7
+Adata = 5f495c5da035cabeb77e8aef10e91a05bd5aa414d1a37fa1099af959b26e5403
+Payload = cfe8ee9b475e36058471e2984ae66f6ba1b3cb477b15155e
+CT = 22c16333ac651cd9c183e78aba3e9312fb3b77dd6f9199502788860aae5534cf84979e30c3327d37
+
+Count = 34
+Nonce = 9cbaf1c83ba60b1e90ea
+Adata = 7ef136bd9a5809676abbaa68016d6fc713e34ac4b768a8246b1198c959f43085
+Payload = c3bcb0aaea93893f05eeb6439c8619dec17670a6439e2921
+CT = ebd9fb86563aa8f10062624441336f982c161ce5717d990a599ca6ec1c61a14c37b5902389e47aee
+
+Count = 35
+Nonce = e25322845d87d8a76753
+Adata = 2a89b9f0e56a1cf87dd38ed78028b6286ef8b7141dd2b3c65c5a8e1ed79bf4aa
+Payload = ae622ff9381854f831892c318bae5c003e74b15199bc12c0
+CT = 144c920f0fe278f353d0b053563d907c7589e4f1479d7a93a0604deb3fd9cea2d89987833ff5c2f1
+
+Count = 36
+Nonce = f4d7978fad36223623cc
+Adata = 8671de7e994967f2521d263925e745af9273682d9c08ced07d4a98fc985f68a0
+Payload = ef9b4ff8da108cabc972192ffecd5f96594c6d0871ffa6aa
+CT = ae4948b3bc1e50beb9f5d005871fc0d3dbde295de1c9ec3cbc866ab47bea7a4d0070e52b492fb8f6
+
+Count = 37
+Nonce = 6597ffb9eaad0fd9d830
+Adata = d2967ddf69ef62a9e23c9118dfaa55df92b4116322f1c9275131e3875dc92faa
+Payload = 5015c894b2437ff15c46bca9236830ff4bb057cd5764f027
+CT = 0b1dcb3cb0b4c32f398f3c43eccfe8f4242f33c99a2a2283efcb3dacac25bed0304f227fd5b77b8f
+
+Count = 38
+Nonce = 80e376b87272d99cde28
+Adata = c9cc8f967dff45c05b9345d03813b6e30dace99556f7df75b7120bb6e5f55827
+Payload = 615f657e24129a3e0f119988959608821219ce8354c4be26
+CT = d3e8b8f7ff8faa666ffe2509187fa7befc7412fd4e3bdb06cd2f7494b1fb0a0c6a2184e5c4787fea
+
+Count = 39
+Nonce = 344cce96455541d403f3
+Adata = 748cce18fb40126ce125dbe341fbbc59d2aacc170ed5ef0293b15713c9184a07
+Payload = 828b6a4cd49f499a6e8e8508f9ab35255d8e9fed33ba4d91
+CT = b67e582a74d7f022a16ada2de7ec18caafdefa6b104baf4ed93b6f8c8a1bf72be75976e4ebe6dd1f
+
+[Nlen = 11]
+
+Key = 97bc7482a87ba005475dfa3448f59d4b3f9c4c969d08b39b1b21ef965c0f5125
+
+Count = 40
+Nonce = 0bcf78103ec52d6df28887
+Adata = 049c10f0cb37ae08eae2d0766563b7c5a8454f841c2061a4f71a0a2158ae6ce5
+Payload = b99bf4dc781795fc4d3a8467b06e1665d4e543657f23129f
+CT = 0d3891fa0caac1f7ebe41b480920ffd34d4155064c24f3b17a483163dd8f228d1f20cd4f86cf38fd
+
+Count = 41
+Nonce = ab6374c6b2faefd92fa3d3
+Adata = f19c044023e5cf339203738ee70e76527519763664c06ae00e002a5ba94c32c6
+Payload = a2e5c51f516db01688b64c173bb25645182a005018022ee1
+CT = f70c598df3c64d3527ebb7fc8408b7de2cfaa1da7984ec361f1ad61758d828b70d4881b7d6ae8cd0
+
+Count = 42
+Nonce = cfb89e7ddcba601e875110
+Adata = 052714010da516c896ac5842a839ae845324643cddb080e6206148432d0d0407
+Payload = 037f206cab78a6ca0745dc8fc137e22e14f3d7183917ef83
+CT = ccd675862502a2e2520a33250150b8b7b220e84db854888c316dd62075fc761e2bc80edc5c564bdf
+
+Count = 43
+Nonce = 967cb6f8530bf8a43adb42
+Adata = cf391a84d03e2e22aec1965cec821f99e7bf21a7c3580dffa531464b22d83225
+Payload = caa3d928d2bf2b7f2cd8a7f357055b6d6895a5e34f47972a
+CT = 4f4f509debe6e52eae4af8b1740dde0a5338f78711a3b4ebfc8b5aca6d606222d6af7cfea0d1f4e1
+
+Count = 44
+Nonce = f5b7b5dd2b5e1ec93710c9
+Adata = e7a6b228a67d37b9d29a38efc547e50b4a6d95d599b45ee189ece21101ac6b5b
+Payload = 4a74ff35418723f2cecec1012484b52114067b2b2393e7f4
+CT = 25b140922a9d4f2ce153a4ff86596a49d7de6a6184e931e8b2ff27a98029b23484e00c2a5d291887
+
+Count = 45
+Nonce = 713de00faff892977d99d0
+Adata = 14ea93488d4284d21d4c7ce14414adf45c1ed9d2d99db866d0e59accb6234dac
+Payload = 3820db475c7cb04a0f74d8e449f026ec951fa59667738698
+CT = e4d92ab8d1ffb0976670d891cc8338da12f86d5d79b334103d2ae816edf857c810b6fdc7f2c71f1d
+
+Count = 46
+Nonce = ba87934808de09b2ae829b
+Adata = 30e2ea2a505f19e8760a0a84961000c7a0b7fe3460a9d3f5a38f54149be2e9ee
+Payload = 0e52a384cedcdf7f179348de6e7336aa86f8855fbd903cfa
+CT = 6df893eed2be958e5f542f8cb4adb392b34786cb4ce821ec93fc57997b977948d55bdb026db5bc48
+
+Count = 47
+Nonce = ea09fbe5da0fa4fe911e18
+Adata = 237dc8512b29bccdeb8ee39cf83b9b6dd203823d175c44d5f605b194e7ec136e
+Payload = 41cee0ecaf9c65cef740440af37954ef49a585779d2abbca
+CT = 2f204ebcf549ee2a800d870e6341b9a89a41ab4ae91b6902ff704a2bcfb8becd0226f76d68fbb08b
+
+Count = 48
+Nonce = 5b80d7affc4ab4a4b68bdd
+Adata = 3a38dd7da30f5c312fb1e978d87b7a39792fd9ea3e9ab1565874e99df587327c
+Payload = 5ff92f6d3ca791421363e10cc84b4e8e21e0ebe5d8c55d6c
+CT = 05472db7875d59f8bed45606f355a516de93740aa2baeba18df9400df42baee6b9a0d75b45840104
+
+Count = 49
+Nonce = 514bba483fe7f2b7e555cc
+Adata = ac8beb419099cdb42a39e9b46fd900cc52eec4b43a96ed18b37b899b63fb931c
+Payload = b0b11dfca9b3936d1b4a423c5acd3d012b399a487c19c994
+CT = fa20629d514c4ce7bf727629bca5aa1c0c7e7851fc1bfc5c847729a70d7b4cff5281aece37006015
+
+[Nlen = 12]
+
+Key = d6ff67379a2ead2ca87aa4f29536258f9fb9fc2e91b0ed18e7b9f5df332dd1dc
+
+Count = 50
+Nonce = 2f1d0717a822e20c7cd28f0a
+Adata = d50741d34c8564d92f396b97be782923ff3c855ea9757bde419f632c83997630
+Payload = 98626ffc6c44f13c964e7fcb7d16e988990d6d063d012d33
+CT = 50e22db70ac2bab6d6af7059c90d00fbf0fb52eee5eb650e08aca7dec636170f481dcb9fefb85c05
+
+Count = 51
+Nonce = 819ecbe71f851743871163cc
+Adata = 48e06c3b2940819e58eb24122a2988c997697347a6e34c21267d76049febdcf8
+Payload = 8d164f598ea141082b1069776fccd87baf6a2563cbdbc9d1
+CT = 70fd9d3c7d9e8af610edb3d329f371cf3052d820e79775a932d42f9954f9d35d989a09e4292949fc
+
+Count = 52
+Nonce = 22168c66967d545823ea0b7a
+Adata = 7f596bc7a815d103ed9f6dc428b60e72aeadcb9382ccde4ac9f3b61e7e8047fd
+Payload = b28a5bc814e7f71ae94586b58281ff05a71191c92e45db74
+CT = 30254fe7c249c0125c56c90bad3983c7f852df91fa4e828b7522efcd96cd4de4cf41e9b67c708f9f
+
+Count = 53
+Nonce = 225557b0faca3d6cbaedec5c
+Adata = c7aafe7d3b419fa4ea06143897054846ac4b25e4744b62ba8a809cc19253a94b
+Payload = 0e71863c2962244c7d1a28fc755f0c73e5cbd630a8dbdeb3
+CT = 2369b56f21336aba9ac3e9ba428e0d648842a7971182d5ffac57f6ae1080efab4ed93f8b4ce1d355
+
+Count = 54
+Nonce = 78912be1a35e156a70fb72f7
+Adata = 12ba8eddff1c2a03ddd25bb924ff065a93fd712b2c4f61eb80d77fab2c4900e0
+Payload = 113efd182f683596862ccd5eba2e2d4ffa709d9b85c6f1d5
+CT = 835a22eb8d718c0ee1531a2d1bb95f58215c997c612908eeed3ccaeb7a814f69d3ec1fbf2ee9792d
+
+Count = 55
+Nonce = 91ad90b58d2044abacf957e1
+Adata = 4fc795b9126c23dd7fd514c2e5a8ca583e88a783b28cbb2a5df09f8b520ba0d1
+Payload = ed55f6b9eb8fe74474c037ede94ffd84ada846ede4ecff74
+CT = ecb595276fd5d412a7cc3f5cfe960f47a0d0e2df0b08a11ac257d67143722a976c9d7f44b09a767d
+
+Count = 56
+Nonce = 4bbe4ca29122c4892ca09b5b
+Adata = 367ecd1b71dfb96a84e2369f28705dfaebf0c73ed35d5364449b2391230be846
+Payload = 8dd497bb777bbc3e56e3af25a43545007bb00f2b9e9f815c
+CT = 563d61fc0a5b82804a580a7d752a8e61d3342fb39372b39b6843a685bde3175695796f6e64f35901
+
+Count = 57
+Nonce = 218e7b8a8fd62927f90b70e5
+Adata = 01815f599d6ba0d1c09f6f673bb6cca4c2a7a74f4e985be4c0f37842c7bbc5a4
+Payload = 80f3e4245c3eab16ef8bf001429122e46bde21735f63adba
+CT = aaceb16589b9de253c99d0d32409a631db71e8df8a7644bfd027e3466e8220144cb0552f9b2800e6
+
+Count = 58
+Nonce = eecc9f106a0721334cc7f5ba
+Adata = bf38d0ee11a796a517539bbc9ab00ff85a4ddbf0a612d46e2bc635180ad34c50
+Payload = 36cefa10af1a3446a2c8d4a1171144b9ddd8e33a7cd5a02d
+CT = 9bf3b2df93cf5b587ecc96f45fc75e6eb066cb286cb06f284c9027fc41bb8c848025fcf9d092a873
+
+Count = 59
+Nonce = e41af8ca408c4c12e37561a4
+Adata = e0b20892875f60b5d8763a04958487fa5b7cf8d67a456e430475b337245d671c
+Payload = 32a4da08bdd51336ed5798c7177b853a534bc98f2e6f7d4e
+CT = 95ffdc68f721cf2294d0d88002e3814167306fd906dbebdb7e6e0e5dc0a03826e51bd94269d7a41d
+
+[Nlen = 13]
+
+Key = 4a75ff2f66dae2935403cce27e829ad8be98185c73f8bc61d3ce950a83007e11
+
+Count = 60
+Nonce = 46eb390b175e75da6193d7edb6
+Adata = 282f05f734f249c0535ee396282218b7c4913c39b59ad2a03ffaf5b0e9b0f780
+Payload = 205f2a664a8512e18321a91c13ec13b9e6b633228c57cc1e
+CT = 58f1584f761983bef4d0060746b5d5ee610ecfda31101a7f5460e9b7856d60a5ad9803c0762f8176
+
+Count = 61
+Nonce = 8a56588fe5e125237b6cdc30f9
+Adata = b3aee5fbf409bcfe9b46ae68d570edbbed32c12d13926ffb5ddc60ff0bdb7f85
+Payload = eca81bbd12d3fd28df85e2cc3dcc2ecbd87408002fd00fe1
+CT = 9aad62a5443550d11f9efdab2de0eba74d47ae4f7d16adf4276664f6567f2f978bd4be4d80cd07be
+
+Count = 62
+Nonce = d908b04840caca2280e5293ade
+Adata = 314a202f836f9f257e22d8c11757832ae5131d357a72df88f3eff0ffcee0da4e
+Payload = ad1109ea5c79bb55d22e9713eb2df42767cb29a2eba3ad2c
+CT = 61fdcebb158cd03151697ae7871c0a998802997e0672e5886e5a9df1b1d6284ef657cde6f74734bb
+
+Count = 63
+Nonce = 6df8c5c28d1728975a0b766cd7
+Adata = 080f82469505118842e5fa70df5323de175a37609904ee5e76288f94ca84b3c5
+Payload = 1a95f06b821879df3fd3ac52fc99a7c1d3e9775263b7d036
+CT = 704f60f9cc3ef7bc00b4f7a271ca70a89f4d5605387b3e2f8cc80aa08572b90e9598d0a73712b720
+
+Count = 64
+Nonce = 6c6ebacce80dde9fefb7e5bb47
+Adata = 93f0fca0c8c84d5cc48160b25e246226d489225c0f8275e52856da592c715aa6
+Payload = 46820aec46ebd0d61706129584058a1498514928a87fe620
+CT = 00f6cccf45f046da1e6266afe61eed61c60c28515b2e1ab386b2c952055899184f0d95ffe3959f89
+
+Count = 65
+Nonce = b94bc20d8c9abca7645fc6bebf
+Adata = e1c083c93663f5a066ef337a61aa3fddde7c301a42463137c375cc2dcdd76954
+Payload = f1fca581d3dbbc61060c0c02adb47bc57954d25a283f66d6
+CT = 90c65d23e0e1786cebb95f9b1306d001b2e503842cdedb75e37a53d77b9e38605febdd7b2b666f98
+
+Count = 66
+Nonce = a4974791d417d7e9eea0f4ae8d
+Adata = 33602f308f3a0f7e1c75fc1e4321d545ffa278234958dbadd37f59a0f85349c3
+Payload = 41712c058d2d56b43b2c79278e790858a289320746c15a60
+CT = aab5656a1ef060c9b1ef7e2f3cc0bda40ff067900401182563ceb824708a20724c99c83f1caacd70
+
+Count = 67
+Nonce = 6003b771afe4e99e1ef1ed4a31
+Adata = f60d8362b2ebf523681bb051fd3ee13919ad86acd963c703c4178a5f01a84236
+Payload = b766022311c5e1d74a607fec7cb8ee805b8397a6c5f374c1
+CT = f73b2a6dbf8f798d4bfb489a6578c9c79152e42aa3b81b64a84e7af3116a18f7ce44ae93f420270b
+
+Count = 68
+Nonce = 27861168ac731a223dc35c03e8
+Adata = b7ba1c66282cb6092ba601407ff9578afdadf7ba7a4d08edef06dbbfd87171bf
+Payload = 0822e3e6ba982091d532cd5271fbde25305d1f6e71880f81
+CT = 5ab3e5296cd1f08704c82f6b42939702515b7733853d723d4009312bdae46958d844eca502bcb005
+
+Count = 69
+Nonce = ef284d1ddf35d1d23de6a2f84b
+Adata = 0b90b3a087b9a4d3267bc57c470695ef7cf658353f2f680ee00ccc32c2ba0bdc
+Payload = bf35ddbad5e059169468ae8537f00ec790cc038b9ed0a5d7
+CT = b702ad593b4169fd7011f0288e4e62620543095186b32c122389523b5ccc33c6b41b139108a99442
diff --git a/lib/crypto/test/crypto_SUITE_data/VPT128.rsp b/lib/crypto/test/crypto_SUITE_data/VPT128.rsp
new file mode 100644
index 0000000000..f79db90b4d
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/VPT128.rsp
@@ -0,0 +1,1383 @@
+# CAVS 11.0
+# "CCM-VPT" information
+# AES Keylen: 128
+# Generated on Tue Mar 15 08:09:24 2011
+
+Alen = 32
+Nlen = 13
+Tlen = 16
+
+[Plen = 0]
+
+Key = 2ebf60f0969013a54a3dedb19d20f6c8
+Nonce = 1de8c5e21f9db33123ff870add
+
+Count = 0
+Adata = e1de6c6119d7db471136285d10b47a450221b16978569190ef6a22b055295603
+Payload = 00
+CT = 0ead29ef205fbb86d11abe5ed704b880
+
+Count = 1
+Adata = 98d477b7ef0e4ded679b0bc8d880f09823ad80e9732fde59c3a87da6a1fcf70b
+Payload = 00
+CT = 5b85d144bb51d4927074d3536a2db83a
+
+Count = 2
+Adata = 28f32de10b6c9d3c3f46efec7aee24006208a54c4d1c2bba4b8cdce166cab7d9
+Payload = 00
+CT = 01045de4a09486eea5efa33ecc6cd299
+
+Count = 3
+Adata = af397a8b8dd73ab702ce8e53aa9f0189995c6c9e920dcb75795149550b499deb
+Payload = 00
+CT = dfd75400b59c3ad387bc86dfbbfb52ac
+
+Count = 4
+Adata = 3fa956bfaa27e249bf0a1276468d808259f3b8e2687851d780885d44cc2f04bd
+Payload = 00
+CT = 2b11d2549b4e2f0a81c07ee90af4d081
+
+Count = 5
+Adata = babbd1b44cae3af06e0150bf0e3d898f6fe862b71ea9f6b727accfc18848fc79
+Payload = 00
+CT = 10f76ab445f4ec158ccc1f7c6fee3ede
+
+Count = 6
+Adata = 7fba0bfda3b03c736c121cf9a257db55060b621be5168619ec4182f13ef6a408
+Payload = 00
+CT = 59e02d6a6aa3fb2692b04e65a0e735da
+
+Count = 7
+Adata = 057354a29808f4ed77671ed3dc36f8b03f5cd952caac5cb80dc3b319f3333e29
+Payload = 00
+CT = 367a2ade4087964dcb0ca2984d44657e
+
+Count = 8
+Adata = ec08b618602d091e9304715cb552b357c16fd1d7f7f023a28d84a98ba21ca0ab
+Payload = 00
+CT = 47cb92cd40bc89328d4dd44fbd727032
+
+Count = 9
+Adata = 45622834ea658b09b17f32777d18b34b387ef957bd344468f68e7178417a7c24
+Payload = 00
+CT = f5185afb8359b5ef995483c0bc4192c3
+
+[Plen = 1]
+
+Key = 6ae7a8e907b8720f4b0d5507c1d0dc41
+Nonce = 7f18ad442e536a0159e7aa8c0f
+
+Count = 10
+Adata = 9c9b0f11e020c6512a63dfa1a5ec8df8bd8e2ad83cf87b80b38635621c5dc0d7
+Payload = 0e
+CT = 4c201784bdab19e255787fecd02000c49d
+
+Count = 11
+Adata = 73616a428f1a567b2e9af86b1fc8aec6d597b1b55f2aa2219b3b662fa6bd3407
+Payload = 30
+CT = 72f14519f06b63fac3d5b2d9bbfa0cb758
+
+Count = 12
+Adata = 6d62f4e15e8bcc9ba4993bc50a046737121016f0d15020b90068250551167b1c
+Payload = 34
+CT = 7676b581a28ca0a0ba5178eba7fe028da6
+
+Count = 13
+Adata = 8f0b8289a1834ecc2167b59ce3c9d3b58465c4cfaad50c728d04360cb7e5bc41
+Payload = ec
+CT = aed99b805c0a4785ff2913cab3e50f6205
+
+Count = 14
+Adata = 477b2a6932f838f0d1bc420c0ca306981d8e2dab945b6f259e15fe888667220a
+Payload = ec
+CT = aeb50e41cd7af84a8fdb6aee144e904616
+
+Count = 15
+Adata = d6518d409b1f05708d0b44f18fb5721f20f3220f8d2f2718650aa9932e4579e0
+Payload = d1
+CT = 9312639c863974f077fe8236c943b464c4
+
+Count = 16
+Adata = 865e7cde73b558e9bfd05356923f8a697970811fc484acad2d5b3528baf1f986
+Payload = 24
+CT = 66d7265cde50bc7a3989458437baf06db5
+
+Count = 17
+Adata = f0c3c67a935eace53ed32435655dd0974fafe283622e8294a15d70977398eae2
+Payload = c5
+CT = 87063144b25d2268063815d1b42ebbac34
+
+Count = 18
+Adata = 341e71b2ef26e9db03882e06d06cde2c0617326cd157d5984d22f6f3407a9c39
+Payload = 34
+CT = 767da45c10d0d6498716bcf3f13ca7e26c
+
+Count = 19
+Adata = 31fce6735ba9a3385df11c153179b8e4141a3c6b8ad6eceaa211f3f17bfd0474
+Payload = 7d
+CT = 3fcb0a6f562974cfb3fb7c8d5cafd50f2b
+
+[Plen = 2]
+
+Key = 3d746ae6cac5cefd01f021c0bbf4bc3c
+Nonce = 597b3614ff9cd567afd1aad4e5
+
+Count = 20
+Adata = 90446190e1ff5e48e8a09d692b217de3ad0ab4a670e7f1b437f9c07a902cad60
+Payload = 4360
+CT = e38fdb77c1f8bbac2903a2ec7bc0f9c5654d
+
+Count = 21
+Adata = 6bc3d30925c67371573271f1a4273ad76e91e07dfab65f7bce0b241b5e4cd00e
+Payload = 17c6
+CT = b72955210d62e1393e4fda647c2b2e59a47d
+
+Count = 22
+Adata = d1bb4cdfc3f2c16d92576068543692aa4b5a427d688387af0f1583e91a0e8b3c
+Payload = 6575
+CT = c59ad54fd88a47b9f6e39cb4606af86d13e8
+
+Count = 23
+Adata = ae6136df9ab43631ef143515dacedbe759b3459e951bfaf4712a21c86352f1c0
+Payload = b1dd
+CT = 11326de841af64b55bb7ebe3fd30ba493c7d
+
+Count = 24
+Adata = ffead34ac26e21158212d07c367c3a7cb6b795887ee2d3d8ae25c60556ea88d3
+Payload = cd16
+CT = 6df93a206339de534271f6469edfa5ed07d3
+
+Count = 25
+Adata = e768e7d867820d46c1cc62ee0e51d4dac6f5c4b5785b5ccfbf05236871bdce2a
+Payload = 12f5
+CT = b21aa8f65144f2ec5809e2ccb38c8760f7bc
+
+Count = 26
+Adata = 402e802885e4119df17fe85f141c3d1af7727fcdb00f8e2c34e42a436d04ac5b
+Payload = 39c0
+CT = 992f9af825957abe7d89e175b6e8c0b84b5f
+
+Count = 27
+Adata = 8a3a622b3d347c0c5210d484adf77fa33205ba02224ddceea71d89c9ad8429ae
+Payload = 912f
+CT = 31c025d6a12e91e84e355934547f6b5dceb8
+
+Count = 28
+Adata = 636114e5e5f83cec94e1df21d6babb9f6a14a532fcbfc3bcf649fbd79ac1abbb
+Payload = cb6d
+CT = 6b826db959a21e9e4ebf25ca4f98501b560d
+
+Count = 29
+Adata = 04e84f9156998c2eca9e96079a6001f2947dc49a081b3d75e47d75f71ed4a606
+Payload = 5bd2
+CT = fb3d2006ff22ff231a6646ae561923818a21
+
+[Plen = 3]
+
+Key = 3e4fa1c6f8b00f1296956735ee86e310
+Nonce = c6a170936568651020edfe15df
+
+Count = 30
+Adata = 00d57896da2435a4271afb9c98f61a650e63a4955357c47d073c5165dd4ea318
+Payload = 3a6734
+CT = 384be657bfc5f385b179be7333eb3f57df546b
+
+Count = 31
+Adata = 50f6e6dd57bd3a24f6bfdc8b1c7b5a36ebdd07fd6d194e6e82da47151d9c88fb
+Payload = 4ffad3
+CT = 4dd601b8ca97bda492546d82dccdebef441f8b
+
+Count = 32
+Adata = 70e132023acae1f88c7a237b68f5bdce56bcfc92be9f403d95d3bcc93b4477a9
+Payload = 8a594b
+CT = 887599fa0f3e397d9a580aa39c7028e1a508c9
+
+Count = 33
+Adata = 08d2b011f36e05dc728c1a8bda3d92c779a3d2f27c4b041810bd6222c852b14d
+Payload = 1f89df
+CT = 1da50d593460d335e2f7a6d40b8fe305b0f690
+
+Count = 34
+Adata = b207eb870aeeab27c6201ef04650bdc7ea30028a243420f7d198f1c9c9a43023
+Payload = 72e9c1
+CT = 70c513a2d49e1a113767ea4219107819d88b65
+
+Count = 35
+Adata = 74294088721fc9e7aabd5f1c66b5369b1e2d2cdb3e73abaa28ecd1c37d4ecea2
+Payload = 016083
+CT = 034c51dab1c819778be8453db163c882063af8
+
+Count = 36
+Adata = abbd347999a1c26368cdb17ab08bf57a8e942d1248296e952f5f42f2cabbf0e6
+Payload = 25f665
+CT = 27dab7537eb435df8d0e48c3f7e0bd1877c866
+
+Count = 37
+Adata = 231b33dc406c9210f59a5df1cfd595c803474db34b9b1848f0bcbe7b28df33c2
+Payload = 158606
+CT = 17aad4da549fc63d55b5910bbbf64435b95220
+
+Count = 38
+Adata = 69b851e63a78baef90637978e3dfe8c47be4b21e85bb89bf67051cf251004376
+Payload = b07452
+CT = b25880d5ee29fb2af47f8040fad585921057f5
+
+Count = 39
+Adata = 9b1f786c887d310b8efd3e8192fe504f603024c94aaa4ec9123736a40bf1605d
+Payload = 65187c
+CT = 6734aebc3ee43e10205f83143e0d3794a6734c
+
+[Plen = 4]
+
+Key = 7ccbb8557f6e08f436d0957d4bbe7fdf
+Nonce = bb8e2ef2ed9484f9021cda7073
+
+Count = 40
+Adata = fba1d18a74a3bb38671ab2842ffaa434cd572a0b45320e4145930b3008d8d350
+Payload = 4cabeb02
+CT = 32501f4235c4dd96e83d5ab4c3c31c523453c317
+
+Count = 41
+Adata = 78b3faecb2bdf6ed14ac2b86ded07aa791b60f5d54f9e24a965a8453f5131898
+Payload = 5ff73653
+CT = 210cc2137907d6a03e66403a7d9330d30d934a8d
+
+Count = 42
+Adata = db1239528eb464dd063e2a97ee83a87d6002ebb4fbafa77036f72c14f3fe959b
+Payload = 062fa9ca
+CT = 78d45d8a44f4bc78fbb969935076134437df82b4
+
+Count = 43
+Adata = 0071f1edb3a0ce57af3c88bb0ccf138f752697a77e55695838fb39de04c78dfb
+Payload = cad710b4
+CT = b42ce4f459692911fea2e0034d06c3b2e89af3d1
+
+Count = 44
+Adata = 7381471a62b1fa6f5061c4c37e9721f07099d007ffaf8639aa2ae3f82da5a559
+Payload = 7ac716b4
+CT = 043ce2f468484e22381923bfcaed16e0cb85b0f8
+
+Count = 45
+Adata = 19bea6d92d5892216e8e4a30dda802387800bb046a6717817fc46c7edafe17b0
+Payload = 362da02c
+CT = 48d6546cd081de39c247df309c4b56c31c03690d
+
+Count = 46
+Adata = 8503c8eb9cebc6110f259e35e03a0740267768130ce6f61b1c7d1d25be942274
+Payload = de52b209
+CT = a0a94649c6c6bd7b3a9d7c4dfa2738847ea3cb33
+
+Count = 47
+Adata = d2445db6efecaa3f426b06de8d496ceed54a1d0171384cc762e21b31e265c6d5
+Payload = 8fe8b383
+CT = f11347c32ca874d18d0b790856837555f4d4699a
+
+Count = 48
+Adata = 8cda7d1e135cf5fde1ec9473c4b42c1bbb445c27fd87b5f73df61ceb2d0b6f75
+Payload = d8d6b2c9
+CT = a62d4689932c2f8d78e322aaffc90846025190f1
+
+Count = 49
+Adata = b506a6ba900c1147c806775324b36eb376aa01d4c3eef6f5a4c25393ecbf2025
+Payload = 6a029e53
+CT = 14f96a13c346a4084918081b4bbe53b50d896788
+
+[Plen = 5]
+
+Key = 3725c7905bfaca415908c617b78f8dee
+Nonce = c98ec4473e051a4d4ac56fd082
+
+Count = 50
+Adata = 11bc87f1c2d2076ba47c5cb530dd6c2a224f7a0f7f554e23d7d29077c7787680
+Payload = f5499a7082
+CT = e378b776242066751af249d521c6eaebdff40b2642
+
+Count = 51
+Adata = d54219ef4fb851bebd1c546011ae3922b8337e19c28d4d58428efd66f80edcf0
+Payload = 513c46fcce
+CT = 470d6bfa68e7258df363e0e9af67a543c86db3c994
+
+Count = 52
+Adata = a92e88edd297da8c7089e21822b3e6cffd6837c78b975c8413fd6cca1b99bcb0
+Payload = 9d62e557c3
+CT = 8b53c8516572b7573e5b27a1d0e15cdb7b06c8857f
+
+Count = 53
+Adata = 77d9c306aa257379053cf1f2043c388a301dac2a9e2bb89eb8bab6eb3f150fe3
+Payload = 7a05db235f
+CT = 6c34f625f9de691a412ad54bbdb6ceac45ed45902b
+
+Count = 54
+Adata = 081568ae0b948aa647b9d4dda5d42641ad5de72aa9874d8d0717d872007720a8
+Payload = 30a22ca0fc
+CT = 269301a65a8a1bb8ba3d6763dcb1bdd3400e3459f7
+
+Count = 55
+Adata = 695ba4dea0f84baf190ec25a25fc00cb9898902d7a17e6f5ff2df323b974f7c4
+Payload = 35e25aa51f
+CT = 23d377a3b9403897d496cabcd5bd9de3282199a8ed
+
+Count = 56
+Adata = 1f3ba0336a634efdd11f8168c0fe25039f9403bfa70b3898f4dbe577dbd52957
+Payload = 8bde704c74
+CT = 9def5d4ad270a81f7cb0ab7ab2b495f51d66abeee5
+
+Count = 57
+Adata = 097b9ebff3ff93a143678d59721fdf359e95cbc82585ae47727a773317925d38
+Payload = 428542ecfb
+CT = 54b46fea5dce68e9b01a4462a2221bd2f3cadf64c0
+
+Count = 58
+Adata = 76d0341dd44c39e43a23dbcf4cb602f15d5fb9fee20c3d0d262d539c3fd1dfd5
+Payload = bd6866ded0
+CT = ab594bd876f2545964ef3978cad3387d61104bab84
+
+Count = 59
+Adata = 7e7c40ad64b511005b4546f9ec61ca24829390fbc4bd8507225bc348ae0807d7
+Payload = 5822755a3e
+CT = 4e13585c98002c41938a935d51905b2a708a2c5194
+
+[Plen = 6]
+
+Key = 80bead98a05d1bb173cd4fca463b8fa3
+Nonce = 8a14a6d255aa4032ebff37a3d7
+
+Count = 60
+Adata = bb4e706e73d21df66f64173859d47e247527cd9832e20dccff8548ed5f554108
+Payload = e479990bf082
+CT = 89c9246238878427f36b1f6c633e4542f32b50ca8edb
+
+Count = 61
+Adata = 9db2182c8a4f5471082bfa1a8496602cbcdef2790f7e8f71f791303bd48dcb05
+Payload = 017a7fd1aecb
+CT = 6ccac2b866ced76fe54da69af5edf8309c7f013bb07e
+
+Count = 62
+Adata = bf483f59fb73681f27b68168c998c90ea8ceea997654c6fab2bd737dcdc884f9
+Payload = 512fc5e4973a
+CT = 3c9f788d5f3f662f53d17f7cb6673415bb2324ca0666
+
+Count = 63
+Adata = b91e641d8210e1ef705fec2beb9f58a391c7d1a38935cd1d13f2c00363388ff5
+Payload = 06212e989616
+CT = 6b9193f15e1340c86156b1065b64af1e4d6c89b32603
+
+Count = 64
+Adata = 5cebf908e232d797fcce8453c4c3000868d4172622a4ee0d6a1bdd876a0b7c96
+Payload = c45629069ebc
+CT = a9e6946f56b9c07ef5349903b928e39e99e2e32625de
+
+Count = 65
+Adata = ab92cbc97f3aa6f9ea4dae5d8c3d9e91231f43ffff548da7b668e61c183ac2cf
+Payload = b949ced37725
+CT = d4f973babf205e40654ea16e83cc6faeaad668c416f3
+
+Count = 66
+Adata = 2c3d2f9c7e89c2b9e07317c4db6e9f00f5faadfad531c5bea79d164ac24d4543
+Payload = 517ff7b383b7
+CT = 3ccf4ada4bb23102a502dbba0c280e1d5fc627fe3a9e
+
+Count = 67
+Adata = d798e77ab0f3697768f23014fd31b9e8762ae65b6aa8a4bbc17ecb8cbe78461f
+Payload = b40d863ca4ff
+CT = d9bd3b556cfa6745fd4c954396e696697731e1f9a262
+
+Count = 68
+Adata = 45b44e3dec57e24d960fd1767797ffdbbab81e38bab37e6974df262c3d932327
+Payload = 56e00289a003
+CT = 3b50bfe06806bdf2b2dd47077c98234eae5d47c3b594
+
+Count = 69
+Adata = 645d27970ccce096d082fccfc1183955bad2611af0dd7c58c9d54430f28bd992
+Payload = aa22bb1de579
+CT = c79206742d7cea66649ad7e204a344d3234125aa324b
+
+[Plen = 7]
+
+Key = dc8ec91184ba18eae31ac2d3b252673f
+Nonce = 0da4c988f521f5648259f2bec2
+
+Count = 70
+Adata = 6d5573c9279897d7d1602d8a95c04bb5ca3fad2dbe89a024b3651eb227e73bb5
+Payload = 2a5775986551c8
+CT = 4f259f2a718faea852a7c4358dfa9f5467357638acac90
+
+Count = 71
+Adata = ff0ab5021ef466e2e898b0993d691145168be558682c74914c172f2b5e863754
+Payload = 8db3c1ca0580f9
+CT = e8c12b78115e9f8767c76e707d48a2144e090812e0192d
+
+Count = 72
+Adata = 2ee03cc28f79773af139c4ea55ec4daa48bb2885b8adcd5f066eceda5c4ec27b
+Payload = 3c69e2e83236b6
+CT = 591b085a26e8d05486df740083c959fb62ef7e2e221602
+
+Count = 73
+Adata = f041504d4c1b3d5be358bd6d350af42921205d29ab22b44ffe221358adef5bb4
+Payload = 777828ab5ccb68
+CT = 120ac21948150ebdc4d2b86b2528f75db4a7f5423f4395
+
+Count = 74
+Adata = 81ea116832d69542ac8d3d22c16c82eecf2ccac39264dd933c4f9c13c8d0f1d4
+Payload = af556fef3584e3
+CT = ca27855d215a85a7b06d1b710baa15daef19069ecf46f0
+
+Count = 75
+Adata = 8a0a120ed290a62456f002da1c250a0ddb1ebd57185a733d8fb562aad482679d
+Payload = 98f26635351f14
+CT = fd808c8721c1723811129add52e1406d50cbff4aa82802
+
+Count = 76
+Adata = 12b5a76faedf6f855e328c2cb87be8aea78c5e926b32d828e167b46205c86de5
+Payload = bd22c1ec05dc26
+CT = d8502b5e1102401563d3da8a6cabb7515f642e42fb4b2e
+
+Count = 77
+Adata = 8dc32f35ef4bcbfd040ad25dc36d0bd2486f93d0cabb7704cd1582dc99f65449
+Payload = 2a87c0d64806fe
+CT = 4ff52a645cd89817609a21f703253e5e56beef4ac71759
+
+Count = 78
+Adata = 83ced632359a11eb0c4c99baad84df5cac15bc5453b6593d9ffb4c5e8c84037f
+Payload = f05f39eb0a3d64
+CT = 952dd3591ee302236c72f98da859b54be7c598d85c37eb
+
+Count = 79
+Adata = 771a818a24e7da7b98f4b4291ef34bec7e1656b0c6c6e9474a989a04ea7de385
+Payload = 59dad755af92c2
+CT = 3ca83de7bb4ca464c8cd38cbcc46e7f09bf3e1c6590c71
+
+[Plen = 8]
+
+Key = 19f97ef5318b8005fc7133fa31dd1236
+Nonce = 01ce9814c6329dbee1d02b1321
+
+Count = 80
+Adata = 85853f120981f33cf1d50fde6b8bc865fe988a9f12579acdb336f9f992b08b89
+Payload = 6d972a673fbe1ca1
+CT = 2f12a7e7acecae5d2563309efc19368cdee8266538ca89d3
+
+Count = 81
+Adata = a4ec5aee89e2cce2115b6c1f42570bc5062887cad08192a682d0b4508fcd936a
+Payload = 68b1b6367a15fe49
+CT = 2a343bb6e9474cb528096a5fec5e5359c369833eac3b7efb
+
+Count = 82
+Adata = f5499a7082bf1e6e2923211271f5f7f6d7c7b26db7963071705a58ddc4dca0dd
+Payload = 707023615563a40e
+CT = 32f5aee1c63116f2754a65863efb60c98dbb536e2b5a69d8
+
+Count = 83
+Adata = 765f267befe6fcfaaa4b46eda32e7bfab87f12ceb07fa3b37be74965bb664a21
+Payload = b56454bc50df3e28
+CT = f7e1d93cc38d8cd40b6e9b7f3b3541ffee66a1f668f67d28
+
+Count = 84
+Adata = 9ce65598cd1f86afc9aaaf172809570cc306333c25523f863c6d0e0154c55e40
+Payload = 962f765da3565bde
+CT = d4aafbdd3004e9227018c9db8baf6be349d93d4eef7d7c9d
+
+Count = 85
+Adata = d0125e30c36232a8c07cee9abc53453b276849a7c04ade80ad586ed8cbcede51
+Payload = 4f18bcc8ee0bbb80
+CT = 0d9d31487d59097c501b28887f05fd66f050525943d101f8
+
+Count = 86
+Adata = 90dfd9e7bb7bf8fb70c22a879ffa760d14cda7b79ce4968f69b8a7f2b7a59642
+Payload = ca293c9e1780b401
+CT = 88acb11e84d206fdda53dde2e1aef96b3658a7635ee54188
+
+Count = 87
+Adata = 58f518710e6b282482a7f1950fa353b13bdda10c9aaea6d5f0d7ea0a965d31e8
+Payload = b9df9fb4a6b299b4
+CT = fb5a123435e02b48b62a5ec234f1efd1b52c8fad1cf09890
+
+Count = 88
+Adata = df052e95aea3769a433ce4e4e800b8418649bbe8c6297eb07545e6802de7e807
+Payload = fb2441d1594a488a
+CT = b9a1cc51ca18fa76bc051ede6f37cf67543a7252d7d9b203
+
+Count = 89
+Adata = 0875020959ed969cfb38636d1d5aabce9658b00171a7614ea9e5395331c7659c
+Payload = 451101250ec6f266
+CT = 07948ca59d94409a5be4be6bc6b18104fac167b6e3fc15f7
+
+[Plen = 9]
+
+Key = c17944bfaeeb808eed66ae7242ab545f
+Nonce = 910b3db64df3728ca98219e01b
+
+Count = 90
+Adata = edf64f98b3ab593cbcf68ab37a8c9472e49cb849d4a744deae925a5a43faf262
+Payload = 7caae2640e734539d3
+CT = 0dae8b3ccf0b439f6ff8ee4a233dfb7753f6bfe321b3e26959
+
+Count = 91
+Adata = 29ac8fd6a20a5df4ec79660c44d373da42de7d7c5fc35982b6c29b480723b484
+Payload = e574b3a37af3bf2251
+CT = 9470dafbbb8bb984ed63b1477d9506a51ae23abbac179d8b02
+
+Count = 92
+Adata = 9ae5a04baa9d02c8854e609899c6240851cbc83f81f752bc04c71affa4eed385
+Payload = 2e3cf0af8c96c7b227
+CT = 5f3899f74deec1149bdb0986198bce2e486581c041029a81d9
+
+Count = 93
+Adata = cc8e789462879e348d20be4e1161d7b7fc6f8371d8f8cb2d25d13f0e07de47b0
+Payload = 16f22817c5b79f9fa6
+CT = 67f6414f04cf99391a0cbb2df2079a6eb964c3469f4f326122
+
+Count = 94
+Adata = c63061f2800228269015693336f78bb535ae8b88869e4ccf4ead2f3b0ea4e48a
+Payload = 64fe8076d4e8538e18
+CT = 15fae92e15905528a4a40ca7622acf7266b7c24cf0c3202e4c
+
+Count = 95
+Adata = 71c14a7031033db15bfe23b75fed9daf8886dd11392a0b787660e7b1a581af11
+Payload = 4814aaac48bdf43c92
+CT = 3910c3f489c5f29a2e7de20e98586cd5d684bf015a7abbe82c
+
+Count = 96
+Adata = 8f4947f8588ed866ed7477d7f1a28046430c6470806a50e3c9e80958c61f1b42
+Payload = 392a692b57a8a97f60
+CT = 482e007396d0afd9dc8d503f5d87818f7c0e173b857cef4288
+
+Count = 97
+Adata = 9d44f6df58c2b43db67e3daa95b176c81daff32e996d670e86405e15eae72e93
+Payload = cba1e00e345b0cb7eb
+CT = baa58956f5230a1157c85e2283d9e80700268a6459d1451d00
+
+Count = 98
+Adata = b6ada12f7a28211e9d2c07cbb3d39fa77aadc077b34c46f93006c1ca2ff66f87
+Payload = 22f5b6752582919dc1
+CT = 53f1df2de4fa973b7d1056aea3d3e4f7a5219170aaa52465e1
+
+Count = 99
+Adata = d6411fd5b25433f67ca75e4560ceb809d3721266beec358dde126b2f6a514137
+Payload = 6e1b55d6f5288c5451
+CT = 1f1f3c8e34508af2edfbfcf8200a8a3f8d995f50284a7280c8
+
+[Plen = 10]
+
+Key = 0fb9df6f638847f5de371f003dd938f4
+Nonce = c9ddf61c052f3502ad6b229819
+
+Count = 100
+Adata = 4f9938d5bc3dcbe47f6b256d5e99723d0891e50c6175aba41b011e4686113c49
+Payload = e10cc36bc1c5d3c646ab
+CT = 7f797367de50be6dc04e4cf0d8c24189affd35060cb7ca3dd136
+
+Count = 101
+Adata = e013a2edd5b86bab8df5c9940d0a0c864478c1ad42668304a643141855adac10
+Payload = 15841284c959febe63f9
+CT = 8bf1a288d6cc9315e51c4148ef85caab151488c1a6b3df540d21
+
+Count = 102
+Adata = 147d77d509f642189594df17574a0ce62b52a838feb62310e11533995ba4c851
+Payload = a8b4e5829069c335d1d8
+CT = 36c1558e8ffcae9e573ddaaa1e7c22b3efa8362abb3d31ee8884
+
+Count = 103
+Adata = 0bb09658e23fe8a08c01a6994ef36cb8dcc9a806297a09c67efe3558ca56bb5d
+Payload = 1bb2da0f1ae7e044deb0
+CT = 85c76a0305728def5855317b141383ad38dd78569d5f846f2520
+
+Count = 104
+Adata = 34eb2e6149bad764837f6f25ddd96865e5b05d5cbf233c4f6cc2aa654dfea3b7
+Payload = 63af538196add9b3fad2
+CT = fddae38d8938b4187c374e6432971aecf6bf7cf5244d21f7f173
+
+Count = 105
+Adata = b69f26fda6d1cd92897e03758cae020c4e1beb019ce5ad987f872940780a9468
+Payload = 6ef2df5a1688ae795537
+CT = f0876f56091dc3d2d3d2e4d0ffc0f0add38a80c7ffe6b4701e54
+
+Count = 106
+Adata = a7375ba32251af0138bd9fd8fcd56a7c43ab2ca9a7fc0117d25f6d4ef9c2fcbc
+Payload = 3f46c83021069ac488a1
+CT = a133783c3e93f76f0e4447fdd0b2f29f39094ba5a7375e278349
+
+Count = 107
+Adata = f9b91f7298b4e43843fc739a2f41c57c3f2cf36378fe4c34b574a43f9cedee7b
+Payload = 86c10a6dfdd6a06ef638
+CT = 18b4ba61e243cdc570dd57500f913ee3f46801e1bba9d4db7ecf
+
+Count = 108
+Adata = 9d35876d9449a1642b5062dfbfc7a26a7ac080b7198f4aeff2c79e463565cfd2
+Payload = 196c80d02b663bdd89fd
+CT = 871930dc34f356760f1856a6b87519b4807a2114ced587f72189
+
+Count = 109
+Adata = f2d5e927eb507f889efc6f21d783851f638f978c74960cc347f89f2703476114
+Payload = bd27ae3ade0781a33d5f
+CT = 23521e36c192ec08bbba2101012808adefe9b8166e04685bd537
+
+[Plen = 11]
+
+Key = 006ff7d3153caf906ec7929f5aef9276
+Nonce = 57db1541a185bd9cdc34d62025
+
+Count = 110
+Adata = 7d9681cac38e778fba11f4464f69ed9ebfea31b7ffcaf2925b3381c65d975974
+Payload = 31be1b241cae79c54c2446
+CT = 9dd8a4244fbdb30b624578a625c43233476bbb959acd9edebe2883
+
+Count = 111
+Adata = 1b0012c468009bd2851653013782c7b71ef43c393afd4dc0aec4d6d0c3fa11c5
+Payload = 8802831e22092b30110cf7
+CT = 24643c1e711ae1fe3f6dc9d477ca066ec2befa854a1faef018ea8b
+
+Count = 112
+Adata = 48b216375c00ca7e9c4048834b37944d2543e24fa091fb3c7290e11c53a6b6a0
+Payload = 3b3f782d637319d7fd161d
+CT = 9759c72d3060d319d37723eb6be9a78dfbd9e16181679b782969ad
+
+Count = 113
+Adata = f3e06a45fcf1f6abeb00727bf2c9bcea00ce621d38f7b7eba17c27e51f04c793
+Payload = e98f5e5a20d02c80372d6d
+CT = 45e9e15a73c3e64e194c533d9574d95b821a5170e9b61d8e6b2ff3
+
+Count = 114
+Adata = b36e27729f9a139d8ec4f61215b7bf1149cbb4d93a5c14bebd7cfb7c6fe585cb
+Payload = ceeed4fde3406ec40f7ac6
+CT = 62886bfdb053a40a211bf8aa193d257907be1330abaa56bc4f431a
+
+Count = 115
+Adata = 8886ed7fa414d74aef704a9751b197cbab02c41c6aedcaf65cda019dc2d2d815
+Payload = b38f03449883773135c0cd
+CT = 1fe9bc44cb90bdff1ba1f31d92029a6428748664b5c815f15ca1b7
+
+Count = 116
+Adata = 816d81af167d2294497d9b06a39fdf75e37cbacf4d10c3a444068c891b361bba
+Payload = 8efb141db7b77c521003cf
+CT = 229dab1de4a4b69c3e62f1386e4ad7c72ce0081a85d4cfd34254c7
+
+Count = 117
+Adata = f427c47e10c45bb3c7e75e9e604503b3560427691470358efdef48ddaf3794d2
+Payload = 6dc38e37d1379732df4dd5
+CT = c1a5313782245dfcf12ceb98eeb05bc376a1042735569d5b63f8fa
+
+Count = 118
+Adata = f3df712b5e8dd8e4aa8b7c5f41e93bd11b0df66a3456a01f3d0094ad91482cdb
+Payload = e0e358aff203369dd5960c
+CT = 4c85e7afa110fc53fbf732065b03ebeb68a9153cb4ed152ce0d64c
+
+Count = 119
+Adata = 264f2c7b095a296eb8ff6b5151ab3d9497ea8dc0002a9e5b09c2fd0ccd32b6ff
+Payload = 57b940550a383b40f3c308
+CT = fbdfff55592bf18edda236fcd16c8360a408e2787f930ed275bf3f
+
+[Plen = 12]
+
+Key = 026331e98aba9e8c23a9e8a91d0b0c97
+Nonce = bccfe69bba168b81cbdf7d018a
+
+Count = 120
+Adata = 26e011143a686a7224ddb8c5b1e5d31713fa22c386785e2c34f498ae56d07ed5
+Payload = a82200ef3a08c390dec5cbf9
+CT = adf4fc6f9be113066c09248fcb56a9c1a1c3bb16fbb9fbaedacdb12b
+
+Count = 121
+Adata = 97a720ae4720546e31263a1a538ce1d35c198c23bd4362e0023a67536328ab9a
+Payload = 7fc58d1bb450b396b9161f53
+CT = 7a13719b15b963000bdaf025002120b619a391fbd23402e5edd4949e
+
+Count = 122
+Adata = aff6c8cefda055c67262e9c68825d1ad2a7488e5b09640a111fabf6254d96cc0
+Payload = e9ea182d7f895f312b9738db
+CT = ec3ce4adde608fa7995bd7ad48b6e9a8de0099a28cebbf5c2bad42ff
+
+Count = 123
+Adata = 35a3963b43f47855ef3df12af5de3626e0c5c8d9cd2a534c737cd695609b05a9
+Payload = cfbc8bcbb5e5bb744bb1f340
+CT = ca6a774b140c6be2f97d1c36df80fd62e751757bb0a32a987980afe6
+
+Count = 124
+Adata = 46a2e6bd3fd5336abf02eace3cd1e1f6dde505ab976a9fa596edd6fbde7175de
+Payload = a334f8f41897cbcaeb5cffdf
+CT = a6e20474b97e1b5c599010a93b211350c70adf9bab5c01081bdc6a99
+
+Count = 125
+Adata = d110651c00ac5540f9d1ed9eb175e06b97163fc36d43f048565e5d0c30a069b1
+Payload = 3f781267290e8e73c6355e75
+CT = 3aaeeee788e75ee574f9b103d7f65690d9a2fb6759d658c9bdfdfc37
+
+Count = 126
+Adata = 978644dc4e36f1d98a2a63e19bbf8af11785d09fce58a95c00cc6bf6cecf6161
+Payload = 3dc39dbb91efe8b16396d488
+CT = 3815613b30063827d15a3bfe0d5df472f49e7f713cd1373293810906
+
+Count = 127
+Adata = 5ae7528c5e965880b1533cbd78c1e81a8187379327a2fc3f76ff45829049e183
+Payload = 6caa8c0764512baa39dabac0
+CT = 697c7087c5b8fb3c8b1655b64bfca9ef00b0f2bbb03c1a3f7a0862e7
+
+Count = 128
+Adata = afe754828be6e3731d3eee54b021b4fa182247bd958e9074fb0094a11030f5e8
+Payload = b19bc92e2305883580dd7742
+CT = b44d35ae82ec58a332119834a03be1d1d262b03c0ab425d533fe4ec1
+
+Count = 129
+Adata = 0650859c635654ca4d815963c0a99f9d2f47456ad37f739c425e924d4360bd7e
+Payload = dab87e79544df1cc98096b91
+CT = df6e82f9f5a4215a2ac584e7da61ca8461925996880e2874393232d6
+
+[Plen = 13]
+
+Key = d32088d50df9aba14d9022c870a0cb85
+Nonce = e16c69861efc206e85aab1255e
+
+Count = 130
+Adata = 0eff7d7bcceb873c3203a8df74f4e91b04bd607ec11202f96cfeb99f5bcdb7aa
+Payload = 4b10788c1a03bca656f04f1f98
+CT = 89f15b1cb665a8851da03b874ca6f73242f2f227350c0277e4e72cdaa6
+
+Count = 131
+Adata = a533b3279db530eaed425842b0d3528f5c5e4c16acfa0f49de43d6491f0060a9
+Payload = de6ea86d3641d916c4394fdd31
+CT = 1c8f8bfd9a27cd358f693b45e594271cc06f81d510075728cfeb89222c
+
+Count = 132
+Adata = 8e6c1cde142e18635c1b4f0cb54d3cf817f22ad7c25bf6a022501682f6a7da1c
+Payload = 6f3b32adc8c0314872947f3d31
+CT = adda113d64a6256b39c40ba5e5ab1aefed75400a41447b2bd8f0605542
+
+Count = 133
+Adata = 248a4389da2d51b87907dc11c46253515503ba80de5d06c9b505cb89906614a6
+Payload = 0cc992a8c736b44fedb4ad498f
+CT = ce28b1386b50a06ca6e4d9d15b46b3a6463876f1a43a287748f339e913
+
+Count = 134
+Adata = 2e2c8244a2cbf53816b59e413207fb75f9c5ce1af06e67d182d3250ea3283bcb
+Payload = 98104fd3f3413ad1f57ef4912c
+CT = 5af16c435f272ef2be2e8009f8f625786bdc58af24b17c1ba34fa87baa
+
+Count = 135
+Adata = 4ada86d88d5f49dfcde13fc30ba9a1af58d5254b47fb1885a20fad915c87952e
+Payload = 3b4fec79d52d8b2a533917b75f
+CT = f9aecfe9794b9f091869632f8bd4a918290cf97208232c76908514b07a
+
+Count = 136
+Adata = 9e3b23232e5a9e69747f8bcb148cd6d282fd9b7ecd6d97e8bb5cdc261b2fc86f
+Payload = f10c19c76ae7ed55e1651155df
+CT = 33ed3a57c681f976aa3565cd0b01d6306bb91c315bb4a23fe23d496d09
+
+Count = 137
+Adata = ccea2c815ea4efadc3007f511d633e98f9fa38b0e0fb572b282ed6a610adf7a9
+Payload = fa34af376868d9a49aa200f59a
+CT = 38d58ca7c40ecd87d1f2746d4e620d9d3004587c5d510e2a857fc857ea
+
+Count = 138
+Adata = f7277fb296e2c0d2c9ceb7013ea8b59fe37e26b3b42a0b8cd01aaaa8d35283d4
+Payload = abe2fd996bb6804ed3286c057d
+CT = 6903de09c7d0946d9878189da982d2438a5138977bde5f514e2335c28c
+
+Count = 139
+Adata = 14dd1810df3eeee78ed3836c77edf510d91ea28f119bf57111e580d70da94b74
+Payload = 395ea6979b77dabd2042aee4ff
+CT = fbbf85073711ce9e6b12da7c2b78100a05448fa6e74bd3ed16c3bd364e
+
+[Plen = 14]
+
+Key = 7301c907b9d2aaac355c5416ff25c59b
+Nonce = 7304b65b6dab466273862c88b9
+
+Count = 140
+Adata = 2c5d114eff62c527cc2e03c33c595a80fe609bfc0fe13ce3380efe05d85cceac
+Payload = 484300aa3a506afcd313b49ead8d
+CT = 928ca58b0d373dc50c52afac787ce8eeb5d5b493661259a9d91ea31a5f7e
+
+Count = 141
+Adata = d9ebc1cbfab9034317132a72e0f11c341331146a59e7a2f26bf4f3d778da52c4
+Payload = 8b318f75ed79a7978adc17c4d2d4
+CT = 51fe2a54da1ef0ae559d0cf60725552193439abfedda67d765d030cef30b
+
+Count = 142
+Adata = 9aea86b9fbd9bd4504ee2e25054942b33d3cdbd84215db7ea337e548cb706780
+Payload = 0256b0d154c768c85070da6ea8c7
+CT = d89915f063a03ff18f31c15c7d3615013c2bc9338868fad0d2fac11df019
+
+Count = 143
+Adata = 08afe10bbfbd65b948a6561bbeaf3ab46a8e3d0a861f1cfc46584156197f30a3
+Payload = 89ed296a3ac03fbfb71422b92117
+CT = 53228c4b0da768866855398bf4e66c3c4cb8c50891d6523245e4c619aa99
+
+Count = 144
+Adata = 7d653792bb8683e07c7d2c800db6f7f08343c85af2377115df4fc86ff7d8fcaa
+Payload = 414b6acb1db479028f5cc8800f2b
+CT = 9b84cfea2ad32e3b501dd3b2dada792d2cb93e45811a4c897ae9d907c9cf
+
+Count = 145
+Adata = 4d73c1484f9429eb15742f29ab05cbab6552abf40e127b93427d649d195ed25a
+Payload = 163f67b3766c3c650ce26c5bd8b5
+CT = ccf0c292410b6b5cd3a377690d441983a87812eaa7b66c5a0e54a01cb882
+
+Count = 146
+Adata = 2fba7a881f019a8745691343d79ef3656e25bb37b93fb5ab7311889f92010a5f
+Payload = 9c5b4aa703c27d16d82013853e16
+CT = 4694ef8634a52a2f076108b7ebe7b0afabd23b33765a63753cad66b0e6db
+
+Count = 147
+Adata = a640343fd4a866aec07b667d25176e11a32fb4d8bfc08fde2c46dc9b492fa010
+Payload = 99eb86b3202c7ce68a2339065f47
+CT = 43242392174b2bdf556222348ab639b8d0f97540373a7b9061aa3b2f7044
+
+Count = 148
+Adata = 9efd58d3ef5f74f663b2b5ca5e96c5a2fe85ca5eac1495d7f1751c7d8b412b3e
+Payload = 3f5c1d038161e65c9ed955c961af
+CT = e593b822b606b16541984efbb45e312c803e29f7be7c5eb236401037a320
+
+Count = 149
+Adata = a7d7ba684c0903323f7efc83dc32815195df325394162fb5a18f201047be7999
+Payload = be8dea2b4e602a787ecd28f2f7f0
+CT = 64424f0a79077d41a18c33c02201fd929c717d75388387dc25bfcf90b707
+
+[Plen = 15]
+
+Key = 38be46d271bf868c198052391f8a2147
+Nonce = 6758f67db9bfea5f0e0972e08b
+
+Count = 150
+Adata = c6de3be97f11d0e2ab85c9353b783f25b37366a78a2012cecf5b7a87138b3c86
+Payload = 61bd1385be92097e866550a55278f0
+CT = 7c9fa8d99b38f825315ece6a2613f55e902f296dcce870263ae50cda4fadae
+
+Count = 151
+Adata = 7c8cf9c650511f33af82e807e60336ec086bd2d9400a5f35652b8c3fcf968ead
+Payload = 7e5e51301fa44a21f2734731ee3710
+CT = 637cea6c3a0ebb7a4548d9fe9a5c15cae8a9e4b606f5fbeac2b829b42a150a
+
+Count = 152
+Adata = 5f8b1400920891e8057639618183c9c847821c1aae79f2a90d75f114db21e975
+Payload = 9cea3b061e5c402d48497ea4948d75
+CT = 81c8805a3bf6b176ff72e06be0e670f5419c6085e5434f056162cf80f6729d
+
+Count = 153
+Adata = 238d3c9d9de32f2040b1dd0dd040b921e456c3653263f4020cffdc552b948a46
+Payload = 20660408d6890aed84aa65dfe23032
+CT = 3d44bf54f323fbb63391fb10965b377fedcc743389a9d48e6b871dc0dd63b2
+
+Count = 154
+Adata = 3b5d61ca21953fdd22280747dd4ae908a511750127875da84dfe7d0063a318c9
+Payload = 9ab83c81f2d2c896c6596660c3974d
+CT = 879a87ddd77839cd7162f8afb7fc488137e0a856d3d911af9f420b68d8110d
+
+Count = 155
+Adata = 78c1751e86144a78285a30dc04f51742bd47e3d36b607bab48d91cddabfff4b7
+Payload = c1ec469aa9c73b677af225a9f5f6f8
+CT = dccefdc68c6dca3ccdc9bb66819dfd5644448fa8445b6cd185bdf9b3718033
+
+Count = 156
+Adata = add33e9a1d7e91e2c160c1123537e3f7e3535881cb4aac1a80ecbe367379212c
+Payload = 9df1d6b6debffdd316aeb27143508e
+CT = 80d36deafb150c88a1952cbe373b8bbd38e4dc44f768cef0c51344e3a7f7b8
+
+Count = 157
+Adata = df7736560b1a13aa8e536500ea6cdb9a6757309aadf25a6a9189055a309c3f8b
+Payload = 19eef017100dc82f26ed0815c55c12
+CT = 04cc4b4b35a7397491d696dab137172e7f2ec918099898b843a34c385f2a57
+
+Count = 158
+Adata = b40c8d22069b8a65cddb51c1ea3571160cacb19fd371552436b19c7122b28d08
+Payload = 2af5db43f2a5fe8b494b40661510bb
+CT = 37d7601fd70f0fd0fe70dea9617bbe94c2709685b0827cc42f3a25b579db28
+
+Count = 159
+Adata = 9de5559ea8ccc70f4375a436ce0b72551a75960ad5ed6a1949ee8f6c47548558
+Payload = 5de41a8ca8ed8011304fa9e9f36498
+CT = 40c6a1d08d47714a87743726870f9d63bf4b40ce7e672587816fdcda16efbe
+
+[Plen = 16]
+
+Key = 70010ed90e6186ecad41f0d3c7c42ff8
+Nonce = a5f4f4986e98472965f5abcc4b
+
+Count = 160
+Adata = 3fec0e5cc24d67139437cbc8112414fc8daccd1a94b49a4c76e2d39303547317
+Payload = be322f58efa7f8c68a635e0b9cce77f2
+CT = 8e4425ae573974f0f0693a188b525812eef08e3fb15f4227e0d989a4d587a8cf
+
+Count = 161
+Adata = b6fecd1edeb55a9a4148b1aefb716a1e162779a5ab2a682e4adce4479c527bd2
+Payload = 0e6118d0409751d36cb642504678535e
+CT = 3e171226f809dde516bc264351e47cbedf7f186e8d3d7c21c549c41ebcc7f505
+
+Count = 162
+Adata = 5c3933c30bf9d4841eff4000aaa1cb4d39cdf8ef1240e2aabbf9da95bdee5270
+Payload = 5c8a5fb36f860d00c21ae9e3f24097c4
+CT = 6cfc5545d7188136b8108df0e5dcb824810a68be1814f53c09aca4066527fef8
+
+Count = 163
+Adata = 7ca7ef30d3ac08aa51a9e5d3d84e8b6bb7fdde921e72b98ad6a93ebf2efc6b04
+Payload = ebd1cb4b35257790c9806be476bd25a3
+CT = dba7c1bd8dbbfba6b38a0ff761210a43cc30245a6e64625c4f6531d7497fb144
+
+Count = 164
+Adata = 90f1416768fca7dd48d01230dabf95f2f1a0c044bf2d755448aaf72316c8448c
+Payload = 842b7e5f22d921b2b8ab3131684b7eff
+CT = b45d74a99a47ad84c2a155227fd7511f10d85725dacc274034669acf7f34fed7
+
+Count = 165
+Adata = adc5c36849283d57acb2bcbc0e12465cb7c1830cb4e314b9ce6e25acbd8d460c
+Payload = f0c2cc5a1b4c4cbe839338fa0d7a3435
+CT = c0b4c6aca3d2c088f9995ce91ae61bd5f731b465eb59c4989e42020d86102a59
+
+Count = 166
+Adata = 80a7a483d1dbcdf00ed02a700e93d8b87fa6ac5c7368d1e81bd1b32cd1621cd7
+Payload = 2c1a5f906f2ae0373cc25e3519df2ba4
+CT = 1c6c5566d7b46c0146c83a260e43044484bcd2775448447ed801b3b0ff071c19
+
+Count = 167
+Adata = 13c02992992d2708250184a579c43bc29a3a8cf1e02dade4496cbd8b1214f97d
+Payload = 1da5190517546f1ad852f64263e1f679
+CT = 2dd313f3afcae32ca2589251747dd99901d1919f1451ad16f115cde863f15303
+
+Count = 168
+Adata = f6f18dfe093e4c0c3fbfa8a5b1f4a703c08addc2ab959741611a594b93d08bf7
+Payload = 13ccb08a580efea53dfba6a59626bbe2
+CT = 23baba7ce090729347f1c2b681ba9402ccae4f6ec07bf73d6f086cf09e2e14ed
+
+Count = 169
+Adata = 63708e12dfa14f192ec5ee5856dc3cf2403817d9628c31899b4613f65e1e61c2
+Payload = e0b5fbc6c2269d445a60273bf844892b
+CT = d0c3f1307ab81172206a4328efd8a6cb2bad8bf67d32a855c3940ac908397a5f
+
+[Plen = 17]
+
+Key = 79eae5baddc5887bdf3031fd1d65085b
+Nonce = 9da59614535d1fad35f2ece00f
+
+Count = 170
+Adata = 46603500af9e4e7a2f9545411a58b21a6efd21f2b5f315d02d964c09270145b3
+Payload = 001343e6191f5f1738e7d19d4eec2b9592
+CT = 2162e27bfbf1d00f2404754a254665fd9270f0edb415993588b2535e2e0e4fd086
+
+Count = 171
+Adata = 278afebc604bb7d87bed3574a2c5053de17eb8ca7e18ddc7892f2c54b38104a8
+Payload = ba47d5bfb36f6150a100e36caa116405c4
+CT = 9b3674225181ee48bde347bbc1bb2a6dc4778e3c4a11f3f9dc42554d45796379ef
+
+Count = 172
+Adata = 3239b2ce4efe4f6a6255dc53347400a6446ed3280c65422386fab471ef09eed6
+Payload = 96eccb7f9b0e16c6883de0a381e4767f5a
+CT = b79d6ae279e099de94de4474ea4e38175aab5540cc01d867f641c9b196fa159291
+
+Count = 173
+Adata = e2a5488d5f7930ea4ce399f2a6c0810265f7c0dc52fe824d19a0fa0d9ffd55e6
+Payload = d68f5990da1a2fe39ed81af145ab834fa4
+CT = f7fef80d38f4a0fb823bbe262e01cd27a46366fbe302e142dcf6aa16337d98550f
+
+Count = 174
+Adata = 0071f1edb3a0ce57af3c88bb0ccf138f752697a77e55695838fb39de04c78dfb
+Payload = cdd4d8b3d8f6e4742793b456cefc9e686d
+CT = eca5792e3a186b6c3b701081a556d0006df88c07797267bf5a49b3d0f601a225ce
+
+Count = 175
+Adata = f5d6989587e463969d97aadabea9538511f8d109cc2d3cecf09ba7cc346aaea0
+Payload = e7d7fc60ae852b68102e01b506f9dab986
+CT = c6a65dfd4c6ba4700ccda5626d5394d1865c9fbf69d81cef238ac513562d4a0dd5
+
+Count = 176
+Adata = e0b5fbc6c2269d445a60273bf844892b26fed03b82869edacd6dd7a63fd69e8d
+Payload = be9f51abfbe2da5a56db0f9a31b67c9f83
+CT = 9feef036190c55424a38ab4d5a1c32f783e2c748c8c9e3190de095de8eb0650203
+
+Count = 177
+Adata = e6bd0010c98e60b9af7cf905c58e0653bc425e2ccc809bd4f9cd7b1f95c18786
+Payload = 81b9c73029cea1936ef8755c80ba8d4093
+CT = a0c866adcb202e8b721bd18beb10c3289305cf563c5b4ba4ebd5bf107f2ad3555b
+
+Count = 178
+Adata = b1688cbc058816974694cd26c0f28ba9418e9912867fc8c5f4e7bd9c891a8d2e
+Payload = 618dc26853ee339689467ffbc2a77be69e
+CT = 40fc63f5b100bc8e95a5db2ca90d358e9e60dbbd8f46343c8442b03a472da4e23f
+
+Count = 179
+Adata = 469e004fee9878ed40621b41d04ec34af175f213d64d16e2f77d0bb2b6efe2e3
+Payload = 4f18bcc8ee0bbb80de30a9e08629323116
+CT = 6e691d550ce53498c2d30d37ed837c591643352e46995e8c1aee43dbdb26b46c30
+
+[Plen = 18]
+
+Key = c14eda0f958465246fe6ab541e5dfd75
+Nonce = 32b63ca7e269223f80a56baaaa
+
+Count = 180
+Adata = 733f8e7670de3446016916510dfe722ce671570121d91331a64feb3d03f210e6
+Payload = 617868ae91f705c6b583b5fd7e1e4086a1bb
+CT = b2dc1e548b3d3f225a34082f4391980a0788b4cc36852fd64a423fb8e872252b248e
+
+Count = 181
+Adata = b6ec659856866959ef6fd4e71ba930f0e3e5fd49d7465fd65f6813ab4ca1a770
+Payload = b8b342c49c28bffc2a1c457db0b537ad46bb
+CT = 6b17343e86e28518c5abf8af8d3aef21e08895a66eb5b902bb23a1a8584249409fda
+
+Count = 182
+Adata = 89eb3636fff80230352a3582be5698e3401c9e0579d48f2680c6e5e24d99f74b
+Payload = 37d694ba94d0af8df662134f20d142903839
+CT = e472e2408e1a956919d5ae9d1d5e9a1c9e0a7fa792fb7246218f7d56d5fa4a5476bd
+
+Count = 183
+Adata = 03434f3709e19a1e37edfcaabc215116763b71ab1c5e053dbdb599f86959f25d
+Payload = 90e4c0550cb7b279ef61f9140b7d94b8003d
+CT = 4340b6af167d889d00d644c636f24c34a60ea83dc3f0012ae6da32a15fd1684835ef
+
+Count = 184
+Adata = 0e2ddb65fcc72094ac388d53a1055c7e902285c4c3c33c13bb6fbb4f1956414a
+Payload = 69b851e63a78baef90637978e3dfe8c47be4
+CT = ba1c271c20b2800b7fd4c4aade503048ddd7f09d38d3dba01995e36bd685c8ea3371
+
+Count = 185
+Adata = a42b2538ee2fb5f6a85d4d00524b01ad3331f61c404069243f35f28e2c2d0a82
+Payload = b7dbf8382115199dd2a2d87938c6ae6c4241
+CT = 647f8ec23bdf23793d1565ab054976e0e472c89becf8d2bb935cb17f44b950df3ef5
+
+Count = 186
+Adata = 09bc5c426dc1faa4d71f50908bd6f297ec8e754d4d20def005585b4bc1fa31da
+Payload = d53698d719c51bf9eae346269c6a1da07162
+CT = 0692ee2d030f211d0554fbf4a1e5c52cd75196e28badf0202097e80561451796194d
+
+Count = 187
+Adata = 2ac87e59c2c86532cf165af3e8ff4871d730f5e742cccca38bbcdffff4472c93
+Payload = cfdb7363985aa01af6f8e8237dbfb7871eb3
+CT = 1c7f059982909afe194f55f140306f0bb880710d4d7f66660891ac655d6eca4a3f3e
+
+Count = 188
+Adata = 05d2fbc3d0ec81f52f31cb0c4bf960c2076867f6d9f0174ed9176e20177b2693
+Payload = 56fdf10dc0c1dfd10965b83938e557459c61
+CT = 855987f7da0be535e6d205eb056a8fc93a52f90ab18925fea6964490f364a975a473
+
+Count = 189
+Adata = c2c3902cfe8622254b3787cc13e79c5a3c388c2357c29f1c1ab5539a10bfae5c
+Payload = e7c9812eda2ed7dcfc80fc5fe0d43e1e5982
+CT = 346df7d4c0e4ed381337418ddd5be692ffb168a00e5e7a39b371024927d3ac98fe43
+
+[Plen = 19]
+
+Key = c5e7147f56ba4530b8799ababeb82772
+Nonce = bdd38e173fb20b981659c597d6
+
+Count = 190
+Adata = 3a069a2bfda44abbb0a82a97e5e9047258c803da2c66190d77149e0f010b3af9
+Payload = 2f3bf0b566440912a1e47a0c07f1cfd39cb440
+CT = bd6265dcba9e14c59e515e395dc60bd053345fa6d7568c738e3a7fdf142d8f2d1562c0
+
+Count = 191
+Adata = 7709132415c94960025cc39c950ead208703a9d5a71e224fd022dc0a1817d0f4
+Payload = 7c880d787726c4ddeb2304b5d161b4a257298e
+CT = eed19811abfcd90ad49620808b5670a198a991f22337efa5cb7db7240e7518b67ffbb1
+
+Count = 192
+Adata = aad77595f87a27f2c7995fc7149317f4cbebcece8336db2068380070784a4283
+Payload = 08c43bbfa706512aa39e2bfa5c365aca11e22e
+CT = 9a9daed67bdc4cfd9c2b0fcf06019ec9de623140bac6094528f02eeda093312fcf716f
+
+Count = 193
+Adata = bdb1b82ba864893c2ee8f7426c7b9a8460b00a50f164fc8f2ff2ae9cddab8657
+Payload = a531c0ed8840b2fcf08d76eca71036153b6e11
+CT = 37685584549aaf2bcf3852d9fd27f216f4ee0e0c041d86dd483c1d6da366e91bd826dd
+
+Count = 194
+Adata = 38b3b9f45041ceb743fc2655b409213fa081427e41c833a2321a09fbd566c80c
+Payload = 177946b4dc3b0b825a505f097a0a203eb21c00
+CT = 8520d3dd00e1165565e57b3c203de43d7d9c1ffde45ca2a83dec2f930bb652a6fcdc5f
+
+Count = 195
+Adata = ec9d8edff25645520801b6e8d14a2fc3b193db70d5e5e878742de83154a578da
+Payload = a2634ef20a2a418b2c3be64f0b5f79d7ea9b7b
+CT = 303adb9bd6f05c5c138ec27a5168bdd4251b648b89aa22cd7d0170a975565cd3a33dc1
+
+Count = 196
+Adata = 8f6c1de4efdc5ac2d6e5452b5b4f58416d618da672f521332fd297ede8350134
+Payload = 40e52edaad5acf2d4eedfb3f9ac2908112e9b1
+CT = d2bcbbb37180d2fa7158df0ac0f55482dd69aed960b33c3df5cd38a82980dc0950ada4
+
+Count = 197
+Adata = b0f1dc85fe223bcf29cdfa9319866bacd0a0a79c554e24d1f10889279e31c0af
+Payload = bf97780f498c23adcf1c49f60873780a235969
+CT = 2dceed6695563e7af0a96dc35244bc09ecd97638fa273c4102b5ca050b23044ac2064f
+
+Count = 198
+Adata = 7d02a323aa769a8201549bf48a520d940bf6f69ed6106f1ce68856c22a594216
+Payload = 58bfe1eb2d38d91f80b3467db94fdcb84ff5f3
+CT = cae67482f1e2c4c8bf066248e37818bb8075ecc15438af1bafac3eac61e1c24ed00ab7
+
+Count = 199
+Adata = d4b90ef8abad08c552c8c3b080b8c37df314d514049d45e27ec4527cb06cdf85
+Payload = a206a1eb70a9d24bb5e72f314e7d91de074f59
+CT = 305f3482ac73cf9c8a520b04144a55ddc8cf464422d9e2f4f84fde49e9701296294d5a
+
+[Plen = 20]
+
+Key = 78c46e3249ca28e1ef0531d80fd37c12
+Nonce = 5de41a86ce3f3fb1b685b3ca4d
+
+Count = 200
+Adata = e98a77f2a941b36232589486b05f4278275588665a06d98aec98915cc5607e06
+Payload = 4802422c9b3b4459ba26e7863ad87b0c172cfe4b
+CT = daea2234ea433533bf0716abe1aa3844b6d3c51e9d5ca3d8ec5065630d2de0717cdeb7d5
+
+Count = 201
+Adata = 5970a836de1f1e91d94d7eef79742cbbd46a759c413715eb0224fd6a27145333
+Payload = 796a69ad0e9379173ef6b66f44f5c84fa70a0e28
+CT = eb8209b57feb087d3bd747429f878b0706f5357d0ff0648ddb07f42f815b38bfc95688b1
+
+Count = 202
+Adata = e3f08834c4894f6fa66a55a280c0e677a79e97c1ef9488b21384e74e57b1b51f
+Payload = 98e1f8cf250183b13ad418024dc40c1a6a7ee8ac
+CT = 0a0998d75479f2db3ff5e92f96b64f52cb81d3f93ddd9a6977ea8e7adf5c5234346e560f
+
+Count = 203
+Adata = 18349be2894d49290339b97f4db28c92b3e112ffac77100abbf9c093935b1a46
+Payload = 4a856d9b50a5b40d6566b38eae6a53ed0c192805
+CT = d86d0d8321ddc567604742a3751810a5ade61350bdee05328a7ea8cc6c2e42bf3faeeda0
+
+Count = 204
+Adata = 7355e34ad13880de17a1d66b02672ea5c9f51774019f64ecbe36747ffcd9b671
+Payload = ad048eb2ad75266b43b59d9d1f073c44e4cbf25e
+CT = 3feceeaadc0d570146946cb0c4757f0c4534c90bafb1435cf929db35ec5986aabaf4a7d1
+
+Count = 205
+Adata = 4be21ba2eb26234ddcbb6aac6b4c3be7ef644af64edf51b7c29ffc3ddd80036b
+Payload = 5b527ac6cc6d1b4c3c56f8315bc96dae91632df9
+CT = c9ba1adebd156a263977091c80bb2ee6309c16ac736be6563cf9f5bce97486b7cc6f1c18
+
+Count = 206
+Adata = 266e0e3365e06d3b1e864c6e5897145df7bdde90eb744013a7b36632d4cf6580
+Payload = cee059cb0fe91a39faccc2914340baeab4b644ce
+CT = 5c0839d37e916b53ffed33bc9832f9a215497f9b2e90335fcea56b969b4fce65442768dd
+
+Count = 207
+Adata = 55a723883a340877d85ad1a5f264f2c834d824c7bbf207cdd8500c9d11ef9225
+Payload = 85321fef6a2b7d31cbd079c4bf2bfbbc979df90b
+CT = 17da7ff71b530c5bcef188e96459b8f43662c25eacd6afdb3578ebc75e8a408d32758931
+
+Count = 208
+Adata = 773864475a1a60a778468a66cbe13dfe3458094e62abb593f50c8495e3a8b81e
+Payload = e227b8d44320bd3ce9d3f7d688f3de887947b1e9
+CT = 70cfd8cc3258cc56ecf206fb53819dc0d8b88abca19fb73fc0488d9f29a09c1b47e3e066
+
+Count = 209
+Adata = f64f3b00c9117aed3c486aa4c8d574b44d679be4069e1078bb7100af38cdb190
+Payload = 206e9eb2bc3f8534d844a38debf1306df808744a
+CT = b286feaacd47f45edd6552a03083732559f74f1fce2c5ef8cdce76b358739e2a1b173fb3
+
+[Plen = 21]
+
+Key = 8883002bf13b3a94b2467225970df938
+Nonce = 818a702d5c8ee973b34e9acda1
+
+Count = 210
+Adata = 545aeac737c0ca2a3d5e1fd966840c3a0d71e0301abbe99c7af18d24cc7e9633
+Payload = d516bbff452e7706c91c7ace3e9baa76d65ff7050f
+CT = b85242fdc06344f2bd9a97b408902ebcd22aece3d42f2da4dd4d817c9fa2d44bc02163a0a9
+
+Count = 211
+Adata = f032db01da60ca078d35c3fb5d05d6750fce1c01911a0422e827e8976946e4dc
+Payload = 590d1aa655fed50ca2e402299f2da6fe20eed56071
+CT = 3449e3a4d0b3e6f8d662ef53a9262234249bce86aa180f41bccbcd47c8b7890754c032269b
+
+Count = 212
+Adata = 71ecb4252518997b53491cf42a3e0fe1496a2af2329a16f9fcd9c4f249900341
+Payload = ecd86cdb7d78d310dca5b477cd9da2612f5a05ab39
+CT = 819c95d9f835e0e4a823590dfb9626ab2b2f1e4de21d6ba58cc2eb474401851bf9502c3413
+
+Count = 213
+Adata = ec7abed9bda4a52fdf1bf278b6bdd6b0a27d4688deb9ff5ca9c8c865a4d2f730
+Payload = 0024b14c283df032cf80c22ad8d2c96289ee229092
+CT = 6d60484ead70c3c6bb062f50eed94da88d9b3976499b94d4b7a2044696c72322e850537b6d
+
+Count = 214
+Adata = c2c77d7ad7b27d7c0f976a1e28881ea4ec7ad03b63a4e67f47280a40b8f58086
+Payload = bc6965d8f62d066d118c14044c1fd2a224b9d95110
+CT = d12d9cda73603599650af97e7a14566820ccc2b7cb9d8da8e718570caf8bed7909fbff3ec6
+
+Count = 215
+Adata = 28929286bd1391468ac75f5c03689f74780ddd7585fc16f9a9bf7b00357a72e5
+Payload = da4a630cabaff0728a1cc3e6a79721a7176b708f1d
+CT = b70e9a0e2ee2c386fe9a2e9c919ca56d131e6b69c6e671012690c61fe3c9abd50a78eb4736
+
+Count = 216
+Adata = ed360d22081b019dc979420a3a45c21c8903c59daedd9f1b4ef2bfdedff0ec1d
+Payload = a95058f8e1f6bc0f143a9ca7e4425a2a63eb2f7e33
+CT = c414a1fa64bb8ffb60bc71ddd249dee0679e3498e8e657e2250427130acef7032454cde7b6
+
+Count = 217
+Adata = 2b4022d0b951fe48635d04fb3e2fa032c07c855fdd73f45670953bb9ddc77cb4
+Payload = fcbbc7f9d1ace60e830ca56ec84814fbd2579993d4
+CT = 91ff3efb54e1d5faf78a4814fe439031d62282750faac6ff0a264b8199550d93c1f06063da
+
+Count = 218
+Adata = 48e553a87a7d3c1bd68af39f96aca67583da86e06701d5e4c4ed404dc66d70f3
+Payload = b95d298d391c6b893c6cad66f9780534516e71455e
+CT = d419d08fbc51587d48ea401ccf7381fe551b6aa3857e68bf636e81c332f72063dc0d6fc2b6
+
+Count = 219
+Adata = e8e2835e47144365a2f218d4c95d7522e824fb43b66d4727ee570f8303dd6dd3
+Payload = bc79d444dff9d9e722effab07b068cb7723ae8fae0
+CT = d13d2d465ab4ea13566917ca4d0d087d764ff31c3bdf3af9e9c4e04bad261dc17cf00a00dd
+
+[Plen = 22]
+
+Key = 5cea00ee44cfb9cfbb598d3812e380ef
+Nonce = 948788a9c8188cb988430a7ebd
+
+Count = 220
+Adata = 50422c5e6a0fb8231b3bb6e2f89607019be6ad92a4dae8e0fe3f9e486476004b
+Payload = 33bfd0713f30fcac8f7f95920ac6d9b803ddd5480dd8
+CT = b168747dea3ae0fbede4402af9a3dc3185d6d162f859d828101682de32923788c70262b84814
+
+Count = 221
+Adata = bb0036b34b0c20094d335a8c74f6b3dea42eeccf4145192eada64ae00c726b2e
+Payload = 5576d94b577ed26820fb13c00ab0e2d1a1c3589bfdc4
+CT = d7a17d478274ce3f4260c678f9d5e75827c85cb10845bafc4ae4d31907def6f648b081174e2a
+
+Count = 222
+Adata = 5140324aa758dbbb5391b5e6edb8a2310c94a4ae51d4fba8a7458d7cc8488baa
+Payload = 13303e14068205cbfa992d4ccb6a265804ea64a15d7f
+CT = 91e79a18d388199c9802f8f4380f23d182e1608ba8fe314e378e9ed6e725a14c07632b02bdbd
+
+Count = 223
+Adata = 74da07d324060e590356988f27d9879fa3a3ade0fe71e2a0e49054211cfa1fe1
+Payload = 567e6d14b446add630d53ea86a537c0938537c4604a8
+CT = d4a9c918614cb181524eeb1099367980be58786cf1295bc2f2f9331536f7f70be09c41bda0ad
+
+Count = 224
+Adata = 0e403cff47adee3ec5bb6b178dabfc7d53b60a04eaad33a2fedd9db705358a4c
+Payload = 9f3d165d44cf1c5770346d211d4ff34ca2ecd6b28549
+CT = 1deab25191c5000012afb899ee2af6c524e7d29870c86b59cc9c3c008bc5876ef86327859cbe
+
+Count = 225
+Adata = 211e6ce3d0c3abdef069e6e4fa35015797bd8a9d64bc9b75f20b028b12cca04a
+Payload = d726e599db6a6d40629bc4bda5e3fa2e5aeda229cea4
+CT = 55f141950e607117000011055686ffa7dce6a6033b25135e6d59a5385a78658d60d254f99962
+
+Count = 226
+Adata = 3c5c67b083322115e1b3112c2b6968efc050094e23e646dce982eac9d6e67d10
+Payload = 42646cfb8a99e48a35cee3f5f9b3e6175695973f6de0
+CT = c0b3c8f75f93f8dd5755364d0ad6e39ed09e93159861e234e83d9a0570dbf2b2fa59ce3cdbd9
+
+Count = 227
+Adata = 37a931f1dd05755b376d1a164aa36b8de802e39f8108a0453c1114754665fe46
+Payload = e814c7b5c72d973a9bc7ccd463f107325ffa3321783b
+CT = 6ac363b912278b6df95c196c909402bbd9f1370b8dba2084e352b1b157267228576dd056c1a3
+
+Count = 228
+Adata = f1ddc2c49da7363526ba36c600c589b4c3121fbb8c5b9a8aa0de0e7453b30568
+Payload = 4f7a5618870945b89f194e31b1aa802c5350326dc691
+CT = cdadf214520359effd829b8942cf85a5d55b36473310bf88ad35ee338e489e55bb49732447cf
+
+Count = 229
+Adata = d14b3d3803df432488b5d66704abef6a500d397e855bc2c2574df746a515cf70
+Payload = f555216840a1f40b411d44128e567617e2694caf1621
+CT = 7782856495abe85c238691aa7d33739e64624885e3a07ab67f9397a81371ef6ebc775cb7007b
+
+[Plen = 23]
+
+Key = cb83f77751e72711401cbbf4f61aa0ed
+Nonce = c0b461b2e15b8b116ef9281704
+
+Count = 230
+Adata = 2bd112231f903fa0dff085db48a2e2a96ec0199249b005d5ab4c2eab753f9ad0
+Payload = eede01b08f9a303cdf14c99d7a45732972c6eff2a1db06
+CT = feb114b7bd3b43497b62454a675a632c3546d2802462c6af57647efda119c59862cd5dd3904efc
+
+Count = 231
+Adata = 864e0e728aea856fae6c6daa6357d1542cef7177f441ba21a563f6c4f6fdc1dd
+Payload = 8a56588fe5e125237b6cdc30f940b8d88b2863ec501a0c
+CT = 9a394d88d7405656df1a50e7e45fa8ddcca85e9ed5a3cc2af4027ca5824b41c7bb238d3e8eeebf
+
+Count = 232
+Adata = dac7f3cba0b5a47f67f85b226b66df695a8ae2501355e36aad105375bb95f732
+Payload = 66e34540d7accf377877aa2d3e6d2db0cfafc608a1eb3d
+CT = 768c5047e50dbc42dc0126fa23723db5882ffb7a2452fdf7fbd7044ce1d7b266bdf545247a3c2b
+
+Count = 233
+Adata = 07f48cdc12aa27119fbdfda4ec07ce6068c92ba7ba9c930905aadd156b1dd56e
+Payload = a9ebd04fba7155c39b5c29c5571b5354c9ae228f5e5b13
+CT = b984c54888d026b63f2aa5124a0443518e2e1ffddbe2d3afabc559b552cf7c7730c7dca25bc3ed
+
+Count = 234
+Adata = 2d24e79abd157af2c21b60932947fd9f9d6478f09ec56fffd341ea04a17b8e5f
+Payload = f179353aef342f0f691caf1fcb811e3f6504e14d6d9381
+CT = e116203ddd955c7acd6a23c8d69e0e3a2284dc3fe82a41488ca99e0f85ac388f981ce25560b8f9
+
+Count = 235
+Adata = fea280f710379e4665b5ed3d1620729a7bc164899dc83e6aee3612d538fa20db
+Payload = 6c19a18eab544acc883c5886eaa89f54d61ae5f1f1368c
+CT = 7c76b48999f539b92c4ad451f7b78f51919ad883748f4c9156faae3d8860bed216e8d497a75962
+
+Count = 236
+Adata = 18f2e3457127c35f2e0cff2d821af8178028fcc7803bc795c49f4a435b37abeb
+Payload = d0df1bdf1df6203241722fb9c9c1cf7405017497ae1545
+CT = c0b00ed82f575347e504a36ed4dedf71428149e52bac8588cd7791c544d1098b2de49d04b1e0c1
+
+Count = 237
+Adata = 35221f0efcb109cb93c38a62c58b5ab8b236437e171e8507cf417a569af1767c
+Payload = 479526b33c42c240b9a4549ca70cbfb691f16ae3be8888
+CT = 57fa33b40ee3b1351dd2d84bba13afb3d67157913b3148c523fd8a2524717f63dac75c22268fa6
+
+Count = 238
+Adata = 95f2ab02af01aeacce86b02cf846f9fbd516963d06e350e8b7f6df2778765a01
+Payload = aa6761148b254a2ff202b620c2ec2c5e623bf61f05e483
+CT = ba087413b984395a56743af7dff33c5b25bbcb6d805d4392904f05dc2397596543df73de5aa708
+
+Count = 239
+Adata = 3746a36154e42dd600049d506f5ce4d034864263b1a65cecd24c8e25fb9c82e1
+Payload = 2f298f106703b8a994cbb20acf47f9442e44f6b5e82c38
+CT = 3f469a1755a2cbdc30bd3eddd258e94169c4cbc76d95f8c3cbfecfa3f75fb111ef0011222b7948
+
+[Plen = 24]
+
+Key = 43c1142877d9f450e12d7b6db47a85ba
+Nonce = 76becd9d27ca8a026215f32712
+
+Count = 240
+Adata = 6a59aacadd416e465264c15e1a1e9bfa084687492710f9bda832e2571e468224
+Payload = b506a6ba900c1147c806775324b36eb376aa01d4c3eef6f5
+CT = 14b14fe5b317411392861638ec383ae40ba95fefe34255dc2ec067887114bc370281de6f00836ce4
+
+Count = 241
+Adata = e82fc3ffd276218a82aede65fe5abf4fd35c7059a26923f8dbb97a59c903a7f4
+Payload = eab8cef576816a82ed036f158e5036f5987b195e60582a6f
+CT = 4b0f27aa559a3ad6b7830e7e46db62a2e578476540f489460d2d30268e9f1ce0e7c762993297d828
+
+Count = 242
+Adata = 776aae7f62225556b6da522c0c9432ac70fe72ac6f3f361071ef3deb4a6715e8
+Payload = 566ef9ce1d397be2547c385639507a9e7d6f9eed9a3b1055
+CT = f7d910913e222bb60efc593df1db2ec9006cc0d6ba97b37c0939e56f0b7200d1b1409f3f8e8179cc
+
+Count = 243
+Adata = d9aef0955922f89747ba4a8ddcdb8c1c7579aefd3c2eb8ad0589c66576a8504c
+Payload = 8c28b6d93b23f1ea031d5020aa92f6608c3d3df0ee24a895
+CT = 2d9f5f861838a1be599d314b6219a237f13e63cbce880bbc138e3b817023993608be06fe92efca8b
+
+Count = 244
+Adata = 13c222a65ce30570ecac85a185a2a0922a8c96d633339a1ca067ce57ae426e1d
+Payload = f0c1cd60f5fa8d1efd5e2e1ab37c4f7e6aef76d15e8d6ac8
+CT = 5176243fd6e1dd4aa7de4f717bf71b2917ec28ea7e21c9e1f3ca13b4ab7fd0d4badf158972570c06
+
+Count = 245
+Adata = ce40fb0cbfdf07676ed55b040ae6be5db8f0a0f28816ae8ea71da3cbd71661d8
+Payload = 570d5f79aa8db14b1ac99ee567cc105ae9e238e482b52628
+CT = f6bab6268996e11f4049ff8eaf47440d94e166dfa21985010a79fa4e8b27a31ff360a1b6c05ff844
+
+Count = 246
+Adata = 446b01d09cbc41b6393ef81ca65ab7e099018187d5f9d22f5074dfc491e72077
+Payload = 7c267223047af946b06f6a45ffde4a5ec49c28b81ca22da4
+CT = dd919b7c2761a912eaef0b2e37551e09b99f76833c0e8e8d5d34ef0ca0b47d6a2ec7442cbb739504
+
+Count = 247
+Adata = 01ec87920b42639d4ba22adb1fbe5138d2849db670a2960fd94a399c1532ed75
+Payload = cbf112e4fb85276c4e09649f3de225b2398e86ac3fe48bc7
+CT = 6a46fbbbd89e7738148905f4f56971e5448dd8971f4828ee8f607d154393e35fd1efc1ae8cb244e4
+
+Count = 248
+Adata = 5032b818d202872f3fe2b08fc7940696df02cf393a6d6247f5c6f5f2125cb08b
+Payload = 4324a89788e8ddae5d560cf937df701743cbbc3bf980558c
+CT = e29341c8abf38dfa07d66d92ff5424403ec8e200d92cf6a5617d9cebea38591a00c9fba4ef9c8e71
+
+Count = 249
+Adata = 27b661861717f00a3ae22ead78f4dc3f32b40e8fcb8ed58167a31a61f2becd77
+Payload = db72d98d63fc10acff7dceec0e2691a80ecee50a0e957ad1
+CT = 7ac530d240e740f8a5fdaf87c6adc5ff73cdbb312e39d9f897062a1ec759a515b938780f902fa7c2
diff --git a/lib/crypto/test/crypto_SUITE_data/VPT192.rsp b/lib/crypto/test/crypto_SUITE_data/VPT192.rsp
new file mode 100644
index 0000000000..abf1775dd1
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/VPT192.rsp
@@ -0,0 +1,1383 @@
+# CAVS 11.0
+# "CCM-VPT" information
+# AES Keylen: 192
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Nlen = 13
+Tlen = 16
+
+[Plen = 0]
+
+Key = 086e2967cde99e90faaea8a94e168bf0e066c503a849a9f3
+Nonce = 929542cd690f1babcf1696cb03
+
+Count = 0
+Adata = 58f70bab24e0a6137e5cd3eb18656f2b5ccddc3f538a0000c65190e4a3668e71
+Payload = 00
+CT = 3bf9d93af6ffac9ac84cd3202d4e0cc8
+
+Count = 1
+Adata = 760d065275e345900a7bbab451cc9309fb161e6cfec526538b98800e4102e14d
+Payload = 00
+CT = b0078a769ab68db44e723993da382abc
+
+Count = 2
+Adata = ffedc67efd355ea404fcbcb3993d3bae81386ded86230270771deb747163bf44
+Payload = 00
+CT = 31fbff2d715a2eb9af54e8320a8e42e1
+
+Count = 3
+Adata = 55153ff5e4d208d2e647794f382c788e0e36f293e63e7290ba9ff2657ae0f167
+Payload = 00
+CT = 945839d62c9d1b899f6dcd0ca9517e68
+
+Count = 4
+Adata = f8813985f59bf284bd3882e899ca9b67fb496f3eb78d7ebe6ffbad084f639915
+Payload = 00
+CT = 903f90d23321a6882d6c4c1955b14847
+
+Count = 5
+Adata = 7b95cd827ab93507f1819ae76627d6e2a31d29890c092e5c300f0e2f9e4ef4d2
+Payload = 00
+CT = 652ec5ab43088eb568186d0d9887b30f
+
+Count = 6
+Adata = bd144c9bb974729aaa1188ceefdf85e1d9fddc0b0c8afe8828ba204aa9293feb
+Payload = 00
+CT = e6c1455d1117eec49338c96f51007309
+
+Count = 7
+Adata = 92b911cdc3137a6f7f32651b788eb82975660aea52b2c03b4759755a6da4a0f8
+Payload = 00
+CT = 1cf3c32fb229dac209523eaa517bb59a
+
+Count = 8
+Adata = a8200dbbfe4086015cdbdec2fc8e4934d0d663527430c424627ed44065ade091
+Payload = 00
+CT = ee10bfeb1cf9b3cd5a0faebd4d8f3fe1
+
+Count = 9
+Adata = 3b7f37b6b8e3c1390a99d59c47f7c102cf659d361a132ef8b4e70b9585bafebb
+Payload = 00
+CT = c51ed994253adb9bb5b9a8c34a27f225
+
+[Plen = 1]
+
+Key = 992d38768b11a236945bd4b327c3728fac24c091238b6553
+Nonce = b248a90b84b0122a5ad8e12760
+
+Count = 10
+Adata = 27cabc40da0e1eda0ea5f8abbb7c179e30776250a7b30d711b0e106c5ee9d84a
+Payload = 1c
+CT = 1a96f58c3f38c44d1a345f3e2da6679f20
+
+Count = 11
+Adata = dc2e28d5ae726c1beadb1e7e92ae7d14f5546320deb81a910bf170cbe0210eaa
+Payload = e9
+CT = ef0579aee7c17482691f3f832d867ffea7
+
+Count = 12
+Adata = c579f912ac1b45d5aa8cf20f78f0a1ace32abd3dc7fd0b3f3a7182a008795c7f
+Payload = 97
+CT = 913452d8ece38ffa1d4107d6a053acd8c8
+
+Count = 13
+Adata = 69ea953dbb910ec589372d797c7379d3f3b9e9fd48894c9b55e6e8eb360a6211
+Payload = f4
+CT = f20d760b9fe29530738157db0ba2d253f0
+
+Count = 14
+Adata = 622835dea57b2c70cca8f7548d6210714070b55b36adde7a4c547269c07aba9c
+Payload = 9f
+CT = 996fc21f24dee7b52f51d69eea30819f4a
+
+Count = 15
+Adata = 67ebda0a3573a9a58751d4169e10c7e8663febb3a8cf769d81bc872113f0720f
+Payload = 43
+CT = 4594c5b8db0064426a77dc536814c56147
+
+Count = 16
+Adata = 255412e380e9a28cbcd345be172c40f72dec3e8a10adfd8a9ab147e9022524e1
+Payload = c1
+CT = c76d36c0b0d699a22da3116dfb8f453181
+
+Count = 17
+Adata = c7c8e7151eb6844a954d091b460f83add0f0a634aa5ac213b774f2451aa497fb
+Payload = 31
+CT = 370c3a1690acc3f0eb09c9cfd3396c7fa9
+
+Count = 18
+Adata = 63f00b2488809fdc49ca5f05d54e98468906308115f7e702da05ddfd970b5537
+Payload = a7
+CT = a1ad45070fe4c61270c13cc52247fee411
+
+Count = 19
+Adata = 8e2c5e55c0bf70014e9897b6f6940e4e738b1e84e8269b6382f0b1fe59b0e162
+Payload = 40
+CT = 46b2a2a8b283ff7eeff5c2670f77b8809d
+
+[Plen = 2]
+
+Key = 5012db40ff6ae23c1e1ce43768c5936c4400b0e79ae77f30
+Nonce = b67e500b35d60ad7264240027c
+
+Count = 20
+Adata = 40affd355416200191ba64edec8d7d27ead235a7b2e01a12662273deb36379b8
+Payload = 0c6c
+CT = c996ef3d6ef9f981557506ecc8797bbaaaa7
+
+Count = 21
+Adata = c5e12e17e02bcc12b3a4c14cf837250e2886db3ee1c717d28bd11e8a3b764ddf
+Payload = 23df
+CT = e6254405257a837c5343b59d5689d6de5269
+
+Count = 22
+Adata = 213b5b6015d472bd593be5acf85ebba6d6a09f3a962be302ba83c6d70c61f241
+Payload = 0dc2
+CT = c838e93e67d37d2367bb1f27f71b54b29317
+
+Count = 23
+Adata = fc1b6e152fe232b6c10b5d89900961c445f4c46833df242c826678b68c869811
+Payload = dc88
+CT = 1972ca3744a4ab375af9060621a9dc4f4c32
+
+Count = 24
+Adata = 5b2eb1a6fa585d61d1fb3da68f5b93829c8e2d5e4fe03782617553d7a130ecf1
+Payload = 8179
+CT = 4483172626e930d24052bc056d8609c4175f
+
+Count = 25
+Adata = e2b3c3bf33cf847660929e48cce51d9d9289945169651aaecb1e939756e93105
+Payload = 01fd
+CT = c407852310207be8d3417de800b372700da2
+
+Count = 26
+Adata = 6051f12cd8aae68b4023aaf7178fd086aa582b8d8821e36637abc97025f5e858
+Payload = ca18
+CT = 0fe228553bc037954dbf4ce5db99792c2c7a
+
+Count = 27
+Adata = 2d3555faf285caaddfe95c010c2a7f233e09c2fc0cd30d644035269280527ad7
+Payload = a855
+CT = 6daf904725668634d6345bd8f90a3831b452
+
+Count = 28
+Adata = 4fca820dc545bf93bdffed33a04b67eb45384e696f092c2197e5d79cecd09913
+Payload = 5555
+CT = 90afdf6098cb3135c3045a54ffce88efaceb
+
+Count = 29
+Adata = 1789ae403e183d2225f431f001d475b53bccdec66572bb027340ae592839ba8b
+Payload = 11dd
+CT = d4278568e8c08ff5ee5ea0a608589c2fc029
+
+[Plen = 3]
+
+Key = fa15cc7f0de294d7341b1fd79326c8be78e67822343c1992
+Nonce = e5257aed2bda0495aa44591db4
+
+Count = 30
+Adata = 31a0338c3839931fa1dd5131cb796c4c6cfde9fb336d8a80ac35dec463be7a94
+Payload = bcb898
+CT = 68f08298d9a2147776dca9c1a42382bce323b2
+
+Count = 31
+Adata = 4863dd810ee70ef0f5da81f60c5ce550abb96454619032322e34657af25207de
+Payload = d1da2e
+CT = 059234a9a77755b324f3a557217752ade14ed7
+
+Count = 32
+Adata = 173594fc26b167f044aeaf9bfe920cab99a27eb2b01827d61f7553cb2018b5fe
+Payload = 394f31
+CT = ed072ba4441a79a90e228a28069fe109d5d876
+
+Count = 33
+Adata = 71cdd16eca9255aeedc23bd623513918ea97da21485074415fe75bcc42f454c0
+Payload = 868bda
+CT = 52c3c065f272f44c5210b5bcc571e819580910
+
+Count = 34
+Adata = e84418d332d16d2298e69e7ff3c37bc7b6e030cc822e73b3f4a0029bc2ea4d80
+Payload = 52d6bf
+CT = 869ea559c5f7f73a1b5f419c9f63ca401894a8
+
+Count = 35
+Adata = 42d962109bea1d50be0f3d83b4c2a6033d53b3d7112591866b1ae52dc84cb5d0
+Payload = 6f8d58
+CT = bbc542220b828cf5365137fb3f1df67cc8d2a1
+
+Count = 36
+Adata = 943b4327b5c70dba63c82f27e0412b3ada012bc0f7dd39ebb13db2f864daf80e
+Payload = fda286
+CT = 29ea9c422b0f41075ac79a0afa2d1047cbbfb5
+
+Count = 37
+Adata = 6076b94caabfa476ab7e6482e4fda9b29f2e2b2883efe44d668c7c74628505bb
+Payload = 8651fb
+CT = 5219e1ae68cd6d6815ecbfd01293d160d4d38a
+
+Count = 38
+Adata = 3e4bb5781f84b4bbd23583e3dae561c6ff4af8eff35e2a4f35b50d2f360d3469
+Payload = c3e179
+CT = 17a963fbaa81cfdbcaee476860cd5102f556e4
+
+Count = 39
+Adata = 364008acbad330d0b8d574641a97b0682c49279cfdc80ff309b7514514d18a44
+Payload = 4a97d5
+CT = 9edfcf7ad1520564b68824a3a939371c21a336
+
+[Plen = 4]
+
+Key = b5330a8447d74a7987fb718cfae246b5c7e057991064eeaf
+Nonce = 2ef29d62b40d8643848797cde8
+
+Count = 40
+Adata = 1225b036e6044df52314016760e92750de0936120395de750a2c54a7fa0cea82
+Payload = b46b343e
+CT = c2c39d6f9344e2de064f269d065a2a6108605916
+
+Count = 41
+Adata = aaa6257d6783936a4445833c2ac3bea8cb7334f22ade9c035d515bbc91d6a78a
+Payload = cb216301
+CT = bd89ca50693d90b8297b90bc41c231d08b0204fb
+
+Count = 42
+Adata = 1c1915fab09348b9a5536495c70d1a040305708c1124797e564b63e008e7b8ab
+Payload = 697a8696
+CT = 1fd22fc79d0146fe373437c529fb2eeb169e4bd7
+
+Count = 43
+Adata = 864d0f786497c7ce283762ca0959ec9c825ed445a5dbe5b4b2e5772fe88ce7f5
+Payload = 6bee3db9
+CT = 1d4694e8e389c549bfc4ede936d7896e544b23ad
+
+Count = 44
+Adata = d5388b0b548c58886dcd335dff2b1ed23ce3eebbb708fb5bbd831c83e959d3fa
+Payload = 85d95855
+CT = f371f10495177a9fe6d9329a585c8737c92a4d29
+
+Count = 45
+Adata = 83cddd189736f224cad6a29efba45e43c75450a14f1541713b7fb926ffc768c6
+Payload = e8b23340
+CT = 9e1a9a113914431a10b1f94a2b99b9e442f3dca4
+
+Count = 46
+Adata = 8fccbd1fc5240691cf24e8807bf3416c1b2d87fc86dbf3955fa2e52b9a3a8457
+Payload = 595c4d7c
+CT = 2ff4e42d383d8dc98b22010dd93cd0cbb396d9e3
+
+Count = 47
+Adata = 513d45f6f37f3f051667dc743215059e06e4fdc8945789b16d50556a2e839368
+Payload = 314e0c7d
+CT = 47e6a52c40c513bfc92d1a7db5ed7cab2d8212b0
+
+Count = 48
+Adata = 70828be102e554f0d4b07641fa3254bc8db06eefaf5b85a7c97e01c217fc8f3f
+Payload = 35753e32
+CT = 43dd9763ea98f4ac6b3eabd483f1e6ab92f3b83c
+
+Count = 49
+Adata = 343d5a4ad39acf81adcf24e9807618932abcb3bc076734f179174c77c8cb89e9
+Payload = a531c0ed
+CT = d39969bcf99fb67b1e2aba2d232db2445e6aec2a
+
+[Plen = 5]
+
+Key = 30419145ae966591b408c29e5fd14d9112542909be5363f7
+Nonce = 27e6b2a482bbc6f13702005708
+
+Count = 50
+Adata = e04e81e860daf9696098c723085d8023c240ebe7a643131e35359ab04bd650fe
+Payload = 8ceaeb89fd
+CT = ec9d5ed36243ddf77b33d8cf2963ba76fd4e19f3c5
+
+Count = 51
+Adata = 6217cd581d4b3b2f7bcf1b8dad9ad6430e2e3a0063cad52260e0a1cd6fc9e73a
+Payload = 7e51d6f870
+CT = 1e2663a2ef6b73fe9e638e205b27f78ed1bb9b0ed0
+
+Count = 52
+Adata = 8aa7847e496f5e9f1f87851442de844f27a21c1b48f82fe525f0dd5a88b8ec38
+Payload = e0023b674d
+CT = 80758e3dd25936115e23158aff1916edec241fad56
+
+Count = 53
+Adata = 3612abc865a4d8d7b86a84109388584df6526525adb1006ec6c8d00048d725bc
+Payload = e2b5b6f36e
+CT = 82c203a9f1f15aae4b70dbee244be1daa74475d7e2
+
+Count = 54
+Adata = 849a99c6f1cae0ad4bcde4bd0811e87ca5ed7b913de1a8285a206e980b4b7043
+Payload = 9a17e4a22a
+CT = fa6051f8b5bbff424487848385f8501ab5a77f327c
+
+Count = 55
+Adata = 9066367c784de0a4d1116bbe95ce55ded85edddb6273c2049ee24e0fb3429352
+Payload = d4e765fc78
+CT = b490d0a6e772d8d5da6f593a8d9956731b42645aa9
+
+Count = 56
+Adata = e7aa9f767fa8920f96f91c41d9e86755faaedaeda596a444b65f99b7a9e23e85
+Payload = 1074349e10
+CT = 700381c48fe3eca12b835dcfd08166ac8831585626
+
+Count = 57
+Adata = bc0db1ebf910b6f4dcad5401401d6bc2272e23130947dc236ca664d5b5ed6d66
+Payload = a46dd7fb58
+CT = c41a62a1c72bcce66018e9e552d2c8a229301361df
+
+Count = 58
+Adata = fcbeba2d0d73239d05f691a52b08152c9dd871f8dc76c2c18b8a638a74460d31
+Payload = 2e0ca09221
+CT = 4e7b15c8be3e41a50a28ea3be14baadf12964a37c4
+
+Count = 59
+Adata = dcdefce64ae4339f46c0759a4a10b29d59daaaf1e5dbf75cf11b4e4f73c5025f
+Payload = 2e108ce0fa
+CT = 4e6739ba65bee2ab25bfafa76dc3e54832b2f76864
+
+[Plen = 6]
+
+Key = 748ad503388a34041a7bdae6361d57894357c333bacf02ca
+Nonce = 518b79d194579b19f2d8845b70
+
+Count = 60
+Adata = 691dd98f61fd213b0840ec5a6f06ef9a1420be0d59bde5e43546347a2a865a94
+Payload = 24d6880aed7e
+CT = 270120f9634ec15536e21d961c675070ec4cff9037bc
+
+Count = 61
+Adata = d1fd047cdb18463766841abb1fcd25257f1458b595bfcf24066ff9385232fa97
+Payload = 2298028d0213
+CT = 214faa7e8c239b303af0b098f902dc24e66fe56adc6e
+
+Count = 62
+Adata = 65a480d120a0459dab69e8f23094801e10092666cc56f9fb2549662982bda6d0
+Payload = f248e5225e3d
+CT = f19f4dd1d00d1b657925a9740d6828bd85cd12205764
+
+Count = 63
+Adata = b738a53fbc9689dd49f68f97f5a99665258cd52e74dc653b594cffec045508aa
+Payload = 611dade00cec
+CT = 62ca051382dc395a1c49129ef6cce0ad5f6ef378aa1c
+
+Count = 64
+Adata = 7006f54184f0ff0ab215ca408d46325b86c1cbae6da7838435b1826ff81f55dd
+Payload = 5871a8300471
+CT = 5ba600c38a415e68468d1b2b516be3d688567d84ab80
+
+Count = 65
+Adata = 9e6e6675d4c6b1e0f3894aac071f4c99a364708edea12f319cbc27b40fabc0f1
+Payload = 3ca8a7520e94
+CT = 3f7f0fa180a40ba1af163049d16817021665d183bc9e
+
+Count = 66
+Adata = 10ceef716f54b74d7c8a435d6aa38a10ff23939ca29e2de7b6c3e0a8269a23c9
+Payload = 9c2a0070fbba
+CT = 9ffda883758a670f35869da9821b6ff1fab3e6062ad4
+
+Count = 67
+Adata = 3ee0865f29be50160273b4a94ec078932b9cd10a858e31838d5b607867e1ce69
+Payload = 436179c74fd2
+CT = 40b6d134c1e208f395250fd79087c858b83755411114
+
+Count = 68
+Adata = ec2b8bfe1ccd491b02aa4a9178fd6f099556963e39e2ca5fe6ecb6b5d2a46085
+Payload = ecfa41c614c5
+CT = ef2de9359af5afcbd9af2d584a0f638d066f2496d9be
+
+Count = 69
+Adata = 5b6f6369643d83b1db33d75257d7dea761e574e6e1f1ecead64e5e354a2f4235
+Payload = b48c10105dbc
+CT = b75bb8e3d38c17861882b8930296fd51d969a1e9489e
+
+[Plen = 7]
+
+Key = b930cca30a3fd230c237c8f3cc6792d0c4084dff5c18d775
+Nonce = 7574802fd82fe96c05431acd40
+
+Count = 70
+Adata = 1cf83928b6a9e525fe578c5c0f40c322be71b3092239bff954dd6883738d6d71
+Payload = 2a755e362373ef
+CT = f06238b0450fd1f4b6cab1383adb420c4724aa7bdfefb7
+
+Count = 71
+Adata = bb5450f66273f63b2f79dce177381ce846584ce4f7a0ad5a0171a56e149370bb
+Payload = fab43224bf8989
+CT = 20a354a2d9f5b7a1f99175d3dff5a73f0053a95c36fd8d
+
+Count = 72
+Adata = 3e5e1037bd2922eb20c34200c470b76e537baf7e7f1d8dd2f7a184a593c66554
+Payload = e3aed6715aa429
+CT = 39b9b0f73cd81734b4ad0e41117940abf530093dac648e
+
+Count = 73
+Adata = 3cc88a096a1a440827f5b7da675389e50b5cce35fa2cc36674d6bfc5a3a966b2
+Payload = e78db0f83997cb
+CT = 3d9ad67e5febf5663a8324014550430c7eaeffbd8568f7
+
+Count = 74
+Adata = 2cca33a10b9da7ba99a6b552d1405f2df3fdfd15358d8fdab5e15296b38f9135
+Payload = 726557906845b1
+CT = a87231160e398f34ab635c4eb5b38b86e71da8af3840ae
+
+Count = 75
+Adata = 2fe5dd58b17914187e29029c53cfe5b015ca74cab750d8f95e05f818c3cdf947
+Payload = 043a759b578be4
+CT = de2d131d31f7dabd9961766e03eaa7e8888227c98d1f42
+
+Count = 76
+Adata = 8b8e3d7c88fa16d70130cee290b7e2eecf0ce711118cd9265093b11467e63554
+Payload = f31f2fb4b3fd80
+CT = 29084932d581be637842d96d13c4aab97e296458745a9d
+
+Count = 77
+Adata = 6341370e126097f9721a13c977eb4875cf1286e15c3adfa4e7597e0e13d93b6a
+Payload = 7e3c8224104669
+CT = a42be4a2763a57a51ac46611366c666cab6bfd3d1baaa5
+
+Count = 78
+Adata = 227926b62f7cdd90e4d3b0cb5457e71fb087d329671f0fa891ec06eb8edeb58a
+Payload = 26a0528ae6f9c1
+CT = fcb7340c8085ff8c7d7e5aec14845f844ad38544a2f11d
+
+Count = 79
+Adata = 05b50c40b02e79b74b94d726a7ce8b2b7216ef8af6e7a42d041d2a692a58ad83
+Payload = 61dcf53d1a184e
+CT = bbcb93bb7c6470f1605ab8a2332012b759ccd2eedbed24
+
+[Plen = 8]
+
+Key = 314c136999e41d137bd7ba17201a9fa406025868334e39b3
+Nonce = 65f7a0f4c0f5bba9d26f7e0ddb
+
+Count = 80
+Adata = 5c7ce4819b30b975ae6ce58dcc1bfa29a8b6dda8f4b76c7e23516487745e829c
+Payload = 4d54d8b06b204445
+CT = 2baf90c490b11f9607482362ab3f157c42d0e9c6c5cffcf0
+
+Count = 81
+Adata = 90257ed88679197b8219bc4c2434a71a4e3664d5859c4ffb9a075654898ffedf
+Payload = b2a35df881cd63a2
+CT = d458158c7a5c38715389509b5b6f2df1faf7e8c39203970f
+
+Count = 82
+Adata = dff8ad83525d8235eacdccc91abeb80795e6b5f463fd28af35c46199f646ceb8
+Payload = e98f5e5a20d02c80
+CT = 8f74162edb41775395328747ca544e987df28883d0377b35
+
+Count = 83
+Adata = cde159c5343cd9d98001cd719d3e9ea25e47e1ff13fc87055d4a53b741f59285
+Payload = 90c3e48313cd4fe4
+CT = f638acf7e85c1437a4ba841883a0d7aeda398c043161966f
+
+Count = 84
+Adata = fa88cf5a08be4fb0c1a7960f45726c303eb559861fa60d17aa8dfe8bb5795382
+Payload = 8ad6d5a28ec075e6
+CT = ec2d9dd675512e3509195efe66c5faf413e0f68df8cb647d
+
+Count = 85
+Adata = fe9e93a9370b43efa1560aeb017ff04fca7f207191e6f707c1c35b2e90c44eb2
+Payload = eb83928f0d5f7aa3
+CT = 8d78dafbf6ce2170b51af067ad69ad96009e50ead3d03f02
+
+Count = 86
+Adata = 35792c854fdf1c8cf7f3f8ed2b8ec4f31fe17bf8d4ba49caec03f954bd8bb17a
+Payload = 4cd74ed2fd083011
+CT = 2a2c06a606996bc26b1cb03ee76587f84364825f7c1fcbe9
+
+Count = 87
+Adata = c084108f9c0a74cbf70f614dceae592546865006930db0401828a0eecff98671
+Payload = 52365f94579e0646
+CT = 34cd17e0ac0f5d958fa70c5e195f1f955d64892f532b7683
+
+Count = 88
+Adata = e8045949de61c5c18a63e628330a4d1d12782379a8f9187755409d1825f453c5
+Payload = 8fb85c857a3e38e7
+CT = e94314f181af63342ddf297bdad58083645a052815d29a83
+
+Count = 89
+Adata = 53cfdfd66d63c2924bd583487b90b1dd9ec199f90d660cb9c3a763a4776abfe1
+Payload = 43d2828e86f7856b
+CT = 2529cafa7d66deb81ad3b2be41dbc39df4c0145dcbae3e76
+
+[Plen = 9]
+
+Key = a19f6be062ec0aaf33046bd52734f3336c85d8368bef86ab
+Nonce = 7f2d07f8169c5672b4df7f6cac
+
+Count = 90
+Adata = d68d5f763db6111c5d6324d694cb0236beab877daae8115ecb75d60530777b58
+Payload = 13511ae5ff6c6860a1
+CT = b3859b757802ebd048467fd8e139eb9ee8fcdca45ed87dc1c8
+
+Count = 91
+Adata = f6e219b29884dab9ea9bad34d9ef8a50ae389c9a908de7154a1f2e894f27141f
+Payload = 7e7e33e1a07d4e8fde
+CT = deaab2712713cd3f3789d0ee8323ea2ee7a68aaaa9c49b98df
+
+Count = 92
+Adata = bcca002d69d9d1044c40ae741ea33ce6b8463f5a28d0514e044fdae2fe7d3c3b
+Payload = cc88980c73e6c5f0cd
+CT = 6c5c199cf48846402437c9fe3d9feb0485e6d7c04423b77a53
+
+Count = 93
+Adata = 39cac8f0825ffdb0668455933ad1581263a23b9e5f1305340528f0320d4b1269
+Payload = 34cb528f50d073cfdc
+CT = 941fd31fd7bef07f35b87e90a71ffe6c30bee1771078a701ab
+
+Count = 94
+Adata = 510a02a44d142c8e975d1d933f828fd7e47d28b88223f1698cf009dc3b079be6
+Payload = cbce3df86438a61065
+CT = 6b1abc68e35625a08c9e9c5be0657649448c38692e8d703d30
+
+Count = 95
+Adata = 40e0418cd52f74d78a8e18ed86210e3661a86d8574aedcee540340d8996d9852
+Payload = 80a2b835f8b0729a4b
+CT = 207639a57fdef12aa213e5f2bfd33101597cfae7cf334a8528
+
+Count = 96
+Adata = 1f2938b3bde19e1af91299c08638061dc3c1ea3284c259d415e996477cb37b0e
+Payload = dd04794e65ce34127a
+CT = 7dd0f8dee2a0b7a293516a7310fbd4ceb90d8db9a86cb6311b
+
+Count = 97
+Adata = cbae5b46e35fa2a279dcaa4c724b923805d4707412a84252b64228c91cedd019
+Payload = 00c4101052f54462d5
+CT = a0109180d59bc7d23cef6165af65f3522dfbfed0293db39ecd
+
+Count = 98
+Adata = d0f27c7f42892f3ad4c0029c5b698abb1d035ba5869a665b1de8861db6c055e8
+Payload = d0865445d3b26b6f49
+CT = 7052d5d554dce8dfa00726434c1349e3e874a2d6bf598d05fc
+
+Count = 99
+Adata = ab0f5a829a9319a74d5d5179aa0a410a0fcf52f344a7a896aeb1f7a6c5d398ea
+Payload = 7c7c8580b944ed3fd3
+CT = dca804103e2a6e8f3aab491e60fc97b3cb5248291e4866dcab
+
+[Plen = 10]
+
+Key = de1c8263345081d2dfa9afdf37675971135e178df554a4d8
+Nonce = a301bb82f91a582db01355c388
+
+Count = 100
+Adata = 9ad52c041390d0d4aaf65a4667c3239c95e7eae6178acc23fb4e70a852d483c6
+Payload = f777aba1fa70f94e6de9
+CT = 9d8bff6d2dcde77104ac6aba025abc01416a7ca9f096ab2529cb
+
+Count = 101
+Adata = b49c7e7b47870c1cc339c7c09aaacfd6115fa8a0f04990367eea10cfacb9d23c
+Payload = 349feebfbe58f93ea3c3
+CT = 5e63ba7369e5e701ca864acb200e85a0d4753a8ba226aca72f98
+
+Count = 102
+Adata = e61ca7310172eec16745a73e34516f65844eecd0dbc5566ac5213626b9096ef1
+Payload = 678a40b4c2c7df0e4c9d
+CT = 0d761478157ac13125d87869784e3321183d8c044657a020e9b9
+
+Count = 103
+Adata = 690f5e5d8da6cdb0f492e80449e152ffe88fea9742564d8383c79cef739a7f74
+Payload = 2b81e0533313664bf615
+CT = 417db49fe4ae78749f5070634d00b1facf0e9e9979ca257a71e2
+
+Count = 104
+Adata = 78e34b0a1d61ccd411cbfd306ea2ef3ce89c0b085deb4cfbaec2ab72ce16daa9
+Payload = 1ac63aa38a206d8e7d68
+CT = 703a6e6f5d9d73b1142d994630ed92e2973b22773f229b45bdad
+
+Count = 105
+Adata = 51bacfcf87ea11da34b76acba8c444792ec3db3c8ee6e600d69679975a682a54
+Payload = 027a7fd7897808ec7a56
+CT = 68862b1b5ec516d3131304571b015bb6b4651f1eb9f6fb3a7b74
+
+Count = 106
+Adata = 5159357a133e4743f903d05bd641da369a3675337760fcd2424a99221ba70b78
+Payload = 1086953d352e94a51a6d
+CT = 7a7ac1f1e2938a9a7328bb0e11ac4608081fd0702a137da0aea3
+
+Count = 107
+Adata = f567820865340314d46a17f520ff315efb6b33bdeda590ca9c4fad604c2d8e8d
+Payload = b8b148aafec4a035e9a7
+CT = d24d1c662979be0a80e252c9ec1317ce30dffeb4c9bf3fd0bbdd
+
+Count = 108
+Adata = 0cfec933831644b468724e808bb3d25fe8f15850ce513fc341da46089c845208
+Payload = 884242a87779d3921f8e
+CT = e2be1664a0c4cdad76cb691e32be3cdd9721a13aabad26dba58c
+
+Count = 109
+Adata = 8edc2b85d44297ac66bdd90d05d8df38124033d6a583bb8dda18a2246ba096e8
+Payload = 25c32770a299020d8500
+CT = 4f3f73bc75241c32ec45333a381be77800654aac335bf9220ac9
+
+[Plen = 11]
+
+Key = 248d36bd15f58e47fcf1c948272355821f8492e6e69f3661
+Nonce = 9e8d492c304cf6ad59102bca0e
+
+Count = 110
+Adata = 9ec08c7ed6b70823d819e9ab019e9929249f966fdb2069311a0ddc680ac468f5
+Payload = 33709d9c7906e2f82dd9e2
+CT = 9114d36b79b1918b2720f40cddce66df9b4802f737bea4bd8f5378
+
+Count = 111
+Adata = ba13974d95f2eeb367b63850609c53dc66c2710f682f10bef0142d48f851b430
+Payload = 84172985e7d194ba28a87c
+CT = 26736772e766e7c922516a12c94615be2bd81bd598f3022f5775a4
+
+Count = 112
+Adata = 5f16180bfac9b7483774cb0e1d57a43e9bf3cf03bf6fe758293aadcbbef25b80
+Payload = 9a34d32070c71d7de8f512
+CT = 38509dd770706e0ee20c042758e936750e335702542bc598e211c4
+
+Count = 113
+Adata = 4352057bdd1735a85dc0fc4dbeedc73279c27eb24a97641236f03f11cdafb8c0
+Payload = 2054a268b1f6fae4f15d91
+CT = 8230ec9fb1418997fba4870762bb2a7d04ba2ad251d595d0619dc4
+
+Count = 114
+Adata = ddf118ae403b2509e75eb7a26d17e73e527acbacfbe49a56fa3210169030144b
+Payload = f71afe9a60f08a0ef694aa
+CT = 557eb06d6047f97dfc6dbc27d85594da3fd35bd8498d7e389ee7cd
+
+Count = 115
+Adata = 973904409e8154132439926f0dc45c0d81bbbd5793f7f81e20eb818bfa374d58
+Payload = cdf5b47ff73306aa55c496
+CT = 6f91fa88f78475d95f3d80055936db383a8ad10b152046d721d3f7
+
+Count = 116
+Adata = 06bca7ef6f91355d19f90bf25590a44a24e5a782f92bc693c031e6de1e948008
+Payload = 9ebf93643854ea5c97a4f3
+CT = 3cdbdd9338e3992f9d5de5d57e228369e24fe955fd8924526af6e5
+
+Count = 117
+Adata = 8321f65baf9dc856ac1c24f3fee5c74d697eb0b50470d59d8f4a14b506e86c53
+Payload = 685116faa5cc527ac8bfa1
+CT = ca35580da57b2109c246b76c23abfb3b4eb39deb8da2064390dfa8
+
+Count = 118
+Adata = a4e7738038a5116592bb9d92d6d4ed191ab774310f6409e4e45fe907674c006f
+Payload = 9e8c4f1292e8d7e5179b34
+CT = 3ce801e5925fa4961d6222b4272c0639e8e6a1d356fb4fea86762c
+
+Count = 119
+Adata = 0df202431ee7f251a38aaf6aa8cd313782bd293af9114005adfe9faab253b572
+Payload = 3ecc2ba566c723462eb0ea
+CT = 9ca86552667050352449fc0633a0f9cdc9490231ec2dd69f6e35db
+
+[Plen = 12]
+
+Key = 77a67fb504b961028633321111aac2c30eb6d71a8cf72056
+Nonce = acadc0330194906f8c75ac287f
+
+Count = 120
+Adata = 8c18486d52571f70f2ba6a747aaa3d4b3ebc2e481ee1b70907dddb94bdfa0ca6
+Payload = 10554c062d269ff6dcd98493
+CT = 7f8b0cad79b545e5addf0b04ff4b0f2b2a5067283210aba8630d0306
+
+Count = 121
+Adata = 4e0b4771c7f6c66f9577c430611fdeec5702296ee3691b6bb8c6a81217edabe4
+Payload = 1c9e7875cf02129ac52daeb0
+CT = 734038de9b91c889b42b21275b16dbdf0b9be3c8c82ac652992d630d
+
+Count = 122
+Adata = 4a687e1d0a95ed2efb95b4c6b040999fcd35136811cd665f934d10224b6064c2
+Payload = 34575694dde459d195b7357a
+CT = 5b89163f897783c2e4b1baede629274d654ef5a4480e24f6bef3bc8c
+
+Count = 123
+Adata = b5330a8447d74a7987fb718cfae246b5c7e057991064eeaf823641a12bfce9f5
+Payload = ab20c8e8aab1aac1e4f64206
+CT = c4fe8843fe2270d295f0cd9142ab5407a08b648ce24e9955e28fe47e
+
+Count = 124
+Adata = 4f19bbc3135d7a216465b4c1df2616e8bfc3cc64af0bf52bdc42543f4d2448d4
+Payload = e556ca05bcd1991d2c9836a9
+CT = 8a888aaee842430e5d9eb93e151e94d311c7cd2c1b9048575076ceac
+
+Count = 125
+Adata = b6ffc7387b19786282bda7caad52eb37fbe7e557afcb80faaf57767e2a0f178a
+Payload = e5b665600a2aa413e117c538
+CT = 8a6825cb5eb97e0090114aaf61b71330d72506050368186a5619f180
+
+Count = 126
+Adata = 6a493c5ef3769ccc4101dbb2eb36e1e5bbc577a057ce0731203ba3f25b52497b
+Payload = 870864a611aa0475d120bc40
+CT = e8d6240d4539de66a02633d7ea21e36f99e5aab6ffa85994d13d5bb0
+
+Count = 127
+Adata = 8215753d9efc51325f182199e39f9082cc3fe524400f2a7434c68df7eb2b06d4
+Payload = 71afe8d00c6f2ea8c8b050d4
+CT = 1e71a87b58fcf4bbb9b6df437cc93a50dea11c5e0b19f14b9c8f16bd
+
+Count = 128
+Adata = eb8f198da6ee92a03913c6575343f6c749d2377a09430eb751b13c041e6edbea
+Payload = 7021f18b8f398a5999fcdcd1
+CT = 1fffb120dbaa504ae8fa534699cbfd1beafa2d2942f6812b8dfc88e6
+
+Count = 129
+Adata = de2ee30359e390db72f682c2ca0f14b72b60ff9bccd8c6fbd19a512b12add794
+Payload = affca856eb412f0b3276ae6e
+CT = c022e8fdbfd2f518437021f9337405235dce6161441caa25cc6007c6
+
+[Plen = 13]
+
+Key = 0d423519e4110c06063061323f8c7c95387776b6ee4e4b6e
+Nonce = 39abe53826d9b8e300fe747533
+
+Count = 130
+Adata = cdd9bf1b4f865e922c678ec4947ea0cb02e78bd5c1538f33aeb818ad3f47e519
+Payload = 4021ff104ff1dbd91e46db249f
+CT = 7953d3cd66d093785d123f65ba37f16761dd6aedbfc789ad96edf1490d
+
+Count = 131
+Adata = 342de5fe61e05c2e58ac2978a871fbdf186a7294ec5f85c4631c21b584231211
+Payload = 95050ca1d494bdb561d4840f8a
+CT = ac77207cfdb5f5142280604eaf8f8e855ae975a1fc64bcce3e7492e9d6
+
+Count = 132
+Adata = 7871482948d8d09d0a7491d915543082cb5fc7d6c1e82ee2218279f54c15c154
+Payload = c45823203b20821a48502f9c67
+CT = fd2a0ffd1201cabb0b04cbdd42017a6515156691b3161b747576078da4
+
+Count = 133
+Adata = 65781d018f27ca0c72a9fa9ab4648ed369646dd3ce45d7ad3a54f6b051f1b6e9
+Payload = e901661b7d47c9918244ee1077
+CT = d0734ac654668130c1100a515225cec7d2566a07cd78181ae94577befe
+
+Count = 134
+Adata = 05556b04dae5cde8525633d1862aa200c54af534e302d2cbd34ddc2b78532a60
+Payload = 5556f799d6a6cffb343f28c1a9
+CT = 6c24db44ff87875a776bcc808c133f51dac00f973fd42e0948fab70ea9
+
+Count = 135
+Adata = 151304e3e4f3c2d4d3227e035d849e0d3841ba00cf6cab1cf2e3e4d6cc760623
+Payload = 56bf26be81c7b55ef898e23981
+CT = 6fcd0a63a8e6fdffbbcc0678a4fe78bdeaa8d408ffe8fe64811aa87742
+
+Count = 136
+Adata = f870cc1fe67d6169279f905b0fe5fd9a0436c36498e4b7c6f584f00f7efe8784
+Payload = 36b304a72dbf4acfffa1d7d624
+CT = 0fc1287a049e026ebcf533970197228d155dda2bc814ff33ebeb9a7ffd
+
+Count = 137
+Adata = 5692c9d452ea1c067e62fdc554ddd2b18c8433d59067f971316797fd9853ae6a
+Payload = fb529eb5ae79a0830474ffbc98
+CT = c220b2688758e82247201bfdbde7ba03e144e34a4ab34791a372a2b8ab
+
+Count = 138
+Adata = dcf7fe16b7ca9e27ec3291103398eaa2e77c7b770b67f8858c215af4c523822d
+Payload = 6218c778955d9a56360f06c704
+CT = 5b6aeba5bc7cd2f7755be2862103c2eb5ef0657306d12b753a0694efcc
+
+Count = 139
+Adata = b0f1e2668611dca86e8d0f58c2a4cf4a9472d81ba013e271800b75841fe5ffde
+Payload = bf6b143fb713a81c965c5a9d8d
+CT = 861938e29e32e0bdd508bedca87cc6119151393461ecf65bfe06e0163b
+
+[Plen = 14]
+
+Key = a60cf7ceb62bf3118532bc61daa25ce946991047f951b536
+Nonce = 7499494faa44a7576f9ed5580d
+
+Count = 140
+Adata = baa482c64eefd09118549a8968f44cfea7a436913a428e30aa4ab44802a4ba35
+Payload = d64f9426febce6a84c954dd5ded5
+CT = f7580f17266d68237747bf57c7ed8242ac1a1979c5a9e7bc67d7698c7efa
+
+Count = 141
+Adata = 2ad8ecc5ac9437ace079419f17e6018625b10490120fbe2f12b41e64b73b653c
+Payload = fcd9b67717bcadeceddea336c671
+CT = ddce2d46cf6d2367d60c51b4df4918abced491c063d8bfd0e7341febddc3
+
+Count = 142
+Adata = 7585ee95e74d7a869bdc0b59ca9939dd57e7b09afab179079d467bfe0668416c
+Payload = 18232d7c792fb80e6ca1c8f2c3cc
+CT = 3934b64da1fe368557733a70daf4659ecbb3dbfbcdb0f913abedf8afab05
+
+Count = 143
+Adata = 41be6ca6188f34da1ce83fb8c27652848dc2a71e32bd3631fb9b33ae69e5d879
+Payload = 764dbefb42644d18d23e5e456868
+CT = 575a25ca9ab5c393e9ecacc77150a220d5ec0b5397d6b4e323b5dc7d1b63
+
+Count = 144
+Adata = 197cee3b15320d57996191dd13106fbd4546a5cc3d2bcf0c886af52ea3d9a855
+Payload = 8003586af34bdd0acae4f5547394
+CT = a114c35b2b9a5381f13607d66aac3a5f713f5d0793b732c6e114805cc9b3
+
+Count = 145
+Adata = ee0b647a47656a6e9e09c2d64f734a2cc3fd45b7ee52fea51c24af59ee22a006
+Payload = da143266516a4145cde92c93f961
+CT = fb03a95789bbcfcef63bde11e059ed90e8650bc16f590789dcc625b9e63d
+
+Count = 146
+Adata = 9f5bfffa01f1425d95465723735b49fc1dffbad06cf37a00ca4b59efa21739c1
+Payload = 3842b033f3ca31a6f8e5a638b39e
+CT = 19552b022b1bbf2dc33754baaaa6bda183dda1aef021d92210e27cdd7c5e
+
+Count = 147
+Adata = 64e92ba2748d07f602808f7c5ded15cb0e43140400d37107e59a01e7d45b4c9c
+Payload = cedf60b17185fc71b957cb759260
+CT = efc8fb80a95472fa828539f78b585e4087fb314f893937e95383e66745c0
+
+Count = 148
+Adata = 6ebcaeb4bd44ff4c990305ac64264dfe2ada5f7cd4b294eb9f492865cd28905c
+Payload = 035f449bb28f43365f4a0556096a
+CT = 2248dfaa6a5ecdbd6498f7d410520a71ce5813c578532b742d704fa92276
+
+Count = 149
+Adata = db617207dccd1f6baea5f2242d5e577adb8d69af3bb1707a7a53a8b75452455c
+Payload = 9a2a45424f4965a71270e77cc403
+CT = bb3dde739798eb2c29a215fedd3bb7fc45d15d6939668065d2282fc589c7
+
+[Plen = 15]
+
+Key = 82d4bc9aac298b09112073277205e1bf42176d1e6339b76c
+Nonce = 70325ef19e581b743095cd5eb1
+
+Count = 150
+Adata = 6d14bb2635c5d0ae83687f1824279cf141173527e1b32d1baf8a27f7fe34a542
+Payload = 25a53fd3e476dc0860eeeea25fcb0c
+CT = 4a1cfd0023557a184b929965b0a445cb3993ca35acf354cb2b4254ff672e7f
+
+Count = 151
+Adata = 9f8a56fecf32fa7d50f033b2524c3d798e254bc87245cce57e38edd6ee5d5f1a
+Payload = 797dca47597947c057789433309b67
+CT = 16c408949e5ae1d07c04e3f4dff42ea25b5eb103bac224cad66ec0f100875c
+
+Count = 152
+Adata = 86f15b8b677b7655f358a2c7fd5785bc84d31e079ed859b6af88e198debd36fc
+Payload = e61f9a663d3a2b50ea2f9475971270
+CT = 89a658b5fa198d40c153e3b2787d39b598cc6ec2295c586e7ae270a01846d1
+
+Count = 153
+Adata = 4de6bd43c28143ea5d40919cb5330a7e674f5bd8aeb7b178343a2851281c8668
+Payload = df990c42a268950677c433555319b3
+CT = b020ce91654b33165cb84492bc76fa97ff732093f7d0a96b30d8cdfd1bd583
+
+Count = 154
+Adata = a5c3a480dea1b2a1e3a0ce416148b04f60104217c9d24a5b267b4aa6aa07a4dd
+Payload = a7e72fb4bec3768594a2f6f5b4379e
+CT = c85eed6779e0d095bfde81325b58d7ad98e32a9156e125ff021ef6951b0c40
+
+Count = 155
+Adata = 51b041f1666c59045d333fe63d43457107e1adad34fcbf965e0d191f3e414776
+Payload = d3d1550047cf90eceaea7000d8e280
+CT = bc6897d380ec36fcc19607c7378dc9390f10df08a84c21031626861b201fbd
+
+Count = 156
+Adata = 22f8a3c9d85b2d53ffd92078d3c94373f855ecd01a8ac521d1abd0f2c7cba9ff
+Payload = 756412c4ee6416f2f4e0342011cde2
+CT = 1addd0172947b0e2df9c43e7fea2abdd5d840bb8c4348a9a548482e6b93043
+
+Count = 157
+Adata = da08b14e1b770b81faaf1e59851df1cba8838cd63bef141340ee378e65fdcbd4
+Payload = 666e4a4b3f6cf598aa763cdada4109
+CT = 09d78898f84f5388810a4b1d352e403f0d49927cd6103e3705ba201e8f73c6
+
+Count = 158
+Adata = 2db3ded385ef9c82fd39ea5782d9befe66e8a070066269b2aa7c4bbfac3711c3
+Payload = eb9013a74352b0677a88bd73052477
+CT = 8429d1748471167751f4cab4ea4b3e2d97f7c2b3b42bf570cce79bf30ccc50
+
+Count = 159
+Adata = 194c9e1eaa8e376f9c41bf33823efa28ee60a9213438665b7002cf0fcad7e644
+Payload = e3126400e3c571a4d39b37bc938a22
+CT = 8caba6d324e6d7b4f8e7407b7ce56bd3c2a4fc45d014a0c54edab2930a5bdc
+
+[Plen = 16]
+
+Key = 6873f1c6c30975aff6f08470264321130a6e5984ade324e9
+Nonce = 7c4d2f7cec04361f187f0726d5
+
+Count = 160
+Adata = 77743b5d83a00d2c8d5f7e10781531b496e09f3bc9295d7ae9799e64668ef8c5
+Payload = 5051a0b0b6766cd6ea29a672769d40fe
+CT = 0ce5ac8d6b256fb7580bf6acc76426af40bce58fd4cd6548df90a0337c842004
+
+Count = 161
+Adata = e883dd42e9ddf7bc64f460ba019c28597587d06e57c3b7242f84d5e7d124ab81
+Payload = b31dfa833b0cda20eaa84d2ecd18f49a
+CT = efa9f6bee65fd941588a1df07ce192cb8707b1a4d9ce3def33703e19eaab6dda
+
+Count = 162
+Adata = 409401eb49cd96b1aad2525c5124c509766ff86f88b2011c67a1d501d3485e31
+Payload = 24bc8dc1e2354667b79ba4d7061448ff
+CT = 780881fc3f66450605b9f409b7ed2eaefd9041ddce37d88e79fba28e385b2327
+
+Count = 163
+Adata = 83bf5c063bf1febf71688a832d615e09d6f14badedeaeb6ffbfe343fc7274e78
+Payload = d41d95a1d2326e12cba636910ddfca53
+CT = 88a9999c0f616d737984664fbc26ac0291d971893543868bd8c69078fc2bdb24
+
+Count = 164
+Adata = 8cdd70524e24318c64d681aa27752d4c86c5348c05c9e48f06ed41594785a6e6
+Payload = e8a4b80e081919f1912542d3136764f2
+CT = b410b433d54a1a902307120da29e02a3866b23e4c991f4007e56a1ee9265c6cf
+
+Count = 165
+Adata = 615985f63571c0f94ffcd4df77326abd41e84f388f061d97573a181da7ee5695
+Payload = 7fca7388058d6d1438b6eee0292131cb
+CT = 237e7fb5d8de6e758a94be3e98d8579a2abbea637996b954027efa9464ced6b9
+
+Count = 166
+Adata = 17aa90f2bff0419011b01dee62be31354431cbc89f22332704b096143d4743f4
+Payload = aa540554ee80dbffa475f702d862d6b6
+CT = f6e0096933d3d89e1657a7dc699bb0e757bc8d48d82ebefc76f17323c518ecc2
+
+Count = 167
+Adata = 85288b2be612e42335c144fb058a7dcd567c382fbcee3962bd5be4cc7a7000a8
+Payload = 6d745581831edba437e70ea89cad217d
+CT = 31c059bc5e4dd8c585c55e762d54472c65470c81e487a26cdc26830f2b51bd1c
+
+Count = 168
+Adata = 288f9f52824b54b608dd7226a0a89d43ae8c05107dbae761e1c756911a003b74
+Payload = 811a61869c7a6b2aa9ac0fcc523ef784
+CT = ddae6dbb4129684b1b8e5f12e3c791d5a3043722be9448c3ef144f2288066f75
+
+Count = 169
+Adata = 51dbaba180d4746edbb3420461919b5b735797bf7dd19f84d80475f5efc2748d
+Payload = 378a4e39817f308ed1e639f943b694c4
+CT = 6b3e42045c2c33ef63c46927f24ff29549aba95e04e11cf18ddf73773d395c1a
+
+[Plen = 17]
+
+Key = 3cf8da27d5be1af024158985f725fd7a6242cbe0041f2c17
+Nonce = 07f77f114d7264a122a7e9db4f
+
+Count = 170
+Adata = 30457e99616f0247f1339b101974ea231904d0ef7bd0d5ee9b57c6c16761a282
+Payload = f6dd2c64bf597e63263ccae1c54e0805fe
+CT = ce3031c3a70600e9340b2ddfe56aa72cffdc5e53e68c51ee55b276eb3f85d2cf63
+
+Count = 171
+Adata = 42370f115bbd4b31bb99fe82cca273b3c93072f96b2e09bdc6718d926d48db69
+Payload = f45fee3e086c28a7c590ec0cc05b972664
+CT = ccb2f3991033562dd7a70b32e07f380f65c6328a7476db2c10ec7bca3f6bd3df42
+
+Count = 172
+Adata = e2d692c5678124998a7862b8e87276b0a19e293a609103c99583b36305bcb2b0
+Payload = 4ad69a8ab433ed8909825c71f6081f64a7
+CT = 723b872dac6c93031bb5bb4fd62cb04da68080f0d51d3b8841683eff361984f7e4
+
+Count = 173
+Adata = b5b38791160959dd2836ec1ad25286c1ba410d7212347a95b5738a3d725bb651
+Payload = 3d47071c13f994cb42fb2887e5c6e53a54
+CT = 05aa1abb0ba6ea4150cccfb9c5e24a1355c1428ef5d40bc9e363817f219af2ed56
+
+Count = 174
+Adata = 02691171795a77d1e3bdad513b6fab5b50d1def81bcc1df15012de3433a6aa78
+Payload = e8a4b80e081919f1912542d3136764f264
+CT = d049a5a91046677b8312a5ed3343cbdb65fdfb37dfd1236198035c8461b304152b
+
+Count = 175
+Adata = 7371d8ae79e628f53ffede174eb068db2318c05e2f6d94ad2233a59369b16db0
+Payload = 549aa84bb182312dd016e3107f3b1f9c5b
+CT = 6c77b5eca9dd4fa7c221042e5f1fb0b55acefde0e84a3ce0cb702ceb73ca1dd9a5
+
+Count = 176
+Adata = bb1e1f51082e470f7245458ec902098e1e41d0ed28efa31be71d21ce86527ff7
+Payload = 31a12ca6d69db2e6e252474d7d59ed6552
+CT = 094c3101cec2cc6cf065a0735d7d424c53f8441d46dc5456a587b765e1a820c11c
+
+Count = 177
+Adata = 7584f57b49e95bbf5a67153e18b9b8c4722644e8f611613c39cbe8c679aba5b4
+Payload = 5bb121e70452a954f420a56aca8cd5c059
+CT = 635c3c401c0dd7dee6174254eaa87ae958d0daddcfcc92349ef059149c54a25cd0
+
+Count = 178
+Adata = 505687182c06e6f4effe7fe03c1f436199a9015380ff21d0b2aa9453cfa10b1d
+Payload = 5b80d1cf745b14cb71cbc8dfe0bc7c7358
+CT = 636dcc686c046a4163fc2fe1c098d35a5948c1242b89490c6ee69dedc1e91286ee
+
+Count = 179
+Adata = 7ebb051741145a3bad87131553375c6debcbcecee9b79ee451bd1429cbb33fc1
+Payload = 79ac204a26b9fee1132370c20f8c5bcada
+CT = 41413ded3ee6806b011497fc2fa8f4e3dba2ddd54e509bca0a45dcf2fd514e1496
+
+[Plen = 18]
+
+Key = b46a3a24c66eb846ca6413c001153dc6998970c12e7acd5a
+Nonce = b79c33c96a0a90030694163e2a
+
+Count = 180
+Adata = ea9405d6a46cac9783a7b48ac2e25cc9a3a519c4658b2a8770a37240d41587fb
+Payload = 56d18d3e2e496440d0a5c9e1bcb464faf5bc
+CT = 01baba2e0d5b49d600d03a7ed84ee878926c0ca478f40a6fbde01f584d938a1c91bf
+
+Count = 181
+Adata = 72340d595f3dbd23b46513f8f2b73b6249328c705e7968084bcb647fe734a967
+Payload = 7a76eac44486afdb112fc4aab939e4d1eedb
+CT = 2d1dddd46794824dc15a3735ddc36853890be4646492b6f4cb169383c075756073b6
+
+Count = 182
+Adata = d5c87c649579da3f632ba95cb0a07c924095e4bdd4e0376e06bb90e07460172e
+Payload = 48348c5ec996f7a97ef0ba2cd6885572fe64
+CT = 1f5fbb4eea84da3fae8549b3b272d9f099b4f584289f560cbf76606942fe1a92dd63
+
+Count = 183
+Adata = ffa6277395d31d5db13034d362228a87610e441c98ca3038e252a9db12bdbcef
+Payload = d5c58f10e1a03d8a2501d1eaf5fcdfff3ae5
+CT = 82aeb800c2b2101cf57422759106537d5d355964f5f5532d7cddd7207f0e9a6aace9
+
+Count = 184
+Adata = daf83d02a9bd992ea58c23e7ad18d41796314bae20e864e729f40ccc215454fc
+Payload = da2a863ab1c58ddde320ecadeecac9c5d2d8
+CT = 8d41b12a92d7a04b33551f328a304547b50890ae047e35aecfc38ffdc07e7d8f5705
+
+Count = 185
+Adata = 21ddad5f550044dc5cb123ade17eeef549c4e0173b216bcc602c1e736764cca8
+Payload = 4573969afa831c244817230406fe51183091
+CT = 1218a18ad99131b29862d09b6204dd9a5741b2bdf539ceaa35015712dd15265ca476
+
+Count = 186
+Adata = 9228265ae5c3daf1485ff8011738da508bf2a73731396c5d9aa56fc554e0c00b
+Payload = edf5557e15473b747a819398c9ac1459ffdb
+CT = ba9e626e365516e2aaf46007ad5698db980b241412124ae20b84c13b0c3671d305c9
+
+Count = 187
+Adata = c0a2ff0de21b3ba961e06015ccd71374856a65a4c57cf8cde0a1643aca8ed868
+Payload = e139263478900df806a0f3446bd6600c1aeb
+CT = b65211245b82206ed6d500db0f2cec8e7d3bee9803747bf9fa63412bfc4e10aea89e
+
+Count = 188
+Adata = b54378f031a31cf3985f573829c9ffca14616742e0a7e03b0a2d7f05eff0219e
+Payload = 660eaff0f113eaa2f5f7ad4b62bb849a3a25
+CT = 316598e0d201c73425825ed4064108185df55afdf430b57845dcf622d4f25cdeb2a3
+
+Count = 189
+Adata = e67f35c18a9336469eae23040f98f52338ca8d0cab269ac32fe6bc7605d3ea56
+Payload = 0f89897271f5d0349d57399005ea60c0cadc
+CT = 58e2be6252e7fda24d22ca0f6110ec42ad0c7ed4c04c4b4dd585891ecfddeab8cc87
+
+[Plen = 19]
+
+Key = 7b71045ccef735bd0c5bea3cf3b7e16e58d9c62061a204e0
+Nonce = 2b9ecfd179242c295fe6c6fa55
+
+Count = 190
+Adata = b89166f97deb9cc7fdeb63639eeafb145895b307749ec1a293b27115f3aa8232
+Payload = 890d05420d57e3b3d8dbef117fe60c3fa6a095
+CT = f842ff6662684de8785af275fa2d82d587de0687ebe35e883cbd53b82f2a4624c03894
+
+Count = 191
+Adata = 4392c3043287dd096b43b4a37ea7f5dc1d298b0623ccbf4fd650a49569a5b27b
+Payload = 6b425cdcdf8304e7fbb70b2973d55e6940025b
+CT = 1a0da6f8b0bcaabc5b36164df61ed083617cc807d4824f0a98db2d87365a42ca3b80e1
+
+Count = 192
+Adata = 9b4fc98fcdcf485205e7054bc9d1e02d0d8584420537e20d3821de2fd6824787
+Payload = c8bf145fcffbafd6cd1a4c5b6cedfe008aacb2
+CT = b9f0ee7ba0c4018d6d9b513fe92670eaabd221404e631735c544edeeb4c0105c55bf0b
+
+Count = 193
+Adata = 45622e1472542be2f63f463d253617eafd4f2ad609f9020884905dd5c22fba53
+Payload = 12b5a76faedf6f855e328c2cb87be8aea78c5e
+CT = 63fa5d4bc1e0c1defeb391483db0664486f2cdc16a4cf37e8e96eed1217d21133e83d1
+
+Count = 194
+Adata = 958689aea3c6cd19020eff9d635ef44ee0793424df38fdf13a238b969d429777
+Payload = f0927c3cb0a876d7877466507da8bfa0bd9a16
+CT = 81dd8618df97d88c27f57b34f863314a9ce4859facf81a636351f6e67d6ec12636ae0b
+
+Count = 195
+Adata = c22911efc36fa739048af0c951ef2449bb3605c52f65120c4d71fe5976026032
+Payload = d2c5d4e2362f19c99de66da7bd9c495c03d9a1
+CT = a38a2ec65910b7923d6770c33857c7b622a7327ce73a7e2db69d30441f89a03fd0e84e
+
+Count = 196
+Adata = 799da61e2c10ebb4783f618b8f69da7704a1b2b925cebc228af57d7ceebb9825
+Payload = 1c9d7f5b329ef4d384b8b7955a20f8a3fc15cd
+CT = 6dd2857f5da15a882439aaf1dfeb7649dd6b5e8d787a9d06b8533ca96fb1db8aecc8e5
+
+Count = 197
+Adata = 14a8e18afe0b9fe18ddfd754219a7e18ed36f419f8262d91678e10daffb31c81
+Payload = 3a64414c3588d7c26871d7d054ac6c8420d491
+CT = 4b2bbb685ab77999c8f0cab4d167e26e01aa028ff5f819d552c08054b5ac02063e102a
+
+Count = 198
+Adata = 7294a8b4ad97c81969e4a2876a3dc0ee322d554726997dc9ed98c5601985ee5b
+Payload = 545dd71bea9967e07a89f84a2027aacd132187
+CT = 25122d3f85a6c9bbda08e52ea5ec2427325f141cde5af8fada67c47cbb5787a6b2d9c9
+
+Count = 199
+Adata = 99294b22d73805805630fb416d20d4fca67419ab660ff45cd19a3729e81b9f69
+Payload = ec1b17b885c018272652453f47fa6e9ed972b9
+CT = 9d54ed9ceaffb67c86d3585bc231e074f80c2a7412640b179bd3e8a417dc38462c16e8
+
+[Plen = 20]
+
+Key = dc7c67715f2709e150cceff020aaacf88a1e7568191acbcf
+Nonce = da56ea046990c70fa216e5e6c4
+
+Count = 200
+Adata = f799818d91be7bab555a2e39f1f45810a94d07179f94fe1151d95ab963c47611
+Payload = f383bd3e6270876b74abbb5d35e7d4f11d83412c
+CT = 377b5df263c5c74f63603692cbb61ea37b6d686c743f71e15490ca41d245768988719ede
+
+Count = 201
+Adata = 69adcae8a1e9a3f2fe9e62591f7b4c5b19d3b50e769521f67e7ea8d7b58d9fc8
+Payload = 615d724ae94a5daf8d27ad5132d507504898f61e
+CT = a5a59286e8ff1d8b9aec209ecc84cd022e76df5ea9bc8cfaf2a1734a792076618c4b9690
+
+Count = 202
+Adata = 4586f73a1f162b2cdb65f6e798a60b5f48938d40b4612d84c1f39244f14efdce
+Payload = 6e923e1f404002aa5cf8f8aaf1b9772da425e21c
+CT = aa6aded341f5428e4b3375650fe8bd7fc2cbcb5cc5122df904b052e4d5580fdeddf5297c
+
+Count = 203
+Adata = 9f7ae892e5662803408d4d062265846441a43c1fa202da59f640ae722a692671
+Payload = 68115771505daa18bb3ce90054bfb7d077e1f37c
+CT = ace9b7bd51e8ea3cacf764cfaaee7d82110fda3ce0ba1bb1af18e15ade3316c21d6b41fb
+
+Count = 204
+Adata = 1f0769a7ae82bd985661e031c4a892c15d3ef37bdcfb45243d02f40fdb51d34b
+Payload = 681fd2a324b3fea4cfebed567ae4546ba373c8f1
+CT = ace7326f2506be80d820609984b59e39c59de1b1dc71e342fbc44289ef7e53e28edf3839
+
+Count = 205
+Adata = bf957ef5ab2805e58ea752da5793f7f23d98fce1b2b67738929e5de8a15f9801
+Payload = a7b9d2d069941e8b943706a02d2847ea713bb103
+CT = 6341321c68215eaf83fc8b6fd3798db817d59843ced1fb4a2a3e349aa590aabbfc3d13bc
+
+Count = 206
+Adata = 833264c1bebb597043b4158087cb651960915d9023189c9509c0d2aed84e7fe4
+Payload = 9b946e8198ce69d2173e970f4e0c103a47ee4160
+CT = 5f6c8e4d997b29f600f51ac0b05dda68210068205079f6c2739e2b789b6e3d3c60389374
+
+Count = 207
+Adata = 94c8414cbbec52e2d73bb8f02ef687c91432495c0c744666317d02e6d46706d2
+Payload = 81ac4618f3db6bcf9bbf67220b7671be4bb4f8a2
+CT = 4554a6d4f26e2beb8c74eaedf527bbec2d5ad1e22a02f287db7217148317d897f65f6a0c
+
+Count = 208
+Adata = fced1131dab3dabdc1a16d3409fa09a90ffe02f0e2c814a63f77f771c08c3389
+Payload = 90851933d4d3257137984cdb9cba2ca737322dac
+CT = 547df9ffd56665552053c11462ebe6f551dc04ec362df9f8b41b1dd4821f8f14e9e633d7
+
+Count = 209
+Adata = 495dfcf91f4735ab35c6bc4deef8468bd988e4099cd291a32b4707f93e13d82b
+Payload = c14ce6d57f0fe7367331c9fe159ae1fb8f1ccb2c
+CT = 05b406197ebaa71264fa4431ebcb2ba9e9f2e26cf61ffb51e56497ca9f39c6665fcbdfa8
+
+[Plen = 21]
+
+Key = f41e369a1599627e76983e9a4fc2e963dab4960b09ebe390
+Nonce = 68ef8285b90f28bcd3cb1bacea
+
+Count = 210
+Adata = dbe3e82e49624d968f5463ceb8af189fb3ad8b3b4122142b110d848a286dae71
+Payload = 81ad3f386bedcbf656ff535c63580d1f87e3c72326
+CT = 9f6028153e06d14d30b862a99a35413413c04a49dc6f68a03a11cf00d58f062a7b36465d13
+
+Count = 211
+Adata = d9acfd611e5bbb08c5d05d56791b8aebabf8d69734ec89153c91a1f65b2e1adb
+Payload = 35f6bb3f6a388f3a5a039b0a495b676d0b928aeb19
+CT = 2b3bac123fd395813c44aaffb0362b469fb10781e3ca1fb470b666523a19f83481f16481ed
+
+Count = 212
+Adata = 6003b771afe4e99e1ef1ed4a31b10540d95f4ac49885f0c8e5cdcb63d213127e
+Payload = 6aa7e3802b5a29d4f9ca88eb59f94af783d1054466
+CT = 746af4ad7eb1336f9f8db91ea09406dc17f2882e9c53cb05bfcd64da2b45c2e9a89a380b49
+
+Count = 213
+Adata = c371644275a6290821e7d308714bec2bf62d36c30f7fa77a0d60b28894f1c82a
+Payload = 13332b67ba5ba18137c306bd860dc3eb0a9a0b871a
+CT = 0dfe3c4aefb0bb3a518437487f608fc09eb986ede048f70fbc680cf7092b3dd90b943fc6e5
+
+Count = 214
+Adata = 8eceb15300ec4220510ed5b7deb3429de6ae5f618e1c222c28990a9ab4b4bac8
+Payload = 05981dc26a1db2d8e2c3d85ea9a4d1dc3432d9edc4
+CT = 1b550aef3ff6a8638484e9ab50c99df7a01154873ee386f33c0b8da8d0c5934e617dd618e5
+
+Count = 215
+Adata = 96d1cf3690c48c77a155ce13e67bbd62e6f03d88c893c1f7c30a6435d5ab36e0
+Payload = 60249343a8cd4d33c6edc583ea7e5c221ef3064787
+CT = 7ee9846efd265788a0aaf476131310098ad08b2d7d3d2db1360fb1121893f4d197731bce4f
+
+Count = 216
+Adata = 379bbc9f919dc2a8687f2a86cc9c3291804240a9b566c58519956848102e6155
+Payload = 79003a8d3d20d412f468f11712cec4d37cee847440
+CT = 67cd2da068cbcea9922fc0e2eba388f8e8cd091eba335ce1bfafc0948f2523e75f2aad86f9
+
+Count = 217
+Adata = 9bff9c9a8f94cd77e7016748da31f86d1b9c68465cbf954511c93a4776981524
+Payload = 7d078a8b200514a00628756250d410f7a0f8a769e6
+CT = 63ca9da675ee0e1b606f4497a9b95cdc34db2a031c7dc265e281307f0f4c38cddc556ac725
+
+Count = 218
+Adata = 25125a4668c31dc2e8a68b6c4c95ad7cf9322852e371b415a357d09acb01b587
+Payload = d9b0eaaff786165f882f41a98dbc0c355b3a1aaf40
+CT = c77dfd82a26d0ce4ee68705c74d1401ecf1997c5ba61c78a2f85a447c3e62b6197d65b9065
+
+Count = 219
+Adata = ad34d8f0902a5b79fb145b8206bb4d3b77e0bd8ae2d0964815389eacb33b4007
+Payload = 17b517ef577f588da374340d2522cc9ea642c8d8ae
+CT = 097800c202944236c53305f8dc4f80b5326145b2540312d067c08a9b4400e1df8bb7ed671a
+
+[Plen = 22]
+
+Key = 3289e59e3a7b29bf4a309afc253030bba4b9bdd64f0722f9
+Nonce = 30259ce106e9bd7a8bacbaf212
+
+Count = 220
+Adata = 2870bd9a26c510e9a256920899bbc77a4eb9b53f927045a943d5ed6b13638cf3
+Payload = 53911a67b65738f87fc7c20d6db8044bde1af95838d1
+CT = 70cf37d4b6f7e707376b1574ce17c040b5143da47abb2fe9afafc2fccd98ccf63b0fdec30eac
+
+Count = 221
+Adata = 611032a95ee87f89ad6be7c0fed8bd245c5f81076087b3bda4cde5587b8d14b6
+Payload = 46917e38b8a542296d290d065b0aa7c8aaa38950c386
+CT = 65cf538bb8059dd62585da7ff8a563c3c1ad4dac81ec102dfd8c231d6a355f079c213ce6858e
+
+Count = 222
+Adata = 2e7ea26d1cceaca3b7862a7a8469e366b52ec27ca127e3317222ee651d8da4a0
+Payload = b527828c89f674dc6f024f8cdd80c694bb3ebd57b2d9
+CT = 9679af3f8956ab2327ae98f57e2f029fd03079abf0b36df11febe34dd568da12c374674b9ac4
+
+Count = 223
+Adata = 0bf4413010daec585de34142224d1cad3072f9720f91ac664ad152820e838741
+Payload = 78230f73f9c0150f630eca4cd679818551d449db82e6
+CT = 5b7d22c0f960caf02ba21d3575d6458e3ada8d27c08cb2916540d9439b832aa44236a7e187ac
+
+Count = 224
+Adata = 2e7cae3306582eb5bad148247aa6c6ec943f8748e84b8a069ca9488b11844716
+Payload = 847bb12e0e56fa07a086eeda5907ae148148fa4107d2
+CT = a7259c9d0ef625f8e82a39a3faa86a1fea463ebd45b80d0768a18dead55700901408aa3f901a
+
+Count = 225
+Adata = 63036dc4ad13aee5dc1832e867f7538da108188fec7b08262af440d07579c451
+Payload = ec59e208c4bb429a371f1b3ffdf07fce5dea8a05f0ce
+CT = cf07cfbbc41b9d657fb3cc465e5fbbc536e44ef9b2a45f2073605d2a441805b6ff89d8beb68c
+
+Count = 226
+Adata = f9ec5ce4b63156d57e451eb67ab6d7a59cc397f43f6d26dc07d1036f0fb4a8cf
+Payload = fb12d94bd21b5748b23132a03065c78dae65a0bd2cfb
+CT = d84cf4f8d2bb88b7fa9de5d993ca0386c56b64416e91dcabef6907811c6b7df4e74c7a63d83b
+
+Count = 227
+Adata = e13a204e16f42bbf4716e95f1cb7e125ffac66a87f591c8ef2c7b8485ff707fd
+Payload = 239fa31d4a65de0318bfc5b60a06d706c129dcf255ac
+CT = 00c18eae4ac501fc501312cfa9a9130daa27180e17c626aa8aa37e858cd990f5593d9ef35f2a
+
+Count = 228
+Adata = c4591c3ad984a1e189c526b719212f8248289eeb277827272b8205d78191eb2d
+Payload = 57caadbb1a56cc5b8a5cf9584552e17e7af9542ba13e
+CT = 749480081af613a4c2f02e21e6fd257511f790d7e354d81e424d6b4528901ae46fb35f8b3106
+
+Count = 229
+Adata = cf4795bc7f43c30d3c3a8fd1b8a9d77d69bf59eb8b59d0f464315f40cb52335d
+Payload = a68c74e05f0a44d4a0372c0e5915b83d8e6729efacbb
+CT = 85d259535faa9b2be89bfb77faba7c36e569ed13eed1f25a4bfda35e1390f3f16f638dcd4047
+
+[Plen = 23]
+
+Key = 40f1aff2e44d05f12126097a0f07ac0359ba1a609356a4e6
+Nonce = 0df3fc6396f851785fca9aa5ff
+
+Count = 230
+Adata = e9699b20b0574fce8b5cbc4ef792eb96e2c1cce36b1b1f06ea2a95fe300633cc
+Payload = 8d98c580fb366f330dbfda20f91d99a0878b47efd14c6d
+CT = 579cdf9da62a2df471e03450516adb4ce99ae0f70b1776a39c3b429a1f922fac0b59e29a122e43
+
+Count = 231
+Adata = bd94c9ad6253c25dc417f87b6e52e03621ccf4b3bff5b402677aeb51e216335f
+Payload = 7391ba60fabe2c632bbaca16af9a235b2c7dae61691c0b
+CT = a995a07da7a26ea457e5246607ed61b7426c0979b3471067bf538e40f9366adf8758968f06ce8a
+
+Count = 232
+Adata = 4f263cda4a50b0e5379ec2fb546b326a07943527c1d175c029455a917753883b
+Payload = 7e1e93a6ca35a2c0e4f08fdb2e7ee22b9f486f0ab919e2
+CT = a41a89bb9729e00798af61ab8609a0c7f159c8126342f964a1199251b54f419720a30de83161de
+
+Count = 233
+Adata = 4d43702be4f0530319555d7f1a3356160f6cae48051f12e22a153d7e405c1149
+Payload = f94ff053c7413f34f96eae41fd1ac101151069af5a9428
+CT = 234bea4e9a5d7df385314031556d83ed7b01ceb780cf33b417e4cceb8dcf45ef33cc0007755bbc
+
+Count = 234
+Adata = f4d7978fad36223623ccb5bb18a7373cba8a6e3b1c921259e319266042db8887
+Payload = ba0716355fffb8ef947d2a15eb58375a1ff1084c566990
+CT = 60030c2802e3fa28e822c465432f75b671e0af548c328bd35aed57f49dcfecf248cf9d246ac024
+
+Count = 235
+Adata = 12e4fe727b1f27a619dd67bb976ddc2b18b2ef8b7184290d9553494a500d933e
+Payload = 872940780a94680a791c937994ceafd2c8b7a22b5f4927
+CT = 5d2d5a6557882acd05437d093cb9ed3ea6a6053385123c97cda0e04d2ff65c2e06a8276bdf6f97
+
+Count = 236
+Adata = 2c16724296ff85e079627be3053ea95adf35722c21886baba343bd6c79b5cb57
+Payload = d71864877f2578db092daba2d6a1f9f4698a9c356c7830
+CT = 0d1c7e9a22393a1c757245d27ed6bb18079b3b2db6232b3494dd2ee0a0fe5bfc9f69234c8142ed
+
+Count = 237
+Adata = cefc4f2fb796c2502329ca3d8f8af3200dd9edb8f164e15acec90536a15b6fdc
+Payload = cda681aa3109ebf5f21ee3a849098ea3a551e844fae4b4
+CT = 17a29bb76c15a9328e410dd8e17ecc4fcb404f5c20bfaf9008ead8e923997508eebf5e776198dc
+
+Count = 238
+Adata = 94fc7eb8febb832097ba6eecd2697da91b5a8a1f2248f67a7659e0ac55a09a0d
+Payload = d4f8d262870b5000a40b8fcce88f55c65c4d12e729975e
+CT = 0efcc87fda1712c7d85461bc40f8172a325cb5fff3cc45f136cc6ea1b0fdb554e0803053875b89
+
+Count = 239
+Adata = 459085184094e302b2e921cc04270b676e75bbcf0e4b53ed387df2bd0e75e0ac
+Payload = 732f211061c0a32c6ad124c58418d560ef5eab2602314c
+CT = a92b3b0d3cdce1eb168ecab52c6f978c814f0c3ed86a575da8ceccae093888daaf92c95817fc3d
+
+[Plen = 24]
+
+Key = 91f9d636a071c3aad1743137e0644a73de9e47bd76acd919
+Nonce = 1bf491ac320d660eb2dd45c6c3
+
+Count = 240
+Adata = 3bdfd7f18d2b6d0804d779f0679aaa2d7d32978c2df8015ae4b758d337be81dd
+Payload = 4eaf9384cad976f65f98042d561d760b5a787330dc658f6c
+CT = 635530cab14e3d0a135bb6eebb5829412676e6dd4995f99cb7e17f235bd660e7e17b2c65320e9fd4
+
+Count = 241
+Adata = 9de45b7e30bb67e88735b8fb7729d6f3de46c78921b228bad8f17cc9c709c387
+Payload = 59bee7d18fd4ba573f3e4f61076f5b9f6a3487e47d98c729
+CT = 7444449ff443f1ab73fdfda2ea2a04d5163a1209e868b1d99f40890c7d650afccda40fb2a4cd603b
+
+Count = 242
+Adata = 783477f981ef0551b5e7a714b640bbb38316c53756c96e30c898cdee3b72e6f4
+Payload = 4e7f3c86d846ff351db81dbe1d2e9ed73ec0450587ae681b
+CT = 63859fc8a3d1b4c9517baf7df06bc19d42ced0e8125e1eeb50236cf1a12a9e3542a4051788f9775a
+
+Count = 243
+Adata = 2851d40243512a43f70f9c25e9b18c122a1433f05c61e65017e197e88b129e43
+Payload = 2db7cb2739c839383b64c2c93c7d5c906d984756c3dedaa9
+CT = 004d6869425f72c477a7700ad13803da1196d2bb562eac59b1bbad9861192df356c6678b2f561ea3
+
+Count = 244
+Adata = 1cfa2d62cc1f6313fb0c6eb21803e09cdf61ee3ddb15192529560e5d8096cafb
+Payload = 2f2b82497c78369890809460d80a16be4f3330e8a0089165
+CT = 02d1210707ef7d64dc4326a3354f49f4333da50535f8e7951da4211d4c28d2d91568117fc99fd911
+
+Count = 245
+Adata = 5a14b556156191b2704936f64df0bf1dd2bd8d587418f4f85472338fcf86aa52
+Payload = 7cfefca725da1b6bb5d9545e3e50f5a624a8160bdb0e7d4e
+CT = 51045fe95e4d5097f91ae69dd315aaec58a683e64efe0bbeda99be0e054bb881a25a74b547d3ed5e
+
+Count = 246
+Adata = 148de640f3c11591a6f8c5c48632c5fb79d3b7e1cef9159c680d71fd1f9801fa
+Payload = 5205165c4e9612974dc92f60d1e328d68aa9466e27dbd499
+CT = 7fffb5123501596b010a9da33ca6779cf6a7d383b22ba2694c1fedb47fa30ff2ead6bf382431b2de
+
+Count = 247
+Adata = f852e38703097cc37c589b7860dbc333e091411462d5576dc9909a8cf6ac99d4
+Payload = f968f2833427abbc9fe1cab7e7a3f905a3b23a35802029ff
+CT = d49251cd4fb0e040d32278740ae6a64fdfbcafd815d05f0f338762a4e4299615c67130a28b56a383
+
+Count = 248
+Adata = 43df03a0e23c7ad0d13485150ca224c0b3f39d4e5f2d718db6308e003d3dc683
+Payload = 67da6ca42655188af0b8e389152b2a1b6e2c3ed88926afa5
+CT = 4a20cfea5dc25376bc7b514af86e75511222ab351cd6d9559dbdf61387294812f483aad76d48d899
+
+Count = 249
+Adata = b297dce04ada2ddebc7e94eff7c51b87eee2f98c410c5c0919d0652653ab7458
+Payload = 9777cf90dd7c7e863506686fc3ba6d3d05328f78b350f92f
+CT = ba8d6cdea6eb357a79c5daac2eff3277793c1a9526a08fdf078177541e19b11dfec995f40c99af70
diff --git a/lib/crypto/test/crypto_SUITE_data/VPT256.rsp b/lib/crypto/test/crypto_SUITE_data/VPT256.rsp
new file mode 100644
index 0000000000..e9cd7eefe9
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/VPT256.rsp
@@ -0,0 +1,1383 @@
+# CAVS 11.0
+# "CCM-VPT" information
+# AES Keylen: 256
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Nlen = 13
+Tlen = 16
+
+[Plen = 0]
+
+Key = c6c14c655e52c8a4c7e8d54e974d698e1f21ee3ba717a0adfa6136d02668c476
+Nonce = 291e91b19de518cd7806de44f6
+
+Count = 0
+Adata = b4f8326944a45d95f91887c2a6ac36b60eea5edef84c1c358146a666b6878335
+Payload = 00
+CT = ca482c674b599046cc7d7ee0d00eec1e
+
+Count = 1
+Adata = 36c17fd901169e5b144fdb2c4bea8cd65ad8acf7b4d3dd39acf2ad83da7b1971
+Payload = 00
+CT = 67747defe5da5fecc00b9bf3b249f434
+
+Count = 2
+Adata = 9a37c654ab8e5a0c6bdfff9793457197d206ed207d768cbc8318cfb39f077b89
+Payload = 00
+CT = c57ef5d0faf49149c311707493a4cfd4
+
+Count = 3
+Adata = 5ab80169184541393a6975f442ee583cd432d71a6d1568fa51159df7c5b8f959
+Payload = 00
+CT = bc2fb5571a7563bb90689a229d2f63a7
+
+Count = 4
+Adata = c78a22a667aafab0c94047e03837d51b11490693d5c57ea27b901ff80b6a38f9
+Payload = 00
+CT = 428888c6420c56806f465b415a66e65a
+
+Count = 5
+Adata = e11e30cbf63623816379f578788b0c8e6b59ee3c9c50aa6e1dcd749172d48fed
+Payload = 00
+CT = 9f1b7520025e1075731adc946b80121d
+
+Count = 6
+Adata = 05716168829276ff7ab23b7dd373db361e6d9e1f11d0028d374a0d3fe62be19f
+Payload = 00
+CT = bd36b053b6a90f19e3b6622cba93105d
+
+Count = 7
+Adata = 3e915389639435629fcc01e1b7022d3574e2848e9151261ad801d03387425dd7
+Payload = 00
+CT = 458595a3413b965b189de46703760aa0
+
+Count = 8
+Adata = 2f496be73a9a5d9db5927e622e166c6ec946150687b21c51c8ca7e680f9775ac
+Payload = 00
+CT = 8b259b84a6ee5669e175affca8ba3b1a
+
+Count = 9
+Adata = 0a8725bd8c8eab9ed52ca47835837b9f00a6c8d834ab17105b01eb4eb30402e7
+Payload = 00
+CT = c5f35fdf2b63e77a18d154f0ddcfedbf
+
+[Plen = 1]
+
+Key = cc49d4a397887cb57bc92c8a8c26a7aac205c653ef4011c1f48390ad35f5df14
+Nonce = 6df8c5c28d1728975a0b766cd7
+
+Count = 10
+Adata = 080f82469505118842e5fa70df5323de175a37609904ee5e76288f94ca84b3c5
+Payload = 1a
+CT = a5f24e87a11a95374d4c190945bf08ef2f
+
+Count = 11
+Adata = f6cfb81373f1cbb0574dda514747d0099635b48cb809c6f1fa30cbb671baa505
+Payload = 40
+CT = ffd43c5f39be92778fdce3c832d2d3a019
+
+Count = 12
+Adata = 5a88b14bada16b513d4aa349b11ce4a77d4cda6f6322ff4939ad77d8ecb63748
+Payload = 41
+CT = fe753b7b661f1aad57c24c889b1c4fe513
+
+Count = 13
+Adata = a92b95b997cf9efded9ff5e1bff2e49d32e65f6283552ded4b05485b011f853f
+Payload = 06
+CT = b91c5ac66e89bf2769ef5f38a3f1738b24
+
+Count = 14
+Adata = a206a1eb70a9d24bb5e72f314e7d91de074f59055653bdd24aab5f2bbe112436
+Payload = c8
+CT = 773fe64379cea1a8ae3627418dd3e489a2
+
+Count = 15
+Adata = d3029f384fd7859c287e38c61a9475d5ddbfd64af93746b1dc86b8842a8c194c
+Payload = e2
+CT = 5dabc529442ff93005551b7689bcb748f7
+
+Count = 16
+Adata = 51ca3d3b70b5e354451a5177d7acfd8e7b44eae55e29d88b5e8eb8fc1e5c62fc
+Payload = 1a
+CT = a5ee68e416617ac974b3d1af7320cd51f6
+
+Count = 17
+Adata = 8c6c6791f1ac957b18bf008e260a0af4a5b7bfdb1e0008d6eaaa227f45cf4f62
+Payload = dd
+CT = 6243883d93d7066991e0fac453400b4fbf
+
+Count = 18
+Adata = b0a1af969a95025385b251afd1e89f353426ed6e5d71019cd73366aa31d5b464
+Payload = 4c
+CT = f3b940d416f3435812f9d1b18f441b7721
+
+Count = 19
+Adata = 7e72b2ca698a18cb0bf625f5daddb0d40643009db938340a9e4fe164a052fee1
+Payload = 88
+CT = 371d27e9a32feea28a6a7e7da2d27e1cc4
+
+[Plen = 2]
+
+Key = 36b0175379e7ae19c277fe656a2252a82796309be0f0d4e1c07fdde88aca4510
+Nonce = 021bd8b551947be4c18cf1a455
+
+Count = 20
+Adata = b5c6e8313b9c68e6bb84bffd65fa4108d243f580eab99bb80563ed1050c8266b
+Payload = be80
+CT = ecacc3152e43d9efea26e16c1d1793e2a8c4
+
+Count = 21
+Adata = 38e5032c5949c2668191ef1af5bb17eddc28abdb4e5bb41eaffec2523b2525d6
+Payload = 82c9
+CT = d0e5d06bf4b50ccce0b2acfd16ce90a8854d
+
+Count = 22
+Adata = 0b50f5173249fb7118f80d25874d6745d88e4ce265fa0dd141ad67ae26c31122
+Payload = 8239
+CT = d0158d784f486c1dc4a2bafd5b02ca1e1c05
+
+Count = 23
+Adata = 0296743a3125b103a2b2a78a109e825ea10834bd684215ab2e85cc4172e37348
+Payload = 16c1
+CT = 44eda3377002a48f9fe306d157358e6df37d
+
+Count = 24
+Adata = a94e64becb803e211785ba51db7f3db042fbf44a7a821509156a6828b0f207e9
+Payload = 2801
+CT = 7a2df6c09bf1dcb1c82bd98c6e2c13a8d7a5
+
+Count = 25
+Adata = 105358cc17b12107e023a23d57b44c66a2c58d8db05100311575e1ea152fc350
+Payload = 65e7
+CT = 37cb2ea363c0d8864363056467570959ba03
+
+Count = 26
+Adata = 669f9a63cf638a202dca1965c4116273249813ce0b39703887d89bdf5b3b12d6
+Payload = 819d
+CT = d3b16519377e6d0252b5f80cdf3d0253eccf
+
+Count = 27
+Adata = e288590a3eba28ac6847a50b0294ab6bd0a548716ff5102c44a5b656b2d9ddd6
+Payload = 761e
+CT = 24329a4dee6ca2cde473f08f76f779856c3c
+
+Count = 28
+Adata = 5b222aae3c7786c3b9021ba672f9136190ec931cf055f84c85706127f74c6d5b
+Payload = 56de
+CT = 04f29e65c0f01e644e74092253b470cd5511
+
+Count = 29
+Adata = 2082f96c7e36b204ad076d8b2f796cccf5cbc80b8384b53a504e07706b07f596
+Payload = b275
+CT = e059809fa107f379957b52ac29fe0bc8a1e2
+
+[Plen = 3]
+
+Key = ddb739acda6c56ec9aefc4f4cbc258587f443da4e76ddfa85dbe0813a8784944
+Nonce = 0bddf342121b82f906368b0d7b
+
+Count = 30
+Adata = 887486fff7922768186363ef17eb78e5cf2fab8f47a4eb327de8b16d63b02acb
+Payload = db457c
+CT = 54473c3f65d6be431e79700378049ac06f2599
+
+Count = 31
+Adata = 0683c20e82d3c66787cb047f0b1eb1c58cdde9fb99ee4e4494bbf27eb62777d1
+Payload = 62a6c5
+CT = eda4853b186edc15c22ba24e470eb5a072da9f
+
+Count = 32
+Adata = 413074619b598f8bed34cab51ddf59941861ba0169ebe7570a5ed01d790c08e5
+Payload = cc67bc
+CT = 4365fc52a1fb5a58bd51931230c1a7dfb1a8c1
+
+Count = 33
+Adata = 2d65a5175c29a095dc082dab9cfcf4b895efbfa715c57614589d4db159543ce9
+Payload = 33800b
+CT = bc824b7d3810f59176cb108c7e969da51d4d79
+
+Count = 34
+Adata = 6a831b6059456be98e6fce608d8c71cb8efb04a96b45c2dfbdaeabf5420a1482
+Payload = b2c826
+CT = 3dca6646ffea832595c9c86e6517215541ddbd
+
+Count = 35
+Adata = 3a04a01160402bf36f33337c340883597207972728c5014213980cd7744e9e41
+Payload = d7e620
+CT = 58e460e89a6725f0fc35622d89d2f3e34be90a
+
+Count = 36
+Adata = 64d8bd3c646f76dc6ce89defd40777fe17316729e22ba90f6a2443ee03f6390b
+Payload = 795af4
+CT = f658b4b1bd7ad5d81686aeb44caa6025d488bd
+
+Count = 37
+Adata = 7bef8d35616108922aab78936967204980b8a4945b31602f5ef2feec9b144841
+Payload = 66efcd
+CT = e9ed8d0553c801f37c2b6f82861a3cd68a75e3
+
+Count = 38
+Adata = 92f7dc22dcbbe6420aca303bd586e5a24f4c3ed923a6ebe01ec1b66eee216341
+Payload = 78b00d
+CT = f7b24de3eeb8ea6c08b466baf246b3667feb3f
+
+Count = 39
+Adata = 71bf573cf63b0022d8143780fc2d9c7dbd0505ac31e9dce0ad68c2428b0878a0
+Payload = 9dd5e1
+CT = 12d7a11db811640c533794bfec6eeb977233ec
+
+[Plen = 4]
+
+Key = 62b82637e567ad27c3066d533ed76e314522ac5c53851a8c958ce6c64b82ffd0
+Nonce = 5bc2896d8b81999546f88232ab
+
+Count = 40
+Adata = fffb40b0d18cb23018aac109bf62d849adca42629d8a9ad1299b83fe274f9a63
+Payload = 87294078
+CT = 2bc22735ab21dfdcfe95bd83592fb6b4168d9a23
+
+Count = 41
+Adata = 75c3b3059e59032067e9cd94d872e66f168e503bcf46bc78d82a4d4a15a29f6e
+Payload = 0f28ee1c
+CT = a3c38951b5de3331078aa13bd3742b59df4f661a
+
+Count = 42
+Adata = 8fb9569f18a256aff71601d8412d22863e5a6e6f639214d180b095fa3b18d60e
+Payload = d41c9c87
+CT = 78f7fbcae52afe7326a12a9aaf22255a38d4bd0d
+
+Count = 43
+Adata = 8b62d9adf6819c46c870df8a1486f0a329672f7d137bb7d8659f419c361a466c
+Payload = 046bc0d8
+CT = a880a7957543692a72f0d599de48b5e5f5a9413f
+
+Count = 44
+Adata = fd98f8f39dfa46ea5926e0ffacbabbe8c34205aade08aa0df82e1d4eaaf95515
+Payload = 39bd4db8
+CT = 95562af530fc357f5482b9004d466bf858586acb
+
+Count = 45
+Adata = 09bf4f77a9883733590a3cc7ee97f3c9b70f4db255620e88cd5080badc73684c
+Payload = b43cdd3a
+CT = 18d7ba77a9e8db046fdd548b52d40375c1e9a448
+
+Count = 46
+Adata = 40326d765e0f6cf4b4deccb128bebf65a7b3c3e5bcf1d58f6158e1e9153b7e85
+Payload = e0052e9b
+CT = 4cee49d64efbdd4ad8d3e863172d9372fca07c20
+
+Count = 47
+Adata = aa5ae6dcdc21b5446489bdabf5c6747bdf3bbfdb3de2c03170efefe5ccb06d69
+Payload = 696825f6
+CT = c58342bb95bd661b32bc18025808f8b4035acad6
+
+Count = 48
+Adata = d3d34f140a856e55b29471fde4c0e5f7306b76d03faab26db79c10f95ffb3122
+Payload = 7eb07739
+CT = d25b1074ac05b072264e31a4b2801a6d790512d7
+
+Count = 49
+Adata = 648a84813ca97aef4ab7e143ee29acb946388660f18eb671194646e0b0136432
+Payload = 9cad70b1
+CT = 304617fcc00514d260e1d211de361c254369e93a
+
+[Plen = 5]
+
+Key = bc29a16e19cfbe32bf4948e8e4484159bc819b7eec504e4441a1a98ca210e576
+Nonce = 4f18bcc8ee0bbb80de30a9e086
+
+Count = 50
+Adata = 574931ae4b24bdf7e9217eca6ce2a07287999e529f6e106e3721c42dacf00f5d
+Payload = 3e8c6d1b12
+CT = 45f3795fcf9c66e1a43103d9a18f5fba5fab83f994
+
+Count = 51
+Adata = 99cd9d15630a55e166114f04093bd1bb6dbb94ecaad126fe5c408dee5f012d9f
+Payload = 76fc98ec66
+CT = 0d838ca8bb6f3cd579294f706213ed0f0bf32f00c5
+
+Count = 52
+Adata = 1516fdf7a7a99f3c9acc7fff686203dec794c3e52272985449ddf5a268a47bc3
+Payload = 6564c247cc
+CT = 1e1bd603117d38e026f706c9273dbcb6dc982751d0
+
+Count = 53
+Adata = 0c9c35be98591bf6737fc8d5624dcdba1a3523c6029013363b9153f0de77725b
+Payload = c11b9c9d76
+CT = ba6488d9abc3e46166767c6ad2aeffb347168b1b55
+
+Count = 54
+Adata = e74afe3ba960e6409dba78ecb9457e2a4ce2e09792b1d2e3858f4c79f7ddba62
+Payload = 45a4e0d7dd
+CT = 3edbf4930033a7dca78bcbf4d75d651ee5fadff31b
+
+Count = 55
+Adata = 96cbe9cd193513599c81f5a520fabaff51ee8cbdb81063c8311b1a57a0b8c8fd
+Payload = e5861b2327
+CT = 9ef90f67fa11585167c83105ee16828a574c84ac86
+
+Count = 56
+Adata = 2e7ea84da4bc4d7cfb463e3f2c8647057afff3fbececa1d20024dac29e41e2cf
+Payload = f5b5bcc38e
+CT = 8ecaa88753ffaba456f78e431f4baa5665f14e1845
+
+Count = 57
+Adata = be125386f5be9532e36786d2e4011f1149abd227b9841150d1c00f7d0efbca4a
+Payload = b6cc89c75d
+CT = cdb39d838034714731f9503993df357954ecb19cd3
+
+Count = 58
+Adata = 3fa8628594b2645bc35530203dca640838037daeaf9cf8acaa0fb76abf27a733
+Payload = 3802f2aa9e
+CT = 437de6ee436c1b008b7572752f04362b2bfdc296bb
+
+Count = 59
+Adata = 642ae3466661ce1f51783deece86c38e986b8c0adea9e410e976f8a2fe0fe10f
+Payload = e082b8741c
+CT = 9bfdac30c1a3f7c3c29dc312c1f51a675400500e32
+
+[Plen = 6]
+
+Key = 5f4b4f97b6aa48adb3336c451aac377fde4adf47897fd9ccdf139f33be76b18c
+Nonce = 7a76eac44486afdb112fc4aab9
+
+Count = 60
+Adata = a66c980f6621e03ff93b55d5a148615c4ad36d6cbdd0b22b173b4b1479fb8ff7
+Payload = 1b62ad19dcac
+CT = 4ad1fcf57c12b14e0e659a6305b4aeffae82f8a66c94
+
+Count = 61
+Adata = c13f65bd491cb172a0f7bbc4a056c579484b62695e90383358d605307d5be0a5
+Payload = 3ef0faaa9b79
+CT = 6f43ab463bc779fa7932d365e2da9b05c00a7318384a
+
+Count = 62
+Adata = 59dcca8fc50740831f8f259eb55d4db11f763a83187d93758d78d166f4d73cd5
+Payload = 1a98ddbf35f1
+CT = 4b2b8c53954f813229912137b7a4945dc07cea24a974
+
+Count = 63
+Adata = 578509ca4f57aadb78056794bf18b0714090970db786e2e838105e672165761c
+Payload = f46a7b1c28ea
+CT = a5d92af088546e045f19f737a24c8addf832ed3f7a42
+
+Count = 64
+Adata = 696c0c6427273cf06be79f2206c43af9cbda0b884efaf04deba0c4bf0a25cb26
+Payload = e98f5e5a20d0
+CT = b83c0fb6806edaae8a7dcd3b0fbb59438f88743ec6e8
+
+Count = 65
+Adata = 95a66b60249ed086eecaeb9bc449afcee9de212619e87516ca947351b25120df
+Payload = 06319c0480e2
+CT = 5782cde8205cd9cb636ca6543c4e35964f47341f2814
+
+Count = 66
+Adata = 2b411bea57b51d10a4d2fb17ef0f204aa53cf112e1130c21d411cdf16a84176d
+Payload = f4c723433b7c
+CT = a57472af9bc2ec82eadf4eb1f055da1a92a82052ab8b
+
+Count = 67
+Adata = ff3bff3a26fc5a91252d795f7e1b06f352314eb676bff50dc9fbe881c446941e
+Payload = 02f809b01ce3
+CT = 534b585cbc5d01b10a7ae24a4ca2bfb07ea2a3b31a97
+
+Count = 68
+Adata = f6be4aad63d33a96c0b5e9c4be62323c9e2308b29961fff980ba0dbda0549274
+Payload = 2b6004823a29
+CT = 7ad3556e9a97231323a4b88af5d7d0b07c0e73ddce1d
+
+Count = 69
+Adata = c3706a28d7420b41e072dcecc06b6b13116cca110bde8faea8e51f5107352d71
+Payload = 236c60cba4fa
+CT = 72df31270444db30eb33d2ede33abbe22f37704fe68b
+
+[Plen = 7]
+
+Key = f7aaeff3a1dc0cc5ecf220c67ad9f6dda060b4f1be3cc609cb4f18b2342a88a2
+Nonce = d0d6871b9adc8623ac63faf00f
+
+Count = 70
+Adata = e97175c23c5b47da8ce67811c6d60a7499b3b7e1347ad860519285b67201fe38
+Payload = d48daa2919348d
+CT = eb32ab153a8e092fa325bafc176a07c31e6cc0a852d288
+
+Count = 71
+Adata = ba45e1859efae362a44a0116a14e488ba369da6c76c3913b6df8e69e5e1111fa
+Payload = f95b716bfe3475
+CT = c6e47057dd8ef1a24840f4f40a7963becde3a85968b29c
+
+Count = 72
+Adata = efcaa6f6cda3036b0b52ff9f36bc38ca74049c32c6b7cdfb8a46ca4144bacd64
+Payload = 4862e3677083f0
+CT = 77dde25b5339748f2a4a5c276727e0a210fc2efb5aeabe
+
+Count = 73
+Adata = 360bcb407603fe92f856bf677625b9882521e6dae8f35fdfc3dc737f9398f609
+Payload = 7f1ca0728f6d65
+CT = 40a3a14eacd7e1051734fc31232ab2ab63474020ab4dc9
+
+Count = 74
+Adata = f12ee9d37946cfd88516cbe4a046f08c9bbba76a3973ff1e2cb14493405bd384
+Payload = 67478ef73290fa
+CT = 58f88fcb112a7ec715244f307609ffa253e4e3659b0ece
+
+Count = 75
+Adata = 5833dde0c577b2be4eb4b3d01d7b0042fa8441ad7043ea462bbbbd56a59790ea
+Payload = 36bb9e511276c5
+CT = 09049f6d31cc41f11047da612d2987fa2e50ada5ae7f9d
+
+Count = 76
+Adata = 1e103c63d8ead36b985f921044cd32b8f9f04a2ba9fa154a09e676ffaa093970
+Payload = d68d6556c5a5b1
+CT = e932646ae61f35382f7648718127ebae7eb7443ebd2c2c
+
+Count = 77
+Adata = a1cfb61d45a140bdea6329ba0fe80429ff9aa4624a1d31bc752f7c97f1d390a0
+Payload = 0568cca4ff79dc
+CT = 3ad7cd98dcc358cc40a5e7fffb1fb9a5dd9d6ba91bede1
+
+Count = 78
+Adata = 116b5b015e44ceef0061b2d2e73fa0b386d5c1e187782beebdfc6efb5a1c6935
+Payload = bd93d08eea4263
+CT = 822cd1b2c9f8e7468d2b70c311732f11ed72b57d83e500
+
+Count = 79
+Adata = 3d55882e6f3f89309b6940a3b408e573458eedd10fc3d0e1f3170eb313367475
+Payload = 4fb62753024e92
+CT = 7009266f21f416b41a70f548e359add30c0e5746fbeb2b
+
+[Plen = 8]
+
+Key = 493e14623cd250058a7fc66a3fee0c24b6e363b966c2314aff53b276b6c2ea7b
+Nonce = fe2d8ae8da94a6df563f89ce00
+
+Count = 80
+Adata = 579a637e37a0974cd2fc3b735d9ed088e8e488ffe210f043e0f9d2079a015ad6
+Payload = e5653e512d8b0b70
+CT = 75d31f8d47bee5c4e2ba537355ae8ab25cc9ed3511ff5053
+
+Count = 81
+Adata = 1583138aa307401dddc40804ac0f414d338fc3ffb2946f09aaaa7079426fc1ee
+Payload = 2c4ba9ce52e01645
+CT = bcfd881238d5f8f1781a9e359804831f31a1efb1ae1cb71d
+
+Count = 82
+Adata = 78d3dda40e433bba7a330ca3e5bd5170f0895f2e3e438402344ced79fcb0c719
+Payload = 5eb2d054a0e58c62
+CT = ce04f188cad062d62dcc77c4e1fe2bafd477598977835f0c
+
+Count = 83
+Adata = dfc762466fa84c27326e0ee4320aa71103d1e9c8a5cf7d9fab5f27d79df94bd6
+Payload = bbbf7830d04ab907
+CT = 2b0959ecba7f57b308946723baf0dbf613359b6e040f9bd5
+
+Count = 84
+Adata = 7e8ea82d1137c1e233522da12626e90a5f66a988e70664cb014c12790d2ab520
+Payload = 10c654c78a9e3c06
+CT = 8070751be0abd2b2003bd62ca51f74088bbbd33e54ac9dd4
+
+Count = 85
+Adata = 873da112557935b3929f713d80744ed08b4b276b86331dbc386fba361726d565
+Payload = 668d32e322e1da3e
+CT = f63b133f48d4348a67e65e7f2cdedf6ef8cc0ee7a6dcfb02
+
+Count = 86
+Adata = cfba97919f703d864efc11eac5f260a5d920d780c52899e5d76f8fe66936ff82
+Payload = e39f6225e8eab6cc
+CT = 732943f982df58780532f8c6639e5d6c7b755fcf516724e3
+
+Count = 87
+Adata = 01abcfee196f9d74fcaa7b69ae24a275485c25af93cc2306d56e41e1eb7f5702
+Payload = 6021a00f6d0610a4
+CT = f09781d30733fe107fd7a33828413ebc252dd9d015773524
+
+Count = 88
+Adata = ce1c31e7121c071d89afab5a9676c9e96cac3d89dcae83136bbb6f5ca8f81e5d
+Payload = bbaf0ac4e77ee78d
+CT = 2b192b188d4b0939d3d51368799325ad1c8233fa071bade0
+
+Count = 89
+Adata = bb210ca5bc07e3c5b06f1d0084a5a72125f177d3e56c151221115ae020177739
+Payload = 98a2336549a23a76
+CT = 081412b92397d4c25d1ea568637f773174a7f920a51b1fe1
+
+[Plen = 9]
+
+Key = b23255372455c69244a0210e6a9e13b155a5ec9d6d0900e54a8f4d9f7a255e3a
+Nonce = 274846196d78f0af2df5860231
+
+Count = 90
+Adata = 69adcae8a1e9a3f2fe9e62591f7b4c5b19d3b50e769521f67e7ea8d7b58d9fc8
+Payload = 615d724ae94a5daf8d
+CT = f019ae51063239287d896e7127f17d13f98013b420219eb877
+
+Count = 91
+Adata = 162d0033c9ea8d8334d485b29eef727302135a07a934eea5fee6041e9f1f47c1
+Payload = 0d9168eeab3b27ba69
+CT = 9cd5b4f54443433d997cc2cd61da9358b4045fef32f8192cbf
+
+Count = 92
+Adata = 3f4ab57efa32f51a4c00790280e77c0e55b85bbda4f854e242368e9a289b5a81
+Payload = 6287dcffdd5fb97885
+CT = f3c300e43227ddff75d280f0ffdd560fb8915978e3bd6205bb
+
+Count = 93
+Adata = 945d18134c148f164b39fd7c4aef0335045553f6ea690a3b1726418d86f0de00
+Payload = 6e5e01b3fd71d16b9c
+CT = ff1adda81209b5ec6c7dbf90420a1ff2e24bd6303b80cfc199
+
+Count = 94
+Adata = 23af12893431b07c2922ab623aed901c0eaaeb9a24efc55273e96aea4dab7038
+Payload = b51521e689b5247362
+CT = 2451fdfd66cd40f492d741f4329ae7cc77d42bf7e5f2ec5ab6
+
+Count = 95
+Adata = b15a118b3132c20c31e6c9d09acdee0e15fcc59d6f18306442682512d22eb10f
+Payload = 7f973617e710fb76fe
+CT = eed3ea0c08689ff10ec9ffdcc2f36edac14613b1d85baf25a9
+
+Count = 96
+Adata = dcfbeb6490f5fa7eaf917462473a6cec98bebf8f17493fe9b994119a6d5a5457
+Payload = 7e909b6727ac3fd02f
+CT = efd4477cc8d45b57df5a61a28bb10265b26043d7a8dd357713
+
+Count = 97
+Adata = 77e9317294f046f315a0d79e3423f29f7d9ebcd36d6eaa2a3fb2f4500309478c
+Payload = a5075638932b5632f8
+CT = 34438a237c5332b508d321c371ae1fd01bdf3b6c75a597da6e
+
+Count = 98
+Adata = 3aa8f204eb127b547e13873ed0238018394e13686c8734e49e3e629deb352c77
+Payload = c10f15a0de78db8aa3
+CT = 504bc9bb3100bf0d539393d1635bc40ac62405a39155406c47
+
+Count = 99
+Adata = 7f67e6f97c6c258f014d721a4edaaa0ddb3f9f09993276ab7b714ea9356c231d
+Payload = 8294f830cfca42cfbe
+CT = 13d0242b20b226484eff89641e1bd5ad6cc827441b17c45ecf
+
+[Plen = 10]
+
+Key = dbf06366f766e2811ecd5d4384d6d08336adc37e0824d620cf0d9e7fd1e7afa9
+Nonce = b3503ed4e277ed9769b20c10c0
+
+Count = 100
+Adata = 9ae5a04baa9d02c8854e609899c6240851cbc83f81f752bc04c71affa4eed385
+Payload = 2e3cf0af8c96c7b22719
+CT = e317df43ab46eb31be7e76f2730d771d56099a0c8d2703d7a24e
+
+Count = 101
+Adata = da77c6d5627a2aa34911bd1f7cc5f8aa68a2c6546adc96a186b9af8e5baac4cf
+Payload = e081c43a07450ce0dfa2
+CT = 2daaebd62095206346c5bcc7a8260ef361dc39fdb776d041f0d4
+
+Count = 102
+Adata = 134d2d9726400d09dd3521326f96fbef993ddc0c4088770057b0f8d70356456f
+Payload = c381d2ae5e72fc82324a
+CT = 0eaafd4279a2d001ab2d19f0cbb0899f221aac9762f2650f8058
+
+Count = 103
+Adata = 0d065dfde1de1f21784c7869eb566c977f807cfbd53578f4616995b51d7dc045
+Payload = 737f4d00c54ddca80eec
+CT = be5462ece29df02b978b3dc92a9bd26b9653e5917359c331fcff
+
+Count = 104
+Adata = 95c54d187f2415535451cbb9cb35869749b171f7043216ce6886dd77baeecf60
+Payload = 4e9e251ebbbbe5dbc8ff
+CT = 83b50af29c6bc958519891dda72c27d272561e00f7041845d998
+
+Count = 105
+Adata = 0f98039e6a9fe360373b48c7850ce113a0ff7b2ae5ce773dd4c67ca967cd691b
+Payload = 0db72b281ab4046d15a6
+CT = c09c04c43d6428ee8cc1928ac628758ad58fc1b5a768d4722848
+
+Count = 106
+Adata = ad840bc55654762e5eba0e4a9e7998992d990a06d70da1b1ca922ef193dab19a
+Payload = 4f7b4f38ff1ba4df5a59
+CT = 825060d4d8cb885cc33ed11dad4dc8b265a53cf0bdd85c5f15f4
+
+Count = 107
+Adata = 911e9876ea98e1bcf710d8fd05b5bf000ea317d926b41b6015998ee1462ab615
+Payload = 58ce55379ef24b72d6d6
+CT = 95e57adbb92267f14fb18eb659a5a7084be48d099467da4395df
+
+Count = 108
+Adata = 3f68a4fb4043bcf9b6d277c97e11365d949c705bd6679c6f0aaf52e62330ad79
+Payload = a219028a953ce1544835
+CT = 6f322d66b2eccdd7d1523b2b2583fd117cec47b1c84d3863159e
+
+Count = 109
+Adata = 02f32242cba6204319075ea8ce806a57845355ae73e6b875955df510096ebff9
+Payload = 83b0ee9a52252c456105
+CT = 4e9bc17675f500c6f8625456eb2b6a2d35c649a84051f843153c
+
+[Plen = 11]
+
+Key = 4dd555bd3a5253a90b68b5d4d46bd050340ee07ddad3a72048c657b5d76bb207
+Nonce = bdb1b82ba864893c2ee8f7426c
+
+Count = 110
+Adata = 9bcc5848e928ba0068f7a867e79e83a6f93593354a8bfcfc306aeeb9821c1da1
+Payload = 8015c0f07a7acd4b1cbdd2
+CT = 8e9f80c726980b3d42e43a6512a0481255b729a10f9edb5f07c60c
+
+Count = 111
+Adata = c2e75952ab49216f305e3776865791ce877cef8c0229ca97561787093fddf1d8
+Payload = c97b62a719720b44b7779c
+CT = c7f122904590cd32e92e748c514444f00ffdb80a4bb7e9eb651946
+
+Count = 112
+Adata = c76a3ff4e6d1f742dd845be2d74c1a9b08e418909b15077deb20373ef55caf91
+Payload = cb7c17ef62464ecc8008f6
+CT = c5f657d83ea488bade511edb609dfc1929ac1ba5753fc83bf945b7
+
+Count = 113
+Adata = bdb69f99f9a144b9ad88c6cfd8ffb8304c201de9b2818552ce6379e6042c1951
+Payload = 893a690cc5221de597d0e8
+CT = 87b0293b99c0db93c9890053b74283296d0fca83b262915289163c
+
+Count = 114
+Adata = 01815f599d6ba0d1c09f6f673bb6cca4c2a7a74f4e985be4c0f37842c7bbc5a4
+Payload = 80f3e4245c3eab16ef8bf0
+CT = 8e79a41300dc6d60b1d21888a34955893059d66549795b3ac2105c
+
+Count = 115
+Adata = a9db62e9ab53c4a805c43838ce36b587d29b75b43fb34c17a22d3981120f3bc5
+Payload = 641c6914920a79943dca39
+CT = 6a962923cee8bfe26393d1377c4e2f20aaa872a9a0b1d1d7f56df0
+
+Count = 116
+Adata = f0c2cc5a1b4c4cbe839338fa0d7a343514801302aef2403530605cf4f44d2811
+Payload = 2286a1eddd80737a724ca9
+CT = 2c0ce1da8162b50c2c15415545aa0c1dd11551891ae553d3a91908
+
+Count = 117
+Adata = 9842922499ad4d487488b3731f48765efe0b4eb59e7b491ba5f6636f09ed564d
+Payload = d8c63e7d7d332198249c0c
+CT = d64c7e4a21d1e7ee7ac5e4d9e07ec5806360843676ef27d811b246
+
+Count = 118
+Adata = 399b71ecb41f4590abda79045cdf6495f27daaa559c1b34f513b5c4ac105ec10
+Payload = 4b81804d777a59b6a107cf
+CT = 450bc07a2b989fc0ff5e27483b8727c5753ede25e1fab0d86963be
+
+Count = 119
+Adata = 2c186c5c3463a4a8bad771feb71e2973c4f6dede2529827707bf4fa40672660f
+Payload = dfc762466fa84c27326e0e
+CT = d14d2271334a8a516c37e64b5c3c1dc577ee8fcf6ef3ebc0783430
+
+[Plen = 12]
+
+Key = d3ad8cda9a0d91a205c4c05665728bb255d50a83403c9ab9243fcbbe95ae7906
+Nonce = 0b5f69697eb1af24e8e6fcb605
+
+Count = 120
+Adata = ea26ea68facdac3c75ba0cdf7b1ad703c9474af83b3fbfc58e548d776b2529b9
+Payload = a203aeb635e195bc33fd42fa
+CT = 62666297a809c982b50722bd56bc555899345e0404b2938edf33168e
+
+Count = 121
+Adata = 0b32069fc7e676f229f1037d3026c93eef199913e426efd786b524ce1dbde543
+Payload = aac414fbad945a49ae178103
+CT = 6aa1d8da307c067728ede1449b15447c904b671824c2ca24c4fc7ad4
+
+Count = 122
+Adata = 7a8658302e5181552292aa56e8209de63b5d86934167549b0d936202681757e1
+Payload = 7ee0ce371329192618e3cda0
+CT = be8502168ec145189e19ade7ea13850e99ef9300c65f5abc9419d13a
+
+Count = 123
+Adata = 4f05600950664d5190a2ebc29c9edb89c20079a4d3e6bc3b27d75e34e2fa3d02
+Payload = b0a1af969a95025385b251af
+CT = 70c463b7077d5e6d034831e8486c93c31bbedc9e5ffa2f4154bceea9
+
+Count = 124
+Adata = 4530e4dc6a4c3733b8ab7e77e384223cc1a8c179fb66818c08aca47e5c705d89
+Payload = 9f6c6d60110fd3782bdf49b0
+CT = 5f09a1418ce78f46ad2529f7f18b556e7da59fd2549dc57a17bf64f8
+
+Count = 125
+Adata = f179353aef342f0f691caf1fcb811e3f6504e14d6d9381c5439b098ff978b01b
+Payload = 90958d7f458d98c48cbb464c
+CT = 50f0415ed865c4fa0a41260b30aad3a838680cbd313004685a5510c5
+
+Count = 126
+Adata = f6df267e5cbc9d2a67b1c0fd762f891ee3b7c435884cb87d8228091b34aeddae
+Payload = 9f7ae892e5662803408d4d06
+CT = 5f1f24b3788e743dc6772d411d57b89ed0c91251aed37a6ca68a50c7
+
+Count = 127
+Adata = 4372e152b1afd99c7f87c8a51dbc3a5c14c49d04ea1c482a45dfbcda54972912
+Payload = 817074e351455f23cb67883d
+CT = 4115b8c2ccad031d4d9de87ad79a3b0feea16ff5fbca16211ea6fdd9
+
+Count = 128
+Adata = 82b6cd1c6618c42ba74e746075dc28700333578131ca6fde6971d2f0c6e31e6a
+Payload = 1b7da3835e074fdf62f1eb3c
+CT = db186fa2c3ef13e1e40b8b7b49f22737c4b2f9fa0a7e3dd4b067fbaa
+
+Count = 129
+Adata = a5422e53975e43168726677930f6d3e13281bdbd13c67c168340ed67e45d15b0
+Payload = 57473e7a105c806867379194
+CT = 9722f25b8db4dc56e1cdf1d3ef43a48dbea8c1547455ad0197af88a2
+
+[Plen = 13]
+
+Key = e300fc7a5b96806382c35af5b2c2e8e26382751b59010d4b1cfc90a4a9cb06df
+Nonce = 55b59eb434dd1ba3723ee0dc72
+
+Count = 130
+Adata = 9b1d85384cb6f47c0b13514a303d4e1d95af4c6442691f314a401135f07829ec
+Payload = 8714eb9ecf8bdb13e919de40f9
+CT = ba6063824d314aa3cbab14b8c54c6520dac0f073856d9b9010b7857736
+
+Count = 131
+Adata = fa17c693d0997140fbc521d39e042d8e08388106874207ca81c85f45c035d6e6
+Payload = a0837676e091213890dc6e0a34
+CT = 9df7fe6a622bb088b26ea4f20820a423dd30796b6016baff106aaef206
+
+Count = 132
+Adata = 27663597b389b78e96c785ca2f5510c8963a5561d2b0b24c4dcdf8e58562c12c
+Payload = b8a2ce7e051b8d094ec43f2a7f
+CT = 85d6466287a11cb96c76f5d2436032bc79c4aef1f74da25e92b0aa7f8a
+
+Count = 133
+Adata = d8f1a83371487d611ce704e0a6731f97a933c43569690022fce33cb5aecdc0a7
+Payload = 9e4103ab1dfb77ae3494507332
+CT = a3358bb79f41e61e16269a8b0e658123d2e5bb324c7ead8897f8e32b0a
+
+Count = 134
+Adata = 05c57aab99f94b315cf8bdd2d6b54440c097fe33c62a96b98b1568cdee4ce62c
+Payload = fb3e3d1b6394d2daebf121f8ac
+CT = c64ab507e12e436ac943eb0090270758ab09f93fa3ba7d7a2aa8eac789
+
+Count = 135
+Adata = 1c1b0933c508c6a8a20846ebd0d0377e24f4abc0c900d3a92bc409ba14ef1434
+Payload = 549ba26a299391538b56ce4bd7
+CT = 69ef2a76ab2900e3a9e404b3eb2293813f1bcb96564f772e9308e42b2d
+
+Count = 136
+Adata = 9f5cf9149f556124d6bb4e3e243cca1502c02682709392cc2ec7eb262fd4d479
+Payload = 287f31e69880823df7798c7970
+CT = 150bb9fa1a3a138dd5cb46814c81877380d5cf097c2fb5177750f8b53a
+
+Count = 137
+Adata = 1a49aaea6fc6fae01a57d2fc207ef9f623dfd0bc2cf736c4a70aaaa0af5dafd3
+Payload = 040d18b128ae4a1935f9509266
+CT = 397990adaa14dba9174b9a6a5acf42c75787edc62a180568c6ef56545d
+
+Count = 138
+Adata = f29a0b2c602ff2cacb587292db301182e6c76c5110b97ca8b706198f0e1dbc26
+Payload = 92441cbe8d70820870bb01ad63
+CT = af3094a20fca13b85209cb555f56d47a0631f2038103e3904b556ba7a5
+
+Count = 139
+Adata = 01fcf5fef50e36175b0510874ea50a4d2005ad5e40e5889b61417700d827251e
+Payload = f11d814df217de96333dee1cbf
+CT = cc69095170ad4f26118f24e4835be15b7ae24edccd0b0934e3af513ed3
+
+[Plen = 14]
+
+Key = 3ae5be5904bae62609ac525e2d1cad90133447573d7b608975a6a2b16cb2efc0
+Nonce = 61bf06b9fa5a450d094f3ddcb5
+
+Count = 140
+Adata = 0245484bcd987787fe97fda6c8ffb6e7058d7b8f7064f27514afaac4048767fd
+Payload = 959403e0771c21a416bd03f38983
+CT = 37a346bc4909965c5497838251826385a52c68914e9d1f63fd297ee6e7ed
+
+Count = 141
+Adata = 52f6a10a022e5ee57eda3fcf53dcf0d922e9a3785b39fad9498327744f2852e4
+Payload = 23fe445efa5bcb318cc85e2ad1ac
+CT = 81c90102c44e7cc9cee2de5b09ad364b603de6afbc2d96d00510894ccbe7
+
+Count = 142
+Adata = d236e3841b9556b32dbd02886724d053a9b8488c5ad1b466b06482a62b79ebb6
+Payload = 762fdc3e0c30c7ecf2ec8808bb79
+CT = d418996232257014b0c6087963781a4321c2ddbc35ce4864457d611219e9
+
+Count = 143
+Adata = 0d2739cfdac782b61f484fa1a423c478c414397ec420327963d79112b2d70a7e
+Payload = b6813d5fe8afa68d646c197337a2
+CT = 14b67803d6ba117526469902efa3296e55efebb17fe145cdca9b31ea7bcc
+
+Count = 144
+Adata = 7f291aa463c4babc76b4a6faf2e27e9401586b1ac83e4b06a4090e94b3ef5fd4
+Payload = 4ce8b6578537215224eb9398c011
+CT = eedff30bbb2296aa66c113e9181059270a0510e7cc1b599705853af2144d
+
+Count = 145
+Adata = 06bca7ef6f91355d19f90bf25590a44a24e5a782f92bc693c031e6de1e948008
+Payload = 9ebf93643854ea5c97a4f38f50bd
+CT = 3c88d63806415da4d58e73fe88bcb55847573bf21e946ce9bdc5f569e3ff
+
+Count = 146
+Adata = 5a44ff94f817c7c028a8f3db35a4d01364d2598432469f09ded86e5127d42d35
+Payload = da989cc7d375ed5fac4d7f938d74
+CT = 78afd99bed605aa7ee67ffe25575b8a61c5687ea02f0276824b8316b76f1
+
+Count = 147
+Adata = 2a755e362373ef27a911c4d93ca07bc97135645442ad7ad6a8ef98146c71e9d7
+Payload = 6fbab5a0f98e21e4d15904af5948
+CT = cd8df0fcc79b961c937384de8149a07ee02791011129fcacffcfb1bf4145
+
+Count = 148
+Adata = f7988873f45a5de314e5381d3f14d8f8c48c9b649bf3e745ed5dc882d507da58
+Payload = b610349e8b370a7c195598573637
+CT = 142771c2b522bd845b7f1826ee36d34204b1ce23f5f58a8eb7cf1fa8cfa7
+
+Count = 149
+Adata = 95d2c8502e28ab3ee2cac52e975c3e7bccb1a93acc33d9c32786f66d6268d198
+Payload = 1d969fd81dab5ced3e6ee70be3bf
+CT = bfa1da8423beeb157c44677a3bbe9c618bb88bbcefb008a5ea6bed4ff949
+
+[Plen = 15]
+
+Key = fab62b3e5deda7a9c1128663cc81c44b74ab1bfe70bc1c9dec7c7fd08173b80a
+Nonce = a5c1b146c82c34b2e6ebeceb58
+
+Count = 150
+Adata = 5e60b02b26e2d5f752eb55ea5f50bb354a6f01b800cea5c815ff0030b8c7d475
+Payload = 54be71705e453177b53c92bbf2ab13
+CT = 788db949697b8cd9abbc74ed9aa40cd6852dc829469368491149d6bb140071
+
+Count = 151
+Adata = 210c04632341fbfc185bfe3cbf6fe272bbe971104173bcb11419b35ab3aaf200
+Payload = 22197f9ad14591e7a6d5f8b18c969a
+CT = 0e2ab7a3e67b2c49b8551ee7e4998556940dc5a7e44bf10234806d00a012b5
+
+Count = 152
+Adata = d3a205dd017e79a67400a937a20ef049f4c40d73311731f03ab857a3f93bd458
+Payload = 096b2f530933c1273304a6ad423726
+CT = 2558e76a3e0d7c892d8440fb2a38390898f7dbde25b0b70d335df71a06987b
+
+Count = 153
+Adata = 0c9b3ba4faf5fc2f310ad1bab06c4ca13474b714feeffb6ad615c1b850bbd6a3
+Payload = d44fdfd9da3a63c1083afe574e91bf
+CT = f87c17e0ed04de6f16ba1801269ea02fd10d1f21b6b963c05aeda8eb09e272
+
+Count = 154
+Adata = d9bb71ad90152d5c1af358c8501fa89ebd4b17bf4ff43841528cccb79fd791b3
+Payload = 8d836acc13ed83c2b2c706415c9679
+CT = a1b0a2f524d33e6cac47e0173499664491d23d90ff55abca17e9d943b98c7f
+
+Count = 155
+Adata = 69dc21eb6f295b12ba493ee8fe6c40d78af946067ce772db316a3cbf00d3c521
+Payload = 2a68e3fe746f593c1b97cb637079c3
+CT = 065b2bc74351e49205172d351876dc9616886c6b2adc97db5a673846b6662c
+
+Count = 156
+Adata = 095eb52135dc6d9c1f56a2571c1389852482e7aa3edc245a3904a0449db24a70
+Payload = 39799b001ed2c334c269acb0f2328c
+CT = 154a533929ec7e9adce94ae69a3d932441dcae1760db90379bd354fa99164e
+
+Count = 157
+Adata = efd7270e0396392fde8b0ddaab00544cbbd504f4d97d4e90d749d1946de90dcb
+Payload = 42143a2b9e1d0b354df3264d08f7b6
+CT = 6e27f212a923b69b5373c01b60f8a9c7c7deb28bdcf84886ef843216b94449
+
+Count = 158
+Adata = 8bc181ce2e66294e803a8dc3834958b5f173bc2123c0726e31f3fca25b622ed6
+Payload = a3dcf26327059a4245b79a38bb8db6
+CT = 8fef3a5a103b27ec5b377c6ed382a935061ae3cd892ba63c44b809d6d29421
+
+Count = 159
+Adata = c39ec70c2c71633ae0dccc41477ac32e47638c885cf59f34ebd4a096d32f91f9
+Payload = 3d54883449ecca8f153436c25a0a01
+CT = 1167400d7ed277210bb4d09432051e3c9ae69a4c59ff8e251c2fe022d065a9
+
+[Plen = 16]
+
+Key = ee8ce187169779d13e443d6428e38b38b55dfb90f0228a8a4e62f8f535806e62
+Nonce = 121642c4218b391c98e6269c8a
+
+Count = 160
+Adata = 718d13e47522ac4cdf3f828063980b6d452fcdcd6e1a1904bf87f548a5fd5a05
+Payload = d15f98f2c6d670f55c78a06648332bc9
+CT = cc17bf8794c843457d899391898ed22a6f9d28fcb64234e1cd793c4144f1da50
+
+Count = 161
+Adata = a371ca29b92ed676bab5dfc4d78631bb6d9bb23a29f822907084a1f0fe17721f
+Payload = 60d55a8d5ab591a51e87fdf6aaa2ad25
+CT = 7d9d7df808aba2153f76ce016b1f54c68b55bbe42d8c97504b97c34a5f16e6a6
+
+Count = 162
+Adata = 01ec87920b42639d4ba22adb1fbe5138d2849db670a2960fd94a399c1532ed75
+Payload = cbf112e4fb85276c4e09649f3de225b2
+CT = d6b93591a99b14dc6ff85768fc5fdc51017d8706acd676ae99e93d5312a4113c
+
+Count = 163
+Adata = eebd2bbf1e9f6d817cd8062a6a9680e7f10464eefeb50b07cb46b14b9b3fcb2c
+Payload = 865b89aa38ee1b5a3ce56620307e8937
+CT = 9b13aedf6af028ea1d1455d7f1c370d45982f0fe5d951a8c62c87894657301e4
+
+Count = 164
+Adata = 72863362612f146699f6b2f6ec3688f2ca6cb1505af7a309c91c1933e34d516a
+Payload = a8efc37d1b8b51f2a47b21dd14da383d
+CT = b5a7e40849956242858a122ad567c1de5addfddbb59f4985947fb3a9ab56333e
+
+Count = 165
+Adata = 9c9efc6593f96207678db813608f2b8bc33ed1bef974ed77ed7b6e74b621b819
+Payload = d9b0eaaff786165f882f41a98dbc0c35
+CT = c4f8cddaa59825efa9de725e4c01f5d6b651053516673402a57538db1a9ce7e9
+
+Count = 166
+Adata = dc482a051b58d8a3904d3af37c37b51983f634a504451bbba6f77d71337f8e78
+Payload = df49d972b6ebbbb18ee975ac635d847e
+CT = c201fe07e4f58801af18465ba2e07d9d86d772b1a1991b7be6589bbccad36171
+
+Count = 167
+Adata = 51ef065a43caa23faf750b02a41ad6ba701aeb8058f6d8738d6f6b005bec7f60
+Payload = 78318aa5cd16699b77bdcea2fc9d1d20
+CT = 6579add09f085a2b564cfd553d20e4c3569387a1a6bcc826e94012670820576e
+
+Count = 168
+Adata = 88e2a74d2920c89c6a101f5f06d0624a6d5eabd9bdb51395ee3983934c55c73d
+Payload = 8e20d65d02dd9a64379f75b6d8328f2d
+CT = 9368f12850c3a9d4166e4641198f76cee9c788b4aae9b2c6caf0c44aa9bd2ed0
+
+Count = 169
+Adata = ada3ed7db2dabbfbc441ef68a5656e628d6d5bd6c1574369688497179a77601a
+Payload = 97e8d8513af41b97801de98cc4269096
+CT = 8aa0ff2468ea2827a1ecda7b059b6975f1df0f01944641a1b04d753e6ab8d3cc
+
+[Plen = 17]
+
+Key = 7da6ef35ad594a09cb74daf27e50a6b30d6b4160cf0de41ee32bbf2a208b911d
+Nonce = 98a32d7fe606583e2906420297
+
+Count = 170
+Adata = 217d130408a738e6a833931e69f8696960c817407301560bbe5fbd92361488b4
+Payload = b0053d1f490809794250d856062d0aaa92
+CT = a6341ee3d60eb34a8a8bc2806d50dd57a3f628ee49a8c2005c7d07d354bf80994d
+
+Count = 171
+Adata = 4ae414bc888a42141d3060c71c2dbbffd425b6a952806982271a8e756b3c9e24
+Payload = 51eb190c6a9f46e8ec1628b090795470c0
+CT = 47da3af0f599fcdb24cd3266fb04838df13c1c5755a5a240c33b2b890a486aac8b
+
+Count = 172
+Adata = 7b7f78ae1a5ee96fdc49dacd71be1a6ac09a6a162d44dea0172886eca5674e46
+Payload = 25144e807e389bb0e45b6dc25558caf61a
+CT = 33256d7ce13e21832c8077143e251d0b2b4cfca1c19abf447d7bc0898d61885144
+
+Count = 173
+Adata = 03f31c6143b77f6ad44749e2256306b8bf82242f2821fad4075b09b388ba81ca
+Payload = dbe1ee14abfe2ecf4edf6db206cf9886ce
+CT = cdd0cde834f894fc860477646db24f7bff229cc7a390867a245dcb7c434f1db347
+
+Count = 174
+Adata = 030390adb572f2bd2a6a4454fd68236cd1d465574328aa001d553375cc63f8a2
+Payload = db6df31f12bf552f81deff5fa2a373fc22
+CT = cd5cd0e38db9ef1c4905e589c9dea401135361b539f9fe0fb7842907c2326aef63
+
+Count = 175
+Adata = 7294ae94358669f2ada4b64c125b248df7fe86c6715e3b6a7b9bb2bd99392c8a
+Payload = ff2a97b49fcc6a50d4549c979d53ccc51f
+CT = e91bb44800cad0631c8f8641f62e1b382e8ed10943929e7d7bf798b2ae8371aae5
+
+Count = 176
+Adata = 4d1513478fc1fb0a18eb6d2a9324fefbd975ecd1b409025de826bc397462acc1
+Payload = 73ddfa0185200a890b7690a7e3986d8818
+CT = 65ecd9fd1a26b0bac3ad8a7188e5ba7529f92b9e49ab83f113f8949dc9e4a36e0d
+
+Count = 177
+Adata = b26a7ff61bfe94864249af7cc9b4a723627dd4463f5a22f0ca6063769522eab7
+Payload = 5c7604f9ac8fdf30ee5820e5aeb75b65d7
+CT = 4a4727053389650326833a33c5ca8c98e6d0e53223adff22a08e3dddf66fff23e3
+
+Count = 178
+Adata = 960f9a85cfbfb6eab223a4139c72ce926a680ea8e8ecc3088cf123de659ad310
+Payload = d44fdfd9da3a63c1083afe574e91bf01c9
+CT = c27efc25453cd9f2c0e1e48125ec68fcf833f49a42521a7a2367f91bfcc2180b7c
+
+Count = 179
+Adata = 3718467effb5d5dc009aaefce84d8cb4fe8f80eb608f4c678f5d0de02ea11e59
+Payload = bb515dc227abb9acad8fefaa14771bb77b
+CT = ad607e3eb8ad039f6554f57c7f0acc4a4ac08bd395c6807223311070659f550934
+
+[Plen = 18]
+
+Key = 0786706f680c27b792d054faa63f499a8e6b5ddb90502946235bf74c022d772c
+Nonce = f61ef1c8c10a863efeb4a1de86
+
+Count = 180
+Adata = 67874c808600a27fcab34d6f69cc5c730831ad4589075dd82479823cb9b41dc3
+Payload = 6a26677836d65bd0d35a027d278b2534e7df
+CT = d1c1f3c60603359c7d6a707f05ecb2296f8e52f2210b7a798ad5c778ee7cfd7fe6e0
+
+Count = 181
+Adata = e0c27cddf919d3092d9a34766c89a5ae6dcf39fe954d1e6f1a70ddf96805def4
+Payload = 4021ff104ff1dbd91e46db249fd82198b0a1
+CT = fbc66bae7f24b595b076a926bdbfb68538f00923bb5a347af13df12f234fca5f03ef
+
+Count = 182
+Adata = 7ae9eca03f616ab39ebb3be26b848842b4aa584e5c8e5695065ad5af34951175
+Payload = 6a681f164efce199a787bccff223b8ae1a98
+CT = d18f8ba87e298fd509b7cecdd0442fb392c9d03ed7bffac83e890caceb6903d9cab5
+
+Count = 183
+Adata = b47c9bc4eb01c74f5db2e6a293bef80db18c58cf06feef7ee0f8a7a9a51c22bb
+Payload = 7861dac338ba3f8274dca04c8c6f92b6d44c
+CT = c3864e7d086f51cedaecd24eae0805ab5c1d4dd8f30870025b2bd1e2a2511574d3e7
+
+Count = 184
+Adata = f6afd661f218c7426b92ee53e65d14898cd0c78a7e594fcc6ac0e3fb5cab1c9c
+Payload = a3f0473c620d2739d5ba4f7156f88d0fb669
+CT = 1817d38252d849757b8a3d73749f1a123e386046d17f337f3cb49884d94995edbdc9
+
+Count = 185
+Adata = d3802911e341577046cfc61d9043b4af059fb4bef3c6a2ff46ccdcb05670af37
+Payload = 07c535d9456a6ff1e41321150d16dae3f7a3
+CT = bc22a16775bf01bd4a2353172f714dfe7ff25fdc77b43bca254d6459263cdfed8fbb
+
+Count = 186
+Adata = db60720db67a60ca286fe744d46173c231fbcc7deb4c9b0d87d52a2247e06b74
+Payload = 5ee220720a896249efdab2ce418318bb5ebf
+CT = e505b4cc3a5c0c0541eac0cc63e48fa6d6eedd1a1d36c8164c55d55dbf0ff1e9517a
+
+Count = 187
+Adata = 57f70ba5493265b30491decc726354e2065e7971a2efd56db9cf0f79b1d76859
+Payload = 98e4eb0361c8bf40bcbe0539b0850e4c35ff
+CT = 23037fbd511dd10c128e773b92e29951bdaeb476e2ca48fd52bec0539b00744a8a07
+
+Count = 188
+Adata = 4a29b9ad548964942f87f28ba267ec0d0e8f72c73b3823ee57693dd63c2605c1
+Payload = 7f0745bea62479c0080ecec52e37c1e32d72
+CT = c4e0d10096f1178ca63ebcc70c5056fea523fad68c62b81d62f2d490ae74f5bb1465
+
+Count = 189
+Adata = acbd2e9911b3218a230d9db5086d91dccac3fc93fc64b0f4a15d56954906b2b7
+Payload = e99ed2ac6c38e033061b5d85f3e77dd72518
+CT = 527946125ced8e7fa82b2f87d180eacaad4913b15d8000266c61ba5aec898eb35b52
+
+[Plen = 19]
+
+Key = bac55f9847d93325bf5071c220c0a3dfeb38f214292d47b4acb7b0a597fe056f
+Nonce = 05b50c458adbba16c55fcc454d
+
+Count = 190
+Adata = 89ad6ae1e550975eaa916a62615e6b6a66366a17a7e06380a95ea5cdcc1d3302
+Payload = c1a994dc198f5676ea85801cd27cc8f47267ec
+CT = 7c9b138177590edaafec4728c4663e77458ffbe3243faec177de4a2e4a293952073e43
+
+Count = 191
+Adata = dfddb719d00398bf48a6cefd27736389e654a93b8595cd5ac446af1996e0f161
+Payload = 791e232bfb42fb18197adc1967da1a83f70168
+CT = c42ca4769594a3b45c131b2d71c0ec00c0e97f8422f736fc435687634d42254b22fd99
+
+Count = 192
+Adata = 58ef310997dcaf067dd217274921504da6dbf0428a2b48a65fe8a02c616ac306
+Payload = 3d4127942459bb8682e662dfc862467582fa68
+CT = 8073a0c94a8fe32ac78fa5ebde78b0f6b5127f38a96e68ef7dbaef1b460cc0980eacd4
+
+Count = 193
+Adata = 511e5d5e100b595f6b20e791830bca37e23f7b785e482a58405bffe7a632a5b8
+Payload = 0e71863c2962244c7d1a28fc755f0c73e5cbd6
+CT = b343016147b47ce03873efc86345faf0d223c15c5c702a82d468929227502e4e35796f
+
+Count = 194
+Adata = e48dfaa53b6807ea6f01d8dca67960b9f321f7851f324459a9bf61fe0be73abb
+Payload = e0f1cd013e6aea4fa484fc3fa35d348b1a2399
+CT = 5dc34a5c50bcb2e3e1ed3b0bb547c2082dcb8e89188c0940182dd99a902d158c5b0810
+
+Count = 195
+Adata = c12c0423fe36e4c88775dd00b4af267b85b7dd2a37a742a3156923c8917c97a3
+Payload = b1cc1946b4fc1dbd033254cdf536f61e9f9cd7
+CT = 0cfe9e1bda2a4511465b93f9e32c009da874c015849acbb7af1892790300bb84fb0558
+
+Count = 196
+Adata = 4255f8af18df7237e0abe98421aec9634443561752d893aaffe76380e829ef32
+Payload = 87284658928208e3bddca83e3ceb13708d88d4
+CT = 3a1ac105fc54504ff8b56f0a2af1e5f3ba60c3e75aaf3077ac6dfb5454851ec3910de6
+
+Count = 197
+Adata = ab83567833d2f3461b5fbecc0e366694bb5ea00933b2b3e792ec3aefe20325df
+Payload = bdb79f931ef3035a33bdd1b032fd9de8f6b2ba
+CT = 008518ce70255bf676d4168424e76b6bc15aade70f42e3e1f2b5bb58433bd11f5dea1f
+
+Count = 198
+Adata = bd1446ba3185d1c16551730947c22142142caa8cc1c540e89ab734ec297401bc
+Payload = 1f9c3a8eb8bc59f3869e10f73883aa8f8990cb
+CT = a2aebdd3d66a015fc3f7d7c32e995c0cbe78dc564f6248cefe5fc7cfb547c90a558925
+
+Count = 199
+Adata = b87577755d2d9489194f6f7cfabf267dc3433a9c91954e81beb72c5e06870922
+Payload = 5f28809181f9a889894da8d6fe1fde6cce354a
+CT = e21a07ccef2ff025cc246fe2e80528eff9dd5db52249d812f7f235afa0732e984e91b2
+
+[Plen = 20]
+
+Key = 8beedeb85d42c2a7fa6f7237b05acb197dd8e1672471ac878064fe5319eab876
+Nonce = 8479bdfad28ebe781e9c01a3f6
+
+Count = 200
+Adata = 7aebdfd955d6e8a19a701d387447a4bdd59a9382156ab0c0dcd37b89419d6eff
+Payload = 7b125c3b9612a8b554913d0384f4795c90cd387c
+CT = 6cc611d816b18c6847b348e46a4119465104254a04e2dfeeeac9c3255f6227704848d5b2
+
+Count = 201
+Adata = d119f300fbd74e754a200ea2c3f9fabc1466d02078c84245db693eef3f5672a6
+Payload = 8b013f5782d5d1af8dbd451a4202866095dac975
+CT = 9cd572b40276f5729e9f30fdacb7e67a5413d44338d48329997c5981d678b5e24a6f01b0
+
+Count = 202
+Adata = d6204303b86acf62d5ab860ca70161288ede56e3cf017c08dca56fd2d6f8f6fe
+Payload = b2b1d82a5523b72ea366a680922ed3a4624536c4
+CT = a56595c9d58093f3b044d3677c9bb3bea38c2bf2a77e3ab68e0a73519591a33ed098b758
+
+Count = 203
+Adata = 8557e22eb4529b43f16b1f8ae47c714ac8a2c827c1408a47704778b4c5b52601
+Payload = f8c4eb4285d3d7744da52775bb44ca436a3154f7
+CT = ef10a6a10570f3a95e87529255f1aa59abf849c1cff6c24251c2fb7b8604dfa10c60ef4a
+
+Count = 204
+Adata = 8c1a4187efbb3d38332f608f2c8bbe64247d9afa2281ced56c586ecb4ab7a85e
+Payload = 6e7fe35fa39c937a0e6b3a8c072e218650f42b8d
+CT = 79abaebc233fb7a71d494f6be99b419c913d36bb6c3c39f915d081d34559179869b32d81
+
+Count = 205
+Adata = a41bb1f256228302cd0548ae2148ff42774d18c2d6d3e38b36bc4938da13bac3
+Payload = 917b467d841850fc6e648f1bc298a7f9f1ee38ca
+CT = 86af0b9e04bb74217d46fafc2c2dc7e3302725fc9389a6a6a74c6eb0e1f87562469f2082
+
+Count = 206
+Adata = b0b024e20c4f75a6dad54c21a9edbce846792e957878b1c8ed2d916c757e2b3c
+Payload = 2b4314fe1a6bfa786b7cfc13fbee861b348efbf6
+CT = 3c97591d9ac8dea5785e89f4155be601f547e6c03bed3a2f5dfdbfcc0d7ac26c88d1962c
+
+Count = 207
+Adata = 42153925c46fc9d5d328312d62f59bb99fdc4ac479a3386d5f88fefd4b32f577
+Payload = e19fa7f83c79920cbff45c41a9dee8fc99e97396
+CT = f64bea1bbcdab6d1acd629a6476b88e658206ea035ea1d99be344fa1467ee91c73bbca67
+
+Count = 208
+Adata = 37ab2a0b7b69942278e21032fc83eba6cdc34f5285a8b711a08da6acd42299fe
+Payload = 53e0475cf492b3d39dad600f5c58eb0bd0021554
+CT = 44340abf7431970e8e8f15e8b2ed8b1111cb08627936ec10a81b36768b606e9a38b2f4c5
+
+Count = 209
+Adata = 4a17522da707b4b2587a0ae367a2cd2831bb593a18ef442a7977eda6de045878
+Payload = c119a383d9a3d4bff4270a1d22076b346db5f61c
+CT = d6cdee605900f062e7057ffaccb20b2eac7ceb2a11575ae03ea8a57bbe4a67c060367b74
+
+[Plen = 21]
+
+Key = c3a0c126cad581012151c25cf85a44472c23f83b6095b6004f4f32cd60ec2db2
+Nonce = 94ab51ce75db8b046d6ab92830
+
+Count = 210
+Adata = 2a243246bfe5b5ab05f51bf5f401af52d5bbaa2549cf57a18e197597fe15dd8c
+Payload = 73b09d18554471309141aa33b687f9248b50fe3154
+CT = b7e8264ca70fd2a4fb76f20a8ad5da3c37f5893fb12abeeaef1187f815ca481ed8ddd3dd37
+
+Count = 211
+Adata = 0595306eb7441622a49800edee0134492d82320707fceba902af2e0c95fe634a
+Payload = b64d00f3a4df754fa4ee6376922fb67ccce0c6209f
+CT = 7215bba75694d6dbced93b4fae7d95647045b12e7accc2b55011dbe92ce7619e0ad48b4ccf
+
+Count = 212
+Adata = bd439dbefec589e120fb4f9825b315bf86523b85c61791cd4da4c8d474ba2714
+Payload = 2b11d1ac74ffe701ec733d32085b1054132726e622
+CT = ef496af886b444958644650b3409334caf8251e8c71e8b1f4d70d8f4c7df4f22847d36b394
+
+Count = 213
+Adata = cfebe1cf82267394065bcecfada6709c6c35a3ac835644f560d4c9a8c1848364
+Payload = a88f22424643a523aa3d7d88f4364f1290f49dd0a2
+CT = 6cd79916b40806b7c00a25b1c8646c0a2c51eade47a85e76a9d07b7b361ca56d53c34cda50
+
+Count = 214
+Adata = 7a37255b682766a0bfecf78e5162528885a339174c2a49325739d2bd8877e64f
+Payload = c81427bc84c6a3cfefd4c4cb210fe82212977e1947
+CT = 0c4c9ce8768d005b85e39cf21d5dcb3aae320917a2fddb010e7508ad03ad287068ecee6020
+
+Count = 215
+Adata = 619f2ae80070e278615466a3fd6c9acb7b510c5679bed7038889c77e78d8bd32
+Payload = 28c4d6de3e2ce51b849b135d9cfd3084f0e3155447
+CT = ec9c6d8acc67468feeac4b64a0af139c4c46625aa2ddea785e6c470c52c4fdf432fd78b66e
+
+Count = 216
+Adata = b2571e56f66a857daffbdc99370ceddd4a7bed3867d600cc797000a3b7b57a9d
+Payload = 4c88151cafef75832bacef43a06e862349d56b67ee
+CT = 88d0ae485da4d617419bb77a9c3ca53bf5701c690b91232cfbd7ffff252498b35274fb2995
+
+Count = 217
+Adata = db409636e3e3bcd606a91aeb7592009896f9ad2c4cc6b7f578e6ad59c0f8fa22
+Payload = 572855e22ce89bc2bcf09cb15a1765d99973449d61
+CT = 9370eeb6dea33856d6c7c488664546c125d633938472b2c50e5e391ad104f9ee33b94f2872
+
+Count = 218
+Adata = 62c89a835721207a182968c516dc8be45774ec846e8dcab9ab8611888f2a76a8
+Payload = 89ce46b3de3afaf2518d419b1a2ac24cabca269a96
+CT = 4d96fde72c7159663bba19a22678e154176f5194732d69c5d6db1b130102af3dae0690673b
+
+Count = 219
+Adata = 33f30ddd83002eea50fd4a8fae39d0980a04160a22ac88b755ac050f1d1f8639
+Payload = edf1682a626e9fbf3d57bb260e0876c6f92ba5b114
+CT = 29a9d37e90253c2b5760e31f325a55de458ed2bff1489903365970c2673c9fd457e1077aad
+
+[Plen = 22]
+
+Key = 9cdebaeee8690b68751070691f49593668a6de12d3a948b38ddbd3f75218b2d4
+Nonce = af1a97d43151f5ea9c48ad36a3
+
+Count = 220
+Adata = f5353fb6bfc8f09d556158132d6cbb97d9045eacdc71f782bcef62d258b1950a
+Payload = 3cbb08f133270e4454bcaaa0f20f6d63c38b6572e766
+CT = 3966930a2ae8fdd8f40e7007f3fde0bd6eb48a46e6d26eef83da9f6384b1a2bda10790dadb3f
+
+Count = 221
+Adata = e3a1555ffe5f34bb43c4a2dae9019b19f1e44a45fb577d495d2a57097612448d
+Payload = 946e86795c332031e2d1ee09d3d4a101fb6800d00911
+CT = 91b31d8245fcd3ad426334aed2262cdf5657efe408a5587bdd120a7d08cd3841cb117af444fb
+
+Count = 222
+Adata = 9c5d43c1a1269cde199509a1eff67cc83a1759b71c9e7a6ee99f76b98c6e23a6
+Payload = b76ce2ab0065ba1c0a754494991c8c452cb416f18ab1
+CT = b2b1795019aa4980aac79e3398ee019b818bf9c58b0545b32f81dcf03e2bcc2aaf62ad366e97
+
+Count = 223
+Adata = b07452a7900a289b91b2771dfdd5108852536659aa259def7b41e38f80bd03ab
+Payload = a3e0d8d0784155bfc45769c52711d4fa68e8bc390c20
+CT = a63d432b618ea62364e5b36226e35924c5d7530d0d94fea17d78533bc9e022dbfb460afdf499
+
+Count = 224
+Adata = 6b30f55c3101540523a92380390f3f84632f42962061b2724cde78ac39809397
+Payload = 6e6a88abbb52a709b47365ad6aa8016fa9a03a9bd834
+CT = 6bb71350a29d549514c1bf0a6b5a8cb1049fd5afd98056defc6dcaeec80b1c639350ab6f1fde
+
+Count = 225
+Adata = 9fc62d14f8b7a6026509275cff80312ff1ade2b5d9c274cb72a506a571439fc1
+Payload = eba1810d537041821121aeff8e0914ac26a550072c8c
+CT = ee7c1af64abfb21eb19374588ffb99728b9abf332d389d37b7251fb8c0ef2b37c36d51219d0f
+
+Count = 226
+Adata = 6b9389cc42113d639fd2b40cbc732ae0dc7c14513b88b36b45a6ea5a06fe4d2b
+Payload = dfc6692cd2442e5ff1f918c8812a27f81d107d16a12f
+CT = da1bf2d7cb8bddc3514bc26f80d8aa26b02f9222a09bd279d9da4437c8a2a252436508134c56
+
+Count = 227
+Adata = db72d98d63fc10acff7dceec0e2691a80ecee50a0e957ad166c77952a50318bd
+Payload = 9ad338cbfd1b52e6ae4178f05e00062274f8b0b25eae
+CT = 9f0ea330e4d4a17a0ef3a2575ff28bfcd9c75f865f1a63943543bc1c5f5991ecc5964a288f79
+
+Count = 228
+Adata = e98b710c47a4d12a73cd8aa2613fc2910c16f4195ea7f15650132493521d19be
+Payload = 9f5a05db89e0e336da066ce81b79ad9be1d0ec4fb7b8
+CT = 9a879e20902f10aa7ab4b64f1a8b20454cef037bb60c0a49ee2b7ceddcbd28abb24b77d5edee
+
+Count = 229
+Adata = 527817316fc48b105f8ab178dd2db1fefa09c50461aa9d8bdf3c03482343bbf9
+Payload = 58f31e5770070a5d4031fb795dc2d298561d3559960d
+CT = 5d2e85ac69c8f9c1e08321de5c305f46fb22da6d97b9b099a68cfa3572d974e03232e09f37fb
+
+[Plen = 23]
+
+Key = d34264a12c35cdd67ac105e2826b071e46f8131d1e325f8e0ae80a6447375135
+Nonce = 3891e308b9f44c5b5a8b59004a
+
+Count = 230
+Adata = 0cda000ed754456a844c9ed61843deea9dadf5e723ea1448057712996d660f8c
+Payload = 79ac1a6a9eca5e07ce635bfd666ef72b16f3f2e140d56c
+CT = 1abcc9b1649deaa0bfa7dcd23508282d9c50ca7fee72486950608d7bcb39dcf03a2cab01587f61
+
+Count = 231
+Adata = 3fb6ddb76809b8e6d703347664ef00a365955124c603900d5c8d4ff476138252
+Payload = 76d12e3c4c5d990bf563c60aa4999e52998d887f97477f
+CT = 15c1fde7b60a2dac84a74125f7ff4154132eb0e139e05b1c4fb40e5c8bc37152a173d4bbb18c3e
+
+Count = 232
+Adata = d9fc295082e8f48569eb073ac1b9566246728fc62ccaab4a5667c472c98b2626
+Payload = a027c28fbe22111fd4c8a226cfe8531c16d7790d561eca
+CT = c33711544475a5b8a50c25099c8e8c1a9c744193f8b9ee019c359008adae3070b5a543ead0effb
+
+Count = 233
+Adata = 7a459aadb48f1a528edae71fcf698b84ed64dc0e18cc23f27ab47eeabeaf833f
+Payload = fa597e37c26c38694abdcf450f9edc529160fa0d651979
+CT = 9949adec383b8cce3b79486a5cf803541bc3c293cbbe5dbd099ab134756b90746762a92a4a9f7f
+
+Count = 234
+Adata = 484207909dec4c35929ebe82fcacf20d2af6d850bd69364ebac9557adeadfbd4
+Payload = 9e4c8aa9b58a8eabc5586892f5541000b43f17d9a051a0
+CT = fd5c59724fdd3a0cb49cefbda632cf063e9c2f470ef684fa4f6adfec85d055310107ba89198afa
+
+Count = 235
+Adata = 88b5448372548e6aab1b262630a28a471d285514703f1bdb10c695850e18fe6d
+Payload = 7d9582cf9e3bb9ee34dce965f56b08e716589486b0641c
+CT = 1e855114646c0d4945186e4aa60dd7e19cfbac181ec338915d23eb2e952afcc89fbddb567d9d75
+
+Count = 236
+Adata = 0e71863c2962244c7d1a28fc755f0c73e5cbd630a8dbdeb38842d7795d830d2e
+Payload = 5a387e7cc22491fc556fe6a0c060b4911d01f0c11f801e
+CT = 3928ada73873255b24ab618f93066b9797a2c85fb1273aaad6c31828314e24198f005955ca8f5e
+
+Count = 237
+Adata = 2aa7a28da38c42fda2e578d9d6340cd8e80b9b32047c3db296d0640d517b0872
+Payload = 87946e910059cbaf48df63b220f397049c65ca10cd1920
+CT = e484bd4afa0e7f08391be49d7395480216c6f28e63be04e531ebbadccfe47182b41904bbfebcfe
+
+Count = 238
+Adata = 3382051c268891da04e6ca73adcead4029f6a1593be4acfe3968e7351a6a2fb5
+Payload = c62f67d208f1c8ffd5d57df9de15ef54f97fbc07d1630a
+CT = a53fb409f2a67c58a411fad68d73305273dc84997fc42e7c582414154236c09ee704cf4a5de411
+
+Count = 239
+Adata = c352828b1920e53bbb60f2ea6a5f15639659e6f3243405c26f6e48628d5519a9
+Payload = 697e73eaaf562d31bdbf7ce9e78c7426fe1c87e421def9
+CT = 0a6ea03155019996cc7bfbc6b4eaab2074bfbf7a8f79dd57c9990029c89d1b37988745fa5737a3
+
+[Plen = 24]
+
+Key = 4ad98dbef0fb2a188b6c49a859c920967214b998435a00b93d931b5acecaf976
+Nonce = 00d772b07788536b688ff2b84a
+
+Count = 240
+Adata = 5f8b1400920891e8057639618183c9c847821c1aae79f2a90d75f114db21e975
+Payload = 9cea3b061e5c402d48497ea4948d75b8af7746d4e570c848
+CT = f28ec535c2d834963c85814ec4173c0b8983dff8dc4a2d4e0f73bfb28ad42aa8f75f549a93594dd4
+
+Count = 241
+Adata = 1ae8108f216defea65d9426da8f8746a3ae408e563d62203063d49bf7e0d6bdf
+Payload = 2b223932fb2fd8433e4b1af9e8234a824569a141f6c96a69
+CT = 4546c70127abacf84a87e513b8b90331639d386dcff38f6f4de907a59c5e4d3f21e1348d7cdf92b6
+
+Count = 242
+Adata = 460f08114b1015fe8b7a9b5dd1b9e6a3d28367c4bd15f29b13c02a8cb9a53968
+Payload = 4d57cbe4a7e780d4ed17267d5ebc91750c2f0209e0444bd2
+CT = 233335d77b63f46f99dbd9970e26d8c62adb9b25d97eaed4ff4239544e2f354d6c6837cd9c23b884
+
+Count = 243
+Adata = 860f4428259d9c5b17698cc95363db6cfee603258582e3a3e8feb886599d4ac4
+Payload = fda8665f87c618646a89c7abdca275fd10c31453ad4b9c99
+CT = 93cc986c5b426cdf1e4538418c383c4e36378d7f9471799f3f6c6f7cc494201069344e2d6d41bd9b
+
+Count = 244
+Adata = 1b43c482f83780c21583f88e5afcf6938edd20f21b74d895161b60c27a6a42f0
+Payload = 98104fd3f3413ad1f57ef4912cb50097dca379a58c47b0d2
+CT = f674b1e02fc54e6a81b20b7b7c2f4924fa57e089b57d55d43787a15352cfceb028202c8730beaa7a
+
+Count = 245
+Adata = b082ccd964617c27a5607b7324faad237ee53acfc18c35502dbf7c1937a9dfcb
+Payload = b46b343e64d2d70e0bd909dbb3f6bedf7e4adc74321be526
+CT = da0fca0db856a3b57f15f631e36cf76c58be45580b210020f3a0ca3da647eb31893e867956097983
+
+Count = 246
+Adata = b8539ba93ef17254ec1d8d62e8f4eae4d41ee1e75345bf90c9cbb26c63bce501
+Payload = 8e12620bb575e6b167b085255b2b5631ff28e04cbef8826d
+CT = e0769c3869f1920a137c7acf0bb11f82d9dc796087c2676be663fbbebbc251b9f1760afa49e89e71
+
+Count = 247
+Adata = b6b09463b5ef5ead1f17f4021693a0d8452e98dcbb8e7590f9fde6394970a6f8
+Payload = 792aaa23b923d1b53173fe19853b9aa402a301d48529873e
+CT = 174e541065a7a50e45bf01f3d5a1d317245798f8bc136238da90cd87e9d9ca5d85430a150e682752
+
+Count = 248
+Adata = 390f6de14d5e1f2f78dbe757c00b89209d0cf8bc48cbbea035779f93de357905
+Payload = ddc5b4e48970ebd72869be6998e9103c014475e8ae6ea29c
+CT = b3a14ad755f49f6c5ca54183c873598f27b0ecc49754479afc0cc4601afb61efa7059cfe49ec9dde
+
+Count = 249
+Adata = 1d75c9e7acb09932db332498d30f82e4009025cb1827047c59a8f97812b568a4
+Payload = d2b66096c475a77648c27235e6972ba8f18761330d3c6adf
+CT = bcd29ea518f1d3cd3c0e8ddfb60d621bd773f81f34068fd9cf7474962c3602dcfcb50039f43e3d6f
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT128.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT128.rsp
new file mode 100644
index 0000000000..0e56a03d42
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT128.rsp
@@ -0,0 +1,1589 @@
+# CAVS 11.0
+# "CCM-DVPT" information
+# AES Keylen: 128
+# Generated on Tue Mar 15 08:09:25 2011
+
+
+[Alen = 0, Plen = 0, Nlen = 7, Tlen = 4]
+
+Key = 4ae701103c63deca5b5a3939d7d05992
+
+Count = 0
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = 02209f55
+Result = Pass
+Payload = 00
+
+Count = 1
+Nonce = 3796cf51b87266
+Adata = 00
+CT = 9a04c241
+Result = Fail
+
+Count = 2
+Nonce = 89ca5a64050f9f
+Adata = 00
+CT = f5f915df
+Result = Fail
+
+Count = 3
+Nonce = ec9d8edff25645
+Adata = 00
+CT = 7a3c3499
+Result = Fail
+
+Count = 4
+Nonce = 05e16f0f42a6f4
+Adata = 00
+CT = f09c2986
+Result = Pass
+Payload = 00
+
+Count = 5
+Nonce = 2e504b694f8df5
+Adata = 00
+CT = 4ae97e71
+Result = Fail
+
+Count = 6
+Nonce = 06d102a9328863
+Adata = 00
+CT = ecb38c8b
+Result = Fail
+
+Count = 7
+Nonce = c288b810fb5334
+Adata = 00
+CT = 9c4dc530
+Result = Fail
+
+Count = 8
+Nonce = 08a166d9eb6610
+Adata = 00
+CT = 67299ef6
+Result = Fail
+
+Count = 9
+Nonce = 4a5810b121c91b
+Adata = 00
+CT = b0538d02
+Result = Fail
+
+Count = 10
+Nonce = 44077341139bf9
+Adata = 00
+CT = 88200ea8
+Result = Fail
+
+Count = 11
+Nonce = a9df4f37847e1f
+Adata = 00
+CT = 19867aa5
+Result = Pass
+Payload = 00
+
+Count = 12
+Nonce = 11df57fcd131e9
+Adata = 00
+CT = 3b392a52
+Result = Pass
+Payload = 00
+
+Count = 13
+Nonce = 890fff56d10dc0
+Adata = 00
+CT = 1c5e47e0
+Result = Pass
+Payload = 00
+
+Count = 14
+Nonce = 9dc18698731b27
+Adata = 00
+CT = 97a56b8b
+Result = Fail
+
+[Alen = 0, Plen = 0, Nlen = 7, Tlen = 16]
+
+Key = 4bb3c4a4f893ad8c9bdc833c325d62b3
+
+Count = 15
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = 75d582db43ce9b13ab4b6f7f14341330
+Result = Pass
+Payload = 00
+
+Count = 16
+Nonce = 3796cf51b87266
+Adata = 00
+CT = 3a65e03af37b81d05acc7ec1bc39deb0
+Result = Fail
+
+Count = 17
+Nonce = 89ca5a64050f9f
+Adata = 00
+CT = efc5721e0b9e4c3c90deab0e1d5c11bd
+Result = Fail
+
+Count = 18
+Nonce = ec9d8edff25645
+Adata = 00
+CT = 91b4b779823f4f0e3979ced93b99736c
+Result = Fail
+
+Count = 19
+Nonce = 05e16f0f42a6f4
+Adata = 00
+CT = e2e87ca82523ccfeb416b42af9d9aadc
+Result = Pass
+Payload = 00
+
+Count = 20
+Nonce = 2e504b694f8df5
+Adata = 00
+CT = 7b85fd105cc960df86ad86846d178274
+Result = Fail
+
+Count = 21
+Nonce = 06d102a9328863
+Adata = 00
+CT = ffa140be27b25f307a6efd9697d66c9b
+Result = Fail
+
+Count = 22
+Nonce = c288b810fb5334
+Adata = 00
+CT = ed356542e0a804a724bfaa422e98a970
+Result = Fail
+
+Count = 23
+Nonce = 08a166d9eb6610
+Adata = 00
+CT = e31dd8dc920fe7900e1b1817fe845c7d
+Result = Fail
+
+Count = 24
+Nonce = 4a5810b121c91b
+Adata = 00
+CT = ae5a0777f03bbf541f305d00acff0396
+Result = Fail
+
+Count = 25
+Nonce = 44077341139bf9
+Adata = 00
+CT = 957dca58616c1cbe99f94fd8f7c257d9
+Result = Fail
+
+Count = 26
+Nonce = a9df4f37847e1f
+Adata = 00
+CT = 0e150af422f6da238bb476810b2d5bc2
+Result = Pass
+Payload = 00
+
+Count = 27
+Nonce = 11df57fcd131e9
+Adata = 00
+CT = 8e1150756ff3a733a1274470f072b74c
+Result = Pass
+Payload = 00
+
+Count = 28
+Nonce = 890fff56d10dc0
+Adata = 00
+CT = a1f70df3fa9cfeb95f869b3fe08466e0
+Result = Pass
+Payload = 00
+
+Count = 29
+Nonce = 9dc18698731b27
+Adata = 00
+CT = fdf3f6c177aa1d71fe3474a5a2eb6bb1
+Result = Fail
+
+[Alen = 0, Plen = 0, Nlen = 13, Tlen = 4]
+
+Key = 4bb3c4a4f893ad8c9bdc833c325d62b3
+
+Count = 30
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = 90156f3f
+Result = Pass
+Payload = 00
+
+Count = 31
+Nonce = a16a2e741f1cd9717285b6d882
+Adata = 00
+CT = 88909016
+Result = Fail
+
+Count = 32
+Nonce = 368f3b8180fd4b851b7b272cb1
+Adata = 00
+CT = de547d03
+Result = Fail
+
+Count = 33
+Nonce = 7bb2bc00c0cafce65b5299ae64
+Adata = 00
+CT = ea4bad52
+Result = Fail
+
+Count = 34
+Nonce = 935c1ef3d4032ff090f91141f3
+Adata = 00
+CT = 1bc82b3d
+Result = Pass
+Payload = 00
+
+Count = 35
+Nonce = 2640b14f10b116411d1b5c1ad1
+Adata = 00
+CT = 92e72250
+Result = Fail
+
+Count = 36
+Nonce = b229c173a13b2d83af91ec45b0
+Adata = 00
+CT = e81f0647
+Result = Fail
+
+Count = 37
+Nonce = 37ca0dc2d6efd9efde69f14f03
+Adata = 00
+CT = 7cb906ec
+Result = Fail
+
+Count = 38
+Nonce = 6b6238aed86d677ba2b3e2622c
+Adata = 00
+CT = d60f815b
+Result = Fail
+
+Count = 39
+Nonce = d6cb2ac67bb13b8f6d31fad64a
+Adata = 00
+CT = d3d4f3b0
+Result = Fail
+
+Count = 40
+Nonce = 32a7cd361ef00e65f5778fdfd4
+Adata = 00
+CT = a9df97ad
+Result = Fail
+
+Count = 41
+Nonce = d0a1508fdefcf5be30a459b813
+Adata = 00
+CT = 36a37a59
+Result = Pass
+Payload = 00
+
+Count = 42
+Nonce = 5381a61b449dc6a42aa4c79b95
+Adata = 00
+CT = dba02a36
+Result = Pass
+Payload = 00
+
+Count = 43
+Nonce = c55430f2da0687ea40313884ab
+Adata = 00
+CT = 25dcb3c5
+Result = Pass
+Payload = 00
+
+Count = 44
+Nonce = ec76d1850acc0979a1f11906fb
+Adata = 00
+CT = 1d2832d0
+Result = Fail
+
+[Alen = 0, Plen = 0, Nlen = 13, Tlen = 16]
+
+Key = 19ebfde2d5468ba0a3031bde629b11fd
+
+Count = 45
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = fb04dc5a44c6bb000f2440f5154364b4
+Result = Pass
+Payload = 00
+
+Count = 46
+Nonce = a16a2e741f1cd9717285b6d882
+Adata = 00
+CT = 5447075bf42a59b91f08064738b015ab
+Result = Fail
+
+Count = 47
+Nonce = 368f3b8180fd4b851b7b272cb1
+Adata = 00
+CT = fdc992847f0815fac67aa935b35208ed
+Result = Fail
+
+Count = 48
+Nonce = 7bb2bc00c0cafce65b5299ae64
+Adata = 00
+CT = 2cabd690a45e59854b7587b26dd77f8e
+Result = Fail
+
+Count = 49
+Nonce = 935c1ef3d4032ff090f91141f3
+Adata = 00
+CT = 3dacc71169f6da77ec91ff1d2f649ed1
+Result = Pass
+Payload = 00
+
+Count = 50
+Nonce = 2640b14f10b116411d1b5c1ad1
+Adata = 00
+CT = 97a2eb170ef03fa12124f1315e3b694f
+Result = Fail
+
+Count = 51
+Nonce = b229c173a13b2d83af91ec45b0
+Adata = 00
+CT = 94d85a83169d8dc76f58baf4d63ecfee
+Result = Fail
+
+Count = 52
+Nonce = 37ca0dc2d6efd9efde69f14f03
+Adata = 00
+CT = d3903c6289ca3684b8ce1174c23153a4
+Result = Fail
+
+Count = 53
+Nonce = 6b6238aed86d677ba2b3e2622c
+Adata = 00
+CT = 5cbac5c418374a68bd7085454c4b0c13
+Result = Fail
+
+Count = 54
+Nonce = d6cb2ac67bb13b8f6d31fad64a
+Adata = 00
+CT = 26317f6b8b0130097441ed04b8009aef
+Result = Fail
+
+Count = 55
+Nonce = 32a7cd361ef00e65f5778fdfd4
+Adata = 00
+CT = b82ab6f3bbf59b6caafc54f05570f74e
+Result = Fail
+
+Count = 56
+Nonce = d0a1508fdefcf5be30a459b813
+Adata = 00
+CT = 1ae34207e74c8c78890ae17e320e84bd
+Result = Pass
+Payload = 00
+
+Count = 57
+Nonce = 5381a61b449dc6a42aa4c79b95
+Adata = 00
+CT = 5c5fa254c0be503b02caffade6b85259
+Result = Pass
+Payload = 00
+
+Count = 58
+Nonce = c55430f2da0687ea40313884ab
+Adata = 00
+CT = 9340266730ea36207bb734819d3553e9
+Result = Pass
+Payload = 00
+
+Count = 59
+Nonce = ec76d1850acc0979a1f11906fb
+Adata = 00
+CT = ec17cccf33bd9a0d4ce7aa20690c1333
+Result = Fail
+
+[Alen = 0, Plen = 24, Nlen = 7, Tlen = 4]
+
+Key = 19ebfde2d5468ba0a3031bde629b11fd
+
+Count = 60
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = a90e8ea44085ced791b2fdb7fd44b5cf0bd7d27718029bb703e1fa6b
+Result = Pass
+Payload = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22
+
+Count = 61
+Nonce = 31f8fa25827d48
+Adata = 00
+CT = 50aafe0578c115c4a8e126ff7b3ccb64dce8ccaa8ceda69f23e5d81c
+Result = Fail
+
+Count = 62
+Nonce = 5340ed7752c9ff
+Adata = 00
+CT = 512ed208bf10d57406537e94d20a5b6e2e9ab0683dfdc685869a97f0
+Result = Fail
+
+Count = 63
+Nonce = 9cbce402511b89
+Adata = 00
+CT = af72db9cd9d6f46607d6f9542ca69988dd15255c5c91171c838e7f95
+Result = Fail
+
+Count = 64
+Nonce = 123a0beace4e39
+Adata = 00
+CT = 47d71409a03c330be9451b3f92c9d21c584391ad1010e9d609b89801
+Result = Pass
+Payload = 9d033e3b66efed1467868f382417c80594877a28bc97f406
+
+Count = 65
+Nonce = 8ea1594a58fe4a
+Adata = 00
+CT = e562c7af0384ea16431ca20934a293a058d722cbfc3186c8eaf5f825
+Result = Fail
+
+Count = 66
+Nonce = 5a7743e59e82da
+Adata = 00
+CT = 004d9d89c401aa79919c2805fcd5de69316e191df56426c05ec1aa6a
+Result = Fail
+
+Count = 67
+Nonce = f477f754d7ee76
+Adata = 00
+CT = d623673d7f6d57c208bde112ca858561f3af5cc2bf5de926f3586c6f
+Result = Fail
+
+Count = 68
+Nonce = 040a257dede70e
+Adata = 00
+CT = fd4733d158b5630f4f6c03ab26b11bff0cbe0d5d3df99a735fa40618
+Result = Fail
+
+Count = 69
+Nonce = dd51b8e91683d1
+Adata = 00
+CT = d352cb996c3075ff367a8dcacbbae46a12fbef08aa96ec835bf4f930
+Result = Fail
+
+Count = 70
+Nonce = ab3cb86cca6fb2
+Adata = 00
+CT = 31730fac20e21eca0aef591faa9fa90b3c058e32af1ce48a66f0496e
+Result = Fail
+
+Count = 71
+Nonce = f67b98efd39b55
+Adata = 00
+CT = dd175905a7ea3aef9fce068e6cb78e9cc60519755a178c77b753181c
+Result = Pass
+Payload = f2e944e1ae47ad5873bf391f1b0cc07f6151eb4c50bb45b2
+
+Count = 72
+Nonce = e60e2c002d1c99
+Adata = 00
+CT = 8ad6b76f54392ee0f2834f09142545bcde9bf03d04d64aa10876f2da
+Result = Pass
+Payload = 70f48dc1d76e5028da07e29852801375a9edb2214a5ea4c0
+
+Count = 73
+Nonce = 098e053fa08043
+Adata = 00
+CT = 808eb3e04c39abde64674f0f7716dde11699cff8dd367c4cd4f7fc07
+Result = Pass
+Payload = bd81680e3dc0b35431c92598dcaa26ef09ca0da5e77193de
+
+Count = 74
+Nonce = 4bf48328725514
+Adata = 00
+CT = e074d13aad43f7b2364d47db0a02326641ca3b2ad61a1c49973a2712
+Result = Fail
+
+[Alen = 0, Plen = 24, Nlen = 7, Tlen = 16]
+
+Key = 197afb02ffbd8f699dacae87094d5243
+
+Count = 75
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = 24ab9eeb0e5508cae80074f1070ee188a637171860881f1f2d9a3fbc210595b7b8b1b41523111a8e
+Result = Pass
+Payload = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22
+
+Count = 76
+Nonce = 31f8fa25827d48
+Adata = 00
+CT = 7ebfda6fa5da1dbffd82dc29b875798fbcef8ba0084fbd2463af747cc88a001fa94e060290f209c4
+Result = Fail
+
+Count = 77
+Nonce = 5340ed7752c9ff
+Adata = 00
+CT = cbf133643851f91ddc7a1e19a0c21990459f2b7728da58f5cf3b8e6c8aeb5eeb0a5efb3700be45a2
+Result = Fail
+
+Count = 78
+Nonce = 9cbce402511b89
+Adata = 00
+CT = 0de7567a945c0af4a2291a651de411e8d0438508f2d4da80f7bd61a0158accbca28913e39fe80906
+Result = Fail
+
+Count = 79
+Nonce = 123a0beace4e39
+Adata = 00
+CT = d43035cdb5a1868aa430e8b41a1dc57a639087238e38bd628feeda2e8f249dd93a8358def7639875
+Result = Pass
+Payload = 9d033e3b66efed1467868f382417c80594877a28bc97f406
+
+Count = 80
+Nonce = 8ea1594a58fe4a
+Adata = 00
+CT = 389547260b354a6cbc909de057d367677049e80613877f6fbf19f89da977e56f308373c616299ad4
+Result = Fail
+
+Count = 81
+Nonce = 5a7743e59e82da
+Adata = 00
+CT = a95aa33483ed3711470025394616bf98fe624fbca8aa6fbc21366b9da457ede2a673351475b53d41
+Result = Fail
+
+Count = 82
+Nonce = f477f754d7ee76
+Adata = 00
+CT = 3d53b6ab8925f429ae14a0065cd203d4f9deddd402a79ac6d889a7cae55efd71b369cd6d43ef363b
+Result = Fail
+
+Count = 83
+Nonce = 040a257dede70e
+Adata = 00
+CT = d5e6e82cb5f8034a89e58adf8298476253f18981bcb3b0364be7f19463dd330a4b9f3cbb30b88fa5
+Result = Fail
+
+Count = 84
+Nonce = dd51b8e91683d1
+Adata = 00
+CT = 02f69107d62ff77145c7d57684c70ba671d55f1c63bb2ad8c2df063f7fdbae27f0736a37fd065fb4
+Result = Fail
+
+Count = 85
+Nonce = ab3cb86cca6fb2
+Adata = 00
+CT = 64ec2f321111da9c5389e8255bfe69876d4f548f94cacd529b45d54cc24cff1b1d8aa1df32fbd81a
+Result = Fail
+
+Count = 86
+Nonce = f67b98efd39b55
+Adata = 00
+CT = 37d63c2bbf44d2eb155ecc1a844841d5c33f1a6d443419330217a4f1f4fb302257b0de7c9da2e750
+Result = Pass
+Payload = f2e944e1ae47ad5873bf391f1b0cc07f6151eb4c50bb45b2
+
+Count = 87
+Nonce = e60e2c002d1c99
+Adata = 00
+CT = 33e0dce4410e51bed5323ea49490207084ac91732bae429236a305d520a1a24930a70a311aa3695d
+Result = Pass
+Payload = 70f48dc1d76e5028da07e29852801375a9edb2214a5ea4c0
+
+Count = 88
+Nonce = 098e053fa08043
+Adata = 00
+CT = 1d732c334319bd775e7cf93dbdc4204bbdb58192be08280481e3d64ed546b6b70ee088a693f55fbb
+Result = Pass
+Payload = bd81680e3dc0b35431c92598dcaa26ef09ca0da5e77193de
+
+Count = 89
+Nonce = 4bf48328725514
+Adata = 00
+CT = c92fc2f0d24593f67d9c09d326158a8138237c4096093f0d737719dd84ccfb397a4f61b70c85262a
+Result = Fail
+
+[Alen = 0, Plen = 24, Nlen = 13, Tlen = 4]
+
+Key = 197afb02ffbd8f699dacae87094d5243
+
+Count = 90
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = 4a550134f94455979ec4bf89ad2bd80d25a77ae94e456134a3e138b9
+Result = Pass
+Payload = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697
+
+Count = 91
+Nonce = 49004912fdd7269279b1f06a89
+Adata = 00
+CT = 118ec53dd1bfbe52d5b9fe5dfebecf2ee674ec983eada654091a5ae9
+Result = Fail
+
+Count = 92
+Nonce = efeb82c8c68d6600b24dd6d8ee
+Adata = 00
+CT = 6b0fea26e4dfe902b5e876c7ba92afbad8aa52d3c1d00ae578b6bcc4
+Result = Fail
+
+Count = 93
+Nonce = 7b93d368dc551640b00ba3cbb5
+Adata = 00
+CT = 640c740e2b8af851712a05948ecee055b25b145ccb82ca58ac542b09
+Result = Fail
+
+Count = 94
+Nonce = 24b7a65391f88bea38fcd54a9a
+Adata = 00
+CT = 05f20b2ae70fcb0ea79aa1845c15b899a799ca60f51e6c296413020a
+Result = Pass
+Payload = 43419715cef9a48dc7280bc035082a6581afd1d82bee9d1a
+
+Count = 95
+Nonce = 6aa3f731522fce7e366ba59945
+Adata = 00
+CT = 9fa576a8a5c72468afa372338cbbc33fef81ad5a873eb38a142d5636
+Result = Fail
+
+Count = 96
+Nonce = a11cf5bed0041ee3cb1fef4b43
+Adata = 00
+CT = 8d26582c74b2b4d960ee9e417c6395daafaebb3aff45d477f3757b6a
+Result = Fail
+
+Count = 97
+Nonce = 273cc5013785baeb5abc79c8bd
+Adata = 00
+CT = cb62a13e38e17cc6635e409c922956ece38f593189a51b99a7001a16
+Result = Fail
+
+Count = 98
+Nonce = d2d4482ea8e98c1cf309671895
+Adata = 00
+CT = f3e29b792423c7fbe743a3b2f890a2bff29519f3636a6232050e9225
+Result = Fail
+
+Count = 99
+Nonce = a8849b44adb48d271979656930
+Adata = 00
+CT = 136e60d6714d906d1f4c02b7bdbb5f3ccdd2165306912dec850ec9f0
+Result = Fail
+
+Count = 100
+Nonce = a632ba0d00511122abcd6227ff
+Adata = 00
+CT = 49b6d0b6eeff74af0de70072d9ccdc68a0ee36a5ddbf098b4eb95533
+Result = Fail
+
+Count = 101
+Nonce = c47af80cd26d047630c1fdf0d1
+Adata = 00
+CT = a2a59041c3f78f6e10c3045118e8a475945e24c85b02abc40f8fb949
+Result = Pass
+Payload = d8306c9c4ea6c69c6e2ad0fc0e49b1e0126b01078d6419ff
+
+Count = 102
+Nonce = 70e132023acae1f88c7a237b68
+Adata = 00
+CT = 19b4ad222795326cb031cfdb07b652dbf64ca5db5ff5d6d569d8ab41
+Result = Pass
+Payload = d0b2bef5ed1a87d9c73d4a459cb05c11799c4f51ad640b1e
+
+Count = 103
+Nonce = 8010d3a2a14f72f5585defc940
+Adata = 00
+CT = 76b66b908657f4df8a329c34ccdde50ae7fc71c4a718b712f00fe764
+Result = Pass
+Payload = 4faba05569bf7ac656780c16995e9122e565fe9984be8a68
+
+Count = 104
+Nonce = a98c2f0e0a7b68942853905191
+Adata = 00
+CT = 20df4662ce6c8c4ce49b14fa791e41ff8598ec93d8a825e879f9eb72
+Result = Fail
+
+[Alen = 0, Plen = 24, Nlen = 13, Tlen = 16]
+
+Key = 90929a4b0ac65b350ad1591611fe4829
+
+Count = 105
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = 4bfe4e35784f0a65b545477e5e2f4bae0e1e6fa717eaf2cb6a9a970b9beb2ac1bd4fd62168f8378a
+Result = Pass
+Payload = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697
+
+Count = 106
+Nonce = 49004912fdd7269279b1f06a89
+Adata = 00
+CT = 0c56a503aa2c12e87450d45a7b714db980fd348f327c0065a65666144994bad0c8195bcb4ade1337
+Result = Fail
+
+Count = 107
+Nonce = efeb82c8c68d6600b24dd6d8ee
+Adata = 00
+CT = 5f69d6c21f771eb98dc724f891f530b1c045f49a054de103a85f868739404b64a7cbdd61b577c388
+Result = Fail
+
+Count = 108
+Nonce = 7b93d368dc551640b00ba3cbb5
+Adata = 00
+CT = d335ba572520c336f711edf27ea738ba5e6b0d772ea443b8b2b164f3c255b699cbf75330d96c3c13
+Result = Fail
+
+Count = 109
+Nonce = 24b7a65391f88bea38fcd54a9a
+Adata = 00
+CT = 9fa846ef8d198c538f84f856bab8f7f9c3bed90b53acb6a32658e077687315eaf11458bdf6e3c36a
+Result = Pass
+Payload = 43419715cef9a48dc7280bc035082a6581afd1d82bee9d1a
+
+Count = 110
+Nonce = 6aa3f731522fce7e366ba59945
+Adata = 00
+CT = b7095030acdc5fbb8fea2c24717c1c236231f9737bcc78f463db3756abba1feef626a956794d7e56
+Result = Fail
+
+Count = 111
+Nonce = a11cf5bed0041ee3cb1fef4b43
+Adata = 00
+CT = d6911d5831163c8ebad0916af1833051b885aae822f9f6657d6fee1de626bc7c93f2caa27a3ecaa0
+Result = Fail
+
+Count = 112
+Nonce = 273cc5013785baeb5abc79c8bd
+Adata = 00
+CT = 6b10a098c96c2bbf9aeb5c9adcf91e4812838dff319f8be989e2d235192f33ba0f357492112d98f4
+Result = Fail
+
+Count = 113
+Nonce = d2d4482ea8e98c1cf309671895
+Adata = 00
+CT = aecd11cbac04e1f79b0fd24052c8cedf393dce9df350d24f800b81e834ea5dd2bdc2c688d9505359
+Result = Fail
+
+Count = 114
+Nonce = a8849b44adb48d271979656930
+Adata = 00
+CT = d3a7a25f71b1988482dc852ed713d55abdcc4bb1129ddcae430889cd5c97343cc0dedfbd62e6b6eb
+Result = Fail
+
+Count = 115
+Nonce = a632ba0d00511122abcd6227ff
+Adata = 00
+CT = 368e1574a433d78d0276ce4a1cacfba834a216693536c00b15acded53c41010554e1c1fe937a7605
+Result = Fail
+
+Count = 116
+Nonce = c47af80cd26d047630c1fdf0d1
+Adata = 00
+CT = 99e40b3c67aca95dd4462c20cbd6b2741e7033fc4f41a975c9390fbdb9ec416267096ccbf2c148e5
+Result = Pass
+Payload = d8306c9c4ea6c69c6e2ad0fc0e49b1e0126b01078d6419ff
+
+Count = 117
+Nonce = 70e132023acae1f88c7a237b68
+Adata = 00
+CT = de079418c25ba67e5fda009998e3fce61bfdc3b7787cf06655c18ae38b7ee7f00f96cfca4fe9a2ef
+Result = Pass
+Payload = d0b2bef5ed1a87d9c73d4a459cb05c11799c4f51ad640b1e
+
+Count = 118
+Nonce = 8010d3a2a14f72f5585defc940
+Adata = 00
+CT = fbab64d8dd8b6e33c7cc6124cd65f004d7247277fe98d5d3b35357a35ff9e58e18d6d80df9fc335d
+Result = Pass
+Payload = 4faba05569bf7ac656780c16995e9122e565fe9984be8a68
+
+Count = 119
+Nonce = a98c2f0e0a7b68942853905191
+Adata = 00
+CT = 372b9af0655df2d0c830b4949a2d2faa8db251ee922a3bff9aba89639f4033be9ba9f3c101acc1bd
+Result = Fail
+
+[Alen = 32, Plen = 0, Nlen = 7, Tlen = 4]
+
+Key = 90929a4b0ac65b350ad1591611fe4829
+
+Count = 120
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 782e4318
+Result = Pass
+Payload = 00
+
+Count = 121
+Nonce = a265480ca88d5f
+Adata = a2248a882ecbf850daf91933a389e78e81623d233dfd47bf8321361a38f138fe
+CT = a04f270a
+Result = Fail
+
+Count = 122
+Nonce = 87ec7423f1ebfc
+Adata = 2bed1ec06c1ca149d9ffbaf048c474ea2de000eb7950f18d6c25acf6ab3f19b5
+CT = 97dfd257
+Result = Fail
+
+Count = 123
+Nonce = b8b04f90616082
+Adata = 4898731e143fcc677c7cf1a8f2b3c4039fb5e57028e33b05e097d1763cbfe4d8
+CT = 6c202a1c
+Result = Fail
+
+Count = 124
+Nonce = 8c687b4318813a
+Adata = fcad52a88544325bb31eb5de4a41dbff6a96f69d0993b969a01792ee23953acf
+CT = 1be535a0
+Result = Pass
+Payload = 00
+
+Count = 125
+Nonce = 29b810eed8fc92
+Adata = 40d1d320eb63a25d7a2b3141563a552114275ddda56beb62cc0c0273d5795faa
+CT = 4fb6617d
+Result = Fail
+
+Count = 126
+Nonce = 62452462c53934
+Adata = 1eb8863ea100babc1713654afcf54f21f8bff754223ad70269ace9d034f26a96
+CT = c056bd3e
+Result = Fail
+
+Count = 127
+Nonce = 4cceba0e7aee97
+Adata = f33e184c967165eb62542999afaca4e3e319840e439b5bb509544fb4b6901445
+CT = 87048576
+Result = Fail
+
+Count = 128
+Nonce = b5151b0601c683
+Adata = 73d27303ec91f28c79b278882034d11eb6a5266746f37edbb77f8409a8738b8c
+CT = ea8c0407
+Result = Fail
+
+Count = 129
+Nonce = 4e5d6d7ac9e71e
+Adata = a01b6e152fe232b6c10b5d89900961c445f4c46833df242c826678b68c869811
+CT = 41c12dc5
+Result = Fail
+
+Count = 130
+Nonce = dc88e989951a3f
+Adata = fdcacfaff46585406cc45a2da364e67e132a91c98900a8f9d7bfb14ec951fca5
+CT = de84cf5c
+Result = Fail
+
+Count = 131
+Nonce = a1aeda4b4cb8dd
+Adata = db3022ef4cd68ae22b501599448ffe2dda15cfd2e259315c6f6d03036edea963
+CT = e617e006
+Result = Pass
+Payload = 00
+
+Count = 132
+Nonce = f248e5225e3d9a
+Adata = fdc64ef76a3bfd0a15d0bc8e8bacaf64346796a3e35afcf2ac1ab136f63f7b6e
+CT = b7909395
+Result = Pass
+Payload = 00
+
+Count = 133
+Nonce = e68228f5c65b73
+Adata = 614efdf89ce2a9fcbd38bdc0b4cece54dfd7532880e0b4ce6eb3a4010b7cb1e7
+CT = 8a05d2ea
+Result = Pass
+Payload = 00
+
+Count = 134
+Nonce = ea167cfd1101d9
+Adata = 28130f938c45a1a92b02dbeadbd8df816b6d934e87cca2dfdbfdc49c7cd84041
+CT = 8643ba47
+Result = Fail
+
+[Alen = 32, Plen = 0, Nlen = 7, Tlen = 16]
+
+Key = 6a798d7c5e1a72b43e20ad5c7b08567b
+
+Count = 135
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 41b476013f45e4a781f253a6f3b1e530
+Result = Pass
+Payload = 00
+
+Count = 136
+Nonce = a265480ca88d5f
+Adata = a2248a882ecbf850daf91933a389e78e81623d233dfd47bf8321361a38f138fe
+CT = f9f018fcd125822616083fffebc4c8e6
+Result = Fail
+
+Count = 137
+Nonce = 87ec7423f1ebfc
+Adata = 2bed1ec06c1ca149d9ffbaf048c474ea2de000eb7950f18d6c25acf6ab3f19b5
+CT = 534cc67c44c877c9c908071ee1082f4c
+Result = Fail
+
+Count = 138
+Nonce = b8b04f90616082
+Adata = 4898731e143fcc677c7cf1a8f2b3c4039fb5e57028e33b05e097d1763cbfe4d8
+CT = 201c0ef2ddaa51b645911b5c37d76e95
+Result = Fail
+
+Count = 139
+Nonce = 8c687b4318813a
+Adata = fcad52a88544325bb31eb5de4a41dbff6a96f69d0993b969a01792ee23953acf
+CT = ec774d9000763bba3a5ac307418827b2
+Result = Pass
+Payload = 00
+
+Count = 140
+Nonce = 29b810eed8fc92
+Adata = 40d1d320eb63a25d7a2b3141563a552114275ddda56beb62cc0c0273d5795faa
+CT = 75798c3fe5202f0e33c9183c837aeaf5
+Result = Fail
+
+Count = 141
+Nonce = 62452462c53934
+Adata = 1eb8863ea100babc1713654afcf54f21f8bff754223ad70269ace9d034f26a96
+CT = 32601de5960c11c925444b5c47d42289
+Result = Fail
+
+Count = 142
+Nonce = 4cceba0e7aee97
+Adata = f33e184c967165eb62542999afaca4e3e319840e439b5bb509544fb4b6901445
+CT = 4c1cd6a774c8e6f4e261db1f73b0aa20
+Result = Fail
+
+Count = 143
+Nonce = b5151b0601c683
+Adata = 73d27303ec91f28c79b278882034d11eb6a5266746f37edbb77f8409a8738b8c
+CT = 8bd9c00ff23310216bbd24981c1e2cf7
+Result = Fail
+
+Count = 144
+Nonce = 4e5d6d7ac9e71e
+Adata = a01b6e152fe232b6c10b5d89900961c445f4c46833df242c826678b68c869811
+CT = 174efd089409f9932b8e631965e762a6
+Result = Fail
+
+Count = 145
+Nonce = dc88e989951a3f
+Adata = fdcacfaff46585406cc45a2da364e67e132a91c98900a8f9d7bfb14ec951fca5
+CT = 8de80f620bd41eee6a58925dc8404bfa
+Result = Fail
+
+Count = 146
+Nonce = a1aeda4b4cb8dd
+Adata = db3022ef4cd68ae22b501599448ffe2dda15cfd2e259315c6f6d03036edea963
+CT = 0b9d79e8e33ec45532af5515a99f05df
+Result = Pass
+Payload = 00
+
+Count = 147
+Nonce = f248e5225e3d9a
+Adata = fdc64ef76a3bfd0a15d0bc8e8bacaf64346796a3e35afcf2ac1ab136f63f7b6e
+CT = 1583e1e5a86001bbcec62292ccfd4d48
+Result = Pass
+Payload = 00
+
+Count = 148
+Nonce = e68228f5c65b73
+Adata = 614efdf89ce2a9fcbd38bdc0b4cece54dfd7532880e0b4ce6eb3a4010b7cb1e7
+CT = b72caac6362e68e445f69f605f21e0a2
+Result = Pass
+Payload = 00
+
+Count = 149
+Nonce = ea167cfd1101d9
+Adata = 28130f938c45a1a92b02dbeadbd8df816b6d934e87cca2dfdbfdc49c7cd84041
+CT = 352769a19ac75b8a116be031b33d6449
+Result = Fail
+
+[Alen = 32, Plen = 0, Nlen = 13, Tlen = 4]
+
+Key = 6a798d7c5e1a72b43e20ad5c7b08567b
+
+Count = 150
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = 9f69f24f
+Result = Pass
+Payload = 00
+
+Count = 151
+Nonce = 8739b4bea1a099fe547499cbc6
+Adata = f6107696edb332b2ea059d8860fee26be42e5e12e1a4f79a8d0eafce1b2278a7
+CT = e17afaa4
+Result = Fail
+
+Count = 152
+Nonce = 0f98fdbde2b04387f27b3401dd
+Adata = 02010329660fa716556193eb4870ee84bd934296a5c52d92bba859cc13caaddc
+CT = 07155b7e
+Result = Fail
+
+Count = 153
+Nonce = 4eed58f381e500902ba5c56864
+Adata = 96056d9ebd7c553c22cc2d9d816b61123750d96c1b08c4b661079424bf3c4946
+CT = d538cf2f
+Result = Fail
+
+Count = 154
+Nonce = 1e7e51f0fa9a33ed618c26f5e3
+Adata = da9b8ffb0f3c2aee2e386cc9f035ec1eb3e629bd1544c11dc21be4fd8ac9074a
+CT = c283466f
+Result = Pass
+Payload = 00
+
+Count = 155
+Nonce = f012f94f5988c79aa179d7fdfc
+Adata = 612b2ef2683109d99452f95099417641d0c2be3f8ab4cbb2a44e83355ba9303c
+CT = aa8d8098
+Result = Fail
+
+Count = 156
+Nonce = 715acf92cfb69ad56036c49e70
+Adata = 960667b85be07304634124b9324be12a1c11451f1fa9db82c683265b4cf8e5ff
+CT = a44b69b0
+Result = Fail
+
+Count = 157
+Nonce = 141be3601e38185a9fa1596d2e
+Adata = 606452c62290b43559a588bb03356f846cecb0ccaf0bdaf67a18abd811d4315a
+CT = f395733f
+Result = Fail
+
+Count = 158
+Nonce = fcdda3c5f0e80843b03d8788da
+Adata = 03f22247a55461a293d253c77483859fdac1b87c2480e208a3df767cfbfde512
+CT = 1e9e9237
+Result = Fail
+
+Count = 159
+Nonce = ca660ed3b917c0aca140dcd3fb
+Adata = 254a86f5b20d344ad86fd5523d08f1864737be57731440c29aa6b42574572f51
+CT = e9d2a722
+Result = Fail
+
+Count = 160
+Nonce = 642ae3466661ce1f51783deece
+Adata = 4432a1cec5976cc13b8fb78341d426c2248f091b597123d263ffafc7f82da5a5
+CT = a90fc438
+Result = Fail
+
+Count = 161
+Nonce = 7864c717ec93db38b10679be47
+Adata = 679aad1ad1e57029e3362b325572fc71cac53184b0f1546867e665a4a59466c4
+CT = 48f3a1ec
+Result = Pass
+Payload = 00
+
+Count = 162
+Nonce = c3bf9dfe9d6c26f543188fb457
+Adata = e301f69ad3a7e08a3d02462f0aa584449eb0449b0e3c50aa8dfaa4472816c8b0
+CT = 24763def
+Result = Pass
+Payload = 00
+
+Count = 163
+Nonce = 1527657d2fd98f7deca55cc649
+Adata = f4c723433b7cafe3cda9bb4940a21a89a8382d13018b622ccd1ffb9ffd3211af
+CT = 63394bee
+Result = Pass
+Payload = 00
+
+Count = 164
+Nonce = b8432d3d5525a0dadbbaa6b6b8
+Adata = 86ee6e37b4a2d9a0b52ec95643b4e8297e237721e15ce8bf7593a98644f83eba
+CT = d79b1686
+Result = Fail
+
+[Alen = 32, Plen = 0, Nlen = 13, Tlen = 16]
+
+Key = f9fdca4ac64fe7f014de0f43039c7571
+
+Count = 165
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = 1859ac36a40a6b28b34266253627797a
+Result = Pass
+Payload = 00
+
+Count = 166
+Nonce = 8739b4bea1a099fe547499cbc6
+Adata = f6107696edb332b2ea059d8860fee26be42e5e12e1a4f79a8d0eafce1b2278a7
+CT = edf8b46eb69ac0044116019dec183072
+Result = Fail
+
+Count = 167
+Nonce = 0f98fdbde2b04387f27b3401dd
+Adata = 02010329660fa716556193eb4870ee84bd934296a5c52d92bba859cc13caaddc
+CT = 66622ac26c7227a0329739612012737c
+Result = Fail
+
+Count = 168
+Nonce = 4eed58f381e500902ba5c56864
+Adata = 96056d9ebd7c553c22cc2d9d816b61123750d96c1b08c4b661079424bf3c4946
+CT = e4c9e86493ee78b1cbf6e55e94731b63
+Result = Fail
+
+Count = 169
+Nonce = 1e7e51f0fa9a33ed618c26f5e3
+Adata = da9b8ffb0f3c2aee2e386cc9f035ec1eb3e629bd1544c11dc21be4fd8ac9074a
+CT = 8b5bfe6b5b5552007300bae71172612f
+Result = Pass
+Payload = 00
+
+Count = 170
+Nonce = f012f94f5988c79aa179d7fdfc
+Adata = 612b2ef2683109d99452f95099417641d0c2be3f8ab4cbb2a44e83355ba9303c
+CT = 1848be3cb7665ac68874c617a75d8bd2
+Result = Fail
+
+Count = 171
+Nonce = 715acf92cfb69ad56036c49e70
+Adata = 960667b85be07304634124b9324be12a1c11451f1fa9db82c683265b4cf8e5ff
+CT = 65a23b7b5ee78af9c7d0113447f78ab9
+Result = Fail
+
+Count = 172
+Nonce = 141be3601e38185a9fa1596d2e
+Adata = 606452c62290b43559a588bb03356f846cecb0ccaf0bdaf67a18abd811d4315a
+CT = 90a420b6d2252392e161dcf4fb953d7e
+Result = Fail
+
+Count = 173
+Nonce = fcdda3c5f0e80843b03d8788da
+Adata = 03f22247a55461a293d253c77483859fdac1b87c2480e208a3df767cfbfde512
+CT = 004cbe11292887e246de7704a4a1a05f
+Result = Fail
+
+Count = 174
+Nonce = ca660ed3b917c0aca140dcd3fb
+Adata = 254a86f5b20d344ad86fd5523d08f1864737be57731440c29aa6b42574572f51
+CT = ad7af41e39ea0c0cd072263e826f3cf0
+Result = Fail
+
+Count = 175
+Nonce = 642ae3466661ce1f51783deece
+Adata = 4432a1cec5976cc13b8fb78341d426c2248f091b597123d263ffafc7f82da5a5
+CT = 16b1a4fadbadc906a949592d6ef319a3
+Result = Fail
+
+Count = 176
+Nonce = 7864c717ec93db38b10679be47
+Adata = 679aad1ad1e57029e3362b325572fc71cac53184b0f1546867e665a4a59466c4
+CT = e9cfb1069380434f221db4229a083a76
+Result = Pass
+Payload = 00
+
+Count = 177
+Nonce = c3bf9dfe9d6c26f543188fb457
+Adata = e301f69ad3a7e08a3d02462f0aa584449eb0449b0e3c50aa8dfaa4472816c8b0
+CT = 380cb57fd531bb1dcf22350518bbf8af
+Result = Pass
+Payload = 00
+
+Count = 178
+Nonce = 1527657d2fd98f7deca55cc649
+Adata = f4c723433b7cafe3cda9bb4940a21a89a8382d13018b622ccd1ffb9ffd3211af
+CT = fbf2becc35b5024078bfcfc1f831b669
+Result = Pass
+Payload = 00
+
+Count = 179
+Nonce = b8432d3d5525a0dadbbaa6b6b8
+Adata = 86ee6e37b4a2d9a0b52ec95643b4e8297e237721e15ce8bf7593a98644f83eba
+CT = 080203eb842b3f98a730abbbf98f493e
+Result = Fail
+
+[Alen = 32, Plen = 24, Nlen = 7, Tlen = 4]
+
+Key = f9fdca4ac64fe7f014de0f43039c7571
+
+Count = 180
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 6be31860ca271ef448de8f8d8b39346daf4b81d7e92d65b338f125fa
+Result = Pass
+Payload = a265480ca88d5f536db0dc6abc40faf0d05be7a966977768
+
+Count = 181
+Nonce = fdd2d6f503c915
+Adata = 5b92394f21ddc3ad49d9b0881b829a5935cb3a4d23e292a62fb66b5e7ab7020e
+CT = 4cc57a9927a6bc401441870d3193bf89ebd163f5c01501c728a66b69
+Result = Fail
+
+Count = 182
+Nonce = 27d73d58100054
+Adata = f6468542923be79b4b06dfe70920d57d1da73a9c16f9c9a12d810d7de0d12467
+CT = 1f16c6d370fff40c011a243356076b67e905d4672ae2f38fee2de18c
+Result = Fail
+
+Count = 183
+Nonce = dd16e0ce1250e3
+Adata = bc65cfd65e9863c8b7457d58afa6bdb48a84170d8aa97ba5b397b52ad17a9242
+CT = 46edb001d58a01dce1bcf064cfc9a04accc82c42b33ba16524537a81
+Result = Fail
+
+Count = 184
+Nonce = ccee19d037cf4a
+Adata = c026696e6425e6c33f45b4145febf1137e7ac26383c9f5aa4cd4e5e8abb19e07
+CT = 9b61335f96fc5b31274cc1fb275f29c1105d68c67b70654f9405edb1
+Result = Pass
+Payload = 0df202431ee7f251a38aaf6aa8cd313782bd293af9114005
+
+Count = 185
+Nonce = 6c8ba94f09cbe6
+Adata = 774ad1a88f8bb063951486d4aec5bf82d5fc535bd0b952f86200c123c37fa496
+CT = 97b5eb2d55847f5d5d9f8c762dace481d8efb19ccfd72265548effe3
+Result = Fail
+
+Count = 186
+Nonce = 1f670302fcdcc8
+Adata = 1a9ff9698cfc96b581d7115c822e4363d7355ec5daed2eae5bf89ee944ac7d9c
+CT = f5cc8198dce8e890587b62572b07413a915bfb55628c901c03459b29
+Result = Fail
+
+Count = 187
+Nonce = 5d05f658c729a2
+Adata = dd9564c1431ed490b17ef69f6115805e54ef156ef4e10e58f7d57a7e86626352
+CT = 50c0b1f6c5e4c86a0c938ecbc762eeaf99b9fe04c2820a43963b04f3
+Result = Fail
+
+Count = 188
+Nonce = 22a77db9fcbc95
+Adata = 86bf1739c10f63df734ee3e60ac40ff5636c49f68ca4c16ece289609eb413e7a
+CT = 1fdbe91189da01c5098cf1538addd85b1cfef0abd0797c141330f633
+Result = Fail
+
+Count = 189
+Nonce = 491e32b0bbfa4c
+Adata = 75bef075c79d6cfd7fc73aefd67b2d215be0648937477ba606b1fe1be591239e
+CT = 462e7cdf9a6a553bca37d4d93bed4986b715d0349238613e10c1f6d7
+Result = Fail
+
+Count = 190
+Nonce = bc4b7d3a380be0
+Adata = 353dbb41e2d525a9f4fcd858d0f0aa1b1e86ac0f936d5c09c6b61c343f94e3fc
+CT = 7d142f26aa6c9d55850c5c9f58ab36a66670d47c515bf93cd37e5543
+Result = Fail
+
+Count = 191
+Nonce = a840e98df72ae9
+Adata = 22c6607732ef1bdc7fcf6197e037cdadd7ee17c008552dd9f04b8564d34fb17c
+CT = f7122cbcec93d53fc7e3fc629ea15d28363cad1c83a23bb3cc5e0c4a
+Result = Pass
+Payload = a2f53385618b41301f4e3ea4c597f411103dac2b37abf5da
+
+Count = 192
+Nonce = 39d93c3cf31a6f
+Adata = 937dfac5cded938438f4e97aabd9beb50dba40f824198260a89729479cfe6869
+CT = e1cad7f946b20c373323218c8a89e56edf3030662e50d459fc12a512
+Result = Pass
+Payload = c1bdef96dc868446be48491b160504546f2a40dd581f9582
+
+Count = 193
+Nonce = 0bbc177019321e
+Adata = f6e02678820f5ccbede6cbded02d6dd58d486166d7b18ee975a688af421fb795
+CT = d4741814466a23e26107d773f103a4c83db9d772dbd5fdc1c2eaf895
+Result = Pass
+Payload = 72a70954d22ad722fc32756afce67b344b2f3c55fe1d9eed
+
+Count = 194
+Nonce = ad048eb2ad7526
+Adata = 0d2739cfdac782b61f484fa1a423c478c414397ec420327963d79112b2d70a7e
+CT = ed35ff66bc7f6d8ec7acf896f994d79f5792cf6d22d6691ff92fa2f7
+Result = Fail
+
+[Alen = 32, Plen = 24, Nlen = 7, Tlen = 16]
+
+Key = a7aa635ea51b0bb20a092bd5573e728c
+
+Count = 195
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = b351ab96b2e45515254558d5212673ee6c776d42dbca3b512cf3a20b7fd7c49e6e79bef475c2906f
+Result = Pass
+Payload = a265480ca88d5f536db0dc6abc40faf0d05be7a966977768
+
+Count = 196
+Nonce = fdd2d6f503c915
+Adata = 5b92394f21ddc3ad49d9b0881b829a5935cb3a4d23e292a62fb66b5e7ab7020e
+CT = df1a5285caa41b4bb47f6e5ceceba4e82721828d68427a3081d18ca149d6766bfaccec88f194eb5b
+Result = Fail
+
+Count = 197
+Nonce = 27d73d58100054
+Adata = f6468542923be79b4b06dfe70920d57d1da73a9c16f9c9a12d810d7de0d12467
+CT = 04a29fc109dfc626e8297e0f586d0bfaf31260017d95f62d5eb4f0875dda5ccd9b94026ba49fb34e
+Result = Fail
+
+Count = 198
+Nonce = dd16e0ce1250e3
+Adata = bc65cfd65e9863c8b7457d58afa6bdb48a84170d8aa97ba5b397b52ad17a9242
+CT = 77e4cd5d319353ecb6b89e2de14bcfee4fbf738b61df14f3920843994def41aed3103995d3392eed
+Result = Fail
+
+Count = 199
+Nonce = ccee19d037cf4a
+Adata = c026696e6425e6c33f45b4145febf1137e7ac26383c9f5aa4cd4e5e8abb19e07
+CT = e676f5dfde8ad810d9e729d142670eef77f2878369a28797d57603d5c45606c68be5535c671d5432
+Result = Pass
+Payload = 0df202431ee7f251a38aaf6aa8cd313782bd293af9114005
+
+Count = 200
+Nonce = 6c8ba94f09cbe6
+Adata = 774ad1a88f8bb063951486d4aec5bf82d5fc535bd0b952f86200c123c37fa496
+CT = 60c51e5c3fe4197454d64fa14017639bcfd1423b9d74e506a0bfd54fb786208e1e49c6d0e645d9fb
+Result = Fail
+
+Count = 201
+Nonce = 1f670302fcdcc8
+Adata = 1a9ff9698cfc96b581d7115c822e4363d7355ec5daed2eae5bf89ee944ac7d9c
+CT = 64d1160365062eca1027cc7036862b027bdda3a9abdf794daf8a9b7a5c50b0be4596290a4d405e79
+Result = Fail
+
+Count = 202
+Nonce = 5d05f658c729a2
+Adata = dd9564c1431ed490b17ef69f6115805e54ef156ef4e10e58f7d57a7e86626352
+CT = 968ca115583c645710d2b47fb196cf55f6ef33f2b01400e22ce9c776932ecf7fddd849be58096b88
+Result = Fail
+
+Count = 203
+Nonce = 22a77db9fcbc95
+Adata = 86bf1739c10f63df734ee3e60ac40ff5636c49f68ca4c16ece289609eb413e7a
+CT = 4985821b16ff6d4d3416573e2fba4d53186d912f0b023a99915d0020da92f483a5a7914cba14b1e7
+Result = Fail
+
+Count = 204
+Nonce = 491e32b0bbfa4c
+Adata = 75bef075c79d6cfd7fc73aefd67b2d215be0648937477ba606b1fe1be591239e
+CT = c7345b031ef85bde766226a7603adaa7dcb07a7b2a8be1b571420e036ea48dddd671be622d372c5b
+Result = Fail
+
+Count = 205
+Nonce = bc4b7d3a380be0
+Adata = 353dbb41e2d525a9f4fcd858d0f0aa1b1e86ac0f936d5c09c6b61c343f94e3fc
+CT = 11460b9acccc13001be236814da6b73f2c8e0467574f151bb619a331f8d67d70c3f3a59b3fab53a5
+Result = Fail
+
+Count = 206
+Nonce = a840e98df72ae9
+Adata = 22c6607732ef1bdc7fcf6197e037cdadd7ee17c008552dd9f04b8564d34fb17c
+CT = 1bcff940a2d9d48e93bbfd13aed5947237485983e6ae04b8b944bb46306a9b1e783f3e54c92d5f5e
+Result = Pass
+Payload = a2f53385618b41301f4e3ea4c597f411103dac2b37abf5da
+
+Count = 207
+Nonce = 39d93c3cf31a6f
+Adata = 937dfac5cded938438f4e97aabd9beb50dba40f824198260a89729479cfe6869
+CT = 3b6c1570c85f297079be14cd66d335251c7b52e131a636f148608963f3037763843b70c35d7011f8
+Result = Pass
+Payload = c1bdef96dc868446be48491b160504546f2a40dd581f9582
+
+Count = 208
+Nonce = 0bbc177019321e
+Adata = f6e02678820f5ccbede6cbded02d6dd58d486166d7b18ee975a688af421fb795
+CT = b540cd8cbe733e0ca2ba2112ea785596d2c1d707f41608514ba2d0944c68cc36d4125b3ef9071d69
+Result = Pass
+Payload = 72a70954d22ad722fc32756afce67b344b2f3c55fe1d9eed
+
+Count = 209
+Nonce = ad048eb2ad7526
+Adata = 0d2739cfdac782b61f484fa1a423c478c414397ec420327963d79112b2d70a7e
+CT = 3c9c1481f1428acf202b510dca67e5e6b2abc5dd71a954da51387922af7182b7d46a33c703e6e7a8
+Result = Fail
+
+[Alen = 32, Plen = 24, Nlen = 13, Tlen = 4]
+
+Key = a7aa635ea51b0bb20a092bd5573e728c
+
+Count = 210
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = 934f893824e880f743d196b22d1f340a52608155087bd28ac25e5329
+Result = Pass
+Payload = 8739b4bea1a099fe547499cbc6d1b13d849b8084c9b6acc5
+
+Count = 211
+Nonce = 0812757ad0cc4d17c4cfe7a642
+Adata = ec6c44a7e94e51a3ca6dee229098391575ec7213c85267fbf7492fdbeee61b10
+CT = f43ba9d834ad85dfab3f1c0c27c3441fe4e411a38a261a6559b3b3ee
+Result = Fail
+
+Count = 212
+Nonce = eff510acc1b85f35029cf7dc00
+Adata = 0923b927b8295c5dfaf67da55e5014293bc8c708fda50af06c1e8aef31cccc86
+CT = c686eac859a7bae3cce97d0b6527a0a7c8c2b24ece35f4370bf6688e
+Result = Fail
+
+Count = 213
+Nonce = 3d13d09057190366c63c8750e9
+Adata = 77e27aa9a7bf30e130c862a3296a1cd7a10195ed1d940f2c97bfff47c6f06e32
+CT = 2b28355ecf7246ddb08d65c464dcaa90af85f434ff95267280ed869c
+Result = Fail
+
+Count = 214
+Nonce = e3c03ef7e1d31961ee0b97bd99
+Adata = 8a3676dd640821b58fb0f0329855fd5882c376ea166b958b7aaad223054e5784
+CT = ecde42091baa1f5c17b79746e21c3de5c78984570748021ccd399507
+Result = Pass
+Payload = 92973ce707733a73118c8ce6b5e3fc77a17f448310c0197f
+
+Count = 215
+Nonce = 5d165ddd4e599387af5967cae6
+Adata = e374f875ce829b62c98fbd67bcf128b5647f25fff9a643300eb95559b889baed
+CT = 5c338435ed4f148342604c9aed63e907c100453d719fda2a3da37b66
+Result = Fail
+
+Count = 216
+Nonce = fcec171162a27a96066181fab2
+Adata = cf431cc3671ec468ea86f6cc09842fcf3a84b3ef0fa1c7b20b232145b4469d62
+CT = 30eac1042015eb82729673edd9939bf9995b2575da4d6c4c7e75dded
+Result = Fail
+
+Count = 217
+Nonce = 2fa8120398d1a946f391367cf6
+Adata = 92558a239c8e13230754f23aec67b153db29fdfc7daf641778185dd2931d89da
+CT = ebd3ce55b40e4bbd8172033948c6c78049161ee8f949eb50722b9c87
+Result = Fail
+
+Count = 218
+Nonce = 88e0ae338bbca9d4299b294354
+Adata = 5db5c388dbadc9f175a5cd5a1472a458d25acd7fb9c951c0cd45edf64da473bb
+CT = 20f79b36ca83baac97600fd8a6dad22c2cd0f9b7e770576048c042e5
+Result = Fail
+
+Count = 219
+Nonce = 4862e36296d6afc9399a95bbb4
+Adata = 36d82ebd0e0f5fe3b12946d041ae5aee16e6d17025406dd776f499bbd8e8b4c8
+CT = 77b76f249f936fb19bd47fe28ad4dbb7725dec365a1cb23a885ba975
+Result = Fail
+
+Count = 220
+Nonce = 2f360a4715074e942244ab7f9b
+Adata = f0087b0086a081c1071481f033a8be8e940c36763084329bb8461b9102238f4f
+CT = cf6763a23c2eab730845d1eb79bbba9f54ee899fe3d70570aa799e79
+Result = Fail
+
+Count = 221
+Nonce = 93e08854560edb096e5d654086
+Adata = bdc60dff08bfd5d44320b75c61e456fd4333c9c3d0294d4a48d936dfd5922ce2
+CT = 1f8086a43c1b2dea557952db88e0dbbdb96aafdb345eddae6c0b0104
+Result = Pass
+Payload = 569e4aec88dd51ca519c0a00c922ee33d3559b98a32d7906
+
+Count = 222
+Nonce = e3f37b68ff508cfe295441d9e3
+Adata = b2b6c5782e4f128467c589d2a6cf55ef12877adb771bbb6245c5bba9dcfd6208
+CT = c0c5f92285b114e0a0777e1bc22b810e7cc4f68c28cd5ce047a28dd8
+Result = Pass
+Payload = 02b5511204bd55f7c37973e26f6df5883c0a530f07c7f8c2
+
+Count = 223
+Nonce = ea98ec44f5a86715014783172e
+Adata = e4692b9f06b666c7451b146c8aeb07a6e30c629d28065c3dde5940325b14b810
+CT = 56327f4db9c18f72bbefc3f316d31f9795dd77f493385ab7b7543552
+Result = Pass
+Payload = 4da40b80579c1d9a5309f7efecb7c059a2f914511ca5fc10
+
+Count = 224
+Nonce = 5a16a8902bd70fa06cfe184c57
+Adata = 399d6b0652836457ec4f701f0dc0e5aed73d16585d61cb1bb5b7ee824fc287c8
+CT = 37d5b17995fac8c94302ec9ba20a36d97678e85199b677f8ee39867e
+Result = Fail
+
+[Alen = 32, Plen = 24, Nlen = 13, Tlen = 16]
+
+Key = 26511fb51fcfa75cb4b44da75a6e5a0e
+
+Count = 225
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = 50038b5fdd364ee747b70d00bd36840ece4ea19998123375c0a458bfcafa3b2609afe0f825cbf503
+Result = Pass
+Payload = 8739b4bea1a099fe547499cbc6d1b13d849b8084c9b6acc5
+
+Count = 226
+Nonce = 0812757ad0cc4d17c4cfe7a642
+Adata = ec6c44a7e94e51a3ca6dee229098391575ec7213c85267fbf7492fdbeee61b10
+CT = 78ed8ff6b5a1255d0fbd0a719a9c27b059ff5f83d0c4962c390042ba8bb5f6798dab01c5afad7306
+Result = Fail
+
+Count = 227
+Nonce = eff510acc1b85f35029cf7dc00
+Adata = 0923b927b8295c5dfaf67da55e5014293bc8c708fda50af06c1e8aef31cccc86
+CT = 4b91d8e616d3f60452fd3a576bd7c265b7f549523ed4a5d7a3463394cf3c25bef8af8f244d0c0b00
+Result = Fail
+
+Count = 228
+Nonce = 3d13d09057190366c63c8750e9
+Adata = 77e27aa9a7bf30e130c862a3296a1cd7a10195ed1d940f2c97bfff47c6f06e32
+CT = ab8cf8891ab62924c0c6f49dd253cfa0c3d6260d0ee4d9ba88caf8ae59d9d1131626da0dddf8722d
+Result = Fail
+
+Count = 229
+Nonce = e3c03ef7e1d31961ee0b97bd99
+Adata = 8a3676dd640821b58fb0f0329855fd5882c376ea166b958b7aaad223054e5784
+CT = c6b7680f321132a8bd00e8e92f785d0b828b100af6392a04d1292373a76970eda77a8194f6276262
+Result = Pass
+Payload = 92973ce707733a73118c8ce6b5e3fc77a17f448310c0197f
+
+Count = 230
+Nonce = 5d165ddd4e599387af5967cae6
+Adata = e374f875ce829b62c98fbd67bcf128b5647f25fff9a643300eb95559b889baed
+CT = aea98867d3d707c43a963c1d7fdcfc953cbd707803b2b5f0a97af19d0b7bf7c7ce398cb0b44d73af
+Result = Fail
+
+Count = 231
+Nonce = fcec171162a27a96066181fab2
+Adata = cf431cc3671ec468ea86f6cc09842fcf3a84b3ef0fa1c7b20b232145b4469d62
+CT = c55e17ba7886eb58126d50bde8c5c211cc1aafd71a3d9e5b343065b4bdd973ee072dbf5160d310f3
+Result = Fail
+
+Count = 232
+Nonce = 2fa8120398d1a946f391367cf6
+Adata = 92558a239c8e13230754f23aec67b153db29fdfc7daf641778185dd2931d89da
+CT = 791a62d5fb39ff9735ad94507e1afe2647714d5cc56b6ff4233ec600bca1d31f704807494fb0f18d
+Result = Fail
+
+Count = 233
+Nonce = 88e0ae338bbca9d4299b294354
+Adata = 5db5c388dbadc9f175a5cd5a1472a458d25acd7fb9c951c0cd45edf64da473bb
+CT = f98a081998e29500f15ebd8978a95423aed4e8e78e0279d17ec183db0e2a33ebb147d0e2363fbb01
+Result = Fail
+
+Count = 234
+Nonce = 4862e36296d6afc9399a95bbb4
+Adata = 36d82ebd0e0f5fe3b12946d041ae5aee16e6d17025406dd776f499bbd8e8b4c8
+CT = 7779814dc295a23b4100ca94bec0ad4ce2f6be6fb75a0c217e67ea2577ade5836c26a89760e0959b
+Result = Fail
+
+Count = 235
+Nonce = 2f360a4715074e942244ab7f9b
+Adata = f0087b0086a081c1071481f033a8be8e940c36763084329bb8461b9102238f4f
+CT = 55640eed12c7595a36ab423da8d8241905b6ff1e906db9624978a7865df8369635269411b3aaeb32
+Result = Fail
+
+Count = 236
+Nonce = 93e08854560edb096e5d654086
+Adata = bdc60dff08bfd5d44320b75c61e456fd4333c9c3d0294d4a48d936dfd5922ce2
+CT = 7fcdce0ba567b9a708d54fdb16125de71dce952f4741684f4f9d302e4f1d2a2aedf2768d7b29163f
+Result = Pass
+Payload = 569e4aec88dd51ca519c0a00c922ee33d3559b98a32d7906
+
+Count = 237
+Nonce = e3f37b68ff508cfe295441d9e3
+Adata = b2b6c5782e4f128467c589d2a6cf55ef12877adb771bbb6245c5bba9dcfd6208
+CT = d42111ba22987eac1ead5cc6cb8548bcda190d118dcd5461a50036af67fadab163e9daa8bd8e9030
+Result = Pass
+Payload = 02b5511204bd55f7c37973e26f6df5883c0a530f07c7f8c2
+
+Count = 238
+Nonce = ea98ec44f5a86715014783172e
+Adata = e4692b9f06b666c7451b146c8aeb07a6e30c629d28065c3dde5940325b14b810
+CT = 1bf0ba0ebb20d8edba59f29a9371750c9c714078f73c335d2f1322ac69b848b001476323aed84c47
+Result = Pass
+Payload = 4da40b80579c1d9a5309f7efecb7c059a2f914511ca5fc10
+
+Count = 239
+Nonce = 5a16a8902bd70fa06cfe184c57
+Adata = 399d6b0652836457ec4f701f0dc0e5aed73d16585d61cb1bb5b7ee824fc287c8
+CT = 9d993b945476ace0b9ca932963ac8835e1bd02e8065da2d816786c4d8cf14c03b031ff723311b3c4
+Result = Fail
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT128.txt b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT128.txt
new file mode 100644
index 0000000000..1606dcb21e
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT128.txt
@@ -0,0 +1,1589 @@
+# CAVS 11.0
+# "CCM-DVPT" information
+# AES Keylen: 128
+# Generated on Tue Mar 15 08:09:25 2011
+
+
+[Alen = 0, Plen = 0, Nlen = 7, Tlen = 4]
+
+Key = 4ae701103c63deca5b5a3939d7d05992
+
+Count = 0
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = 02209f55
+Result = Pass (0)
+Payload = 00
+
+Count = 1
+Nonce = 3796cf51b87266
+Adata = 00
+CT = 9a04c241
+Result = Fail (2 - CT changed)
+
+Count = 2
+Nonce = 89ca5a64050f9f
+Adata = 00
+CT = f5f915df
+Result = Fail (1 - Adata changed)
+
+Count = 3
+Nonce = ec9d8edff25645
+Adata = 00
+CT = 7a3c3499
+Result = Fail (1 - Adata changed)
+
+Count = 4
+Nonce = 05e16f0f42a6f4
+Adata = 00
+CT = f09c2986
+Result = Pass (0)
+Payload = 00
+
+Count = 5
+Nonce = 2e504b694f8df5
+Adata = 00
+CT = 4ae97e71
+Result = Fail (2 - CT changed)
+
+Count = 6
+Nonce = 06d102a9328863
+Adata = 00
+CT = ecb38c8b
+Result = Fail (1 - Adata changed)
+
+Count = 7
+Nonce = c288b810fb5334
+Adata = 00
+CT = 9c4dc530
+Result = Fail (2 - CT changed)
+
+Count = 8
+Nonce = 08a166d9eb6610
+Adata = 00
+CT = 67299ef6
+Result = Fail (2 - CT changed)
+
+Count = 9
+Nonce = 4a5810b121c91b
+Adata = 00
+CT = b0538d02
+Result = Fail (1 - Adata changed)
+
+Count = 10
+Nonce = 44077341139bf9
+Adata = 00
+CT = 88200ea8
+Result = Fail (1 - Adata changed)
+
+Count = 11
+Nonce = a9df4f37847e1f
+Adata = 00
+CT = 19867aa5
+Result = Pass (0)
+Payload = 00
+
+Count = 12
+Nonce = 11df57fcd131e9
+Adata = 00
+CT = 3b392a52
+Result = Pass (0)
+Payload = 00
+
+Count = 13
+Nonce = 890fff56d10dc0
+Adata = 00
+CT = 1c5e47e0
+Result = Pass (0)
+Payload = 00
+
+Count = 14
+Nonce = 9dc18698731b27
+Adata = 00
+CT = 97a56b8b
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 0, Nlen = 7, Tlen = 16]
+
+Key = 4bb3c4a4f893ad8c9bdc833c325d62b3
+
+Count = 15
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = 75d582db43ce9b13ab4b6f7f14341330
+Result = Pass (0)
+Payload = 00
+
+Count = 16
+Nonce = 3796cf51b87266
+Adata = 00
+CT = 3a65e03af37b81d05acc7ec1bc39deb0
+Result = Fail (2 - CT changed)
+
+Count = 17
+Nonce = 89ca5a64050f9f
+Adata = 00
+CT = efc5721e0b9e4c3c90deab0e1d5c11bd
+Result = Fail (1 - Adata changed)
+
+Count = 18
+Nonce = ec9d8edff25645
+Adata = 00
+CT = 91b4b779823f4f0e3979ced93b99736c
+Result = Fail (1 - Adata changed)
+
+Count = 19
+Nonce = 05e16f0f42a6f4
+Adata = 00
+CT = e2e87ca82523ccfeb416b42af9d9aadc
+Result = Pass (0)
+Payload = 00
+
+Count = 20
+Nonce = 2e504b694f8df5
+Adata = 00
+CT = 7b85fd105cc960df86ad86846d178274
+Result = Fail (2 - CT changed)
+
+Count = 21
+Nonce = 06d102a9328863
+Adata = 00
+CT = ffa140be27b25f307a6efd9697d66c9b
+Result = Fail (1 - Adata changed)
+
+Count = 22
+Nonce = c288b810fb5334
+Adata = 00
+CT = ed356542e0a804a724bfaa422e98a970
+Result = Fail (2 - CT changed)
+
+Count = 23
+Nonce = 08a166d9eb6610
+Adata = 00
+CT = e31dd8dc920fe7900e1b1817fe845c7d
+Result = Fail (2 - CT changed)
+
+Count = 24
+Nonce = 4a5810b121c91b
+Adata = 00
+CT = ae5a0777f03bbf541f305d00acff0396
+Result = Fail (1 - Adata changed)
+
+Count = 25
+Nonce = 44077341139bf9
+Adata = 00
+CT = 957dca58616c1cbe99f94fd8f7c257d9
+Result = Fail (1 - Adata changed)
+
+Count = 26
+Nonce = a9df4f37847e1f
+Adata = 00
+CT = 0e150af422f6da238bb476810b2d5bc2
+Result = Pass (0)
+Payload = 00
+
+Count = 27
+Nonce = 11df57fcd131e9
+Adata = 00
+CT = 8e1150756ff3a733a1274470f072b74c
+Result = Pass (0)
+Payload = 00
+
+Count = 28
+Nonce = 890fff56d10dc0
+Adata = 00
+CT = a1f70df3fa9cfeb95f869b3fe08466e0
+Result = Pass (0)
+Payload = 00
+
+Count = 29
+Nonce = 9dc18698731b27
+Adata = 00
+CT = fdf3f6c177aa1d71fe3474a5a2eb6bb1
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 0, Nlen = 13, Tlen = 4]
+
+Key = 4bb3c4a4f893ad8c9bdc833c325d62b3
+
+Count = 30
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = 90156f3f
+Result = Pass (0)
+Payload = 00
+
+Count = 31
+Nonce = a16a2e741f1cd9717285b6d882
+Adata = 00
+CT = 88909016
+Result = Fail (2 - CT changed)
+
+Count = 32
+Nonce = 368f3b8180fd4b851b7b272cb1
+Adata = 00
+CT = de547d03
+Result = Fail (1 - Adata changed)
+
+Count = 33
+Nonce = 7bb2bc00c0cafce65b5299ae64
+Adata = 00
+CT = ea4bad52
+Result = Fail (1 - Adata changed)
+
+Count = 34
+Nonce = 935c1ef3d4032ff090f91141f3
+Adata = 00
+CT = 1bc82b3d
+Result = Pass (0)
+Payload = 00
+
+Count = 35
+Nonce = 2640b14f10b116411d1b5c1ad1
+Adata = 00
+CT = 92e72250
+Result = Fail (2 - CT changed)
+
+Count = 36
+Nonce = b229c173a13b2d83af91ec45b0
+Adata = 00
+CT = e81f0647
+Result = Fail (1 - Adata changed)
+
+Count = 37
+Nonce = 37ca0dc2d6efd9efde69f14f03
+Adata = 00
+CT = 7cb906ec
+Result = Fail (2 - CT changed)
+
+Count = 38
+Nonce = 6b6238aed86d677ba2b3e2622c
+Adata = 00
+CT = d60f815b
+Result = Fail (2 - CT changed)
+
+Count = 39
+Nonce = d6cb2ac67bb13b8f6d31fad64a
+Adata = 00
+CT = d3d4f3b0
+Result = Fail (1 - Adata changed)
+
+Count = 40
+Nonce = 32a7cd361ef00e65f5778fdfd4
+Adata = 00
+CT = a9df97ad
+Result = Fail (1 - Adata changed)
+
+Count = 41
+Nonce = d0a1508fdefcf5be30a459b813
+Adata = 00
+CT = 36a37a59
+Result = Pass (0)
+Payload = 00
+
+Count = 42
+Nonce = 5381a61b449dc6a42aa4c79b95
+Adata = 00
+CT = dba02a36
+Result = Pass (0)
+Payload = 00
+
+Count = 43
+Nonce = c55430f2da0687ea40313884ab
+Adata = 00
+CT = 25dcb3c5
+Result = Pass (0)
+Payload = 00
+
+Count = 44
+Nonce = ec76d1850acc0979a1f11906fb
+Adata = 00
+CT = 1d2832d0
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 0, Nlen = 13, Tlen = 16]
+
+Key = 19ebfde2d5468ba0a3031bde629b11fd
+
+Count = 45
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = fb04dc5a44c6bb000f2440f5154364b4
+Result = Pass (0)
+Payload = 00
+
+Count = 46
+Nonce = a16a2e741f1cd9717285b6d882
+Adata = 00
+CT = 5447075bf42a59b91f08064738b015ab
+Result = Fail (2 - CT changed)
+
+Count = 47
+Nonce = 368f3b8180fd4b851b7b272cb1
+Adata = 00
+CT = fdc992847f0815fac67aa935b35208ed
+Result = Fail (1 - Adata changed)
+
+Count = 48
+Nonce = 7bb2bc00c0cafce65b5299ae64
+Adata = 00
+CT = 2cabd690a45e59854b7587b26dd77f8e
+Result = Fail (1 - Adata changed)
+
+Count = 49
+Nonce = 935c1ef3d4032ff090f91141f3
+Adata = 00
+CT = 3dacc71169f6da77ec91ff1d2f649ed1
+Result = Pass (0)
+Payload = 00
+
+Count = 50
+Nonce = 2640b14f10b116411d1b5c1ad1
+Adata = 00
+CT = 97a2eb170ef03fa12124f1315e3b694f
+Result = Fail (2 - CT changed)
+
+Count = 51
+Nonce = b229c173a13b2d83af91ec45b0
+Adata = 00
+CT = 94d85a83169d8dc76f58baf4d63ecfee
+Result = Fail (1 - Adata changed)
+
+Count = 52
+Nonce = 37ca0dc2d6efd9efde69f14f03
+Adata = 00
+CT = d3903c6289ca3684b8ce1174c23153a4
+Result = Fail (2 - CT changed)
+
+Count = 53
+Nonce = 6b6238aed86d677ba2b3e2622c
+Adata = 00
+CT = 5cbac5c418374a68bd7085454c4b0c13
+Result = Fail (2 - CT changed)
+
+Count = 54
+Nonce = d6cb2ac67bb13b8f6d31fad64a
+Adata = 00
+CT = 26317f6b8b0130097441ed04b8009aef
+Result = Fail (1 - Adata changed)
+
+Count = 55
+Nonce = 32a7cd361ef00e65f5778fdfd4
+Adata = 00
+CT = b82ab6f3bbf59b6caafc54f05570f74e
+Result = Fail (1 - Adata changed)
+
+Count = 56
+Nonce = d0a1508fdefcf5be30a459b813
+Adata = 00
+CT = 1ae34207e74c8c78890ae17e320e84bd
+Result = Pass (0)
+Payload = 00
+
+Count = 57
+Nonce = 5381a61b449dc6a42aa4c79b95
+Adata = 00
+CT = 5c5fa254c0be503b02caffade6b85259
+Result = Pass (0)
+Payload = 00
+
+Count = 58
+Nonce = c55430f2da0687ea40313884ab
+Adata = 00
+CT = 9340266730ea36207bb734819d3553e9
+Result = Pass (0)
+Payload = 00
+
+Count = 59
+Nonce = ec76d1850acc0979a1f11906fb
+Adata = 00
+CT = ec17cccf33bd9a0d4ce7aa20690c1333
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 24, Nlen = 7, Tlen = 4]
+
+Key = 19ebfde2d5468ba0a3031bde629b11fd
+
+Count = 60
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = a90e8ea44085ced791b2fdb7fd44b5cf0bd7d27718029bb703e1fa6b
+Result = Pass (0)
+Payload = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22
+
+Count = 61
+Nonce = 31f8fa25827d48
+Adata = 00
+CT = 50aafe0578c115c4a8e126ff7b3ccb64dce8ccaa8ceda69f23e5d81c
+Result = Fail (2 - CT changed)
+
+Count = 62
+Nonce = 5340ed7752c9ff
+Adata = 00
+CT = 512ed208bf10d57406537e94d20a5b6e2e9ab0683dfdc685869a97f0
+Result = Fail (1 - Adata changed)
+
+Count = 63
+Nonce = 9cbce402511b89
+Adata = 00
+CT = af72db9cd9d6f46607d6f9542ca69988dd15255c5c91171c838e7f95
+Result = Fail (1 - Adata changed)
+
+Count = 64
+Nonce = 123a0beace4e39
+Adata = 00
+CT = 47d71409a03c330be9451b3f92c9d21c584391ad1010e9d609b89801
+Result = Pass (0)
+Payload = 9d033e3b66efed1467868f382417c80594877a28bc97f406
+
+Count = 65
+Nonce = 8ea1594a58fe4a
+Adata = 00
+CT = e562c7af0384ea16431ca20934a293a058d722cbfc3186c8eaf5f825
+Result = Fail (2 - CT changed)
+
+Count = 66
+Nonce = 5a7743e59e82da
+Adata = 00
+CT = 004d9d89c401aa79919c2805fcd5de69316e191df56426c05ec1aa6a
+Result = Fail (1 - Adata changed)
+
+Count = 67
+Nonce = f477f754d7ee76
+Adata = 00
+CT = d623673d7f6d57c208bde112ca858561f3af5cc2bf5de926f3586c6f
+Result = Fail (2 - CT changed)
+
+Count = 68
+Nonce = 040a257dede70e
+Adata = 00
+CT = fd4733d158b5630f4f6c03ab26b11bff0cbe0d5d3df99a735fa40618
+Result = Fail (2 - CT changed)
+
+Count = 69
+Nonce = dd51b8e91683d1
+Adata = 00
+CT = d352cb996c3075ff367a8dcacbbae46a12fbef08aa96ec835bf4f930
+Result = Fail (1 - Adata changed)
+
+Count = 70
+Nonce = ab3cb86cca6fb2
+Adata = 00
+CT = 31730fac20e21eca0aef591faa9fa90b3c058e32af1ce48a66f0496e
+Result = Fail (1 - Adata changed)
+
+Count = 71
+Nonce = f67b98efd39b55
+Adata = 00
+CT = dd175905a7ea3aef9fce068e6cb78e9cc60519755a178c77b753181c
+Result = Pass (0)
+Payload = f2e944e1ae47ad5873bf391f1b0cc07f6151eb4c50bb45b2
+
+Count = 72
+Nonce = e60e2c002d1c99
+Adata = 00
+CT = 8ad6b76f54392ee0f2834f09142545bcde9bf03d04d64aa10876f2da
+Result = Pass (0)
+Payload = 70f48dc1d76e5028da07e29852801375a9edb2214a5ea4c0
+
+Count = 73
+Nonce = 098e053fa08043
+Adata = 00
+CT = 808eb3e04c39abde64674f0f7716dde11699cff8dd367c4cd4f7fc07
+Result = Pass (0)
+Payload = bd81680e3dc0b35431c92598dcaa26ef09ca0da5e77193de
+
+Count = 74
+Nonce = 4bf48328725514
+Adata = 00
+CT = e074d13aad43f7b2364d47db0a02326641ca3b2ad61a1c49973a2712
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 24, Nlen = 7, Tlen = 16]
+
+Key = 197afb02ffbd8f699dacae87094d5243
+
+Count = 75
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = 24ab9eeb0e5508cae80074f1070ee188a637171860881f1f2d9a3fbc210595b7b8b1b41523111a8e
+Result = Pass (0)
+Payload = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22
+
+Count = 76
+Nonce = 31f8fa25827d48
+Adata = 00
+CT = 7ebfda6fa5da1dbffd82dc29b875798fbcef8ba0084fbd2463af747cc88a001fa94e060290f209c4
+Result = Fail (2 - CT changed)
+
+Count = 77
+Nonce = 5340ed7752c9ff
+Adata = 00
+CT = cbf133643851f91ddc7a1e19a0c21990459f2b7728da58f5cf3b8e6c8aeb5eeb0a5efb3700be45a2
+Result = Fail (1 - Adata changed)
+
+Count = 78
+Nonce = 9cbce402511b89
+Adata = 00
+CT = 0de7567a945c0af4a2291a651de411e8d0438508f2d4da80f7bd61a0158accbca28913e39fe80906
+Result = Fail (1 - Adata changed)
+
+Count = 79
+Nonce = 123a0beace4e39
+Adata = 00
+CT = d43035cdb5a1868aa430e8b41a1dc57a639087238e38bd628feeda2e8f249dd93a8358def7639875
+Result = Pass (0)
+Payload = 9d033e3b66efed1467868f382417c80594877a28bc97f406
+
+Count = 80
+Nonce = 8ea1594a58fe4a
+Adata = 00
+CT = 389547260b354a6cbc909de057d367677049e80613877f6fbf19f89da977e56f308373c616299ad4
+Result = Fail (2 - CT changed)
+
+Count = 81
+Nonce = 5a7743e59e82da
+Adata = 00
+CT = a95aa33483ed3711470025394616bf98fe624fbca8aa6fbc21366b9da457ede2a673351475b53d41
+Result = Fail (1 - Adata changed)
+
+Count = 82
+Nonce = f477f754d7ee76
+Adata = 00
+CT = 3d53b6ab8925f429ae14a0065cd203d4f9deddd402a79ac6d889a7cae55efd71b369cd6d43ef363b
+Result = Fail (2 - CT changed)
+
+Count = 83
+Nonce = 040a257dede70e
+Adata = 00
+CT = d5e6e82cb5f8034a89e58adf8298476253f18981bcb3b0364be7f19463dd330a4b9f3cbb30b88fa5
+Result = Fail (2 - CT changed)
+
+Count = 84
+Nonce = dd51b8e91683d1
+Adata = 00
+CT = 02f69107d62ff77145c7d57684c70ba671d55f1c63bb2ad8c2df063f7fdbae27f0736a37fd065fb4
+Result = Fail (1 - Adata changed)
+
+Count = 85
+Nonce = ab3cb86cca6fb2
+Adata = 00
+CT = 64ec2f321111da9c5389e8255bfe69876d4f548f94cacd529b45d54cc24cff1b1d8aa1df32fbd81a
+Result = Fail (1 - Adata changed)
+
+Count = 86
+Nonce = f67b98efd39b55
+Adata = 00
+CT = 37d63c2bbf44d2eb155ecc1a844841d5c33f1a6d443419330217a4f1f4fb302257b0de7c9da2e750
+Result = Pass (0)
+Payload = f2e944e1ae47ad5873bf391f1b0cc07f6151eb4c50bb45b2
+
+Count = 87
+Nonce = e60e2c002d1c99
+Adata = 00
+CT = 33e0dce4410e51bed5323ea49490207084ac91732bae429236a305d520a1a24930a70a311aa3695d
+Result = Pass (0)
+Payload = 70f48dc1d76e5028da07e29852801375a9edb2214a5ea4c0
+
+Count = 88
+Nonce = 098e053fa08043
+Adata = 00
+CT = 1d732c334319bd775e7cf93dbdc4204bbdb58192be08280481e3d64ed546b6b70ee088a693f55fbb
+Result = Pass (0)
+Payload = bd81680e3dc0b35431c92598dcaa26ef09ca0da5e77193de
+
+Count = 89
+Nonce = 4bf48328725514
+Adata = 00
+CT = c92fc2f0d24593f67d9c09d326158a8138237c4096093f0d737719dd84ccfb397a4f61b70c85262a
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 24, Nlen = 13, Tlen = 4]
+
+Key = 197afb02ffbd8f699dacae87094d5243
+
+Count = 90
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = 4a550134f94455979ec4bf89ad2bd80d25a77ae94e456134a3e138b9
+Result = Pass (0)
+Payload = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697
+
+Count = 91
+Nonce = 49004912fdd7269279b1f06a89
+Adata = 00
+CT = 118ec53dd1bfbe52d5b9fe5dfebecf2ee674ec983eada654091a5ae9
+Result = Fail (2 - CT changed)
+
+Count = 92
+Nonce = efeb82c8c68d6600b24dd6d8ee
+Adata = 00
+CT = 6b0fea26e4dfe902b5e876c7ba92afbad8aa52d3c1d00ae578b6bcc4
+Result = Fail (1 - Adata changed)
+
+Count = 93
+Nonce = 7b93d368dc551640b00ba3cbb5
+Adata = 00
+CT = 640c740e2b8af851712a05948ecee055b25b145ccb82ca58ac542b09
+Result = Fail (1 - Adata changed)
+
+Count = 94
+Nonce = 24b7a65391f88bea38fcd54a9a
+Adata = 00
+CT = 05f20b2ae70fcb0ea79aa1845c15b899a799ca60f51e6c296413020a
+Result = Pass (0)
+Payload = 43419715cef9a48dc7280bc035082a6581afd1d82bee9d1a
+
+Count = 95
+Nonce = 6aa3f731522fce7e366ba59945
+Adata = 00
+CT = 9fa576a8a5c72468afa372338cbbc33fef81ad5a873eb38a142d5636
+Result = Fail (2 - CT changed)
+
+Count = 96
+Nonce = a11cf5bed0041ee3cb1fef4b43
+Adata = 00
+CT = 8d26582c74b2b4d960ee9e417c6395daafaebb3aff45d477f3757b6a
+Result = Fail (1 - Adata changed)
+
+Count = 97
+Nonce = 273cc5013785baeb5abc79c8bd
+Adata = 00
+CT = cb62a13e38e17cc6635e409c922956ece38f593189a51b99a7001a16
+Result = Fail (2 - CT changed)
+
+Count = 98
+Nonce = d2d4482ea8e98c1cf309671895
+Adata = 00
+CT = f3e29b792423c7fbe743a3b2f890a2bff29519f3636a6232050e9225
+Result = Fail (2 - CT changed)
+
+Count = 99
+Nonce = a8849b44adb48d271979656930
+Adata = 00
+CT = 136e60d6714d906d1f4c02b7bdbb5f3ccdd2165306912dec850ec9f0
+Result = Fail (1 - Adata changed)
+
+Count = 100
+Nonce = a632ba0d00511122abcd6227ff
+Adata = 00
+CT = 49b6d0b6eeff74af0de70072d9ccdc68a0ee36a5ddbf098b4eb95533
+Result = Fail (1 - Adata changed)
+
+Count = 101
+Nonce = c47af80cd26d047630c1fdf0d1
+Adata = 00
+CT = a2a59041c3f78f6e10c3045118e8a475945e24c85b02abc40f8fb949
+Result = Pass (0)
+Payload = d8306c9c4ea6c69c6e2ad0fc0e49b1e0126b01078d6419ff
+
+Count = 102
+Nonce = 70e132023acae1f88c7a237b68
+Adata = 00
+CT = 19b4ad222795326cb031cfdb07b652dbf64ca5db5ff5d6d569d8ab41
+Result = Pass (0)
+Payload = d0b2bef5ed1a87d9c73d4a459cb05c11799c4f51ad640b1e
+
+Count = 103
+Nonce = 8010d3a2a14f72f5585defc940
+Adata = 00
+CT = 76b66b908657f4df8a329c34ccdde50ae7fc71c4a718b712f00fe764
+Result = Pass (0)
+Payload = 4faba05569bf7ac656780c16995e9122e565fe9984be8a68
+
+Count = 104
+Nonce = a98c2f0e0a7b68942853905191
+Adata = 00
+CT = 20df4662ce6c8c4ce49b14fa791e41ff8598ec93d8a825e879f9eb72
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 24, Nlen = 13, Tlen = 16]
+
+Key = 90929a4b0ac65b350ad1591611fe4829
+
+Count = 105
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = 4bfe4e35784f0a65b545477e5e2f4bae0e1e6fa717eaf2cb6a9a970b9beb2ac1bd4fd62168f8378a
+Result = Pass (0)
+Payload = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697
+
+Count = 106
+Nonce = 49004912fdd7269279b1f06a89
+Adata = 00
+CT = 0c56a503aa2c12e87450d45a7b714db980fd348f327c0065a65666144994bad0c8195bcb4ade1337
+Result = Fail (2 - CT changed)
+
+Count = 107
+Nonce = efeb82c8c68d6600b24dd6d8ee
+Adata = 00
+CT = 5f69d6c21f771eb98dc724f891f530b1c045f49a054de103a85f868739404b64a7cbdd61b577c388
+Result = Fail (1 - Adata changed)
+
+Count = 108
+Nonce = 7b93d368dc551640b00ba3cbb5
+Adata = 00
+CT = d335ba572520c336f711edf27ea738ba5e6b0d772ea443b8b2b164f3c255b699cbf75330d96c3c13
+Result = Fail (1 - Adata changed)
+
+Count = 109
+Nonce = 24b7a65391f88bea38fcd54a9a
+Adata = 00
+CT = 9fa846ef8d198c538f84f856bab8f7f9c3bed90b53acb6a32658e077687315eaf11458bdf6e3c36a
+Result = Pass (0)
+Payload = 43419715cef9a48dc7280bc035082a6581afd1d82bee9d1a
+
+Count = 110
+Nonce = 6aa3f731522fce7e366ba59945
+Adata = 00
+CT = b7095030acdc5fbb8fea2c24717c1c236231f9737bcc78f463db3756abba1feef626a956794d7e56
+Result = Fail (2 - CT changed)
+
+Count = 111
+Nonce = a11cf5bed0041ee3cb1fef4b43
+Adata = 00
+CT = d6911d5831163c8ebad0916af1833051b885aae822f9f6657d6fee1de626bc7c93f2caa27a3ecaa0
+Result = Fail (1 - Adata changed)
+
+Count = 112
+Nonce = 273cc5013785baeb5abc79c8bd
+Adata = 00
+CT = 6b10a098c96c2bbf9aeb5c9adcf91e4812838dff319f8be989e2d235192f33ba0f357492112d98f4
+Result = Fail (2 - CT changed)
+
+Count = 113
+Nonce = d2d4482ea8e98c1cf309671895
+Adata = 00
+CT = aecd11cbac04e1f79b0fd24052c8cedf393dce9df350d24f800b81e834ea5dd2bdc2c688d9505359
+Result = Fail (2 - CT changed)
+
+Count = 114
+Nonce = a8849b44adb48d271979656930
+Adata = 00
+CT = d3a7a25f71b1988482dc852ed713d55abdcc4bb1129ddcae430889cd5c97343cc0dedfbd62e6b6eb
+Result = Fail (1 - Adata changed)
+
+Count = 115
+Nonce = a632ba0d00511122abcd6227ff
+Adata = 00
+CT = 368e1574a433d78d0276ce4a1cacfba834a216693536c00b15acded53c41010554e1c1fe937a7605
+Result = Fail (1 - Adata changed)
+
+Count = 116
+Nonce = c47af80cd26d047630c1fdf0d1
+Adata = 00
+CT = 99e40b3c67aca95dd4462c20cbd6b2741e7033fc4f41a975c9390fbdb9ec416267096ccbf2c148e5
+Result = Pass (0)
+Payload = d8306c9c4ea6c69c6e2ad0fc0e49b1e0126b01078d6419ff
+
+Count = 117
+Nonce = 70e132023acae1f88c7a237b68
+Adata = 00
+CT = de079418c25ba67e5fda009998e3fce61bfdc3b7787cf06655c18ae38b7ee7f00f96cfca4fe9a2ef
+Result = Pass (0)
+Payload = d0b2bef5ed1a87d9c73d4a459cb05c11799c4f51ad640b1e
+
+Count = 118
+Nonce = 8010d3a2a14f72f5585defc940
+Adata = 00
+CT = fbab64d8dd8b6e33c7cc6124cd65f004d7247277fe98d5d3b35357a35ff9e58e18d6d80df9fc335d
+Result = Pass (0)
+Payload = 4faba05569bf7ac656780c16995e9122e565fe9984be8a68
+
+Count = 119
+Nonce = a98c2f0e0a7b68942853905191
+Adata = 00
+CT = 372b9af0655df2d0c830b4949a2d2faa8db251ee922a3bff9aba89639f4033be9ba9f3c101acc1bd
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 0, Nlen = 7, Tlen = 4]
+
+Key = 90929a4b0ac65b350ad1591611fe4829
+
+Count = 120
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 782e4318
+Result = Pass (0)
+Payload = 00
+
+Count = 121
+Nonce = a265480ca88d5f
+Adata = a2248a882ecbf850daf91933a389e78e81623d233dfd47bf8321361a38f138fe
+CT = a04f270a
+Result = Fail (2 - CT changed)
+
+Count = 122
+Nonce = 87ec7423f1ebfc
+Adata = 2bed1ec06c1ca149d9ffbaf048c474ea2de000eb7950f18d6c25acf6ab3f19b5
+CT = 97dfd257
+Result = Fail (1 - Adata changed)
+
+Count = 123
+Nonce = b8b04f90616082
+Adata = 4898731e143fcc677c7cf1a8f2b3c4039fb5e57028e33b05e097d1763cbfe4d8
+CT = 6c202a1c
+Result = Fail (1 - Adata changed)
+
+Count = 124
+Nonce = 8c687b4318813a
+Adata = fcad52a88544325bb31eb5de4a41dbff6a96f69d0993b969a01792ee23953acf
+CT = 1be535a0
+Result = Pass (0)
+Payload = 00
+
+Count = 125
+Nonce = 29b810eed8fc92
+Adata = 40d1d320eb63a25d7a2b3141563a552114275ddda56beb62cc0c0273d5795faa
+CT = 4fb6617d
+Result = Fail (2 - CT changed)
+
+Count = 126
+Nonce = 62452462c53934
+Adata = 1eb8863ea100babc1713654afcf54f21f8bff754223ad70269ace9d034f26a96
+CT = c056bd3e
+Result = Fail (1 - Adata changed)
+
+Count = 127
+Nonce = 4cceba0e7aee97
+Adata = f33e184c967165eb62542999afaca4e3e319840e439b5bb509544fb4b6901445
+CT = 87048576
+Result = Fail (2 - CT changed)
+
+Count = 128
+Nonce = b5151b0601c683
+Adata = 73d27303ec91f28c79b278882034d11eb6a5266746f37edbb77f8409a8738b8c
+CT = ea8c0407
+Result = Fail (2 - CT changed)
+
+Count = 129
+Nonce = 4e5d6d7ac9e71e
+Adata = a01b6e152fe232b6c10b5d89900961c445f4c46833df242c826678b68c869811
+CT = 41c12dc5
+Result = Fail (1 - Adata changed)
+
+Count = 130
+Nonce = dc88e989951a3f
+Adata = fdcacfaff46585406cc45a2da364e67e132a91c98900a8f9d7bfb14ec951fca5
+CT = de84cf5c
+Result = Fail (1 - Adata changed)
+
+Count = 131
+Nonce = a1aeda4b4cb8dd
+Adata = db3022ef4cd68ae22b501599448ffe2dda15cfd2e259315c6f6d03036edea963
+CT = e617e006
+Result = Pass (0)
+Payload = 00
+
+Count = 132
+Nonce = f248e5225e3d9a
+Adata = fdc64ef76a3bfd0a15d0bc8e8bacaf64346796a3e35afcf2ac1ab136f63f7b6e
+CT = b7909395
+Result = Pass (0)
+Payload = 00
+
+Count = 133
+Nonce = e68228f5c65b73
+Adata = 614efdf89ce2a9fcbd38bdc0b4cece54dfd7532880e0b4ce6eb3a4010b7cb1e7
+CT = 8a05d2ea
+Result = Pass (0)
+Payload = 00
+
+Count = 134
+Nonce = ea167cfd1101d9
+Adata = 28130f938c45a1a92b02dbeadbd8df816b6d934e87cca2dfdbfdc49c7cd84041
+CT = 8643ba47
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 0, Nlen = 7, Tlen = 16]
+
+Key = 6a798d7c5e1a72b43e20ad5c7b08567b
+
+Count = 135
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 41b476013f45e4a781f253a6f3b1e530
+Result = Pass (0)
+Payload = 00
+
+Count = 136
+Nonce = a265480ca88d5f
+Adata = a2248a882ecbf850daf91933a389e78e81623d233dfd47bf8321361a38f138fe
+CT = f9f018fcd125822616083fffebc4c8e6
+Result = Fail (2 - CT changed)
+
+Count = 137
+Nonce = 87ec7423f1ebfc
+Adata = 2bed1ec06c1ca149d9ffbaf048c474ea2de000eb7950f18d6c25acf6ab3f19b5
+CT = 534cc67c44c877c9c908071ee1082f4c
+Result = Fail (1 - Adata changed)
+
+Count = 138
+Nonce = b8b04f90616082
+Adata = 4898731e143fcc677c7cf1a8f2b3c4039fb5e57028e33b05e097d1763cbfe4d8
+CT = 201c0ef2ddaa51b645911b5c37d76e95
+Result = Fail (1 - Adata changed)
+
+Count = 139
+Nonce = 8c687b4318813a
+Adata = fcad52a88544325bb31eb5de4a41dbff6a96f69d0993b969a01792ee23953acf
+CT = ec774d9000763bba3a5ac307418827b2
+Result = Pass (0)
+Payload = 00
+
+Count = 140
+Nonce = 29b810eed8fc92
+Adata = 40d1d320eb63a25d7a2b3141563a552114275ddda56beb62cc0c0273d5795faa
+CT = 75798c3fe5202f0e33c9183c837aeaf5
+Result = Fail (2 - CT changed)
+
+Count = 141
+Nonce = 62452462c53934
+Adata = 1eb8863ea100babc1713654afcf54f21f8bff754223ad70269ace9d034f26a96
+CT = 32601de5960c11c925444b5c47d42289
+Result = Fail (1 - Adata changed)
+
+Count = 142
+Nonce = 4cceba0e7aee97
+Adata = f33e184c967165eb62542999afaca4e3e319840e439b5bb509544fb4b6901445
+CT = 4c1cd6a774c8e6f4e261db1f73b0aa20
+Result = Fail (2 - CT changed)
+
+Count = 143
+Nonce = b5151b0601c683
+Adata = 73d27303ec91f28c79b278882034d11eb6a5266746f37edbb77f8409a8738b8c
+CT = 8bd9c00ff23310216bbd24981c1e2cf7
+Result = Fail (2 - CT changed)
+
+Count = 144
+Nonce = 4e5d6d7ac9e71e
+Adata = a01b6e152fe232b6c10b5d89900961c445f4c46833df242c826678b68c869811
+CT = 174efd089409f9932b8e631965e762a6
+Result = Fail (1 - Adata changed)
+
+Count = 145
+Nonce = dc88e989951a3f
+Adata = fdcacfaff46585406cc45a2da364e67e132a91c98900a8f9d7bfb14ec951fca5
+CT = 8de80f620bd41eee6a58925dc8404bfa
+Result = Fail (1 - Adata changed)
+
+Count = 146
+Nonce = a1aeda4b4cb8dd
+Adata = db3022ef4cd68ae22b501599448ffe2dda15cfd2e259315c6f6d03036edea963
+CT = 0b9d79e8e33ec45532af5515a99f05df
+Result = Pass (0)
+Payload = 00
+
+Count = 147
+Nonce = f248e5225e3d9a
+Adata = fdc64ef76a3bfd0a15d0bc8e8bacaf64346796a3e35afcf2ac1ab136f63f7b6e
+CT = 1583e1e5a86001bbcec62292ccfd4d48
+Result = Pass (0)
+Payload = 00
+
+Count = 148
+Nonce = e68228f5c65b73
+Adata = 614efdf89ce2a9fcbd38bdc0b4cece54dfd7532880e0b4ce6eb3a4010b7cb1e7
+CT = b72caac6362e68e445f69f605f21e0a2
+Result = Pass (0)
+Payload = 00
+
+Count = 149
+Nonce = ea167cfd1101d9
+Adata = 28130f938c45a1a92b02dbeadbd8df816b6d934e87cca2dfdbfdc49c7cd84041
+CT = 352769a19ac75b8a116be031b33d6449
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 0, Nlen = 13, Tlen = 4]
+
+Key = 6a798d7c5e1a72b43e20ad5c7b08567b
+
+Count = 150
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = 9f69f24f
+Result = Pass (0)
+Payload = 00
+
+Count = 151
+Nonce = 8739b4bea1a099fe547499cbc6
+Adata = f6107696edb332b2ea059d8860fee26be42e5e12e1a4f79a8d0eafce1b2278a7
+CT = e17afaa4
+Result = Fail (2 - CT changed)
+
+Count = 152
+Nonce = 0f98fdbde2b04387f27b3401dd
+Adata = 02010329660fa716556193eb4870ee84bd934296a5c52d92bba859cc13caaddc
+CT = 07155b7e
+Result = Fail (1 - Adata changed)
+
+Count = 153
+Nonce = 4eed58f381e500902ba5c56864
+Adata = 96056d9ebd7c553c22cc2d9d816b61123750d96c1b08c4b661079424bf3c4946
+CT = d538cf2f
+Result = Fail (1 - Adata changed)
+
+Count = 154
+Nonce = 1e7e51f0fa9a33ed618c26f5e3
+Adata = da9b8ffb0f3c2aee2e386cc9f035ec1eb3e629bd1544c11dc21be4fd8ac9074a
+CT = c283466f
+Result = Pass (0)
+Payload = 00
+
+Count = 155
+Nonce = f012f94f5988c79aa179d7fdfc
+Adata = 612b2ef2683109d99452f95099417641d0c2be3f8ab4cbb2a44e83355ba9303c
+CT = aa8d8098
+Result = Fail (2 - CT changed)
+
+Count = 156
+Nonce = 715acf92cfb69ad56036c49e70
+Adata = 960667b85be07304634124b9324be12a1c11451f1fa9db82c683265b4cf8e5ff
+CT = a44b69b0
+Result = Fail (1 - Adata changed)
+
+Count = 157
+Nonce = 141be3601e38185a9fa1596d2e
+Adata = 606452c62290b43559a588bb03356f846cecb0ccaf0bdaf67a18abd811d4315a
+CT = f395733f
+Result = Fail (2 - CT changed)
+
+Count = 158
+Nonce = fcdda3c5f0e80843b03d8788da
+Adata = 03f22247a55461a293d253c77483859fdac1b87c2480e208a3df767cfbfde512
+CT = 1e9e9237
+Result = Fail (2 - CT changed)
+
+Count = 159
+Nonce = ca660ed3b917c0aca140dcd3fb
+Adata = 254a86f5b20d344ad86fd5523d08f1864737be57731440c29aa6b42574572f51
+CT = e9d2a722
+Result = Fail (1 - Adata changed)
+
+Count = 160
+Nonce = 642ae3466661ce1f51783deece
+Adata = 4432a1cec5976cc13b8fb78341d426c2248f091b597123d263ffafc7f82da5a5
+CT = a90fc438
+Result = Fail (1 - Adata changed)
+
+Count = 161
+Nonce = 7864c717ec93db38b10679be47
+Adata = 679aad1ad1e57029e3362b325572fc71cac53184b0f1546867e665a4a59466c4
+CT = 48f3a1ec
+Result = Pass (0)
+Payload = 00
+
+Count = 162
+Nonce = c3bf9dfe9d6c26f543188fb457
+Adata = e301f69ad3a7e08a3d02462f0aa584449eb0449b0e3c50aa8dfaa4472816c8b0
+CT = 24763def
+Result = Pass (0)
+Payload = 00
+
+Count = 163
+Nonce = 1527657d2fd98f7deca55cc649
+Adata = f4c723433b7cafe3cda9bb4940a21a89a8382d13018b622ccd1ffb9ffd3211af
+CT = 63394bee
+Result = Pass (0)
+Payload = 00
+
+Count = 164
+Nonce = b8432d3d5525a0dadbbaa6b6b8
+Adata = 86ee6e37b4a2d9a0b52ec95643b4e8297e237721e15ce8bf7593a98644f83eba
+CT = d79b1686
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 0, Nlen = 13, Tlen = 16]
+
+Key = f9fdca4ac64fe7f014de0f43039c7571
+
+Count = 165
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = 1859ac36a40a6b28b34266253627797a
+Result = Pass (0)
+Payload = 00
+
+Count = 166
+Nonce = 8739b4bea1a099fe547499cbc6
+Adata = f6107696edb332b2ea059d8860fee26be42e5e12e1a4f79a8d0eafce1b2278a7
+CT = edf8b46eb69ac0044116019dec183072
+Result = Fail (2 - CT changed)
+
+Count = 167
+Nonce = 0f98fdbde2b04387f27b3401dd
+Adata = 02010329660fa716556193eb4870ee84bd934296a5c52d92bba859cc13caaddc
+CT = 66622ac26c7227a0329739612012737c
+Result = Fail (1 - Adata changed)
+
+Count = 168
+Nonce = 4eed58f381e500902ba5c56864
+Adata = 96056d9ebd7c553c22cc2d9d816b61123750d96c1b08c4b661079424bf3c4946
+CT = e4c9e86493ee78b1cbf6e55e94731b63
+Result = Fail (1 - Adata changed)
+
+Count = 169
+Nonce = 1e7e51f0fa9a33ed618c26f5e3
+Adata = da9b8ffb0f3c2aee2e386cc9f035ec1eb3e629bd1544c11dc21be4fd8ac9074a
+CT = 8b5bfe6b5b5552007300bae71172612f
+Result = Pass (0)
+Payload = 00
+
+Count = 170
+Nonce = f012f94f5988c79aa179d7fdfc
+Adata = 612b2ef2683109d99452f95099417641d0c2be3f8ab4cbb2a44e83355ba9303c
+CT = 1848be3cb7665ac68874c617a75d8bd2
+Result = Fail (2 - CT changed)
+
+Count = 171
+Nonce = 715acf92cfb69ad56036c49e70
+Adata = 960667b85be07304634124b9324be12a1c11451f1fa9db82c683265b4cf8e5ff
+CT = 65a23b7b5ee78af9c7d0113447f78ab9
+Result = Fail (1 - Adata changed)
+
+Count = 172
+Nonce = 141be3601e38185a9fa1596d2e
+Adata = 606452c62290b43559a588bb03356f846cecb0ccaf0bdaf67a18abd811d4315a
+CT = 90a420b6d2252392e161dcf4fb953d7e
+Result = Fail (2 - CT changed)
+
+Count = 173
+Nonce = fcdda3c5f0e80843b03d8788da
+Adata = 03f22247a55461a293d253c77483859fdac1b87c2480e208a3df767cfbfde512
+CT = 004cbe11292887e246de7704a4a1a05f
+Result = Fail (2 - CT changed)
+
+Count = 174
+Nonce = ca660ed3b917c0aca140dcd3fb
+Adata = 254a86f5b20d344ad86fd5523d08f1864737be57731440c29aa6b42574572f51
+CT = ad7af41e39ea0c0cd072263e826f3cf0
+Result = Fail (1 - Adata changed)
+
+Count = 175
+Nonce = 642ae3466661ce1f51783deece
+Adata = 4432a1cec5976cc13b8fb78341d426c2248f091b597123d263ffafc7f82da5a5
+CT = 16b1a4fadbadc906a949592d6ef319a3
+Result = Fail (1 - Adata changed)
+
+Count = 176
+Nonce = 7864c717ec93db38b10679be47
+Adata = 679aad1ad1e57029e3362b325572fc71cac53184b0f1546867e665a4a59466c4
+CT = e9cfb1069380434f221db4229a083a76
+Result = Pass (0)
+Payload = 00
+
+Count = 177
+Nonce = c3bf9dfe9d6c26f543188fb457
+Adata = e301f69ad3a7e08a3d02462f0aa584449eb0449b0e3c50aa8dfaa4472816c8b0
+CT = 380cb57fd531bb1dcf22350518bbf8af
+Result = Pass (0)
+Payload = 00
+
+Count = 178
+Nonce = 1527657d2fd98f7deca55cc649
+Adata = f4c723433b7cafe3cda9bb4940a21a89a8382d13018b622ccd1ffb9ffd3211af
+CT = fbf2becc35b5024078bfcfc1f831b669
+Result = Pass (0)
+Payload = 00
+
+Count = 179
+Nonce = b8432d3d5525a0dadbbaa6b6b8
+Adata = 86ee6e37b4a2d9a0b52ec95643b4e8297e237721e15ce8bf7593a98644f83eba
+CT = 080203eb842b3f98a730abbbf98f493e
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 24, Nlen = 7, Tlen = 4]
+
+Key = f9fdca4ac64fe7f014de0f43039c7571
+
+Count = 180
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 6be31860ca271ef448de8f8d8b39346daf4b81d7e92d65b338f125fa
+Result = Pass (0)
+Payload = a265480ca88d5f536db0dc6abc40faf0d05be7a966977768
+
+Count = 181
+Nonce = fdd2d6f503c915
+Adata = 5b92394f21ddc3ad49d9b0881b829a5935cb3a4d23e292a62fb66b5e7ab7020e
+CT = 4cc57a9927a6bc401441870d3193bf89ebd163f5c01501c728a66b69
+Result = Fail (2 - CT changed)
+
+Count = 182
+Nonce = 27d73d58100054
+Adata = f6468542923be79b4b06dfe70920d57d1da73a9c16f9c9a12d810d7de0d12467
+CT = 1f16c6d370fff40c011a243356076b67e905d4672ae2f38fee2de18c
+Result = Fail (1 - Adata changed)
+
+Count = 183
+Nonce = dd16e0ce1250e3
+Adata = bc65cfd65e9863c8b7457d58afa6bdb48a84170d8aa97ba5b397b52ad17a9242
+CT = 46edb001d58a01dce1bcf064cfc9a04accc82c42b33ba16524537a81
+Result = Fail (1 - Adata changed)
+
+Count = 184
+Nonce = ccee19d037cf4a
+Adata = c026696e6425e6c33f45b4145febf1137e7ac26383c9f5aa4cd4e5e8abb19e07
+CT = 9b61335f96fc5b31274cc1fb275f29c1105d68c67b70654f9405edb1
+Result = Pass (0)
+Payload = 0df202431ee7f251a38aaf6aa8cd313782bd293af9114005
+
+Count = 185
+Nonce = 6c8ba94f09cbe6
+Adata = 774ad1a88f8bb063951486d4aec5bf82d5fc535bd0b952f86200c123c37fa496
+CT = 97b5eb2d55847f5d5d9f8c762dace481d8efb19ccfd72265548effe3
+Result = Fail (2 - CT changed)
+
+Count = 186
+Nonce = 1f670302fcdcc8
+Adata = 1a9ff9698cfc96b581d7115c822e4363d7355ec5daed2eae5bf89ee944ac7d9c
+CT = f5cc8198dce8e890587b62572b07413a915bfb55628c901c03459b29
+Result = Fail (1 - Adata changed)
+
+Count = 187
+Nonce = 5d05f658c729a2
+Adata = dd9564c1431ed490b17ef69f6115805e54ef156ef4e10e58f7d57a7e86626352
+CT = 50c0b1f6c5e4c86a0c938ecbc762eeaf99b9fe04c2820a43963b04f3
+Result = Fail (2 - CT changed)
+
+Count = 188
+Nonce = 22a77db9fcbc95
+Adata = 86bf1739c10f63df734ee3e60ac40ff5636c49f68ca4c16ece289609eb413e7a
+CT = 1fdbe91189da01c5098cf1538addd85b1cfef0abd0797c141330f633
+Result = Fail (2 - CT changed)
+
+Count = 189
+Nonce = 491e32b0bbfa4c
+Adata = 75bef075c79d6cfd7fc73aefd67b2d215be0648937477ba606b1fe1be591239e
+CT = 462e7cdf9a6a553bca37d4d93bed4986b715d0349238613e10c1f6d7
+Result = Fail (1 - Adata changed)
+
+Count = 190
+Nonce = bc4b7d3a380be0
+Adata = 353dbb41e2d525a9f4fcd858d0f0aa1b1e86ac0f936d5c09c6b61c343f94e3fc
+CT = 7d142f26aa6c9d55850c5c9f58ab36a66670d47c515bf93cd37e5543
+Result = Fail (1 - Adata changed)
+
+Count = 191
+Nonce = a840e98df72ae9
+Adata = 22c6607732ef1bdc7fcf6197e037cdadd7ee17c008552dd9f04b8564d34fb17c
+CT = f7122cbcec93d53fc7e3fc629ea15d28363cad1c83a23bb3cc5e0c4a
+Result = Pass (0)
+Payload = a2f53385618b41301f4e3ea4c597f411103dac2b37abf5da
+
+Count = 192
+Nonce = 39d93c3cf31a6f
+Adata = 937dfac5cded938438f4e97aabd9beb50dba40f824198260a89729479cfe6869
+CT = e1cad7f946b20c373323218c8a89e56edf3030662e50d459fc12a512
+Result = Pass (0)
+Payload = c1bdef96dc868446be48491b160504546f2a40dd581f9582
+
+Count = 193
+Nonce = 0bbc177019321e
+Adata = f6e02678820f5ccbede6cbded02d6dd58d486166d7b18ee975a688af421fb795
+CT = d4741814466a23e26107d773f103a4c83db9d772dbd5fdc1c2eaf895
+Result = Pass (0)
+Payload = 72a70954d22ad722fc32756afce67b344b2f3c55fe1d9eed
+
+Count = 194
+Nonce = ad048eb2ad7526
+Adata = 0d2739cfdac782b61f484fa1a423c478c414397ec420327963d79112b2d70a7e
+CT = ed35ff66bc7f6d8ec7acf896f994d79f5792cf6d22d6691ff92fa2f7
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 24, Nlen = 7, Tlen = 16]
+
+Key = a7aa635ea51b0bb20a092bd5573e728c
+
+Count = 195
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = b351ab96b2e45515254558d5212673ee6c776d42dbca3b512cf3a20b7fd7c49e6e79bef475c2906f
+Result = Pass (0)
+Payload = a265480ca88d5f536db0dc6abc40faf0d05be7a966977768
+
+Count = 196
+Nonce = fdd2d6f503c915
+Adata = 5b92394f21ddc3ad49d9b0881b829a5935cb3a4d23e292a62fb66b5e7ab7020e
+CT = df1a5285caa41b4bb47f6e5ceceba4e82721828d68427a3081d18ca149d6766bfaccec88f194eb5b
+Result = Fail (2 - CT changed)
+
+Count = 197
+Nonce = 27d73d58100054
+Adata = f6468542923be79b4b06dfe70920d57d1da73a9c16f9c9a12d810d7de0d12467
+CT = 04a29fc109dfc626e8297e0f586d0bfaf31260017d95f62d5eb4f0875dda5ccd9b94026ba49fb34e
+Result = Fail (1 - Adata changed)
+
+Count = 198
+Nonce = dd16e0ce1250e3
+Adata = bc65cfd65e9863c8b7457d58afa6bdb48a84170d8aa97ba5b397b52ad17a9242
+CT = 77e4cd5d319353ecb6b89e2de14bcfee4fbf738b61df14f3920843994def41aed3103995d3392eed
+Result = Fail (1 - Adata changed)
+
+Count = 199
+Nonce = ccee19d037cf4a
+Adata = c026696e6425e6c33f45b4145febf1137e7ac26383c9f5aa4cd4e5e8abb19e07
+CT = e676f5dfde8ad810d9e729d142670eef77f2878369a28797d57603d5c45606c68be5535c671d5432
+Result = Pass (0)
+Payload = 0df202431ee7f251a38aaf6aa8cd313782bd293af9114005
+
+Count = 200
+Nonce = 6c8ba94f09cbe6
+Adata = 774ad1a88f8bb063951486d4aec5bf82d5fc535bd0b952f86200c123c37fa496
+CT = 60c51e5c3fe4197454d64fa14017639bcfd1423b9d74e506a0bfd54fb786208e1e49c6d0e645d9fb
+Result = Fail (2 - CT changed)
+
+Count = 201
+Nonce = 1f670302fcdcc8
+Adata = 1a9ff9698cfc96b581d7115c822e4363d7355ec5daed2eae5bf89ee944ac7d9c
+CT = 64d1160365062eca1027cc7036862b027bdda3a9abdf794daf8a9b7a5c50b0be4596290a4d405e79
+Result = Fail (1 - Adata changed)
+
+Count = 202
+Nonce = 5d05f658c729a2
+Adata = dd9564c1431ed490b17ef69f6115805e54ef156ef4e10e58f7d57a7e86626352
+CT = 968ca115583c645710d2b47fb196cf55f6ef33f2b01400e22ce9c776932ecf7fddd849be58096b88
+Result = Fail (2 - CT changed)
+
+Count = 203
+Nonce = 22a77db9fcbc95
+Adata = 86bf1739c10f63df734ee3e60ac40ff5636c49f68ca4c16ece289609eb413e7a
+CT = 4985821b16ff6d4d3416573e2fba4d53186d912f0b023a99915d0020da92f483a5a7914cba14b1e7
+Result = Fail (2 - CT changed)
+
+Count = 204
+Nonce = 491e32b0bbfa4c
+Adata = 75bef075c79d6cfd7fc73aefd67b2d215be0648937477ba606b1fe1be591239e
+CT = c7345b031ef85bde766226a7603adaa7dcb07a7b2a8be1b571420e036ea48dddd671be622d372c5b
+Result = Fail (1 - Adata changed)
+
+Count = 205
+Nonce = bc4b7d3a380be0
+Adata = 353dbb41e2d525a9f4fcd858d0f0aa1b1e86ac0f936d5c09c6b61c343f94e3fc
+CT = 11460b9acccc13001be236814da6b73f2c8e0467574f151bb619a331f8d67d70c3f3a59b3fab53a5
+Result = Fail (1 - Adata changed)
+
+Count = 206
+Nonce = a840e98df72ae9
+Adata = 22c6607732ef1bdc7fcf6197e037cdadd7ee17c008552dd9f04b8564d34fb17c
+CT = 1bcff940a2d9d48e93bbfd13aed5947237485983e6ae04b8b944bb46306a9b1e783f3e54c92d5f5e
+Result = Pass (0)
+Payload = a2f53385618b41301f4e3ea4c597f411103dac2b37abf5da
+
+Count = 207
+Nonce = 39d93c3cf31a6f
+Adata = 937dfac5cded938438f4e97aabd9beb50dba40f824198260a89729479cfe6869
+CT = 3b6c1570c85f297079be14cd66d335251c7b52e131a636f148608963f3037763843b70c35d7011f8
+Result = Pass (0)
+Payload = c1bdef96dc868446be48491b160504546f2a40dd581f9582
+
+Count = 208
+Nonce = 0bbc177019321e
+Adata = f6e02678820f5ccbede6cbded02d6dd58d486166d7b18ee975a688af421fb795
+CT = b540cd8cbe733e0ca2ba2112ea785596d2c1d707f41608514ba2d0944c68cc36d4125b3ef9071d69
+Result = Pass (0)
+Payload = 72a70954d22ad722fc32756afce67b344b2f3c55fe1d9eed
+
+Count = 209
+Nonce = ad048eb2ad7526
+Adata = 0d2739cfdac782b61f484fa1a423c478c414397ec420327963d79112b2d70a7e
+CT = 3c9c1481f1428acf202b510dca67e5e6b2abc5dd71a954da51387922af7182b7d46a33c703e6e7a8
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 24, Nlen = 13, Tlen = 4]
+
+Key = a7aa635ea51b0bb20a092bd5573e728c
+
+Count = 210
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = 934f893824e880f743d196b22d1f340a52608155087bd28ac25e5329
+Result = Pass (0)
+Payload = 8739b4bea1a099fe547499cbc6d1b13d849b8084c9b6acc5
+
+Count = 211
+Nonce = 0812757ad0cc4d17c4cfe7a642
+Adata = ec6c44a7e94e51a3ca6dee229098391575ec7213c85267fbf7492fdbeee61b10
+CT = f43ba9d834ad85dfab3f1c0c27c3441fe4e411a38a261a6559b3b3ee
+Result = Fail (2 - CT changed)
+
+Count = 212
+Nonce = eff510acc1b85f35029cf7dc00
+Adata = 0923b927b8295c5dfaf67da55e5014293bc8c708fda50af06c1e8aef31cccc86
+CT = c686eac859a7bae3cce97d0b6527a0a7c8c2b24ece35f4370bf6688e
+Result = Fail (1 - Adata changed)
+
+Count = 213
+Nonce = 3d13d09057190366c63c8750e9
+Adata = 77e27aa9a7bf30e130c862a3296a1cd7a10195ed1d940f2c97bfff47c6f06e32
+CT = 2b28355ecf7246ddb08d65c464dcaa90af85f434ff95267280ed869c
+Result = Fail (1 - Adata changed)
+
+Count = 214
+Nonce = e3c03ef7e1d31961ee0b97bd99
+Adata = 8a3676dd640821b58fb0f0329855fd5882c376ea166b958b7aaad223054e5784
+CT = ecde42091baa1f5c17b79746e21c3de5c78984570748021ccd399507
+Result = Pass (0)
+Payload = 92973ce707733a73118c8ce6b5e3fc77a17f448310c0197f
+
+Count = 215
+Nonce = 5d165ddd4e599387af5967cae6
+Adata = e374f875ce829b62c98fbd67bcf128b5647f25fff9a643300eb95559b889baed
+CT = 5c338435ed4f148342604c9aed63e907c100453d719fda2a3da37b66
+Result = Fail (2 - CT changed)
+
+Count = 216
+Nonce = fcec171162a27a96066181fab2
+Adata = cf431cc3671ec468ea86f6cc09842fcf3a84b3ef0fa1c7b20b232145b4469d62
+CT = 30eac1042015eb82729673edd9939bf9995b2575da4d6c4c7e75dded
+Result = Fail (1 - Adata changed)
+
+Count = 217
+Nonce = 2fa8120398d1a946f391367cf6
+Adata = 92558a239c8e13230754f23aec67b153db29fdfc7daf641778185dd2931d89da
+CT = ebd3ce55b40e4bbd8172033948c6c78049161ee8f949eb50722b9c87
+Result = Fail (2 - CT changed)
+
+Count = 218
+Nonce = 88e0ae338bbca9d4299b294354
+Adata = 5db5c388dbadc9f175a5cd5a1472a458d25acd7fb9c951c0cd45edf64da473bb
+CT = 20f79b36ca83baac97600fd8a6dad22c2cd0f9b7e770576048c042e5
+Result = Fail (2 - CT changed)
+
+Count = 219
+Nonce = 4862e36296d6afc9399a95bbb4
+Adata = 36d82ebd0e0f5fe3b12946d041ae5aee16e6d17025406dd776f499bbd8e8b4c8
+CT = 77b76f249f936fb19bd47fe28ad4dbb7725dec365a1cb23a885ba975
+Result = Fail (1 - Adata changed)
+
+Count = 220
+Nonce = 2f360a4715074e942244ab7f9b
+Adata = f0087b0086a081c1071481f033a8be8e940c36763084329bb8461b9102238f4f
+CT = cf6763a23c2eab730845d1eb79bbba9f54ee899fe3d70570aa799e79
+Result = Fail (1 - Adata changed)
+
+Count = 221
+Nonce = 93e08854560edb096e5d654086
+Adata = bdc60dff08bfd5d44320b75c61e456fd4333c9c3d0294d4a48d936dfd5922ce2
+CT = 1f8086a43c1b2dea557952db88e0dbbdb96aafdb345eddae6c0b0104
+Result = Pass (0)
+Payload = 569e4aec88dd51ca519c0a00c922ee33d3559b98a32d7906
+
+Count = 222
+Nonce = e3f37b68ff508cfe295441d9e3
+Adata = b2b6c5782e4f128467c589d2a6cf55ef12877adb771bbb6245c5bba9dcfd6208
+CT = c0c5f92285b114e0a0777e1bc22b810e7cc4f68c28cd5ce047a28dd8
+Result = Pass (0)
+Payload = 02b5511204bd55f7c37973e26f6df5883c0a530f07c7f8c2
+
+Count = 223
+Nonce = ea98ec44f5a86715014783172e
+Adata = e4692b9f06b666c7451b146c8aeb07a6e30c629d28065c3dde5940325b14b810
+CT = 56327f4db9c18f72bbefc3f316d31f9795dd77f493385ab7b7543552
+Result = Pass (0)
+Payload = 4da40b80579c1d9a5309f7efecb7c059a2f914511ca5fc10
+
+Count = 224
+Nonce = 5a16a8902bd70fa06cfe184c57
+Adata = 399d6b0652836457ec4f701f0dc0e5aed73d16585d61cb1bb5b7ee824fc287c8
+CT = 37d5b17995fac8c94302ec9ba20a36d97678e85199b677f8ee39867e
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 24, Nlen = 13, Tlen = 16]
+
+Key = 26511fb51fcfa75cb4b44da75a6e5a0e
+
+Count = 225
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = 50038b5fdd364ee747b70d00bd36840ece4ea19998123375c0a458bfcafa3b2609afe0f825cbf503
+Result = Pass (0)
+Payload = 8739b4bea1a099fe547499cbc6d1b13d849b8084c9b6acc5
+
+Count = 226
+Nonce = 0812757ad0cc4d17c4cfe7a642
+Adata = ec6c44a7e94e51a3ca6dee229098391575ec7213c85267fbf7492fdbeee61b10
+CT = 78ed8ff6b5a1255d0fbd0a719a9c27b059ff5f83d0c4962c390042ba8bb5f6798dab01c5afad7306
+Result = Fail (2 - CT changed)
+
+Count = 227
+Nonce = eff510acc1b85f35029cf7dc00
+Adata = 0923b927b8295c5dfaf67da55e5014293bc8c708fda50af06c1e8aef31cccc86
+CT = 4b91d8e616d3f60452fd3a576bd7c265b7f549523ed4a5d7a3463394cf3c25bef8af8f244d0c0b00
+Result = Fail (1 - Adata changed)
+
+Count = 228
+Nonce = 3d13d09057190366c63c8750e9
+Adata = 77e27aa9a7bf30e130c862a3296a1cd7a10195ed1d940f2c97bfff47c6f06e32
+CT = ab8cf8891ab62924c0c6f49dd253cfa0c3d6260d0ee4d9ba88caf8ae59d9d1131626da0dddf8722d
+Result = Fail (1 - Adata changed)
+
+Count = 229
+Nonce = e3c03ef7e1d31961ee0b97bd99
+Adata = 8a3676dd640821b58fb0f0329855fd5882c376ea166b958b7aaad223054e5784
+CT = c6b7680f321132a8bd00e8e92f785d0b828b100af6392a04d1292373a76970eda77a8194f6276262
+Result = Pass (0)
+Payload = 92973ce707733a73118c8ce6b5e3fc77a17f448310c0197f
+
+Count = 230
+Nonce = 5d165ddd4e599387af5967cae6
+Adata = e374f875ce829b62c98fbd67bcf128b5647f25fff9a643300eb95559b889baed
+CT = aea98867d3d707c43a963c1d7fdcfc953cbd707803b2b5f0a97af19d0b7bf7c7ce398cb0b44d73af
+Result = Fail (2 - CT changed)
+
+Count = 231
+Nonce = fcec171162a27a96066181fab2
+Adata = cf431cc3671ec468ea86f6cc09842fcf3a84b3ef0fa1c7b20b232145b4469d62
+CT = c55e17ba7886eb58126d50bde8c5c211cc1aafd71a3d9e5b343065b4bdd973ee072dbf5160d310f3
+Result = Fail (1 - Adata changed)
+
+Count = 232
+Nonce = 2fa8120398d1a946f391367cf6
+Adata = 92558a239c8e13230754f23aec67b153db29fdfc7daf641778185dd2931d89da
+CT = 791a62d5fb39ff9735ad94507e1afe2647714d5cc56b6ff4233ec600bca1d31f704807494fb0f18d
+Result = Fail (2 - CT changed)
+
+Count = 233
+Nonce = 88e0ae338bbca9d4299b294354
+Adata = 5db5c388dbadc9f175a5cd5a1472a458d25acd7fb9c951c0cd45edf64da473bb
+CT = f98a081998e29500f15ebd8978a95423aed4e8e78e0279d17ec183db0e2a33ebb147d0e2363fbb01
+Result = Fail (2 - CT changed)
+
+Count = 234
+Nonce = 4862e36296d6afc9399a95bbb4
+Adata = 36d82ebd0e0f5fe3b12946d041ae5aee16e6d17025406dd776f499bbd8e8b4c8
+CT = 7779814dc295a23b4100ca94bec0ad4ce2f6be6fb75a0c217e67ea2577ade5836c26a89760e0959b
+Result = Fail (1 - Adata changed)
+
+Count = 235
+Nonce = 2f360a4715074e942244ab7f9b
+Adata = f0087b0086a081c1071481f033a8be8e940c36763084329bb8461b9102238f4f
+CT = 55640eed12c7595a36ab423da8d8241905b6ff1e906db9624978a7865df8369635269411b3aaeb32
+Result = Fail (1 - Adata changed)
+
+Count = 236
+Nonce = 93e08854560edb096e5d654086
+Adata = bdc60dff08bfd5d44320b75c61e456fd4333c9c3d0294d4a48d936dfd5922ce2
+CT = 7fcdce0ba567b9a708d54fdb16125de71dce952f4741684f4f9d302e4f1d2a2aedf2768d7b29163f
+Result = Pass (0)
+Payload = 569e4aec88dd51ca519c0a00c922ee33d3559b98a32d7906
+
+Count = 237
+Nonce = e3f37b68ff508cfe295441d9e3
+Adata = b2b6c5782e4f128467c589d2a6cf55ef12877adb771bbb6245c5bba9dcfd6208
+CT = d42111ba22987eac1ead5cc6cb8548bcda190d118dcd5461a50036af67fadab163e9daa8bd8e9030
+Result = Pass (0)
+Payload = 02b5511204bd55f7c37973e26f6df5883c0a530f07c7f8c2
+
+Count = 238
+Nonce = ea98ec44f5a86715014783172e
+Adata = e4692b9f06b666c7451b146c8aeb07a6e30c629d28065c3dde5940325b14b810
+CT = 1bf0ba0ebb20d8edba59f29a9371750c9c714078f73c335d2f1322ac69b848b001476323aed84c47
+Result = Pass (0)
+Payload = 4da40b80579c1d9a5309f7efecb7c059a2f914511ca5fc10
+
+Count = 239
+Nonce = 5a16a8902bd70fa06cfe184c57
+Adata = 399d6b0652836457ec4f701f0dc0e5aed73d16585d61cb1bb5b7ee824fc287c8
+CT = 9d993b945476ace0b9ca932963ac8835e1bd02e8065da2d816786c4d8cf14c03b031ff723311b3c4
+Result = Fail (2 - CT changed)
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT192.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT192.rsp
new file mode 100644
index 0000000000..e0978a99ac
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT192.rsp
@@ -0,0 +1,1589 @@
+# CAVS 11.0
+# "CCM-DVPT" information
+# AES Keylen: 192
+# Generated on Tue Mar 15 08:09:25 2011
+
+
+[Alen = 0, Plen = 0, Nlen = 7, Tlen = 4]
+
+Key = c98ad7f38b2c7e970c9b965ec87a08208384718f78206c6c
+
+Count = 0
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = 9d4b7f3b
+Result = Pass
+Payload = 00
+
+Count = 1
+Nonce = 3796cf51b87266
+Adata = 00
+CT = 80745de9
+Result = Fail
+
+Count = 2
+Nonce = 89ca5a64050f9f
+Adata = 00
+CT = 2f6fa823
+Result = Fail
+
+Count = 3
+Nonce = ec9d8edff25645
+Adata = 00
+CT = 3cc132c6
+Result = Fail
+
+Count = 4
+Nonce = 05e16f0f42a6f4
+Adata = 00
+CT = c79d5557
+Result = Pass
+Payload = 00
+
+Count = 5
+Nonce = 2e504b694f8df5
+Adata = 00
+CT = 41e0eea0
+Result = Fail
+
+Count = 6
+Nonce = 06d102a9328863
+Adata = 00
+CT = 1f129266
+Result = Fail
+
+Count = 7
+Nonce = c288b810fb5334
+Adata = 00
+CT = 41b0e4e2
+Result = Fail
+
+Count = 8
+Nonce = 08a166d9eb6610
+Adata = 00
+CT = 5082e06a
+Result = Fail
+
+Count = 9
+Nonce = 4a5810b121c91b
+Adata = 00
+CT = 70587cce
+Result = Fail
+
+Count = 10
+Nonce = 44077341139bf9
+Adata = 00
+CT = 6aaa0acd
+Result = Fail
+
+Count = 11
+Nonce = a9df4f37847e1f
+Adata = 00
+CT = 22976e42
+Result = Pass
+Payload = 00
+
+Count = 12
+Nonce = 11df57fcd131e9
+Adata = 00
+CT = f440ea1d
+Result = Pass
+Payload = 00
+
+Count = 13
+Nonce = 890fff56d10dc0
+Adata = 00
+CT = 88903fb9
+Result = Pass
+Payload = 00
+
+Count = 14
+Nonce = 9dc18698731b27
+Adata = 00
+CT = 3ff345c3
+Result = Fail
+
+[Alen = 0, Plen = 0, Nlen = 7, Tlen = 16]
+
+Key = 4bb3c4a4f893ad8c9bdc833c325d62b3d3ad1bccf9282a65
+
+Count = 15
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = 17223038fa99d53681ca1beabe78d1b4
+Result = Pass
+Payload = 00
+
+Count = 16
+Nonce = 3796cf51b87266
+Adata = 00
+CT = d0e1eeef4d2a264536bb1c2c1bde7c35
+Result = Fail
+
+Count = 17
+Nonce = 89ca5a64050f9f
+Adata = 00
+CT = 81d587f8673fd514c23172af7fb7523d
+Result = Fail
+
+Count = 18
+Nonce = ec9d8edff25645
+Adata = 00
+CT = 500142447e535207899ab1499994daea
+Result = Fail
+
+Count = 19
+Nonce = 05e16f0f42a6f4
+Adata = 00
+CT = fdfdbb38bf161785114f9ee2018e892f
+Result = Pass
+Payload = 00
+
+Count = 20
+Nonce = 2e504b694f8df5
+Adata = 00
+CT = 38fe9622eaa2a50152cf57e393dd3063
+Result = Fail
+
+Count = 21
+Nonce = 06d102a9328863
+Adata = 00
+CT = 73af4b87c167572e1400a0ee28209aff
+Result = Fail
+
+Count = 22
+Nonce = c288b810fb5334
+Adata = 00
+CT = ace2248b9f23efa813449c82217e4a4a
+Result = Fail
+
+Count = 23
+Nonce = 08a166d9eb6610
+Adata = 00
+CT = a9bb0e469829d9cf09ad765c5b0b58bf
+Result = Fail
+
+Count = 24
+Nonce = 4a5810b121c91b
+Adata = 00
+CT = a5977f0826926ec0d32541b2bd4e2b1e
+Result = Fail
+
+Count = 25
+Nonce = 44077341139bf9
+Adata = 00
+CT = 6938fb5afec1a84e4abb062e1a943c20
+Result = Fail
+
+Count = 26
+Nonce = a9df4f37847e1f
+Adata = 00
+CT = 7e3bbe0eb13988a93972f2fbcd35659e
+Result = Pass
+Payload = 00
+
+Count = 27
+Nonce = 11df57fcd131e9
+Adata = 00
+CT = 48d7a15cf4f5808eb45d1ad817470554
+Result = Pass
+Payload = 00
+
+Count = 28
+Nonce = 890fff56d10dc0
+Adata = 00
+CT = 97185ce68af1e6ab718c8c4b83ec04cd
+Result = Pass
+Payload = 00
+
+Count = 29
+Nonce = 9dc18698731b27
+Adata = 00
+CT = a81bc8f5a18293ffe19505a3687ce3f3
+Result = Fail
+
+[Alen = 0, Plen = 0, Nlen = 13, Tlen = 4]
+
+Key = 4bb3c4a4f893ad8c9bdc833c325d62b3d3ad1bccf9282a65
+
+Count = 30
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = fe69ed84
+Result = Pass
+Payload = 00
+
+Count = 31
+Nonce = a16a2e741f1cd9717285b6d882
+Adata = 00
+CT = db7ffc82
+Result = Fail
+
+Count = 32
+Nonce = 368f3b8180fd4b851b7b272cb1
+Adata = 00
+CT = 7a677329
+Result = Fail
+
+Count = 33
+Nonce = 7bb2bc00c0cafce65b5299ae64
+Adata = 00
+CT = d903d8f7
+Result = Fail
+
+Count = 34
+Nonce = 935c1ef3d4032ff090f91141f3
+Adata = 00
+CT = 215e0bf2
+Result = Pass
+Payload = 00
+
+Count = 35
+Nonce = 2640b14f10b116411d1b5c1ad1
+Adata = 00
+CT = 0d38100f
+Result = Fail
+
+Count = 36
+Nonce = b229c173a13b2d83af91ec45b0
+Adata = 00
+CT = 9f8ab5f7
+Result = Fail
+
+Count = 37
+Nonce = 37ca0dc2d6efd9efde69f14f03
+Adata = 00
+CT = 7d811d50
+Result = Fail
+
+Count = 38
+Nonce = 6b6238aed86d677ba2b3e2622c
+Adata = 00
+CT = c2e18439
+Result = Fail
+
+Count = 39
+Nonce = d6cb2ac67bb13b8f6d31fad64a
+Adata = 00
+CT = d8b5817b
+Result = Fail
+
+Count = 40
+Nonce = 32a7cd361ef00e65f5778fdfd4
+Adata = 00
+CT = 28cd70ff
+Result = Fail
+
+Count = 41
+Nonce = d0a1508fdefcf5be30a459b813
+Adata = 00
+CT = 790b2624
+Result = Pass
+Payload = 00
+
+Count = 42
+Nonce = 5381a61b449dc6a42aa4c79b95
+Adata = 00
+CT = 9e46632d
+Result = Pass
+Payload = 00
+
+Count = 43
+Nonce = c55430f2da0687ea40313884ab
+Adata = 00
+CT = 39b82901
+Result = Pass
+Payload = 00
+
+Count = 44
+Nonce = ec76d1850acc0979a1f11906fb
+Adata = 00
+CT = 4c0cf71f
+Result = Fail
+
+[Alen = 0, Plen = 0, Nlen = 13, Tlen = 16]
+
+Key = 19ebfde2d5468ba0a3031bde629b11fd4094afcb205393fa
+
+Count = 45
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = 0c66a8e547ed4f8c2c9a9a1eb5d455b9
+Result = Pass
+Payload = 00
+
+Count = 46
+Nonce = a16a2e741f1cd9717285b6d882
+Adata = 00
+CT = 38757b3a61a4dc97ca3ab88bf1240695
+Result = Fail
+
+Count = 47
+Nonce = 368f3b8180fd4b851b7b272cb1
+Adata = 00
+CT = 11875da4445d92391d0fab5f3625497b
+Result = Fail
+
+Count = 48
+Nonce = 7bb2bc00c0cafce65b5299ae64
+Adata = 00
+CT = 64477bcd4316e5c5789e1a678fdef943
+Result = Fail
+
+Count = 49
+Nonce = 935c1ef3d4032ff090f91141f3
+Adata = 00
+CT = 87da5dbc04e39fc468f43675d4e7df33
+Result = Pass
+Payload = 00
+
+Count = 50
+Nonce = 2640b14f10b116411d1b5c1ad1
+Adata = 00
+CT = bf0d53ee529d8cafc5ad7a8f2d85e7a2
+Result = Fail
+
+Count = 51
+Nonce = b229c173a13b2d83af91ec45b0
+Adata = 00
+CT = 676370637ad78c705d43fce066dc909f
+Result = Fail
+
+Count = 52
+Nonce = 37ca0dc2d6efd9efde69f14f03
+Adata = 00
+CT = 289936db0f9f148a3c9e2d28f7d7de51
+Result = Fail
+
+Count = 53
+Nonce = 6b6238aed86d677ba2b3e2622c
+Adata = 00
+CT = 58a283641627669d5514f2af559b6c14
+Result = Fail
+
+Count = 54
+Nonce = d6cb2ac67bb13b8f6d31fad64a
+Adata = 00
+CT = a6b058540ed905d6e3499a13ea1f3d83
+Result = Fail
+
+Count = 55
+Nonce = 32a7cd361ef00e65f5778fdfd4
+Adata = 00
+CT = 7a19b3377384f09915d0e1ae93a9f16c
+Result = Fail
+
+Count = 56
+Nonce = d0a1508fdefcf5be30a459b813
+Adata = 00
+CT = a0d047a1f9940d325e474da54aa13897
+Result = Pass
+Payload = 00
+
+Count = 57
+Nonce = 5381a61b449dc6a42aa4c79b95
+Adata = 00
+CT = 8a4768a2093694b6bcb7083c0bb6331c
+Result = Pass
+Payload = 00
+
+Count = 58
+Nonce = c55430f2da0687ea40313884ab
+Adata = 00
+CT = a7cafd6f68dc1f15a3603da654ce27bc
+Result = Pass
+Payload = 00
+
+Count = 59
+Nonce = ec76d1850acc0979a1f11906fb
+Adata = 00
+CT = c49845f2ea3c9981ad7e9b942f615b8d
+Result = Fail
+
+[Alen = 0, Plen = 24, Nlen = 7, Tlen = 4]
+
+Key = 19ebfde2d5468ba0a3031bde629b11fd4094afcb205393fa
+
+Count = 60
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = 411986d04d6463100bff03f7d0bde7ea2c3488784378138cddc93a54
+Result = Pass
+Payload = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22
+
+Count = 61
+Nonce = 31f8fa25827d48
+Adata = 00
+CT = 32b649ab56162e55d4148a1292d6a225a988eb1308298273b6889036
+Result = Fail
+
+Count = 62
+Nonce = 5340ed7752c9ff
+Adata = 00
+CT = a963c3568ab413b174cd95cc1e3ca61ee181292bebdb28179b4de35f
+Result = Fail
+
+Count = 63
+Nonce = 9cbce402511b89
+Adata = 00
+CT = 0396e6c8db43e5fac205f4c576fd577368adcb688cf3d7e76df9ffc5
+Result = Fail
+
+Count = 64
+Nonce = 123a0beace4e39
+Adata = 00
+CT = b41bfba94edcafc41b4c144269b9126a6d47b19e83b15772b28c8e38
+Result = Pass
+Payload = 9d033e3b66efed1467868f382417c80594877a28bc97f406
+
+Count = 65
+Nonce = 8ea1594a58fe4a
+Adata = 00
+CT = 01e3bb938e16d0284d1d0fee049d80fb97356ae4d84127cf7336a30a
+Result = Fail
+
+Count = 66
+Nonce = 5a7743e59e82da
+Adata = 00
+CT = abd7551c5e84e9bef5fbfad3e24d13f02864410eae9177ad0c40cc72
+Result = Fail
+
+Count = 67
+Nonce = f477f754d7ee76
+Adata = 00
+CT = 3b5ae49e0974f41826152432b46f1a85ab4995afefbbccddfc9fd290
+Result = Fail
+
+Count = 68
+Nonce = 040a257dede70e
+Adata = 00
+CT = 21fb4324de4ba1e2762b3041ce26e43a3d191458a046d489e485910b
+Result = Fail
+
+Count = 69
+Nonce = dd51b8e91683d1
+Adata = 00
+CT = 99ca8f542fd06481e23719214c9892442f393d72899deea08695053f
+Result = Fail
+
+Count = 70
+Nonce = ab3cb86cca6fb2
+Adata = 00
+CT = 5fcc05342cdc27f66b324ae7387205bfb4ab6302bfe0af09050d2054
+Result = Fail
+
+Count = 71
+Nonce = f67b98efd39b55
+Adata = 00
+CT = 0a7fe63046daf8a979935b897088c64acc1b47a5a9b86fdd6def28ab
+Result = Pass
+Payload = f2e944e1ae47ad5873bf391f1b0cc07f6151eb4c50bb45b2
+
+Count = 72
+Nonce = e60e2c002d1c99
+Adata = 00
+CT = daf7d7dfa512ceb1d7d3435634d9a70b3ef6c6dc38f409e068941fce
+Result = Pass
+Payload = 70f48dc1d76e5028da07e29852801375a9edb2214a5ea4c0
+
+Count = 73
+Nonce = 098e053fa08043
+Adata = 00
+CT = cdb417dff6502208775f21e35cdb8e3e1199308d1a94229051a1ec4a
+Result = Pass
+Payload = bd81680e3dc0b35431c92598dcaa26ef09ca0da5e77193de
+
+Count = 74
+Nonce = 4bf48328725514
+Adata = 00
+CT = e75441093c8ccba6eac5913dc246ce96de4784a01051498298eaddaf
+Result = Fail
+
+[Alen = 0, Plen = 24, Nlen = 7, Tlen = 16]
+
+Key = 197afb02ffbd8f699dacae87094d524324576b99844f75e1
+
+Count = 75
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = cba4b4aeb85f0492fd8d905c4a6d8233139833373ef188a8c5a5ebecf7ac8607fe412189e83d9d20
+Result = Pass
+Payload = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22
+
+Count = 76
+Nonce = 31f8fa25827d48
+Adata = 00
+CT = ca62713728b5c9d652504b0ae8fd4fee5d297ee6a8d19cb6e699f15f14d34dcaf9ba8ed4b877c97d
+Result = Fail
+
+Count = 77
+Nonce = 5340ed7752c9ff
+Adata = 00
+CT = 93012c0a5f6f1025b8c4a5d897d3eea0b1c77be8000c9e59f3b8899459788c58794f177cfd838f35
+Result = Fail
+
+Count = 78
+Nonce = 9cbce402511b89
+Adata = 00
+CT = b8eb95f72f643c2c51ad74775cc203d215c86626e903eb013ad22e8fa4d2f9725ce4f212a8844855
+Result = Fail
+
+Count = 79
+Nonce = 123a0beace4e39
+Adata = 00
+CT = 71f17cf21c44267c676657db9e55bee33273787474e77b17b5eab45d7d096577643815e6d467312d
+Result = Pass
+Payload = 9d033e3b66efed1467868f382417c80594877a28bc97f406
+
+Count = 80
+Nonce = 8ea1594a58fe4a
+Adata = 00
+CT = d6737f642260c4ee3b19cb78cc2ef1767213416b82c71e918b1a5ecca7354af824fea617b9b69031
+Result = Fail
+
+Count = 81
+Nonce = 5a7743e59e82da
+Adata = 00
+CT = cbe60d633399daa6ee66418be6d16e292ea47a93c291fce2c54c98f8007ed55a21759f5452559538
+Result = Fail
+
+Count = 82
+Nonce = f477f754d7ee76
+Adata = 00
+CT = 2a78a7beb8df4bf5d35ff0b2853bc51ce127163d2f56e00ea555aa972e1c2e3f439f85663ae25889
+Result = Fail
+
+Count = 83
+Nonce = 040a257dede70e
+Adata = 00
+CT = ee78ddbea9c3aede9f88af0e82464d9d1afe81de16aa18c49aeb326578fa615e86969348d9bbfb7f
+Result = Fail
+
+Count = 84
+Nonce = dd51b8e91683d1
+Adata = 00
+CT = cdf7cb74d978e7ea738e288ed79edfccf10b553c09d1856e2efbff1da769af3b72099cbda3cbf091
+Result = Fail
+
+Count = 85
+Nonce = ab3cb86cca6fb2
+Adata = 00
+CT = 90b990a1ea254592f2c226c969b332fc7bfe5f808729c2d83291a566e6641a965ffdabe097050dc5
+Result = Fail
+
+Count = 86
+Nonce = f67b98efd39b55
+Adata = 00
+CT = 44a6aa954c3508b3c9264c20c272e80c0e95d50ddec2849084b47504dced5b70c302cc93502cc37e
+Result = Pass
+Payload = f2e944e1ae47ad5873bf391f1b0cc07f6151eb4c50bb45b2
+
+Count = 87
+Nonce = e60e2c002d1c99
+Adata = 00
+CT = 9d4ff7a44cdb9b14f586efc3d6be02d069b425c06bec4eed37109739a3676f03adfd740dbaa4940d
+Result = Pass
+Payload = 70f48dc1d76e5028da07e29852801375a9edb2214a5ea4c0
+
+Count = 88
+Nonce = 098e053fa08043
+Adata = 00
+CT = 23da95e102c7921a51b19b5733ea5776ab6c287f6057c00ec4bfacbb2f246b570efd93d98e99be49
+Result = Pass
+Payload = bd81680e3dc0b35431c92598dcaa26ef09ca0da5e77193de
+
+Count = 89
+Nonce = 4bf48328725514
+Adata = 00
+CT = 53d00d5839d0a1e695916151f9450b7311982917edcbd7c66496912db41761a1d2aecfda04fb2cfa
+Result = Fail
+
+[Alen = 0, Plen = 24, Nlen = 13, Tlen = 4]
+
+Key = 197afb02ffbd8f699dacae87094d524324576b99844f75e1
+
+Count = 90
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = 042653c674ef2a90f7fb11d30848e530ae59478f1051633a34fad277
+Result = Pass
+Payload = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697
+
+Count = 91
+Nonce = 49004912fdd7269279b1f06a89
+Adata = 00
+CT = 1902d9769a7ba3d3268e1257395c8c2e5f98eef295dcbfa5a35df775
+Result = Fail
+
+Count = 92
+Nonce = efeb82c8c68d6600b24dd6d8ee
+Adata = 00
+CT = ebacb8e78c0ad9d3ed99f1821b0b0085beac351f88a79ef71faaf310
+Result = Fail
+
+Count = 93
+Nonce = 7b93d368dc551640b00ba3cbb5
+Adata = 00
+CT = efc1d5b6f0a48e4ce3e821d743d34206b28c69485c410fa94d5e6103
+Result = Fail
+
+Count = 94
+Nonce = 24b7a65391f88bea38fcd54a9a
+Adata = 00
+CT = 3c1836e5d0f0473dab7bfd7a95ba69575f7f841970ac6c6769ac966a
+Result = Pass
+Payload = 43419715cef9a48dc7280bc035082a6581afd1d82bee9d1a
+
+Count = 95
+Nonce = 6aa3f731522fce7e366ba59945
+Adata = 00
+CT = 2c583e54d75a02948c7f6dcd12cba32a65e8d605fba7ec10c47e9a8e
+Result = Fail
+
+Count = 96
+Nonce = a11cf5bed0041ee3cb1fef4b43
+Adata = 00
+CT = a8632dee22f34315b05c40135c6dd471c63b09438da834dc1f3f537f
+Result = Fail
+
+Count = 97
+Nonce = 273cc5013785baeb5abc79c8bd
+Adata = 00
+CT = 0f03ea1b2561951d79062e19a85d98293c8c2846936c724c26421940
+Result = Fail
+
+Count = 98
+Nonce = d2d4482ea8e98c1cf309671895
+Adata = 00
+CT = f9764405e54d827ac433fd624506b92e123463a5b01f21ffa3a22ac7
+Result = Fail
+
+Count = 99
+Nonce = a8849b44adb48d271979656930
+Adata = 00
+CT = a326e0cf3f97adff3249944880ddfb8d616cd18a086e046289429246
+Result = Fail
+
+Count = 100
+Nonce = a632ba0d00511122abcd6227ff
+Adata = 00
+CT = f188bc1a72e81b34d75b402e4f8ef3d638d2f56a409eab064c9649b7
+Result = Fail
+
+Count = 101
+Nonce = c47af80cd26d047630c1fdf0d1
+Adata = 00
+CT = 341df3a273e85cf387ab823bdf9c34a1ae2c86940cb4bfcde2e93f29
+Result = Pass
+Payload = d8306c9c4ea6c69c6e2ad0fc0e49b1e0126b01078d6419ff
+
+Count = 102
+Nonce = 70e132023acae1f88c7a237b68
+Adata = 00
+CT = a0e7997fd67ea66b6274d719b84da92433fdf7d512b160da35c7081d
+Result = Pass
+Payload = d0b2bef5ed1a87d9c73d4a459cb05c11799c4f51ad640b1e
+
+Count = 103
+Nonce = 8010d3a2a14f72f5585defc940
+Adata = 00
+CT = dd8fd11e1c0746e7273fdd2e7dfa1ee4fc8ad835ca3141c0f83a9ad7
+Result = Pass
+Payload = 4faba05569bf7ac656780c16995e9122e565fe9984be8a68
+
+Count = 104
+Nonce = a98c2f0e0a7b68942853905191
+Adata = 00
+CT = 39b0d3603f1289b5885ac244953275d28491952e7e57d93c7ff1eb5d
+Result = Fail
+
+[Alen = 0, Plen = 24, Nlen = 13, Tlen = 16]
+
+Key = 90929a4b0ac65b350ad1591611fe48297e03956f6083e451
+
+Count = 105
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = a5b7d8cca2069908d1ed88e6a9fe2c9bede3131dad54671ea7ade30a07d185692ab0ebdf4c78cf7a
+Result = Pass
+Payload = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697
+
+Count = 106
+Nonce = 49004912fdd7269279b1f06a89
+Adata = 00
+CT = 9a98617fb97a0dfe466be692272dcdaec1c5443a3b51312ef042c86363cc05afb98c66e16be8a445
+Result = Fail
+
+Count = 107
+Nonce = efeb82c8c68d6600b24dd6d8ee
+Adata = 00
+CT = d3068ae815c3605d7670058abb9384f4c15b75150eb7910041a8f6ac697430627826bd76b19da027
+Result = Fail
+
+Count = 108
+Nonce = 7b93d368dc551640b00ba3cbb5
+Adata = 00
+CT = 388a289bb85533b667b141a78d0c79acdeb9fbf72886d5ab980581017fefef92c2b50ae20b93c81c
+Result = Fail
+
+Count = 109
+Nonce = 24b7a65391f88bea38fcd54a9a
+Adata = 00
+CT = 71f68480a8801d4966c84807c5ff6139d83ba0a5b902bee3327f5f91763c0a0bec43264c27cd237f
+Result = Pass
+Payload = 43419715cef9a48dc7280bc035082a6581afd1d82bee9d1a
+
+Count = 110
+Nonce = 6aa3f731522fce7e366ba59945
+Adata = 00
+CT = 8627bf1e3edafc69f1328c393dd8e7bd1c182d021e6d3a3652c4b7fd911ca77950ff2d035e47b7ec
+Result = Fail
+
+Count = 111
+Nonce = a11cf5bed0041ee3cb1fef4b43
+Adata = 00
+CT = b10ea86a384432a45f50b3c2e482595b46c81c61ca39bc0f4ffcb29bde8b9a81945d671b0f619045
+Result = Fail
+
+Count = 112
+Nonce = 273cc5013785baeb5abc79c8bd
+Adata = 00
+CT = 3ace8b7e03a0c1fa9e97f46975ab0a4924446e791540e225578cc14aa558e18d5f777ab6e16dcfee
+Result = Fail
+
+Count = 113
+Nonce = d2d4482ea8e98c1cf309671895
+Adata = 00
+CT = 8190abe4c21e320e10825e269190bb10a354691958e2436275433c4ae28757c8544c86f1f74ea6a5
+Result = Fail
+
+Count = 114
+Nonce = a8849b44adb48d271979656930
+Adata = 00
+CT = 1d7e308c34cdca7b7b222f4ebc92afd8055bff542c0b76d3d7752ebe9c5dbf00ee8ad60ac34dd7d0
+Result = Fail
+
+Count = 115
+Nonce = a632ba0d00511122abcd6227ff
+Adata = 00
+CT = 9c2609f7af5b634a16e58f2e9cc7a9ef7812a12d209847000a4432b35d3b884e4169c28d287499ff
+Result = Fail
+
+Count = 116
+Nonce = c47af80cd26d047630c1fdf0d1
+Adata = 00
+CT = 5b0b5e6690d648e1b92c12cfddb431d6d3dfe689d01db8199256ace490c2f0afb93ba32be58fd1de
+Result = Pass
+Payload = d8306c9c4ea6c69c6e2ad0fc0e49b1e0126b01078d6419ff
+
+Count = 117
+Nonce = 70e132023acae1f88c7a237b68
+Adata = 00
+CT = 8722fca71fdf750ec5d62fc6d7ba079aef19210da764067aefd8535dd6b7fa701c9ca8c8b635c30b
+Result = Pass
+Payload = d0b2bef5ed1a87d9c73d4a459cb05c11799c4f51ad640b1e
+
+Count = 118
+Nonce = 8010d3a2a14f72f5585defc940
+Adata = 00
+CT = 91ac457f5e53492301e72d9d495277ed17edb30e8c7a48d21b5d2cd4d5b6d2ef48413245a6b27b67
+Result = Pass
+Payload = 4faba05569bf7ac656780c16995e9122e565fe9984be8a68
+
+Count = 119
+Nonce = a98c2f0e0a7b68942853905191
+Adata = 00
+CT = d2fe5293b7d53ed46ddf02a5618039adbae22845ce72e434fdc83ea4863c3e84a5456f7f853a1ea6
+Result = Fail
+
+[Alen = 32, Plen = 0, Nlen = 7, Tlen = 4]
+
+Key = 90929a4b0ac65b350ad1591611fe48297e03956f6083e451
+
+Count = 120
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 1d089a5f
+Result = Pass
+Payload = 00
+
+Count = 121
+Nonce = a265480ca88d5f
+Adata = a2248a882ecbf850daf91933a389e78e81623d233dfd47bf8321361a38f138fe
+CT = 2f46022a
+Result = Fail
+
+Count = 122
+Nonce = 87ec7423f1ebfc
+Adata = 2bed1ec06c1ca149d9ffbaf048c474ea2de000eb7950f18d6c25acf6ab3f19b5
+CT = 67dc4693
+Result = Fail
+
+Count = 123
+Nonce = b8b04f90616082
+Adata = 4898731e143fcc677c7cf1a8f2b3c4039fb5e57028e33b05e097d1763cbfe4d8
+CT = 7027a849
+Result = Fail
+
+Count = 124
+Nonce = 8c687b4318813a
+Adata = fcad52a88544325bb31eb5de4a41dbff6a96f69d0993b969a01792ee23953acf
+CT = 5c6a4de2
+Result = Pass
+Payload = 00
+
+Count = 125
+Nonce = 29b810eed8fc92
+Adata = 40d1d320eb63a25d7a2b3141563a552114275ddda56beb62cc0c0273d5795faa
+CT = 1d855f5d
+Result = Fail
+
+Count = 126
+Nonce = 62452462c53934
+Adata = 1eb8863ea100babc1713654afcf54f21f8bff754223ad70269ace9d034f26a96
+CT = 1b318980
+Result = Fail
+
+Count = 127
+Nonce = 4cceba0e7aee97
+Adata = f33e184c967165eb62542999afaca4e3e319840e439b5bb509544fb4b6901445
+CT = cf871f91
+Result = Fail
+
+Count = 128
+Nonce = b5151b0601c683
+Adata = 73d27303ec91f28c79b278882034d11eb6a5266746f37edbb77f8409a8738b8c
+CT = 4f0e04bc
+Result = Fail
+
+Count = 129
+Nonce = 4e5d6d7ac9e71e
+Adata = a01b6e152fe232b6c10b5d89900961c445f4c46833df242c826678b68c869811
+CT = fc9013df
+Result = Fail
+
+Count = 130
+Nonce = dc88e989951a3f
+Adata = fdcacfaff46585406cc45a2da364e67e132a91c98900a8f9d7bfb14ec951fca5
+CT = 5134def3
+Result = Fail
+
+Count = 131
+Nonce = a1aeda4b4cb8dd
+Adata = db3022ef4cd68ae22b501599448ffe2dda15cfd2e259315c6f6d03036edea963
+CT = 5814103a
+Result = Pass
+Payload = 00
+
+Count = 132
+Nonce = f248e5225e3d9a
+Adata = fdc64ef76a3bfd0a15d0bc8e8bacaf64346796a3e35afcf2ac1ab136f63f7b6e
+CT = 74c75c4a
+Result = Pass
+Payload = 00
+
+Count = 133
+Nonce = e68228f5c65b73
+Adata = 614efdf89ce2a9fcbd38bdc0b4cece54dfd7532880e0b4ce6eb3a4010b7cb1e7
+CT = 9884898b
+Result = Pass
+Payload = 00
+
+Count = 134
+Nonce = ea167cfd1101d9
+Adata = 28130f938c45a1a92b02dbeadbd8df816b6d934e87cca2dfdbfdc49c7cd84041
+CT = 0b1cbfb1
+Result = Fail
+
+[Alen = 32, Plen = 0, Nlen = 7, Tlen = 16]
+
+Key = 6a798d7c5e1a72b43e20ad5c7b08567b12ab744b61c070e2
+
+Count = 135
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 5280a2137fee3deefcfe9b63a1199fb3
+Result = Pass
+Payload = 00
+
+Count = 136
+Nonce = a265480ca88d5f
+Adata = a2248a882ecbf850daf91933a389e78e81623d233dfd47bf8321361a38f138fe
+CT = d40a7318c5f2d82f838c0beeefe0d598
+Result = Fail
+
+Count = 137
+Nonce = 87ec7423f1ebfc
+Adata = 2bed1ec06c1ca149d9ffbaf048c474ea2de000eb7950f18d6c25acf6ab3f19b5
+CT = 7551978bc9592bf9e294b4984c5862bb
+Result = Fail
+
+Count = 138
+Nonce = b8b04f90616082
+Adata = 4898731e143fcc677c7cf1a8f2b3c4039fb5e57028e33b05e097d1763cbfe4d8
+CT = 859cf444f89225b32a55a1645bd24979
+Result = Fail
+
+Count = 139
+Nonce = 8c687b4318813a
+Adata = fcad52a88544325bb31eb5de4a41dbff6a96f69d0993b969a01792ee23953acf
+CT = 29e967a0245607c36cf3eaf00fdae566
+Result = Pass
+Payload = 00
+
+Count = 140
+Nonce = 29b810eed8fc92
+Adata = 40d1d320eb63a25d7a2b3141563a552114275ddda56beb62cc0c0273d5795faa
+CT = 9daa0e1c4df5f2bf507b1a57a1135b86
+Result = Fail
+
+Count = 141
+Nonce = 62452462c53934
+Adata = 1eb8863ea100babc1713654afcf54f21f8bff754223ad70269ace9d034f26a96
+CT = 18caec79720a5d67d7457e9b7c7a153c
+Result = Fail
+
+Count = 142
+Nonce = 4cceba0e7aee97
+Adata = f33e184c967165eb62542999afaca4e3e319840e439b5bb509544fb4b6901445
+CT = 5f2c455546c56f514a0f69f05345c2c4
+Result = Fail
+
+Count = 143
+Nonce = b5151b0601c683
+Adata = 73d27303ec91f28c79b278882034d11eb6a5266746f37edbb77f8409a8738b8c
+CT = b7e4846ff30b7c3673a962a2701c0387
+Result = Fail
+
+Count = 144
+Nonce = 4e5d6d7ac9e71e
+Adata = a01b6e152fe232b6c10b5d89900961c445f4c46833df242c826678b68c869811
+CT = 7b5fa0d42a616ab05ac2c58c904ce92f
+Result = Fail
+
+Count = 145
+Nonce = dc88e989951a3f
+Adata = fdcacfaff46585406cc45a2da364e67e132a91c98900a8f9d7bfb14ec951fca5
+CT = c8c67f558b5844b149dd47824c8cb9d8
+Result = Fail
+
+Count = 146
+Nonce = a1aeda4b4cb8dd
+Adata = db3022ef4cd68ae22b501599448ffe2dda15cfd2e259315c6f6d03036edea963
+CT = 70a09aaf22ac316124a169f6b0a83ffe
+Result = Pass
+Payload = 00
+
+Count = 147
+Nonce = f248e5225e3d9a
+Adata = fdc64ef76a3bfd0a15d0bc8e8bacaf64346796a3e35afcf2ac1ab136f63f7b6e
+CT = 5bc85ed5521a91b9eb42b437950f0e06
+Result = Pass
+Payload = 00
+
+Count = 148
+Nonce = e68228f5c65b73
+Adata = 614efdf89ce2a9fcbd38bdc0b4cece54dfd7532880e0b4ce6eb3a4010b7cb1e7
+CT = 989ec0e7b192ea010dd61d3fb64e8de0
+Result = Pass
+Payload = 00
+
+Count = 149
+Nonce = ea167cfd1101d9
+Adata = 28130f938c45a1a92b02dbeadbd8df816b6d934e87cca2dfdbfdc49c7cd84041
+CT = 15c2dbe7fa307654d8ca7c0f8d6d2f14
+Result = Fail
+
+[Alen = 32, Plen = 0, Nlen = 13, Tlen = 4]
+
+Key = 6a798d7c5e1a72b43e20ad5c7b08567b12ab744b61c070e2
+
+Count = 150
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = 5e0eaebd
+Result = Pass
+Payload = 00
+
+Count = 151
+Nonce = 8739b4bea1a099fe547499cbc6
+Adata = f6107696edb332b2ea059d8860fee26be42e5e12e1a4f79a8d0eafce1b2278a7
+CT = 71b7fc33
+Result = Fail
+
+Count = 152
+Nonce = 0f98fdbde2b04387f27b3401dd
+Adata = 02010329660fa716556193eb4870ee84bd934296a5c52d92bba859cc13caaddc
+CT = 93227bd4
+Result = Fail
+
+Count = 153
+Nonce = 4eed58f381e500902ba5c56864
+Adata = 96056d9ebd7c553c22cc2d9d816b61123750d96c1b08c4b661079424bf3c4946
+CT = ced654e2
+Result = Fail
+
+Count = 154
+Nonce = 1e7e51f0fa9a33ed618c26f5e3
+Adata = da9b8ffb0f3c2aee2e386cc9f035ec1eb3e629bd1544c11dc21be4fd8ac9074a
+CT = bf7a8e0c
+Result = Pass
+Payload = 00
+
+Count = 155
+Nonce = f012f94f5988c79aa179d7fdfc
+Adata = 612b2ef2683109d99452f95099417641d0c2be3f8ab4cbb2a44e83355ba9303c
+CT = 840caa3e
+Result = Fail
+
+Count = 156
+Nonce = 715acf92cfb69ad56036c49e70
+Adata = 960667b85be07304634124b9324be12a1c11451f1fa9db82c683265b4cf8e5ff
+CT = 1e22fc41
+Result = Fail
+
+Count = 157
+Nonce = 141be3601e38185a9fa1596d2e
+Adata = 606452c62290b43559a588bb03356f846cecb0ccaf0bdaf67a18abd811d4315a
+CT = 968ccbbf
+Result = Fail
+
+Count = 158
+Nonce = fcdda3c5f0e80843b03d8788da
+Adata = 03f22247a55461a293d253c77483859fdac1b87c2480e208a3df767cfbfde512
+CT = 0a31cc96
+Result = Fail
+
+Count = 159
+Nonce = ca660ed3b917c0aca140dcd3fb
+Adata = 254a86f5b20d344ad86fd5523d08f1864737be57731440c29aa6b42574572f51
+CT = a456c3da
+Result = Fail
+
+Count = 160
+Nonce = 642ae3466661ce1f51783deece
+Adata = 4432a1cec5976cc13b8fb78341d426c2248f091b597123d263ffafc7f82da5a5
+CT = 29746eea
+Result = Fail
+
+Count = 161
+Nonce = 7864c717ec93db38b10679be47
+Adata = 679aad1ad1e57029e3362b325572fc71cac53184b0f1546867e665a4a59466c4
+CT = df7f63ca
+Result = Pass
+Payload = 00
+
+Count = 162
+Nonce = c3bf9dfe9d6c26f543188fb457
+Adata = e301f69ad3a7e08a3d02462f0aa584449eb0449b0e3c50aa8dfaa4472816c8b0
+CT = bf0b1445
+Result = Pass
+Payload = 00
+
+Count = 163
+Nonce = 1527657d2fd98f7deca55cc649
+Adata = f4c723433b7cafe3cda9bb4940a21a89a8382d13018b622ccd1ffb9ffd3211af
+CT = ae8533f5
+Result = Pass
+Payload = 00
+
+Count = 164
+Nonce = b8432d3d5525a0dadbbaa6b6b8
+Adata = 86ee6e37b4a2d9a0b52ec95643b4e8297e237721e15ce8bf7593a98644f83eba
+CT = 9426cf89
+Result = Fail
+
+[Alen = 32, Plen = 0, Nlen = 13, Tlen = 16]
+
+Key = f9fdca4ac64fe7f014de0f43039c757194d544ce5d15eed4
+
+Count = 165
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = d07ccf9fdc3d33aa94cda3d230da707c
+Result = Pass
+Payload = 00
+
+Count = 166
+Nonce = 8739b4bea1a099fe547499cbc6
+Adata = f6107696edb332b2ea059d8860fee26be42e5e12e1a4f79a8d0eafce1b2278a7
+CT = 65fe32b649dc328c9f531584897e85b3
+Result = Fail
+
+Count = 167
+Nonce = 0f98fdbde2b04387f27b3401dd
+Adata = 02010329660fa716556193eb4870ee84bd934296a5c52d92bba859cc13caaddc
+CT = ec31fb6b41c2dae87cf395fc1fe3a080
+Result = Fail
+
+Count = 168
+Nonce = 4eed58f381e500902ba5c56864
+Adata = 96056d9ebd7c553c22cc2d9d816b61123750d96c1b08c4b661079424bf3c4946
+CT = 33c2f2312dd5bfcadbb05f8d0a33fd4a
+Result = Fail
+
+Count = 169
+Nonce = 1e7e51f0fa9a33ed618c26f5e3
+Adata = da9b8ffb0f3c2aee2e386cc9f035ec1eb3e629bd1544c11dc21be4fd8ac9074a
+CT = a9e81afd1030d195c679e2c837aeb736
+Result = Pass
+Payload = 00
+
+Count = 170
+Nonce = f012f94f5988c79aa179d7fdfc
+Adata = 612b2ef2683109d99452f95099417641d0c2be3f8ab4cbb2a44e83355ba9303c
+CT = 1db000f0e7d3a03718293fc118678427
+Result = Fail
+
+Count = 171
+Nonce = 715acf92cfb69ad56036c49e70
+Adata = 960667b85be07304634124b9324be12a1c11451f1fa9db82c683265b4cf8e5ff
+CT = ea37900f049db8fc5cbf46edb5fcac2c
+Result = Fail
+
+Count = 172
+Nonce = 141be3601e38185a9fa1596d2e
+Adata = 606452c62290b43559a588bb03356f846cecb0ccaf0bdaf67a18abd811d4315a
+CT = d1097ebd7ad0a41f61ba32a44dc15305
+Result = Fail
+
+Count = 173
+Nonce = fcdda3c5f0e80843b03d8788da
+Adata = 03f22247a55461a293d253c77483859fdac1b87c2480e208a3df767cfbfde512
+CT = 0979729272d8b42f2e3dc0eb181a1217
+Result = Fail
+
+Count = 174
+Nonce = ca660ed3b917c0aca140dcd3fb
+Adata = 254a86f5b20d344ad86fd5523d08f1864737be57731440c29aa6b42574572f51
+CT = 4457200916a20116b096225606f1a9e2
+Result = Fail
+
+Count = 175
+Nonce = 642ae3466661ce1f51783deece
+Adata = 4432a1cec5976cc13b8fb78341d426c2248f091b597123d263ffafc7f82da5a5
+CT = cc6b51f39a3dcfb54abbb89f4df21114
+Result = Fail
+
+Count = 176
+Nonce = 7864c717ec93db38b10679be47
+Adata = 679aad1ad1e57029e3362b325572fc71cac53184b0f1546867e665a4a59466c4
+CT = aac09cef9697927331251f028d24c31f
+Result = Pass
+Payload = 00
+
+Count = 177
+Nonce = c3bf9dfe9d6c26f543188fb457
+Adata = e301f69ad3a7e08a3d02462f0aa584449eb0449b0e3c50aa8dfaa4472816c8b0
+CT = 56c00070eae0db329894a045d866bbaf
+Result = Pass
+Payload = 00
+
+Count = 178
+Nonce = 1527657d2fd98f7deca55cc649
+Adata = f4c723433b7cafe3cda9bb4940a21a89a8382d13018b622ccd1ffb9ffd3211af
+CT = 090016bb96aeaabbf66fd34fc97591a4
+Result = Pass
+Payload = 00
+
+Count = 179
+Nonce = b8432d3d5525a0dadbbaa6b6b8
+Adata = 86ee6e37b4a2d9a0b52ec95643b4e8297e237721e15ce8bf7593a98644f83eba
+CT = 264407dfe796bf7f6eb1f26c1f8504ef
+Result = Fail
+
+[Alen = 32, Plen = 24, Nlen = 7, Tlen = 4]
+
+Key = f9fdca4ac64fe7f014de0f43039c757194d544ce5d15eed4
+
+Count = 180
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 9f6ca4af9b159148c889a6584d1183ea26e2614874b0504575dea8d1
+Result = Pass
+Payload = a265480ca88d5f536db0dc6abc40faf0d05be7a966977768
+
+Count = 181
+Nonce = fdd2d6f503c915
+Adata = 5b92394f21ddc3ad49d9b0881b829a5935cb3a4d23e292a62fb66b5e7ab7020e
+CT = 84d8212e9cfc2121252baa3b065b1edcf50497b9594db1ebd7965825
+Result = Fail
+
+Count = 182
+Nonce = 27d73d58100054
+Adata = f6468542923be79b4b06dfe70920d57d1da73a9c16f9c9a12d810d7de0d12467
+CT = 5f60a8f867a33b2077ecc69863b295c3c6aeae7d7cade7f8f7f796fe
+Result = Fail
+
+Count = 183
+Nonce = dd16e0ce1250e3
+Adata = bc65cfd65e9863c8b7457d58afa6bdb48a84170d8aa97ba5b397b52ad17a9242
+CT = 1353b3fa1bb1d57ffb139017885c02e26c90231a24b5a615b8f1f2ae
+Result = Fail
+
+Count = 184
+Nonce = ccee19d037cf4a
+Adata = c026696e6425e6c33f45b4145febf1137e7ac26383c9f5aa4cd4e5e8abb19e07
+CT = c3116d9040e1ed4f7c9464d270fb302bd3f1561c25c5b95b8b4b53f6
+Result = Pass
+Payload = 0df202431ee7f251a38aaf6aa8cd313782bd293af9114005
+
+Count = 185
+Nonce = 6c8ba94f09cbe6
+Adata = 774ad1a88f8bb063951486d4aec5bf82d5fc535bd0b952f86200c123c37fa496
+CT = 0ca17e8f89bea67db48a8f132ef6c6df7a292914d401299af6bf3800
+Result = Fail
+
+Count = 186
+Nonce = 1f670302fcdcc8
+Adata = 1a9ff9698cfc96b581d7115c822e4363d7355ec5daed2eae5bf89ee944ac7d9c
+CT = 0ce543569e8187f3cec70399ff922e4903cb1d12f990f05613244cf6
+Result = Fail
+
+Count = 187
+Nonce = 5d05f658c729a2
+Adata = dd9564c1431ed490b17ef69f6115805e54ef156ef4e10e58f7d57a7e86626352
+CT = 3acdbc163a350f312791b152a41e57627b1cc8bf3e41c8aea5876de8
+Result = Fail
+
+Count = 188
+Nonce = 22a77db9fcbc95
+Adata = 86bf1739c10f63df734ee3e60ac40ff5636c49f68ca4c16ece289609eb413e7a
+CT = 604518e436edf7a0561d5e284f3915839a6d28cb06ef792a1970ed17
+Result = Fail
+
+Count = 189
+Nonce = 491e32b0bbfa4c
+Adata = 75bef075c79d6cfd7fc73aefd67b2d215be0648937477ba606b1fe1be591239e
+CT = fc79b520d67da891e63654d7927db6c8012c96985a0059d5f68d8da4
+Result = Fail
+
+Count = 190
+Nonce = bc4b7d3a380be0
+Adata = 353dbb41e2d525a9f4fcd858d0f0aa1b1e86ac0f936d5c09c6b61c343f94e3fc
+CT = d86bb51a98770098d0feb39170bd979199a8f741041df13790ee4c14
+Result = Fail
+
+Count = 191
+Nonce = a840e98df72ae9
+Adata = 22c6607732ef1bdc7fcf6197e037cdadd7ee17c008552dd9f04b8564d34fb17c
+CT = 51b6b928bdd1cc0bd0a0aed2cda302472d618ffaa60e179029c87855
+Result = Pass
+Payload = a2f53385618b41301f4e3ea4c597f411103dac2b37abf5da
+
+Count = 192
+Nonce = 39d93c3cf31a6f
+Adata = 937dfac5cded938438f4e97aabd9beb50dba40f824198260a89729479cfe6869
+CT = d0abab9b8e9d6c11bb9c15bea8a486704bed32c57297055b4de8ed8d
+Result = Pass
+Payload = c1bdef96dc868446be48491b160504546f2a40dd581f9582
+
+Count = 193
+Nonce = 0bbc177019321e
+Adata = f6e02678820f5ccbede6cbded02d6dd58d486166d7b18ee975a688af421fb795
+CT = 92fd519a966c0fbdd7087ff5a1bd946cd663502db378383531d69947
+Result = Pass
+Payload = 72a70954d22ad722fc32756afce67b344b2f3c55fe1d9eed
+
+Count = 194
+Nonce = ad048eb2ad7526
+Adata = 0d2739cfdac782b61f484fa1a423c478c414397ec420327963d79112b2d70a7e
+CT = 7f239b1916830161f3b52b7ab13542a5a0a97a17f30ca5fa30768d4d
+Result = Fail
+
+[Alen = 32, Plen = 24, Nlen = 7, Tlen = 16]
+
+Key = a7aa635ea51b0bb20a092bd5573e728ccd4b3e8cdd2ab33d
+
+Count = 195
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 6aab64c4787599d8f213446beadb16e08dba60e97f56dbd14d1d980d6fe0fb44b421992662b97975
+Result = Pass
+Payload = a265480ca88d5f536db0dc6abc40faf0d05be7a966977768
+
+Count = 196
+Nonce = fdd2d6f503c915
+Adata = 5b92394f21ddc3ad49d9b0881b829a5935cb3a4d23e292a62fb66b5e7ab7020e
+CT = 4980b2ee49b1aaf393175f5ab9bae95ec7904557dfa206603c51d36c826f01384100886198a7f6a3
+Result = Fail
+
+Count = 197
+Nonce = 27d73d58100054
+Adata = f6468542923be79b4b06dfe70920d57d1da73a9c16f9c9a12d810d7de0d12467
+CT = 86a02bdd6ae733eee26f8eab898b336105978b5bbd6df781758a111aae4f735b7dd4d9802f2a8406
+Result = Fail
+
+Count = 198
+Nonce = dd16e0ce1250e3
+Adata = bc65cfd65e9863c8b7457d58afa6bdb48a84170d8aa97ba5b397b52ad17a9242
+CT = 59cfab8956813c48e09332a2bb8a30dbcdf5afb2529532ab8cef14ebc2951069739d5d657d82addb
+Result = Fail
+
+Count = 199
+Nonce = ccee19d037cf4a
+Adata = c026696e6425e6c33f45b4145febf1137e7ac26383c9f5aa4cd4e5e8abb19e07
+CT = 67d989ea935b9ce190e3a7f3b645305e1e308a7fe617f80f170a2b9c309de6c2326115a76efbdf98
+Result = Pass
+Payload = 0df202431ee7f251a38aaf6aa8cd313782bd293af9114005
+
+Count = 200
+Nonce = 6c8ba94f09cbe6
+Adata = 774ad1a88f8bb063951486d4aec5bf82d5fc535bd0b952f86200c123c37fa496
+CT = 2522a5e4d157193ef2c264cfe877db8ac75b3cc5aab08a814bcd14af0205af716f2b864f0c397f65
+Result = Fail
+
+Count = 201
+Nonce = 1f670302fcdcc8
+Adata = 1a9ff9698cfc96b581d7115c822e4363d7355ec5daed2eae5bf89ee944ac7d9c
+CT = 4536422bbad220079ee09e700e103efdaac832d016a20813762d5d8adafe75a191310a2618930c48
+Result = Fail
+
+Count = 202
+Nonce = 5d05f658c729a2
+Adata = dd9564c1431ed490b17ef69f6115805e54ef156ef4e10e58f7d57a7e86626352
+CT = d6711a78adf54f4effe647d531c4618cf32e3037eb700580206f80080dfa3e66e6371c0cde6cd205
+Result = Fail
+
+Count = 203
+Nonce = 22a77db9fcbc95
+Adata = 86bf1739c10f63df734ee3e60ac40ff5636c49f68ca4c16ece289609eb413e7a
+CT = e44034a397778e1c6babab27f5a50fa4aac0e83d6b3eb25db1b5b2b35c8a8125efccd1f4102f3e82
+Result = Fail
+
+Count = 204
+Nonce = 491e32b0bbfa4c
+Adata = 75bef075c79d6cfd7fc73aefd67b2d215be0648937477ba606b1fe1be591239e
+CT = b8e31c5910623e405f2ebf65821963e5b8814043612395feca36f53b01943f03cb8b69b5af53e505
+Result = Fail
+
+Count = 205
+Nonce = bc4b7d3a380be0
+Adata = 353dbb41e2d525a9f4fcd858d0f0aa1b1e86ac0f936d5c09c6b61c343f94e3fc
+CT = 4000faf8558f2f4e01e45e90796cd236e5211d1704270f31c3bfc6851049d32105fd16bd45b29f29
+Result = Fail
+
+Count = 206
+Nonce = a840e98df72ae9
+Adata = 22c6607732ef1bdc7fcf6197e037cdadd7ee17c008552dd9f04b8564d34fb17c
+CT = 53bb608f6236798839af35888cb0fa4797b599271084cc13847b022733ca5a5e3c4d472332484b7f
+Result = Pass
+Payload = a2f53385618b41301f4e3ea4c597f411103dac2b37abf5da
+
+Count = 207
+Nonce = 39d93c3cf31a6f
+Adata = 937dfac5cded938438f4e97aabd9beb50dba40f824198260a89729479cfe6869
+CT = be54551d1d2f1b3eb60ffe3b165524ff90ca09fb252bf21c1c79edbf38c50e0f240a2d70f65aa79f
+Result = Pass
+Payload = c1bdef96dc868446be48491b160504546f2a40dd581f9582
+
+Count = 208
+Nonce = 0bbc177019321e
+Adata = f6e02678820f5ccbede6cbded02d6dd58d486166d7b18ee975a688af421fb795
+CT = f07c1072d8f8e077dfbb3ad86dd92d32b41f29e647dcd7e3a82cd3ebaf6c2d3e21749bdf570ad28d
+Result = Pass
+Payload = 72a70954d22ad722fc32756afce67b344b2f3c55fe1d9eed
+
+Count = 209
+Nonce = ad048eb2ad7526
+Adata = 0d2739cfdac782b61f484fa1a423c478c414397ec420327963d79112b2d70a7e
+CT = 7f7cf7f4d0645934cb0a5e67b4227a909aa55dba09b2c39cef93a8759845326683a0d9c22151f486
+Result = Fail
+
+[Alen = 32, Plen = 24, Nlen = 13, Tlen = 4]
+
+Key = a7aa635ea51b0bb20a092bd5573e728ccd4b3e8cdd2ab33d
+
+Count = 210
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = 16e543d0e20615ff0df15acd9927ddfe40668a54bb854cccc25e9fce
+Result = Pass
+Payload = 8739b4bea1a099fe547499cbc6d1b13d849b8084c9b6acc5
+
+Count = 211
+Nonce = 0812757ad0cc4d17c4cfe7a642
+Adata = ec6c44a7e94e51a3ca6dee229098391575ec7213c85267fbf7492fdbeee61b10
+CT = df35b109caf690656ae278bbd8f8bba687a2ce11b105dae98ecedb3e
+Result = Fail
+
+Count = 212
+Nonce = eff510acc1b85f35029cf7dc00
+Adata = 0923b927b8295c5dfaf67da55e5014293bc8c708fda50af06c1e8aef31cccc86
+CT = 7075da2291e2cb527eb926ed08d8020c5f8f0f2d4a6a4745728da544
+Result = Fail
+
+Count = 213
+Nonce = 3d13d09057190366c63c8750e9
+Adata = 77e27aa9a7bf30e130c862a3296a1cd7a10195ed1d940f2c97bfff47c6f06e32
+CT = 18a77a66457b53286b1aea0845304cac8e66a02d5c642e4c02a9b9bc
+Result = Fail
+
+Count = 214
+Nonce = e3c03ef7e1d31961ee0b97bd99
+Adata = 8a3676dd640821b58fb0f0329855fd5882c376ea166b958b7aaad223054e5784
+CT = 24e1d3820101412d8f4d57118cab8f7e489d5cac78802dd5ccf8ecf0
+Result = Pass
+Payload = 92973ce707733a73118c8ce6b5e3fc77a17f448310c0197f
+
+Count = 215
+Nonce = 5d165ddd4e599387af5967cae6
+Adata = e374f875ce829b62c98fbd67bcf128b5647f25fff9a643300eb95559b889baed
+CT = b5929bc9648e24a553c5cd953ecb9d67ee508d2d4ac7b46e661181d5
+Result = Fail
+
+Count = 216
+Nonce = fcec171162a27a96066181fab2
+Adata = cf431cc3671ec468ea86f6cc09842fcf3a84b3ef0fa1c7b20b232145b4469d62
+CT = 54aa018dc7fdf8a54809e1393d18031bab4aa5ca35c201907d74517d
+Result = Fail
+
+Count = 217
+Nonce = 2fa8120398d1a946f391367cf6
+Adata = 92558a239c8e13230754f23aec67b153db29fdfc7daf641778185dd2931d89da
+CT = 69bcc300a459862b3cd284c15dd4af53dc7e95f3067bb8254a8edd83
+Result = Fail
+
+Count = 218
+Nonce = 88e0ae338bbca9d4299b294354
+Adata = 5db5c388dbadc9f175a5cd5a1472a458d25acd7fb9c951c0cd45edf64da473bb
+CT = 5c2d2df0d8aade3e5ae0f8d8b4b4d7c565817a31b2865dc270ad39a6
+Result = Fail
+
+Count = 219
+Nonce = 4862e36296d6afc9399a95bbb4
+Adata = 36d82ebd0e0f5fe3b12946d041ae5aee16e6d17025406dd776f499bbd8e8b4c8
+CT = df1b3f98b6b0060191e7eb817f5908ddc0bc6f83860349e8ae423997
+Result = Fail
+
+Count = 220
+Nonce = 2f360a4715074e942244ab7f9b
+Adata = f0087b0086a081c1071481f033a8be8e940c36763084329bb8461b9102238f4f
+CT = 16e59dd38395c7be7f580371edabb1e9bf21270de270aa283309108e
+Result = Fail
+
+Count = 221
+Nonce = 93e08854560edb096e5d654086
+Adata = bdc60dff08bfd5d44320b75c61e456fd4333c9c3d0294d4a48d936dfd5922ce2
+CT = 0ef8981dd37c055a3c3e14786fc662b2a11065964911d35ebcc87096
+Result = Pass
+Payload = 569e4aec88dd51ca519c0a00c922ee33d3559b98a32d7906
+
+Count = 222
+Nonce = e3f37b68ff508cfe295441d9e3
+Adata = b2b6c5782e4f128467c589d2a6cf55ef12877adb771bbb6245c5bba9dcfd6208
+CT = fc1870cfc440f74f73f40e682cf4713d027c297b9426c3efe981e935
+Result = Pass
+Payload = 02b5511204bd55f7c37973e26f6df5883c0a530f07c7f8c2
+
+Count = 223
+Nonce = ea98ec44f5a86715014783172e
+Adata = e4692b9f06b666c7451b146c8aeb07a6e30c629d28065c3dde5940325b14b810
+CT = 9fc2c462dff1ba9756772d73de5c4e822b5ea0bc88845a323b98de4f
+Result = Pass
+Payload = 4da40b80579c1d9a5309f7efecb7c059a2f914511ca5fc10
+
+Count = 224
+Nonce = 5a16a8902bd70fa06cfe184c57
+Adata = 399d6b0652836457ec4f701f0dc0e5aed73d16585d61cb1bb5b7ee824fc287c8
+CT = 05fc586d5c780b8e06f618b5bb85f591665a54390eba4e14af3b74e1
+Result = Fail
+
+[Alen = 32, Plen = 24, Nlen = 13, Tlen = 16]
+
+Key = 26511fb51fcfa75cb4b44da75a6e5a0eb8d9c8f3b906f886
+
+Count = 225
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = c5b0b2ef17498c5570eb335df4588032958ba3d69bf6f3178464a6f7fa2b76744e8e8d95691cecb8
+Result = Pass
+Payload = 8739b4bea1a099fe547499cbc6d1b13d849b8084c9b6acc5
+
+Count = 226
+Nonce = 0812757ad0cc4d17c4cfe7a642
+Adata = ec6c44a7e94e51a3ca6dee229098391575ec7213c85267fbf7492fdbeee61b10
+CT = d1f0518929f4ae2f0543de2a7dfe4bb0110bb3057e524a1c06bd6dc2e6bcc3436cffb969ae900388
+Result = Fail
+
+Count = 227
+Nonce = eff510acc1b85f35029cf7dc00
+Adata = 0923b927b8295c5dfaf67da55e5014293bc8c708fda50af06c1e8aef31cccc86
+CT = 1aa7dfa3a9818142c4971cbf4f64d4cbdbd354c6958ef474bb56d90669c726d866fe2206b8828727
+Result = Fail
+
+Count = 228
+Nonce = 3d13d09057190366c63c8750e9
+Adata = 77e27aa9a7bf30e130c862a3296a1cd7a10195ed1d940f2c97bfff47c6f06e32
+CT = 90352a5ec92d4fa52a96ae28251a57933728b2a3670e2ecd9953fec4e091b3573214e1ecac1ac00c
+Result = Fail
+
+Count = 229
+Nonce = e3c03ef7e1d31961ee0b97bd99
+Adata = 8a3676dd640821b58fb0f0329855fd5882c376ea166b958b7aaad223054e5784
+CT = eaa995946ed91d6a08ade14b260ac752cbd1081d5a7cad90783618374f6d03df28ee57a1a5aa38d8
+Result = Pass
+Payload = 92973ce707733a73118c8ce6b5e3fc77a17f448310c0197f
+
+Count = 230
+Nonce = 5d165ddd4e599387af5967cae6
+Adata = e374f875ce829b62c98fbd67bcf128b5647f25fff9a643300eb95559b889baed
+CT = 0e320c4ece6ef0305a431a07a5a34d463ec4a37fc513c4b947bb3f30d6e674d10a496806c1c8933e
+Result = Fail
+
+Count = 231
+Nonce = fcec171162a27a96066181fab2
+Adata = cf431cc3671ec468ea86f6cc09842fcf3a84b3ef0fa1c7b20b232145b4469d62
+CT = 10685888091597c50acc54b2fb65150b83a7115351d6f8bd7dd7ee3f75cfb47fa72433644f9cf62e
+Result = Fail
+
+Count = 232
+Nonce = 2fa8120398d1a946f391367cf6
+Adata = 92558a239c8e13230754f23aec67b153db29fdfc7daf641778185dd2931d89da
+CT = e456abf9ee83e0a68fbdb09c4a7afaba0efb0aa6d74a17c443314076072a0ebd253fe1ab4883ebea
+Result = Fail
+
+Count = 233
+Nonce = 88e0ae338bbca9d4299b294354
+Adata = 5db5c388dbadc9f175a5cd5a1472a458d25acd7fb9c951c0cd45edf64da473bb
+CT = 5adadfd296edaf4bea92c8245983dc31b11335f682fb222c16a72444f0949868f0e71907acbb29f4
+Result = Fail
+
+Count = 234
+Nonce = 4862e36296d6afc9399a95bbb4
+Adata = 36d82ebd0e0f5fe3b12946d041ae5aee16e6d17025406dd776f499bbd8e8b4c8
+CT = c2bb4d5a830646b3f8bf84044851c3b676c4ec02e43dcbf1ab2025208191d73041c038cf2562bb8c
+Result = Fail
+
+Count = 235
+Nonce = 2f360a4715074e942244ab7f9b
+Adata = f0087b0086a081c1071481f033a8be8e940c36763084329bb8461b9102238f4f
+CT = 9589b8abcb47e54e6e8fad3e64fec7ed4f70ac435bb3e548b7e6d183efa1f51b7ff31eaa52ed59ba
+Result = Fail
+
+Count = 236
+Nonce = 93e08854560edb096e5d654086
+Adata = bdc60dff08bfd5d44320b75c61e456fd4333c9c3d0294d4a48d936dfd5922ce2
+CT = af63f27e2a9e70f106477493dc141d16a1d059dd7a8a7810d990b642039f24755790332b3cc47c49
+Result = Pass
+Payload = 569e4aec88dd51ca519c0a00c922ee33d3559b98a32d7906
+
+Count = 237
+Nonce = e3f37b68ff508cfe295441d9e3
+Adata = b2b6c5782e4f128467c589d2a6cf55ef12877adb771bbb6245c5bba9dcfd6208
+CT = 1d2ae88c878684a0b404986252b3a7583e1a5a51163ddc606d3968fdceaae5138c411a29d0d333ee
+Result = Pass
+Payload = 02b5511204bd55f7c37973e26f6df5883c0a530f07c7f8c2
+
+Count = 238
+Nonce = ea98ec44f5a86715014783172e
+Adata = e4692b9f06b666c7451b146c8aeb07a6e30c629d28065c3dde5940325b14b810
+CT = 30c154c616946eccc2e241d336ad33720953e449a0e6b0f0dbf8e9464909bdf337e48093c082a10b
+Result = Pass
+Payload = 4da40b80579c1d9a5309f7efecb7c059a2f914511ca5fc10
+
+Count = 239
+Nonce = 5a16a8902bd70fa06cfe184c57
+Adata = 399d6b0652836457ec4f701f0dc0e5aed73d16585d61cb1bb5b7ee824fc287c8
+CT = 0c95b692b07b39039b40c80cf52ff71608ae87c973ac9ccb88bba8f204bb98b17cb3c8644e472b1e
+Result = Fail
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT192.txt b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT192.txt
new file mode 100644
index 0000000000..27671e1a0a
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT192.txt
@@ -0,0 +1,1589 @@
+# CAVS 11.0
+# "CCM-DVPT" information
+# AES Keylen: 192
+# Generated on Tue Mar 15 08:09:25 2011
+
+
+[Alen = 0, Plen = 0, Nlen = 7, Tlen = 4]
+
+Key = c98ad7f38b2c7e970c9b965ec87a08208384718f78206c6c
+
+Count = 0
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = 9d4b7f3b
+Result = Pass (0)
+Payload = 00
+
+Count = 1
+Nonce = 3796cf51b87266
+Adata = 00
+CT = 80745de9
+Result = Fail (2 - CT changed)
+
+Count = 2
+Nonce = 89ca5a64050f9f
+Adata = 00
+CT = 2f6fa823
+Result = Fail (1 - Adata changed)
+
+Count = 3
+Nonce = ec9d8edff25645
+Adata = 00
+CT = 3cc132c6
+Result = Fail (1 - Adata changed)
+
+Count = 4
+Nonce = 05e16f0f42a6f4
+Adata = 00
+CT = c79d5557
+Result = Pass (0)
+Payload = 00
+
+Count = 5
+Nonce = 2e504b694f8df5
+Adata = 00
+CT = 41e0eea0
+Result = Fail (2 - CT changed)
+
+Count = 6
+Nonce = 06d102a9328863
+Adata = 00
+CT = 1f129266
+Result = Fail (1 - Adata changed)
+
+Count = 7
+Nonce = c288b810fb5334
+Adata = 00
+CT = 41b0e4e2
+Result = Fail (2 - CT changed)
+
+Count = 8
+Nonce = 08a166d9eb6610
+Adata = 00
+CT = 5082e06a
+Result = Fail (2 - CT changed)
+
+Count = 9
+Nonce = 4a5810b121c91b
+Adata = 00
+CT = 70587cce
+Result = Fail (1 - Adata changed)
+
+Count = 10
+Nonce = 44077341139bf9
+Adata = 00
+CT = 6aaa0acd
+Result = Fail (1 - Adata changed)
+
+Count = 11
+Nonce = a9df4f37847e1f
+Adata = 00
+CT = 22976e42
+Result = Pass (0)
+Payload = 00
+
+Count = 12
+Nonce = 11df57fcd131e9
+Adata = 00
+CT = f440ea1d
+Result = Pass (0)
+Payload = 00
+
+Count = 13
+Nonce = 890fff56d10dc0
+Adata = 00
+CT = 88903fb9
+Result = Pass (0)
+Payload = 00
+
+Count = 14
+Nonce = 9dc18698731b27
+Adata = 00
+CT = 3ff345c3
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 0, Nlen = 7, Tlen = 16]
+
+Key = 4bb3c4a4f893ad8c9bdc833c325d62b3d3ad1bccf9282a65
+
+Count = 15
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = 17223038fa99d53681ca1beabe78d1b4
+Result = Pass (0)
+Payload = 00
+
+Count = 16
+Nonce = 3796cf51b87266
+Adata = 00
+CT = d0e1eeef4d2a264536bb1c2c1bde7c35
+Result = Fail (2 - CT changed)
+
+Count = 17
+Nonce = 89ca5a64050f9f
+Adata = 00
+CT = 81d587f8673fd514c23172af7fb7523d
+Result = Fail (1 - Adata changed)
+
+Count = 18
+Nonce = ec9d8edff25645
+Adata = 00
+CT = 500142447e535207899ab1499994daea
+Result = Fail (1 - Adata changed)
+
+Count = 19
+Nonce = 05e16f0f42a6f4
+Adata = 00
+CT = fdfdbb38bf161785114f9ee2018e892f
+Result = Pass (0)
+Payload = 00
+
+Count = 20
+Nonce = 2e504b694f8df5
+Adata = 00
+CT = 38fe9622eaa2a50152cf57e393dd3063
+Result = Fail (2 - CT changed)
+
+Count = 21
+Nonce = 06d102a9328863
+Adata = 00
+CT = 73af4b87c167572e1400a0ee28209aff
+Result = Fail (1 - Adata changed)
+
+Count = 22
+Nonce = c288b810fb5334
+Adata = 00
+CT = ace2248b9f23efa813449c82217e4a4a
+Result = Fail (2 - CT changed)
+
+Count = 23
+Nonce = 08a166d9eb6610
+Adata = 00
+CT = a9bb0e469829d9cf09ad765c5b0b58bf
+Result = Fail (2 - CT changed)
+
+Count = 24
+Nonce = 4a5810b121c91b
+Adata = 00
+CT = a5977f0826926ec0d32541b2bd4e2b1e
+Result = Fail (1 - Adata changed)
+
+Count = 25
+Nonce = 44077341139bf9
+Adata = 00
+CT = 6938fb5afec1a84e4abb062e1a943c20
+Result = Fail (1 - Adata changed)
+
+Count = 26
+Nonce = a9df4f37847e1f
+Adata = 00
+CT = 7e3bbe0eb13988a93972f2fbcd35659e
+Result = Pass (0)
+Payload = 00
+
+Count = 27
+Nonce = 11df57fcd131e9
+Adata = 00
+CT = 48d7a15cf4f5808eb45d1ad817470554
+Result = Pass (0)
+Payload = 00
+
+Count = 28
+Nonce = 890fff56d10dc0
+Adata = 00
+CT = 97185ce68af1e6ab718c8c4b83ec04cd
+Result = Pass (0)
+Payload = 00
+
+Count = 29
+Nonce = 9dc18698731b27
+Adata = 00
+CT = a81bc8f5a18293ffe19505a3687ce3f3
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 0, Nlen = 13, Tlen = 4]
+
+Key = 4bb3c4a4f893ad8c9bdc833c325d62b3d3ad1bccf9282a65
+
+Count = 30
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = fe69ed84
+Result = Pass (0)
+Payload = 00
+
+Count = 31
+Nonce = a16a2e741f1cd9717285b6d882
+Adata = 00
+CT = db7ffc82
+Result = Fail (2 - CT changed)
+
+Count = 32
+Nonce = 368f3b8180fd4b851b7b272cb1
+Adata = 00
+CT = 7a677329
+Result = Fail (1 - Adata changed)
+
+Count = 33
+Nonce = 7bb2bc00c0cafce65b5299ae64
+Adata = 00
+CT = d903d8f7
+Result = Fail (1 - Adata changed)
+
+Count = 34
+Nonce = 935c1ef3d4032ff090f91141f3
+Adata = 00
+CT = 215e0bf2
+Result = Pass (0)
+Payload = 00
+
+Count = 35
+Nonce = 2640b14f10b116411d1b5c1ad1
+Adata = 00
+CT = 0d38100f
+Result = Fail (2 - CT changed)
+
+Count = 36
+Nonce = b229c173a13b2d83af91ec45b0
+Adata = 00
+CT = 9f8ab5f7
+Result = Fail (1 - Adata changed)
+
+Count = 37
+Nonce = 37ca0dc2d6efd9efde69f14f03
+Adata = 00
+CT = 7d811d50
+Result = Fail (2 - CT changed)
+
+Count = 38
+Nonce = 6b6238aed86d677ba2b3e2622c
+Adata = 00
+CT = c2e18439
+Result = Fail (2 - CT changed)
+
+Count = 39
+Nonce = d6cb2ac67bb13b8f6d31fad64a
+Adata = 00
+CT = d8b5817b
+Result = Fail (1 - Adata changed)
+
+Count = 40
+Nonce = 32a7cd361ef00e65f5778fdfd4
+Adata = 00
+CT = 28cd70ff
+Result = Fail (1 - Adata changed)
+
+Count = 41
+Nonce = d0a1508fdefcf5be30a459b813
+Adata = 00
+CT = 790b2624
+Result = Pass (0)
+Payload = 00
+
+Count = 42
+Nonce = 5381a61b449dc6a42aa4c79b95
+Adata = 00
+CT = 9e46632d
+Result = Pass (0)
+Payload = 00
+
+Count = 43
+Nonce = c55430f2da0687ea40313884ab
+Adata = 00
+CT = 39b82901
+Result = Pass (0)
+Payload = 00
+
+Count = 44
+Nonce = ec76d1850acc0979a1f11906fb
+Adata = 00
+CT = 4c0cf71f
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 0, Nlen = 13, Tlen = 16]
+
+Key = 19ebfde2d5468ba0a3031bde629b11fd4094afcb205393fa
+
+Count = 45
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = 0c66a8e547ed4f8c2c9a9a1eb5d455b9
+Result = Pass (0)
+Payload = 00
+
+Count = 46
+Nonce = a16a2e741f1cd9717285b6d882
+Adata = 00
+CT = 38757b3a61a4dc97ca3ab88bf1240695
+Result = Fail (2 - CT changed)
+
+Count = 47
+Nonce = 368f3b8180fd4b851b7b272cb1
+Adata = 00
+CT = 11875da4445d92391d0fab5f3625497b
+Result = Fail (1 - Adata changed)
+
+Count = 48
+Nonce = 7bb2bc00c0cafce65b5299ae64
+Adata = 00
+CT = 64477bcd4316e5c5789e1a678fdef943
+Result = Fail (1 - Adata changed)
+
+Count = 49
+Nonce = 935c1ef3d4032ff090f91141f3
+Adata = 00
+CT = 87da5dbc04e39fc468f43675d4e7df33
+Result = Pass (0)
+Payload = 00
+
+Count = 50
+Nonce = 2640b14f10b116411d1b5c1ad1
+Adata = 00
+CT = bf0d53ee529d8cafc5ad7a8f2d85e7a2
+Result = Fail (2 - CT changed)
+
+Count = 51
+Nonce = b229c173a13b2d83af91ec45b0
+Adata = 00
+CT = 676370637ad78c705d43fce066dc909f
+Result = Fail (1 - Adata changed)
+
+Count = 52
+Nonce = 37ca0dc2d6efd9efde69f14f03
+Adata = 00
+CT = 289936db0f9f148a3c9e2d28f7d7de51
+Result = Fail (2 - CT changed)
+
+Count = 53
+Nonce = 6b6238aed86d677ba2b3e2622c
+Adata = 00
+CT = 58a283641627669d5514f2af559b6c14
+Result = Fail (2 - CT changed)
+
+Count = 54
+Nonce = d6cb2ac67bb13b8f6d31fad64a
+Adata = 00
+CT = a6b058540ed905d6e3499a13ea1f3d83
+Result = Fail (1 - Adata changed)
+
+Count = 55
+Nonce = 32a7cd361ef00e65f5778fdfd4
+Adata = 00
+CT = 7a19b3377384f09915d0e1ae93a9f16c
+Result = Fail (1 - Adata changed)
+
+Count = 56
+Nonce = d0a1508fdefcf5be30a459b813
+Adata = 00
+CT = a0d047a1f9940d325e474da54aa13897
+Result = Pass (0)
+Payload = 00
+
+Count = 57
+Nonce = 5381a61b449dc6a42aa4c79b95
+Adata = 00
+CT = 8a4768a2093694b6bcb7083c0bb6331c
+Result = Pass (0)
+Payload = 00
+
+Count = 58
+Nonce = c55430f2da0687ea40313884ab
+Adata = 00
+CT = a7cafd6f68dc1f15a3603da654ce27bc
+Result = Pass (0)
+Payload = 00
+
+Count = 59
+Nonce = ec76d1850acc0979a1f11906fb
+Adata = 00
+CT = c49845f2ea3c9981ad7e9b942f615b8d
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 24, Nlen = 7, Tlen = 4]
+
+Key = 19ebfde2d5468ba0a3031bde629b11fd4094afcb205393fa
+
+Count = 60
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = 411986d04d6463100bff03f7d0bde7ea2c3488784378138cddc93a54
+Result = Pass (0)
+Payload = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22
+
+Count = 61
+Nonce = 31f8fa25827d48
+Adata = 00
+CT = 32b649ab56162e55d4148a1292d6a225a988eb1308298273b6889036
+Result = Fail (2 - CT changed)
+
+Count = 62
+Nonce = 5340ed7752c9ff
+Adata = 00
+CT = a963c3568ab413b174cd95cc1e3ca61ee181292bebdb28179b4de35f
+Result = Fail (1 - Adata changed)
+
+Count = 63
+Nonce = 9cbce402511b89
+Adata = 00
+CT = 0396e6c8db43e5fac205f4c576fd577368adcb688cf3d7e76df9ffc5
+Result = Fail (1 - Adata changed)
+
+Count = 64
+Nonce = 123a0beace4e39
+Adata = 00
+CT = b41bfba94edcafc41b4c144269b9126a6d47b19e83b15772b28c8e38
+Result = Pass (0)
+Payload = 9d033e3b66efed1467868f382417c80594877a28bc97f406
+
+Count = 65
+Nonce = 8ea1594a58fe4a
+Adata = 00
+CT = 01e3bb938e16d0284d1d0fee049d80fb97356ae4d84127cf7336a30a
+Result = Fail (2 - CT changed)
+
+Count = 66
+Nonce = 5a7743e59e82da
+Adata = 00
+CT = abd7551c5e84e9bef5fbfad3e24d13f02864410eae9177ad0c40cc72
+Result = Fail (1 - Adata changed)
+
+Count = 67
+Nonce = f477f754d7ee76
+Adata = 00
+CT = 3b5ae49e0974f41826152432b46f1a85ab4995afefbbccddfc9fd290
+Result = Fail (2 - CT changed)
+
+Count = 68
+Nonce = 040a257dede70e
+Adata = 00
+CT = 21fb4324de4ba1e2762b3041ce26e43a3d191458a046d489e485910b
+Result = Fail (2 - CT changed)
+
+Count = 69
+Nonce = dd51b8e91683d1
+Adata = 00
+CT = 99ca8f542fd06481e23719214c9892442f393d72899deea08695053f
+Result = Fail (1 - Adata changed)
+
+Count = 70
+Nonce = ab3cb86cca6fb2
+Adata = 00
+CT = 5fcc05342cdc27f66b324ae7387205bfb4ab6302bfe0af09050d2054
+Result = Fail (1 - Adata changed)
+
+Count = 71
+Nonce = f67b98efd39b55
+Adata = 00
+CT = 0a7fe63046daf8a979935b897088c64acc1b47a5a9b86fdd6def28ab
+Result = Pass (0)
+Payload = f2e944e1ae47ad5873bf391f1b0cc07f6151eb4c50bb45b2
+
+Count = 72
+Nonce = e60e2c002d1c99
+Adata = 00
+CT = daf7d7dfa512ceb1d7d3435634d9a70b3ef6c6dc38f409e068941fce
+Result = Pass (0)
+Payload = 70f48dc1d76e5028da07e29852801375a9edb2214a5ea4c0
+
+Count = 73
+Nonce = 098e053fa08043
+Adata = 00
+CT = cdb417dff6502208775f21e35cdb8e3e1199308d1a94229051a1ec4a
+Result = Pass (0)
+Payload = bd81680e3dc0b35431c92598dcaa26ef09ca0da5e77193de
+
+Count = 74
+Nonce = 4bf48328725514
+Adata = 00
+CT = e75441093c8ccba6eac5913dc246ce96de4784a01051498298eaddaf
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 24, Nlen = 7, Tlen = 16]
+
+Key = 197afb02ffbd8f699dacae87094d524324576b99844f75e1
+
+Count = 75
+Nonce = 5a8aa485c316e9
+Adata = 00
+CT = cba4b4aeb85f0492fd8d905c4a6d8233139833373ef188a8c5a5ebecf7ac8607fe412189e83d9d20
+Result = Pass (0)
+Payload = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22
+
+Count = 76
+Nonce = 31f8fa25827d48
+Adata = 00
+CT = ca62713728b5c9d652504b0ae8fd4fee5d297ee6a8d19cb6e699f15f14d34dcaf9ba8ed4b877c97d
+Result = Fail (2 - CT changed)
+
+Count = 77
+Nonce = 5340ed7752c9ff
+Adata = 00
+CT = 93012c0a5f6f1025b8c4a5d897d3eea0b1c77be8000c9e59f3b8899459788c58794f177cfd838f35
+Result = Fail (1 - Adata changed)
+
+Count = 78
+Nonce = 9cbce402511b89
+Adata = 00
+CT = b8eb95f72f643c2c51ad74775cc203d215c86626e903eb013ad22e8fa4d2f9725ce4f212a8844855
+Result = Fail (1 - Adata changed)
+
+Count = 79
+Nonce = 123a0beace4e39
+Adata = 00
+CT = 71f17cf21c44267c676657db9e55bee33273787474e77b17b5eab45d7d096577643815e6d467312d
+Result = Pass (0)
+Payload = 9d033e3b66efed1467868f382417c80594877a28bc97f406
+
+Count = 80
+Nonce = 8ea1594a58fe4a
+Adata = 00
+CT = d6737f642260c4ee3b19cb78cc2ef1767213416b82c71e918b1a5ecca7354af824fea617b9b69031
+Result = Fail (2 - CT changed)
+
+Count = 81
+Nonce = 5a7743e59e82da
+Adata = 00
+CT = cbe60d633399daa6ee66418be6d16e292ea47a93c291fce2c54c98f8007ed55a21759f5452559538
+Result = Fail (1 - Adata changed)
+
+Count = 82
+Nonce = f477f754d7ee76
+Adata = 00
+CT = 2a78a7beb8df4bf5d35ff0b2853bc51ce127163d2f56e00ea555aa972e1c2e3f439f85663ae25889
+Result = Fail (2 - CT changed)
+
+Count = 83
+Nonce = 040a257dede70e
+Adata = 00
+CT = ee78ddbea9c3aede9f88af0e82464d9d1afe81de16aa18c49aeb326578fa615e86969348d9bbfb7f
+Result = Fail (2 - CT changed)
+
+Count = 84
+Nonce = dd51b8e91683d1
+Adata = 00
+CT = cdf7cb74d978e7ea738e288ed79edfccf10b553c09d1856e2efbff1da769af3b72099cbda3cbf091
+Result = Fail (1 - Adata changed)
+
+Count = 85
+Nonce = ab3cb86cca6fb2
+Adata = 00
+CT = 90b990a1ea254592f2c226c969b332fc7bfe5f808729c2d83291a566e6641a965ffdabe097050dc5
+Result = Fail (1 - Adata changed)
+
+Count = 86
+Nonce = f67b98efd39b55
+Adata = 00
+CT = 44a6aa954c3508b3c9264c20c272e80c0e95d50ddec2849084b47504dced5b70c302cc93502cc37e
+Result = Pass (0)
+Payload = f2e944e1ae47ad5873bf391f1b0cc07f6151eb4c50bb45b2
+
+Count = 87
+Nonce = e60e2c002d1c99
+Adata = 00
+CT = 9d4ff7a44cdb9b14f586efc3d6be02d069b425c06bec4eed37109739a3676f03adfd740dbaa4940d
+Result = Pass (0)
+Payload = 70f48dc1d76e5028da07e29852801375a9edb2214a5ea4c0
+
+Count = 88
+Nonce = 098e053fa08043
+Adata = 00
+CT = 23da95e102c7921a51b19b5733ea5776ab6c287f6057c00ec4bfacbb2f246b570efd93d98e99be49
+Result = Pass (0)
+Payload = bd81680e3dc0b35431c92598dcaa26ef09ca0da5e77193de
+
+Count = 89
+Nonce = 4bf48328725514
+Adata = 00
+CT = 53d00d5839d0a1e695916151f9450b7311982917edcbd7c66496912db41761a1d2aecfda04fb2cfa
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 24, Nlen = 13, Tlen = 4]
+
+Key = 197afb02ffbd8f699dacae87094d524324576b99844f75e1
+
+Count = 90
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = 042653c674ef2a90f7fb11d30848e530ae59478f1051633a34fad277
+Result = Pass (0)
+Payload = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697
+
+Count = 91
+Nonce = 49004912fdd7269279b1f06a89
+Adata = 00
+CT = 1902d9769a7ba3d3268e1257395c8c2e5f98eef295dcbfa5a35df775
+Result = Fail (2 - CT changed)
+
+Count = 92
+Nonce = efeb82c8c68d6600b24dd6d8ee
+Adata = 00
+CT = ebacb8e78c0ad9d3ed99f1821b0b0085beac351f88a79ef71faaf310
+Result = Fail (1 - Adata changed)
+
+Count = 93
+Nonce = 7b93d368dc551640b00ba3cbb5
+Adata = 00
+CT = efc1d5b6f0a48e4ce3e821d743d34206b28c69485c410fa94d5e6103
+Result = Fail (1 - Adata changed)
+
+Count = 94
+Nonce = 24b7a65391f88bea38fcd54a9a
+Adata = 00
+CT = 3c1836e5d0f0473dab7bfd7a95ba69575f7f841970ac6c6769ac966a
+Result = Pass (0)
+Payload = 43419715cef9a48dc7280bc035082a6581afd1d82bee9d1a
+
+Count = 95
+Nonce = 6aa3f731522fce7e366ba59945
+Adata = 00
+CT = 2c583e54d75a02948c7f6dcd12cba32a65e8d605fba7ec10c47e9a8e
+Result = Fail (2 - CT changed)
+
+Count = 96
+Nonce = a11cf5bed0041ee3cb1fef4b43
+Adata = 00
+CT = a8632dee22f34315b05c40135c6dd471c63b09438da834dc1f3f537f
+Result = Fail (1 - Adata changed)
+
+Count = 97
+Nonce = 273cc5013785baeb5abc79c8bd
+Adata = 00
+CT = 0f03ea1b2561951d79062e19a85d98293c8c2846936c724c26421940
+Result = Fail (2 - CT changed)
+
+Count = 98
+Nonce = d2d4482ea8e98c1cf309671895
+Adata = 00
+CT = f9764405e54d827ac433fd624506b92e123463a5b01f21ffa3a22ac7
+Result = Fail (2 - CT changed)
+
+Count = 99
+Nonce = a8849b44adb48d271979656930
+Adata = 00
+CT = a326e0cf3f97adff3249944880ddfb8d616cd18a086e046289429246
+Result = Fail (1 - Adata changed)
+
+Count = 100
+Nonce = a632ba0d00511122abcd6227ff
+Adata = 00
+CT = f188bc1a72e81b34d75b402e4f8ef3d638d2f56a409eab064c9649b7
+Result = Fail (1 - Adata changed)
+
+Count = 101
+Nonce = c47af80cd26d047630c1fdf0d1
+Adata = 00
+CT = 341df3a273e85cf387ab823bdf9c34a1ae2c86940cb4bfcde2e93f29
+Result = Pass (0)
+Payload = d8306c9c4ea6c69c6e2ad0fc0e49b1e0126b01078d6419ff
+
+Count = 102
+Nonce = 70e132023acae1f88c7a237b68
+Adata = 00
+CT = a0e7997fd67ea66b6274d719b84da92433fdf7d512b160da35c7081d
+Result = Pass (0)
+Payload = d0b2bef5ed1a87d9c73d4a459cb05c11799c4f51ad640b1e
+
+Count = 103
+Nonce = 8010d3a2a14f72f5585defc940
+Adata = 00
+CT = dd8fd11e1c0746e7273fdd2e7dfa1ee4fc8ad835ca3141c0f83a9ad7
+Result = Pass (0)
+Payload = 4faba05569bf7ac656780c16995e9122e565fe9984be8a68
+
+Count = 104
+Nonce = a98c2f0e0a7b68942853905191
+Adata = 00
+CT = 39b0d3603f1289b5885ac244953275d28491952e7e57d93c7ff1eb5d
+Result = Fail (2 - CT changed)
+
+[Alen = 0, Plen = 24, Nlen = 13, Tlen = 16]
+
+Key = 90929a4b0ac65b350ad1591611fe48297e03956f6083e451
+
+Count = 105
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = 00
+CT = a5b7d8cca2069908d1ed88e6a9fe2c9bede3131dad54671ea7ade30a07d185692ab0ebdf4c78cf7a
+Result = Pass (0)
+Payload = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697
+
+Count = 106
+Nonce = 49004912fdd7269279b1f06a89
+Adata = 00
+CT = 9a98617fb97a0dfe466be692272dcdaec1c5443a3b51312ef042c86363cc05afb98c66e16be8a445
+Result = Fail (2 - CT changed)
+
+Count = 107
+Nonce = efeb82c8c68d6600b24dd6d8ee
+Adata = 00
+CT = d3068ae815c3605d7670058abb9384f4c15b75150eb7910041a8f6ac697430627826bd76b19da027
+Result = Fail (1 - Adata changed)
+
+Count = 108
+Nonce = 7b93d368dc551640b00ba3cbb5
+Adata = 00
+CT = 388a289bb85533b667b141a78d0c79acdeb9fbf72886d5ab980581017fefef92c2b50ae20b93c81c
+Result = Fail (1 - Adata changed)
+
+Count = 109
+Nonce = 24b7a65391f88bea38fcd54a9a
+Adata = 00
+CT = 71f68480a8801d4966c84807c5ff6139d83ba0a5b902bee3327f5f91763c0a0bec43264c27cd237f
+Result = Pass (0)
+Payload = 43419715cef9a48dc7280bc035082a6581afd1d82bee9d1a
+
+Count = 110
+Nonce = 6aa3f731522fce7e366ba59945
+Adata = 00
+CT = 8627bf1e3edafc69f1328c393dd8e7bd1c182d021e6d3a3652c4b7fd911ca77950ff2d035e47b7ec
+Result = Fail (2 - CT changed)
+
+Count = 111
+Nonce = a11cf5bed0041ee3cb1fef4b43
+Adata = 00
+CT = b10ea86a384432a45f50b3c2e482595b46c81c61ca39bc0f4ffcb29bde8b9a81945d671b0f619045
+Result = Fail (1 - Adata changed)
+
+Count = 112
+Nonce = 273cc5013785baeb5abc79c8bd
+Adata = 00
+CT = 3ace8b7e03a0c1fa9e97f46975ab0a4924446e791540e225578cc14aa558e18d5f777ab6e16dcfee
+Result = Fail (2 - CT changed)
+
+Count = 113
+Nonce = d2d4482ea8e98c1cf309671895
+Adata = 00
+CT = 8190abe4c21e320e10825e269190bb10a354691958e2436275433c4ae28757c8544c86f1f74ea6a5
+Result = Fail (2 - CT changed)
+
+Count = 114
+Nonce = a8849b44adb48d271979656930
+Adata = 00
+CT = 1d7e308c34cdca7b7b222f4ebc92afd8055bff542c0b76d3d7752ebe9c5dbf00ee8ad60ac34dd7d0
+Result = Fail (1 - Adata changed)
+
+Count = 115
+Nonce = a632ba0d00511122abcd6227ff
+Adata = 00
+CT = 9c2609f7af5b634a16e58f2e9cc7a9ef7812a12d209847000a4432b35d3b884e4169c28d287499ff
+Result = Fail (1 - Adata changed)
+
+Count = 116
+Nonce = c47af80cd26d047630c1fdf0d1
+Adata = 00
+CT = 5b0b5e6690d648e1b92c12cfddb431d6d3dfe689d01db8199256ace490c2f0afb93ba32be58fd1de
+Result = Pass (0)
+Payload = d8306c9c4ea6c69c6e2ad0fc0e49b1e0126b01078d6419ff
+
+Count = 117
+Nonce = 70e132023acae1f88c7a237b68
+Adata = 00
+CT = 8722fca71fdf750ec5d62fc6d7ba079aef19210da764067aefd8535dd6b7fa701c9ca8c8b635c30b
+Result = Pass (0)
+Payload = d0b2bef5ed1a87d9c73d4a459cb05c11799c4f51ad640b1e
+
+Count = 118
+Nonce = 8010d3a2a14f72f5585defc940
+Adata = 00
+CT = 91ac457f5e53492301e72d9d495277ed17edb30e8c7a48d21b5d2cd4d5b6d2ef48413245a6b27b67
+Result = Pass (0)
+Payload = 4faba05569bf7ac656780c16995e9122e565fe9984be8a68
+
+Count = 119
+Nonce = a98c2f0e0a7b68942853905191
+Adata = 00
+CT = d2fe5293b7d53ed46ddf02a5618039adbae22845ce72e434fdc83ea4863c3e84a5456f7f853a1ea6
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 0, Nlen = 7, Tlen = 4]
+
+Key = 90929a4b0ac65b350ad1591611fe48297e03956f6083e451
+
+Count = 120
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 1d089a5f
+Result = Pass (0)
+Payload = 00
+
+Count = 121
+Nonce = a265480ca88d5f
+Adata = a2248a882ecbf850daf91933a389e78e81623d233dfd47bf8321361a38f138fe
+CT = 2f46022a
+Result = Fail (2 - CT changed)
+
+Count = 122
+Nonce = 87ec7423f1ebfc
+Adata = 2bed1ec06c1ca149d9ffbaf048c474ea2de000eb7950f18d6c25acf6ab3f19b5
+CT = 67dc4693
+Result = Fail (1 - Adata changed)
+
+Count = 123
+Nonce = b8b04f90616082
+Adata = 4898731e143fcc677c7cf1a8f2b3c4039fb5e57028e33b05e097d1763cbfe4d8
+CT = 7027a849
+Result = Fail (1 - Adata changed)
+
+Count = 124
+Nonce = 8c687b4318813a
+Adata = fcad52a88544325bb31eb5de4a41dbff6a96f69d0993b969a01792ee23953acf
+CT = 5c6a4de2
+Result = Pass (0)
+Payload = 00
+
+Count = 125
+Nonce = 29b810eed8fc92
+Adata = 40d1d320eb63a25d7a2b3141563a552114275ddda56beb62cc0c0273d5795faa
+CT = 1d855f5d
+Result = Fail (2 - CT changed)
+
+Count = 126
+Nonce = 62452462c53934
+Adata = 1eb8863ea100babc1713654afcf54f21f8bff754223ad70269ace9d034f26a96
+CT = 1b318980
+Result = Fail (1 - Adata changed)
+
+Count = 127
+Nonce = 4cceba0e7aee97
+Adata = f33e184c967165eb62542999afaca4e3e319840e439b5bb509544fb4b6901445
+CT = cf871f91
+Result = Fail (2 - CT changed)
+
+Count = 128
+Nonce = b5151b0601c683
+Adata = 73d27303ec91f28c79b278882034d11eb6a5266746f37edbb77f8409a8738b8c
+CT = 4f0e04bc
+Result = Fail (2 - CT changed)
+
+Count = 129
+Nonce = 4e5d6d7ac9e71e
+Adata = a01b6e152fe232b6c10b5d89900961c445f4c46833df242c826678b68c869811
+CT = fc9013df
+Result = Fail (1 - Adata changed)
+
+Count = 130
+Nonce = dc88e989951a3f
+Adata = fdcacfaff46585406cc45a2da364e67e132a91c98900a8f9d7bfb14ec951fca5
+CT = 5134def3
+Result = Fail (1 - Adata changed)
+
+Count = 131
+Nonce = a1aeda4b4cb8dd
+Adata = db3022ef4cd68ae22b501599448ffe2dda15cfd2e259315c6f6d03036edea963
+CT = 5814103a
+Result = Pass (0)
+Payload = 00
+
+Count = 132
+Nonce = f248e5225e3d9a
+Adata = fdc64ef76a3bfd0a15d0bc8e8bacaf64346796a3e35afcf2ac1ab136f63f7b6e
+CT = 74c75c4a
+Result = Pass (0)
+Payload = 00
+
+Count = 133
+Nonce = e68228f5c65b73
+Adata = 614efdf89ce2a9fcbd38bdc0b4cece54dfd7532880e0b4ce6eb3a4010b7cb1e7
+CT = 9884898b
+Result = Pass (0)
+Payload = 00
+
+Count = 134
+Nonce = ea167cfd1101d9
+Adata = 28130f938c45a1a92b02dbeadbd8df816b6d934e87cca2dfdbfdc49c7cd84041
+CT = 0b1cbfb1
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 0, Nlen = 7, Tlen = 16]
+
+Key = 6a798d7c5e1a72b43e20ad5c7b08567b12ab744b61c070e2
+
+Count = 135
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 5280a2137fee3deefcfe9b63a1199fb3
+Result = Pass (0)
+Payload = 00
+
+Count = 136
+Nonce = a265480ca88d5f
+Adata = a2248a882ecbf850daf91933a389e78e81623d233dfd47bf8321361a38f138fe
+CT = d40a7318c5f2d82f838c0beeefe0d598
+Result = Fail (2 - CT changed)
+
+Count = 137
+Nonce = 87ec7423f1ebfc
+Adata = 2bed1ec06c1ca149d9ffbaf048c474ea2de000eb7950f18d6c25acf6ab3f19b5
+CT = 7551978bc9592bf9e294b4984c5862bb
+Result = Fail (1 - Adata changed)
+
+Count = 138
+Nonce = b8b04f90616082
+Adata = 4898731e143fcc677c7cf1a8f2b3c4039fb5e57028e33b05e097d1763cbfe4d8
+CT = 859cf444f89225b32a55a1645bd24979
+Result = Fail (1 - Adata changed)
+
+Count = 139
+Nonce = 8c687b4318813a
+Adata = fcad52a88544325bb31eb5de4a41dbff6a96f69d0993b969a01792ee23953acf
+CT = 29e967a0245607c36cf3eaf00fdae566
+Result = Pass (0)
+Payload = 00
+
+Count = 140
+Nonce = 29b810eed8fc92
+Adata = 40d1d320eb63a25d7a2b3141563a552114275ddda56beb62cc0c0273d5795faa
+CT = 9daa0e1c4df5f2bf507b1a57a1135b86
+Result = Fail (2 - CT changed)
+
+Count = 141
+Nonce = 62452462c53934
+Adata = 1eb8863ea100babc1713654afcf54f21f8bff754223ad70269ace9d034f26a96
+CT = 18caec79720a5d67d7457e9b7c7a153c
+Result = Fail (1 - Adata changed)
+
+Count = 142
+Nonce = 4cceba0e7aee97
+Adata = f33e184c967165eb62542999afaca4e3e319840e439b5bb509544fb4b6901445
+CT = 5f2c455546c56f514a0f69f05345c2c4
+Result = Fail (2 - CT changed)
+
+Count = 143
+Nonce = b5151b0601c683
+Adata = 73d27303ec91f28c79b278882034d11eb6a5266746f37edbb77f8409a8738b8c
+CT = b7e4846ff30b7c3673a962a2701c0387
+Result = Fail (2 - CT changed)
+
+Count = 144
+Nonce = 4e5d6d7ac9e71e
+Adata = a01b6e152fe232b6c10b5d89900961c445f4c46833df242c826678b68c869811
+CT = 7b5fa0d42a616ab05ac2c58c904ce92f
+Result = Fail (1 - Adata changed)
+
+Count = 145
+Nonce = dc88e989951a3f
+Adata = fdcacfaff46585406cc45a2da364e67e132a91c98900a8f9d7bfb14ec951fca5
+CT = c8c67f558b5844b149dd47824c8cb9d8
+Result = Fail (1 - Adata changed)
+
+Count = 146
+Nonce = a1aeda4b4cb8dd
+Adata = db3022ef4cd68ae22b501599448ffe2dda15cfd2e259315c6f6d03036edea963
+CT = 70a09aaf22ac316124a169f6b0a83ffe
+Result = Pass (0)
+Payload = 00
+
+Count = 147
+Nonce = f248e5225e3d9a
+Adata = fdc64ef76a3bfd0a15d0bc8e8bacaf64346796a3e35afcf2ac1ab136f63f7b6e
+CT = 5bc85ed5521a91b9eb42b437950f0e06
+Result = Pass (0)
+Payload = 00
+
+Count = 148
+Nonce = e68228f5c65b73
+Adata = 614efdf89ce2a9fcbd38bdc0b4cece54dfd7532880e0b4ce6eb3a4010b7cb1e7
+CT = 989ec0e7b192ea010dd61d3fb64e8de0
+Result = Pass (0)
+Payload = 00
+
+Count = 149
+Nonce = ea167cfd1101d9
+Adata = 28130f938c45a1a92b02dbeadbd8df816b6d934e87cca2dfdbfdc49c7cd84041
+CT = 15c2dbe7fa307654d8ca7c0f8d6d2f14
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 0, Nlen = 13, Tlen = 4]
+
+Key = 6a798d7c5e1a72b43e20ad5c7b08567b12ab744b61c070e2
+
+Count = 150
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = 5e0eaebd
+Result = Pass (0)
+Payload = 00
+
+Count = 151
+Nonce = 8739b4bea1a099fe547499cbc6
+Adata = f6107696edb332b2ea059d8860fee26be42e5e12e1a4f79a8d0eafce1b2278a7
+CT = 71b7fc33
+Result = Fail (2 - CT changed)
+
+Count = 152
+Nonce = 0f98fdbde2b04387f27b3401dd
+Adata = 02010329660fa716556193eb4870ee84bd934296a5c52d92bba859cc13caaddc
+CT = 93227bd4
+Result = Fail (1 - Adata changed)
+
+Count = 153
+Nonce = 4eed58f381e500902ba5c56864
+Adata = 96056d9ebd7c553c22cc2d9d816b61123750d96c1b08c4b661079424bf3c4946
+CT = ced654e2
+Result = Fail (1 - Adata changed)
+
+Count = 154
+Nonce = 1e7e51f0fa9a33ed618c26f5e3
+Adata = da9b8ffb0f3c2aee2e386cc9f035ec1eb3e629bd1544c11dc21be4fd8ac9074a
+CT = bf7a8e0c
+Result = Pass (0)
+Payload = 00
+
+Count = 155
+Nonce = f012f94f5988c79aa179d7fdfc
+Adata = 612b2ef2683109d99452f95099417641d0c2be3f8ab4cbb2a44e83355ba9303c
+CT = 840caa3e
+Result = Fail (2 - CT changed)
+
+Count = 156
+Nonce = 715acf92cfb69ad56036c49e70
+Adata = 960667b85be07304634124b9324be12a1c11451f1fa9db82c683265b4cf8e5ff
+CT = 1e22fc41
+Result = Fail (1 - Adata changed)
+
+Count = 157
+Nonce = 141be3601e38185a9fa1596d2e
+Adata = 606452c62290b43559a588bb03356f846cecb0ccaf0bdaf67a18abd811d4315a
+CT = 968ccbbf
+Result = Fail (2 - CT changed)
+
+Count = 158
+Nonce = fcdda3c5f0e80843b03d8788da
+Adata = 03f22247a55461a293d253c77483859fdac1b87c2480e208a3df767cfbfde512
+CT = 0a31cc96
+Result = Fail (2 - CT changed)
+
+Count = 159
+Nonce = ca660ed3b917c0aca140dcd3fb
+Adata = 254a86f5b20d344ad86fd5523d08f1864737be57731440c29aa6b42574572f51
+CT = a456c3da
+Result = Fail (1 - Adata changed)
+
+Count = 160
+Nonce = 642ae3466661ce1f51783deece
+Adata = 4432a1cec5976cc13b8fb78341d426c2248f091b597123d263ffafc7f82da5a5
+CT = 29746eea
+Result = Fail (1 - Adata changed)
+
+Count = 161
+Nonce = 7864c717ec93db38b10679be47
+Adata = 679aad1ad1e57029e3362b325572fc71cac53184b0f1546867e665a4a59466c4
+CT = df7f63ca
+Result = Pass (0)
+Payload = 00
+
+Count = 162
+Nonce = c3bf9dfe9d6c26f543188fb457
+Adata = e301f69ad3a7e08a3d02462f0aa584449eb0449b0e3c50aa8dfaa4472816c8b0
+CT = bf0b1445
+Result = Pass (0)
+Payload = 00
+
+Count = 163
+Nonce = 1527657d2fd98f7deca55cc649
+Adata = f4c723433b7cafe3cda9bb4940a21a89a8382d13018b622ccd1ffb9ffd3211af
+CT = ae8533f5
+Result = Pass (0)
+Payload = 00
+
+Count = 164
+Nonce = b8432d3d5525a0dadbbaa6b6b8
+Adata = 86ee6e37b4a2d9a0b52ec95643b4e8297e237721e15ce8bf7593a98644f83eba
+CT = 9426cf89
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 0, Nlen = 13, Tlen = 16]
+
+Key = f9fdca4ac64fe7f014de0f43039c757194d544ce5d15eed4
+
+Count = 165
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = d07ccf9fdc3d33aa94cda3d230da707c
+Result = Pass (0)
+Payload = 00
+
+Count = 166
+Nonce = 8739b4bea1a099fe547499cbc6
+Adata = f6107696edb332b2ea059d8860fee26be42e5e12e1a4f79a8d0eafce1b2278a7
+CT = 65fe32b649dc328c9f531584897e85b3
+Result = Fail (2 - CT changed)
+
+Count = 167
+Nonce = 0f98fdbde2b04387f27b3401dd
+Adata = 02010329660fa716556193eb4870ee84bd934296a5c52d92bba859cc13caaddc
+CT = ec31fb6b41c2dae87cf395fc1fe3a080
+Result = Fail (1 - Adata changed)
+
+Count = 168
+Nonce = 4eed58f381e500902ba5c56864
+Adata = 96056d9ebd7c553c22cc2d9d816b61123750d96c1b08c4b661079424bf3c4946
+CT = 33c2f2312dd5bfcadbb05f8d0a33fd4a
+Result = Fail (1 - Adata changed)
+
+Count = 169
+Nonce = 1e7e51f0fa9a33ed618c26f5e3
+Adata = da9b8ffb0f3c2aee2e386cc9f035ec1eb3e629bd1544c11dc21be4fd8ac9074a
+CT = a9e81afd1030d195c679e2c837aeb736
+Result = Pass (0)
+Payload = 00
+
+Count = 170
+Nonce = f012f94f5988c79aa179d7fdfc
+Adata = 612b2ef2683109d99452f95099417641d0c2be3f8ab4cbb2a44e83355ba9303c
+CT = 1db000f0e7d3a03718293fc118678427
+Result = Fail (2 - CT changed)
+
+Count = 171
+Nonce = 715acf92cfb69ad56036c49e70
+Adata = 960667b85be07304634124b9324be12a1c11451f1fa9db82c683265b4cf8e5ff
+CT = ea37900f049db8fc5cbf46edb5fcac2c
+Result = Fail (1 - Adata changed)
+
+Count = 172
+Nonce = 141be3601e38185a9fa1596d2e
+Adata = 606452c62290b43559a588bb03356f846cecb0ccaf0bdaf67a18abd811d4315a
+CT = d1097ebd7ad0a41f61ba32a44dc15305
+Result = Fail (2 - CT changed)
+
+Count = 173
+Nonce = fcdda3c5f0e80843b03d8788da
+Adata = 03f22247a55461a293d253c77483859fdac1b87c2480e208a3df767cfbfde512
+CT = 0979729272d8b42f2e3dc0eb181a1217
+Result = Fail (2 - CT changed)
+
+Count = 174
+Nonce = ca660ed3b917c0aca140dcd3fb
+Adata = 254a86f5b20d344ad86fd5523d08f1864737be57731440c29aa6b42574572f51
+CT = 4457200916a20116b096225606f1a9e2
+Result = Fail (1 - Adata changed)
+
+Count = 175
+Nonce = 642ae3466661ce1f51783deece
+Adata = 4432a1cec5976cc13b8fb78341d426c2248f091b597123d263ffafc7f82da5a5
+CT = cc6b51f39a3dcfb54abbb89f4df21114
+Result = Fail (1 - Adata changed)
+
+Count = 176
+Nonce = 7864c717ec93db38b10679be47
+Adata = 679aad1ad1e57029e3362b325572fc71cac53184b0f1546867e665a4a59466c4
+CT = aac09cef9697927331251f028d24c31f
+Result = Pass (0)
+Payload = 00
+
+Count = 177
+Nonce = c3bf9dfe9d6c26f543188fb457
+Adata = e301f69ad3a7e08a3d02462f0aa584449eb0449b0e3c50aa8dfaa4472816c8b0
+CT = 56c00070eae0db329894a045d866bbaf
+Result = Pass (0)
+Payload = 00
+
+Count = 178
+Nonce = 1527657d2fd98f7deca55cc649
+Adata = f4c723433b7cafe3cda9bb4940a21a89a8382d13018b622ccd1ffb9ffd3211af
+CT = 090016bb96aeaabbf66fd34fc97591a4
+Result = Pass (0)
+Payload = 00
+
+Count = 179
+Nonce = b8432d3d5525a0dadbbaa6b6b8
+Adata = 86ee6e37b4a2d9a0b52ec95643b4e8297e237721e15ce8bf7593a98644f83eba
+CT = 264407dfe796bf7f6eb1f26c1f8504ef
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 24, Nlen = 7, Tlen = 4]
+
+Key = f9fdca4ac64fe7f014de0f43039c757194d544ce5d15eed4
+
+Count = 180
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 9f6ca4af9b159148c889a6584d1183ea26e2614874b0504575dea8d1
+Result = Pass (0)
+Payload = a265480ca88d5f536db0dc6abc40faf0d05be7a966977768
+
+Count = 181
+Nonce = fdd2d6f503c915
+Adata = 5b92394f21ddc3ad49d9b0881b829a5935cb3a4d23e292a62fb66b5e7ab7020e
+CT = 84d8212e9cfc2121252baa3b065b1edcf50497b9594db1ebd7965825
+Result = Fail (2 - CT changed)
+
+Count = 182
+Nonce = 27d73d58100054
+Adata = f6468542923be79b4b06dfe70920d57d1da73a9c16f9c9a12d810d7de0d12467
+CT = 5f60a8f867a33b2077ecc69863b295c3c6aeae7d7cade7f8f7f796fe
+Result = Fail (1 - Adata changed)
+
+Count = 183
+Nonce = dd16e0ce1250e3
+Adata = bc65cfd65e9863c8b7457d58afa6bdb48a84170d8aa97ba5b397b52ad17a9242
+CT = 1353b3fa1bb1d57ffb139017885c02e26c90231a24b5a615b8f1f2ae
+Result = Fail (1 - Adata changed)
+
+Count = 184
+Nonce = ccee19d037cf4a
+Adata = c026696e6425e6c33f45b4145febf1137e7ac26383c9f5aa4cd4e5e8abb19e07
+CT = c3116d9040e1ed4f7c9464d270fb302bd3f1561c25c5b95b8b4b53f6
+Result = Pass (0)
+Payload = 0df202431ee7f251a38aaf6aa8cd313782bd293af9114005
+
+Count = 185
+Nonce = 6c8ba94f09cbe6
+Adata = 774ad1a88f8bb063951486d4aec5bf82d5fc535bd0b952f86200c123c37fa496
+CT = 0ca17e8f89bea67db48a8f132ef6c6df7a292914d401299af6bf3800
+Result = Fail (2 - CT changed)
+
+Count = 186
+Nonce = 1f670302fcdcc8
+Adata = 1a9ff9698cfc96b581d7115c822e4363d7355ec5daed2eae5bf89ee944ac7d9c
+CT = 0ce543569e8187f3cec70399ff922e4903cb1d12f990f05613244cf6
+Result = Fail (1 - Adata changed)
+
+Count = 187
+Nonce = 5d05f658c729a2
+Adata = dd9564c1431ed490b17ef69f6115805e54ef156ef4e10e58f7d57a7e86626352
+CT = 3acdbc163a350f312791b152a41e57627b1cc8bf3e41c8aea5876de8
+Result = Fail (2 - CT changed)
+
+Count = 188
+Nonce = 22a77db9fcbc95
+Adata = 86bf1739c10f63df734ee3e60ac40ff5636c49f68ca4c16ece289609eb413e7a
+CT = 604518e436edf7a0561d5e284f3915839a6d28cb06ef792a1970ed17
+Result = Fail (2 - CT changed)
+
+Count = 189
+Nonce = 491e32b0bbfa4c
+Adata = 75bef075c79d6cfd7fc73aefd67b2d215be0648937477ba606b1fe1be591239e
+CT = fc79b520d67da891e63654d7927db6c8012c96985a0059d5f68d8da4
+Result = Fail (1 - Adata changed)
+
+Count = 190
+Nonce = bc4b7d3a380be0
+Adata = 353dbb41e2d525a9f4fcd858d0f0aa1b1e86ac0f936d5c09c6b61c343f94e3fc
+CT = d86bb51a98770098d0feb39170bd979199a8f741041df13790ee4c14
+Result = Fail (1 - Adata changed)
+
+Count = 191
+Nonce = a840e98df72ae9
+Adata = 22c6607732ef1bdc7fcf6197e037cdadd7ee17c008552dd9f04b8564d34fb17c
+CT = 51b6b928bdd1cc0bd0a0aed2cda302472d618ffaa60e179029c87855
+Result = Pass (0)
+Payload = a2f53385618b41301f4e3ea4c597f411103dac2b37abf5da
+
+Count = 192
+Nonce = 39d93c3cf31a6f
+Adata = 937dfac5cded938438f4e97aabd9beb50dba40f824198260a89729479cfe6869
+CT = d0abab9b8e9d6c11bb9c15bea8a486704bed32c57297055b4de8ed8d
+Result = Pass (0)
+Payload = c1bdef96dc868446be48491b160504546f2a40dd581f9582
+
+Count = 193
+Nonce = 0bbc177019321e
+Adata = f6e02678820f5ccbede6cbded02d6dd58d486166d7b18ee975a688af421fb795
+CT = 92fd519a966c0fbdd7087ff5a1bd946cd663502db378383531d69947
+Result = Pass (0)
+Payload = 72a70954d22ad722fc32756afce67b344b2f3c55fe1d9eed
+
+Count = 194
+Nonce = ad048eb2ad7526
+Adata = 0d2739cfdac782b61f484fa1a423c478c414397ec420327963d79112b2d70a7e
+CT = 7f239b1916830161f3b52b7ab13542a5a0a97a17f30ca5fa30768d4d
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 24, Nlen = 7, Tlen = 16]
+
+Key = a7aa635ea51b0bb20a092bd5573e728ccd4b3e8cdd2ab33d
+
+Count = 195
+Nonce = 5a8aa485c316e9
+Adata = 3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22ec22b1a268f88e2c
+CT = 6aab64c4787599d8f213446beadb16e08dba60e97f56dbd14d1d980d6fe0fb44b421992662b97975
+Result = Pass (0)
+Payload = a265480ca88d5f536db0dc6abc40faf0d05be7a966977768
+
+Count = 196
+Nonce = fdd2d6f503c915
+Adata = 5b92394f21ddc3ad49d9b0881b829a5935cb3a4d23e292a62fb66b5e7ab7020e
+CT = 4980b2ee49b1aaf393175f5ab9bae95ec7904557dfa206603c51d36c826f01384100886198a7f6a3
+Result = Fail (2 - CT changed)
+
+Count = 197
+Nonce = 27d73d58100054
+Adata = f6468542923be79b4b06dfe70920d57d1da73a9c16f9c9a12d810d7de0d12467
+CT = 86a02bdd6ae733eee26f8eab898b336105978b5bbd6df781758a111aae4f735b7dd4d9802f2a8406
+Result = Fail (1 - Adata changed)
+
+Count = 198
+Nonce = dd16e0ce1250e3
+Adata = bc65cfd65e9863c8b7457d58afa6bdb48a84170d8aa97ba5b397b52ad17a9242
+CT = 59cfab8956813c48e09332a2bb8a30dbcdf5afb2529532ab8cef14ebc2951069739d5d657d82addb
+Result = Fail (1 - Adata changed)
+
+Count = 199
+Nonce = ccee19d037cf4a
+Adata = c026696e6425e6c33f45b4145febf1137e7ac26383c9f5aa4cd4e5e8abb19e07
+CT = 67d989ea935b9ce190e3a7f3b645305e1e308a7fe617f80f170a2b9c309de6c2326115a76efbdf98
+Result = Pass (0)
+Payload = 0df202431ee7f251a38aaf6aa8cd313782bd293af9114005
+
+Count = 200
+Nonce = 6c8ba94f09cbe6
+Adata = 774ad1a88f8bb063951486d4aec5bf82d5fc535bd0b952f86200c123c37fa496
+CT = 2522a5e4d157193ef2c264cfe877db8ac75b3cc5aab08a814bcd14af0205af716f2b864f0c397f65
+Result = Fail (2 - CT changed)
+
+Count = 201
+Nonce = 1f670302fcdcc8
+Adata = 1a9ff9698cfc96b581d7115c822e4363d7355ec5daed2eae5bf89ee944ac7d9c
+CT = 4536422bbad220079ee09e700e103efdaac832d016a20813762d5d8adafe75a191310a2618930c48
+Result = Fail (1 - Adata changed)
+
+Count = 202
+Nonce = 5d05f658c729a2
+Adata = dd9564c1431ed490b17ef69f6115805e54ef156ef4e10e58f7d57a7e86626352
+CT = d6711a78adf54f4effe647d531c4618cf32e3037eb700580206f80080dfa3e66e6371c0cde6cd205
+Result = Fail (2 - CT changed)
+
+Count = 203
+Nonce = 22a77db9fcbc95
+Adata = 86bf1739c10f63df734ee3e60ac40ff5636c49f68ca4c16ece289609eb413e7a
+CT = e44034a397778e1c6babab27f5a50fa4aac0e83d6b3eb25db1b5b2b35c8a8125efccd1f4102f3e82
+Result = Fail (2 - CT changed)
+
+Count = 204
+Nonce = 491e32b0bbfa4c
+Adata = 75bef075c79d6cfd7fc73aefd67b2d215be0648937477ba606b1fe1be591239e
+CT = b8e31c5910623e405f2ebf65821963e5b8814043612395feca36f53b01943f03cb8b69b5af53e505
+Result = Fail (1 - Adata changed)
+
+Count = 205
+Nonce = bc4b7d3a380be0
+Adata = 353dbb41e2d525a9f4fcd858d0f0aa1b1e86ac0f936d5c09c6b61c343f94e3fc
+CT = 4000faf8558f2f4e01e45e90796cd236e5211d1704270f31c3bfc6851049d32105fd16bd45b29f29
+Result = Fail (1 - Adata changed)
+
+Count = 206
+Nonce = a840e98df72ae9
+Adata = 22c6607732ef1bdc7fcf6197e037cdadd7ee17c008552dd9f04b8564d34fb17c
+CT = 53bb608f6236798839af35888cb0fa4797b599271084cc13847b022733ca5a5e3c4d472332484b7f
+Result = Pass (0)
+Payload = a2f53385618b41301f4e3ea4c597f411103dac2b37abf5da
+
+Count = 207
+Nonce = 39d93c3cf31a6f
+Adata = 937dfac5cded938438f4e97aabd9beb50dba40f824198260a89729479cfe6869
+CT = be54551d1d2f1b3eb60ffe3b165524ff90ca09fb252bf21c1c79edbf38c50e0f240a2d70f65aa79f
+Result = Pass (0)
+Payload = c1bdef96dc868446be48491b160504546f2a40dd581f9582
+
+Count = 208
+Nonce = 0bbc177019321e
+Adata = f6e02678820f5ccbede6cbded02d6dd58d486166d7b18ee975a688af421fb795
+CT = f07c1072d8f8e077dfbb3ad86dd92d32b41f29e647dcd7e3a82cd3ebaf6c2d3e21749bdf570ad28d
+Result = Pass (0)
+Payload = 72a70954d22ad722fc32756afce67b344b2f3c55fe1d9eed
+
+Count = 209
+Nonce = ad048eb2ad7526
+Adata = 0d2739cfdac782b61f484fa1a423c478c414397ec420327963d79112b2d70a7e
+CT = 7f7cf7f4d0645934cb0a5e67b4227a909aa55dba09b2c39cef93a8759845326683a0d9c22151f486
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 24, Nlen = 13, Tlen = 4]
+
+Key = a7aa635ea51b0bb20a092bd5573e728ccd4b3e8cdd2ab33d
+
+Count = 210
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = 16e543d0e20615ff0df15acd9927ddfe40668a54bb854cccc25e9fce
+Result = Pass (0)
+Payload = 8739b4bea1a099fe547499cbc6d1b13d849b8084c9b6acc5
+
+Count = 211
+Nonce = 0812757ad0cc4d17c4cfe7a642
+Adata = ec6c44a7e94e51a3ca6dee229098391575ec7213c85267fbf7492fdbeee61b10
+CT = df35b109caf690656ae278bbd8f8bba687a2ce11b105dae98ecedb3e
+Result = Fail (2 - CT changed)
+
+Count = 212
+Nonce = eff510acc1b85f35029cf7dc00
+Adata = 0923b927b8295c5dfaf67da55e5014293bc8c708fda50af06c1e8aef31cccc86
+CT = 7075da2291e2cb527eb926ed08d8020c5f8f0f2d4a6a4745728da544
+Result = Fail (1 - Adata changed)
+
+Count = 213
+Nonce = 3d13d09057190366c63c8750e9
+Adata = 77e27aa9a7bf30e130c862a3296a1cd7a10195ed1d940f2c97bfff47c6f06e32
+CT = 18a77a66457b53286b1aea0845304cac8e66a02d5c642e4c02a9b9bc
+Result = Fail (1 - Adata changed)
+
+Count = 214
+Nonce = e3c03ef7e1d31961ee0b97bd99
+Adata = 8a3676dd640821b58fb0f0329855fd5882c376ea166b958b7aaad223054e5784
+CT = 24e1d3820101412d8f4d57118cab8f7e489d5cac78802dd5ccf8ecf0
+Result = Pass (0)
+Payload = 92973ce707733a73118c8ce6b5e3fc77a17f448310c0197f
+
+Count = 215
+Nonce = 5d165ddd4e599387af5967cae6
+Adata = e374f875ce829b62c98fbd67bcf128b5647f25fff9a643300eb95559b889baed
+CT = b5929bc9648e24a553c5cd953ecb9d67ee508d2d4ac7b46e661181d5
+Result = Fail (2 - CT changed)
+
+Count = 216
+Nonce = fcec171162a27a96066181fab2
+Adata = cf431cc3671ec468ea86f6cc09842fcf3a84b3ef0fa1c7b20b232145b4469d62
+CT = 54aa018dc7fdf8a54809e1393d18031bab4aa5ca35c201907d74517d
+Result = Fail (1 - Adata changed)
+
+Count = 217
+Nonce = 2fa8120398d1a946f391367cf6
+Adata = 92558a239c8e13230754f23aec67b153db29fdfc7daf641778185dd2931d89da
+CT = 69bcc300a459862b3cd284c15dd4af53dc7e95f3067bb8254a8edd83
+Result = Fail (2 - CT changed)
+
+Count = 218
+Nonce = 88e0ae338bbca9d4299b294354
+Adata = 5db5c388dbadc9f175a5cd5a1472a458d25acd7fb9c951c0cd45edf64da473bb
+CT = 5c2d2df0d8aade3e5ae0f8d8b4b4d7c565817a31b2865dc270ad39a6
+Result = Fail (2 - CT changed)
+
+Count = 219
+Nonce = 4862e36296d6afc9399a95bbb4
+Adata = 36d82ebd0e0f5fe3b12946d041ae5aee16e6d17025406dd776f499bbd8e8b4c8
+CT = df1b3f98b6b0060191e7eb817f5908ddc0bc6f83860349e8ae423997
+Result = Fail (1 - Adata changed)
+
+Count = 220
+Nonce = 2f360a4715074e942244ab7f9b
+Adata = f0087b0086a081c1071481f033a8be8e940c36763084329bb8461b9102238f4f
+CT = 16e59dd38395c7be7f580371edabb1e9bf21270de270aa283309108e
+Result = Fail (1 - Adata changed)
+
+Count = 221
+Nonce = 93e08854560edb096e5d654086
+Adata = bdc60dff08bfd5d44320b75c61e456fd4333c9c3d0294d4a48d936dfd5922ce2
+CT = 0ef8981dd37c055a3c3e14786fc662b2a11065964911d35ebcc87096
+Result = Pass (0)
+Payload = 569e4aec88dd51ca519c0a00c922ee33d3559b98a32d7906
+
+Count = 222
+Nonce = e3f37b68ff508cfe295441d9e3
+Adata = b2b6c5782e4f128467c589d2a6cf55ef12877adb771bbb6245c5bba9dcfd6208
+CT = fc1870cfc440f74f73f40e682cf4713d027c297b9426c3efe981e935
+Result = Pass (0)
+Payload = 02b5511204bd55f7c37973e26f6df5883c0a530f07c7f8c2
+
+Count = 223
+Nonce = ea98ec44f5a86715014783172e
+Adata = e4692b9f06b666c7451b146c8aeb07a6e30c629d28065c3dde5940325b14b810
+CT = 9fc2c462dff1ba9756772d73de5c4e822b5ea0bc88845a323b98de4f
+Result = Pass (0)
+Payload = 4da40b80579c1d9a5309f7efecb7c059a2f914511ca5fc10
+
+Count = 224
+Nonce = 5a16a8902bd70fa06cfe184c57
+Adata = 399d6b0652836457ec4f701f0dc0e5aed73d16585d61cb1bb5b7ee824fc287c8
+CT = 05fc586d5c780b8e06f618b5bb85f591665a54390eba4e14af3b74e1
+Result = Fail (2 - CT changed)
+
+[Alen = 32, Plen = 24, Nlen = 13, Tlen = 16]
+
+Key = 26511fb51fcfa75cb4b44da75a6e5a0eb8d9c8f3b906f886
+
+Count = 225
+Nonce = 5a8aa485c316e9403aff859fbb
+Adata = a16a2e741f1cd9717285b6d882c1fc53655e9773761ad697a7ee6410184c7982
+CT = c5b0b2ef17498c5570eb335df4588032958ba3d69bf6f3178464a6f7fa2b76744e8e8d95691cecb8
+Result = Pass (0)
+Payload = 8739b4bea1a099fe547499cbc6d1b13d849b8084c9b6acc5
+
+Count = 226
+Nonce = 0812757ad0cc4d17c4cfe7a642
+Adata = ec6c44a7e94e51a3ca6dee229098391575ec7213c85267fbf7492fdbeee61b10
+CT = d1f0518929f4ae2f0543de2a7dfe4bb0110bb3057e524a1c06bd6dc2e6bcc3436cffb969ae900388
+Result = Fail (2 - CT changed)
+
+Count = 227
+Nonce = eff510acc1b85f35029cf7dc00
+Adata = 0923b927b8295c5dfaf67da55e5014293bc8c708fda50af06c1e8aef31cccc86
+CT = 1aa7dfa3a9818142c4971cbf4f64d4cbdbd354c6958ef474bb56d90669c726d866fe2206b8828727
+Result = Fail (1 - Adata changed)
+
+Count = 228
+Nonce = 3d13d09057190366c63c8750e9
+Adata = 77e27aa9a7bf30e130c862a3296a1cd7a10195ed1d940f2c97bfff47c6f06e32
+CT = 90352a5ec92d4fa52a96ae28251a57933728b2a3670e2ecd9953fec4e091b3573214e1ecac1ac00c
+Result = Fail (1 - Adata changed)
+
+Count = 229
+Nonce = e3c03ef7e1d31961ee0b97bd99
+Adata = 8a3676dd640821b58fb0f0329855fd5882c376ea166b958b7aaad223054e5784
+CT = eaa995946ed91d6a08ade14b260ac752cbd1081d5a7cad90783618374f6d03df28ee57a1a5aa38d8
+Result = Pass (0)
+Payload = 92973ce707733a73118c8ce6b5e3fc77a17f448310c0197f
+
+Count = 230
+Nonce = 5d165ddd4e599387af5967cae6
+Adata = e374f875ce829b62c98fbd67bcf128b5647f25fff9a643300eb95559b889baed
+CT = 0e320c4ece6ef0305a431a07a5a34d463ec4a37fc513c4b947bb3f30d6e674d10a496806c1c8933e
+Result = Fail (2 - CT changed)
+
+Count = 231
+Nonce = fcec171162a27a96066181fab2
+Adata = cf431cc3671ec468ea86f6cc09842fcf3a84b3ef0fa1c7b20b232145b4469d62
+CT = 10685888091597c50acc54b2fb65150b83a7115351d6f8bd7dd7ee3f75cfb47fa72433644f9cf62e
+Result = Fail (1 - Adata changed)
+
+Count = 232
+Nonce = 2fa8120398d1a946f391367cf6
+Adata = 92558a239c8e13230754f23aec67b153db29fdfc7daf641778185dd2931d89da
+CT = e456abf9ee83e0a68fbdb09c4a7afaba0efb0aa6d74a17c443314076072a0ebd253fe1ab4883ebea
+Result = Fail (2 - CT changed)
+
+Count = 233
+Nonce = 88e0ae338bbca9d4299b294354
+Adata = 5db5c388dbadc9f175a5cd5a1472a458d25acd7fb9c951c0cd45edf64da473bb
+CT = 5adadfd296edaf4bea92c8245983dc31b11335f682fb222c16a72444f0949868f0e71907acbb29f4
+Result = Fail (2 - CT changed)
+
+Count = 234
+Nonce = 4862e36296d6afc9399a95bbb4
+Adata = 36d82ebd0e0f5fe3b12946d041ae5aee16e6d17025406dd776f499bbd8e8b4c8
+CT = c2bb4d5a830646b3f8bf84044851c3b676c4ec02e43dcbf1ab2025208191d73041c038cf2562bb8c
+Result = Fail (1 - Adata changed)
+
+Count = 235
+Nonce = 2f360a4715074e942244ab7f9b
+Adata = f0087b0086a081c1071481f033a8be8e940c36763084329bb8461b9102238f4f
+CT = 9589b8abcb47e54e6e8fad3e64fec7ed4f70ac435bb3e548b7e6d183efa1f51b7ff31eaa52ed59ba
+Result = Fail (1 - Adata changed)
+
+Count = 236
+Nonce = 93e08854560edb096e5d654086
+Adata = bdc60dff08bfd5d44320b75c61e456fd4333c9c3d0294d4a48d936dfd5922ce2
+CT = af63f27e2a9e70f106477493dc141d16a1d059dd7a8a7810d990b642039f24755790332b3cc47c49
+Result = Pass (0)
+Payload = 569e4aec88dd51ca519c0a00c922ee33d3559b98a32d7906
+
+Count = 237
+Nonce = e3f37b68ff508cfe295441d9e3
+Adata = b2b6c5782e4f128467c589d2a6cf55ef12877adb771bbb6245c5bba9dcfd6208
+CT = 1d2ae88c878684a0b404986252b3a7583e1a5a51163ddc606d3968fdceaae5138c411a29d0d333ee
+Result = Pass (0)
+Payload = 02b5511204bd55f7c37973e26f6df5883c0a530f07c7f8c2
+
+Count = 238
+Nonce = ea98ec44f5a86715014783172e
+Adata = e4692b9f06b666c7451b146c8aeb07a6e30c629d28065c3dde5940325b14b810
+CT = 30c154c616946eccc2e241d336ad33720953e449a0e6b0f0dbf8e9464909bdf337e48093c082a10b
+Result = Pass (0)
+Payload = 4da40b80579c1d9a5309f7efecb7c059a2f914511ca5fc10
+
+Count = 239
+Nonce = 5a16a8902bd70fa06cfe184c57
+Adata = 399d6b0652836457ec4f701f0dc0e5aed73d16585d61cb1bb5b7ee824fc287c8
+CT = 0c95b692b07b39039b40c80cf52ff71608ae87c973ac9ccb88bba8f204bb98b17cb3c8644e472b1e
+Result = Fail (2 - CT changed)
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT256.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT256.rsp
new file mode 100644
index 0000000000..b8045d8291
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT256.rsp
@@ -0,0 +1,1589 @@
+# CAVS 11.0
+# "CCM-DVPT" information
+# AES Keylen: 256
+# Generated on Tue Mar 15 08:09:26 2011
+
+
+[Alen = 0, Plen = 0, Nlen = 7, Tlen = 4]
+
+Key = eda32f751456e33195f1f499cf2dc7c97ea127b6d488f211ccc5126fbb24afa6
+
+Count = 0
+Nonce = a544218dadd3c1
+Adata = 00
+CT = 469c90bb
+Result = Pass
+Payload = 00
+
+Count = 1
+Nonce = d3d5424e20fbec
+Adata = 00
+CT = 46a908ed
+Result = Fail
+
+Count = 2
+Nonce = e776620a3bd961
+Adata = 00
+CT = fdd35c4d
+Result = Fail
+
+Count = 3
+Nonce = 6c7a3be9f9ad55
+Adata = 00
+CT = 869ce60e
+Result = Fail
+
+Count = 4
+Nonce = dbb3923156cfd6
+Adata = 00
+CT = 1302d515
+Result = Pass
+Payload = 00
+
+Count = 5
+Nonce = b390f67eaef8f5
+Adata = 00
+CT = 156416ee
+Result = Fail
+
+Count = 6
+Nonce = a259c114eaac89
+Adata = 00
+CT = 4fe06e92
+Result = Pass
+Payload = 00
+
+Count = 7
+Nonce = 7fc8804fef18ef
+Adata = 00
+CT = 611091aa
+Result = Fail
+
+Count = 8
+Nonce = fbaf4cbc49fa0f
+Adata = 00
+CT = 696e9371
+Result = Fail
+
+Count = 9
+Nonce = 2ed0c8761dbf04
+Adata = 00
+CT = a0e0a2cb
+Result = Fail
+
+Count = 10
+Nonce = 346bb04ea0db86
+Adata = 00
+CT = 43cc0375
+Result = Fail
+
+Count = 11
+Nonce = e1be89af98ffd7
+Adata = 00
+CT = e5417f6b
+Result = Pass
+Payload = 00
+
+Count = 12
+Nonce = a6a0d57aaaf012
+Adata = 00
+CT = fff8a068
+Result = Fail
+
+Count = 13
+Nonce = 1aa758eb2f9a28
+Adata = 00
+CT = f8fa8e71
+Result = Pass
+Payload = 00
+
+Count = 14
+Nonce = 2911167fc98fc3
+Adata = 00
+CT = 0bfa2d9d
+Result = Fail
+
+[Alen = 0, Plen = 0, Nlen = 7, Tlen = 16]
+
+Key = e1b8a927a95efe94656677b692662000278b441c79e879dd5c0ddc758bdc9ee8
+
+Count = 15
+Nonce = a544218dadd3c1
+Adata = 00
+CT = 8207eb14d33855a52acceed17dbcbf6e
+Result = Pass
+Payload = 00
+
+Count = 16
+Nonce = d3d5424e20fbec
+Adata = 00
+CT = 60f8e127cb4d30db6df0622158cd931d
+Result = Fail
+
+Count = 17
+Nonce = e776620a3bd961
+Adata = 00
+CT = 4239f29871651e9a26b8b06ffc5b3748
+Result = Fail
+
+Count = 18
+Nonce = 6c7a3be9f9ad55
+Adata = 00
+CT = 5d35364c621fe8959dfe70ab44700fbe
+Result = Fail
+
+Count = 19
+Nonce = dbb3923156cfd6
+Adata = 00
+CT = e4dc5e03aacea691262ee69cee8ffbbe
+Result = Pass
+Payload = 00
+
+Count = 20
+Nonce = b390f67eaef8f5
+Adata = 00
+CT = c8eb7643b4ed3c796c3873e8c6624e0d
+Result = Fail
+
+Count = 21
+Nonce = a259c114eaac89
+Adata = 00
+CT = f79c53fd5e69835b7e70496ea999718b
+Result = Pass
+Payload = 00
+
+Count = 22
+Nonce = 7fc8804fef18ef
+Adata = 00
+CT = 687e00723a419fa81c0923b8b8e245ae
+Result = Fail
+
+Count = 23
+Nonce = fbaf4cbc49fa0f
+Adata = 00
+CT = 499ab350309ad6091ec4aaf6bf0cbd00
+Result = Fail
+
+Count = 24
+Nonce = 2ed0c8761dbf04
+Adata = 00
+CT = c27b9f14787dc5375f59d0c561a23446
+Result = Fail
+
+Count = 25
+Nonce = 346bb04ea0db86
+Adata = 00
+CT = 655c737722c78ac96582a883d407b2bb
+Result = Fail
+
+Count = 26
+Nonce = e1be89af98ffd7
+Adata = 00
+CT = 10d3f6fe08280d45e67e58fe41a7f036
+Result = Pass
+Payload = 00
+
+Count = 27
+Nonce = a6a0d57aaaf012
+Adata = 00
+CT = b4e425e43edb92c606f7cb2de8a06932
+Result = Fail
+
+Count = 28
+Nonce = 1aa758eb2f9a28
+Adata = 00
+CT = 2590df2453cb94c304ba0a2bff3f3c71
+Result = Pass
+Payload = 00
+
+Count = 29
+Nonce = 2911167fc98fc3
+Adata = 00
+CT = 1f344e30dfa95b2319e274caa5780e60
+Result = Fail
+
+[Alen = 0, Plen = 0, Nlen = 13, Tlen = 4]
+
+Key = e1b8a927a95efe94656677b692662000278b441c79e879dd5c0ddc758bdc9ee8
+
+Count = 30
+Nonce = a544218dadd3c10583db49cf39
+Adata = 00
+CT = 8a19a133
+Result = Pass
+Payload = 00
+
+Count = 31
+Nonce = 3c0e2815d37d844f7ac240ba9d
+Adata = 00
+CT = 2e317f1b
+Result = Fail
+
+Count = 32
+Nonce = 75549e7e5657e5fe19872fcee0
+Adata = 00
+CT = 979bdcfe
+Result = Fail
+
+Count = 33
+Nonce = d071ff72735820d73485870e83
+Adata = 00
+CT = 8ef89acf
+Result = Fail
+
+Count = 34
+Nonce = 79ac204a26b9fee1132370c20f
+Adata = 00
+CT = 154024b2
+Result = Pass
+Payload = 00
+
+Count = 35
+Nonce = a64bbc3d6d377dab513f7d9ce8
+Adata = 00
+CT = 8dbcc439
+Result = Fail
+
+Count = 36
+Nonce = 0545fd9ecbc73ccdbbbd4244fd
+Adata = 00
+CT = 5c349fb2
+Result = Pass
+Payload = 00
+
+Count = 37
+Nonce = 182fb47a12becf0bfe65df1287
+Adata = 00
+CT = 79df3e02
+Result = Fail
+
+Count = 38
+Nonce = f342059a6f9dc14226b40debc4
+Adata = 00
+CT = fbc2c500
+Result = Fail
+
+Count = 39
+Nonce = 6cbfe6bb4c9b171b93d28e9f8f
+Adata = 00
+CT = 2fac1bca
+Result = Fail
+
+Count = 40
+Nonce = 82877df921c6ade43064ad963e
+Adata = 00
+CT = 99948f6e
+Result = Fail
+
+Count = 41
+Nonce = 0a37f2e7c66490e97285f1b09e
+Adata = 00
+CT = c59bf14c
+Result = Pass
+Payload = 00
+
+Count = 42
+Nonce = d7b9c346ce2f8bad9623122e10
+Adata = 00
+CT = b764c393
+Result = Fail
+
+Count = 43
+Nonce = c1ad812bf2bbb2cdaee4636ee7
+Adata = 00
+CT = 5b96f41d
+Result = Pass
+Payload = 00
+
+Count = 44
+Nonce = b6ce7d00731184b24428df046b
+Adata = 00
+CT = f7e12df1
+Result = Fail
+
+[Alen = 0, Plen = 0, Nlen = 13, Tlen = 16]
+
+Key = af063639e66c284083c5cf72b70d8bc277f5978e80d9322d99f2fdc718cda569
+
+Count = 45
+Nonce = a544218dadd3c10583db49cf39
+Adata = 00
+CT = 97e1a8dd4259ccd2e431e057b0397fcf
+Result = Pass
+Payload = 00
+
+Count = 46
+Nonce = 3c0e2815d37d844f7ac240ba9d
+Adata = 00
+CT = 5a9596c511ea6a8671adefc4f2157d8b
+Result = Fail
+
+Count = 47
+Nonce = 75549e7e5657e5fe19872fcee0
+Adata = 00
+CT = 66f5c53efbc74fa02dedc303fd95133a
+Result = Fail
+
+Count = 48
+Nonce = d071ff72735820d73485870e83
+Adata = 00
+CT = 2dfd3c852f68eace45acf433a6aa9c05
+Result = Fail
+
+Count = 49
+Nonce = 79ac204a26b9fee1132370c20f
+Adata = 00
+CT = 5c8c9a5b97be8c7bc01ca8d693b809f9
+Result = Pass
+Payload = 00
+
+Count = 50
+Nonce = a64bbc3d6d377dab513f7d9ce8
+Adata = 00
+CT = ec093121bdcd589285f2262be8db5c4e
+Result = Fail
+
+Count = 51
+Nonce = 0545fd9ecbc73ccdbbbd4244fd
+Adata = 00
+CT = 84201662b213c7a1ff0c1b3c25e4ec45
+Result = Pass
+Payload = 00
+
+Count = 52
+Nonce = 182fb47a12becf0bfe65df1287
+Adata = 00
+CT = bbe746d6d31e8e9745faed4095ab8d5d
+Result = Fail
+
+Count = 53
+Nonce = f342059a6f9dc14226b40debc4
+Adata = 00
+CT = 646c1258dc4aa6fc380818e70e5f4328
+Result = Fail
+
+Count = 54
+Nonce = 6cbfe6bb4c9b171b93d28e9f8f
+Adata = 00
+CT = 15fa37ca7f2883a4642c1ed41b8f6293
+Result = Fail
+
+Count = 55
+Nonce = 82877df921c6ade43064ad963e
+Adata = 00
+CT = c6acf5e5ded4efb2c314370ebb9e9cde
+Result = Fail
+
+Count = 56
+Nonce = 0a37f2e7c66490e97285f1b09e
+Adata = 00
+CT = 586e728193ce6db9a926b03b2d77dd6e
+Result = Pass
+Payload = 00
+
+Count = 57
+Nonce = d7b9c346ce2f8bad9623122e10
+Adata = 00
+CT = 642a187e71feff5989e28184aded0199
+Result = Fail
+
+Count = 58
+Nonce = c1ad812bf2bbb2cdaee4636ee7
+Adata = 00
+CT = 64864d21b6ee3fca13f07fc0486e232d
+Result = Pass
+Payload = 00
+
+Count = 59
+Nonce = b6ce7d00731184b24428df046b
+Adata = 00
+CT = 58c63ce68f132d30d177c5834344cc5d
+Result = Fail
+
+[Alen = 0, Plen = 24, Nlen = 7, Tlen = 4]
+
+Key = af063639e66c284083c5cf72b70d8bc277f5978e80d9322d99f2fdc718cda569
+
+Count = 60
+Nonce = a544218dadd3c1
+Adata = 00
+CT = 64a1341679972dc5869fcf69b19d5c5ea50aa0b5e985f5b722aa8d59
+Result = Pass
+Payload = d3d5424e20fbec43ae495353ed830271515ab104f8860c98
+
+Count = 61
+Nonce = bfcda8b5a2d0d2
+Adata = 00
+CT = c5b7f802bffc498c1626e3774f1d9f94045dfd8e1a10a20277d00a75
+Result = Fail
+
+Count = 62
+Nonce = 6bae7f35c56b27
+Adata = 00
+CT = bf432e246b7fa4aff8b3ada738432b51f6872ed92284db9d28588021
+Result = Fail
+
+Count = 63
+Nonce = c5e4214b1bf209
+Adata = 00
+CT = 0d5760ad0e156e401120a1ebd1b139248784c88e10e3425437921120
+Result = Fail
+
+Count = 64
+Nonce = 9d773a31fe2ec7
+Adata = 00
+CT = 5acfbe5e488976d8b9b77e69a736e8c919053f9415551209dce2d25e
+Result = Pass
+Payload = 839d8cfa2c921c3cceb7d1f46bd2eaad706e53f64523d8c0
+
+Count = 65
+Nonce = f42cb0cce9efb6
+Adata = 00
+CT = be8be6046ac58411a00c131dd4a72d565f98d87a2c89124b1ef530d0
+Result = Fail
+
+Count = 66
+Nonce = 24b7a65391f88b
+Adata = 00
+CT = f00628e10e8e0115b4a4532a1212a23aade4090832c1972d750125f3
+Result = Pass
+Payload = 3bed52236182c19418867d468dbf47c8aac46c02445f99bb
+
+Count = 67
+Nonce = d2a7eb45780df3
+Adata = 00
+CT = 9078151f674d5f7b56e2451b0316156f776459f17d277e0108aaaf93
+Result = Fail
+
+Count = 68
+Nonce = 046cbfd26093d8
+Adata = 00
+CT = 921cbecce3b06f3d655a5a0a4d212320d4f147575079fd23bd95e677
+Result = Fail
+
+Count = 69
+Nonce = 51b13b0b04d077
+Adata = 00
+CT = 8cab1ff22d474e9863c153e84680e2a66981f036051360477e2ebb1d
+Result = Fail
+
+Count = 70
+Nonce = ce2e9967bf9eb7
+Adata = 00
+CT = 15f476b5aefe072548a54f59506d9c3b9ce29025340214be662f8684
+Result = Fail
+
+Count = 71
+Nonce = b672c91376f533
+Adata = 00
+CT = 758aa03dc72c362c43b5f85bfaa3db4a74860887a8c29e47d5642830
+Result = Pass
+Payload = 4f7a561e61b7861719e4445057ac9b74a9be953b772b09ec
+
+Count = 72
+Nonce = 62f6f1872462d8
+Adata = 00
+CT = ec645769b22161567e6a7e23aa06575bc767a34aa54d3cba01472fe1
+Result = Fail
+
+Count = 73
+Nonce = a6d01fb88ca547
+Adata = 00
+CT = 615cbeabbe163ba8bc9c073df9ad40833fcf3f424644ccc37aa999d7
+Result = Pass
+Payload = a36155de477364236591e453008114075b4872120ef17264
+
+Count = 74
+Nonce = 46ad6ebbd8644a
+Adata = 00
+CT = 0ed6cc6451de57ca672d56dee45d4548a810d5c49dfe442dd27b7cf2
+Result = Fail
+
+[Alen = 0, Plen = 24, Nlen = 7, Tlen = 16]
+
+Key = f7079dfa3b5c7b056347d7e437bcded683abd6e2c9e069d333284082cbb5d453
+
+Count = 75
+Nonce = a544218dadd3c1
+Adata = 00
+CT = bc51c3925a960e7732533e4ef3a4f69ee6826de952bcb0fd374f3bb6db8377ebfc79674858c4f305
+Result = Pass
+Payload = d3d5424e20fbec43ae495353ed830271515ab104f8860c98
+
+Count = 76
+Nonce = bfcda8b5a2d0d2
+Adata = 00
+CT = afa1fa8e8a70e26b02161150556d604101fdf423f332c3363275f2a4907d51b734fe7238cebbd48f
+Result = Fail
+
+Count = 77
+Nonce = 6bae7f35c56b27
+Adata = 00
+CT = 72bc8ef21a847047091b673ccf231d35ecf6f4049741703be672f1f22cbe4a5305f19aaa6967237b
+Result = Fail
+
+Count = 78
+Nonce = c5e4214b1bf209
+Adata = 00
+CT = b719f6555fc4e5424273f5903d5672af460413110278707f400b152113c3976be63dcd9e7a84ddac
+Result = Fail
+
+Count = 79
+Nonce = 9d773a31fe2ec7
+Adata = 00
+CT = 4539bb13382b034ddb16a3329148f9243a4eee998fe444aff2870ce198af11f4fb698a67af6c89ad
+Result = Pass
+Payload = 839d8cfa2c921c3cceb7d1f46bd2eaad706e53f64523d8c0
+
+Count = 80
+Nonce = f42cb0cce9efb6
+Adata = 00
+CT = 47cbb909cb12fa0a4b0f1aefd54c52d1edd1533290f76b8ccc98b3f5758972bf08ea9e88dc6e54ed
+Result = Fail
+
+Count = 81
+Nonce = 24b7a65391f88b
+Adata = 00
+CT = 6d0f928352a17d63aca1899cbd305e1f831f1638d27c1e24432704eff9b6830476db3d30d4c103e4
+Result = Pass
+Payload = 3bed52236182c19418867d468dbf47c8aac46c02445f99bb
+
+Count = 82
+Nonce = d2a7eb45780df3
+Adata = 00
+CT = e0e686d917f78b3b0058fed7b084976244789073a6305ff571256981db86f1e768170a104ebfb81d
+Result = Fail
+
+Count = 83
+Nonce = 046cbfd26093d8
+Adata = 00
+CT = 960c573f5d6934a4cac49d06998f827b3d665cf02c998fe55efbbae6a346863a93d52e0321cef8b2
+Result = Fail
+
+Count = 84
+Nonce = 51b13b0b04d077
+Adata = 00
+CT = 7cf8f4806848e34aa7d3bd7e2cb9f5d9ff21395ff6d34826ac2fdc3cc683f6120e405f446a10e0f3
+Result = Fail
+
+Count = 85
+Nonce = ce2e9967bf9eb7
+Adata = 00
+CT = e4f6445ca36e7ee3323f11f6a5ca8ded0c85871e092aa687d254f7765b6155054a5efde28dd38750
+Result = Fail
+
+Count = 86
+Nonce = b672c91376f533
+Adata = 00
+CT = f23ac1426cb1130c9a0913b347d8efafb6ed125913aa678a9dc42d22a5436bc12eff5505edb25e19
+Result = Pass
+Payload = 4f7a561e61b7861719e4445057ac9b74a9be953b772b09ec
+
+Count = 87
+Nonce = 62f6f1872462d8
+Adata = 00
+CT = ac9f131389181b1023f1ee47633aa433fc5d93a87d9ece962db05feb368ab772d977fd97b35262fa
+Result = Fail
+
+Count = 88
+Nonce = a6d01fb88ca547
+Adata = 00
+CT = 773b8eea2e9830297ac11d3c1f6ea4008c96040e83d76d55789d2043179fdd8fdcbd52313b7b15cb
+Result = Pass
+Payload = a36155de477364236591e453008114075b4872120ef17264
+
+Count = 89
+Nonce = 46ad6ebbd8644a
+Adata = 00
+CT = d3fae92043c419fe8ac0d7491ca8041ad089559d895103cf079a2bac0ab4bc249bbdb330181cdd16
+Result = Fail
+
+[Alen = 0, Plen = 24, Nlen = 13, Tlen = 4]
+
+Key = f7079dfa3b5c7b056347d7e437bcded683abd6e2c9e069d333284082cbb5d453
+
+Count = 90
+Nonce = a544218dadd3c10583db49cf39
+Adata = 00
+CT = 63e00d30e4b08fd2a1cc8d70fab327b2368e77a93be4f4123d14fb3f
+Result = Pass
+Payload = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e
+
+Count = 91
+Nonce = 894dcaa61008eb8fb052c60d41
+Adata = 00
+CT = bb5425b3869b76856ec58e39886fb6f6f2ac13fe44cb132d8d0c0099
+Result = Fail
+
+Count = 92
+Nonce = 8feba0d720aa4a5e35abc99e82
+Adata = 00
+CT = 2ca3be419d5be5ed682f8954d2c20efd9e6d360814735daeefd4365c
+Result = Fail
+
+Count = 93
+Nonce = ed04c9ca8702aec8d0a58e09a0
+Adata = 00
+CT = 3d34bda62db39d6118d6fd5cd38f1a3820ca69ce584b94a2a4ccbef1
+Result = Fail
+
+Count = 94
+Nonce = 1501a243bf60b2cb40d5aa20ca
+Adata = 00
+CT = 377b2f1e7bd9e3d1077038e084f61950761361095f7eeebbf1a72afc
+Result = Pass
+Payload = f5730a05fec31a11662e2e14e362ccc75c7c30cdfccbf994
+
+Count = 95
+Nonce = c6edaf35f0cb433500a8c3a613
+Adata = 00
+CT = 9cef6c889ff51666df9dd1dd2215c15f4b2078a29373c106be4f5f9a
+Result = Fail
+
+Count = 96
+Nonce = d65e0e53f765f9d5e6795c0c5e
+Adata = 00
+CT = 6cab3060bf3b33b163b933c2ed0ba51406810b54d0edcf5c9d0ef4f7
+Result = Pass
+Payload = 20e394c7cc90bdfa6186fc1ba6fff158dfc690e24ba4c9fb
+
+Count = 97
+Nonce = 2b0163418a341588db0f5786d8
+Adata = 00
+CT = f9543a659e9a8b7d75dd859df923817452735f5051726422c08a9e85
+Result = Fail
+
+Count = 98
+Nonce = f16bba081bddda83546eabc9a5
+Adata = 00
+CT = 0d20bf6a9d02da72091d94cdb38743bfea2473d3ab62dcad75dd819a
+Result = Fail
+
+Count = 99
+Nonce = ace99268a32b9c1b5ccd8b0d84
+Adata = 00
+CT = 8bca01e6ebd7ebcdfe52b88e314670ffeb35882fc05394b386e205f9
+Result = Fail
+
+Count = 100
+Nonce = 24570517bbb0df1b3fbd32f57a
+Adata = 00
+CT = 7061c84e2e1d9d58013543ff82666055a1f055c1296c42c8f73a8bf0
+Result = Fail
+
+Count = 101
+Nonce = a6b2371acf8321864c08ddb4d8
+Adata = 00
+CT = c5aa500d1f7c09a590e9d15d6860c4433684e04dd6bc5c8f94f223f0
+Result = Pass
+Payload = 1a43ca628026219c5a430c54021a5a3152ae517167399635
+
+Count = 102
+Nonce = f8e2d4e043f5fe7a72b6117811
+Adata = 00
+CT = e3efa7971e27ba1245ee9491ebdbb28ad9b24b325da5760417af8b14
+Result = Fail
+
+Count = 103
+Nonce = c2b60f14c894ec6178fe79919f
+Adata = 00
+CT = 852cca903d7fdf899807bd14642057534c8a0ccacb8c7b8fb4d35d44
+Result = Pass
+Payload = 3e707d98f19972a63d913e6ea7533af2f41ff98aee2b2a36
+
+Count = 104
+Nonce = 4de4c909ac0cc5fc608baf45ac
+Adata = 00
+CT = e04fd4f5b60833021ed57c98de300bb68d0d892b2bf68e080bc044b1
+Result = Fail
+
+[Alen = 0, Plen = 24, Nlen = 13, Tlen = 16]
+
+Key = 1b0e8df63c57f05d9ac457575ea764524b8610ae5164e6215f426f5a7ae6ede4
+
+Count = 105
+Nonce = a544218dadd3c10583db49cf39
+Adata = 00
+CT = f0050ad16392021a3f40207bed3521fb1e9f808f49830c423a578d179902f912f9ea1afbce1120b3
+Result = Pass
+Payload = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e
+
+Count = 106
+Nonce = 894dcaa61008eb8fb052c60d41
+Adata = 00
+CT = c408190d0fbf5034f83b24a8ed9657331a7ce141de4fae769084607b83bd06e6442eac8dacf583cc
+Result = Fail
+
+Count = 107
+Nonce = 8feba0d720aa4a5e35abc99e82
+Adata = 00
+CT = 52b3d31d02d1b92b38cbae8c510204dde6bf9588e994296c9002a46cfb734290924a15e9c3d99924
+Result = Fail
+
+Count = 108
+Nonce = ed04c9ca8702aec8d0a58e09a0
+Adata = 00
+CT = f80190470212ce1e64bf4c64ca0133d90469abf87a8233c2b238e316c3f9adccce95e8c8b9c7e8d2
+Result = Fail
+
+Count = 109
+Nonce = 1501a243bf60b2cb40d5aa20ca
+Adata = 00
+CT = 254b847d4175bbb44a82b4e805514fa444c224710933f3ec8aaa3f0133234c0cd91609982adc034b
+Result = Pass
+Payload = f5730a05fec31a11662e2e14e362ccc75c7c30cdfccbf994
+
+Count = 110
+Nonce = c6edaf35f0cb433500a8c3a613
+Adata = 00
+CT = 7a5c7bc02aa69efc5a159d653f3993399f69e20752c3b00633255731cd88345860da913bc696fdc1
+Result = Fail
+
+Count = 111
+Nonce = d65e0e53f765f9d5e6795c0c5e
+Adata = 00
+CT = c3618c991b15de641d291419ff6957e8b9ae5046dd8c6f08fafb76adf12f36740347e3edae62bca4
+Result = Pass
+Payload = 20e394c7cc90bdfa6186fc1ba6fff158dfc690e24ba4c9fb
+
+Count = 112
+Nonce = 2b0163418a341588db0f5786d8
+Adata = 00
+CT = 240927bfd671a92aef0311395ad55ae42233ecee53873da4066f55f23d4e55bcbbbf2312ea2d8071
+Result = Fail
+
+Count = 113
+Nonce = f16bba081bddda83546eabc9a5
+Adata = 00
+CT = 4731a7e690c77cd47582ce54a1cec23d94c856b93a9fc767004753689cc84810b8414f1464c0c5b9
+Result = Fail
+
+Count = 114
+Nonce = ace99268a32b9c1b5ccd8b0d84
+Adata = 00
+CT = f0ea12eaff20c3a50674aa1546aaae3bd5c9249108535b21504da83478ede24026ec91fb12769e4b
+Result = Fail
+
+Count = 115
+Nonce = 24570517bbb0df1b3fbd32f57a
+Adata = 00
+CT = 5b164d9752ad6c497a7ab2d0bf8be68fea084ea5839b07b7c9fcf9b9fd5e99767a7b1679b57ea961
+Result = Fail
+
+Count = 116
+Nonce = a6b2371acf8321864c08ddb4d8
+Adata = 00
+CT = bd37326da18e5ac79a1a9512f724bb539530868576b79c67acb5a51d10a58d6584fbe73f1063c31b
+Result = Pass
+Payload = 1a43ca628026219c5a430c54021a5a3152ae517167399635
+
+Count = 117
+Nonce = f8e2d4e043f5fe7a72b6117811
+Adata = 00
+CT = 0455b4dd1069281e10531c0dc180ced9a5ef5d3fe0007470ce54cd7623a80a176f29a01b3abb642e
+Result = Fail
+
+Count = 118
+Nonce = c2b60f14c894ec6178fe79919f
+Adata = 00
+CT = ecd337640022635ce1ed273756d02b7feeb2515614c1fadc95c66d3f411b478853886afd177d88c3
+Result = Pass
+Payload = 3e707d98f19972a63d913e6ea7533af2f41ff98aee2b2a36
+
+Count = 119
+Nonce = 4de4c909ac0cc5fc608baf45ac
+Adata = 00
+CT = e25d7c9fb388596b13a13b885d5b24e31579a3494ad256da830b2b6317716b3975e2b101aebdd920
+Result = Fail
+
+[Alen = 32, Plen = 0, Nlen = 7, Tlen = 4]
+
+Key = 1b0e8df63c57f05d9ac457575ea764524b8610ae5164e6215f426f5a7ae6ede4
+
+Count = 120
+Nonce = a544218dadd3c1
+Adata = d3d5424e20fbec43ae495353ed830271515ab104f8860c988d15b6d36c038eab
+CT = 92d00fbe
+Result = Pass
+Payload = 00
+
+Count = 121
+Nonce = 78c46e3249ca28
+Adata = 232e957c65ffa11988e830d4617d500f1c4a35c1221f396c41ab214f074ca2dc
+CT = 9143e5c4
+Result = Fail
+
+Count = 122
+Nonce = c18d9e7971e2ae
+Adata = 0d40324aa758dbbb5391b5e6edb8a2310c94a4ae51d4fba8a7458d7cc8488baa
+CT = 54337466
+Result = Fail
+
+Count = 123
+Nonce = 162d061351d82d
+Adata = 106d1fb32d948b0d8884f178ad2332a599445fae0f6f71f9ebe53a60b2df9b8e
+CT = bf0bf84c
+Result = Fail
+
+Count = 124
+Nonce = 3fcb328bc96404
+Adata = 10b2ffed4f95af0f98ed4f77c677b5786ad01b31c095bbc6e1c99cf13977abba
+CT = 11250056
+Result = Pass
+Payload = 00
+
+Count = 125
+Nonce = b3fd1eb1422277
+Adata = fa5398cf4cddbe4b45e9f5d7491cd9eefc5e494255961ba3f4b40d22b5f5fe76
+CT = 13de5339
+Result = Fail
+
+Count = 126
+Nonce = c42ac63de6f12a
+Adata = 7ff8d06c5abcc50d3820de34b03089e6c5b202bcbaabca892825553d4d30020a
+CT = 4eed80fd
+Result = Pass
+Payload = 00
+
+Count = 127
+Nonce = d4a7a672237e17
+Adata = d1cdad7fe886d07625a4334be6de4df0645d2a8b4008a8d35f04e6bcf87bfa56
+CT = 4bc2e450
+Result = Fail
+
+Count = 128
+Nonce = b23255372455c6
+Adata = d2e2c3607c40e0a807b86c6ebbc502ab42bdb7f85ab26299cd963bbba3a3a8fa
+CT = b30e6bbd
+Result = Fail
+
+Count = 129
+Nonce = 92272d40475fbb
+Adata = 2f3af695ee33a9ebe6a48ed1b00e337261857110bb104191a54fd13bd960d8bc
+CT = f7c11fe2
+Result = Fail
+
+Count = 130
+Nonce = c4a756f6024a9d
+Adata = 2317b324b6420ada9ea7bf52b71c5faf2485528da5f56b42c517be6355cdb28b
+CT = 76673751
+Result = Fail
+
+Count = 131
+Nonce = 3a1701b185d33a
+Adata = e5d54df8ed9f89b98c5ebb1bc5d5279c2e182784ff4cd9c869ae152e29d7a2b2
+CT = 9a5382c3
+Result = Pass
+Payload = 00
+
+Count = 132
+Nonce = e4db2e80dc3f63
+Adata = 7616bdf5737d01f936072b6576fa76556dfa072f7e2d7de16b9dc96ac8de409c
+CT = 9e632f56
+Result = Fail
+
+Count = 133
+Nonce = 4f490ce07e0150
+Adata = 3e12d09632c644c540077c6f90726d4167423a679322b2000a3f19cfcea02b33
+CT = e1842c46
+Result = Pass
+Payload = 00
+
+Count = 134
+Nonce = b4aaf9ad1bde60
+Adata = 8c96c891456ddec29fe04299506723db2079a6667f96db5d198bf085acf2a4ef
+CT = 9f644671
+Result = Fail
+
+[Alen = 32, Plen = 0, Nlen = 7, Tlen = 16]
+
+Key = a4bc10b1a62c96d459fbaf3a5aa3face7313bb9e1253e696f96a7a8e36801088
+
+Count = 135
+Nonce = a544218dadd3c1
+Adata = d3d5424e20fbec43ae495353ed830271515ab104f8860c988d15b6d36c038eab
+CT = 93af11a08379eb37a16aa2837f09d69d
+Result = Pass
+Payload = 00
+
+Count = 136
+Nonce = 78c46e3249ca28
+Adata = 232e957c65ffa11988e830d4617d500f1c4a35c1221f396c41ab214f074ca2dc
+CT = d19b0c14ec686a7961ca7c386d125a65
+Result = Fail
+
+Count = 137
+Nonce = c18d9e7971e2ae
+Adata = 0d40324aa758dbbb5391b5e6edb8a2310c94a4ae51d4fba8a7458d7cc8488baa
+CT = 02ea916d60e2ceec6d9dc9b1185569b3
+Result = Fail
+
+Count = 138
+Nonce = 162d061351d82d
+Adata = 106d1fb32d948b0d8884f178ad2332a599445fae0f6f71f9ebe53a60b2df9b8e
+CT = fabd2d0c422b47d363ea9936ff4a311b
+Result = Fail
+
+Count = 139
+Nonce = 3fcb328bc96404
+Adata = 10b2ffed4f95af0f98ed4f77c677b5786ad01b31c095bbc6e1c99cf13977abba
+CT = b3884b69d117146cfa5529901753ddc0
+Result = Pass
+Payload = 00
+
+Count = 140
+Nonce = b3fd1eb1422277
+Adata = fa5398cf4cddbe4b45e9f5d7491cd9eefc5e494255961ba3f4b40d22b5f5fe76
+CT = 7162026b6306e74fe32ece8433801bc2
+Result = Fail
+
+Count = 141
+Nonce = c42ac63de6f12a
+Adata = 7ff8d06c5abcc50d3820de34b03089e6c5b202bcbaabca892825553d4d30020a
+CT = b53d93cbfd3d5cf3720cef5080bc7224
+Result = Pass
+Payload = 00
+
+Count = 142
+Nonce = d4a7a672237e17
+Adata = d1cdad7fe886d07625a4334be6de4df0645d2a8b4008a8d35f04e6bcf87bfa56
+CT = c8bbecf69ecf8d10f0863bb4b7cbed51
+Result = Fail
+
+Count = 143
+Nonce = b23255372455c6
+Adata = d2e2c3607c40e0a807b86c6ebbc502ab42bdb7f85ab26299cd963bbba3a3a8fa
+CT = 6037145cc23a175760ae4b573907c80c
+Result = Fail
+
+Count = 144
+Nonce = 92272d40475fbb
+Adata = 2f3af695ee33a9ebe6a48ed1b00e337261857110bb104191a54fd13bd960d8bc
+CT = df7ea77425d631f652ffe096a8157f71
+Result = Fail
+
+Count = 145
+Nonce = c4a756f6024a9d
+Adata = 2317b324b6420ada9ea7bf52b71c5faf2485528da5f56b42c517be6355cdb28b
+CT = 7182b25ef5b113c13fa8f6769e74f1e2
+Result = Fail
+
+Count = 146
+Nonce = 3a1701b185d33a
+Adata = e5d54df8ed9f89b98c5ebb1bc5d5279c2e182784ff4cd9c869ae152e29d7a2b2
+CT = 0a5d1bc02c5fe096a8b9d94d1267c49a
+Result = Pass
+Payload = 00
+
+Count = 147
+Nonce = e4db2e80dc3f63
+Adata = 7616bdf5737d01f936072b6576fa76556dfa072f7e2d7de16b9dc96ac8de409c
+CT = 9eb6d9757ec7c56cc8c79461e0017486
+Result = Fail
+
+Count = 148
+Nonce = 4f490ce07e0150
+Adata = 3e12d09632c644c540077c6f90726d4167423a679322b2000a3f19cfcea02b33
+CT = 1eda43bf07f2bf003107f3a0ba3a4c18
+Result = Pass
+Payload = 00
+
+Count = 149
+Nonce = b4aaf9ad1bde60
+Adata = 8c96c891456ddec29fe04299506723db2079a6667f96db5d198bf085acf2a4ef
+CT = 5287cc160c5dd3a0f9c1986aac2a621c
+Result = Fail
+
+[Alen = 32, Plen = 0, Nlen = 13, Tlen = 4]
+
+Key = a4bc10b1a62c96d459fbaf3a5aa3face7313bb9e1253e696f96a7a8e36801088
+
+Count = 150
+Nonce = a544218dadd3c10583db49cf39
+Adata = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e09a1005e024f6907
+CT = 866d4227
+Result = Pass
+Payload = 00
+
+Count = 151
+Nonce = e8de970f6ee8e80ede933581b5
+Adata = 89f8b068d34f56bc49d839d8e47b347e6dae737b903b278632447e6c0485d26a
+CT = 94cb1127
+Result = Fail
+
+Count = 152
+Nonce = 6de75d3c05e83755083399a5f7
+Adata = 504b08cf34cbe17acf631ef219ae01437ebb6a980ab2f00121bb3073701b6511
+CT = 82c2b67a
+Result = Fail
+
+Count = 153
+Nonce = 58d43b9f1581c590daab1a5c56
+Adata = 749f149ef306c70a5d006d9777adbbf7c0de453898c2978ef7c281535ea9b24c
+CT = 8c8283f9
+Result = Fail
+
+Count = 154
+Nonce = dfdcbdff329f7af70731d8e276
+Adata = 2ae56ddde2876d70b3b34eda8c2b1d096c836d5225d53ec460b724b6e16aa5a3
+CT = c4ac0952
+Result = Pass
+Payload = 00
+
+Count = 155
+Nonce = 199ec321d1d24d5408076912d6
+Adata = a77526f3614cd974498a76d8b3cb7bacc623fdc9c85503289c462df888b199ed
+CT = c59aa931
+Result = Fail
+
+Count = 156
+Nonce = 60f2490ba0c658848859fcbea8
+Adata = 3ad743283064929bf4fe4e0807f710f5e6a273e22614c728c3280a27b6c614a0
+CT = 27c3953d
+Result = Pass
+Payload = 00
+
+Count = 157
+Nonce = 6f29ca274190400720bba27651
+Adata = c0850aaf141bd3f1b24f4d882590f58682b41f874748f29f8925b4914f444842
+CT = cb1ac8eb
+Result = Fail
+
+Count = 158
+Nonce = f1dfb6fdb31cb423226f181c09
+Adata = ac6b08900fc1c9463e7dfdb60eee444c4989d7b200e675f3220ba1e14eed0ab4
+CT = 4dcc55cc
+Result = Fail
+
+Count = 159
+Nonce = 0d45226c98eaa9bb445a3aa4f9
+Adata = b9cb3e1a5bcccb0b0599414c9822275b66fa0f913d51bdb0a2228cbb5aad0e0a
+CT = 727d8f5e
+Result = Fail
+
+Count = 160
+Nonce = 39cdbb24bd273a3fe96f42ca9d
+Adata = ddfe6c22f4cdc3128050072005f5bd4ecdef1d836e891683f1ba921d33fafba7
+CT = 5aa56a54
+Result = Fail
+
+Count = 161
+Nonce = db113f38f0504615c5c9347c3d
+Adata = 3b71bc84e48c6dadf6ead14621d22468a3d4c9c103ac96970269730bcfce239b
+CT = c38fbdff
+Result = Pass
+Payload = 00
+
+Count = 162
+Nonce = d16a20ef5f6587f1ee3cb7850b
+Adata = b1133e1cd369617a9f937e9a1eb86a0979ee30b5b7b0b6ff838d9e11301d6b72
+CT = 6be30c42
+Result = Fail
+
+Count = 163
+Nonce = d35f531f714694b5e49303a980
+Adata = 55b791ee495299916ff3c2327b4990952bebd0a2da9acfc553c6c996e354a4b5
+CT = d34e90bb
+Result = Pass
+Payload = 00
+
+Count = 164
+Nonce = 220624db34a022b758473994a2
+Adata = 5b3b2ae87b0d6759f38a858423227f8687f35478a8f565409b741eadcac4d8c4
+CT = 4a5d14bc
+Result = Fail
+
+[Alen = 32, Plen = 0, Nlen = 13, Tlen = 16]
+
+Key = 8c5cf3457ff22228c39c051c4e05ed4093657eb303f859a9d4b0f8be0127d88a
+
+Count = 165
+Nonce = a544218dadd3c10583db49cf39
+Adata = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e09a1005e024f6907
+CT = 867b0d87cf6e0f718200a97b4f6d5ad5
+Result = Pass
+Payload = 00
+
+Count = 166
+Nonce = e8de970f6ee8e80ede933581b5
+Adata = 89f8b068d34f56bc49d839d8e47b347e6dae737b903b278632447e6c0485d26a
+CT = 677a040d46ee3f2b7838273bdad14f16
+Result = Fail
+
+Count = 167
+Nonce = 6de75d3c05e83755083399a5f7
+Adata = 504b08cf34cbe17acf631ef219ae01437ebb6a980ab2f00121bb3073701b6511
+CT = f650d46ade2cbabbc68ead6df1ea0c37
+Result = Fail
+
+Count = 168
+Nonce = 58d43b9f1581c590daab1a5c56
+Adata = 749f149ef306c70a5d006d9777adbbf7c0de453898c2978ef7c281535ea9b24c
+CT = 11b8fe8c139ee38f77fd8fa552cbff67
+Result = Fail
+
+Count = 169
+Nonce = dfdcbdff329f7af70731d8e276
+Adata = 2ae56ddde2876d70b3b34eda8c2b1d096c836d5225d53ec460b724b6e16aa5a3
+CT = ad879c64425e6c1ec4841bbb0f99aa8b
+Result = Pass
+Payload = 00
+
+Count = 170
+Nonce = 199ec321d1d24d5408076912d6
+Adata = a77526f3614cd974498a76d8b3cb7bacc623fdc9c85503289c462df888b199ed
+CT = 3c64f8731930ae000162c10654531066
+Result = Fail
+
+Count = 171
+Nonce = 60f2490ba0c658848859fcbea8
+Adata = 3ad743283064929bf4fe4e0807f710f5e6a273e22614c728c3280a27b6c614a0
+CT = e2751f153fc76c0dec5e0cf2d30c1a28
+Result = Pass
+Payload = 00
+
+Count = 172
+Nonce = 6f29ca274190400720bba27651
+Adata = c0850aaf141bd3f1b24f4d882590f58682b41f874748f29f8925b4914f444842
+CT = 76127bf891141e73854752ed10c02bd0
+Result = Fail
+
+Count = 173
+Nonce = f1dfb6fdb31cb423226f181c09
+Adata = ac6b08900fc1c9463e7dfdb60eee444c4989d7b200e675f3220ba1e14eed0ab4
+CT = 4bd833f9da0496e5f6a08a05d02df385
+Result = Fail
+
+Count = 174
+Nonce = 0d45226c98eaa9bb445a3aa4f9
+Adata = b9cb3e1a5bcccb0b0599414c9822275b66fa0f913d51bdb0a2228cbb5aad0e0a
+CT = 05f166328a67a8c58b10a7348f3df612
+Result = Fail
+
+Count = 175
+Nonce = 39cdbb24bd273a3fe96f42ca9d
+Adata = ddfe6c22f4cdc3128050072005f5bd4ecdef1d836e891683f1ba921d33fafba7
+CT = 42499bcd949a5163855a9794f11f917e
+Result = Fail
+
+Count = 176
+Nonce = db113f38f0504615c5c9347c3d
+Adata = 3b71bc84e48c6dadf6ead14621d22468a3d4c9c103ac96970269730bcfce239b
+CT = fc85464a81fe372c12c9e4f0f3bf9c37
+Result = Pass
+Payload = 00
+
+Count = 177
+Nonce = d16a20ef5f6587f1ee3cb7850b
+Adata = b1133e1cd369617a9f937e9a1eb86a0979ee30b5b7b0b6ff838d9e11301d6b72
+CT = 8c7501f423647dee77668858c5e350bb
+Result = Fail
+
+Count = 178
+Nonce = d35f531f714694b5e49303a980
+Adata = 55b791ee495299916ff3c2327b4990952bebd0a2da9acfc553c6c996e354a4b5
+CT = b1c09b093788da19e33c5a6e82ed9627
+Result = Pass
+Payload = 00
+
+Count = 179
+Nonce = 220624db34a022b758473994a2
+Adata = 5b3b2ae87b0d6759f38a858423227f8687f35478a8f565409b741eadcac4d8c4
+CT = d2231ee1455b0bc337c4f8173fb8647c
+Result = Fail
+
+[Alen = 32, Plen = 24, Nlen = 7, Tlen = 4]
+
+Key = 8c5cf3457ff22228c39c051c4e05ed4093657eb303f859a9d4b0f8be0127d88a
+
+Count = 180
+Nonce = a544218dadd3c1
+Adata = d3d5424e20fbec43ae495353ed830271515ab104f8860c988d15b6d36c038eab
+CT = c2fe12658139f5d0dd22cadf2e901695b579302a72fc56083ebc7720
+Result = Pass
+Payload = 78c46e3249ca28e1ef0531d80fd37c124d9aecb7be6668e3
+
+Count = 181
+Nonce = 6ba004fd176791
+Adata = 5a053b2a1bb87e85d56527bfcdcd3ecafb991bb10e4c862bb0751c700a29f54b
+CT = 94748ba81229e53c38583a8564b23ebbafc6f6efdf4c2a81c44db2c9
+Result = Fail
+
+Count = 182
+Nonce = 45c5c284836414
+Adata = 8f01a61eb17366d4e70942ab69b4f4bcf8ff6a97f5972ee5780a264c9dcf7d93
+CT = 1d670ccf3e9ba59186c48da2e5bd0ab21973eee2ea2985bf83a09067
+Result = Fail
+
+Count = 183
+Nonce = c69f7679c80546
+Adata = 5d6c04a5b422b46065a79a889e30ac8d1b53b65d230d4c88190903a24e1fe1ea
+CT = 2c8c80ff10fac1bf6c9c83533c1514ee032c0983730b0657392ae25d
+Result = Fail
+
+Count = 184
+Nonce = 57b940550a383b
+Adata = 33c2c3a57bf8393b126982c96d87daeacd5eadad1519073ad8c84cb9b760296f
+CT = e1b4ec4279bb62902c12521e6b874171695c5da46c647cc03b91ff03
+Result = Pass
+Payload = 6fb5ce32a851676753ba3523edc5ca82af1843ffc08f1ef0
+
+Count = 185
+Nonce = 11edd12ea5873d
+Adata = e32e5384038379e2b7382ba337b6f7a72a1569e110ee89c4dd6aa6f7e69f5250
+CT = b5dda89fe879d6a665b99285b6d937fd5877ebef4de049fb64b837fb
+Result = Fail
+
+Count = 186
+Nonce = f32222e9eec4bd
+Adata = 684595e36eda1db5f586941c9f34c9f8d477970d5ccc14632d1f0cec8190ae68
+CT = 224db21beb8cd0069007660e783c3f85706b014128368aab2a4e56a7
+Result = Pass
+Payload = 2c29d4e2bb9294e90cb04ec697e663a1f7385a39f90c8ccf
+
+Count = 187
+Nonce = e0a0a7f262cb51
+Adata = 1d93b2856ad2bf3700440f9a281bd8947ba209e9ffd18e69921ed0678c957c6c
+CT = ba1ce3a799e1173178b6788723005566f9269d5828c85d28e960a769
+Result = Fail
+
+Count = 188
+Nonce = 40316e7b38bdad
+Adata = 6e49acd9c26944740c778e74b1dbaa8d640c7e18e949a1661f8a77543db69e1f
+CT = 79d59e4bb251988c019c4eaaee2a2513f9cb0521334018fded14a5a5
+Result = Fail
+
+Count = 189
+Nonce = 33008ef5baf263
+Adata = a726f31d9a22bfc0e7e4c3111b0d304e106ab04ed318f8bfe6ec9cb3a811285b
+CT = af4350795f24087aa05070d6d5f55ebb12d7ad3141066866d7d6c61d
+Result = Fail
+
+Count = 190
+Nonce = b48a16fb9a065d
+Adata = be05e9c934c1dcba45223d47c6646a2d13c3b93265e354ae4970484b5101d809
+CT = 22d2da531be1f0d1da4bc21f984d29bf56bed2e92da6bf42d0605b84
+Result = Fail
+
+Count = 191
+Nonce = 14c9bd561c47c1
+Adata = 141ae365f8e65ab9196c4e8cd4e62189b304d67de38f2117e84ec0ec8f260ebd
+CT = 61b46c9024eed3989064a52df90349c18e14e4b552779d3f8f9d6814
+Result = Pass
+Payload = c22524a1ea444be3412b0d773d4ea2ff0af4c1ad2383cba8
+
+Count = 192
+Nonce = 5fb871eac2e52a
+Adata = ff23906e9067da8999842318f2a867759ca2d171395c2ff31fa5a4e2ab349c45
+CT = 539799c2b22a33dd648fc4497d12f9455beaf932f1eaaff4d930f5ce
+Result = Fail
+
+Count = 193
+Nonce = 1ccec9923aa6e8
+Adata = 88a6d037009a1c1756f72bb4589d6d940bd514ed55386baefacc6ac3ca6f8795
+CT = 52f8205534447d722be2b9377f7395938cc88af081a11ccb0d83fa19
+Result = Pass
+Payload = 518a7fb11c463bf23798982118f3cfe4d7ddde9184f37d4f
+
+Count = 194
+Nonce = 68a5351e4422c8
+Adata = 303c767468f48ac9f6e331bbad535b06aa00ab593327320799e17eff63afd3fe
+CT = d11c892ae155098f5e4b5fe60c7afd74fb2dbcc4db956556f243e273
+Result = Fail
+
+[Alen = 32, Plen = 24, Nlen = 7, Tlen = 16]
+
+Key = 705334e30f53dd2f92d190d2c1437c8772f940c55aa35e562214ed45bd458ffe
+
+Count = 195
+Nonce = a544218dadd3c1
+Adata = d3d5424e20fbec43ae495353ed830271515ab104f8860c988d15b6d36c038eab
+CT = 3341168eb8c48468c414347fb08f71d2086f7c2d1bd581ce1ac68bd42f5ec7fa7e068cc0ecd79c2a
+Result = Pass
+Payload = 78c46e3249ca28e1ef0531d80fd37c124d9aecb7be6668e3
+
+Count = 196
+Nonce = 6ba004fd176791
+Adata = 5a053b2a1bb87e85d56527bfcdcd3ecafb991bb10e4c862bb0751c700a29f54b
+CT = d543acda712b898cbb27b8f598b2e4438ce587a836e2785147c3338a2400809e739b63ba8227d2f9
+Result = Fail
+
+Count = 197
+Nonce = 45c5c284836414
+Adata = 8f01a61eb17366d4e70942ab69b4f4bcf8ff6a97f5972ee5780a264c9dcf7d93
+CT = 39a8af5c976b995ea8049e55b68bc65503592ab00915638646288ce9dd1c7088c752e35947fdca98
+Result = Fail
+
+Count = 198
+Nonce = c69f7679c80546
+Adata = 5d6c04a5b422b46065a79a889e30ac8d1b53b65d230d4c88190903a24e1fe1ea
+CT = 950fbf6445f6ffb68178f52f5079d0c6081a48ae1f267a0b7fd89caef9388fbb82361b8d53d9edc6
+Result = Fail
+
+Count = 199
+Nonce = 57b940550a383b
+Adata = 33c2c3a57bf8393b126982c96d87daeacd5eadad1519073ad8c84cb9b760296f
+CT = fbfed2c94f50ca10466da9903ef85833ad48ca00556e66d14d8b30df941f3536ffb42083ef0e1c30
+Result = Pass
+Payload = 6fb5ce32a851676753ba3523edc5ca82af1843ffc08f1ef0
+
+Count = 200
+Nonce = 11edd12ea5873d
+Adata = e32e5384038379e2b7382ba337b6f7a72a1569e110ee89c4dd6aa6f7e69f5250
+CT = 2ebfeb7a843618b37025352df3538526517ed320adfb486c04cf3426e8f975125a7eed00e5f33b6c
+Result = Fail
+
+Count = 201
+Nonce = f32222e9eec4bd
+Adata = 684595e36eda1db5f586941c9f34c9f8d477970d5ccc14632d1f0cec8190ae68
+CT = dae13e6967c8b1ee0dd2d5ba1dd1de69f22c95da39528f9ef78e9e5e9faa058112af57f4ac78db2c
+Result = Pass
+Payload = 2c29d4e2bb9294e90cb04ec697e663a1f7385a39f90c8ccf
+
+Count = 202
+Nonce = e0a0a7f262cb51
+Adata = 1d93b2856ad2bf3700440f9a281bd8947ba209e9ffd18e69921ed0678c957c6c
+CT = e683040a0bcf04c1748e7746400d6ef0f7cd8e77a29517790c63959ce534a0f87fb42a9b000dec84
+Result = Fail
+
+Count = 203
+Nonce = 40316e7b38bdad
+Adata = 6e49acd9c26944740c778e74b1dbaa8d640c7e18e949a1661f8a77543db69e1f
+CT = 829e50e8c09e727a58287e6eb7d38edeb8ab39db279c06397d1a2111dc21aec79ef73193b306d31f
+Result = Fail
+
+Count = 204
+Nonce = 33008ef5baf263
+Adata = a726f31d9a22bfc0e7e4c3111b0d304e106ab04ed318f8bfe6ec9cb3a811285b
+CT = 873c91e76dca0062ae66325aefb84ece3e98928f8dbc5fee7c516d2d1a8318893923f398ca249401
+Result = Fail
+
+Count = 205
+Nonce = b48a16fb9a065d
+Adata = be05e9c934c1dcba45223d47c6646a2d13c3b93265e354ae4970484b5101d809
+CT = 343f6c86f2b852ac388a096faec4472107a924aba56d0cb88055e777bb57eb49497cd2e233ee06fd
+Result = Fail
+
+Count = 206
+Nonce = 14c9bd561c47c1
+Adata = 141ae365f8e65ab9196c4e8cd4e62189b304d67de38f2117e84ec0ec8f260ebd
+CT = a654238fb8b05e293dba07f9d68d75a7f0fbf40fe20edaeba1586bf922412e73ce338e372615c3bc
+Result = Pass
+Payload = c22524a1ea444be3412b0d773d4ea2ff0af4c1ad2383cba8
+
+Count = 207
+Nonce = 5fb871eac2e52a
+Adata = ff23906e9067da8999842318f2a867759ca2d171395c2ff31fa5a4e2ab349c45
+CT = 4846816923ed9f0254bdd0be01028f75061d3594ad3a45bd03538d108df6ecd6f39acfe076ba5fb8
+Result = Fail
+
+Count = 208
+Nonce = 1ccec9923aa6e8
+Adata = 88a6d037009a1c1756f72bb4589d6d940bd514ed55386baefacc6ac3ca6f8795
+CT = 765067ef768908d91ee4c3923943e0c7be70e2e06db99a4b3e3f51ee37fdcc5d81dd85d9e9d4f44e
+Result = Pass
+Payload = 518a7fb11c463bf23798982118f3cfe4d7ddde9184f37d4f
+
+Count = 209
+Nonce = 68a5351e4422c8
+Adata = 303c767468f48ac9f6e331bbad535b06aa00ab593327320799e17eff63afd3fe
+CT = e58ea6c1522e5a3e93a85edd05ae80d6cf5c4dd6d604a8f8d8a906488f79ad5d2234d72458dcfcd4
+Result = Fail
+
+[Alen = 32, Plen = 24, Nlen = 13, Tlen = 4]
+
+Key = 705334e30f53dd2f92d190d2c1437c8772f940c55aa35e562214ed45bd458ffe
+
+Count = 210
+Nonce = a544218dadd3c10583db49cf39
+Adata = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e09a1005e024f6907
+CT = c0ea400b599561e7905b99262b4565d5c3dc49fad84d7c69ef891339
+Result = Pass
+Payload = e8de970f6ee8e80ede933581b5bcf4d837e2b72baa8b00c3
+
+Count = 211
+Nonce = 8fa501c5dd9ac9b868144c9fa5
+Adata = 5bb40e3bb72b4509324a7edc852f72535f1f6283156e63f6959ffaf39dcde800
+CT = 60871e03ea0eb968536c99f926ea24ef43d41272ad9fb7f63d488623
+Result = Fail
+
+Count = 212
+Nonce = 9bc0d1502a47e46350fe8667ca
+Adata = 07203674260208d5bd4d39506836f7e76ffc58e938799f21aff7bb4dea4410d2
+CT = 81d7859dcbe51dcc94fe2591cd3b0540003d49a8c4dccbf4527e5ed0
+Result = Fail
+
+Count = 213
+Nonce = 611cb4c66e88f6acf96fea1919
+Adata = 327ee3657e49d4d988362fabae303ccea6638e5cb45993d9d56269bc3d3af32b
+CT = bef380ad725b65fb5fceeabf09c665bc35089f434ec831494d20d5fa
+Result = Fail
+
+Count = 214
+Nonce = 0dd613c0fe28e913c0edbb8404
+Adata = 2ad306575b577c2f61da7212ab63e3db3941f1f751f2356c7443531a90b9d141
+CT = fabe11c9629e598228f5209f3dbcc641fe4b1a22cadb0821d2898c3b
+Result = Pass
+Payload = 9522fb1f1aa58493cba682d788186d902cfc93e80fd6b998
+
+Count = 215
+Nonce = 68806dfe720d0a9a84697de5f2
+Adata = c6b0e4dfd723d7637510f887b7852f60ecdf72e0d33396560fed6534d5b7f015
+CT = b7eb87f84951640de731d4093f1a4ed5f831138a27465d3941e92090
+Result = Fail
+
+Count = 216
+Nonce = 3e0fe3427eeda80f02dda4fed5
+Adata = ae0d1c9c834d60ff0ecfb3c0d78c72ddb789e58adfc166c81d5fc6395b31ec33
+CT = d88f8fcd772125212ce09c2a6e5b5693dd35073f992004f0d18fc889
+Result = Pass
+Payload = 38333ce78110bf53a2c2abc7db99e133ad218ca43ff7a7bc
+
+Count = 217
+Nonce = 7c0c76d9f9316ff6c98758b464
+Adata = 31a0338c3839931fa1dd5131cb796c4c6cfde9fb336d8a80ac35dec463be7a94
+CT = d2d7d52b11304fc1d15b8c20e296ba7c63d99f4ce86cc8ae0f39ecea
+Result = Fail
+
+Count = 218
+Nonce = 07c728135bdfede0e0c8036b17
+Adata = 25a152850b4b80b19d8f0b504b2a8a241824b3a1fca8d85c8713b2c0c84b5e02
+CT = ae1d9f82efb464d5dc2018cffa309634c09b34d1122c4bd994b1d516
+Result = Fail
+
+Count = 219
+Nonce = 710c96d7a6f09de83f0507f28a
+Adata = 2d64acfdbfc582cd9a933790eb1b739fb02e53f511255e49f421bb7acc98a130
+CT = 477c985d92ad1b69d22315235a29e3d3a5991487cbdc8d11d394d047
+Result = Fail
+
+Count = 220
+Nonce = 977bbcdeb6a7d9dcf8664bc2d8
+Adata = 135786125258a49475338ac1961d2718433b9e84cf64f63ca52913e8dd12e505
+CT = d1c085c75d808dc6db493b8a0b4d884e0700d2844a1b4b46bd3d22eb
+Result = Fail
+
+Count = 221
+Nonce = 60122cbd219e5cf17415e8bc09
+Adata = 895a45ddbe0c80793eccbf820de13a233b6aa7045cfd5313388e7184c392b216
+CT = 76bdd9a7b34bf14ae121a87fdfa144f71b848744af6a2f0b1c0d067c
+Result = Pass
+Payload = 794e734966e6d0001699aec3f8ab8f194de7653d3091b1b9
+
+Count = 222
+Nonce = 83a07f2e685959cb50a1bd2bce
+Adata = 02afe300ec0cf0acb59108b2f70e069300294e34f40bb032cb59907599664408
+CT = 413e2e8df9d65b4e5d3b63a738258aaee643f364be9a01b974192744
+Result = Fail
+
+Count = 223
+Nonce = 3542fbe0f59a6d5f3abf619b7d
+Adata = dd4531f158a2fa3bc8a339f770595048f4a42bc1b03f2e824efc6ba4985119d8
+CT = 617d8036e2039d516709062379e0550cbd71ebb90fea967c79018ad5
+Result = Pass
+Payload = c5b3d71312ea14f2f8fae5bd1a453192b6604a45db75c5ed
+
+Count = 224
+Nonce = 48f2d4c0b17072e0a9c300d90b
+Adata = c56175e2cfe0d37454d989afcc36686fb34c015439601567506a4d0003182be7
+CT = 40e609c739e409750a6c41d9c6ea64ce36f70711b4ca3e365c916f91
+Result = Fail
+
+[Alen = 32, Plen = 24, Nlen = 13, Tlen = 16]
+
+Key = 314a202f836f9f257e22d8c11757832ae5131d357a72df88f3eff0ffcee0da4e
+
+Count = 225
+Nonce = a544218dadd3c10583db49cf39
+Adata = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e09a1005e024f6907
+CT = 8d34cdca37ce77be68f65baf3382e31efa693e63f914a781367f30f2eaad8c063ca50795acd90203
+Result = Pass
+Payload = e8de970f6ee8e80ede933581b5bcf4d837e2b72baa8b00c3
+
+Count = 226
+Nonce = 8fa501c5dd9ac9b868144c9fa5
+Adata = 5bb40e3bb72b4509324a7edc852f72535f1f6283156e63f6959ffaf39dcde800
+CT = 516c0095cc3d85fd55e48da17c592e0c7014b9daafb82bdc4b41096dfdbe9cc1ab610f8f3e038d16
+Result = Fail
+
+Count = 227
+Nonce = 9bc0d1502a47e46350fe8667ca
+Adata = 07203674260208d5bd4d39506836f7e76ffc58e938799f21aff7bb4dea4410d2
+CT = 0293eae9f8d8bd7ad45357f733fc7b5d990d894783e18501d81ec96df41b8fa8262ed2db880b5e85
+Result = Fail
+
+Count = 228
+Nonce = 611cb4c66e88f6acf96fea1919
+Adata = 327ee3657e49d4d988362fabae303ccea6638e5cb45993d9d56269bc3d3af32b
+CT = 256bad8295e67d8d450f5ecc8276920ec23b1156c57be7c96ee80f60f72db2cbf25b2f8c6af8749c
+Result = Fail
+
+Count = 229
+Nonce = 0dd613c0fe28e913c0edbb8404
+Adata = 2ad306575b577c2f61da7212ab63e3db3941f1f751f2356c7443531a90b9d141
+CT = 6df09613ea986c2d91a57a45a0942cbf20e0dfca12fbda8c945ee6db24aea5f5098952f1203339ce
+Result = Pass
+Payload = 9522fb1f1aa58493cba682d788186d902cfc93e80fd6b998
+
+Count = 230
+Nonce = 68806dfe720d0a9a84697de5f2
+Adata = c6b0e4dfd723d7637510f887b7852f60ecdf72e0d33396560fed6534d5b7f015
+CT = c5b64577d3c34e50f7da5072db5bda1d1d2c6db1a4f1183e2cc4c90ac3f798957cb09a05868a8ad5
+Result = Fail
+
+Count = 231
+Nonce = 3e0fe3427eeda80f02dda4fed5
+Adata = ae0d1c9c834d60ff0ecfb3c0d78c72ddb789e58adfc166c81d5fc6395b31ec33
+CT = 2bfe51f1f43b982d47f76ea8206ddbf585d6f30cec0d4ef16b1556631d3b52bf24154afec1448ef6
+Result = Pass
+Payload = 38333ce78110bf53a2c2abc7db99e133ad218ca43ff7a7bc
+
+Count = 232
+Nonce = 7c0c76d9f9316ff6c98758b464
+Adata = 31a0338c3839931fa1dd5131cb796c4c6cfde9fb336d8a80ac35dec463be7a94
+CT = 1622ae109073f44a4596722d9943fea774dfc2a1f939fc0914f42ec81e3af71c9a5de7e0ac16ca69
+Result = Fail
+
+Count = 233
+Nonce = 07c728135bdfede0e0c8036b17
+Adata = 25a152850b4b80b19d8f0b504b2a8a241824b3a1fca8d85c8713b2c0c84b5e02
+CT = 4c0b361a766d366d983c41e793d75635e17f6eab2eadcf9743d67d90850c4c76a43df1f95170b29b
+Result = Fail
+
+Count = 234
+Nonce = 710c96d7a6f09de83f0507f28a
+Adata = 2d64acfdbfc582cd9a933790eb1b739fb02e53f511255e49f421bb7acc98a130
+CT = 5b02347f30213df7f1506d7dca41b838c92aea0f190c5dba7bd5d5c8c098299394333b34fae9a110
+Result = Fail
+
+Count = 235
+Nonce = 977bbcdeb6a7d9dcf8664bc2d8
+Adata = 135786125258a49475338ac1961d2718433b9e84cf64f63ca52913e8dd12e505
+CT = c77283ca15484d82469ce7249d1fb8e5f4c3bc8245fb4d97e26149d4a9711be81b4f69aa9fabd7f6
+Result = Fail
+
+Count = 236
+Nonce = 60122cbd219e5cf17415e8bc09
+Adata = 895a45ddbe0c80793eccbf820de13a233b6aa7045cfd5313388e7184c392b216
+CT = bf0d219bb50fcc1d51f654bb0fd8b44efa25aef39e2f11afe47d00f2eebb544e6ba7559ac2f34edb
+Result = Pass
+Payload = 794e734966e6d0001699aec3f8ab8f194de7653d3091b1b9
+
+Count = 237
+Nonce = 83a07f2e685959cb50a1bd2bce
+Adata = 02afe300ec0cf0acb59108b2f70e069300294e34f40bb032cb59907599664408
+CT = 1609f8de59da4f50ce034977d132d4f9881a9b85ffa5bb886fa3fddc87690a359fe55f8fa12ba749
+Result = Fail
+
+Count = 238
+Nonce = 3542fbe0f59a6d5f3abf619b7d
+Adata = dd4531f158a2fa3bc8a339f770595048f4a42bc1b03f2e824efc6ba4985119d8
+CT = 39c2e8f6edfe663b90963b98eb79e2d4f7f28a5053ae8881567a6b4426f1667136bed4a5e32a2bc1
+Result = Pass
+Payload = c5b3d71312ea14f2f8fae5bd1a453192b6604a45db75c5ed
+
+Count = 239
+Nonce = 48f2d4c0b17072e0a9c300d90b
+Adata = c56175e2cfe0d37454d989afcc36686fb34c015439601567506a4d0003182be7
+CT = 27c575be0b99af9b106f53f471c31cac4d54ea0bcb602a33fb67bb6092cd579f722ae9b680da083d
+Result = Fail
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT256.txt b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT256.txt
new file mode 100644
index 0000000000..6d9a3eadcb
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/DVPT256.txt
@@ -0,0 +1,1589 @@
+# CAVS 11.0
+# "CCM-DVPT" information
+# AES Keylen: 256
+# Generated on Tue Mar 15 08:09:26 2011
+
+
+[Alen = 0, Plen = 0, Nlen = 7, Tlen = 4]
+
+Key = eda32f751456e33195f1f499cf2dc7c97ea127b6d488f211ccc5126fbb24afa6
+
+Count = 0
+Nonce = a544218dadd3c1
+Adata = 00
+CT = 469c90bb
+Result = Pass (0)
+Payload = 00
+
+Count = 1
+Nonce = d3d5424e20fbec
+Adata = 00
+CT = 46a908ed
+Result = Fail (2 - CT changed)
+
+Count = 2
+Nonce = e776620a3bd961
+Adata = 00
+CT = fdd35c4d
+Result = Fail (1 - Adata changed)
+
+Count = 3
+Nonce = 6c7a3be9f9ad55
+Adata = 00
+CT = 869ce60e
+Result = Fail (1 - Adata changed)
+
+Count = 4
+Nonce = dbb3923156cfd6
+Adata = 00
+CT = 1302d515
+Result = Pass (0)
+Payload = 00
+
+Count = 5
+Nonce = b390f67eaef8f5
+Adata = 00
+CT = 156416ee
+Result = Fail (2 - CT changed)
+
+Count = 6
+Nonce = a259c114eaac89
+Adata = 00
+CT = 4fe06e92
+Result = Pass (0)
+Payload = 00
+
+Count = 7
+Nonce = 7fc8804fef18ef
+Adata = 00
+CT = 611091aa
+Result = Fail (2 - CT changed)
+
+Count = 8
+Nonce = fbaf4cbc49fa0f
+Adata = 00
+CT = 696e9371
+Result = Fail (2 - CT changed)
+
+Count = 9
+Nonce = 2ed0c8761dbf04
+Adata = 00
+CT = a0e0a2cb
+Result = Fail (2 - CT changed)
+
+Count = 10
+Nonce = 346bb04ea0db86
+Adata = 00
+CT = 43cc0375
+Result = Fail (1 - Adata changed)
+
+Count = 11
+Nonce = e1be89af98ffd7
+Adata = 00
+CT = e5417f6b
+Result = Pass (0)
+Payload = 00
+
+Count = 12
+Nonce = a6a0d57aaaf012
+Adata = 00
+CT = fff8a068
+Result = Fail (1 - Adata changed)
+
+Count = 13
+Nonce = 1aa758eb2f9a28
+Adata = 00
+CT = f8fa8e71
+Result = Pass (0)
+Payload = 00
+
+Count = 14
+Nonce = 2911167fc98fc3
+Adata = 00
+CT = 0bfa2d9d
+Result = Fail (1 - Adata changed)
+
+[Alen = 0, Plen = 0, Nlen = 7, Tlen = 16]
+
+Key = e1b8a927a95efe94656677b692662000278b441c79e879dd5c0ddc758bdc9ee8
+
+Count = 15
+Nonce = a544218dadd3c1
+Adata = 00
+CT = 8207eb14d33855a52acceed17dbcbf6e
+Result = Pass (0)
+Payload = 00
+
+Count = 16
+Nonce = d3d5424e20fbec
+Adata = 00
+CT = 60f8e127cb4d30db6df0622158cd931d
+Result = Fail (2 - CT changed)
+
+Count = 17
+Nonce = e776620a3bd961
+Adata = 00
+CT = 4239f29871651e9a26b8b06ffc5b3748
+Result = Fail (1 - Adata changed)
+
+Count = 18
+Nonce = 6c7a3be9f9ad55
+Adata = 00
+CT = 5d35364c621fe8959dfe70ab44700fbe
+Result = Fail (1 - Adata changed)
+
+Count = 19
+Nonce = dbb3923156cfd6
+Adata = 00
+CT = e4dc5e03aacea691262ee69cee8ffbbe
+Result = Pass (0)
+Payload = 00
+
+Count = 20
+Nonce = b390f67eaef8f5
+Adata = 00
+CT = c8eb7643b4ed3c796c3873e8c6624e0d
+Result = Fail (2 - CT changed)
+
+Count = 21
+Nonce = a259c114eaac89
+Adata = 00
+CT = f79c53fd5e69835b7e70496ea999718b
+Result = Pass (0)
+Payload = 00
+
+Count = 22
+Nonce = 7fc8804fef18ef
+Adata = 00
+CT = 687e00723a419fa81c0923b8b8e245ae
+Result = Fail (2 - CT changed)
+
+Count = 23
+Nonce = fbaf4cbc49fa0f
+Adata = 00
+CT = 499ab350309ad6091ec4aaf6bf0cbd00
+Result = Fail (2 - CT changed)
+
+Count = 24
+Nonce = 2ed0c8761dbf04
+Adata = 00
+CT = c27b9f14787dc5375f59d0c561a23446
+Result = Fail (2 - CT changed)
+
+Count = 25
+Nonce = 346bb04ea0db86
+Adata = 00
+CT = 655c737722c78ac96582a883d407b2bb
+Result = Fail (1 - Adata changed)
+
+Count = 26
+Nonce = e1be89af98ffd7
+Adata = 00
+CT = 10d3f6fe08280d45e67e58fe41a7f036
+Result = Pass (0)
+Payload = 00
+
+Count = 27
+Nonce = a6a0d57aaaf012
+Adata = 00
+CT = b4e425e43edb92c606f7cb2de8a06932
+Result = Fail (1 - Adata changed)
+
+Count = 28
+Nonce = 1aa758eb2f9a28
+Adata = 00
+CT = 2590df2453cb94c304ba0a2bff3f3c71
+Result = Pass (0)
+Payload = 00
+
+Count = 29
+Nonce = 2911167fc98fc3
+Adata = 00
+CT = 1f344e30dfa95b2319e274caa5780e60
+Result = Fail (1 - Adata changed)
+
+[Alen = 0, Plen = 0, Nlen = 13, Tlen = 4]
+
+Key = e1b8a927a95efe94656677b692662000278b441c79e879dd5c0ddc758bdc9ee8
+
+Count = 30
+Nonce = a544218dadd3c10583db49cf39
+Adata = 00
+CT = 8a19a133
+Result = Pass (0)
+Payload = 00
+
+Count = 31
+Nonce = 3c0e2815d37d844f7ac240ba9d
+Adata = 00
+CT = 2e317f1b
+Result = Fail (2 - CT changed)
+
+Count = 32
+Nonce = 75549e7e5657e5fe19872fcee0
+Adata = 00
+CT = 979bdcfe
+Result = Fail (1 - Adata changed)
+
+Count = 33
+Nonce = d071ff72735820d73485870e83
+Adata = 00
+CT = 8ef89acf
+Result = Fail (1 - Adata changed)
+
+Count = 34
+Nonce = 79ac204a26b9fee1132370c20f
+Adata = 00
+CT = 154024b2
+Result = Pass (0)
+Payload = 00
+
+Count = 35
+Nonce = a64bbc3d6d377dab513f7d9ce8
+Adata = 00
+CT = 8dbcc439
+Result = Fail (2 - CT changed)
+
+Count = 36
+Nonce = 0545fd9ecbc73ccdbbbd4244fd
+Adata = 00
+CT = 5c349fb2
+Result = Pass (0)
+Payload = 00
+
+Count = 37
+Nonce = 182fb47a12becf0bfe65df1287
+Adata = 00
+CT = 79df3e02
+Result = Fail (2 - CT changed)
+
+Count = 38
+Nonce = f342059a6f9dc14226b40debc4
+Adata = 00
+CT = fbc2c500
+Result = Fail (2 - CT changed)
+
+Count = 39
+Nonce = 6cbfe6bb4c9b171b93d28e9f8f
+Adata = 00
+CT = 2fac1bca
+Result = Fail (2 - CT changed)
+
+Count = 40
+Nonce = 82877df921c6ade43064ad963e
+Adata = 00
+CT = 99948f6e
+Result = Fail (1 - Adata changed)
+
+Count = 41
+Nonce = 0a37f2e7c66490e97285f1b09e
+Adata = 00
+CT = c59bf14c
+Result = Pass (0)
+Payload = 00
+
+Count = 42
+Nonce = d7b9c346ce2f8bad9623122e10
+Adata = 00
+CT = b764c393
+Result = Fail (1 - Adata changed)
+
+Count = 43
+Nonce = c1ad812bf2bbb2cdaee4636ee7
+Adata = 00
+CT = 5b96f41d
+Result = Pass (0)
+Payload = 00
+
+Count = 44
+Nonce = b6ce7d00731184b24428df046b
+Adata = 00
+CT = f7e12df1
+Result = Fail (1 - Adata changed)
+
+[Alen = 0, Plen = 0, Nlen = 13, Tlen = 16]
+
+Key = af063639e66c284083c5cf72b70d8bc277f5978e80d9322d99f2fdc718cda569
+
+Count = 45
+Nonce = a544218dadd3c10583db49cf39
+Adata = 00
+CT = 97e1a8dd4259ccd2e431e057b0397fcf
+Result = Pass (0)
+Payload = 00
+
+Count = 46
+Nonce = 3c0e2815d37d844f7ac240ba9d
+Adata = 00
+CT = 5a9596c511ea6a8671adefc4f2157d8b
+Result = Fail (2 - CT changed)
+
+Count = 47
+Nonce = 75549e7e5657e5fe19872fcee0
+Adata = 00
+CT = 66f5c53efbc74fa02dedc303fd95133a
+Result = Fail (1 - Adata changed)
+
+Count = 48
+Nonce = d071ff72735820d73485870e83
+Adata = 00
+CT = 2dfd3c852f68eace45acf433a6aa9c05
+Result = Fail (1 - Adata changed)
+
+Count = 49
+Nonce = 79ac204a26b9fee1132370c20f
+Adata = 00
+CT = 5c8c9a5b97be8c7bc01ca8d693b809f9
+Result = Pass (0)
+Payload = 00
+
+Count = 50
+Nonce = a64bbc3d6d377dab513f7d9ce8
+Adata = 00
+CT = ec093121bdcd589285f2262be8db5c4e
+Result = Fail (2 - CT changed)
+
+Count = 51
+Nonce = 0545fd9ecbc73ccdbbbd4244fd
+Adata = 00
+CT = 84201662b213c7a1ff0c1b3c25e4ec45
+Result = Pass (0)
+Payload = 00
+
+Count = 52
+Nonce = 182fb47a12becf0bfe65df1287
+Adata = 00
+CT = bbe746d6d31e8e9745faed4095ab8d5d
+Result = Fail (2 - CT changed)
+
+Count = 53
+Nonce = f342059a6f9dc14226b40debc4
+Adata = 00
+CT = 646c1258dc4aa6fc380818e70e5f4328
+Result = Fail (2 - CT changed)
+
+Count = 54
+Nonce = 6cbfe6bb4c9b171b93d28e9f8f
+Adata = 00
+CT = 15fa37ca7f2883a4642c1ed41b8f6293
+Result = Fail (2 - CT changed)
+
+Count = 55
+Nonce = 82877df921c6ade43064ad963e
+Adata = 00
+CT = c6acf5e5ded4efb2c314370ebb9e9cde
+Result = Fail (1 - Adata changed)
+
+Count = 56
+Nonce = 0a37f2e7c66490e97285f1b09e
+Adata = 00
+CT = 586e728193ce6db9a926b03b2d77dd6e
+Result = Pass (0)
+Payload = 00
+
+Count = 57
+Nonce = d7b9c346ce2f8bad9623122e10
+Adata = 00
+CT = 642a187e71feff5989e28184aded0199
+Result = Fail (1 - Adata changed)
+
+Count = 58
+Nonce = c1ad812bf2bbb2cdaee4636ee7
+Adata = 00
+CT = 64864d21b6ee3fca13f07fc0486e232d
+Result = Pass (0)
+Payload = 00
+
+Count = 59
+Nonce = b6ce7d00731184b24428df046b
+Adata = 00
+CT = 58c63ce68f132d30d177c5834344cc5d
+Result = Fail (1 - Adata changed)
+
+[Alen = 0, Plen = 24, Nlen = 7, Tlen = 4]
+
+Key = af063639e66c284083c5cf72b70d8bc277f5978e80d9322d99f2fdc718cda569
+
+Count = 60
+Nonce = a544218dadd3c1
+Adata = 00
+CT = 64a1341679972dc5869fcf69b19d5c5ea50aa0b5e985f5b722aa8d59
+Result = Pass (0)
+Payload = d3d5424e20fbec43ae495353ed830271515ab104f8860c98
+
+Count = 61
+Nonce = bfcda8b5a2d0d2
+Adata = 00
+CT = c5b7f802bffc498c1626e3774f1d9f94045dfd8e1a10a20277d00a75
+Result = Fail (2 - CT changed)
+
+Count = 62
+Nonce = 6bae7f35c56b27
+Adata = 00
+CT = bf432e246b7fa4aff8b3ada738432b51f6872ed92284db9d28588021
+Result = Fail (1 - Adata changed)
+
+Count = 63
+Nonce = c5e4214b1bf209
+Adata = 00
+CT = 0d5760ad0e156e401120a1ebd1b139248784c88e10e3425437921120
+Result = Fail (1 - Adata changed)
+
+Count = 64
+Nonce = 9d773a31fe2ec7
+Adata = 00
+CT = 5acfbe5e488976d8b9b77e69a736e8c919053f9415551209dce2d25e
+Result = Pass (0)
+Payload = 839d8cfa2c921c3cceb7d1f46bd2eaad706e53f64523d8c0
+
+Count = 65
+Nonce = f42cb0cce9efb6
+Adata = 00
+CT = be8be6046ac58411a00c131dd4a72d565f98d87a2c89124b1ef530d0
+Result = Fail (2 - CT changed)
+
+Count = 66
+Nonce = 24b7a65391f88b
+Adata = 00
+CT = f00628e10e8e0115b4a4532a1212a23aade4090832c1972d750125f3
+Result = Pass (0)
+Payload = 3bed52236182c19418867d468dbf47c8aac46c02445f99bb
+
+Count = 67
+Nonce = d2a7eb45780df3
+Adata = 00
+CT = 9078151f674d5f7b56e2451b0316156f776459f17d277e0108aaaf93
+Result = Fail (2 - CT changed)
+
+Count = 68
+Nonce = 046cbfd26093d8
+Adata = 00
+CT = 921cbecce3b06f3d655a5a0a4d212320d4f147575079fd23bd95e677
+Result = Fail (2 - CT changed)
+
+Count = 69
+Nonce = 51b13b0b04d077
+Adata = 00
+CT = 8cab1ff22d474e9863c153e84680e2a66981f036051360477e2ebb1d
+Result = Fail (2 - CT changed)
+
+Count = 70
+Nonce = ce2e9967bf9eb7
+Adata = 00
+CT = 15f476b5aefe072548a54f59506d9c3b9ce29025340214be662f8684
+Result = Fail (1 - Adata changed)
+
+Count = 71
+Nonce = b672c91376f533
+Adata = 00
+CT = 758aa03dc72c362c43b5f85bfaa3db4a74860887a8c29e47d5642830
+Result = Pass (0)
+Payload = 4f7a561e61b7861719e4445057ac9b74a9be953b772b09ec
+
+Count = 72
+Nonce = 62f6f1872462d8
+Adata = 00
+CT = ec645769b22161567e6a7e23aa06575bc767a34aa54d3cba01472fe1
+Result = Fail (1 - Adata changed)
+
+Count = 73
+Nonce = a6d01fb88ca547
+Adata = 00
+CT = 615cbeabbe163ba8bc9c073df9ad40833fcf3f424644ccc37aa999d7
+Result = Pass (0)
+Payload = a36155de477364236591e453008114075b4872120ef17264
+
+Count = 74
+Nonce = 46ad6ebbd8644a
+Adata = 00
+CT = 0ed6cc6451de57ca672d56dee45d4548a810d5c49dfe442dd27b7cf2
+Result = Fail (1 - Adata changed)
+
+[Alen = 0, Plen = 24, Nlen = 7, Tlen = 16]
+
+Key = f7079dfa3b5c7b056347d7e437bcded683abd6e2c9e069d333284082cbb5d453
+
+Count = 75
+Nonce = a544218dadd3c1
+Adata = 00
+CT = bc51c3925a960e7732533e4ef3a4f69ee6826de952bcb0fd374f3bb6db8377ebfc79674858c4f305
+Result = Pass (0)
+Payload = d3d5424e20fbec43ae495353ed830271515ab104f8860c98
+
+Count = 76
+Nonce = bfcda8b5a2d0d2
+Adata = 00
+CT = afa1fa8e8a70e26b02161150556d604101fdf423f332c3363275f2a4907d51b734fe7238cebbd48f
+Result = Fail (2 - CT changed)
+
+Count = 77
+Nonce = 6bae7f35c56b27
+Adata = 00
+CT = 72bc8ef21a847047091b673ccf231d35ecf6f4049741703be672f1f22cbe4a5305f19aaa6967237b
+Result = Fail (1 - Adata changed)
+
+Count = 78
+Nonce = c5e4214b1bf209
+Adata = 00
+CT = b719f6555fc4e5424273f5903d5672af460413110278707f400b152113c3976be63dcd9e7a84ddac
+Result = Fail (1 - Adata changed)
+
+Count = 79
+Nonce = 9d773a31fe2ec7
+Adata = 00
+CT = 4539bb13382b034ddb16a3329148f9243a4eee998fe444aff2870ce198af11f4fb698a67af6c89ad
+Result = Pass (0)
+Payload = 839d8cfa2c921c3cceb7d1f46bd2eaad706e53f64523d8c0
+
+Count = 80
+Nonce = f42cb0cce9efb6
+Adata = 00
+CT = 47cbb909cb12fa0a4b0f1aefd54c52d1edd1533290f76b8ccc98b3f5758972bf08ea9e88dc6e54ed
+Result = Fail (2 - CT changed)
+
+Count = 81
+Nonce = 24b7a65391f88b
+Adata = 00
+CT = 6d0f928352a17d63aca1899cbd305e1f831f1638d27c1e24432704eff9b6830476db3d30d4c103e4
+Result = Pass (0)
+Payload = 3bed52236182c19418867d468dbf47c8aac46c02445f99bb
+
+Count = 82
+Nonce = d2a7eb45780df3
+Adata = 00
+CT = e0e686d917f78b3b0058fed7b084976244789073a6305ff571256981db86f1e768170a104ebfb81d
+Result = Fail (2 - CT changed)
+
+Count = 83
+Nonce = 046cbfd26093d8
+Adata = 00
+CT = 960c573f5d6934a4cac49d06998f827b3d665cf02c998fe55efbbae6a346863a93d52e0321cef8b2
+Result = Fail (2 - CT changed)
+
+Count = 84
+Nonce = 51b13b0b04d077
+Adata = 00
+CT = 7cf8f4806848e34aa7d3bd7e2cb9f5d9ff21395ff6d34826ac2fdc3cc683f6120e405f446a10e0f3
+Result = Fail (2 - CT changed)
+
+Count = 85
+Nonce = ce2e9967bf9eb7
+Adata = 00
+CT = e4f6445ca36e7ee3323f11f6a5ca8ded0c85871e092aa687d254f7765b6155054a5efde28dd38750
+Result = Fail (1 - Adata changed)
+
+Count = 86
+Nonce = b672c91376f533
+Adata = 00
+CT = f23ac1426cb1130c9a0913b347d8efafb6ed125913aa678a9dc42d22a5436bc12eff5505edb25e19
+Result = Pass (0)
+Payload = 4f7a561e61b7861719e4445057ac9b74a9be953b772b09ec
+
+Count = 87
+Nonce = 62f6f1872462d8
+Adata = 00
+CT = ac9f131389181b1023f1ee47633aa433fc5d93a87d9ece962db05feb368ab772d977fd97b35262fa
+Result = Fail (1 - Adata changed)
+
+Count = 88
+Nonce = a6d01fb88ca547
+Adata = 00
+CT = 773b8eea2e9830297ac11d3c1f6ea4008c96040e83d76d55789d2043179fdd8fdcbd52313b7b15cb
+Result = Pass (0)
+Payload = a36155de477364236591e453008114075b4872120ef17264
+
+Count = 89
+Nonce = 46ad6ebbd8644a
+Adata = 00
+CT = d3fae92043c419fe8ac0d7491ca8041ad089559d895103cf079a2bac0ab4bc249bbdb330181cdd16
+Result = Fail (1 - Adata changed)
+
+[Alen = 0, Plen = 24, Nlen = 13, Tlen = 4]
+
+Key = f7079dfa3b5c7b056347d7e437bcded683abd6e2c9e069d333284082cbb5d453
+
+Count = 90
+Nonce = a544218dadd3c10583db49cf39
+Adata = 00
+CT = 63e00d30e4b08fd2a1cc8d70fab327b2368e77a93be4f4123d14fb3f
+Result = Pass (0)
+Payload = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e
+
+Count = 91
+Nonce = 894dcaa61008eb8fb052c60d41
+Adata = 00
+CT = bb5425b3869b76856ec58e39886fb6f6f2ac13fe44cb132d8d0c0099
+Result = Fail (2 - CT changed)
+
+Count = 92
+Nonce = 8feba0d720aa4a5e35abc99e82
+Adata = 00
+CT = 2ca3be419d5be5ed682f8954d2c20efd9e6d360814735daeefd4365c
+Result = Fail (1 - Adata changed)
+
+Count = 93
+Nonce = ed04c9ca8702aec8d0a58e09a0
+Adata = 00
+CT = 3d34bda62db39d6118d6fd5cd38f1a3820ca69ce584b94a2a4ccbef1
+Result = Fail (1 - Adata changed)
+
+Count = 94
+Nonce = 1501a243bf60b2cb40d5aa20ca
+Adata = 00
+CT = 377b2f1e7bd9e3d1077038e084f61950761361095f7eeebbf1a72afc
+Result = Pass (0)
+Payload = f5730a05fec31a11662e2e14e362ccc75c7c30cdfccbf994
+
+Count = 95
+Nonce = c6edaf35f0cb433500a8c3a613
+Adata = 00
+CT = 9cef6c889ff51666df9dd1dd2215c15f4b2078a29373c106be4f5f9a
+Result = Fail (2 - CT changed)
+
+Count = 96
+Nonce = d65e0e53f765f9d5e6795c0c5e
+Adata = 00
+CT = 6cab3060bf3b33b163b933c2ed0ba51406810b54d0edcf5c9d0ef4f7
+Result = Pass (0)
+Payload = 20e394c7cc90bdfa6186fc1ba6fff158dfc690e24ba4c9fb
+
+Count = 97
+Nonce = 2b0163418a341588db0f5786d8
+Adata = 00
+CT = f9543a659e9a8b7d75dd859df923817452735f5051726422c08a9e85
+Result = Fail (2 - CT changed)
+
+Count = 98
+Nonce = f16bba081bddda83546eabc9a5
+Adata = 00
+CT = 0d20bf6a9d02da72091d94cdb38743bfea2473d3ab62dcad75dd819a
+Result = Fail (2 - CT changed)
+
+Count = 99
+Nonce = ace99268a32b9c1b5ccd8b0d84
+Adata = 00
+CT = 8bca01e6ebd7ebcdfe52b88e314670ffeb35882fc05394b386e205f9
+Result = Fail (2 - CT changed)
+
+Count = 100
+Nonce = 24570517bbb0df1b3fbd32f57a
+Adata = 00
+CT = 7061c84e2e1d9d58013543ff82666055a1f055c1296c42c8f73a8bf0
+Result = Fail (1 - Adata changed)
+
+Count = 101
+Nonce = a6b2371acf8321864c08ddb4d8
+Adata = 00
+CT = c5aa500d1f7c09a590e9d15d6860c4433684e04dd6bc5c8f94f223f0
+Result = Pass (0)
+Payload = 1a43ca628026219c5a430c54021a5a3152ae517167399635
+
+Count = 102
+Nonce = f8e2d4e043f5fe7a72b6117811
+Adata = 00
+CT = e3efa7971e27ba1245ee9491ebdbb28ad9b24b325da5760417af8b14
+Result = Fail (1 - Adata changed)
+
+Count = 103
+Nonce = c2b60f14c894ec6178fe79919f
+Adata = 00
+CT = 852cca903d7fdf899807bd14642057534c8a0ccacb8c7b8fb4d35d44
+Result = Pass (0)
+Payload = 3e707d98f19972a63d913e6ea7533af2f41ff98aee2b2a36
+
+Count = 104
+Nonce = 4de4c909ac0cc5fc608baf45ac
+Adata = 00
+CT = e04fd4f5b60833021ed57c98de300bb68d0d892b2bf68e080bc044b1
+Result = Fail (1 - Adata changed)
+
+[Alen = 0, Plen = 24, Nlen = 13, Tlen = 16]
+
+Key = 1b0e8df63c57f05d9ac457575ea764524b8610ae5164e6215f426f5a7ae6ede4
+
+Count = 105
+Nonce = a544218dadd3c10583db49cf39
+Adata = 00
+CT = f0050ad16392021a3f40207bed3521fb1e9f808f49830c423a578d179902f912f9ea1afbce1120b3
+Result = Pass (0)
+Payload = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e
+
+Count = 106
+Nonce = 894dcaa61008eb8fb052c60d41
+Adata = 00
+CT = c408190d0fbf5034f83b24a8ed9657331a7ce141de4fae769084607b83bd06e6442eac8dacf583cc
+Result = Fail (2 - CT changed)
+
+Count = 107
+Nonce = 8feba0d720aa4a5e35abc99e82
+Adata = 00
+CT = 52b3d31d02d1b92b38cbae8c510204dde6bf9588e994296c9002a46cfb734290924a15e9c3d99924
+Result = Fail (1 - Adata changed)
+
+Count = 108
+Nonce = ed04c9ca8702aec8d0a58e09a0
+Adata = 00
+CT = f80190470212ce1e64bf4c64ca0133d90469abf87a8233c2b238e316c3f9adccce95e8c8b9c7e8d2
+Result = Fail (1 - Adata changed)
+
+Count = 109
+Nonce = 1501a243bf60b2cb40d5aa20ca
+Adata = 00
+CT = 254b847d4175bbb44a82b4e805514fa444c224710933f3ec8aaa3f0133234c0cd91609982adc034b
+Result = Pass (0)
+Payload = f5730a05fec31a11662e2e14e362ccc75c7c30cdfccbf994
+
+Count = 110
+Nonce = c6edaf35f0cb433500a8c3a613
+Adata = 00
+CT = 7a5c7bc02aa69efc5a159d653f3993399f69e20752c3b00633255731cd88345860da913bc696fdc1
+Result = Fail (2 - CT changed)
+
+Count = 111
+Nonce = d65e0e53f765f9d5e6795c0c5e
+Adata = 00
+CT = c3618c991b15de641d291419ff6957e8b9ae5046dd8c6f08fafb76adf12f36740347e3edae62bca4
+Result = Pass (0)
+Payload = 20e394c7cc90bdfa6186fc1ba6fff158dfc690e24ba4c9fb
+
+Count = 112
+Nonce = 2b0163418a341588db0f5786d8
+Adata = 00
+CT = 240927bfd671a92aef0311395ad55ae42233ecee53873da4066f55f23d4e55bcbbbf2312ea2d8071
+Result = Fail (2 - CT changed)
+
+Count = 113
+Nonce = f16bba081bddda83546eabc9a5
+Adata = 00
+CT = 4731a7e690c77cd47582ce54a1cec23d94c856b93a9fc767004753689cc84810b8414f1464c0c5b9
+Result = Fail (2 - CT changed)
+
+Count = 114
+Nonce = ace99268a32b9c1b5ccd8b0d84
+Adata = 00
+CT = f0ea12eaff20c3a50674aa1546aaae3bd5c9249108535b21504da83478ede24026ec91fb12769e4b
+Result = Fail (2 - CT changed)
+
+Count = 115
+Nonce = 24570517bbb0df1b3fbd32f57a
+Adata = 00
+CT = 5b164d9752ad6c497a7ab2d0bf8be68fea084ea5839b07b7c9fcf9b9fd5e99767a7b1679b57ea961
+Result = Fail (1 - Adata changed)
+
+Count = 116
+Nonce = a6b2371acf8321864c08ddb4d8
+Adata = 00
+CT = bd37326da18e5ac79a1a9512f724bb539530868576b79c67acb5a51d10a58d6584fbe73f1063c31b
+Result = Pass (0)
+Payload = 1a43ca628026219c5a430c54021a5a3152ae517167399635
+
+Count = 117
+Nonce = f8e2d4e043f5fe7a72b6117811
+Adata = 00
+CT = 0455b4dd1069281e10531c0dc180ced9a5ef5d3fe0007470ce54cd7623a80a176f29a01b3abb642e
+Result = Fail (1 - Adata changed)
+
+Count = 118
+Nonce = c2b60f14c894ec6178fe79919f
+Adata = 00
+CT = ecd337640022635ce1ed273756d02b7feeb2515614c1fadc95c66d3f411b478853886afd177d88c3
+Result = Pass (0)
+Payload = 3e707d98f19972a63d913e6ea7533af2f41ff98aee2b2a36
+
+Count = 119
+Nonce = 4de4c909ac0cc5fc608baf45ac
+Adata = 00
+CT = e25d7c9fb388596b13a13b885d5b24e31579a3494ad256da830b2b6317716b3975e2b101aebdd920
+Result = Fail (1 - Adata changed)
+
+[Alen = 32, Plen = 0, Nlen = 7, Tlen = 4]
+
+Key = 1b0e8df63c57f05d9ac457575ea764524b8610ae5164e6215f426f5a7ae6ede4
+
+Count = 120
+Nonce = a544218dadd3c1
+Adata = d3d5424e20fbec43ae495353ed830271515ab104f8860c988d15b6d36c038eab
+CT = 92d00fbe
+Result = Pass (0)
+Payload = 00
+
+Count = 121
+Nonce = 78c46e3249ca28
+Adata = 232e957c65ffa11988e830d4617d500f1c4a35c1221f396c41ab214f074ca2dc
+CT = 9143e5c4
+Result = Fail (2 - CT changed)
+
+Count = 122
+Nonce = c18d9e7971e2ae
+Adata = 0d40324aa758dbbb5391b5e6edb8a2310c94a4ae51d4fba8a7458d7cc8488baa
+CT = 54337466
+Result = Fail (1 - Adata changed)
+
+Count = 123
+Nonce = 162d061351d82d
+Adata = 106d1fb32d948b0d8884f178ad2332a599445fae0f6f71f9ebe53a60b2df9b8e
+CT = bf0bf84c
+Result = Fail (1 - Adata changed)
+
+Count = 124
+Nonce = 3fcb328bc96404
+Adata = 10b2ffed4f95af0f98ed4f77c677b5786ad01b31c095bbc6e1c99cf13977abba
+CT = 11250056
+Result = Pass (0)
+Payload = 00
+
+Count = 125
+Nonce = b3fd1eb1422277
+Adata = fa5398cf4cddbe4b45e9f5d7491cd9eefc5e494255961ba3f4b40d22b5f5fe76
+CT = 13de5339
+Result = Fail (2 - CT changed)
+
+Count = 126
+Nonce = c42ac63de6f12a
+Adata = 7ff8d06c5abcc50d3820de34b03089e6c5b202bcbaabca892825553d4d30020a
+CT = 4eed80fd
+Result = Pass (0)
+Payload = 00
+
+Count = 127
+Nonce = d4a7a672237e17
+Adata = d1cdad7fe886d07625a4334be6de4df0645d2a8b4008a8d35f04e6bcf87bfa56
+CT = 4bc2e450
+Result = Fail (2 - CT changed)
+
+Count = 128
+Nonce = b23255372455c6
+Adata = d2e2c3607c40e0a807b86c6ebbc502ab42bdb7f85ab26299cd963bbba3a3a8fa
+CT = b30e6bbd
+Result = Fail (2 - CT changed)
+
+Count = 129
+Nonce = 92272d40475fbb
+Adata = 2f3af695ee33a9ebe6a48ed1b00e337261857110bb104191a54fd13bd960d8bc
+CT = f7c11fe2
+Result = Fail (2 - CT changed)
+
+Count = 130
+Nonce = c4a756f6024a9d
+Adata = 2317b324b6420ada9ea7bf52b71c5faf2485528da5f56b42c517be6355cdb28b
+CT = 76673751
+Result = Fail (1 - Adata changed)
+
+Count = 131
+Nonce = 3a1701b185d33a
+Adata = e5d54df8ed9f89b98c5ebb1bc5d5279c2e182784ff4cd9c869ae152e29d7a2b2
+CT = 9a5382c3
+Result = Pass (0)
+Payload = 00
+
+Count = 132
+Nonce = e4db2e80dc3f63
+Adata = 7616bdf5737d01f936072b6576fa76556dfa072f7e2d7de16b9dc96ac8de409c
+CT = 9e632f56
+Result = Fail (1 - Adata changed)
+
+Count = 133
+Nonce = 4f490ce07e0150
+Adata = 3e12d09632c644c540077c6f90726d4167423a679322b2000a3f19cfcea02b33
+CT = e1842c46
+Result = Pass (0)
+Payload = 00
+
+Count = 134
+Nonce = b4aaf9ad1bde60
+Adata = 8c96c891456ddec29fe04299506723db2079a6667f96db5d198bf085acf2a4ef
+CT = 9f644671
+Result = Fail (1 - Adata changed)
+
+[Alen = 32, Plen = 0, Nlen = 7, Tlen = 16]
+
+Key = a4bc10b1a62c96d459fbaf3a5aa3face7313bb9e1253e696f96a7a8e36801088
+
+Count = 135
+Nonce = a544218dadd3c1
+Adata = d3d5424e20fbec43ae495353ed830271515ab104f8860c988d15b6d36c038eab
+CT = 93af11a08379eb37a16aa2837f09d69d
+Result = Pass (0)
+Payload = 00
+
+Count = 136
+Nonce = 78c46e3249ca28
+Adata = 232e957c65ffa11988e830d4617d500f1c4a35c1221f396c41ab214f074ca2dc
+CT = d19b0c14ec686a7961ca7c386d125a65
+Result = Fail (2 - CT changed)
+
+Count = 137
+Nonce = c18d9e7971e2ae
+Adata = 0d40324aa758dbbb5391b5e6edb8a2310c94a4ae51d4fba8a7458d7cc8488baa
+CT = 02ea916d60e2ceec6d9dc9b1185569b3
+Result = Fail (1 - Adata changed)
+
+Count = 138
+Nonce = 162d061351d82d
+Adata = 106d1fb32d948b0d8884f178ad2332a599445fae0f6f71f9ebe53a60b2df9b8e
+CT = fabd2d0c422b47d363ea9936ff4a311b
+Result = Fail (1 - Adata changed)
+
+Count = 139
+Nonce = 3fcb328bc96404
+Adata = 10b2ffed4f95af0f98ed4f77c677b5786ad01b31c095bbc6e1c99cf13977abba
+CT = b3884b69d117146cfa5529901753ddc0
+Result = Pass (0)
+Payload = 00
+
+Count = 140
+Nonce = b3fd1eb1422277
+Adata = fa5398cf4cddbe4b45e9f5d7491cd9eefc5e494255961ba3f4b40d22b5f5fe76
+CT = 7162026b6306e74fe32ece8433801bc2
+Result = Fail (2 - CT changed)
+
+Count = 141
+Nonce = c42ac63de6f12a
+Adata = 7ff8d06c5abcc50d3820de34b03089e6c5b202bcbaabca892825553d4d30020a
+CT = b53d93cbfd3d5cf3720cef5080bc7224
+Result = Pass (0)
+Payload = 00
+
+Count = 142
+Nonce = d4a7a672237e17
+Adata = d1cdad7fe886d07625a4334be6de4df0645d2a8b4008a8d35f04e6bcf87bfa56
+CT = c8bbecf69ecf8d10f0863bb4b7cbed51
+Result = Fail (2 - CT changed)
+
+Count = 143
+Nonce = b23255372455c6
+Adata = d2e2c3607c40e0a807b86c6ebbc502ab42bdb7f85ab26299cd963bbba3a3a8fa
+CT = 6037145cc23a175760ae4b573907c80c
+Result = Fail (2 - CT changed)
+
+Count = 144
+Nonce = 92272d40475fbb
+Adata = 2f3af695ee33a9ebe6a48ed1b00e337261857110bb104191a54fd13bd960d8bc
+CT = df7ea77425d631f652ffe096a8157f71
+Result = Fail (2 - CT changed)
+
+Count = 145
+Nonce = c4a756f6024a9d
+Adata = 2317b324b6420ada9ea7bf52b71c5faf2485528da5f56b42c517be6355cdb28b
+CT = 7182b25ef5b113c13fa8f6769e74f1e2
+Result = Fail (1 - Adata changed)
+
+Count = 146
+Nonce = 3a1701b185d33a
+Adata = e5d54df8ed9f89b98c5ebb1bc5d5279c2e182784ff4cd9c869ae152e29d7a2b2
+CT = 0a5d1bc02c5fe096a8b9d94d1267c49a
+Result = Pass (0)
+Payload = 00
+
+Count = 147
+Nonce = e4db2e80dc3f63
+Adata = 7616bdf5737d01f936072b6576fa76556dfa072f7e2d7de16b9dc96ac8de409c
+CT = 9eb6d9757ec7c56cc8c79461e0017486
+Result = Fail (1 - Adata changed)
+
+Count = 148
+Nonce = 4f490ce07e0150
+Adata = 3e12d09632c644c540077c6f90726d4167423a679322b2000a3f19cfcea02b33
+CT = 1eda43bf07f2bf003107f3a0ba3a4c18
+Result = Pass (0)
+Payload = 00
+
+Count = 149
+Nonce = b4aaf9ad1bde60
+Adata = 8c96c891456ddec29fe04299506723db2079a6667f96db5d198bf085acf2a4ef
+CT = 5287cc160c5dd3a0f9c1986aac2a621c
+Result = Fail (1 - Adata changed)
+
+[Alen = 32, Plen = 0, Nlen = 13, Tlen = 4]
+
+Key = a4bc10b1a62c96d459fbaf3a5aa3face7313bb9e1253e696f96a7a8e36801088
+
+Count = 150
+Nonce = a544218dadd3c10583db49cf39
+Adata = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e09a1005e024f6907
+CT = 866d4227
+Result = Pass (0)
+Payload = 00
+
+Count = 151
+Nonce = e8de970f6ee8e80ede933581b5
+Adata = 89f8b068d34f56bc49d839d8e47b347e6dae737b903b278632447e6c0485d26a
+CT = 94cb1127
+Result = Fail (2 - CT changed)
+
+Count = 152
+Nonce = 6de75d3c05e83755083399a5f7
+Adata = 504b08cf34cbe17acf631ef219ae01437ebb6a980ab2f00121bb3073701b6511
+CT = 82c2b67a
+Result = Fail (1 - Adata changed)
+
+Count = 153
+Nonce = 58d43b9f1581c590daab1a5c56
+Adata = 749f149ef306c70a5d006d9777adbbf7c0de453898c2978ef7c281535ea9b24c
+CT = 8c8283f9
+Result = Fail (1 - Adata changed)
+
+Count = 154
+Nonce = dfdcbdff329f7af70731d8e276
+Adata = 2ae56ddde2876d70b3b34eda8c2b1d096c836d5225d53ec460b724b6e16aa5a3
+CT = c4ac0952
+Result = Pass (0)
+Payload = 00
+
+Count = 155
+Nonce = 199ec321d1d24d5408076912d6
+Adata = a77526f3614cd974498a76d8b3cb7bacc623fdc9c85503289c462df888b199ed
+CT = c59aa931
+Result = Fail (2 - CT changed)
+
+Count = 156
+Nonce = 60f2490ba0c658848859fcbea8
+Adata = 3ad743283064929bf4fe4e0807f710f5e6a273e22614c728c3280a27b6c614a0
+CT = 27c3953d
+Result = Pass (0)
+Payload = 00
+
+Count = 157
+Nonce = 6f29ca274190400720bba27651
+Adata = c0850aaf141bd3f1b24f4d882590f58682b41f874748f29f8925b4914f444842
+CT = cb1ac8eb
+Result = Fail (2 - CT changed)
+
+Count = 158
+Nonce = f1dfb6fdb31cb423226f181c09
+Adata = ac6b08900fc1c9463e7dfdb60eee444c4989d7b200e675f3220ba1e14eed0ab4
+CT = 4dcc55cc
+Result = Fail (2 - CT changed)
+
+Count = 159
+Nonce = 0d45226c98eaa9bb445a3aa4f9
+Adata = b9cb3e1a5bcccb0b0599414c9822275b66fa0f913d51bdb0a2228cbb5aad0e0a
+CT = 727d8f5e
+Result = Fail (2 - CT changed)
+
+Count = 160
+Nonce = 39cdbb24bd273a3fe96f42ca9d
+Adata = ddfe6c22f4cdc3128050072005f5bd4ecdef1d836e891683f1ba921d33fafba7
+CT = 5aa56a54
+Result = Fail (1 - Adata changed)
+
+Count = 161
+Nonce = db113f38f0504615c5c9347c3d
+Adata = 3b71bc84e48c6dadf6ead14621d22468a3d4c9c103ac96970269730bcfce239b
+CT = c38fbdff
+Result = Pass (0)
+Payload = 00
+
+Count = 162
+Nonce = d16a20ef5f6587f1ee3cb7850b
+Adata = b1133e1cd369617a9f937e9a1eb86a0979ee30b5b7b0b6ff838d9e11301d6b72
+CT = 6be30c42
+Result = Fail (1 - Adata changed)
+
+Count = 163
+Nonce = d35f531f714694b5e49303a980
+Adata = 55b791ee495299916ff3c2327b4990952bebd0a2da9acfc553c6c996e354a4b5
+CT = d34e90bb
+Result = Pass (0)
+Payload = 00
+
+Count = 164
+Nonce = 220624db34a022b758473994a2
+Adata = 5b3b2ae87b0d6759f38a858423227f8687f35478a8f565409b741eadcac4d8c4
+CT = 4a5d14bc
+Result = Fail (1 - Adata changed)
+
+[Alen = 32, Plen = 0, Nlen = 13, Tlen = 16]
+
+Key = 8c5cf3457ff22228c39c051c4e05ed4093657eb303f859a9d4b0f8be0127d88a
+
+Count = 165
+Nonce = a544218dadd3c10583db49cf39
+Adata = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e09a1005e024f6907
+CT = 867b0d87cf6e0f718200a97b4f6d5ad5
+Result = Pass (0)
+Payload = 00
+
+Count = 166
+Nonce = e8de970f6ee8e80ede933581b5
+Adata = 89f8b068d34f56bc49d839d8e47b347e6dae737b903b278632447e6c0485d26a
+CT = 677a040d46ee3f2b7838273bdad14f16
+Result = Fail (2 - CT changed)
+
+Count = 167
+Nonce = 6de75d3c05e83755083399a5f7
+Adata = 504b08cf34cbe17acf631ef219ae01437ebb6a980ab2f00121bb3073701b6511
+CT = f650d46ade2cbabbc68ead6df1ea0c37
+Result = Fail (1 - Adata changed)
+
+Count = 168
+Nonce = 58d43b9f1581c590daab1a5c56
+Adata = 749f149ef306c70a5d006d9777adbbf7c0de453898c2978ef7c281535ea9b24c
+CT = 11b8fe8c139ee38f77fd8fa552cbff67
+Result = Fail (1 - Adata changed)
+
+Count = 169
+Nonce = dfdcbdff329f7af70731d8e276
+Adata = 2ae56ddde2876d70b3b34eda8c2b1d096c836d5225d53ec460b724b6e16aa5a3
+CT = ad879c64425e6c1ec4841bbb0f99aa8b
+Result = Pass (0)
+Payload = 00
+
+Count = 170
+Nonce = 199ec321d1d24d5408076912d6
+Adata = a77526f3614cd974498a76d8b3cb7bacc623fdc9c85503289c462df888b199ed
+CT = 3c64f8731930ae000162c10654531066
+Result = Fail (2 - CT changed)
+
+Count = 171
+Nonce = 60f2490ba0c658848859fcbea8
+Adata = 3ad743283064929bf4fe4e0807f710f5e6a273e22614c728c3280a27b6c614a0
+CT = e2751f153fc76c0dec5e0cf2d30c1a28
+Result = Pass (0)
+Payload = 00
+
+Count = 172
+Nonce = 6f29ca274190400720bba27651
+Adata = c0850aaf141bd3f1b24f4d882590f58682b41f874748f29f8925b4914f444842
+CT = 76127bf891141e73854752ed10c02bd0
+Result = Fail (2 - CT changed)
+
+Count = 173
+Nonce = f1dfb6fdb31cb423226f181c09
+Adata = ac6b08900fc1c9463e7dfdb60eee444c4989d7b200e675f3220ba1e14eed0ab4
+CT = 4bd833f9da0496e5f6a08a05d02df385
+Result = Fail (2 - CT changed)
+
+Count = 174
+Nonce = 0d45226c98eaa9bb445a3aa4f9
+Adata = b9cb3e1a5bcccb0b0599414c9822275b66fa0f913d51bdb0a2228cbb5aad0e0a
+CT = 05f166328a67a8c58b10a7348f3df612
+Result = Fail (2 - CT changed)
+
+Count = 175
+Nonce = 39cdbb24bd273a3fe96f42ca9d
+Adata = ddfe6c22f4cdc3128050072005f5bd4ecdef1d836e891683f1ba921d33fafba7
+CT = 42499bcd949a5163855a9794f11f917e
+Result = Fail (1 - Adata changed)
+
+Count = 176
+Nonce = db113f38f0504615c5c9347c3d
+Adata = 3b71bc84e48c6dadf6ead14621d22468a3d4c9c103ac96970269730bcfce239b
+CT = fc85464a81fe372c12c9e4f0f3bf9c37
+Result = Pass (0)
+Payload = 00
+
+Count = 177
+Nonce = d16a20ef5f6587f1ee3cb7850b
+Adata = b1133e1cd369617a9f937e9a1eb86a0979ee30b5b7b0b6ff838d9e11301d6b72
+CT = 8c7501f423647dee77668858c5e350bb
+Result = Fail (1 - Adata changed)
+
+Count = 178
+Nonce = d35f531f714694b5e49303a980
+Adata = 55b791ee495299916ff3c2327b4990952bebd0a2da9acfc553c6c996e354a4b5
+CT = b1c09b093788da19e33c5a6e82ed9627
+Result = Pass (0)
+Payload = 00
+
+Count = 179
+Nonce = 220624db34a022b758473994a2
+Adata = 5b3b2ae87b0d6759f38a858423227f8687f35478a8f565409b741eadcac4d8c4
+CT = d2231ee1455b0bc337c4f8173fb8647c
+Result = Fail (1 - Adata changed)
+
+[Alen = 32, Plen = 24, Nlen = 7, Tlen = 4]
+
+Key = 8c5cf3457ff22228c39c051c4e05ed4093657eb303f859a9d4b0f8be0127d88a
+
+Count = 180
+Nonce = a544218dadd3c1
+Adata = d3d5424e20fbec43ae495353ed830271515ab104f8860c988d15b6d36c038eab
+CT = c2fe12658139f5d0dd22cadf2e901695b579302a72fc56083ebc7720
+Result = Pass (0)
+Payload = 78c46e3249ca28e1ef0531d80fd37c124d9aecb7be6668e3
+
+Count = 181
+Nonce = 6ba004fd176791
+Adata = 5a053b2a1bb87e85d56527bfcdcd3ecafb991bb10e4c862bb0751c700a29f54b
+CT = 94748ba81229e53c38583a8564b23ebbafc6f6efdf4c2a81c44db2c9
+Result = Fail (2 - CT changed)
+
+Count = 182
+Nonce = 45c5c284836414
+Adata = 8f01a61eb17366d4e70942ab69b4f4bcf8ff6a97f5972ee5780a264c9dcf7d93
+CT = 1d670ccf3e9ba59186c48da2e5bd0ab21973eee2ea2985bf83a09067
+Result = Fail (1 - Adata changed)
+
+Count = 183
+Nonce = c69f7679c80546
+Adata = 5d6c04a5b422b46065a79a889e30ac8d1b53b65d230d4c88190903a24e1fe1ea
+CT = 2c8c80ff10fac1bf6c9c83533c1514ee032c0983730b0657392ae25d
+Result = Fail (1 - Adata changed)
+
+Count = 184
+Nonce = 57b940550a383b
+Adata = 33c2c3a57bf8393b126982c96d87daeacd5eadad1519073ad8c84cb9b760296f
+CT = e1b4ec4279bb62902c12521e6b874171695c5da46c647cc03b91ff03
+Result = Pass (0)
+Payload = 6fb5ce32a851676753ba3523edc5ca82af1843ffc08f1ef0
+
+Count = 185
+Nonce = 11edd12ea5873d
+Adata = e32e5384038379e2b7382ba337b6f7a72a1569e110ee89c4dd6aa6f7e69f5250
+CT = b5dda89fe879d6a665b99285b6d937fd5877ebef4de049fb64b837fb
+Result = Fail (2 - CT changed)
+
+Count = 186
+Nonce = f32222e9eec4bd
+Adata = 684595e36eda1db5f586941c9f34c9f8d477970d5ccc14632d1f0cec8190ae68
+CT = 224db21beb8cd0069007660e783c3f85706b014128368aab2a4e56a7
+Result = Pass (0)
+Payload = 2c29d4e2bb9294e90cb04ec697e663a1f7385a39f90c8ccf
+
+Count = 187
+Nonce = e0a0a7f262cb51
+Adata = 1d93b2856ad2bf3700440f9a281bd8947ba209e9ffd18e69921ed0678c957c6c
+CT = ba1ce3a799e1173178b6788723005566f9269d5828c85d28e960a769
+Result = Fail (2 - CT changed)
+
+Count = 188
+Nonce = 40316e7b38bdad
+Adata = 6e49acd9c26944740c778e74b1dbaa8d640c7e18e949a1661f8a77543db69e1f
+CT = 79d59e4bb251988c019c4eaaee2a2513f9cb0521334018fded14a5a5
+Result = Fail (2 - CT changed)
+
+Count = 189
+Nonce = 33008ef5baf263
+Adata = a726f31d9a22bfc0e7e4c3111b0d304e106ab04ed318f8bfe6ec9cb3a811285b
+CT = af4350795f24087aa05070d6d5f55ebb12d7ad3141066866d7d6c61d
+Result = Fail (2 - CT changed)
+
+Count = 190
+Nonce = b48a16fb9a065d
+Adata = be05e9c934c1dcba45223d47c6646a2d13c3b93265e354ae4970484b5101d809
+CT = 22d2da531be1f0d1da4bc21f984d29bf56bed2e92da6bf42d0605b84
+Result = Fail (1 - Adata changed)
+
+Count = 191
+Nonce = 14c9bd561c47c1
+Adata = 141ae365f8e65ab9196c4e8cd4e62189b304d67de38f2117e84ec0ec8f260ebd
+CT = 61b46c9024eed3989064a52df90349c18e14e4b552779d3f8f9d6814
+Result = Pass (0)
+Payload = c22524a1ea444be3412b0d773d4ea2ff0af4c1ad2383cba8
+
+Count = 192
+Nonce = 5fb871eac2e52a
+Adata = ff23906e9067da8999842318f2a867759ca2d171395c2ff31fa5a4e2ab349c45
+CT = 539799c2b22a33dd648fc4497d12f9455beaf932f1eaaff4d930f5ce
+Result = Fail (1 - Adata changed)
+
+Count = 193
+Nonce = 1ccec9923aa6e8
+Adata = 88a6d037009a1c1756f72bb4589d6d940bd514ed55386baefacc6ac3ca6f8795
+CT = 52f8205534447d722be2b9377f7395938cc88af081a11ccb0d83fa19
+Result = Pass (0)
+Payload = 518a7fb11c463bf23798982118f3cfe4d7ddde9184f37d4f
+
+Count = 194
+Nonce = 68a5351e4422c8
+Adata = 303c767468f48ac9f6e331bbad535b06aa00ab593327320799e17eff63afd3fe
+CT = d11c892ae155098f5e4b5fe60c7afd74fb2dbcc4db956556f243e273
+Result = Fail (1 - Adata changed)
+
+[Alen = 32, Plen = 24, Nlen = 7, Tlen = 16]
+
+Key = 705334e30f53dd2f92d190d2c1437c8772f940c55aa35e562214ed45bd458ffe
+
+Count = 195
+Nonce = a544218dadd3c1
+Adata = d3d5424e20fbec43ae495353ed830271515ab104f8860c988d15b6d36c038eab
+CT = 3341168eb8c48468c414347fb08f71d2086f7c2d1bd581ce1ac68bd42f5ec7fa7e068cc0ecd79c2a
+Result = Pass (0)
+Payload = 78c46e3249ca28e1ef0531d80fd37c124d9aecb7be6668e3
+
+Count = 196
+Nonce = 6ba004fd176791
+Adata = 5a053b2a1bb87e85d56527bfcdcd3ecafb991bb10e4c862bb0751c700a29f54b
+CT = d543acda712b898cbb27b8f598b2e4438ce587a836e2785147c3338a2400809e739b63ba8227d2f9
+Result = Fail (2 - CT changed)
+
+Count = 197
+Nonce = 45c5c284836414
+Adata = 8f01a61eb17366d4e70942ab69b4f4bcf8ff6a97f5972ee5780a264c9dcf7d93
+CT = 39a8af5c976b995ea8049e55b68bc65503592ab00915638646288ce9dd1c7088c752e35947fdca98
+Result = Fail (1 - Adata changed)
+
+Count = 198
+Nonce = c69f7679c80546
+Adata = 5d6c04a5b422b46065a79a889e30ac8d1b53b65d230d4c88190903a24e1fe1ea
+CT = 950fbf6445f6ffb68178f52f5079d0c6081a48ae1f267a0b7fd89caef9388fbb82361b8d53d9edc6
+Result = Fail (1 - Adata changed)
+
+Count = 199
+Nonce = 57b940550a383b
+Adata = 33c2c3a57bf8393b126982c96d87daeacd5eadad1519073ad8c84cb9b760296f
+CT = fbfed2c94f50ca10466da9903ef85833ad48ca00556e66d14d8b30df941f3536ffb42083ef0e1c30
+Result = Pass (0)
+Payload = 6fb5ce32a851676753ba3523edc5ca82af1843ffc08f1ef0
+
+Count = 200
+Nonce = 11edd12ea5873d
+Adata = e32e5384038379e2b7382ba337b6f7a72a1569e110ee89c4dd6aa6f7e69f5250
+CT = 2ebfeb7a843618b37025352df3538526517ed320adfb486c04cf3426e8f975125a7eed00e5f33b6c
+Result = Fail (2 - CT changed)
+
+Count = 201
+Nonce = f32222e9eec4bd
+Adata = 684595e36eda1db5f586941c9f34c9f8d477970d5ccc14632d1f0cec8190ae68
+CT = dae13e6967c8b1ee0dd2d5ba1dd1de69f22c95da39528f9ef78e9e5e9faa058112af57f4ac78db2c
+Result = Pass (0)
+Payload = 2c29d4e2bb9294e90cb04ec697e663a1f7385a39f90c8ccf
+
+Count = 202
+Nonce = e0a0a7f262cb51
+Adata = 1d93b2856ad2bf3700440f9a281bd8947ba209e9ffd18e69921ed0678c957c6c
+CT = e683040a0bcf04c1748e7746400d6ef0f7cd8e77a29517790c63959ce534a0f87fb42a9b000dec84
+Result = Fail (2 - CT changed)
+
+Count = 203
+Nonce = 40316e7b38bdad
+Adata = 6e49acd9c26944740c778e74b1dbaa8d640c7e18e949a1661f8a77543db69e1f
+CT = 829e50e8c09e727a58287e6eb7d38edeb8ab39db279c06397d1a2111dc21aec79ef73193b306d31f
+Result = Fail (2 - CT changed)
+
+Count = 204
+Nonce = 33008ef5baf263
+Adata = a726f31d9a22bfc0e7e4c3111b0d304e106ab04ed318f8bfe6ec9cb3a811285b
+CT = 873c91e76dca0062ae66325aefb84ece3e98928f8dbc5fee7c516d2d1a8318893923f398ca249401
+Result = Fail (2 - CT changed)
+
+Count = 205
+Nonce = b48a16fb9a065d
+Adata = be05e9c934c1dcba45223d47c6646a2d13c3b93265e354ae4970484b5101d809
+CT = 343f6c86f2b852ac388a096faec4472107a924aba56d0cb88055e777bb57eb49497cd2e233ee06fd
+Result = Fail (1 - Adata changed)
+
+Count = 206
+Nonce = 14c9bd561c47c1
+Adata = 141ae365f8e65ab9196c4e8cd4e62189b304d67de38f2117e84ec0ec8f260ebd
+CT = a654238fb8b05e293dba07f9d68d75a7f0fbf40fe20edaeba1586bf922412e73ce338e372615c3bc
+Result = Pass (0)
+Payload = c22524a1ea444be3412b0d773d4ea2ff0af4c1ad2383cba8
+
+Count = 207
+Nonce = 5fb871eac2e52a
+Adata = ff23906e9067da8999842318f2a867759ca2d171395c2ff31fa5a4e2ab349c45
+CT = 4846816923ed9f0254bdd0be01028f75061d3594ad3a45bd03538d108df6ecd6f39acfe076ba5fb8
+Result = Fail (1 - Adata changed)
+
+Count = 208
+Nonce = 1ccec9923aa6e8
+Adata = 88a6d037009a1c1756f72bb4589d6d940bd514ed55386baefacc6ac3ca6f8795
+CT = 765067ef768908d91ee4c3923943e0c7be70e2e06db99a4b3e3f51ee37fdcc5d81dd85d9e9d4f44e
+Result = Pass (0)
+Payload = 518a7fb11c463bf23798982118f3cfe4d7ddde9184f37d4f
+
+Count = 209
+Nonce = 68a5351e4422c8
+Adata = 303c767468f48ac9f6e331bbad535b06aa00ab593327320799e17eff63afd3fe
+CT = e58ea6c1522e5a3e93a85edd05ae80d6cf5c4dd6d604a8f8d8a906488f79ad5d2234d72458dcfcd4
+Result = Fail (1 - Adata changed)
+
+[Alen = 32, Plen = 24, Nlen = 13, Tlen = 4]
+
+Key = 705334e30f53dd2f92d190d2c1437c8772f940c55aa35e562214ed45bd458ffe
+
+Count = 210
+Nonce = a544218dadd3c10583db49cf39
+Adata = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e09a1005e024f6907
+CT = c0ea400b599561e7905b99262b4565d5c3dc49fad84d7c69ef891339
+Result = Pass (0)
+Payload = e8de970f6ee8e80ede933581b5bcf4d837e2b72baa8b00c3
+
+Count = 211
+Nonce = 8fa501c5dd9ac9b868144c9fa5
+Adata = 5bb40e3bb72b4509324a7edc852f72535f1f6283156e63f6959ffaf39dcde800
+CT = 60871e03ea0eb968536c99f926ea24ef43d41272ad9fb7f63d488623
+Result = Fail (2 - CT changed)
+
+Count = 212
+Nonce = 9bc0d1502a47e46350fe8667ca
+Adata = 07203674260208d5bd4d39506836f7e76ffc58e938799f21aff7bb4dea4410d2
+CT = 81d7859dcbe51dcc94fe2591cd3b0540003d49a8c4dccbf4527e5ed0
+Result = Fail (1 - Adata changed)
+
+Count = 213
+Nonce = 611cb4c66e88f6acf96fea1919
+Adata = 327ee3657e49d4d988362fabae303ccea6638e5cb45993d9d56269bc3d3af32b
+CT = bef380ad725b65fb5fceeabf09c665bc35089f434ec831494d20d5fa
+Result = Fail (1 - Adata changed)
+
+Count = 214
+Nonce = 0dd613c0fe28e913c0edbb8404
+Adata = 2ad306575b577c2f61da7212ab63e3db3941f1f751f2356c7443531a90b9d141
+CT = fabe11c9629e598228f5209f3dbcc641fe4b1a22cadb0821d2898c3b
+Result = Pass (0)
+Payload = 9522fb1f1aa58493cba682d788186d902cfc93e80fd6b998
+
+Count = 215
+Nonce = 68806dfe720d0a9a84697de5f2
+Adata = c6b0e4dfd723d7637510f887b7852f60ecdf72e0d33396560fed6534d5b7f015
+CT = b7eb87f84951640de731d4093f1a4ed5f831138a27465d3941e92090
+Result = Fail (2 - CT changed)
+
+Count = 216
+Nonce = 3e0fe3427eeda80f02dda4fed5
+Adata = ae0d1c9c834d60ff0ecfb3c0d78c72ddb789e58adfc166c81d5fc6395b31ec33
+CT = d88f8fcd772125212ce09c2a6e5b5693dd35073f992004f0d18fc889
+Result = Pass (0)
+Payload = 38333ce78110bf53a2c2abc7db99e133ad218ca43ff7a7bc
+
+Count = 217
+Nonce = 7c0c76d9f9316ff6c98758b464
+Adata = 31a0338c3839931fa1dd5131cb796c4c6cfde9fb336d8a80ac35dec463be7a94
+CT = d2d7d52b11304fc1d15b8c20e296ba7c63d99f4ce86cc8ae0f39ecea
+Result = Fail (2 - CT changed)
+
+Count = 218
+Nonce = 07c728135bdfede0e0c8036b17
+Adata = 25a152850b4b80b19d8f0b504b2a8a241824b3a1fca8d85c8713b2c0c84b5e02
+CT = ae1d9f82efb464d5dc2018cffa309634c09b34d1122c4bd994b1d516
+Result = Fail (2 - CT changed)
+
+Count = 219
+Nonce = 710c96d7a6f09de83f0507f28a
+Adata = 2d64acfdbfc582cd9a933790eb1b739fb02e53f511255e49f421bb7acc98a130
+CT = 477c985d92ad1b69d22315235a29e3d3a5991487cbdc8d11d394d047
+Result = Fail (2 - CT changed)
+
+Count = 220
+Nonce = 977bbcdeb6a7d9dcf8664bc2d8
+Adata = 135786125258a49475338ac1961d2718433b9e84cf64f63ca52913e8dd12e505
+CT = d1c085c75d808dc6db493b8a0b4d884e0700d2844a1b4b46bd3d22eb
+Result = Fail (1 - Adata changed)
+
+Count = 221
+Nonce = 60122cbd219e5cf17415e8bc09
+Adata = 895a45ddbe0c80793eccbf820de13a233b6aa7045cfd5313388e7184c392b216
+CT = 76bdd9a7b34bf14ae121a87fdfa144f71b848744af6a2f0b1c0d067c
+Result = Pass (0)
+Payload = 794e734966e6d0001699aec3f8ab8f194de7653d3091b1b9
+
+Count = 222
+Nonce = 83a07f2e685959cb50a1bd2bce
+Adata = 02afe300ec0cf0acb59108b2f70e069300294e34f40bb032cb59907599664408
+CT = 413e2e8df9d65b4e5d3b63a738258aaee643f364be9a01b974192744
+Result = Fail (1 - Adata changed)
+
+Count = 223
+Nonce = 3542fbe0f59a6d5f3abf619b7d
+Adata = dd4531f158a2fa3bc8a339f770595048f4a42bc1b03f2e824efc6ba4985119d8
+CT = 617d8036e2039d516709062379e0550cbd71ebb90fea967c79018ad5
+Result = Pass (0)
+Payload = c5b3d71312ea14f2f8fae5bd1a453192b6604a45db75c5ed
+
+Count = 224
+Nonce = 48f2d4c0b17072e0a9c300d90b
+Adata = c56175e2cfe0d37454d989afcc36686fb34c015439601567506a4d0003182be7
+CT = 40e609c739e409750a6c41d9c6ea64ce36f70711b4ca3e365c916f91
+Result = Fail (1 - Adata changed)
+
+[Alen = 32, Plen = 24, Nlen = 13, Tlen = 16]
+
+Key = 314a202f836f9f257e22d8c11757832ae5131d357a72df88f3eff0ffcee0da4e
+
+Count = 225
+Nonce = a544218dadd3c10583db49cf39
+Adata = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e09a1005e024f6907
+CT = 8d34cdca37ce77be68f65baf3382e31efa693e63f914a781367f30f2eaad8c063ca50795acd90203
+Result = Pass (0)
+Payload = e8de970f6ee8e80ede933581b5bcf4d837e2b72baa8b00c3
+
+Count = 226
+Nonce = 8fa501c5dd9ac9b868144c9fa5
+Adata = 5bb40e3bb72b4509324a7edc852f72535f1f6283156e63f6959ffaf39dcde800
+CT = 516c0095cc3d85fd55e48da17c592e0c7014b9daafb82bdc4b41096dfdbe9cc1ab610f8f3e038d16
+Result = Fail (2 - CT changed)
+
+Count = 227
+Nonce = 9bc0d1502a47e46350fe8667ca
+Adata = 07203674260208d5bd4d39506836f7e76ffc58e938799f21aff7bb4dea4410d2
+CT = 0293eae9f8d8bd7ad45357f733fc7b5d990d894783e18501d81ec96df41b8fa8262ed2db880b5e85
+Result = Fail (1 - Adata changed)
+
+Count = 228
+Nonce = 611cb4c66e88f6acf96fea1919
+Adata = 327ee3657e49d4d988362fabae303ccea6638e5cb45993d9d56269bc3d3af32b
+CT = 256bad8295e67d8d450f5ecc8276920ec23b1156c57be7c96ee80f60f72db2cbf25b2f8c6af8749c
+Result = Fail (1 - Adata changed)
+
+Count = 229
+Nonce = 0dd613c0fe28e913c0edbb8404
+Adata = 2ad306575b577c2f61da7212ab63e3db3941f1f751f2356c7443531a90b9d141
+CT = 6df09613ea986c2d91a57a45a0942cbf20e0dfca12fbda8c945ee6db24aea5f5098952f1203339ce
+Result = Pass (0)
+Payload = 9522fb1f1aa58493cba682d788186d902cfc93e80fd6b998
+
+Count = 230
+Nonce = 68806dfe720d0a9a84697de5f2
+Adata = c6b0e4dfd723d7637510f887b7852f60ecdf72e0d33396560fed6534d5b7f015
+CT = c5b64577d3c34e50f7da5072db5bda1d1d2c6db1a4f1183e2cc4c90ac3f798957cb09a05868a8ad5
+Result = Fail (2 - CT changed)
+
+Count = 231
+Nonce = 3e0fe3427eeda80f02dda4fed5
+Adata = ae0d1c9c834d60ff0ecfb3c0d78c72ddb789e58adfc166c81d5fc6395b31ec33
+CT = 2bfe51f1f43b982d47f76ea8206ddbf585d6f30cec0d4ef16b1556631d3b52bf24154afec1448ef6
+Result = Pass (0)
+Payload = 38333ce78110bf53a2c2abc7db99e133ad218ca43ff7a7bc
+
+Count = 232
+Nonce = 7c0c76d9f9316ff6c98758b464
+Adata = 31a0338c3839931fa1dd5131cb796c4c6cfde9fb336d8a80ac35dec463be7a94
+CT = 1622ae109073f44a4596722d9943fea774dfc2a1f939fc0914f42ec81e3af71c9a5de7e0ac16ca69
+Result = Fail (2 - CT changed)
+
+Count = 233
+Nonce = 07c728135bdfede0e0c8036b17
+Adata = 25a152850b4b80b19d8f0b504b2a8a241824b3a1fca8d85c8713b2c0c84b5e02
+CT = 4c0b361a766d366d983c41e793d75635e17f6eab2eadcf9743d67d90850c4c76a43df1f95170b29b
+Result = Fail (2 - CT changed)
+
+Count = 234
+Nonce = 710c96d7a6f09de83f0507f28a
+Adata = 2d64acfdbfc582cd9a933790eb1b739fb02e53f511255e49f421bb7acc98a130
+CT = 5b02347f30213df7f1506d7dca41b838c92aea0f190c5dba7bd5d5c8c098299394333b34fae9a110
+Result = Fail (2 - CT changed)
+
+Count = 235
+Nonce = 977bbcdeb6a7d9dcf8664bc2d8
+Adata = 135786125258a49475338ac1961d2718433b9e84cf64f63ca52913e8dd12e505
+CT = c77283ca15484d82469ce7249d1fb8e5f4c3bc8245fb4d97e26149d4a9711be81b4f69aa9fabd7f6
+Result = Fail (1 - Adata changed)
+
+Count = 236
+Nonce = 60122cbd219e5cf17415e8bc09
+Adata = 895a45ddbe0c80793eccbf820de13a233b6aa7045cfd5313388e7184c392b216
+CT = bf0d219bb50fcc1d51f654bb0fd8b44efa25aef39e2f11afe47d00f2eebb544e6ba7559ac2f34edb
+Result = Pass (0)
+Payload = 794e734966e6d0001699aec3f8ab8f194de7653d3091b1b9
+
+Count = 237
+Nonce = 83a07f2e685959cb50a1bd2bce
+Adata = 02afe300ec0cf0acb59108b2f70e069300294e34f40bb032cb59907599664408
+CT = 1609f8de59da4f50ce034977d132d4f9881a9b85ffa5bb886fa3fddc87690a359fe55f8fa12ba749
+Result = Fail (1 - Adata changed)
+
+Count = 238
+Nonce = 3542fbe0f59a6d5f3abf619b7d
+Adata = dd4531f158a2fa3bc8a339f770595048f4a42bc1b03f2e824efc6ba4985119d8
+CT = 39c2e8f6edfe663b90963b98eb79e2d4f7f28a5053ae8881567a6b4426f1667136bed4a5e32a2bc1
+Result = Pass (0)
+Payload = c5b3d71312ea14f2f8fae5bd1a453192b6604a45db75c5ed
+
+Count = 239
+Nonce = 48f2d4c0b17072e0a9c300d90b
+Adata = c56175e2cfe0d37454d989afcc36686fb34c015439601567506a4d0003182be7
+CT = 27c575be0b99af9b106f53f471c31cac4d54ea0bcb602a33fb67bb6092cd579f722ae9b680da083d
+Result = Fail (1 - Adata changed)
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/Readme.txt b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/Readme.txt
new file mode 100644
index 0000000000..88bdc95fd0
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/Readme.txt
@@ -0,0 +1,9 @@
+There are two sets of CCM example files:
+
+1. The response (.rsp) files contain properly formatted CAVS response files.
+
+2. The three DVPT{128/192/256}.txt files contain the same values as the
+ DVPT{128/192/256}.rsp files but have additional information. For the cases
+ that fail, the reason for failure is in parentheses following the result:
+ e.g., Result = Fail (2 - CT changed)
+ This additional information is not in properly formatted response files.
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VADT128.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VADT128.rsp
new file mode 100644
index 0000000000..a4fe9130a0
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VADT128.rsp
@@ -0,0 +1,1823 @@
+# CAVS 11.0
+# "CCM-VADT" information
+# AES Keylen: 128
+# Generated on Tue Mar 15 08:09:24 2011
+
+Plen = 24
+Nlen = 13
+Tlen = 16
+
+[Alen = 0]
+
+Key = d24a3d3dde8c84830280cb87abad0bb3
+Nonce = f1100035bb24a8d26004e0e24b
+
+Count = 0
+Adata = 00
+Payload = 7c86135ed9c2a515aaae0e9a208133897269220f30870006
+CT = 1faeb0ee2ca2cd52f0aa3966578344f24e69b742c4ab37ab1123301219c70599b7c373ad4b3ad67b
+
+Count = 1
+Adata = 00
+Payload = 48df73208cdc63d716752df7794807b1b2a80794a2433455
+CT = 2bf7d09079bc0b904c711a0b0e4a70ca8ea892d9566f03f8b77a140819f39ef045103e785e1df8c2
+
+Count = 2
+Adata = 00
+Payload = b99de8168e8c13ea4aef66bdb93133dff5d57e9837ff6ccb
+CT = dab54ba67bec7bad10eb5141ce3344a4c9d5ebd5c3d35b664b01098842a618390619b86e00850b2e
+
+Count = 3
+Adata = 00
+Payload = 09fc21ac4a1f43de29621cacf3ad84e055c6b220721af7ce
+CT = 6ad4821cbf7f2b9973662b5084aff39b69c6276d8636c0638bd518724ab84fb814fe7b5570769f7f
+
+Count = 4
+Adata = 00
+Payload = cb43320d7488dfd6eed9efd88f440ea3f6f77a0df09d0727
+CT = a86b91bd81e8b791b4ddd824f84679d8caf7ef4004b1308a7229cbcecef221570cee8345b38cd6ec
+
+Count = 5
+Adata = 00
+Payload = a350ed58c04473e113b9088b1fb9dad92807f6b63b0d690c
+CT = c0784ee835241ba649bd3f7768bbada2140763fbcf215ea1fee47fec27d7764e5e2819c850088bac
+
+Count = 6
+Adata = 00
+Payload = 0709e691faf41383fab5d1848a8eee77101d1c99e526a264
+CT = 642145210f947bc4a0b1e678fd8c990c2c1d89d4110a95c954d610bc1ab4bc9a8a28c7306f7c539e
+
+Count = 7
+Adata = 00
+Payload = e7b913c2f0630562eb1c16b3b1ed84090c011a15c09e5471
+CT = 8491b07205036d25b118214fc6eff37230018f5834b263dc2e31657ecc51f5ec8590482fc053230d
+
+Count = 8
+Adata = 00
+Payload = 6b909697074900d41ce8c7d559b229af11fb3cec334784d4
+CT = 08b83527f229689346ecf0292eb05ed42dfba9a1c76bb379d500827f2081b00397102f90fc9ccd88
+
+Count = 9
+Adata = 00
+Payload = 495ff03335bcb39a317b9ea3f8bb6306fa771f3c55adebce
+CT = 2a775383c0dcdbdd6b7fa95f8fb9147dc6778a71a181dc63e2e7997803029476598c0e8d4fc63857
+
+[Alen = 1]
+
+Key = 08b0da255d2083808a1b4d367090bacc
+Nonce = 777828b13679a9e2ca89568233
+
+Count = 10
+Adata = dd
+Payload = 1b156d7e2bf7c9a25ad91cff7b0b02161cb78ff9162286b0
+CT = e8b80af4960d5417c15726406e345c5c46831192b03432eed16b6282283e16602331bcca9d51ce76
+
+Count = 11
+Adata = c5
+Payload = 032fee9dbffccc751e6a1ee6d07bb218b3a7ec6bf5740ead
+CT = f0828917020651c085e42459c544ec52e99372005362baf308ebeed45f67ef8733737c9c6f82daad
+
+Count = 12
+Adata = 68
+Payload = 9c4cd65b92070bc382fd18146611defb4204acddfdf6b276
+CT = 6fe1b1d12ffd9676197322ab732e80b1183032b65be00628f9b477e3a23bfdfdb619c7bc531fbcce
+
+Count = 13
+Adata = be
+Payload = 2ff93ef2fc5fe2c297ace05f3f7585aed75ef90ade3acf89
+CT = dc54597841a57f770c22dae02a4adbe48d6a6761782c7bd7aa82130f5a86c0cd0433585e5c208cf7
+
+Count = 14
+Adata = 7a
+Payload = 62766e9acd41285eeed9b4007340dbb611699624274ad117
+CT = 91db091070bbb5eb75578ebf667f85fc4b5d084f815c65499d60012a2f25463e036ceecea57b3c97
+
+Count = 15
+Adata = 13
+Payload = ea689c268a04912d0527b16d9d9406df38302fb11cb64a99
+CT = 19c5fbac37fe0c989ea98bd288ab58956204b1dabaa0fec7e337897c90eb260729a729aed1c8a244
+
+Count = 16
+Adata = e5
+Payload = f31e35953beb211efcce487ba8c0cd1a8446343d5851b9fd
+CT = 00b3521f8611bcab674072c4bdff9350de72aa56fe470da373dc2911c75b37cd995481d42b04524a
+
+Count = 17
+Adata = e3
+Payload = c4ac3c645387584c2a95b1f16b8317730592924dd831a388
+CT = 37015beeee7dc5f9b11b8b4e7ebc49395fa60c267e2717d684f76ecf3dc5f3307ce982f185321248
+
+Count = 18
+Adata = d5
+Payload = 81af394c2ea3a85e1ea954596e3772f01635d007794c0b19
+CT = 72025ec6935935eb85276ee67b082cba4c014e6cdf5abf472c38d0fe4e4eba054c1420c39a3dcc61
+
+Count = 19
+Adata = ed
+Payload = e013a2edd5b86bab8df5c9940d0a0c864478c1ad42668304
+CT = 13bec5676842f61e167bf32b183552cc1e4c5fc6e470375a7cfa6c9945f5aee3c799eee37b0605db
+
+[Alen = 2]
+
+Key = 1538cc03b60880bf3e7d388e29f27739
+Nonce = 9e734de325026b5d7128193973
+
+Count = 20
+Adata = c93c
+Payload = e7b819a853ffe79baaa72097ff0d04f02640ae62bcfd3da5
+CT = 1d8f42f9730424fa27240bd6277f4882604f440324b11b003ca01d874439b4e1f79a26d8c6dc433a
+
+Count = 21
+Adata = 4cf9
+Payload = dc6cf325ed6d968efba9f57e48a58f4578cc3540fe121ba2
+CT = 265ba874cd9655ef762ade3f90d7c3373ec3df21665e3d07b40653cd23afc7cc7a31fa13ba8f4e49
+
+Count = 22
+Adata = b469
+Payload = 22ab6a0daf953165dda864cceeeb782e275c0b072aedd284
+CT = d89c315c8f6ef204502b4f8d3699345c6153e166b2a1f421c8c10aaf90b1116be216f912c82ca96a
+
+Count = 23
+Adata = cf6b
+Payload = a35f62a431fee63468dc02fdf7bef78d3a5937de56151939
+CT = 596839f511052555e55f29bc2fccbbff7c56ddbfce593f9c2f568ef41324189fb3644edcd76dc19c
+
+Count = 24
+Adata = af7c
+Payload = 548840cb0400824af809fb68447500b77e977128200d3b81
+CT = aebf1b9a24fb412b758ad0299c074cc538989b49b8411d242548c244a875d3681d715db3da19962f
+
+Count = 25
+Adata = 61dc
+Payload = 440b6095c77495e73fff54c785b7ceb5eb358731c213ffcd
+CT = be3c3bc4e78f5686b27c7f865dc582c7ad3a6d505a5fd968b599bc8927ad8d43067807f4b858f854
+
+Count = 26
+Adata = b97e
+Payload = 50c59ca54eb64575b82b13c6dac96488af369e9f5f86cdf2
+CT = aaf2c7f46e4d861435a8388702bb28fae93974fec7caeb577454774ee78f76e555cf743df340381e
+
+Count = 27
+Adata = 57ab
+Payload = 21b8eb1f0bda26ca36167ce7bc2e796818bf11fc8c192885
+CT = db8fb04e2b21e5abbb9557a6645c351a5eb0fb9d14550e20e0a22a5ee031978271c7dd2a0d4e7018
+
+Count = 28
+Adata = 5f9c
+Payload = b4d84fb1e81e18c89391a7a59fc05fedaf160e0d0d027a7c
+CT = 4eef14e0c8e5dba91e128ce447b2139fe919e46c954e5cd99a242ebae5c6da57ee38e5c227c46b32
+
+Count = 29
+Adata = e0c4
+Payload = 54dc5a0e1b67577cda4e7dbd48b769c120c1d13dd567cfad
+CT = aeeb015f3b9c941d57cd56fc90c525b366ce3b5c4d2be908a5f8a92f4201c4658289307167cee810
+
+[Alen = 3]
+
+Key = f149e41d848f59276cfddd743bafa9a9
+Nonce = 14b756d66fc51134e203d1c6f9
+
+Count = 30
+Adata = f5827e
+Payload = 9759e6f21f5a588010f57e6d6eae178d8b20ab59cda66f42
+CT = f634bf00f1f9f1f93f41049d7f3797b05e805f0b14850f4e78e2a23411147a6187da6818506232ee
+
+Count = 31
+Adata = e9699b
+Payload = 1555bc87d6c688fd221a2c75cd1e4dd1c1693207ac421d24
+CT = 7438e575386521840dae5685dc87cdec14c9c65575617d28f10835db9897b7528e3204fe3a81424f
+
+Count = 32
+Adata = 972896
+Payload = b72b2a080d92f3f3bb7d96222982de82a28c9eebaddba247
+CT = d64673fae3315a8a94c9ecd2381b5ebf772c6ab974f8c24b3efa05ba4a73ec2234461d459f54acd2
+
+Count = 33
+Adata = 3053f3
+Payload = b5417ed6933ffe2b57ea601d77e97eb12fa1fb8fdc06c86f
+CT = d42c27247d9c5752785e1aed6670fe8cfa010fdd0525a863b557537c6525e827750917a1ed49602f
+
+Count = 34
+Adata = 24db75
+Payload = 4e7f42666035a00e62783283c54b027603917685d27326bc
+CT = 2f121b948e9609774dcc4873d4d2824bd63182d70b5046b0dfd06b037e9094f120eb3d8649d48918
+
+Count = 35
+Adata = ff27a4
+Payload = 7bf180699c294421ad9565cacc27227a4b3a7cf9637290c6
+CT = 1a9cd99b728aed5882211f3addbea2479e9a88abba51f0cabfa8cfabbd79b3e3210482e6f3822fee
+
+Count = 36
+Adata = 77ec24
+Payload = 3d47071c13f994cb42fb2887e5c6e53a542be7ddad9779e0
+CT = 5c2a5eeefd5a3db26d4f5277f45f6507818b138f74b419ec3b9575e347051e98d0c8646ad46318e6
+
+Count = 37
+Adata = 6d7748
+Payload = 317d5da0a2ec12c3b96c83dd61cc955242a9c1c640e2b92f
+CT = 501004524c4fbbba96d8f92d7055156f9709359499c1d92378e7af65eb0388ae7a52f58f6ba32109
+
+Count = 38
+Adata = 029674
+Payload = c9bb21306ee1b4a6c4fa5443af2e181716993cbb374e177c
+CT = a8d678c280421ddfeb4e2eb3beb7982ac339c8e9ee6d77708019fa97ff70d4d21c0bd83caa434b3a
+
+Count = 39
+Adata = 60dfe8
+Payload = 44eb7edd6bee501ad97873aa7ecbf7ed8b613760d7c95e15
+CT = 2586272f854df963f6cc095a6f5277d05ec1c3320eea3e191814ed48a21d97ea02e86d7e6e8834cb
+
+[Alen = 4]
+
+Key = 9a57a22c7f26feff8ca6cceff214e4c2
+Nonce = 88f30fd2b04fb8ddbce8fc26e6
+
+Count = 40
+Adata = a95bdff6
+Payload = 035c516776c706a7dd5f181fa6aa891b04dd423042ea0667
+CT = b92f7ec2ebecebdbd2977b3874e61bf496a382153b2529fc9b6443a35f329b2068916fb6ab8227eb
+
+Count = 41
+Adata = d2672cbb
+Payload = 3ba306bcec94615c347f990b62841a16df7b321f113f1714
+CT = 81d0291971bf8c203bb7fa2cb0c888f94d05f23a68f0388f19e2aa492ce9ddfb6de0ab7a447f5351
+
+Count = 42
+Adata = 737f4d00
+Payload = 68313a29ace3efe521c3ca1e5bac8e98d6b4434c80a7dc74
+CT = d242158c31c802992e0ba93989e01c7744ca8369f968f3ef2bf683b1209f104e82ba39f7c62cd666
+
+Count = 43
+Adata = 3610b1ae
+Payload = 963bfe556138317bebe3936b18a2c1dd100dc73be6fde556
+CT = 2c48d1f0fc13dc07e42bf04ccaee53328273071e9f32cacd4fc7d5cac043f182edbe5c2658f73092
+
+Count = 44
+Adata = f1aa7f72
+Payload = 52d5c53ee4f23cb050a95db54112b44033c34ac31de96be8
+CT = e8a6ea9b79d9d1cc5f613e92935e26afa1bd8ae664264473b8234f3fbaca3dc2c497418219151b05
+
+Count = 45
+Adata = 6b1013aa
+Payload = a302aebc0f8fd61badc8371991beacf5933de46effacb8ce
+CT = 1971811992a43b67a200543e43f23e1a0143244b866397558fa5f9539e0500f139016e4a4337d86b
+
+Count = 46
+Adata = 33028129
+Payload = f7d653c23254875625b20e1ef60ae92847046d84bb4ce857
+CT = 4da57c67af7f6a2a2a7a6d3924467bc7d57aada1c283c7ccfa2379fde155e64b5b84e336056445c3
+
+Count = 47
+Adata = 2cab4a09
+Payload = 872a3f7230e626abff519e5aeecc93897249405daeaffc98
+CT = 3d5910d7adcdcbd7f099fd7d3c800166e0378078d760d30358208335cb81e4fb10923fca4ddb9ff9
+
+Count = 48
+Adata = 73142ba7
+Payload = 766f94e7d9b1ce74bbaf2c99d215350f060122767fc1953f
+CT = cc1cbb42449a2308b4674fbe0059a7e0947fe253060ebaa42d6ecfb49ac8983415503efef1e21950
+
+Count = 49
+Adata = bc9f967e
+Payload = 5f089ed9267363bc23c6c7b8f73208a36f61fa8ea8084ff7
+CT = e57bb17cbb588ec02c0ea49f257e9a4cfd1f3aabd1c7606c1978a62d15430fc20b87940292b49641
+
+[Alen = 5]
+
+Key = 54caf96ef6d448734700aadab50faf7a
+Nonce = a3803e752ae849c910d8da36af
+
+Count = 50
+Adata = 5f476348dd
+Payload = c69f7c5a50f3e72123371bbfd6bdf532b99ef78500508dfe
+CT = 20c43ad83610880249f1632dd418ec9a5ed333b50e996d1a4e5a32fbe7961b832b722bc07a18595b
+
+Count = 51
+Adata = 07db8aada5
+Payload = 9cf8b638f2b295b85cf782fabab11153dc091b4afcd761a9
+CT = 7aa3f0ba9451fa9b3631fa68b81408fb3b44df7af21e814d401a2222443696021b5faa520129b563
+
+Count = 52
+Adata = 31ef6561ff
+Payload = 62b8263dc015ef873cd16272e4da89799b910f2b04204420
+CT = 84e360bfa6f680a456171ae0e67f90d17cdccb1b0ae9a4c4f842681d2e90da5718234ed893197662
+
+Count = 53
+Adata = e97dfcbafb
+Payload = 810bed3a2bc0f9d75389155b7a39d9d014c08646814f9718
+CT = 6750abb84d2396f4394f6dc9789cc078f38d42768f8677fc33a08eb30ee154f71279682ab02eff27
+
+Count = 54
+Adata = 4981c51fcc
+Payload = 063d23fc3ec344c1ba3486802e01e55617455d5cfbfb5279
+CT = e066657e58202be2d0f2fe122ca4fcfef008996cf532b29d8d3071c79f0cf86fe4148cb5e8ace0ce
+
+Count = 55
+Adata = c8437dba76
+Payload = 41db5b245ea0fab985b93e7fc0a00cd3cca5bdbb642b7ebf
+CT = a7801da63843959aef7f46edc205157b2be8798b6ae29e5b842700619dc1599603f3f3f6cfdf5e0b
+
+Count = 56
+Adata = 6f65a24344
+Payload = b0e36734b2ba871d59df0b029c7f32af68e003a689ac4911
+CT = 56b821b6d459e83e331973909eda2b078fadc7968765a9f539a0cd8d8bbf211b907f34411f868c79
+
+Count = 57
+Adata = cd62d6d203
+Payload = 747e53e627eabde0cd77d78d1bd720bea518f8a2f76e57a2
+CT = 922515644109d2c3a7b1af1f1972391642553c92f9a7b746c4a90e5fc11266bab77eea1d24fbdbb9
+
+Count = 58
+Adata = 9663b3c8e6
+Payload = c70c92ec4c518802662fa4c41a6a33a22599f79f8f7264b3
+CT = 2157d46e2ab2e7210ce9dc5618cf2a0ac2d433af81bb8457b3c1246f7dd6462ce757db82db45f36e
+
+Count = 59
+Adata = 35c4720d3c
+Payload = a26835605b66fc08abdbb5dc77e39783d60b8e8f2314e95f
+CT = 443373e23d85932bc11dcd4e75468e2b31464abf2ddd09bbd472c06a5f4c04f97d06ec401d3e7fd9
+
+[Alen = 6]
+
+Key = cc0c084d7de011e2f031616a302e7a31
+Nonce = f0b4522847f6f8336fe534a4e7
+
+Count = 60
+Adata = da853a27aee2
+Payload = 15b369889699b6de1fa3ee73e5fe19814e46f129074c965b
+CT = f39755d160a64611368a8eccf6fcbc45ef7f1f56240eb19a2e3ca4ec3c776ab58843f617d605fd72
+
+Count = 61
+Adata = d4ed4584678e
+Payload = a18c0460b56a5bcd5bf6842cec6ed44d90b2bfa968a6a7e7
+CT = 47a838394355ab0272dfe493ff6c7189318b51d64be48026327804c44c8f17a4446a3d5ba85f9c7f
+
+Count = 62
+Adata = 590a27721a36
+Payload = 41cee0ecaf9c65cef740440af37954ef49a585779d2abbca
+CT = a7eadcb559a39501de6924b5e07bf12be89c6b08be689c0bbcd00e9cb726d75e4283820ee81d933a
+
+Count = 63
+Adata = 58830fb0b1f3
+Payload = dce983e4e3734a9bd8848dba0d744d07bbeba602f4006025
+CT = 3acdbfbd154cba54f1aded051e76e8c31ad2487dd74247e4d5d71a1f0f1b6518c35f0632a30931fd
+
+Count = 64
+Adata = eedd0d767a25
+Payload = 4653b3e879ab18b65c5c3706a5139698262cb830a22d943b
+CT = a0778fb18f94e879757557b9b611335c8715564f816fb3fa3ad112899e9ba442660eb5dfe33b2f96
+
+Count = 65
+Adata = 618bcf2e3e79
+Payload = 8586383281925363ac15fb19c26d64c639c75920c792dc2c
+CT = 63a2046b77ada3ac853c9ba6d16fc10298feb75fe4d0fbed54fba446028919342b2fe86ee67efcc7
+
+Count = 66
+Adata = 549c9b84c7f7
+Payload = 95c25ae4445cd8c4d267df82687484667e309992fcf1e737
+CT = 73e666bdb263280bfb4ebf3d7b7621a2df0977eddfb3c0f69fc23013142f62881ccfa3037067e1ef
+
+Count = 67
+Adata = 92d7fa6a8135
+Payload = e58034bbb0e6f5e724e32ee56896dadae25c2a3efb8c6f2f
+CT = 03a408e246d905280dca4e5a7b947f1e4365c441d8ce48ee8263568d56fae8bf35b2f2cdecbffe0a
+
+Count = 68
+Adata = f43e126c0f83
+Payload = d98f0dddfe9cb3cae1336970d5efb55316a65e2c51e316f4
+CT = 3fab318408a34305c81a09cfc6ed1097b79fb05372a13135de2c2fbfdddc7dd6672714af174c5121
+
+Count = 69
+Adata = f02074812dde
+Payload = 548747b1669c6383b793054d93957f9e99d605761c6c23b5
+CT = b2a37be890a3934c9eba65f28097da5a38efeb093f2e04743704560ff23ce0000fba8812c45940ad
+
+[Alen = 7]
+
+Key = d7572ed0e37261efa02f8c83e695efdc
+Nonce = f4f96d7b4384a3930b3d830f82
+
+Count = 70
+Adata = 922340ec94861f
+Payload = 1edef80c57d17f969f8bde10ab38a1a8811a124de72c526e
+CT = de14558cc686e1836f1f121ea1b941a9ebd4f0fb916dc870fd541b988a801cb5751c7faaf5b0c164
+
+Count = 71
+Adata = 4eb379f21b1531
+Payload = ddd5282a207c1dcb03c1c3bbc9eb12a7bd28534118db2735
+CT = 1d1f85aab12b83def3550fb5c36af2a6d7e6b1f76e9abd2bc068bd1b1c309dfbd52d9a24be07c630
+
+Count = 72
+Adata = 7fa89e9d6e3fec
+Payload = c5b7c462eb166f48bb59c8102ee7b3dc67a28e5de7570c51
+CT = 057d69e27a41f15d4bcd041e246653dd0d6c6ceb9116964f2d114d6ab082738d05d60acca8e8ccfb
+
+Count = 73
+Adata = fda8665f87c618
+Payload = af793815e147e3180f5146aa6a582e343dc479f26b4226b2
+CT = 6fb3959570107d0dffc58aa460d9ce35570a9b441d03bcac1cc84bd77fe00e1a13433f2c10e3b799
+
+Count = 74
+Adata = 46bde207491ebd
+Payload = 47c76a0bbd5b1616b278089d41a050c509c7a1c280574bf7
+CT = 870dc78b2c0c880342ecc4934b21b0c463094374f616d1e9990c81f1bae32c953bf02ddbde047632
+
+Count = 75
+Adata = a799f5f895fd7a
+Payload = d554806ffc3900a0952a3c094c745808950697a6e5d62c1d
+CT = 159e2def6d6e9eb565bef00746f5b809ffc875109397b6031af19f1f080dd1dd2da799059755e49f
+
+Count = 76
+Adata = 20225831a9ee06
+Payload = ba45e1859efae362a44a0116a14e488ba369da6c76c3913b
+CT = 7a8f4c050fad7d7754decd18abcfa88ac9a738da00820b2523d3b9a0060834ac4860dae0eac570ef
+
+Count = 77
+Adata = 785360916464eb
+Payload = 57bc338946ff78cf76adf5021e2e44e34e687fb68ad703f3
+CT = 97769e09d7a8e6da8639390c14afa4e224a69d00fc9699edff96e7cf841a66c50bbb6fb2bac7ef51
+
+Count = 78
+Adata = 57b946369226db
+Payload = 9ac5be9929c4fe5a9992749a38dc69874866db3d4747da97
+CT = 5a0f1319b893604f6906b894325d898622a8398b3106408986e1c33a45f9d52755c374650635bef6
+
+Count = 79
+Adata = 73e4da8973c1e3
+Payload = 5a05410aa3a71f5f1a253b8576eba269c06a4c30591144cc
+CT = 9acfec8a32f0814aeab1f78b7c6a4268aaa4ae862f50ded2d78592c2d89c15edc5bb7486aa93f896
+
+[Alen = 8]
+
+Key = 98a42d7a0c5917deaf3b4de3f0cbe0a1
+Nonce = 03d33ab0c2df7bfce88b5ee4c4
+
+Count = 80
+Adata = 2d5438b728b950d9
+Payload = 9aa9c8358117564371366beeec923051ef433252197aaad5
+CT = 9ff942baa60f440c17a78e9581216b9a947a67f04d54911feecfff971fdfaa856310b014aa59c978
+
+Count = 81
+Adata = 6e430b497a16e7f5
+Payload = 5758a500978c71a9b90f6e5beae9d96ef05a41486b10ea2e
+CT = 52082f8fb09463e6df9e8b20875a82a58b6314ea3f3ed1e46a4d7b4b4df6c831ee32116ee4dad98c
+
+Count = 82
+Adata = e12f98507d6514c3
+Payload = 49efe18c76a8355127d914a3a830c1c6ff2a163d728526e1
+CT = 4cbf6b0351b0271e4148f1d8c5839a0d8413439f26ab1d2b3243fc75cd1624e152f451678edcac87
+
+Count = 83
+Adata = eecf8d641ee0bee9
+Payload = 49ae2309fbe6ce4e9421516b8f79ae64b1316cb849eaf638
+CT = 4cfea986dcfedc01f2b0b410e2caf5afca08391a1dc4cdf2dd6d8ca57da1880e1baff43736b3da34
+
+Count = 84
+Adata = 9066367c784de0a4
+Payload = b1bda5fa4242aa6aad0f5a5b1d31d86b8d4a97588b3e315d
+CT = b4ed2f75655ab825cb9ebf20708283a0f673c2fadf100a97f05439a661001513a96b896de46b7081
+
+Count = 85
+Adata = edf848b2510f7803
+Payload = eaa8608f6763d968576a7e89056b9828a1686c8441b06377
+CT = eff8ea00407bcb2731fb9bf268d8c3e3da513926159e58bdcf20709b2dc2ff9946094190b5ea09d1
+
+Count = 86
+Adata = 0f49cae81c8628d2
+Payload = f32029cf51609f0df9832ad1b283ea94a5356f70112c1328
+CT = f670a34076788d429f12cfaadf30b15fde0c3ad2450228e2a5bb6b4f87b9b198665203e4fdf9e7f7
+
+Count = 87
+Adata = b0c47e9cce46a276
+Payload = 7a550ef9254a8da6e4fee290a76ea838ffb61d3533d4d31f
+CT = 7f05847602529fe9826f07ebcaddf3f3848f489767fae8d529f416f89f1a34bbbf2ce40d943c6d8b
+
+Count = 88
+Adata = a6fe7c9ce2d49f85
+Payload = e67c486dd7ba9a9061844b9354f55890321ae626efaa28cc
+CT = e32cc2e2f0a288df0715aee83946035b4923b384bb8413067eb95550b91b955d5c2d72d5c189b704
+
+Count = 89
+Adata = eb1d11cc4876f58f
+Payload = 35f2c810091e930a52e4a3f28c9c8184967f1554c2675eb5
+CT = 30a2429f2e06814534754689e12fda4fed4640f69649657f0e8e8a5a7e0ea6860bab4a4320f03ae5
+
+[Alen = 9]
+
+Key = 2a68e3fe746f593c1b97cb637079c3e5
+Nonce = cd62d0f27b7f4864dc7c343acd
+
+Count = 90
+Adata = abe4f1d3812bfe3ccf
+Payload = 13b4a874888db0e5d8fd814b5e7e04f7fdfbc1601ccc02bc
+CT = 032835a3dbf688d09cf2a32a92b101959d33ff47500f92f4fd49840440f866d1a22b0854996111d8
+
+Count = 91
+Adata = 2e21f466814d3d6340
+Payload = 08b5c773364cded74d7b308984313c17ff90eed496a27a2b
+CT = 18295aa46537e6e2097412e848fe39759f58d0f3da61ea63de2f5c335df537fbbc6ae59cd562732f
+
+Count = 92
+Adata = dba22aabcea0e694fc
+Payload = bbac1790abb7aafe272ec472c897e6363e335b3c4126c762
+CT = ab308a47f8cc92cb6321e6130458e3545efb651b0de5572acc5ed6e4a907ff4742ab6c835a427f92
+
+Count = 93
+Adata = 97e9d16bd757395ec1
+Payload = 7249612dc09809bbca9dd311e720f7da2cb54ce33e3eb9c3
+CT = 62d5fcfa93e3318e8e92f1702beff2b84c7d72c472fd298b1714b5a3df454f3bc35869da75adc882
+
+Count = 94
+Adata = 866cf710470cac74d3
+Payload = 060ae0ab9857324a3b2ac79f3b6e6f90f5de884ce9c7b930
+CT = 16967d7ccb2c0a7f7f25e5fef7a16af29516b66ba5042978aa33dffe2596832f98a9c8413bd898b9
+
+Count = 95
+Adata = 2dd7a7f832b29ccce2
+Payload = f77a9fd5363836deefd34e1bea0882484a7ab746b4495d59
+CT = e7e6020265430eebabdc6c7a26c7872a2ab28961f88acd11dd5049f7c53d6a7fe5d7f959689ee960
+
+Count = 96
+Adata = 502349a60e897356b5
+Payload = 96118dbfe53434d8aed88769a535eb0c8b5849dca1c81c34
+CT = 868d1068b64f0cedead7a50869faee6eeb9077fbed0b8c7ced9c3a0d0de8788471c5f6c2f9638b7c
+
+Count = 97
+Adata = debed45c9acf129268
+Payload = df5a47d3eb5c0b6cabb6711a45400602d205b82ecae9e849
+CT = cfc6da04b8273359efb9537b898f0360b2cd8609862a7801d49b4b9bead1b7de2021cff280d6f93b
+
+Count = 98
+Adata = 2726702dd62a6e5344
+Payload = 5a7649cb001fbb6f653cbca17756c5c1a078c2e240d92085
+CT = 4aead41c5364835a21339ec0bb99c0a3c0b0fcc50c1ab0cd69df31aba209d87ee22bd6a1dcadb168
+
+Count = 99
+Adata = e8006cfb0536696ac7
+Payload = 95186d41f927cdbef42157f21d966e88061b6558b5ec932f
+CT = 8584f096aa5cf58bb02e7593d1596bea66d35b7ff92f03677cc5b60c881fe834a789d28447d8fb54
+
+[Alen = 10]
+
+Key = 46b067cf9b1a28cf187002e90b14e130
+Nonce = bad8c03292bf01cfd8d34f860c
+
+Count = 100
+Adata = 8d65880eddb9fd96d276
+Payload = cc0915194218d4536e467433cd6d79ff1d9eb9ff160ab684
+CT = bd56edc015692c6ab9bec493a9893863598414a3d11a6a0f27ecdcb257d0d30491e5bf1aa8f90958
+
+Count = 101
+Adata = 8a65cde13149d9d54a5b
+Payload = 28257133b1d8b0b2be4faecd6e819ac783707a5c5f50c302
+CT = 597a89eae6a9488b69b71e6d0a65db5bc76ad70098401f89b10f9fc201e4128696dcd899dd2e24ea
+
+Count = 102
+Adata = e999ec3e1bfb25b5877c
+Payload = 96ab0cfc204bafc4f5851d6c682d631d0c5ad03ac925a943
+CT = e7f4f425773a57fd227dadcc0cc9228148407d660e3575c8c522e5ba5adbc6a639cbd06f103ebc9e
+
+Count = 103
+Adata = a8554441e073d6065dce
+Payload = 50925853a84a33ff392154e4e737efc18dcfc98f4d5235a9
+CT = 21cda08aff3bcbc6eed9e44483d3ae5dc9d564d38a42e922e1a4e0f7ebc3cff3915d27971cce7e91
+
+Count = 104
+Adata = 838f0be8d04d28d77549
+Payload = d0700658d5f4010ff21091f3d119c99645e339198029c3a9
+CT = a12ffe818285f93625e82153b5fd880a01f9944547391f22c215c88d80bffc881aff10ba40f11976
+
+Count = 105
+Adata = 20f014d928d5b25fbaf4
+Payload = 4bdf28748a0c281dd49c7294ae8e55fe7a52d45ff6384db3
+CT = 3a80d0addd7dd0240364c234ca6a14623e487903312891382cc9391bc06aa6ca9d486a4e2a218c54
+
+Count = 106
+Adata = 56c026b8a71974ff7ecd
+Payload = f75db057f0276fff85014f54ecdec8f90b96a2a982db14cb
+CT = 8602488ea75697c652f9fff4883a89654f8c0ff545cbc840778b05c6c582a0bb7d1d9dcf6a46b9f6
+
+Count = 107
+Adata = 75c3b9e52648a4f9aca9
+Payload = c15c554169dbb9b08494afaa44819a10dc9ddad54199ab54
+CT = b003ad983eaa4189536c1f0a2065db8c98877789868977dff47d9ebbd3cff14623b10cecc94b53d6
+
+Count = 108
+Adata = 1c76c3014a14b7fa1ca8
+Payload = 19eef6f798fc68086aad1cda6d7976cdcfe6b8af74598032
+CT = 68b10e2ecf8d9031bd55ac7a099d37518bfc15f3b3495cb9d2b74b84dc170c00dce85b56e346a976
+
+Count = 109
+Adata = a4eb60d4eb7ead1bd0e6
+Payload = e06e5dba5ac35cfd07949e5cc12ad70507d4a86a952ecca3
+CT = 9131a5630db2a4c4d06c2efca5ce969943ce0536523e1028d92e19fd8b5c1fcbff36adaa5e47ae84
+
+[Alen = 11]
+
+Key = e94dac9c90984790a7c0c867536615ff
+Nonce = c19f06f91e645d4199365f18c0
+
+Count = 110
+Adata = 537038b5357e358a930bd6
+Payload = 4d64461c55eb16bf7b9120f22be349598f2f394da8460dc6
+CT = e9fc5004c2359724e1e4411ae6f834ef6bea046d549753c88790c1648f461a31c84e62ea8592a074
+
+Count = 111
+Adata = 7e3d7b3eada988668f3784
+Payload = eab7d5dbd91d4cbbac8d79fadd70b5dcb3baadac5cb713a3
+CT = 4e2fc3c34ec3cd2036f81812106bc86a577f908ca0664dadacb1d1c9231d2c22ecfeed622792dfd0
+
+Count = 112
+Adata = 78b107b29c4878ff18f749
+Payload = 3c6ae2e2578875a1f5611582528e058aece2ddc33a4dde3d
+CT = 98f2f4fac056f43a6f14746a9f95783c0827e0e3c69c8033fffe60299768f048e7098033cde046b0
+
+Count = 113
+Adata = d293908bb516c5f3a411b9
+Payload = d7a46e726ed43f1580eb52141a93390982cc809dc833e3f0
+CT = 733c786af90abe8e1a9e33fcd78844bf6609bdbd34e2bdfe4ee6ebc0d90a0de05b428495c93e1801
+
+Count = 114
+Adata = 33ef208faad4d2948c9e67
+Payload = b1fe5d9d34157193fc0608cd8ecb872e17720f5f6814a466
+CT = 15664b85a3cbf0086673692543d0fa98f3b7327f94c5fa687e7e64cc0fcd6a92c79ceb6ce2abd8ee
+
+Count = 115
+Adata = b7f7ed9ccac3c2b4fbfee0
+Payload = de6bb539fb7a9c87414f62a7cf25a4cfca176509e991af41
+CT = 7af3a3216ca41d1cdb3a034f023ed9792ed258291540f14fb02b53bc779e0976b634b0d1b88fc0a9
+
+Count = 116
+Adata = a6e287383927f76e4927af
+Payload = 8719d20c20c8959068b8adcd65e6f6bc7b3693828f0735a0
+CT = 2381c414b716140bf2cdcc25a8fd8b0a9ff3aea273d66bae3c37fa936243b393f07fcccb0fc13e41
+
+Count = 117
+Adata = 70828be6dd93954f4e7b6b
+Payload = 30b39426831f61c8ba5f2ef5b71f0c4b2f916e3b5a578110
+CT = 942b823e14c1e053202a4f1d7a0471fdcb54531ba686df1e0d7534a489e6d242966ebea4455f8f79
+
+Count = 118
+Adata = 506015fc2831df293f4da0
+Payload = 818d5d810f678629f078723f5c6c3657271077533bfb7c29
+CT = 25154b9998b907b26a0d13d791774be1c3d54a73c72a2227ccbf64f04e95b180d09e843847d22104
+
+Count = 119
+Adata = e9394b0245b379e68e3dea
+Payload = f0613205a7a0822849df9e8a3cf6caf281f3adfa966c5507
+CT = 54f9241d307e03b3d3aaff62f1edb744653690da6abd0b0927b546ef8cd717073832584fb25a0645
+
+[Alen = 12]
+
+Key = f6bb5d59b0fa9de0828b115303bf94aa
+Nonce = 05358f33e1fc6a53ab5a5c98ce
+
+Count = 120
+Adata = 040b25771239cc2a39446e3c
+Payload = 011fc50329bfd63a85ebd4f7693363602f1a4147371270b7
+CT = 4432d7eb42980734d34f19c50cf8abf71ac1b19ed75a727854e5d050a405f755047d09cb0f49546a
+
+Count = 121
+Adata = 50a1d37fa2f3462bd304631b
+Payload = c90e40540d372ab1eb00ea5d5b8de5bf7c94ce4e376d6949
+CT = 8c2352bc6610fbbfbda4276f3e462d28494f3e97d7256b862abee8547ee3f24cfa677468ecc1d121
+
+Count = 122
+Adata = ac3bb872a41df35e415d2b0c
+Payload = 9e7be78c0ab9e6a4c6c257e77c63681bea35d951f168b0c5
+CT = db56f564619e37aa90669ad519a8a08cdfee29881120b20a61cef865ce4080e7c7abfc43f62c03a3
+
+Count = 123
+Adata = e3106ae6456153dd922640a1
+Payload = 00df0c5a5d3eceb2bd293066529799544f846672a9a1d31b
+CT = 45f21eb236191fbceb8dfd54375c51c37a5f96ab49e9d1d4e1d19c321a1e0852adba939b447220ab
+
+Count = 124
+Adata = 297b4498bf5427e6341aa927
+Payload = 14967a0476dbaea03b07fa8d40d344eabaf479be2443243a
+CT = 51bb68ec1dfc7fae6da337bf25188c7d8f2f8967c40b26f579ea5fb65018abdcde1a39f6859ecb56
+
+Count = 125
+Adata = 5de60dc0e3b5bda0b33a9520
+Payload = 2da3716d76d10b6766a1f9cbf9f420316fd5f396e7b9a2ba
+CT = 688e63851df6da69300534f99c3fe8a65a0e034f07f1a075c2629ff871ee15745fd8c1ddbdae4c29
+
+Count = 126
+Adata = 1c9b8541943ad50b4243c179
+Payload = 8c1b3ba18d1f5cff74a457aadd6b3e7d093d06ad2622e6a0
+CT = c9362949e6388df122009a98b8a0f6ea3ce6f674c66ae46f04e198ad16ad1106d3ba6172f4a13a8f
+
+Count = 127
+Adata = 51e926d2542ac8faef61465a
+Payload = 88936e97db070c0ec2aa58d1c6f5b34df3d32ddf7db34a8b
+CT = cdbe7c7fb020dd00940e95e3a33e7bdac608dd069dfb484475981131e3934ec6d41e00d502729799
+
+Count = 128
+Adata = ebefbac97b363e6f32526aac
+Payload = c20742e4b410c5b661da373a905fb0ed55b20e0e879eff5c
+CT = 872a500cdf3714b8377efa08f594787a6069fed767d6fd93e2c005b5bebe07ff578b1b4bc51971cd
+
+Count = 129
+Adata = 1ef059ac7d648e9e32d9b1f2
+Payload = 65c55ca21a89a8325365bf2be861d700559de2eabb41b37f
+CT = 20e84e4a71ae793c05c172198daa1f97604612335b09b1b021a25f15b5b4229a872a9199972c85b3
+
+[Alen = 13]
+
+Key = d1da2e961e78063af8de41865b226873
+Nonce = 03739f5474857006340cce554d
+
+Count = 130
+Adata = e3afd091d2b588465872a6300f
+Payload = 8e5fa1a6662a8378cda15697e926841594f2f394fa5a34ab
+CT = ca0d95e3ff186ad6b88d45fc4079e6b7b4a615e7e8dd5f4742d522cc9dc19c47a4fa0b1528069cf8
+
+Count = 131
+Adata = ce3186bb737753b59ee76b748c
+Payload = 311ebc5ff2f625944562ea699b2690df3e6e64a17c62bd3a
+CT = 754c881a6bc4cc3a304ef9023279f27d1e3a82d26ee5d6d659b26510b8f25610799e011d7c850ecd
+
+Count = 132
+Adata = bfd636989dfbcb0edc9f014cc8
+Payload = c96cee5ba7b799f16254a17b1870cdb85fe0ef3f42110c13
+CT = 8d3eda1e3e85705f1778b210b12faf1a7fb4094c509667ff52942aa0d39649f3d9ed535bebc2b603
+
+Count = 133
+Adata = 4812b092aa59d57451bfd812c3
+Payload = 13b1b4404dc5735655139414fcbd02c5327ae9fb148bd324
+CT = 57e38005d4f79af8203f877f55e26067122e0f88060cb8c8c1e61efb9c1d84ddac2d24f43531f569
+
+Count = 134
+Adata = f6ef9ac4f4c9ce1e4309c64fa8
+Payload = 6c5b59319e2710f5d63407f85b424d1860425ef8ce0cfe53
+CT = 28096d740715f95ba3181493f21d2fba4016b88bdc8b95bf13350de0ef34df12fb945b0ae0a0d9bd
+
+Count = 135
+Adata = 9bf12168bb3d79ebd25262f2b4
+Payload = 968e1d78008da78611e82985c4028e86770858cfe61c3723
+CT = d2dc293d99bf4e2864c43aee6d5dec24575cbebcf49b5ccfa0734563638598d8c4bf1fcd94009925
+
+Count = 136
+Adata = 7d870d7e52d3053c65eefad477
+Payload = 6a1306d911434cc7400d2f9a95e36aedceddca2b3d583f51
+CT = 2e41329c8871a56935213cf13cbc084fee892c582fdf54bda1f5fc53b08aca82bccfba6fbcb27e69
+
+Count = 137
+Adata = e95099f04371e445e5eaa1d80e
+Payload = b9197eb50c8168d16b8a12bd261d553ffcc521d979b26fee
+CT = fd4b4af095b3817f1ea601d68f42379ddc91c7aa6b3504027d1a922953facbd630d7fea6b63594ec
+
+Count = 138
+Adata = 3e80eb03db6545204ef4241ad6
+Payload = 95f59e36eac8eb3b51709d635b07fa2da0976ea20e25807f
+CT = d1a7aa7373fa0295245c8e08f258988f80c388d11ca2eb9383fa000d10078256b71249d9d1f1846c
+
+Count = 139
+Adata = 9748798c0f3cc766795c8ce0e4
+Payload = a48db9add9ecdeb49e51d3ab7bb2075202ed2aa50c0195b1
+CT = e0df8de840de371aeb7dc0c0d2ed65f022b9ccd61e86fe5d2773c2f55b752477c489facee812c614
+
+[Alen = 14]
+
+Key = 1eee667267ef10b03624cf9c341e3f75
+Nonce = 0630a3eae27e505c61c56e6560
+
+Count = 140
+Adata = d24651ef0561282d3e20e834960c
+Payload = 798e31cce0a83702a95171fb1162a17b9ce00ec3592ce262
+CT = f3c3e52f1a1ff528a8d3783ee4e75f114e3e6416334815d2d9236d5c5c9319092078411b72c51ba8
+
+Count = 141
+Adata = c527d309ab29ee91c5fc53117e71
+Payload = d79cd4c8891ec4ce2c51136712d23b32266b2b73768aeb1e
+CT = 5dd1002b73a906e42dd31aa2e757c558f4b541a61cee1caed8ad2a48cb734e3f93e602c15c7c775e
+
+Count = 142
+Adata = a93dfc3944514ddfc5acdd89fab7
+Payload = d7fa81c949f1f2af29dbd56529b307e3b348e996d0936455
+CT = 5db7552ab34630852859dca0dc36f98961968343baf793e5f34b297f3f106a9cdae255f7634fbd0f
+
+Count = 143
+Adata = e502abe21c7b22120693a08ef3e6
+Payload = 6330caaeddf0473d564d175b9408c6f12e6d3cd4ee2c423f
+CT = e97d1e4d2747851757cf1e9e618d389bfcb356018448b58f4f5d9c3dbfe3e2fe03a002e55039ebe6
+
+Count = 144
+Adata = a49b34dfad43333fb2ffd701a2d6
+Payload = 45671482c390e65f75de15ca91b93596e9bf3d6fc9178bcb
+CT = cf2ac06139272475745c1c0f643ccbfc3b6157baa3737c7b6f7bb0749c99d75740f2d193fef36c60
+
+Count = 145
+Adata = 9e4d8aa3dbdc4d4b4b8d72734f52
+Payload = c8f34bea8bdc403a48d8ed9268429141cd03c29558050ef4
+CT = 42be9f09716b8210495ae4579dc76f2b1fdda8403261f944ceec82fc674da9efa6926e8641729ed8
+
+Count = 146
+Adata = 052327ad59cc791259817fd0ed96
+Payload = d8d1c57b16c23894b66023c29f8648ce4a6074647e1f5f69
+CT = 529c1198ec75fabeb7e22a076a03b6a498be1eb1147ba8d92ff19e93f60c8f3a511300fddc38ee59
+
+Count = 147
+Adata = 14bc3c44c001ccb261a2a0526523
+Payload = 71c14a7031033db15bfe23b75fed9daf8886dd11392a0b78
+CT = fb8c9e93cbb4ff9b5a7c2a72aa6863c55a58b7c4534efcc87fa00fb244eda0d77cf6c05c8fd590af
+
+Count = 148
+Adata = 3477384c396a9e9efb3e169722cb
+Payload = afa795f836763a1210bb36fef167864f73ba3b6abc593537
+CT = 25ea411bccc1f83811393f3b04e27825a16451bfd63dc287bae19612657c87d3bb73cfb8cee7c8a8
+
+Count = 149
+Adata = 0c3b9a6924ad506038cb2d6590c9
+Payload = ca4a186f116a179579e3d327aec3f5be358bc7094f853bc3
+CT = 4007cc8cebddd5bf7861dae25b460bd4e755addc25e1cc733d9713d2e916c23ac3039de34c295fc4
+
+[Alen = 15]
+
+Key = dbbd26f5d9e970e4e384b2273961be5a
+Nonce = 0b1eabe504ef4822542e397fec
+
+Count = 150
+Adata = 477937301c83ba02d50760b603e0ea
+Payload = 553714e17a208a2eceb847a4a2d95088388b1ac8d8ca43e0
+CT = 1c80213268bad5402c4dc9b5d836ab7499810d0d8a974716df9a0e986ab2890736423bb3772cec3e
+
+Count = 151
+Adata = c91eb5a07ff19c044023e5cf339203
+Payload = c94d0b9e728413c58202cb3f6b82dba7aa9e3ca0a72c40c7
+CT = 80fa3e4d601e4cab60f7452e116d205b0b942b65f571443139f907a92cb01215e3cda84ae13af48b
+
+Count = 152
+Adata = 38c71a8e9b279c605c7f0418a0afc1
+Payload = b4e8c4fd5ad98a1be8b5a11677c57ca1c1694e3528092aa9
+CT = fd5ff12e4843d5750a402f070d2a875d606359f07a542e5f3dbd8dbf7485106cdf9ea0e7088a5650
+
+Count = 153
+Adata = f2c76ef617fa2bfc8a4d6bcbb15fe8
+Payload = 578ce26cdb5ba2e8798e23588e5cd04ef782820b80e49a42
+CT = 1e3bd7bfc9c1fd869b7bad49f4b32bb2568895ced2b99eb4853fde6f4dca88ff11bbce20ed9e5012
+
+Count = 154
+Adata = 36004342dd74e7966692a848b2c11e
+Payload = 78733c635d4d4e8b0729732f1e174dfcec4e020a7ac3870d
+CT = 31c409b04fd711e5e5dcfd3e64f8b6004d4415cf289e83fbd94e979108fcecbd32f6bdf72f0ccb4d
+
+Count = 155
+Adata = db92bc3fe5d4141aeb39baea6f114c
+Payload = c7aafe7760945e45703c1e19f1032dfd56ddc216c3b03826
+CT = 8e1dcba4720e012b92c990088becd601f7d7d5d391ed3cd0229c8f9d4e39fc16cbdb44236ef125c7
+
+Count = 156
+Adata = 34ec2d5b6f0d950509b47a0637d74c
+Payload = 2345e36a63be0b78df95e60907c78da0e48e61e70685a1f3
+CT = 6af2d6b9712454163d6068187d28765c4584762254d8a5051c9ab7cb0a779c3fa78c9ee12603802b
+
+Count = 157
+Adata = 6ab658d177c2dd87c9b8787cd70182
+Payload = b0725f735543eb0c0ec88ae69b140f5787d28ef4a2e36d57
+CT = f9c56aa047d9b462ec3d04f7e1fbf4ab26d89931f0be69a1648c6307ec5ea304045a7cdc93f36b9d
+
+Count = 158
+Adata = 483f135c61250fa610b4d14b99ecf0
+Payload = 315a947bf5291278d446d332ee5ca0def7655d5c957a8fb4
+CT = 78eda1a8e7b34d1636b35d2394b35b22566f4a99c7278b42364ff3b1ad915347b1c7f062b10d3da4
+
+Count = 159
+Adata = bb022aed60819ef84ae83ce27db9d0
+Payload = f78d00755bcb45e6822121fe7cb03c8e627c9f548ccd7e7c
+CT = be3a35a649511a8860d4afef065fc772c3768891de907a8a7569808dab58d42181543b2e2d05992c
+
+[Alen = 16]
+
+Key = 10a7720f2e18f739c26924925af6b670
+Nonce = 8c4e7813ab9bce9dafee01c628
+
+Count = 160
+Adata = a209941fab710fda38d11c68b13d930f
+Payload = e59782a9aea45f467b90e51a0fdf166baba05663def2d8b6
+CT = e357b1ccdaca6f3506dc45279c2e4c59f5307a5fd6a99cd72341ea8c0785569973f90ee9ee645acc
+
+Count = 161
+Adata = 2e2f6f9755a492ee54df77b2ecab9808
+Payload = 042a072f6ebf11f79fcb4f5a64f7946dc837d9d2355785ea
+CT = 02ea344a1ad12184e287ef67f706ce5f96a7f5ee3d0cc18b703eb81224cdb1fd2e1cfb2fbfe1e402
+
+Count = 162
+Adata = 99e98c9983c85d1f49ae43ebad67a652
+Payload = 5db6bda27910e7b8b61ac476c6532570b71b3932bd6a698c
+CT = 5b768ec70d7ed7cbcb56644b55a27f42e98b150eb5312ded64c4aea7f17f18f068897557c93ffaaa
+
+Count = 163
+Adata = 37a837d73fa15793f6f823fb99c2ea74
+Payload = 8cac261a461c3ddd2642b8e4e5c3389e491fcb2ff8356412
+CT = 8a6c157f32720dae5b0e18d9763262ac178fe713f06e20736f3b2e70e6e2dc7acc74a823a7f49722
+
+Count = 164
+Adata = 11119a4e779cfb64c736d425e4ff554d
+Payload = 3429f9b088b501d7944c462694d0799568282e7ce07d3e61
+CT = 32e9cad5fcdb31a4e900e61b072123a736b80240e8267a000dc3b57096f0df1d4eb5328c416921bc
+
+Count = 165
+Adata = 962d7d4305f23d1692747b504960c0a4
+Payload = a46ae4c71d4c9eb72fabfa76b8074aa02e07653eca10eef5
+CT = a2aad7a26922aec452e75a4b2bf6109270974902c24baa94f62ed804e9f2ac0f7001d0f35ea9f3c1
+
+Count = 166
+Adata = bbb1fdfefcf3657ba6cd93ff341a04e1
+Payload = 92f5e3083f57c77ac9553a2024a66489698bd2261f05d415
+CT = 9435d06d4b39f709b4199a1db7573ebb371bfe1a175e9074907dcd7ac1e0bb248d46c3036c39fb02
+
+Count = 167
+Adata = 74be126f7c596642dafa8fe3da904e69
+Payload = 41ecc3aae5cfebfad7921a47a0684601ffe73816380f8716
+CT = 472cf0cf91a1db89aadeba7a33991c33a177142a3054c37787cbb80fd21127feca7e76fd6947d5b7
+
+Count = 168
+Adata = d72cc521c90a468522af8966c24799f3
+Payload = 8850bdda4bd0271e333db344a47b837183eb48269c3dc0b6
+CT = 8e908ebf3fbe176d4e711379378ad943dd7b641a946684d7cdb5d1243b6e73b8e380d8ca041647db
+
+Count = 169
+Adata = 28f427fba8d0bb0380bbe5072ccfa519
+Payload = fdd3ca2f193f93f5a349b50357d26748b767cde6ab5cbfe7
+CT = fb13f94a6d51a386de05153ec4233d7ae9f7e1daa307fb864a0ae8604b103f882f17db893ed5c576
+
+[Alen = 17]
+
+Key = 6bffab1f4f4c1ff66b4a669b515b2f8d
+Nonce = ddb34d5e0140fb96d690e1a2b7
+
+Count = 170
+Adata = 5cbba9ea778e01af00afb2a934f28c7211
+Payload = d91b12e8655dd92b1332fc1d71c391c96a17111562d90ba3
+CT = d302e5b2d5d90433186b804cd7717e2db2f22cdc34fb2942ab30780a2c4f12af8f35350d65284c59
+
+Count = 171
+Adata = 1583138aa307401dddc40804ac0f414d33
+Payload = eeafb08d4a4819f5682a01d44371e34cc5729079e74e73a6
+CT = e4b647d7faccc4ed63737d85e5c30ca81d97adb0b16c514746577901b7f6feb88b8e2b8562f9cb5f
+
+Count = 172
+Adata = 23931c258c84086500c6a3b6eda457e6b5
+Payload = b8737d5bbfc976c2d8d9786148dea664dd83cee98df537b5
+CT = b26a8a010f4dabdad3800430ee6c49800566f320dbd715548735a59390ba7a892741694f3a89b0bf
+
+Count = 173
+Adata = e12f98507d6514c3b551d240595346bc9e
+Payload = eb021b63c61c0b194bd44870608d7ef0b932b6104412d7a9
+CT = e11bec397698d601408d3421c63f911461d78bd91230f548f4f81ed18cc1820375a7bec2318cde1e
+
+Count = 174
+Adata = e14b87d49d231c0199eec627fd7f1b5332
+Payload = 93b42584c4956078359d77e80aef52281b9228a1f66aa36b
+CT = 99add2de7411bd603ec40bb9ac5dbdccc3771568a048818a187b430caa60d98dc3e2aeefe6249b44
+
+Count = 175
+Adata = ca095aec96a8b093e62b10f0950ce35ce7
+Payload = 6a788d8238c7b313b8eba27b210a71c36819d719115b9b76
+CT = 60617ad888436e0bb3b2de2a87b89e27b0fcead04779b9970a77372b727408e1bf5a70790b9eba3a
+
+Count = 176
+Adata = d1cac02b34ad33c0e77a5bda2c3baf5e5d
+Payload = 3bc1ee54d0094603dfc68eee118e547d031fb36e464e776d
+CT = 31d8190e608d9b1bd49ff2bfb73cbb99dbfa8ea7106c558cdc1f5cb4d4fa2204e82eedcb3784443d
+
+Count = 177
+Adata = 065c06b49a49898e20bb679e35edbb1f76
+Payload = 8a12adb8b746216baa8a418725e608e4377f13816a036a10
+CT = 800b5ae207c2fc73a1d33dd68354e700ef9a2e483c2148f12413f9496592a75a1d6e42ee3a258607
+
+Count = 178
+Adata = 98a42d7a0c5917deaf3b4de3f0cbe0a191
+Payload = 30a226c07401d0ae24c73d682e3a6e7e377ec1613bafba17
+CT = 3abbd19ac4850db62f9e41398888819aef9bfca86d8d98f6b571a3150887df1ac5f813676b2eb24f
+
+Count = 179
+Adata = e245a7528931841b52a5f59d861d98d7b7
+Payload = 3d17bcdf30445ebd8a9b6aa2fe11d443c1161bb1ee69ced0
+CT = 370e4b8580c083a581c216f358a33ba719f32678b84bec3131aa5e4657c92e31c69ab18d447d3578
+
+[Alen = 18]
+
+Key = ae6136df9ab43631ef143515dacedbe7
+Nonce = c5c445792208a50c8e93d64aa3
+
+Count = 180
+Adata = e04006b68c83a5dd4ceac3cde238e48895ae
+Payload = 6a493c5ef3769ccc4101dbb2eb36e1e5bbc577a057ce0731
+CT = c7584c0203c2535c5702c6ae93b7cbfb066f4a055c627a180d6d676d11fce907b5c93fa1ed7bff2b
+
+Count = 181
+Adata = 5da64e368f45153ea5b7ddca966b6c5b699a
+Payload = 15e0c672c6764f3699d9d3e7120f8ce5daab166f08fdd074
+CT = b8f1b62e36c280a68fdacefb6a8ea6fb67012bca0351ad5d2cd45f211b1a1364c91ad07959bf0ee5
+
+Count = 182
+Adata = 1b315d024bb5d1e03d7510e61f37d8adb10a
+Payload = de907d58cd8f5a72acaa1d329b937dfbbfed65a4e45eb029
+CT = 73810d043d3b95e2baa9002ee31257e502475801eff2cd0018f021a98b2edfb0b7500363099c2a1a
+
+Count = 183
+Adata = 8691ba4f9232ca86f919fe72ddb39c91d707
+Payload = c7fa314d27be79f9d3e2d1e188c1785b0c970f91b8ed4290
+CT = 6aeb4111d70ab669c5e1ccfdf0405245b13d3234b3413fb92ac9aeb018c48f3902276ac759710b6d
+
+Count = 184
+Adata = ff0baf1cbb5884a9290ea7b5ee49915efb4b
+Payload = 33b05b20f3c849fac091a5028cbfa0bc9a1c32514136fee3
+CT = 9ea12b7c037c866ad692b81ef43e8aa227b60ff44a9a83ca7dac49f606dadb9f7034e0a1860d519b
+
+Count = 185
+Adata = 2d118cda20700bc2748ea1753fbca6f74933
+Payload = f43832e420e2eccd5d80502bea2ba1804e17d4433318fc86
+CT = 592942b8d056235d4b834d3792aa8b9ef3bde9e638b481af623ccbab19c1442806e21c5a820945da
+
+Count = 186
+Adata = 0c7a5fd2010c999a8a0efa81f89ff5bfefe0
+Payload = ceb203c842a962183f22e602644fc66e4290b3d5be445fb4
+CT = 63a37394b21dad882921fb1e1cceec70ff3a8e70b5e8229ddbcd18947ac1800856c9c92eb0388c70
+
+Count = 187
+Adata = 73fdddb9e0a64f5671fd70c4ea8443507789
+Payload = d6015b6bd5f5eabb2a649129f8f727c06a3ad59499f21caf
+CT = 7b102b372541252b3c678c3580760dded790e831925e618639c29ea73b0c5aa130d8b14f7b9926a9
+
+Count = 188
+Adata = 82c4484e3a6e18b6bbfd78b69b00c40b30c5
+Payload = c288b810fb533441bd549d02c0b28d5b834293683eaacda2
+CT = 6f99c84c0be7fbd1ab57801eb833a7453ee8aecd3506b08bf0a0f148ae138c2ea02538c8fd7ac76c
+
+Count = 189
+Adata = 267d8385b14721eded743cffd69e4d595f7e
+Payload = 667cc47d13c34923be2441300066a6c150b24d66c947ca7b
+CT = cb6db421e37786b3a8275c2c78e78cdfed1870c3c2ebb75285eb537e7583f04e040a0ddc41106213
+
+[Alen = 19]
+
+Key = f1908328edf2996ebfc9655472ca5ad0
+Nonce = 4c693364546930b6c5250e2699
+
+Count = 190
+Adata = 4a3634e5028df97fbe00eb016e8ea4f1918faa
+Payload = eede01b08f9a303cdf14c99d7a45732972c6eff2a1db06eb
+CT = 90c850790b0b380f5aeb2488fdf43c9d5ef1759861e86f6e52570e769629dcc2e568737ba53a1195
+
+Count = 191
+Adata = 041b93e3fc059fa44aa755e88df277b9b6e499
+Payload = e61ca7310172eec16745a73e34516f65844eecd0dbc5566a
+CT = 980af6f885e3e6f2e2ba4a2bb3e020d1a87976ba1bf63feff1d82ec19a2e3ec43bbdb34e10999d90
+
+Count = 192
+Adata = d1be393376cb5d23cf8139da0fd92f3d520ae9
+Payload = ea887edee68ad5fa6bae928aa480dda898037f820700ec52
+CT = 949e2f17621bddc9ee517f9f2331921cb434e5e8c73385d7f2abb0ce4de9eeb5e8af9cdf3391d3cc
+
+Count = 193
+Adata = f3e551b34d2db1286a9f41085e4dda95ec3f75
+Payload = 71fe1ba5d299495d2a56039c64032ec6263d437f55e3f5be
+CT = 0fe84a6c5608416eafa9ee89e3b261720a0ad91595d09c3b239c73b01ba49a8498b5ff4833851069
+
+Count = 194
+Adata = a69ddc66e63a3415f21009d53adcf26bc1a9a5
+Payload = bd04d854216740a6ceb9827cbddd83761d19feb2a21d78ef
+CT = c312899da5f648954b466f693a6cccc2312e64d8622e116a2248dacd3903c26a2dc5ae649566ad67
+
+Count = 195
+Adata = 5735d6f5882d8f27155eb4cc285a65138ad64a
+Payload = 33b44873a7a1e5b0fdbb7e7347623e4fa1ccd937feb26fda
+CT = 4da219ba2330ed8378449366c0d371fb8dfb435d3e81065fd4156cf7d97b2e744351b6960a807cf8
+
+Count = 196
+Adata = 5d94ed976ab2063512690ae704c3b115519742
+Payload = d3909d577a4e89642227cc6fc146b61bc18392175e342898
+CT = ad86cc9efedf8157a7d8217a46f7f9afedb4087d9e07411d5a50086b6711ac72533c3c5717f6892c
+
+Count = 197
+Adata = db20b384620ab8691aed2fed14a745188d94c0
+Payload = ba0716355fffb8ef947d2a15eb58375a1ff1084c56699029
+CT = c41147fcdb6eb0dc1182c7006ce978ee33c69226965af9ac54fb74ecb9a5163b01b9dbf97ff2f999
+
+Count = 198
+Adata = 94897cdd04e0c8480b2ef7b5201dda37558ba9
+Payload = 5f4b4f97b6aa48adb3336c451aac377fde4adf47897fd9cc
+CT = 215d1e5e323b409e36cc81509d1d78cbf27d452d494cb049d2a81702f665ff5c54f586defd268c94
+
+Count = 199
+Adata = 95c44e1e5ad256b3ce1cc1d87137a1e09f1fd4
+Payload = 598e91d39c414496fd5e69f2cf80826b4e7d59ba28e0a0d8
+CT = 2798c01a18d04ca578a184e74831cddf624ac3d0e8d3c95dfa641889723e163825ab65727e8a5343
+
+[Alen = 20]
+
+Key = 61cb8eb792e95d099a1455fb789d8d16
+Nonce = 1f37b3e59137f2a60dc09d16ac
+
+Count = 200
+Adata = 09db3efac9473f713da630ae92c2c8604c61c51e
+Payload = 6ad541695a37c32d73ff6d5f870abd5b0f362a8968c4fce0
+CT = e65fcc975865c1499b088b58ba163283085d8ca68dc3b235d89756e5d78753ef22c012ae34b39a20
+
+Count = 201
+Adata = b6d07035aed9c141c713cc3bce60f7ba8ac2545f
+Payload = 9cce4c82fe9d38ef64ac8abdf0619f201a25ce6903675627
+CT = 1044c17cfccf3a8b8c5b6cbacd7d10f81d4e6846e66018f2fc78ebae9c143a7283b0641e1f83f5a0
+
+Count = 202
+Adata = 80a5ab693378af29cd5a33555cb3579f9ae540aa
+Payload = 7295a7aed3e987baef19ad68c33ba5a5dcbff27875ff5236
+CT = fe1f2a50d1bb85de07ee4b6ffe272a7ddbd4545790f81ce35a7e44348d2b3085348f787128a4e96a
+
+Count = 203
+Adata = 220817144a15a0a654fc1beaabce60270aa72df8
+Payload = eb21fe20fc4f92452b261eac0d7b70016f7469afdff7a3f5
+CT = 67ab73defe1d9021c3d1f8ab3067ffd9681fcf803af0ed2024dfc096cd8a09d2d81f6146fb54082a
+
+Count = 204
+Adata = 5a2423c2ff2d642c80ac1ca27dd779321f3e9c01
+Payload = 23bf80f51dfd83f63986910e69d54a315c2bfb43f432b7de
+CT = af350d0b1faf8192d171770954c9c5e95b405d6c1135f90b5da82204f4dd8f535cb2fec2f133d882
+
+Count = 205
+Adata = f2c76ef617fa2bfc8a4d6bcbb15fe88436fdc216
+Payload = fc3a50cc8a68778327923ea697f5388da4c814381e29c5e4
+CT = 70b0dd32883a75e7cf65d8a1aae9b755a3a3b217fb2e8b31108630135498ba409f4b6c8caee8a85b
+
+Count = 206
+Adata = b40c8c1d2cee490653105ca2443356cdb63e4fd0
+Payload = 465e41c69928d08c33e063ea119595a04d0de6bffd17bba5
+CT = cad4cc389b7ad2e8db1785ed2c891a784a6640901810f570f89c515837d129ba41f9c24b0229ddcf
+
+Count = 207
+Adata = 6ebfa1e8f80b3cdb1bedf2e3c7e74f30f55c38e1
+Payload = 3f98ee3922f8f1086e3135ae66c5465426b13c8794954880
+CT = b31263c720aaf36c86c6d3a95bd9c98c21da9aa871920655a352fa6b9c4e40733ddcd3fcdaf9ae63
+
+Count = 208
+Adata = 6d0159861031c1a5f01aab35927fe2ab28154d19
+Payload = 5b43067a5ab3a9f9e633fdc084c44ffa7f11edd12ea5873d
+CT = d7c98b8458e1ab9d0ec41bc7b9d8c022787a4bfecba2c9e82c1aa13f062c0f1f5008e27ff2191942
+
+Count = 209
+Adata = 15e5ade017b30ab41878a2747e93aa91c61c2908
+Payload = e40b7e9e46e339e64891526e730b3bf6562fa37acefce307
+CT = 6881f36044b13b82a066b4694e17b42e514405552bfbadd2e149dd02bc7face0c4dfe4e501c2ac2a
+
+[Alen = 21]
+
+Key = be1ed49e2cb0caf6b6a0940c58453b93
+Nonce = b78ad129457681fa7346435b97
+
+Count = 210
+Adata = 161d92c7df1ebb0924719e066e08b95eb4914a5eda
+Payload = a9eec383f63892521e4616fcbadc5485942ffaf4669c43a7
+CT = 949be340720c4fdc4adc05cb777dd81a2549628d33fba07e62d2b338a7b34ebd9d85c244c952d681
+
+Count = 211
+Adata = 6b1d94bc0c6e45fc905c509ea667853e4b2c5a8848
+Payload = 7b44a093162bfc8b4d65f1031d890a6b08a3705b142c0c26
+CT = 46318050921f210519ffe234d02886f4b9c5e822414befff8a4defafeb3d61dad8c007b68d8fb9b3
+
+Count = 212
+Adata = 868dd3e241f60f097a7a2fe571307ee5eb961218ca
+Payload = 28c4d6de3e2ce51b849b135d9cfd3084f0e3155447cad9d5
+CT = 15b1f61dba183895d001006a515cbc1b41858d2d12ad3a0c57cbab553b511d68a4f41db211d0a2fc
+
+Count = 213
+Adata = 3776f37fbf8803bdfd246ffaff2e59658a6c3f0ebb
+Payload = 16d345606a315ad2406abbcb43cd8cabe948107ba6d17a72
+CT = 2ba665a3ee05875c14f0a8fc8e6c0034582e8802f3b699ab0290fd7dbf0afa3e597274e3c9fe170b
+
+Count = 214
+Adata = d0f2769eba9b8e618f00eed6b34c261c59322a253b
+Payload = fcbbcdd9599a86e7c8ccb9347065789a9728ca1220fa51ca
+CT = c1ceed1addae5b699c56aa03bdc4f405264e526b759db2139c7dec3960e6aba3174d793b4e08f449
+
+Count = 215
+Adata = 2be180892faed0bb75887668d187807666d3c66c68
+Payload = 8d145b1f792cc31a2e5b86216609bb018e7aea3012ff70a5
+CT = b0617bdcfd181e947ac19516aba8379e3f1c72494798937c7057b9e2d844e86ee5c3ecfb3270804e
+
+Count = 216
+Adata = 52859849a5b7c1d432c3bfb35271cd8141db2ec774
+Payload = 741db990b43ef34993c33d1c4953b67b128b9299dfe86d74
+CT = 49689953300a2ec7c7592e2b84f23ae4a3ed0ae08a8f8ead1150fa899152eef7a30ae0f20986818e
+
+Count = 217
+Adata = aa192759625f4e42d1d1fa73dc0f62199142155615
+Payload = 51dca5c0f8e5d49596f32d3eb87437bcae866640310ce1e3
+CT = 6ca985037cd1091bc2693e0975d5bb231fe0fe39646b023aba7ff9203608089558698ec29472dda7
+
+Count = 218
+Adata = 6de564226884188ec7bea3894535a875cff2a42fdb
+Payload = dfaa7aa8b28626210d5c24e2ddfe516189be05aabe26f3b2
+CT = e2df5a6b36b2fbaf59c637d5105fddfe38d89dd3eb41106b85bd0a5074ef852575baf5f12c22663e
+
+Count = 219
+Adata = f245f2ee23755df863dee55d7ef0c3c09a0b6f0b0c
+Payload = eedf00aab5edefdd6549d37ed44358e11c588c24f141dc57
+CT = d3aa206931d9325331d3c04919e2d47ead3e145da4263f8e9eb617436bae012331daf020fce24e47
+
+[Alen = 22]
+
+Key = 34ab6fd7f54a2e0276fcb7cf1e203aba
+Nonce = 6091afb62c1a8eed4da5624dd7
+
+Count = 220
+Adata = 1ab5cc3d7b01dc74e6cf838bb565fea3187d33d552a2
+Payload = 8d164f598ea141082b1069776fccd87baf6a2563cbdbc9d1
+CT = 0d30ab07153b5153637969e6bd3539448c541e42b3d432fd7ef14622a9b621d1721b944c60f7fd67
+
+Count = 221
+Adata = 1f1ac4674b272bc7a4ee9f4eae33e969b16fa90a69ba
+Payload = 14e99a2ef0de650adbd785c692342cdb765e6d20d5fca09a
+CT = 94cf7e706b44755193be855740cdcde455605601adf35bb6dfa4ec2c92671c64ee07946527be67f0
+
+Count = 222
+Adata = 43ee77f12ea42e82a02275a68aa95cbd1bb440442bcf
+Payload = 383242c709fe5f2ce782bf8c83b645d171f2bd238abc655d
+CT = b814a69992644f77afebbf1d514fa4ee52cc8602f2b39e71173572fbf3d9495760aae4347397b110
+
+Count = 223
+Adata = ae2ff288199be25bf640811541394ad7e1dd0dc0d24d
+Payload = 9c16a5b638c35c97c5c981c1b8dbcba11aec30e72e45a936
+CT = 1c3041e8a3594ccc8da081506a222a9e39d20bc6564a521a4d2327956e030b9df753e063b5b71201
+
+Count = 224
+Adata = 4ccfb4281852b5ca7e787723d689384a68ff9437db31
+Payload = ec9d8edff25645520801b6e8d14a2fc3b193db70d5e5e878
+CT = 6cbb6a8169cc55094068b67903b3cefc92ade051adea1354e4dac0c9130f5641afd035dd884b6271
+
+Count = 225
+Adata = d3a2fffc798fd9cc2f409471faf18caa2ff3dcf4e652
+Payload = 0db33eda4188a9165147e24e40f79fee1985eb68d5162728
+CT = 8d95da84da12b94d192ee2df920e7ed13abbd049ad19dc0448807dd50a9cf41651083c49c7493ceb
+
+Count = 226
+Adata = 7b5121aa4d1e314f209ffe3e92cd26ee4f74d91e27f2
+Payload = e0d3ea4308376423c4322503f56e427a64e2e6d8b4f5e668
+CT = 60f50e1d93ad74788c5b25922797a34547dcddf9ccfa1d448ea0da53046733f522ded40a09c6d7a6
+
+Count = 227
+Adata = 6e12c112720ef346bbbe7d1c19483721b1c52c438dad
+Payload = 491f2bca585d6b5fdf38d18890e4d1bc923fe26930b3d2f1
+CT = c939cf94c3c77b049751d119421d3083b101d94848bc29dd345cb5a968f39654b994686699d532c2
+
+Count = 228
+Adata = 20433402a2d869c95ac4a070c7a3da838c928a385f89
+Payload = f45908d691ddaf89c0bc129ffada94c3ceda5f47d63ef76a
+CT = 747fec880a47bfd288d5120e282375fcede46466ae310c46cce85eb55339b886b7121b306fccc0b2
+
+Count = 229
+Adata = 42f944c21cc221beaacb288115ac628346b8a1d94bd5
+Payload = e300fc7a5b96806382c35af5b2c2e8e26382751b59010d4b
+CT = 63261824c00c9038caaa5a64603b09dd40bc4e3a210ef667a37ca5ce12aa6f0659467642deb8bfcd
+
+[Alen = 23]
+
+Key = ea96f90fbae12a857f5c97e0cba57943
+Nonce = 21cc46d9ced1539b0ad946e600
+
+Count = 230
+Adata = 105258d2f25f62675aee975cfdb668aff833f05b61eb2a
+Payload = 49db80f22bc267a70e5636dfbc8a21c83d9691fe4b9c3051
+CT = d2fcc8b7809b5fc07e44083e437d8180157f1782a9ce9f65c7fa9ee2e7cdc1b755258f2212a8a8f4
+
+Count = 231
+Adata = 0f5938540651fa4ca03867e67518eb2b73f60dd8750fa0
+Payload = 26618e21099a79d6c517335389551323065ad89c8848ea12
+CT = bd46c664a2c341b1b5050db276a2b36b2eb35ee06a1a4526bfdb9bfcd3b969fb2e41221eb92b0147
+
+Count = 232
+Adata = d6b228960fcbcf07c7bede616139db62b3808718a5b511
+Payload = 4de1d6d57144896ddea1c30f49afecd27bdf4840ed9928b5
+CT = d6c69e90da1db10aaeb3fdeeb6584c9a5336ce3c0fcb8781f8beea22cba93203c912209c78c03aa1
+
+Count = 233
+Adata = 75f8f071e229355e286882917ce5dd4f1db591fee51b6c
+Payload = 785359b1dc754a1e1b6d8731bd2d917ce3e91507401310e8
+CT = e37411f4772c72796b7fb9d042da3134cb00937ba241bfdc69a2e3ea4a40f7c491912c1a0778ebde
+
+Count = 234
+Adata = 4afb62aa8648ac7474dd16fcc376f8909c69e1ce36e6d1
+Payload = ab627aac1496d011ed2edcb2fc6b2afbcc394654f56124f6
+CT = 304532e9bfcfe8769d3ce253039c8ab3e4d0c02817338bc2a75c7ba2a769c27903e99b72639b0841
+
+Count = 235
+Adata = 736fdf94db820a2efe89e7fc9dcfe7c23d5754ac2bcc7c
+Payload = 40722cffb37f1455c2618408e777ed0f4b1bd039952730cc
+CT = db5564ba18262c32b273bae918804d4763f2564577759ff8f84f4ca4a69fde75d7207e50494819b6
+
+Count = 236
+Adata = 8a9a0367137c28db4c4e78d9cd9a68cde0d1b4583532ae
+Payload = dcaabf7a061502618541c09ea59dbbbd52b2692fd0064747
+CT = 478df73fad4c3a06f553fe7f5a6a1bf57a5bef533254e873a0c34a24d3ee0946034c71fba4dbb333
+
+Count = 237
+Adata = 34dbbff560ef04ea731b8979aef2ae50972f4db3efe14a
+Payload = dd641a893b16e0e173ea2eda20638bb01849ac11e64e8ddb
+CT = 464352cc904fd88603f8103bdf942bf830a02a6d041c22ef0f5e24a435a39a716c39f43dabdc4281
+
+Count = 238
+Adata = f3d1fcd912252431db9d8ccfc3e203d5b34d537468b4c6
+Payload = 9aa3e8ad92777dfeb121a646ce2e918d1e12b30754bc0947
+CT = 0184a0e8392e4599c13398a731d931c536fb357bb6eea673f623d59f66764d859a772bb50ec91fc3
+
+Count = 239
+Adata = 513b4cdc551c203ed5f1e659813584862023911590b672
+Payload = c8f44ae4b02fffdbce0df773c24075f877945fc7a86be460
+CT = 53d302a11b76c7bcbe1fc9923db7d5b05f7dd9bb4a394b543b6549eb16fba96318afb3df51f4675f
+
+[Alen = 24]
+
+Key = 35b403a15212097085d6e2b77ec3d4f2
+Nonce = daa423bf9256c3fcc347a293aa
+
+Count = 240
+Adata = d3c0ed74e5f25e4c1e479e1a51182bb018698ec267269149
+Payload = 7dd7396db6613eb80909a3b8c0029b624912aabedda0659b
+CT = 5b00cf8a66baa7fe22502ed6f4861af71fa64b550d643f95eee82c19ecba34280604b58d92dacd3f
+
+Count = 241
+Adata = 62f4fe53e99a9b0c51e9561d910d7e2ffe19a5176c9dec06
+Payload = 897f0dfd90213f64a9277a0eda4f134f303fa89f56ca54fb
+CT = afa8fb1a40faa622827ef760eecb92da668b4974860e0ef5ab4999e9689d52b8afeb87923efa3b48
+
+Count = 242
+Adata = 191c4dfa653c20292657f7694c6b6a4a410c49a879abd217
+Payload = 2b7cf9e6e2d6abcd7775f8a6eb6294e822041c4c45f09c3c
+CT = 0dab0f01320d328b5c2c75c8dfe6157d74b0fda79534c632cdc71e556c34fd4e1b5ebc50d38da8b3
+
+Count = 243
+Adata = ba34741f8edb51470eb20f891869aabeab562d92571ac943
+Payload = dccb9a4625512496b372a2b8b768f75741d8c2e30e57d638
+CT = fa1c6ca1f58abdd0982b2fd683ec76c2176c2308de938c3646223d381090661c2ee2370d29a572a9
+
+Count = 244
+Adata = 8b922aca6125722ec490b134a45864397f4e2c281d6e2089
+Payload = e0e452c990665465160b02cad6367ca89723613488d8efbf
+CT = c633a42e40bdcd233d528fa4e2b2fd3dc19780df581cb5b1f78af50466646b7c7e652f787afe5357
+
+Count = 245
+Adata = afb9fd78e3f8eaf4e8c91da62b2da534508e54f7dfa214fc
+Payload = b536fdb8839f87080ae65ec35da347e792622ffe18a61d46
+CT = 93e10b5f53441e4e21bfd3ad6927c672c4d6ce15c8624748cc9d9a1270f78648a6b66cb8c0f2471b
+
+Count = 246
+Adata = ecf942ccee7396cb3ee177eadd4d96a4af1d90afdce97376
+Payload = c81233826e5125e1f31fe275184ccba8f1a743e58e146e4d
+CT = eec5c565be8abca7d8466f1b2cc84a3da713a20e5ed03443b17d3d6f1fc4f530841b749d9f3a0a7a
+
+Count = 247
+Adata = 16fea92ffcaad563792aa924bffe7ef690edc90ea4e29cc0
+Payload = 24ab253b5b06552665c3c810254c0ed15e68a783180d7eee
+CT = 027cd3dc8bddcc604e9a457e11c88f4408dc4668c8c924e05852ed48cf88d9ab2326aa46b6541b60
+
+Count = 248
+Adata = 76f110eecd369d79e21fb208058359d3a2f37581d1f7f691
+Payload = 7f596bc7a815d103ed9f6dc428b60e72aeadcb9382ccde4a
+CT = 598e9d2078ce4845c6c6e0aa1c328fe7f8192a7852088444c62dff6bcade5ac2edb8ec9797ce433e
+
+Count = 249
+Adata = 8834c776a3237f060ae0ab9857324a3b2ac79f3b6e6f90f5
+Payload = 11cbfb3d348c7abef99f562607e289de34a2bb379a5dfe50
+CT = 371c0ddae457e3f8d2c6db483366084b62165adc4a99a45eb936ac4764575f85352c24ab23209d42
+
+[Alen = 25]
+
+Key = 7a459aadb48f1a528edae71fcf698b84
+Nonce = fa4616b715ea898772b0e89dd4
+
+Count = 250
+Adata = 0c0b4a45df5c3919c1e1669c5af5d398d9545e44307d95c481
+Payload = 0b3d947de8632dc8ff752f619ba7c84716fac7a23e101641
+CT = 7db9f3f7dc26fc2adf58d4525d26d5601e977de5a7c33911a1138cff7b624f9908b5b4d7e90a824a
+
+Count = 251
+Adata = aa27a28a36b5a2cee57ffeca0233feb4bdd4eacb2cae28e98f
+Payload = e6dedce2c278c44e5678d13e7d5b5d3501d61bb0bb6b5558
+CT = 905abb68f63d15ac76552a0dbbda401209bba1f722b87a08e23f92b598f7a248a894e6b8f5691bee
+
+Count = 252
+Adata = 66220aa9b40a1772caba7749a544bff938e804dbc6e556498f
+Payload = a276b0922fbd5094bf89b9329d07341e039d6204397b81c0
+CT = d4f2d7181bf881769fa442015b8629390bf0d843a0a8ae90e94043c0d80fd651469232fe9d47a81f
+
+Count = 253
+Adata = 3d765d20e03a4cebfda50316c4b7d8b6c55078d5b3e9cbc567
+Payload = b99afbc2dbb377350cc58d4bfe8e954cef25d7b27b82fad4
+CT = cf1e9c48eff6a6d72ce87678380f886be7486df5e251d58425088b522fc0731097e729448236b317
+
+Count = 254
+Adata = e91b6265879153e1692b00a112b4205111c8eb1a7b7f2c6898
+Payload = 56114cc783b80ca2dd2881387b6d92a59a237dfc8e976d8b
+CT = 20952b4db7fddd40fd057a0bbdec8f82924ec7bb174442db2208cf07574cc4f3f83ed6301b904404
+
+Count = 255
+Adata = 340b16f352817babb4fb70e9e6e18784b3e67bdd449872158c
+Payload = eb21fe20fc4f92452b261eac0d7b70016f7469afdff7a3f5
+CT = 9da599aac80a43a70b0be59fcbfa6d266719d3e846248ca514b0a900068e55cd24c92bbb78c521ad
+
+Count = 256
+Adata = 5a2423c2ff2d642c80ac1ca27dd779321f3e9c01445be684dc
+Payload = b15083a73607c9d7e197a8cc884ad3be98ac343f6493df67
+CT = c7d4e42d02421835c1ba53ff4ecbce9990c18e78fd40f0373f8ba66d74321c80c057f010078d2f28
+
+Count = 257
+Adata = 5fe8bb27a59a5f4e370adbba96484c2365fc0d8c6e58d7d3e6
+Payload = 07542d18e8f2d3e199fca0f90cabb78b169525fdce81666a
+CT = 71d04a92dcb70203b9d15bcaca2aaaac1ef89fba5752493a0a189319e4f06d53c1405d37b06cc8eb
+
+Count = 258
+Adata = 23e5422e8d7560a9e65642b5e723a47536c16791f3a0cf918d
+Payload = cd574ed56bdfd1408f7831e0b24b4345ee979ac906a7aa22
+CT = bbd3295f5f9a00a2af55cad374ca5e62e6fa208e9f748572dd72f48ae03670249d74f8460b63b1ae
+
+Count = 259
+Adata = fcc9422ba5023a9997baa9c4ee6cb196ffe96e08eb9c2b8a75
+Payload = 8c9abe94beed4c9bd46adb1d04fbfe7016dd50d324525abb
+CT = fa1ed91e8aa89d79f447202ec27ae3571eb0ea94bd8175eb1717c00c93d36a77141b723d573c8c65
+
+[Alen = 26]
+
+Key = ca748225057f735f712ecc64791367f0
+Nonce = 1341a6998eb1f50d4b710a13ac
+
+Count = 260
+Adata = 5fb96b045f494808c02014f06074bd45b8a8ad12b4cb448ec162
+Payload = e92cd0cb97afe4fb00c4f12e9b9abe1d08db98f49a27f461
+CT = 82b666694232e86e82295beae66ae67d56aceb5d6b1484ceb4a6843ec16078038c10afedc41f5362
+
+Count = 261
+Adata = 87db0d9d69bc0cf69cabeb92570e482bbc8ff3e1ba72f12f3225
+Payload = a6dbad96ad23ff61479df39b99f0673a09f2a7eaebbd34b9
+CT = cd411b3478bef3f4c570595fe4003f5a5785d4431a8e4416a7c6566d0b8ff97f946d7c7773a845f2
+
+Count = 262
+Adata = a061a09024f1e03b223695d4703ee202e90e07156b95859a22e3
+Payload = b1dd81cc3b2b0efe540a3194d6fe304cd2de53db7929ebe1
+CT = da47376eeeb6026bd6e79b50ab0e682c8ca92072881a9b4ee1d66a4728b67b42602e23c8500b0115
+
+Count = 263
+Adata = 0dd513c5d8d62b723ab8b0a3aaa477e843d9149dc8a2f878e585
+Payload = fb30c2e98f3d7e4ed7431da285711d3d287884db13a474e7
+CT = 90aa744b5aa072db55aeb766f881455d760ff772e297044803c51e8c59ed13b3e5d9b489d4ea2ccf
+
+Count = 264
+Adata = 3ff59c40bd796048e586eccc23a82e4d09fc5e779f38eb4afbed
+Payload = 886f9f91a6566ceb99c39462ab675a3ae3be98f68787626f
+CT = e3f5293373cb607e1b2e3ea6d697025abdc9eb5f76b412c0f1ec270b43fc5a9811b56ccf033789c6
+
+Count = 265
+Adata = 0df7ef91f7124da867e992bcbc6fb38232ff6d5205f38768da72
+Payload = ed370d1c2d6dc03e4fae4deb9343a7d4339562cffd427587
+CT = 86adbbbef8f0ccabcd43e72feeb3ffb46de211660c710528bb4ed25940d58cba64271fe1d2e8013d
+
+Count = 266
+Adata = 6777de159c34d005b94f67c33ae4a35ebab09d9cb9c56b4c9c81
+Payload = 2f77c2eb07db14bd713c5af10c0760ea3a6ca5ff8d046d36
+CT = 44ed7449d2461828f3d1f03571f7388a641bd6567c371d99392636a5e373c1354ea9b969abb4932a
+
+Count = 267
+Adata = 75559898f4ba03c55afc25ea91aa61a93c2f8270a5fa51b6f6dc
+Payload = 360fb89429dc9b48358097d930c8561b2bd18dc0a470d1d6
+CT = 5d950e36fc4197ddb76d3d1d4d380e7b75a6fe695543a17959a7e8bc0570f19159f91fc14ac6532a
+
+Count = 268
+Adata = 5e03fc430473c5de96d68907fa506f9da353ae48a965445e1f24
+Payload = f2d8d67b9f291c3edc264893922622b2693f3e7231137eba
+CT = 994260d94ab410ab5ecbe257efd67ad237484ddbc0200e1507e559568c27a30b5676f98cc66f57d6
+
+Count = 269
+Adata = 7eee4869e77f6db12c91d1f647cad2340d33a3defaeb362d311d
+Payload = 7fd6fb81c36e44b150af10e04683b1ec9b5dda87c71ff939
+CT = 144c4d2316f34824d242ba243b73e98cc52aa92e362c89964910615920f6f3c3421a9c2bec1bec7e
+
+[Alen = 27]
+
+Key = fdf2b2c7fcb3789b4e90abe607dca2af
+Nonce = a69ddc66e63a3415f21009d53a
+
+Count = 270
+Adata = c76846da496ed87b9c0f65c6266c9a822224acde9775efb186a4a5
+Payload = d7aa4efa5d75195a400018bd38f7d8cd53fdffe88df1837f
+CT = 150d9a8b78d9c04239d66207a1f95021bbb1b7c70d7c354825d05e5a2e76a90f6fe489fd74cab2a3
+
+Count = 271
+Adata = 4efbd225553b541c3f53cabe8a1ac03845b0e846c8616b3ea2cc7d
+Payload = 5f94a2e48d348a1d56c55a659306e319c3d2ad78b9fe43a7
+CT = 9d337695a89853052f1320df0a086bf52b9ee5573973f590be6af49ce97d5e0e77c7fd5d9cc6d932
+
+Count = 272
+Adata = 7631cf7822a545daefa16a5ec43c877d475a82d5aa2d51cec7fbb4
+Payload = a44b010fc1c659eac9241a58b11a73d7ce33156ddfc54c3c
+CT = 66ecd57ee46a80f2b0f260e22814fb3b267f5d425f48fa0b924b268cab915f999aea3e1cc3a88ccd
+
+Count = 273
+Adata = e4da34663edc44370bfd8aa8315945471a893a1cc069628a071ee0
+Payload = 28d157f5741f1be057d5219711414c0638b47d165a905a6a
+CT = ea76838451b3c2f82e035b2d884fc4ead0f83539da1dec5dc368f5af8e311e67209e02dfa2613377
+
+Count = 274
+Adata = 077509eae1dc367540f87832c5780f6c5b29e180bc6c1fee38e826
+Payload = ba7432a8e34bfaa91b35c8dfd822d86850be39e63150257f
+CT = 78d3e6d9c6e723b162e3b265412c5084b8f271c9b1dd9348ad175fcad35d29396380b79a28784cff
+
+Count = 275
+Adata = a513d750ca1e8bf6cb7b8cea5204e064c15c2dc40d742b31cf5459
+Payload = 3f5830b0ce8849a660af7d58a60c19a9824a3033bb5fed43
+CT = fdffe4c1eb2490be197907e23f0291456a06781c3bd25b7493b4b3e33d325359c9c651290ce73bed
+
+Count = 276
+Adata = e439db829c1291df49fc42c2fa1a92118c2665f11e13f28dc6f11a
+Payload = e69b2a243340df5dc70b2cb05be12e5992ee36f7d9f4ca84
+CT = 243cfe5516ec0645bedd560ac2efa6b57aa27ed859797cb371f88ca5857c6d801e726a01c621a0c3
+
+Count = 277
+Adata = a12c690568114fd7a677f49d74e84fc1a6b7f7d2a08693266c0a91
+Payload = 9de35b840a69a84701ffae1b1d2bf13c34b42a57d14c524d
+CT = 5f448ff52fc5715f7829d4a1842579d0dcf8627851c1e47a0592d360fc6a46aa18c4ce5d74fa4532
+
+Count = 278
+Adata = 1813bf176a1127f4d508d7663ae750f9c4bcb84a6e26811ac60d46
+Payload = 9e2fa20bf76768a5a1467d90a048bb503a2c33bbbaa71653
+CT = 5c88767ad2cbb1bdd890072a394633bcd2607b943a2aa0648b772cef893495cf0a94e8ebf06e920b
+
+Count = 279
+Adata = cc6e9cc2699d3ba0e624e715599480d6b7dbc6eeea0d12a9236444
+Payload = 6681b1cbeceea57a828324831407280b00f4917ed52a10df
+CT = a42665bac9427c62fb555e398d09a0e7e8b8d95155a7a6e8b1851d571a1ef8aed565b784dcaaac4e
+
+[Alen = 28]
+
+Key = 7d870d7e52d3053c65eefad47764cfeb
+Nonce = 37d888f4aa452d7bf217f5a529
+
+Count = 280
+Adata = 9610949f6d23d5b1f3989b2f4e524fab4f297a5bec8ddad4f16cb616
+Payload = 109317556c21c969eda65a94176d7a11462c9ae18a865b6d
+CT = 4e6b967b1571c6d7b9e118b112b7ac949a4a175650316a242dd579cb0d201d22c86bbc7fbe47bd0d
+
+Count = 281
+Adata = 96118dbfe53434d8aed88769a535eb0c8b5849dca1c81c34626ac9b9
+Payload = 3e6c914a196e175079315b1c92b2b8a844deb472e249e3d3
+CT = 60941064603e18ee2d76193997686e2d98b839c538fed29af0dd7aef4a609f3587652173446ebd82
+
+Count = 282
+Adata = 21fc96f73975298207f818909088295d6d6861677130ca258c2174f6
+Payload = e0014147d5771b4380dc0192d45f36f7d60776d1ba47374d
+CT = bef9c069ac2714fdd49b43b7d185e0720a61fb6660f0060463e4405d45caf4836467edbf35089d87
+
+Count = 283
+Adata = 72a5151abcb55933ff7c9314f3235eba2a400121454144c2670e8359
+Payload = 0f1c6dffeda98f7a159f9cc61820bfb29910d8eaa41b751a
+CT = 51e4ecd194f980c441d8dee31dfa69374576555d7eac44537441c813e90fac775eddb7290df059d9
+
+Count = 284
+Adata = dbbf192914b1ad73666e9f5e9c22c08ca398f7524af62b1046a863bd
+Payload = c1ddd14e380cc91324cf2a381df1da1ccffd90ae436a373a
+CT = 9f255060415cc6ad7088681d182b0c99139b1d1999dd067334d9316f1f1c3142c1c9b26e5c220a32
+
+Count = 285
+Adata = 28e4b88fbf04e9897057ff5bfde7eb04fa480256817a50fa281030b4
+Payload = d4dae9c4cae92afb80f9a5c99383ff16e23a2ec942eed4d2
+CT = 8a2268eab3b92545d4bee7ec965929933e5ca37e9859e59bc0b188e33bfab29b237d6c6920ce3418
+
+Count = 286
+Adata = d9ebc1cbfab9034317132a72e0f11c341331146a59e7a2f26bf4f3d7
+Payload = 8a188d40a6e6fbb06a9f06304349a7a808b092cc2fc10b9e
+CT = d4e00c6edfb6f40e3ed844154693712dd4d61f7bf5763ad7fdde04d21b876468bd9184101b5f32d0
+
+Count = 287
+Adata = 34ad69f192ae4dcab771aeeacf01bbd32609bcbbea8ff9df31ded719
+Payload = 590c1aac30ab166b1caff748452fc146765c372e226ffc26
+CT = 07f49b8249fb19d548e8b56d40f517c3aa3aba99f8d8cd6f068c65e9d0e5f1b81c86393900e64c19
+
+Count = 288
+Adata = f5e50ce1f99ed5e9f2baa54b96ae7039234b1131e734ec190695d28d
+Payload = 16d0522b2e691e42bd80ce95e00c8a7a1fc738169e904bdb
+CT = 4828d305573911fce9c78cb0e5d65cffc3a1b5a144277a9206ab3b72c56c8df4a12dba89a2f21276
+
+Count = 289
+Adata = 9b1e7e52ea1a12444d884866e11dcf367b70b816460936fdaebba36d
+Payload = 0bddf342121b82f906368b0d7b04df1c682ecd4c2b2b43df
+CT = 5525726c6b4b8d475271c9287ede0999b44840fbf19c72960170ca7b16d23537eeb3034105334699
+
+[Alen = 29]
+
+Key = 8fcac40527c0e7ca8eaff265ca12c053
+Nonce = ae9f012fd9af60a400e20b1690
+
+Count = 290
+Adata = 9ce65598cd1f86afc9aaaf172809570cc306333c25523f863c6d0e0154
+Payload = 78d1e96af8cebdcc7e7e2a4ddcfa34f6cf9a24fb85672ad7
+CT = 9adb9a95a9379ad795d8d3ffd4e37a045160d6d727f974a6cb3b5151f327e65447e52c7525562c91
+
+Count = 291
+Adata = e7c78ef4c4b959ee00cb1a09d71221a43892ef8ad705edd27ed85d03a3
+Payload = bc59f18c8473941abc681a92741ab5ee13679829f542b8f4
+CT = 5e538273d58ab30157cee3207c03fb1c8d9d6a0557dce68534e5b08e27d8f5eeef0f064ff620652a
+
+Count = 292
+Adata = f1bce6f2a4bdd3a07ebf5f8d47f931d27e7e63389d70e1059f701216be
+Payload = 5575d950312c14c89ac609dfb0b2fd1af732bb6aae5e8651
+CT = b77faaaf60d533d37160f06db8abb3e869c849460cc0d82044c0a96baae318f4714f0206812516b5
+
+Count = 293
+Adata = 3da3bb091016e54477dae88af1c84c1a51b59c1bb49a05deb6f32064e6
+Payload = df5947d8c6094ccc25816639ec42214b28731bfd7b8312dc
+CT = 3d53342797f06bd7ce279f8be45b6fb9b689e9d1d91d4cad4e7bdce2dc6aae24178aab6984f31028
+
+Count = 294
+Adata = c4cd183071c37a8157c6930a7d4d530cf4b7eb021682327810bd48209e
+Payload = 2fbb6dc235761875411ef59ae06110df8f15f66b721b0fd6
+CT = cdb11e3d648f3f6eaab80c28e8785e2d11ef0447d08551a7f18ece8260bd56ecdee768022d0dd8d1
+
+Count = 295
+Adata = 0e0fece7b6b659b642668e8ba3dca330523e70279155f485f3f6f8041e
+Payload = cd149d17dba7ec50000b8c5390d114697fafb61025301f4e
+CT = 2f1eeee88a5ecb4bebad75e198c85a9be155443c87ae413f6f0fb3b7440b84ddc3cc53819c2e93be
+
+Count = 296
+Adata = a35c6f70f637a9a5e6f215c694fdf65b6fd85f794ed3eaa1bc19abe592
+Payload = 030390adb572f2bd2a6a4454fd68236cd1d465574328aa00
+CT = e109e352e48bd5a6c1ccbde6f5716d9e4f2e977be1b6f47129ca778c51f9320f121dd803ece8d5da
+
+Count = 297
+Adata = c2992096828325820e2d7acaa17ac789b6830ec3128dd7f904398afbec
+Payload = f2d9cf953c8d3a051d9b3eae4307a3cb4fffaa2435b49586
+CT = 10d3bc6a6d741d1ef63dc71c4b1eed39d1055808972acbf79c223a5ad65120bfca4a5992e5ebc6fc
+
+Count = 298
+Adata = c023763a285ea934bc5bc7ddfc2aefe2b3f9eafe7b87c61383dcc07990
+Payload = 4b92e8d2ffaa4af8f3e0ac037a900bd18e195f490a3d71e1
+CT = a9989b2dae536de3184655b17289452310e3ad65a8a32f905c3bc4f618ffb3a159f4e2d0622cea6e
+
+Count = 299
+Adata = 0a39ec0163c7aeb1b4fbe7cb4fa5b0592fade70f430e23730a23ed4160
+Payload = 7c0e6a0d35f8ac854c7245ebc73693731bbbc3e6fab64446
+CT = 9e0419f264018b9ea7d4bc59cf2fdd81854131ca58281a376f099dce6e18435fba4d26c1e93bda0c
+
+[Alen = 30]
+
+Key = ddf9f150cc3f1c15e8e773663c5b061c
+Nonce = 98c5036b7d54da9a1177105600
+
+Count = 300
+Adata = 20c5ab290e6d97f53c74121951f39ba865b3acc465fa3f0fb8a591622277
+Payload = 79d8841ab83279724ce35e1a8abd4e158168dcf388ab4c3d
+CT = d00d29396ffa9e691290d746527777bf96a851f306d4da0b1816df1e0e82bb7bc8105930ad6a2232
+
+Count = 301
+Adata = 0e205a4dc5d5ead0d9ff7f182dc140fc49511c01b0fdbc7e6d6cb5fdf027
+Payload = 88b2572fbe7cf2b46df04db476ffedb41778ae2eb3c3aae4
+CT = 2167fa0c69b415af3383c4e8ae35d41e00b8232e3dbc3cd2df823c8ccd466807f2bd1c4032f0cfeb
+
+Count = 302
+Adata = 48043560d60381e83c11d4bc9d997d3ee2add6b0524b779c62dfaa73ce0a
+Payload = d44bf28b010e076b45db1b053af03db718b60748da51db1f
+CT = 7d9e5fa8d6c6e0701ba89259e23a041d0f768a48542e4d2931f5be8c9965345c760c72cc1b7908d1
+
+Count = 303
+Adata = f0729a8a2fd073699ab87b521cbe0420b43529556a505f5f87874d1a053c
+Payload = eab8cffb512eabe267cd64353552513defe97c2d10f35503
+CT = 436d62d886e64cf939beed69ed986897f829f12d9e8cc335381d94a828a95872ebdfda8a4c6a196b
+
+Count = 304
+Adata = fc2cd69bb61223f713e33a5071d09bf2783640c307c22d836dd94952dd37
+Payload = 001056926546c261fbbdf92b94498e038c2bcfd0b6345497
+CT = a9c5fbb1b28e257aa5ce70774c83b7a99beb42d0384bc2a163931808533f4f70d7a78242ced110eb
+
+Count = 305
+Adata = 8f653c5c003c807d16d17f833eebb97c9c2f0e5aae3780a52ce53a6c33f7
+Payload = 29ffaef9415fd300127ffd26ef324083a9d90e0f60e2ab4f
+CT = 802a03da9697341b4c0c747a37f87929be19830fee9d3d79f34553198f8e40fde6473f9cf04f1de6
+
+Count = 306
+Adata = 8d05e7d3077151c6d9378cb08e049e4d7c28a908f7f7c079c46ff92cd01b
+Payload = 9874dc5ca1b541f7b21c7b3860fa6b0c3ab1b712ab0fca98
+CT = 31a1717f767da6ecec6ff264b83052a62d713a1225705cae0fac20e8d45d2b0771d140b5e4a47c87
+
+Count = 307
+Adata = d4feb3ea76ac2945651f557406f3f38a2d7e9232ed55ff4eaf1201dd8255
+Payload = 1e01c7128c821fb9c971a27fc7c6f9bb902fa735de583b8a
+CT = b7d46a315b4af8a297022b231f0cc01187ef2a355027adbcd3cacfe4281e52d79e60eeb38319bc3a
+
+Count = 308
+Adata = 7cbb4ae995a3367a256cafd11cd6c6cab5bf3252fa97f27a8a1434ca9a27
+Payload = 51cd306fac7d20e3c7043eae3a6dfec046c5c24a666a0723
+CT = f8189d4c7bb5c7f89977b7f2e2a7c76a51054f4ae81591158f0d7646a799b14288bb2f354b5d8847
+
+Count = 309
+Adata = bd40b06a4beded2be3d176266b10772c7fa2949f0a9b20d613af90c2daf5
+Payload = fc5b26befc633a3e8ace011aa7a42bd0258a9f3dc14fc1c8
+CT = 558e8b9d2babdd25d4bd88467f6e127a324a123d4f3057fefd7f95e1d331e700aa9ef83f09b689fd
+
+[Alen = 31]
+
+Key = b1dc81d116d94f5eced526b37c004b95
+Nonce = 97c8f69fb91b17299461fd8d63
+
+Count = 310
+Adata = f8b08aa83bed09ca342249b2cf9e2b45a89dcfb8711a120395e455921af481
+Payload = 54390715b6e7c7bd51a234db059a51ba030cf22ee00b7277
+CT = cb629994c3418a662a8cde1b5f4d99aa7df66e24c53dc6df11297930fd44c63675b7cca70671ef4d
+
+Count = 311
+Adata = 0351c969dd38eeaa4b9b0000e346eeb1a2cd462033c59d9e6e3331822045cd
+Payload = 65b5e856a8cf35dffd42c5ba105cba4c434aa1c2a0390352
+CT = faee76d7dd697804866c2f7a4a8b725c3db03dc8850fb7fa7e77f5566ca2fd9293835bceb461dbaa
+
+Count = 312
+Adata = 5db8b6bc16740680f78fba917733a6899cdba5e4c10a8058963d1265681eaa
+Payload = 9a7685e3daac43ccf22cad0df900ba8acddc5d420846118d
+CT = 052d1b62af0a0e17890247cda3d7729ab326c1482d70a525ec2cf9f5d35521c1c000685e49d2ed42
+
+Count = 313
+Adata = e7d6024611210da0cfb90a9955195aa0a0539280a3a7c792a1540930daae2d
+Payload = c18d9e7971e2ae5fc128777086338fbe194443324e2d2cd1
+CT = 5ed600f80444e384ba069db0dce447ae67bedf386b1b987966f33dfb44ae413283b238616c6b99fb
+
+Count = 314
+Adata = 77a878c9c76f3e6a4ddd330d1d8828949d08e0fedffe0d8e2e557b29e7c78c
+Payload = fcf8982f7342f1b953658453cd5ea413700eff00f1ee7d6f
+CT = 63a306ae06e4bc62284b6e9397896c030ef4630ad4d8c9c731df6fc6b4cf0b6332936ed7cfe9455e
+
+Count = 315
+Adata = aa540554ee80dbffa475f702d862d6b60e0a4090792420a26d02926517723e
+Payload = 0d5690d2a7083ad6daf22b308314b8f5363aca77ca72835e
+CT = 920d0e53d2ae770da1dcc1f0d9c370e548c0567def4437f67c8162a815f2809601ad02595e2e0ff4
+
+Count = 316
+Adata = fae86f95dd06fb7fbae63a646615555aec8153dc328bdf79da5d4cc9677ed6
+Payload = f6e313cc35e8f8812b10a44f8ad00b6893f8084d942effe0
+CT = 69b88d4d404eb55a503e4e8fd007c378ed029447b1184b487fcaa11bdeab86f60f9cd0a2b45cee1a
+
+Count = 317
+Adata = fd525302d2fb246a47cf4e3a27808bda89d8488cf450f1a1c7df6eedd810ee
+Payload = 91e961ea2eb750577c5137c609602dbfcc4c07955ba429ec
+CT = 0eb2ff6b5b111d8c077fdd0653b7e5afb2b69b9f7e929d440a86a810881bd969744ad80f579400f1
+
+Count = 318
+Adata = 767b1bdf9793a512d3a84e99ef77b43011a3bcb8de4cd375dfe47a79293e01
+Payload = 98438c4411bead6f30c89ead762a12bf39391d3652b78b7a
+CT = 071812c56418e0b44be6746d2cfddaaf47c3813c77813fd2250ca00d3231819ecdf501ad39c864f3
+
+Count = 319
+Adata = aac7014f606df6feec415a75e29015891007f07518c955875fbf5619262ff2
+Payload = 540cb00c0eface3d1b2d632d80a642f53c78ff672a1ff6ff
+CT = cb572e8d7b5c83e6600389edda718ae54282636d0f2942571224d1d0294d46981d7dc39114a693d2
+
+[Alen = 32]
+
+Key = 5a33980e71e7d67fd6cf171454dc96e5
+Nonce = 33ae68ebb8010c6b3da6b9cb29
+
+Count = 320
+Adata = eca622a37570df619e10ebb18bebadb2f2b49c4d2b2ff715873bb672e30fc0ff
+Payload = a34dfa24847c365291ce1b54bcf8d9a75d861e5133cc3a74
+CT = 7a60fa7ee8859e283cce378fb6b95522ab8b70efcdb0265f7c4b4fa597666b86dd1353e400f28864
+
+Count = 321
+Adata = 55a62968c222a8501d1ae56a9a815667f8a9554607b7c56e6753f8fa92a4d054
+Payload = 764dbefb42644d18d23e5e4568685d14dbacfa418d36c4ef
+CT = af60bea12e9de5627f3e729e6229d1912da194ff734ad8c4423862a715dda2f63a4197f894515803
+
+Count = 322
+Adata = f8436e35b7a1c810ac6aabe8e2d48a3678d19e1e96337dada514ee5fc075fce4
+Payload = cecef24b62676a5623bedae8087b9b05d7e22b41a14dd2d5
+CT = 17e3f2110e9ec22c8ebef633023a178021ef45ff5f31cefec200f190bd700f6108f9959f6d12f0f0
+
+Count = 323
+Adata = 548e2152f3a15b8fb81dc01062d99f7b4fc8f074e5cbdc1030c97f8ccc02ec3f
+Payload = 53c164a4990c6e0637267ff2556c1542712fc584f6ff7458
+CT = 8aec64fef5f5c67c9a2653295f2d99c78722ab3a088368733a66ebc4e0777a6fc140a51e04a10f86
+
+Count = 324
+Adata = d100f1d08ef1e3eda4aef22cd970c2b785c4ff9b523c401b4064324aecf7f2d9
+Payload = 15681d2121ac56a63b9d0a38b9c4eccf84fdb746d32c14b4
+CT = cc451d7b4d55fedc969d26e3b385604a72f0d9f82d50089fb810cdc08db0a9966dffeb43ba26446e
+
+Count = 325
+Adata = eece934a807c9f21487cd810f15fd55d7bb4421882333ff2c43b0353de7fc5a6
+Payload = 412a8ef924ca156de860f147575e5731825f0a3759688928
+CT = 98078ea34833bd174560dd9c5d1fdbb474526489a7149503cfc5b397578f8d02a0b936ffac29b99a
+
+Count = 326
+Adata = 86311ff444d9be90459b6ee3652e1705ed0b5cdac3d27293ddea3378fb686ee5
+Payload = 54ba8a020d0876fa369dc32e8627f565ba3dda862ea0bcfe
+CT = 8d978a5861f1de809b9deff58c6679e04c30b438d0dca0d52c3fcd6d618c260d51724126f257534a
+
+Count = 327
+Adata = ab6efbc44a8906d5c067eaed71af467e130aaf170827a58beb03c55069674125
+Payload = 7a15506fd1dae444d77b2a3ae7b57a8d5b4f10e25a9f78e2
+CT = a3385035bd234c3e7a7b06e1edf4f608ad427e5ca4e364c9bf8b2821920640b992b00cd1c9618025
+
+Count = 328
+Adata = ddb640923d083725587aced81ae1d7409983d1f1e3ccc8dcf94376dc1bbcae8b
+Payload = b18a61a89cd698f32e059b7a2a9f62a46be2c248790a9915
+CT = 68a761f2f02f30898305b7a120deee219defacf68776853e4cd52d41a968284af8907ccbb4588cc0
+
+Count = 329
+Adata = d95ec4a6f594be1ba39fa1aa933dc0a5dafff5ce44509577ebb3a3e8084c4401
+Payload = 16ee3bc9ec8b4448e292b8973618e02a99da1c348539d5c7
+CT = cfc33b938072ec324f92944c3c596caf6fd7728a7b45c9ec47449a5cb4943ff2846c589b7c98ef49
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VADT192.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VADT192.rsp
new file mode 100644
index 0000000000..1a7a5875fe
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VADT192.rsp
@@ -0,0 +1,1823 @@
+# CAVS 11.0
+# "CCM-VADT" information
+# AES Keylen: 192
+# Generated on Tue Mar 15 08:09:25 2011
+
+Plen = 24
+Nlen = 13
+Tlen = 16
+
+[Alen = 0]
+
+Key = 26511fb51fcfa75cb4b44da75a6e5a0eb8d9c8f3b906f886
+Nonce = 15b369889699b6de1fa3ee73e5
+
+Count = 0
+Adata = 00
+Payload = 39f08a2af1d8da6212550639b91fb2573e39a8eb5d801de8
+CT = 6342b8700edec97a960eb16e7cb1eb4412fb4e263ddd2206b090155d34a76c8324e5550c3ef426ed
+
+Count = 1
+Adata = 00
+Payload = 296fbda0017351491c2187273fbde2c3a427170e430a703c
+CT = 73dd8ffafe754251987a3070fa13bbd088e5f1c323574fd2167ee33e75d05023a7d63c770cfef2ea
+
+Count = 2
+Adata = 00
+Payload = eb61c284fe009921039ef6a9ce50e702823e44b35357923f
+CT = b1d3f0de01068a3987c541fe0bfebe11aefca27e330aadd170647420f79c0d91cbbd69b806fe96a5
+
+Count = 3
+Adata = 00
+Payload = ffeccc6460d23fdcc387c697e75dbb959b78013a8282eaa4
+CT = a55efe3e9fd42cc447dc71c022f3e286b7bae7f7e2dfd54a8a3ef2324754539ac774872282534386
+
+Count = 4
+Adata = 00
+Payload = 90958d7f458d98c48cbb464c74bf495a49846dd468c514e9
+CT = ca27bf25ba8b8bdc08e0f11bb111104965468b1908982b07e292cd0e32535a848e327bc53cdae94c
+
+Count = 5
+Adata = 00
+Payload = a4fad5205d38206e25097075687ca86032b95b3fe7e82a07
+CT = fe48e77aa23e3376a152c722add2f1731e7bbdf287b515e9bb21701af36936be5f62d02b84df87c3
+
+Count = 6
+Adata = 00
+Payload = b37114c65372b052cbeecf83d05a5da44f7b5bbff7d986b5
+CT = e9c3269cac74a34a4fb578d415f404b763b9bd729784b95b7da7f975367be24341e4af51b8bb156a
+
+Count = 7
+Adata = 00
+Payload = 9c0f0426f171ff18b2a4392f61fb4ee4a44c476fe03dc930
+CT = c6bd367c0e77ec0036ff8e78a45517f7888ea1a28060f6de360c6d50a96f316eda0b216cbb6380ef
+
+Count = 8
+Adata = 00
+Payload = 7b6e0a480a40585545b0e940e8d97c9ec987bd3c0e9c16a8
+CT = 21dc3812f5464b4dc1eb5e172d77258de5455bf16ec1294634cd1bd98e8137b578a174e39efe09b8
+
+Count = 9
+Adata = 00
+Payload = 34dac6dbc28be62332a6935efc122e37b26ee100eb4033f8
+CT = 6e68f4813d8df53bb6fd240939bc77249eac07cd8b1d0c16909a895a3b08b63d7a2a1e75d25e7861
+
+[Alen = 1]
+
+Key = 9748798c0f3cc766795c8ce0e4c979c1930dfe7faefea84a
+Nonce = cdf4ba655acfe8e2134fa0542f
+
+Count = 10
+Adata = 67
+Payload = 100fa71462277d76ca81f2cfdb3d39d3894b0ca28074a0f0
+CT = 36e2415b4f888a6072f260d7e786d803be16f8b9cbee112d7ff74e3b05b7d7c13284573bd3e7e481
+
+Count = 11
+Adata = 17
+Payload = 0217eb6778691f8dfe2d0e5241f05fcbcf97b9171f4de3f0
+CT = 24fa0d2855c6e89b465e9c4a7d4bbe1bf8ca4d0c54d7522d3ee7ce845f85dfc770d96dee9ca54ccd
+
+Count = 12
+Adata = dc
+Payload = a78b7bc6c1a7250c5fc236f2a8343725a9a7bd3ca81b53e4
+CT = 81669d89ec08d21ae7b1a4ea948fd6f59efa4927e381e239dc14ddd8ae0aa5d810040a8d1d4da1e9
+
+Count = 13
+Adata = 0c
+Payload = 390c808d998582793bb10ee60568eb8d975c51d68b4e4da9
+CT = 1fe166c2b42a756f83c29cfe39d30a5da001a5cdc0d4fc746b40dec7e647720f1f5e8474bf570c2f
+
+Count = 14
+Adata = 3e
+Payload = bcd9747fb54184b61b2e9e049caa75e22006e250f3722c0e
+CT = 9a34923098ee73a0a35d0c1ca0119432175b164bb8e89dd3c10c4aac45d90119cce490cc8681a49f
+
+Count = 15
+Adata = 7e
+Payload = d0342e3cd2c1142b642da7297ee3b9978cec405e6810f12f
+CT = f6d9c873ff6ee33ddc5e353142585847bbb1b445238a40f2f9a95091d2cab7d3d9fa3e10d3e67ac9
+
+Count = 16
+Adata = e3
+Payload = 7fab91d1aa072947d22f0dc322355a022fe7f0747f4a184b
+CT = 5946779e87a8de516a5c9fdb1e8ebbd218ba046f34d0a996180f7818c373e89f7ff3003f53260060
+
+Count = 17
+Adata = 3e
+Payload = e487143dc4d98dcc6a2dfe6ee0f85d565d1f46bb0fafe62a
+CT = c26af272e9767adad25e6c76dc43bc866a42b2a0443557f71905f581585e59e3c8c038b5bf966559
+
+Count = 18
+Adata = 3b
+Payload = 976b489244ed6789a34251500057d1d4a3229367a42b9066
+CT = b186aedd6942909f1b31c3483cec3004947f677cefb121bbea56569c34f8d9eea23e85fec18cfc51
+
+Count = 19
+Adata = a5
+Payload = 71efa75961dfd60ad533082a8cfe111214eb02573adc4591
+CT = 570241164c70211c6d409a32b045f0c223b6f64c7146f44c212da23548f2ca4e9a8a07962be6422c
+
+[Alen = 2]
+
+Key = 393dcac5a28d77297946d7ab471ae03bd303ba3499e2ce26
+Nonce = fe7329f343f6e726a90b11ae37
+
+Count = 20
+Adata = 1c8b
+Payload = 262f4ac988812500cb437f52f0c182148e85a0bec67a2736
+CT = e6d43f822ad168aa9c2e29c07f4592d7bbeb0203f418f3020ecdbc200be353112faf20e2be711908
+
+Count = 21
+Adata = 9db5
+Payload = d5982c462ad40458660cd7b120ce07fce9afe812caedcebd
+CT = 1563590d888449f231618123af4a173fdcc14aaff88f1a89015e5cd97b7dd3d981321ae0b2d99e1a
+
+Count = 22
+Adata = 69cf
+Payload = 1a95f06b821879df3fd3ac52fc99a7c1d3e9775263b7d036
+CT = da6e85202048347568befac0731db702e687d5ef51d50402bf3e75863c7acd2699caba3cc301f4b2
+
+Count = 23
+Adata = 6c6e
+Payload = 373c157e59b934a1afb57d4c5dd9ca7fb736b206a6210bef
+CT = f7c76035fbe9790bf8d82bded25ddabc825810bb9443dfdb5d6a8f7a9f52a8038aa9dc1bdc9ed876
+
+Count = 24
+Adata = dafa
+Payload = 26e10a2ed8cc883a6552aee162c5542ff8bb8e758a1975f8
+CT = e61a7f657a9cc590323ff873ed4144eccdd52cc8b87ba1cc8a15603f10cbfdb041f8b2b12cc8f037
+
+Count = 25
+Adata = c8b1
+Payload = dd235b05c15479dfe0326ba206ac784eca50038bbeb35d32
+CT = 1dd82e4e63043475b75f3d308928688dff3ea1368cd189061278bf62ba6a4819513d49fdcdb45480
+
+Count = 26
+Adata = af48
+Payload = a0818342a5cae4a90ef281d3d1289d83f273f418a545fcbf
+CT = 607af609079aa903599fd7415eac8d40c71d56a59727288b8b4d00309b50f9ea72f8105c94475b52
+
+Count = 27
+Adata = b1cd
+Payload = 33c0d06b6583bb4d15b4a07364c4be70ac6e72795c3dae0f
+CT = f33ba520c7d3f6e742d9f6e1eb40aeb39900d0c46e5f7a3b220ba58e97936612c4183ba86705b2f9
+
+Count = 28
+Adata = 649a
+Payload = 3ba11282d61fe36e38cab7b559c2fd9cbe8bf7eb5863bde9
+CT = fb5a67c9744faec46fa7e127d646ed5f8be555566a0169dd87d602dc85bb260fb3df1221e2fbd10c
+
+Count = 29
+Adata = 593c
+Payload = a97faefcae36732fcfe47736c2334ea7d411bf7638b0c019
+CT = 6984dbb70c663e85988921a44db75e64e17f1dcb0ad2142deb3835b7eecad6dac9785ad1d370ede4
+
+[Alen = 3]
+
+Key = a74abc4347e4be0acb0a73bb8f7d25c35bae13b77f80233a
+Nonce = 6a850e94940da8781159ba97ef
+
+Count = 30
+Adata = a4490e
+Payload = 6372824bf416cd072a7ad0ae5f9f596c6127520c1b688ab4
+CT = b14a07bdc119d87611342c4c6935c5786ff1f9ae2eb49e6191c88a3cb4fbafcb8a4a157d587d7e39
+
+Count = 31
+Adata = 5cad2e
+Payload = 295f4f3417a77fcf0bbda17b0fd629ad57a6086573c87eb1
+CT = fb67cac222a86abe30f35d99397cb5b95970a3c746146a64235c34d1390bba5b008c3fb29c2df958
+
+Count = 32
+Adata = ebdf4c
+Payload = 86f354a505de941d34cd98e3af3706d56a938ab9a2797182
+CT = 54cbd15330d1816c0f836401999d9ac16445211b97a565575a733bba0a6992d0664dc77d2b5d194c
+
+Count = 33
+Adata = 7c0d70
+Payload = 88c3bfb546abe2f6bfc92a7c56c627e24ab92a8a87a6b43c
+CT = 5afb3a4373a4f7878487d69e606cbbf6446f8128b27aa0e90902a31b15eed99c2dc4ed1bf11cad96
+
+Count = 34
+Adata = 8fa501
+Payload = 75d4216bad77943bfe82be216157843b0da0fd16eeee8471
+CT = a7eca49d9878814ac5cc42c357fd182f037656b4db3290a42f25595ae00103d4eb20288158132e7d
+
+Count = 35
+Adata = b7aca7
+Payload = bf1401e8dcf6f681ed6dd74c7e23b7e54b384608b0e5ec52
+CT = 6d2c841ee9f9e3f0d6232bae48892bf145eeedaa8539f88760e67693b509ea4795b7da32c5c5d17f
+
+Count = 36
+Adata = 1f283f
+Payload = 7e623e7ef7d0a678b5d22a8402d89220f4f1bf759e3084dd
+CT = ac5abb88c2dfb3098e9cd66634720e34fa2714d7abec900880ef8ea380a1a0a38b2c20288e637a9f
+
+Count = 37
+Adata = e93f31
+Payload = 14f80e7a6298d85d31fb80376a394a8f88b0ae47f00450c7
+CT = c6c08b8c5797cd2c0ab57cd55c93d69b866605e5c5d84412d553aafe8536385d34c412c14d3a1563
+
+Count = 38
+Adata = 27e9a5
+Payload = 3330df12249639961f562a74b34f60b0a8bc7c783f6572fd
+CT = e1085ae411992ce72418d69685e5fca4a66ad7da0ab96628f594d366c8fc826ce58309e9053c27f7
+
+Count = 39
+Adata = 72d566
+Payload = 1a1860ac8c11c5d262f8141738cae8ff91ca05906dc98bb4
+CT = c820e55ab91ed0a359b6e8f50e6074eb9f1cae3258159f61cdd6ac6c42cd3d11e0344a9c1001e253
+
+[Alen = 4]
+
+Key = df052e95aea3769a433ce4e4e800b8418649bbe8c6297eb0
+Nonce = ba356d392c3f700f4f2706a4ca
+
+Count = 40
+Adata = 8ffc0e3d
+Payload = e8c1a89228d8212f75c136bab7923a89f9fea18e781cb836
+CT = 66b5d782323925e1bd0a8413a9a5a881356453d5df2cbeb199b2e1e803550dcdde55fd66ecb45edd
+
+Count = 41
+Adata = 2b4f9cfc
+Payload = a12c6324e022affd61b7e0d8cccbeb23e2e6c65355c1d586
+CT = 2f581c34fac3ab33a97c5271d2fc792b2e7c3408f2f1d3019e8fbc507244ba234a0581dc69962a66
+
+Count = 42
+Adata = b4de3039
+Payload = 7cccb26f1dd227bc77458b99fd9e00f8e801adaece7bfcd1
+CT = f2b8cd7f07332372bf8e3930e3a992f0249b5ff5694bfa5628a2857099af20a4ae08e687bdb02c75
+
+Count = 43
+Adata = bc59f18c
+Payload = 692b53c1355475c71ceff0b0952a8b3541b2938270247d44
+CT = e75f2cd12fb57109d42442198b1d193d8d2861d9d7147bc3e33a6416e387d9e571a1954471ec9cc7
+
+Count = 44
+Adata = 4fd9fd39
+Payload = 7e3e755e25bbe78d4a7770f9356ab9f4ff1bbfdba46383f5
+CT = f04a0a4e3f5ae34382bcc2502b5d2bfc33814d8003538572180f9735f994c8335e593f30b331a920
+
+Count = 45
+Adata = 296cd04c
+Payload = 997b712cd9295dc43cc19b40679f218c27af3e8c638d2e5d
+CT = 170f0e3cc3c8590af40a29e979a8b384eb35ccd7c4bd28da91990fa537d2657d01f66872ba9af22f
+
+Count = 46
+Adata = 88037d3e
+Payload = 577981ccb6c893dfe6405075fcb41507de7f9bfda860791f
+CT = d90dfedcac2997112e8be2dce283870f12e569a60f507f984915cb93e84028c7aedce1a2dadbb6bb
+
+Count = 47
+Adata = fc4bb852
+Payload = 37ba9f57ec230675ce060ba3d388095adf15907aa0b0673d
+CT = b9cee047f6c202bb06cdb90acdbf9b52138f6221078061ba25baa6385af8d7b807a2d2ab19aa4999
+
+Count = 48
+Adata = f40ec14f
+Payload = 401e0cdc132a9e4a9b5ceeed3c181f67e5203ea69508deff
+CT = ce6a73cc09cb9a8453975c44222f8d6f29baccfd3238d8786adcdb44870e1105b7318d8bad0af957
+
+Count = 49
+Adata = 90e2c63b
+Payload = 0234dae5bd7ae66c67ff0c1a3f1a191a0d7bceb451bc2b7d
+CT = 8c40a5f5a79be2a2af34beb3212d8b12c1e13ceff68c2dfa8b079fb71d45bd985bffd343c3362653
+
+[Alen = 5]
+
+Key = 16d345606a315ad2406abbcb43cd8cabe948107ba6d17a72
+Nonce = d4ef3e9e04f1b7f20ffc5a022e
+
+Count = 50
+Adata = a468f08d07
+Payload = d3bef460223c81e4579c9d1d463ac5e0881685de1420a411
+CT = abb85db49a9b1c8724ecbc734cc8373bd20083cfa4007b1cfe4d3a3bb25f89f692884be230c6035c
+
+Count = 51
+Adata = 4497649a54
+Payload = 81ad3f386bedcbf656ff535c63580d1f87e3c72326461ee1
+CT = f9ab96ecd34a5695258f723269aaffc4ddf5c1329666c1ecd05ae56511a230627e02d066c52a919e
+
+Count = 52
+Adata = c30ddd994e
+Payload = 84b88264afec06b370dfcebf5e1d3e2c1f005faf248b3215
+CT = fcbe2bb0174b9bd003afefd154efccf7451659be94abed188ef92fc17dca026f1ac1eaf78a05017c
+
+Count = 53
+Adata = 9573270f7e
+Payload = 9e4c8aa9b58a8eabc5586892f5541000b43f17d9a051a040
+CT = e64a237d0d2d13c8b62849fcffa6e2dbee2911c810717f4d38eddff1e60e2d9ae74a936364b8df21
+
+Count = 54
+Adata = 40336790fc
+Payload = 260f67122dfbe03365bc9e35e9d4ac4b2eb150eddb30857d
+CT = 5e09cec6955c7d5016ccbf5be3265e9074a756fc6b105a70aa3d464ad89cae59b474d019a5a7605c
+
+Count = 55
+Adata = 0b310c8529
+Payload = 1d55e7352bd895c4ef77389a7225c664f72b38c8de778d57
+CT = 65534ee1937f08a79c0719f478d734bfad3d3ed96e57525abeab0c520e64939c6950c0fa406eafb1
+
+Count = 56
+Adata = 5756b2c681
+Payload = fbd315e1f5bd0f0e60ee6684c88f3543452c62ea0701d11d
+CT = 83d5bc354d1a926d139e47eac27dc7981f3a64fbb7210e10d22d339c382343bf39c239fd64c2a64f
+
+Count = 57
+Adata = 3b919e3665
+Payload = d68d6556c5a5b1f5a123389b3ce966d5837cb8fcf5accfff
+CT = ae8bcc827d022c96d25319f5361b940ed96abeed458c10f2fcd6b562a1b6aa10be92a81f99ed540c
+
+Count = 58
+Adata = 58749b643f
+Payload = 062cb6962fa5b3a6239b95f3a51b478a1f32b081dc538a80
+CT = 7e2a1f4297022ec550ebb49dafe9b5514524b6906c73558d4b853022237d94d253b375bf2150e699
+
+Count = 59
+Adata = a5d50c008b
+Payload = 08c62ff9bd7bcf189f530d5065f8764532d2692f69858483
+CT = 70c0862d05dc527bec232c3e6f0a849e68c46f3ed9a55b8ee7aee0d403b2cf6f8b993eebd6b93615
+
+[Alen = 6]
+
+Key = 1c476cfd7dd300d961fd3f24a6fe0e80742b00851676ca63
+Nonce = e300fc7a5b96806382c35af5b2
+
+Count = 60
+Adata = 28130f938c45
+Payload = 6f3938932b5c1280311e892280d8a822a828a0be7fdb1bcd
+CT = df48662fe134e75a85abc2cece2c3b6236c88a70fa792e9beadc9601adf9fbdf4e3e94b395b0a332
+
+Count = 61
+Adata = f600024a7bf9
+Payload = 0af7345e71f4e8886503395ade0b0296a5856e086638b06a
+CT = ba866ae2bb9c1d52d1b672b690ff91d63b6544c6e39a853c0692a40a6aba8d7c5addae21de90fea9
+
+Count = 62
+Adata = 4eef510d1f48
+Payload = 37f57772f056f45a5ce9f46d27be1858980c8935b9c839b7
+CT = 878429ce3a3e0180e85cbf81694a8b1806eca3fb3c6a0ce122f64becb581070411957e632e19bb8f
+
+Count = 63
+Adata = 4c9c76b6fad5
+Payload = 8bb10c82bcabb7fb2b169252ab443b01df217cf908b8c241
+CT = 3bc0523e76c342219fa3d9bee5b0a84141c156378d1af71708c59f83aa97d069b6d83d9387051f43
+
+Count = 64
+Adata = 5572ecfc7e53
+Payload = d1ccb4654a22b1afe32f3d3035fdccd87e9cbed83c679007
+CT = 61bdead9804a4475579a76dc7b095f98e07c9416b9c5a551f04686ee1d7b985d903f1de6cf78f8f4
+
+Count = 65
+Adata = bffdf9d20d74
+Payload = f990a8f6ba14065d48665db36eb470c49f38e2b6376a9bde
+CT = 49e1f64a707cf387fcd3165f2040e38401d8c878b2c8ae88f8118f1b9f39b51965ae9ef1bdb40111
+
+Count = 66
+Adata = 3f27e678c580
+Payload = f8c7d89639ab742a8bcfffe776e868d671e1fbdd55807a8a
+CT = 48b6862af3c381f03f7ab40b381cfb96ef01d113d0224fdca3236d02f33f49759f281315e449bfef
+
+Count = 67
+Adata = 1294cb9db5f5
+Payload = 8601cfd7d935e8a8487b9c39d55ca27096255f2eb9e009e3
+CT = 3670916b135d1d72fcced7d59ba8313008c575e03c423cb5e74770a07c242c3854ceb242dadc1976
+
+Count = 68
+Adata = cec271332b75
+Payload = 77c85b8022f58337b364142a2474fe5cfddb31cfca48af46
+CT = c7b9053ce89d76ed07d15fc66a806d1c633b1b014fea9a10d6c65f19175cfa49898655ccdddb864a
+
+Count = 69
+Adata = da06bd140502
+Payload = b0f2db802475fa70af02057373844f637a3244cda4b4f93d
+CT = 0083853cee1d0faa1bb74e9f3d70dc23e4d26e032116cc6b458822e49e69031431b3eea872a72eb7
+
+[Alen = 7]
+
+Key = 79d1e38a70df1cf239be168833dcd0570bc8f37b3aa26c37
+Nonce = 8229d6d7e9e21fdc789bff5dcf
+
+Count = 70
+Adata = 076887d2abe900
+Payload = 83c24f3a77b83b4ef45277ba90225f3ba1722312f52b1a07
+CT = 19d880f1d959a68f162de243d4a45747ace704613359b27218d1531a066de60a95d2924a6910e990
+
+Count = 71
+Adata = 7535bcc6fbd1a0
+Payload = 24f85ef683cc521387f484bc0b2ad9172f61884c09a9718c
+CT = bee2913d2d2dcfd2658b11454facd16b22f4af3fcfdbd9f96dbf58406020e6df7b312b6825127f9a
+
+Count = 72
+Adata = f4f96d7b4384a3
+Payload = 212bedfa06b5e1a2c3a2f31f6f791dd9df8ef26077821c0a
+CT = bb312231a8547c6321dd66e62bff15a5d21bd513b1f0b47f64dd755177efc87f8b1daf1fd88e51a6
+
+Count = 73
+Adata = 3b7e3d9c1a7fa2
+Payload = 8b9036914bb0f440c8dbcfde9b9547be5e5ef1f56492c75e
+CT = 118af95ae55169812aa45a27df134fc253cbd686a2e06f2b0be31cab31f1a20805d5c07dc516d707
+
+Count = 74
+Adata = a8c35fae8912d6
+Payload = 50f3f3a91bf6fd9573d5ef54b9bb5805205b2f9865d81fd7
+CT = cae93c62b517605491aa7aadfd3d50792dce08eba3aab7a2399df9a45ad153c0dfb3fec3b9d6f7c5
+
+Count = 75
+Adata = db636541f2429d
+Payload = 6fbda8d435555e735443f1e6bc09e96065092efd89edd64a
+CT = f5a7671f9bb4c3b2b63c641ff88fe11c689c098e4f9f7e3fe20b7da94eac8c7ef8478671165e0d82
+
+Count = 76
+Adata = a8de55170c6dc0
+Payload = 640ef4c246a2c6e16ddc49072a5aeef70319149ffba071ef
+CT = fe143b09e8435b208fa3dcfe6edce68b0e8c33ec3dd2d99a4979c35bdbf9538666b6fa57f0f915d8
+
+Count = 77
+Adata = f8d64ce2aa66e6
+Payload = a14e3910766f31594a28ad2c3678c31d0c3aee88484ca6d6
+CT = 3b54f6dbd88eac98a85738d572fecb6101afc9fb8e3e0ea3752824a691da2e99374ae6c031d74ffb
+
+Count = 78
+Adata = b3c340afdc53a8
+Payload = 1b8e0a09e6364020b4cac704dc19bfa79455295604cf9c9a
+CT = 8194c5c248d7dde156b552fd989fb7db99c00e25c2bd34ef04159a68706faa2e8c3376b4dbeb423a
+
+Count = 79
+Adata = 73824034001519
+Payload = 52c84a0735eea6c5c230644075ebfc5db0c3128056e7a8f4
+CT = c8d285cc9b0f3b04204ff1b9316df421bd5635f390950081e5adc7564721ead2af75cb98e61148b4
+
+[Alen = 8]
+
+Key = 72e6cebdaf88205c4e74428664bc0d7eb4687a272217b7ca
+Nonce = 3820db475c7cb04a0f74d8e449
+
+Count = 80
+Adata = f427c47e10c45bb3
+Payload = 54bc7e3c227df4e83252a5848fea12dfdb2d14b9e67c1629
+CT = 91e7baff2b42af63e26c87ce6991af22422c1f82906858b1721961de5c768f4d19bd3034f44f08d2
+
+Count = 81
+Adata = ca25504f3f5559aa
+Payload = ff4493fea916f49fbb3cae2838bc84e293531092cc0904ab
+CT = 3a1f573da029af146b028c62dec7391f0a521ba9ba1d4a3342968c638ecb8a2b358e8eaefd931efb
+
+Count = 82
+Adata = 8215753d9efc5132
+Payload = af16ab8558269a93d8e8c9e38f12a8768947d8b69be0e259
+CT = 6a4d6f465119c11808d6eba96969158b1046d38dedf4acc1f8ac11752fe51e354f3f8a68815539aa
+
+Count = 83
+Adata = 9e7cdbc6202e6492
+Payload = 744a167ae31a8ca20df82290766429de9ef0b7dfe199a78d
+CT = b111d2b9ea25d729ddc600da901f942307f1bce4978de915489de8e241dcab16bdcbf1a1ff4d8d10
+
+Count = 84
+Adata = b8d511d0ab86a07f
+Payload = eeb39de1fe21b5aba654da45fe1481decb22365fa4cbe49d
+CT = 2be85922f71eee20766af80f186f3c2352233d64d2dfaa053fab212a1b6dc7b953e2bc211be194ae
+
+Count = 85
+Adata = c74a5d4265f9f3d5
+Payload = e95c20e80153bae3fde3c3d82b6b33b35fc1959fa31a5d11
+CT = 2c07e42b086ce1682ddde192cd108e4ec6c09ea4d50e138973918ab70fe048d6c5b63a01725eddfb
+
+Count = 86
+Adata = fd849d3ada03181a
+Payload = 6d00606c72cea3deaea5b51ae09e61924355e167058ef42c
+CT = a85ba4af7bf1f8557e9b975006e5dc6fda54ea5c739abab487089bc20867f474c1127aa1320f0000
+
+Count = 87
+Adata = 56825a68681f498c
+Payload = c47705d897a6c7e7aed710b96e2d8532c23b82090e21b114
+CT = 012cc11b9e999c6c7ee932f3885638cf5b3a89327835ff8c34a23b0b6ac4d297dd7832a5e2102272
+
+Count = 88
+Adata = 72e4da839913a26e
+Payload = c822a1ee581cf85b0482c821473385bd3f28528e5e5760d9
+CT = 0d79652d5123a3d0d4bcea6ba1483840a62959b528432e41dd665766c7af21ff890bd40178f1c660
+
+Count = 89
+Adata = 138457571ee8dafd
+Payload = 3ffb82a83308da66e95ac63ae92931b09ffe0e42afbb4979
+CT = faa0466b3a3781ed3964e4700f528c4d06ff0579d9af07e16a6a58bb772c79481dc26861ffbd68c6
+
+[Alen = 9]
+
+Key = 39c03a0c8634047b1635348f284d3dc1e752ab40548eb337
+Nonce = 9e2ea8eb7f56087ee506925648
+
+Count = 90
+Adata = 28d157f09a71da80dd
+Payload = 0662e63c88e963d3e0cf2c4653515ae4474a2c78ab0394c0
+CT = 01dcd4dd3b8c1369518136ce45e8bb9df565b0ad231a887b02ada34addf0aa2f4744ed2e07995491
+
+Count = 91
+Adata = c17d311362c41d442b
+Payload = d6df8b60c697093987b3d89a3667b36504b6ddddf12b0900
+CT = d161b98175f2798336fdc21220de521cb6994108793215bb38a27466b8741bffce44ef04b23af321
+
+Count = 92
+Adata = 006669ef1a11b65b1d
+Payload = 49ad29ef5e82b08752ac5a50dd982e4bcb700005454ade6c
+CT = 4e131b0eede7c03de3e240d8cb21cf32795f9cd0cd53c2d77d11372fb0dab1c99b159e5fe9f91118
+
+Count = 93
+Adata = 8eafce9ba466fd53eb
+Payload = 385f9fb139dbf88561b7a500b0c7b835fe57e2698c6d9f76
+CT = 3fe1ad508abe883fd0f9bf88a67e594c4c787ebc047483cd09e4898a4046f6ec9f40e412915007e4
+
+Count = 94
+Adata = 796e55fbe7bed46d02
+Payload = 4ebb149b01cbacba32d11168ca61928ea149dcf2ee2c1001
+CT = 4905267ab2aedc00839f0be0dcd873f71366402766350cba5d40a9902481bfac7ff33d08fb4b3d31
+
+Count = 95
+Adata = 8f958d796be0566512
+Payload = 0d974e5621caa1d86eaaee689ccbca57843373fcf20db407
+CT = 0a297cb792afd162dfe4f4e08a722b2e361cef297a14a8bcd972d09a17172161eb68a30b593b1bd6
+
+Count = 96
+Adata = cc879ff2d583a7288c
+Payload = f8e0dac6a691dfb231411b5c5f70a0daff83cc637b0c7bb3
+CT = ff5ee82715f4af08800f01d449c941a34dac50b6f3156708119cc26a80c152c253fbc36cb886e0fc
+
+Count = 97
+Adata = 4765d696d19dec58bc
+Payload = 096a36396ccfa260f28fb0919157a5076b53506c51a2a4ef
+CT = 0ed404d8dfaad2da43c1aa1987ee447ed97cccb9d9bbb8549de06cc5c3bc4ad75076c774576843fb
+
+Count = 98
+Adata = a004f283afc3309c31
+Payload = 5b943269be41e2758a4ea6a3cc621b711a8ba6002783aa72
+CT = 5c2a00880d2492cf3b00bc2bdadbfa08a8a43ad5af9ab6c9135493b44f79a5774df6b2943b0bec67
+
+Count = 99
+Adata = cdd5d8aefe49a315ad
+Payload = 5f27867109e74862ce0dbc9ba73c420b93067bdede17ae51
+CT = 5899b490ba8238d87f43a613b185a3722129e70b560eb2ea7a5da4a29a9012d78b6de6f1b3e8c9ed
+
+[Alen = 10]
+
+Key = e2a92ffbb0b5eb68cb82687f12449fae5167d375131b0b10
+Nonce = 441ad5e1382e083a95224f395d
+
+Count = 100
+Adata = 2352648299b0413cb2ce
+Payload = 048c9ba4597c3bb595bfd5048e5e9a1296f30e5c0118b177
+CT = 25247a258e4ac0a988d8def60cc174a9d4578cd5346fb5150c96e8ab8774baa421f39c64a386c418
+
+Count = 101
+Adata = ce003c836a6f5f066053
+Payload = 02ea8e7e488c863584f828df13dfeb68433294d11d9ca9d7
+CT = 23426fff9fba7d29999f232d914005d30196165828ebadb5d453036cdc6bad0c5e770a6249a52e74
+
+Count = 102
+Adata = d11be73a104ccc6346d5
+Payload = 6d5573c9279897d7d1602d8a95c04bb5ca3fad2dbe89a024
+CT = 4cfd9248f0ae6ccbcc072678175fa50e889b2fa48bfea4464627ad75bbfe17f3f5ddfd3dbc1045f3
+
+Count = 103
+Adata = 6a7b80b6738ff0a23ad5
+Payload = 97a813e75d95d25c2edb1c705c4ffe4d7c08c756761fbc0b
+CT = b600f2668aa3294033bc1782ded010f63eac45df4368b869af8943f74706cc3394a170fd49f7011a
+
+Count = 104
+Adata = a391acdb3a06dae4a671
+Payload = a78981ac244307451e4d3fd7f654b70cc4e6518aa47a3c18
+CT = 8621602df375fc59032a342574cb59b78642d303910d387af22597f63074ca3533bb5e107860481f
+
+Count = 105
+Adata = 0b9f28f2d3215785f569
+Payload = 5d649d79ff0e304e164a383c74f13d7ffab145d00cb0ec2c
+CT = 7ccc7cf82838cb520b2d33cef66ed3c4b815c75939c7e84e905b5609f593c6ea9281f66cd2e646dd
+
+Count = 106
+Adata = 7928b1091cbfb2eef0fe
+Payload = 83a273687dced7b94d569f81d75508595cde668f06406183
+CT = a20a92e9aaf82ca55031947355cae6e21e7ae406333765e1428195355618ea0cf87260ad20b6d7b9
+
+Count = 107
+Adata = 3b74afb81f54a93c79d5
+Payload = b4dc3c059cf7b47dd0bb7f165a63fc80b5c6b5f3ca7eeb73
+CT = 9574dd844bc14f61cddc74e4d8fc123bf762377aff09ef1155019659f41a5f0430695b4ada9d8b8d
+
+Count = 108
+Adata = a46ae4c71d4c9eb72fab
+Payload = 7e919581c5105d98717d0613e1ca869c6516506ea482d5c2
+CT = 5f3974001226a6846c1a0de16355682727b2d2e791f5d1a01514b252f33dc870c42260e48c4fa9fd
+
+Count = 109
+Adata = a1ace61711f0a09ac17d
+Payload = 3a4558b55214f21cbd2ae2eda5a2321cfc2f102e059b744a
+CT = 1bedb93485220900a04de91f273ddca7be8b92a730ec7028c263c667d7ed58907452c092905d0b31
+
+[Alen = 11]
+
+Key = ef1ad3eb0bde7d4728389da2255d1f8a66ecb72e6f2f1ac4
+Nonce = 8e7d8a44244daa7df2b340993e
+
+Count = 110
+Adata = 521583c25eb4a3b2e46120
+Payload = 9f580cc6c62a05ce125c6bec109a48ca527ee26a64b14b68
+CT = ff0ff95bcb0bccd5e4aadd77ac6770f5013654eb3c6386fded2c87135861b43a99f258b6938f66e3
+
+Count = 111
+Adata = 31adb39e947f8883fa4b69
+Payload = f16bba081bddda83546eabc9a55c81a439720dd8562ce964
+CT = 913c4f9516fc1398a2981d5219a1b99b6a3abb590efe24f132b87476d66a1bd405f484ef9ac8ab7e
+
+Count = 112
+Adata = f05f39eb0a3d6460076aa8
+Payload = 6baf784f63cf45a1836fa8f3609fff7870ce8cbd1e91268c
+CT = 0bf88dd26eee8cba75991e68dc62c74723863a3c4643eb19a120b455b366cb104fd8b6dc2c80471e
+
+Count = 113
+Adata = 74c7a633ff73ff507009c5
+Payload = d8176a6de1c15a14c8b8b58725c179dc84c9308268d718d5
+CT = b8409ff0ece0930f3e4e031c993c41e3d78186033005d5400c8ca09f4bf06b1c27e75abf15112e49
+
+Count = 114
+Adata = ab322a88cf44b9ca774415
+Payload = 3706e4d8ff748574f382e5f9b0a3b6258f1f360fd87001b0
+CT = 57511145f2554c6f057453620c5e8e1adc57808e80a2cc25b3159274a7de3550baf759f7fae53dbc
+
+Count = 115
+Adata = d6fe6e17221d4e06ed3ab9
+Payload = e02217394772deffe218c405e40f2a3a56ca01d55d6d3330
+CT = 8075e2a44a5317e414ee729e58f212050582b75405bffea516fba8d193e133e6f78daa39681cb262
+
+Count = 116
+Adata = 2739d2cdfcbe7d5cd7d28c
+Payload = bb713f74a884bd1a994adba87561d637853c6181290ef5e8
+CT = db26cae9a5a574016fbc6d33c99cee08d674d70071dc387d65f92db3b3d1c2de04c69c5d06b0e001
+
+Count = 117
+Adata = 5841571299cd064a6262b7
+Payload = 9641dedd50d80ac0abf7591436065fa2e23e4687abbb86e4
+CT = f6162b405df9c3db5d01ef8f8afb679db176f006f3694b716e4d20ab5ffad6f71155f6839dfdbb25
+
+Count = 118
+Adata = dc5d7fd97bb3243ba585fa
+Payload = aefda8501193edacb8abb94fff875529a537a462c4b9b69c
+CT = ceaa5dcd1cb224b74e5d0fd4437a6d16f67f12e39c6b7b090ebc3af2de52b8bee3d130fa973f716b
+
+Count = 119
+Adata = 8789e0b3e0dc13d9725b37
+Payload = 65e53f549b62aca03f21ab2a494b93805e02cfecf4f12aa4
+CT = 05b2cac9964365bbc9d71db1f5b6abbf0d4a796dac23e731b5cd5a004a0ef28e30383bdaed8f93c7
+
+[Alen = 12]
+
+Key = 44cba20b7204ed85327c9c71c6fea00b47ce7bdde9dea490
+Nonce = f3329154d8908f4e4a5b079992
+
+Count = 120
+Adata = f1e0af185180d2eb63e50e37
+Payload = 6333bde218b784ccd8370492f7c8c722f8ef143af66d71d7
+CT = b9401a4927b34dc15e9193db00212f85f0c319781ec90e3b4484d93cb422cb564acc63d3d18e169c
+
+Count = 121
+Adata = ea74231e49e667ca1c21d46d
+Payload = 3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e
+CT = e67d8fbeec794d42fc64d7f36a87d2ac22aafa440021ea72c4c151d9927e6a9f19d47ff7d79ca6f6
+
+Count = 122
+Adata = 7f5871a8300471dc325f8289
+Payload = c642c9722d84d708682350dc70bdaa9a1181a415a9e72b93
+CT = 1c316ed912801e05ee85c7958754423d19ada9574143547f959eee29be1415ab03444de0fa42707d
+
+Count = 123
+Adata = ee7e6075ba52846de5d62549
+Payload = 2286a1eddd80737a724ca941217e9f0232870b6c2f20d29c
+CT = f8f50646e284ba77f4ea3e08d69777a53aab062ec784ad70ce97c1c8aea70de04580d7b37f8c014d
+
+Count = 124
+Adata = a30f2fd445820cdf80014554
+Payload = 92577d5db20391110309d490f52acecdfc18382f368bbe42
+CT = 4824daf68d07581c85af43d902c3266af434356dde2fc1ae23b536f993381e525a14599dd5c02e80
+
+Count = 125
+Adata = 0cfec933831644b468724e80
+Payload = 6803dc3f7c06568ca78ee5aa2e9b1b354a4f1e067ff6a25b
+CT = b2707b9443029f81212872e3d972f392426313449752ddb7d6ea722fdd82ede2c7b8832dde3cbe80
+
+Count = 126
+Adata = 6bd14e3bf91dc7fd6be07647
+Payload = 5580672e52aacb9d714a34c31c33fc221e13e8f90849adba
+CT = 8ff3c0856dae0290f7eca38aebda1485163fe5bbe0edd2565c2994b2b469ad977564d83db1ebfe38
+
+Count = 127
+Adata = 6c6ad35e97d023217018162f
+Payload = 1bd1bcc6766d251144376d91ff93ef83033d0e0ee546266f
+CT = c1a21b6d4969ec1cc291fad8087a07240b11034c0de25983ac31ebf9e255eecf3c69ddf198760556
+
+Count = 128
+Adata = 52c35db85cc34b6efed180ee
+Payload = 28f71a2fe498f89203a5d23e8f8fa64b124aea6459fe721d
+CT = f284bd84db9c319f8503457778664eec1a66e726b15a0df13424079e3de87fa59c3d10fd62380a90
+
+Count = 129
+Adata = a96e4776270683ee7d0c9b6e
+Payload = 5be078ead1926074afca81f9a97dc93dcb954c955e4343e4
+CT = 8193df41ee96a979296c16b05e94219ac3b941d7b6e73c082258e1f3fc3eb7e976c86c8a21bd6569
+
+[Alen = 13]
+
+Key = b5f43f3ae38a6165f0f990abe9ee50cd9ad7e847a0a51731
+Nonce = 13501aebda19a9bf1b5ffaa42a
+
+Count = 130
+Adata = ead4c45ff9db54f9902a6de181
+Payload = 3726c1aaf85ee8099a7ebd3268700e07d4b3f292c65bba34
+CT = fd80e88f07dad09eed5569a4f9bb65c42ef426dda40450119503d811701642143013f28ce384d912
+
+Count = 131
+Adata = e63b89e95df8338ecdcc885c3b
+Payload = 37f86aa62b1e31e9ded3e1a38a7e1a8a638d619ac109694f
+CT = fd5e4383d49a097ea9f835351bb5714999cab5d5a356836ac6d3f9c7b9f25e09ce164a11370b8b05
+
+Count = 132
+Adata = a2161536e263459e0b0a29a225
+Payload = 1749f5977197359a5d318d5fea38aba95b3603f1d7011e66
+CT = ddefdcb28e130d0d2a1a59c97bf3c06aa171d7beb55ef443e02b848b006c28803303fd97bdc35476
+
+Count = 133
+Adata = 8ac95a6ae0bce0fb07f85368ab
+Payload = 0842bfb8b38283257c2ea58b29c8350775f1dbf15f73c905
+CT = c2e4969d4c06bbb20b05711db8035ec48fb60fbe3d2c2320431de2bc45b2b726bfda92939a11f68b
+
+Count = 134
+Adata = 44cc9b2510680c4d73f1938c77
+Payload = 68d09fce5e89e4ef6d453b8ee326090cedb97b75b886c7b3
+CT = a276b6eba10ddc781a6eef1872ed62cf17feaf3adad92d96786add8c2619f0782ca12312a1d64266
+
+Count = 135
+Adata = d8a662ab8449bd037da0346a24
+Payload = 45245de4ac6a6196a0b15b77c622a21bb50627379ddb4256
+CT = 8f8274c153ee5901d79a8fe157e9c9d84f41f378ff84a873b6bd4a09f9b4aa2864d39ff1a03e0ff7
+
+Count = 136
+Adata = 8ed39da1d9179e77156eb909f3
+Payload = e928e37dbe8389a53c650edc86f83cd3589a53dc8e45adfd
+CT = 238eca584107b1324b4eda4a17335710a2dd8793ec1a47d819b6935778ffbc0953974de0a9d87a31
+
+Count = 137
+Adata = 423515f7bd592d6a7a2408661a
+Payload = 4c3bdc6186297896097b3297ba90bcde78dc8a9efe3bd8b1
+CT = 869df54479ad40017e50e6012b5bd71d829b5ed19c64329400a3da0d3ce34a272b51582a998f461e
+
+Count = 138
+Adata = 5a6bc2cd6890a473d478a582b4
+Payload = 1c5ebaeb7b926a39b8aaf65a4c484b113d6f2caafadc33ea
+CT = d6f893ce841652aecf8122ccdd8320d2c728f8e59883d9cf4ef28c338f497a40f550f2945734ad1a
+
+Count = 139
+Adata = 7bdc26b5b4df58af539d91eb2e
+Payload = be5c9fee6babf569c66e6a0d0f3c4dc314f40c0aeca493f7
+CT = 74fab6cb942fcdfeb145be9b9ef72600eeb3d8458efb79d2e07f1998e57ba9b611568632dc5cb9fe
+
+[Alen = 14]
+
+Key = 13f179aa2a23bc90a85660306394940e9bb226ce3885ec01
+Nonce = aaa52c63ca1f74a203d08c2078
+
+Count = 140
+Adata = 5cc924222692979a8e28ab1e0018
+Payload = d3b36c6289ad6ae7c5d885fe83d62a76270689ce05fa3b48
+CT = bc4fcef401c2e1d1c335734ff23ea52c3474d2e6f31648a7f58649400ac9e825b038d67f0c2a6f1c
+
+Count = 141
+Adata = 21fb9cdd9b110bbbc6832275dfa7
+Payload = a7742dd9c3e8bbad08157fbd01ebfb94e1639117c4b4eb5d
+CT = c8888f4f4b87309b0ef8890c700374cef211ca3f325898b23fa5ad4142e0b4650fa5cc8f7ef70d62
+
+Count = 142
+Adata = 9919ddb6ee6c330646cd15953d39
+Payload = 297b4498bf5427e6341aa9275c1f62e3b0c9b150a195ae72
+CT = 4687e60e373bacd032f75f962df7edb9a3bbea785779dd9dfec551d11b8647432cc4320173939600
+
+Count = 143
+Adata = f94cfd1f8c7902a57784c10b9a5a
+Payload = 2218868033e17220655f0196dab6193c58293ca105d467d9
+CT = 4de42416bb8ef91663b2f727ab5e96664b5b6789f3381436a79a075ec2cacee1482b8328b697a3b2
+
+Count = 144
+Adata = 63f3fe58c348dc6bcbb44c3c370f
+Payload = 4a9bc26fb10000a57b9e73a8a3d30f66ef9de8782201ffa8
+CT = 256760f9396f8b937d738519d23b803cfcefb350d4ed8c4739cbe17b4edd64a3dcd2b8ae3352c04a
+
+Count = 145
+Adata = dec0ce763833305aa9c9efdc2c65
+Payload = 1b61b3ff3e4847a17f55f7565826b0e2ccc1368f4de32022
+CT = 749d1169b627cc9779b801e729ce3fb8dfb36da7bb0f53cdf54665c476d0741164685b0d81caca31
+
+Count = 146
+Adata = 592ef6784ee839a049e0d96257fa
+Payload = 32e5998b37987a38800f5bfe3132979ca1447314570aaef7
+CT = 5d193b1dbff7f10e86e2ad4f40da18c6b236283ca1e6dd18500d93b11fecc8b4560320878ba53550
+
+Count = 147
+Adata = 4a47a82b999a2a739959f153a091
+Payload = 84acfb6cf10b301558e5acbf41bbbe0b145dc66dc600f4df
+CT = eb5059fa7964bb235e085a0e30533151072f9d4530ec87303c2a41443578adaf31483bbb6b9f10b0
+
+Count = 148
+Adata = 4ceba98cc0ff5de1a7d580cf23d2
+Payload = d7c73d77a286df38aad116843620911c92e11486be5fcb0c
+CT = b83b9fe12ae9540eac3ce03547c81e4681934fae48b3b8e32232a856c07999e99a4701988b486ef2
+
+Count = 149
+Adata = 15e3b3c5794fececd703ac58ccb2
+Payload = 140882c5d3534bb0861e7ba9423e67439a02ee6f0b0b00f3
+CT = 7bf420535b3cc08680f38d1833d6e8198970b547fde7731cb3a6d50a92f3183c0c5090edc3c7f822
+
+[Alen = 15]
+
+Key = c1dfc48273d406a3a7b9176f80b2dc4e9a7f68134bab66d2
+Nonce = 1ac53ba965cdaeeef7326a37e4
+
+Count = 150
+Adata = 39ba54a410a58a5d11615a2163cc3b
+Payload = 67d9728a88f1fac3af43ed6d634ba902896bd226858697d9
+CT = 360f0fc714994e3b59448b50cdd61d511b4f09e0e5fb5ac826a51fe5b9b598a17eb3da10f936813b
+
+Count = 151
+Adata = 38b0cca09d69320105d24ee3f96684
+Payload = a8365ba9fcfff060b28895f7a2d786c5991a8f7758962caa
+CT = f9e026e460974498448ff3ca0c4a32960b3e54b138ebe1bbba673a94f4280e84724f4a2510165e9a
+
+Count = 152
+Adata = 76718dfb9c68acdd82592d96def39a
+Payload = 497be597dd695cb159d8a64f44049c3b549ac927837b1b90
+CT = 18ad98da4101e849afdfc072ea992868c6be12e1e306d68118865ab37be6f015316e0d177b6c2e91
+
+Count = 153
+Adata = dd719ba1710916a546233c1494a7a7
+Payload = ca452c21383ebc3fb584f0d59a227374854983f243a3f460
+CT = 9b93516ca45608c7438396e834bfc727176d583423de39713d903f67ad0d72fb8ffea2035216b769
+
+Count = 154
+Adata = d893fa2bd7c70e21a5934dc2e99037
+Payload = 3dd118ed65453d3d7844d8de78d7a43587ac5e9305b11464
+CT = 6c0765a0f92d89c58e43bee3d64a10661588855565ccd9750b885e3e054f519d0355db1bd589bb35
+
+Count = 155
+Adata = 97c60265a3a6993b97ac1b375a79b8
+Payload = a7375ba32251af0138bd9fd8fcd56a7c43ab2ca9a7fc0117
+CT = f6e126eebe391bf9cebaf9e55248de2fd18ff76fc781cc064a950e4bed4137e38787839e39924821
+
+Count = 156
+Adata = acfdf302ed116ac4755069d1704423
+Payload = d39d188f28521e4fb0a0c5e48e6d6efe4383c95b2535ea8d
+CT = 824b65c2b43aaab746a7a3d920f0daadd1a7129d4548279cca94dd97fd2a5d50eb7dd6234b40c525
+
+Count = 157
+Adata = d449f97164aae9a3046624e98810bc
+Payload = 758102470e221e30d87d2807b5f8b793a7a56c83eecf32a4
+CT = 24577f0a924aaac82e7a4e3a1b6503c03581b7458eb2ffb596f11450d5d2ba55ffb4a6cf7eab847a
+
+Count = 158
+Adata = 3e6c914a196e175079315b1c92b2b8
+Payload = 1db875c4b4f9dd4926dfb5604d6c4d21aba7d905aed9d1b0
+CT = 4c6e0889289169b1d0d8d35de3f1f972398302c3cea41ca164894e9218ecacd143fb62df69a13d33
+
+Count = 159
+Adata = e2b7b00d0cfbdfcc24f1819ae1869f
+Payload = d7a75bc621addccbbe162b86d536d69c887c278384af54e7
+CT = 8671268bbdc5683348114dbb7bab62cf1a58fc45e4d299f685a7c19bc9c2f8e36ed95015ebb679ae
+
+[Alen = 16]
+
+Key = d8a662ab8449bd037da0346a24565683a3bbbbd1800e3c1c
+Nonce = 166fb8d0e110124c09013e0568
+
+Count = 160
+Adata = 1c1c082eeb5b8548283d50cc2ace1c35
+Payload = 61fdd10938557080191d13dd6c3002dd445d9af988029199
+CT = 23c05927502a4ee6e61e4e10552d49b020643eab476eeacc867601fe79a122a7817819655183283e
+
+Count = 161
+Adata = cae884fa25adedd883ef4e7c855def19
+Payload = 8c7ae2c3c503e9072d6e04e44c2ea78fd24994503567a136
+CT = ce476aedad7cd761d26d59297533ece2b6703002fa0bda63160bb976ab072aec8fcea8eab3dc5aff
+
+Count = 162
+Adata = a350ed58c04473e113b9088b1fb9dad9
+Payload = 863f9a26182f131c594972398b52b3a01a9d314fd9390bf4
+CT = c402120870502d7aa64a2ff4b24ff8cd7ea4951d165570a1291b2c13a3f5e49ce35b9047ee1e8627
+
+Count = 163
+Adata = cb7090f7a465782f680fd44cbc558107
+Payload = bd94c9ad6253c25dc417f87b6e52e03621ccf4b3bff5b402
+CT = ffa941830a2cfc3b3b14a5b6574fab5b45f550e17099cf57fdd9fd1d469a9042b80e6458d25292b4
+
+Count = 164
+Adata = 914cf55a3fc739b5f87ac7518cc4171b
+Payload = c313bd213dc29c00691e25ce028884192e21a820003aece4
+CT = 812e350f55bda266961d78033b95cf744a180c72cf5697b1a8b8e82175ff30c69ea71d2cfb814ada
+
+Count = 165
+Adata = adc8b69d84ef7ae62f9ca9f371d3488e
+Payload = 85e4e053b976e06a64dfa8523130cdd802d3e7c3d6d797c2
+CT = c7d9687dd109de0c9bdcf59f082d86b566ea439119bbec9776fa36db27b2f84d1b8ab55e2fc89ab8
+
+Count = 166
+Adata = 29ed477994dd231d3a71157eb56d219d
+Payload = c77aae5fd09dc9bceee7428e0734d4b0556528396a58f909
+CT = 85472671b8e2f7da11e41f433e299fdd315c8c6ba534825c0e32058ea939036805a735198934a072
+
+Count = 167
+Adata = 494c8f931029a4919e2dcbc16512a8bf
+Payload = 1f47273103f265f963e498878361c06c01a5ffcfb630a161
+CT = 5d7aaf1f6b8d5b9f9ce7c54aba7c8b01659c5b9d795cda3437098c81475f8a1d8f3b0e63d499d387
+
+Count = 168
+Adata = 53200bc5d1f1fb0eeff02d2bc42f7d54
+Payload = a38231af405dc7b70c8dbc8cb84e6be8a0dc2e95fddc2ce8
+CT = e1bfb9812822f9d1f38ee14181532085c4e58ac732b057bd9d7317973878957e8fc1fa57a025a3e9
+
+Count = 169
+Adata = 61e0e28bf344a9a1b04b15156e06498e
+Payload = a0d3a94ba6bb3bedf38220d1cba7e91273ad19f9a1c436c0
+CT = e2ee2165cec4058b0c817d1cf2baa27f1794bdab6ea84d95b0aa1befae96e71b9d221673844b1cb7
+
+[Alen = 17]
+
+Key = 116f4855121d6aa53e8b8b43a2e23d468c8568c744f49de5
+Nonce = 924322a3ef0c64412f460a91b2
+
+Count = 170
+Adata = 03c2d22a3bb08bbb96b2811ce4b1110a83
+Payload = 1bd3b5db392402790be16e8d0a715453928f17f3384c13a7
+CT = ad736402626df0f9393fe4491eb812725ad39d6facf20b5b2f9340b0d48a17ae1cc71d7515e61ee9
+
+Count = 171
+Adata = f390387610741d560325b5d2010d8cd4a0
+Payload = c93aaa04279e451b6880ed7b7fdb3ca9e80ab76180434937
+CT = 7f9a7bdd7cd7b79b5a5e67bf6b127a8820563dfd14fd51cb717bae4c040561bcfcf80fd842ae8dd8
+
+Count = 172
+Adata = 891d7988a56415a7b433f463b1e80eaa62
+Payload = 2611612ccb5ffefaa73195509bb52c641472bca0dfd09d49
+CT = 90b1b0f590160c7a95ef1f948f7c6a45dc2e363c4b6e85b5bc9fb15d874feccb6b5f581fa470734f
+
+Count = 173
+Adata = 831c0fed5e600dd82d7d55669262a9a17d
+Payload = 08136e946e306cde0544ddc2f3f4a529c89c7b77a5e635c1
+CT = beb3bf4d35799e5e379a5706e73de30800c0f1eb31582d3da72589ee50d23f925f7998ab3ccac37f
+
+Count = 174
+Adata = 32ca9d412d4ef0e89928496e96c9de7f2e
+Payload = 695aaac402942de7d899cc3f741c7fb2b2d8247a7676cf29
+CT = dffa7b1d59dddf67ea4746fb60d539937a84aee6e2c8d7d555c0b608f331dca47c65f5c879f2d532
+
+Count = 175
+Adata = 0746b2e6149c7f55854e9ca3e6861bf0e9
+Payload = 8f958d796be0566512f0512dcebd2e12f3160b05b72ae955
+CT = 39355ca030a9a4e5202edbe9da7468333b4a81992394f1a9b039bd916e923e2fc1f7c60eb59916fd
+
+Count = 176
+Adata = 0e4cbd1c574d656112bf6e70a8f23347f0
+Payload = 367ecd1b71dfb96a84e2369f28705dfaebf0c73ed35d5364
+CT = 80de1cc22a964beab63cbc5b3cb91bdb23ac4da247e34b98ac07f2c0847069fe5be26e623033f532
+
+Count = 177
+Adata = 1a05ff12412bf728497536534c234901ce
+Payload = a9ccee975feb10f635d548a8502f7c8b6adbd2be74117257
+CT = 1f6c3f4e04a2e276070bc26c44e63aaaa2875822e0af6aabf4e66a2b210e5a03bb10ff2926ed8a48
+
+Count = 178
+Adata = 3bd063a51c71fab5aeb47e7f8f958d796b
+Payload = 7df6220599d6235eb450989b6f0cd6c96db62b0d13afc4f4
+CT = cb56f3dcc29fd1de868e125f7bc590e8a5eaa1918711dc08ec90169d0c5c11fff8f255fedb13a99a
+
+Count = 179
+Adata = f0d334e0a27c3d00d56b15c2ee426e6347
+Payload = 6f65a24344c32debaf9f8c3fa426fe0b139e8ad1c8b1fbbb
+CT = d9c5739a1f8adf6b9d4106fbb0efb82adbc2004d5c0fe347170141cf3f207c4f0fc1b0238477cfad
+
+[Alen = 18]
+
+Key = e67f3ba11282d61fe36e38cab7b559c2fd9cbe8bf7eb5863
+Nonce = a727ed373886dd872859b92ccd
+
+Count = 180
+Adata = 68d199e8fced02b7aeba31aa94068a25d27a
+Payload = d7a954dae563b93385c02c82e0143b6c17ce3067d8b54120
+CT = c6cfaa1f54d041089bd81f89197e57a53b2880cefc3f9d877e30b2bcc3f1ea9ec2b8f28bf0af4ecf
+
+Count = 181
+Adata = fc4bbe329a86089ebe2a2f3320dad55a9bda
+Payload = a206a1eb70a9d24bb5e72f314e7d91de074f59055653bdd2
+CT = b3605f2ec11a2a70abff1c3ab717fd172ba9e9ac72d961753a6e6844102d6bb86986c030765d3393
+
+Count = 182
+Adata = d8741e540330692d83cc806a8ac1c4742be6
+Payload = 56ef76dbec6b8b46f5b7b4e311c0baaa6fcf54c69c0b9c3b
+CT = 4789881e5dd8737debaf87e8e8aad6634329e46fb881409c3f92a80b1d82f8c1dc32bfe64adca12a
+
+Count = 183
+Adata = c8b1992dfba55b4ab86b480546c861655e1a
+Payload = 2729636112f2abe2c76ea5e52a3f80b0f882f0f3b6f7c806
+CT = 364f9da4a34153d9d97696eed355ec79d464405a927d14a12fb48ad162b0c0678674d79d26a6b5ef
+
+Count = 184
+Adata = 347e12eec56e95aafcc7d25bf10fc756b4e4
+Payload = dd433eb7422c7c4dccee57a1679633ced3b5f08df763d457
+CT = cc25c072f39f8476d2f664aa9efc5f07ff534024d3e908f081c7cd81c974d985bf24b7fe9542141a
+
+Count = 185
+Adata = 45b35a04d6e2645e9a5aef206ed4e36199c9
+Payload = 70523bc397417e09d791a4976960e02636ca7144a5681cf7
+CT = 6134c50626f28632c989979c900a8cef1a2cc1ed81e2c050a7f6a5c04e59896074e1594706ab27e9
+
+Count = 186
+Adata = 378b48531fe34f55125b2f14f59715dd6ef0
+Payload = 514cb462dd4b117f26cac22062fcbeb353650c71649a7b3d
+CT = 402a4aa76cf8e94438d2f12b9b96d27a7f83bcd84010a79aa9d16c3ab79276cff345444511940a9d
+
+Count = 187
+Adata = 73ed686d6fecdc031cd97653137f269d6537
+Payload = 7f0c2b261db3f3de0ce3a733f4b8c446c374567d96d00379
+CT = 6e6ad5e3ac000be512fb94380dd2a88fef92e6d4b25adfdef92bf8aa6facbe6f9607ea02b54a1bf0
+
+Count = 188
+Adata = 5b0441107e5560be94f030a41cedbdb116d9
+Payload = ebb3e2ad7803508ba46e81e220b1cff33ea8381504110e9f
+CT = fad51c68c9b0a8b0ba76b2e9d9dba33a124e88bc209bd238e4936ee93b5c7a302913292df33c1700
+
+Count = 189
+Adata = feedcc5f8524fe7d49bcd178415b9f4c450a
+Payload = 3216dce3b8b1ce0e79e40fffcac728ab191aaaf319d971d3
+CT = 237022260902363567fc3cf433ad446235fc1a5a3d53ad7493426b6193afe765a76b3dec00266e69
+
+[Alen = 19]
+
+Key = e0a29a2c7840cf9b41de49780b9ee92d646a4bfc5b9da74a
+Nonce = fc9fd876b1edded09f70b18824
+
+Count = 190
+Adata = 36e15baafa0002efbb4bb26503b7e3b79f6c68
+Payload = 344dc8b6bd66a1fbbe330a95af5dd2a8783dc264d6a9267d
+CT = 43b3b96aa5a54378f3bb573ffda3e154aa7f425fc3008175b60a77b9d38740356b544b1c0f259086
+
+Count = 191
+Adata = 712b788f0276e2b5a58be80f9114a12ab2a268
+Payload = 6d0546d4e95d1cfcb37a8f88a62064f5d95791311511535b
+CT = 1afb3708f19efe7ffef2d222f4de57090b15110a00b8f4535f750bb4cd42db3038e2c1622b72cea8
+
+Count = 192
+Adata = 07f77f114d7264a122a7e9db4fc8d091334a03
+Payload = 05024ce13b9057dd2c509db7dbcbd5585e4e64a1e2e380ff
+CT = 72fc3d3d2353b55e61d8c01d8935e6a48c0ce49af74a27f761e77b59ef7eeeae35bb53bb9543b64a
+
+Count = 193
+Adata = 899b036138cee77cd28382ba27984d858a6351
+Payload = 77b8e735b13b10e45e411ab94c6fe1a9eb89f0a7af40ff1a
+CT = 004696e9a9f8f26713c947131e91d25539cb709cbae9581244a60fdb473098a11b2176d37b2c4643
+
+Count = 194
+Adata = 4b000440a8484a5201cd54aec058919769772e
+Payload = 6b21800ae599a15254bb33f0bb080788fb6e9fa054bfd8b2
+CT = 1cdff1d6fd5a43d119336e5ae9f63474292c1f9b41167fba58d4afc30a7f672ea34e05ec1843d848
+
+Count = 195
+Adata = 73a222e681ed1ca47d92a6dd90625d895fbf29
+Payload = bfa9d9af6e1f32b6626a1cd89b1c32513b5b50a18ddab028
+CT = c857a87376dcd0352fe24172c9e201ade919d09a987317204ef270e0f3b5e3ca0b8440af65c76e85
+
+Count = 196
+Adata = 7109a3a36b286059bc1a1abb2767c92f884e3f
+Payload = c68b1bc0050e19780ab53efbea175634f70a7245d966966e
+CT = b1756a1c1dcdfbfb473d6351b8e965c82548f27ecccf3166ffb66991b38a0345fbbff5f2362f87de
+
+Count = 197
+Adata = cd15973753b94b77bb4b778de8b3b0cabbde85
+Payload = 4256f1c9b64390fe2120df9fd38e497c2903c2ca5679ab75
+CT = 35a88015ae80727d6ca8823581707a80fb4142f143d00c7dd033a087c44c2e44adbeb333aa9ded10
+
+Count = 198
+Adata = 6e5e0793855f7145e13a5872f563e5ec61cfd2
+Payload = bb0036b34b0c20094d335a8c74f6b3dea42eeccf4145192e
+CT = ccfe476f53cfc28a00bb072626088022766c6cf454ecbe26ff9c8713422fe38d5bbf2dedccbffe10
+
+Count = 199
+Adata = f844684f5404e7d8eedfa20394b40b4f5d910a
+Payload = 86afa9cdd743916563ebfd3adbdd56e015ea3a4ebc61cfe2
+CT = f151d811cf8073e62e63a0908923651cc7a8ba75a9c868eae75de56eabcf8e02c1a27705adef2732
+
+[Alen = 20]
+
+Key = 26d0a3a8509d97f81379d21981fe1a02c579121ab7356ca0
+Nonce = 8015c0f07a7acd4b1cbdd21b54
+
+Count = 200
+Adata = 093ed26ada5628cfb8cfc1391526b3bcc4af97d9
+Payload = 37ab2a0b7b69942278e21032fc83eba6cdc34f5285a8b711
+CT = a3a60b422eb070b499cf6da0a404b13a05cedda549c6b93e6ca0e07e04674f21a46df2659a5905fb
+
+Count = 201
+Adata = 7df13c9d2247aa40af7bbe2da98bd366d8b47b43
+Payload = 93925579b6367ff592ecbd59495fdeccb50f31ea4fa390bc
+CT = 079f7430e3ef9b6373c1c0cb11d884507d02a31d83cd9e93836597806f5da1d176c745d95c4fa46a
+
+Count = 202
+Adata = 7f369bbc99b6f08049eeb43566269a174829d4dd
+Payload = 8363aef9c7c34e1f8149de46c97d5ac79d38c6ed31ab1d12
+CT = 176e8fb0921aaa896064a3d491fa005b5535541afdc5133df826dda99111691993027628c70ff6ae
+
+Count = 203
+Adata = 04aa8442179f62babad0c006e36af0c21105f27a
+Payload = 17281acb525b13653000ab45d86e70106c10a93c99b18f76
+CT = 83253b820782f7f3d12dd6d780e92a8ca41d3bcb55df8159d074b018143a7ea1b5369b7f80eae20d
+
+Count = 204
+Adata = 997e646014f19a53beab8877ca6022bef23016f1
+Payload = 5d48a71557608736eded309027a80349a18e9ce5dee2bc6a
+CT = c945865c02b963a00cc04d027f2f59d569830e12128cb2455db17d3f75214c3cf39858617cfee57a
+
+Count = 205
+Adata = 60ffcb23d6b88e485b920af81d1083f6291d06ac
+Payload = 6c9d11cfb64d96bfab61c04a25d9e19294fb7330fb4847c8
+CT = f8903086e39472294a4cbdd87d5ebb0e5cf6e1c7372649e79550998376e61e11a5a69e9f8fe1c329
+
+Count = 206
+Adata = d574632658bf456dfbb11c2653602ed0f4dae777
+Payload = 7d41688c86d5e3bc53966810f2299fdd732e3471fb0a88f9
+CT = e94c49c5d30c072ab2bb1582aaaec541bb23a686376486d6a1b0d05a7ebc657c3235479893bf7e5d
+
+Count = 207
+Adata = d896ed60128f4bb0277d3af94c5138cf91697aa9
+Payload = 8c7ae2c3c503e9072d6e04e44c2ea78fd24994503567a136
+CT = 1877c38a90da0d91cc43797614a9fd131a4406a7f909af1980c98c8959c158ce209aebcbd554f250
+
+Count = 208
+Adata = a350ed58c04473e113b9088b1fb9dad92807f6b6
+Payload = 49bc9d3bcf3c22daa8cf55c1b59d4bffddc2412d60518e98
+CT = ddb1bc729ae5c64c49e22853ed1a116315cfd3daac3f80b7573175f9105cd16ee384465ebb232200
+
+Count = 209
+Adata = 1db5887001204194e8b5dcee92c8af8fa5f7321f
+Payload = 25f3788e0d3dd8f5821faa4e45a9d6b3995fd881f927135c
+CT = b1fe59c758e43c636332d7dc1d2e8c2f51524a7635491d732b67e993384f2e7229d1838efd040d99
+
+[Alen = 21]
+
+Key = aac60835c309d837aacc635931af95702a4784c214283ebb
+Nonce = 0e20602d4dc38baa1ebf94ded5
+
+Count = 210
+Adata = 796e55fbe7bed46d025599c258964a99574c523f6a
+Payload = e8610756528f75607b83926597ef515f4b32a8386437e6d4
+CT = e0a3d5f43e688ce104f4ae1a4fcd85500aa6b8fdbcd1b8d3003c0c3b7369e79339433e1754c0937f
+
+Count = 211
+Adata = 5170836711fcb1a350b087907d8a17c7637aa1595b
+Payload = c61b0c1845fa9b2e0013b3fa9a8cb4f4fbbc6846f63ed180
+CT = ced9deba291d62af7f648f8542ae60fbba2878832ed88f87120a7f18d021833b167bf330c4858239
+
+Count = 212
+Adata = 2a68e3fe746f593c1b97cb637079c3e5ee352c107a
+Payload = 10c654c78a9e3c0628f004b061e28c39a3c23e7250f53615
+CT = 18048665e679c587578738cfb9c05836e2562eb788136812ca9698d9a88e892c364e57dd35c2f17a
+
+Count = 213
+Adata = bf38ca0e89b8f5ccd29387f7f193ab5a967caa715b
+Payload = fa3a959fdff853c39f76da626094a1ea6dbc78bd2f091a79
+CT = f2f8473db31faa42e001e61db8b675e52c286878f7ef447ef3839d6f7e20a2e343f4c4da9eb9be13
+
+Count = 214
+Adata = bee00f2f75a4415ce993d2d14a6d8e01d1d59a48f6
+Payload = 76d12e3c4c5d990bf563c60aa4999e52998d887f97477f6d
+CT = 7e13fc9e20ba608a8a14fa757cbb4a5dd81998ba4fa1216a6630bfb7a2a2441e020efdf36274b72f
+
+Count = 215
+Adata = d5b614e4e8f72a5d8b1ec2b375da5dac64c2cc30b1
+Payload = 693fae7af84aa397f0b2baaed9b3c7953f75e7424c49b634
+CT = 61fd7cd894ad5a168fc586d10191139a7ee1f78794afe833866bcee343ec5aae61f9effa19b99d3b
+
+Count = 216
+Adata = 33f11aa36d8ab0fc53486839a576b31ee915dbd769
+Payload = 56ce9a09f38127b14dbbdcaa59f363c92a3b9843ad20e2b7
+CT = 5e0c48ab9f66de3032cce0d581d1b7c66baf888675c6bcb00331b60eb252f744a06b4a95aa9f4e7c
+
+Count = 217
+Adata = f40bce1a6817b29b9e8b56f214fcca7dfde17e7ee6
+Payload = 5cd8986e974d09ede34ba68fd81d6109a64092e7fbbaf87d
+CT = 541a4accfbaaf06c9c3c9af0003fb506e7d48222235ca67a4153778a644cb2469cef3ad125e257bc
+
+Count = 218
+Adata = 53c457d8d4d4ab95ba116c28b82c16743cb09de9fe
+Payload = 9c3c610f204d98702dd91ea28e0cc14830b26bb5e2ee0349
+CT = 94feb3ad4caa61f152ae22dd562e154771267b703a085d4e7013e1c34dbc5efc7bcd4f8e52797644
+
+Count = 219
+Adata = c7acf1b17609dc336df1006ffac6497777cdfd497c
+Payload = 90c5dd9db0316dac89db18f70491bdf0a06a6a7f72b77d9a
+CT = 98070f3fdcd6942df6ac2488dcb369ffe1fe7abaaa51239d66aed667c761b7dea44822e30cff671f
+
+[Alen = 22]
+
+Key = 671544bf2988056f7f9ccd526861391a27233793a23f811f
+Nonce = 0a259148a1d081e0df381ecd0c
+
+Count = 220
+Adata = 61dafc237cb52f83ab773ba8a885462b6f77d4924611
+Payload = 576b069ae2713f53d2924c1fd68f786cb2eec68892f9e1be
+CT = ce06b3d09b02921f290544032a081a7766612940048867281bb089af0245792c16e6320cf5ffa19e
+
+Count = 221
+Adata = 87e49b8164e7052becfa0c966991637b38df833fc5f7
+Payload = d7eb0d7dd737805cd3b8dbf451aeea2fa1f6a96eb58cb428
+CT = 4e86b837ae442d10282fd3e8ad298834757946a623fd32be3cec29bd5df92363d6bb75456f5cd32b
+
+Count = 222
+Adata = d302a518d7c625756d3e4c8cc2b1d973a19107c945fc
+Payload = 77d8c9e6321314524afd05b7ad599c29f4eedda9e9f0763f
+CT = eeb57cac4b60b91eb16a0dab51defe32206132617f81f0a901ca82cddb78a2fe3904d1d8bf6fe5b2
+
+Count = 223
+Adata = 6566bb616a94bb03df5c26b722bcd38d516285c5f6c1
+Payload = abbf28b3ae164051648293d0b94e11f5af8468450005c7c0
+CT = 32d29df9d765ed1d9f159bcc45c973ee7b0b878d96744156d095ad121f0f76f07b715cad996def52
+
+Count = 224
+Adata = 141be3601e38185a9fa1596d2ee406415c9673af32f5
+Payload = b67d50110f844b36a00d352123012a1123c7c3cba959dc48
+CT = 2f10e55b76f7e67a5b9a3d3ddf86480af7482c033f285ade8529ec8f477462dc2409482c3479756d
+
+Count = 225
+Adata = a2969243b0955402ab45a430fef2ef9e0c025006732b
+Payload = 2a63f7b09b43fee65738e8115bd8419b3ef3e8f86eca707f
+CT = b30e42fae23053aaacafe00da75f2380ea7c0730f8bbf6e9b14fe8dbb3c361ea61d7b44e689a1c48
+
+Count = 226
+Adata = 87faef55c54250c30232ccaf5efa1ff41b6243b2a5bc
+Payload = 59dad755af92c29522da4348ab9b3037fe87004f5fa1394a
+CT = c0b7621fd6e16fd9d94d4b54571c522c2a08ef87c9d0bfdc54f0659fae291f943f2f3b33688602cb
+
+Count = 227
+Adata = 5d895fb949344e603ce5de029842b20d2bb614ecbbb8
+Payload = 64d8bd3c646f76dc6ce89defd40777fe17316729e22ba90f
+CT = fdb508761d1cdb90977f95f3288015e5c3be88e1745a2f993af4e3a7a20390a8da264299712a34e3
+
+Count = 228
+Adata = 74cc8da150b0bacdefa8943900b4ea047611d96be70a
+Payload = 0c3c9a634a000f00be003846eac7482e303a5bef3a70fe75
+CT = 95512f293373a24c4597305a16402a35e4b5b427ac0178e3a7f79d2b5a9bde5bd453bc8a03e971d8
+
+Count = 229
+Adata = 65f6adbaaa803dbad5ba9cb6d231314d55147cc61399
+Payload = 712c788928c8a1562bc1f3f0eb1286e15c3405f6a6fa0443
+CT = e841cdc351bb0c1ad056fbec1795e4fa88bbea3e308b82d5ffccebfb8c833833db40e98a1950fb70
+
+[Alen = 23]
+
+Key = 90e2c63b6e5394b1aeec03f95a9d13a01a7d4e9d58610786
+Nonce = dada5465eb9b7229807a39e557
+
+Count = 230
+Adata = f5629ca0eea589f6cf963d875a7d2efb656983f2dd2231
+Payload = 44dd098b1f869d670a8a841900c4bef023a1946a0c278354
+CT = 6b38ca85450e05e7b9362ed7e6e291a130ff233b5a561cdef7ec84dd992fdf98514f845dac8f656e
+
+Count = 231
+Adata = d43d7753530a7280b76221906dca85d396b6cf05125018
+Payload = cea19562328bd1fea889f575db6a28a14b7d06fb9f9c98bb
+CT = e144566c6803497e1b355fbb3d4c07f05823b1aac9ed07313613ed15d527d9dc58ab6893e723db58
+
+Count = 232
+Adata = 75650ce366757618af20205b69af7e5d4e82c398c00101
+Payload = f0641f595b791edd860977fcf699688587a354e053e9c7fe
+CT = df81dc5701f1865d35b5dd3210bf47d494fde3b105985874ef8728d1bf3a2d93db3266bafadb7c26
+
+Count = 233
+Adata = c00f1b8066677c63e898fddfb8a1b482b536963da0628d
+Payload = c7486a084f8475e6f5138e8d6e9f42a1de90f05aa88a362d
+CT = e8ada906150ced6646af244388b96df0cdce470bfefba9a7a5bce94d7564d297fe87730f1a36acf4
+
+Count = 234
+Adata = 5a89ab6b26b2ca78f98a8f8409fe8008b97ba9ef185d41
+Payload = 091ef698e16dc43a11d3ea005d5a5cdb7f1bdb5665a6c81e
+CT = 26fb3596bbe55cbaa26f40cebb7c738a6c456c0733d75794cd971b07fc14c512b8df6dd964b129d0
+
+Count = 235
+Adata = 5d24d80f22afe713c4076c200c1bab36917907fde7b6d3
+Payload = 62f204394b367c4410746001e02dfd171858396568fdd43b
+CT = 4d17c73711bee4c4a3c8cacf060bd2460b068e343e8c4bb1a192b781dc94448d4a0f6a439a716339
+
+Count = 236
+Adata = 4a47a82b999a2a739959f153a091a65c4d7387646da66b
+Payload = ac1cd5ba4997af91dbd74aee7730f9ee92cf8a360ca96a8a
+CT = 83f916b4131f3711686be0209116d6bf81913d675ad8f500cade9533b272e0a3edeba68362b057b4
+
+Count = 237
+Adata = d9fc295082e8f48569eb073ac1b9566246728fc62ccaab
+Payload = d0a249a97b5f1486721a50d4c4ab3f5d674a0e29925d5bf2
+CT = ff478aa721d78c06c1a6fa1a228d100c7414b978c42cc4785d68df8ff28345be4d83541a72071059
+
+Count = 238
+Adata = 720a9dc3e33ac080775a06f67f4a6591c37d0e101944a0
+Payload = 77fb98f24172f5d5edadbf466ee910855a71d46090b789ee
+CT = 581e5bfc1bfa6d555e11158888cf3fd4492f6331c6c61664caa7ec8892be6a18458c663665495035
+
+Count = 239
+Adata = 13cdaaa4f5721c6d7e709cc048063cfb8b9d92e6425903
+Payload = 77fb98f24172f5d5edadbf466ee910855a71d46090b789ee
+CT = 581e5bfc1bfa6d555e11158888cf3fd4492f6331c6c61664862fda880e45e891a3a50da7e14344c8
+
+[Alen = 24]
+
+Key = 13cdaaa4f5721c6d7e709cc048063cfb8b9d92e6425903e6
+Nonce = f97b532259babac5322e9d9a79
+
+Count = 240
+Adata = ad6622279832502839a82348486d42e9b38626e8f06317c4
+Payload = d7c837971b973f5f651102bf8d032e7dcd10e306739a0d6c
+CT = 4709600418f2839841e6d126359f6982bdb53acc7ff209635623d15b24184481eadc63bb8c878fc4
+
+Count = 241
+Adata = ad4833aa53218949cfd724814a43889a74a2114bbef4cf37
+Payload = 7d672bccd0fb01ce79320ed61779146aa432038daa13cb41
+CT = eda67c5fd39ebd095dc5dd4fafe55395d497da47a67bcf4e614c3e546273f0aeef207bd3f4d32fca
+
+Count = 242
+Adata = 54a723826086c7175e8fdc854b62d780de6ac1f90b57dd3a
+Payload = 0e1b73df74982f535a5fb08bc13d22515ee10969efe033bb
+CT = 9eda244c77fd93947ea8631279a165ae2e44d0a3e38837b413c6395ce9aee2e22ac0606beb140185
+
+Count = 243
+Adata = bec02d7df4cc3deefdd7e7d3ea82d381c870ad46bc06d64f
+Payload = 9a55aff269b180118ff0ea99e851c7474d19d23e641f16a9
+CT = 0a94f8616ad43cd6ab07390050cd80b83dbc0bf4687712a661e4f02150bedd86dfa49f52b214239d
+
+Count = 244
+Adata = 1b8090d712e0ec95a01bc3aeb6f5230c67c355e0ed68043a
+Payload = ff19294e8faed8353dbcab0b146e2ef928dd2680833424bd
+CT = 6fd87edd8ccb64f2194b7892acf269065878ff4a8f5c20b2f0e82b9f04bfc0cc0ba432b5135450c2
+
+Count = 245
+Adata = 5ed0b9f25d07b26717cdcb2507bef9d681ecd9389831ac15
+Payload = db1eba6ac4a79aa1d97838d263c7c4ffa7d354770e762805
+CT = 4bdfedf9c7c22666fd8feb4bdb5b8300d7768dbd021e2c0a2e64c82b60880c5c7506321a1060a481
+
+Count = 246
+Adata = 55f16fefaf2168aebc61b5e01d9e1f7bfe215eaaef118974
+Payload = 012d45168505ca9fde5aed123875639a207d473b993dc7b8
+CT = 91ec128586607658faad3e8b80e9246550d89ef19555c3b77152f64dc993b36ad9d5d12bb52b1ad5
+
+Count = 247
+Adata = 9893bf14fd3a86c418a35c5667e642d5998507e396596c50
+Payload = b205f26d6c8a8d6085ab28d595703cae046f96d82093082b
+CT = 22c4a5fe6fef31a7a15cfb4c2dec7b5174ca4f122cfb0c243e5c69256b6326ebb7ee6e677d396765
+
+Count = 248
+Adata = 244b840085bda9576c8424bb05a925a6b09cad2d0528ab8d
+Payload = 549ba26a299391538b56ce4bd71dbbfd96995836f8915ca5
+CT = c45af5f92af62d94afa11dd26f81fc02e63c81fcf4f958aa2083dac565c7a63908f0022e2867bb68
+
+Count = 249
+Adata = 9e8d492c304cf6ad59102bca0e0b23620338c15fc9ecd1e9
+Payload = 9e9dbd78a1066800ae33253be6104015158a0187e4f38116
+CT = 0e5ceaeba263d4c78ac4f6a25e8c07ea652fd84de89b851968242fe32958ea32e670ae1b3543974f
+
+[Alen = 25]
+
+Key = 90851933d4d3257137984cdb9cba2ca737322dac4dbd64bc
+Nonce = be02df3a840322df8d448c600c
+
+Count = 250
+Adata = 69a9dd9ac8be489c3a3f7f070bdaca10699171f66ab3da9351
+Payload = ba1785a149cb8b69a4e011c11a3ff06f6d7218f525ac81b5
+CT = 89ab2efefa8406336d9e2245199fbc9454f0ef650b9ed0f446c7246bd3130803bf8d703ef5bdf15c
+
+Count = 251
+Adata = 0c39a72f0f38d2713c164b0f870646fc65b9838a322ecfddd0
+Payload = 263dc4fb5cd8798ce0f183a816e51fafba167533dde1bf96
+CT = 15816fa4ef97f4d6298fb02c15455354839482a3f3d3eed7096a6a4422e582c5d02973952ac80e5f
+
+Count = 252
+Adata = 911d9f5c4c34c2f4b69be1e253d43fe729e2ab2622130394b1
+Payload = 7b5da2c283116713f3d80c7907114270964541e03ab80d50
+CT = 48e1099d305eea493aa63ffd04b10e8bafc7b670148a5c115965f6df4332fe7a2cdc4d1b80e28a34
+
+Count = 253
+Adata = 8a961df9c23f6d5ecdafa94c61164a22f460a1bf7415258d39
+Payload = 541a2b3ee25022c92fdc6783a6cbde90680ad3dc41868e5f
+CT = 67a68061511faf93e6a25407a56b926b5188244c6fb4df1e18bed174081b2170ffc6ab53b54c9ddb
+
+Count = 254
+Adata = cac7a248a4d4e96a9733627e247234995d6aa57e491498118a
+Payload = ebb2e893da9f32c363f98bc76fd14eda59e7cc620070f6d3
+CT = d80e43cc69d0bf99aa87b8436c71022160653bf22e42a792bac3d3a2b9ef6d4c8715f9a5c6fe8245
+
+Count = 255
+Adata = 41eacf70d05a6d0cdbdd38f197a52987def8fde37f332eebd9
+Payload = 199cca0d0e1c70ec405d6816cbddc69f8ada624f2c168891
+CT = 2a206152bd53fdb689235b92c87d8a64b35895df0224d9d07f9610c82fe9a7c78e8f1980e886b446
+
+Count = 256
+Adata = 78b6ed20ed85337c969618bd41917cd85c37e7c35c3a12e25f
+Payload = ca481f557306f9ce386edd0cfde375a550cb5b574be524f7
+CT = f9f4b40ac0497494f110ee88fe43395e6949acc765d775b6aab366637ec41d0bf557f578be424a8b
+
+Count = 257
+Adata = 87faef55c54250c30232ccaf5efa1ff41b6243b2a5bc93e7cf
+Payload = 6f1b4ff66d3aec7b0c0d9e202acc52722e15bca0983291e0
+CT = 5ca7e4a9de756121c573ada4296c1e8917974b30b600c0a1e57a5b3ae26469d229425f887ad5a2a1
+
+Count = 258
+Adata = 7f19ac3e53a629a2df1cb56d68fde0c80a46be40a996830e2a
+Payload = 7533c88ce55c2243b64b6c5bd01aed4dd6ac8bb9fd333e06
+CT = 468f63d35613af197f355fdfd3baa1b6ef2e7c29d3016f476ce4fe492062f74bff4c3c0e9ea849a4
+
+Count = 259
+Adata = 0516a69bfd8785ad001367b51e5410b75c11b761be08b9eea5
+Payload = 19ea09a9bfd10db2a74e398859d8f4831fa5749767773acf
+CT = 2a56a2f60c9e80e86e300a0c5a78b8782627830749456b8ead47ffc17b871f530f62b9f9aec98509
+
+[Alen = 26]
+
+Key = 5c5d02c93faa74a848e5046fc52f236049e28cd8096dcac6
+Nonce = 54cbf2889437673b8875a0f567
+
+Count = 260
+Adata = 09fc21ac4a1f43de29621cacf3ad84e055c6b220721af7ce33bb
+Payload = b4da43ebfe9396b68f4689fba8837c68d0064841c6ddd4a7
+CT = d40725397229021a18f3481e3a85f70445557bb2a85e4ae8101a34c777e918e16186fda05a386572
+
+Count = 261
+Adata = 10f0c45d06a138a964fb11b2d450620a2977bcd2952afe371cad
+Payload = 7b628930d44e22907277db057395601b82b65479fbd59613
+CT = 1bbfefe258f4b63ce5c21ae0e193eb7717e5678a9556085cc1e79234882846d916dabae40b1bd055
+
+Count = 262
+Adata = 64dbb170a037b36beed28a2637c87830e2b23f8eea6cd9a7331c
+Payload = 9db30b669fc5d25f05e0dc708d597da6ddce2dacc85ae99c
+CT = fd6e6db4137f46f392551d951f5ff6ca489d1e5fa6d977d3e35499e3c09dc384eb41344ee8be3769
+
+Count = 263
+Adata = c47de6608546a02c6eebd6628c9123f6936c0154d3df52a367e5
+Payload = 62036cbed3666d85624d3dc9c1f437454b9ab5c03ce0de92
+CT = 02de0a6c5fdcf929f5f8fc2c53f2bc29dec98633526340ddd605189608ce40b237dde7bed6fde487
+
+Count = 264
+Adata = bab7e36098d59d3a31d7784d549aebfc6938bbd0612c85c0edb7
+Payload = 5c9bc739f6b6fe4214f3c6aad307d1f208892d79de010e37
+CT = 3c46a1eb7a0c6aee8346074f41015a9e9dda1e8ab0829078c31f69c847440be20bd08cfef330002f
+
+Count = 265
+Adata = 8a9716135fa38c250e249f6712f7cb3ad9210d7278b53d599df9
+Payload = 0df109298083d3896214b84ff6edb11e9cfdbd88f5702839
+CT = 6d2c6ffb0c394725f5a179aa64eb3a7209ae8e7b9bf3b676ca83622b127fa50fc9637998c0ddd44d
+
+Count = 266
+Adata = 2d52447d1244d2ebc28650e7b05654bad35b3a68eedc7f851530
+Payload = 518f651f6d82f670b63767ad8476ed8fc24df12a45110611
+CT = 315203cde13862dc2182a648167066e3571ec2d92b92985e81e738b9e4b0dc7b7a39eb7d03adc64a
+
+Count = 267
+Adata = 3cba0fd2bb16ae1d997cbe659a2dd101885c97f2322b0172b5d6
+Payload = e91a694bea2d351928b6098660d49f382c087f6777de159c
+CT = 89c70f996697a1b5bf03c863f2d21454b95b4c94195d8bd3d298c05b1d2e597f44f8621ecd11ed16
+
+Count = 268
+Adata = c7f93152016bba584dadc6002ec493a46305726068886d2340da
+Payload = 2d14792ed349a878b2b879e7fa5f438a50e36947ce827e73
+CT = 4dc91ffc5ff33cd4250db8026859c8e6c5b05ab4a001e03c5fd5221fceecbf0dc7211a1aec06793a
+
+Count = 269
+Adata = 799cac048eaccded37ca6a70dd89595e1ee04606212da5572679
+Payload = 315b8d95938d304015bbc94ea03c21f6dc25c90f991ba680
+CT = 5186eb471f37a4ec820e08ab323aaa9a4976fafcf79838cf5c25f00b862b49fcfe8447949f39787c
+
+[Alen = 27]
+
+Key = 0234dae5bd7ae66c67ff0c1a3f1a191a0d7bceb451bc2b7d
+Nonce = 16d345606a315ad2406abbcb43
+
+Count = 270
+Adata = c37fdf7449fd7e943595d75e977089c623be0a3926e63fdbbfdf4a
+Payload = 0f960a89a7e806f8709047cb7a2e7c4211ad724692c88a05
+CT = 3907880d25f910eab12dd14e704d1b33ea7c453634d54da2a461f44dac1112ae3f9c65671a931d3e
+
+Count = 271
+Adata = 85f647d940a6d1acb6b7851912f807063515631eaabaa019dcfb99
+Payload = ab40a4baa39b0e568bf2193fecbc36b84c76bb50523b2912
+CT = 9dd1263e218a18444a4f8fbae6df51c9b7a78c20f426eeb5ed15db6e142ee07b59eb5b0ad3a59194
+
+Count = 272
+Adata = 79ae14843b2e7ccf0fd85218184f7844fbb35e934476841b056b3a
+Payload = b74c06d9077c568762796d5be14f3563e7205a6e9bc65bcb
+CT = 81dd845d856d4095a3c4fbdeeb2c52121cf16d1e3ddb9c6c203f11f66b74366caeca8dbded2bf17a
+
+Count = 273
+Adata = 542d86fd7ff591f97e6926a090553538bc3b8a6bcd45f2e29c7d9f
+Payload = f2179beb5635a6d8a8340acea0ffcf4428e5de1306a8c12b
+CT = c486196fd424b0ca69899c4baa9ca835d334e963a0b5068ced925fb9a4cf6b6bf17f72ab044653d1
+
+Count = 274
+Adata = 4392c3043287dd096b43b4a37ea7f5dc1d298b0623ccbf4fd650a4
+Payload = d1a9e4593bc3d02c407e84a1736e587c1819c72195a07d57
+CT = e73866ddb9d2c63e81c31224790d3f0de3c8f05133bdbaf0d1f677deca1bfda83c1b9223aaaedbfc
+
+Count = 275
+Adata = 966954582e78e99ba68d6ffaf794b55a82325834ec4f373b2bd227
+Payload = 15b94910853a8f23dfb8b31c0262b8461f777075cc0937e9
+CT = 2328cb94072b99311e0525990801df37e4a647056a14f04e12937871932a7ca3e1e27a90a7f73694
+
+Count = 276
+Adata = b7aca715dcc402565cb711b001f21e8e95ec54c4afab2e2dcc8a2f
+Payload = fd1681cc306518bf77766f55226afac3eb21e31ed897075c
+CT = cb870348b2740eadb6cbf9d028099db210f0d46e7e8ac0fba0464ff4ddeccbd523a5ed3b32337f7c
+
+Count = 277
+Adata = 290a36f7daeeeafca4431446b396dbec0bea0a1f6f081418811656
+Payload = 0804fa48fc76f98bb021e3501bef8875b64a3b508adf8594
+CT = 3e9578cc7e67ef99719c75d5118cef044d9b0c202cc242332f68ed5e44a71c5ba8bade07b7bf5495
+
+Count = 278
+Adata = f0739a855422310a21ed863376bce9d75dc7c687b9b535cb7a05cc
+Payload = 4f5c6d80a3955f12f4d2594e02a045c42fabb11d90817fff
+CT = 79cdef0421844900356fcfcb08c322b5d47a866d369cb8583b5dc1fbe32743e257b7c1c9d624adc8
+
+Count = 279
+Adata = ffac0edb0b62977bb5040e4128a48deaf711f5e6a84d8f677341f3
+Payload = 5c29c458212d010a0d9c5a547aba1138eb4ce94742fef01e
+CT = 6ab846dca33c1718cc21ccd170d97649109dde37e4e337b9e53b654de1976294897cae0476ac6248
+
+[Alen = 28]
+
+Key = 6351a67fd6daabd2fd49ee944dd41dd37301f958dd17fcc3
+Nonce = b8d517b033754058128d13d11a
+
+Count = 280
+Adata = 511c6924fa96db716f6b053b7a48aebdc1504145a56cd02d6be2590d
+Payload = 0c0663dd69ccbffbbd0c8c2e9473d0354451ae7a20fa3695
+CT = 19f2745df5007619c79c84d174e4521b942776478a0601d982c560fede4741e2fd3b54b3a48f3e38
+
+Count = 281
+Adata = d9ccd93317441e9d6ccc358f31e7e2ccef8c921b23d742993eff9d53
+Payload = 34a882834172924d39d2df5d637d9d273a99a9222971701c
+CT = 215c9503ddbe5baf4342d7a283ea1f09eaef711f838d4750ee82d927a2aa678e792acdeb615409f8
+
+Count = 282
+Adata = c268d65f7a7b30d3d198b2045fc8d1db7adda56604fa567d8855d1a5
+Payload = 5b7450b73d68de079e92bba56c7860f11126b8fdedd3334d
+CT = 4e804737a1a417e5e402b35a8cefe2dfc15060c0472f04017a48226389d24ed3ec3da2da1a9bdf7c
+
+Count = 283
+Adata = 4c2b6815156f0643b4573825e28b9f2a668a4976e3342884f48bc310
+Payload = 140c6933248f052e05bd4a36aec185ee86730108cc2989b6
+CT = 01f87eb3b843cccc7f2d42c94e5607c05605d93566d5befa16fe6bd83993ccbdd50e1ca061f4845f
+
+Count = 284
+Adata = f11c873354b3c0cff2c8f8010e9e364582b9c05c62efdefbdcc2e1c0
+Payload = 2a083de317380d94dd991349a7b8761c7c98013b1b0227e0
+CT = 3ffc2a638bf4c476a7091bb6472ff432aceed906b1fe10ac577c5893cb3896400012e48f5b190b73
+
+Count = 285
+Adata = d0a056754098d7f7ef2f639d61ea3d2b9cc936c48a1b2c5a9e96d169
+Payload = 02769283d5a06c363c2cc66c09b1ac954134e3ec7df773f2
+CT = 17828503496ca5d446bcce93e9262ebb91423bd1d70b44be80c80101fdfe6dc4cfce080bf921582e
+
+Count = 286
+Adata = 56de0e55653b9a04a3ded71c31f8807c3c8dd96bc82892e4acccef30
+Payload = 4890404bc5b24822b4cf7a2fe28abc52fbefb919ae0629ec
+CT = 5d6457cb597e81c0ce5f72d0021d3e7c2b99612404fa1ea0122dfc20e3088dcd33b6706a0c1fdfa8
+
+Count = 287
+Adata = 794a86f5b20d344ad86fd5523d08f1864737be57731440c29aa6b425
+Payload = 161f8501f59338f72026815c77cad6d8d581859192cd5644
+CT = 03eb9281695ff1155ab689a3975d54f605f75dac3831610828f0a78ce798448529afe26eec875aa6
+
+Count = 288
+Adata = b1eafc03ea2fa3e9e3842a09a225e83055de8a1f412badd6fc9ead12
+Payload = b3f38aedbf08dd7ead9d402c5aaa1ec9279c7e4bfd4a2967
+CT = a6079d6d23c4149cd70d48d3ba3d9ce7f7eaa67657b61e2ba48856a266c0d404474316f418f8f4e4
+
+Count = 289
+Adata = 8fec99f1be0e69267620c0b934bf984d60c1437f74c6ac19610fe188
+Payload = 5c09e2a6a055fe9c21e06e5519cf56b8e2e7fb44094e79f9
+CT = 49fdf5263c99377e5b7066aaf958d49632912379a3b24eb56412292d8015285efaa6f1154580eb57
+
+[Alen = 29]
+
+Key = 9a5a9560baed3b8e0e90b92655d4e5f33889e5d7253d9f6c
+Nonce = c0049382cdd8646756d4e6bff5
+
+Count = 290
+Adata = c95a86d52088a8b0107cc5b437a8938b2c9e74e46e2e03bb9bceecdbe3
+Payload = 5bbe9c1fb2563e3e82999fe097b28da4dc6ff2e020f3b4f3
+CT = 6d5401db42b5c48b79203b6ad82806d7460ac4c82ad0809b811020480e834f6fe55900a162a4e61a
+
+Count = 291
+Adata = 1dd56442fa09a42890b1b4274b950770ea8beea2e048193dfa755a5943
+Payload = 8a85a9b32a323c6af156a3fa2f1448b6387cc3660aa8a0f4
+CT = bc6f3477dad1c6df0aef0770608ec3c5a219f54e008b949cba9827513c7f1de970d316b6f81c109d
+
+Count = 292
+Adata = c834096e059ea73ddc90b0c982f9a3a31bfc6b1b81a03f9d41c9c741e7
+Payload = 1e02c13104937fe084b18eba1ea8951dcc5e75b692937dea
+CT = 28e85cf5f47085557f082a3051321e6e563b439e98b04982c9d79dd3255a8323f8229ac1c6d76ae4
+
+Count = 293
+Adata = 9249022bdead3d86ef5bd03acf053132d08663ba1f2426e19c126b22e9
+Payload = 3225570fb15ae13a13c71e364ae9a9fef03d1c9a7fa5dfa0
+CT = 04cfcacb41b91b8fe87ebabc0573228d6a582ab27586ebc8425dc81f93257ae8399fc2d48b4a7685
+
+Count = 294
+Adata = 3c3a92c4ece49fb9f84243d7c1bc91f595fce118305a758c83985c34b4
+Payload = fa0a458174537ddba25708b8d0c22d5517d57b122517b0c9
+CT = cce0d84584b0876e59eeac329f58a6268db04d3a2f3484a1b595003c58e69600c2a3b9ec45c0e15a
+
+Count = 295
+Adata = b49b845ccf76acf508f9db8543c73375d530d91f3b0e4ed70decfd2c2d
+Payload = b7fbdaeaa3ee1d0bbf5ec47898b069ec4ba6a140a3e83996
+CT = 8111472e530de7be44e760f2d72ae29fd1c39768a9cb0dfe0da009261c43c6640303696655e2981f
+
+Count = 296
+Adata = 3aabdf589eeb1709bb3d60b08bc71eaa3ffeba4e2903a5dbd8339aae85
+Payload = 9aea86b9fbd9bd4504ee2e25054942b33d3cdbd84215db7e
+CT = ac001b7d0b3a47f0ff578aaf4ad3c9c0a759edf04836ef16dfdcdbd4ad711c493d3176f032a02af0
+
+Count = 297
+Adata = 6a79879cd62bd1dbf9609897d2ebf2dc4dda43cc15fcb241aaa0deb4b3
+Payload = 3a861638ccd6591e51e2a525be59447e4a28bab32e36a5f3
+CT = 0c6c8bfc3c35a3abaa5b01aff1c3cf0dd04d8c9b2415919bfd59b45c05873c670f5f8bb47732d59f
+
+Count = 298
+Adata = c5b6ca474eb251817ae4d2f47c0632c381e222aae3b6f585a0dcae120a
+Payload = c7da4e9ba6e5758be726e6e227d7bddb0332228f7e3ecb6b
+CT = f130d35f56068f3e1c9f4268684d36a8995714a7741dff031572a24bc00b40a6b4b172b3648142e7
+
+Count = 299
+Adata = 64a96d191f1d5f95f5fed6259e33e7206adc07b0279e16cb453a9c6438
+Payload = 2b9347d3e195152dce22afdb92acd179eb484872285704c3
+CT = 1d79da171176ef98359b0b51dd365a0a712d7e5a227430ab828bc33396179ac39ce0027a1d62e0fe
+
+[Alen = 30]
+
+Key = 3e61094c80df0053e86d43fccf4e1d3ee2cdb862d3237b0a
+Nonce = 63f00b2488809fdc49ca5f05d5
+
+Count = 300
+Adata = a08763ca936abdeece06467bef8c3c47c3a473636a039d4db540c867d3e3
+Payload = 1fada8f4c7daea0d1c370184c169485b80a278708ed41451
+CT = 680dd22f16a1290bde42c9792dfa997aed24d5bd2265b6e095aa6b99d3f894d3790c2aa2dae1ba2c
+
+Count = 301
+Adata = 19508a6c83b992c660a1a28597e07c729ea2ed39401aadbf9d7586b5720d
+Payload = e9f1f2cf0b8d563e2d20f39f9f464a808b136dba364a6446
+CT = 9e518814daf69538ef553b6273d59ba1e695c0779afbc6f72d9d77109f4597e9c4c8cf7023dc5f3b
+
+Count = 302
+Adata = e5929c3b5d68a4c9fcf1168ea35bf8c0bf3043cb1ed54ff301578b3b7266
+Payload = 07a74c3b874849ecbf013713b80a84337c90b690cea0b837
+CT = 700736e056338aea7d74ffee5499551211161b5d62111a86b2544ecc3c7d5accd22ac075e7b44d5a
+
+Count = 303
+Adata = caa5cc5d0d87680eafc29429bac55c9e33167d485789c7c124b5c57a1ba8
+Payload = 4255f2cf90f0d15e9bead4be799165c57f7225980713d609
+CT = 35f58814418b1258599f1c439502b4e412f48855aba274b8f1a8a1db25de0fab7cabb11a18497584
+
+Count = 304
+Adata = f61cf7ae23a66777bd3fabc3d542feed2b00c6d4f46a772fda11b5214551
+Payload = 70b1e2e4cf260b108f5a52d0d8234838ffd6ffe7b4acd78d
+CT = 0711983f1e5dc8164d2f9a2d34b099199250522a181d753c5a9718ed0257a50e38de86154054fc3a
+
+Count = 305
+Adata = 85f647d940a6d1acb6b7851912f807063515631eaabaa019dcfb993e86f4
+Payload = af4be10b3a59ea99dadc75fbe5651f6f7630852bb556aa39
+CT = d8eb9bd0eb22299f18a9bd0609f6ce4e1bb628e619e70888550d1acca34c28ba8a3b890bb0542b23
+
+Count = 306
+Adata = 296cd04c4d9ab493def7aeb6841a45309e777028868efe45166235c56b2d
+Payload = 72d5663727592f1bfc9c65be83f4d3508126fecc4e34ae72
+CT = 05751cecf622ec1d3ee9ad436f670271eca05301e2850cc3a268dc1596a7855639c63fa76ad8479b
+
+Count = 307
+Adata = f380ca0a26a94adcf2c1ce26d226d3bf520268c72412e58a71acd9a66d00
+Payload = 3e2ccce03c10ce1527ef8e002adb265edba5779fbd4fcaf6
+CT = 498cb63bed6b0d13e59a46fdc648f77fb623da5211fe6847e3416c75fc28924a21cc123e62a7894c
+
+Count = 308
+Adata = 8825532a31680cb3b5bdb027802d2d8718755e135367e0c8c88e21288311
+Payload = a18dfe7f2d7bbaf316366f67445170afcbe18e2a1de1e947
+CT = d62d84a4fc0079f5d443a79aa8c2a18ea66723e7b1504bf6ff1a47f23d08485951aab18b393584ef
+
+Count = 309
+Adata = f768375589b687fb17c56673af4263626da69eb991007d94d4f5a163fd05
+Payload = 17ca72a440c944fefd6c08ecc3a8ecb54d96b9cad9d2aa4c
+CT = 606a087f91b287f83f19c0112f3b3d9420101407756308fd7d024456bcb69a4f77008773a3f48805
+
+[Alen = 31]
+
+Key = b5664dd6ed435df006052f6ded74bb7ce9482ca9229886f7
+Nonce = 7a1649896f3e030c18f0205599
+
+Count = 310
+Adata = c5f1a26351e53e6509c8bbbed03c42c23ad81c65fccec7ffa1cb494c7f1fc4
+Payload = 0b6de49b530703affc94010c2b793ddc6de0c44d48037ff2
+CT = 56b02fea595cc24e798691ae905be3d466ca68ca744005dba260b5ea3b047020b73b5bafa17e5084
+
+Count = 311
+Adata = 89899be18b4c389afa769b11ecd22e9fad8f38fd614ea5f8eb7a066c0ed8d8
+Payload = 2f1821aa57e5278ffd33c17d46615b77363149dbc9847041
+CT = 72c5eadb5dbee66e782151dffd43857f3d1be55cf5c70a685e4bd97b9dc83134867c00c2acea0aaf
+
+Count = 312
+Adata = d43b841f174335f1347834590b0984a2cb35f7a00a0ee993157d2d4f848748
+Payload = c7da4e95cb38342c6d5bf0c381d5a192adc3bfc1cda3a1d7
+CT = 9a0785e4c163f5cde84960613af77f9aa6e91346f1e0dbfe55202ba34bb9918fe915776de65947c0
+
+Count = 313
+Adata = c1093518efd80245e3c42371f220b21f2034e6738fe02ef43e828190f01aef
+Payload = 414a70aba5a219dbd41cdc46b84812b28cc4f7399218004d
+CT = 1c97bbdaaff9d83a510e4ce4036accba87ee5bbeae5b7a642fdf807b5a6880f2d4c36d558b40eb90
+
+Count = 314
+Adata = 90f627d5b939625bc76fe1bd4643b39edc11d3dc7f4bfe16e61bc26c3d49d8
+Payload = 58b260d3f645a35bad7a3842440bc03608248bd46e725e60
+CT = 056faba2fc1e62ba2868a8e0ff291e3e030e2753523124495a9307ca4239380a45bb7f87e41c4cf7
+
+Count = 315
+Adata = 2f360a4715074e942244ab7f9b6db127b0442df9af2efa2e78db1a94312905
+Payload = 5505caa97218957e90247fde60275bdafce4b16bcb36c263
+CT = 08d801d87843549f1536ef7cdb0585d2f7ce1decf775b84af3aeadff9dd60468aef2a8e2c56dda7d
+
+Count = 316
+Adata = 7db564811f14bc5c2098d5635655c3671fbd8288ea14944af925eaec653408
+Payload = b93e40f556a786e39126b8834a6ecacd2dc9f0f528bab135
+CT = e4e38b845cfc470214342821f14c14c526e35c7214f9cb1c8335f2e31a0468b830c5009cd02dbd5f
+
+Count = 317
+Adata = 36be91854d3d02a5d62503bb9047ef4354280510f7576c4272fd757240b621
+Payload = 543a070fdb3a855dd7d83fbc5f983671ad9e905f307148e4
+CT = 09e7cc7ed16144bc52caaf1ee4bae879a6b43cd80c3232cd5d772a599e91504e022b9dbfb124b71a
+
+Count = 318
+Adata = 6aa6ea668df60b0db85592d0a819c9df9e1099916272aafb8813ccc2f2dd96
+Payload = 86ef67572cb339c6706eb5909b96848aba5246a196972a1e
+CT = db32ac2626e8f827f57c253220b45a82b178ea26aad450379846cd12430f7adc910d1f0c51d80636
+
+Count = 319
+Adata = 3a64414c3588d7c26871d7d054ac6c8420d4917e3baad4a343685916265321
+Payload = cecef24b62676a5623bedae8087b9b05d7e22b41a14dd2d5
+CT = 9313393a683cabb7a6ac4a4ab359450ddcc887c69d0ea8fcd9ee65ac3a8fae1b00a4f1dfe2577293
+
+[Alen = 32]
+
+Key = 50925853a84a33ff392154e4e737efc18dcfc98f4d5235a9
+Nonce = 809343e986f6ff47f54d4cac22
+
+Count = 320
+Adata = d70aef3532bdc5293a3ebb11589ac1f801c9f93ea0d656e1d04068facf9f768b
+Payload = 718f061e8b972a3adcf465d66c5b28e8661f080127f6722f
+CT = bad3b0e6772e9c4c9c631c095e259d99692292932efb72b8966e91a19617bb748f3495aa433585bb
+
+Count = 321
+Adata = 1ee0eb409398bc252175cb460ef9a2da4c9beab2ef6d8206e4fcce74df785246
+Payload = 72e6cebdaf88205c4e74428664bc0d7eb4687a272217b7ca
+CT = b9ba78455331962a0ee33b5956c2b80fbb55e0b52b1ab75dc8f70aa565a12ca3545e68110968040f
+
+Count = 322
+Adata = 3820db475c7cb04a0f74d8e449f026ec951fa59667738698b0ed5c8cb09a8c96
+Payload = d959dd38a458039e2400d21d27b9a2faee8fe23683330cb5
+CT = 12056bc058e1b5e86497abc215c7178be1b278a48a3e0c22daf38076c810e14a7843444a02f010e0
+
+Count = 323
+Adata = f555216840a1f40b411d44128e567617e2694caf16216ea74c604a8d6ec01e72
+Payload = 337f12e8ebc0544b82fcdd3c4a0dab0e5e75c9f433a27d66
+CT = f823a4101779e23dc26ba4e378731e7f514853663aaf7df1594aebf9b8318877bdec2900a22df858
+
+Count = 324
+Adata = 2311a6fe1feeda3a1f16310d635496c0dd662024f0b0f1de79325e030cb850e5
+Payload = 463c65fa7becae5605af80d1feca59075ee88c0abfc72cb4
+CT = 8d60d302875518204538f90eccb4ec7651d51698b6ca2c231d9872d1c10a6594b5c349b84f710d64
+
+Count = 325
+Adata = b2c633e3181ae5fe7828707ed5b70e0460088a84465eadeecdbcfa0e9ff19bb1
+Payload = 23c1732959c4bf85bc707e45cc964b6227acd3a8fc73e675
+CT = e89dc5d1a57d09f3fce7079afee8fe132891493af57ee6e2a9db7c4bcaf6087e158c1a5d4eb1c2cc
+
+Count = 326
+Adata = 791f23252094b9b99fafe7fac1d8ff3ba09305c476041e75afb245ac438b4069
+Payload = 02f60f967e7fbcf957313619882407ea8a03fc943062296c
+CT = c9aab96e82c60a8f17a64fc6ba5ab29b853e6606396f29fb5e1c87d9e1c1f3b7d30fdc2f0ccac783
+
+Count = 327
+Adata = 22197f9ad14591e7a6d5f8b18c969a553de9a85309757fa5d319cc505c24f438
+Payload = 6c1aa088d1a6086d0e72636744a6840c80ab8223409c61b7
+CT = a74616702d1fbe1b4ee51ab876d8317d8f9618b1499161201514b449a741e07f9287f7e9090fa54b
+
+Count = 328
+Adata = 0bb18f7280a30767cd769cb5ffd3edd1c18914b92d1b2192e27ac88f57135616
+Payload = 57275bc3b4d63b9b01b0b0760235c9785d45761cace23f1e
+CT = 9c7bed3b486f8ded4127c9a9304b7c095278ec8ea5ef3f892c889b610157e16e9f31558c669298a7
+
+Count = 329
+Adata = 3e5f0f32e27be18ca6f84de11e6e9c25fc0c4cb0cf83633eea1f033aa1373f3c
+Payload = eba27a27f0d4604a5296a41b3fe995c50c66bcba302d0447
+CT = 20feccdf0c6dd63c1201ddc40d9720b4035b2628392004d0fbe19321dc22c748a17aa5eda29d8cf3
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VADT256.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VADT256.rsp
new file mode 100644
index 0000000000..af4f5c1df7
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VADT256.rsp
@@ -0,0 +1,1823 @@
+# CAVS 11.0
+# "CCM-VADT" information
+# AES Keylen: 256
+# Generated on Tue Mar 15 08:09:25 2011
+
+Plen = 24
+Nlen = 13
+Tlen = 16
+
+[Alen = 0]
+
+Key = 26511fb51fcfa75cb4b44da75a6e5a0eb8d9c8f3b906f886df3ba3e6da3a1389
+Nonce = 72a60f345a1978fb40f28a2fa4
+
+Count = 0
+Adata = 00
+Payload = 30d56ff2a25b83fee791110fcaea48e41db7c7f098a81000
+CT = 55f068c0bbba8b598013dd1841fd740fda2902322148ab5e935753e601b79db4ae730b6ae3500731
+
+Count = 1
+Adata = 00
+Payload = e44b4307234281209bd41f89dbe2cc3fbf68e14df2f7fce4
+CT = 816e44353aa38987fc56d39e50f5f0d478f6248f4b1747ba003abc6a4b020625adc8b6cd7bafbd42
+
+Count = 2
+Adata = 00
+Payload = 8db7a73856bcb4007346bb3e00096f69e75e97c0bb960f3b
+CT = e892a00a4f5dbca714c477298b1e538220c052020276b465e7cfa7a208a8b3e6b6377236045df17d
+
+Count = 3
+Adata = 00
+Payload = 48f3ceda4fd390a7eb38f7f5bcd14310af6b5a557e676d44
+CT = 2dd6c9e8563298008cba3be237c67ffb68f59f97c787d61a81b39a0c55822e32042b4f8981021090
+
+Count = 4
+Adata = 00
+Payload = 7cdb2c9b167b3ae811289acf7dc1814bbe241f553447699f
+CT = 19fe2ba90f9a324f76aa56d8f6d6bda079bada978da7d2c1091117e2ad77db510d902038743b5a98
+
+Count = 5
+Adata = 00
+Payload = 41eacf70d05a6d0cdbdd38f197a52987def8fde37f332eeb
+CT = 24cfc842c9bb65abbc5ff4e61cb2156c19663821c6d395b5ac7379b8e51592b98e4874f4592278a8
+
+Count = 6
+Adata = 00
+Payload = bde9e3eb9f0c57302c9185b1cb912ef76d88f2f9c3b51e9a
+CT = d8cce4d986ed5f974b1349a64086121caa16373b7a55a5c4d08c1c902c4c2f078452dd6943b85028
+
+Count = 7
+Adata = 00
+Payload = 6f9ccc033c6bfbdfad4719ad033c927e2175727a9a021dc6
+CT = 0ab9cb31258af378cac5d5ba882bae95e6ebb7b823e2a69832fefb87445f1ca42811899acc0cdf68
+
+Count = 8
+Adata = 00
+Payload = cc67bc3b7afd625b2610226d3b30e111e6aa47a3254f711a
+CT = a942bb09631c6afc4192ee7ab027ddfa213482619cafca4481d605a1019c8e9778b8928b4636053e
+
+Count = 9
+Adata = 00
+Payload = a10c81725f49ab9075fbf4d96be030a2d881d8501b115d61
+CT = c429864046a8a337127938cee0f70c491f1f1d92a2f1e63f96a82e8411e5b04426dc608298c6408d
+
+[Alen = 1]
+
+Key = a4490ed6ab51dbfccd6f3702a857575dad44da3a27eaf31178abc97da60d1e4b
+Nonce = 26ceaf6e3b28190a17c4f0c378
+
+Count = 10
+Adata = 9e
+Payload = 1b5cc6b1651dec4bbbf5130343852e971c7ff1774100d9be
+CT = 789bce069a725a96c484e64a9e54dcb7a7c268c85df47815a462ff2dd8ba44a381e1f6edab12b5a9
+
+Count = 11
+Adata = 4e
+Payload = e7ab98901c0cb1d7d76e125d8ac8e86edf6f469fa937bc10
+CT = 846c9027e363070aa81fe71457191a4e64d2df20b5c31dbb6b0789c5866b7e3312ad992e228d6d20
+
+Count = 12
+Adata = cc
+Payload = 53bc7e3648d0b389b887b065e9e8f79685beb2eb36e2eb95
+CT = 307b7681b7bf0554c7f6452c343905b63e032b542a164a3e39b1b1a480fdd268c1c75b131cde798b
+
+Count = 13
+Adata = 45
+Payload = 6d7262476da95db63b322c5193ea05030923c3cbf0f8e8b1
+CT = 0eb56af092c6eb6b4443d9184e3bf723b29e5a74ec0c491a32060fea35c3e9528fd18994fae9fce8
+
+Count = 14
+Adata = 2c
+Payload = 8246bf7b81b287411777df7ecb53a1795e54b150ff3dd584
+CT = e181b7cc7edd319c68062a3716825359e5e928efe3c9742fb4e0a604ab30a764e8c98a9cafbca8d4
+
+Count = 15
+Adata = a9
+Payload = 2596ca8772bc69b50bcbf33088c6efbab614b691ed836f92
+CT = 4651c2308dd3df6874ba067955171d9a0da92f2ef177ce397ca72f1acf6dfd078b6f4eb82fa01e9b
+
+Count = 16
+Adata = 85
+Payload = 703065d701f4fcadee20d64300b3082c0c76490eb2dc4ba7
+CT = 13f76d60fe9b4a709151230add62fa0cb7cbd0b1ae28ea0c2a85c9252ee62612dc29cffa7289b2ca
+
+Count = 17
+Adata = dc
+Payload = a1aeda4b4cb8dd2943675181561bac48ba07e8de5b327837
+CT = c269d2fcb3d76bf43c16a4c88bca5e6801ba716147c6d99c9fbdac729413152c089d3939e30b8602
+
+Count = 18
+Adata = ce
+Payload = aa17341f4cead054d41c171dd34c459f7052da225c6c365d
+CT = c9d03ca8b3856689ab6de2540e9db7bfcbef439d409897f6f86266c273f8184e901b50c04845b8ab
+
+Count = 19
+Adata = a6
+Payload = 448cdd9cbbf863eb666fda36b825f3798827da3c1349611f
+CT = 274bd52b4497d536191e2f7f65f40159339a43830fbdc0b4ddd02d5c9ae2bbac47a7a076edb1d207
+
+[Alen = 2]
+
+Key = df594db94ef8eca56a417afe946085eaed444c7cc648d07d58132e6cb5bc2bc3
+Nonce = c1ad812bf2bbb2cdaee4636ee7
+
+Count = 20
+Adata = c0c3
+Payload = f4d7978fad36223623ccb5bb18a7373cba8a6e3b1c921259
+CT = bea778540a90033b2c0d087e3cc447711ea25f7eea96855506ec97f23bd6ea97834f92f7263c3195
+
+Count = 21
+Adata = 34b9
+Payload = f6c043c70136585d012ae0df6f42b25584e374649d0116c5
+CT = bcb0ac1ca69079500eeb5d1a4b21c21820cb45216b0581c9f3230df0b52b5cb7ac907dcadcb662ca
+
+Count = 22
+Adata = d4ab
+Payload = dec0c896b04490816409da1783478ef2510231d0a28c5b39
+CT = 94b0274d17e2b18c6bc867d2a724febff52a00955488cc35a99c3165ce83102891ef3885088ed6eb
+
+Count = 23
+Adata = 2a3a
+Payload = cbfd94fc31785d30214271dab2264134805fee6e52aa0b5c
+CT = 818d7b2796de7c3d2e83cc1f964531792477df2ba4ae9c50c9d8078607994ae5dff0de6526fb53d1
+
+Count = 24
+Adata = 4eb1
+Payload = 134d2d9726400d09dd3521326f96fbef993ddc0c40887700
+CT = 593dc24c81e62c04d2f49cf74bf58ba23d15ed49b68ce00c7e84da7d2564533e7ad55390ec3a6ff9
+
+Count = 25
+Adata = 0a79
+Payload = 1ccdcf789d42caba80d7893feaf26d3853fbcaf7d964df0b
+CT = 56bd20a33ae4ebb78f1634face911d75f7d3fbb22f604807520849295a56191367a696999ffef8e9
+
+Count = 26
+Adata = 865f
+Payload = 4042dbe148db3e6dc542b25d57a5787af535d38e8c34c71b
+CT = 0a32343aef7d1f60ca830f9873c60837511de2cb7a305017bc4aceed1a10309b6402b9e9420b33a3
+
+Count = 27
+Adata = f4ae
+Payload = 85b6894fec36294aa934cdc3523fd95c90ad56cbd18545dd
+CT = cfc666944b900847a6f57006765ca9113485678e2781d2d176c180d2e299ccf0b8781ba6de8a72ce
+
+Count = 28
+Adata = 10bf
+Payload = 0f27f4fc8538a676a763b3e5db845a1bfb20d5fab340dee3
+CT = 45571b27229e877ba8a20e20ffe72a565f08e4bf454449ef98d91c68d94873a5d6557611a5402a0a
+
+Count = 29
+Adata = b92e
+Payload = 1b5ec0cb03810a12fc6a0a1ff565afb001405d2a45a1f18a
+CT = 512e2f10a4272b1ff3abb7dad106dffda5686c6fb3a566865321cedf1122354636e130acbd69718b
+
+[Alen = 3]
+
+Key = d98193ab2a465e3fcd85651aaeca18b8e91489b73b7c7e93b518c4b5b81fc6ac
+Nonce = 2247dc7e2674e9e0a63fe70613
+
+Count = 30
+Adata = 4dc2f4
+Payload = edba7d6312144e90ec9eaace7576045a46e553dcb8ee5a98
+CT = 44b9ea727c847336fd739ad11f4b906b292edb810462f06ef59626ad5cdac2e4d4cb07b538a1fd8f
+
+Count = 31
+Adata = 2f3bf0
+Payload = 52a9626f5279c11e17e96f5dc5e1c1f58c1e913020d8499b
+CT = fbaaf57e3ce9fcb806045f42afdc55c4e3d5196d9c54e36ded0d53402253453e494ad350994ca77a
+
+Count = 32
+Adata = 95d2cf
+Payload = 87b6447d97a74d0b315031078aa06fffc7b9f246bfa5f147
+CT = 2eb5d36cf93770ad20bd0118e09dfbcea8727a1b03295bb196dbc3bff865a1d94b164df23d708e8e
+
+Count = 33
+Adata = 0caba9
+Payload = 1852848046706f2e274ba381a2bee1422df4f61d93219af7
+CT = b151139128e0528836a6939ec8837573423f7e402fad3001791b4469fe50d45f8efb81217cd68580
+
+Count = 34
+Adata = f8d459
+Payload = 99aac82fa66a15e4f76b76cf4590150999d5cf8468df7f42
+CT = 30a95f3ec8fa2842e68646d02fad8138f61e47d9d453d5b4587106da25012f92f01cc2db8d11ac29
+
+Count = 35
+Adata = e883dd
+Payload = 4e2f0f91990b855a00d27fbb2e8db7184cd82909de361b52
+CT = e72c9880f79bb8fc113f4fa444b023292313a15462bab1a464148536847290e4fdda7966fe6d5e3b
+
+Count = 36
+Adata = e45da4
+Payload = e558be3fd246170b294d18ffa708842242681890baf8bed9
+CT = 4c5b292ebcd62aad38a028e0cd3510132da390cd0674142fcc4cb33472825363940e2b26424b7802
+
+Count = 37
+Adata = 3b6fc8
+Payload = f8b284c2d851289275973fcd807fac5d8e5e3b6a75ba2ace
+CT = 51b113d3b6c11534647a0fd2ea42386ce195b337c9368038a99dd8dbe89b3ecf663eda1b0f92be7f
+
+Count = 38
+Adata = 043d68
+Payload = 8edf1eb90f0ad33be8a7c6446899e06addc10b3badc4ea25
+CT = 27dc89a8619aee9df94af65b02a4745bb20a8366114840d3dc4894c8fa0a1e1aa760acf9360042f5
+
+Count = 39
+Adata = e89257
+Payload = 8fe9a6bd82462c97f436d382d1ff971c95406b1a6c847d81
+CT = 26ea31acecd61131e5dbe39dbbc2032dfa8be347d008d777cdad1590fd8bf2d7ea919e60d0316566
+
+[Alen = 4]
+
+Key = 45c8afd7373cb0f6b092af3a633d9fd97c4ca378e19d75f9b74d089429726c29
+Nonce = fdb1fa230ae0b172ff98fc7496
+
+Count = 40
+Adata = 270981af
+Payload = 0b92adbb251dc29a67f0bb97f8e7160862b6c4e843d07fd9
+CT = 274e2faea3271ea6fa0494c1951f115b5491a893056c3ee4c76fc350e585277e373e9119bf9595cb
+
+Count = 41
+Adata = 633f3efa
+Payload = 1f88dfd4f5c52c22b1db47f9f4fb6e2f8bcd78d593061369
+CT = 33545dc173fff01e2c2f68af9903697cbdea14aed5ba52540fa7e55dc54e80488a05ee7f1fc96e9d
+
+Count = 42
+Adata = aad86fb5
+Payload = b2b4cb5e90ebf4bd265093b7f5efd4d62dc60e29737aa496
+CT = 9e68494b16d12881bba4bce19817d3851be1625235c6e5ab18151c17d9e3f97244000a3b2d3c2f95
+
+Count = 43
+Adata = ed42941a
+Payload = f312b47d05f8eb5a29943b41347cb1983c75cb7a458a3868
+CT = dfce366883c23766b46014175984b6cb0a52a7010336795562d521c4b5c7a6f2c5ac65f2fd15b066
+
+Count = 44
+Adata = e5b085d8
+Payload = e9fb86938ea7f04cc230296859e7c96fcc352f968c9473e4
+CT = c5270486089d2c705fc4063e341fce3cfa1243edca2832d9e491a31218f688744098851672a09a64
+
+Count = 45
+Adata = 3776f37f
+Payload = 8af6b7540f997954812e38dbd99ccfaedd5c69963c353a4e
+CT = a62a354189a3a5681cda178db464c8fdeb7b05ed7a897b730ece28347d7ebf8291d7eb66b7651b4e
+
+Count = 46
+Adata = 4eb08c9e
+Payload = b90cfd9dd58e320d98510483b1d939bdb5f3b81666ecee59
+CT = 95d07f8853b4ee3105a52bd5dc213eee83d4d46d2050af64cbd25fb40480d15c039878b5d2f25afb
+
+Count = 47
+Adata = c7f93152
+Payload = 02caabc6ed0641681e7148c10cf3159fe35e44013252071e
+CT = 2e1629d36b3c9d5483856797610b12ccd579287a74ee4623fbfd98c8567b78d4b9c3a49a4641908e
+
+Count = 48
+Adata = 57957630
+Payload = 2f29882fdf1418d04f0b9d44272995a56973c4369c687a99
+CT = 03f50a3a592ec4ecd2ffb2124ad192f65f54a84ddad43ba4655c1abcb3ed1a175f12721a407c5d00
+
+Count = 49
+Adata = 19da955d
+Payload = 4e427130be9e94639320529ec135715e65da1117b5ba3c76
+CT = 629ef32538a4485f0ed47dc8accd760d53fd7d6cf3067d4b90621a5e5683df421a0dc52341485d1b
+
+[Alen = 5]
+
+Key = a2e6bf39efd1ceddc92b4333ed92d65efeea6c031ca345adb93a7770a8039bcd
+Nonce = 693cbb46bc8366086ec7cd7776
+
+Count = 50
+Adata = 3ba11282d6
+Payload = d822f84b023f12ea9e3ce16b904278e4aaab5e11c2c23f3f
+CT = 9f91fd2f6472e33b02b1eabb9d6655729d44c44dad6b3883fe0667bcc5806b225224b04ade8b21c1
+
+Count = 51
+Adata = 3f3a4718ea
+Payload = af87b347b59e37a424004a00907dcbcf6a554e6782a9be12
+CT = e834b623d3d3c675b88d41d09d59e6595dbad43bed00b9aea6750fffa5a487540ce65770cd836e99
+
+Count = 52
+Adata = ff79ca8965
+Payload = 82b7cd168b6a82cb2d837f41ceda0c27adc5f5b28030454b
+CT = c504c872ed27731ab10e7491c3fe21b19a2a6feeef9942f7e7cfafe32bd71ea9813607c5df446c9d
+
+Count = 53
+Adata = 0021be18ed
+Payload = 1c1a0f144df76781e7c85ab178ed9b1ce8c6dc3f15c59149
+CT = 5ba90a702bba96507b45516175c9b68adf2946637a6c96f576716fe674c33ad3b9d3e54cc86bfccf
+
+Count = 54
+Adata = 9ae7996547
+Payload = d9bb71ad90152d5c1af358c8501fa89ebd4b17bf4ff43841
+CT = 9e0874c9f658dc8d867e53185d3b85088aa48de3205d3ffdab55dbee34f1bab555bbb196095fb5fd
+
+Count = 55
+Adata = fa292d1958
+Payload = fc7d028a1aa05c74b7ffe333ba6f676913b0f9f1ffa050b8
+CT = bbce07ee7cedada52b72e8e3b74b4aff245f63ad9009570476a4e9e759d5bb79c187a157099e3d12
+
+Count = 56
+Adata = 88800df7b6
+Payload = c9ea772e61742a6706da3ab3e81df14b31506ae58b063ece
+CT = 8e59724a0739dbb69a573163e539dcdd06bff0b9e4af39729f0f3699c9743ad6c9f09dc00ea10487
+
+Count = 57
+Adata = 715041afd4
+Payload = 70d2b8d64121ceccf1961444e8d33b7b7f998aeb58d3d270
+CT = 3761bdb2276c3f1d6d1b1f94e5f716ed487610b7377ad5cc560d78cba6d9f50e9c2677a710f92155
+
+Count = 58
+Adata = 14682301a9
+Payload = 1013946815001a2c08acca4196e0d6668ffbb3883cf111e7
+CT = 57a0910c734debfd9421c1919bc4fbf0b81429d45358165b95ffb6e29172a283d47e4478e2e1f7c4
+
+Count = 59
+Adata = e44c3c21c1
+Payload = f40dc834067bd163e0004d0ec5dd4b96e2a1ea31ea431c98
+CT = b3becd50603620b27c8d46dec8f96600d54e706d85ea1b24ccf233caf0bad9f68f71d78ee58512ec
+
+[Alen = 6]
+
+Key = c5a850167a5bfdf56636ce9e56e2952855504e35cc4f5d24ee5e168853be82d8
+Nonce = c45b165477e8bfa9ca3a1cd3ca
+
+Count = 60
+Adata = 4759557e9bab
+Payload = e758796d7db73bccb1697c42df691ac57974b40ca9186a43
+CT = 93ad58bd5f4f77ac4f92b0ae16c62489e4074c7f152e2ed8a88179e0d32f4928eff13b4ce2873338
+
+Count = 61
+Adata = 2ea07d393a0a
+Payload = ce60ddbe40b70bd55a9147036ad079dec1558ef4c2c625b3
+CT = ba95fc6e624f47b5a46a8befa37f47925c2676877ef06128b7d812c4d69f1f53ee9158382e56625b
+
+Count = 62
+Adata = aa6667faedc1
+Payload = 89eb3056770a6157f06921bc153834447c4b6d862d10d185
+CT = fd1e118655f22d370e92ed50dc970a08e13895f59126951e26fdbed62b228db008a1b14bd7942e12
+
+Count = 63
+Adata = 9e2127d92311
+Payload = 132f3e19e12f462a7463226b716c41a05a59c76f0e1a2f72
+CT = 67da1fc9c3d70a4a8a98ee87b8c37fecc72a3f1cb22c6be9124e1eb78de01b8af83b684baf3e43ad
+
+Count = 64
+Adata = 2f191bc9cff6
+Payload = b8611cbb9a3667b9458ca57eb636eb1dc580e7dbb5701692
+CT = cc943d6bb8ce2bd9bb7769927f99d55158f31fa809465209cb0f79736d1a810d06a776094f9fb67f
+
+Count = 65
+Adata = ad739d5f4736
+Payload = 112f89ccbdadc2433008d3ede2290f9ce81e5c736abf42a8
+CT = 65daa81c9f558e23cef31f012b8631d0756da400d6890633bfba2348f629471c232c9ff7e5f6f85a
+
+Count = 66
+Adata = 01acc909b7d3
+Payload = d47f2ff745de39a9055ad002de6334971fde480bef268b33
+CT = a08a0e27672675c9fba11cee17cc0adb82adb0785310cfa8c0f694d03ffed043787343827ea2603f
+
+Count = 67
+Adata = ce003c836a6f
+Payload = 13be365884b8a91a284ca24f70011e48794b51be275153b9
+CT = 674b1788a640e57ad6b76ea3b9ae2004e438a9cd9b671722279b553998a6fee0a86e177a448573a4
+
+Count = 68
+Adata = 6a759a4efd00
+Payload = d5c87c649579da3f632ba95cb0a07c924095e4bdd4e0376e
+CT = a13d5db4b781965f9dd065b0790f42dedde61cce68d673f54eeb434cca3ea719827417e94d6ed564
+
+Count = 69
+Adata = 02b84a26c773
+Payload = b7bc1580c68fd5d06c1bf75c31dad7a3e26d636d7eee20b9
+CT = c3493450e47799b092e03bb0f875e9ef7f1e9b1ec2d86422a74b5e4e2edb91fbbe722bfaf1500db4
+
+[Alen = 7]
+
+Key = ae8f93c3efe38e2af07e256961dd33028faa0716e5320a7ab319a10d2f4c5548
+Nonce = 6333bde218b784ccd8370492f7
+
+Count = 70
+Adata = 0b1fabdf2a4107
+Payload = bc9ca92a9c9919e39095d3e53fb148694620ae61227e0069
+CT = 45811b0c8f754bf03950e520cd4afc81c2e3eb8a11f4fd386d5a6e4b1fbee15d35939c721004502e
+
+Count = 71
+Adata = 2fc7f5c0ce052f
+Payload = f25a4ca20bbf4969bed6b93c1c77e3d7415f60fe3784216b
+CT = 0b47fe8418531b7a17138ff9ee8c573fc59c2515040edc3a24a68f98716190fb55f743a8bf62a085
+
+Count = 72
+Adata = 8a74412da3034b
+Payload = 3237bf953989d17c65a0fafd2bb1e32c237f98f55389e8f8
+CT = cb2a0db32a65836fcc65cc38d94a57c4a7bcdd1e600315a923afef7b4955d7d1e8f1abef9933bf9f
+
+Count = 73
+Adata = 7139f3c1d6cc36
+Payload = 55d86dc0423cfc2616ef996a3316e776707f8d25c985884a
+CT = acc5dfe651d0ae35bf2aafafc1ed539ef4bcc8cefa0f751b8e824c62632dff5cbc103d3060fbd174
+
+Count = 74
+Adata = af7a380f079aa1
+Payload = ac48398adb10292314973946f261ec39397442ca09b98dd8
+CT = 55558bacc8fc7b30bd520f83009a58d1bdb707213a33708980202d518ca871c9544f4a8c55fd8d20
+
+Count = 75
+Adata = e602abe8f72964
+Payload = 2fb78654e4395df8c37f260d74def234a3a4e3d2b1fe8614
+CT = d6aa3472f7d50feb6aba10c8862546dc2767a63982747b454b33ea6e4344033f74f513d1e41b82ae
+
+Count = 76
+Adata = 82741c5fd6e1df
+Payload = d488bdda400932de56a9f105f0e74ee79c2ed869faaadc31
+CT = 2d950ffc53e560cdff6cc7c0021cfa0f18ed9d82c920216073ccf18c7ea7dce79d0be1204c593234
+
+Count = 77
+Adata = 78f0cc22535402
+Payload = b22aba8d3e9f4b4bf006e26062de15daf94597731a600912
+CT = 4b3708ab2d73195859c3d4a59025a1327d86d29829eaf443b81b8af57b85093778690266e20e2fbb
+
+Count = 78
+Adata = 18e468139dd16f
+Payload = bd864f7b8efd6ed2b068f425482d449bf53a203ea88e1ca1
+CT = 449bfd5d9d113cc119adc2e0bad6f07371f965d59b04e1f09b94a857e7a0423ef6c9cbebde1f9c40
+
+Count = 79
+Adata = a6dab47c0fbfe1
+Payload = 47d9d18b6addc5f88986f0457b666faae59aba4fa3a02abb
+CT = bec463ad793197eb2043c680899ddb426159ffa4902ad7ea64718820065a739fbd3ba560a416895c
+
+[Alen = 8]
+
+Key = 548c2d1eb7d91e003633d4d9ff199e4a8447180edd89ac7867d25a1db288b5ce
+Nonce = 23b205bd6ff8ed0bab0c98999c
+
+Count = 80
+Adata = a6601111cd92c943
+Payload = 49fd5cbe4aff89dc3b8718f9ce545d612cbbebb289ecbf42
+CT = 3cfc6211e359ae322802fc9566f377b0dfe17d1dfe0878ebf2a9047e37cc0be1fab0006af8db8dc4
+
+Count = 81
+Adata = 96f0b7cd7439721d
+Payload = 94a95e945f660d1571b4d7d22709b000b45ff98b2129a4ae
+CT = e1a8603bf6c02afb623133be8fae9ad147056f2456cd6307106a430b04938e97f2e4cda81108ad3e
+
+Count = 82
+Adata = 2ee135dc2ddd9501
+Payload = aeed3aea01755c912213c8c276a2b75dad24f888a611efa3
+CT = dbec0445a8d37b7f31962caede059d8c5e7e6e27d1f5280ab2ab219c6c4952d52505cd9f904b0e04
+
+Count = 83
+Adata = 10c361934fd6ff77
+Payload = be1fcebea4c22a1d71e08047b028d7f4ccab0a6b8085d344
+CT = cb1ef0110d640df36265642b188ffd253ff19cc4f76114edfc1f7b2fe314faea28ab0dae349feb9c
+
+Count = 84
+Adata = 3f6c8a69917f7776
+Payload = 87680ac26fe1511e0f1f745aa4c2a5b9f6c0117dcf08feaa
+CT = f269346dc64776f01c9a90360c658f68059a87d2b8ec390308e529d64e786a29661cccddc0366f3b
+
+Count = 85
+Adata = 0f7a1426ff3b5ee1
+Payload = 9e004b072a27b085e59ca201c157c7d3c906a2c3b455c56e
+CT = eb0175a88381976bf619466d69f0ed023a5c346cc3b102c797c6510b85dfd097f3eac276aff00ba2
+
+Count = 86
+Adata = faa5bed84dcf168e
+Payload = a1bf47b15cd66e43daff420edf014a14b11994b97ada4030
+CT = d4be791ef57049adc97aa66277a660c5424302160d3e87998e522b6f13f99ecb553b6de845940907
+
+Count = 87
+Adata = 2851dae3cb3fcb1c
+Payload = 2d15734871adc63ff32d7002ab40c4a235a4d5fad223953f
+CT = 58144de7d80be1d1e0a8946e03e7ee73c6fe4355a5c752967a9ca39566189ee96c86462bfea78af5
+
+Count = 88
+Adata = 35a29c1bcbe2182f
+Payload = 5a84c4fdd47510fb7aebc0f79d7b625ccd0a96575740b8e6
+CT = 2f85fa527dd33715696e249b35dc488d3e5000f820a47f4fa613b5fbbe73a2df6c630a00ff4b1b92
+
+Count = 89
+Adata = 45820ae66c3e8e77
+Payload = 2052a94e1392dc1db0e89be19ea8f7379ee4cb607a914c89
+CT = 555397e1ba34fbf3a36d7f8d360fdde66dbe5dcf0d758b20d19feb067e9f6225376da21b4899d296
+
+[Alen = 9]
+
+Key = aab793e377a12484dbdd74c9b3a85c74c286e1cc498663fbd7c718b5633bb91a
+Nonce = 10022cddb323e88b3c08f95a0f
+
+Count = 90
+Adata = 82b8c736037ce2f2e8
+Payload = 7c0889854658d3408c5d8043aad2f4ae4a89449a36f8a3b8
+CT = 1044250f58857c69f72b5d3454d43949e5c02b3822970b280de1a3f7fc5d06cc30f06075f5504ed7
+
+Count = 91
+Adata = 8f2777ec4930f7e349
+Payload = bd845561f099500a6ff3fd09964dc3820f7ab48ba4ed04d5
+CT = d1c8f9ebee44ff231485207e684b0e65a033db29b082ac45835840df6fa96f5c972ac09d94148cbc
+
+Count = 92
+Adata = 5cab3b846870709569
+Payload = a6e09404fe60badfc63dc228057485e6f563ba82acdabd7c
+CT = caac388ee0bd15f6bd4b1f5ffb7248015a2ad520b8b515ec2f83ef84b299cfdb61d2b5039d536c3f
+
+Count = 93
+Adata = 0938f2e2ebb64f8af8
+Payload = 33404d7e0e620c1030b91020e33619c5f53d8b210fa86489
+CT = 5f0ce1f410bfa3394bcfcd571d30d4225a74e4831bc7cc19db04e655cbe22b9ea508d2a03757b97c
+
+Count = 94
+Adata = 82f78ca0e0da2b2d3a
+Payload = 617868ae91f705c6b583b5fd7e1e4086a1bb9f087a50bf50
+CT = 0d34c4248f2aaaefcef5688a80188d610ef2f0aa6e3f17c04bd88dc6985f819004c2b634c5303ed8
+
+Count = 95
+Adata = 401191aa3fd34abe87
+Payload = 949cdd7c2973d7519e7bca98b2c5947e6d8e91c90e632319
+CT = f8d071f637ae7878e50d17ef4cc35999c2c7fe6b1a0c8b894ff3572e4ebf78473760d8cb4b0366b4
+
+Count = 96
+Adata = 4df4377596d8987671
+Payload = f6720a0bd8705c70e0f923338965e810b3ea939bad652327
+CT = 9a3ea681c6adf3599b8ffe44776325f71ca3fc39b90a8bb7de95ec3eee17753e60fb3c0661bdd098
+
+Count = 97
+Adata = 6593194b9970545c5a
+Payload = de9b0556661e726f3e6e34515ff7196420fe61b4f38419f2
+CT = b2d7a9dc78c3dd464518e926a1f1d4838fb70e16e7ebb162b8590ff04f967e51fbd1be84f01b4dcb
+
+Count = 98
+Adata = ab2d432058b540ac72
+Payload = 6cad7f3b9f196839bbc5a7f755c09aa8e17c83d9cb8b3954
+CT = 00e1d3b181c4c710c0b37a80abc6574f4e35ec7bdfe491c471d67b75b2da855a12ffb24ddd64a048
+
+Count = 99
+Adata = 5dc631eeeacb5a0b0b
+Payload = 70a55aec1144357377612fd0bbc2c817f33465a656219957
+CT = 1ce9f6660f999a5a0c17f2a745c405f05c7d0a04424e31c71fc798dd16c1fadef607a9297cbfbfef
+
+[Alen = 10]
+
+Key = 06ac39896073a44283611a66ccab067e2dd2faa8da82ff9a45bb29e54d2e6e77
+Nonce = 6c7942c9819cf69b817bfcdb0a
+
+Count = 100
+Adata = 215e2a6c24325340fdec
+Payload = 3216dce3b8b1ce0e79e40fffcac728ab191aaaf319d971d3
+CT = c5b3b50ed8a7b7b96b02ba9464b6a2ff80e90548605699a63d70e6dffb31a376a1eb7f94526dca48
+
+Count = 101
+Adata = e0a29a2c7840cf9b41de
+Payload = 7e5e5710a693ebfa36335cf7965574740880acdddd13fb1a
+CT = 89fb3efdc685924d24d5e99c3824fe2091730366a49c136fcbf516608fe20e06bbff931e84683545
+
+Count = 102
+Adata = b8026fbada6339d84802
+Payload = 08c342a50aa23362622934dfab55d9b22c22c249ad08138c
+CT = ff662b486ab44ad570cf81b4052453e6b5d16df2d487fbf9d70eb14f3fa0229906b9e0360be3d3f9
+
+Count = 103
+Adata = 65f4b3a00c1c1ef39445
+Payload = e085aba85882c75d5e41559167731496cf17d3907894352a
+CT = 1720c2453894beea4ca7e0fac9029ec256e47c2b011bdd5f4184771199a427861bf17cd8401e794e
+
+Count = 104
+Adata = 96118dbfe53434d8aed8
+Payload = 710f890be2b8da77c1eff429ede9cc931d50f059748cbcb6
+CT = 86aae0e682aea3c0d3094142439846c784a35fe20d0354c34e20b2db52fde68f88bfb886fdcb2c47
+
+Count = 105
+Adata = cdf4b485d2e04709cf8f
+Payload = cda96efee4e188ab3048bc1904ac2c36ab018f2ab7602682
+CT = 3a0c071384f7f11c22ae0972aadda66232f22091ceefcef782ee3df38ddea8e269eb47e39900345e
+
+Count = 106
+Adata = 50e57e57cf8e49e3a4e6
+Payload = 3dc596d52e520779a50bcba3049388b340dbf6d0f2eb94cf
+CT = ca60ff384e447eceb7ed7ec8aae202e7d928596b8b647cba44aaac4ed86f687cfc031f22827725f1
+
+Count = 107
+Adata = 48c670f11ff7f74e7003
+Payload = a33105c0dccf8e3b687212a870af9f710462756705fe09b3
+CT = 54946c2dbcd9f78c7a94a7c3dede15259d91dadc7c71e1c6d75255006ac037d6a4d048f1fc338012
+
+Count = 108
+Adata = 465e3be6113a2fb2ee20
+Payload = 573ac2436158eb7dd9be981e3cfbe75d3a188ea9cf2b1ee2
+CT = a09fabae014e92cacb582d75928a6d09a3eb2112b6a4f6976c1da33a80bc8157cece1acf9400b2bb
+
+Count = 109
+Adata = ee4e10574faeae85e9b6
+Payload = ca35bdb54e73eac5a5200a296b3aba5f37c87349746102d4
+CT = 3d90d4582e659372b7c6bf42c54b300bae3bdcf20deeeaa165c1cb98da4a1a920ca1ed9a7b6ec514
+
+[Alen = 11]
+
+Key = 50412c6444bcf9829506ab019e98234af1541061557412740bc120b456052763
+Nonce = 85684f94c3702c5d870310166d
+
+Count = 110
+Adata = f706a3e09df95d3e21d2e0
+Payload = 6cdbd63f6d591f59776f828533b28e2453a214d1d0dd8a39
+CT = 8c8b4ae854a5d5c265b25e3b54bded9444cc454b3e0e6a24d6c05eaf406a5ebd578e19edd5227380
+
+Count = 111
+Adata = e46b25b9a41a858e87900a
+Payload = 100132c315bfc9c4fb93023f5d3500d7208a68acb4d2c630
+CT = f051ae142c43035fe94ede813a3a636737e439365a01262d5088446e42591c0ede68e82334d97cfa
+
+Count = 112
+Adata = 28d34b29afe6586fd9bf0e
+Payload = d5460c1db0d24dedc63c4c78ce6d1f0b2d46f3b01934525c
+CT = 351690ca892e8776d4e190c6a9627cbb3a28a22af7e7b2413eaaef2823f5ac3f313f560bd774d10e
+
+Count = 113
+Adata = 2852d4fd68a3e9e47d44a7
+Payload = d2d73b62e3b1c9ab75f3544ff8616741e0adbae84b8cf9d0
+CT = 3287a7b5da4d0330672e88f19f6e04f1f7c3eb72a55f19cd62d30d99bb7dadec34e2891c156a1f5d
+
+Count = 114
+Adata = ec1c17b2ab13d7c8ac874f
+Payload = 74796d78d6ad03634ed80800af530212baa7e5093651cedf
+CT = 9429f1afef51c9f85c05d4bec85c61a2adc9b493d8822ec241c9a05ebf9ed27792bbced83b5dc582
+
+Count = 115
+Adata = 4f1ab5ddb1c199e9a5daab
+Payload = fb432488b5d08d576a90f085181ad883407a6ce9ea29950a
+CT = 1b13b85f8c2c47cc784d2c3b7f15bb3357143d7304fa75171ffc24020e86b1314724104e6b57b3ce
+
+Count = 116
+Adata = 864e0e728aea856fae6c6d
+Payload = 2b82d96ed1778412378abe4e09c633acf3359b9709ae3dcb
+CT = cbd245b9e88b4e89255762f06ec9501ce45bca0de77dddd6539bbb0af8ecf77b4508533247b3501a
+
+Count = 117
+Adata = 21ee21a5ed0d75d0380a28
+Payload = 85143071241bb65261fe7afcc102416e59b9e46ee0c90073
+CT = 6544aca61de77cc97323a642a60d22de4ed7b5f40e1ae06ef8981ec6ce7c4687b178f2103fa8c8be
+
+Count = 118
+Adata = 2b63f7b676f13f45d103dd
+Payload = 185577b48237acbdaa3590b8057fe374f875ce829b62c98f
+CT = f805eb63bbcb6626b8e84c06627080c4ef1b9f1875b1299265d9d899c6b71c0ab3049ea1dbfaf6a9
+
+Count = 119
+Adata = a33e86d813c2c4ff3bab20
+Payload = f051beb936e60fd4f3bca31964f1ad3e6fa16dd27b65a6db
+CT = 1001226e0f1ac54fe1617fa703fece8e78cf3c4895b646c6b246474c4e79822f5fd55f2fb0067a40
+
+[Alen = 12]
+
+Key = 8a56588fe5e125237b6cdc30f940b8d88b2863ec501a0cb00b1abade1b5ce0ed
+Nonce = d80210b9f9776ea36dc0e0a787
+
+Count = 120
+Adata = e4296d1c8cf4ffc4b2635135
+Payload = c825952293e434ea866db558aaf486ef09a92bf366988f71
+CT = b8b3b15fdf6a4a0b5abc313afc769e4e8413bd887552583ede3ed995d1b70561c8e28a7b1a7e3dc8
+
+Count = 121
+Adata = d18bfcc1584eeb8695388ebe
+Payload = a1e0248355bfd1d881fb1a4798cda2f6f6ad513c69c5f9b4
+CT = d17600fe1931af395d2a9e25ce4fba577b17c7477a0f2efb561575f6743c5759494be59afa0c3e11
+
+Count = 122
+Adata = 14682301a99bf680805d1ffe
+Payload = ded135fcbf62219bfba2cba40c2d2cbe4815ddaac1342231
+CT = ae471181f3ec5f7a27734fc65aaf341fc5af4bd1d2fef57e34f689367228cbaf3cd76fb407109cf6
+
+Count = 123
+Adata = 8853aa2dfea9c4d370678bb6
+Payload = 12d3900c6c01968b8344762e0e883e5e219f42b052dc6215
+CT = 6245b471208fe86a5f95f24c580a26ffac25d4cb4116b55a2cacb7fc3856abcf759feb8dc0998ab1
+
+Count = 124
+Adata = c5d3b9c593c3185fe4b6d1bc
+Payload = 8c3c1193fe1a1ebad7e01a1eed1a32c08a0091b1c948e184
+CT = fcaa35eeb294605b0b319e7cbb982a6107ba07cada8236cb42a740cd3262424a2c3d77849ead6149
+
+Count = 125
+Adata = dfb9e8149b51f89b1ec00a8e
+Payload = 8219618b7728ac89237705ecf84012cc7c80293c4cf171d8
+CT = f28f45f63ba6d268ffa6818eaec20a6df13abf475f3ba69747d4dbe0f9415d40843070e1e93059eb
+
+Count = 126
+Adata = 08a4590d262e4dbcb7e23ffc
+Payload = b344b7dc239617fa51b9ea10a349e940c3163779f5284c9c
+CT = c3d293a16f18691b8d686e72f5cbf1e14eaca102e6e29bd31215b3dccba4ca5de64be7fab8a7a22c
+
+Count = 127
+Adata = 74aab7b5b96238710637c6e5
+Payload = 740d4b25ca7221d0826057701a6bfd66c50a82f010a57be8
+CT = 049b6f5886fc5f315eb1d3124ce9e5c748b0148b036faca734e09945ee44c95c7923d8b9249ade7b
+
+Count = 128
+Adata = 420aac47a3f212fffca40549
+Payload = 5d9000489186abdf4f0a2794f0222fcaa156fe6309c10f79
+CT = 2d062435dd08d53e93dba3f6a6a0376b2cec68181a0bd8360a568dd779526a0058d522af1dafde30
+
+Count = 129
+Adata = 6e80dd7f1badf3a1c9ab25c7
+Payload = ac2c44263363810bec3a309aa618b303e05099dfdbeb5c16
+CT = dcba605b7fedffea30ebb4f8f09aaba26dea0fa4c8218b59279442c88d612ed1a39ae0005f88155d
+
+[Alen = 13]
+
+Key = a4cc7e1c90f8684e6a5f95e6898ab4e3c194cb46e196d8228062b9f3fa744930
+Nonce = cdc2712e51c7f333d6bad78eee
+
+Count = 130
+Adata = 569c56b27268d3db54e728aac0
+Payload = 10d4cff95ef490923c9e0906880729d4d05412e7675cce76
+CT = be3ce3e9dc72499839a98ae52abb17415e8547687e8a3c7b8aaaac20d4c9276f2851cbba2b04d185
+
+Count = 131
+Adata = d75635b6450e43285fba966835
+Payload = c9db03e2efbab713b0b640421018d3971ffe2abd70fe8fa1
+CT = 67332ff26d3c6e19b581c3a1b2a4ed02912f7f3269287dacc121ff83891335dd1214ea6fc25f6a68
+
+Count = 132
+Adata = 70750acea6a05f8b7b425d262b
+Payload = add631ce5846ce71434aad4998f8e429aed430e7d38bdbb2
+CT = 033e1ddedac0177b467d2eaa3a44dabc20056568ca5d29bf549e71ec517cd65150f42b3cb53f936e
+
+Count = 133
+Adata = 2a567c7ec7edaa5a438ae3bb35
+Payload = a514d170422feb1d87bb7725a9e77cc6fc8afb45c2af6d90
+CT = 0bfcfd60c0a93217828cf4c60b5b4253725baecadb799f9d0e432ec394ddbb65205dc40a5a8e90a4
+
+Count = 134
+Adata = 0f8795385b805246a0a2573afc
+Payload = 79d8841ab83279724ce35e1a8abd4e158168dcf388ab4c3d
+CT = d730a80a3ab4a07849d4ddf9280170800fb9897c917dbe30926b0d977107a3918717f79b63f36b0a
+
+Count = 135
+Adata = 111d224c102b136159fbeb44a7
+Payload = 2edd498e54b23aab6f4fd7b3f22c4c787e3a4f1fb06c9ec7
+CT = 8035659ed634e3a16a785450509072edf0eb1a90a9ba6ccac2cd61599bb93db3dd3dabc12aa90932
+
+Count = 136
+Adata = df0821c9ea6ab329c626d11b4b
+Payload = 6e3e25db29da2c787bb37755ee770e2402fb8208da23389d
+CT = c0d609cbab5cf5727e84f4b64ccb30b18c2ad787c3f5ca90bd027ecd00cc6dc5ffd5d746d92281e9
+
+Count = 137
+Adata = aacaf4839c35338d6e2b47ac45
+Payload = d4ed4584678e982ace8664e77d0e55be356be558cead3755
+CT = 7a056994e5084120cbb1e704dfb26b2bbbbab0d7d77bc5583c01354a450eda2588be7578530e38c0
+
+Count = 138
+Adata = dc6eed3f8bd1b5563c1eeb9afa
+Payload = 4ebf00eadaf70711f630f5badf0214d8518a200afb0e5765
+CT = e0572cfa5871de1bf30776597dbe2a4ddf5b7585e2d8a5688d7a1d546e25ba026cd46556eb2c4b7e
+
+Count = 139
+Adata = fbfe7e910f242a78dd6e69a2ec
+Payload = 2729636112f2abe2c76ea5e52a3f80b0f882f0f3b6f7c806
+CT = 89c14f71907472e8c25926068883be257653a57caf213a0b0e951aee790239e7067ef37f497b4bf4
+
+[Alen = 14]
+
+Key = 347e12eec56e95aafcc7d25bf10fc756b4e42bc2e43da7f97df24331f27f1f5c
+Nonce = b8d517b033754058128d13d11a
+
+Count = 140
+Adata = 511c6924fa96db716f6b053b7a48
+Payload = ca88dddfc876a12f45f19562bc9ca250f43267ab251a7f34
+CT = eeedcfa8f5b5b48c1d7e277526eecb7294213b9f5785167ae949b93003dfe63c95c1d49edfb4de3f
+
+Count = 141
+Adata = 10c26d5939618189a9503623f55f
+Payload = de0c0d17c3950e7f8985b56d60623cbd010cd765da4df5ab
+CT = fa691f60fe561bdcd10a077afa10559f611f8b51a8d29ce585c32a90d77fed97eb0ac164ed616e1c
+
+Count = 142
+Adata = bc09c59d20e55a9e184d70af2c7c
+Payload = 2f35102d78a32fcde1cfb563ea8d310ecb83c146ab8de362
+CT = 0b50025a45603a6eb940077470ff582cab909d72d9128a2c180fdf5f63045f326057cf74fd4cee6b
+
+Count = 143
+Adata = b75887f13d6e8c4b35b27b965693
+Payload = a3fcce3420effdd6edb37271735a0d30c10c65233aee173f
+CT = 8799dc431d2ce875b53cc066e9286412a11f391748717e7134959a180fc2cf2ba99af21cc1bc8e5c
+
+Count = 144
+Adata = 603401a9b8ecde4d5c86b6107363
+Payload = 4ac918727e41b8c536484e3781c403e260c278712853508d
+CT = 6eac0a054382ad666ec7fc201bb66ac000d124455acc39c32ca2e5195dbd44f0a119538c95788510
+
+Count = 145
+Adata = 7206b06f306124ca3a302e84c5a6
+Payload = 97d770cbb2c42a552e450cc4e35e5668b2ff89cec735cc91
+CT = b3b262bc8f073ff676cabed3792c3f4ad2ecd5fab5aaa5df74a4e1198878a76291594b9826d4b563
+
+Count = 146
+Adata = b15efed90a5d1d62f545ac22af6e
+Payload = 86bb2ae50e36c72936240a74502172625cbca210cf285077
+CT = a2de389233f5d28a6eabb863ca531b403caffe24bdb73939ff5f993dcfbd048274da7439c0f9ef5a
+
+Count = 147
+Adata = c9eb714ed9858a8dc11a26ee3f00
+Payload = 0dc79993047fd6e7260aac4d847fdb4d16483f28b13b5f17
+CT = 29a28be439bcc3447e851e5a1e0db26f765b631cc3a436590e87710559a375ece6ef2953b6aa2542
+
+Count = 148
+Adata = 07ca22271e95cb48a872046822b7
+Payload = f950e96d65a55efb3be3a55daffb421afad1d5625e3440a1
+CT = dd35fb1a58664b58636c174a35892b389ac289562cab29ef998035c81716e2d1ed4b4d56ff18af5d
+
+Count = 149
+Adata = b65f6773516124317cfb4b1fcdf5
+Payload = e160e28e601a49d16db18f25410756b330b036c42e615fd6
+CT = c505f0f95dd95c72353e3d32db753f9150a36af05cfe36981ae73a9b6896d8fc1b8c0d772d632983
+
+[Alen = 15]
+
+Key = 520902aa27c16dee112812b2e685aa203aeb8b8633bd1bfc99728a482d96c1fe
+Nonce = ddf50502f414c1bf24888f1328
+
+Count = 150
+Adata = 22b4f8f1aac02a9b2ef785d0ff6f93
+Payload = 533fee7d2c7740db55770e48cb1b541d990ea3f8f08ed1a6
+CT = fc867b319e0e4ab45ec518a1b5dcec4f29982173f3abfd4d8a8f8d14d2bdac84c3737cfbd75b7c0b
+
+Count = 151
+Adata = d0a43de391d492746ecf322acd6e5b
+Payload = cced20b59a6b2c3c45ea6c87802440c9c47b1015e83d86c3
+CT = 6354b5f9281226534e587a6efee3f89b74ed929eeb18aa28fce59f5e6e3cee284b4cc747ff5ee13f
+
+Count = 152
+Adata = 3a789c06f87f05933c34a1cf9834a8
+Payload = 90939a4530181ad6900664f66bfc2ce0289432a0afe9babe
+CT = 3f2a0f09826110b99bb4721f153b94b29802b02baccc9655ddaef56d8255125f7c316c6c59ce779f
+
+Count = 153
+Adata = 785260973f112c56d9f891160c4c11
+Payload = 86cd926b9565b76a88fde73c31e9ac908ffd1e6ca30b59ce
+CT = 29740727271cbd05834ff1d54f2e14c23f6b9ce7a02e752555810cbcdf48f05d0a7808673c82d08d
+
+Count = 154
+Adata = bf6a144591c0ea7b10274fbd3345a1
+Payload = 6ecd1c1acc6290672f9cf639ed0cebcb21ed0c56f35a5ce3
+CT = c17489567e1b9a08242ee0d093cb5399917b8eddf07f700849e41e5d34a698ae1d96f16bc68da944
+
+Count = 155
+Adata = 7d9488b500d89a27f367f34a448a87
+Payload = b01e3f4fb5ee7501e8c2f4ccefb542ae20d7fd61a2c41c8b
+CT = 1fa7aa0307977f6ee370e2259172fafc90417feaa1e130601bc54e546d1a6fcf6187169feb1ea533
+
+Count = 156
+Adata = 060fc718e994edc7bac9962ca7f28d
+Payload = 22ab6a0daf953165dda864cceeeb782e275c0b072aedd284
+CT = 8d12ff411dec3b0ad61a7225902cc07c97ca898c29c8fe6ff2eb6c0ab42acf42985c721bfd576e71
+
+Count = 157
+Adata = cb6f96dd06015967279ade310a7401
+Payload = f96ed20b23c784015ff58f5f040798ca75e3b98045deca8e
+CT = 56d7474791be8e6e544799b67ac02098c5753b0b46fbe665ac502b8e65cc1329b6895afdd354f5db
+
+Count = 158
+Adata = 9aa6d501455019b4ef4c7fb789d22f
+Payload = 648a84813ca97aef4ab7e143ee29acb946388660f18eb671
+CT = cb3311cd8ed070804105f7aa90ee14ebf6ae04ebf2ab9a9a87e5f8a8148f21adf721477c36bd99ca
+
+Count = 159
+Adata = ebd1d12bbd14176a0d4080aa1edb89
+Payload = 32d71e59634126ac6c6156a80a0dfa0175b29e9f40a31696
+CT = 9d6e8b15d1382cc367d3404174ca4253c5241c1443863a7dda9ea0427522dbeaa509a11755434760
+
+[Alen = 16]
+
+Key = 57da1c2704219ed59abfdf04743a9a93c87a63d471818de0f1564b2db6421562
+Nonce = 4b60a47b7e90f622fa0bf803e1
+
+Count = 160
+Adata = 0ae8c012ff39753510df3ee80707e4e2
+Payload = ddc3c1aa73fb6de92bb4db138e26f3c2e0543ab4f5924871
+CT = daa8256d4753fdf9cfef876295badaba89b45cc497f54d220ec2c6fb687753bca4580adc6aa2f296
+
+Count = 161
+Adata = d5b22e7697ba70e00c7ef32709563f01
+Payload = 34270576724083e9989764d08a0d5c1b4738f34927a1e436
+CT = 334ce1b146e813f97ccc38a1919175632ed8953945c6e1658f30b9c8e380c98bb939a4e8a85af758
+
+Count = 162
+Adata = 6b4edef415763aabcef01863e8197aec
+Payload = 904fe88e7a8e76447a64b488ef84184d0f1ab1b67f0c5a7d
+CT = 97240c494e26e6549e3fe8f9f418313566fad7c61d6b5f2e53e80d8ccc687fd303f4cdef44b6e8b9
+
+Count = 163
+Adata = 4c099809061024c010a77e9621fc2bcf
+Payload = 51fe7bac8f3255f17f64fb9322210fb7d8da8e762498b233
+CT = 56959f6bbb9ac5e19b3fa7e239bd26cfb13ae80646ffb7600c635dac5b70338dac3f33ce16a99145
+
+Count = 164
+Adata = 9d329439588164d5a96675a85c07a039
+Payload = eab6dbc13bb92df36b1882df2b8f34c3cefa41f95717fbd7
+CT = eddd3f060f11bde38f43deae30131dbba71a27893570fe84f996e8163affb1494bb3c12eeadf16b6
+
+Count = 165
+Adata = b768fc3daf29ff9e8bd575072d986e99
+Payload = c44c9c287d3eac7c30570d9c4adf2e4857c598f7c54cd126
+CT = c32778ef49963c6cd40c51ed514307303e25fe87a72bd47598b4206a9622d5631751a497dfb1f662
+
+Count = 166
+Adata = 3efc7cc2d16bf82d2bcfbc559a09b2c9
+Payload = c11b9c9d7607f387359c0038d3e8ec4d527562ce63c3384c
+CT = c670785a42af6397d1c75c49c874c5353b9504be01a43d1f7dd300167d267ad700dea37fb475ecdd
+
+Count = 167
+Adata = 0ff89eff92a530b66684cd75a39481e7
+Payload = cc17904b166f28df82f57889f391159a4a308e752d714ee5
+CT = cb7c748c22c7b8cf66ae24f8e80d3ce223d0e8054f164bb6303e9c9bd0d8e4aac42894ca03d6ab06
+
+Count = 168
+Adata = fbd11bc75759f0461e796f6917aeb42b
+Payload = 6f97e595ea2f40612ea84a2097b974d235055fe1dae59403
+CT = 68fc0152de87d071caf316518c255daa5ce53991b88291500953f46e0e9cf1369e9eb018a4df3c09
+
+Count = 169
+Adata = b79940952f42537484aa2907c72dffa9
+Payload = a48cbf933b88c0ec5ddcdd8fcad186391c2cbef308607de5
+CT = a3e75b540f2050fcb98781fed14daf4175ccd8836a0778b68a1702dfa0cd9c290c5ff9c35cc83705
+
+[Alen = 17]
+
+Key = 9267ebc99ccf648b146cba3c251187e24a9947d806ceb0ced6894211641a1e0d
+Nonce = 9b7298950280e8762ecdc9bbe4
+
+Count = 170
+Adata = 5824689453bc406bf891b85e4576e38fe8
+Payload = 967daf12f16f166b7b5038f83a1cf0b980f5abf4c7746f2a
+CT = 7cfe2a7a54306eb8d8a63d3d1ae86794f9a2c22198b2cb4f10ca926f1a430c08c12e23db3d913e93
+
+Count = 171
+Adata = cd15973753b94b77bb4b778de8b3b0cabb
+Payload = c4a756f6024a9dceabf6e264fffff9c719217fb418141ac5
+CT = 2e24d39ea715e51d0800e7a1df0b6eea6076166147d2bea05d5b674fd15410cc235dba6d8c8d82a8
+
+Count = 172
+Adata = ed8540f7ce451c522c1ff5d2d1030d7b3f
+Payload = e0d5de7d1eace211c0e70859ff315ff485d1200c6dd13f93
+CT = 0a565b15bbf39ac263110d9cdfc5c8d9fc8649d932179bf688750b5f36c86e7eda9015e960a7471a
+
+Count = 173
+Adata = cbbecf92551a15f5cf00a5be4a50b0eb17
+Payload = 05a4a4ba28fe8876f9bcfa5ec60651fd3fd4732f22049bd5
+CT = ef2721d28da1f0a55a4aff9be6f2c6d046831afa7dc23fb0d5fa842209dbbc04c87965f78500fec1
+
+Count = 174
+Adata = 873ba7f8b71517ec50297b21cf94cdb7a5
+Payload = 9cdebaeee8690b68751070691f49593668a6de12d3a948b3
+CT = 765d3f864d3673bbd6e675ac3fbdce1b11f1b7c78c6fecd67d147edbe114bfdb3f3b9b37d5719ef5
+
+Count = 175
+Adata = ac087420feb1e1e8c2546c2a8b8a5af0d0
+Payload = 5672e61cf664d73918dc1ca84df1fce82db0e305a61d57b9
+CT = bcf16374533bafeabb2a196d6d056bc554e78ad0f9dbf3dc57b4c2bbc377937d15b3b89543e29d0e
+
+Count = 176
+Adata = a12c690568114fd7a677f49d74e84fc1a6
+Payload = 0f5452e6b51540cf219998590995cd7f8785fa40b4f217fc
+CT = e5d7d78e104a381c826f9d9c29615a52fed29395eb34b3992e6ca774074b47b59adabeaf8835582d
+
+Count = 177
+Adata = 7a78ddfe5afb2dc90ee4a600c2fc014b0f
+Payload = 9ad338cbfd1b52e6ae4178f05e00062274f8b0b25eae72f7
+CT = 7050bda358442a350db77d357ef4910f0dafd9670168d692bd320f48a7221537e3cbed5ac4154a56
+
+Count = 178
+Adata = 6053e466ed1f647a3cd88c4d2052ec00cb
+Payload = d17b8d556e83190c84d4a812957c64ffa7f336298f4e2c72
+CT = 3bf8083dcbdc61df2722add7b588f3d2dea45ffcd088881740574e201f9a26932a87c8d822505814
+
+Count = 179
+Adata = f7673e3beb526834d6507058fe62e34987
+Payload = 2eaef86b0f602364f86510eabc58bc9ad1e6f0a6f6df0b83
+CT = c42d7d03aa3f5bb75b93152f9cac2bb7a8b19973a919afe6837dfa3fdef2f012b6609de2ac5dd9d6
+
+[Alen = 18]
+
+Key = 7a855e1690ee638de01db43b37401dcd569c1ae03dc73dd0a917d0cadb5abc29
+Nonce = 8f160a873a1166c8b32bccbba7
+
+Count = 180
+Adata = 72674aca7eba2fc0eeafbd143c2c4d8aa6c8
+Payload = 33ae68ebb8010c6b3da6b9cb29fe9f8bd09b59ec39f4ce4b
+CT = b22afdf4f12c43ec23e01ac1215a3f5286059211207e957057e9a9203da74387a9468f8af5e27547
+
+Count = 181
+Adata = f7da3f100b80e2ade812f1700aab6b72f746
+Payload = dbb29817b86cb80e0d008742cedfbf52b236f15ee8cad50e
+CT = 5a360d08f141f78913462448c67b1f8be4a83aa3f1408e35a3985f12a49eac424a35c94645917e91
+
+Count = 182
+Adata = 4b05eaadf98505d0806c233b2cdcaf4254e8
+Payload = 145aa8cfd544a2f46bae1aa83cbdb3d21c3d1350078a3af4
+CT = 95de3dd09c69ed7375e8b9a23419130b4aa3d8ad1e0061cf4ab089a8724b87a1167180963d44ec65
+
+Count = 183
+Adata = 05a3aaa08b9a6aaeb84704431425d0e45a14
+Payload = 6b32e8906dc89194a69410b79cd041b62eb01afb28a3e10a
+CT = eab67d8f24e5de13b8d2b3bd9474e16f782ed1063129ba310a7d1520141892e140448292185c41c7
+
+Count = 184
+Adata = 74db01edc26a2d2044cb8eaad8b907b78863
+Payload = 545ed03588fd85a8bbfeee66d2082ae6f8e2f3c9dbd8725f
+CT = d5da452ac1d0ca2fa5b84d6cdaac8a3fae7c3834c252296472d3eee219d94bd788f62df4add5ec40
+
+Count = 185
+Adata = 5f2c6ddf5a2403e04dac8b2813c060b67e76
+Payload = 66dd5fd8611c551973a3d0c078ec2b4d39ad163d9168de3c
+CT = e759cac728311a9e6de573ca70488b946f33ddc088e28507c600496f4f8b1b7da118ee36d8cd57f8
+
+Count = 186
+Adata = a650a2a5e3c6f7c95614570aaefd0cdd9a42
+Payload = 6f364b3f778376cbf3f4b0b0c5350a8fa278f9d8c25faad6
+CT = eeb2de203eae394cedb213bacd91aa56f4e63225dbd5f1ed4710004d06ce7a7efbd19da4e3ce3cf7
+
+Count = 187
+Adata = 477c2484cf5c56b813313927be8387b1024f
+Payload = 3de4798d8ad84c460b92abc10b7f5e7c9fae46a1dd353687
+CT = bc60ec92c3f503c115d408cb03dbfea5c9308d5cc4bf6dbc304099641c4ec3dc2c54fdf4f48dbef2
+
+Count = 188
+Adata = 564e1df74aa2d7ee33b66cfeda810774e16c
+Payload = 7769b45fea11f530fb9a67f1b5b1964a34cfa32bbb03f4b1
+CT = f6ed2140a33cbab7e5dcc4fbbd153693625168d6a289af8a905c1b05e8945685f8688faea777eb43
+
+Count = 189
+Adata = d5e66502529b0045883d935e05acd242baa8
+Payload = 0c0a502b42f81b51806c7080a8155280f493f2922cdc7df8
+CT = 8d8ec5340bd554d69e2ad38aa0b1f259a20d396f355626c3ea5a3b6a8bafde4006b993cfb3b13557
+
+[Alen = 19]
+
+Key = 0ebdc6ddb4c502725dd6ee8da95d56a0d1044b4694d6ba8475a4434f23a8474f
+Nonce = fb717a8c82114477253acc14f6
+
+Count = 190
+Adata = 41e9d65632f74f449a6842d5e6c4a86ef83791
+Payload = c7360282c85484a5a33ab1c68dd70873ab4e74ffd4a62cd5
+CT = 2e961b3a2fa1609a4e6fd04bff6ac5e306ae2638706f997b42be2e2ba05c54b619850db5c9d684fe
+
+Count = 191
+Adata = 555304659bde926cb2553b8a4605251fcddd92
+Payload = 1332314d1cf783b9f64e0fa2d42d43d225da9fd5165b5f0a
+CT = fa9228f5fb0267861b1b6e2fa6908e42883acd12b292eaa4bbdee2605bc69601b1e83d1e7a0b400d
+
+Count = 192
+Adata = 69ea953dbb910ec589372d797c7379d3f3b9e9
+Payload = f264da8606ea429e0e25da3f2efafe28beaff05b42097369
+CT = 1bc4c33ee11fa6a1e370bbb25c4733b8134fa29ce6c0c6c7304611baf530932da7954f714514d228
+
+Count = 193
+Adata = d7186a67061319b44eedc0677ebf5d932d5bce
+Payload = c9ee6482144dc61c43041324a2c18ede370011cb4882b0c5
+CT = 204e7d3af3b82223ae5172a9d07c434e9ae0430cec4b056b6d1d44e26404b7324767f0b3f7486f8b
+
+Count = 194
+Adata = 38f37d5e2da017f1953ff3701be0b38809ba80
+Payload = 40524a4d32a711e7d5a59809878c318f42b6e2375b77b8a7
+CT = a9f253f5d552f5d838f0f984f531fc1fef56b0f0ffbe0d095453724d2db19f606c85d00e49b0bb38
+
+Count = 195
+Adata = b3b2d249cd3517555fa692bbe9116f069e7405
+Payload = 961c15bd7dc34cd5409c9e8869988676ec6845ecb0ee85fd
+CT = 7fbc0c059a36a8eaadc9ff051b254be64188172b142730536db1e4112fcd650e8c0f0f6fbf2d07e1
+
+Count = 196
+Adata = f5b5bcc38efaff01f69bd3a106dcfca3cc6414
+Payload = 879568ab9ebdea768a5459ced1d3181d822536c3d1ba38c3
+CT = 6e35711379480e4967013843a36ed58d2fc5640475738d6d1cedb29e68322e47ff9997f859257d98
+
+Count = 197
+Adata = a2098e3e23826e01f31107a208202f710eff00
+Payload = 47cb57599686716c75d7ecef5541d20fb908e6d98c39925a
+CT = ae6b4ee17173955398828d6227fc1f9f14e8b41e28f027f41c12bf2a3571ed672592b27e986e9058
+
+Count = 198
+Adata = 20a3d53e77201599540344c4e746c3ae3a5f84
+Payload = 4a8667b5ee09d3d4a6dca9a95f4ad406f1da94b846dcc6b8
+CT = a3267e0d09fc37eb4b89c8242df719965c3ac67fe2157316f12b2be8f5966d96602111c28f87b104
+
+Count = 199
+Adata = 92c592ead4b3f193cc36687593d4f0f412a5d5
+Payload = 1dc9e32ac4176f64bd78a6edd651ebeea3ba85dfcd8298a8
+CT = f469fa9223e28b5b502dc760a4ec267e0e5ad718694b2d06776df0a0cf048892e65bd8ad77cb2255
+
+[Alen = 20]
+
+Key = 2ff64bbec197a63315c2f328dcb4837d0cdc21a5d6f89ff1d97cb51195330cd8
+Nonce = a235f8ee3de9896b71910ac02c
+
+Count = 200
+Adata = 2b411bea57b51d10a4d2fb17ef0f204aa53cf112
+Payload = 4a17522da707b4b2587a0ae367a2cd2831bb593a18ef442a
+CT = 1bf122798bd8ee8e73391d589bd046a294d1615794e69cb9e6f3ba30143acbc3a1c1c6ec74333107
+
+Count = 201
+Adata = 0248359f8071143c3cc1d61882a3547a0b3d2175
+Payload = 4a6a7151465c2abd7e7fa1fd13019ad098b6ebcd190e96f7
+CT = 1b8c01056a837081553cb646ef73115a3ddcd3a095074e6436cb510c13a039f4df8cc26a942f9911
+
+Count = 202
+Adata = cca77bc4cf6c0abd3393dac3fbe90fbc8a1154f7
+Payload = a94f5ede43929d48d2c5a58c3262d9127d2ac3cb2fbd5768
+CT = f8a92e8a6f4dc774f986b237ce105298d840fba6a3b48ffb7fe0dedc2899dff81a251cff16bf5897
+
+Count = 203
+Adata = 9c082a84646c070bb11b7d6b92b62f06ee5b5b71
+Payload = 7303bd41cf47289a3111366d08e8e21548baf293052029eb
+CT = 22e5cd15e39872a61a5221d6f49a699fedd0cafe8929f17886c43ac23800de60a1fd2caef0f03261
+
+Count = 204
+Adata = 1c3ede1982a807a410ae1e21947bf430f8db7027
+Payload = fa9743a67978c20316cb91801d7789e350079aae3aadbd43
+CT = ab7133f255a7983f3d88863be1050269f56da2c3b6a465d026f7907e235c09d3322c4092d2e88f88
+
+Count = 205
+Adata = deb05a30a026ff66ce71e98afa62f0255aef84f5
+Payload = 99599b4042dcdb685350cdecfdf24992fd5b165670025d0c
+CT = c8bfeb146e0381547813da570180c21858312e3bfc0b859f6bb44a28c145d49f49f2821d4044e4b6
+
+Count = 206
+Adata = 93dd9b00a3353e5331338dcfcb7ca7e0bb873a4e
+Payload = 451101250ec6f26652249d59dc974b7361d571a8101cdfd3
+CT = 14f771712219a85a79678ae220e5c0f9c4bf49c59c1507400f7d20aa3d792d6a3ebc5ee0df2fd89c
+
+Count = 207
+Adata = 0855263860043207543c8c34648d53ec51c4f47e
+Payload = b2db87b7787531968d603098cb20ca7c438b4af72623fea9
+CT = e33df7e354aa6baaa6232723375241f6e6e1729aaa2a263a7ca4733f0208668b0a7879305e861d71
+
+Count = 208
+Adata = ee2d3a66deb3ebca867a902bb9202226ed516ded
+Payload = ca18ce38086223e63b4f0b616d110010f9e45eac42f2ba46
+CT = 9bfebe6c24bd79da100c1cda91638b9a5c8e66c1cefb62d5d76b482ff20429da8f60f0f863e1af50
+
+Count = 209
+Adata = 8e531aaea849addab6a83497cbc504f489505952
+Payload = 5717ed5da5b8aa806a18bfe979502bab6632c9428d3a7725
+CT = 06f19d098967f0bc415ba8528522a021c358f12f0133afb6aab66e1ac2346ef97850a4985c64b737
+
+[Alen = 21]
+
+Key = 24e9f08a9a007f9976919e10dc432002e2e078a339677f00105c72ed35633a3f
+Nonce = 15977424eeec0ec7f647e6c798
+
+Count = 210
+Adata = 2d838eb51a4bc69a001a18adf2084a680f02a3c5fc
+Payload = d3416a81b4246eb0bf8119a72a886bbc0ac9449c69f71d2f
+CT = e001a8fae390dc5d672cdd18f86a1f728158ec83a002050def9af5679edbcbb7db20ab6af30698db
+
+Count = 211
+Adata = d83ee7ce22fd1a2882d8d552346e4d7b3efdd67da4
+Payload = 22b6f10b482448626f6c7bebb14f1497896d071738133b4d
+CT = 11f633701f90fa8fb7c1bf5463ad605902fcaf08f1e6236fd435a5a38f84387f63b13407f65ec86c
+
+Count = 212
+Adata = 2d5537b24d0b0f7a45703c1e131656ec9edc12cdf7
+Payload = d60edc830be8207ffd9e9f646d3b4343b10b3d56acb89d44
+CT = e54e1ef85c5c929225335bdbbfd9378d3a9a9549654d85662ede8a705f8c988f55459542bd631b1c
+
+Count = 213
+Adata = 1a750eb326923412d94ccb35f5acd0f87415268178
+Payload = 716d3132f449a9def383978102ae50ed3ccae0cb346ba1df
+CT = 422df349a3fd1b332b2e533ed04c2423b75b48d4fd9eb9fd986de774a612230ce6c71449d26732ce
+
+Count = 214
+Adata = b10fc523bc4562d44edfe5956f93c15c4ab38bba3c
+Payload = 063c2ae2a15f26f979bf90657d20643e3184f1a9f75a3aad
+CT = 357ce899f6eb9414a11254daafc210f0ba1559b63eaf228fe710431005264fa7d3fc04bac50fc1ec
+
+Count = 215
+Adata = fe4f60ce9634e7dbc5e56204c4bf8aa9be577027ec
+Payload = bdc513e56a5bb70c02abc041af04d6e45e735d10cc88357f
+CT = 8e85d19e3def05e1da0604fe7de6a22ad5e2f50f057d2d5d5c13bea6ad0cad724e6cd02c89517ffc
+
+Count = 216
+Adata = 48f3ceda4fd390a7eb38f7f5bcd14310af6b5a557e
+Payload = 7dc5d8cd90ce2faf76bbd0d52e5ae11b310fc2b0051c4377
+CT = 4e851ab6c77a9d42ae16146afcb895d5ba9e6aafcce95b55d2a5531655aae01e249f213e0e04af0d
+
+Count = 217
+Adata = 199ec321d1d24d5408076912d6bb2b6f192d6b347f
+Payload = 66c2696edec26ba3d07bd3f485a0d6ce8a1b0a85b20083e7
+CT = 5582ab158976d94e08d6174b5742a200018aa29a7bf59bc52a127ef341345f9641b26e91265e1482
+
+Count = 218
+Adata = 8b013f5782d5d1af8dbd451a4202866095dac975fc
+Payload = f4da8ac3e8fe5ec6a5b6a2f27b68396e850b46a024d441f0
+CT = c79a48b8bf4aec2b7d1b664da98a4da00e9aeebfed2159d2a005ca13c4bf715c3b7b2782f799b23a
+
+Count = 219
+Adata = e320df32b71cc530e8493b12b9afbeabc255c5eb44
+Payload = 244891cb4af66cc8e99a3784a2e82475e51bd5c7fde67cf5
+CT = 170853b01d42de253137f33b700a50bb6e8a7dd8341364d704642aff9cb9288d49f0e567dd837e05
+
+[Alen = 22]
+
+Key = 0ec1b22b8df05dc92135d2dfbefed8ea81458f5ea1b801e8a218faf6cbdf1a79
+Nonce = 97ebcb8575bb58260208d5c227
+
+Count = 220
+Adata = a2f6337f86dd00d1a58448851e95d8c9bace4a5c8710
+Payload = 2f59d94d4ab8eeb84c2a6fefb7fb0a3ac059c1e1a65ae34a
+CT = 7ca0b1dbe34b0391e524b868b0af08b3e096917664d6aa2cabc1f9d0132394149c9062b74b82f04b
+
+Count = 221
+Adata = abf26b05558252c8e38c52b1ace087bbd1eb3d561239
+Payload = c25381853f73a3dc4195fdcbc45dfa1a40eb8324749adb2e
+CT = 91aae91396804ef5e89b2a4cc309f8936024d3b3b61692486d7df57c6a792f6f6b24cb5f87e92123
+
+Count = 222
+Adata = a13ade56b47803897666e42ef2ef88be0e779ac86c28
+Payload = 8dc5226a2a13088c87f4bf94262e0c0413f06b35d2fda79b
+CT = de3c4afc83e0e5a52efa6813217a0e8d333f3ba21071eefd4ac19b0b74cd9d5e100598b96c9f1f2e
+
+Count = 223
+Adata = 3c5b68b65edf62755b7e064bd26c843816bf6c1cd481
+Payload = ee4b23039cd512cfab8c7a2d0f2c78d66764520bc88759e1
+CT = bdb24b953526ffe60282adaa08787a5f47ab029c0a0b1087a77a27eabfc79f192c0ac491280af8d0
+
+Count = 224
+Adata = 0213fe13c49083d7c00335e1864dc139c9e7123162d1
+Payload = 30b48d4021838090fbd5251069ff8c631452daee5ef899db
+CT = 634de5d688706db952dbf2976eab8eea349d8a799c74d0bd39935f91c1e29fc1e4c5c5427ca9da79
+
+Count = 225
+Adata = a32291746b151be8134e183798aa82bef210343feaf6
+Payload = 2286a1eddd80737a724ca941217e9f0232870b6c2f20d29c
+CT = 717fc97b74739e53db427ec6262a9d8b12485bfbedac9bfaaeaec90ada2a1ffef64c3873af645a40
+
+Count = 226
+Adata = a30f2fd445820cdf800145540602c877da0e4c311272
+Payload = fe703ca0901e4a706ce1393c7d8ce18a03eb2caadbfa7b8e
+CT = ad89543639eda759c5efeebb7ad8e30323247c3d197632e87932952831d0ba25c77c18fe154d8ed8
+
+Count = 227
+Adata = ed438e393e0e37629cb25044ae89de9fd0d42d60c1a3
+Payload = 7043c67726870bb5816da925925bc2722478311c8a606cca
+CT = 23baaee18f74e69c28637ea2950fc0fb04b7618b48ec25ac234fd0241d00f3890a23ccd0bf16dcbf
+
+Count = 228
+Adata = 1013946815001a2c08acca4196e0d6668ffbb3883cf1
+Payload = 695e9712dbbf883e9bf8af9188bd01fc631968928258168d
+CT = 3aa7ff84724c651732f678168fe9037543d6380540d45febaf43498b0c3f70c119f82d5812db940f
+
+Count = 229
+Adata = 44cc9b2510680c4d73f1938c77de21242c8ee790ed7f
+Payload = 67ba90d22c6bb5f649bc0c505c5ed23a299882559a3bf520
+CT = 3443f844859858dfe0b2dbd75b0ad0b30957d2c258b7bc46db66dbb03a4c943ac089ed11eb214bbb
+
+[Alen = 23]
+
+Key = 0875020959ed969cfb38636d1d5aabce9658b00171a7614ea9e5395331c7659c
+Nonce = 451101250ec6f26652249d59dc
+
+Count = 230
+Adata = 7cc9c51b69f98a06391ab32742fb6365e15106c811fe8a
+Payload = 065ef9eeafbe077c1c7049f43eb0d8999708e8609f214d5c
+CT = 990065322a438e136860f7b019807e9feff52a642bf3d44a9163fa7a867f04cab6f52dc250070f31
+
+Count = 231
+Adata = 7bb1bc069a783d45d51d8ecd0a53ab7a386fa1f5ef12a1
+Payload = 69b2b056f2265e707d3e31e68bff6a060544c8a737b2a9b9
+CT = f6ec2c8a77dbd71f092e8fa2accfcc007db90aa3836030affd33dd9155619fb040dcd6038c7b7367
+
+Count = 232
+Adata = 0dd220919d0eeee3b7cec36c47e376b778583b38bf61c8
+Payload = b98d79aaa4c04171398c7f1189497acaa7546ef068bc7a3f
+CT = 26d3e576213dc81e4d9cc155ae79dcccdfa9acf4dc6ee3294fcba5a886b1f33cf1cf44618d28f01f
+
+Count = 233
+Adata = 1c1915fab09348b9a5536495c70d1a040305708c112479
+Payload = eeaeb773ade5fb2d27b50bb892916333e0b123c6e3ae5bdb
+CT = 71f02baf2818724253a5b5fcb5a1c535984ce1c2577cc2cdeafe2c670eac203d5e90b9d520e7a618
+
+Count = 234
+Adata = 614b0ac4611b6c6d3b4ed089510dcd2215567bc3789f85
+Payload = f2198e1f91fde2672a1ef60403c0d175f366b6780ee9f1c2
+CT = 6d4712c314006b085e0e484024f077738b9b747cba3b68d4f0388746438e83b731b5588fef53f1f3
+
+Count = 235
+Adata = 866fea4483d4e903566844e31c24283571832dfae32c74
+Payload = ba37617342b4eefd4bdce8fad30c4751b206d47814973b3a
+CT = 2569fdafc74967923fcc56bef43ce157cafb167ca045a22cfca81f8b36d16698a600fd701f2c6424
+
+Count = 236
+Adata = 9d7546f7e8b949c539d21a357f81d0151e278d0bf2c5a5
+Payload = 69adcae8a1e9a3f2fe9e62591f7b4c5b19d3b50e769521f6
+CT = f6f3563424142a9d8a8edc1d384bea5d612e770ac247b8e04c15a6d292c7ed2f31cf9512435ec7d2
+
+Count = 237
+Adata = 42b692048c8b3cce1b5e83f4f33232a7d7d0bc20695e7e
+Payload = e0753d4248643642c7a96404de8d76c9d80527b659ec6d31
+CT = 7f2ba19ecd99bf2db3b9da40f9bdd0cfa0f8e5b2ed3ef427a2ad73179d0314b5fe52dd7217518cb8
+
+Count = 238
+Adata = f1dfb6fdb31cb423226f181c0988a52ee4015aef4536f4
+Payload = 79ba959c7221b293e2115f538d9394c64284c756563c04b0
+CT = e6e40940f7dc3bfc9601e117aaa332c03a790552e2ee9da69ccc5ba1caf933b80bfc6f281109688f
+
+Count = 239
+Adata = 8eafce9ba466fd53eb87f499d7c76bd486db0e90a3d281
+Payload = e1590206717a708cad9cca7d23a3b8ee5f7fb7786aa3be47
+CT = 7e079edaf487f9e3d98c743904931ee82782757cde71275173271ec36d92fff34609169f579c8f1d
+
+[Alen = 24]
+
+Key = ef4c1d2314e671f666cc6667660f1438a293208c7cc29b412d81277f0a635c91
+Nonce = 50b23b052922366c25dd40e348
+
+Count = 240
+Adata = cd0522ebe1fed82465277d1c10ae9316a98b4469be63b180
+Payload = c99c3e79125b6fd95e737326a842424eb6c6ecea4c0475c4
+CT = 76df4be4ec8373864399acda11294b220b9f7c3a7d2b3660b25764e40ac6a171e7e6bab4fdee4288
+
+Count = 241
+Adata = ce5bf070678cb07e963263b1562ff79311144addb6e4de4f
+Payload = eede01b08f9a303cdf14c99d7a45732972c6eff2a1db06eb
+CT = 519d742d71422c63c2fe1661c32e7a45cf9f7f2290f4454ffca49758d17f2073066b82667eae6ce3
+
+Count = 242
+Adata = 07175be2475cc735c9a3c1140895277378debf8fb1c87c24
+Payload = 6d5579aaaf8737b01620424f3ddeaf538f10dfad094e5ec4
+CT = d2160c37515f2bef0bca9db384b5a63f32494f7d38611d607c1d64d7e9de47a6ad7878283da9d870
+
+Count = 243
+Adata = c821a8d4bab9d993c20dd206955304a55968e6db5ab6480d
+Payload = d0628b2027f06c246497977d05f211b2c2e302d5b82700b5
+CT = 6f21febdd928707b797d4881bc9918de7fba920589084311adc2bb471862d25cfe25e66fedb8e28c
+
+Count = 244
+Adata = 68439bc9d176feeeb4119d00ed5449dfefb72b5a582bfd97
+Payload = 6cc9749f48c61050e421afa3a10ad3dd3aa02cc3f8586915
+CT = d38a0102b61e0c0ff9cb705f1861dab187f9bc13c9772ab1319a493abc947945f1312395ea98d937
+
+Count = 245
+Adata = adb262c924942e4e1964e9d97c6a8c159fbf9bfedc5ff296
+Payload = 92d50736466e64e6225962e76bd90da824f716a3301a1a90
+CT = 2d9672abb8b678b93fb3bd1bd2b204c499ae86730135593421d0602d29447ba6b24a67509eaee1e8
+
+Count = 246
+Adata = fc7b08707d3c3dac7689ec18088ee6502ef08d3ffbff38ed
+Payload = 87c7ac031fd63e4c83280dce6b68a92dfafb6ea19388fa9f
+CT = 3884d99ee10e22139ec2d232d203a04147a2fe71a2a7b93be52a2eeacb1f023e849161b6306b6cfa
+
+Count = 247
+Adata = fd43dfb66041b117f2ac54c94f7b6e2677860864d9494175
+Payload = 6b53c46266b2f4284d8fe7f0549c98977344d67e178e9a8e
+CT = d410b1ff986ae8775065380cedf791fbce1d46ae26a1d92a0d8c5b1e96b21460e0b5414639abeb0b
+
+Count = 248
+Adata = ef1ad3eb0bde7d4728389da2255d1f8a66ecb72e6f2f1ac4
+Payload = 8e7d8a44244daa7df2b340993e32dac50e05d7b2e103be98
+CT = 313effd9da95b622ef599f658759d3a9b35c4762d02cfd3c1c97260d20797d374c595cbc2ff080bc
+
+Count = 249
+Adata = 9895b24d12b004b215583eac70a95f4fba7442164f35c57b
+Payload = cec07df916ffb7a453d0eb588b7462096f22874bd5abf814
+CT = 71830864e827abfb4e3a34a4321f6b65d27b179be484bbb06cd287afcbdbc5531f11246080b22677
+
+[Alen = 25]
+
+Key = 8544808e8fbf8c3a5e1d4ca751d4b603af9fe119eabc6923205815e0e748b7e7
+Nonce = b44a58724596b4d8dea827c1a0
+
+Count = 250
+Adata = f5b2c88f5232c37273b1e66aa31cfa7201e33c21d60054d025
+Payload = 617d54fc6a23601c79e3984f93bfc2d151fde420863206b3
+CT = 57b3414db48982c6567265e1e0173bf38fdfaffe4461fbebc1411af83237c0f9eb0bfe8ed914da66
+
+Count = 251
+Adata = 8fabe14dcb3aa2fd28281147c326e98ad699ca7997f03a105d
+Payload = 337290d0b4ce1e87afc3cf01d6c98f8c17a4603120dcfcd1
+CT = 05bc85616a64fc5d805232afa56176aec9862befe28f01897ed6e23720b60ffe54bbb9f7ff371008
+
+Count = 252
+Adata = cf193eb3d755cb8e06c5be2334b5c8b7a22b6524d46d547ba3
+Payload = 01ef7ac6470aa02ccd8c1712827e52699d05751b78e4c5a6
+CT = 37216f7799a042f6e21deabcf1d6ab4b43273ec5bab738feb6aa6b284e7720acbd027a50317f816a
+
+Count = 253
+Adata = b4cadb5f9cb66415c3a3b71421b926f147566a174160a0bcc0
+Payload = 64fb9322210fb7d8da8e762498b233b0eb172c91231c50cb
+CT = 52358693ffa55502f51f8b8aeb1aca923535674fe14fad937058e9c0164ca079668097fde19e5302
+
+Count = 254
+Adata = 48400d76ff882d6d5129c8674acc71f445356c9db9c91f8256
+Payload = 291aa463c4babc76b4a6faf2e27e9401586b1ac83e4b06a4
+CT = 1fd4b1d21a105eac9b37075c91d66d2386495116fc18fbfcf988611d5ce0f65b217bb4787bf59bbc
+
+Count = 255
+Adata = 749d369d837002ad33feb8aa22c3f68705eb4872e1b8f85a7f
+Payload = 141cdd7f964a78815be144a785c6a2a298c54230e73039e2
+CT = 22d2c8ce48e09a5b7470b909f66e5b8046e709ee2563c4bad6251a5fd375a48583a6d0f8eb75cbb4
+
+Count = 256
+Adata = 80214108b16d030feff6e056c9a07a00a1d5e3ebb07abd3f4a
+Payload = fa2441cb7f9d072b8a3f1a496b2be6728a38b94a4f44c9be
+CT = ccea547aa137e5f1a5aee7e718831f50541af2948d1734e6af1dab0f105414293cb130bea285fd6a
+
+Count = 257
+Adata = 8b9fabe29718a8f297c9bf6f199c80bbc71f94eb3034a11ecb
+Payload = c8ce88ab40b62229223d46cc44f21bb39cfef27aa9fdccad
+CT = fe009d1a9e1cc0f30dacbb62375ae29142dcb9a46bae31f51cc3f7640a42460be877fb7059a3ed61
+
+Count = 258
+Adata = 8812f28a0cd5fdaa226fdd44ed857241007377057be3bea577
+Payload = cf59f75ca4d6d216cf8862b44b5192c382c140f862def117
+CT = f997e2ed7a7c30cce0199f1a38f96be15ce30b26a08d0c4fbbe0ddd2e7f4aa2024b3fec9281b6cac
+
+Count = 259
+Adata = c8f05e96d703a4850bae1421ae9ff3aec7531baf9b899dfd75
+Payload = 4eed58f381e500902ba5c56864f6249d191e14d1b1fad3dd
+CT = 78234d425f4fe24a043438c6175eddbfc73c5f0f73a92e85e5df1e5e96bb84f730fcb253d468278f
+
+[Alen = 26]
+
+Key = e19eaddd9f1574447e7e6525f7fd67e3b42807e44fbb60e75d8c3e98abc18361
+Nonce = a8c459ce0223358826fb1ec0f0
+
+Count = 260
+Adata = ef88f4393d6c1e7b7be55a12144209ee051bb779e440432721ef
+Payload = b3b0de10b7c0996662f1b064e04e528b7d85ca1166985d33
+CT = d63e6082c95c6c5ff2bc0771321a4f883ef61cff7b99e0ea8a20a1abe7c842ebc08c8c81a2743c81
+
+Count = 261
+Adata = a4c891c9dd1fcc982c35bc74cfe71651bae424602519672b466d
+Payload = 4f0b40913f07269550b7b06ab9027a4d9331f8ef98a45dca
+CT = 2a85fe03419bd3acc0fa077f6b56674ed0422e0185a5e013845e2d6de83ab729dd200a21088a1ec3
+
+Count = 262
+Adata = 4db5730cb9794f3b1facc9d6738115d02ba9f27ba02330fbb856
+Payload = 841e032773d58bc72a3237bc9b24c61b9efdd850fc2ea605
+CT = e190bdb50d497efeba7f80a94970db18dd8e0ebee12f1bdc10ed272c732247a696a608ef67510f9c
+
+Count = 263
+Adata = 471a900ee49f2cfa1d3eb37c951d810c349364d4cc3b5b64fc47
+Payload = b4db42e523e65557157b93dc0281601f7997e6731543a914
+CT = d155fc775d7aa06e853624c9d0d57d1c3ae4309d084214cd15f0df52e392c37ec15f7458469dae84
+
+Count = 264
+Adata = 7b40b3443d00a0348a060db109e8882157612c43084ac5c3e9c5
+Payload = 73e0ed35c0e847188e607cde46586eb9e237fbdc5d59163c
+CT = 166e53a7be74b2211e2dcbcb940c73baa1442d324058abe5421433dafea2b5484ba87b5050e1fb49
+
+Count = 265
+Adata = d563f5c048a1b45265182b99ca7b9004fdc73a9cb07806dd44fc
+Payload = 4f7669caaedee961dbba6bde9d09fee1a20eee55baaf98f5
+CT = 2af8d758d0421c584bf7dccb4f5de3e2e17d38bba7ae252cdf91749fe3cd52a9431d9a847a8c2a9a
+
+Count = 266
+Adata = d301a61eb17366d4e70942ab69b4f4bcf8ff6a97f5972ee5780a
+Payload = 154454fb74e9565c56775a8e4654f75a38b954dd28c4e939
+CT = 70caea690a75a365c63aed9b9400ea597bca823335c554e07563d37846f5185bb44d71be1ea6a73c
+
+Count = 267
+Adata = f74b48d168f77fbd3429728c0b168ecbd854264eaef70b74fffb
+Payload = 716b371857e68a17b20ea06651cdcfd4560a741830ca8a13
+CT = 14e5898a297a7f2e224317738399d2d71579a2f62dcb37ca55e93bc2d3f05d7016747690fb920e12
+
+Count = 268
+Adata = 3a257ce3592a8f88162f0bb4ecd5db3bb79b54ab17b0bbc61506
+Payload = cfdb7363985aa01af6f8e8237dbfb7871eb39303b4135269
+CT = aa55cdf1e6c6552366b55f36afebaa845dc045eda912efb01c46822f839f09c41b7aa6dc06035c93
+
+Count = 269
+Adata = 21916ebeca9e66b77cf55d1cac80a4c85d8b6b014f268ffa73ca
+Payload = b4b67ac551d1966caa20d951351387f384c2e5d81a76a92c
+CT = d138c4572f4d63553a6d6e44e7479af0c7b13336077714f54f8e77600c5bbc6d028fa25ba61a1719
+
+[Alen = 27]
+
+Key = 9498f02e50487cfbda1ce6459e241233bd4c4cb10281dcb51915dbc7fb6545c0
+Nonce = e3bd4bc3a60cddd26c20aa8636
+
+Count = 270
+Adata = 70cfcb828d483216b46c3cd22e2f9ee879e9e3059b566179b6e16c
+Payload = 0d16cc69caa9f19b88b05e151b3d26accd018ca4a5786a80
+CT = f1c4bedb8d6f91676881daa37656a7e6402f472735b04a0f1f8332f4236437737438e7aa1b5100c7
+
+Count = 271
+Adata = e7e5779282db80f424dc050b2c1e7754b2a5d3a8beae77beb74e34
+Payload = 148de640f3c11591a6f8c5c48632c5fb79d3b7e1cef9159c
+CT = e85f94f2b407756d46c94172eb5944b1f4fd7c625e3135138be2f6f356c2eb401468be15104e7763
+
+Count = 272
+Adata = d17e8189a94a559b07be9549f73d653172740e8e978f5b0a38ad43
+Payload = 00a23b25bca7c206edd051814d81083db1cd00048ce8ead5
+CT = fc704997fb61a2fa0de1d53720ea89773ce3cb871c20ca5a9646f2b6c2455603f1a6f20ea5a4611a
+
+Count = 273
+Adata = fda37ff136895de7ebeaf81e701e5751245201baed2e13d7e1b591
+Payload = a89409b0977f60a029dc4c1560ba6dbe7c65b068633acf74
+CT = 54467b02d0b9005cc9edc8a30dd1ecf4f14b7bebf3f2effb303fa5d8321241b1c9e18a5909d6e428
+
+Count = 274
+Adata = 9c179fd0d6277a5e073e77dd6abb4cba00ad9c9932e6c002b951c7
+Payload = e16c69861efc206e85aab1255e69d6d33c52cf058dec9d0b
+CT = 1dbe1b34593a4092659b359333025799b17c04861d24bd849e8cb01db1da077502814db1610662ce
+
+Count = 275
+Adata = cf5703228e615428d3d3805e428e754961d205c5aa0297ecdea71d
+Payload = 62036cbed3666d85624d3dc9c1f437454b9ab5c03ce0de92
+CT = 9ed11e0c94a00d79827cb97fac9fb60fc6b47e43ac28fe1d40a02a49857d7b280330b8105efac854
+
+Count = 276
+Adata = bab7e36098d59d3a31d7784d549aebfc6938bbd0612c85c0edb796
+Payload = 790ac86c5e9d8ce8cbec1dfb7e4fc4dca3d0b1039adfe585
+CT = 85d8bade195bec142bdd994d132445962efe7a800a17c50a5ecfa9dd03e2db70aa212ee7dcb573fd
+
+Count = 277
+Adata = 96f0b7cd7439721d4c9cc4f69585f8c90a95bed8fea22150efffba
+Payload = 3cfacd61ea3398de20ca6bdb00e81af482320614bdfb8642
+CT = c028bfd3adf5f822c0fbef6d6d839bbe0f1ccd972d33a6cde17a7a0cd162945a3616892e101e3e93
+
+Count = 278
+Adata = ee71e53d0b4eef82575c2bd38d7bd21b41fabe58c6f571954fe159
+Payload = d75c153e34ae1c6d1fcf5b1052190d8882041e1f9c5490e2
+CT = 2b8e678c73687c91fffedfa63f728cc20f2ad59c0c9cb06d15fadc2d79841d230cd55c04379f22b4
+
+Count = 279
+Adata = 18a4aa894861c7720ddb43809c3d2ed2af2f1bfe8f9fd4f872c14c
+Payload = 0e728056c7c64214be8f1f1727408d8cca8c42e2ac7bf67e
+CT = f2a0f2e4800022e85ebe9ba14a2b0cc647a289613cb3d6f1b229b9bae4634eea6b723f432e19ae55
+
+[Alen = 28]
+
+Key = 3ac7d5bc4698c021e49a685cd71057e09821633957d1d59c3c30cbc3f2d1dbf8
+Nonce = 54c8ff5459702aac058bb3be04
+
+Count = 280
+Adata = ecbd7091732e49c0f4bda2e63235ea43bbf8c8730f955f9c049dd1ec
+Payload = 89198d3acc39b950f0d411119c478c60b2422ffe7e26e00b
+CT = 7717b8e4447afcea1eeebf3e39ffdab2f52828e7931ef27e475acd27900478f09fec1f479ab3a7c8
+
+Count = 281
+Adata = 9a04820205234795ecd540b6a0b2fbd0b19f18106c42f374a2b98425
+Payload = c0f61950f98110db4226e269cf197c7e2794c5b87ad68cf9
+CT = 3ef82c8e71c25561ac1c4c466aa12aac60fec2a197ee9e8cf7b7ed6e8ede6ef5a73b484bf13b3424
+
+Count = 282
+Adata = 0e4dbd167da0240298f4795102ef18ff9a8772c6fd73b3374cdfa30a
+Payload = 7960dbc9136880e2eea7956c3271adfe2aba7dca53da917d
+CT = 876eee179b2bc558009d3b4397c9fb2c6dd07ad3bee28308e47d08ea0788f7ca0ecd846689c8027a
+
+Count = 283
+Adata = 2de4291068a5d290b599a73c6a8ecff4f9fd6c9cc48f14c233e18581
+Payload = 0c5d7055bbfbd2bc213cfbbafa763b71b1fde6f4de96fa59
+CT = f253458b33b89706cf0655955fce6da3f697e1ed33aee82cd081f66b1c7b70718dc50367c3da6792
+
+Count = 284
+Adata = dedeb714f555575fcedbd9de8171484090e6466dd4fba3c6b7c42eae
+Payload = b5654edcc8f09e4f80d0258c9376d7c53fb68f78d333b18b
+CT = 4b6b7b0240b3dbf56eea8ba336ce811778dc88613e0ba3fece672883438da186741e6c542b3f805d
+
+Count = 285
+Adata = 03d340904ace1cd52d4b72a96d96afd77aee68ac3936415005ed0d56
+Payload = d796f3409a7eeb896c3d4ebef46e9c6e553aab28b1cc4a90
+CT = 2998c69e123dae338207e09151d6cabc1250ac315cf458e5cf58d4a5552bc8ed1b1dda46703a256e
+
+Count = 286
+Adata = c67f9aa8cf1be3b4377c30c175d33ab2af390982c6a015d99209acdd
+Payload = e4dd279a79a381c68de777df941a4779e50a1381c8aa9122
+CT = 1ad31244f1e0c47c63ddd9f031a211aba260149825928357f95cf2b57e06de4d01bbb6c0e39f37e1
+
+Count = 287
+Adata = fef1b2ccd661b9fac85ba005addebdf8317ab104920549d3a490a21a
+Payload = bbf0c267d952aeb6f810601b9cf1962a92dcaba7273e6902
+CT = 45fef7b95111eb0c162ace343949c0f8d5b6acbeca067b777589cd12984286af98908db88920323c
+
+Count = 288
+Adata = 693fae7af84aa397f0b2baaed9b3c7953f75e7424c49b6349c2fc20f
+Payload = e8b13a263e0c4fb5645e500e88ab8074ab7d92e5a8dac6aa
+CT = 16bf0ff8b64f0a0f8a64fe212d13d6a6ec1795fc45e2d4dfee8fc441da990dd92c0caeac9d956699
+
+Count = 289
+Adata = 85e5df4ddec99f0bea14b3338b2eb190ab6584f5253c6c2ee3064637
+Payload = 067de2869333ed22c7b63ed7eeba1301bbac69b0d430adb5
+CT = f873d7581b70a898298c90f84b0245d3fcc66ea93908bfc0d502f5434bea8c3c13ad5422ff90e218
+
+[Alen = 29]
+
+Key = 948882c3667caa81c9b900996e3d591e6fcb3d08333eeb29911e9c6338710c17
+Nonce = 43b0aca2f0a9030f90559fa6d3
+
+Count = 290
+Adata = a516ca8405e5c8854e667921b5c5e1968bdd052915b55ac9984b7eefb3
+Payload = 8b9130b0c3c15366831bbb19f377e3209a8dbf7619cd09bd
+CT = 4646b2acdeb11174171da23999cd54e297daa32bbc13d30512e57c576b315f48c11877178389aaa0
+
+Count = 291
+Adata = db3121ea71294983b185207a9d8de3e484a66c0431bf07c962eb82977c
+Payload = 7f369bbc99b6f08049eeb43566269a174829d4dddb05cb9b
+CT = b2e119a084c6b292dde8ad150c9c2dd5457ec8807edb112366775e693f93af6575dccc7903538065
+
+Count = 292
+Adata = 1651cf38fd9b2da65ebb4922b97dcb861128eeefa060d6c1c94b25eb4e
+Payload = fd0900b5fa72e2fba43d611bad25de40a3507a5cc5d186c7
+CT = 30de82a9e702a0e9303b783bc79f6982ae076601600f5c7fb70d8de40c2068de96a274d3b5086b5a
+
+Count = 293
+Adata = af87b347b59e37a424004a00907dcbcf6a554e6782a9be12cb3047625e
+Payload = 36318d80c02a1da41ef1652d9a752e155526b5f597fba226
+CT = fbe60f9cdd5a5fb68af77c0df0cf99d75871a9a83225789ee7da096d2fb28f20f64a000fe93e96e2
+
+Count = 294
+Adata = 0680d5bacefa2ab14aa12b0e517a1432862d4215dc72dc4d5ac6b96c1c
+Payload = 7a29aa2994d11215ab3ef3382b3db6ed581164a235c4b1d1
+CT = b7fe283589a150073f38ea184187012f554678ff901a6b69b88748a2de31261534cdb2237565bf8a
+
+Count = 295
+Adata = 9af701f0a9de52309267289bd170fb97c03c131c0a169d736137ff3d74
+Payload = 3542fbe0f59a6d5f3abf619b7d58b199f7caff0205093f8b
+CT = f89579fce8ea2f4daeb978bb17e2065bfa9de35fa0d7e5330c003eb65ceedc98ae4e38ef341ee47d
+
+Count = 296
+Adata = dab7845fb7ead205569475753c7e26540c09d3a74312f2de25181511f8
+Payload = 83c15520d9541c86b3dd809ede42de22bbb2b75ff18a023b
+CT = 4e16d73cc4245e9427db99beb4f869e0b6e5ab025454d8835c2fb596d8ff6a863604cd224fa3be42
+
+Count = 297
+Adata = a844d6dbd05545ecc736994dc9fc2260c5ab63ed6ffdc40b915f8744a1
+Payload = 793a188fa3efa32f41d6e4c5b42353b95024117d546c79ca
+CT = b4ed9a93be9fe13dd5d0fde5de99e47b5d730d20f1b2a3722ac782e2cd8ecb06172eef2cb9b0e331
+
+Count = 298
+Adata = f9112503884615c0e8a1d8414724b0d19298988f393a27c436b2b6734c
+Payload = 6b237444fb0e1f4150701546c4cb24021c5edad30d9b31dd
+CT = a6f4f658e67e5d53c4760c66ae7193c01109c68ea845eb65f814492b42571033f4dffc0282ea2f51
+
+Count = 299
+Adata = d633a5a3defdde6a68f959ef39a91c6ea6e13ef1a7859d2c2c94d3a5b4
+Payload = 6342312e8a72f71f2e5afe04cfcde4d60a41556111752103
+CT = ae95b3329702b50dba5ce724a57753140716493cb4abfbbb75999099df2de6e436bd99f0341423f4
+
+[Alen = 30]
+
+Key = 3bf52cc5ee86b9a0190f390a5c0366a560b557000dbe5115fd9ee11630a62769
+Nonce = f9fbd02f28ecc929d369182752
+
+Count = 300
+Adata = ebf0b3e3199a5c3773c761c725c7600add5f9d8321c9f8e5e5fd1c7a5d2f
+Payload = 094b538110495e938b08cf748a6bcf3e0c80ff9c66570237
+CT = 4d8b53016fc8bc9677184c0fa15bbd3d671b9366d82ecb67f8562eadcdcbcdbad1299bea1523f5d2
+
+Count = 301
+Adata = a865b88d512e485ab3f2844c29e6dde0cf1151efa9ad3b3021d06fffb74b
+Payload = 23edddd8732cdbf03af08162f0e4a24c9222bdbb4549c663
+CT = 672ddd580cad39f5c6e00219dbd4d04ff9b9d141fb300f3359ff77cf0962455b3539dbf91f3077cc
+
+Count = 302
+Adata = 16918dbc785d94a8f1720c5ad234dde860219874c9fb076a5c290903f85b
+Payload = 1798286c37c1504fc0d7402681f6f70711ef506dcc3e29d0
+CT = 535828ec4840b24a3cc7c35daac685047a743c977247e0806dbed76d94c90595b49d50c84c3efc76
+
+Count = 303
+Adata = a2969243b0955402ab45a430fef2ef9e0c025006732bf8e592e3d3884918
+Payload = 0d02778f90a164a4f9ada9dc7fd24eeb941069621418ef32
+CT = 49c2770fef2086a105bd2aa754e23ce8ff8b0598aa61266248fbe60c146056e5cb01268403e4b9f5
+
+Count = 304
+Adata = 2de5222a0609f058f60e9e581b6e4f0ddebed84fc8302c8e985d17b89241
+Payload = b0c3858231e284af6d231f043b95772f5e7b16a34ffcd2ec
+CT = f40385024e6366aa91339c7f10a5052c35e07a59f1851bbcacff35df1ec942b43eef5aef980cb038
+
+Count = 305
+Adata = 3fc7453df038a92829dc103d44b63ad097d7cd7f9ae7996547012090c7c4
+Payload = 319f396cc02834f8e69d65f77496d0eb31ce1a7b7e324820
+CT = 755f39ecbfa9d6fd1a8de68c5fa6a2e85a557681c04b817091a93f5fc28e5f4f351cfb888da763dc
+
+Count = 306
+Adata = 18f1e92bd3c4a597ed970911d03a78ff9a6790147c9bb0ca5f23b70cce7a
+Payload = 25550c03f8fa02b3781330f96e0fdc58681b0c0bc5e83fe9
+CT = 61950c83877be0b68403b382453fae5b038060f17b91f6b92c6a90ef2e9a969ec0576fae1d126a85
+
+Count = 307
+Adata = 09ecb2406054716418ff3600c3c5cacb0845a377a2d80542abc36ec81bb1
+Payload = 210ff7975e08388b9a46eb732230e3a3856a497549b5eb49
+CT = 65cff7172189da8e66566808090091a0eef1258ff7cc221959fd6aeb047200907911621e8756b45f
+
+Count = 308
+Adata = 62d515bb0525b565a6a3613ae20343c8da7424c8368e8cad6a862b7d37a5
+Payload = 5d867265965bb2aafebb0691de9e157a24066d06fe3cbd7c
+CT = 194672e5e9da50af02ab85eaf5ae67794f9d01fc4045742cc4db6d5fd910c83fd77aefba3f7665d8
+
+Count = 309
+Adata = 00617ca141e55b045a188e4934caf6db63d4577f634db92c22010e1cbf1e
+Payload = 396b27afd16a1081f37bbc1f742b549f5f68df799b93083f
+CT = 7dab272faeebf2840f6b3f645f1b269c34f3b38325eac16fdf5f21f32cbe5d272004f1c104cbcae9
+
+[Alen = 31]
+
+Key = e45bb1730d0d539aab3805350ac986540de9f0f6c239ee70395c291397b70309
+Nonce = d5c7824af715bb7822b6b340fe
+
+Count = 310
+Adata = 860f4a09ad8b3d345c2aa18ffb803f0bc3b734a4d047a1437701a5e3d95288
+Payload = bc8b3bc48c7a88c9fafde258b6ccaa9d4f0d018703d63871
+CT = 95f083ad6bbaee6ab540fe023858f8baf25e333fd3e89c00e678a392d228b210dc5c991905dacf3f
+
+Count = 311
+Adata = 8a84b57915bdbe7bf5a1c1a426512b3c178d883251cc46c95a8bbc8ed9e56b
+Payload = 9499ea48edab9bc21b91dd614f04934ca20db8630622f481
+CT = bde252210a6bfd61542cc13bc190c16b1f5e8adbd61c50f010fbdd3b305522dae6b652322d89d9ac
+
+Count = 312
+Adata = ed8540f7ce451c522c1ff5d2d1030d7b3fbd1219a21aaa84044c4f23c08f5d
+Payload = 73843a4e9e7937fed24bb1fae15822213b1aa86c07f1b5d1
+CT = 5aff822779b9515d9df6ada06fcc700686499ad4d7cf11a08b6b08548e794eaf85ad9f5de80b1c00
+
+Count = 313
+Adata = 61bb196b212feab645f05a8aa1986f6210a384c15bc749245d840b3565fb36
+Payload = a8e24266e5981b2ed14213a29f961cbbf7f02f63a33c987e
+CT = 8199fa0f02587d8d9eff0ff811024e9c4aa31ddb73023c0fcc73643a7ee9291e15137d7046a92f3f
+
+Count = 314
+Adata = a49c2df94ba65107f375ce1c53b72406143f6bcd270945de5b7811682fe361
+Payload = 3e3c402caeca41687d12897102e04312edf7b8c7d8567a22
+CT = 1747f845490a27cb32af952b8c74113550a48a7f0868de53204438662ea82f423a69c6e4e3c0623a
+
+Count = 315
+Adata = 7c48480e9bc87ba299e03899698b2259eef150ee0f2efff40a5583b80ab484
+Payload = cfa9292b9052ac6bb863205d3c0dc2d9e20d2ba6a680d2ed
+CT = e6d291427792cac8f7de3c07b29990fe5f5e191e76be769c6ea00b9cd881e3f4b1e838dfa31f6560
+
+Count = 316
+Adata = 5cf9744090366d828b477dc890eab8ebebd44f6aeaa5b101291bf67d12867e
+Payload = e0fe4e139ab0deb4fdf2145b719f35c50b869e6cb20608b5
+CT = c985f67a7d70b817b24f0801ff0b67e2b6d5acd46238acc4c59b3b87d722a58cd1de58f3963d12b3
+
+Count = 317
+Adata = 761d74be5fae170a1bdfa16081b44c1e49972e15ce0818df1390bf7204f619
+Payload = 665fdcdf55a1231e9912562eaa5a5011d69f6948e29e3f8f
+CT = 4f2464b6b26145bdd6af4a7424ce02366bcc5bf032a09bfe158759886124f1f0ce8147c94f4e7114
+
+Count = 318
+Adata = 9815353b69d0b4effa52cefff13703fa71a6296f9cca0f02568661be4b64cb
+Payload = 7b2d52a5186d912cf6b83ace7740ceda3f5f443530c5a49f
+CT = 5256eaccffadf78fb9052694f9d49cfd820c768de0fb00ee6310a79c9932456dbc00515b264f3168
+
+Count = 319
+Adata = 69dd1a050c8d79dafbbe3403af4dc1f070b9b2b980888aa796e6cff68d9060
+Payload = 3cea5ff50167c5641066852fd00061df35b1f66bedb894b7
+CT = 1591e79ce6a7a3c75fdb99755e9433f888e2c4d33d8630c6da7e97f9984a7db3b93aefb4316d9acb
+
+[Alen = 32]
+
+Key = 2e6e34070caf1b8820ed39edfa83459abe1c15a1827f1c39f7ac316c4c27910f
+Nonce = c49ccef869bb86d21932cb443b
+
+Count = 320
+Adata = d37e35d7cdccd9824a1ae4c787819735e4af798a3beb49d4705336d6496853ad
+Payload = 771a7baa9cf83aa253349f6475d5e74dba4525307b022ba7
+CT = eebac2475004970071dfa2cfb855c4e78b1add8dcbccfc0bd6b14027324b657a56263df148665393
+
+Count = 321
+Adata = ab22bc22bf2628b0e0ab245c3db2fc5128d13a011c2cc9b9fea05a79a3410704
+Payload = dad95a4b4d3754613f0542caa62cfe4e375dfbdd369ec32e
+CT = 4379e3a681cbf9c31dee7f616bacdde40602036086501482a8c810b6944815fd2e434193520b1d5b
+
+Count = 322
+Adata = c48c5aacf701137fc40fd0d3649641aaa5be427ceee702cf7ddf6408f458a581
+Payload = 3f28df9263e473be648fabad163aa4142b633388b16d8392
+CT = a688667faf18de1c46649606dbba87be1a3ccb3501a3543e8aa447b79284c588bef50b423de97908
+
+Count = 323
+Adata = 477c2484cf5c56b813313927be8387b1024f995e98fc87f1029091c01424bdc2
+Payload = f83107b50a1f192ed45cc43fa80e6b519bfd859173ea9ee9
+CT = 6191be58c6e3b48cf6b7f994658e48fbaaa27d2cc3244945d4f4a413eb3ac2c474134995d4db9a16
+
+Count = 324
+Adata = 143bc037f1d0bd4ec16825c58cb3796bf8989200d27bda9beabbbc49247f59f7
+Payload = dfeb324ba459ec4a5c54d2534e98002412e67db19cfc66bb
+CT = 464b8ba668a541e87ebfeff88318238e23b9850c2c32b11756a3fb2e06734b28fbd57942a609d914
+
+Count = 325
+Adata = ffc416f1dae4e43c1a01339a604c44d6a0f25ab9ca3978c6aacb6d270d510ee6
+Payload = 0765949e6f22c422ebd47dc1ed73f1b849d7a058a1656fc2
+CT = 9ec52d73a3de6980c93f406a20f3d212788858e511abb86edb94280d3c4a1cd8cb00705f60ae36f2
+
+Count = 326
+Adata = 6090b596b4082ec6926576137f6561cf13916860ad1cfc43650d1b5142a12041
+Payload = 6db320cbe76bc5b8cee9ef89aca11765571c6c501993195a
+CT = f41399262b97681aec02d222612134cf664394eda95dcef612caca26cc3bbb289da3be0616b3445f
+
+Count = 327
+Adata = 178ba75adb7c5bea6769270bb3b4f6ce208d4a786913d3ced7bb4090b5f65544
+Payload = 0875020959ed969cfb38636d1d5aabce9658b00171a7614e
+CT = 91d5bbe495113b3ed9d35ec6d0da8864a70748bcc169b6e26cc8c665289d907628eb0e299c2d411e
+
+Count = 328
+Adata = 90f0474dca998916075b1b1428df14d90be05491bb8d5d88e32e65ec890ba9d3
+Payload = 4f89ca6ad371f86a6e073ec12fb1b928bb10d6639233b918
+CT = d62973871f8d55c84cec036ae2319a828a4f2ede22fd6eb4f7e481607a2a0529f9cda1d5903325b7
+
+Count = 329
+Adata = 5ad8dd40ecdce52d5b30424ca0bccb666f34f66b0c9a4c1260051ac04ca06aab
+Payload = fe2009d0a4a1711b83057b948cd0b174a3a042fd97579ab8
+CT = 6780b03d685ddcb9a1ee463f415092de92ffba4027994d140a1b9ba2bfe5bf778b859f0ff0c29a67
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VNT128.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VNT128.rsp
new file mode 100644
index 0000000000..b796541cf5
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VNT128.rsp
@@ -0,0 +1,456 @@
+# CAVS 11.0
+# "CCM-VNT" information
+# AES Keylen: 128
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Plen = 24
+Tlen = 16
+
+[Nlen = 7]
+
+Key = c0425ed20cd28fda67a2bcc0ab342a49
+
+Count = 0
+Nonce = 37667f334dce90
+Adata = 0b3e8d9785c74c8f41ea257d4d87495ffbbb335542b12e0d62bb177ec7a164d9
+Payload = 4f065a23eeca6b18d118e1de4d7e5ca1a7c0e556d786d407
+CT = 768fccdf4898bca099e33c3d40565497dec22dd6e33dcf4384d71be8565c21a455db45816da8158c
+
+Count = 1
+Nonce = f7a5098b2a4d92
+Adata = bc498326755503ff25d02805eb3517221b54eb4fd79af0fcdf9312b2a9ad95f7
+Payload = 3e2144e2a381b718962a77e167778bf579957a8fae29612c
+CT = 98ce91033fabaa8fe853d347be6cbe5de102fdccf042e7be697b41c9a69acaf8386140ee6e36f406
+
+Count = 2
+Nonce = 732d2dd64b4a25
+Adata = 495b03df82e317e4f351c5323d17c673f4c77856983179d7c7cb75c2b0573c72
+Payload = 4bb0d170bdcc70fd18f19605cf9c6181082c4367f1e6fbce
+CT = 9bd9304259962448fa8487bc15d950303621213afd88f1e32d442ff663242fa269c4a742a220edc5
+
+Count = 3
+Nonce = fefd3ac595428f
+Adata = 91ffb6be8e129cef9189f7e0fec8e937afcfc6083b6a79a778a724bb3e8d0794
+Payload = 9e8c4f1292e8d7e5179b34ae5d2ba2491d7754acc54bb91d
+CT = a5d012b3062cc93b831860d76539169c88854b85550c67fc564a2f1cb7d77e0223287740d5ff9003
+
+Count = 4
+Nonce = e14d81ee3b873a
+Adata = ecdc5249ceb48e8d5a4483043921c00c1acb1843fae00155a28f3a127150b1c4
+Payload = f99e23288e6b5ae85c14610994d90d5fcbcab62b4ed1333e
+CT = cc4ee711d0202deb58664e00cf0cf70b737f48ddadcefd6cd217fb611daeb66fa2d8e1bd43cb2131
+
+Count = 5
+Nonce = 2cbeaba94dbbd1
+Adata = d129674c6c91c1c89f4408139afe187026b8114893d0f172f16469b183fee97e
+Payload = 1b42cb685bd462fbd40e0273a81c767aa81cb43f17d3c0c9
+CT = 1a1b1c7130aa63098dea17ffbb2216d1d276cb10145b0762a45116736e95d823e579d73dc31dc487
+
+Count = 6
+Nonce = 8a961df9c23f6d
+Adata = 07185502bf6d275c84e3ac4f5f77c3d4b30d8e106603be84410c11849a3c18ea
+Payload = 434e182d04ecda519a6119fbaa4c45e8c9803a9a3eb51dae
+CT = 3f603939c6226d8208b2b0e675b82557609ceaeeee4032c7837ed517dbd7e6fe34ea42b01c69d370
+
+Count = 7
+Nonce = d3604d390faab3
+Adata = c95e7329d36145664da69d25f24b301d334e1bca2baa74b2d5c325ed7d04fae4
+Payload = ee104be898a225eb1da99163bbf768d8ae6d5850af6f8767
+CT = 3e6a7683d9d804f791f77d2b69996102ba82477ec4557747ef2e0b322f51abb366a1e8e37f4fe4ee
+
+Count = 8
+Nonce = db5004a1cdae8e
+Adata = 1370fc9d5bf1ad2d071be5a28b235402a85270f536b5601c221519a3b329c71a
+Payload = 59bee7d18fd4ba573f3e4f61076f5b9f6a3487e47d98c729
+CT = 6db54d6f5c3f3efa6da67aea1234d46e8b679a5c257c66d82e4ef944778281ed186b4a8099b47fff
+
+Count = 9
+Nonce = 783477f981ef05
+Adata = 04bbf2a826bdf3d55069b1936c4f8e8e08189f54066a035c950c7347604b1b65
+Payload = 6150f132b25727ebbaed9f16bd91ebce00c68e5b39bc0ef9
+CT = 36f78cef22cacaf9f3d4464821737f7fbacd79be517b4727bc5c098625c51ac7fdd15da2cc9ef4b6
+
+[Nlen = 8]
+
+Key = 0b6256bd328a4cda2510d527c0f73ed4
+
+Count = 10
+Nonce = 21fd9011d6d9484a
+Adata = 66ff35c4f86ad7755b149e14e299034763023e7384f4af8c35277d2c7e1a7de2
+Payload = 78a292662b8e05abc2d44fbefd0840795e7493028015d9f2
+CT = 5a0be834c57b59d47a4590d8d19a1206d3c06e937a9b57f74034d9fdb43c3f48932aa72177b23bf6
+
+Count = 11
+Nonce = 97f940d7c1230bd8
+Adata = 78337ddfe38be7897372b0f805603a9a9e55598452285764641c3bb7aeb54a3c
+Payload = 772aeff60eb3adf5a9589ad54dda0401cc9765589609dbd3
+CT = ef5c408dc6d0b501925a47def54d8deb9880a07a3e6380bca20a3995cf25c5a7b9477d8916adff73
+
+Count = 12
+Nonce = acfdf302ed116ac4
+Adata = fe9d9989bffae3c9e6161eb0aa9d54ee8f5051f0dcabb5a750c5478c11798ce1
+Payload = 99ffe16de323a9b65fe60305a2d062cae490ccca6d9fe9da
+CT = 1bbc2c7877d845591660636cb6ccf4edcd4c156996a26a707d0e2fe322f203c08f44d7f9bd7258c3
+
+Count = 13
+Nonce = c8d36e13b7459c47
+Adata = 3f3c3a4c26dba18f385274ac5ac3df73282686488d91bc8190b7f61071b07f62
+Payload = 316ee95430329f706348886b8ac7779e3056809e25da0a03
+CT = fd2db9611a26a3e90f4861467df60edcc595f442332b089905fdd72307c3355b19ea66d4a16ef17d
+
+Count = 14
+Nonce = 5822755a3e47c27d
+Adata = 1d72d6b371e85ca359483761704f80b3360f4d6610e6d5e490b0d509f73c3233
+Payload = af4ae8f19cf6cbd199677fe033859f56906f1979b1b5926d
+CT = d5ed6f8d5c42f4f3ea527094173b278724a2ba787e416ad759124db19ab1373a5376f46ec7095ef4
+
+Count = 15
+Nonce = 6c1c94c2e71b865b
+Adata = 298cac1e4684182786f386ef3de79c11e30b2dab7579b8ca18d0312200860403
+Payload = 6e4d992d7541e02a4aa167e56c7e47206abc25fea6c5125d
+CT = 560cd43a502a6e8b1af478a3b640a68937d1a83057110d38eaa52d69ab9790edc384b9a5d8c91dbf
+
+Count = 16
+Nonce = ce7ec65cfeda31da
+Adata = 13c1298cbf7fe6a9ab378f86d3c2207944cc2a232f9383513ceb3b202086d365
+Payload = 196c80d02b663bdd89fdaa31e329b5a8f7c596236ee8dd80
+CT = 00174dd83a7f8edc71afbe5da095160336be9184f693db3db1f45de395e021c6fb1b2991c91bd643
+
+Count = 17
+Nonce = ddb739acda6c56ec
+Adata = 7f89bbe513b9a7ebe9be3f6eb88782080593c83e8cbe47fbe15bdc3e5782090f
+Payload = e95e142217c838d1f998a52e342e4f2d80b1cfd35cf6b73d
+CT = 819d73dadaf095652cf39729b2e2cad7fc7783887a5acc15713d941b845d96a5bf65e9f80ae7f923
+
+Count = 18
+Nonce = d9bb71ad90152d5c
+Adata = 20bfcba120cdbeb07c5f4d70338ffce493822d78a03c9e80b5b934e16e39f70e
+Payload = f1fe98b50ea2f9f088f6f93910757cf744d5aabf3081966d
+CT = 36decda8ade6ab104a201c6d370412b907a559738eef59665e99761cb1ac77d772b9cce9345d9a75
+
+Count = 19
+Nonce = 2c9ec9f1f1358c50
+Adata = 96f0b1edec4ad14407dcaf30ed68942b46c48d58b2dd63af60fccd5bdd48e560
+Payload = d74badb8ad7f2c2bcdf67e497151d35a4fc2a3c4c871868a
+CT = 0e9066270da6e03cb4307c43adc71b4b596213a63fc8032085ce60506ac3bd97327904ad2e072a6a
+
+[Nlen = 9]
+
+Key = afdccc84f257cb768b7ad735edbd1990
+
+Count = 20
+Nonce = b7776aa998f4d1189b
+Adata = 9f9ac464de508b98e789243fdb32db458538f8a291ed93ddf8aeaacfbfc371aa
+Payload = 56d0942490e546798f30d3c60ad4e3e110fc04f5b1c1fa83
+CT = 96f124c74fd737819008ddef440320f4a3733d0062c83c893e259aecf12ba08f2a2e966a3341d6d4
+
+Count = 21
+Nonce = 278cf1f09b13f467fe
+Adata = af9627922758a9f7792345716782e8837ca78e8f9db16e3fe12a7124a3d4e99d
+Payload = aa9b9e80cef47b6db3816b1d665f233e696337e21bb8333a
+CT = 5eba7e3b3ecab78121b0d56acb9dbfc6756c1255b42f145d11751638ed36c1fd3c7268b71633c1cf
+
+Count = 22
+Nonce = 4ae701103c63deca5b
+Adata = 5872a1507c833c581ac2750b2b54add4b92be14e45d72db7679f8fa2b4d1eeeb
+Payload = e832b053854fbd40c0d8b6d6b8fd5de2da0c173f5fe594ef
+CT = 3b2b964c3a90d51c0ace186db79818b4d0f7b81236d36017d3635aa1d8167087600b01643b0a5ce5
+
+Count = 23
+Nonce = cfb5b12928e1c36849
+Adata = febe755bb8e4475d8d12f5e96269abd0d4e40d73cb966e2c523343e9a6d2d71a
+Payload = f46d6970dcc37d32d93ff062e68034c1906ee487fd28eefa
+CT = 0d5332a42fc583f4f81744b899cdf2a64cad1e78d577112fee6f8c4b252e10b42fbaf8c7af1e9f3e
+
+Count = 24
+Nonce = 68d5863cafc69e6ceb
+Adata = 048ba28abb191ded5449dfe9dc7d19f9b132a2a9fd779aab7da44d2887485954
+Payload = dd4438d7ba3edc73872e42dbbf78cf300fe4bf0eac9e16b6
+CT = 874d3ef7f916db2c2799b6892ef4bfbeb4729ecbf26ac4983a8639f21f8548fae45dc76de57bcee0
+
+Count = 25
+Nonce = ea09fbe5da0fa4fe91
+Adata = 63ee18eb720b21ee4c157dafcb8c7bcc6817f54d5c1b8dd7058c37228a03f8ad
+Payload = c1811d613bf0789beeef693611ef733cd173da703b66ab3c
+CT = cbe5c799952b28fadf414607a6cf8194e9f41194abace4541d3853a52971b0ab46cc0a3eded435c1
+
+Count = 26
+Nonce = 0021be18ed76b3a34c
+Adata = bb5eded483f0ae1106fd08c5e2b91cf06d3a7a73518ad4c479fb05e631ba5399
+Payload = 2d5531d1c51c6ea100b028596bf9f24dd90be14eab58f07b
+CT = 7af0449f7359b7f3e5f6c1e7bc264c7724037f4f16077fd0a2a8e3cfb827c7e6edabb34f7bbafd01
+
+Count = 27
+Nonce = 449b51ee0760179e35
+Adata = e99bdf783070a3a48431704e90277ca65a9704c12eeae2e2d70b62f816115267
+Payload = c4896d58442877c986e4f862a9f3a3179f0e9b96316a90d8
+CT = af7531c073df01077fd5c8ea9a5530c2fe1688d529e5c2f24aa8feae6a500919a336dbba1d9fb7e9
+
+Count = 28
+Nonce = 232114642e0c6b55b5
+Adata = da288d2014616f16a2abf5923dea49aded1748592adbcd97415c33ebfa57150d
+Payload = 11fd3f94b5a5ce94f2740a27a0771aeeac77f3155d2bc12c
+CT = f0c174a7927da0bb88e92917af8ae1df4ffc3527004e9e2d0b25cea7ed6e4fe9069a2ce49875230d
+
+Count = 29
+Nonce = 660cb6d654afcbdab4
+Adata = bd96c3c225099fc58cc1f97779304606b11efe9712fba13abf74fc1d7d44a900
+Payload = 793c0bc3deb6e0bec4c1d1fc17e455eb1aa5e9e25cada861
+CT = fa4b14a381ee41fec7b7279e58f0d06a3beec26d645f81336218635754d5563f2cd48bdbb267e5ca
+
+[Nlen = 10]
+
+Key = 6ccb68d3838d4ddf660b9cd904cad40f
+
+Count = 30
+Nonce = c4fb7519a19f13d9d1fc
+Adata = 092e64fef08b5655a86cdb8de63ffaa7772e8730844e9016141af8bad2216246
+Payload = 5ea35c082e2b190e9d98e6b2daad8672f587b4f2968072fc
+CT = cda5fe3d15d00150b99120c7f206b88a4c2c4a39ca9143425603ab284a73a38cc916f8b653c92ab4
+
+Count = 31
+Nonce = 45927852550961f1ae9e
+Adata = 53ae030474795ffda4d9ac0fc3c45afb592ddd761f7b5335c13a6747e21075a7
+Payload = 6c5f468077536b4c9a94ea4a6fe3cf621083a210daee45b6
+CT = 694847b6429cbc3902d9cb7049625aef1e97b569e1e3169035bb811491d142cf1b26350f8451bd14
+
+Count = 32
+Nonce = d8c54463dfcf02d0e327
+Adata = ff95c0ed0da32d1b5f57570b815a50592ecdc9c1c4e727e0f6dfd93fc10ce88d
+Payload = 7321a6de8d694ea05623206f5df438c5c2cdd6b1eccab4d8
+CT = 9cf8ef119aa5cf3d6305d50b2b520a0b10bcd240e27276749c68e8e641b0120f7dd66e8f0cfa4205
+
+Count = 33
+Nonce = f690f3a996928275050b
+Adata = 41c05fda535770699ed22cef253753b658437f833afe65c9c393581d835f0fea
+Payload = 56520a4bfd7b73a471e0446f9524a407e81c2681b7329e35
+CT = 14aa15f9f64c4c64f6e88094e012ecb24193249f044c033dda44a62f97c0fead3f65b28928bfbcc3
+
+Count = 34
+Nonce = 26eb9ef25be62148fa61
+Adata = 8f45608a07521de86ed5a84a851e629b579b51d7bf4cc7202a773e0f9e9d8748
+Payload = c68094c26c7f017b79f126dc26b3bbcb95f97535ca412da5
+CT = 7ba8a0c2fe2b230768d1c1874085ddff8926931961bc4558f0d5444466bcc631bef8e58fe5818af7
+
+Count = 35
+Nonce = fad21bc27dabafe7a4ae
+Adata = dc5d7fd97bb3243ba585fa0d71a07191667af418e30a6b76bedd05b32c673403
+Payload = c247fa8d8091cd3f299cdacba7fb7af93549e9e3160f9cf8
+CT = 3097d2ec0f8bf00b22504ab03a75e740d3e59c269c3ee3f00b5419293a67eb008aef0f9f675201df
+
+Count = 36
+Nonce = c911348848fe67406dea
+Adata = 50d50a0b5ed4d6904ec3045263af0255a6494b7a7e2e95ea806c4bb788423dc1
+Payload = d846c170ae0111348362901503b26d58f5efc17b6d296aba
+CT = 5d72562f7dfb47bf34b90ee4ea11ff9f726c915b07f4d843dec5a554f4bbecbf6943ffdab8d8a26a
+
+Count = 37
+Nonce = bb921b46a16d20ae4046
+Adata = 7d17f8f60ad1e61a168b5b0e7fbbc90cee79b612b6d6c0d7ff6ede042341e8a1
+Payload = 71bb6ae84262646c9be95e0f4289ffeab7555ec6746c6ae9
+CT = bac123320888b553666249756e6d63b3498760791cbe9e34e5b1162b7489a59a50c0f0f3618e6c2e
+
+Count = 38
+Nonce = 61a8b8cbfc9bdbadb2a3
+Adata = 51cf2a8949e13eaa087a34c9ec4d7fd92b862efd6a0b1fef8b016fa2c6933426
+Payload = 362f9a46aab59fb6213c83d791b2129b34367ac2de2048fb
+CT = b8a57e8714d8789f4ef2af29e0efec21b1ef67fdabc7cdf0ed5505f1f0ff77723771338585c456b7
+
+Count = 39
+Nonce = 6bc4cd23c32a913998a7
+Adata = 92fbc970b5e64198ce2a138de92767edff8d82f12f8832444b346d159657356b
+Payload = fa442383da234cf8f0c5fb667218bc3bea0c091b3a8e6b77
+CT = cdfe3e83aba43a9804c5a1832e0e47a9a153359cc32db907714025f485c7f40256049f16f859b859
+
+[Nlen = 11]
+
+Key = e6ab9e70a4fb51b01c2e262233e64c0d
+
+Count = 40
+Nonce = 74e689eb5af9441dd690a6
+Adata = 42f6518ee0fbe42f28e13b4bb2eb60517b37c9744394d9143393a879c3e107c7
+Payload = ba15916733550d7aa82b2f6b117cd3f54c83ddc16cd0288a
+CT = dcc151443288f35d39ed8fae6f0ce1d1eb656f4f7fd65c0b16f322ce85d7c54e71ac560fd4da9651
+
+Count = 41
+Nonce = eb118fb41284bfcb1bc338
+Adata = b5a6067fbac46578cfc8d3fe04108588c9de077eb009249374f205553bba9d02
+Payload = 863da00c7accf45418d47c1eda72338734dcc49cd599f328
+CT = d64de7a56146b971e21bf5784d67bab32dd837cfb81591da4a0177883346dc896eb39e8a32bc1393
+
+Count = 42
+Nonce = caba2716d07e95de83855e
+Adata = 0e0ff2c73ea5fa8f8726a3514cf906ce1610a1a6dc19b22682f9e4619f762d82
+Payload = 2af6d5636ab65db2058b2ba16df257369fc4e8aef8b9481c
+CT = 3c9e006c7d8eff5f448b0cc9c27c964713241aa7fed3665d775ea25fb272981de8b8aa0a637498fb
+
+Count = 43
+Nonce = 314c136999e41d137bd7ba
+Adata = 366c659bc45d0a88acd54ef7eeaa3e140e1cafb1b01474a065a9d460c5e83bfd
+Payload = 217b19ea6a431a1f66bd9d02b718e8507a08ab8e6f603e3f
+CT = 33d7b672b23e8b03a39ff3fd1e7b0f2be67163e3e3bae072f2aaa211dec623947a50b1252bc5aad3
+
+Count = 44
+Nonce = 6fe51f5013f53d4e4fd907
+Adata = ff182f2e179d790e827cbfd0bd8b9297ecae57ffcef9e25ef114474a22e4ec5b
+Payload = c6bf582b49dd4ab6cb33f3f88e8a4d14fe32b308ee3b4682
+CT = 26cd5dc5eac2acda283ca03354260ad57af79e20c5e92f5775ed171bb0fbaa6f431c5411cf9b536d
+
+Count = 45
+Nonce = 24bc8dc1e2354667b79ba4
+Adata = d0d48d01fc79685c6bee04d45e40d06cdf1f4607542b1ece556fc2d1bb2b03f1
+Payload = 90f52ebb1bd5439386faeaa194623285f750672a7baae64b
+CT = a7f43f56c50705a1a101044b954414fdfbe32b518e934d38f391749ea3acd624c01e4583ab1506b7
+
+Count = 46
+Nonce = 89ce46b3de3afaf2518d41
+Adata = 5767202c913584d653f37d926a0c5ac1c67db3efd1dc58fbff998778a6856254
+Payload = b2ab379a0dd15baf91415eee3a4e56e7eca54d4c1c3094f8
+CT = 9f530e455a54b86835eacd8801b34c884a3b2ac819ba38f894e43a6b1cf73cb2d6a1dd8331549520
+
+Count = 47
+Nonce = d3208eb695e84c7a925037
+Adata = 91d8fa65a6885f162a795afe2898f391990a8b3a87c11f94734dcbddf5f58da8
+Payload = f15e39f0e4eaa5bf81359d8e30186522f1a1a415436668cf
+CT = 7f1d9fcd9e5cce3a81e3495bfecec817fd7180d8bbfe0abab27fb6425fcc3537ce471425a5b17dcf
+
+Count = 48
+Nonce = 067de2869333ed22c7b63e
+Adata = c31e441fd551b3fdfbe23ceec5ec1f838f31a5300f6055ad2a936a9d0c1c856e
+Payload = 1536d9c9a09302d142c85638202f5bbf0c287f68115d51d8
+CT = b1a5c7a7fd23228dc7ea26885802daa0719f6a23681e1d65dfb879c21b46f3307ef22f1da579303f
+
+Count = 49
+Nonce = 15f61b4526d19bceae1093
+Adata = b97b122af73e928e617e98684f845be4cb80566345739b7a884c6a3eec5102bf
+Payload = 37c81988c07a5b01e2b40ff9f9ada5f50ca764efb717ff9e
+CT = 0d93a5c77482d573b7f1b8c5e283f2571efc9f54216a4c01900504a73c8817ff2b55618b2602bf38
+
+[Nlen = 12]
+
+Key = 005e8f4d8e0cbf4e1ceeb5d87a275848
+
+Count = 50
+Nonce = 0ec3ac452b547b9062aac8fa
+Adata = 2f1821aa57e5278ffd33c17d46615b77363149dbc98470413f6543a6b749f2ca
+Payload = b6f345204526439daf84998f380dcfb4b4167c959c04ff65
+CT = 9575e16f35da3c88a19c26a7b762044f4d7bbbafeff05d754829e2a7752fa3a14890972884b511d8
+
+Count = 51
+Nonce = 472711261a9262bef077c0b7
+Adata = 17c87889a2652636bcf712d111c86b9d68d64d18d531928030a5ec97c59931a4
+Payload = 9d63df773b3799e361c5328d44bbb12f4154747ecf7cc667
+CT = 53323b82d7a754d82cebf0d4bc930ef06d11e162c5c027c4715a641834bbb75bb6572ca5a45c3183
+
+Count = 52
+Nonce = 6a7b80b6738ff0a23ad58fb2
+Adata = 26c12e5cdfe225a5be56d7a8aaf9fd4eb327d2f29c2ebc7396022f884f33ce54
+Payload = ba1978d58492c7f827cafef87d00f1a137f3f05a2dedb14d
+CT = aa1d9eacabdcdd0f54681653ac44042a3dd47e338d15604e86a0e926daf21d17b359253d0d5d5d00
+
+Count = 53
+Nonce = d8e133e7ff8e0a0ec6c4096e
+Adata = ef9e432c15d8c93a4b5c0666608e61c824cd466d7940d642acd3dc33057c0395
+Payload = 2836de99c0f641cd55e89f5af76638947b8227377ef88bfb
+CT = 5edb056d85dafeaaf74bdf4caa47339d6a75bf1ee998565e9f9cdf6ab825f6e026f5be2ad895033e
+
+Count = 54
+Nonce = 2fa8120398d1a946f391367c
+Adata = 377cd407ad28dc02bd3835a31d92f8295c9dbe597f56662ceda112c588dc73a5
+Payload = 7a37255b682766a0bfecf78e5162528885a339174c2a4932
+CT = 701f5f506fc7e9ea4a27a4db5cb890f7be3b4f6bcb20f97ed3021f6ad620648b8196ab1693710398
+
+Count = 55
+Nonce = 8d638ef43f56dece910139e9
+Adata = 87ea7b095388de70ac0ed23e86f502400910028a8ab5e3bbb91d05821c0d2d61
+Payload = 7370d9b453936955b9c9d336f4b283237986232de007bf41
+CT = be2f03f6ce1731418a5f53b6f6e467b73992a0c8102d8ffc2d236162688096d80b8733d2afbcd244
+
+Count = 56
+Nonce = f479ea8812b6b2f6ac78fe9d
+Adata = 20c2b8f5d3a65a66ba8a25e2ee339a779a32d45f5db91077efae6cf308feef50
+Payload = 59ff9f7581a781808d36fed378080963f35c00ea5a6e3932
+CT = d127c956349c16e2186f55b72254c677f03c61f1c4ada9e661bb9415b32d6a58f5f7647ed41de685
+
+Count = 57
+Nonce = 423515f7bd592d6a7a240866
+Adata = 19eef6f798fc68086aad1cda6d7976cdcfe6b8af74598032972c939db300d8c1
+Payload = 3c379f90b11c622a765756a15efc8fc3ca7b08b3281945f5
+CT = 15792e01fc17f5294c3405484291082c00a8f46dd9af8ca230ba95c4058501234a1b97543c998e9d
+
+Count = 58
+Nonce = c3f3da69e13c5733039744b1
+Adata = eedf00aab5edefdd6549d37ed44358e11c588c24f141dc5731303fe0bd56b11e
+Payload = 9db6fe9adb8c0fee87cac9a7f01a7ed8a84f0512d09b1834
+CT = 9b6b829ca1dc4e90d4402188632ea3377cbec2ba60f0f072afca1b08b6dd589a17a32d49b6f7135b
+
+Count = 59
+Nonce = 0a57d59f21ead5b6d80cd2ce
+Adata = de5f2d413c98c6ea2a5640a7b1c424aebe75cbc78b06710b5bff8bec6afb5a76
+Payload = 0b5f6389f7c20f4ba326e8f05d373ca27b7ebe59e6d729f0
+CT = 0b704e14bc7d2977d89e0b2e7ed7fe3c9e0f2ea80d2d6165f344f2f1b2218d9b4283fe640a6d315b
+
+[Nlen = 13]
+
+Key = ac87fef3b76e725d66d905625a387e82
+
+Count = 60
+Nonce = 61bf06b9fa5a450d094f3ddcb5
+Adata = 0245484bcd987787fe97fda6c8ffb6e7058d7b8f7064f27514afaac4048767fd
+Payload = 959403e0771c21a416bd03f3898390e90d0a0899f69f9552
+CT = cabf8aa613d5357aa3e70173d43f1f202b628a61d18e8b572eb66bb8213a515aa61e5f0945cd57f4
+
+Count = 61
+Nonce = 2a27257bfaadf23a87df082c57
+Adata = 0001dc666c9daf3560daeaf514270db0b5075d295068e6caf231c1de0e1a9300
+Payload = 6cbbfa6d736fbcc4cf73ab4d7be537420e0e574ee1f2d1b5
+CT = 72d525e6bb312bf2c20b91f41108779789c25720797ebffa4cd9d735f51430275387c565cf1a69bc
+
+Count = 62
+Nonce = b94ac8ed14895c80a91fda8367
+Adata = e1eaf35fb266f243a3fa407cd41815ae6432ad79877bfa59d8f196cbf19bfbb2
+Payload = e6ec561496ce18d96b26d594a47ffad02d68ef25d2d2edb9
+CT = c63500445239bbdf71a8dfe3f8c01061d659cfeb038b825dc89fb5f507f5aeefaa9365f0b18dcb3c
+
+Count = 63
+Nonce = bbae10aa491ac9c668a3ba8d7a
+Adata = 981fc31e64fbad244ba1ef0303ba1e4beef5bacca74f60ffdb9142a25a1ad5a3
+Payload = b9bec3e2adc83620772048d6cbfb6f78e4fad74d754ffbbb
+CT = 9c629c375f014e162895cfc25a972c29839f97407e7c7cca83d0a61d453d596fbc5c2e315d9780bf
+
+Count = 64
+Nonce = e0b10e78e9fb41ee970143e9e3
+Adata = 399b71ecb41f4590abda79045cdf6495f27daaa559c1b34f513b5c4ac105ec10
+Payload = 4b81804d777a59b6a107cf3c99c9d1a35bd8e4ed36596789
+CT = 867799b30558697d6efb4afcfe458cfad8da21139a0b43128e8f8e13b7896b244d0c9aa52ed31a95
+
+Count = 65
+Nonce = 17b61109f5e37754e4e92a28d7
+Adata = 0bc2fdd890c19882640f8d4188b88b9db99cc1934cc3e98a5df08589287968a6
+Payload = 347c1eb4aff917bc0012f005e74caadc93f4f18f2b614ece
+CT = ee19f3120991b67b2389e6f36543d99590f2e6d785c9c8ecc40eb85585cc3b7520a940a4e993327d
+
+Count = 66
+Nonce = db3ca9e80ab761804349379961
+Adata = ce01369d08d37dcda2c899c9fc0d11ccf94a0051b2816a1d6c3ad07fc8dd02d7
+Payload = f0e1af1276d2918be91a191814660bfe735463d3983de1ed
+CT = 0f1b1228729b181772d7cf55ad257fbcb19cd46f7b31a885401358c7b44aea27617b429583103a1a
+
+Count = 67
+Nonce = 1f57959cecbd377374477e33b3
+Adata = de1c7c83ac61e1f99ae99b198f4af5d24f8de60ea98fe637f3a801fab38b2a4b
+Payload = 42a42b84df098ceb43519c4cb86c14c2fafca39346159e13
+CT = 12425453de653d0fe8103013fde1ebf4a8fe18f76f0c9d60e93525fe8048c3b2147a149f12eaecd3
+
+Count = 68
+Nonce = c9db03e2efbab713b0b6404210
+Adata = a2969243b0955402ab45a430fef2ef9e0c025006732bf8e592e3d3884918696a
+Payload = d633a5a3defdde6a68f959ef39a91c6ea6e13ef1a7859d2c
+CT = 5cdc183c32b4c1878eb83e8473a17c55c88e2ad6b944ab1f64ddee42614aa737231207636c114575
+
+Count = 69
+Nonce = 89ed296a3ac03fbfb71422b921
+Adata = 1ffbe1aff0a1e7fa3e68be31a74612a1519b59397e7007ef61fc015f316d55b5
+Payload = bff42516e30c92ed46710013c656600406a48a84c1fa32ce
+CT = e08c1ab4ae7edb5184c30ffb3e74689ea855f50b0e890392f26b130720f75c422fdf66fb174383b5
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VNT192.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VNT192.rsp
new file mode 100644
index 0000000000..06e9ff5655
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VNT192.rsp
@@ -0,0 +1,456 @@
+# CAVS 11.0
+# "CCM-VNT" information
+# AES Keylen: 192
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Plen = 24
+Tlen = 16
+
+[Nlen = 7]
+
+Key = ceb009aea4454451feadf0e6b36f45555dd04723baa448e8
+
+Count = 0
+Nonce = 764043c49460b7
+Adata = 6e80dd7f1badf3a1c9ab25c75f10bde78c23fa0eb8f9aaa53adefbf4cbf78fe4
+Payload = c8d275f919e17d7fe69c2a1f58939dfe4d403791b5df1310
+CT = 8a0f3d8229e48e7487fd95a28ad392c80b3681d4fbc7bbfd2dd6ef1c45d4ccb723dc074414db506d
+
+Count = 1
+Nonce = 026a0b8b17be95
+Adata = 44caa8ecfaf38e5e773cb0366e1b04aa0b9fac5c34a362310f471960c4a1e1c9
+Payload = 0e52a384cedcdf7f179348de6e7336aa86f8855fbd903cfa
+CT = 3417044bad5fddd9455579123dda4fd342c273a57ff6333dfedf191496d88cbe17c6271b65096e66
+
+Count = 2
+Nonce = ea09fbe5da0fa4
+Adata = 1d9799f2bb0f7ab57fe3de27949ff64066131c81bfee172b308f9bb0b3171067
+Payload = 469ff9698cfc96b581d7115c822e4363d7355ec5daed2eae
+CT = 1dae7cc16f1b469290902cfad47b959784b4d6f48a79e690d47e30b635d10d1663477d61d7ffb55d
+
+Count = 3
+Nonce = 8d27bcbf9ebfd3
+Adata = a7070b85b7add9193c9dcd2e6c03f6e7ecc52ffe9e099866baf7472f20c03aab
+Payload = 225651d072dc9d93762dd79691ac2b6ddba00ec1252d69eb
+CT = 5da819adefbf794612eb458519debcd524c283763eb3d7252eca8766bdf0db6bb2dcc793e1749c21
+
+Count = 4
+Nonce = 13f560187b6077
+Adata = c4ab4244db75f8256e55c5b613a07b11c963c3cc24f66128aad4ba8b7ca99331
+Payload = a38231af405dc7b70c8dbc8cb84e6be8a0dc2e95fddc2ce8
+CT = 3aedcf8347aa23fd3325ce08b6b00462536baed69968a753feab6761c55431bb5668e1f5b7505e89
+
+Count = 5
+Nonce = 61e0e28bf344a9
+Adata = 5f998952de70449ad46428f2ff8a01c5af43c0107a1bcc6930f19d4112598666
+Payload = db21b37e875d7709a02239ce6ea529cf37255d5b617c153d
+CT = b8f5fed39c723d7643d6dcf2efd3bbd1ba0da1ec901305fd64b2302ace4f66216ca8b4d776197692
+
+Count = 6
+Nonce = f6be4aad63d33a
+Adata = 18339be863fb8a887d04ae9ff3b4a7db095075cd5d113a9ec87b41fe85ea405e
+Payload = e53101e6eabcda32c13d7b1dd1d88e7c2ca3ddc2064f64c6
+CT = b758858ab60e1630a0883d4d330119a593729a3015c42525effb985b9c2dd9ec954bd25d9c464c67
+
+Count = 7
+Nonce = 2c1c59aa0d8eff
+Adata = d44af86b89fda8448a9b2fcae20ea156dd8738c8251699c02b785811c830bf72
+Payload = 1fd7188a43dee7b059420e8634d71d2c0658f6d0d308dc73
+CT = d046f845a67800a5a58f461e5a8641e8fc9b4c53b32e61d172adafffbacb297d67f6b5c02b982e04
+
+Count = 8
+Nonce = 48e4598edd191e
+Adata = 61588bdc980ea2310e87dec4c651e9a55c27e3858b6505cbf3bf85e51931badc
+Payload = c25868f390af5e59c035cb5830e018c62c5b96bd35b764f1
+CT = 0ece161bd77b7f969b3b20c818769a98c178d84524544664500ff4cfe66ade1832babc019778acc3
+
+Count = 9
+Nonce = 6d576ce3c5fcb5
+Adata = 92c598cb5ca2926c11f67c3b3cf25493d77606fa60d7290430e0e975091644a6
+Payload = bcd97479db934357a163a9e5f5a85999ca987f8243d8017b
+CT = bee185e11b3d42bac846b9d92c70a078aebfa630ab763840391031b3a22b2adeb9791ee35765c8cc
+
+[Nlen = 8]
+
+Key = 1dd56442fa09a42890b1b4274b950770ea8beea2e048193d
+
+Count = 10
+Nonce = ad749d596d88a4b4
+Adata = c67219909828adef64422286008e1e306867a1c0b3da95444507a68b45c953e4
+Payload = bd92d6744cde446fc8621625658fc4bc00dcb97f06195ad7
+CT = 076cffd0ca978fe2bad411ced45a090abafb22a99896f6a75a1969276aa2b0cdb37ccaf2845dbf6e
+
+Count = 11
+Nonce = b1dc81d116d94f5e
+Adata = aa4b71906b6642f10f66c2391ec157c7cde97eb322db10045af4c5248807f691
+Payload = 9aa6dbe1cd3eb98d330c937d31ef93bee8938b6c5cfd38de
+CT = 720f6876ac91665f20147483f0655fdbe21963a01e36f1daa67e36d7cc8d54cfec0762514475127b
+
+Count = 12
+Nonce = e758738df5c89af3
+Adata = 5715fa238f432c926e62dd93708d0e3145428e0ed45e1efa8148d2c4ab6cba50
+Payload = ce80b99039a16e69018d1e3c239dd1bf06e94a78b0b1df37
+CT = acdf7ba3edca1563727ed85cabf085c2f0c8f27556c3c064ef50d85bc3ade6a773d956b2660ac367
+
+Count = 13
+Nonce = d586c4c67d535476
+Adata = 1e8dc63c6c54a540b6b02067ba7c719221cf289fa3897299722c9a2bd6eed05b
+Payload = 2f88305117f9a5d807d54b7e95ecfeb7327e52d9acac352f
+CT = e42b86e619be1a38973c934babeb4688243a9012c85d643d81e024aaf0a62b353f9bed36681288d2
+
+Count = 14
+Nonce = 77e83758f68d272b
+Adata = 25c80edef3d5bd8b049fa731215b80ca2ee9ee6fb051326e8c6d0b9e11e3d7ef
+Payload = 92e47b82b728d639777d5d5843de2a5c364956cb4b21cabd
+CT = 1b9177f5b76403cb8c690b39c3dd22b55da35cebccb9b64e05fe32f796f0b4a75a459fce6c7d740c
+
+Count = 15
+Nonce = 311dc245549206cd
+Adata = 87767f13bb4904d0df0d64eb22c9ddb65e81b5739baad86ad5e2c239ffde9f6c
+Payload = 8691c0301a216a5f3ed9123886d100309bd85630d6b845f5
+CT = f39fe3620a03b37a4bf457909e0770447b498ad2a2f0f9d7b75f9e4239e43bbf93066897e60f6fbe
+
+Count = 16
+Nonce = 2a17b70f10e120c0
+Adata = 981fc31e64fbad244ba1ef0303ba1e4beef5bacca74f60ffdb9142a25a1ad5a3
+Payload = b9bec3e2adc83620772048d6cbfb6f78e4fad74d754ffbbb
+CT = 92187955ee1ae702ef01a385537119b2bd4545402e8b2384a0c069a2439a2d8843302c6a9999e658
+
+Count = 17
+Nonce = e0b10e78e9fb41ee
+Adata = 9d072b8a3f1a496b2be6728a38b94a4f44c9be40c8793b69afd81d01696a6b4a
+Payload = cea28e7cd0eff0c5eafeec908d4aa8ba303e72ada33db087
+CT = c605e48f2e66e8e0a92471e466981ae5e31db3e4ad80b09f5005b06d15f63f2f015cfe447828da09
+
+Count = 18
+Nonce = 02d72dde23f9772c
+Adata = 2dc44c39940e2d9c94d2dbe40bbf5cca5efb4d4b250a31aa24f208b87e9c2453
+Payload = 809343e986f6ff47f54d4cac22ed39babd12271d4c7edb58
+CT = 0bb59581f22f6b15de76c0066645495a5c19e44381c349263ed92ebb789c314a89c83542b15ed694
+
+Count = 19
+Nonce = 28c4d6de3e2ce51b
+Adata = 913a8eda924589d3206ce0a951fef93668c6c0c454824b217997bff6b3026d54
+Payload = a19f65ffdafd6ad5ee43570f7e168f94a8b4a7b7402ac80b
+CT = f0c91a29f1222b906550ef5c7c0944c5c4236cb6c31122cfada8e796f2ce7f9449f42de504873868
+
+[Nlen = 9]
+
+Key = 8cc622645065c72d0d2aca75802cf1bbbd81096721627c08
+
+Count = 20
+Nonce = cd84acbe9abb6a990a
+Adata = 447b6f36acdad2d1cfd6e9a92f4055ad90142e61f4a19927caea9dbe634d3208
+Payload = 597b3614ff9cd567afd1aad4e5f52cc3fa4ca32b9b213c55
+CT = 2d7fb83e6621eed9073e0386d032c6941bef37b2cf36a4c6c5e36222d17c6fb0631c3f560a3ce4a4
+
+Count = 21
+Nonce = 1fc7a43ed124745d04
+Adata = c892b095173076a40e24522297be27fd3a765c8d417f24c71a9f03b3fe3d8e20
+Payload = 415cd8312dd20a1c26f4b90d98104cdfbe06739466fc0aa5
+CT = 7bebd6f55f15ae57ab73f92f7be6ff37ddd99740e988f01a7a2a13c22df4a156e6d6063235452c85
+
+Count = 22
+Nonce = 19ff5e7c1f2c594abc
+Adata = effcea4e4dbc57410426b39fcf51c9daecd9d310888590d77827973a29c4ebff
+Payload = 97fd2c259a4e672e9555a9a5b98f4c0ec8c4c49c7ade26a4
+CT = a460674c2f358762e97dfc958d90973e1e419dbc6a832e987579b2c4a6bcf0356f48cf8959cfa54a
+
+Count = 23
+Nonce = 64d9bd368ac2357cf2
+Adata = 62c5a16f946b4312517f67c80afe2614c822e3a01b87dc81538c00bbf3fc0108
+Payload = b6ada12f7a28211e9d2c07cbb3d39fa77aadc077b34c46f9
+CT = 8fb5e0954388b9b58519482962487e9b0768f0cee08afe9a92be2b06a0ecd2d00877abded7d9634c
+
+Count = 24
+Nonce = b4aaf2cd93efc0ce93
+Adata = 79d8841ab83279724ce35e1a8abd4e158168dcf388ab4c3d1ae70413e4e43d14
+Payload = dd42449da4c95e858b796085b6b5b3b5eef484dbf3c2bc8b
+CT = 893f86e29972928c1f3c3e25c73947c8d677814bca7fff2cf8d301ceace678f9bf91fc361dff5812
+
+Count = 25
+Nonce = 132f3e19e12f462a74
+Adata = 176cc5a280f6171d00e247edacc81f05c1b9faa87fc831163ac9d76aae59a6c3
+Payload = 8ea05a5033ab8b009664fa2800c24e217488ce6888cad147
+CT = 4771d210ea678dbfab96e320e9c44b68f47cb05b01826ccf42ca4f4ccf986eb6a6b85b99db2fcd93
+
+Count = 26
+Nonce = de709ba64cb75704c0
+Adata = 0cf8e9ab95766b6fa85e88d86e4f349a17c0d90509939e343eede988e7462255
+Payload = 51dd9fda9549f25dd868245a6a54b8d59346d2f336adf9af
+CT = fccc3e44afa6bd2fbcfc5c834db63dc9d152c04c0dc0b43d393162252ae91ca46fb8e8338cbeb75d
+
+Count = 27
+Nonce = b11b4c1b7a26387265
+Adata = 14ed867cc909c0619f366918a7d5ae25279fb137e1dee7fd98ddbe3bd19d841d
+Payload = e35ea4a16e274fcab457fd4dc7886c3d81fc668c19e0f374
+CT = dcca8aa2eab8ac3f5db9cd9560ae0758d7df40d7d868d1f71f498ea6ec8251a6d149c7ca38b25fe4
+
+Count = 28
+Nonce = 20d03227a7fcaef1ce
+Adata = c5c15245e641687d0ca9e913406acd2de3f21fbaf2dc5e4e8963222da61d02a6
+Payload = 6775e5faffd0b13e78da70a789042245d5ef31eab5245380
+CT = 4bb8ed2207f36f40f62d3a2c90f8e3bd8f589059b69037118ce3ab864545ea81943ef0ea9489d223
+
+Count = 29
+Nonce = 267f76b9ec0f5e7c6f
+Adata = 2b421be47d07dcb12a0706f7490d05024fce8f433079e18ec78f4c8678f5f155
+Payload = 9330bb23428ab45f573923e977db74882282cbe1371da68e
+CT = c6ae24f82ac5cf9c18a2d98e610027eb2566a1ccfcf99945655e14c7bc8be97ea47388cb7b18bcf0
+
+[Nlen = 10]
+
+Key = ab72eef2aba30205c986e2052d6e2c67881d24ae5fceaa8f
+
+Count = 30
+Nonce = d7a46e726ed43f1580eb
+Adata = baa86f14271b2be7dbb37ddc7c95ce4857e57aa94624d594d7bd6ceeaada8d5f
+Payload = 2a794b84fc9e4a7e6d70a82b5141fd132177a86b4e8fc13a
+CT = 2d7f76464417613bb61d3657481346b74fc9d6abc6a3babd39365dce86859cd82395d11bfc8cf188
+
+Count = 31
+Nonce = d0afcbc1b2524a4a4553
+Adata = 7c267223047af946b06f6a45ffde4a5ec49c28b81ca22da4a36bf523e89e9da8
+Payload = bfc5ce1316ccdbcd8ac62484e7656c87947ff98cbba8e1e9
+CT = 4772c121367d0e8d3edade883342395f3ea065fe7dd7be8c8355b915ca2633fd557ca7ed41e00926
+
+Count = 32
+Nonce = 6eecffd227e8d5349523
+Adata = df7736560b1a13aa8e536500ea6cdb9a6757309aadf25a6a9189055a309c3f8b
+Payload = 19eef017100dc82f26ed0815c55c122e0b1587302894c391
+CT = e2864c6e12ac089daaa1e94af4b2ed04060d7ef65d2f72f0e7d017514d498f1f3c07d650afde8293
+
+Count = 33
+Nonce = a67c0675753f725a8fd4
+Adata = 7dd546397a9a0129861fb6815d419a307f90d259d55f3503961754126cd1b776
+Payload = 80f1f1ea46c92d28f2d60eab39ce056a4aefe63fa688538e
+CT = 882c687c03eaaad9d7f591649e736f0c1c78f95e40d40cd77499a8544bc2a8fe95f55fefc7316f8d
+
+Count = 34
+Nonce = eb83928f0d5f7aa3a74f
+Adata = 060cd3e4aecdb03837dfa9f544318c0a16cdc37fa2a3135be7888ac67e7eb26b
+Payload = 81e9174e9472777b6b184707108c01d6ea6b5d108ec3c6c8
+CT = 243cfa0a0a36a4c20333968910e6f52acc04c6f74e704180623f3a13fc13db958cbac49f7421d6af
+
+Count = 35
+Nonce = 5757abe01f7a1183fdcf
+Adata = 744629263041f0eccfce4a1ebcc18c4c984010f9241d35966263a8b2f72ee26b
+Payload = 991049f26b529af8b0bee0cc83989cf817d248254182f332
+CT = b20469b5f33f0996e8de869ad10ce09924a0bdd7b67a89a09c447a3132fbe5213133650000d50b06
+
+Count = 36
+Nonce = d9adfc5b44ad7aa94b05
+Adata = aa6a5448c6ec87be75eca35725ad2e902dbccf840d25b2bdf7e62e4a8fa4a511
+Payload = 14682301a99bf680805d1ffe62e1506d48cee8c51ef1d255
+CT = 9b44efa185b0c10325bb4c3c0815e6a6e46eea366b9a416b5ae554cb440eadd875657fd5cecc214a
+
+Count = 37
+Nonce = dc3ca30782c9c0a7fe89
+Adata = e788c98ae85b11b3ae884eed6f3b8f5bcf5ab1b7b20ad3f44f760b2287cc5793
+Payload = f9cb86f24536931a1b095b426a07e4621c000cf09b472bf8
+CT = 463f9124d1cc387a0f8b971d1e2da448f0efffc3956ebb2af8312986315522081f0989838ef0429b
+
+Count = 38
+Nonce = 9523f53f92b6e4ba86e5
+Adata = c3b123ccc916d26a2e6a8b5e30041ad69a944217e9b402b7acc0170c31e8c2e4
+Payload = b9bdcac80f64175836ab51bb1a1bee5ffe3a6b9b71afe3ef
+CT = c356b5a78cebd123808fb740754dc47a8ec7c9448bfacf39768e94f062e86129cc9210dfcd3e6128
+
+Count = 39
+Nonce = 16bdf18c09d60f3a2a32
+Adata = eedd0796f23612749e9fd282c864f3118d0683409d3bef1fda352e1422273c7e
+Payload = cc96133e473d197be1bafdfc1a21d58e57d0d89b2ba1c3ff
+CT = f9d78e9e3a41b3bcbfe756385a3715776eb84bb7d8d15432978757883f07802b25e9a5b15c43b451
+
+[Nlen = 11]
+
+Key = af84c6f302c59aeee6d5728ed5da2e3c64a5a781c52c4d1b
+
+Count = 40
+Nonce = df990c42a268950677c433
+Adata = a6ab5d78427f297a4b7e21f1091ff3a5b20caa3fe1cbcb09459d9df596a6c8e1
+Payload = 6db41aeb5f7c24df8929dbc30483b3c7934b3bd1cdce5bb9
+CT = 8c9328258bf71970d33e23a3ff81cc1c9cbe196a1294264bfd6a7255e4801963bb30a63de3fc5b82
+
+Count = 41
+Nonce = b7ea72641bbe2dca6d85e7
+Adata = 4e0f2ddf183281ec131693bdcea3fc9743733c07a486a42d5737735b3f6e3fdf
+Payload = 726844e41b1e4d883024b32fee0dcea38c889cb328885b7c
+CT = 9a133e4582c2ebc445862a9c6f2f4e39223c84081e322c8f262de30da6ef505fe640c53d765f672c
+
+Count = 42
+Nonce = 446fee1e75e79c0dfc9ddc
+Adata = 42b598eaee271e06d9e98dd94152b28ef10f506d65bd660b2fb8b1be9a2d7254
+Payload = 0cdcf348ecc9c3588001802c2106fb64be9c301adcc66e73
+CT = 0c2657b0482b6ca92e1b1c8fdf75eae3b0cd3af205e9bca396ecb1e46beb16000d585e1d9559ee22
+
+Count = 43
+Nonce = 2e6e34070caf1b8820ed39
+Adata = 8bd1ef3a1831fcc8919d736fb23111ca3ef4cccaf20264fab8eb3b071e56667f
+Payload = ca0860cc1e96506c2beb25b53d2947fbab634f0372afc8ba
+CT = 19e4774030e43e6853ab5bf176ba9c4b59f29f285977e3c15198cbe3e34c884c3f56a732974aa1d6
+
+Count = 44
+Nonce = 428542ecfb94a745980aa6
+Adata = 8efe01716b9018084e2ea7616f85b7333d945c0c970f8cdd400130b98db67cda
+Payload = bc6b59120ba2845b0e41f65a55e2ef1c45a81485c926c14c
+CT = cb48b0af6fad251d409d14ce0fbfae9cd9c40bf4a0c1e2b7e7cec415030997e1ac5db974b617b5a7
+
+Count = 45
+Nonce = eff703e6d72ddd23ff52d9
+Adata = d7fc74035e66709d2590b7bb3276245dd43824c9896fbd801ec1d07018b39b6b
+Payload = 1a5432e8085511ddac1be91be3e2945f85f0cdcc3a1c9f8d
+CT = c0a00cbaec65b7ca525fb26e80ee0cd18c7ef47c39c704833e59bfecf263bfdb24686627fd95e120
+
+Count = 46
+Nonce = 6a652ce21334a40a259dcf
+Adata = 5d24d80f22afe713c4076c200c1bab36917907fde7b6d34e141066f543526db6
+Payload = eb8f1988cb405041bf48d138ad41da7ef364d4ac59a9e324
+CT = d4f23166c09a15466c7e0e2b30627ee5a84f22d7e6135b4a0652b67d559a84b4a915ca6a420fd300
+
+Count = 47
+Nonce = 9382e12d447c0ca23cc9c3
+Adata = 239129eb760f8a770410c160e4e13a6b9497077c3e463b65397393fcd3cb5c70
+Payload = b40e80564263c7f450c53ef84df67247d72e8a04dbb284bc
+CT = 6de2ba26caa80874814816154784912c55e3d6da83488e7250f5a52f82211542b4e2661cf870c80c
+
+Count = 48
+Nonce = 2c3a4148cbb02504a2483f
+Adata = 33c3bdbf185b580353de79e51e675b03b31e195f19ba1f063d44def0441dc528
+Payload = 60a31736d99c3dcf25b349f6110e1c152b93506e85a01e67
+CT = 4d5e705d08f3ed1ca6f1caa74b46e4b1eee18a0783686f207de16aaa41d06bc071657dacf14da754
+
+Count = 49
+Nonce = 691cdf6fe9ecc2154d0101
+Adata = dc096596644c4e09c44078b86e5e0887c45094042eb0d74a6a13aa2524463076
+Payload = 77e6441ee017a93dd876ff2c7980540c77ee15edb0f23933
+CT = 24cecc81c8ac7ca9906372dc5263f2220b4dd162f1e08283f07f23e65475a20fd96e45c6c695cd83
+
+[Nlen = 12]
+
+Key = d49b255aed8be1c02eb6d8ae2bac6dcd7901f1f61df3bbf5
+
+Count = 50
+Nonce = 1af29e721c98e81fb6286370
+Adata = 64f8a0eee5487a4958a489ed35f1327e2096542c1bdb2134fb942ca91804c274
+Payload = 062eafb0cd09d26e65108c0f56fcc7a305f31c34e0f3a24c
+CT = 721344e2fd05d2ee50713531052d75e4071103ab0436f65f0af2a663da51bac626c9f4128ba5ec0b
+
+Count = 51
+Nonce = ca650ed993c4010c1b0bd1f2
+Adata = 4efbd225553b541c3f53cabe8a1ac03845b0e846c8616b3ea2cc7d50d344340c
+Payload = fc375d984fa13af4a5a7516f3434365cd9473cd316e8964c
+CT = 5b300c718d5a64f537f6cbb4d212d0f903b547ab4b21af56ef7662525021c5777c2d74ea239a4c44
+
+Count = 52
+Nonce = 318adeb8d8df47878ca59117
+Adata = feccf08d8c3a9be9a2c0f93f888e486b0076e2e9e2fd068c04b2db735cbeb23a
+Payload = 610a52216f47a544ec562117e0741e5f8b2e02bc9bc9122e
+CT = 83f14f6ba09a6e6b50f0d94d7d79376561f891f9a6162d0f8925c37cc35c1c8530b0be4817814a8e
+
+Count = 53
+Nonce = b4cadb5f9cb66415c3a3b714
+Adata = c4384069e09a3d4de2c94e7e6055d8a00394e268398d6ea32914097aec37a1f4
+Payload = 22bade59214fa4b933cb5e3dc5f096e239af4c2f44f582b0
+CT = 2296e3f8a2245224d274f1b90ed1287cbeeb464c70a89ee475ecb546efb8872a3f8b0281b3901752
+
+Count = 54
+Nonce = 72e6cebdaf88205c4e744286
+Adata = feaf010f462ad40a38eefb788b648e1cc292cd4bb08ebeff3c39182862296042
+Payload = 30655a6b5a5965db992e7248d24141055e988d726abb8e72
+CT = 69b27f2bbaa61c4f24e1c25e0779147fef79ec1582486b4651cffa571570618e2ada3376bd9f3e5f
+
+Count = 55
+Nonce = d8030fb31eca2c43f3f5eb88
+Adata = 66704365ddd0145febeb33f68b228a3f09e1e5a4b68149e6e06d886301841295
+Payload = 9d014a02507a6f266bd1ace21b55ab8b73983ff503bb9adb
+CT = 233a883650538ab8c0da30b90527f880fcad5b16bd435e762beeeea7a638c717e63764b3a5118a0c
+
+Count = 56
+Nonce = 58038cc35ad3dcd75195e125
+Adata = 3da7a757e942409a3b39ccdc0669ce6401f7e133c07c4c42e366d70a8e9bdd49
+Payload = eccfd817fa5e3a0146967fae13fc2471ee3944cee37969f4
+CT = 415a36872a04f5b4b5372f63394ab9fb353e0eb9b430450133a87fa29e5fbfa9bc0430b0cac00b7e
+
+Count = 57
+Nonce = acd82ae31bfcabd90af5af45
+Adata = ce22126f01bde16249c47102b4da68ad3edebcd4a16c24a16ea7ccdd5d364d10
+Payload = 9d2126d34963d3ba12cd841bd321036cb82cfb78f2a6535f
+CT = 88a5b889e6fd74fc15336e23374b430988416c7e6b6e7248b336cbbeb64fbebf2e7076a98ecf5bbe
+
+Count = 58
+Nonce = d24457d567fd0a65fdabf219
+Adata = 0091d39f3478d2c59bf874b96db9ce0f7e8b85a9b805e07dc96b219819d51663
+Payload = 6da3ac85505e93c4f391ea367a9e15fa9b388ef7ae2693c1
+CT = 7039a8a49cfa6402b4ba3b840e69200c13ac4a3eb1c709a30ea909047af4998c660afbaf346ed65b
+
+Count = 59
+Nonce = 50c59ca54eb64575b82b13c6
+Adata = 5e4e42cbf172853c351d597c7d6d38b1a9cbb7ac92c00863a80ac4a2d9f0e7fd
+Payload = 25b2ba0a937b71f3ee68e7172cf2c4524b662efcd08ce2b3
+CT = e95fc44287ce39c5ad6b91c88582563fa68a9e304094deb8b193dd767f17783f0b51ac0fb7323301
+
+[Nlen = 13]
+
+Key = 36ad1e3fb630d1b1fbccfd685f44edd8984427b78deae7a9
+
+Count = 60
+Nonce = 3af625df8be9d7685a842f260e
+Adata = 308443033ecd4a814475672b814b7c6d813d0ec2a0caeecbcaba18a2840cdb6c
+Payload = 8b9db1c8f9b4892a5654c85467bcffa2e15e28392c938952
+CT = 6bc6890fee299c712fb8d9df9c141f24ee1572b8f15112c2f8c99ccf2d82788cf613a61d60dae458
+
+Count = 61
+Nonce = 24eaeaa437649e61b706942b8d
+Adata = fff75462f96157d9554bddb6aac156fefd88fd4a90a8536dfc28cc577f19c83a
+Payload = 49ff4ff85f7407ca383cfa4fd7177adb4dab26e642c8186d
+CT = 3647fae50c588d792442f43a20125e77ab5db3c469391d24d0a421bbbc002eb9ac9ad01f625f824b
+
+Count = 62
+Nonce = 7325932d6694aaf61a8204c172
+Adata = be20ceb8ca14e9bef7158b280a26bcac763da79cd0eba9b1833ea808c5e7a66a
+Payload = 2861494eb40b9d964d339797c1b6aac63c6674187768957c
+CT = 286dc74001e2a6000a23db164f4b2912de4afcf1df8c3aa5ee32a7ffd4e7bc303d3482fbac431828
+
+Count = 63
+Nonce = 61c9949df5853e42599e5ee0c7
+Adata = 243d09ceb16755cb58d62065df84890b840ad9b7eec1132c6427cd7c3d843fcc
+Payload = 943a49073db6ae94a88844ed895f8fd99ed25c3f42a2f78c
+CT = d3c56bd265a2cb0811dd218f248800ceade4f02b5403b9635eb30cbec49cbb51c41cd5032b7fd759
+
+Count = 64
+Nonce = 07b6c18dd3b0fd9e8ff026a436
+Adata = e85f141c3d1af7727fcdb00f8e2c34e42a436d04ac5b8ca9f321a178a2056806
+Payload = a18b0a4618063c0519818d113b8e5435aaf153f664058f1b
+CT = 69f933a2a5e774e8d013cbf78c6ab0b73e6ca323d0c52691acb5cf2631987d3d963349b035324aac
+
+Count = 65
+Nonce = 0c075df70630dec2fe81834945
+Adata = f3f5c5ffbfe8247bc0c33c793652f749fe91b6dd141cf0db56e71cef8a2fd266
+Payload = ddc4bac4115e8cb06d29d22e400674dbc615a667f933603d
+CT = 26bdd25c9f204fc7520d26c161464c28fb35e395b295b3db4e239d33283d18415b54c2aad4bde354
+
+Count = 66
+Nonce = 0c2d20375057fcd4241d290f6a
+Adata = 70ff1b9ff8ec08fdb18b0e7dbe01127ed0cfe0b0a449ca2ace4992b7b6248b71
+Payload = dacbdf1979e000d52b573e74800761b30acc26681f372acd
+CT = 6a642c389433a3464fc64783ae6a14a9a45f0998b56a5b9162d7e0320dc930df3640a786d7ea9ae4
+
+Count = 67
+Nonce = ea0801cb3dab853750a922dd25
+Adata = d83360d0896e022bf014bd33710ab212ddedda6d95a54996f33db304e5f12f01
+Payload = 46cc5653bbd8300dfb0df6d0af3fb7c7639a830bdc9f68c7
+CT = f1b0728920351d9edfdbe7df360b21f6cc5b628dcf43a3f10d06b4a545609a2128a95d4d73471559
+
+Count = 68
+Nonce = 97e6de379c90fccf3fa8f27013
+Adata = 539f8eb802bfecaa4fb5b19debbf3d4847db9c4e0473a308ab3f3c859e68fecf
+Payload = 8b013f52a828905013f250fb9c006a173f6c66a64b5ba317
+CT = 556a439bc979dac1cfea8c5b64aa78547f52a62896c19893f3512baf72cd79ba9301194be204bcc0
+
+Count = 69
+Nonce = e832b6330d3e5e190598cb9c61
+Adata = 093be516277e8b197ba5e9c85a831529befff0f3971510ab611dfe0dfb50a2ad
+Payload = 635d2d7894bb816f154210946a369df37ea492993ba23af9
+CT = d8e19c67e5aa7f14a16ecaaac414a2b15a15bb5f966932e6b0bfe9a5857fd36df94aeadda7f83a79
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VNT256.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VNT256.rsp
new file mode 100644
index 0000000000..2817684910
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VNT256.rsp
@@ -0,0 +1,456 @@
+# CAVS 11.0
+# "CCM-VNT" information
+# AES Keylen: 256
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Plen = 24
+Tlen = 16
+
+[Nlen = 7]
+
+Key = 553521a765ab0c3fd203654e9916330e189bdf951feee9b44b10da208fee7acf
+
+Count = 0
+Nonce = aaa23f101647d8
+Adata = a355d4c611812e5f9258d7188b3df8851477094ffc2af2cf0c8670db903fbbe0
+Payload = 644eb34b9a126e437b5e015eea141ca1a88020f2d5d6cc2c
+CT = 27ed90668174ebf8241a3c74b35e1246b6617e4123578f153bdb67062a13ef4e986f5bb3d0bb4307
+
+Count = 1
+Nonce = 195c0b84baacc8
+Adata = c7d9557b2ed415652ce6faa8cff5217ac803530ec902890b31eaaf3eeb0aa98b
+Payload = fe012718481b2c4e1d7f9a7685e3daac43ccf22cad0df900
+CT = 893af0f130f1317de9f217234274b0c04fcc202cea9a0df882c00b5b463654adbf82888099a7d258
+
+Count = 2
+Nonce = 363e0e921c6f11
+Adata = 805678936d4e94746ab4818dc5f50c41e32cf32e7a8aafb300fb91af6406108c
+Payload = 7e7e33e1a07d4e8fde2f33304f21cb564d146860ccfeb49f
+CT = 645cdd11a1c232815ce1e07ca3ea83f372eba46cedafddd980adf2762a1617adfd4d8356bb48aa8a
+
+Count = 3
+Nonce = e323cc866af462
+Adata = 163c747f3ba4ffd68af87f2475f48f2714659a2ec43b9ed115e02fe0e3c8be99
+Payload = 2bfc76f3b108ba3118b07433c4d3d5f41564d22547c12822
+CT = 0db04c6b068e73e3c4d71059bdeee3d27622f99dfd07d868fb9c02753c57fec7e1a5fa8f3860501b
+
+Count = 4
+Nonce = 03ae777078b95d
+Adata = f1dacf9062dff9a6a3d0498f9d058782f891475684196bf2d8e7e905393acff7
+Payload = 38c4275a5f605fd1d99517e13deebf0c9794ef586070fa9a
+CT = df8f524872b5f06f3f219ba76524990b466409894930d7e0d104990e598eabd88cc8342ac16424b5
+
+Count = 5
+Nonce = 1c6c351d4fe9be
+Adata = 14285e97cc3cae452e1a52e2fa0bbe24df96abf2faf6b9779acc59764612eadd
+Payload = 9e2220f3c17532e1ce0d6f562b049fcef35bcaf9a7e196be
+CT = c274b28228a6b13b670c325080f88d188d40d78d385481eae004894b1861db5d2d8ae98ed8926c1e
+
+Count = 6
+Nonce = a121dc27479397
+Adata = 359421e9f78cc4a31f4f019977d7fd29780524e20288798c50002a682a6368b9
+Payload = d42b16b32e77637724144eaddb21ca8d7db4e7f73acbf707
+CT = 56e3e3e59e978161355e7d8573dc0657db400ca0b083dae8ed2ac2cb63e1b9d7dc598634198fe4fc
+
+Count = 7
+Nonce = b1f0e26b60bf1d
+Adata = 2ab4239fffd13762fb5391f5a4760d12d96ea12666a793b4d651e9f4891c22c1
+Payload = 9a2851083ad4e7b915bb0526bb4054e4c0b4adf8626edc90
+CT = 5b2e0215523ff37f0df46e84f996fc9fc779986c766fa51595b8a23ee377d5c2850f4ed95a385253
+
+Count = 8
+Nonce = 50412c6444bcf9
+Adata = 09cdcaa87ddf8bbe6db8411d14bb9064e4a121286cc8a6e97fce1844935f436b
+Payload = b28a5bc814e7f71ae94586b58281ff05a71191c92e45db74
+CT = 05cbc32a6ca797684636dedd16ce65a1eed69bcab1b1bdbd514ef5cbf9991a919fb4974d55506ce1
+
+Count = 9
+Nonce = 225557b0faca3d
+Adata = 21611da060fa90cf7fd68b721caf303307a56e56453326495b628c7dc93cd175
+Payload = e831b739e8eb9f787f63c0bb071ddcc9f44cab8d5b447d23
+CT = a97e0879407eb3b7f93118ca73f17eb34e9f4baf43b07be2e8a3f7b848054cb235e1b58d6a12c5cb
+
+[Nlen = 8]
+
+Key = 472bf7946bce1d3c6f168f4475e5bb3a67d5df2fa01e64bce8bb6e43a6c8b177
+
+Count = 10
+Nonce = 790134a8db83f2da
+Adata = a7a86a4407b7ecebc89434baa65ef173e88bd2dad9899b717ca578867c2d916f
+Payload = 59eb45bbbeb054b0b97334d53580ce03f699ac2a7e490143
+CT = db4961070f528ccd1a5a0681ee4d0ce3515fb890bccedc2dbc00b1d8b2bc393a8d09e87af7811f55
+
+Count = 11
+Nonce = fb2441d1594a488a
+Adata = 0875020959ed969cfb38636d1d5aabce9658b00171a7614ea9e5395331c7659c
+Payload = 451101250ec6f26652249d59dc974b7361d571a8101cdfd3
+CT = 1bca7b0d35a68c0ffc568ffc8221cca738b67b95e3ab26efee21c5738d1f7fddf3030d004a702704
+
+Count = 12
+Nonce = 0855263860043207
+Adata = c7fc24863c33f7e8cf97b337918495d52d864ac570c99cbb09d151758d6b504e
+Payload = 61fcd7ef9bf151b9d8a81dc1ba4f82c45e9c2e4784627acd
+CT = 9b939b6b188e1d0fe016f366fb01eb79a99ef7b1b57c6f7ab223454c57c714d96681cd4d55615afd
+
+Count = 13
+Nonce = 415cd251a5e36943
+Adata = 1a393c7e85fb286709f4eb50f09640e1d65ec1135cb4443820136b3cec69772a
+Payload = 66ae08d494dc9df9b7f8f53199fa37d0c88885458b168c57
+CT = 1731e260ae31b8068ad1099313b167d9e6cbe49f471da61a9af96d3ce4ea94213b60cb69d92050e6
+
+Count = 14
+Nonce = d95bd65242bb2265
+Adata = d0e20e1358be5cc1c45c1cf02c82d0a6d0824cfcb65774cf95f047b9f2cc1d3f
+Payload = 312c3791c64d79205a11eebfc14b2d7a6b00391793c9559b
+CT = c3fbe558ff9ea83ed86b7d66503ee38eee94e4a41fd53f0f627a352d056712e0d44404c61712e2ab
+
+Count = 15
+Nonce = 3f0bf0141dd3ace0
+Adata = 9dd4ed18209dd6cdf19cc76fee443827e7331aaf020960c15d7bbed0f6a3b1f7
+Payload = 08354480047eee3beeb5ab165da17d23f2f1a4ad98720611
+CT = 2db9d2c54134d37ebefcecb9e2076034b975677fde58ef6032645a322fa9bc8aace600f942a84db4
+
+Count = 16
+Nonce = 3fd8b3a3ff563a42
+Adata = e58327efebad3276a7cd1b1ccb56db0caddd02a303cd9fc7ea5c607a2ebefaae
+Payload = d1abd89351384e1a3c3366f77c3175f6390801554d7cd783
+CT = be284dcb357ae99ada7cc891730320ebb32ca627eb8c80623957a2a5b6164218fc83e12c42d5c532
+
+Count = 17
+Nonce = 14db1ffc1c87117f
+Adata = 6c2b091433833a0ed915354dcb70d982095b614dc51a95a22cec417184d8e786
+Payload = 0594307491f157821e63f50c94034f9284f095d5b897153c
+CT = a114c84a10071e359bba2b2ba4ea67f893e27e6ea880aa4b2cf16ce68a93f8839245baebb2278300
+
+Count = 18
+Nonce = 40b0f74ff27a3fc8
+Adata = 3b9e1f4e9b57a6dfb5e0ca7ef601fc6af30a1f8650228e51e0dc61180d0bec6b
+Payload = fc8b7dbceef6b0ffcbade789e09303044042cd671607e819
+CT = d00ef56074a8213740af8b8f974f778db560ac365d6ce916b8d191130e864bcfcd1dec94a1aaeaef
+
+Count = 19
+Nonce = 96cbe9cd19351359
+Adata = cf498fd042f9a07503e490cec4873d4df91162cfde60bd2cbb2b710c6681a9fd
+Payload = 315e81c9ce556dcf97a5b68503fd2228a7a6a174a15cd618
+CT = 7383c2de08bce3f0b7e504dc03d062f44396bcedd2180fd954e6ec9f6ae1e0976ecf04dbee6463c2
+
+[Nlen = 9]
+
+Key = 58ae7965a508e8dd2eda69b5d888a28a1cb3783bad55d59d5b0da87137b72e93
+
+Count = 20
+Nonce = caa3d928d2bf2b7f2c
+Adata = 304678b3ffd3200e33a8912bcb556b3cfec53ca17f70ecba00d359f9f51d3e3b
+Payload = e61bad17640ecff926d0b0238271ee4c9f8e801dd7243e9e
+CT = 7bb1137c14cb4d324a4a8f1115c619ebf74927f0bed60a8d5a9140ff50dc4da375c7d2de80de097f
+
+Count = 21
+Nonce = cf09ca67659a583bb1
+Adata = 5507c4c3107cb446d19975f91207dbf3e2a51d1dcfd7da2f082159dbc3f41547
+Payload = 1887bb0c02500093a30a44b99e137483704b06615d308c6b
+CT = 834d3b2e5f0915c2348c706b4d2ff2717983ab4490edcc63971f02b7122d1e4f78de9c3376520f5a
+
+Count = 22
+Nonce = 97f940d7c1230bd8d2
+Adata = 56be2c9e09b555373d58f6fe2a0ca9b4ddba899addddf12b0fda860ad791773a
+Payload = 5ac67c9bec9b95c54e187a4a6812f5d701c4ac8f847c005b
+CT = 9f372ba1c87a115847cd708aaf5b8a143b6981ffc2c61cefd30ece13481609809b218de04c4e5ed0
+
+Count = 23
+Nonce = 147c7ebb6c92245054
+Adata = f95d64a513a9f3e6c95c9ed27b22fafd7dd10da52636029523142149116aff53
+Payload = 08f199a8d7e3ea821dd3106e8947cd2e9d485342b25a6471
+CT = c438aa6d187643d030dfe4d6b5b578f84838f4dc5c396d700c0986ecd7dab44e5e97db37392a485a
+
+Count = 24
+Nonce = b9bad794d49cdac9b3
+Adata = de9ff2a43f49cdc502cd17a373989bafd13fa6ccff6660557ce05b6295186d47
+Payload = 40d1cd4063750184356a1d7cae1cf1824f552c5d59a62dc1
+CT = 9952b25f4f4f375440cd958456184fe61610381ba92ca48f38dd977042c4d97da84e4effa650799a
+
+Count = 25
+Nonce = bbe054fbef86db3ce7
+Adata = dcec76181e3b872a5a6e79f070354e38866c7f67fc428fbca29ae6d929b1dd7f
+Payload = 5f29808ba74b672a0f82b3b7581dc32478c6e790e2b8c61c
+CT = 4d176f48b09b772dde8adbdaef720aba128a8d38a902847ebf22c81a5d824b4916660be6f9b513e6
+
+Count = 26
+Nonce = 6a35e1a4307f6efc6d
+Adata = af28120505a84a75b0f6b18cc9d8c75c661bf143be29c11d8ede78b9bb98c98a
+Payload = 5e2f601395ec406fcf96785f768162e849f867dca77667ab
+CT = 4e305e26d34711c6aa775f490939cc6560d3cb6905f5b0f5588ace6fc303600abc8e5825cbaedc7c
+
+Count = 27
+Nonce = f6c237fb3cfe95ec84
+Adata = 038f8ed89444784417a9c23bf11e9b436174e6c10959e00faa1704ce2f7f2c7e
+Payload = dfd9cacbf7d73d688447ebab13d2e13f3613652379b386f6
+CT = fb16c17a6b22a8658f446203ad46a48b34808083b271cabb015a1f78abc287bd2a63381ead07c558
+
+Count = 28
+Nonce = 50d024a3e7455d7249
+Adata = 8513365786b7988b208984e11022c15573f978bbdc29e8a7a4745c8a81885a1d
+Payload = 400317786b7df63373ffe541efcee6318cfc95bb673aad3e
+CT = d33b3141fea3a9ebdeb80d1da32dae42680be78471fb3023721f714120162514555b60560afa4256
+
+Count = 29
+Nonce = 02769283d5a06c363c
+Adata = 292c0be3713c6c588cb4e29a1c43b3e6353e33556194e568e800e4e44e8281e0
+Payload = 12ba8eddff1c2a03ddd25bb924ff065a93fd712b2c4f61eb
+CT = b15b1789c323a68568f86f35483bd7e204beff8f318ae14351f5e62b3b923a937e6c307af202fab3
+
+[Nlen = 10]
+
+Key = aecc5e18088bf9fd7b17f089bdd5607b69903b04b726361f8a81e221b1c91891
+
+Count = 30
+Nonce = c527d309ab29ee91c5fc
+Adata = 8f9a73e7bc1c11e2919020ba3a404cbddf861e9e78477218e3be2cd4337b278d
+Payload = d4291c99901345afe29f58912a414a7498f37b44362bdf3c
+CT = 392784a9e0b14bcd37639ec5409d6ead3e75f855e5a92c33ffc040ef3977e0035ce6ea6d157c18d3
+
+Count = 31
+Nonce = eebc31a5813b4fb93b63
+Adata = 9c87ad77953bf8a811e001ddb946eefafbfaa598150e85f0701853fa307d77d6
+Payload = ebcfd71120b0f9a2cccb898e6dfa082998cbe10032de3e61
+CT = e38eaad1e2df77e85e7129a8ce0f82cfc32b0aef79ab651bade65aa17e4dfb0aafe18cf71a72b180
+
+Count = 32
+Nonce = 231b33dc406c9210f59a
+Adata = 38be46d271bf868c198052391f8a2147c663700d9bb25a0caaa36974f18dacea
+Payload = 9032f910347daf661092b5c1f15b5ffed1369b194d9e12f0
+CT = 868b85288828501cf1d06610fec25e8b8a4b437e2e4f5563b7f3b898a2356909784598f8a8916f5a
+
+Count = 33
+Nonce = f2a88c3ebc74e62f24c7
+Adata = 5f495c5da035cabeb77e8aef10e91a05bd5aa414d1a37fa1099af959b26e5403
+Payload = cfe8ee9b475e36058471e2984ae66f6ba1b3cb477b15155e
+CT = 22c16333ac651cd9c183e78aba3e9312fb3b77dd6f9199502788860aae5534cf84979e30c3327d37
+
+Count = 34
+Nonce = 9cbaf1c83ba60b1e90ea
+Adata = 7ef136bd9a5809676abbaa68016d6fc713e34ac4b768a8246b1198c959f43085
+Payload = c3bcb0aaea93893f05eeb6439c8619dec17670a6439e2921
+CT = ebd9fb86563aa8f10062624441336f982c161ce5717d990a599ca6ec1c61a14c37b5902389e47aee
+
+Count = 35
+Nonce = e25322845d87d8a76753
+Adata = 2a89b9f0e56a1cf87dd38ed78028b6286ef8b7141dd2b3c65c5a8e1ed79bf4aa
+Payload = ae622ff9381854f831892c318bae5c003e74b15199bc12c0
+CT = 144c920f0fe278f353d0b053563d907c7589e4f1479d7a93a0604deb3fd9cea2d89987833ff5c2f1
+
+Count = 36
+Nonce = f4d7978fad36223623cc
+Adata = 8671de7e994967f2521d263925e745af9273682d9c08ced07d4a98fc985f68a0
+Payload = ef9b4ff8da108cabc972192ffecd5f96594c6d0871ffa6aa
+CT = ae4948b3bc1e50beb9f5d005871fc0d3dbde295de1c9ec3cbc866ab47bea7a4d0070e52b492fb8f6
+
+Count = 37
+Nonce = 6597ffb9eaad0fd9d830
+Adata = d2967ddf69ef62a9e23c9118dfaa55df92b4116322f1c9275131e3875dc92faa
+Payload = 5015c894b2437ff15c46bca9236830ff4bb057cd5764f027
+CT = 0b1dcb3cb0b4c32f398f3c43eccfe8f4242f33c99a2a2283efcb3dacac25bed0304f227fd5b77b8f
+
+Count = 38
+Nonce = 80e376b87272d99cde28
+Adata = c9cc8f967dff45c05b9345d03813b6e30dace99556f7df75b7120bb6e5f55827
+Payload = 615f657e24129a3e0f119988959608821219ce8354c4be26
+CT = d3e8b8f7ff8faa666ffe2509187fa7befc7412fd4e3bdb06cd2f7494b1fb0a0c6a2184e5c4787fea
+
+Count = 39
+Nonce = 344cce96455541d403f3
+Adata = 748cce18fb40126ce125dbe341fbbc59d2aacc170ed5ef0293b15713c9184a07
+Payload = 828b6a4cd49f499a6e8e8508f9ab35255d8e9fed33ba4d91
+CT = b67e582a74d7f022a16ada2de7ec18caafdefa6b104baf4ed93b6f8c8a1bf72be75976e4ebe6dd1f
+
+[Nlen = 11]
+
+Key = 97bc7482a87ba005475dfa3448f59d4b3f9c4c969d08b39b1b21ef965c0f5125
+
+Count = 40
+Nonce = 0bcf78103ec52d6df28887
+Adata = 049c10f0cb37ae08eae2d0766563b7c5a8454f841c2061a4f71a0a2158ae6ce5
+Payload = b99bf4dc781795fc4d3a8467b06e1665d4e543657f23129f
+CT = 0d3891fa0caac1f7ebe41b480920ffd34d4155064c24f3b17a483163dd8f228d1f20cd4f86cf38fd
+
+Count = 41
+Nonce = ab6374c6b2faefd92fa3d3
+Adata = f19c044023e5cf339203738ee70e76527519763664c06ae00e002a5ba94c32c6
+Payload = a2e5c51f516db01688b64c173bb25645182a005018022ee1
+CT = f70c598df3c64d3527ebb7fc8408b7de2cfaa1da7984ec361f1ad61758d828b70d4881b7d6ae8cd0
+
+Count = 42
+Nonce = cfb89e7ddcba601e875110
+Adata = 052714010da516c896ac5842a839ae845324643cddb080e6206148432d0d0407
+Payload = 037f206cab78a6ca0745dc8fc137e22e14f3d7183917ef83
+CT = ccd675862502a2e2520a33250150b8b7b220e84db854888c316dd62075fc761e2bc80edc5c564bdf
+
+Count = 43
+Nonce = 967cb6f8530bf8a43adb42
+Adata = cf391a84d03e2e22aec1965cec821f99e7bf21a7c3580dffa531464b22d83225
+Payload = caa3d928d2bf2b7f2cd8a7f357055b6d6895a5e34f47972a
+CT = 4f4f509debe6e52eae4af8b1740dde0a5338f78711a3b4ebfc8b5aca6d606222d6af7cfea0d1f4e1
+
+Count = 44
+Nonce = f5b7b5dd2b5e1ec93710c9
+Adata = e7a6b228a67d37b9d29a38efc547e50b4a6d95d599b45ee189ece21101ac6b5b
+Payload = 4a74ff35418723f2cecec1012484b52114067b2b2393e7f4
+CT = 25b140922a9d4f2ce153a4ff86596a49d7de6a6184e931e8b2ff27a98029b23484e00c2a5d291887
+
+Count = 45
+Nonce = 713de00faff892977d99d0
+Adata = 14ea93488d4284d21d4c7ce14414adf45c1ed9d2d99db866d0e59accb6234dac
+Payload = 3820db475c7cb04a0f74d8e449f026ec951fa59667738698
+CT = e4d92ab8d1ffb0976670d891cc8338da12f86d5d79b334103d2ae816edf857c810b6fdc7f2c71f1d
+
+Count = 46
+Nonce = ba87934808de09b2ae829b
+Adata = 30e2ea2a505f19e8760a0a84961000c7a0b7fe3460a9d3f5a38f54149be2e9ee
+Payload = 0e52a384cedcdf7f179348de6e7336aa86f8855fbd903cfa
+CT = 6df893eed2be958e5f542f8cb4adb392b34786cb4ce821ec93fc57997b977948d55bdb026db5bc48
+
+Count = 47
+Nonce = ea09fbe5da0fa4fe911e18
+Adata = 237dc8512b29bccdeb8ee39cf83b9b6dd203823d175c44d5f605b194e7ec136e
+Payload = 41cee0ecaf9c65cef740440af37954ef49a585779d2abbca
+CT = 2f204ebcf549ee2a800d870e6341b9a89a41ab4ae91b6902ff704a2bcfb8becd0226f76d68fbb08b
+
+Count = 48
+Nonce = 5b80d7affc4ab4a4b68bdd
+Adata = 3a38dd7da30f5c312fb1e978d87b7a39792fd9ea3e9ab1565874e99df587327c
+Payload = 5ff92f6d3ca791421363e10cc84b4e8e21e0ebe5d8c55d6c
+CT = 05472db7875d59f8bed45606f355a516de93740aa2baeba18df9400df42baee6b9a0d75b45840104
+
+Count = 49
+Nonce = 514bba483fe7f2b7e555cc
+Adata = ac8beb419099cdb42a39e9b46fd900cc52eec4b43a96ed18b37b899b63fb931c
+Payload = b0b11dfca9b3936d1b4a423c5acd3d012b399a487c19c994
+CT = fa20629d514c4ce7bf727629bca5aa1c0c7e7851fc1bfc5c847729a70d7b4cff5281aece37006015
+
+[Nlen = 12]
+
+Key = d6ff67379a2ead2ca87aa4f29536258f9fb9fc2e91b0ed18e7b9f5df332dd1dc
+
+Count = 50
+Nonce = 2f1d0717a822e20c7cd28f0a
+Adata = d50741d34c8564d92f396b97be782923ff3c855ea9757bde419f632c83997630
+Payload = 98626ffc6c44f13c964e7fcb7d16e988990d6d063d012d33
+CT = 50e22db70ac2bab6d6af7059c90d00fbf0fb52eee5eb650e08aca7dec636170f481dcb9fefb85c05
+
+Count = 51
+Nonce = 819ecbe71f851743871163cc
+Adata = 48e06c3b2940819e58eb24122a2988c997697347a6e34c21267d76049febdcf8
+Payload = 8d164f598ea141082b1069776fccd87baf6a2563cbdbc9d1
+CT = 70fd9d3c7d9e8af610edb3d329f371cf3052d820e79775a932d42f9954f9d35d989a09e4292949fc
+
+Count = 52
+Nonce = 22168c66967d545823ea0b7a
+Adata = 7f596bc7a815d103ed9f6dc428b60e72aeadcb9382ccde4ac9f3b61e7e8047fd
+Payload = b28a5bc814e7f71ae94586b58281ff05a71191c92e45db74
+CT = 30254fe7c249c0125c56c90bad3983c7f852df91fa4e828b7522efcd96cd4de4cf41e9b67c708f9f
+
+Count = 53
+Nonce = 225557b0faca3d6cbaedec5c
+Adata = c7aafe7d3b419fa4ea06143897054846ac4b25e4744b62ba8a809cc19253a94b
+Payload = 0e71863c2962244c7d1a28fc755f0c73e5cbd630a8dbdeb3
+CT = 2369b56f21336aba9ac3e9ba428e0d648842a7971182d5ffac57f6ae1080efab4ed93f8b4ce1d355
+
+Count = 54
+Nonce = 78912be1a35e156a70fb72f7
+Adata = 12ba8eddff1c2a03ddd25bb924ff065a93fd712b2c4f61eb80d77fab2c4900e0
+Payload = 113efd182f683596862ccd5eba2e2d4ffa709d9b85c6f1d5
+CT = 835a22eb8d718c0ee1531a2d1bb95f58215c997c612908eeed3ccaeb7a814f69d3ec1fbf2ee9792d
+
+Count = 55
+Nonce = 91ad90b58d2044abacf957e1
+Adata = 4fc795b9126c23dd7fd514c2e5a8ca583e88a783b28cbb2a5df09f8b520ba0d1
+Payload = ed55f6b9eb8fe74474c037ede94ffd84ada846ede4ecff74
+CT = ecb595276fd5d412a7cc3f5cfe960f47a0d0e2df0b08a11ac257d67143722a976c9d7f44b09a767d
+
+Count = 56
+Nonce = 4bbe4ca29122c4892ca09b5b
+Adata = 367ecd1b71dfb96a84e2369f28705dfaebf0c73ed35d5364449b2391230be846
+Payload = 8dd497bb777bbc3e56e3af25a43545007bb00f2b9e9f815c
+CT = 563d61fc0a5b82804a580a7d752a8e61d3342fb39372b39b6843a685bde3175695796f6e64f35901
+
+Count = 57
+Nonce = 218e7b8a8fd62927f90b70e5
+Adata = 01815f599d6ba0d1c09f6f673bb6cca4c2a7a74f4e985be4c0f37842c7bbc5a4
+Payload = 80f3e4245c3eab16ef8bf001429122e46bde21735f63adba
+CT = aaceb16589b9de253c99d0d32409a631db71e8df8a7644bfd027e3466e8220144cb0552f9b2800e6
+
+Count = 58
+Nonce = eecc9f106a0721334cc7f5ba
+Adata = bf38d0ee11a796a517539bbc9ab00ff85a4ddbf0a612d46e2bc635180ad34c50
+Payload = 36cefa10af1a3446a2c8d4a1171144b9ddd8e33a7cd5a02d
+CT = 9bf3b2df93cf5b587ecc96f45fc75e6eb066cb286cb06f284c9027fc41bb8c848025fcf9d092a873
+
+Count = 59
+Nonce = e41af8ca408c4c12e37561a4
+Adata = e0b20892875f60b5d8763a04958487fa5b7cf8d67a456e430475b337245d671c
+Payload = 32a4da08bdd51336ed5798c7177b853a534bc98f2e6f7d4e
+CT = 95ffdc68f721cf2294d0d88002e3814167306fd906dbebdb7e6e0e5dc0a03826e51bd94269d7a41d
+
+[Nlen = 13]
+
+Key = 4a75ff2f66dae2935403cce27e829ad8be98185c73f8bc61d3ce950a83007e11
+
+Count = 60
+Nonce = 46eb390b175e75da6193d7edb6
+Adata = 282f05f734f249c0535ee396282218b7c4913c39b59ad2a03ffaf5b0e9b0f780
+Payload = 205f2a664a8512e18321a91c13ec13b9e6b633228c57cc1e
+CT = 58f1584f761983bef4d0060746b5d5ee610ecfda31101a7f5460e9b7856d60a5ad9803c0762f8176
+
+Count = 61
+Nonce = 8a56588fe5e125237b6cdc30f9
+Adata = b3aee5fbf409bcfe9b46ae68d570edbbed32c12d13926ffb5ddc60ff0bdb7f85
+Payload = eca81bbd12d3fd28df85e2cc3dcc2ecbd87408002fd00fe1
+CT = 9aad62a5443550d11f9efdab2de0eba74d47ae4f7d16adf4276664f6567f2f978bd4be4d80cd07be
+
+Count = 62
+Nonce = d908b04840caca2280e5293ade
+Adata = 314a202f836f9f257e22d8c11757832ae5131d357a72df88f3eff0ffcee0da4e
+Payload = ad1109ea5c79bb55d22e9713eb2df42767cb29a2eba3ad2c
+CT = 61fdcebb158cd03151697ae7871c0a998802997e0672e5886e5a9df1b1d6284ef657cde6f74734bb
+
+Count = 63
+Nonce = 6df8c5c28d1728975a0b766cd7
+Adata = 080f82469505118842e5fa70df5323de175a37609904ee5e76288f94ca84b3c5
+Payload = 1a95f06b821879df3fd3ac52fc99a7c1d3e9775263b7d036
+CT = 704f60f9cc3ef7bc00b4f7a271ca70a89f4d5605387b3e2f8cc80aa08572b90e9598d0a73712b720
+
+Count = 64
+Nonce = 6c6ebacce80dde9fefb7e5bb47
+Adata = 93f0fca0c8c84d5cc48160b25e246226d489225c0f8275e52856da592c715aa6
+Payload = 46820aec46ebd0d61706129584058a1498514928a87fe620
+CT = 00f6cccf45f046da1e6266afe61eed61c60c28515b2e1ab386b2c952055899184f0d95ffe3959f89
+
+Count = 65
+Nonce = b94bc20d8c9abca7645fc6bebf
+Adata = e1c083c93663f5a066ef337a61aa3fddde7c301a42463137c375cc2dcdd76954
+Payload = f1fca581d3dbbc61060c0c02adb47bc57954d25a283f66d6
+CT = 90c65d23e0e1786cebb95f9b1306d001b2e503842cdedb75e37a53d77b9e38605febdd7b2b666f98
+
+Count = 66
+Nonce = a4974791d417d7e9eea0f4ae8d
+Adata = 33602f308f3a0f7e1c75fc1e4321d545ffa278234958dbadd37f59a0f85349c3
+Payload = 41712c058d2d56b43b2c79278e790858a289320746c15a60
+CT = aab5656a1ef060c9b1ef7e2f3cc0bda40ff067900401182563ceb824708a20724c99c83f1caacd70
+
+Count = 67
+Nonce = 6003b771afe4e99e1ef1ed4a31
+Adata = f60d8362b2ebf523681bb051fd3ee13919ad86acd963c703c4178a5f01a84236
+Payload = b766022311c5e1d74a607fec7cb8ee805b8397a6c5f374c1
+CT = f73b2a6dbf8f798d4bfb489a6578c9c79152e42aa3b81b64a84e7af3116a18f7ce44ae93f420270b
+
+Count = 68
+Nonce = 27861168ac731a223dc35c03e8
+Adata = b7ba1c66282cb6092ba601407ff9578afdadf7ba7a4d08edef06dbbfd87171bf
+Payload = 0822e3e6ba982091d532cd5271fbde25305d1f6e71880f81
+CT = 5ab3e5296cd1f08704c82f6b42939702515b7733853d723d4009312bdae46958d844eca502bcb005
+
+Count = 69
+Nonce = ef284d1ddf35d1d23de6a2f84b
+Adata = 0b90b3a087b9a4d3267bc57c470695ef7cf658353f2f680ee00ccc32c2ba0bdc
+Payload = bf35ddbad5e059169468ae8537f00ec790cc038b9ed0a5d7
+CT = b702ad593b4169fd7011f0288e4e62620543095186b32c122389523b5ccc33c6b41b139108a99442
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VPT128.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VPT128.rsp
new file mode 100644
index 0000000000..f79db90b4d
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VPT128.rsp
@@ -0,0 +1,1383 @@
+# CAVS 11.0
+# "CCM-VPT" information
+# AES Keylen: 128
+# Generated on Tue Mar 15 08:09:24 2011
+
+Alen = 32
+Nlen = 13
+Tlen = 16
+
+[Plen = 0]
+
+Key = 2ebf60f0969013a54a3dedb19d20f6c8
+Nonce = 1de8c5e21f9db33123ff870add
+
+Count = 0
+Adata = e1de6c6119d7db471136285d10b47a450221b16978569190ef6a22b055295603
+Payload = 00
+CT = 0ead29ef205fbb86d11abe5ed704b880
+
+Count = 1
+Adata = 98d477b7ef0e4ded679b0bc8d880f09823ad80e9732fde59c3a87da6a1fcf70b
+Payload = 00
+CT = 5b85d144bb51d4927074d3536a2db83a
+
+Count = 2
+Adata = 28f32de10b6c9d3c3f46efec7aee24006208a54c4d1c2bba4b8cdce166cab7d9
+Payload = 00
+CT = 01045de4a09486eea5efa33ecc6cd299
+
+Count = 3
+Adata = af397a8b8dd73ab702ce8e53aa9f0189995c6c9e920dcb75795149550b499deb
+Payload = 00
+CT = dfd75400b59c3ad387bc86dfbbfb52ac
+
+Count = 4
+Adata = 3fa956bfaa27e249bf0a1276468d808259f3b8e2687851d780885d44cc2f04bd
+Payload = 00
+CT = 2b11d2549b4e2f0a81c07ee90af4d081
+
+Count = 5
+Adata = babbd1b44cae3af06e0150bf0e3d898f6fe862b71ea9f6b727accfc18848fc79
+Payload = 00
+CT = 10f76ab445f4ec158ccc1f7c6fee3ede
+
+Count = 6
+Adata = 7fba0bfda3b03c736c121cf9a257db55060b621be5168619ec4182f13ef6a408
+Payload = 00
+CT = 59e02d6a6aa3fb2692b04e65a0e735da
+
+Count = 7
+Adata = 057354a29808f4ed77671ed3dc36f8b03f5cd952caac5cb80dc3b319f3333e29
+Payload = 00
+CT = 367a2ade4087964dcb0ca2984d44657e
+
+Count = 8
+Adata = ec08b618602d091e9304715cb552b357c16fd1d7f7f023a28d84a98ba21ca0ab
+Payload = 00
+CT = 47cb92cd40bc89328d4dd44fbd727032
+
+Count = 9
+Adata = 45622834ea658b09b17f32777d18b34b387ef957bd344468f68e7178417a7c24
+Payload = 00
+CT = f5185afb8359b5ef995483c0bc4192c3
+
+[Plen = 1]
+
+Key = 6ae7a8e907b8720f4b0d5507c1d0dc41
+Nonce = 7f18ad442e536a0159e7aa8c0f
+
+Count = 10
+Adata = 9c9b0f11e020c6512a63dfa1a5ec8df8bd8e2ad83cf87b80b38635621c5dc0d7
+Payload = 0e
+CT = 4c201784bdab19e255787fecd02000c49d
+
+Count = 11
+Adata = 73616a428f1a567b2e9af86b1fc8aec6d597b1b55f2aa2219b3b662fa6bd3407
+Payload = 30
+CT = 72f14519f06b63fac3d5b2d9bbfa0cb758
+
+Count = 12
+Adata = 6d62f4e15e8bcc9ba4993bc50a046737121016f0d15020b90068250551167b1c
+Payload = 34
+CT = 7676b581a28ca0a0ba5178eba7fe028da6
+
+Count = 13
+Adata = 8f0b8289a1834ecc2167b59ce3c9d3b58465c4cfaad50c728d04360cb7e5bc41
+Payload = ec
+CT = aed99b805c0a4785ff2913cab3e50f6205
+
+Count = 14
+Adata = 477b2a6932f838f0d1bc420c0ca306981d8e2dab945b6f259e15fe888667220a
+Payload = ec
+CT = aeb50e41cd7af84a8fdb6aee144e904616
+
+Count = 15
+Adata = d6518d409b1f05708d0b44f18fb5721f20f3220f8d2f2718650aa9932e4579e0
+Payload = d1
+CT = 9312639c863974f077fe8236c943b464c4
+
+Count = 16
+Adata = 865e7cde73b558e9bfd05356923f8a697970811fc484acad2d5b3528baf1f986
+Payload = 24
+CT = 66d7265cde50bc7a3989458437baf06db5
+
+Count = 17
+Adata = f0c3c67a935eace53ed32435655dd0974fafe283622e8294a15d70977398eae2
+Payload = c5
+CT = 87063144b25d2268063815d1b42ebbac34
+
+Count = 18
+Adata = 341e71b2ef26e9db03882e06d06cde2c0617326cd157d5984d22f6f3407a9c39
+Payload = 34
+CT = 767da45c10d0d6498716bcf3f13ca7e26c
+
+Count = 19
+Adata = 31fce6735ba9a3385df11c153179b8e4141a3c6b8ad6eceaa211f3f17bfd0474
+Payload = 7d
+CT = 3fcb0a6f562974cfb3fb7c8d5cafd50f2b
+
+[Plen = 2]
+
+Key = 3d746ae6cac5cefd01f021c0bbf4bc3c
+Nonce = 597b3614ff9cd567afd1aad4e5
+
+Count = 20
+Adata = 90446190e1ff5e48e8a09d692b217de3ad0ab4a670e7f1b437f9c07a902cad60
+Payload = 4360
+CT = e38fdb77c1f8bbac2903a2ec7bc0f9c5654d
+
+Count = 21
+Adata = 6bc3d30925c67371573271f1a4273ad76e91e07dfab65f7bce0b241b5e4cd00e
+Payload = 17c6
+CT = b72955210d62e1393e4fda647c2b2e59a47d
+
+Count = 22
+Adata = d1bb4cdfc3f2c16d92576068543692aa4b5a427d688387af0f1583e91a0e8b3c
+Payload = 6575
+CT = c59ad54fd88a47b9f6e39cb4606af86d13e8
+
+Count = 23
+Adata = ae6136df9ab43631ef143515dacedbe759b3459e951bfaf4712a21c86352f1c0
+Payload = b1dd
+CT = 11326de841af64b55bb7ebe3fd30ba493c7d
+
+Count = 24
+Adata = ffead34ac26e21158212d07c367c3a7cb6b795887ee2d3d8ae25c60556ea88d3
+Payload = cd16
+CT = 6df93a206339de534271f6469edfa5ed07d3
+
+Count = 25
+Adata = e768e7d867820d46c1cc62ee0e51d4dac6f5c4b5785b5ccfbf05236871bdce2a
+Payload = 12f5
+CT = b21aa8f65144f2ec5809e2ccb38c8760f7bc
+
+Count = 26
+Adata = 402e802885e4119df17fe85f141c3d1af7727fcdb00f8e2c34e42a436d04ac5b
+Payload = 39c0
+CT = 992f9af825957abe7d89e175b6e8c0b84b5f
+
+Count = 27
+Adata = 8a3a622b3d347c0c5210d484adf77fa33205ba02224ddceea71d89c9ad8429ae
+Payload = 912f
+CT = 31c025d6a12e91e84e355934547f6b5dceb8
+
+Count = 28
+Adata = 636114e5e5f83cec94e1df21d6babb9f6a14a532fcbfc3bcf649fbd79ac1abbb
+Payload = cb6d
+CT = 6b826db959a21e9e4ebf25ca4f98501b560d
+
+Count = 29
+Adata = 04e84f9156998c2eca9e96079a6001f2947dc49a081b3d75e47d75f71ed4a606
+Payload = 5bd2
+CT = fb3d2006ff22ff231a6646ae561923818a21
+
+[Plen = 3]
+
+Key = 3e4fa1c6f8b00f1296956735ee86e310
+Nonce = c6a170936568651020edfe15df
+
+Count = 30
+Adata = 00d57896da2435a4271afb9c98f61a650e63a4955357c47d073c5165dd4ea318
+Payload = 3a6734
+CT = 384be657bfc5f385b179be7333eb3f57df546b
+
+Count = 31
+Adata = 50f6e6dd57bd3a24f6bfdc8b1c7b5a36ebdd07fd6d194e6e82da47151d9c88fb
+Payload = 4ffad3
+CT = 4dd601b8ca97bda492546d82dccdebef441f8b
+
+Count = 32
+Adata = 70e132023acae1f88c7a237b68f5bdce56bcfc92be9f403d95d3bcc93b4477a9
+Payload = 8a594b
+CT = 887599fa0f3e397d9a580aa39c7028e1a508c9
+
+Count = 33
+Adata = 08d2b011f36e05dc728c1a8bda3d92c779a3d2f27c4b041810bd6222c852b14d
+Payload = 1f89df
+CT = 1da50d593460d335e2f7a6d40b8fe305b0f690
+
+Count = 34
+Adata = b207eb870aeeab27c6201ef04650bdc7ea30028a243420f7d198f1c9c9a43023
+Payload = 72e9c1
+CT = 70c513a2d49e1a113767ea4219107819d88b65
+
+Count = 35
+Adata = 74294088721fc9e7aabd5f1c66b5369b1e2d2cdb3e73abaa28ecd1c37d4ecea2
+Payload = 016083
+CT = 034c51dab1c819778be8453db163c882063af8
+
+Count = 36
+Adata = abbd347999a1c26368cdb17ab08bf57a8e942d1248296e952f5f42f2cabbf0e6
+Payload = 25f665
+CT = 27dab7537eb435df8d0e48c3f7e0bd1877c866
+
+Count = 37
+Adata = 231b33dc406c9210f59a5df1cfd595c803474db34b9b1848f0bcbe7b28df33c2
+Payload = 158606
+CT = 17aad4da549fc63d55b5910bbbf64435b95220
+
+Count = 38
+Adata = 69b851e63a78baef90637978e3dfe8c47be4b21e85bb89bf67051cf251004376
+Payload = b07452
+CT = b25880d5ee29fb2af47f8040fad585921057f5
+
+Count = 39
+Adata = 9b1f786c887d310b8efd3e8192fe504f603024c94aaa4ec9123736a40bf1605d
+Payload = 65187c
+CT = 6734aebc3ee43e10205f83143e0d3794a6734c
+
+[Plen = 4]
+
+Key = 7ccbb8557f6e08f436d0957d4bbe7fdf
+Nonce = bb8e2ef2ed9484f9021cda7073
+
+Count = 40
+Adata = fba1d18a74a3bb38671ab2842ffaa434cd572a0b45320e4145930b3008d8d350
+Payload = 4cabeb02
+CT = 32501f4235c4dd96e83d5ab4c3c31c523453c317
+
+Count = 41
+Adata = 78b3faecb2bdf6ed14ac2b86ded07aa791b60f5d54f9e24a965a8453f5131898
+Payload = 5ff73653
+CT = 210cc2137907d6a03e66403a7d9330d30d934a8d
+
+Count = 42
+Adata = db1239528eb464dd063e2a97ee83a87d6002ebb4fbafa77036f72c14f3fe959b
+Payload = 062fa9ca
+CT = 78d45d8a44f4bc78fbb969935076134437df82b4
+
+Count = 43
+Adata = 0071f1edb3a0ce57af3c88bb0ccf138f752697a77e55695838fb39de04c78dfb
+Payload = cad710b4
+CT = b42ce4f459692911fea2e0034d06c3b2e89af3d1
+
+Count = 44
+Adata = 7381471a62b1fa6f5061c4c37e9721f07099d007ffaf8639aa2ae3f82da5a559
+Payload = 7ac716b4
+CT = 043ce2f468484e22381923bfcaed16e0cb85b0f8
+
+Count = 45
+Adata = 19bea6d92d5892216e8e4a30dda802387800bb046a6717817fc46c7edafe17b0
+Payload = 362da02c
+CT = 48d6546cd081de39c247df309c4b56c31c03690d
+
+Count = 46
+Adata = 8503c8eb9cebc6110f259e35e03a0740267768130ce6f61b1c7d1d25be942274
+Payload = de52b209
+CT = a0a94649c6c6bd7b3a9d7c4dfa2738847ea3cb33
+
+Count = 47
+Adata = d2445db6efecaa3f426b06de8d496ceed54a1d0171384cc762e21b31e265c6d5
+Payload = 8fe8b383
+CT = f11347c32ca874d18d0b790856837555f4d4699a
+
+Count = 48
+Adata = 8cda7d1e135cf5fde1ec9473c4b42c1bbb445c27fd87b5f73df61ceb2d0b6f75
+Payload = d8d6b2c9
+CT = a62d4689932c2f8d78e322aaffc90846025190f1
+
+Count = 49
+Adata = b506a6ba900c1147c806775324b36eb376aa01d4c3eef6f5a4c25393ecbf2025
+Payload = 6a029e53
+CT = 14f96a13c346a4084918081b4bbe53b50d896788
+
+[Plen = 5]
+
+Key = 3725c7905bfaca415908c617b78f8dee
+Nonce = c98ec4473e051a4d4ac56fd082
+
+Count = 50
+Adata = 11bc87f1c2d2076ba47c5cb530dd6c2a224f7a0f7f554e23d7d29077c7787680
+Payload = f5499a7082
+CT = e378b776242066751af249d521c6eaebdff40b2642
+
+Count = 51
+Adata = d54219ef4fb851bebd1c546011ae3922b8337e19c28d4d58428efd66f80edcf0
+Payload = 513c46fcce
+CT = 470d6bfa68e7258df363e0e9af67a543c86db3c994
+
+Count = 52
+Adata = a92e88edd297da8c7089e21822b3e6cffd6837c78b975c8413fd6cca1b99bcb0
+Payload = 9d62e557c3
+CT = 8b53c8516572b7573e5b27a1d0e15cdb7b06c8857f
+
+Count = 53
+Adata = 77d9c306aa257379053cf1f2043c388a301dac2a9e2bb89eb8bab6eb3f150fe3
+Payload = 7a05db235f
+CT = 6c34f625f9de691a412ad54bbdb6ceac45ed45902b
+
+Count = 54
+Adata = 081568ae0b948aa647b9d4dda5d42641ad5de72aa9874d8d0717d872007720a8
+Payload = 30a22ca0fc
+CT = 269301a65a8a1bb8ba3d6763dcb1bdd3400e3459f7
+
+Count = 55
+Adata = 695ba4dea0f84baf190ec25a25fc00cb9898902d7a17e6f5ff2df323b974f7c4
+Payload = 35e25aa51f
+CT = 23d377a3b9403897d496cabcd5bd9de3282199a8ed
+
+Count = 56
+Adata = 1f3ba0336a634efdd11f8168c0fe25039f9403bfa70b3898f4dbe577dbd52957
+Payload = 8bde704c74
+CT = 9def5d4ad270a81f7cb0ab7ab2b495f51d66abeee5
+
+Count = 57
+Adata = 097b9ebff3ff93a143678d59721fdf359e95cbc82585ae47727a773317925d38
+Payload = 428542ecfb
+CT = 54b46fea5dce68e9b01a4462a2221bd2f3cadf64c0
+
+Count = 58
+Adata = 76d0341dd44c39e43a23dbcf4cb602f15d5fb9fee20c3d0d262d539c3fd1dfd5
+Payload = bd6866ded0
+CT = ab594bd876f2545964ef3978cad3387d61104bab84
+
+Count = 59
+Adata = 7e7c40ad64b511005b4546f9ec61ca24829390fbc4bd8507225bc348ae0807d7
+Payload = 5822755a3e
+CT = 4e13585c98002c41938a935d51905b2a708a2c5194
+
+[Plen = 6]
+
+Key = 80bead98a05d1bb173cd4fca463b8fa3
+Nonce = 8a14a6d255aa4032ebff37a3d7
+
+Count = 60
+Adata = bb4e706e73d21df66f64173859d47e247527cd9832e20dccff8548ed5f554108
+Payload = e479990bf082
+CT = 89c9246238878427f36b1f6c633e4542f32b50ca8edb
+
+Count = 61
+Adata = 9db2182c8a4f5471082bfa1a8496602cbcdef2790f7e8f71f791303bd48dcb05
+Payload = 017a7fd1aecb
+CT = 6ccac2b866ced76fe54da69af5edf8309c7f013bb07e
+
+Count = 62
+Adata = bf483f59fb73681f27b68168c998c90ea8ceea997654c6fab2bd737dcdc884f9
+Payload = 512fc5e4973a
+CT = 3c9f788d5f3f662f53d17f7cb6673415bb2324ca0666
+
+Count = 63
+Adata = b91e641d8210e1ef705fec2beb9f58a391c7d1a38935cd1d13f2c00363388ff5
+Payload = 06212e989616
+CT = 6b9193f15e1340c86156b1065b64af1e4d6c89b32603
+
+Count = 64
+Adata = 5cebf908e232d797fcce8453c4c3000868d4172622a4ee0d6a1bdd876a0b7c96
+Payload = c45629069ebc
+CT = a9e6946f56b9c07ef5349903b928e39e99e2e32625de
+
+Count = 65
+Adata = ab92cbc97f3aa6f9ea4dae5d8c3d9e91231f43ffff548da7b668e61c183ac2cf
+Payload = b949ced37725
+CT = d4f973babf205e40654ea16e83cc6faeaad668c416f3
+
+Count = 66
+Adata = 2c3d2f9c7e89c2b9e07317c4db6e9f00f5faadfad531c5bea79d164ac24d4543
+Payload = 517ff7b383b7
+CT = 3ccf4ada4bb23102a502dbba0c280e1d5fc627fe3a9e
+
+Count = 67
+Adata = d798e77ab0f3697768f23014fd31b9e8762ae65b6aa8a4bbc17ecb8cbe78461f
+Payload = b40d863ca4ff
+CT = d9bd3b556cfa6745fd4c954396e696697731e1f9a262
+
+Count = 68
+Adata = 45b44e3dec57e24d960fd1767797ffdbbab81e38bab37e6974df262c3d932327
+Payload = 56e00289a003
+CT = 3b50bfe06806bdf2b2dd47077c98234eae5d47c3b594
+
+Count = 69
+Adata = 645d27970ccce096d082fccfc1183955bad2611af0dd7c58c9d54430f28bd992
+Payload = aa22bb1de579
+CT = c79206742d7cea66649ad7e204a344d3234125aa324b
+
+[Plen = 7]
+
+Key = dc8ec91184ba18eae31ac2d3b252673f
+Nonce = 0da4c988f521f5648259f2bec2
+
+Count = 70
+Adata = 6d5573c9279897d7d1602d8a95c04bb5ca3fad2dbe89a024b3651eb227e73bb5
+Payload = 2a5775986551c8
+CT = 4f259f2a718faea852a7c4358dfa9f5467357638acac90
+
+Count = 71
+Adata = ff0ab5021ef466e2e898b0993d691145168be558682c74914c172f2b5e863754
+Payload = 8db3c1ca0580f9
+CT = e8c12b78115e9f8767c76e707d48a2144e090812e0192d
+
+Count = 72
+Adata = 2ee03cc28f79773af139c4ea55ec4daa48bb2885b8adcd5f066eceda5c4ec27b
+Payload = 3c69e2e83236b6
+CT = 591b085a26e8d05486df740083c959fb62ef7e2e221602
+
+Count = 73
+Adata = f041504d4c1b3d5be358bd6d350af42921205d29ab22b44ffe221358adef5bb4
+Payload = 777828ab5ccb68
+CT = 120ac21948150ebdc4d2b86b2528f75db4a7f5423f4395
+
+Count = 74
+Adata = 81ea116832d69542ac8d3d22c16c82eecf2ccac39264dd933c4f9c13c8d0f1d4
+Payload = af556fef3584e3
+CT = ca27855d215a85a7b06d1b710baa15daef19069ecf46f0
+
+Count = 75
+Adata = 8a0a120ed290a62456f002da1c250a0ddb1ebd57185a733d8fb562aad482679d
+Payload = 98f26635351f14
+CT = fd808c8721c1723811129add52e1406d50cbff4aa82802
+
+Count = 76
+Adata = 12b5a76faedf6f855e328c2cb87be8aea78c5e926b32d828e167b46205c86de5
+Payload = bd22c1ec05dc26
+CT = d8502b5e1102401563d3da8a6cabb7515f642e42fb4b2e
+
+Count = 77
+Adata = 8dc32f35ef4bcbfd040ad25dc36d0bd2486f93d0cabb7704cd1582dc99f65449
+Payload = 2a87c0d64806fe
+CT = 4ff52a645cd89817609a21f703253e5e56beef4ac71759
+
+Count = 78
+Adata = 83ced632359a11eb0c4c99baad84df5cac15bc5453b6593d9ffb4c5e8c84037f
+Payload = f05f39eb0a3d64
+CT = 952dd3591ee302236c72f98da859b54be7c598d85c37eb
+
+Count = 79
+Adata = 771a818a24e7da7b98f4b4291ef34bec7e1656b0c6c6e9474a989a04ea7de385
+Payload = 59dad755af92c2
+CT = 3ca83de7bb4ca464c8cd38cbcc46e7f09bf3e1c6590c71
+
+[Plen = 8]
+
+Key = 19f97ef5318b8005fc7133fa31dd1236
+Nonce = 01ce9814c6329dbee1d02b1321
+
+Count = 80
+Adata = 85853f120981f33cf1d50fde6b8bc865fe988a9f12579acdb336f9f992b08b89
+Payload = 6d972a673fbe1ca1
+CT = 2f12a7e7acecae5d2563309efc19368cdee8266538ca89d3
+
+Count = 81
+Adata = a4ec5aee89e2cce2115b6c1f42570bc5062887cad08192a682d0b4508fcd936a
+Payload = 68b1b6367a15fe49
+CT = 2a343bb6e9474cb528096a5fec5e5359c369833eac3b7efb
+
+Count = 82
+Adata = f5499a7082bf1e6e2923211271f5f7f6d7c7b26db7963071705a58ddc4dca0dd
+Payload = 707023615563a40e
+CT = 32f5aee1c63116f2754a65863efb60c98dbb536e2b5a69d8
+
+Count = 83
+Adata = 765f267befe6fcfaaa4b46eda32e7bfab87f12ceb07fa3b37be74965bb664a21
+Payload = b56454bc50df3e28
+CT = f7e1d93cc38d8cd40b6e9b7f3b3541ffee66a1f668f67d28
+
+Count = 84
+Adata = 9ce65598cd1f86afc9aaaf172809570cc306333c25523f863c6d0e0154c55e40
+Payload = 962f765da3565bde
+CT = d4aafbdd3004e9227018c9db8baf6be349d93d4eef7d7c9d
+
+Count = 85
+Adata = d0125e30c36232a8c07cee9abc53453b276849a7c04ade80ad586ed8cbcede51
+Payload = 4f18bcc8ee0bbb80
+CT = 0d9d31487d59097c501b28887f05fd66f050525943d101f8
+
+Count = 86
+Adata = 90dfd9e7bb7bf8fb70c22a879ffa760d14cda7b79ce4968f69b8a7f2b7a59642
+Payload = ca293c9e1780b401
+CT = 88acb11e84d206fdda53dde2e1aef96b3658a7635ee54188
+
+Count = 87
+Adata = 58f518710e6b282482a7f1950fa353b13bdda10c9aaea6d5f0d7ea0a965d31e8
+Payload = b9df9fb4a6b299b4
+CT = fb5a123435e02b48b62a5ec234f1efd1b52c8fad1cf09890
+
+Count = 88
+Adata = df052e95aea3769a433ce4e4e800b8418649bbe8c6297eb07545e6802de7e807
+Payload = fb2441d1594a488a
+CT = b9a1cc51ca18fa76bc051ede6f37cf67543a7252d7d9b203
+
+Count = 89
+Adata = 0875020959ed969cfb38636d1d5aabce9658b00171a7614ea9e5395331c7659c
+Payload = 451101250ec6f266
+CT = 07948ca59d94409a5be4be6bc6b18104fac167b6e3fc15f7
+
+[Plen = 9]
+
+Key = c17944bfaeeb808eed66ae7242ab545f
+Nonce = 910b3db64df3728ca98219e01b
+
+Count = 90
+Adata = edf64f98b3ab593cbcf68ab37a8c9472e49cb849d4a744deae925a5a43faf262
+Payload = 7caae2640e734539d3
+CT = 0dae8b3ccf0b439f6ff8ee4a233dfb7753f6bfe321b3e26959
+
+Count = 91
+Adata = 29ac8fd6a20a5df4ec79660c44d373da42de7d7c5fc35982b6c29b480723b484
+Payload = e574b3a37af3bf2251
+CT = 9470dafbbb8bb984ed63b1477d9506a51ae23abbac179d8b02
+
+Count = 92
+Adata = 9ae5a04baa9d02c8854e609899c6240851cbc83f81f752bc04c71affa4eed385
+Payload = 2e3cf0af8c96c7b227
+CT = 5f3899f74deec1149bdb0986198bce2e486581c041029a81d9
+
+Count = 93
+Adata = cc8e789462879e348d20be4e1161d7b7fc6f8371d8f8cb2d25d13f0e07de47b0
+Payload = 16f22817c5b79f9fa6
+CT = 67f6414f04cf99391a0cbb2df2079a6eb964c3469f4f326122
+
+Count = 94
+Adata = c63061f2800228269015693336f78bb535ae8b88869e4ccf4ead2f3b0ea4e48a
+Payload = 64fe8076d4e8538e18
+CT = 15fae92e15905528a4a40ca7622acf7266b7c24cf0c3202e4c
+
+Count = 95
+Adata = 71c14a7031033db15bfe23b75fed9daf8886dd11392a0b787660e7b1a581af11
+Payload = 4814aaac48bdf43c92
+CT = 3910c3f489c5f29a2e7de20e98586cd5d684bf015a7abbe82c
+
+Count = 96
+Adata = 8f4947f8588ed866ed7477d7f1a28046430c6470806a50e3c9e80958c61f1b42
+Payload = 392a692b57a8a97f60
+CT = 482e007396d0afd9dc8d503f5d87818f7c0e173b857cef4288
+
+Count = 97
+Adata = 9d44f6df58c2b43db67e3daa95b176c81daff32e996d670e86405e15eae72e93
+Payload = cba1e00e345b0cb7eb
+CT = baa58956f5230a1157c85e2283d9e80700268a6459d1451d00
+
+Count = 98
+Adata = b6ada12f7a28211e9d2c07cbb3d39fa77aadc077b34c46f93006c1ca2ff66f87
+Payload = 22f5b6752582919dc1
+CT = 53f1df2de4fa973b7d1056aea3d3e4f7a5219170aaa52465e1
+
+Count = 99
+Adata = d6411fd5b25433f67ca75e4560ceb809d3721266beec358dde126b2f6a514137
+Payload = 6e1b55d6f5288c5451
+CT = 1f1f3c8e34508af2edfbfcf8200a8a3f8d995f50284a7280c8
+
+[Plen = 10]
+
+Key = 0fb9df6f638847f5de371f003dd938f4
+Nonce = c9ddf61c052f3502ad6b229819
+
+Count = 100
+Adata = 4f9938d5bc3dcbe47f6b256d5e99723d0891e50c6175aba41b011e4686113c49
+Payload = e10cc36bc1c5d3c646ab
+CT = 7f797367de50be6dc04e4cf0d8c24189affd35060cb7ca3dd136
+
+Count = 101
+Adata = e013a2edd5b86bab8df5c9940d0a0c864478c1ad42668304a643141855adac10
+Payload = 15841284c959febe63f9
+CT = 8bf1a288d6cc9315e51c4148ef85caab151488c1a6b3df540d21
+
+Count = 102
+Adata = 147d77d509f642189594df17574a0ce62b52a838feb62310e11533995ba4c851
+Payload = a8b4e5829069c335d1d8
+CT = 36c1558e8ffcae9e573ddaaa1e7c22b3efa8362abb3d31ee8884
+
+Count = 103
+Adata = 0bb09658e23fe8a08c01a6994ef36cb8dcc9a806297a09c67efe3558ca56bb5d
+Payload = 1bb2da0f1ae7e044deb0
+CT = 85c76a0305728def5855317b141383ad38dd78569d5f846f2520
+
+Count = 104
+Adata = 34eb2e6149bad764837f6f25ddd96865e5b05d5cbf233c4f6cc2aa654dfea3b7
+Payload = 63af538196add9b3fad2
+CT = fddae38d8938b4187c374e6432971aecf6bf7cf5244d21f7f173
+
+Count = 105
+Adata = b69f26fda6d1cd92897e03758cae020c4e1beb019ce5ad987f872940780a9468
+Payload = 6ef2df5a1688ae795537
+CT = f0876f56091dc3d2d3d2e4d0ffc0f0add38a80c7ffe6b4701e54
+
+Count = 106
+Adata = a7375ba32251af0138bd9fd8fcd56a7c43ab2ca9a7fc0117d25f6d4ef9c2fcbc
+Payload = 3f46c83021069ac488a1
+CT = a133783c3e93f76f0e4447fdd0b2f29f39094ba5a7375e278349
+
+Count = 107
+Adata = f9b91f7298b4e43843fc739a2f41c57c3f2cf36378fe4c34b574a43f9cedee7b
+Payload = 86c10a6dfdd6a06ef638
+CT = 18b4ba61e243cdc570dd57500f913ee3f46801e1bba9d4db7ecf
+
+Count = 108
+Adata = 9d35876d9449a1642b5062dfbfc7a26a7ac080b7198f4aeff2c79e463565cfd2
+Payload = 196c80d02b663bdd89fd
+CT = 871930dc34f356760f1856a6b87519b4807a2114ced587f72189
+
+Count = 109
+Adata = f2d5e927eb507f889efc6f21d783851f638f978c74960cc347f89f2703476114
+Payload = bd27ae3ade0781a33d5f
+CT = 23521e36c192ec08bbba2101012808adefe9b8166e04685bd537
+
+[Plen = 11]
+
+Key = 006ff7d3153caf906ec7929f5aef9276
+Nonce = 57db1541a185bd9cdc34d62025
+
+Count = 110
+Adata = 7d9681cac38e778fba11f4464f69ed9ebfea31b7ffcaf2925b3381c65d975974
+Payload = 31be1b241cae79c54c2446
+CT = 9dd8a4244fbdb30b624578a625c43233476bbb959acd9edebe2883
+
+Count = 111
+Adata = 1b0012c468009bd2851653013782c7b71ef43c393afd4dc0aec4d6d0c3fa11c5
+Payload = 8802831e22092b30110cf7
+CT = 24643c1e711ae1fe3f6dc9d477ca066ec2befa854a1faef018ea8b
+
+Count = 112
+Adata = 48b216375c00ca7e9c4048834b37944d2543e24fa091fb3c7290e11c53a6b6a0
+Payload = 3b3f782d637319d7fd161d
+CT = 9759c72d3060d319d37723eb6be9a78dfbd9e16181679b782969ad
+
+Count = 113
+Adata = f3e06a45fcf1f6abeb00727bf2c9bcea00ce621d38f7b7eba17c27e51f04c793
+Payload = e98f5e5a20d02c80372d6d
+CT = 45e9e15a73c3e64e194c533d9574d95b821a5170e9b61d8e6b2ff3
+
+Count = 114
+Adata = b36e27729f9a139d8ec4f61215b7bf1149cbb4d93a5c14bebd7cfb7c6fe585cb
+Payload = ceeed4fde3406ec40f7ac6
+CT = 62886bfdb053a40a211bf8aa193d257907be1330abaa56bc4f431a
+
+Count = 115
+Adata = 8886ed7fa414d74aef704a9751b197cbab02c41c6aedcaf65cda019dc2d2d815
+Payload = b38f03449883773135c0cd
+CT = 1fe9bc44cb90bdff1ba1f31d92029a6428748664b5c815f15ca1b7
+
+Count = 116
+Adata = 816d81af167d2294497d9b06a39fdf75e37cbacf4d10c3a444068c891b361bba
+Payload = 8efb141db7b77c521003cf
+CT = 229dab1de4a4b69c3e62f1386e4ad7c72ce0081a85d4cfd34254c7
+
+Count = 117
+Adata = f427c47e10c45bb3c7e75e9e604503b3560427691470358efdef48ddaf3794d2
+Payload = 6dc38e37d1379732df4dd5
+CT = c1a5313782245dfcf12ceb98eeb05bc376a1042735569d5b63f8fa
+
+Count = 118
+Adata = f3df712b5e8dd8e4aa8b7c5f41e93bd11b0df66a3456a01f3d0094ad91482cdb
+Payload = e0e358aff203369dd5960c
+CT = 4c85e7afa110fc53fbf732065b03ebeb68a9153cb4ed152ce0d64c
+
+Count = 119
+Adata = 264f2c7b095a296eb8ff6b5151ab3d9497ea8dc0002a9e5b09c2fd0ccd32b6ff
+Payload = 57b940550a383b40f3c308
+CT = fbdfff55592bf18edda236fcd16c8360a408e2787f930ed275bf3f
+
+[Plen = 12]
+
+Key = 026331e98aba9e8c23a9e8a91d0b0c97
+Nonce = bccfe69bba168b81cbdf7d018a
+
+Count = 120
+Adata = 26e011143a686a7224ddb8c5b1e5d31713fa22c386785e2c34f498ae56d07ed5
+Payload = a82200ef3a08c390dec5cbf9
+CT = adf4fc6f9be113066c09248fcb56a9c1a1c3bb16fbb9fbaedacdb12b
+
+Count = 121
+Adata = 97a720ae4720546e31263a1a538ce1d35c198c23bd4362e0023a67536328ab9a
+Payload = 7fc58d1bb450b396b9161f53
+CT = 7a13719b15b963000bdaf025002120b619a391fbd23402e5edd4949e
+
+Count = 122
+Adata = aff6c8cefda055c67262e9c68825d1ad2a7488e5b09640a111fabf6254d96cc0
+Payload = e9ea182d7f895f312b9738db
+CT = ec3ce4adde608fa7995bd7ad48b6e9a8de0099a28cebbf5c2bad42ff
+
+Count = 123
+Adata = 35a3963b43f47855ef3df12af5de3626e0c5c8d9cd2a534c737cd695609b05a9
+Payload = cfbc8bcbb5e5bb744bb1f340
+CT = ca6a774b140c6be2f97d1c36df80fd62e751757bb0a32a987980afe6
+
+Count = 124
+Adata = 46a2e6bd3fd5336abf02eace3cd1e1f6dde505ab976a9fa596edd6fbde7175de
+Payload = a334f8f41897cbcaeb5cffdf
+CT = a6e20474b97e1b5c599010a93b211350c70adf9bab5c01081bdc6a99
+
+Count = 125
+Adata = d110651c00ac5540f9d1ed9eb175e06b97163fc36d43f048565e5d0c30a069b1
+Payload = 3f781267290e8e73c6355e75
+CT = 3aaeeee788e75ee574f9b103d7f65690d9a2fb6759d658c9bdfdfc37
+
+Count = 126
+Adata = 978644dc4e36f1d98a2a63e19bbf8af11785d09fce58a95c00cc6bf6cecf6161
+Payload = 3dc39dbb91efe8b16396d488
+CT = 3815613b30063827d15a3bfe0d5df472f49e7f713cd1373293810906
+
+Count = 127
+Adata = 5ae7528c5e965880b1533cbd78c1e81a8187379327a2fc3f76ff45829049e183
+Payload = 6caa8c0764512baa39dabac0
+CT = 697c7087c5b8fb3c8b1655b64bfca9ef00b0f2bbb03c1a3f7a0862e7
+
+Count = 128
+Adata = afe754828be6e3731d3eee54b021b4fa182247bd958e9074fb0094a11030f5e8
+Payload = b19bc92e2305883580dd7742
+CT = b44d35ae82ec58a332119834a03be1d1d262b03c0ab425d533fe4ec1
+
+Count = 129
+Adata = 0650859c635654ca4d815963c0a99f9d2f47456ad37f739c425e924d4360bd7e
+Payload = dab87e79544df1cc98096b91
+CT = df6e82f9f5a4215a2ac584e7da61ca8461925996880e2874393232d6
+
+[Plen = 13]
+
+Key = d32088d50df9aba14d9022c870a0cb85
+Nonce = e16c69861efc206e85aab1255e
+
+Count = 130
+Adata = 0eff7d7bcceb873c3203a8df74f4e91b04bd607ec11202f96cfeb99f5bcdb7aa
+Payload = 4b10788c1a03bca656f04f1f98
+CT = 89f15b1cb665a8851da03b874ca6f73242f2f227350c0277e4e72cdaa6
+
+Count = 131
+Adata = a533b3279db530eaed425842b0d3528f5c5e4c16acfa0f49de43d6491f0060a9
+Payload = de6ea86d3641d916c4394fdd31
+CT = 1c8f8bfd9a27cd358f693b45e594271cc06f81d510075728cfeb89222c
+
+Count = 132
+Adata = 8e6c1cde142e18635c1b4f0cb54d3cf817f22ad7c25bf6a022501682f6a7da1c
+Payload = 6f3b32adc8c0314872947f3d31
+CT = adda113d64a6256b39c40ba5e5ab1aefed75400a41447b2bd8f0605542
+
+Count = 133
+Adata = 248a4389da2d51b87907dc11c46253515503ba80de5d06c9b505cb89906614a6
+Payload = 0cc992a8c736b44fedb4ad498f
+CT = ce28b1386b50a06ca6e4d9d15b46b3a6463876f1a43a287748f339e913
+
+Count = 134
+Adata = 2e2c8244a2cbf53816b59e413207fb75f9c5ce1af06e67d182d3250ea3283bcb
+Payload = 98104fd3f3413ad1f57ef4912c
+CT = 5af16c435f272ef2be2e8009f8f625786bdc58af24b17c1ba34fa87baa
+
+Count = 135
+Adata = 4ada86d88d5f49dfcde13fc30ba9a1af58d5254b47fb1885a20fad915c87952e
+Payload = 3b4fec79d52d8b2a533917b75f
+CT = f9aecfe9794b9f091869632f8bd4a918290cf97208232c76908514b07a
+
+Count = 136
+Adata = 9e3b23232e5a9e69747f8bcb148cd6d282fd9b7ecd6d97e8bb5cdc261b2fc86f
+Payload = f10c19c76ae7ed55e1651155df
+CT = 33ed3a57c681f976aa3565cd0b01d6306bb91c315bb4a23fe23d496d09
+
+Count = 137
+Adata = ccea2c815ea4efadc3007f511d633e98f9fa38b0e0fb572b282ed6a610adf7a9
+Payload = fa34af376868d9a49aa200f59a
+CT = 38d58ca7c40ecd87d1f2746d4e620d9d3004587c5d510e2a857fc857ea
+
+Count = 138
+Adata = f7277fb296e2c0d2c9ceb7013ea8b59fe37e26b3b42a0b8cd01aaaa8d35283d4
+Payload = abe2fd996bb6804ed3286c057d
+CT = 6903de09c7d0946d9878189da982d2438a5138977bde5f514e2335c28c
+
+Count = 139
+Adata = 14dd1810df3eeee78ed3836c77edf510d91ea28f119bf57111e580d70da94b74
+Payload = 395ea6979b77dabd2042aee4ff
+CT = fbbf85073711ce9e6b12da7c2b78100a05448fa6e74bd3ed16c3bd364e
+
+[Plen = 14]
+
+Key = 7301c907b9d2aaac355c5416ff25c59b
+Nonce = 7304b65b6dab466273862c88b9
+
+Count = 140
+Adata = 2c5d114eff62c527cc2e03c33c595a80fe609bfc0fe13ce3380efe05d85cceac
+Payload = 484300aa3a506afcd313b49ead8d
+CT = 928ca58b0d373dc50c52afac787ce8eeb5d5b493661259a9d91ea31a5f7e
+
+Count = 141
+Adata = d9ebc1cbfab9034317132a72e0f11c341331146a59e7a2f26bf4f3d778da52c4
+Payload = 8b318f75ed79a7978adc17c4d2d4
+CT = 51fe2a54da1ef0ae559d0cf60725552193439abfedda67d765d030cef30b
+
+Count = 142
+Adata = 9aea86b9fbd9bd4504ee2e25054942b33d3cdbd84215db7ea337e548cb706780
+Payload = 0256b0d154c768c85070da6ea8c7
+CT = d89915f063a03ff18f31c15c7d3615013c2bc9338868fad0d2fac11df019
+
+Count = 143
+Adata = 08afe10bbfbd65b948a6561bbeaf3ab46a8e3d0a861f1cfc46584156197f30a3
+Payload = 89ed296a3ac03fbfb71422b92117
+CT = 53228c4b0da768866855398bf4e66c3c4cb8c50891d6523245e4c619aa99
+
+Count = 144
+Adata = 7d653792bb8683e07c7d2c800db6f7f08343c85af2377115df4fc86ff7d8fcaa
+Payload = 414b6acb1db479028f5cc8800f2b
+CT = 9b84cfea2ad32e3b501dd3b2dada792d2cb93e45811a4c897ae9d907c9cf
+
+Count = 145
+Adata = 4d73c1484f9429eb15742f29ab05cbab6552abf40e127b93427d649d195ed25a
+Payload = 163f67b3766c3c650ce26c5bd8b5
+CT = ccf0c292410b6b5cd3a377690d441983a87812eaa7b66c5a0e54a01cb882
+
+Count = 146
+Adata = 2fba7a881f019a8745691343d79ef3656e25bb37b93fb5ab7311889f92010a5f
+Payload = 9c5b4aa703c27d16d82013853e16
+CT = 4694ef8634a52a2f076108b7ebe7b0afabd23b33765a63753cad66b0e6db
+
+Count = 147
+Adata = a640343fd4a866aec07b667d25176e11a32fb4d8bfc08fde2c46dc9b492fa010
+Payload = 99eb86b3202c7ce68a2339065f47
+CT = 43242392174b2bdf556222348ab639b8d0f97540373a7b9061aa3b2f7044
+
+Count = 148
+Adata = 9efd58d3ef5f74f663b2b5ca5e96c5a2fe85ca5eac1495d7f1751c7d8b412b3e
+Payload = 3f5c1d038161e65c9ed955c961af
+CT = e593b822b606b16541984efbb45e312c803e29f7be7c5eb236401037a320
+
+Count = 149
+Adata = a7d7ba684c0903323f7efc83dc32815195df325394162fb5a18f201047be7999
+Payload = be8dea2b4e602a787ecd28f2f7f0
+CT = 64424f0a79077d41a18c33c02201fd929c717d75388387dc25bfcf90b707
+
+[Plen = 15]
+
+Key = 38be46d271bf868c198052391f8a2147
+Nonce = 6758f67db9bfea5f0e0972e08b
+
+Count = 150
+Adata = c6de3be97f11d0e2ab85c9353b783f25b37366a78a2012cecf5b7a87138b3c86
+Payload = 61bd1385be92097e866550a55278f0
+CT = 7c9fa8d99b38f825315ece6a2613f55e902f296dcce870263ae50cda4fadae
+
+Count = 151
+Adata = 7c8cf9c650511f33af82e807e60336ec086bd2d9400a5f35652b8c3fcf968ead
+Payload = 7e5e51301fa44a21f2734731ee3710
+CT = 637cea6c3a0ebb7a4548d9fe9a5c15cae8a9e4b606f5fbeac2b829b42a150a
+
+Count = 152
+Adata = 5f8b1400920891e8057639618183c9c847821c1aae79f2a90d75f114db21e975
+Payload = 9cea3b061e5c402d48497ea4948d75
+CT = 81c8805a3bf6b176ff72e06be0e670f5419c6085e5434f056162cf80f6729d
+
+Count = 153
+Adata = 238d3c9d9de32f2040b1dd0dd040b921e456c3653263f4020cffdc552b948a46
+Payload = 20660408d6890aed84aa65dfe23032
+CT = 3d44bf54f323fbb63391fb10965b377fedcc743389a9d48e6b871dc0dd63b2
+
+Count = 154
+Adata = 3b5d61ca21953fdd22280747dd4ae908a511750127875da84dfe7d0063a318c9
+Payload = 9ab83c81f2d2c896c6596660c3974d
+CT = 879a87ddd77839cd7162f8afb7fc488137e0a856d3d911af9f420b68d8110d
+
+Count = 155
+Adata = 78c1751e86144a78285a30dc04f51742bd47e3d36b607bab48d91cddabfff4b7
+Payload = c1ec469aa9c73b677af225a9f5f6f8
+CT = dccefdc68c6dca3ccdc9bb66819dfd5644448fa8445b6cd185bdf9b3718033
+
+Count = 156
+Adata = add33e9a1d7e91e2c160c1123537e3f7e3535881cb4aac1a80ecbe367379212c
+Payload = 9df1d6b6debffdd316aeb27143508e
+CT = 80d36deafb150c88a1952cbe373b8bbd38e4dc44f768cef0c51344e3a7f7b8
+
+Count = 157
+Adata = df7736560b1a13aa8e536500ea6cdb9a6757309aadf25a6a9189055a309c3f8b
+Payload = 19eef017100dc82f26ed0815c55c12
+CT = 04cc4b4b35a7397491d696dab137172e7f2ec918099898b843a34c385f2a57
+
+Count = 158
+Adata = b40c8d22069b8a65cddb51c1ea3571160cacb19fd371552436b19c7122b28d08
+Payload = 2af5db43f2a5fe8b494b40661510bb
+CT = 37d7601fd70f0fd0fe70dea9617bbe94c2709685b0827cc42f3a25b579db28
+
+Count = 159
+Adata = 9de5559ea8ccc70f4375a436ce0b72551a75960ad5ed6a1949ee8f6c47548558
+Payload = 5de41a8ca8ed8011304fa9e9f36498
+CT = 40c6a1d08d47714a87743726870f9d63bf4b40ce7e672587816fdcda16efbe
+
+[Plen = 16]
+
+Key = 70010ed90e6186ecad41f0d3c7c42ff8
+Nonce = a5f4f4986e98472965f5abcc4b
+
+Count = 160
+Adata = 3fec0e5cc24d67139437cbc8112414fc8daccd1a94b49a4c76e2d39303547317
+Payload = be322f58efa7f8c68a635e0b9cce77f2
+CT = 8e4425ae573974f0f0693a188b525812eef08e3fb15f4227e0d989a4d587a8cf
+
+Count = 161
+Adata = b6fecd1edeb55a9a4148b1aefb716a1e162779a5ab2a682e4adce4479c527bd2
+Payload = 0e6118d0409751d36cb642504678535e
+CT = 3e171226f809dde516bc264351e47cbedf7f186e8d3d7c21c549c41ebcc7f505
+
+Count = 162
+Adata = 5c3933c30bf9d4841eff4000aaa1cb4d39cdf8ef1240e2aabbf9da95bdee5270
+Payload = 5c8a5fb36f860d00c21ae9e3f24097c4
+CT = 6cfc5545d7188136b8108df0e5dcb824810a68be1814f53c09aca4066527fef8
+
+Count = 163
+Adata = 7ca7ef30d3ac08aa51a9e5d3d84e8b6bb7fdde921e72b98ad6a93ebf2efc6b04
+Payload = ebd1cb4b35257790c9806be476bd25a3
+CT = dba7c1bd8dbbfba6b38a0ff761210a43cc30245a6e64625c4f6531d7497fb144
+
+Count = 164
+Adata = 90f1416768fca7dd48d01230dabf95f2f1a0c044bf2d755448aaf72316c8448c
+Payload = 842b7e5f22d921b2b8ab3131684b7eff
+CT = b45d74a99a47ad84c2a155227fd7511f10d85725dacc274034669acf7f34fed7
+
+Count = 165
+Adata = adc5c36849283d57acb2bcbc0e12465cb7c1830cb4e314b9ce6e25acbd8d460c
+Payload = f0c2cc5a1b4c4cbe839338fa0d7a3435
+CT = c0b4c6aca3d2c088f9995ce91ae61bd5f731b465eb59c4989e42020d86102a59
+
+Count = 166
+Adata = 80a7a483d1dbcdf00ed02a700e93d8b87fa6ac5c7368d1e81bd1b32cd1621cd7
+Payload = 2c1a5f906f2ae0373cc25e3519df2ba4
+CT = 1c6c5566d7b46c0146c83a260e43044484bcd2775448447ed801b3b0ff071c19
+
+Count = 167
+Adata = 13c02992992d2708250184a579c43bc29a3a8cf1e02dade4496cbd8b1214f97d
+Payload = 1da5190517546f1ad852f64263e1f679
+CT = 2dd313f3afcae32ca2589251747dd99901d1919f1451ad16f115cde863f15303
+
+Count = 168
+Adata = f6f18dfe093e4c0c3fbfa8a5b1f4a703c08addc2ab959741611a594b93d08bf7
+Payload = 13ccb08a580efea53dfba6a59626bbe2
+CT = 23baba7ce090729347f1c2b681ba9402ccae4f6ec07bf73d6f086cf09e2e14ed
+
+Count = 169
+Adata = 63708e12dfa14f192ec5ee5856dc3cf2403817d9628c31899b4613f65e1e61c2
+Payload = e0b5fbc6c2269d445a60273bf844892b
+CT = d0c3f1307ab81172206a4328efd8a6cb2bad8bf67d32a855c3940ac908397a5f
+
+[Plen = 17]
+
+Key = 79eae5baddc5887bdf3031fd1d65085b
+Nonce = 9da59614535d1fad35f2ece00f
+
+Count = 170
+Adata = 46603500af9e4e7a2f9545411a58b21a6efd21f2b5f315d02d964c09270145b3
+Payload = 001343e6191f5f1738e7d19d4eec2b9592
+CT = 2162e27bfbf1d00f2404754a254665fd9270f0edb415993588b2535e2e0e4fd086
+
+Count = 171
+Adata = 278afebc604bb7d87bed3574a2c5053de17eb8ca7e18ddc7892f2c54b38104a8
+Payload = ba47d5bfb36f6150a100e36caa116405c4
+CT = 9b3674225181ee48bde347bbc1bb2a6dc4778e3c4a11f3f9dc42554d45796379ef
+
+Count = 172
+Adata = 3239b2ce4efe4f6a6255dc53347400a6446ed3280c65422386fab471ef09eed6
+Payload = 96eccb7f9b0e16c6883de0a381e4767f5a
+CT = b79d6ae279e099de94de4474ea4e38175aab5540cc01d867f641c9b196fa159291
+
+Count = 173
+Adata = e2a5488d5f7930ea4ce399f2a6c0810265f7c0dc52fe824d19a0fa0d9ffd55e6
+Payload = d68f5990da1a2fe39ed81af145ab834fa4
+CT = f7fef80d38f4a0fb823bbe262e01cd27a46366fbe302e142dcf6aa16337d98550f
+
+Count = 174
+Adata = 0071f1edb3a0ce57af3c88bb0ccf138f752697a77e55695838fb39de04c78dfb
+Payload = cdd4d8b3d8f6e4742793b456cefc9e686d
+CT = eca5792e3a186b6c3b701081a556d0006df88c07797267bf5a49b3d0f601a225ce
+
+Count = 175
+Adata = f5d6989587e463969d97aadabea9538511f8d109cc2d3cecf09ba7cc346aaea0
+Payload = e7d7fc60ae852b68102e01b506f9dab986
+CT = c6a65dfd4c6ba4700ccda5626d5394d1865c9fbf69d81cef238ac513562d4a0dd5
+
+Count = 176
+Adata = e0b5fbc6c2269d445a60273bf844892b26fed03b82869edacd6dd7a63fd69e8d
+Payload = be9f51abfbe2da5a56db0f9a31b67c9f83
+CT = 9feef036190c55424a38ab4d5a1c32f783e2c748c8c9e3190de095de8eb0650203
+
+Count = 177
+Adata = e6bd0010c98e60b9af7cf905c58e0653bc425e2ccc809bd4f9cd7b1f95c18786
+Payload = 81b9c73029cea1936ef8755c80ba8d4093
+CT = a0c866adcb202e8b721bd18beb10c3289305cf563c5b4ba4ebd5bf107f2ad3555b
+
+Count = 178
+Adata = b1688cbc058816974694cd26c0f28ba9418e9912867fc8c5f4e7bd9c891a8d2e
+Payload = 618dc26853ee339689467ffbc2a77be69e
+CT = 40fc63f5b100bc8e95a5db2ca90d358e9e60dbbd8f46343c8442b03a472da4e23f
+
+Count = 179
+Adata = 469e004fee9878ed40621b41d04ec34af175f213d64d16e2f77d0bb2b6efe2e3
+Payload = 4f18bcc8ee0bbb80de30a9e08629323116
+CT = 6e691d550ce53498c2d30d37ed837c591643352e46995e8c1aee43dbdb26b46c30
+
+[Plen = 18]
+
+Key = c14eda0f958465246fe6ab541e5dfd75
+Nonce = 32b63ca7e269223f80a56baaaa
+
+Count = 180
+Adata = 733f8e7670de3446016916510dfe722ce671570121d91331a64feb3d03f210e6
+Payload = 617868ae91f705c6b583b5fd7e1e4086a1bb
+CT = b2dc1e548b3d3f225a34082f4391980a0788b4cc36852fd64a423fb8e872252b248e
+
+Count = 181
+Adata = b6ec659856866959ef6fd4e71ba930f0e3e5fd49d7465fd65f6813ab4ca1a770
+Payload = b8b342c49c28bffc2a1c457db0b537ad46bb
+CT = 6b17343e86e28518c5abf8af8d3aef21e08895a66eb5b902bb23a1a8584249409fda
+
+Count = 182
+Adata = 89eb3636fff80230352a3582be5698e3401c9e0579d48f2680c6e5e24d99f74b
+Payload = 37d694ba94d0af8df662134f20d142903839
+CT = e472e2408e1a956919d5ae9d1d5e9a1c9e0a7fa792fb7246218f7d56d5fa4a5476bd
+
+Count = 183
+Adata = 03434f3709e19a1e37edfcaabc215116763b71ab1c5e053dbdb599f86959f25d
+Payload = 90e4c0550cb7b279ef61f9140b7d94b8003d
+CT = 4340b6af167d889d00d644c636f24c34a60ea83dc3f0012ae6da32a15fd1684835ef
+
+Count = 184
+Adata = 0e2ddb65fcc72094ac388d53a1055c7e902285c4c3c33c13bb6fbb4f1956414a
+Payload = 69b851e63a78baef90637978e3dfe8c47be4
+CT = ba1c271c20b2800b7fd4c4aade503048ddd7f09d38d3dba01995e36bd685c8ea3371
+
+Count = 185
+Adata = a42b2538ee2fb5f6a85d4d00524b01ad3331f61c404069243f35f28e2c2d0a82
+Payload = b7dbf8382115199dd2a2d87938c6ae6c4241
+CT = 647f8ec23bdf23793d1565ab054976e0e472c89becf8d2bb935cb17f44b950df3ef5
+
+Count = 186
+Adata = 09bc5c426dc1faa4d71f50908bd6f297ec8e754d4d20def005585b4bc1fa31da
+Payload = d53698d719c51bf9eae346269c6a1da07162
+CT = 0692ee2d030f211d0554fbf4a1e5c52cd75196e28badf0202097e80561451796194d
+
+Count = 187
+Adata = 2ac87e59c2c86532cf165af3e8ff4871d730f5e742cccca38bbcdffff4472c93
+Payload = cfdb7363985aa01af6f8e8237dbfb7871eb3
+CT = 1c7f059982909afe194f55f140306f0bb880710d4d7f66660891ac655d6eca4a3f3e
+
+Count = 188
+Adata = 05d2fbc3d0ec81f52f31cb0c4bf960c2076867f6d9f0174ed9176e20177b2693
+Payload = 56fdf10dc0c1dfd10965b83938e557459c61
+CT = 855987f7da0be535e6d205eb056a8fc93a52f90ab18925fea6964490f364a975a473
+
+Count = 189
+Adata = c2c3902cfe8622254b3787cc13e79c5a3c388c2357c29f1c1ab5539a10bfae5c
+Payload = e7c9812eda2ed7dcfc80fc5fe0d43e1e5982
+CT = 346df7d4c0e4ed381337418ddd5be692ffb168a00e5e7a39b371024927d3ac98fe43
+
+[Plen = 19]
+
+Key = c5e7147f56ba4530b8799ababeb82772
+Nonce = bdd38e173fb20b981659c597d6
+
+Count = 190
+Adata = 3a069a2bfda44abbb0a82a97e5e9047258c803da2c66190d77149e0f010b3af9
+Payload = 2f3bf0b566440912a1e47a0c07f1cfd39cb440
+CT = bd6265dcba9e14c59e515e395dc60bd053345fa6d7568c738e3a7fdf142d8f2d1562c0
+
+Count = 191
+Adata = 7709132415c94960025cc39c950ead208703a9d5a71e224fd022dc0a1817d0f4
+Payload = 7c880d787726c4ddeb2304b5d161b4a257298e
+CT = eed19811abfcd90ad49620808b5670a198a991f22337efa5cb7db7240e7518b67ffbb1
+
+Count = 192
+Adata = aad77595f87a27f2c7995fc7149317f4cbebcece8336db2068380070784a4283
+Payload = 08c43bbfa706512aa39e2bfa5c365aca11e22e
+CT = 9a9daed67bdc4cfd9c2b0fcf06019ec9de623140bac6094528f02eeda093312fcf716f
+
+Count = 193
+Adata = bdb1b82ba864893c2ee8f7426c7b9a8460b00a50f164fc8f2ff2ae9cddab8657
+Payload = a531c0ed8840b2fcf08d76eca71036153b6e11
+CT = 37685584549aaf2bcf3852d9fd27f216f4ee0e0c041d86dd483c1d6da366e91bd826dd
+
+Count = 194
+Adata = 38b3b9f45041ceb743fc2655b409213fa081427e41c833a2321a09fbd566c80c
+Payload = 177946b4dc3b0b825a505f097a0a203eb21c00
+CT = 8520d3dd00e1165565e57b3c203de43d7d9c1ffde45ca2a83dec2f930bb652a6fcdc5f
+
+Count = 195
+Adata = ec9d8edff25645520801b6e8d14a2fc3b193db70d5e5e878742de83154a578da
+Payload = a2634ef20a2a418b2c3be64f0b5f79d7ea9b7b
+CT = 303adb9bd6f05c5c138ec27a5168bdd4251b648b89aa22cd7d0170a975565cd3a33dc1
+
+Count = 196
+Adata = 8f6c1de4efdc5ac2d6e5452b5b4f58416d618da672f521332fd297ede8350134
+Payload = 40e52edaad5acf2d4eedfb3f9ac2908112e9b1
+CT = d2bcbbb37180d2fa7158df0ac0f55482dd69aed960b33c3df5cd38a82980dc0950ada4
+
+Count = 197
+Adata = b0f1dc85fe223bcf29cdfa9319866bacd0a0a79c554e24d1f10889279e31c0af
+Payload = bf97780f498c23adcf1c49f60873780a235969
+CT = 2dceed6695563e7af0a96dc35244bc09ecd97638fa273c4102b5ca050b23044ac2064f
+
+Count = 198
+Adata = 7d02a323aa769a8201549bf48a520d940bf6f69ed6106f1ce68856c22a594216
+Payload = 58bfe1eb2d38d91f80b3467db94fdcb84ff5f3
+CT = cae67482f1e2c4c8bf066248e37818bb8075ecc15438af1bafac3eac61e1c24ed00ab7
+
+Count = 199
+Adata = d4b90ef8abad08c552c8c3b080b8c37df314d514049d45e27ec4527cb06cdf85
+Payload = a206a1eb70a9d24bb5e72f314e7d91de074f59
+CT = 305f3482ac73cf9c8a520b04144a55ddc8cf464422d9e2f4f84fde49e9701296294d5a
+
+[Plen = 20]
+
+Key = 78c46e3249ca28e1ef0531d80fd37c12
+Nonce = 5de41a86ce3f3fb1b685b3ca4d
+
+Count = 200
+Adata = e98a77f2a941b36232589486b05f4278275588665a06d98aec98915cc5607e06
+Payload = 4802422c9b3b4459ba26e7863ad87b0c172cfe4b
+CT = daea2234ea433533bf0716abe1aa3844b6d3c51e9d5ca3d8ec5065630d2de0717cdeb7d5
+
+Count = 201
+Adata = 5970a836de1f1e91d94d7eef79742cbbd46a759c413715eb0224fd6a27145333
+Payload = 796a69ad0e9379173ef6b66f44f5c84fa70a0e28
+CT = eb8209b57feb087d3bd747429f878b0706f5357d0ff0648ddb07f42f815b38bfc95688b1
+
+Count = 202
+Adata = e3f08834c4894f6fa66a55a280c0e677a79e97c1ef9488b21384e74e57b1b51f
+Payload = 98e1f8cf250183b13ad418024dc40c1a6a7ee8ac
+CT = 0a0998d75479f2db3ff5e92f96b64f52cb81d3f93ddd9a6977ea8e7adf5c5234346e560f
+
+Count = 203
+Adata = 18349be2894d49290339b97f4db28c92b3e112ffac77100abbf9c093935b1a46
+Payload = 4a856d9b50a5b40d6566b38eae6a53ed0c192805
+CT = d86d0d8321ddc567604742a3751810a5ade61350bdee05328a7ea8cc6c2e42bf3faeeda0
+
+Count = 204
+Adata = 7355e34ad13880de17a1d66b02672ea5c9f51774019f64ecbe36747ffcd9b671
+Payload = ad048eb2ad75266b43b59d9d1f073c44e4cbf25e
+CT = 3feceeaadc0d570146946cb0c4757f0c4534c90bafb1435cf929db35ec5986aabaf4a7d1
+
+Count = 205
+Adata = 4be21ba2eb26234ddcbb6aac6b4c3be7ef644af64edf51b7c29ffc3ddd80036b
+Payload = 5b527ac6cc6d1b4c3c56f8315bc96dae91632df9
+CT = c9ba1adebd156a263977091c80bb2ee6309c16ac736be6563cf9f5bce97486b7cc6f1c18
+
+Count = 206
+Adata = 266e0e3365e06d3b1e864c6e5897145df7bdde90eb744013a7b36632d4cf6580
+Payload = cee059cb0fe91a39faccc2914340baeab4b644ce
+CT = 5c0839d37e916b53ffed33bc9832f9a215497f9b2e90335fcea56b969b4fce65442768dd
+
+Count = 207
+Adata = 55a723883a340877d85ad1a5f264f2c834d824c7bbf207cdd8500c9d11ef9225
+Payload = 85321fef6a2b7d31cbd079c4bf2bfbbc979df90b
+CT = 17da7ff71b530c5bcef188e96459b8f43662c25eacd6afdb3578ebc75e8a408d32758931
+
+Count = 208
+Adata = 773864475a1a60a778468a66cbe13dfe3458094e62abb593f50c8495e3a8b81e
+Payload = e227b8d44320bd3ce9d3f7d688f3de887947b1e9
+CT = 70cfd8cc3258cc56ecf206fb53819dc0d8b88abca19fb73fc0488d9f29a09c1b47e3e066
+
+Count = 209
+Adata = f64f3b00c9117aed3c486aa4c8d574b44d679be4069e1078bb7100af38cdb190
+Payload = 206e9eb2bc3f8534d844a38debf1306df808744a
+CT = b286feaacd47f45edd6552a03083732559f74f1fce2c5ef8cdce76b358739e2a1b173fb3
+
+[Plen = 21]
+
+Key = 8883002bf13b3a94b2467225970df938
+Nonce = 818a702d5c8ee973b34e9acda1
+
+Count = 210
+Adata = 545aeac737c0ca2a3d5e1fd966840c3a0d71e0301abbe99c7af18d24cc7e9633
+Payload = d516bbff452e7706c91c7ace3e9baa76d65ff7050f
+CT = b85242fdc06344f2bd9a97b408902ebcd22aece3d42f2da4dd4d817c9fa2d44bc02163a0a9
+
+Count = 211
+Adata = f032db01da60ca078d35c3fb5d05d6750fce1c01911a0422e827e8976946e4dc
+Payload = 590d1aa655fed50ca2e402299f2da6fe20eed56071
+CT = 3449e3a4d0b3e6f8d662ef53a9262234249bce86aa180f41bccbcd47c8b7890754c032269b
+
+Count = 212
+Adata = 71ecb4252518997b53491cf42a3e0fe1496a2af2329a16f9fcd9c4f249900341
+Payload = ecd86cdb7d78d310dca5b477cd9da2612f5a05ab39
+CT = 819c95d9f835e0e4a823590dfb9626ab2b2f1e4de21d6ba58cc2eb474401851bf9502c3413
+
+Count = 213
+Adata = ec7abed9bda4a52fdf1bf278b6bdd6b0a27d4688deb9ff5ca9c8c865a4d2f730
+Payload = 0024b14c283df032cf80c22ad8d2c96289ee229092
+CT = 6d60484ead70c3c6bb062f50eed94da88d9b3976499b94d4b7a2044696c72322e850537b6d
+
+Count = 214
+Adata = c2c77d7ad7b27d7c0f976a1e28881ea4ec7ad03b63a4e67f47280a40b8f58086
+Payload = bc6965d8f62d066d118c14044c1fd2a224b9d95110
+CT = d12d9cda73603599650af97e7a14566820ccc2b7cb9d8da8e718570caf8bed7909fbff3ec6
+
+Count = 215
+Adata = 28929286bd1391468ac75f5c03689f74780ddd7585fc16f9a9bf7b00357a72e5
+Payload = da4a630cabaff0728a1cc3e6a79721a7176b708f1d
+CT = b70e9a0e2ee2c386fe9a2e9c919ca56d131e6b69c6e671012690c61fe3c9abd50a78eb4736
+
+Count = 216
+Adata = ed360d22081b019dc979420a3a45c21c8903c59daedd9f1b4ef2bfdedff0ec1d
+Payload = a95058f8e1f6bc0f143a9ca7e4425a2a63eb2f7e33
+CT = c414a1fa64bb8ffb60bc71ddd249dee0679e3498e8e657e2250427130acef7032454cde7b6
+
+Count = 217
+Adata = 2b4022d0b951fe48635d04fb3e2fa032c07c855fdd73f45670953bb9ddc77cb4
+Payload = fcbbc7f9d1ace60e830ca56ec84814fbd2579993d4
+CT = 91ff3efb54e1d5faf78a4814fe439031d62282750faac6ff0a264b8199550d93c1f06063da
+
+Count = 218
+Adata = 48e553a87a7d3c1bd68af39f96aca67583da86e06701d5e4c4ed404dc66d70f3
+Payload = b95d298d391c6b893c6cad66f9780534516e71455e
+CT = d419d08fbc51587d48ea401ccf7381fe551b6aa3857e68bf636e81c332f72063dc0d6fc2b6
+
+Count = 219
+Adata = e8e2835e47144365a2f218d4c95d7522e824fb43b66d4727ee570f8303dd6dd3
+Payload = bc79d444dff9d9e722effab07b068cb7723ae8fae0
+CT = d13d2d465ab4ea13566917ca4d0d087d764ff31c3bdf3af9e9c4e04bad261dc17cf00a00dd
+
+[Plen = 22]
+
+Key = 5cea00ee44cfb9cfbb598d3812e380ef
+Nonce = 948788a9c8188cb988430a7ebd
+
+Count = 220
+Adata = 50422c5e6a0fb8231b3bb6e2f89607019be6ad92a4dae8e0fe3f9e486476004b
+Payload = 33bfd0713f30fcac8f7f95920ac6d9b803ddd5480dd8
+CT = b168747dea3ae0fbede4402af9a3dc3185d6d162f859d828101682de32923788c70262b84814
+
+Count = 221
+Adata = bb0036b34b0c20094d335a8c74f6b3dea42eeccf4145192eada64ae00c726b2e
+Payload = 5576d94b577ed26820fb13c00ab0e2d1a1c3589bfdc4
+CT = d7a17d478274ce3f4260c678f9d5e75827c85cb10845bafc4ae4d31907def6f648b081174e2a
+
+Count = 222
+Adata = 5140324aa758dbbb5391b5e6edb8a2310c94a4ae51d4fba8a7458d7cc8488baa
+Payload = 13303e14068205cbfa992d4ccb6a265804ea64a15d7f
+CT = 91e79a18d388199c9802f8f4380f23d182e1608ba8fe314e378e9ed6e725a14c07632b02bdbd
+
+Count = 223
+Adata = 74da07d324060e590356988f27d9879fa3a3ade0fe71e2a0e49054211cfa1fe1
+Payload = 567e6d14b446add630d53ea86a537c0938537c4604a8
+CT = d4a9c918614cb181524eeb1099367980be58786cf1295bc2f2f9331536f7f70be09c41bda0ad
+
+Count = 224
+Adata = 0e403cff47adee3ec5bb6b178dabfc7d53b60a04eaad33a2fedd9db705358a4c
+Payload = 9f3d165d44cf1c5770346d211d4ff34ca2ecd6b28549
+CT = 1deab25191c5000012afb899ee2af6c524e7d29870c86b59cc9c3c008bc5876ef86327859cbe
+
+Count = 225
+Adata = 211e6ce3d0c3abdef069e6e4fa35015797bd8a9d64bc9b75f20b028b12cca04a
+Payload = d726e599db6a6d40629bc4bda5e3fa2e5aeda229cea4
+CT = 55f141950e607117000011055686ffa7dce6a6033b25135e6d59a5385a78658d60d254f99962
+
+Count = 226
+Adata = 3c5c67b083322115e1b3112c2b6968efc050094e23e646dce982eac9d6e67d10
+Payload = 42646cfb8a99e48a35cee3f5f9b3e6175695973f6de0
+CT = c0b3c8f75f93f8dd5755364d0ad6e39ed09e93159861e234e83d9a0570dbf2b2fa59ce3cdbd9
+
+Count = 227
+Adata = 37a931f1dd05755b376d1a164aa36b8de802e39f8108a0453c1114754665fe46
+Payload = e814c7b5c72d973a9bc7ccd463f107325ffa3321783b
+CT = 6ac363b912278b6df95c196c909402bbd9f1370b8dba2084e352b1b157267228576dd056c1a3
+
+Count = 228
+Adata = f1ddc2c49da7363526ba36c600c589b4c3121fbb8c5b9a8aa0de0e7453b30568
+Payload = 4f7a5618870945b89f194e31b1aa802c5350326dc691
+CT = cdadf214520359effd829b8942cf85a5d55b36473310bf88ad35ee338e489e55bb49732447cf
+
+Count = 229
+Adata = d14b3d3803df432488b5d66704abef6a500d397e855bc2c2574df746a515cf70
+Payload = f555216840a1f40b411d44128e567617e2694caf1621
+CT = 7782856495abe85c238691aa7d33739e64624885e3a07ab67f9397a81371ef6ebc775cb7007b
+
+[Plen = 23]
+
+Key = cb83f77751e72711401cbbf4f61aa0ed
+Nonce = c0b461b2e15b8b116ef9281704
+
+Count = 230
+Adata = 2bd112231f903fa0dff085db48a2e2a96ec0199249b005d5ab4c2eab753f9ad0
+Payload = eede01b08f9a303cdf14c99d7a45732972c6eff2a1db06
+CT = feb114b7bd3b43497b62454a675a632c3546d2802462c6af57647efda119c59862cd5dd3904efc
+
+Count = 231
+Adata = 864e0e728aea856fae6c6daa6357d1542cef7177f441ba21a563f6c4f6fdc1dd
+Payload = 8a56588fe5e125237b6cdc30f940b8d88b2863ec501a0c
+CT = 9a394d88d7405656df1a50e7e45fa8ddcca85e9ed5a3cc2af4027ca5824b41c7bb238d3e8eeebf
+
+Count = 232
+Adata = dac7f3cba0b5a47f67f85b226b66df695a8ae2501355e36aad105375bb95f732
+Payload = 66e34540d7accf377877aa2d3e6d2db0cfafc608a1eb3d
+CT = 768c5047e50dbc42dc0126fa23723db5882ffb7a2452fdf7fbd7044ce1d7b266bdf545247a3c2b
+
+Count = 233
+Adata = 07f48cdc12aa27119fbdfda4ec07ce6068c92ba7ba9c930905aadd156b1dd56e
+Payload = a9ebd04fba7155c39b5c29c5571b5354c9ae228f5e5b13
+CT = b984c54888d026b63f2aa5124a0443518e2e1ffddbe2d3afabc559b552cf7c7730c7dca25bc3ed
+
+Count = 234
+Adata = 2d24e79abd157af2c21b60932947fd9f9d6478f09ec56fffd341ea04a17b8e5f
+Payload = f179353aef342f0f691caf1fcb811e3f6504e14d6d9381
+CT = e116203ddd955c7acd6a23c8d69e0e3a2284dc3fe82a41488ca99e0f85ac388f981ce25560b8f9
+
+Count = 235
+Adata = fea280f710379e4665b5ed3d1620729a7bc164899dc83e6aee3612d538fa20db
+Payload = 6c19a18eab544acc883c5886eaa89f54d61ae5f1f1368c
+CT = 7c76b48999f539b92c4ad451f7b78f51919ad883748f4c9156faae3d8860bed216e8d497a75962
+
+Count = 236
+Adata = 18f2e3457127c35f2e0cff2d821af8178028fcc7803bc795c49f4a435b37abeb
+Payload = d0df1bdf1df6203241722fb9c9c1cf7405017497ae1545
+CT = c0b00ed82f575347e504a36ed4dedf71428149e52bac8588cd7791c544d1098b2de49d04b1e0c1
+
+Count = 237
+Adata = 35221f0efcb109cb93c38a62c58b5ab8b236437e171e8507cf417a569af1767c
+Payload = 479526b33c42c240b9a4549ca70cbfb691f16ae3be8888
+CT = 57fa33b40ee3b1351dd2d84bba13afb3d67157913b3148c523fd8a2524717f63dac75c22268fa6
+
+Count = 238
+Adata = 95f2ab02af01aeacce86b02cf846f9fbd516963d06e350e8b7f6df2778765a01
+Payload = aa6761148b254a2ff202b620c2ec2c5e623bf61f05e483
+CT = ba087413b984395a56743af7dff33c5b25bbcb6d805d4392904f05dc2397596543df73de5aa708
+
+Count = 239
+Adata = 3746a36154e42dd600049d506f5ce4d034864263b1a65cecd24c8e25fb9c82e1
+Payload = 2f298f106703b8a994cbb20acf47f9442e44f6b5e82c38
+CT = 3f469a1755a2cbdc30bd3eddd258e94169c4cbc76d95f8c3cbfecfa3f75fb111ef0011222b7948
+
+[Plen = 24]
+
+Key = 43c1142877d9f450e12d7b6db47a85ba
+Nonce = 76becd9d27ca8a026215f32712
+
+Count = 240
+Adata = 6a59aacadd416e465264c15e1a1e9bfa084687492710f9bda832e2571e468224
+Payload = b506a6ba900c1147c806775324b36eb376aa01d4c3eef6f5
+CT = 14b14fe5b317411392861638ec383ae40ba95fefe34255dc2ec067887114bc370281de6f00836ce4
+
+Count = 241
+Adata = e82fc3ffd276218a82aede65fe5abf4fd35c7059a26923f8dbb97a59c903a7f4
+Payload = eab8cef576816a82ed036f158e5036f5987b195e60582a6f
+CT = 4b0f27aa559a3ad6b7830e7e46db62a2e578476540f489460d2d30268e9f1ce0e7c762993297d828
+
+Count = 242
+Adata = 776aae7f62225556b6da522c0c9432ac70fe72ac6f3f361071ef3deb4a6715e8
+Payload = 566ef9ce1d397be2547c385639507a9e7d6f9eed9a3b1055
+CT = f7d910913e222bb60efc593df1db2ec9006cc0d6ba97b37c0939e56f0b7200d1b1409f3f8e8179cc
+
+Count = 243
+Adata = d9aef0955922f89747ba4a8ddcdb8c1c7579aefd3c2eb8ad0589c66576a8504c
+Payload = 8c28b6d93b23f1ea031d5020aa92f6608c3d3df0ee24a895
+CT = 2d9f5f861838a1be599d314b6219a237f13e63cbce880bbc138e3b817023993608be06fe92efca8b
+
+Count = 244
+Adata = 13c222a65ce30570ecac85a185a2a0922a8c96d633339a1ca067ce57ae426e1d
+Payload = f0c1cd60f5fa8d1efd5e2e1ab37c4f7e6aef76d15e8d6ac8
+CT = 5176243fd6e1dd4aa7de4f717bf71b2917ec28ea7e21c9e1f3ca13b4ab7fd0d4badf158972570c06
+
+Count = 245
+Adata = ce40fb0cbfdf07676ed55b040ae6be5db8f0a0f28816ae8ea71da3cbd71661d8
+Payload = 570d5f79aa8db14b1ac99ee567cc105ae9e238e482b52628
+CT = f6bab6268996e11f4049ff8eaf47440d94e166dfa21985010a79fa4e8b27a31ff360a1b6c05ff844
+
+Count = 246
+Adata = 446b01d09cbc41b6393ef81ca65ab7e099018187d5f9d22f5074dfc491e72077
+Payload = 7c267223047af946b06f6a45ffde4a5ec49c28b81ca22da4
+CT = dd919b7c2761a912eaef0b2e37551e09b99f76833c0e8e8d5d34ef0ca0b47d6a2ec7442cbb739504
+
+Count = 247
+Adata = 01ec87920b42639d4ba22adb1fbe5138d2849db670a2960fd94a399c1532ed75
+Payload = cbf112e4fb85276c4e09649f3de225b2398e86ac3fe48bc7
+CT = 6a46fbbbd89e7738148905f4f56971e5448dd8971f4828ee8f607d154393e35fd1efc1ae8cb244e4
+
+Count = 248
+Adata = 5032b818d202872f3fe2b08fc7940696df02cf393a6d6247f5c6f5f2125cb08b
+Payload = 4324a89788e8ddae5d560cf937df701743cbbc3bf980558c
+CT = e29341c8abf38dfa07d66d92ff5424403ec8e200d92cf6a5617d9cebea38591a00c9fba4ef9c8e71
+
+Count = 249
+Adata = 27b661861717f00a3ae22ead78f4dc3f32b40e8fcb8ed58167a31a61f2becd77
+Payload = db72d98d63fc10acff7dceec0e2691a80ecee50a0e957ad1
+CT = 7ac530d240e740f8a5fdaf87c6adc5ff73cdbb312e39d9f897062a1ec759a515b938780f902fa7c2
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VPT192.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VPT192.rsp
new file mode 100644
index 0000000000..abf1775dd1
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VPT192.rsp
@@ -0,0 +1,1383 @@
+# CAVS 11.0
+# "CCM-VPT" information
+# AES Keylen: 192
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Nlen = 13
+Tlen = 16
+
+[Plen = 0]
+
+Key = 086e2967cde99e90faaea8a94e168bf0e066c503a849a9f3
+Nonce = 929542cd690f1babcf1696cb03
+
+Count = 0
+Adata = 58f70bab24e0a6137e5cd3eb18656f2b5ccddc3f538a0000c65190e4a3668e71
+Payload = 00
+CT = 3bf9d93af6ffac9ac84cd3202d4e0cc8
+
+Count = 1
+Adata = 760d065275e345900a7bbab451cc9309fb161e6cfec526538b98800e4102e14d
+Payload = 00
+CT = b0078a769ab68db44e723993da382abc
+
+Count = 2
+Adata = ffedc67efd355ea404fcbcb3993d3bae81386ded86230270771deb747163bf44
+Payload = 00
+CT = 31fbff2d715a2eb9af54e8320a8e42e1
+
+Count = 3
+Adata = 55153ff5e4d208d2e647794f382c788e0e36f293e63e7290ba9ff2657ae0f167
+Payload = 00
+CT = 945839d62c9d1b899f6dcd0ca9517e68
+
+Count = 4
+Adata = f8813985f59bf284bd3882e899ca9b67fb496f3eb78d7ebe6ffbad084f639915
+Payload = 00
+CT = 903f90d23321a6882d6c4c1955b14847
+
+Count = 5
+Adata = 7b95cd827ab93507f1819ae76627d6e2a31d29890c092e5c300f0e2f9e4ef4d2
+Payload = 00
+CT = 652ec5ab43088eb568186d0d9887b30f
+
+Count = 6
+Adata = bd144c9bb974729aaa1188ceefdf85e1d9fddc0b0c8afe8828ba204aa9293feb
+Payload = 00
+CT = e6c1455d1117eec49338c96f51007309
+
+Count = 7
+Adata = 92b911cdc3137a6f7f32651b788eb82975660aea52b2c03b4759755a6da4a0f8
+Payload = 00
+CT = 1cf3c32fb229dac209523eaa517bb59a
+
+Count = 8
+Adata = a8200dbbfe4086015cdbdec2fc8e4934d0d663527430c424627ed44065ade091
+Payload = 00
+CT = ee10bfeb1cf9b3cd5a0faebd4d8f3fe1
+
+Count = 9
+Adata = 3b7f37b6b8e3c1390a99d59c47f7c102cf659d361a132ef8b4e70b9585bafebb
+Payload = 00
+CT = c51ed994253adb9bb5b9a8c34a27f225
+
+[Plen = 1]
+
+Key = 992d38768b11a236945bd4b327c3728fac24c091238b6553
+Nonce = b248a90b84b0122a5ad8e12760
+
+Count = 10
+Adata = 27cabc40da0e1eda0ea5f8abbb7c179e30776250a7b30d711b0e106c5ee9d84a
+Payload = 1c
+CT = 1a96f58c3f38c44d1a345f3e2da6679f20
+
+Count = 11
+Adata = dc2e28d5ae726c1beadb1e7e92ae7d14f5546320deb81a910bf170cbe0210eaa
+Payload = e9
+CT = ef0579aee7c17482691f3f832d867ffea7
+
+Count = 12
+Adata = c579f912ac1b45d5aa8cf20f78f0a1ace32abd3dc7fd0b3f3a7182a008795c7f
+Payload = 97
+CT = 913452d8ece38ffa1d4107d6a053acd8c8
+
+Count = 13
+Adata = 69ea953dbb910ec589372d797c7379d3f3b9e9fd48894c9b55e6e8eb360a6211
+Payload = f4
+CT = f20d760b9fe29530738157db0ba2d253f0
+
+Count = 14
+Adata = 622835dea57b2c70cca8f7548d6210714070b55b36adde7a4c547269c07aba9c
+Payload = 9f
+CT = 996fc21f24dee7b52f51d69eea30819f4a
+
+Count = 15
+Adata = 67ebda0a3573a9a58751d4169e10c7e8663febb3a8cf769d81bc872113f0720f
+Payload = 43
+CT = 4594c5b8db0064426a77dc536814c56147
+
+Count = 16
+Adata = 255412e380e9a28cbcd345be172c40f72dec3e8a10adfd8a9ab147e9022524e1
+Payload = c1
+CT = c76d36c0b0d699a22da3116dfb8f453181
+
+Count = 17
+Adata = c7c8e7151eb6844a954d091b460f83add0f0a634aa5ac213b774f2451aa497fb
+Payload = 31
+CT = 370c3a1690acc3f0eb09c9cfd3396c7fa9
+
+Count = 18
+Adata = 63f00b2488809fdc49ca5f05d54e98468906308115f7e702da05ddfd970b5537
+Payload = a7
+CT = a1ad45070fe4c61270c13cc52247fee411
+
+Count = 19
+Adata = 8e2c5e55c0bf70014e9897b6f6940e4e738b1e84e8269b6382f0b1fe59b0e162
+Payload = 40
+CT = 46b2a2a8b283ff7eeff5c2670f77b8809d
+
+[Plen = 2]
+
+Key = 5012db40ff6ae23c1e1ce43768c5936c4400b0e79ae77f30
+Nonce = b67e500b35d60ad7264240027c
+
+Count = 20
+Adata = 40affd355416200191ba64edec8d7d27ead235a7b2e01a12662273deb36379b8
+Payload = 0c6c
+CT = c996ef3d6ef9f981557506ecc8797bbaaaa7
+
+Count = 21
+Adata = c5e12e17e02bcc12b3a4c14cf837250e2886db3ee1c717d28bd11e8a3b764ddf
+Payload = 23df
+CT = e6254405257a837c5343b59d5689d6de5269
+
+Count = 22
+Adata = 213b5b6015d472bd593be5acf85ebba6d6a09f3a962be302ba83c6d70c61f241
+Payload = 0dc2
+CT = c838e93e67d37d2367bb1f27f71b54b29317
+
+Count = 23
+Adata = fc1b6e152fe232b6c10b5d89900961c445f4c46833df242c826678b68c869811
+Payload = dc88
+CT = 1972ca3744a4ab375af9060621a9dc4f4c32
+
+Count = 24
+Adata = 5b2eb1a6fa585d61d1fb3da68f5b93829c8e2d5e4fe03782617553d7a130ecf1
+Payload = 8179
+CT = 4483172626e930d24052bc056d8609c4175f
+
+Count = 25
+Adata = e2b3c3bf33cf847660929e48cce51d9d9289945169651aaecb1e939756e93105
+Payload = 01fd
+CT = c407852310207be8d3417de800b372700da2
+
+Count = 26
+Adata = 6051f12cd8aae68b4023aaf7178fd086aa582b8d8821e36637abc97025f5e858
+Payload = ca18
+CT = 0fe228553bc037954dbf4ce5db99792c2c7a
+
+Count = 27
+Adata = 2d3555faf285caaddfe95c010c2a7f233e09c2fc0cd30d644035269280527ad7
+Payload = a855
+CT = 6daf904725668634d6345bd8f90a3831b452
+
+Count = 28
+Adata = 4fca820dc545bf93bdffed33a04b67eb45384e696f092c2197e5d79cecd09913
+Payload = 5555
+CT = 90afdf6098cb3135c3045a54ffce88efaceb
+
+Count = 29
+Adata = 1789ae403e183d2225f431f001d475b53bccdec66572bb027340ae592839ba8b
+Payload = 11dd
+CT = d4278568e8c08ff5ee5ea0a608589c2fc029
+
+[Plen = 3]
+
+Key = fa15cc7f0de294d7341b1fd79326c8be78e67822343c1992
+Nonce = e5257aed2bda0495aa44591db4
+
+Count = 30
+Adata = 31a0338c3839931fa1dd5131cb796c4c6cfde9fb336d8a80ac35dec463be7a94
+Payload = bcb898
+CT = 68f08298d9a2147776dca9c1a42382bce323b2
+
+Count = 31
+Adata = 4863dd810ee70ef0f5da81f60c5ce550abb96454619032322e34657af25207de
+Payload = d1da2e
+CT = 059234a9a77755b324f3a557217752ade14ed7
+
+Count = 32
+Adata = 173594fc26b167f044aeaf9bfe920cab99a27eb2b01827d61f7553cb2018b5fe
+Payload = 394f31
+CT = ed072ba4441a79a90e228a28069fe109d5d876
+
+Count = 33
+Adata = 71cdd16eca9255aeedc23bd623513918ea97da21485074415fe75bcc42f454c0
+Payload = 868bda
+CT = 52c3c065f272f44c5210b5bcc571e819580910
+
+Count = 34
+Adata = e84418d332d16d2298e69e7ff3c37bc7b6e030cc822e73b3f4a0029bc2ea4d80
+Payload = 52d6bf
+CT = 869ea559c5f7f73a1b5f419c9f63ca401894a8
+
+Count = 35
+Adata = 42d962109bea1d50be0f3d83b4c2a6033d53b3d7112591866b1ae52dc84cb5d0
+Payload = 6f8d58
+CT = bbc542220b828cf5365137fb3f1df67cc8d2a1
+
+Count = 36
+Adata = 943b4327b5c70dba63c82f27e0412b3ada012bc0f7dd39ebb13db2f864daf80e
+Payload = fda286
+CT = 29ea9c422b0f41075ac79a0afa2d1047cbbfb5
+
+Count = 37
+Adata = 6076b94caabfa476ab7e6482e4fda9b29f2e2b2883efe44d668c7c74628505bb
+Payload = 8651fb
+CT = 5219e1ae68cd6d6815ecbfd01293d160d4d38a
+
+Count = 38
+Adata = 3e4bb5781f84b4bbd23583e3dae561c6ff4af8eff35e2a4f35b50d2f360d3469
+Payload = c3e179
+CT = 17a963fbaa81cfdbcaee476860cd5102f556e4
+
+Count = 39
+Adata = 364008acbad330d0b8d574641a97b0682c49279cfdc80ff309b7514514d18a44
+Payload = 4a97d5
+CT = 9edfcf7ad1520564b68824a3a939371c21a336
+
+[Plen = 4]
+
+Key = b5330a8447d74a7987fb718cfae246b5c7e057991064eeaf
+Nonce = 2ef29d62b40d8643848797cde8
+
+Count = 40
+Adata = 1225b036e6044df52314016760e92750de0936120395de750a2c54a7fa0cea82
+Payload = b46b343e
+CT = c2c39d6f9344e2de064f269d065a2a6108605916
+
+Count = 41
+Adata = aaa6257d6783936a4445833c2ac3bea8cb7334f22ade9c035d515bbc91d6a78a
+Payload = cb216301
+CT = bd89ca50693d90b8297b90bc41c231d08b0204fb
+
+Count = 42
+Adata = 1c1915fab09348b9a5536495c70d1a040305708c1124797e564b63e008e7b8ab
+Payload = 697a8696
+CT = 1fd22fc79d0146fe373437c529fb2eeb169e4bd7
+
+Count = 43
+Adata = 864d0f786497c7ce283762ca0959ec9c825ed445a5dbe5b4b2e5772fe88ce7f5
+Payload = 6bee3db9
+CT = 1d4694e8e389c549bfc4ede936d7896e544b23ad
+
+Count = 44
+Adata = d5388b0b548c58886dcd335dff2b1ed23ce3eebbb708fb5bbd831c83e959d3fa
+Payload = 85d95855
+CT = f371f10495177a9fe6d9329a585c8737c92a4d29
+
+Count = 45
+Adata = 83cddd189736f224cad6a29efba45e43c75450a14f1541713b7fb926ffc768c6
+Payload = e8b23340
+CT = 9e1a9a113914431a10b1f94a2b99b9e442f3dca4
+
+Count = 46
+Adata = 8fccbd1fc5240691cf24e8807bf3416c1b2d87fc86dbf3955fa2e52b9a3a8457
+Payload = 595c4d7c
+CT = 2ff4e42d383d8dc98b22010dd93cd0cbb396d9e3
+
+Count = 47
+Adata = 513d45f6f37f3f051667dc743215059e06e4fdc8945789b16d50556a2e839368
+Payload = 314e0c7d
+CT = 47e6a52c40c513bfc92d1a7db5ed7cab2d8212b0
+
+Count = 48
+Adata = 70828be102e554f0d4b07641fa3254bc8db06eefaf5b85a7c97e01c217fc8f3f
+Payload = 35753e32
+CT = 43dd9763ea98f4ac6b3eabd483f1e6ab92f3b83c
+
+Count = 49
+Adata = 343d5a4ad39acf81adcf24e9807618932abcb3bc076734f179174c77c8cb89e9
+Payload = a531c0ed
+CT = d39969bcf99fb67b1e2aba2d232db2445e6aec2a
+
+[Plen = 5]
+
+Key = 30419145ae966591b408c29e5fd14d9112542909be5363f7
+Nonce = 27e6b2a482bbc6f13702005708
+
+Count = 50
+Adata = e04e81e860daf9696098c723085d8023c240ebe7a643131e35359ab04bd650fe
+Payload = 8ceaeb89fd
+CT = ec9d5ed36243ddf77b33d8cf2963ba76fd4e19f3c5
+
+Count = 51
+Adata = 6217cd581d4b3b2f7bcf1b8dad9ad6430e2e3a0063cad52260e0a1cd6fc9e73a
+Payload = 7e51d6f870
+CT = 1e2663a2ef6b73fe9e638e205b27f78ed1bb9b0ed0
+
+Count = 52
+Adata = 8aa7847e496f5e9f1f87851442de844f27a21c1b48f82fe525f0dd5a88b8ec38
+Payload = e0023b674d
+CT = 80758e3dd25936115e23158aff1916edec241fad56
+
+Count = 53
+Adata = 3612abc865a4d8d7b86a84109388584df6526525adb1006ec6c8d00048d725bc
+Payload = e2b5b6f36e
+CT = 82c203a9f1f15aae4b70dbee244be1daa74475d7e2
+
+Count = 54
+Adata = 849a99c6f1cae0ad4bcde4bd0811e87ca5ed7b913de1a8285a206e980b4b7043
+Payload = 9a17e4a22a
+CT = fa6051f8b5bbff424487848385f8501ab5a77f327c
+
+Count = 55
+Adata = 9066367c784de0a4d1116bbe95ce55ded85edddb6273c2049ee24e0fb3429352
+Payload = d4e765fc78
+CT = b490d0a6e772d8d5da6f593a8d9956731b42645aa9
+
+Count = 56
+Adata = e7aa9f767fa8920f96f91c41d9e86755faaedaeda596a444b65f99b7a9e23e85
+Payload = 1074349e10
+CT = 700381c48fe3eca12b835dcfd08166ac8831585626
+
+Count = 57
+Adata = bc0db1ebf910b6f4dcad5401401d6bc2272e23130947dc236ca664d5b5ed6d66
+Payload = a46dd7fb58
+CT = c41a62a1c72bcce66018e9e552d2c8a229301361df
+
+Count = 58
+Adata = fcbeba2d0d73239d05f691a52b08152c9dd871f8dc76c2c18b8a638a74460d31
+Payload = 2e0ca09221
+CT = 4e7b15c8be3e41a50a28ea3be14baadf12964a37c4
+
+Count = 59
+Adata = dcdefce64ae4339f46c0759a4a10b29d59daaaf1e5dbf75cf11b4e4f73c5025f
+Payload = 2e108ce0fa
+CT = 4e6739ba65bee2ab25bfafa76dc3e54832b2f76864
+
+[Plen = 6]
+
+Key = 748ad503388a34041a7bdae6361d57894357c333bacf02ca
+Nonce = 518b79d194579b19f2d8845b70
+
+Count = 60
+Adata = 691dd98f61fd213b0840ec5a6f06ef9a1420be0d59bde5e43546347a2a865a94
+Payload = 24d6880aed7e
+CT = 270120f9634ec15536e21d961c675070ec4cff9037bc
+
+Count = 61
+Adata = d1fd047cdb18463766841abb1fcd25257f1458b595bfcf24066ff9385232fa97
+Payload = 2298028d0213
+CT = 214faa7e8c239b303af0b098f902dc24e66fe56adc6e
+
+Count = 62
+Adata = 65a480d120a0459dab69e8f23094801e10092666cc56f9fb2549662982bda6d0
+Payload = f248e5225e3d
+CT = f19f4dd1d00d1b657925a9740d6828bd85cd12205764
+
+Count = 63
+Adata = b738a53fbc9689dd49f68f97f5a99665258cd52e74dc653b594cffec045508aa
+Payload = 611dade00cec
+CT = 62ca051382dc395a1c49129ef6cce0ad5f6ef378aa1c
+
+Count = 64
+Adata = 7006f54184f0ff0ab215ca408d46325b86c1cbae6da7838435b1826ff81f55dd
+Payload = 5871a8300471
+CT = 5ba600c38a415e68468d1b2b516be3d688567d84ab80
+
+Count = 65
+Adata = 9e6e6675d4c6b1e0f3894aac071f4c99a364708edea12f319cbc27b40fabc0f1
+Payload = 3ca8a7520e94
+CT = 3f7f0fa180a40ba1af163049d16817021665d183bc9e
+
+Count = 66
+Adata = 10ceef716f54b74d7c8a435d6aa38a10ff23939ca29e2de7b6c3e0a8269a23c9
+Payload = 9c2a0070fbba
+CT = 9ffda883758a670f35869da9821b6ff1fab3e6062ad4
+
+Count = 67
+Adata = 3ee0865f29be50160273b4a94ec078932b9cd10a858e31838d5b607867e1ce69
+Payload = 436179c74fd2
+CT = 40b6d134c1e208f395250fd79087c858b83755411114
+
+Count = 68
+Adata = ec2b8bfe1ccd491b02aa4a9178fd6f099556963e39e2ca5fe6ecb6b5d2a46085
+Payload = ecfa41c614c5
+CT = ef2de9359af5afcbd9af2d584a0f638d066f2496d9be
+
+Count = 69
+Adata = 5b6f6369643d83b1db33d75257d7dea761e574e6e1f1ecead64e5e354a2f4235
+Payload = b48c10105dbc
+CT = b75bb8e3d38c17861882b8930296fd51d969a1e9489e
+
+[Plen = 7]
+
+Key = b930cca30a3fd230c237c8f3cc6792d0c4084dff5c18d775
+Nonce = 7574802fd82fe96c05431acd40
+
+Count = 70
+Adata = 1cf83928b6a9e525fe578c5c0f40c322be71b3092239bff954dd6883738d6d71
+Payload = 2a755e362373ef
+CT = f06238b0450fd1f4b6cab1383adb420c4724aa7bdfefb7
+
+Count = 71
+Adata = bb5450f66273f63b2f79dce177381ce846584ce4f7a0ad5a0171a56e149370bb
+Payload = fab43224bf8989
+CT = 20a354a2d9f5b7a1f99175d3dff5a73f0053a95c36fd8d
+
+Count = 72
+Adata = 3e5e1037bd2922eb20c34200c470b76e537baf7e7f1d8dd2f7a184a593c66554
+Payload = e3aed6715aa429
+CT = 39b9b0f73cd81734b4ad0e41117940abf530093dac648e
+
+Count = 73
+Adata = 3cc88a096a1a440827f5b7da675389e50b5cce35fa2cc36674d6bfc5a3a966b2
+Payload = e78db0f83997cb
+CT = 3d9ad67e5febf5663a8324014550430c7eaeffbd8568f7
+
+Count = 74
+Adata = 2cca33a10b9da7ba99a6b552d1405f2df3fdfd15358d8fdab5e15296b38f9135
+Payload = 726557906845b1
+CT = a87231160e398f34ab635c4eb5b38b86e71da8af3840ae
+
+Count = 75
+Adata = 2fe5dd58b17914187e29029c53cfe5b015ca74cab750d8f95e05f818c3cdf947
+Payload = 043a759b578be4
+CT = de2d131d31f7dabd9961766e03eaa7e8888227c98d1f42
+
+Count = 76
+Adata = 8b8e3d7c88fa16d70130cee290b7e2eecf0ce711118cd9265093b11467e63554
+Payload = f31f2fb4b3fd80
+CT = 29084932d581be637842d96d13c4aab97e296458745a9d
+
+Count = 77
+Adata = 6341370e126097f9721a13c977eb4875cf1286e15c3adfa4e7597e0e13d93b6a
+Payload = 7e3c8224104669
+CT = a42be4a2763a57a51ac46611366c666cab6bfd3d1baaa5
+
+Count = 78
+Adata = 227926b62f7cdd90e4d3b0cb5457e71fb087d329671f0fa891ec06eb8edeb58a
+Payload = 26a0528ae6f9c1
+CT = fcb7340c8085ff8c7d7e5aec14845f844ad38544a2f11d
+
+Count = 79
+Adata = 05b50c40b02e79b74b94d726a7ce8b2b7216ef8af6e7a42d041d2a692a58ad83
+Payload = 61dcf53d1a184e
+CT = bbcb93bb7c6470f1605ab8a2332012b759ccd2eedbed24
+
+[Plen = 8]
+
+Key = 314c136999e41d137bd7ba17201a9fa406025868334e39b3
+Nonce = 65f7a0f4c0f5bba9d26f7e0ddb
+
+Count = 80
+Adata = 5c7ce4819b30b975ae6ce58dcc1bfa29a8b6dda8f4b76c7e23516487745e829c
+Payload = 4d54d8b06b204445
+CT = 2baf90c490b11f9607482362ab3f157c42d0e9c6c5cffcf0
+
+Count = 81
+Adata = 90257ed88679197b8219bc4c2434a71a4e3664d5859c4ffb9a075654898ffedf
+Payload = b2a35df881cd63a2
+CT = d458158c7a5c38715389509b5b6f2df1faf7e8c39203970f
+
+Count = 82
+Adata = dff8ad83525d8235eacdccc91abeb80795e6b5f463fd28af35c46199f646ceb8
+Payload = e98f5e5a20d02c80
+CT = 8f74162edb41775395328747ca544e987df28883d0377b35
+
+Count = 83
+Adata = cde159c5343cd9d98001cd719d3e9ea25e47e1ff13fc87055d4a53b741f59285
+Payload = 90c3e48313cd4fe4
+CT = f638acf7e85c1437a4ba841883a0d7aeda398c043161966f
+
+Count = 84
+Adata = fa88cf5a08be4fb0c1a7960f45726c303eb559861fa60d17aa8dfe8bb5795382
+Payload = 8ad6d5a28ec075e6
+CT = ec2d9dd675512e3509195efe66c5faf413e0f68df8cb647d
+
+Count = 85
+Adata = fe9e93a9370b43efa1560aeb017ff04fca7f207191e6f707c1c35b2e90c44eb2
+Payload = eb83928f0d5f7aa3
+CT = 8d78dafbf6ce2170b51af067ad69ad96009e50ead3d03f02
+
+Count = 86
+Adata = 35792c854fdf1c8cf7f3f8ed2b8ec4f31fe17bf8d4ba49caec03f954bd8bb17a
+Payload = 4cd74ed2fd083011
+CT = 2a2c06a606996bc26b1cb03ee76587f84364825f7c1fcbe9
+
+Count = 87
+Adata = c084108f9c0a74cbf70f614dceae592546865006930db0401828a0eecff98671
+Payload = 52365f94579e0646
+CT = 34cd17e0ac0f5d958fa70c5e195f1f955d64892f532b7683
+
+Count = 88
+Adata = e8045949de61c5c18a63e628330a4d1d12782379a8f9187755409d1825f453c5
+Payload = 8fb85c857a3e38e7
+CT = e94314f181af63342ddf297bdad58083645a052815d29a83
+
+Count = 89
+Adata = 53cfdfd66d63c2924bd583487b90b1dd9ec199f90d660cb9c3a763a4776abfe1
+Payload = 43d2828e86f7856b
+CT = 2529cafa7d66deb81ad3b2be41dbc39df4c0145dcbae3e76
+
+[Plen = 9]
+
+Key = a19f6be062ec0aaf33046bd52734f3336c85d8368bef86ab
+Nonce = 7f2d07f8169c5672b4df7f6cac
+
+Count = 90
+Adata = d68d5f763db6111c5d6324d694cb0236beab877daae8115ecb75d60530777b58
+Payload = 13511ae5ff6c6860a1
+CT = b3859b757802ebd048467fd8e139eb9ee8fcdca45ed87dc1c8
+
+Count = 91
+Adata = f6e219b29884dab9ea9bad34d9ef8a50ae389c9a908de7154a1f2e894f27141f
+Payload = 7e7e33e1a07d4e8fde
+CT = deaab2712713cd3f3789d0ee8323ea2ee7a68aaaa9c49b98df
+
+Count = 92
+Adata = bcca002d69d9d1044c40ae741ea33ce6b8463f5a28d0514e044fdae2fe7d3c3b
+Payload = cc88980c73e6c5f0cd
+CT = 6c5c199cf48846402437c9fe3d9feb0485e6d7c04423b77a53
+
+Count = 93
+Adata = 39cac8f0825ffdb0668455933ad1581263a23b9e5f1305340528f0320d4b1269
+Payload = 34cb528f50d073cfdc
+CT = 941fd31fd7bef07f35b87e90a71ffe6c30bee1771078a701ab
+
+Count = 94
+Adata = 510a02a44d142c8e975d1d933f828fd7e47d28b88223f1698cf009dc3b079be6
+Payload = cbce3df86438a61065
+CT = 6b1abc68e35625a08c9e9c5be0657649448c38692e8d703d30
+
+Count = 95
+Adata = 40e0418cd52f74d78a8e18ed86210e3661a86d8574aedcee540340d8996d9852
+Payload = 80a2b835f8b0729a4b
+CT = 207639a57fdef12aa213e5f2bfd33101597cfae7cf334a8528
+
+Count = 96
+Adata = 1f2938b3bde19e1af91299c08638061dc3c1ea3284c259d415e996477cb37b0e
+Payload = dd04794e65ce34127a
+CT = 7dd0f8dee2a0b7a293516a7310fbd4ceb90d8db9a86cb6311b
+
+Count = 97
+Adata = cbae5b46e35fa2a279dcaa4c724b923805d4707412a84252b64228c91cedd019
+Payload = 00c4101052f54462d5
+CT = a0109180d59bc7d23cef6165af65f3522dfbfed0293db39ecd
+
+Count = 98
+Adata = d0f27c7f42892f3ad4c0029c5b698abb1d035ba5869a665b1de8861db6c055e8
+Payload = d0865445d3b26b6f49
+CT = 7052d5d554dce8dfa00726434c1349e3e874a2d6bf598d05fc
+
+Count = 99
+Adata = ab0f5a829a9319a74d5d5179aa0a410a0fcf52f344a7a896aeb1f7a6c5d398ea
+Payload = 7c7c8580b944ed3fd3
+CT = dca804103e2a6e8f3aab491e60fc97b3cb5248291e4866dcab
+
+[Plen = 10]
+
+Key = de1c8263345081d2dfa9afdf37675971135e178df554a4d8
+Nonce = a301bb82f91a582db01355c388
+
+Count = 100
+Adata = 9ad52c041390d0d4aaf65a4667c3239c95e7eae6178acc23fb4e70a852d483c6
+Payload = f777aba1fa70f94e6de9
+CT = 9d8bff6d2dcde77104ac6aba025abc01416a7ca9f096ab2529cb
+
+Count = 101
+Adata = b49c7e7b47870c1cc339c7c09aaacfd6115fa8a0f04990367eea10cfacb9d23c
+Payload = 349feebfbe58f93ea3c3
+CT = 5e63ba7369e5e701ca864acb200e85a0d4753a8ba226aca72f98
+
+Count = 102
+Adata = e61ca7310172eec16745a73e34516f65844eecd0dbc5566ac5213626b9096ef1
+Payload = 678a40b4c2c7df0e4c9d
+CT = 0d761478157ac13125d87869784e3321183d8c044657a020e9b9
+
+Count = 103
+Adata = 690f5e5d8da6cdb0f492e80449e152ffe88fea9742564d8383c79cef739a7f74
+Payload = 2b81e0533313664bf615
+CT = 417db49fe4ae78749f5070634d00b1facf0e9e9979ca257a71e2
+
+Count = 104
+Adata = 78e34b0a1d61ccd411cbfd306ea2ef3ce89c0b085deb4cfbaec2ab72ce16daa9
+Payload = 1ac63aa38a206d8e7d68
+CT = 703a6e6f5d9d73b1142d994630ed92e2973b22773f229b45bdad
+
+Count = 105
+Adata = 51bacfcf87ea11da34b76acba8c444792ec3db3c8ee6e600d69679975a682a54
+Payload = 027a7fd7897808ec7a56
+CT = 68862b1b5ec516d3131304571b015bb6b4651f1eb9f6fb3a7b74
+
+Count = 106
+Adata = 5159357a133e4743f903d05bd641da369a3675337760fcd2424a99221ba70b78
+Payload = 1086953d352e94a51a6d
+CT = 7a7ac1f1e2938a9a7328bb0e11ac4608081fd0702a137da0aea3
+
+Count = 107
+Adata = f567820865340314d46a17f520ff315efb6b33bdeda590ca9c4fad604c2d8e8d
+Payload = b8b148aafec4a035e9a7
+CT = d24d1c662979be0a80e252c9ec1317ce30dffeb4c9bf3fd0bbdd
+
+Count = 108
+Adata = 0cfec933831644b468724e808bb3d25fe8f15850ce513fc341da46089c845208
+Payload = 884242a87779d3921f8e
+CT = e2be1664a0c4cdad76cb691e32be3cdd9721a13aabad26dba58c
+
+Count = 109
+Adata = 8edc2b85d44297ac66bdd90d05d8df38124033d6a583bb8dda18a2246ba096e8
+Payload = 25c32770a299020d8500
+CT = 4f3f73bc75241c32ec45333a381be77800654aac335bf9220ac9
+
+[Plen = 11]
+
+Key = 248d36bd15f58e47fcf1c948272355821f8492e6e69f3661
+Nonce = 9e8d492c304cf6ad59102bca0e
+
+Count = 110
+Adata = 9ec08c7ed6b70823d819e9ab019e9929249f966fdb2069311a0ddc680ac468f5
+Payload = 33709d9c7906e2f82dd9e2
+CT = 9114d36b79b1918b2720f40cddce66df9b4802f737bea4bd8f5378
+
+Count = 111
+Adata = ba13974d95f2eeb367b63850609c53dc66c2710f682f10bef0142d48f851b430
+Payload = 84172985e7d194ba28a87c
+CT = 26736772e766e7c922516a12c94615be2bd81bd598f3022f5775a4
+
+Count = 112
+Adata = 5f16180bfac9b7483774cb0e1d57a43e9bf3cf03bf6fe758293aadcbbef25b80
+Payload = 9a34d32070c71d7de8f512
+CT = 38509dd770706e0ee20c042758e936750e335702542bc598e211c4
+
+Count = 113
+Adata = 4352057bdd1735a85dc0fc4dbeedc73279c27eb24a97641236f03f11cdafb8c0
+Payload = 2054a268b1f6fae4f15d91
+CT = 8230ec9fb1418997fba4870762bb2a7d04ba2ad251d595d0619dc4
+
+Count = 114
+Adata = ddf118ae403b2509e75eb7a26d17e73e527acbacfbe49a56fa3210169030144b
+Payload = f71afe9a60f08a0ef694aa
+CT = 557eb06d6047f97dfc6dbc27d85594da3fd35bd8498d7e389ee7cd
+
+Count = 115
+Adata = 973904409e8154132439926f0dc45c0d81bbbd5793f7f81e20eb818bfa374d58
+Payload = cdf5b47ff73306aa55c496
+CT = 6f91fa88f78475d95f3d80055936db383a8ad10b152046d721d3f7
+
+Count = 116
+Adata = 06bca7ef6f91355d19f90bf25590a44a24e5a782f92bc693c031e6de1e948008
+Payload = 9ebf93643854ea5c97a4f3
+CT = 3cdbdd9338e3992f9d5de5d57e228369e24fe955fd8924526af6e5
+
+Count = 117
+Adata = 8321f65baf9dc856ac1c24f3fee5c74d697eb0b50470d59d8f4a14b506e86c53
+Payload = 685116faa5cc527ac8bfa1
+CT = ca35580da57b2109c246b76c23abfb3b4eb39deb8da2064390dfa8
+
+Count = 118
+Adata = a4e7738038a5116592bb9d92d6d4ed191ab774310f6409e4e45fe907674c006f
+Payload = 9e8c4f1292e8d7e5179b34
+CT = 3ce801e5925fa4961d6222b4272c0639e8e6a1d356fb4fea86762c
+
+Count = 119
+Adata = 0df202431ee7f251a38aaf6aa8cd313782bd293af9114005adfe9faab253b572
+Payload = 3ecc2ba566c723462eb0ea
+CT = 9ca86552667050352449fc0633a0f9cdc9490231ec2dd69f6e35db
+
+[Plen = 12]
+
+Key = 77a67fb504b961028633321111aac2c30eb6d71a8cf72056
+Nonce = acadc0330194906f8c75ac287f
+
+Count = 120
+Adata = 8c18486d52571f70f2ba6a747aaa3d4b3ebc2e481ee1b70907dddb94bdfa0ca6
+Payload = 10554c062d269ff6dcd98493
+CT = 7f8b0cad79b545e5addf0b04ff4b0f2b2a5067283210aba8630d0306
+
+Count = 121
+Adata = 4e0b4771c7f6c66f9577c430611fdeec5702296ee3691b6bb8c6a81217edabe4
+Payload = 1c9e7875cf02129ac52daeb0
+CT = 734038de9b91c889b42b21275b16dbdf0b9be3c8c82ac652992d630d
+
+Count = 122
+Adata = 4a687e1d0a95ed2efb95b4c6b040999fcd35136811cd665f934d10224b6064c2
+Payload = 34575694dde459d195b7357a
+CT = 5b89163f897783c2e4b1baede629274d654ef5a4480e24f6bef3bc8c
+
+Count = 123
+Adata = b5330a8447d74a7987fb718cfae246b5c7e057991064eeaf823641a12bfce9f5
+Payload = ab20c8e8aab1aac1e4f64206
+CT = c4fe8843fe2270d295f0cd9142ab5407a08b648ce24e9955e28fe47e
+
+Count = 124
+Adata = 4f19bbc3135d7a216465b4c1df2616e8bfc3cc64af0bf52bdc42543f4d2448d4
+Payload = e556ca05bcd1991d2c9836a9
+CT = 8a888aaee842430e5d9eb93e151e94d311c7cd2c1b9048575076ceac
+
+Count = 125
+Adata = b6ffc7387b19786282bda7caad52eb37fbe7e557afcb80faaf57767e2a0f178a
+Payload = e5b665600a2aa413e117c538
+CT = 8a6825cb5eb97e0090114aaf61b71330d72506050368186a5619f180
+
+Count = 126
+Adata = 6a493c5ef3769ccc4101dbb2eb36e1e5bbc577a057ce0731203ba3f25b52497b
+Payload = 870864a611aa0475d120bc40
+CT = e8d6240d4539de66a02633d7ea21e36f99e5aab6ffa85994d13d5bb0
+
+Count = 127
+Adata = 8215753d9efc51325f182199e39f9082cc3fe524400f2a7434c68df7eb2b06d4
+Payload = 71afe8d00c6f2ea8c8b050d4
+CT = 1e71a87b58fcf4bbb9b6df437cc93a50dea11c5e0b19f14b9c8f16bd
+
+Count = 128
+Adata = eb8f198da6ee92a03913c6575343f6c749d2377a09430eb751b13c041e6edbea
+Payload = 7021f18b8f398a5999fcdcd1
+CT = 1fffb120dbaa504ae8fa534699cbfd1beafa2d2942f6812b8dfc88e6
+
+Count = 129
+Adata = de2ee30359e390db72f682c2ca0f14b72b60ff9bccd8c6fbd19a512b12add794
+Payload = affca856eb412f0b3276ae6e
+CT = c022e8fdbfd2f518437021f9337405235dce6161441caa25cc6007c6
+
+[Plen = 13]
+
+Key = 0d423519e4110c06063061323f8c7c95387776b6ee4e4b6e
+Nonce = 39abe53826d9b8e300fe747533
+
+Count = 130
+Adata = cdd9bf1b4f865e922c678ec4947ea0cb02e78bd5c1538f33aeb818ad3f47e519
+Payload = 4021ff104ff1dbd91e46db249f
+CT = 7953d3cd66d093785d123f65ba37f16761dd6aedbfc789ad96edf1490d
+
+Count = 131
+Adata = 342de5fe61e05c2e58ac2978a871fbdf186a7294ec5f85c4631c21b584231211
+Payload = 95050ca1d494bdb561d4840f8a
+CT = ac77207cfdb5f5142280604eaf8f8e855ae975a1fc64bcce3e7492e9d6
+
+Count = 132
+Adata = 7871482948d8d09d0a7491d915543082cb5fc7d6c1e82ee2218279f54c15c154
+Payload = c45823203b20821a48502f9c67
+CT = fd2a0ffd1201cabb0b04cbdd42017a6515156691b3161b747576078da4
+
+Count = 133
+Adata = 65781d018f27ca0c72a9fa9ab4648ed369646dd3ce45d7ad3a54f6b051f1b6e9
+Payload = e901661b7d47c9918244ee1077
+CT = d0734ac654668130c1100a515225cec7d2566a07cd78181ae94577befe
+
+Count = 134
+Adata = 05556b04dae5cde8525633d1862aa200c54af534e302d2cbd34ddc2b78532a60
+Payload = 5556f799d6a6cffb343f28c1a9
+CT = 6c24db44ff87875a776bcc808c133f51dac00f973fd42e0948fab70ea9
+
+Count = 135
+Adata = 151304e3e4f3c2d4d3227e035d849e0d3841ba00cf6cab1cf2e3e4d6cc760623
+Payload = 56bf26be81c7b55ef898e23981
+CT = 6fcd0a63a8e6fdffbbcc0678a4fe78bdeaa8d408ffe8fe64811aa87742
+
+Count = 136
+Adata = f870cc1fe67d6169279f905b0fe5fd9a0436c36498e4b7c6f584f00f7efe8784
+Payload = 36b304a72dbf4acfffa1d7d624
+CT = 0fc1287a049e026ebcf533970197228d155dda2bc814ff33ebeb9a7ffd
+
+Count = 137
+Adata = 5692c9d452ea1c067e62fdc554ddd2b18c8433d59067f971316797fd9853ae6a
+Payload = fb529eb5ae79a0830474ffbc98
+CT = c220b2688758e82247201bfdbde7ba03e144e34a4ab34791a372a2b8ab
+
+Count = 138
+Adata = dcf7fe16b7ca9e27ec3291103398eaa2e77c7b770b67f8858c215af4c523822d
+Payload = 6218c778955d9a56360f06c704
+CT = 5b6aeba5bc7cd2f7755be2862103c2eb5ef0657306d12b753a0694efcc
+
+Count = 139
+Adata = b0f1e2668611dca86e8d0f58c2a4cf4a9472d81ba013e271800b75841fe5ffde
+Payload = bf6b143fb713a81c965c5a9d8d
+CT = 861938e29e32e0bdd508bedca87cc6119151393461ecf65bfe06e0163b
+
+[Plen = 14]
+
+Key = a60cf7ceb62bf3118532bc61daa25ce946991047f951b536
+Nonce = 7499494faa44a7576f9ed5580d
+
+Count = 140
+Adata = baa482c64eefd09118549a8968f44cfea7a436913a428e30aa4ab44802a4ba35
+Payload = d64f9426febce6a84c954dd5ded5
+CT = f7580f17266d68237747bf57c7ed8242ac1a1979c5a9e7bc67d7698c7efa
+
+Count = 141
+Adata = 2ad8ecc5ac9437ace079419f17e6018625b10490120fbe2f12b41e64b73b653c
+Payload = fcd9b67717bcadeceddea336c671
+CT = ddce2d46cf6d2367d60c51b4df4918abced491c063d8bfd0e7341febddc3
+
+Count = 142
+Adata = 7585ee95e74d7a869bdc0b59ca9939dd57e7b09afab179079d467bfe0668416c
+Payload = 18232d7c792fb80e6ca1c8f2c3cc
+CT = 3934b64da1fe368557733a70daf4659ecbb3dbfbcdb0f913abedf8afab05
+
+Count = 143
+Adata = 41be6ca6188f34da1ce83fb8c27652848dc2a71e32bd3631fb9b33ae69e5d879
+Payload = 764dbefb42644d18d23e5e456868
+CT = 575a25ca9ab5c393e9ecacc77150a220d5ec0b5397d6b4e323b5dc7d1b63
+
+Count = 144
+Adata = 197cee3b15320d57996191dd13106fbd4546a5cc3d2bcf0c886af52ea3d9a855
+Payload = 8003586af34bdd0acae4f5547394
+CT = a114c35b2b9a5381f13607d66aac3a5f713f5d0793b732c6e114805cc9b3
+
+Count = 145
+Adata = ee0b647a47656a6e9e09c2d64f734a2cc3fd45b7ee52fea51c24af59ee22a006
+Payload = da143266516a4145cde92c93f961
+CT = fb03a95789bbcfcef63bde11e059ed90e8650bc16f590789dcc625b9e63d
+
+Count = 146
+Adata = 9f5bfffa01f1425d95465723735b49fc1dffbad06cf37a00ca4b59efa21739c1
+Payload = 3842b033f3ca31a6f8e5a638b39e
+CT = 19552b022b1bbf2dc33754baaaa6bda183dda1aef021d92210e27cdd7c5e
+
+Count = 147
+Adata = 64e92ba2748d07f602808f7c5ded15cb0e43140400d37107e59a01e7d45b4c9c
+Payload = cedf60b17185fc71b957cb759260
+CT = efc8fb80a95472fa828539f78b585e4087fb314f893937e95383e66745c0
+
+Count = 148
+Adata = 6ebcaeb4bd44ff4c990305ac64264dfe2ada5f7cd4b294eb9f492865cd28905c
+Payload = 035f449bb28f43365f4a0556096a
+CT = 2248dfaa6a5ecdbd6498f7d410520a71ce5813c578532b742d704fa92276
+
+Count = 149
+Adata = db617207dccd1f6baea5f2242d5e577adb8d69af3bb1707a7a53a8b75452455c
+Payload = 9a2a45424f4965a71270e77cc403
+CT = bb3dde739798eb2c29a215fedd3bb7fc45d15d6939668065d2282fc589c7
+
+[Plen = 15]
+
+Key = 82d4bc9aac298b09112073277205e1bf42176d1e6339b76c
+Nonce = 70325ef19e581b743095cd5eb1
+
+Count = 150
+Adata = 6d14bb2635c5d0ae83687f1824279cf141173527e1b32d1baf8a27f7fe34a542
+Payload = 25a53fd3e476dc0860eeeea25fcb0c
+CT = 4a1cfd0023557a184b929965b0a445cb3993ca35acf354cb2b4254ff672e7f
+
+Count = 151
+Adata = 9f8a56fecf32fa7d50f033b2524c3d798e254bc87245cce57e38edd6ee5d5f1a
+Payload = 797dca47597947c057789433309b67
+CT = 16c408949e5ae1d07c04e3f4dff42ea25b5eb103bac224cad66ec0f100875c
+
+Count = 152
+Adata = 86f15b8b677b7655f358a2c7fd5785bc84d31e079ed859b6af88e198debd36fc
+Payload = e61f9a663d3a2b50ea2f9475971270
+CT = 89a658b5fa198d40c153e3b2787d39b598cc6ec2295c586e7ae270a01846d1
+
+Count = 153
+Adata = 4de6bd43c28143ea5d40919cb5330a7e674f5bd8aeb7b178343a2851281c8668
+Payload = df990c42a268950677c433555319b3
+CT = b020ce91654b33165cb84492bc76fa97ff732093f7d0a96b30d8cdfd1bd583
+
+Count = 154
+Adata = a5c3a480dea1b2a1e3a0ce416148b04f60104217c9d24a5b267b4aa6aa07a4dd
+Payload = a7e72fb4bec3768594a2f6f5b4379e
+CT = c85eed6779e0d095bfde81325b58d7ad98e32a9156e125ff021ef6951b0c40
+
+Count = 155
+Adata = 51b041f1666c59045d333fe63d43457107e1adad34fcbf965e0d191f3e414776
+Payload = d3d1550047cf90eceaea7000d8e280
+CT = bc6897d380ec36fcc19607c7378dc9390f10df08a84c21031626861b201fbd
+
+Count = 156
+Adata = 22f8a3c9d85b2d53ffd92078d3c94373f855ecd01a8ac521d1abd0f2c7cba9ff
+Payload = 756412c4ee6416f2f4e0342011cde2
+CT = 1addd0172947b0e2df9c43e7fea2abdd5d840bb8c4348a9a548482e6b93043
+
+Count = 157
+Adata = da08b14e1b770b81faaf1e59851df1cba8838cd63bef141340ee378e65fdcbd4
+Payload = 666e4a4b3f6cf598aa763cdada4109
+CT = 09d78898f84f5388810a4b1d352e403f0d49927cd6103e3705ba201e8f73c6
+
+Count = 158
+Adata = 2db3ded385ef9c82fd39ea5782d9befe66e8a070066269b2aa7c4bbfac3711c3
+Payload = eb9013a74352b0677a88bd73052477
+CT = 8429d1748471167751f4cab4ea4b3e2d97f7c2b3b42bf570cce79bf30ccc50
+
+Count = 159
+Adata = 194c9e1eaa8e376f9c41bf33823efa28ee60a9213438665b7002cf0fcad7e644
+Payload = e3126400e3c571a4d39b37bc938a22
+CT = 8caba6d324e6d7b4f8e7407b7ce56bd3c2a4fc45d014a0c54edab2930a5bdc
+
+[Plen = 16]
+
+Key = 6873f1c6c30975aff6f08470264321130a6e5984ade324e9
+Nonce = 7c4d2f7cec04361f187f0726d5
+
+Count = 160
+Adata = 77743b5d83a00d2c8d5f7e10781531b496e09f3bc9295d7ae9799e64668ef8c5
+Payload = 5051a0b0b6766cd6ea29a672769d40fe
+CT = 0ce5ac8d6b256fb7580bf6acc76426af40bce58fd4cd6548df90a0337c842004
+
+Count = 161
+Adata = e883dd42e9ddf7bc64f460ba019c28597587d06e57c3b7242f84d5e7d124ab81
+Payload = b31dfa833b0cda20eaa84d2ecd18f49a
+CT = efa9f6bee65fd941588a1df07ce192cb8707b1a4d9ce3def33703e19eaab6dda
+
+Count = 162
+Adata = 409401eb49cd96b1aad2525c5124c509766ff86f88b2011c67a1d501d3485e31
+Payload = 24bc8dc1e2354667b79ba4d7061448ff
+CT = 780881fc3f66450605b9f409b7ed2eaefd9041ddce37d88e79fba28e385b2327
+
+Count = 163
+Adata = 83bf5c063bf1febf71688a832d615e09d6f14badedeaeb6ffbfe343fc7274e78
+Payload = d41d95a1d2326e12cba636910ddfca53
+CT = 88a9999c0f616d737984664fbc26ac0291d971893543868bd8c69078fc2bdb24
+
+Count = 164
+Adata = 8cdd70524e24318c64d681aa27752d4c86c5348c05c9e48f06ed41594785a6e6
+Payload = e8a4b80e081919f1912542d3136764f2
+CT = b410b433d54a1a902307120da29e02a3866b23e4c991f4007e56a1ee9265c6cf
+
+Count = 165
+Adata = 615985f63571c0f94ffcd4df77326abd41e84f388f061d97573a181da7ee5695
+Payload = 7fca7388058d6d1438b6eee0292131cb
+CT = 237e7fb5d8de6e758a94be3e98d8579a2abbea637996b954027efa9464ced6b9
+
+Count = 166
+Adata = 17aa90f2bff0419011b01dee62be31354431cbc89f22332704b096143d4743f4
+Payload = aa540554ee80dbffa475f702d862d6b6
+CT = f6e0096933d3d89e1657a7dc699bb0e757bc8d48d82ebefc76f17323c518ecc2
+
+Count = 167
+Adata = 85288b2be612e42335c144fb058a7dcd567c382fbcee3962bd5be4cc7a7000a8
+Payload = 6d745581831edba437e70ea89cad217d
+CT = 31c059bc5e4dd8c585c55e762d54472c65470c81e487a26cdc26830f2b51bd1c
+
+Count = 168
+Adata = 288f9f52824b54b608dd7226a0a89d43ae8c05107dbae761e1c756911a003b74
+Payload = 811a61869c7a6b2aa9ac0fcc523ef784
+CT = ddae6dbb4129684b1b8e5f12e3c791d5a3043722be9448c3ef144f2288066f75
+
+Count = 169
+Adata = 51dbaba180d4746edbb3420461919b5b735797bf7dd19f84d80475f5efc2748d
+Payload = 378a4e39817f308ed1e639f943b694c4
+CT = 6b3e42045c2c33ef63c46927f24ff29549aba95e04e11cf18ddf73773d395c1a
+
+[Plen = 17]
+
+Key = 3cf8da27d5be1af024158985f725fd7a6242cbe0041f2c17
+Nonce = 07f77f114d7264a122a7e9db4f
+
+Count = 170
+Adata = 30457e99616f0247f1339b101974ea231904d0ef7bd0d5ee9b57c6c16761a282
+Payload = f6dd2c64bf597e63263ccae1c54e0805fe
+CT = ce3031c3a70600e9340b2ddfe56aa72cffdc5e53e68c51ee55b276eb3f85d2cf63
+
+Count = 171
+Adata = 42370f115bbd4b31bb99fe82cca273b3c93072f96b2e09bdc6718d926d48db69
+Payload = f45fee3e086c28a7c590ec0cc05b972664
+CT = ccb2f3991033562dd7a70b32e07f380f65c6328a7476db2c10ec7bca3f6bd3df42
+
+Count = 172
+Adata = e2d692c5678124998a7862b8e87276b0a19e293a609103c99583b36305bcb2b0
+Payload = 4ad69a8ab433ed8909825c71f6081f64a7
+CT = 723b872dac6c93031bb5bb4fd62cb04da68080f0d51d3b8841683eff361984f7e4
+
+Count = 173
+Adata = b5b38791160959dd2836ec1ad25286c1ba410d7212347a95b5738a3d725bb651
+Payload = 3d47071c13f994cb42fb2887e5c6e53a54
+CT = 05aa1abb0ba6ea4150cccfb9c5e24a1355c1428ef5d40bc9e363817f219af2ed56
+
+Count = 174
+Adata = 02691171795a77d1e3bdad513b6fab5b50d1def81bcc1df15012de3433a6aa78
+Payload = e8a4b80e081919f1912542d3136764f264
+CT = d049a5a91046677b8312a5ed3343cbdb65fdfb37dfd1236198035c8461b304152b
+
+Count = 175
+Adata = 7371d8ae79e628f53ffede174eb068db2318c05e2f6d94ad2233a59369b16db0
+Payload = 549aa84bb182312dd016e3107f3b1f9c5b
+CT = 6c77b5eca9dd4fa7c221042e5f1fb0b55acefde0e84a3ce0cb702ceb73ca1dd9a5
+
+Count = 176
+Adata = bb1e1f51082e470f7245458ec902098e1e41d0ed28efa31be71d21ce86527ff7
+Payload = 31a12ca6d69db2e6e252474d7d59ed6552
+CT = 094c3101cec2cc6cf065a0735d7d424c53f8441d46dc5456a587b765e1a820c11c
+
+Count = 177
+Adata = 7584f57b49e95bbf5a67153e18b9b8c4722644e8f611613c39cbe8c679aba5b4
+Payload = 5bb121e70452a954f420a56aca8cd5c059
+CT = 635c3c401c0dd7dee6174254eaa87ae958d0daddcfcc92349ef059149c54a25cd0
+
+Count = 178
+Adata = 505687182c06e6f4effe7fe03c1f436199a9015380ff21d0b2aa9453cfa10b1d
+Payload = 5b80d1cf745b14cb71cbc8dfe0bc7c7358
+CT = 636dcc686c046a4163fc2fe1c098d35a5948c1242b89490c6ee69dedc1e91286ee
+
+Count = 179
+Adata = 7ebb051741145a3bad87131553375c6debcbcecee9b79ee451bd1429cbb33fc1
+Payload = 79ac204a26b9fee1132370c20f8c5bcada
+CT = 41413ded3ee6806b011497fc2fa8f4e3dba2ddd54e509bca0a45dcf2fd514e1496
+
+[Plen = 18]
+
+Key = b46a3a24c66eb846ca6413c001153dc6998970c12e7acd5a
+Nonce = b79c33c96a0a90030694163e2a
+
+Count = 180
+Adata = ea9405d6a46cac9783a7b48ac2e25cc9a3a519c4658b2a8770a37240d41587fb
+Payload = 56d18d3e2e496440d0a5c9e1bcb464faf5bc
+CT = 01baba2e0d5b49d600d03a7ed84ee878926c0ca478f40a6fbde01f584d938a1c91bf
+
+Count = 181
+Adata = 72340d595f3dbd23b46513f8f2b73b6249328c705e7968084bcb647fe734a967
+Payload = 7a76eac44486afdb112fc4aab939e4d1eedb
+CT = 2d1dddd46794824dc15a3735ddc36853890be4646492b6f4cb169383c075756073b6
+
+Count = 182
+Adata = d5c87c649579da3f632ba95cb0a07c924095e4bdd4e0376e06bb90e07460172e
+Payload = 48348c5ec996f7a97ef0ba2cd6885572fe64
+CT = 1f5fbb4eea84da3fae8549b3b272d9f099b4f584289f560cbf76606942fe1a92dd63
+
+Count = 183
+Adata = ffa6277395d31d5db13034d362228a87610e441c98ca3038e252a9db12bdbcef
+Payload = d5c58f10e1a03d8a2501d1eaf5fcdfff3ae5
+CT = 82aeb800c2b2101cf57422759106537d5d355964f5f5532d7cddd7207f0e9a6aace9
+
+Count = 184
+Adata = daf83d02a9bd992ea58c23e7ad18d41796314bae20e864e729f40ccc215454fc
+Payload = da2a863ab1c58ddde320ecadeecac9c5d2d8
+CT = 8d41b12a92d7a04b33551f328a304547b50890ae047e35aecfc38ffdc07e7d8f5705
+
+Count = 185
+Adata = 21ddad5f550044dc5cb123ade17eeef549c4e0173b216bcc602c1e736764cca8
+Payload = 4573969afa831c244817230406fe51183091
+CT = 1218a18ad99131b29862d09b6204dd9a5741b2bdf539ceaa35015712dd15265ca476
+
+Count = 186
+Adata = 9228265ae5c3daf1485ff8011738da508bf2a73731396c5d9aa56fc554e0c00b
+Payload = edf5557e15473b747a819398c9ac1459ffdb
+CT = ba9e626e365516e2aaf46007ad5698db980b241412124ae20b84c13b0c3671d305c9
+
+Count = 187
+Adata = c0a2ff0de21b3ba961e06015ccd71374856a65a4c57cf8cde0a1643aca8ed868
+Payload = e139263478900df806a0f3446bd6600c1aeb
+CT = b65211245b82206ed6d500db0f2cec8e7d3bee9803747bf9fa63412bfc4e10aea89e
+
+Count = 188
+Adata = b54378f031a31cf3985f573829c9ffca14616742e0a7e03b0a2d7f05eff0219e
+Payload = 660eaff0f113eaa2f5f7ad4b62bb849a3a25
+CT = 316598e0d201c73425825ed4064108185df55afdf430b57845dcf622d4f25cdeb2a3
+
+Count = 189
+Adata = e67f35c18a9336469eae23040f98f52338ca8d0cab269ac32fe6bc7605d3ea56
+Payload = 0f89897271f5d0349d57399005ea60c0cadc
+CT = 58e2be6252e7fda24d22ca0f6110ec42ad0c7ed4c04c4b4dd585891ecfddeab8cc87
+
+[Plen = 19]
+
+Key = 7b71045ccef735bd0c5bea3cf3b7e16e58d9c62061a204e0
+Nonce = 2b9ecfd179242c295fe6c6fa55
+
+Count = 190
+Adata = b89166f97deb9cc7fdeb63639eeafb145895b307749ec1a293b27115f3aa8232
+Payload = 890d05420d57e3b3d8dbef117fe60c3fa6a095
+CT = f842ff6662684de8785af275fa2d82d587de0687ebe35e883cbd53b82f2a4624c03894
+
+Count = 191
+Adata = 4392c3043287dd096b43b4a37ea7f5dc1d298b0623ccbf4fd650a49569a5b27b
+Payload = 6b425cdcdf8304e7fbb70b2973d55e6940025b
+CT = 1a0da6f8b0bcaabc5b36164df61ed083617cc807d4824f0a98db2d87365a42ca3b80e1
+
+Count = 192
+Adata = 9b4fc98fcdcf485205e7054bc9d1e02d0d8584420537e20d3821de2fd6824787
+Payload = c8bf145fcffbafd6cd1a4c5b6cedfe008aacb2
+CT = b9f0ee7ba0c4018d6d9b513fe92670eaabd221404e631735c544edeeb4c0105c55bf0b
+
+Count = 193
+Adata = 45622e1472542be2f63f463d253617eafd4f2ad609f9020884905dd5c22fba53
+Payload = 12b5a76faedf6f855e328c2cb87be8aea78c5e
+CT = 63fa5d4bc1e0c1defeb391483db0664486f2cdc16a4cf37e8e96eed1217d21133e83d1
+
+Count = 194
+Adata = 958689aea3c6cd19020eff9d635ef44ee0793424df38fdf13a238b969d429777
+Payload = f0927c3cb0a876d7877466507da8bfa0bd9a16
+CT = 81dd8618df97d88c27f57b34f863314a9ce4859facf81a636351f6e67d6ec12636ae0b
+
+Count = 195
+Adata = c22911efc36fa739048af0c951ef2449bb3605c52f65120c4d71fe5976026032
+Payload = d2c5d4e2362f19c99de66da7bd9c495c03d9a1
+CT = a38a2ec65910b7923d6770c33857c7b622a7327ce73a7e2db69d30441f89a03fd0e84e
+
+Count = 196
+Adata = 799da61e2c10ebb4783f618b8f69da7704a1b2b925cebc228af57d7ceebb9825
+Payload = 1c9d7f5b329ef4d384b8b7955a20f8a3fc15cd
+CT = 6dd2857f5da15a882439aaf1dfeb7649dd6b5e8d787a9d06b8533ca96fb1db8aecc8e5
+
+Count = 197
+Adata = 14a8e18afe0b9fe18ddfd754219a7e18ed36f419f8262d91678e10daffb31c81
+Payload = 3a64414c3588d7c26871d7d054ac6c8420d491
+CT = 4b2bbb685ab77999c8f0cab4d167e26e01aa028ff5f819d552c08054b5ac02063e102a
+
+Count = 198
+Adata = 7294a8b4ad97c81969e4a2876a3dc0ee322d554726997dc9ed98c5601985ee5b
+Payload = 545dd71bea9967e07a89f84a2027aacd132187
+CT = 25122d3f85a6c9bbda08e52ea5ec2427325f141cde5af8fada67c47cbb5787a6b2d9c9
+
+Count = 199
+Adata = 99294b22d73805805630fb416d20d4fca67419ab660ff45cd19a3729e81b9f69
+Payload = ec1b17b885c018272652453f47fa6e9ed972b9
+CT = 9d54ed9ceaffb67c86d3585bc231e074f80c2a7412640b179bd3e8a417dc38462c16e8
+
+[Plen = 20]
+
+Key = dc7c67715f2709e150cceff020aaacf88a1e7568191acbcf
+Nonce = da56ea046990c70fa216e5e6c4
+
+Count = 200
+Adata = f799818d91be7bab555a2e39f1f45810a94d07179f94fe1151d95ab963c47611
+Payload = f383bd3e6270876b74abbb5d35e7d4f11d83412c
+CT = 377b5df263c5c74f63603692cbb61ea37b6d686c743f71e15490ca41d245768988719ede
+
+Count = 201
+Adata = 69adcae8a1e9a3f2fe9e62591f7b4c5b19d3b50e769521f67e7ea8d7b58d9fc8
+Payload = 615d724ae94a5daf8d27ad5132d507504898f61e
+CT = a5a59286e8ff1d8b9aec209ecc84cd022e76df5ea9bc8cfaf2a1734a792076618c4b9690
+
+Count = 202
+Adata = 4586f73a1f162b2cdb65f6e798a60b5f48938d40b4612d84c1f39244f14efdce
+Payload = 6e923e1f404002aa5cf8f8aaf1b9772da425e21c
+CT = aa6aded341f5428e4b3375650fe8bd7fc2cbcb5cc5122df904b052e4d5580fdeddf5297c
+
+Count = 203
+Adata = 9f7ae892e5662803408d4d062265846441a43c1fa202da59f640ae722a692671
+Payload = 68115771505daa18bb3ce90054bfb7d077e1f37c
+CT = ace9b7bd51e8ea3cacf764cfaaee7d82110fda3ce0ba1bb1af18e15ade3316c21d6b41fb
+
+Count = 204
+Adata = 1f0769a7ae82bd985661e031c4a892c15d3ef37bdcfb45243d02f40fdb51d34b
+Payload = 681fd2a324b3fea4cfebed567ae4546ba373c8f1
+CT = ace7326f2506be80d820609984b59e39c59de1b1dc71e342fbc44289ef7e53e28edf3839
+
+Count = 205
+Adata = bf957ef5ab2805e58ea752da5793f7f23d98fce1b2b67738929e5de8a15f9801
+Payload = a7b9d2d069941e8b943706a02d2847ea713bb103
+CT = 6341321c68215eaf83fc8b6fd3798db817d59843ced1fb4a2a3e349aa590aabbfc3d13bc
+
+Count = 206
+Adata = 833264c1bebb597043b4158087cb651960915d9023189c9509c0d2aed84e7fe4
+Payload = 9b946e8198ce69d2173e970f4e0c103a47ee4160
+CT = 5f6c8e4d997b29f600f51ac0b05dda68210068205079f6c2739e2b789b6e3d3c60389374
+
+Count = 207
+Adata = 94c8414cbbec52e2d73bb8f02ef687c91432495c0c744666317d02e6d46706d2
+Payload = 81ac4618f3db6bcf9bbf67220b7671be4bb4f8a2
+CT = 4554a6d4f26e2beb8c74eaedf527bbec2d5ad1e22a02f287db7217148317d897f65f6a0c
+
+Count = 208
+Adata = fced1131dab3dabdc1a16d3409fa09a90ffe02f0e2c814a63f77f771c08c3389
+Payload = 90851933d4d3257137984cdb9cba2ca737322dac
+CT = 547df9ffd56665552053c11462ebe6f551dc04ec362df9f8b41b1dd4821f8f14e9e633d7
+
+Count = 209
+Adata = 495dfcf91f4735ab35c6bc4deef8468bd988e4099cd291a32b4707f93e13d82b
+Payload = c14ce6d57f0fe7367331c9fe159ae1fb8f1ccb2c
+CT = 05b406197ebaa71264fa4431ebcb2ba9e9f2e26cf61ffb51e56497ca9f39c6665fcbdfa8
+
+[Plen = 21]
+
+Key = f41e369a1599627e76983e9a4fc2e963dab4960b09ebe390
+Nonce = 68ef8285b90f28bcd3cb1bacea
+
+Count = 210
+Adata = dbe3e82e49624d968f5463ceb8af189fb3ad8b3b4122142b110d848a286dae71
+Payload = 81ad3f386bedcbf656ff535c63580d1f87e3c72326
+CT = 9f6028153e06d14d30b862a99a35413413c04a49dc6f68a03a11cf00d58f062a7b36465d13
+
+Count = 211
+Adata = d9acfd611e5bbb08c5d05d56791b8aebabf8d69734ec89153c91a1f65b2e1adb
+Payload = 35f6bb3f6a388f3a5a039b0a495b676d0b928aeb19
+CT = 2b3bac123fd395813c44aaffb0362b469fb10781e3ca1fb470b666523a19f83481f16481ed
+
+Count = 212
+Adata = 6003b771afe4e99e1ef1ed4a31b10540d95f4ac49885f0c8e5cdcb63d213127e
+Payload = 6aa7e3802b5a29d4f9ca88eb59f94af783d1054466
+CT = 746af4ad7eb1336f9f8db91ea09406dc17f2882e9c53cb05bfcd64da2b45c2e9a89a380b49
+
+Count = 213
+Adata = c371644275a6290821e7d308714bec2bf62d36c30f7fa77a0d60b28894f1c82a
+Payload = 13332b67ba5ba18137c306bd860dc3eb0a9a0b871a
+CT = 0dfe3c4aefb0bb3a518437487f608fc09eb986ede048f70fbc680cf7092b3dd90b943fc6e5
+
+Count = 214
+Adata = 8eceb15300ec4220510ed5b7deb3429de6ae5f618e1c222c28990a9ab4b4bac8
+Payload = 05981dc26a1db2d8e2c3d85ea9a4d1dc3432d9edc4
+CT = 1b550aef3ff6a8638484e9ab50c99df7a01154873ee386f33c0b8da8d0c5934e617dd618e5
+
+Count = 215
+Adata = 96d1cf3690c48c77a155ce13e67bbd62e6f03d88c893c1f7c30a6435d5ab36e0
+Payload = 60249343a8cd4d33c6edc583ea7e5c221ef3064787
+CT = 7ee9846efd265788a0aaf476131310098ad08b2d7d3d2db1360fb1121893f4d197731bce4f
+
+Count = 216
+Adata = 379bbc9f919dc2a8687f2a86cc9c3291804240a9b566c58519956848102e6155
+Payload = 79003a8d3d20d412f468f11712cec4d37cee847440
+CT = 67cd2da068cbcea9922fc0e2eba388f8e8cd091eba335ce1bfafc0948f2523e75f2aad86f9
+
+Count = 217
+Adata = 9bff9c9a8f94cd77e7016748da31f86d1b9c68465cbf954511c93a4776981524
+Payload = 7d078a8b200514a00628756250d410f7a0f8a769e6
+CT = 63ca9da675ee0e1b606f4497a9b95cdc34db2a031c7dc265e281307f0f4c38cddc556ac725
+
+Count = 218
+Adata = 25125a4668c31dc2e8a68b6c4c95ad7cf9322852e371b415a357d09acb01b587
+Payload = d9b0eaaff786165f882f41a98dbc0c355b3a1aaf40
+CT = c77dfd82a26d0ce4ee68705c74d1401ecf1997c5ba61c78a2f85a447c3e62b6197d65b9065
+
+Count = 219
+Adata = ad34d8f0902a5b79fb145b8206bb4d3b77e0bd8ae2d0964815389eacb33b4007
+Payload = 17b517ef577f588da374340d2522cc9ea642c8d8ae
+CT = 097800c202944236c53305f8dc4f80b5326145b2540312d067c08a9b4400e1df8bb7ed671a
+
+[Plen = 22]
+
+Key = 3289e59e3a7b29bf4a309afc253030bba4b9bdd64f0722f9
+Nonce = 30259ce106e9bd7a8bacbaf212
+
+Count = 220
+Adata = 2870bd9a26c510e9a256920899bbc77a4eb9b53f927045a943d5ed6b13638cf3
+Payload = 53911a67b65738f87fc7c20d6db8044bde1af95838d1
+CT = 70cf37d4b6f7e707376b1574ce17c040b5143da47abb2fe9afafc2fccd98ccf63b0fdec30eac
+
+Count = 221
+Adata = 611032a95ee87f89ad6be7c0fed8bd245c5f81076087b3bda4cde5587b8d14b6
+Payload = 46917e38b8a542296d290d065b0aa7c8aaa38950c386
+CT = 65cf538bb8059dd62585da7ff8a563c3c1ad4dac81ec102dfd8c231d6a355f079c213ce6858e
+
+Count = 222
+Adata = 2e7ea26d1cceaca3b7862a7a8469e366b52ec27ca127e3317222ee651d8da4a0
+Payload = b527828c89f674dc6f024f8cdd80c694bb3ebd57b2d9
+CT = 9679af3f8956ab2327ae98f57e2f029fd03079abf0b36df11febe34dd568da12c374674b9ac4
+
+Count = 223
+Adata = 0bf4413010daec585de34142224d1cad3072f9720f91ac664ad152820e838741
+Payload = 78230f73f9c0150f630eca4cd679818551d449db82e6
+CT = 5b7d22c0f960caf02ba21d3575d6458e3ada8d27c08cb2916540d9439b832aa44236a7e187ac
+
+Count = 224
+Adata = 2e7cae3306582eb5bad148247aa6c6ec943f8748e84b8a069ca9488b11844716
+Payload = 847bb12e0e56fa07a086eeda5907ae148148fa4107d2
+CT = a7259c9d0ef625f8e82a39a3faa86a1fea463ebd45b80d0768a18dead55700901408aa3f901a
+
+Count = 225
+Adata = 63036dc4ad13aee5dc1832e867f7538da108188fec7b08262af440d07579c451
+Payload = ec59e208c4bb429a371f1b3ffdf07fce5dea8a05f0ce
+CT = cf07cfbbc41b9d657fb3cc465e5fbbc536e44ef9b2a45f2073605d2a441805b6ff89d8beb68c
+
+Count = 226
+Adata = f9ec5ce4b63156d57e451eb67ab6d7a59cc397f43f6d26dc07d1036f0fb4a8cf
+Payload = fb12d94bd21b5748b23132a03065c78dae65a0bd2cfb
+CT = d84cf4f8d2bb88b7fa9de5d993ca0386c56b64416e91dcabef6907811c6b7df4e74c7a63d83b
+
+Count = 227
+Adata = e13a204e16f42bbf4716e95f1cb7e125ffac66a87f591c8ef2c7b8485ff707fd
+Payload = 239fa31d4a65de0318bfc5b60a06d706c129dcf255ac
+CT = 00c18eae4ac501fc501312cfa9a9130daa27180e17c626aa8aa37e858cd990f5593d9ef35f2a
+
+Count = 228
+Adata = c4591c3ad984a1e189c526b719212f8248289eeb277827272b8205d78191eb2d
+Payload = 57caadbb1a56cc5b8a5cf9584552e17e7af9542ba13e
+CT = 749480081af613a4c2f02e21e6fd257511f790d7e354d81e424d6b4528901ae46fb35f8b3106
+
+Count = 229
+Adata = cf4795bc7f43c30d3c3a8fd1b8a9d77d69bf59eb8b59d0f464315f40cb52335d
+Payload = a68c74e05f0a44d4a0372c0e5915b83d8e6729efacbb
+CT = 85d259535faa9b2be89bfb77faba7c36e569ed13eed1f25a4bfda35e1390f3f16f638dcd4047
+
+[Plen = 23]
+
+Key = 40f1aff2e44d05f12126097a0f07ac0359ba1a609356a4e6
+Nonce = 0df3fc6396f851785fca9aa5ff
+
+Count = 230
+Adata = e9699b20b0574fce8b5cbc4ef792eb96e2c1cce36b1b1f06ea2a95fe300633cc
+Payload = 8d98c580fb366f330dbfda20f91d99a0878b47efd14c6d
+CT = 579cdf9da62a2df471e03450516adb4ce99ae0f70b1776a39c3b429a1f922fac0b59e29a122e43
+
+Count = 231
+Adata = bd94c9ad6253c25dc417f87b6e52e03621ccf4b3bff5b402677aeb51e216335f
+Payload = 7391ba60fabe2c632bbaca16af9a235b2c7dae61691c0b
+CT = a995a07da7a26ea457e5246607ed61b7426c0979b3471067bf538e40f9366adf8758968f06ce8a
+
+Count = 232
+Adata = 4f263cda4a50b0e5379ec2fb546b326a07943527c1d175c029455a917753883b
+Payload = 7e1e93a6ca35a2c0e4f08fdb2e7ee22b9f486f0ab919e2
+CT = a41a89bb9729e00798af61ab8609a0c7f159c8126342f964a1199251b54f419720a30de83161de
+
+Count = 233
+Adata = 4d43702be4f0530319555d7f1a3356160f6cae48051f12e22a153d7e405c1149
+Payload = f94ff053c7413f34f96eae41fd1ac101151069af5a9428
+CT = 234bea4e9a5d7df385314031556d83ed7b01ceb780cf33b417e4cceb8dcf45ef33cc0007755bbc
+
+Count = 234
+Adata = f4d7978fad36223623ccb5bb18a7373cba8a6e3b1c921259e319266042db8887
+Payload = ba0716355fffb8ef947d2a15eb58375a1ff1084c566990
+CT = 60030c2802e3fa28e822c465432f75b671e0af548c328bd35aed57f49dcfecf248cf9d246ac024
+
+Count = 235
+Adata = 12e4fe727b1f27a619dd67bb976ddc2b18b2ef8b7184290d9553494a500d933e
+Payload = 872940780a94680a791c937994ceafd2c8b7a22b5f4927
+CT = 5d2d5a6557882acd05437d093cb9ed3ea6a6053385123c97cda0e04d2ff65c2e06a8276bdf6f97
+
+Count = 236
+Adata = 2c16724296ff85e079627be3053ea95adf35722c21886baba343bd6c79b5cb57
+Payload = d71864877f2578db092daba2d6a1f9f4698a9c356c7830
+CT = 0d1c7e9a22393a1c757245d27ed6bb18079b3b2db6232b3494dd2ee0a0fe5bfc9f69234c8142ed
+
+Count = 237
+Adata = cefc4f2fb796c2502329ca3d8f8af3200dd9edb8f164e15acec90536a15b6fdc
+Payload = cda681aa3109ebf5f21ee3a849098ea3a551e844fae4b4
+CT = 17a29bb76c15a9328e410dd8e17ecc4fcb404f5c20bfaf9008ead8e923997508eebf5e776198dc
+
+Count = 238
+Adata = 94fc7eb8febb832097ba6eecd2697da91b5a8a1f2248f67a7659e0ac55a09a0d
+Payload = d4f8d262870b5000a40b8fcce88f55c65c4d12e729975e
+CT = 0efcc87fda1712c7d85461bc40f8172a325cb5fff3cc45f136cc6ea1b0fdb554e0803053875b89
+
+Count = 239
+Adata = 459085184094e302b2e921cc04270b676e75bbcf0e4b53ed387df2bd0e75e0ac
+Payload = 732f211061c0a32c6ad124c58418d560ef5eab2602314c
+CT = a92b3b0d3cdce1eb168ecab52c6f978c814f0c3ed86a575da8ceccae093888daaf92c95817fc3d
+
+[Plen = 24]
+
+Key = 91f9d636a071c3aad1743137e0644a73de9e47bd76acd919
+Nonce = 1bf491ac320d660eb2dd45c6c3
+
+Count = 240
+Adata = 3bdfd7f18d2b6d0804d779f0679aaa2d7d32978c2df8015ae4b758d337be81dd
+Payload = 4eaf9384cad976f65f98042d561d760b5a787330dc658f6c
+CT = 635530cab14e3d0a135bb6eebb5829412676e6dd4995f99cb7e17f235bd660e7e17b2c65320e9fd4
+
+Count = 241
+Adata = 9de45b7e30bb67e88735b8fb7729d6f3de46c78921b228bad8f17cc9c709c387
+Payload = 59bee7d18fd4ba573f3e4f61076f5b9f6a3487e47d98c729
+CT = 7444449ff443f1ab73fdfda2ea2a04d5163a1209e868b1d99f40890c7d650afccda40fb2a4cd603b
+
+Count = 242
+Adata = 783477f981ef0551b5e7a714b640bbb38316c53756c96e30c898cdee3b72e6f4
+Payload = 4e7f3c86d846ff351db81dbe1d2e9ed73ec0450587ae681b
+CT = 63859fc8a3d1b4c9517baf7df06bc19d42ced0e8125e1eeb50236cf1a12a9e3542a4051788f9775a
+
+Count = 243
+Adata = 2851d40243512a43f70f9c25e9b18c122a1433f05c61e65017e197e88b129e43
+Payload = 2db7cb2739c839383b64c2c93c7d5c906d984756c3dedaa9
+CT = 004d6869425f72c477a7700ad13803da1196d2bb562eac59b1bbad9861192df356c6678b2f561ea3
+
+Count = 244
+Adata = 1cfa2d62cc1f6313fb0c6eb21803e09cdf61ee3ddb15192529560e5d8096cafb
+Payload = 2f2b82497c78369890809460d80a16be4f3330e8a0089165
+CT = 02d1210707ef7d64dc4326a3354f49f4333da50535f8e7951da4211d4c28d2d91568117fc99fd911
+
+Count = 245
+Adata = 5a14b556156191b2704936f64df0bf1dd2bd8d587418f4f85472338fcf86aa52
+Payload = 7cfefca725da1b6bb5d9545e3e50f5a624a8160bdb0e7d4e
+CT = 51045fe95e4d5097f91ae69dd315aaec58a683e64efe0bbeda99be0e054bb881a25a74b547d3ed5e
+
+Count = 246
+Adata = 148de640f3c11591a6f8c5c48632c5fb79d3b7e1cef9159c680d71fd1f9801fa
+Payload = 5205165c4e9612974dc92f60d1e328d68aa9466e27dbd499
+CT = 7fffb5123501596b010a9da33ca6779cf6a7d383b22ba2694c1fedb47fa30ff2ead6bf382431b2de
+
+Count = 247
+Adata = f852e38703097cc37c589b7860dbc333e091411462d5576dc9909a8cf6ac99d4
+Payload = f968f2833427abbc9fe1cab7e7a3f905a3b23a35802029ff
+CT = d49251cd4fb0e040d32278740ae6a64fdfbcafd815d05f0f338762a4e4299615c67130a28b56a383
+
+Count = 248
+Adata = 43df03a0e23c7ad0d13485150ca224c0b3f39d4e5f2d718db6308e003d3dc683
+Payload = 67da6ca42655188af0b8e389152b2a1b6e2c3ed88926afa5
+CT = 4a20cfea5dc25376bc7b514af86e75511222ab351cd6d9559dbdf61387294812f483aad76d48d899
+
+Count = 249
+Adata = b297dce04ada2ddebc7e94eff7c51b87eee2f98c410c5c0919d0652653ab7458
+Payload = 9777cf90dd7c7e863506686fc3ba6d3d05328f78b350f92f
+CT = ba8d6cdea6eb357a79c5daac2eff3277793c1a9526a08fdf078177541e19b11dfec995f40c99af70
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VPT256.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VPT256.rsp
new file mode 100644
index 0000000000..e9cd7eefe9
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VPT256.rsp
@@ -0,0 +1,1383 @@
+# CAVS 11.0
+# "CCM-VPT" information
+# AES Keylen: 256
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Nlen = 13
+Tlen = 16
+
+[Plen = 0]
+
+Key = c6c14c655e52c8a4c7e8d54e974d698e1f21ee3ba717a0adfa6136d02668c476
+Nonce = 291e91b19de518cd7806de44f6
+
+Count = 0
+Adata = b4f8326944a45d95f91887c2a6ac36b60eea5edef84c1c358146a666b6878335
+Payload = 00
+CT = ca482c674b599046cc7d7ee0d00eec1e
+
+Count = 1
+Adata = 36c17fd901169e5b144fdb2c4bea8cd65ad8acf7b4d3dd39acf2ad83da7b1971
+Payload = 00
+CT = 67747defe5da5fecc00b9bf3b249f434
+
+Count = 2
+Adata = 9a37c654ab8e5a0c6bdfff9793457197d206ed207d768cbc8318cfb39f077b89
+Payload = 00
+CT = c57ef5d0faf49149c311707493a4cfd4
+
+Count = 3
+Adata = 5ab80169184541393a6975f442ee583cd432d71a6d1568fa51159df7c5b8f959
+Payload = 00
+CT = bc2fb5571a7563bb90689a229d2f63a7
+
+Count = 4
+Adata = c78a22a667aafab0c94047e03837d51b11490693d5c57ea27b901ff80b6a38f9
+Payload = 00
+CT = 428888c6420c56806f465b415a66e65a
+
+Count = 5
+Adata = e11e30cbf63623816379f578788b0c8e6b59ee3c9c50aa6e1dcd749172d48fed
+Payload = 00
+CT = 9f1b7520025e1075731adc946b80121d
+
+Count = 6
+Adata = 05716168829276ff7ab23b7dd373db361e6d9e1f11d0028d374a0d3fe62be19f
+Payload = 00
+CT = bd36b053b6a90f19e3b6622cba93105d
+
+Count = 7
+Adata = 3e915389639435629fcc01e1b7022d3574e2848e9151261ad801d03387425dd7
+Payload = 00
+CT = 458595a3413b965b189de46703760aa0
+
+Count = 8
+Adata = 2f496be73a9a5d9db5927e622e166c6ec946150687b21c51c8ca7e680f9775ac
+Payload = 00
+CT = 8b259b84a6ee5669e175affca8ba3b1a
+
+Count = 9
+Adata = 0a8725bd8c8eab9ed52ca47835837b9f00a6c8d834ab17105b01eb4eb30402e7
+Payload = 00
+CT = c5f35fdf2b63e77a18d154f0ddcfedbf
+
+[Plen = 1]
+
+Key = cc49d4a397887cb57bc92c8a8c26a7aac205c653ef4011c1f48390ad35f5df14
+Nonce = 6df8c5c28d1728975a0b766cd7
+
+Count = 10
+Adata = 080f82469505118842e5fa70df5323de175a37609904ee5e76288f94ca84b3c5
+Payload = 1a
+CT = a5f24e87a11a95374d4c190945bf08ef2f
+
+Count = 11
+Adata = f6cfb81373f1cbb0574dda514747d0099635b48cb809c6f1fa30cbb671baa505
+Payload = 40
+CT = ffd43c5f39be92778fdce3c832d2d3a019
+
+Count = 12
+Adata = 5a88b14bada16b513d4aa349b11ce4a77d4cda6f6322ff4939ad77d8ecb63748
+Payload = 41
+CT = fe753b7b661f1aad57c24c889b1c4fe513
+
+Count = 13
+Adata = a92b95b997cf9efded9ff5e1bff2e49d32e65f6283552ded4b05485b011f853f
+Payload = 06
+CT = b91c5ac66e89bf2769ef5f38a3f1738b24
+
+Count = 14
+Adata = a206a1eb70a9d24bb5e72f314e7d91de074f59055653bdd24aab5f2bbe112436
+Payload = c8
+CT = 773fe64379cea1a8ae3627418dd3e489a2
+
+Count = 15
+Adata = d3029f384fd7859c287e38c61a9475d5ddbfd64af93746b1dc86b8842a8c194c
+Payload = e2
+CT = 5dabc529442ff93005551b7689bcb748f7
+
+Count = 16
+Adata = 51ca3d3b70b5e354451a5177d7acfd8e7b44eae55e29d88b5e8eb8fc1e5c62fc
+Payload = 1a
+CT = a5ee68e416617ac974b3d1af7320cd51f6
+
+Count = 17
+Adata = 8c6c6791f1ac957b18bf008e260a0af4a5b7bfdb1e0008d6eaaa227f45cf4f62
+Payload = dd
+CT = 6243883d93d7066991e0fac453400b4fbf
+
+Count = 18
+Adata = b0a1af969a95025385b251afd1e89f353426ed6e5d71019cd73366aa31d5b464
+Payload = 4c
+CT = f3b940d416f3435812f9d1b18f441b7721
+
+Count = 19
+Adata = 7e72b2ca698a18cb0bf625f5daddb0d40643009db938340a9e4fe164a052fee1
+Payload = 88
+CT = 371d27e9a32feea28a6a7e7da2d27e1cc4
+
+[Plen = 2]
+
+Key = 36b0175379e7ae19c277fe656a2252a82796309be0f0d4e1c07fdde88aca4510
+Nonce = 021bd8b551947be4c18cf1a455
+
+Count = 20
+Adata = b5c6e8313b9c68e6bb84bffd65fa4108d243f580eab99bb80563ed1050c8266b
+Payload = be80
+CT = ecacc3152e43d9efea26e16c1d1793e2a8c4
+
+Count = 21
+Adata = 38e5032c5949c2668191ef1af5bb17eddc28abdb4e5bb41eaffec2523b2525d6
+Payload = 82c9
+CT = d0e5d06bf4b50ccce0b2acfd16ce90a8854d
+
+Count = 22
+Adata = 0b50f5173249fb7118f80d25874d6745d88e4ce265fa0dd141ad67ae26c31122
+Payload = 8239
+CT = d0158d784f486c1dc4a2bafd5b02ca1e1c05
+
+Count = 23
+Adata = 0296743a3125b103a2b2a78a109e825ea10834bd684215ab2e85cc4172e37348
+Payload = 16c1
+CT = 44eda3377002a48f9fe306d157358e6df37d
+
+Count = 24
+Adata = a94e64becb803e211785ba51db7f3db042fbf44a7a821509156a6828b0f207e9
+Payload = 2801
+CT = 7a2df6c09bf1dcb1c82bd98c6e2c13a8d7a5
+
+Count = 25
+Adata = 105358cc17b12107e023a23d57b44c66a2c58d8db05100311575e1ea152fc350
+Payload = 65e7
+CT = 37cb2ea363c0d8864363056467570959ba03
+
+Count = 26
+Adata = 669f9a63cf638a202dca1965c4116273249813ce0b39703887d89bdf5b3b12d6
+Payload = 819d
+CT = d3b16519377e6d0252b5f80cdf3d0253eccf
+
+Count = 27
+Adata = e288590a3eba28ac6847a50b0294ab6bd0a548716ff5102c44a5b656b2d9ddd6
+Payload = 761e
+CT = 24329a4dee6ca2cde473f08f76f779856c3c
+
+Count = 28
+Adata = 5b222aae3c7786c3b9021ba672f9136190ec931cf055f84c85706127f74c6d5b
+Payload = 56de
+CT = 04f29e65c0f01e644e74092253b470cd5511
+
+Count = 29
+Adata = 2082f96c7e36b204ad076d8b2f796cccf5cbc80b8384b53a504e07706b07f596
+Payload = b275
+CT = e059809fa107f379957b52ac29fe0bc8a1e2
+
+[Plen = 3]
+
+Key = ddb739acda6c56ec9aefc4f4cbc258587f443da4e76ddfa85dbe0813a8784944
+Nonce = 0bddf342121b82f906368b0d7b
+
+Count = 30
+Adata = 887486fff7922768186363ef17eb78e5cf2fab8f47a4eb327de8b16d63b02acb
+Payload = db457c
+CT = 54473c3f65d6be431e79700378049ac06f2599
+
+Count = 31
+Adata = 0683c20e82d3c66787cb047f0b1eb1c58cdde9fb99ee4e4494bbf27eb62777d1
+Payload = 62a6c5
+CT = eda4853b186edc15c22ba24e470eb5a072da9f
+
+Count = 32
+Adata = 413074619b598f8bed34cab51ddf59941861ba0169ebe7570a5ed01d790c08e5
+Payload = cc67bc
+CT = 4365fc52a1fb5a58bd51931230c1a7dfb1a8c1
+
+Count = 33
+Adata = 2d65a5175c29a095dc082dab9cfcf4b895efbfa715c57614589d4db159543ce9
+Payload = 33800b
+CT = bc824b7d3810f59176cb108c7e969da51d4d79
+
+Count = 34
+Adata = 6a831b6059456be98e6fce608d8c71cb8efb04a96b45c2dfbdaeabf5420a1482
+Payload = b2c826
+CT = 3dca6646ffea832595c9c86e6517215541ddbd
+
+Count = 35
+Adata = 3a04a01160402bf36f33337c340883597207972728c5014213980cd7744e9e41
+Payload = d7e620
+CT = 58e460e89a6725f0fc35622d89d2f3e34be90a
+
+Count = 36
+Adata = 64d8bd3c646f76dc6ce89defd40777fe17316729e22ba90f6a2443ee03f6390b
+Payload = 795af4
+CT = f658b4b1bd7ad5d81686aeb44caa6025d488bd
+
+Count = 37
+Adata = 7bef8d35616108922aab78936967204980b8a4945b31602f5ef2feec9b144841
+Payload = 66efcd
+CT = e9ed8d0553c801f37c2b6f82861a3cd68a75e3
+
+Count = 38
+Adata = 92f7dc22dcbbe6420aca303bd586e5a24f4c3ed923a6ebe01ec1b66eee216341
+Payload = 78b00d
+CT = f7b24de3eeb8ea6c08b466baf246b3667feb3f
+
+Count = 39
+Adata = 71bf573cf63b0022d8143780fc2d9c7dbd0505ac31e9dce0ad68c2428b0878a0
+Payload = 9dd5e1
+CT = 12d7a11db811640c533794bfec6eeb977233ec
+
+[Plen = 4]
+
+Key = 62b82637e567ad27c3066d533ed76e314522ac5c53851a8c958ce6c64b82ffd0
+Nonce = 5bc2896d8b81999546f88232ab
+
+Count = 40
+Adata = fffb40b0d18cb23018aac109bf62d849adca42629d8a9ad1299b83fe274f9a63
+Payload = 87294078
+CT = 2bc22735ab21dfdcfe95bd83592fb6b4168d9a23
+
+Count = 41
+Adata = 75c3b3059e59032067e9cd94d872e66f168e503bcf46bc78d82a4d4a15a29f6e
+Payload = 0f28ee1c
+CT = a3c38951b5de3331078aa13bd3742b59df4f661a
+
+Count = 42
+Adata = 8fb9569f18a256aff71601d8412d22863e5a6e6f639214d180b095fa3b18d60e
+Payload = d41c9c87
+CT = 78f7fbcae52afe7326a12a9aaf22255a38d4bd0d
+
+Count = 43
+Adata = 8b62d9adf6819c46c870df8a1486f0a329672f7d137bb7d8659f419c361a466c
+Payload = 046bc0d8
+CT = a880a7957543692a72f0d599de48b5e5f5a9413f
+
+Count = 44
+Adata = fd98f8f39dfa46ea5926e0ffacbabbe8c34205aade08aa0df82e1d4eaaf95515
+Payload = 39bd4db8
+CT = 95562af530fc357f5482b9004d466bf858586acb
+
+Count = 45
+Adata = 09bf4f77a9883733590a3cc7ee97f3c9b70f4db255620e88cd5080badc73684c
+Payload = b43cdd3a
+CT = 18d7ba77a9e8db046fdd548b52d40375c1e9a448
+
+Count = 46
+Adata = 40326d765e0f6cf4b4deccb128bebf65a7b3c3e5bcf1d58f6158e1e9153b7e85
+Payload = e0052e9b
+CT = 4cee49d64efbdd4ad8d3e863172d9372fca07c20
+
+Count = 47
+Adata = aa5ae6dcdc21b5446489bdabf5c6747bdf3bbfdb3de2c03170efefe5ccb06d69
+Payload = 696825f6
+CT = c58342bb95bd661b32bc18025808f8b4035acad6
+
+Count = 48
+Adata = d3d34f140a856e55b29471fde4c0e5f7306b76d03faab26db79c10f95ffb3122
+Payload = 7eb07739
+CT = d25b1074ac05b072264e31a4b2801a6d790512d7
+
+Count = 49
+Adata = 648a84813ca97aef4ab7e143ee29acb946388660f18eb671194646e0b0136432
+Payload = 9cad70b1
+CT = 304617fcc00514d260e1d211de361c254369e93a
+
+[Plen = 5]
+
+Key = bc29a16e19cfbe32bf4948e8e4484159bc819b7eec504e4441a1a98ca210e576
+Nonce = 4f18bcc8ee0bbb80de30a9e086
+
+Count = 50
+Adata = 574931ae4b24bdf7e9217eca6ce2a07287999e529f6e106e3721c42dacf00f5d
+Payload = 3e8c6d1b12
+CT = 45f3795fcf9c66e1a43103d9a18f5fba5fab83f994
+
+Count = 51
+Adata = 99cd9d15630a55e166114f04093bd1bb6dbb94ecaad126fe5c408dee5f012d9f
+Payload = 76fc98ec66
+CT = 0d838ca8bb6f3cd579294f706213ed0f0bf32f00c5
+
+Count = 52
+Adata = 1516fdf7a7a99f3c9acc7fff686203dec794c3e52272985449ddf5a268a47bc3
+Payload = 6564c247cc
+CT = 1e1bd603117d38e026f706c9273dbcb6dc982751d0
+
+Count = 53
+Adata = 0c9c35be98591bf6737fc8d5624dcdba1a3523c6029013363b9153f0de77725b
+Payload = c11b9c9d76
+CT = ba6488d9abc3e46166767c6ad2aeffb347168b1b55
+
+Count = 54
+Adata = e74afe3ba960e6409dba78ecb9457e2a4ce2e09792b1d2e3858f4c79f7ddba62
+Payload = 45a4e0d7dd
+CT = 3edbf4930033a7dca78bcbf4d75d651ee5fadff31b
+
+Count = 55
+Adata = 96cbe9cd193513599c81f5a520fabaff51ee8cbdb81063c8311b1a57a0b8c8fd
+Payload = e5861b2327
+CT = 9ef90f67fa11585167c83105ee16828a574c84ac86
+
+Count = 56
+Adata = 2e7ea84da4bc4d7cfb463e3f2c8647057afff3fbececa1d20024dac29e41e2cf
+Payload = f5b5bcc38e
+CT = 8ecaa88753ffaba456f78e431f4baa5665f14e1845
+
+Count = 57
+Adata = be125386f5be9532e36786d2e4011f1149abd227b9841150d1c00f7d0efbca4a
+Payload = b6cc89c75d
+CT = cdb39d838034714731f9503993df357954ecb19cd3
+
+Count = 58
+Adata = 3fa8628594b2645bc35530203dca640838037daeaf9cf8acaa0fb76abf27a733
+Payload = 3802f2aa9e
+CT = 437de6ee436c1b008b7572752f04362b2bfdc296bb
+
+Count = 59
+Adata = 642ae3466661ce1f51783deece86c38e986b8c0adea9e410e976f8a2fe0fe10f
+Payload = e082b8741c
+CT = 9bfdac30c1a3f7c3c29dc312c1f51a675400500e32
+
+[Plen = 6]
+
+Key = 5f4b4f97b6aa48adb3336c451aac377fde4adf47897fd9ccdf139f33be76b18c
+Nonce = 7a76eac44486afdb112fc4aab9
+
+Count = 60
+Adata = a66c980f6621e03ff93b55d5a148615c4ad36d6cbdd0b22b173b4b1479fb8ff7
+Payload = 1b62ad19dcac
+CT = 4ad1fcf57c12b14e0e659a6305b4aeffae82f8a66c94
+
+Count = 61
+Adata = c13f65bd491cb172a0f7bbc4a056c579484b62695e90383358d605307d5be0a5
+Payload = 3ef0faaa9b79
+CT = 6f43ab463bc779fa7932d365e2da9b05c00a7318384a
+
+Count = 62
+Adata = 59dcca8fc50740831f8f259eb55d4db11f763a83187d93758d78d166f4d73cd5
+Payload = 1a98ddbf35f1
+CT = 4b2b8c53954f813229912137b7a4945dc07cea24a974
+
+Count = 63
+Adata = 578509ca4f57aadb78056794bf18b0714090970db786e2e838105e672165761c
+Payload = f46a7b1c28ea
+CT = a5d92af088546e045f19f737a24c8addf832ed3f7a42
+
+Count = 64
+Adata = 696c0c6427273cf06be79f2206c43af9cbda0b884efaf04deba0c4bf0a25cb26
+Payload = e98f5e5a20d0
+CT = b83c0fb6806edaae8a7dcd3b0fbb59438f88743ec6e8
+
+Count = 65
+Adata = 95a66b60249ed086eecaeb9bc449afcee9de212619e87516ca947351b25120df
+Payload = 06319c0480e2
+CT = 5782cde8205cd9cb636ca6543c4e35964f47341f2814
+
+Count = 66
+Adata = 2b411bea57b51d10a4d2fb17ef0f204aa53cf112e1130c21d411cdf16a84176d
+Payload = f4c723433b7c
+CT = a57472af9bc2ec82eadf4eb1f055da1a92a82052ab8b
+
+Count = 67
+Adata = ff3bff3a26fc5a91252d795f7e1b06f352314eb676bff50dc9fbe881c446941e
+Payload = 02f809b01ce3
+CT = 534b585cbc5d01b10a7ae24a4ca2bfb07ea2a3b31a97
+
+Count = 68
+Adata = f6be4aad63d33a96c0b5e9c4be62323c9e2308b29961fff980ba0dbda0549274
+Payload = 2b6004823a29
+CT = 7ad3556e9a97231323a4b88af5d7d0b07c0e73ddce1d
+
+Count = 69
+Adata = c3706a28d7420b41e072dcecc06b6b13116cca110bde8faea8e51f5107352d71
+Payload = 236c60cba4fa
+CT = 72df31270444db30eb33d2ede33abbe22f37704fe68b
+
+[Plen = 7]
+
+Key = f7aaeff3a1dc0cc5ecf220c67ad9f6dda060b4f1be3cc609cb4f18b2342a88a2
+Nonce = d0d6871b9adc8623ac63faf00f
+
+Count = 70
+Adata = e97175c23c5b47da8ce67811c6d60a7499b3b7e1347ad860519285b67201fe38
+Payload = d48daa2919348d
+CT = eb32ab153a8e092fa325bafc176a07c31e6cc0a852d288
+
+Count = 71
+Adata = ba45e1859efae362a44a0116a14e488ba369da6c76c3913b6df8e69e5e1111fa
+Payload = f95b716bfe3475
+CT = c6e47057dd8ef1a24840f4f40a7963becde3a85968b29c
+
+Count = 72
+Adata = efcaa6f6cda3036b0b52ff9f36bc38ca74049c32c6b7cdfb8a46ca4144bacd64
+Payload = 4862e3677083f0
+CT = 77dde25b5339748f2a4a5c276727e0a210fc2efb5aeabe
+
+Count = 73
+Adata = 360bcb407603fe92f856bf677625b9882521e6dae8f35fdfc3dc737f9398f609
+Payload = 7f1ca0728f6d65
+CT = 40a3a14eacd7e1051734fc31232ab2ab63474020ab4dc9
+
+Count = 74
+Adata = f12ee9d37946cfd88516cbe4a046f08c9bbba76a3973ff1e2cb14493405bd384
+Payload = 67478ef73290fa
+CT = 58f88fcb112a7ec715244f307609ffa253e4e3659b0ece
+
+Count = 75
+Adata = 5833dde0c577b2be4eb4b3d01d7b0042fa8441ad7043ea462bbbbd56a59790ea
+Payload = 36bb9e511276c5
+CT = 09049f6d31cc41f11047da612d2987fa2e50ada5ae7f9d
+
+Count = 76
+Adata = 1e103c63d8ead36b985f921044cd32b8f9f04a2ba9fa154a09e676ffaa093970
+Payload = d68d6556c5a5b1
+CT = e932646ae61f35382f7648718127ebae7eb7443ebd2c2c
+
+Count = 77
+Adata = a1cfb61d45a140bdea6329ba0fe80429ff9aa4624a1d31bc752f7c97f1d390a0
+Payload = 0568cca4ff79dc
+CT = 3ad7cd98dcc358cc40a5e7fffb1fb9a5dd9d6ba91bede1
+
+Count = 78
+Adata = 116b5b015e44ceef0061b2d2e73fa0b386d5c1e187782beebdfc6efb5a1c6935
+Payload = bd93d08eea4263
+CT = 822cd1b2c9f8e7468d2b70c311732f11ed72b57d83e500
+
+Count = 79
+Adata = 3d55882e6f3f89309b6940a3b408e573458eedd10fc3d0e1f3170eb313367475
+Payload = 4fb62753024e92
+CT = 7009266f21f416b41a70f548e359add30c0e5746fbeb2b
+
+[Plen = 8]
+
+Key = 493e14623cd250058a7fc66a3fee0c24b6e363b966c2314aff53b276b6c2ea7b
+Nonce = fe2d8ae8da94a6df563f89ce00
+
+Count = 80
+Adata = 579a637e37a0974cd2fc3b735d9ed088e8e488ffe210f043e0f9d2079a015ad6
+Payload = e5653e512d8b0b70
+CT = 75d31f8d47bee5c4e2ba537355ae8ab25cc9ed3511ff5053
+
+Count = 81
+Adata = 1583138aa307401dddc40804ac0f414d338fc3ffb2946f09aaaa7079426fc1ee
+Payload = 2c4ba9ce52e01645
+CT = bcfd881238d5f8f1781a9e359804831f31a1efb1ae1cb71d
+
+Count = 82
+Adata = 78d3dda40e433bba7a330ca3e5bd5170f0895f2e3e438402344ced79fcb0c719
+Payload = 5eb2d054a0e58c62
+CT = ce04f188cad062d62dcc77c4e1fe2bafd477598977835f0c
+
+Count = 83
+Adata = dfc762466fa84c27326e0ee4320aa71103d1e9c8a5cf7d9fab5f27d79df94bd6
+Payload = bbbf7830d04ab907
+CT = 2b0959ecba7f57b308946723baf0dbf613359b6e040f9bd5
+
+Count = 84
+Adata = 7e8ea82d1137c1e233522da12626e90a5f66a988e70664cb014c12790d2ab520
+Payload = 10c654c78a9e3c06
+CT = 8070751be0abd2b2003bd62ca51f74088bbbd33e54ac9dd4
+
+Count = 85
+Adata = 873da112557935b3929f713d80744ed08b4b276b86331dbc386fba361726d565
+Payload = 668d32e322e1da3e
+CT = f63b133f48d4348a67e65e7f2cdedf6ef8cc0ee7a6dcfb02
+
+Count = 86
+Adata = cfba97919f703d864efc11eac5f260a5d920d780c52899e5d76f8fe66936ff82
+Payload = e39f6225e8eab6cc
+CT = 732943f982df58780532f8c6639e5d6c7b755fcf516724e3
+
+Count = 87
+Adata = 01abcfee196f9d74fcaa7b69ae24a275485c25af93cc2306d56e41e1eb7f5702
+Payload = 6021a00f6d0610a4
+CT = f09781d30733fe107fd7a33828413ebc252dd9d015773524
+
+Count = 88
+Adata = ce1c31e7121c071d89afab5a9676c9e96cac3d89dcae83136bbb6f5ca8f81e5d
+Payload = bbaf0ac4e77ee78d
+CT = 2b192b188d4b0939d3d51368799325ad1c8233fa071bade0
+
+Count = 89
+Adata = bb210ca5bc07e3c5b06f1d0084a5a72125f177d3e56c151221115ae020177739
+Payload = 98a2336549a23a76
+CT = 081412b92397d4c25d1ea568637f773174a7f920a51b1fe1
+
+[Plen = 9]
+
+Key = b23255372455c69244a0210e6a9e13b155a5ec9d6d0900e54a8f4d9f7a255e3a
+Nonce = 274846196d78f0af2df5860231
+
+Count = 90
+Adata = 69adcae8a1e9a3f2fe9e62591f7b4c5b19d3b50e769521f67e7ea8d7b58d9fc8
+Payload = 615d724ae94a5daf8d
+CT = f019ae51063239287d896e7127f17d13f98013b420219eb877
+
+Count = 91
+Adata = 162d0033c9ea8d8334d485b29eef727302135a07a934eea5fee6041e9f1f47c1
+Payload = 0d9168eeab3b27ba69
+CT = 9cd5b4f54443433d997cc2cd61da9358b4045fef32f8192cbf
+
+Count = 92
+Adata = 3f4ab57efa32f51a4c00790280e77c0e55b85bbda4f854e242368e9a289b5a81
+Payload = 6287dcffdd5fb97885
+CT = f3c300e43227ddff75d280f0ffdd560fb8915978e3bd6205bb
+
+Count = 93
+Adata = 945d18134c148f164b39fd7c4aef0335045553f6ea690a3b1726418d86f0de00
+Payload = 6e5e01b3fd71d16b9c
+CT = ff1adda81209b5ec6c7dbf90420a1ff2e24bd6303b80cfc199
+
+Count = 94
+Adata = 23af12893431b07c2922ab623aed901c0eaaeb9a24efc55273e96aea4dab7038
+Payload = b51521e689b5247362
+CT = 2451fdfd66cd40f492d741f4329ae7cc77d42bf7e5f2ec5ab6
+
+Count = 95
+Adata = b15a118b3132c20c31e6c9d09acdee0e15fcc59d6f18306442682512d22eb10f
+Payload = 7f973617e710fb76fe
+CT = eed3ea0c08689ff10ec9ffdcc2f36edac14613b1d85baf25a9
+
+Count = 96
+Adata = dcfbeb6490f5fa7eaf917462473a6cec98bebf8f17493fe9b994119a6d5a5457
+Payload = 7e909b6727ac3fd02f
+CT = efd4477cc8d45b57df5a61a28bb10265b26043d7a8dd357713
+
+Count = 97
+Adata = 77e9317294f046f315a0d79e3423f29f7d9ebcd36d6eaa2a3fb2f4500309478c
+Payload = a5075638932b5632f8
+CT = 34438a237c5332b508d321c371ae1fd01bdf3b6c75a597da6e
+
+Count = 98
+Adata = 3aa8f204eb127b547e13873ed0238018394e13686c8734e49e3e629deb352c77
+Payload = c10f15a0de78db8aa3
+CT = 504bc9bb3100bf0d539393d1635bc40ac62405a39155406c47
+
+Count = 99
+Adata = 7f67e6f97c6c258f014d721a4edaaa0ddb3f9f09993276ab7b714ea9356c231d
+Payload = 8294f830cfca42cfbe
+CT = 13d0242b20b226484eff89641e1bd5ad6cc827441b17c45ecf
+
+[Plen = 10]
+
+Key = dbf06366f766e2811ecd5d4384d6d08336adc37e0824d620cf0d9e7fd1e7afa9
+Nonce = b3503ed4e277ed9769b20c10c0
+
+Count = 100
+Adata = 9ae5a04baa9d02c8854e609899c6240851cbc83f81f752bc04c71affa4eed385
+Payload = 2e3cf0af8c96c7b22719
+CT = e317df43ab46eb31be7e76f2730d771d56099a0c8d2703d7a24e
+
+Count = 101
+Adata = da77c6d5627a2aa34911bd1f7cc5f8aa68a2c6546adc96a186b9af8e5baac4cf
+Payload = e081c43a07450ce0dfa2
+CT = 2daaebd62095206346c5bcc7a8260ef361dc39fdb776d041f0d4
+
+Count = 102
+Adata = 134d2d9726400d09dd3521326f96fbef993ddc0c4088770057b0f8d70356456f
+Payload = c381d2ae5e72fc82324a
+CT = 0eaafd4279a2d001ab2d19f0cbb0899f221aac9762f2650f8058
+
+Count = 103
+Adata = 0d065dfde1de1f21784c7869eb566c977f807cfbd53578f4616995b51d7dc045
+Payload = 737f4d00c54ddca80eec
+CT = be5462ece29df02b978b3dc92a9bd26b9653e5917359c331fcff
+
+Count = 104
+Adata = 95c54d187f2415535451cbb9cb35869749b171f7043216ce6886dd77baeecf60
+Payload = 4e9e251ebbbbe5dbc8ff
+CT = 83b50af29c6bc958519891dda72c27d272561e00f7041845d998
+
+Count = 105
+Adata = 0f98039e6a9fe360373b48c7850ce113a0ff7b2ae5ce773dd4c67ca967cd691b
+Payload = 0db72b281ab4046d15a6
+CT = c09c04c43d6428ee8cc1928ac628758ad58fc1b5a768d4722848
+
+Count = 106
+Adata = ad840bc55654762e5eba0e4a9e7998992d990a06d70da1b1ca922ef193dab19a
+Payload = 4f7b4f38ff1ba4df5a59
+CT = 825060d4d8cb885cc33ed11dad4dc8b265a53cf0bdd85c5f15f4
+
+Count = 107
+Adata = 911e9876ea98e1bcf710d8fd05b5bf000ea317d926b41b6015998ee1462ab615
+Payload = 58ce55379ef24b72d6d6
+CT = 95e57adbb92267f14fb18eb659a5a7084be48d099467da4395df
+
+Count = 108
+Adata = 3f68a4fb4043bcf9b6d277c97e11365d949c705bd6679c6f0aaf52e62330ad79
+Payload = a219028a953ce1544835
+CT = 6f322d66b2eccdd7d1523b2b2583fd117cec47b1c84d3863159e
+
+Count = 109
+Adata = 02f32242cba6204319075ea8ce806a57845355ae73e6b875955df510096ebff9
+Payload = 83b0ee9a52252c456105
+CT = 4e9bc17675f500c6f8625456eb2b6a2d35c649a84051f843153c
+
+[Plen = 11]
+
+Key = 4dd555bd3a5253a90b68b5d4d46bd050340ee07ddad3a72048c657b5d76bb207
+Nonce = bdb1b82ba864893c2ee8f7426c
+
+Count = 110
+Adata = 9bcc5848e928ba0068f7a867e79e83a6f93593354a8bfcfc306aeeb9821c1da1
+Payload = 8015c0f07a7acd4b1cbdd2
+CT = 8e9f80c726980b3d42e43a6512a0481255b729a10f9edb5f07c60c
+
+Count = 111
+Adata = c2e75952ab49216f305e3776865791ce877cef8c0229ca97561787093fddf1d8
+Payload = c97b62a719720b44b7779c
+CT = c7f122904590cd32e92e748c514444f00ffdb80a4bb7e9eb651946
+
+Count = 112
+Adata = c76a3ff4e6d1f742dd845be2d74c1a9b08e418909b15077deb20373ef55caf91
+Payload = cb7c17ef62464ecc8008f6
+CT = c5f657d83ea488bade511edb609dfc1929ac1ba5753fc83bf945b7
+
+Count = 113
+Adata = bdb69f99f9a144b9ad88c6cfd8ffb8304c201de9b2818552ce6379e6042c1951
+Payload = 893a690cc5221de597d0e8
+CT = 87b0293b99c0db93c9890053b74283296d0fca83b262915289163c
+
+Count = 114
+Adata = 01815f599d6ba0d1c09f6f673bb6cca4c2a7a74f4e985be4c0f37842c7bbc5a4
+Payload = 80f3e4245c3eab16ef8bf0
+CT = 8e79a41300dc6d60b1d21888a34955893059d66549795b3ac2105c
+
+Count = 115
+Adata = a9db62e9ab53c4a805c43838ce36b587d29b75b43fb34c17a22d3981120f3bc5
+Payload = 641c6914920a79943dca39
+CT = 6a962923cee8bfe26393d1377c4e2f20aaa872a9a0b1d1d7f56df0
+
+Count = 116
+Adata = f0c2cc5a1b4c4cbe839338fa0d7a343514801302aef2403530605cf4f44d2811
+Payload = 2286a1eddd80737a724ca9
+CT = 2c0ce1da8162b50c2c15415545aa0c1dd11551891ae553d3a91908
+
+Count = 117
+Adata = 9842922499ad4d487488b3731f48765efe0b4eb59e7b491ba5f6636f09ed564d
+Payload = d8c63e7d7d332198249c0c
+CT = d64c7e4a21d1e7ee7ac5e4d9e07ec5806360843676ef27d811b246
+
+Count = 118
+Adata = 399b71ecb41f4590abda79045cdf6495f27daaa559c1b34f513b5c4ac105ec10
+Payload = 4b81804d777a59b6a107cf
+CT = 450bc07a2b989fc0ff5e27483b8727c5753ede25e1fab0d86963be
+
+Count = 119
+Adata = 2c186c5c3463a4a8bad771feb71e2973c4f6dede2529827707bf4fa40672660f
+Payload = dfc762466fa84c27326e0e
+CT = d14d2271334a8a516c37e64b5c3c1dc577ee8fcf6ef3ebc0783430
+
+[Plen = 12]
+
+Key = d3ad8cda9a0d91a205c4c05665728bb255d50a83403c9ab9243fcbbe95ae7906
+Nonce = 0b5f69697eb1af24e8e6fcb605
+
+Count = 120
+Adata = ea26ea68facdac3c75ba0cdf7b1ad703c9474af83b3fbfc58e548d776b2529b9
+Payload = a203aeb635e195bc33fd42fa
+CT = 62666297a809c982b50722bd56bc555899345e0404b2938edf33168e
+
+Count = 121
+Adata = 0b32069fc7e676f229f1037d3026c93eef199913e426efd786b524ce1dbde543
+Payload = aac414fbad945a49ae178103
+CT = 6aa1d8da307c067728ede1449b15447c904b671824c2ca24c4fc7ad4
+
+Count = 122
+Adata = 7a8658302e5181552292aa56e8209de63b5d86934167549b0d936202681757e1
+Payload = 7ee0ce371329192618e3cda0
+CT = be8502168ec145189e19ade7ea13850e99ef9300c65f5abc9419d13a
+
+Count = 123
+Adata = 4f05600950664d5190a2ebc29c9edb89c20079a4d3e6bc3b27d75e34e2fa3d02
+Payload = b0a1af969a95025385b251af
+CT = 70c463b7077d5e6d034831e8486c93c31bbedc9e5ffa2f4154bceea9
+
+Count = 124
+Adata = 4530e4dc6a4c3733b8ab7e77e384223cc1a8c179fb66818c08aca47e5c705d89
+Payload = 9f6c6d60110fd3782bdf49b0
+CT = 5f09a1418ce78f46ad2529f7f18b556e7da59fd2549dc57a17bf64f8
+
+Count = 125
+Adata = f179353aef342f0f691caf1fcb811e3f6504e14d6d9381c5439b098ff978b01b
+Payload = 90958d7f458d98c48cbb464c
+CT = 50f0415ed865c4fa0a41260b30aad3a838680cbd313004685a5510c5
+
+Count = 126
+Adata = f6df267e5cbc9d2a67b1c0fd762f891ee3b7c435884cb87d8228091b34aeddae
+Payload = 9f7ae892e5662803408d4d06
+CT = 5f1f24b3788e743dc6772d411d57b89ed0c91251aed37a6ca68a50c7
+
+Count = 127
+Adata = 4372e152b1afd99c7f87c8a51dbc3a5c14c49d04ea1c482a45dfbcda54972912
+Payload = 817074e351455f23cb67883d
+CT = 4115b8c2ccad031d4d9de87ad79a3b0feea16ff5fbca16211ea6fdd9
+
+Count = 128
+Adata = 82b6cd1c6618c42ba74e746075dc28700333578131ca6fde6971d2f0c6e31e6a
+Payload = 1b7da3835e074fdf62f1eb3c
+CT = db186fa2c3ef13e1e40b8b7b49f22737c4b2f9fa0a7e3dd4b067fbaa
+
+Count = 129
+Adata = a5422e53975e43168726677930f6d3e13281bdbd13c67c168340ed67e45d15b0
+Payload = 57473e7a105c806867379194
+CT = 9722f25b8db4dc56e1cdf1d3ef43a48dbea8c1547455ad0197af88a2
+
+[Plen = 13]
+
+Key = e300fc7a5b96806382c35af5b2c2e8e26382751b59010d4b1cfc90a4a9cb06df
+Nonce = 55b59eb434dd1ba3723ee0dc72
+
+Count = 130
+Adata = 9b1d85384cb6f47c0b13514a303d4e1d95af4c6442691f314a401135f07829ec
+Payload = 8714eb9ecf8bdb13e919de40f9
+CT = ba6063824d314aa3cbab14b8c54c6520dac0f073856d9b9010b7857736
+
+Count = 131
+Adata = fa17c693d0997140fbc521d39e042d8e08388106874207ca81c85f45c035d6e6
+Payload = a0837676e091213890dc6e0a34
+CT = 9df7fe6a622bb088b26ea4f20820a423dd30796b6016baff106aaef206
+
+Count = 132
+Adata = 27663597b389b78e96c785ca2f5510c8963a5561d2b0b24c4dcdf8e58562c12c
+Payload = b8a2ce7e051b8d094ec43f2a7f
+CT = 85d6466287a11cb96c76f5d2436032bc79c4aef1f74da25e92b0aa7f8a
+
+Count = 133
+Adata = d8f1a83371487d611ce704e0a6731f97a933c43569690022fce33cb5aecdc0a7
+Payload = 9e4103ab1dfb77ae3494507332
+CT = a3358bb79f41e61e16269a8b0e658123d2e5bb324c7ead8897f8e32b0a
+
+Count = 134
+Adata = 05c57aab99f94b315cf8bdd2d6b54440c097fe33c62a96b98b1568cdee4ce62c
+Payload = fb3e3d1b6394d2daebf121f8ac
+CT = c64ab507e12e436ac943eb0090270758ab09f93fa3ba7d7a2aa8eac789
+
+Count = 135
+Adata = 1c1b0933c508c6a8a20846ebd0d0377e24f4abc0c900d3a92bc409ba14ef1434
+Payload = 549ba26a299391538b56ce4bd7
+CT = 69ef2a76ab2900e3a9e404b3eb2293813f1bcb96564f772e9308e42b2d
+
+Count = 136
+Adata = 9f5cf9149f556124d6bb4e3e243cca1502c02682709392cc2ec7eb262fd4d479
+Payload = 287f31e69880823df7798c7970
+CT = 150bb9fa1a3a138dd5cb46814c81877380d5cf097c2fb5177750f8b53a
+
+Count = 137
+Adata = 1a49aaea6fc6fae01a57d2fc207ef9f623dfd0bc2cf736c4a70aaaa0af5dafd3
+Payload = 040d18b128ae4a1935f9509266
+CT = 397990adaa14dba9174b9a6a5acf42c75787edc62a180568c6ef56545d
+
+Count = 138
+Adata = f29a0b2c602ff2cacb587292db301182e6c76c5110b97ca8b706198f0e1dbc26
+Payload = 92441cbe8d70820870bb01ad63
+CT = af3094a20fca13b85209cb555f56d47a0631f2038103e3904b556ba7a5
+
+Count = 139
+Adata = 01fcf5fef50e36175b0510874ea50a4d2005ad5e40e5889b61417700d827251e
+Payload = f11d814df217de96333dee1cbf
+CT = cc69095170ad4f26118f24e4835be15b7ae24edccd0b0934e3af513ed3
+
+[Plen = 14]
+
+Key = 3ae5be5904bae62609ac525e2d1cad90133447573d7b608975a6a2b16cb2efc0
+Nonce = 61bf06b9fa5a450d094f3ddcb5
+
+Count = 140
+Adata = 0245484bcd987787fe97fda6c8ffb6e7058d7b8f7064f27514afaac4048767fd
+Payload = 959403e0771c21a416bd03f38983
+CT = 37a346bc4909965c5497838251826385a52c68914e9d1f63fd297ee6e7ed
+
+Count = 141
+Adata = 52f6a10a022e5ee57eda3fcf53dcf0d922e9a3785b39fad9498327744f2852e4
+Payload = 23fe445efa5bcb318cc85e2ad1ac
+CT = 81c90102c44e7cc9cee2de5b09ad364b603de6afbc2d96d00510894ccbe7
+
+Count = 142
+Adata = d236e3841b9556b32dbd02886724d053a9b8488c5ad1b466b06482a62b79ebb6
+Payload = 762fdc3e0c30c7ecf2ec8808bb79
+CT = d418996232257014b0c6087963781a4321c2ddbc35ce4864457d611219e9
+
+Count = 143
+Adata = 0d2739cfdac782b61f484fa1a423c478c414397ec420327963d79112b2d70a7e
+Payload = b6813d5fe8afa68d646c197337a2
+CT = 14b67803d6ba117526469902efa3296e55efebb17fe145cdca9b31ea7bcc
+
+Count = 144
+Adata = 7f291aa463c4babc76b4a6faf2e27e9401586b1ac83e4b06a4090e94b3ef5fd4
+Payload = 4ce8b6578537215224eb9398c011
+CT = eedff30bbb2296aa66c113e9181059270a0510e7cc1b599705853af2144d
+
+Count = 145
+Adata = 06bca7ef6f91355d19f90bf25590a44a24e5a782f92bc693c031e6de1e948008
+Payload = 9ebf93643854ea5c97a4f38f50bd
+CT = 3c88d63806415da4d58e73fe88bcb55847573bf21e946ce9bdc5f569e3ff
+
+Count = 146
+Adata = 5a44ff94f817c7c028a8f3db35a4d01364d2598432469f09ded86e5127d42d35
+Payload = da989cc7d375ed5fac4d7f938d74
+CT = 78afd99bed605aa7ee67ffe25575b8a61c5687ea02f0276824b8316b76f1
+
+Count = 147
+Adata = 2a755e362373ef27a911c4d93ca07bc97135645442ad7ad6a8ef98146c71e9d7
+Payload = 6fbab5a0f98e21e4d15904af5948
+CT = cd8df0fcc79b961c937384de8149a07ee02791011129fcacffcfb1bf4145
+
+Count = 148
+Adata = f7988873f45a5de314e5381d3f14d8f8c48c9b649bf3e745ed5dc882d507da58
+Payload = b610349e8b370a7c195598573637
+CT = 142771c2b522bd845b7f1826ee36d34204b1ce23f5f58a8eb7cf1fa8cfa7
+
+Count = 149
+Adata = 95d2c8502e28ab3ee2cac52e975c3e7bccb1a93acc33d9c32786f66d6268d198
+Payload = 1d969fd81dab5ced3e6ee70be3bf
+CT = bfa1da8423beeb157c44677a3bbe9c618bb88bbcefb008a5ea6bed4ff949
+
+[Plen = 15]
+
+Key = fab62b3e5deda7a9c1128663cc81c44b74ab1bfe70bc1c9dec7c7fd08173b80a
+Nonce = a5c1b146c82c34b2e6ebeceb58
+
+Count = 150
+Adata = 5e60b02b26e2d5f752eb55ea5f50bb354a6f01b800cea5c815ff0030b8c7d475
+Payload = 54be71705e453177b53c92bbf2ab13
+CT = 788db949697b8cd9abbc74ed9aa40cd6852dc829469368491149d6bb140071
+
+Count = 151
+Adata = 210c04632341fbfc185bfe3cbf6fe272bbe971104173bcb11419b35ab3aaf200
+Payload = 22197f9ad14591e7a6d5f8b18c969a
+CT = 0e2ab7a3e67b2c49b8551ee7e4998556940dc5a7e44bf10234806d00a012b5
+
+Count = 152
+Adata = d3a205dd017e79a67400a937a20ef049f4c40d73311731f03ab857a3f93bd458
+Payload = 096b2f530933c1273304a6ad423726
+CT = 2558e76a3e0d7c892d8440fb2a38390898f7dbde25b0b70d335df71a06987b
+
+Count = 153
+Adata = 0c9b3ba4faf5fc2f310ad1bab06c4ca13474b714feeffb6ad615c1b850bbd6a3
+Payload = d44fdfd9da3a63c1083afe574e91bf
+CT = f87c17e0ed04de6f16ba1801269ea02fd10d1f21b6b963c05aeda8eb09e272
+
+Count = 154
+Adata = d9bb71ad90152d5c1af358c8501fa89ebd4b17bf4ff43841528cccb79fd791b3
+Payload = 8d836acc13ed83c2b2c706415c9679
+CT = a1b0a2f524d33e6cac47e0173499664491d23d90ff55abca17e9d943b98c7f
+
+Count = 155
+Adata = 69dc21eb6f295b12ba493ee8fe6c40d78af946067ce772db316a3cbf00d3c521
+Payload = 2a68e3fe746f593c1b97cb637079c3
+CT = 065b2bc74351e49205172d351876dc9616886c6b2adc97db5a673846b6662c
+
+Count = 156
+Adata = 095eb52135dc6d9c1f56a2571c1389852482e7aa3edc245a3904a0449db24a70
+Payload = 39799b001ed2c334c269acb0f2328c
+CT = 154a533929ec7e9adce94ae69a3d932441dcae1760db90379bd354fa99164e
+
+Count = 157
+Adata = efd7270e0396392fde8b0ddaab00544cbbd504f4d97d4e90d749d1946de90dcb
+Payload = 42143a2b9e1d0b354df3264d08f7b6
+CT = 6e27f212a923b69b5373c01b60f8a9c7c7deb28bdcf84886ef843216b94449
+
+Count = 158
+Adata = 8bc181ce2e66294e803a8dc3834958b5f173bc2123c0726e31f3fca25b622ed6
+Payload = a3dcf26327059a4245b79a38bb8db6
+CT = 8fef3a5a103b27ec5b377c6ed382a935061ae3cd892ba63c44b809d6d29421
+
+Count = 159
+Adata = c39ec70c2c71633ae0dccc41477ac32e47638c885cf59f34ebd4a096d32f91f9
+Payload = 3d54883449ecca8f153436c25a0a01
+CT = 1167400d7ed277210bb4d09432051e3c9ae69a4c59ff8e251c2fe022d065a9
+
+[Plen = 16]
+
+Key = ee8ce187169779d13e443d6428e38b38b55dfb90f0228a8a4e62f8f535806e62
+Nonce = 121642c4218b391c98e6269c8a
+
+Count = 160
+Adata = 718d13e47522ac4cdf3f828063980b6d452fcdcd6e1a1904bf87f548a5fd5a05
+Payload = d15f98f2c6d670f55c78a06648332bc9
+CT = cc17bf8794c843457d899391898ed22a6f9d28fcb64234e1cd793c4144f1da50
+
+Count = 161
+Adata = a371ca29b92ed676bab5dfc4d78631bb6d9bb23a29f822907084a1f0fe17721f
+Payload = 60d55a8d5ab591a51e87fdf6aaa2ad25
+CT = 7d9d7df808aba2153f76ce016b1f54c68b55bbe42d8c97504b97c34a5f16e6a6
+
+Count = 162
+Adata = 01ec87920b42639d4ba22adb1fbe5138d2849db670a2960fd94a399c1532ed75
+Payload = cbf112e4fb85276c4e09649f3de225b2
+CT = d6b93591a99b14dc6ff85768fc5fdc51017d8706acd676ae99e93d5312a4113c
+
+Count = 163
+Adata = eebd2bbf1e9f6d817cd8062a6a9680e7f10464eefeb50b07cb46b14b9b3fcb2c
+Payload = 865b89aa38ee1b5a3ce56620307e8937
+CT = 9b13aedf6af028ea1d1455d7f1c370d45982f0fe5d951a8c62c87894657301e4
+
+Count = 164
+Adata = 72863362612f146699f6b2f6ec3688f2ca6cb1505af7a309c91c1933e34d516a
+Payload = a8efc37d1b8b51f2a47b21dd14da383d
+CT = b5a7e40849956242858a122ad567c1de5addfddbb59f4985947fb3a9ab56333e
+
+Count = 165
+Adata = 9c9efc6593f96207678db813608f2b8bc33ed1bef974ed77ed7b6e74b621b819
+Payload = d9b0eaaff786165f882f41a98dbc0c35
+CT = c4f8cddaa59825efa9de725e4c01f5d6b651053516673402a57538db1a9ce7e9
+
+Count = 166
+Adata = dc482a051b58d8a3904d3af37c37b51983f634a504451bbba6f77d71337f8e78
+Payload = df49d972b6ebbbb18ee975ac635d847e
+CT = c201fe07e4f58801af18465ba2e07d9d86d772b1a1991b7be6589bbccad36171
+
+Count = 167
+Adata = 51ef065a43caa23faf750b02a41ad6ba701aeb8058f6d8738d6f6b005bec7f60
+Payload = 78318aa5cd16699b77bdcea2fc9d1d20
+CT = 6579add09f085a2b564cfd553d20e4c3569387a1a6bcc826e94012670820576e
+
+Count = 168
+Adata = 88e2a74d2920c89c6a101f5f06d0624a6d5eabd9bdb51395ee3983934c55c73d
+Payload = 8e20d65d02dd9a64379f75b6d8328f2d
+CT = 9368f12850c3a9d4166e4641198f76cee9c788b4aae9b2c6caf0c44aa9bd2ed0
+
+Count = 169
+Adata = ada3ed7db2dabbfbc441ef68a5656e628d6d5bd6c1574369688497179a77601a
+Payload = 97e8d8513af41b97801de98cc4269096
+CT = 8aa0ff2468ea2827a1ecda7b059b6975f1df0f01944641a1b04d753e6ab8d3cc
+
+[Plen = 17]
+
+Key = 7da6ef35ad594a09cb74daf27e50a6b30d6b4160cf0de41ee32bbf2a208b911d
+Nonce = 98a32d7fe606583e2906420297
+
+Count = 170
+Adata = 217d130408a738e6a833931e69f8696960c817407301560bbe5fbd92361488b4
+Payload = b0053d1f490809794250d856062d0aaa92
+CT = a6341ee3d60eb34a8a8bc2806d50dd57a3f628ee49a8c2005c7d07d354bf80994d
+
+Count = 171
+Adata = 4ae414bc888a42141d3060c71c2dbbffd425b6a952806982271a8e756b3c9e24
+Payload = 51eb190c6a9f46e8ec1628b090795470c0
+CT = 47da3af0f599fcdb24cd3266fb04838df13c1c5755a5a240c33b2b890a486aac8b
+
+Count = 172
+Adata = 7b7f78ae1a5ee96fdc49dacd71be1a6ac09a6a162d44dea0172886eca5674e46
+Payload = 25144e807e389bb0e45b6dc25558caf61a
+CT = 33256d7ce13e21832c8077143e251d0b2b4cfca1c19abf447d7bc0898d61885144
+
+Count = 173
+Adata = 03f31c6143b77f6ad44749e2256306b8bf82242f2821fad4075b09b388ba81ca
+Payload = dbe1ee14abfe2ecf4edf6db206cf9886ce
+CT = cdd0cde834f894fc860477646db24f7bff229cc7a390867a245dcb7c434f1db347
+
+Count = 174
+Adata = 030390adb572f2bd2a6a4454fd68236cd1d465574328aa001d553375cc63f8a2
+Payload = db6df31f12bf552f81deff5fa2a373fc22
+CT = cd5cd0e38db9ef1c4905e589c9dea401135361b539f9fe0fb7842907c2326aef63
+
+Count = 175
+Adata = 7294ae94358669f2ada4b64c125b248df7fe86c6715e3b6a7b9bb2bd99392c8a
+Payload = ff2a97b49fcc6a50d4549c979d53ccc51f
+CT = e91bb44800cad0631c8f8641f62e1b382e8ed10943929e7d7bf798b2ae8371aae5
+
+Count = 176
+Adata = 4d1513478fc1fb0a18eb6d2a9324fefbd975ecd1b409025de826bc397462acc1
+Payload = 73ddfa0185200a890b7690a7e3986d8818
+CT = 65ecd9fd1a26b0bac3ad8a7188e5ba7529f92b9e49ab83f113f8949dc9e4a36e0d
+
+Count = 177
+Adata = b26a7ff61bfe94864249af7cc9b4a723627dd4463f5a22f0ca6063769522eab7
+Payload = 5c7604f9ac8fdf30ee5820e5aeb75b65d7
+CT = 4a4727053389650326833a33c5ca8c98e6d0e53223adff22a08e3dddf66fff23e3
+
+Count = 178
+Adata = 960f9a85cfbfb6eab223a4139c72ce926a680ea8e8ecc3088cf123de659ad310
+Payload = d44fdfd9da3a63c1083afe574e91bf01c9
+CT = c27efc25453cd9f2c0e1e48125ec68fcf833f49a42521a7a2367f91bfcc2180b7c
+
+Count = 179
+Adata = 3718467effb5d5dc009aaefce84d8cb4fe8f80eb608f4c678f5d0de02ea11e59
+Payload = bb515dc227abb9acad8fefaa14771bb77b
+CT = ad607e3eb8ad039f6554f57c7f0acc4a4ac08bd395c6807223311070659f550934
+
+[Plen = 18]
+
+Key = 0786706f680c27b792d054faa63f499a8e6b5ddb90502946235bf74c022d772c
+Nonce = f61ef1c8c10a863efeb4a1de86
+
+Count = 180
+Adata = 67874c808600a27fcab34d6f69cc5c730831ad4589075dd82479823cb9b41dc3
+Payload = 6a26677836d65bd0d35a027d278b2534e7df
+CT = d1c1f3c60603359c7d6a707f05ecb2296f8e52f2210b7a798ad5c778ee7cfd7fe6e0
+
+Count = 181
+Adata = e0c27cddf919d3092d9a34766c89a5ae6dcf39fe954d1e6f1a70ddf96805def4
+Payload = 4021ff104ff1dbd91e46db249fd82198b0a1
+CT = fbc66bae7f24b595b076a926bdbfb68538f00923bb5a347af13df12f234fca5f03ef
+
+Count = 182
+Adata = 7ae9eca03f616ab39ebb3be26b848842b4aa584e5c8e5695065ad5af34951175
+Payload = 6a681f164efce199a787bccff223b8ae1a98
+CT = d18f8ba87e298fd509b7cecdd0442fb392c9d03ed7bffac83e890caceb6903d9cab5
+
+Count = 183
+Adata = b47c9bc4eb01c74f5db2e6a293bef80db18c58cf06feef7ee0f8a7a9a51c22bb
+Payload = 7861dac338ba3f8274dca04c8c6f92b6d44c
+CT = c3864e7d086f51cedaecd24eae0805ab5c1d4dd8f30870025b2bd1e2a2511574d3e7
+
+Count = 184
+Adata = f6afd661f218c7426b92ee53e65d14898cd0c78a7e594fcc6ac0e3fb5cab1c9c
+Payload = a3f0473c620d2739d5ba4f7156f88d0fb669
+CT = 1817d38252d849757b8a3d73749f1a123e386046d17f337f3cb49884d94995edbdc9
+
+Count = 185
+Adata = d3802911e341577046cfc61d9043b4af059fb4bef3c6a2ff46ccdcb05670af37
+Payload = 07c535d9456a6ff1e41321150d16dae3f7a3
+CT = bc22a16775bf01bd4a2353172f714dfe7ff25fdc77b43bca254d6459263cdfed8fbb
+
+Count = 186
+Adata = db60720db67a60ca286fe744d46173c231fbcc7deb4c9b0d87d52a2247e06b74
+Payload = 5ee220720a896249efdab2ce418318bb5ebf
+CT = e505b4cc3a5c0c0541eac0cc63e48fa6d6eedd1a1d36c8164c55d55dbf0ff1e9517a
+
+Count = 187
+Adata = 57f70ba5493265b30491decc726354e2065e7971a2efd56db9cf0f79b1d76859
+Payload = 98e4eb0361c8bf40bcbe0539b0850e4c35ff
+CT = 23037fbd511dd10c128e773b92e29951bdaeb476e2ca48fd52bec0539b00744a8a07
+
+Count = 188
+Adata = 4a29b9ad548964942f87f28ba267ec0d0e8f72c73b3823ee57693dd63c2605c1
+Payload = 7f0745bea62479c0080ecec52e37c1e32d72
+CT = c4e0d10096f1178ca63ebcc70c5056fea523fad68c62b81d62f2d490ae74f5bb1465
+
+Count = 189
+Adata = acbd2e9911b3218a230d9db5086d91dccac3fc93fc64b0f4a15d56954906b2b7
+Payload = e99ed2ac6c38e033061b5d85f3e77dd72518
+CT = 527946125ced8e7fa82b2f87d180eacaad4913b15d8000266c61ba5aec898eb35b52
+
+[Plen = 19]
+
+Key = bac55f9847d93325bf5071c220c0a3dfeb38f214292d47b4acb7b0a597fe056f
+Nonce = 05b50c458adbba16c55fcc454d
+
+Count = 190
+Adata = 89ad6ae1e550975eaa916a62615e6b6a66366a17a7e06380a95ea5cdcc1d3302
+Payload = c1a994dc198f5676ea85801cd27cc8f47267ec
+CT = 7c9b138177590edaafec4728c4663e77458ffbe3243faec177de4a2e4a293952073e43
+
+Count = 191
+Adata = dfddb719d00398bf48a6cefd27736389e654a93b8595cd5ac446af1996e0f161
+Payload = 791e232bfb42fb18197adc1967da1a83f70168
+CT = c42ca4769594a3b45c131b2d71c0ec00c0e97f8422f736fc435687634d42254b22fd99
+
+Count = 192
+Adata = 58ef310997dcaf067dd217274921504da6dbf0428a2b48a65fe8a02c616ac306
+Payload = 3d4127942459bb8682e662dfc862467582fa68
+CT = 8073a0c94a8fe32ac78fa5ebde78b0f6b5127f38a96e68ef7dbaef1b460cc0980eacd4
+
+Count = 193
+Adata = 511e5d5e100b595f6b20e791830bca37e23f7b785e482a58405bffe7a632a5b8
+Payload = 0e71863c2962244c7d1a28fc755f0c73e5cbd6
+CT = b343016147b47ce03873efc86345faf0d223c15c5c702a82d468929227502e4e35796f
+
+Count = 194
+Adata = e48dfaa53b6807ea6f01d8dca67960b9f321f7851f324459a9bf61fe0be73abb
+Payload = e0f1cd013e6aea4fa484fc3fa35d348b1a2399
+CT = 5dc34a5c50bcb2e3e1ed3b0bb547c2082dcb8e89188c0940182dd99a902d158c5b0810
+
+Count = 195
+Adata = c12c0423fe36e4c88775dd00b4af267b85b7dd2a37a742a3156923c8917c97a3
+Payload = b1cc1946b4fc1dbd033254cdf536f61e9f9cd7
+CT = 0cfe9e1bda2a4511465b93f9e32c009da874c015849acbb7af1892790300bb84fb0558
+
+Count = 196
+Adata = 4255f8af18df7237e0abe98421aec9634443561752d893aaffe76380e829ef32
+Payload = 87284658928208e3bddca83e3ceb13708d88d4
+CT = 3a1ac105fc54504ff8b56f0a2af1e5f3ba60c3e75aaf3077ac6dfb5454851ec3910de6
+
+Count = 197
+Adata = ab83567833d2f3461b5fbecc0e366694bb5ea00933b2b3e792ec3aefe20325df
+Payload = bdb79f931ef3035a33bdd1b032fd9de8f6b2ba
+CT = 008518ce70255bf676d4168424e76b6bc15aade70f42e3e1f2b5bb58433bd11f5dea1f
+
+Count = 198
+Adata = bd1446ba3185d1c16551730947c22142142caa8cc1c540e89ab734ec297401bc
+Payload = 1f9c3a8eb8bc59f3869e10f73883aa8f8990cb
+CT = a2aebdd3d66a015fc3f7d7c32e995c0cbe78dc564f6248cefe5fc7cfb547c90a558925
+
+Count = 199
+Adata = b87577755d2d9489194f6f7cfabf267dc3433a9c91954e81beb72c5e06870922
+Payload = 5f28809181f9a889894da8d6fe1fde6cce354a
+CT = e21a07ccef2ff025cc246fe2e80528eff9dd5db52249d812f7f235afa0732e984e91b2
+
+[Plen = 20]
+
+Key = 8beedeb85d42c2a7fa6f7237b05acb197dd8e1672471ac878064fe5319eab876
+Nonce = 8479bdfad28ebe781e9c01a3f6
+
+Count = 200
+Adata = 7aebdfd955d6e8a19a701d387447a4bdd59a9382156ab0c0dcd37b89419d6eff
+Payload = 7b125c3b9612a8b554913d0384f4795c90cd387c
+CT = 6cc611d816b18c6847b348e46a4119465104254a04e2dfeeeac9c3255f6227704848d5b2
+
+Count = 201
+Adata = d119f300fbd74e754a200ea2c3f9fabc1466d02078c84245db693eef3f5672a6
+Payload = 8b013f5782d5d1af8dbd451a4202866095dac975
+CT = 9cd572b40276f5729e9f30fdacb7e67a5413d44338d48329997c5981d678b5e24a6f01b0
+
+Count = 202
+Adata = d6204303b86acf62d5ab860ca70161288ede56e3cf017c08dca56fd2d6f8f6fe
+Payload = b2b1d82a5523b72ea366a680922ed3a4624536c4
+CT = a56595c9d58093f3b044d3677c9bb3bea38c2bf2a77e3ab68e0a73519591a33ed098b758
+
+Count = 203
+Adata = 8557e22eb4529b43f16b1f8ae47c714ac8a2c827c1408a47704778b4c5b52601
+Payload = f8c4eb4285d3d7744da52775bb44ca436a3154f7
+CT = ef10a6a10570f3a95e87529255f1aa59abf849c1cff6c24251c2fb7b8604dfa10c60ef4a
+
+Count = 204
+Adata = 8c1a4187efbb3d38332f608f2c8bbe64247d9afa2281ced56c586ecb4ab7a85e
+Payload = 6e7fe35fa39c937a0e6b3a8c072e218650f42b8d
+CT = 79abaebc233fb7a71d494f6be99b419c913d36bb6c3c39f915d081d34559179869b32d81
+
+Count = 205
+Adata = a41bb1f256228302cd0548ae2148ff42774d18c2d6d3e38b36bc4938da13bac3
+Payload = 917b467d841850fc6e648f1bc298a7f9f1ee38ca
+CT = 86af0b9e04bb74217d46fafc2c2dc7e3302725fc9389a6a6a74c6eb0e1f87562469f2082
+
+Count = 206
+Adata = b0b024e20c4f75a6dad54c21a9edbce846792e957878b1c8ed2d916c757e2b3c
+Payload = 2b4314fe1a6bfa786b7cfc13fbee861b348efbf6
+CT = 3c97591d9ac8dea5785e89f4155be601f547e6c03bed3a2f5dfdbfcc0d7ac26c88d1962c
+
+Count = 207
+Adata = 42153925c46fc9d5d328312d62f59bb99fdc4ac479a3386d5f88fefd4b32f577
+Payload = e19fa7f83c79920cbff45c41a9dee8fc99e97396
+CT = f64bea1bbcdab6d1acd629a6476b88e658206ea035ea1d99be344fa1467ee91c73bbca67
+
+Count = 208
+Adata = 37ab2a0b7b69942278e21032fc83eba6cdc34f5285a8b711a08da6acd42299fe
+Payload = 53e0475cf492b3d39dad600f5c58eb0bd0021554
+CT = 44340abf7431970e8e8f15e8b2ed8b1111cb08627936ec10a81b36768b606e9a38b2f4c5
+
+Count = 209
+Adata = 4a17522da707b4b2587a0ae367a2cd2831bb593a18ef442a7977eda6de045878
+Payload = c119a383d9a3d4bff4270a1d22076b346db5f61c
+CT = d6cdee605900f062e7057ffaccb20b2eac7ceb2a11575ae03ea8a57bbe4a67c060367b74
+
+[Plen = 21]
+
+Key = c3a0c126cad581012151c25cf85a44472c23f83b6095b6004f4f32cd60ec2db2
+Nonce = 94ab51ce75db8b046d6ab92830
+
+Count = 210
+Adata = 2a243246bfe5b5ab05f51bf5f401af52d5bbaa2549cf57a18e197597fe15dd8c
+Payload = 73b09d18554471309141aa33b687f9248b50fe3154
+CT = b7e8264ca70fd2a4fb76f20a8ad5da3c37f5893fb12abeeaef1187f815ca481ed8ddd3dd37
+
+Count = 211
+Adata = 0595306eb7441622a49800edee0134492d82320707fceba902af2e0c95fe634a
+Payload = b64d00f3a4df754fa4ee6376922fb67ccce0c6209f
+CT = 7215bba75694d6dbced93b4fae7d95647045b12e7accc2b55011dbe92ce7619e0ad48b4ccf
+
+Count = 212
+Adata = bd439dbefec589e120fb4f9825b315bf86523b85c61791cd4da4c8d474ba2714
+Payload = 2b11d1ac74ffe701ec733d32085b1054132726e622
+CT = ef496af886b444958644650b3409334caf8251e8c71e8b1f4d70d8f4c7df4f22847d36b394
+
+Count = 213
+Adata = cfebe1cf82267394065bcecfada6709c6c35a3ac835644f560d4c9a8c1848364
+Payload = a88f22424643a523aa3d7d88f4364f1290f49dd0a2
+CT = 6cd79916b40806b7c00a25b1c8646c0a2c51eade47a85e76a9d07b7b361ca56d53c34cda50
+
+Count = 214
+Adata = 7a37255b682766a0bfecf78e5162528885a339174c2a49325739d2bd8877e64f
+Payload = c81427bc84c6a3cfefd4c4cb210fe82212977e1947
+CT = 0c4c9ce8768d005b85e39cf21d5dcb3aae320917a2fddb010e7508ad03ad287068ecee6020
+
+Count = 215
+Adata = 619f2ae80070e278615466a3fd6c9acb7b510c5679bed7038889c77e78d8bd32
+Payload = 28c4d6de3e2ce51b849b135d9cfd3084f0e3155447
+CT = ec9c6d8acc67468feeac4b64a0af139c4c46625aa2ddea785e6c470c52c4fdf432fd78b66e
+
+Count = 216
+Adata = b2571e56f66a857daffbdc99370ceddd4a7bed3867d600cc797000a3b7b57a9d
+Payload = 4c88151cafef75832bacef43a06e862349d56b67ee
+CT = 88d0ae485da4d617419bb77a9c3ca53bf5701c690b91232cfbd7ffff252498b35274fb2995
+
+Count = 217
+Adata = db409636e3e3bcd606a91aeb7592009896f9ad2c4cc6b7f578e6ad59c0f8fa22
+Payload = 572855e22ce89bc2bcf09cb15a1765d99973449d61
+CT = 9370eeb6dea33856d6c7c488664546c125d633938472b2c50e5e391ad104f9ee33b94f2872
+
+Count = 218
+Adata = 62c89a835721207a182968c516dc8be45774ec846e8dcab9ab8611888f2a76a8
+Payload = 89ce46b3de3afaf2518d419b1a2ac24cabca269a96
+CT = 4d96fde72c7159663bba19a22678e154176f5194732d69c5d6db1b130102af3dae0690673b
+
+Count = 219
+Adata = 33f30ddd83002eea50fd4a8fae39d0980a04160a22ac88b755ac050f1d1f8639
+Payload = edf1682a626e9fbf3d57bb260e0876c6f92ba5b114
+CT = 29a9d37e90253c2b5760e31f325a55de458ed2bff1489903365970c2673c9fd457e1077aad
+
+[Plen = 22]
+
+Key = 9cdebaeee8690b68751070691f49593668a6de12d3a948b38ddbd3f75218b2d4
+Nonce = af1a97d43151f5ea9c48ad36a3
+
+Count = 220
+Adata = f5353fb6bfc8f09d556158132d6cbb97d9045eacdc71f782bcef62d258b1950a
+Payload = 3cbb08f133270e4454bcaaa0f20f6d63c38b6572e766
+CT = 3966930a2ae8fdd8f40e7007f3fde0bd6eb48a46e6d26eef83da9f6384b1a2bda10790dadb3f
+
+Count = 221
+Adata = e3a1555ffe5f34bb43c4a2dae9019b19f1e44a45fb577d495d2a57097612448d
+Payload = 946e86795c332031e2d1ee09d3d4a101fb6800d00911
+CT = 91b31d8245fcd3ad426334aed2262cdf5657efe408a5587bdd120a7d08cd3841cb117af444fb
+
+Count = 222
+Adata = 9c5d43c1a1269cde199509a1eff67cc83a1759b71c9e7a6ee99f76b98c6e23a6
+Payload = b76ce2ab0065ba1c0a754494991c8c452cb416f18ab1
+CT = b2b1795019aa4980aac79e3398ee019b818bf9c58b0545b32f81dcf03e2bcc2aaf62ad366e97
+
+Count = 223
+Adata = b07452a7900a289b91b2771dfdd5108852536659aa259def7b41e38f80bd03ab
+Payload = a3e0d8d0784155bfc45769c52711d4fa68e8bc390c20
+CT = a63d432b618ea62364e5b36226e35924c5d7530d0d94fea17d78533bc9e022dbfb460afdf499
+
+Count = 224
+Adata = 6b30f55c3101540523a92380390f3f84632f42962061b2724cde78ac39809397
+Payload = 6e6a88abbb52a709b47365ad6aa8016fa9a03a9bd834
+CT = 6bb71350a29d549514c1bf0a6b5a8cb1049fd5afd98056defc6dcaeec80b1c639350ab6f1fde
+
+Count = 225
+Adata = 9fc62d14f8b7a6026509275cff80312ff1ade2b5d9c274cb72a506a571439fc1
+Payload = eba1810d537041821121aeff8e0914ac26a550072c8c
+CT = ee7c1af64abfb21eb19374588ffb99728b9abf332d389d37b7251fb8c0ef2b37c36d51219d0f
+
+Count = 226
+Adata = 6b9389cc42113d639fd2b40cbc732ae0dc7c14513b88b36b45a6ea5a06fe4d2b
+Payload = dfc6692cd2442e5ff1f918c8812a27f81d107d16a12f
+CT = da1bf2d7cb8bddc3514bc26f80d8aa26b02f9222a09bd279d9da4437c8a2a252436508134c56
+
+Count = 227
+Adata = db72d98d63fc10acff7dceec0e2691a80ecee50a0e957ad166c77952a50318bd
+Payload = 9ad338cbfd1b52e6ae4178f05e00062274f8b0b25eae
+CT = 9f0ea330e4d4a17a0ef3a2575ff28bfcd9c75f865f1a63943543bc1c5f5991ecc5964a288f79
+
+Count = 228
+Adata = e98b710c47a4d12a73cd8aa2613fc2910c16f4195ea7f15650132493521d19be
+Payload = 9f5a05db89e0e336da066ce81b79ad9be1d0ec4fb7b8
+CT = 9a879e20902f10aa7ab4b64f1a8b20454cef037bb60c0a49ee2b7ceddcbd28abb24b77d5edee
+
+Count = 229
+Adata = 527817316fc48b105f8ab178dd2db1fefa09c50461aa9d8bdf3c03482343bbf9
+Payload = 58f31e5770070a5d4031fb795dc2d298561d3559960d
+CT = 5d2e85ac69c8f9c1e08321de5c305f46fb22da6d97b9b099a68cfa3572d974e03232e09f37fb
+
+[Plen = 23]
+
+Key = d34264a12c35cdd67ac105e2826b071e46f8131d1e325f8e0ae80a6447375135
+Nonce = 3891e308b9f44c5b5a8b59004a
+
+Count = 230
+Adata = 0cda000ed754456a844c9ed61843deea9dadf5e723ea1448057712996d660f8c
+Payload = 79ac1a6a9eca5e07ce635bfd666ef72b16f3f2e140d56c
+CT = 1abcc9b1649deaa0bfa7dcd23508282d9c50ca7fee72486950608d7bcb39dcf03a2cab01587f61
+
+Count = 231
+Adata = 3fb6ddb76809b8e6d703347664ef00a365955124c603900d5c8d4ff476138252
+Payload = 76d12e3c4c5d990bf563c60aa4999e52998d887f97477f
+CT = 15c1fde7b60a2dac84a74125f7ff4154132eb0e139e05b1c4fb40e5c8bc37152a173d4bbb18c3e
+
+Count = 232
+Adata = d9fc295082e8f48569eb073ac1b9566246728fc62ccaab4a5667c472c98b2626
+Payload = a027c28fbe22111fd4c8a226cfe8531c16d7790d561eca
+CT = c33711544475a5b8a50c25099c8e8c1a9c744193f8b9ee019c359008adae3070b5a543ead0effb
+
+Count = 233
+Adata = 7a459aadb48f1a528edae71fcf698b84ed64dc0e18cc23f27ab47eeabeaf833f
+Payload = fa597e37c26c38694abdcf450f9edc529160fa0d651979
+CT = 9949adec383b8cce3b79486a5cf803541bc3c293cbbe5dbd099ab134756b90746762a92a4a9f7f
+
+Count = 234
+Adata = 484207909dec4c35929ebe82fcacf20d2af6d850bd69364ebac9557adeadfbd4
+Payload = 9e4c8aa9b58a8eabc5586892f5541000b43f17d9a051a0
+CT = fd5c59724fdd3a0cb49cefbda632cf063e9c2f470ef684fa4f6adfec85d055310107ba89198afa
+
+Count = 235
+Adata = 88b5448372548e6aab1b262630a28a471d285514703f1bdb10c695850e18fe6d
+Payload = 7d9582cf9e3bb9ee34dce965f56b08e716589486b0641c
+CT = 1e855114646c0d4945186e4aa60dd7e19cfbac181ec338915d23eb2e952afcc89fbddb567d9d75
+
+Count = 236
+Adata = 0e71863c2962244c7d1a28fc755f0c73e5cbd630a8dbdeb38842d7795d830d2e
+Payload = 5a387e7cc22491fc556fe6a0c060b4911d01f0c11f801e
+CT = 3928ada73873255b24ab618f93066b9797a2c85fb1273aaad6c31828314e24198f005955ca8f5e
+
+Count = 237
+Adata = 2aa7a28da38c42fda2e578d9d6340cd8e80b9b32047c3db296d0640d517b0872
+Payload = 87946e910059cbaf48df63b220f397049c65ca10cd1920
+CT = e484bd4afa0e7f08391be49d7395480216c6f28e63be04e531ebbadccfe47182b41904bbfebcfe
+
+Count = 238
+Adata = 3382051c268891da04e6ca73adcead4029f6a1593be4acfe3968e7351a6a2fb5
+Payload = c62f67d208f1c8ffd5d57df9de15ef54f97fbc07d1630a
+CT = a53fb409f2a67c58a411fad68d73305273dc84997fc42e7c582414154236c09ee704cf4a5de411
+
+Count = 239
+Adata = c352828b1920e53bbb60f2ea6a5f15639659e6f3243405c26f6e48628d5519a9
+Payload = 697e73eaaf562d31bdbf7ce9e78c7426fe1c87e421def9
+CT = 0a6ea03155019996cc7bfbc6b4eaab2074bfbf7a8f79dd57c9990029c89d1b37988745fa5737a3
+
+[Plen = 24]
+
+Key = 4ad98dbef0fb2a188b6c49a859c920967214b998435a00b93d931b5acecaf976
+Nonce = 00d772b07788536b688ff2b84a
+
+Count = 240
+Adata = 5f8b1400920891e8057639618183c9c847821c1aae79f2a90d75f114db21e975
+Payload = 9cea3b061e5c402d48497ea4948d75b8af7746d4e570c848
+CT = f28ec535c2d834963c85814ec4173c0b8983dff8dc4a2d4e0f73bfb28ad42aa8f75f549a93594dd4
+
+Count = 241
+Adata = 1ae8108f216defea65d9426da8f8746a3ae408e563d62203063d49bf7e0d6bdf
+Payload = 2b223932fb2fd8433e4b1af9e8234a824569a141f6c96a69
+CT = 4546c70127abacf84a87e513b8b90331639d386dcff38f6f4de907a59c5e4d3f21e1348d7cdf92b6
+
+Count = 242
+Adata = 460f08114b1015fe8b7a9b5dd1b9e6a3d28367c4bd15f29b13c02a8cb9a53968
+Payload = 4d57cbe4a7e780d4ed17267d5ebc91750c2f0209e0444bd2
+CT = 233335d77b63f46f99dbd9970e26d8c62adb9b25d97eaed4ff4239544e2f354d6c6837cd9c23b884
+
+Count = 243
+Adata = 860f4428259d9c5b17698cc95363db6cfee603258582e3a3e8feb886599d4ac4
+Payload = fda8665f87c618646a89c7abdca275fd10c31453ad4b9c99
+CT = 93cc986c5b426cdf1e4538418c383c4e36378d7f9471799f3f6c6f7cc494201069344e2d6d41bd9b
+
+Count = 244
+Adata = 1b43c482f83780c21583f88e5afcf6938edd20f21b74d895161b60c27a6a42f0
+Payload = 98104fd3f3413ad1f57ef4912cb50097dca379a58c47b0d2
+CT = f674b1e02fc54e6a81b20b7b7c2f4924fa57e089b57d55d43787a15352cfceb028202c8730beaa7a
+
+Count = 245
+Adata = b082ccd964617c27a5607b7324faad237ee53acfc18c35502dbf7c1937a9dfcb
+Payload = b46b343e64d2d70e0bd909dbb3f6bedf7e4adc74321be526
+CT = da0fca0db856a3b57f15f631e36cf76c58be45580b210020f3a0ca3da647eb31893e867956097983
+
+Count = 246
+Adata = b8539ba93ef17254ec1d8d62e8f4eae4d41ee1e75345bf90c9cbb26c63bce501
+Payload = 8e12620bb575e6b167b085255b2b5631ff28e04cbef8826d
+CT = e0769c3869f1920a137c7acf0bb11f82d9dc796087c2676be663fbbebbc251b9f1760afa49e89e71
+
+Count = 247
+Adata = b6b09463b5ef5ead1f17f4021693a0d8452e98dcbb8e7590f9fde6394970a6f8
+Payload = 792aaa23b923d1b53173fe19853b9aa402a301d48529873e
+CT = 174e541065a7a50e45bf01f3d5a1d317245798f8bc136238da90cd87e9d9ca5d85430a150e682752
+
+Count = 248
+Adata = 390f6de14d5e1f2f78dbe757c00b89209d0cf8bc48cbbea035779f93de357905
+Payload = ddc5b4e48970ebd72869be6998e9103c014475e8ae6ea29c
+CT = b3a14ad755f49f6c5ca54183c873598f27b0ecc49754479afc0cc4601afb61efa7059cfe49ec9dde
+
+Count = 249
+Adata = 1d75c9e7acb09932db332498d30f82e4009025cb1827047c59a8f97812b568a4
+Payload = d2b66096c475a77648c27235e6972ba8f18761330d3c6adf
+CT = bcd29ea518f1d3cd3c0e8ddfb60d621bd773f81f34068fd9cf7474962c3602dcfcb50039f43e3d6f
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VTT128.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VTT128.rsp
new file mode 100644
index 0000000000..a05492b485
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VTT128.rsp
@@ -0,0 +1,393 @@
+# CAVS 11.0
+# "CCM-VTT" information
+# AES Keylen: 128
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Plen = 24
+Nlen = 13
+
+[Tlen = 4]
+
+Key = 43b1a6bc8d0d22d6d1ca95c18593cca5
+Nonce = 9882578e750b9682c6ca7f8f86
+
+Count = 0
+Adata = 2084f3861c9ad0ccee7c63a7e05aece5db8b34bd8724cc06b4ca99a7f9c4914f
+Payload = a2b381c7d1545c408fe29817a21dc435a154c87256346b05
+CT = cc69ed76985e0ed4c8365a72775e5a19bfccc71aeb116c85a8c74677
+
+Count = 1
+Adata = 79db716e6b0b1627890d378c4560eba7871883d94527be3454dc3c257ea93556
+Payload = 47f4cdd574264f48716d02d616cf27c759fdf787cdcd43b1
+CT = 292ea1643d2c1ddc36b9c0b3c38cb9eb4765f8ef70e84431676e2df1
+
+Count = 2
+Adata = 0d02778f90a164a4f9ada9dc7fd24eeb941069621418ef32c3f9ca6bf6fb2c4a
+Payload = 5eadeaec29561244ede706b6eb30a1c371d74450a105c3f9
+CT = 3077865d605c40d0aa33c4d33e733fef6f4f4b381c20c479eb1321a1
+
+Count = 3
+Adata = 02e5a1306f612bdec098458cff3e691d93f050ba11ba627355dc7029d2cea5ab
+Payload = aac9fb69fed114c62db65090947096a2f5c85c271c6a6d53
+CT = c41397d8b7db46526a6292f54133088eeb50534fa14f6ad3dd8cb4ca
+
+Count = 4
+Adata = 25144e807e389bb0e45b6dc25558caf61a2263869c4d0e4079d07674d7091110
+Payload = fb6e8d38ce38a8c1e710f3a33c682e6dabf055fb33fe75f8
+CT = 95b4e1898732fa55a0c431c6e92bb041b5685a938edb7278b659a844
+
+Count = 5
+Adata = be303c1ed9327ad88dae7cb5930b5a786d4f5477ef9370a9fdb56501964cb8fa
+Payload = 87d81389a6062e8ed501ea964c2fe35b2d3de9fd676c04f7
+CT = e9027f38ef0c7c1a92d528f3996c7d7733a5e695da490377e9e5e005
+
+Count = 6
+Adata = 46dfb8f3e06c3f168e5ac9b341e7710d7b9c6a19b32389eafb58036de0a27756
+Payload = e1bd9095fa9bb811e4054643feea3eac13fb57b43a0502a0
+CT = 8f67fc24b391ea85a3d184262ba9a0800d6358dc87200520c9fc48e0
+
+Count = 7
+Adata = 19eb03c35c352b79e8c32fa40bb9759b0565e04a6c18519ace346e2e9987a250
+Payload = 92f7dc22dcbbe6420aca303bd586e5a24f4c3ed923a6ebe0
+CT = fc2db09395b1b4d64d1ef25e00c57b8e51d431b19e83ec60ac73022c
+
+Count = 8
+Adata = efa6ddd6fb8e4480a0f64414694e5f9e7f2e9b97cbe9cd145b65173d072ab001
+Payload = cecdf831c4044c8fe149e4cd579a1aecf222bf8e9dadba09
+CT = a01794808d0e1e1ba69d26a882d984c0ecbab0e62088bd895dc8d581
+
+Count = 9
+Adata = 1b156d7e2bf7c9a25ad91cff7b0b02161cb78ff9162286b0622fccda2e251c97
+Payload = 7cfb0973ea13dedc33ef6728db90f47559273ea6d3cd4db6
+CT = 122165c2a3198c48743ba54d0ed36a5947bf31ce6ee84a36b941b65b
+
+[Tlen = 6]
+
+Key = 44e89189b815b4649c4e9b38c4275a5a
+Nonce = 374c83e94384061ac01963f88d
+
+Count = 10
+Adata = cd149d17dba7ec50000b8c5390d114697fafb61025301f4e3eaa9f4535718a08
+Payload = 8db6ae1eb959963931d1c5224f29ef50019d2b0db7f5f76f
+CT = df952dce0f843374d33da94c969eff07b7bc2418ca9ee01e32bc2ffa8600
+
+Count = 11
+Adata = 463c65fa7becae5605af80d1feca59075ee88c0abfc72cb463312b3c772ec308
+Payload = bde3fc83287ddd1227bdab4305102c94d885412eb332bf6b
+CT = efc07f539ea0785fc551c72ddca73cc36ea44e3bce59a81a8b847d3a0c98
+
+Count = 12
+Adata = ab153b0a8933f2eb0d721621c86de0cfe100d13e09654824b09d54277912c79d
+Payload = 82176e573c6070faa08d18b5957f119bb1ff51d744b04240
+CT = d034ed878abdd5b7426174db4cc801cc07de5ec239db5531fb4f9d559a8e
+
+Count = 13
+Adata = b22aba8d3e9f4b4bf006e26062de15daf94597731a6009129bfd12957877b1ce
+Payload = bcfc4485eaf225d945146374b737cdf5301c7738ea9f142a
+CT = eedfc7555c2f8094a7f80f1a6e80dda2863d782d97f4035b1e09ff3d6a6c
+
+Count = 14
+Adata = eb80a43c5986deee6925d7c6d53cbdcbe11194843ea133f72d3590d8e8363efa
+Payload = aa182e3ec4fb2f7a905c03582b2ee100ab81a9a311a778bc
+CT = f83badee72268a3772b06f36f299f1571da0a6b66ccc6fcdb60ba1175f1b
+
+Count = 15
+Adata = 3ee186594f110fb788a8bf8aa8be5d4ad52d6e3bd5f406f080d9df0d7553a851
+Payload = 8ad6db8216af16bfda3261a220d078cc98c8ad134e4a80ca
+CT = d8f55852a072b3f238de0dccf967689b2ee9a206332197bb4a75860f3dd6
+
+Count = 16
+Adata = d36fc18b5b12662ff5f6ea55af7c7a82d25d386220e399a85a590b1505c0dcd5
+Payload = a65d24bd1ab92d8d294d654423412860e113c976f12ed76b
+CT = f47ea76dac6488c0cba1092afaf638375732c6638c45c01a00cf106d70a4
+
+Count = 17
+Adata = f0028503e7cd54474c56dc8b2416fe41f416eed73c63ddd141bdd51a0f8fe49c
+Payload = 6e9dc61dd9cf19a6eebc10c9b51c13970636de2c9ea33592
+CT = 3cbe45cd6f12bceb0c507ca76cab03c0b017d139e3c822e3c0193a87ddfb
+
+Count = 18
+Adata = 9a58a226a578bda012dbd7d04b11c879179aaaa36c6145418586cb103360c6c2
+Payload = b526896c11e514b5b4c26351859e2a33800fefd6fd9e6d1a
+CT = e7050abca738b1f8562e0f3f5c293a64362ee0c380f57a6b444d9b63ffab
+
+Count = 19
+Adata = c015fb08540755a8a8adc387d60553478667158964202eb2d25e28efd94c8c76
+Payload = 88907b639f3fd07f40bf6b9b6334b11b2852557975721bf3
+CT = dab3f8b329e27532a25307f5ba83a14c9e735a6c08190c82c339ba21fcf7
+
+[Tlen = 8]
+
+Key = 368f35a1f80eaaacd6bb136609389727
+Nonce = 842a8445847502ea77363a16b6
+
+Count = 20
+Adata = 34396dfcfa6f742aea7040976bd596497a7a6fa4fb85ee8e4ca394d02095b7bf
+Payload = 1cccd55825316a94c5979e049310d1d717cdfb7624289dac
+CT = 1a58094f0e8c6035a5584bfa8d1009c5f78fd2ca487ff222f6d1d897d6051618
+
+Count = 21
+Adata = 25865c1b89f1973bfa680d8458df35a56993a7e81e407e061794004068e481ab
+Payload = 36004342dd74e7966692a848b2c11e1fc311eac9d9cef616
+CT = 30949f55f6c9ed37065d7db6acc1c60d2353c375b5999998ceca422687f41550
+
+Count = 22
+Adata = e6209480da9e49172ba58a9048f2f1b0349030e8e7a79dcdf295eecd613f401a
+Payload = e81f4fb360bcae372d8be3f32655a29bc10a2f31876173cc
+CT = ee8b93a44b01a4964d44360d38557a892148068deb361c42d2b981fc741f2591
+
+Count = 23
+Adata = 112c969882e685b4ae1ee6b67f680e6a1d9d840e627d12118f991c1a3d71314c
+Payload = 27d6443e729d35d7a0690fcb7fe0b20892875f60b5d8763a
+CT = 2142982959203f76c0a6da3561e06a1a72c576dcd98f19b4a1fd47cd41fcf013
+
+Count = 24
+Adata = 73ef62870c50faca5d4e6c6ec45fa7b54bf79ed229fcf1fc8c79c9c09596039b
+Payload = 6c17ad5496dfccde8b877630e1e582dab52aaabe385a321f
+CT = 6a837143bd62c67feb48a3ceffe55ac855688302540d5d9143eb86ffa6958d71
+
+Count = 25
+Adata = b537f0f2981405f6069b401966656461b3516a32d181777121a60cea537e7cef
+Payload = dc4a1e39561f14321238272adff8b74a4e770c0a0c864a52
+CT = dadec22e7da21e9372f7f2d4c1f86f58ae3525b660d125dc1dfc38975c948d29
+
+Count = 26
+Adata = 96bd747ccdcd5fa6cd920514a2f38203e82ee9c7ec6e88080e9f6e2a6a812b0d
+Payload = c51958d7d7d39906b14d4ebb574db881355ec3e6b41838dd
+CT = c38d84c0fc6e93a7d1829b45494d6093d51cea5ad84f575320a48ee3845d9e7a
+
+Count = 27
+Adata = 690d6a2377314fc2f7dd06ae401e3585c79faf648a7af358ae4ef615669222eb
+Payload = 9eaf24f84e8818e286410de321d65ffbf25d1a14073c60da
+CT = 983bf8ef65351243e68ed81d3fd687e9121f33a86b6b0f54884188f946c9a317
+
+Count = 28
+Adata = 748dc83299a43033239ad2fef2dc3d72b76a38ca127607cef72de94a56d5e5c0
+Payload = 71c8eb0079559a306e236c49b7ce1b6cfe26c7888733eb7e
+CT = 775c371752e890910eecb9b7a9cec37e1e64ee34eb6484f00ae2dd33327f8459
+
+Count = 29
+Adata = 35a49535684637f67573fb0b4fdc1bdd8a57650a1d8f29b866fa552a6e0cdf91
+Payload = f09569906381138cc49e3fc2384c5d33c34abd3d617c487b
+CT = f601b587483c192da451ea3c264c8521230894810d2b27f5c50821a48b93d0ca
+
+[Tlen = 10]
+
+Key = 996a09a652fa6c82eae8be7886d7e75e
+Nonce = a8b3eb68f205a46d8f632c3367
+
+Count = 30
+Adata = c71620d0477c8137b77ec5c72ced4df3a1e987fd9af6b5b10853f0526d876cd5
+Payload = 84cdd7380f47524b86168ed95386faa402831f22045183d0
+CT = a7fbf9dd1b099ed3acf6bcbd0b6f7cae57bee99f9d084f826d86e69c07f053d1a607
+
+Count = 31
+Adata = 7b40b3443d00a0348a060db109e8882157612c43084ac5c3e9c5350c88bc165d
+Payload = 7ebb051741145a3bad87131553375c6debcbcecee9b79ee4
+CT = 5d8d2bf2555a96a3876721710bdeda67bef6387370ee52b694af9359a96acfb31a4a
+
+Count = 32
+Adata = 5cab3b84687070956916c11cab0ceea61adb6ea1f909be63d73df96fbfa3a9f4
+Payload = 35a29c1bcbe2182f34fe05f09dfb9ac4a496f95819ef11ec
+CT = 1694b2fedfacd4b71e1e3794c5121ccef1ab0fe580b6ddbe36d3920d1012bf093a5c
+
+Count = 33
+Adata = 6d440b44a069a6967f8750c3b4f8118798fe32d2eaa696ccc7f24e16d6366753
+Payload = a0e21d971876ae4048a61b43a3ac07c685005a20bccbe6ec
+CT = 83d433720c3862d862462927fb4581ccd03dac9d25922abec23025c1776811647f99
+
+Count = 34
+Adata = 06904325b8c6fc2b5a0412ba8062cd48d3af51beacb5ced9e2bdf8d0e056b738
+Payload = 8d333ed7d4b208e794e1673f6df692caee4e3a00fc49115e
+CT = ae051032c0fcc47fbe01555b351f14c0bb73ccbd6510dd0c6efeeaed29e65f1a8908
+
+Count = 35
+Adata = e5049e1c32f0a000024882e4fca9b77adb6c87fdbad96d0c8e97bdb8f46789dc
+Payload = 4189351b5caea375a0299e81c621bf434b6b97da68ad44be
+CT = 62bf1bfe48e06fed8ac9ace59ec839491e566167f1f488ec70d42f84a5411dfa43f9
+
+Count = 36
+Adata = 6f0be1905d1b5b607574ad93a1e7b4a536020fc6798acae862253916a0562707
+Payload = 5a063a24410b3d265c9a32a027cb2382a52bb8e35db15b98
+CT = 793014c15545f1be767a00c47f22a588f0164e5ec4e897caadd2256112d1f7d04934
+
+Count = 37
+Adata = a90f9f55ef22f5e6c542ed3573a9ab67d9c3b6775587fc2be70817479347ce00
+Payload = 0b72cb09a444be2d7b34cf9997fc5b885851d7e6092008b4
+CT = 2844e5ecb00a72b551d4fdfdcf15dd820d6c215b9079c4e6e187f5f37e8a5029ca4e
+
+Count = 38
+Adata = 4dd64fd7d8b571704cddabef854c51691ace4c30de74bfecad42eaed65284ebf
+Payload = ce2d996c9a4cf85edb888822773e03179feeb9e4b0928d6a
+CT = ed1bb7898e0234c6f168ba462fd7851dcad34f5929cb4138fbbb92009435f9ab6691
+
+Count = 39
+Adata = 75f4031d2e5098a9ea3eaa20c2423fbc1705ea18289efb96e311f3fefc153b67
+Payload = aa182e3ec4fb2f7a905c03582b2ee100ab81a9a311a778bc
+CT = 892e00dbd0b5e3e2babc313c73c7670afebc5f1e88feb4ee3cae38db7cc9d577b0ed
+
+[Tlen = 12]
+
+Key = 3ee186594f110fb788a8bf8aa8be5d4a
+Nonce = 44f705d52acf27b7f17196aa9b
+
+Count = 40
+Adata = 2c16724296ff85e079627be3053ea95adf35722c21886baba343bd6c79b5cb57
+Payload = d71864877f2578db092daba2d6a1f9f4698a9c356c7830a1
+CT = b4dd74e7a0cc51aea45dfb401a41d5822c96901a83247ea0d6965f5aa6e31302a9cc2b36
+
+Count = 41
+Adata = 78230f73f9c0150f630eca4cd679818551d449db82e665d8dc25fc53ebc11293
+Payload = 048ba28abb191ded5449dfe9dc7d19f9b132a2a9fd779aab
+CT = 674eb2ea64f03498f9398f0b109d358ff42eae86122bd4aa6356e2548a22e7cbee3b89d4
+
+Count = 42
+Adata = c09191a7d2fca98fca486f8843f275a78d57b8c9a6d330d5652ba641f928c6d8
+Payload = adf51386b3cc133ea9d18e679fe4bbf10ea780b7bed57d6a
+CT = ce3003e66c253a4b04a1de85530497874bbb8c985189336b35516f170a2aada38d1d94eb
+
+Count = 43
+Adata = ea46cc1a7ba5afaa6176f8dedc049283d2ac38fa74ef37ea1fc575328033b222
+Payload = f660a28551416b2f8e21466ba99daee280a91740d98219cf
+CT = 95a5b2e58ea8425a23511689657d8294c5b51b6f36de57ceea2d3237788a02ff15258351
+
+Count = 44
+Adata = 3093b74eb088bdd59999629d59509920938f4feabbd29df8e0b44364c8b55244
+Payload = b9a96f0e4c6dea8861e888bdd693b300017718da958aaa00
+CT = da6c7f6e9384c3fdcc98d85f1a739f76446b14f57ad6e40165fb6719509987930d350890
+
+Count = 45
+Adata = 5580672e52aacb9d714a34c31c33fc221e13e8f90849adbad3f6b3bec8571838
+Payload = cc4acdbd34ec9b7cbc3e23a53e0627c2a7c63206f3e0298d
+CT = af8fddddeb05b209114e7347f2e60bb4e2da3e291cbc678c8ecdf173444c334cfda5b22b
+
+Count = 46
+Adata = c7acf1b17609dc336df1006ffac6497777cdfd497c8c91525377c130accce0bc
+Payload = ed75d28be4794ad81bbc0f26a11c5466f23c0270d2d7b8f8
+CT = 8eb0c2eb3b9063adb6cc5fc46dfc7810b7200e5f3d8bf6f92221c860022d92b0f961c3e6
+
+Count = 47
+Adata = ac1adca686e1d129142c49f26b52941d037d8052b8a27d5215b7ffcfd2202481
+Payload = b8234b8bd34d9c6ceffebbb85722764e7d37e43c495256e0
+CT = dbe65beb0ca4b519428eeb5a9bc25a38382be813a60e18e11c73d6a695afc704228ed7a1
+
+Count = 48
+Adata = 472bf7946bce1d3c6f168f4475e5bb3a67d5df2fa01e64bce8bb6e43a6c8b177
+Payload = 790134a8db83f2da35dde832c3ae45ec62aff0274495d6e7
+CT = 1ac424c8046adbaf98adb8d00f4e699a27b3fc08abc998e6bf1e81950e44c63183a679d7
+
+Count = 49
+Adata = 1340ac7ff04dd7450afc13f8fa52df6d526c744a2dc2f76b0aadf284da270508
+Payload = 21ea2f778cf37aa02fea30e855c20a77909548da4ee7eb61
+CT = 422f3f17531a53d5829a600a99222601d58944f5a1bba560c2c3a1876e49a47a9b44b737
+
+[Tlen = 14]
+
+Key = 7b2d52a5186d912cf6b83ace7740ceda
+Nonce = f47be3a2b019d1beededf5b80c
+
+Count = 50
+Adata = 76cf3522aff97a44b4edd0eef3b81e3ab3cd1ccc93a767a133afd508315f05ed
+Payload = ea384b081f60bb450808e0c20dc2914ae14a320612c3e1e8
+CT = 79070f33114a980dfd48215051e224dfd01471ac293242afddb36e37da1ee8a88a77d7f12cc6
+
+Count = 51
+Adata = 41aa11ec55980609482575b97eee172590ff545d5798fd4246313da3fdbbcda6
+Payload = 811d54bad842a8b92b96fc03b4fff8b5f1939fd3a49876dc
+CT = 12221081d6688bf1ded63d91e8df4d20c0cddc799f69d59ba850b0116f3269b5e44e57de7166
+
+Count = 52
+Adata = dedfb02e93b975270f50cffa3351c85975a7b21fd89bbb921c40c1e5310e6702
+Payload = 8bbf87b490020b863fc596a8d169d79c0cb3506e1f1f5aa2
+CT = 1880c38f9e2828ceca85573a8d4962093ded13c424eef9e50f053627bd0c90714820c4fbe5ec
+
+Count = 53
+Adata = a727ed3d13331ee6a224ae4b73f0ccb04b997fcf88533a1f57e9b055275de92b
+Payload = 7294ae94358669f2ada4b64c125b248df7fe86c6715e3b6a
+CT = e1abeaaf3bac4aba58e477de4e7b9118c6a0c56c4aaf982df865a77d66f1232cd7e36af3d1be
+
+Count = 54
+Adata = 6704dc39a259152d2dc3f08b8799ffecf4e1bc38ce5b77c71cc293c6664ef2dd
+Payload = 48033c46389f6221fb9cdda1ecb8fc25fdec6afe4eaa5fd0
+CT = db3c787d36b541690edc1c33b09849b0ccb22954755bfc97e1fba154f6b166549d0d6bb9b573
+
+Count = 55
+Adata = 6cba004dfb5e5d9e1433bf1223039ae1d2df89cd2db68f550327a22c8f946ae9
+Payload = 01acc909b7d3bb3b3e1f72845f05238d2e1d9162976d3bd2
+CT = 92938d32b9f99873cb5fb316032596181f43d2c8ac9c9895c485e9e28ae33959f8acbb640fbf
+
+Count = 56
+Adata = dd5799710523aa1da0b1209fab1e6f2ed177444ed3880d462deebbd5f774c621
+Payload = 3706def87786e49baec2d13407865286cb4e05908cac430f
+CT = a4399ac379acc7d35b8210a65ba6e713fa10463ab75de0488ef976fa9bda9544ed94ef266ed2
+
+Count = 57
+Adata = 5d7505ff863d218f6822150455b977ad2df3c02be094f6832ee68872b1ae7a01
+Payload = f38d4b225d9b80a0c5fadc61476aef419ad3d18937d8661f
+CT = 60b20f1953b1a3e830ba1df31b4a5ad4ab8d92230c29c5580caadf1dbd07515e3bfb6992e2cd
+
+Count = 58
+Adata = 796b62c7abf797de7f6bad8bf5d549688ccb7ada62fff9469c14b08208b07a8a
+Payload = 993bb3a85f67f6c1a809d8094ee80e2ad9b694063af2fdb3
+CT = 0a04f793514dd5895d49199b12c8bbbfe8e8d7ac01035ef4733ad369e4a067b7976c9d6d0456
+
+Count = 59
+Adata = 84fd27557aeb283282366083e3586f3a59691ccd0d43ec81c4e5f4e85715eba8
+Payload = 1286506be19fb865a288b09dda8af4323567cd9a66e08643
+CT = 81b91450efb59b2d57c8710f86aa41a704398e305d11250439860d66891f32ce0a09788f5899
+
+[Tlen = 16]
+
+Key = 4189351b5caea375a0299e81c621bf43
+Nonce = 48c0906930561e0ab0ef4cd972
+
+Count = 60
+Adata = 40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951
+Payload = 4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef
+CT = 26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6d80e8bf80f4a46cab06d4313f0db9be9
+
+Count = 61
+Adata = ac8dde7ba60e4ba226eecb0a789b1c4673ddffe8f371464389f52f767004f0a6
+Payload = 7c0889854658d3408c5d8043aad2f4ae4a89449a36f8a3b8
+CT = 1ff831cfc51ae62ea29b0791941972254cd0b846294d7be196363d27b9e11fee55111b273399f5ff
+
+Count = 62
+Adata = 8f2777ec4930f7e349c3bd4830120cebdd896db9d8a33d34f101672024bd737f
+Payload = c641cf589020b94026ae5ac0bfdc29822cc13862a54614c7
+CT = a5b1771213628c2e0868dd128117af092a98c4bebaf3cc9ef741e15ad9b2f5ab864ad94d3f9de562
+
+Count = 63
+Adata = a87426f83bf91bd3c3556bf859cd97f51c92609879f02dbca9c7ae637a3fbf05
+Payload = d204994c128d6204ef2939c22572daa56c12df2e4d3e33e9
+CT = b1f4210691cf576ac1efbe101bb95c2e6a4b23f2528bebb0652a083ea1b43b7da026692c7aa796d7
+
+Count = 64
+Adata = 7ff9ca86f820e4d57995d450611009ffaa726e6fbe4ce1558ca1e775daed9ec2
+Payload = aff9bb0238689255f54cd5fdebe6d3dff5f5604ab8d77038
+CT = cc090348bb2aa73bdb8a522fd52d5554f3ac9c96a762a861057e0faa2711cfa1e3da5499f9a1ee0b
+
+Count = 65
+Adata = faa6b7f8c6e076b5e5b981119b7ec2e0b9c73da4064f9704e303d5792f59674b
+Payload = 95d2cf30b6174b17278ad9f44079a2199082dab917f89763
+CT = f622777a35557e79094c5e267eb2249296db2665084d4f3a90b39704d8913391ebd3424117b93b68
+
+Count = 66
+Adata = b553e65640c1ad0d2ff748c5b2af9d970c74131cff4fa73384a33dfec056332e
+Payload = aaa53244520e157c4890a0e62100a12daa84f9be710242d7
+CT = c9558a0ed14c2012665627341fcb27a6acdd05626eb79a8ed0a6cb58733be0a3b608afdf78eaa70c
+
+Count = 67
+Adata = a9be73668b94bc6a212744522a0adff03d49fd495daadaf6cd32f4ca25ebc2b5
+Payload = 1066b96c3c44301073717520ea5c07adbac7759b88d52154
+CT = 73960126bf06057e5db7f2f2d4978126bc9e89479760f90daf20ce64e6a821e39ca96aded43f0875
+
+Count = 68
+Adata = 8b516c47e6630b2c31d8eefd8ba152d7315582a3f4d3f0e0eb2984a365b434db
+Payload = b5969813d0f892febe64ed52d429cc737b5df8d5e0c63207
+CT = d666205953baa79090a26a80eae24af87d040409ff73ea5ecf4699d23f5fc6742bffebbd16858f6e
+
+Count = 69
+Adata = 8ad3e84edbe7d9305848746cbd0f769bce47d5ae4609513210e54cd3b984db1f
+Payload = daa90a2de3937e7942e6711f165a89b9e077fe322cab597d
+CT = b959b26760d14b176c20f6cd28910f32e62e02ee331e81243713601bb16dc91af84ac19ebd43a1ec
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VTT192.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VTT192.rsp
new file mode 100644
index 0000000000..75b0c429f6
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VTT192.rsp
@@ -0,0 +1,393 @@
+# CAVS 11.0
+# "CCM-VTT" information
+# AES Keylen: 192
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Plen = 24
+Nlen = 13
+
+[Tlen = 4]
+
+Key = 11fd45743d946e6d37341fec49947e8c70482494a8f07fcc
+Nonce = c6aeebcb146cfafaae66f78aab
+
+Count = 0
+Adata = 7dc8c52144a7cb65b3e5a846e8fd7eae37bf6996c299b56e49144ebf43a1770f
+Payload = ee7e6075ba52846de5d6254959a18affc4faf59c8ef63489
+CT = 137d9da59baf5cbfd46620c5f298fc766de10ac68e774edf1f2c5bad
+
+Count = 1
+Adata = edb8834974b02fc9ab29b4b3c49683426124e729b44e43cde4ab9bb1b30b5531
+Payload = d05410f42d4759f8cab3884785cf8f60ecbf902e525b92e8
+CT = 2d57ed240cba812afb038dcb2ef6f9e945a46f7452dae8be24285996
+
+Count = 2
+Adata = 8baf194e81e47a6ca82ca51b488339d014a0a494007793aa5201ac72fc3f808d
+Payload = db3022ef4cd68ae22b501599448ffe2dda15cfd2e259315c
+CT = 2633df3f6d2b52301ae01015efb688a4730e3088e2d84b0a6c510570
+
+Count = 3
+Adata = c0b55acc7fbfa9d9af6e1f32b6626a1cd89b1c32513b5b50a18ddab028470953
+Payload = 7f0745bea62479c0080ecec52e37c1e32d72a6b3864da44a
+CT = 8204b86e87d9a11239becb49850eb76a846959e986ccde1cb418cfd2
+
+Count = 4
+Adata = 9dc672e64c468242ddeec318c71f9b8cbaa14639eba3c861acfc26463fb7d5d7
+Payload = 263dbe1bd5e9d9b29b316fe36ec8bb10f64543b4921c01f6
+CT = db3e43cbf4140160aa816a6fc5f1cd995f5ebcee929d7ba03e5b5794
+
+Count = 5
+Adata = 1798286c37c1504fc0d7402681f6f70711ef506dcc3e29d0183dc578ed976f92
+Payload = 22dbba2b1a39074ddac736767ebdedc37e4208b233e03b34
+CT = dfd847fb3bc4df9feb7733fad5849b4ad759f7e833614162f63b4847
+
+Count = 6
+Adata = ed2898d0bcb34eebf98b5279bc3e8a20214321a7e23bc55b2b7613b1a9b94f2c
+Payload = f0f1235ee88d04de3f3d1489ec6b28b285a6a4fbb344911a
+CT = 0df2de8ec970dc0c0e8d110547525e3b2cbd5ba1b3c5eb4c7ab29a40
+
+Count = 7
+Adata = 50c4a285d6a4e64efceb288b82e7c8277307cf1eaa4b8b9294f97a1c38926a60
+Payload = 0e50aa6a3079c0b8d61e51c3bd93b592a03719acb9f0252e
+CT = f35357ba1184186ae7ae544f16aac31b092ce6f6b9715f7868f40ff6
+
+Count = 8
+Adata = b48a16fb9a065d3aeb2bdf1860e4b0f1348c8f13cd00b1729ff8c19e4e9724f3
+Payload = 82f39f5207afcfd677a7544579f2b888a1eabdee4e835924
+CT = 7ff0628226521704461751c9d2cbce0108f142b44e022372ceeff92c
+
+Count = 9
+Adata = d92b80544f29aba52496e2c9a0aa4adeb89820be321cfd2f0a53585a15d04c7f
+Payload = bc3b08eec6506d1497572f901f0e5f3e9854b40b0f992d08
+CT = 4138f53ee7adb5c6a6e72a1cb43729b7314f4b510f18575e619c1124
+
+[Tlen = 6]
+
+Key = 146a163bbf10746e7c1201546ba46de769be23f9d7cc2c80
+Nonce = f5827e51707d8d64bb522985bb
+
+Count = 10
+Adata = 599b12ebd3347a5ad098772c44c49eed954ec27c3ba6206d899ddaabca23a762
+Payload = 473b6600559aefb67f7976f0a5cc744fb456efd86f615648
+CT = 26d2be30e171439d54a0fec291c6024d1de09d61b44f53258ba1360406f9
+
+Count = 11
+Adata = 3a8423feb661db30542dc3cfb596280429397f80755a4bc8d4d941d03b61aacc
+Payload = 7edfce3dedd65a8592aec2bfc7a751e2360f3137941fc960
+CT = 1f36160d593df6aeb9774a8df3ad27e09fb9438e4f31cc0db5e5938e8c75
+
+Count = 12
+Adata = 0dc79993047fd6e7260aac4d847fdb4d16483f28b13b5f17330744d401d2875b
+Payload = a9fb3ebba43c273cacbf0f7187030c69172f31382e9e059b
+CT = c812e68b10d78b1787668743b3097a6bbe994381f5b000f694f534b76f0b
+
+Count = 13
+Adata = 6546d9a90e0e763679d5469a1bcffcc4f18f35f50c7714d14c7329b76ce7984e
+Payload = a7573e5b7dd7f4ce9e4480f603c14145a27f7c7a9246a3cf
+CT = c6bee66bc93c58e5b59d08c437cb37470bc90ec34968a6a23c6c025faa1b
+
+Count = 14
+Adata = 7f398ff0d47e2c0fccd8a16cc9e79b4813abac42e346fa33ba033956f798d6ac
+Payload = 84370557e0bbf74fd0a4533185adfe202d9fa9d622bba72f
+CT = e5dedd6754505b64fb7ddb03b1a788228429db6ff995a242ae0f88d836be
+
+Count = 15
+Adata = d0f46fb37d516cc957aaefd3be2a8bede885330a8edb96f3e5e0ab8cd03a8c59
+Payload = 029575400bd3f2621c7d9ca9b6a09ea6f776968b19dc3f3e
+CT = 637cad70bf385e4937a4149b82aae8a45ec0e432c2f23a5366d09f64b4c2
+
+Count = 16
+Adata = 4abaa4260c864572e12553c5aabfe62e4e7038490d4ba160119fc5d646780cc6
+Payload = 448be3821d94452425fae41a06457260a2666e890fa94954
+CT = 25623bb2a97fe90f0e236c28324f04620bd01c30d4874c39677fd479c852
+
+Count = 17
+Adata = 686e0578eadd19583291a01e11a29fc95a2c156da100dd85429ad58ba65440c6
+Payload = aebfe3e15a876412ec9df714f1afa898e69004c1ef25732b
+CT = cf563bd1ee6cc839c7447f26c5a5de9a4f267678340b7646bbc332573774
+
+Count = 18
+Adata = e3d29f970667286a81586aa02bb490c72d8bb3a308eafec5da0d105fddd1a157
+Payload = 08b2ce5f7296016e86d02f8c7952d746703ee4f0429b8df3
+CT = 695b166fc67dad45ad09a7be4d58a144d988964999b5889e33171a8ccec1
+
+Count = 19
+Adata = 9e2ea8eb7f56087ee506925648661eeefffd643a056cd4f4fc5cc23172b5c637
+Payload = e73d7d23736db17cca816ab2440062a8051177d47feb514e
+CT = 86d4a513c7861d57e158e280700a14aaaca7056da4c55423bc8299cc9f95
+
+[Tlen = 8]
+
+Key = bdf277af2226f03ec1a0ba7a8532ade6aea9b3d519fe2d38
+Nonce = cc3c596be884e7caed503315c0
+
+Count = 20
+Adata = 4d6546167b3ed55f01c62bd384e02e1039c0d67ef7abe33291fecb136272f73b
+Payload = 0ff89eff92a530b66684cd75a39481e7e069a7d05e89b692
+CT = 6ef66a52c866bd5df20ec5096de92167ad83cab0e095ad0c778a299f1224f10c
+
+Count = 21
+Adata = 95722ef5e0cf9f482e4c359f1fd6b9efe2b6e0630413c40285b8958c31188ca4
+Payload = b1ea02e3721e44c327443fcf4b424cce19afbb9e8cf06b76
+CT = d0e4f64e28ddc928b3ce37b3853fec4e5445d6fe32ec70e8a5c2c6b097a04d50
+
+Count = 22
+Adata = f7b76a2a4fe0a1b07a6b193b4600aec02360eb35853d88fe8a4f31a8dda48ad9
+Payload = c1f9c7b2e0ba712b4d2b32e4693b145228213999703767fc
+CT = a0f7331fba79fcc0d9a13a98a746b4d265cb54f9ce2b7c62f62e74c2312f9243
+
+Count = 23
+Adata = 406f39cb77b8d8c63f7797d184b6ebde819af7d48de5003538c022fe96b841ce
+Payload = ebf3a717546199c6f6b14efe8888613ca7e075e8290b277c
+CT = 8afd53ba0ea2142d623b468246f5c1bcea0a188897173ce2f1cb228ffd2ff8e6
+
+Count = 24
+Adata = 3dd3110703a95b05b9b9cff92ab7244e6c6dcb4509522c305d5d33e03f1b0b60
+Payload = a0e317b790870e6703e6077dfb8ea327c12e29a17107284c
+CT = c1ede31aca44838c976c0f0135f303a78cc444c1cf1b33d21f38e2d280a8f3ff
+
+Count = 25
+Adata = 044ae4064156b6ebc0921cb2c3c607976339f824d4dc6902eac66910dce086b2
+Payload = 8a16990690717dc16eea24da39878a2ee7c1579976e5b173
+CT = eb186dabcab2f02afa602ca6f7fa2aaeaa2b3af9c8f9aaedafbcf46b4e75bb11
+
+Count = 26
+Adata = 5479cc7f92460ff7a3e500f76d70e3036c44300005058b5517e3f64ad41b46b3
+Payload = 1e7e51f0fa9a33ed618c26f5e37754df0f7de7778882c26c
+CT = 7f70a55da059be06f5062e892d0af45f42978a17369ed9f2fac11c84d08e918e
+
+Count = 27
+Adata = f950e96d65a55efb3be3a55daffb421afad1d5625e3440a16414085469effe1c
+Payload = 3ef1f4c438dce131990ba536d7a6166022ae7de4a436f87c
+CT = 5fff0069621f6cda0d81ad4a19dbb6e06f4410841a2ae3e2b50cb871173d9bb8
+
+Count = 28
+Adata = 52742be3969830ba9c2bce26c98c2fb44ac881ec55c85627b2c94ba17b0de8cf
+Payload = 3c7b4a68dfb766e24739f14932563fb81f24591f0e31e895
+CT = 5d75bec58574eb09d3b3f935fc2b9f3852ce347fb02df30b4ce29627efbc3523
+
+Count = 29
+Adata = e16e5dc034719e5d815f937b672cf34d5d420a3945c8f73645241779d2bec150
+Payload = 03038acd2d8351e4e5aa308e554abfcd0d0334d8f864ec60
+CT = 620d7e607740dc0f712038f29b371f4d40e959b84678f7fe095168ed90827db2
+
+[Tlen = 10]
+
+Key = 62f8eba1c2c5f66215493a6fa6ae007aae5be92f7880336a
+Nonce = 15769753f503aa324f4b0e8ee0
+
+Count = 30
+Adata = 1bc05440ee3e34d0f25e90ca1ecbb555d0fb92b311621d171be6f2b719923d23
+Payload = f5522e3405d9b77cbf3257db2b9675e618e8744a0ee03f0f
+CT = b9103942dbbb93e15086751c9bb0a3d33112b55f95b7d4f32ff0bb90a8879812683f
+
+Count = 31
+Adata = 25c32770a299020d8500d8a4b5d7621e4379dbd6ef34a9aceefd4055ea6144f5
+Payload = c8bf145fcffbafd6cd1a4c5b6cedfe008aacb2528ef51c80
+CT = 84fd032911998b4b22ae6e9cdccb2835a356734715a2f77c6982d0796e1bd1cc9879
+
+Count = 32
+Adata = cba0e0140f094e17652ea6f64c26f69dd9429bfefb41aaf104c38f3f6501f4f9
+Payload = f8813985f59bf284bd3882e899ca9b67fb496f3eb78d7ebe
+CT = b4c32ef32bf9d619528ca02f29ec4d52d2b3ae2b2cda9542fe08edf50e05d4d85faf
+
+Count = 33
+Adata = a846d0f56eb963b308ab8f697adca378ab6ccf9f739edcd7f5db197b2ffa99ac
+Payload = 72862d82d940748d54369e3143192453069b80d10f32e569
+CT = 3ec43af407225010bb82bcf6f33ff2662f6141c494650e95800ae2523c5f161ed96f
+
+Count = 34
+Adata = 1dc5f6d6103ed2ae7f4ecd7b1bae4d5b9c0adef9100527b1737e1cf57f1175ef
+Payload = 46f2199305ff4e1f21a89d96d3902c54939f52278ba7aa0e
+CT = 0ab00ee5db9d6a82ce1cbf5163b6fa61ba65933210f041f234a29547607846bc9834
+
+Count = 35
+Adata = 8c28bcb9c31191c347dd64e552af5aff500e6e6f39e866351dd7065501a2837d
+Payload = 18c38c41a4e70c3f7362249ea329059b0e026bce7ae976b0
+CT = 54819b377a8528a29cd60659130fd3ae27f8aadbe1be9d4c95f73957e86152df56bd
+
+Count = 36
+Adata = 1081afd5bf9f1a87169973ebdca85c2b69598154673d7ca9d6e2f63d52030fc1
+Payload = c89e388dd6124c41251e7422b420a71e4618f5cf9f0a63fc
+CT = 84dc2ffb087068dccaaa56e50406712b6fe234da045d8800b2b028cd785f4f964069
+
+Count = 37
+Adata = 079bc543c966734fa70814139ba8051271ee1c4f701579013c427f8efb141db7
+Payload = 68449bc3f6c8bd8f3a46a8e147522d979948c88ca791d204
+CT = 24068cb528aa9912d5f28a26f774fba2b0b209993cc639f8fd3ef357e5e69f504c95
+
+Count = 38
+Adata = e7094697b78d20174ec3c97a48abcf67c2ba6790b4db5fda82b454becd2a25ef
+Payload = 330088153204c3d5de7744047b60887c8c044e4eeaae4bab
+CT = 7f429f63ec66e74831c366c3cb465e49a5fe8f5b71f9a057e092ed15d1a074306a9e
+
+Count = 39
+Adata = f8d64ce2aa66e67de0f2fa584dec858983333b0570882ab628419bcee541395a
+Payload = 893c5c45db989bd39485caa05ed700bb17c526b426edf4ba
+CT = c57e4b3305fabf4e7b31e867eef1d68e3e3fe7a1bdba1f46afaad39e9183b2970027
+
+[Tlen = 12]
+
+Key = 5a5667197f46b8027980d0a3166c0a419713d4df0629a860
+Nonce = 6236b01079d180fce156fbaab4
+
+Count = 40
+Adata = 29bdf65b29394d363d5243d4249bad087520f8d733a763daa1356be458d487e5
+Payload = d0e4024d6e33daafc011fe463545ed20f172872f6f33cefa
+CT = 479f3d408bfa00d1cd1c8bf11a167ce7ae4bcdb011f04e38733013b8ebe5e92b1917640c
+
+Count = 41
+Adata = 314f069dd4ac5aa3fdc2a74e83daa1d5d18330cd3b90684a9260bb48f5626d49
+Payload = 9ebd994a9af0cb94552ffd749fdd97f75a1ebd0ad3de3a9a
+CT = 09c6a6477f3911ea582288c3b08e06300527f795ad1dba58425a1bad4381dc84fee903e3
+
+Count = 42
+Adata = 3aa7f30ac5bfbcb3f8de7c5e76269c608fbc76361d215e78abc0e308ddc3528f
+Payload = 590a27721a36987d1ffa15f23c6ca5cc556dfcfa6993a2fb
+CT = ce71187fffff420312f76045133f340b0a54b66517502239efcb43c6aaec88b51d0a378b
+
+Count = 43
+Adata = 5630345f662df248886f771b2b77cc0cbdc8fe4cc4a6cde52b1ea4e5d946cebe
+Payload = 65f4b3a00c1c1ef39445a69b2150b034705410140ff9dad0
+CT = f28f8cade9d5c48d9948d32c0e0321f32f6d5a8b713a5a12b9a60374d9304316e2fc50d9
+
+Count = 44
+Adata = 38ee97f0dc635c7416a024e3af5c95dd1d496db8a5a5c3bcc20b9093ca906dfb
+Payload = 0edea2afaeaf650704d2c6c6622aad82169807c983c17309
+CT = 99a59da24b66bf7909dfb3714d793c4549a14d56fd02f3cb07611163d6b0f1734292ed8c
+
+Count = 45
+Adata = ea3b3f3c5b28f7d48af2ccf97083937baccb0a6b1a041080a73b15b9640ccf44
+Payload = b80175a03dff1b10078ded64ed759e5453e3bc0657c68590
+CT = 2f7a4aadd836c16e0a8098d3c2260f930cdaf69929050552edefbcbb51d9d607b7b2e8f8
+
+Count = 46
+Adata = 287f31e69880823df7798c7970c0e42e600bf567ad78f5d559d0182d570c03cb
+Payload = 531c1e721e185f58b2c654b9098ce0c1338bab4149c7bef7
+CT = c467217ffbd18526bfcb210e26df71066cb2e1de37043e35f2b6d4dc8afae25ff400d73d
+
+Count = 47
+Adata = 1d4579c9410cc34ade1352ed433e0d4faaaa28200e359bcb4140d35939b3a792
+Payload = cead1c5af16ca89bc0821775f8cba8c25620a03dfd27d6f1
+CT = 59d6235714a572e5cd8f62c2d79839050919eaa283e4563319cd80c1ce0f9ed40f1e9dec
+
+Count = 48
+Adata = 3fec0e5cc24d67139437cbc8112414fc8daccd1a94b49a4c76e2d39303547317
+Payload = be322f58efa7f8c68a635e0b9cce77f28e3f8faaa76fcad4
+CT = 294910550a6e22b8876e2bbcb39de635d106c535d9ac4a16e53d5aeccfb4a6837b79a625
+
+Count = 49
+Adata = ec6857533675b5ed8d4315b0d5f59c826f3ccb2d0bd6f604bd54f7c9542123ce
+Payload = c222374d366baf2d0301340582aa056c04441ac766065ab1
+CT = 55590840d3a275530e0c41b2adf994ab5b7d505818c5da73385e080bf29ae097c328789a
+
+[Tlen = 14]
+
+Key = d2d4482ea8e98c1cf309671895a16610152ce283434bca38
+Nonce = 6ee177d48f59bd37045ec03731
+
+Count = 50
+Adata = 9ef2d0d556d05cf9d1ee9dab9b322a389c75cd4e9dee2c0d08eea961efce8690
+Payload = 78168e5cc3cddf4b90d5bc11613465030903e0196f1fe443
+CT = e2324a6d5643dfc8aea8c08cbbc245494a3dcbcb800c797c3abcdb0563978785bf7fd71c6c1f
+
+Count = 51
+Adata = 6f99d9ce00a4be502a5d2c76a07b914d56f49a1592c1ee2e46e11b3c9da0d083
+Payload = 3c3992cac792e019720d38f768beac3deb6a43e7e1f59f20
+CT = a61d56fb521ce09a4c70446ab2488c77a85468350ee6021fcb0e8ec0879db8ffa59125eac239
+
+Count = 52
+Adata = deae66f68bb18178d1bc0734f19fd3ab390049c2ca083a159f5c078fcb4f0a38
+Payload = 8eaae72e532943d66ce8250c6b434d299b6afbf8e2b4f8b1
+CT = 148e231fc6a7435552955991b1b56d63d854d02a0da7658e664a2d992f7cf821e19bb7d4dff8
+
+Count = 53
+Adata = e2d592cb412e65f9044257d78e7491f9f80c8b08102c2d5da20535cef74ad8c8
+Payload = 1b8096b79ace8c6ee5dbd8735f1287aa2c94865f382dc2da
+CT = 81a452860f408ceddba6a4ee85e4a7e06faaad8dd73e5fe546a4a816b709a55db450ac249c5c
+
+Count = 54
+Adata = 78a292662b8e05abc2d44fbefd0840795e7493028015d9f2aae7b3b7a4634437
+Payload = 014f15219463ac22820ba6a1fa04d7f686003ef24004da67
+CT = 9b6bd11001edaca1bc76da3c20f2f7bcc53e1520af174758fbebbdb2e35ebf682f7fe30996bc
+
+Count = 55
+Adata = de6ea86d3641d916c4394fdd31e6a50194993d6ef1d3dfd9fffca20b2f58107d
+Payload = cc8c855a4c122046916bdcf8089eba3ddb80483e201c7102
+CT = 56a8416bd99c20c5af16a065d2689a7798be63eccf0fec3deee137bb5b1e7385aa1bd5d69831
+
+Count = 56
+Adata = 87b937b1d36e8a9ab33a1d3eed617030923acaabc7e620dfcb3c388936030fc6
+Payload = 3fb7d1f17e7e36d5d4b816cc6db11d1d85848c577fdfe938
+CT = a59315c0ebf03656eac56a51b7473d57c6baa78590cc74079b13b729c70e1fa89c43a05a544b
+
+Count = 57
+Adata = 116f4855121d6aa53e8b8b43a2e23d468c8568c744f49de5f7f1a60cf4e16278
+Payload = 268fe424d6db30f680c10fe2684707a0778069958e9a3bf7
+CT = bcab201543553075bebc737fb2b127ea34be42476189a6c82d900340d90dc4f09a7171d331d6
+
+Count = 58
+Adata = e13e0c9cef1f86160a75ccb131586370b0edabbf8b3b63f21f3a6fee072dd926
+Payload = 9d64de7161895884e7fa3d6e9eb996e7ebe511b01fe19cd4
+CT = 07401a40f4075807d98741f3444fb6ada8db3a62f0f201ebe4ad0d90322ed2813a3343029e93
+
+Count = 59
+Adata = d4cd69b26ea43596278b8caec441fedcf0d729d4e0c27ed1332f48871c96e958
+Payload = e4abe343f98a2df09413c3defb85b56a6d34dba305dcce46
+CT = 7e8f27726c042d73aa6ebf43217395202e0af071eacf53790065601bb59972c35b580852e684
+
+[Tlen = 16]
+
+Key = a7177fd129674c6c91c1c89f4408139afe187026b8114893
+Nonce = 31bb28f0e1e63c36ca3959dd18
+
+Count = 60
+Adata = 2529a834668187213f5342a1f3deea0dc2765478c7d71c9c21b9eb1351a5f6cb
+Payload = 2cea0f7304860a4f40a28c8b890db60f3891b9982478495e
+CT = 5bb7aa6ab9c02a5712d62343fbe61f774e598d6b87545612380ea23dcffc9574f672bca92e306411
+
+Count = 61
+Adata = a4dbf26802b2dba1bf828f57618fd197d3e60b6efc9d884f965ce3b43e1dc008
+Payload = 2baf3d378942bd44f67fb787def50aaf446bf15c56243484
+CT = 5cf2982e34049d5ca40b184fac1ea3d732a3c5aff5082bc8b93605b46a8a6a9c7e02cb8feac67af4
+
+Count = 62
+Adata = cbd1302c9fffe29fe882838236f64fe9d9ba35db5499e90f0faa35f34c7490f2
+Payload = a0639aa4e7a8bda4e9e096d17c1c47d3786010fabe9c72d2
+CT = d73e3fbd5aee9dbcbb9439190ef7eeab0ea824091db06d9e82e411c052c0a025ab15767b0242ebf7
+
+Count = 63
+Adata = b6112eb8299b28445aca8f72e7170a1cd8bbfee4d2145fbe8d49c6af8831c4d4
+Payload = e2d78ce5df9284c045b84df33f551211ddccf7bb14cd4529
+CT = 958a29fc62d4a4d817cce23b4dbebb69ab04c348b7e15a65ab58a892f7142414d3f7cf10925a403a
+
+Count = 64
+Adata = c70a9fb811894b73e445b78db7a931705a181f3a8730341cbb50eaff43572c6e
+Payload = c3f1e735a6741aa481ad577a98dbac1f03cc80ea0dae1b94
+CT = b4ac422c1b323abcd3d9f8b2ea3005677504b419ae8204d8b5b3ce6bae6ecb060289508d6e9212fe
+
+Count = 65
+Adata = c7cbda495a7dc1d91837f652a9d084df9b717e99b29bf1ab7f6c17b3341ecd6c
+Payload = db8cd5d76e459afce765e07da98f4ac58231224238c293c7
+CT = acd170ced303bae4b5114fb5db64e3bdf4f916b19bee8c8ba16229a91a2298ffe104f9c032720abb
+
+Count = 66
+Adata = 4bd3a656796cb1fa87976f3a93471e33dd1209ce33d7a28aaca4d17c99d78c94
+Payload = fd66aebc94f2513b1b9218396b08c63a869b9c4dd0752a91
+CT = 8a3b0ba529b4712349e6b7f119e36f42f053a8be735935ddb9cacc4fdb44402971a0eee7f1ad90d7
+
+Count = 67
+Adata = 448cdd9cbbf863eb666fda36b825f3798827da3c1349611f45605ab734b24498
+Payload = 5831e9a6af0234d051ffd17a14b8e3c8da95067ab767901b
+CT = 2f6c4cbf124414c8038b7eb266534ab0ac5d3289144b8f5713306e7f0a61d4b3da372db669321143
+
+Count = 68
+Adata = f8f04f12174b5205866515ce3775bd8e11d50d8b96142be0c347a773379fb928
+Payload = 248a4969621cf291bec7f0d76d80b7f019d4eb002a22c46a
+CT = 53d7ec70df5ad289ecb35f1f1f6b1e886f1cdff3890edb2609726d3a3d04005dc13629658624d05b
+
+Count = 69
+Adata = 4ecd7c2188fb9cfc84a9ee2fab29ccbbd48a574ec20f1959eedfe96887fe0eb3
+Payload = 68f36fd96de8c57210f6f41da5b67d68533d722c604dda62
+CT = 1faecac0d0aee56a42825bd5d75dd41025f546dfc361c52e8631fb934e918210097f3cefc7f3b0ee
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VTT256.rsp b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VTT256.rsp
new file mode 100644
index 0000000000..dbe86fbb71
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/VTT256.rsp
@@ -0,0 +1,393 @@
+# CAVS 11.0
+# "CCM-VTT" information
+# AES Keylen: 256
+# Generated on Tue Mar 15 08:09:25 2011
+
+Alen = 32
+Plen = 24
+Nlen = 13
+
+[Tlen = 4]
+
+Key = 9074b1ae4ca3342fe5bf6f14bcf2f27904f0b15179d95a654f61e699692e6f71
+Nonce = 2e1e0132468500d4bd47862563
+
+Count = 0
+Adata = 3c5f5404370abdcb1edde99de60d0682c600b034e063b7d3237723da70ab7552
+Payload = 239029f150bccbd67edbb67f8ae456b4ea066a4beee065f9
+CT = 9c8d5dd227fd9f81237601830afee4f0115636c8e5d5fd743cb9afed
+
+Count = 1
+Adata = ab91d1aa072947d22f0dc322355a022fe7f0747f4a184b48446bd27999ef01fe
+Payload = 25a43fd8bf241d67dab9e3c106cd27b71fd45a87b9254a53
+CT = 9ab94bfbc86549308714543d86d795f3e4840604b210d2de169d7775
+
+Count = 2
+Adata = 4c3bdc6186297896097b3297ba90bcde78dc8a9efe3bd8b10a85eed1bf63a30c
+Payload = e63d8303fa5c51550e417e77ec1ec647c9e2a853cab00fee
+CT = 5920f7208d1d050253ecc98b6c04740332b2f4d0c1859763b9c2e299
+
+Count = 3
+Adata = 8587324c1ff6712aed8af134744de5df1f88c5d2cb33f4f888af9fd39eb8e813
+Payload = f27548ec1608d3b8a5bdcbccb7e09cf4b5c29d3661b13a61
+CT = 4d683ccf614987eff8107c3037fa2eb04e92c1b56a84a2ec02f73205
+
+Count = 4
+Adata = 58820fb68ba1cd73b05a6698b4394ba1b13e8e296480f5afe1154d9b8536007c
+Payload = ecbd7091732e49c0f4bda2e63235ea43bbf8c8730f955f9c
+CT = 53a004b2046f1d97a910151ab22f580740a894f004a0c7114e1dd81b
+
+Count = 5
+Adata = f3034031933e7807d47140cf5c7794e42a228a522a83883b0765b57a411bad85
+Payload = 3002c6fb49497c7d1d06e1bd4edd57a9e54bbbb74e948c79
+CT = 8f1fb2d83e08282a40ab5641cec7e5ed1e1be73445a114f446525bc4
+
+Count = 6
+Adata = 05981dc26a1db2d8e2c3d85ea9a4d1dc3432d9edc4795ca03ca4661d2fc35b8c
+Payload = 214acfb2613b266f2929d43c7666f3a23e61423061cdbec3
+CT = 9e57bb91167a7238748463c0f67c41e6c5311eb36af8264e651844a3
+
+Count = 7
+Adata = 968a302a27624c304e894633af600c3cc7c614b7da3af0bf2d3f239c7605338a
+Payload = 9c575d592a9622c014c1303329757a65a414a9ed0c1b1b3f
+CT = 234a297a5dd77697496c87cfa96fc8215f44f56e072e83b249fd550d
+
+Count = 8
+Adata = 9011231ec382ecaaae57f34de1ac6bbb50741014a978160ce59c60491e64f30d
+Payload = 426a4c83793abdcff5e2a99e161785dc27c6168a329ee465
+CT = fd7738a00e7be998a84f1e62960d3798dc964a0939ab7ce84137defa
+
+Count = 9
+Adata = 96f0b1edec4ad14407dcaf30ed68942b46c48d58b2dd63af60fccd5bdd48e560
+Payload = e04006b68c83a5dd4ceac3cde238e48895ae17728fdc7bbe
+CT = 5f5d7295fbc2f18a11477431622256cc6efe4bf184e9e33356a4953f
+
+[Tlen = 6]
+
+Key = 8596a69890b0e47d43aeeca54b52029331da06fae63aa3249faaca94e2605feb
+Nonce = 20442e1c3f3c88919c39978b78
+
+Count = 10
+Adata = 4e0d3aa502bd03fe1761b167c4e0df1d228301d3ebaa4a0281becd813266e255
+Payload = f0b065da6ecb9ddcab855152d3b4155037adfa758ba96070
+CT = d6a0f377f7c1b14dcdba729cae5271b027e71cc7850173ec265867a29eb3
+
+Count = 11
+Adata = aeef2d1e3d3c9920a4fdb5f9d963b88e78a5d0edae531e3b55e702ed609d9a3c
+Payload = f2a8855e34854656df0776e80255ad1d125841c727201509
+CT = d4b813f3ad8f6ac7b93855267fb3c9fd0212a7752988069566e89a72dc0e
+
+Count = 12
+Adata = 3051ffb19862370bc46ca94a8eb906a660d539b18e965583e95acc149190e3e9
+Payload = 20955a0ca3c9c10d4055406ec12226130ecdaf195b08d65e
+CT = 0685cca13ac3ed9c266a63a0bcc442f31e8749ab55a0c5c2dff4f6257e06
+
+Count = 13
+Adata = aafa45a107d909756b4a1956d5228b50316fc5852afdeecf401fa2a71aabea46
+Payload = 246b60d17ea70deb1380fbf4bd767d88f53069b0f4136511
+CT = 027bf67ce7ad217a75bfd83ac0901968e57a8f02fabb768def0017c9acc1
+
+Count = 14
+Adata = ccdeab6a28b1b9e9f0c67116a91f2215b229d0edcd35d696db2bcf54e77db743
+Payload = 5b735697c5577ee0e352cf6a1495c490d6f7e97c3898f0ee
+CT = 7d63c03a5c5d5271856deca46973a070c6bd0fce3630e372c73969437912
+
+Count = 15
+Adata = 33a1e7d4820ed6a76a6dab90b4ba830888caf12a262e4eb6d75a505b2207de36
+Payload = 1170416faf81896c7f00815f53c2be5f7246d4794895b4b1
+CT = 3760d7c2368ba5fd193fa2912e24dabf620c32cb463da72dd7cb3721fcdd
+
+Count = 16
+Adata = 3df3edd9fc93be9960b5a632e2847b30b10187c8f83de5b45fcb2e3ed475569a
+Payload = 556765ffe5c46015cbd8194e32abc41e8f711773e2bcac90
+CT = 7377f3527cce4c84ade73a804f4da0fe9f3bf1c1ec14bf0c82183448e643
+
+Count = 17
+Adata = 4cb8663a1a934b6b27cbc1ed3040fbb99fbb6812f8ca35ff73cc13feeb483af7
+Payload = 3070e269f3e87cd82af3896895a5dd6fbfa9898279e0f73b
+CT = 166074c46ae250494cccaaa6e843b98fafe36f307748e4a76069901b5e3a
+
+Count = 18
+Adata = 876df130c01d0b9b8ebe43e71046c365e13124169026876d50d7e155f0299676
+Payload = dd18d40728c561e24e6e54834348dde5683f067baf8df469
+CT = fb0842aab1cf4d732851774d3eaeb9057875e0c9a125e7f56d65c2b005d4
+
+Count = 19
+Adata = da08b14e1b770b81faaf1e59851df1cba8838cd63bef141340ee378e65fdcbd4
+Payload = 7064a2491f716f4a2969815e4a281a54690ced9f794b264e
+CT = 567434e4867b43db4f56a29037ce7eb479460b2d77e335d275b37e9fb9e9
+
+[Tlen = 8]
+
+Key = bae73483de27b581a7c13f178a6d7bda168c1b4a1cb9180512a13e3ab914eb61
+Nonce = daf54faef6e4fc7867624b76f2
+
+Count = 20
+Adata = 7022eaa52c9da821da72d2edd98f6b91dfe474999b75b34699aeb38465f70c1c
+Payload = 28ef408d57930086011b167ac04b866e5b58fe6690a0b9c3
+CT = 356367c6cee4453658418d9517f7c6faddcd7c65aef460138cf050f48c505151
+
+Count = 21
+Adata = a61b6c1f0293a7c35520abf158a995e5ae59b43ec5f38ff6fd6529970c9f83ac
+Payload = 1c5ad37d2a55afbc390b27cde0c42d6651fe191239bfaa27
+CT = 01d6f436b322ea0c6051bc2237786df2d76b9b1107eb73f76bca352f92f383e1
+
+Count = 22
+Adata = 0f1c6dffeda98f7a159f9cc61820bfb29910d8eaa41b751a41f9fe5648f02fba
+Payload = 6efe6652d46a84166d30befe2fbee0795e9475b401eedd60
+CT = 737241194d1dc1a6346a2511f802a0edd801f7b73fba04b014fd7c84052208d9
+
+Count = 23
+Adata = 151110a9ce7e44e5d76d9cad53c1819317527fcd169051f01c6a3efcc06ea999
+Payload = 55b791ee495299916ff3c2327b4990952bebd0a2da9acfc5
+CT = 483bb6a5d025dc2136a959ddacf5d001ad7e52a1e4ce1615c3ebc7214b9eef31
+
+Count = 24
+Adata = 0ba1210696d735eebc13b609d0ec33bc740805105dd82f065b82892b931f1e6d
+Payload = 794a86f5b20d344ad86fd5523d08f1864737be57731440c2
+CT = 64c6a1be2b7a71fa81354ebdeab4b112c1a23c544d409912eff08182f8a00f13
+
+Count = 25
+Adata = 5a3b71b0fdecce8bd759d3d72321b5c3e882c82627c14e0b59cc8c6d191f243f
+Payload = efa6ddd6fb8e4480a0f64414694e5f9e7f2e9b97cbe9cd14
+CT = f22afa9d62f90130f9acdffbbef21f0af9bb1994f5bd14c46894be1f8fa14538
+
+Count = 26
+Adata = 5d344c5b94695a66192b6692e420c8eaa3cb482502be837b2a0a91b787fbe48e
+Payload = 561dd3bf419ae33ff521a43898cf12c6a5c6163eec22abc1
+CT = 4b91f4f4d8eda68fac7b3fd74f7352522353943dd2767211f4393bca514c3336
+
+Count = 27
+Adata = 08344486df2b2f9a6880a03503a3986c485f067c480c31a51607553b875f91fa
+Payload = 6d3596f25401f2e3b099613236f1d88a2f3d8edc1f04bc0c
+CT = 70b9b1b9cd76b753e9c3fadde14d981ea9a80cdf215065dcb708ffd04c8c2da0
+
+Count = 28
+Adata = 9d0824a4dc7e67326c5b68a6ea99cb68298a2af2cc1952351454b038f6270603
+Payload = c563a43e4cc0f93d955432f68287e63400a7fdcae738ba84
+CT = d8ef8375d5b7bc8dcc0ea919553ba6a086327fc9d96c63541511d7d684d58762
+
+Count = 29
+Adata = c4384069e09a3d4de2c94e7e6055d8a00394e268398d6ea32914097aec37a1f4
+Payload = 18c5865b414b2a06b4d71ab9550985b4f3c3d7817e8a8d7c
+CT = 0549a110d83c6fb6ed8d815682b5c5207556558240de54acef0919c5f5daf093
+
+[Tlen = 10]
+
+Key = d5b321b0ac2fedce0933d57d12195c7b9941f4caa95529125ed21c41fac43374
+Nonce = b35fb2262edfa14938a0fba03e
+
+Count = 30
+Adata = ba762bbda601d711e2dfc9dbe3003d39df1043ca845612b8e9dc9ff5c5d06ec4
+Payload = 6aa6ea668df60b0db85592d0a819c9df9e1099916272aafb
+CT = 97027de5effd82c58f8dbfb909d7696fbe2d54916262912001a4d765bc1c95c90a95
+
+Count = 31
+Adata = 77a685958ca801dbcbf346d6bac72662d3870899d7bcdef6665d57bacd4e558f
+Payload = c2992096828325820e2d7acaa17ac789b6830ec3128dd7f9
+CT = 3f3db715e088ac4a39f557a300b4673996bec3c3129dec22288aecb4c38c2391c21d
+
+Count = 32
+Adata = 3a54d3e14bbd0549570ef12425c4b36fd25382d56b68e217bc711ab1625fe9bb
+Payload = e5151262cafdd2f4dea187372dacb9e5975065572446f2a5
+CT = 18b185e1a8f65b3ce979aa5e8c621955b76da8572456c97edb4bd2cb1f1222e0d64f
+
+Count = 33
+Adata = 5c7604f9ac8fdf30ee5820e5aeb75b65d7855e5d2ff9ccf021640707bf1f53e8
+Payload = 1fe786f52daab92a6aa5f43263bed74153d90579a34bceff
+CT = e24311764fa130e25d7dd95bc27077f173e4c879a35bf5249283c1a61e9113462325
+
+Count = 34
+Adata = 42b8863ea100babc1713654afcf54f21f8bff754223ad70269ace9d034f26a96
+Payload = 56c3130c5af210b5bcf7c58b968fc75fc92b9c339efb7aee
+CT = ab67848f38f9997d8b2fe8e2374167efe91651339eeb4135bd3ffe1b1051ec3206db
+
+Count = 35
+Adata = c5a369a8291f4278e797ff11ea5e777d69df3b9c0c32d46150ed4b3e2c3defdd
+Payload = daa716f3cd1e008b46318ec90d976c3fbf88c3ff73cf0052
+CT = 27038170af15894371e9a3a0ac59cc8f9fb50eff73df3b8910d5d255f193b29eb961
+
+Count = 36
+Adata = 63bdceb36a032d3e0e81b4e98ad9861e2c708cef4e870c5b88a87ecc24449be3
+Payload = 42477d7d44881dabccfce52efb8a2cc917b182a23b71fb49
+CT = bfe3eafe26839463fb24c8475a448c79378c4fa23b61c0924e524729fb06212508e6
+
+Count = 37
+Adata = b7f8e7b66726e07c3c73d74135f068bb8025c9da9ba70affb9ed9a69675f0eef
+Payload = 07f48cdc12aa27119fbdfda4ec07ce6068c92ba7ba9c9309
+CT = fa501b5f70a1aed9a865d0cd4dc96ed048f4e6a7ba8ca8d2222af86d91fb6a2b09d3
+
+Count = 38
+Adata = 09891ed14f4488069cd6a5744061e06f8ff8d1bc87b10448b3fbfc1a4e327787
+Payload = e2e7002b769fb5b4201053457158147d99b0d5147f3acac2
+CT = 1f4397a814943c7c17c87e2cd096b4cdb98d18147f2af1194cddcb65a76c40698017
+
+Count = 39
+Adata = 8f9786940943752c536548497f9dae2bd8d677b8bbcb0121a9c9f3c399b62e4b
+Payload = 86be1d1949fe03b8b80ef7abb3e27394273d7b76d7697f0e
+CT = 7b1a8a9a2bf58a708fd6dac2122cd3240700b676d77944d5ddb42d504b6fc47d6575
+
+[Tlen = 12]
+
+Key = 7f4af6765cad1d511db07e33aaafd57646ec279db629048aa6770af24849aa0d
+Nonce = dde2a362ce81b2b6913abc3095
+
+Count = 40
+Adata = 404f5df97ece7431987bc098cce994fc3c063b519ffa47b0365226a0015ef695
+Payload = 7ebef26bf4ecf6f0ebb2eb860edbf900f27b75b4a6340fdb
+CT = 353022db9c568bd7183a13c40b1ba30fcc768c54264aa2cd2927a053c9244d3217a7ad05
+
+Count = 41
+Adata = e9ed05813262fbe769c1104d8ba5c836dbd229a22a681de3565d17ac1129f96b
+Payload = fdf5a5fb377bb52ad07a971c6a9da3e1a68d279be9ac4ed7
+CT = b67b754b5fc1c80d23f26f5e6f5df9ee9880de7b69d2e3c11c000c9d88f047ca198c4e65
+
+Count = 42
+Adata = f246f1e948c81c98ea13f03dd8eea878449d0c3d5b5fe87c633bbe0106fcb899
+Payload = e5e6b57e74ce7afbde3697e2a69d61ca615aa3dfd32fe31f
+CT = ae6865ce1c7407dc2dbe6fa0a35d3bc55f575a3f53514e095c09878f1a963b795b29f4dd
+
+Count = 43
+Adata = e4683285695348ff04a61d51d90b868dfe4cf6ea246544727adeaeface571d57
+Payload = ef2c3a6bb8602d290045854a5f223e6f43bfd0bb9278fa88
+CT = a4a2eadbd0da500ef3cd7d085ae264607db2295b1206579e807d196d2628df1c384816f7
+
+Count = 44
+Adata = 42695369dbd69f07b46db282653704c34106aad82efdcc99b452598b5353f904
+Payload = beda29c7fe15c73ee5bef96485eb8c9e3cd3ea7ee633ef45
+CT = f554f97796afba1916360126802bd69102de139e664d4253961c666279394e1e28cf1b02
+
+Count = 45
+Adata = 58c3ce3906633475441229cfcdf05e02ff3738ae8d1b255974f431b3309ed41e
+Payload = 419c96ba8142b27e3377716358c97a8a636d7fe8403165e1
+CT = 0a12460ae9f8cf59c0ff89215d0920855d608608c04fc8f764efe624dd6c6f8b8cdc76e3
+
+Count = 46
+Adata = a9c06d8029f8da31629c3a6ddceb6009220a69fc614af1c231ae8702b3a85d6e
+Payload = 69bb441a7640f77e124d66af45a0e9f646658a838dfcb957
+CT = 223594aa1efa8a59e1c59eed4060b3f9786873630d8214410ef4b71970b9f80087533cf7
+
+Count = 47
+Adata = a92e88edd297da8c7089e21822b3e6cffd6837c78b975c8413fd6cca1b99bcb0
+Payload = a45b755658d38bdea57d1faae21d75428a17f2c74a33d2d5
+CT = efd5a5e63069f6f956f5e7e8e7dd2f4db41a0b27ca4d7fc36e27dfbf1ff7f08d1b213848
+
+Count = 48
+Adata = 421533453c8129fc8e681c68b9d7371adb0a19442ede7accd185129fcb7db648
+Payload = 2c3e28b61cede08121e80ee08c4f1f19dabb19add9d2dc8a
+CT = 67b0f80674579da6d260f6a2898f4516e4b6e04d59ac719ca48d1a0b815139fa28652d94
+
+Count = 49
+Adata = 55351bc7ddbc6b668d435088f1f9cf6f53caae16d4292b14bc0deec20f393ba0
+Payload = 81fa7fd41ba267bcbdf024cef1543b041cadd96b62a7cf1f
+CT = ca74af6473181a9b4e78dc8cf494610b22a0208be2d962091301c87a2a94df147c8cce4c
+
+[Tlen = 14]
+
+Key = 5c8b59d3e7986c277d5ad51e4a2233251076809ebf59463f47cd10b4aa951f8c
+Nonce = 21ff892b743d661189e205c7f3
+
+Count = 50
+Adata = f1e0af185180d2eb63e50e37ba692647cac2c6a149d70c81dbd34685ed78feaa
+Payload = 138ee53b1914d3322c2dd0a4e02faab2236555131d5eea08
+CT = 5b2f3026f30fdd50accc40ddd093b7997f23d7c6d3c8bc425f82c828413643b8794494cb5236
+
+Count = 51
+Adata = 45c5c284836414407268d7c8a89a0146759cfc92242004027d58d0828fad74e7
+Payload = fe3df84ee9b237f9edd77a5b8af96bc3e184579ac9c6e246
+CT = b69c2d5303a9399b6d36ea22ba4576e8bdc2d54f0750b40c6db5c92de5fb3aafba9537795e17
+
+Count = 52
+Adata = a41ea42692eac0914fef35e58409007342cef027de141223ffb46da7f58df034
+Payload = e0f5c02f9f84e57fada3f3575f1b1a748f360e0ea781b7b8
+CT = a8541532759feb1d2d42632e6fa7075fd3708cdb6917e1f21af6cf931ac943fd3affa6ad6fd1
+
+Count = 53
+Adata = 17dae00f2a9417780ecfef98f290a5ca9b17c873a9149cd81c18bd33164a0405
+Payload = 3a77a2ec5a1be6cbfbbfaab3e65427cb38d6798b132ff5c7
+CT = 72d677f1b000e8a97b5e3acad6e83ae06490fb5eddb9a38d38a3f09c56ae653be49b355fb938
+
+Count = 54
+Adata = 33b44873a7a1e5b0fdbb7e7347623e4fa1ccd937feb26fda2749b42f00744e50
+Payload = d0628b26019dad84de628d9dabf42cfb195165a369c22b49
+CT = 98c35e3beb86a3e65e831de49b4831d04517e776a7547d03974deec7ce2e1f296890bee795cb
+
+Count = 55
+Adata = f4fc5acff75d404849675b813cf7adcaeb8f3d56cb9a54a083f8ec07feb666bb
+Payload = 10b5ec41036e4bc5d61728e8811b520b7080c2177c122cbd
+CT = 5814395ce97545a756f6b891b1a74f202cc640c2b2847af798a3bc56f900bee7e8271c6dab22
+
+Count = 56
+Adata = ba051d1bc19b9a27520834fa3977b6413a319c9a52c8785e3e9594bd4265d911
+Payload = 648a84813ca97aef4ab7e143ee29acb946388660f18eb671
+CT = 2c2b519cd6b2748dca56713ade95b1921a7e04b53f18e03be6623d80c677633a9e4f999bb885
+
+Count = 57
+Adata = f5c629299d18901c8c34c42e8fc29a70c377c160fdea4a6068a36867707575f7
+Payload = 3ead49ed0b41de79c829098d034b666bce052d79bf1f56db
+CT = 760c9cf0e15ad01b48c899f433f77b409243afac71890091c65b88ff4fdd9b8187f7d71ba04b
+
+Count = 58
+Adata = da486fd2953a72838e67e1909ed4042df67c355b648a45bcd2cc1ba610659e76
+Payload = 4543457c8fdf463c4bf8515a762cdc83d9aaa887d3eaa2af
+CT = 0de2906165c4485ecb19c1234690c1a885ec2a521d7cf4e5727c3404564ed41528973d389c7c
+
+Count = 59
+Adata = a0b1d3600f6eba910a11537d61fa12184959f1c3ae386570cbbc9106f7a7ba07
+Payload = 22071ef5d204417f99bc2faf53ecc4c6cf795e77805633ee
+CT = 6aa6cbe8381f4f1d195dbfd66350d9ed933fdca24ec065a446ecb536703a7a97928f80fcc7cf
+
+[Tlen = 16]
+
+Key = 60823b64e0b2da3a7eb772bd5941c534e6ff94ea96b564e2b38f82c78bb54522
+Nonce = 48526f1bffc97dd65e42906983
+
+Count = 60
+Adata = fab62b3e5deda7a9c1128663cc81c44b74ab1bfe70bc1c9dec7c7fd08173b80a
+Payload = a8be794613835c4366e75817d228438f011a2ec8a86f9797
+CT = cc3efe04d84a4ec5cb6a6c28dc2c2d386a359d9550dbdec963ddd56464aed6d0613159d1aa181dcb
+
+Count = 61
+Adata = b3ff11e57eeab41bc597622c770c9eea333e178d5bd5689c6a30011187a965b8
+Payload = 7590769380dc91832da023798dfdd447b9f7adaa09d7e2d0
+CT = 1110f1d14b158305802d174683f9baf0d2d81ef7f163ab8e7c1273765bc5bfdeca429cc8ebd8aca2
+
+Count = 62
+Adata = 2a953a081c5d52bc500c9c12f56cd2aab5c920d73098335baa5d947100cb3411
+Payload = 30e4de5e8c275677f8f4f7bbf9d101f96b38d79968ea028c
+CT = 5464591c47ee44f15579c384f7d56f4e001764c4905e4bd2886229c09b986bee3a8a3025c150d3a3
+
+Count = 63
+Adata = 99cc9d1b3db79640dfdc4423af3ded03c329f7ba5b6b509269c10e59519053b8
+Payload = 852698f6ab4aa794b3d657c4a2ca7b9c8bfb5fc9b4ad0aca
+CT = e1a61fb46083b5121e5b63fbacce152be0d4ec944c19439480cd04041918c4071ea5ac263f36c544
+
+Count = 64
+Adata = b76aef71eaf03c2d0dc0623e90596fcb0bc4dbbed1d5bb24c8af37d778863e5b
+Payload = cd337fcf362d301d66916c7097bdeb31df8206e00f7ac106
+CT = a9b3f88dfde4229bcb1c584f99b98586b4adb5bdf7ce8858f001d6002eafaec49c472acdfaedf1de
+
+Count = 65
+Adata = 42a718d892e229a1807b74bd730fb15500ac4a790392100aef362cd7628d5806
+Payload = 0041a0cf48fcf870b21db6107cfd9ef91e409afc7562ffa7
+CT = 64c1278d8335eaf61f90822f72f9f04e756f29a18dd6b6f975d86cde91b6610496c3bb5276238741
+
+Count = 66
+Adata = e788c98ae85b11b3ae884eed6f3b8f5bcf5ab1b7b20ad3f44f760b2287cc5793
+Payload = fcc74ef1908dbcab9b05c76ee5a9941cdef933d433c0d25f
+CT = 9847c9b35b44ae2d3688f351ebadfaabb5d68089cb749b01db7d9f10e75d1b213beae0e0230dd82b
+
+Count = 67
+Adata = d330fc1ca406dd9528e9281aa1a3cdf013b698c14a4e55371e7539c9f6867dd4
+Payload = 611dade00cec14743be4e035cafe7507df5fb94b278875b1
+CT = 059d2aa2c72506f29669d40ac4fa1bb0b4700a16df3c3cefc63ba64291e73e6349ed089a53564291
+
+Count = 68
+Adata = 06bbadd5d22d1796d88415d7a4b024313f243bd0f58aafc75bb554a691d7e54f
+Payload = b67b5dd7f90ecd48a45853cb193e0d9702d78898f07e831d
+CT = d2fbda9532c7dfce09d567f4173a632069f83bc508caca43ac4d7bd964a2f9e2303df688dd0513da
+
+Count = 69
+Adata = 54da66d406f2d98edd999b673ef44d46ffd196091c8b7582ac2ed6bf13dc648f
+Payload = d092dc436c41836bdb815e473bc6a1906f37624e73b494f9
+CT = b4125b01a78891ed760c6a7835c2cf270418d1138b00dda7b4cd237cd9a7c9d93b9cc0f171818dae
diff --git a/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/ccmtestvectors.zip b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/ccmtestvectors.zip
new file mode 100644
index 0000000000..34bb67b1ac
--- /dev/null
+++ b/lib/crypto/test/crypto_SUITE_data/aes_ccm_vectors/ccmtestvectors.zip
Binary files differ
diff --git a/lib/crypto/test/engine_SUITE.erl b/lib/crypto/test/engine_SUITE.erl
index bb9aa49b50..4b3ea10315 100644
--- a/lib/crypto/test/engine_SUITE.erl
+++ b/lib/crypto/test/engine_SUITE.erl
@@ -39,6 +39,10 @@ all() ->
get_all_possible_methods,
engine_load_all_methods,
engine_load_some_methods,
+ multiple_engine_load,
+ engine_list,
+ get_id_and_name,
+ engine_by_id,
bad_arguments,
unknown_engine,
pre_command_fail_bad_value,
@@ -46,6 +50,7 @@ all() ->
failed_engine_init,
ctrl_cmd_string,
ctrl_cmd_string_optional,
+ ensure_load,
{group, engine_stored_key}
].
@@ -97,7 +102,7 @@ init_per_group(engine_stored_key, Config) ->
{error, notexist} ->
{skip, "OTP Test engine not found"};
{error, notsup} ->
- {skip, "Engine not supported on this OpenSSL version"};
+ {skip, "Engine not supported on this SSL version"};
{error, bad_engine_id} ->
{skip, "Dynamic Engine not supported"};
Other ->
@@ -132,11 +137,12 @@ get_all_possible_methods() ->
get_all_possible_methods(Config) when is_list(Config) ->
try
List = crypto:engine_get_all_methods(),
+ true = erlang:is_list(List),
ct:log("crypto:engine_get_all_methods() -> ~p\n", [List]),
ok
catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
+ {skip, "Engine not supported on this SSL version"}
end.
engine_load_all_methods()->
@@ -149,13 +155,12 @@ engine_load_all_methods(Config) when is_list(Config) ->
{error, notexist} ->
{skip, "OTP Test engine not found"};
{ok, Engine} ->
- try
+ try
Md5Hash1 = <<106,30,3,246,166,222,229,158,244,217,241,179,50,232,107,109>>,
Md5Hash1 = crypto:hash(md5, "Don't panic"),
Md5Hash2 = <<0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15>>,
case crypto:engine_load(<<"dynamic">>,
[{<<"SO_PATH">>, Engine},
- {<<"ID">>, <<"MD5">>},
<<"LOAD">>],
[]) of
{ok, E} ->
@@ -181,7 +186,7 @@ engine_load_all_methods(Config) when is_list(Config) ->
end
catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
+ {skip, "Engine not supported on this SSL version"}
end
end.
@@ -195,21 +200,20 @@ engine_load_some_methods(Config) when is_list(Config) ->
{error, notexist} ->
{skip, "OTP Test engine not found"};
{ok, Engine} ->
- try
+ try
Md5Hash1 = <<106,30,3,246,166,222,229,158,244,217,241,179,50,232,107,109>>,
Md5Hash1 = crypto:hash(md5, "Don't panic"),
Md5Hash2 = <<0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15>>,
EngineMethods = crypto:engine_get_all_methods() --
- [engine_method_dh,engine_method_rand,
+ [engine_method_dh, engine_method_rand,
engine_method_ciphers, engine_method_store,
engine_method_pkey_meths, engine_method_pkey_asn1_meths],
case crypto:engine_load(<<"dynamic">>,
[{<<"SO_PATH">>, Engine},
- {<<"ID">>, <<"MD5">>},
<<"LOAD">>],
[],
EngineMethods) of
- {ok, E} ->
+ {ok, E} ->
case crypto:hash(md5, "Don't panic") of
Md5Hash1 ->
ct:fail(fail_to_load_engine_still_original);
@@ -232,7 +236,168 @@ engine_load_some_methods(Config) when is_list(Config) ->
end
catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
+ {skip, "Engine not supported on this SSL version"}
+ end
+ end.
+
+multiple_engine_load()->
+ [{doc, "Use a dummy md5 engine that does not implement md5"
+ "but rather returns a static binary to test that crypto:engine_load "
+ "functions works when called multiple times."}].
+
+multiple_engine_load(Config) when is_list(Config) ->
+ case crypto:get_test_engine() of
+ {error, notexist} ->
+ {skip, "OTP Test engine not found"};
+ {ok, Engine} ->
+ try
+ Md5Hash1 = <<106,30,3,246,166,222,229,158,244,217,241,179,50,232,107,109>>,
+ Md5Hash1 = crypto:hash(md5, "Don't panic"),
+ Md5Hash2 = <<0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15>>,
+ case crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ <<"LOAD">>],
+ []) of
+ {ok, E} ->
+ {ok, E1} = crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ <<"LOAD">>],
+ []),
+ {ok, E2} = crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ <<"LOAD">>],
+ []),
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash1 ->
+ ct:fail(fail_to_load_still_original_engine);
+ Md5Hash2 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_load_engine)
+ end,
+ ok = crypto:engine_unload(E2),
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash1 ->
+ ct:fail(fail_to_load_still_original_engine);
+ Md5Hash2 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_load_engine)
+ end,
+ ok = crypto:engine_unload(E),
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash1 ->
+ ct:fail(fail_to_load_still_original_engine);
+ Md5Hash2 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_load_engine)
+ end,
+ ok = crypto:engine_unload(E1),
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash2 ->
+ ct:fail(fail_to_unload_still_test_engine);
+ Md5Hash1 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_unload_engine)
+ end;
+ {error, bad_engine_id} ->
+ {skip, "Dynamic Engine not supported"}
+ end
+ catch
+ error:notsup ->
+ {skip, "Engine not supported on this SSL version"}
+ end
+ end.
+
+engine_list()->
+ [{doc, "Test add and remove engine ID to the SSL internal engine list."}].
+
+engine_list(Config) when is_list(Config) ->
+ case crypto:get_test_engine() of
+ {error, notexist} ->
+ {skip, "OTP Test engine not found"};
+ {ok, Engine} ->
+ try
+ EngineList0 = crypto:engine_list(),
+ case crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ <<"LOAD">>],
+ []) of
+ {ok, E} ->
+ EngineList0 = crypto:engine_list(),
+ ok = crypto:engine_add(E),
+ [<<"MD5">>] = lists:subtract(crypto:engine_list(), EngineList0),
+ ok = crypto:engine_remove(E),
+ EngineList0 = crypto:engine_list(),
+ ok = crypto:engine_unload(E);
+ {error, bad_engine_id} ->
+ {skip, "Dynamic Engine not supported"}
+ end
+ catch
+ error:notsup ->
+ {skip, "Engine not supported on this SSL version"}
+ end
+ end.
+
+get_id_and_name()->
+ [{doc, "Test fetching id and name from an engine."}].
+
+get_id_and_name(Config) when is_list(Config) ->
+ case crypto:get_test_engine() of
+ {error, notexist} ->
+ {skip, "OTP Test engine not found"};
+ {ok, Engine} ->
+ try
+ case crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ <<"LOAD">>],
+ []) of
+ {ok, E} ->
+ <<"MD5">> = crypto:engine_get_id(E),
+ <<"MD5 test engine">> = crypto:engine_get_name(E),
+ ok = crypto:engine_unload(E);
+ {error, bad_engine_id} ->
+ {skip, "Dynamic Engine not supported"}
+ end
+ catch
+ error:notsup ->
+ {skip, "Engine not supported on this SSL version"}
+ end
+ end.
+
+engine_by_id()->
+ [{doc, "Test fetching a new reference the the engine when the"
+ "engine id is added to the SSL engine list."}].
+
+engine_by_id(Config) when is_list(Config) ->
+ case crypto:get_test_engine() of
+ {error, notexist} ->
+ {skip, "OTP Test engine not found"};
+ {ok, Engine} ->
+ try
+ case crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ <<"LOAD">>],
+ []) of
+ {ok, E} ->
+ case crypto:engine_by_id(<<"MD5">>) of
+ {error,bad_engine_id} ->
+ ok;
+ {ok, _} ->
+ ct:fail(fail_engine_found)
+ end,
+ ok = crypto:engine_add(E),
+ {ok, _E1} = crypto:engine_by_id(<<"MD5">>),
+ ok = crypto:engine_remove(E),
+ ok = crypto:engine_unload(E);
+ {error, bad_engine_id} ->
+ {skip, "Dynamic Engine not supported"}
+ end
+ catch
+ error:notsup ->
+ {skip, "Engine not supported on this SSL version"}
end
end.
@@ -246,7 +411,7 @@ bad_arguments(Config) when is_list(Config) ->
{error, notexist} ->
{skip, "OTP Test engine not found"};
{ok, Engine} ->
- try
+ try
try
crypto:engine_load(fail_engine, [], [])
catch
@@ -276,7 +441,7 @@ bad_arguments(Config) when is_list(Config) ->
end
catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
+ {skip, "Engine not supported on this SSL version"}
end
end.
@@ -289,7 +454,7 @@ unknown_engine(Config) when is_list(Config) ->
ok
catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
+ {skip, "Engine not supported on this SSL version"}
end.
pre_command_fail_bad_value() ->
@@ -311,7 +476,7 @@ pre_command_fail_bad_value(Config) when is_list(Config) ->
end
catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
+ {skip, "Engine not supported on this SSL version"}
end.
pre_command_fail_bad_key() ->
@@ -334,9 +499,9 @@ pre_command_fail_bad_key(Config) when is_list(Config) ->
{skip, "Dynamic Engine not supported"}
end
end
- catch
+ catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
+ {skip, "Engine not supported on this SSL version"}
end.
failed_engine_init()->
@@ -352,18 +517,20 @@ failed_engine_init(Config) when is_list(Config) ->
[{<<"SO_PATH">>, Engine},
{<<"ID">>, <<"MD5">>}],
[]) of
- {error, add_engine_failed} ->
+ {error, engine_init_failed} ->
ok;
{error, bad_engine_id} ->
{skip, "Dynamic Engine not supported"}
end
end
- catch
+ catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
+ {skip, "Engine not supported on this SSL version"}
end.
+%%-------------------------------------------------------------------------
+%% Test the optional flag in ctrl comands
ctrl_cmd_string()->
[{doc, "Test that a not known optional ctrl comand do not fail"}].
ctrl_cmd_string(Config) when is_list(Config) ->
@@ -377,22 +544,22 @@ ctrl_cmd_string(Config) when is_list(Config) ->
{<<"ID">>, <<"MD5">>},
<<"LOAD">>],
[]) of
- {ok, E} ->
+ {ok, E} ->
case crypto:engine_ctrl_cmd_string(E, <<"TEST">>, <<"17">>) of
ok ->
ct:fail(fail_ctrl_cmd_should_fail);
- {error,ctrl_cmd_failed} ->
+ {error,ctrl_cmd_failed} ->
ok
end,
- ok = crypto:engine_unload(E);
+ ok = crypto:engine_unload(E);
{error, bad_engine_id} ->
{skip, "Dynamic Engine not supported"}
end
end
- catch
+ catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
- end.
+ {skip, "Engine not supported on this SSL version"}
+ end.
ctrl_cmd_string_optional()->
[{doc, "Test that a not known optional ctrl comand do not fail"}].
@@ -407,22 +574,63 @@ ctrl_cmd_string_optional(Config) when is_list(Config) ->
{<<"ID">>, <<"MD5">>},
<<"LOAD">>],
[]) of
- {ok, E} ->
+ {ok, E} ->
case crypto:engine_ctrl_cmd_string(E, <<"TEST">>, <<"17">>, true) of
ok ->
ok;
- _ ->
+ _ ->
ct:fail(fail_ctrl_cmd_string)
end,
- ok = crypto:engine_unload(E);
+ ok = crypto:engine_unload(E);
{error, bad_engine_id} ->
{skip, "Dynamic Engine not supported"}
end
end
- catch
+ catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
- end.
+ {skip, "Engine not supported on this SSL version"}
+ end.
+
+ensure_load()->
+ [{doc, "Test the special ensure load function."}].
+
+ensure_load(Config) when is_list(Config) ->
+ case crypto:get_test_engine() of
+ {error, notexist} ->
+ {skip, "OTP Test engine not found"};
+ {ok, Engine} ->
+ try
+ Md5Hash1 = <<106,30,3,246,166,222,229,158,244,217,241,179,50,232,107,109>>,
+ Md5Hash1 = crypto:hash(md5, "Don't panic"),
+ Md5Hash2 = <<0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15>>,
+ case crypto:ensure_engine_loaded(<<"MD5">>, Engine) of
+ {ok, E} ->
+ {ok, _E1} = crypto:ensure_engine_loaded(<<"MD5">>, Engine),
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash1 ->
+ ct:fail(fail_to_load_still_original_engine);
+ Md5Hash2 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_load_engine)
+ end,
+ ok = crypto:ensure_engine_unloaded(E),
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash2 ->
+ ct:fail(fail_to_unload_still_test_engine);
+ Md5Hash1 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_unload_engine)
+ end;
+ {error, bad_engine_id} ->
+ {skip, "Dynamic Engine not supported"}
+ end
+ catch
+ error:notsup ->
+ {skip, "Engine not supported on this SSL version"}
+ end
+ end.
%%%----------------------------------------------------------------
%%% Pub/priv key storage tests. Those are for testing the crypto.erl
@@ -467,7 +675,7 @@ sign_verify_rsa_pwd_bad_pwd(Config) ->
_ -> {fail, "PWD prot pubkey sign succeded with no pwd!"}
catch
error:badarg -> ok
- end.
+ end.
priv_encrypt_pub_decrypt_rsa(Config) ->
Priv = #{engine => engine_ref(Config),
@@ -540,7 +748,7 @@ get_pub_from_priv_key_rsa_pwd_no_pwd(Config) ->
{skip, "RSA not supported"};
{error, Error} ->
{fail, {wrong_error,Error}};
- Pub ->
+ Pub ->
ct:log("rsa Pub = ~p",[Pub]),
{fail, "PWD prot pubkey fetch succeded although no pwd!"}
end.
@@ -556,7 +764,7 @@ get_pub_from_priv_key_rsa_pwd_bad_pwd(Config) ->
{skip, "RSA not supported"};
{error, Error} ->
{fail, {wrong_error,Error}};
- Pub ->
+ Pub ->
ct:log("rsa Pub = ~p",[Pub]),
{fail, "PWD prot pubkey fetch succeded with bad pwd!"}
end.
@@ -590,7 +798,7 @@ get_pub_from_priv_key_ecdsa(Config) ->
ct:log("ecdsa Pub = ~p",[Pub]),
sign_verify(ecdsa, sha, Priv, Pub)
end.
-
+
%%%================================================================
%%% Help for engine_stored_pub_priv_keys* test cases
%%%
diff --git a/lib/crypto/vsn.mk b/lib/crypto/vsn.mk
index 0d7b0e5575..64d593f64a 100644
--- a/lib/crypto/vsn.mk
+++ b/lib/crypto/vsn.mk
@@ -1 +1 @@
-CRYPTO_VSN = 4.3.1
+CRYPTO_VSN = 4.3.3
diff --git a/lib/debugger/doc/src/notes.xml b/lib/debugger/doc/src/notes.xml
index 9f7214ac69..395b69973d 100644
--- a/lib/debugger/doc/src/notes.xml
+++ b/lib/debugger/doc/src/notes.xml
@@ -33,6 +33,21 @@
<p>This document describes the changes made to the Debugger
application.</p>
+<section><title>Debugger 4.2.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Debugger 4.2.5</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/debugger/vsn.mk b/lib/debugger/vsn.mk
index d62e5915a7..a3cbb497f8 100644
--- a/lib/debugger/vsn.mk
+++ b/lib/debugger/vsn.mk
@@ -1 +1 @@
-DEBUGGER_VSN = 4.2.5
+DEBUGGER_VSN = 4.2.6
diff --git a/lib/dialyzer/doc/src/notes.xml b/lib/dialyzer/doc/src/notes.xml
index 4ec72eecd9..3cf776e566 100644
--- a/lib/dialyzer/doc/src/notes.xml
+++ b/lib/dialyzer/doc/src/notes.xml
@@ -32,6 +32,21 @@
<p>This document describes the changes made to the Dialyzer
application.</p>
+<section><title>Dialyzer 3.3.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> Optimize Dialyzer's handling of left-associative use
+ of <c>andalso</c> and <c>orelse</c> in guards. </p>
+ <p>
+ Own Id: OTP-15268 Aux Id: ERL-680 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Dialyzer 3.3</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/dialyzer/test/small_SUITE_data/results/left_assoc b/lib/dialyzer/test/small_SUITE_data/results/left_assoc
new file mode 100644
index 0000000000..58cdad29de
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/results/left_assoc
@@ -0,0 +1,2 @@
+
+left_assoc.erl:93: The variable __@2 can never match since previous clauses completely covered the type binary()
diff --git a/lib/dialyzer/test/small_SUITE_data/src/left_assoc.erl b/lib/dialyzer/test/small_SUITE_data/src/left_assoc.erl
new file mode 100644
index 0000000000..0250e4ab49
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/left_assoc.erl
@@ -0,0 +1,96 @@
+-module(left_assoc).
+
+%% As pointed out in ERL-680, analyzing guards with short circuit
+%% operators becomes very slow as the number of left associations
+%% grows.
+
+-spec from_iso8601('Elixir.String':t(), 'Elixir.Calendar':calendar()) ->
+ {ok, t()} | {error, atom()}.
+
+-export_type([t/0]).
+
+-type t() ::
+ #{'__struct__' := 'Elixir.Date',
+ calendar := 'Elixir.Calendar':calendar(),
+ day := 'Elixir.Calendar':day(),
+ month := 'Elixir.Calendar':month(),
+ year := 'Elixir.Calendar':year()}.
+
+-export([from_iso8601/1,
+ from_iso8601/2]).
+
+from_iso8601(__@1) ->
+ from_iso8601(__@1, 'Elixir.Calendar.ISO').
+
+from_iso8601(<<45/integer,_rest@1/binary>>, _calendar@1) ->
+ case raw_from_iso8601(_rest@1, _calendar@1) of
+ {ok,#{year := _year@1} = _date@1} ->
+ {ok,_date@1#{year := - _year@1}};
+ __@1 ->
+ __@1
+ end;
+from_iso8601(<<_rest@1/binary>>, _calendar@1) ->
+ raw_from_iso8601(_rest@1, _calendar@1).
+
+raw_from_iso8601(_string@1, _calendar@1) ->
+ case _string@1 of
+ <<_y1@1/integer,
+ _y2@1/integer,
+ _y3@1/integer,
+ _y4@1/integer,
+ 45/integer,
+ _m1@1/integer,
+ _m2@1/integer,
+ 45/integer,
+ _d1@1/integer,
+ _d2@1/integer>>
+ when
+ ((((((((((((((_y1@1 >= 48
+ andalso
+ _y1@1 =< 57)
+ andalso
+ _y2@1 >= 48)
+ andalso
+ _y2@1 =< 57)
+ andalso
+ _y3@1 >= 48)
+ andalso
+ _y3@1 =< 57)
+ andalso
+ _y4@1 >= 48)
+ andalso
+ _y4@1 =< 57)
+ andalso
+ _m1@1 >= 48)
+ andalso
+ _m1@1 =< 57)
+ andalso
+ _m2@1 >= 48)
+ andalso
+ _m2@1 =< 57)
+ andalso
+ _d1@1 >= 48)
+ andalso
+ _d1@1 =< 57)
+ andalso
+ _d2@1 >= 48)
+ andalso
+ _d2@1 =< 57 ->
+ {ok,
+ #{year => (_y1@1 - 48) * 1000 + (_y2@1 - 48) * 100
+ +
+ (_y3@1 - 48) * 10
+ +
+ (_y4@1 - 48),
+ month => (_m1@1 - 48) * 10 + (_m2@1 - 48),
+ day => (_d1@1 - 48) * 10 + (_d2@1 - 48),
+ calendar => _calendar@1,
+ '__struct__' => 'Elixir.Date'}};
+ __@1 ->
+ case __@1 of
+ _ ->
+ {error,invalid_format};
+ __@2 ->
+ error({with_clause,__@2})
+ end
+ end.
diff --git a/lib/dialyzer/vsn.mk b/lib/dialyzer/vsn.mk
index 7240b66fb5..98ab533a58 100644
--- a/lib/dialyzer/vsn.mk
+++ b/lib/dialyzer/vsn.mk
@@ -1 +1 @@
-DIALYZER_VSN = 3.3
+DIALYZER_VSN = 3.3.1
diff --git a/lib/diameter/doc/src/Makefile b/lib/diameter/doc/src/Makefile
index 7672598060..7c7fbeafef 100644
--- a/lib/diameter/doc/src/Makefile
+++ b/lib/diameter/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2010-2016. All Rights Reserved.
+# Copyright Ericsson AB 2010-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/lib/diameter/doc/src/notes.xml b/lib/diameter/doc/src/notes.xml
index 3232c3380a..4bfc98de40 100644
--- a/lib/diameter/doc/src/notes.xml
+++ b/lib/diameter/doc/src/notes.xml
@@ -43,6 +43,26 @@ first.</p>
<!-- ===================================================================== -->
+<section><title>diameter 2.1.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix function_clause when sending an outgoing request
+ after DPA has been sent in response to an incoming DPR.
+ The caused the diameter_peer_fsm gen_server associated
+ with the peer connection to fail, which could then result
+ in the transport connection being reset before the peer
+ closed it upon reception of DPA.</p>
+ <p>
+ Own Id: OTP-15198 Aux Id: ERIERL-213 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>diameter 2.1.5</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/diameter/src/base/diameter_peer_fsm.erl b/lib/diameter/src/base/diameter_peer_fsm.erl
index d99f11a697..cf5e7f21d3 100644
--- a/lib/diameter/src/base/diameter_peer_fsm.erl
+++ b/lib/diameter/src/base/diameter_peer_fsm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -901,7 +901,7 @@ outgoing(#diameter_packet{header = #diameter_header{is_request = false}}
ok;
%% Outgoing request: discard.
-outgoing(Msg, #state{dpr = {_,_,_}}) ->
+outgoing(Msg, #state{}) ->
invalid(false, send_after_dpr, header(Msg)).
header(#diameter_packet{header = H}) ->
diff --git a/lib/diameter/src/diameter.appup.src b/lib/diameter/src/diameter.appup.src
index 3389f11937..51830f5276 100644
--- a/lib/diameter/src/diameter.appup.src
+++ b/lib/diameter/src/diameter.appup.src
@@ -58,7 +58,8 @@
{"2.1.1", [{restart_application, diameter}]}, %% 20.1.2
{"2.1.2", [{restart_application, diameter}]}, %% 20.1.3
{"2.1.3", [{restart_application, diameter}]}, %% 20.2
- {"2.1.4", [{restart_application, diameter}]} %% 20.3
+ {"2.1.4", [{restart_application, diameter}]}, %% 20.3
+ {"2.1.5", [{update, diameter_peer_fsm}]} %% 21.0
],
[
{"0.9", [{restart_application, diameter}]},
@@ -98,6 +99,7 @@
{"2.1.1", [{restart_application, diameter}]},
{"2.1.2", [{restart_application, diameter}]},
{"2.1.3", [{restart_application, diameter}]},
- {"2.1.4", [{restart_application, diameter}]}
+ {"2.1.4", [{restart_application, diameter}]},
+ {"2.1.5", [{update, diameter_peer_fsm}]}
]
}.
diff --git a/lib/diameter/vsn.mk b/lib/diameter/vsn.mk
index 3081034df9..8c75c9e55e 100644
--- a/lib/diameter/vsn.mk
+++ b/lib/diameter/vsn.mk
@@ -17,5 +17,5 @@
# %CopyrightEnd%
APPLICATION = diameter
-DIAMETER_VSN = 2.1.5
+DIAMETER_VSN = 2.1.6
APP_VSN = $(APPLICATION)-$(DIAMETER_VSN)$(PRE_VSN)
diff --git a/lib/edoc/doc/src/notes.xml b/lib/edoc/doc/src/notes.xml
index 2ef941b06d..e818887eb8 100644
--- a/lib/edoc/doc/src/notes.xml
+++ b/lib/edoc/doc/src/notes.xml
@@ -32,6 +32,21 @@
<p>This document describes the changes made to the EDoc
application.</p>
+<section><title>Edoc 0.9.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Edoc 0.9.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/edoc/vsn.mk b/lib/edoc/vsn.mk
index bea9277e1f..0b3636f030 100644
--- a/lib/edoc/vsn.mk
+++ b/lib/edoc/vsn.mk
@@ -1 +1 @@
-EDOC_VSN = 0.9.3
+EDOC_VSN = 0.9.4
diff --git a/lib/eldap/doc/src/notes.xml b/lib/eldap/doc/src/notes.xml
index ef7dda510c..07c2b0a3e8 100644
--- a/lib/eldap/doc/src/notes.xml
+++ b/lib/eldap/doc/src/notes.xml
@@ -31,6 +31,21 @@
</header>
<p>This document describes the changes made to the Eldap application.</p>
+<section><title>Eldap 1.2.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Eldap 1.2.4</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/eldap/vsn.mk b/lib/eldap/vsn.mk
index f2b3cd47f2..6e8951aba4 100644
--- a/lib/eldap/vsn.mk
+++ b/lib/eldap/vsn.mk
@@ -1 +1 @@
-ELDAP_VSN = 1.2.4
+ELDAP_VSN = 1.2.5
diff --git a/lib/erl_docgen/doc/src/notes.xml b/lib/erl_docgen/doc/src/notes.xml
index 7a09b62351..97c842a324 100644
--- a/lib/erl_docgen/doc/src/notes.xml
+++ b/lib/erl_docgen/doc/src/notes.xml
@@ -31,7 +31,23 @@
</header>
<p>This document describes the changes made to the <em>erl_docgen</em> application.</p>
- <section><title>Erl_Docgen 0.8</title>
+ <section><title>Erl_Docgen 0.8.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Indexing for the online search function has been
+ corrected for CREF documents.</p>
+ <p>
+ Own Id: OTP-14406</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erl_Docgen 0.8</title>
<section><title>Improvements and New Features</title>
<list>
diff --git a/lib/erl_docgen/priv/xsl/db_eix.xsl b/lib/erl_docgen/priv/xsl/db_eix.xsl
index b496614854..6bce577f08 100644
--- a/lib/erl_docgen/priv/xsl/db_eix.xsl
+++ b/lib/erl_docgen/priv/xsl/db_eix.xsl
@@ -3,7 +3,7 @@
#
# %CopyrightBegin%
#
- # Copyright Ericsson AB 2009-2016. All Rights Reserved.
+ # Copyright Ericsson AB 2009-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -199,11 +199,34 @@
<xsl:template name="name">
<xsl:param name="lastfuncsblock"/>
+ <xsl:variable name="signature">
+ <xsl:variable name="signature1">
+ <xsl:choose>
+ <xsl:when test="ancestor::cref">
+ <xsl:value-of
+ select="normalize-space(nametext)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of
+ select="normalize-space(substring-before(., '->'))"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="string-length($signature1) > 0">
+ <xsl:value-of select="$signature1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="normalize-space(.)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
<xsl:variable name="tmpstring">
- <xsl:value-of select="substring-before(substring-after(., '('), '->')"/>
+ <xsl:value-of select="substring-after($signature, '(')"/>
</xsl:variable>
- <xsl:variable name="ustring">
+ <xsl:variable name="argstring">
<xsl:choose>
<xsl:when test="string-length($tmpstring) > 0">
<xsl:call-template name="remove-paren">
@@ -219,10 +242,19 @@
</xsl:variable>
<xsl:variable name="arity">
- <xsl:call-template name="calc-arity">
- <xsl:with-param name="string" select="substring-before($ustring, ')')"/>
- <xsl:with-param name="no-of-pars" select="0"/>
- </xsl:call-template>
+ <xsl:choose>
+ <xsl:when
+ test="string-length(substring-before(., '->')) > 0">
+ <xsl:call-template name="calc-arity">
+ <xsl:with-param
+ name="string"
+ select="substring-before($argstring, ')')"/>
+ <xsl:with-param name="no-of-pars" select="0"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+
</xsl:variable>
<xsl:variable name="fname">
@@ -250,10 +282,18 @@
</xsl:variable>
<xsl:text> {"</xsl:text><xsl:value-of select="$fname"/>
+ <xsl:text>", "</xsl:text>
+ <xsl:call-template name="escape-doublequotes">
+ <xsl:with-param name="string" select="$signature"/>
+ </xsl:call-template>
<xsl:text>", "</xsl:text><xsl:value-of select="$fname"/>
- <xsl:text>(</xsl:text><xsl:value-of select="normalize-space($tmpstring)"/>
- <xsl:text>", "</xsl:text><xsl:value-of select="$fname"/>
- <xsl:text>-</xsl:text><xsl:value-of select="$arity"/><xsl:text>"}</xsl:text>
+ <xsl:choose>
+ <xsl:when test="string-length($arity) > 0">
+ <xsl:text>-</xsl:text><xsl:value-of select="$arity"/>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ <xsl:text>"}</xsl:text>
<xsl:choose>
<xsl:when test="($lastfuncsblock = 'true') and (position() = last())">
@@ -345,6 +385,27 @@
</xsl:template>
+ <xsl:template name="escape-doublequotes">
+ <xsl:param name="string"/>
+ <xsl:param name="pPat">"</xsl:param>
+ <xsl:param name="pRep">\"</xsl:param>
+
+ <xsl:choose>
+ <xsl:when test="not(contains($string, $pPat))">
+ <xsl:copy-of select="$string"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:copy-of select="substring-before($string, $pPat)"/>
+ <xsl:copy-of select="$pRep"/>
+ <xsl:call-template name="escape-doublequotes">
+ <xsl:with-param
+ name="string"
+ select="substring-after($string, $pPat)"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
<!-- default content handling -->
<xsl:template match="text()"/>
diff --git a/lib/erl_docgen/vsn.mk b/lib/erl_docgen/vsn.mk
index 0b24604daa..3b2f6db6a1 100644
--- a/lib/erl_docgen/vsn.mk
+++ b/lib/erl_docgen/vsn.mk
@@ -1 +1 @@
-ERL_DOCGEN_VSN = 0.8
+ERL_DOCGEN_VSN = 0.8.1
diff --git a/lib/erl_interface/configure.in b/lib/erl_interface/configure.in
index a155ceef7e..46dd995289 100644
--- a/lib/erl_interface/configure.in
+++ b/lib/erl_interface/configure.in
@@ -29,11 +29,6 @@ dnl m4_define(EI_VERSION,regexp(m4_include(VERSION),[version \([-.0-9A-Za-z]+\)]
AC_INIT()
-if test "x$no_recursion" != "xyes" -a "x$OVERRIDE_CONFIG_CACHE" = "x"; then
- # We do not want to use a common cache!
- cache_file=/dev/null
-fi
-
dnl How to set srcdir absolute is taken from the GNU Emacs distribution
#### Make srcdir absolute, if it isn't already. It's important to
#### avoid running the path through pwd unnecessary, since pwd can
diff --git a/lib/erl_interface/doc/src/Makefile b/lib/erl_interface/doc/src/Makefile
index 173bd2e83b..507a84a453 100644
--- a/lib/erl_interface/doc/src/Makefile
+++ b/lib/erl_interface/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1998-2017. All Rights Reserved.
+# Copyright Ericsson AB 1998-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/lib/erl_interface/doc/src/notes.xml b/lib/erl_interface/doc/src/notes.xml
index 1438317d8d..07ddd82718 100644
--- a/lib/erl_interface/doc/src/notes.xml
+++ b/lib/erl_interface/doc/src/notes.xml
@@ -31,6 +31,53 @@
</header>
<p>This document describes the changes made to the Erl_interface application.</p>
+<section><title>Erl_Interface 3.10.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Make <c>ei_connect</c> and friends also accept state
+ <c>ok_simultaneous</c> during handshake, which means the
+ other node has initiated a connection setup that will be
+ cancelled in favor of this connection.</p>
+ <p>
+ Own Id: OTP-15161 Aux Id: ERIERL-191 </p>
+ </item>
+ <item>
+ <p>
+ Fixed bug in <c>ei_receive_msg</c>,
+ <c>ei_xreceive_msg</c>, <c>ei_receive_msg_tmo</c> and
+ <c>ei_xreceive_msg_tmo</c>. The <c>x-&gt;index</c> was
+ set to entire buffer size instead of the number of bytes
+ actually received.</p>
+ <p>
+ Own Id: OTP-15171</p>
+ </item>
+ <item>
+ <p>
+ Fixed bug in <c>ei_connect_init</c> which could be
+ provoked if called by concurrent threads.
+ <c>ei_connect_init</c> called posix interface
+ <c>gethostbyname</c> which is documented as not thread
+ safe.</p>
+ <p>
+ Own Id: OTP-15191</p>
+ </item>
+ <item>
+ <p>
+ Fixed bug in erl_compare_ext() ignoring the tail of lists
+ of otherwise equal content. Example: <c>[a | b]</c> and
+ <c>[a | c]</c> compared equal and <c>{[a], b}</c> and
+ <c>{[a], c}</c> compared equal.</p>
+ <p>
+ Own Id: OTP-15277 Aux Id: PR-1929 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Erl_Interface 3.10.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/erl_interface/src/legacy/erl_marshal.c b/lib/erl_interface/src/legacy/erl_marshal.c
index c18067b9bc..932bba43bf 100644
--- a/lib/erl_interface/src/legacy/erl_marshal.c
+++ b/lib/erl_interface/src/legacy/erl_marshal.c
@@ -1803,7 +1803,7 @@ static int cmp_exe2(unsigned char **e1, unsigned char **e2)
k = 0;
while (1) {
if (k++ == min){
- if (i == j) return 0;
+ if (i == j) return compare_top_ext(e1 , e2);
if (i < j) return -1;
return 1;
}
diff --git a/lib/erl_interface/src/misc/ei_pthreads.c b/lib/erl_interface/src/misc/ei_pthreads.c
index 8c7e86555d..c6d07a9a0a 100644
--- a/lib/erl_interface/src/misc/ei_pthreads.c
+++ b/lib/erl_interface/src/misc/ei_pthreads.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/lib/erl_interface/test/ei_connect_SUITE.erl b/lib/erl_interface/test/ei_connect_SUITE.erl
index 24cd384295..75b6bf18da 100644
--- a/lib/erl_interface/test/ei_connect_SUITE.erl
+++ b/lib/erl_interface/test/ei_connect_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c b/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c
index fbd86cdb50..29c03d7604 100644
--- a/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c
+++ b/lib/erl_interface/test/ei_connect_SUITE_data/ei_connect_test.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2001-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2001-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/lib/erl_interface/test/ei_decode_SUITE.erl b/lib/erl_interface/test/ei_decode_SUITE.erl
index 499f10611e..75560ea7c9 100644
--- a/lib/erl_interface/test/ei_decode_SUITE.erl
+++ b/lib/erl_interface/test/ei_decode_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c b/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c
index 5a9be1e9a2..f945a7d378 100644
--- a/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c
+++ b/lib/erl_interface/test/ei_decode_SUITE_data/ei_decode_test.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2004-2017. All Rights Reserved.
+ * Copyright Ericsson AB 2004-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/lib/erl_interface/test/ei_decode_encode_SUITE.erl b/lib/erl_interface/test/ei_decode_encode_SUITE.erl
index 6476e92be9..0f23cdfbb9 100644
--- a/lib/erl_interface/test/ei_decode_encode_SUITE.erl
+++ b/lib/erl_interface/test/ei_decode_encode_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c b/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c
index 6285b5e199..9977683d59 100644
--- a/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c
+++ b/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2004-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2004-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/lib/erl_interface/test/ei_encode_SUITE.erl b/lib/erl_interface/test/ei_encode_SUITE.erl
index 8c3b0e193b..0267a5126f 100644
--- a/lib/erl_interface/test/ei_encode_SUITE.erl
+++ b/lib/erl_interface/test/ei_encode_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/erl_interface/test/ei_format_SUITE.erl b/lib/erl_interface/test/ei_format_SUITE.erl
index b11a6ff164..e074c184c1 100644
--- a/lib/erl_interface/test/ei_format_SUITE.erl
+++ b/lib/erl_interface/test/ei_format_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/erl_interface/test/ei_print_SUITE.erl b/lib/erl_interface/test/ei_print_SUITE.erl
index cad2686018..c75ce55a7d 100644
--- a/lib/erl_interface/test/ei_print_SUITE.erl
+++ b/lib/erl_interface/test/ei_print_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/erl_interface/test/ei_tmo_SUITE.erl b/lib/erl_interface/test/ei_tmo_SUITE.erl
index 1e76a99e1e..5b9de80128 100644
--- a/lib/erl_interface/test/ei_tmo_SUITE.erl
+++ b/lib/erl_interface/test/ei_tmo_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/erl_interface/test/erl_connect_SUITE.erl b/lib/erl_interface/test/erl_connect_SUITE.erl
index ad4e34c548..782691b8fb 100644
--- a/lib/erl_interface/test/erl_connect_SUITE.erl
+++ b/lib/erl_interface/test/erl_connect_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/erl_interface/test/erl_eterm_SUITE.erl b/lib/erl_interface/test/erl_eterm_SUITE.erl
index 84b58fed54..77910a9fc7 100644
--- a/lib/erl_interface/test/erl_eterm_SUITE.erl
+++ b/lib/erl_interface/test/erl_eterm_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/erl_interface/test/erl_ext_SUITE.erl b/lib/erl_interface/test/erl_ext_SUITE.erl
index 806339b122..ff3b495f7b 100644
--- a/lib/erl_interface/test/erl_ext_SUITE.erl
+++ b/lib/erl_interface/test/erl_ext_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/erl_interface/test/erl_ext_SUITE_data/ext_test.c b/lib/erl_interface/test/erl_ext_SUITE_data/ext_test.c
index 1e986feacf..6b47c3e510 100644
--- a/lib/erl_interface/test/erl_ext_SUITE_data/ext_test.c
+++ b/lib/erl_interface/test/erl_ext_SUITE_data/ext_test.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2002-2017. All Rights Reserved.
+ * Copyright Ericsson AB 2002-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -88,6 +88,11 @@ TESTCASE(compare_list) {
// erlang:term_to_binary([0, 1000])
unsigned char term4[] = {131,108,0,0,0,2,97,0,98,0,0,3,232,106};
+ // erlang:term_to_binary([a|b])
+ unsigned char term5a[] = {131,108,0,0,0,1,100,0,1,97,100,0,1,98};
+ // erlang:term_to_binary([a|c])
+ unsigned char term5b[] = {131,108,0,0,0,1,100,0,1,97,100,0,1,99};
+
erl_init(NULL, 0);
start_a = term1;
start_b = term2;
@@ -103,6 +108,13 @@ TESTCASE(compare_list) {
test_compare_ext("lists1", start_a, end_a, start_b, end_b, -1);
+ start_a = term5a;
+ start_b = term5b;
+ end_a = term5a + sizeof(term5a);
+ end_b = term5b + sizeof(term5b);
+
+ test_compare_ext("lists5", start_a, end_a, start_b, end_b, -1);
+
report(1);
}
diff --git a/lib/erl_interface/test/erl_format_SUITE.erl b/lib/erl_interface/test/erl_format_SUITE.erl
index d984dcb08e..69dfdcc4c8 100644
--- a/lib/erl_interface/test/erl_format_SUITE.erl
+++ b/lib/erl_interface/test/erl_format_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/erl_interface/test/erl_global_SUITE.erl b/lib/erl_interface/test/erl_global_SUITE.erl
index 560afd58ba..6d3a75c8d7 100644
--- a/lib/erl_interface/test/erl_global_SUITE.erl
+++ b/lib/erl_interface/test/erl_global_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/erl_interface/test/erl_match_SUITE.erl b/lib/erl_interface/test/erl_match_SUITE.erl
index f1f6892ae0..bb62d6288d 100644
--- a/lib/erl_interface/test/erl_match_SUITE.erl
+++ b/lib/erl_interface/test/erl_match_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/erl_interface/test/port_call_SUITE.erl b/lib/erl_interface/test/port_call_SUITE.erl
index d31b2372ab..5c4f5f3cee 100644
--- a/lib/erl_interface/test/port_call_SUITE.erl
+++ b/lib/erl_interface/test/port_call_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/erl_interface/vsn.mk b/lib/erl_interface/vsn.mk
index 586b23c5b3..06ef907d6c 100644
--- a/lib/erl_interface/vsn.mk
+++ b/lib/erl_interface/vsn.mk
@@ -1,2 +1,2 @@
-EI_VSN = 3.10.3
+EI_VSN = 3.10.4
ERL_INTERFACE_VSN = $(EI_VSN)
diff --git a/lib/et/doc/src/et_collector.xml b/lib/et/doc/src/et_collector.xml
index ba24c121e0..fd90ecfc41 100644
--- a/lib/et/doc/src/et_collector.xml
+++ b/lib/et/doc/src/et_collector.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2002</year><year>2016</year>
+ <year>2002</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/et/doc/src/et_selector.xml b/lib/et/doc/src/et_selector.xml
index b819bbf0c6..30ca74c872 100644
--- a/lib/et/doc/src/et_selector.xml
+++ b/lib/et/doc/src/et_selector.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2002</year><year>2016</year>
+ <year>2002</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/et/doc/src/notes.xml b/lib/et/doc/src/notes.xml
index e7cec937b3..110d3b2110 100644
--- a/lib/et/doc/src/notes.xml
+++ b/lib/et/doc/src/notes.xml
@@ -37,6 +37,21 @@
one section in this document. The title of each section is the
version number of <c>Event Tracer (ET)</c>.</p>
+<section><title>ET 1.6.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>ET 1.6.2</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/et/src/et_collector.erl b/lib/et/src/et_collector.erl
index b432df8c62..3609238509 100644
--- a/lib/et/src/et_collector.erl
+++ b/lib/et/src/et_collector.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/et/vsn.mk b/lib/et/vsn.mk
index 08ded8b6f1..9563a38000 100644
--- a/lib/et/vsn.mk
+++ b/lib/et/vsn.mk
@@ -1 +1 @@
-ET_VSN = 1.6.2
+ET_VSN = 1.6.3
diff --git a/lib/eunit/doc/src/notes.xml b/lib/eunit/doc/src/notes.xml
index 0d2d61d553..67a9ae5fcb 100644
--- a/lib/eunit/doc/src/notes.xml
+++ b/lib/eunit/doc/src/notes.xml
@@ -33,6 +33,21 @@
</header>
<p>This document describes the changes made to the EUnit application.</p>
+<section><title>Eunit 2.3.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Eunit 2.3.6</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/eunit/vsn.mk b/lib/eunit/vsn.mk
index 054e21f6ad..46ef5eea3c 100644
--- a/lib/eunit/vsn.mk
+++ b/lib/eunit/vsn.mk
@@ -1 +1 @@
-EUNIT_VSN = 2.3.6
+EUNIT_VSN = 2.3.7
diff --git a/lib/ftp/doc/src/notes.xml b/lib/ftp/doc/src/notes.xml
index 50f38941e5..01c1f88cf1 100644
--- a/lib/ftp/doc/src/notes.xml
+++ b/lib/ftp/doc/src/notes.xml
@@ -33,7 +33,22 @@
<file>notes.xml</file>
</header>
- <section><title>FTP 1.0</title>
+ <section><title>Ftp 1.0.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>FTP 1.0</title>
<section><title>First released version</title>
<list>
diff --git a/lib/ftp/src/ftp.app.src b/lib/ftp/src/ftp.app.src
index 237174358f..66ccace390 100644
--- a/lib/ftp/src/ftp.app.src
+++ b/lib/ftp/src/ftp.app.src
@@ -1,6 +1,6 @@
{application, ftp,
[{description, "FTP client"},
- {vsn, "1.0"},
+ {vsn, "%VSN%"},
{registered, []},
{mod, { ftp_app, []}},
{applications,
diff --git a/lib/ftp/vsn.mk b/lib/ftp/vsn.mk
index 3099144a6e..d5d6c45b28 100644
--- a/lib/ftp/vsn.mk
+++ b/lib/ftp/vsn.mk
@@ -19,6 +19,6 @@
# %CopyrightEnd%
APPLICATION = ftp
-FTP_VSN = 1.0
+FTP_VSN = 1.0.1
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(FTP_VSN)$(PRE_VSN)"
diff --git a/lib/hipe/doc/src/Makefile b/lib/hipe/doc/src/Makefile
index bd6a7b2f74..104c15f2bb 100644
--- a/lib/hipe/doc/src/Makefile
+++ b/lib/hipe/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2006-2017. All Rights Reserved.
+# Copyright Ericsson AB 2006-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/lib/hipe/doc/src/notes.xml b/lib/hipe/doc/src/notes.xml
index f47868296a..d9f58382bc 100644
--- a/lib/hipe/doc/src/notes.xml
+++ b/lib/hipe/doc/src/notes.xml
@@ -31,6 +31,21 @@
</header>
<p>This document describes the changes made to HiPE.</p>
+<section><title>Hipe 3.18.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Hipe 3.18</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/hipe/icode/hipe_beam_to_icode.erl b/lib/hipe/icode/hipe_beam_to_icode.erl
index f429d40272..ffe81ef9b8 100644
--- a/lib/hipe/icode/hipe_beam_to_icode.erl
+++ b/lib/hipe/icode/hipe_beam_to_icode.erl
@@ -647,6 +647,13 @@ trans_fun([{put_tuple,_Size,Reg}|Instructions], Env) ->
Primop = hipe_icode:mk_primop(Dest,mktuple,Src),
Moves ++ [Primop | trans_fun(Instructions2,Env2)];
%%--- put --- SHOULD NOT REALLY EXIST HERE; put INSTRUCTIONS ARE HANDLED ABOVE.
+%%--- put_tuple2 ---
+trans_fun([{put_tuple2,Reg,{list,Elements}}|Instructions], Env) ->
+ Dest = [mk_var(Reg)],
+ {Moves,Vars,Env2} = trans_elements(Elements, [], [], Env),
+ Src = lists:reverse(Vars),
+ Primop = hipe_icode:mk_primop(Dest, mktuple, Src),
+ Moves ++ [Primop | trans_fun(Instructions, Env2)];
%%--- badmatch ---
trans_fun([{badmatch,Arg}|Instructions], Env) ->
BadVar = trans_arg(Arg),
@@ -1139,9 +1146,10 @@ trans_fun([{test,has_map_fields,{f,Lbl},Map,{list,Keys}}|Instructions], Env) ->
lists:flatten([[K, {r, 0}] || K <- Keys])),
[MapMove, TestInstructions | trans_fun(Instructions, Env2)];
trans_fun([{get_map_elements,{f,Lbl},Map,{list,KVPs}}|Instructions], Env) ->
+ KVPs1 = overwrite_map_last(Map, KVPs),
{MapMove, MapVar, Env1} = mk_move_and_var(Map, Env),
{TestInstructions, GetInstructions, Env2} =
- trans_map_query(MapVar, map_label(Lbl), Env1, KVPs),
+ trans_map_query(MapVar, map_label(Lbl), Env1, KVPs1),
[MapMove, TestInstructions, GetInstructions | trans_fun(Instructions, Env2)];
%%--- put_map_assoc ---
trans_fun([{put_map_assoc,{f,Lbl},Map,Dst,_N,{list,Pairs}}|Instructions], Env) ->
@@ -1563,6 +1571,21 @@ trans_type_test2(function2, Lbl, Arg, Arity, Env) ->
hipe_icode:label_name(True), map_label(Lbl)),
{[Move1,Move2,I,True],Env2}.
+
+%%
+%% Makes sure that if a get_map_elements instruction will overwrite
+%% the map source, it will be done last.
+%%
+overwrite_map_last(Map, KVPs) ->
+ overwrite_map_last2(Map, KVPs, []).
+
+overwrite_map_last2(Map, [Key,Map|KVPs], _Last) ->
+ overwrite_map_last2(Map, KVPs, [Key,Map]);
+overwrite_map_last2(Map, [Key,Val|KVPs], Last) ->
+ [Key,Val|overwrite_map_last2(Map, KVPs, Last)];
+overwrite_map_last2(_Map, [], Last) ->
+ Last.
+
%%
%% Handles the get_map_elements instruction and the has_map_fields
%% test instruction.
@@ -1683,6 +1706,19 @@ trans_puts([{put,X}|Code], Vars, Moves, Env) ->
trans_puts(Code, Vars, Moves, Env) -> %% No more put operations
{Moves, Code, Vars, Env}.
+trans_elements([X|Code], Vars, Moves, Env) ->
+ case type(X) of
+ var ->
+ Var = mk_var(X),
+ trans_elements(Code, [Var|Vars], Moves, Env);
+ #beam_const{value=C} ->
+ Var = mk_var(new),
+ Move = hipe_icode:mk_move(Var, hipe_icode:mk_const(C)),
+ trans_elements(Code, [Var|Vars], [Move|Moves], Env)
+ end;
+trans_elements([], Vars, Moves, Env) ->
+ {Moves, Vars, Env}.
+
%%-----------------------------------------------------------------------
%% The code for this instruction is a bit large because we are treating
%% different cases differently. We want to use the icode `type'
diff --git a/lib/hipe/vsn.mk b/lib/hipe/vsn.mk
index b081cb0c26..b51f17aff0 100644
--- a/lib/hipe/vsn.mk
+++ b/lib/hipe/vsn.mk
@@ -1 +1 @@
-HIPE_VSN = 3.18
+HIPE_VSN = 3.18.1
diff --git a/lib/inets/doc/src/mod_security.xml b/lib/inets/doc/src/mod_security.xml
index d65d2ff998..6f3f3c048a 100644
--- a/lib/inets/doc/src/mod_security.xml
+++ b/lib/inets/doc/src/mod_security.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1998</year><year>2016</year>
+ <year>1998</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml
index 88a4335f60..e34dd78a2a 100644
--- a/lib/inets/doc/src/notes.xml
+++ b/lib/inets/doc/src/notes.xml
@@ -33,12 +33,63 @@
<file>notes.xml</file>
</header>
- <section><title>Inets 7.0</title>
+ <section><title>Inets 7.0.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
<item>
<p>
+ Enhance error handling, that is mod_get will return 403
+ if a path is a directory and not a file.</p>
+ <p>
+ Own Id: OTP-15192</p>
+ </item>
+ <item>
+ <p>
+ Do not use chunked-encoding with 1xx, 204 and 304
+ responses when using mod_esi. Old behavior was not
+ compliant with HTTP/1.1 RFC and could cause clients to
+ hang when they received 1xx, 204 or 304 responses that
+ included an empty chunked-encoded body.</p>
+ <p>
+ Own Id: OTP-15241</p>
+ </item>
+ <item>
+ <p>
+ Add robust handling of chunked-encoded HTTP responses
+ with an empty body (1xx, 204, 304). Old behavior could
+ cause the client to hang when connecting to a faulty
+ server implementation.</p>
+ <p>
+ Own Id: OTP-15242</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Inets 7.0.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Change status code for no mod found to handle request to
+ 501</p>
+ <p>
+ Own Id: OTP-15215</p>
+ </item>
+ </list>
+ </section>
+
+ </section>
+
+ <section><title>Inets 7.0</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
Fixed HTTP content injection bug in httpc (ERL-456).</p>
<p>
Own Id: OTP-14726</p>
@@ -92,6 +143,34 @@
</section>
+ <section><title>Inets 6.5.2.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Do not use chunked-encoding with 1xx, 204 and 304
+ responses when using mod_esi. Old behavior was not
+ compliant with HTTP/1.1 RFC and could cause clients to
+ hang when they received 1xx, 204 or 304 responses that
+ included an empty chunked-encoded body.</p>
+ <p>
+ Own Id: OTP-15241</p>
+ </item>
+ <item>
+ <p>
+ Add robust handling of chunked-encoded HTTP responses
+ with an empty body (1xx, 204, 304). Old behavior could
+ cause the client to hang when connecting to a faulty
+ server implementation.</p>
+ <p>
+ Own Id: OTP-15242</p>
+ </item>
+ </list>
+ </section>
+
+ </section>
+
<section><title>Inets 6.5.2.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/inets/src/http_client/httpc_handler.erl b/lib/inets/src/http_client/httpc_handler.erl
index 5e05b8170a..1bf5d25c98 100644
--- a/lib/inets/src/http_client/httpc_handler.erl
+++ b/lib/inets/src/http_client/httpc_handler.erl
@@ -961,13 +961,23 @@ handle_http_body(_, #state{status = {ssl_tunnel, Request},
NewState = answer_request(Request, ClientErrMsg, State),
{stop, normal, NewState};
-handle_http_body(<<>>, #state{status_line = {_,304, _}} = State) ->
+%% All 1xx (informational), 204 (no content), and 304 (not modified)
+%% responses MUST NOT include a message-body, and thus are always
+%% terminated by the first empty line after the header fields.
+%% This implies that chunked encoding MUST NOT be used for these
+%% status codes.
+handle_http_body(<<>>, #state{headers = Headers,
+ status_line = {_,StatusCode, _}} = State)
+ when Headers#http_response_h.'transfer-encoding' =/= "chunked" andalso
+ (StatusCode =:= 204 orelse %% No Content
+ StatusCode =:= 304 orelse %% Not Modified
+ 100 =< StatusCode andalso StatusCode =< 199) -> %% Informational
handle_response(State#state{body = <<>>});
-handle_http_body(<<>>, #state{status_line = {_,204, _}} = State) ->
- handle_response(State#state{body = <<>>});
-handle_http_body(<<>>, #state{request = #request{method = head}} = State) ->
+handle_http_body(<<>>, #state{headers = Headers,
+ request = #request{method = head}} = State)
+ when Headers#http_response_h.'transfer-encoding' =/= "chunked" ->
handle_response(State#state{body = <<>>});
handle_http_body(Body, #state{headers = Headers,
diff --git a/lib/inets/src/http_client/httpc_manager.erl b/lib/inets/src/http_client/httpc_manager.erl
index 0333442bf2..0dc0483fa9 100644
--- a/lib/inets/src/http_client/httpc_manager.erl
+++ b/lib/inets/src/http_client/httpc_manager.erl
@@ -863,7 +863,7 @@ select_session(Candidates, _, Max, pipeline) ->
select_session(Candidates, Max).
select_session([] = _Candidates, _Max) ->
- ?hcrd("select session - no candicate", []),
+ ?hcrd("select session - no candidate", []),
no_connection;
select_session(Candidates, Max) ->
NewCandidates =
diff --git a/lib/inets/src/http_server/httpd_example.erl b/lib/inets/src/http_server/httpd_example.erl
index 52f5fa03a9..37e4f97bc0 100644
--- a/lib/inets/src/http_server/httpd_example.erl
+++ b/lib/inets/src/http_server/httpd_example.erl
@@ -22,7 +22,7 @@
-export([print/1]).
-export([get/2, put/2, post/2, yahoo/2, test1/2, get_bin/2, peer/2,new_status_and_location/2]).
--export([newformat/3, post_chunked/3]).
+-export([newformat/3, post_chunked/3, post_204/3]).
%% These are used by the inets test-suite
-export([delay/1, chunk_timeout/3]).
@@ -151,6 +151,12 @@ post_chunked(SessionID, _Env, {last, _Body, undefined} = _Bodychunk) ->
post_chunked(_, _, _Body) ->
exit(body_not_chunked).
+post_204(SessionID, _Env, _Input) ->
+ mod_esi:deliver(SessionID,
+ ["Status: 204 No Content" ++ "\r\n\r\n"]),
+ mod_esi:deliver(SessionID, []).
+
+
newformat(SessionID,_,_) ->
mod_esi:deliver(SessionID, "Content-Type:text/html\r\n\r\n"),
mod_esi:deliver(SessionID, top("new esi format test")),
diff --git a/lib/inets/src/http_server/httpd_file.erl b/lib/inets/src/http_server/httpd_file.erl
index fb71834e95..bf7554bd08 100644
--- a/lib/inets/src/http_server/httpd_file.erl
+++ b/lib/inets/src/http_server/httpd_file.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/inets/src/http_server/mod_esi.erl b/lib/inets/src/http_server/mod_esi.erl
index 21aafa7f7b..443b7ee564 100644
--- a/lib/inets/src/http_server/mod_esi.erl
+++ b/lib/inets/src/http_server/mod_esi.erl
@@ -394,7 +394,16 @@ deliver_webpage_chunk(#mod{config_db = Db} = ModData, Pid, Timeout) ->
Continue;
{Headers, Body} ->
{ok, NewHeaders, StatusCode} = httpd_esi:handle_headers(Headers),
- IsDisableChunkedSend = httpd_response:is_disable_chunked_send(Db),
+ %% All 1xx (informational), 204 (no content), and 304 (not modified)
+ %% responses MUST NOT include a message-body, and thus are always
+ %% terminated by the first empty line after the header fields.
+ %% This implies that chunked encoding MUST NOT be used for these
+ %% status codes.
+ IsDisableChunkedSend =
+ httpd_response:is_disable_chunked_send(Db) orelse
+ StatusCode =:= 204 orelse %% No Content
+ StatusCode =:= 304 orelse %% Not Modified
+ (100 =< StatusCode andalso StatusCode =< 199), %% Informational
case (ModData#mod.http_version =/= "HTTP/1.1") or
(IsDisableChunkedSend) of
true ->
@@ -405,8 +414,8 @@ deliver_webpage_chunk(#mod{config_db = Db} = ModData, Pid, Timeout) ->
send_headers(ModData, StatusCode,
[{"transfer-encoding",
"chunked"} | NewHeaders])
- end,
- handle_body(Pid, ModData, Body, Timeout, length(Body),
+ end,
+ handle_body(Pid, ModData, Body, Timeout, length(Body),
IsDisableChunkedSend);
timeout ->
send_headers(ModData, 504, [{"connection", "close"}]),
diff --git a/lib/inets/src/inets_app/inets.appup.src b/lib/inets/src/inets_app/inets.appup.src
index 0dcf66265e..b197590bfd 100644
--- a/lib/inets/src/inets_app/inets.appup.src
+++ b/lib/inets/src/inets_app/inets.appup.src
@@ -18,10 +18,12 @@
%% %CopyrightEnd%
{"%VSN%",
[
+ {<<"7\\..*">>,[{restart_application, inets}]},
{<<"6\\..*">>,[{restart_application, inets}]},
{<<"5\\..*">>,[{restart_application, inets}]}
],
[
+ {<<"7\\..*">>,[{restart_application, inets}]},
{<<"6\\..*">>,[{restart_application, inets}]},
{<<"5\\..*">>,[{restart_application, inets}]}
]
diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl
index 6e048a4d56..3d375222b5 100644
--- a/lib/inets/test/httpc_SUITE.erl
+++ b/lib/inets/test/httpc_SUITE.erl
@@ -169,7 +169,8 @@ misc() ->
[
server_does_not_exist,
timeout_memory_leak,
- wait_for_whole_response
+ wait_for_whole_response,
+ post_204_chunked
].
sim_mixed() ->
@@ -1391,6 +1392,59 @@ wait_for_whole_response(Config) when is_list(Config) ->
ReqSeqNumServer ! shutdown.
%%--------------------------------------------------------------------
+post_204_chunked() ->
+ [{doc,"Test that chunked encoded 204 responses do not freeze the http client"}].
+post_204_chunked(_Config) ->
+ Msg = "HTTP/1.1 204 No Content\r\n" ++
+ "Date: Thu, 23 Aug 2018 13:36:29 GMT\r\n" ++
+ "Content-Type: text/html\r\n" ++
+ "Server: inets/6.5.2.3\r\n" ++
+ "Cache-Control: no-cache\r\n" ++
+ "Pragma: no-cache\r\n" ++
+ "Expires: Fri, 24 Aug 2018 07:49:35 GMT\r\n" ++
+ "Transfer-Encoding: chunked\r\n" ++
+ "\r\n",
+ Chunk = "0\r\n\r\n",
+
+ {ok, ListenSocket} = gen_tcp:listen(0, [{active,once}, binary]),
+ {ok,{_,Port}} = inet:sockname(ListenSocket),
+ spawn(fun () -> custom_server(Msg, Chunk, ListenSocket) end),
+
+ {ok,Host} = inet:gethostname(),
+ End = "/cgi-bin/erl/httpd_example:post_204",
+ URL = ?URL_START ++ Host ++ ":" ++ integer_to_list(Port) ++ End,
+ {ok, _} = httpc:request(post, {URL, [], "text/html", []}, [], []),
+ timer:sleep(500),
+ %% Second request times out in the faulty case.
+ {ok, _} = httpc:request(post, {URL, [], "text/html", []}, [], []).
+
+custom_server(Msg, Chunk, ListenSocket) ->
+ {ok, Accept} = gen_tcp:accept(ListenSocket),
+ receive_packet(),
+ send_response(Msg, Chunk, Accept),
+ custom_server_loop(Msg, Chunk, Accept).
+
+custom_server_loop(Msg, Chunk, Accept) ->
+ receive_packet(),
+ send_response(Msg, Chunk, Accept),
+ custom_server_loop(Msg, Chunk, Accept).
+
+send_response(Msg, Chunk, Socket) ->
+ inet:setopts(Socket, [{active, once}]),
+ gen_tcp:send(Socket, Msg),
+ timer:sleep(250),
+ gen_tcp:send(Socket, Chunk).
+
+receive_packet() ->
+ receive
+ {tcp, _, Msg} ->
+ ct:log("Message received: ~p", [Msg])
+ after
+ 1000 ->
+ ct:fail("Timeout: did not recive packet")
+ end.
+
+%%--------------------------------------------------------------------
stream_fun_server_close() ->
[{doc, "Test that an error msg is received when using a receiver fun as stream target"}].
stream_fun_server_close(Config) when is_list(Config) ->
diff --git a/lib/inets/test/httpd_SUITE.erl b/lib/inets/test/httpd_SUITE.erl
index c5751e79a6..5b6740fba3 100644
--- a/lib/inets/test/httpd_SUITE.erl
+++ b/lib/inets/test/httpd_SUITE.erl
@@ -120,7 +120,7 @@ groups() ->
disturbing_0_9,
reload_config_file
]},
- {post, [], [chunked_post, chunked_chunked_encoded_post]},
+ {post, [], [chunked_post, chunked_chunked_encoded_post, post_204]},
{basic_auth, [], [basic_auth_1_1, basic_auth_1_0, basic_auth_0_9]},
{auth_api, [], [auth_api_1_1, auth_api_1_0, auth_api_0_9
]},
@@ -753,6 +753,42 @@ chunked_chunked_encoded_post(Config) when is_list(Config) ->
[{http_version, "HTTP/1.1"} | Config],
[{statuscode, 200}]).
+%%-------------------------------------------------------------------------
+post_204() ->
+ [{doc,"Test that 204 responses are not chunk encoded"}].
+post_204(Config) ->
+ Host = proplists:get_value(host, Config),
+ Port = proplists:get_value(port, Config),
+ SockType = proplists:get_value(type, Config),
+ TranspOpts = transport_opts(SockType, Config),
+ Request = "POST /cgi-bin/erl/httpd_example:post_204 ",
+
+ try inets_test_lib:connect_bin(SockType, Host, Port, TranspOpts) of
+ {ok, Socket} ->
+ RequestStr = http_request(Request, "HTTP/1.1", Host),
+ ok = inets_test_lib:send(SockType, Socket, RequestStr),
+ receive
+ {tcp, Socket, Data} ->
+ case binary:match(Data, <<"chunked">>,[]) of
+ nomatch ->
+ ok;
+ {_, _} ->
+ ct:fail("Chunked encoding detected.")
+ end
+ after 2000 ->
+ ct:fail(connection_timed_out)
+ end;
+ ConnectError ->
+ ct:fail({connect_error, ConnectError,
+ [SockType, Host, Port, TranspOpts]})
+ catch
+ T:E ->
+ ct:fail({connect_failure,
+ [{type, T},
+ {error, E},
+ {stacktrace, erlang:get_stacktrace()},
+ {args, [SockType, Host, Port, TranspOpts]}]})
+ end.
%%-------------------------------------------------------------------------
htaccess_1_1(Config) when is_list(Config) ->
@@ -2047,6 +2083,7 @@ head_status(_) ->
basic_conf() ->
[{modules, [mod_alias, mod_range, mod_responsecontrol,
mod_trace, mod_esi, mod_cgi, mod_get, mod_head]}].
+
not_sup_conf() ->
[{modules, [mod_get]}].
diff --git a/lib/inets/vsn.mk b/lib/inets/vsn.mk
index b76390ad66..26adb854e1 100644
--- a/lib/inets/vsn.mk
+++ b/lib/inets/vsn.mk
@@ -19,6 +19,6 @@
# %CopyrightEnd%
APPLICATION = inets
-INETS_VSN = 7.0
+INETS_VSN = 7.0.2
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(INETS_VSN)$(PRE_VSN)"
diff --git a/lib/jinterface/doc/src/Makefile b/lib/jinterface/doc/src/Makefile
index 6f1ecc8dea..d80bb38ec1 100644
--- a/lib/jinterface/doc/src/Makefile
+++ b/lib/jinterface/doc/src/Makefile
@@ -3,7 +3,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2000-2017. All Rights Reserved.
+# Copyright Ericsson AB 2000-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/lib/jinterface/doc/src/notes.xml b/lib/jinterface/doc/src/notes.xml
index 640712ad98..e4bfddcd17 100644
--- a/lib/jinterface/doc/src/notes.xml
+++ b/lib/jinterface/doc/src/notes.xml
@@ -31,6 +31,21 @@
</header>
<p>This document describes the changes made to the Jinterface application.</p>
+<section><title>Jinterface 1.9.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Jinterface 1.9</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/jinterface/vsn.mk b/lib/jinterface/vsn.mk
index f527a83092..a8dc815145 100644
--- a/lib/jinterface/vsn.mk
+++ b/lib/jinterface/vsn.mk
@@ -1 +1 @@
-JINTERFACE_VSN = 1.9
+JINTERFACE_VSN = 1.9.1
diff --git a/lib/kernel/doc/src/gen_sctp.xml b/lib/kernel/doc/src/gen_sctp.xml
index 737800c6b1..1e08b25f66 100644
--- a/lib/kernel/doc/src/gen_sctp.xml
+++ b/lib/kernel/doc/src/gen_sctp.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2007</year><year>2016</year>
+ <year>2007</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -331,6 +331,37 @@ connect(Socket, Ip, Port>,
with <anno>SockType</anno> <c>seqpacket</c>, and with reasonably large
<seealso marker="inet#option-sndbuf">kernel</seealso> and driver
<seealso marker="inet#option-buffer">buffers</seealso>.</p>
+ <p>
+ If the socket is in
+ <seealso marker="#option-active">passive</seealso>
+ mode data can be received through the
+ <seealso marker="#recv/1"><c>recv/1,2</c></seealso>
+ calls.
+ </p>
+ <p>
+ If the socket is in
+ <seealso marker="#option-active">active</seealso>
+ mode data received data is delivered to the controlling process
+ as messages:
+ </p>
+ <code type="none">
+{sctp, <anno>Socket</anno>, FromIP, FromPort, {AncData, Data}}
+ </code>
+ <p>
+ See
+ <seealso marker="#recv/1"><c>recv/1,2</c></seealso>
+ for a description of the message fields.
+ </p>
+ <note>
+ <p>
+ This message format unfortunately differs slightly from the
+ <seealso marker="gen_udp#open/1"><c>gen_udp</c></seealso>
+ message format with ancillary data,
+ and from the
+ <seealso marker="#recv/1"><c>recv/1,2</c></seealso>
+ return tuple format.
+ </p>
+ </note>
</desc>
</func>
@@ -380,6 +411,19 @@ connect(Socket, Ip, Port>,
socket option
<seealso marker="#option-sctp_get_peer_addr_info"><c>sctp_get_peer_addr_info</c></seealso>,
but this does still not produce the stream number).</p>
+ <p>
+ <c><anno>AncData</anno></c> may also contain
+ <seealso marker="inet#type-ancillary_data">
+ ancillary data
+ </seealso>
+ from the socket
+ <seealso marker="#type-option">options</seealso>
+ <seealso marker="inet#option-recvtos"><c>recvtos</c></seealso>,
+ <seealso marker="inet#option-recvtclass"><c>recvtclass</c></seealso>
+ or
+ <seealso marker="inet#option-recvttl"><c>recvttl</c></seealso>,
+ if that is supported by the platform for the socket.
+ </p>
<p>The <c><anno>Data</anno></c> received can be a <c>binary()</c>
or a <c>list()</c> of bytes (integers in the range 0 through 255)
depending on the socket mode, or an SCTP event.</p>
@@ -544,12 +588,25 @@ connect(Socket, Ip, Port>,
<seealso marker="#recv/1"><c>recv</c></seealso> call
to retrieve the available data from the socket.</p>
</item>
+ <item>
+ <p>
+ If <c>true|once|N</c> (active modes)
+ received data or events are sent to the owning process.
+ See <seealso marker="#open/0"><c>open/0..2</c></seealso>
+ for the message format.
+ </p>
+ </item>
<item>
- <p>If <c>true</c> (full active mode), the pending data or events are
- sent to the owning process.</p>
- <p>Notice that this can cause the message queue to overflow,
- as there is no way to throttle the sender in this case
- (no flow control).</p>
+ <p>
+ If <c>true</c> (full active mode) there is no flow control.
+ </p>
+ <note>
+ <p>
+ Note that this can cause the message queue to overflow
+ causing for example the virtual machine
+ to run out of memory and crash.
+ </p>
+ </note>
</item>
<item>
<p>If <c>once</c>, only one message is automatically placed
diff --git a/lib/kernel/doc/src/gen_tcp.xml b/lib/kernel/doc/src/gen_tcp.xml
index e6104b0c76..24d63693fd 100644
--- a/lib/kernel/doc/src/gen_tcp.xml
+++ b/lib/kernel/doc/src/gen_tcp.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2017</year>
+ <year>1997</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -70,6 +70,32 @@ do_recv(Sock, Bs) ->
<name name="option"/>
</datatype>
<datatype>
+ <name name="pktoptions_value"/>
+ <desc>
+ <p>
+ If the platform implements the IPv4 option
+ <c>IP_PKTOPTIONS</c>, or the IPv6 option
+ <c>IPV6_PKTOPTIONS</c> or <c>IPV6_2292PKTOPTIONS</c> for the socket
+ this value is returned from
+ <seealso marker="inet#getopts/2"><c>inet:getopts/2</c></seealso>
+ when called with the option name
+ <seealso marker="#type-option_name"><c>pktoptions</c></seealso>.
+ </p>
+ <note>
+ <p>
+ This option appears to be VERY Linux specific,
+ and its existence in future Linux kernel versions
+ is also worrying since the option is part of RFC 2292
+ which is since long (2003) obsoleted by RFC 3542
+ that <em>explicitly</em> removes this possibility to get
+ packet information from a stream socket.
+ For comparision: it has existed in FreeBSD but is now removed,
+ at least since FreeBSD 10.
+ </p>
+ </note>
+ </desc>
+ </datatype>
+ <datatype>
<name name="option_name"/>
</datatype>
<datatype>
diff --git a/lib/kernel/doc/src/gen_udp.xml b/lib/kernel/doc/src/gen_udp.xml
index f79566ef71..840ca3c188 100644
--- a/lib/kernel/doc/src/gen_udp.xml
+++ b/lib/kernel/doc/src/gen_udp.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2016</year>
+ <year>1997</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -147,7 +147,21 @@
at the opened port, if the socket is in an active mode, the packets
are delivered as messages to the controlling process:</p>
<code type="none">
-{udp, Socket, IP, InPortNo, Packet}</code>
+{udp, Socket, IP, InPortNo, Packet} % Without ancillary data
+{udp, Socket, IP, InPortNo, AncData, Packet} % With ancillary data
+ </code>
+ <p>
+ The message contains an <c>AncData</c> field
+ if any of the socket
+ <seealso marker="#type-option">options</seealso>
+ <seealso marker="inet#option-recvtos"><c>recvtos</c></seealso>,
+ <seealso marker="inet#option-recvtclass"><c>recvtclass</c></seealso>
+ or
+ <seealso marker="inet#option-recvttl"><c>recvttl</c></seealso>
+ are active, otherwise it does not.
+ </p>
+ <p>
+ </p>
<p>If the socket is not in an active mode, data can be
retrieved through the
<seealso marker="#recv/2"><c>recv/2,3</c></seealso> calls.
@@ -179,9 +193,22 @@
<name name="recv" arity="3"/>
<fsummary>Receive a packet from a passive socket.</fsummary>
<desc>
- <p>Receives a packet from a socket in passive mode. Optional parameter
+ <p>
+ Receives a packet from a socket in passive mode. Optional parameter
<c><anno>Timeout</anno></c> specifies a time-out in milliseconds.
- Defaults to <c>infinity</c>.</p>
+ Defaults to <c>infinity</c>.
+ </p>
+ <p>
+ If any of the socket
+ <seealso marker="#type-option">options</seealso>
+ <seealso marker="inet#option-recvtos"><c>recvtos</c></seealso>,
+ <seealso marker="inet#option-recvtclass"><c>recvtclass</c></seealso>
+ or
+ <seealso marker="inet#option-recvttl"><c>recvttl</c></seealso>
+ are active, the <c><anno>RecvData</anno></c> tuple contains an
+ <c><anno>AncData</anno></c> field,
+ otherwise it does not.
+ </p>
</desc>
</func>
diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml
index f281d61459..ed775d67eb 100644
--- a/lib/kernel/doc/src/inet.xml
+++ b/lib/kernel/doc/src/inet.xml
@@ -177,6 +177,27 @@ fe80::204:acff:fe17:bf38
</desc>
</datatype>
<datatype>
+ <name name="ancillary_data"/>
+ <desc>
+ <p>
+ Ancillary data received with the data packet
+ or read with the socket option
+ <seealso marker="gen_tcp#type-pktoptions_value">
+ <c>pktoptions</c>
+ </seealso>
+ from a TCP socket.
+ </p>
+ <p>
+ The value(s) correspond to the currently active socket
+ <seealso marker="#type-socket_setopt">options</seealso>
+ <seealso marker="inet#option-recvtos"><c>recvtos</c></seealso>,
+ <seealso marker="inet#option-recvtclass"><c>recvtclass</c></seealso>
+ and
+ <seealso marker="inet#option-recvttl"><c>recvttl</c></seealso>.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
<name name="posix"/>
<desc>
<p>An atom that is named from the POSIX error codes used in Unix,
@@ -344,7 +365,11 @@ fe80::204:acff:fe17:bf38
<desc>
<p>Gets one or more options for a socket. For a list of available
options, see
- <seealso marker="#setopts/2"><c>setopts/2</c></seealso>.</p>
+ <seealso marker="#setopts/2"><c>setopts/2</c></seealso>.
+ See also the description for the type
+ <seealso marker="gen_tcp#type-pktoptions_value">
+ <c>gen_tcp:pktoptions_value()</c>
+ </seealso>.</p>
<p>The number of elements in the returned
<c><anno>OptionValues</anno></c>
list does not necessarily correspond to the number of options
@@ -360,7 +385,7 @@ fe80::204:acff:fe17:bf38
socket options not (explicitly) supported by the emulator. The
use of raw socket options makes the code non-portable, but
allows the Erlang programmer to take advantage of unusual features
- present on the current platform.</p>
+ present on a particular platform.</p>
<p><c>RawOptReq</c> consists of tag <c>raw</c> followed
by the protocol level, the option number, and either a binary
or the size, in bytes, of the
@@ -1115,6 +1140,100 @@ setcap cap_sys_admin,cap_sys_ptrace,cap_dac_read_search+epi beam.smp</code>
the socket. You are encouraged to use
<seealso marker="#getopts/2"><c>getopts/2</c></seealso>
to retrieve the size set by your operating system.</p>
+ <marker id="option-recvtclass"></marker>
+ </item>
+ <tag><c>{recvtclass, Boolean}</c></tag>
+ <item>
+ <p>
+ If set to <c>true</c> activates returning the received
+ <c>TCLASS</c> value on platforms that implements
+ the protocol <c>IPPROTO_IPV6</c>
+ option <c>IPV6_RECVTCLASS</c> or <c>IPV6_2292RECVTCLASS</c>
+ for the socket.
+ The value is returned as a <c>{tclass,TCLASS}</c> tuple
+ regardless of if the platform returns an <c>IPV6_TCLASS</c>
+ or an <c>IPV6_RECVTCLASS</c> CMSG value.
+ </p>
+ <p>
+ For packet oriented sockets that supports receiving
+ ancillary data with the payload data
+ (<c>gen_udp</c> and <c>gen_sctp</c>),
+ the <c>TCLASS</c> value is returned
+ in an extended return tuple contained in an
+ <seealso marker="inet#type-ancillary_data">
+ ancillary data
+ </seealso>
+ list.
+ For stream oriented sockets (<c>gen_tcp</c>)
+ the only way to get the <c>TCLASS</c>
+ value is if the platform supports the
+ <seealso marker="gen_tcp#type-pktoptions_value">
+ <c>pktoptions</c>
+ </seealso>
+ option.
+ </p>
+ <marker id="option-recvtos"></marker>
+ </item>
+ <tag><c>{recvtos, Boolean}</c></tag>
+ <item>
+ <p>
+ If set to <c>true</c> activates returning the received
+ <c>TOS</c> value on platforms that implements
+ the protocol <c>IPPROTO_IP</c> option <c>IP_RECVTOS</c>
+ for the socket.
+ The value is returned as a <c>{tos,TOS}</c> tuple
+ regardless of if the platform returns an <c>IP_TOS</c>
+ or an <c>IP_RECVTOS</c> CMSG value.
+ </p>
+ <p>
+ For packet oriented sockets that supports receiving
+ ancillary data with the payload data
+ (<c>gen_udp</c> and <c>gen_sctp</c>),
+ the <c>TOS</c> value is returned
+ in an extended return tuple contained in an
+ <seealso marker="inet#type-ancillary_data">
+ ancillary data
+ </seealso>
+ list.
+ For stream oriented sockets (<c>gen_tcp</c>)
+ the only way to get the <c>TOS</c>
+ value is if the platform supports the
+ <seealso marker="gen_tcp#type-pktoptions_value">
+ <c>pktoptions</c>
+ </seealso>
+ option.
+ </p>
+ <marker id="option-recvttl"></marker>
+ </item>
+ <tag><c>{recvttl, Boolean}</c></tag>
+ <item>
+ <p>
+ If set to <c>true</c> activates returning the received
+ <c>TTL</c> value on platforms that implements
+ the protocol <c>IPPROTO_IP</c> option <c>IP_RECVTTL</c>
+ for the socket.
+ The value is returned as a <c>{ttl,TTL}</c> tuple
+ regardless of if the platform returns an <c>IP_TTL</c>
+ or an <c>IP_RECVTTL</c> CMSG value.
+ </p>
+ <p>
+ For packet oriented sockets that supports receiving
+ ancillary data with the payload data
+ (<c>gen_udp</c> and <c>gen_sctp</c>),
+ the <c>TTL</c> value is returned
+ in an extended return tuple contained in an
+ <seealso marker="inet#type-ancillary_data">
+ ancillary data
+ </seealso>
+ list.
+ For stream oriented sockets (<c>gen_tcp</c>)
+ the only way to get the <c>TTL</c>
+ value is if the platform supports the
+ <seealso marker="gen_tcp#type-pktoptions_value">
+ <c>pktoptions</c>
+ </seealso>
+ option.
+ </p>
</item>
<tag><c>{reuseaddr, Boolean}</c></tag>
<item>
diff --git a/lib/kernel/doc/src/logger.xml b/lib/kernel/doc/src/logger.xml
index a4d6efa2d8..464c65ba76 100644
--- a/lib/kernel/doc/src/logger.xml
+++ b/lib/kernel/doc/src/logger.xml
@@ -527,7 +527,7 @@ start(_, []) ->
Error -> Error
end.</code>
<p>This reads the <c>logger</c> configuration parameter from
- the <c>my_all</c> application and starts the configured
+ the <c>my_app</c> application and starts the configured
handlers. The contents of the configuration use the same
rules as the
<seealso marker="logger_chapter#handler-configuration">logger handler configuration</seealso>.
diff --git a/lib/kernel/doc/src/logger_chapter.xml b/lib/kernel/doc/src/logger_chapter.xml
index c2cdf38a64..fdb21fa24c 100644
--- a/lib/kernel/doc/src/logger_chapter.xml
+++ b/lib/kernel/doc/src/logger_chapter.xml
@@ -208,11 +208,13 @@
coversion to a string:</p>
<pre>fun((<seealso marker="logger#type-report"><c>logger:report()</c></seealso>,<seealso marker="logger#type-report_cb_config"><c>logger:report_cb_config()</c></seealso>) -> <seealso marker="stdlib:unicode#type-chardata"><c>unicode:chardata()</c></seealso>)
</pre>
- <p>The fun must obey the <c>encoding</c>, <c>depth</c>
- and <c>chars_limit</c> parameters provided in the second
- argument, as the formatter cannot do anything useful of these
- parameters with the returned string. This variant is used when
- the formatting of the report depends on the size and encoding
+ <p>The fun must obey the <c>depth</c> and <c>chars_limit</c>
+ parameters provided in the second argument, as the formatter
+ cannot do anything useful of these parameters with the
+ returned string. The extra data also contains a field named
+ <c>single_line</c>, indicating if the printed log message may
+ contain line breaks or not. This variant is used when the
+ formatting of the report depends on the size or single line
parameters.</p>
<p>Example, format string and arguments:</p>
<code>logger:error("The file does not exist: ~ts",[Filename])</code>
@@ -507,7 +509,7 @@ logger:debug(#{got => connection_request, id => Id, state => State},
<c>logger_level</c></seealso>. It is changed during
runtime with <seealso marker="logger#set_primary_config-2">
<c>logger:set_primary_config(level,Level)</c></seealso>.</p>
- <p>Defaults to <c>info</c>.</p>
+ <p>Defaults to <c>notice</c>.</p>
</item>
<tag><c>filters = [{FilterId,Filter}]</c></tag>
<item>
diff --git a/lib/kernel/doc/src/logger_formatter.xml b/lib/kernel/doc/src/logger_formatter.xml
index 5a060fd42b..24772fd6c4 100644
--- a/lib/kernel/doc/src/logger_formatter.xml
+++ b/lib/kernel/doc/src/logger_formatter.xml
@@ -82,13 +82,6 @@
in STDLIB.</p>
<p>Defaults to <c>unlimited</c>.</p>
</item>
- <tag><c>encoding = </c><seealso marker="stdlib:unicode#type-encoding">
- <c>unicode:encoding()</c></seealso></tag>
- <item>
- <p>This parameter must reflect the encoding of the device
- that the handler prints to.</p>
- <p>Defaults to <c>utf8</c></p>
- </item>
<tag><c>legacy_header = boolean()</c></tag>
<item>
<p>If set to <c>true</c> a header field is added to
diff --git a/lib/kernel/doc/src/logger_std_h.xml b/lib/kernel/doc/src/logger_std_h.xml
index b526ed037d..fcd8189bae 100644
--- a/lib/kernel/doc/src/logger_std_h.xml
+++ b/lib/kernel/doc/src/logger_std_h.xml
@@ -59,13 +59,22 @@
<item>
<p>This has the value <c>standard_io</c>, <c>standard_error</c>,
<c>{file,LogFileName}</c>, or <c>{file,LogFileName,LogFileOpts}</c>.</p>
+ <p>If <c>LogFileOpts</c> is specified, it replaces the default
+ list of options used when opening the log file. The default
+ list is <c>[raw,append,delayed_write]</c>. One reason to do
+ so can be to change <c>append</c> to, for
+ example, <c>write</c>, ensuring that the old log is
+ truncated when a node is restarted. See the reference manual
+ for <seealso marker="file#open-2"><c>file:open/2</c></seealso>
+ for more information about file options.</p>
+ <p>Log files are always UTF-8 encoded. The encoding can not be
+ changed by setting the option <c>{encoding,Encoding}</c>
+ in <c>LogFileOpts</c>.</p>
+ <p>Notice that the standard handler does not have support for
+ circular logging. Use the disk_log handler,
+ <seealso marker="logger_disk_log_h"><c>logger_disk_log_h</c></seealso>,
+ for this.</p>
<p> Defaults to <c>standard_io</c>.</p>
- <p>It is recommended not to specify <c>LogFileOpts</c> unless absolutely
- necessary. The default options used by the handler to open a file for logging are
- <c>raw</c>, <c>append</c>, and <c>delayed_write</c>. Notice that the standard
- handler does not have support for circular logging. Use the disk_log handler,
- <seealso marker="logger_disk_log_h"><c>logger_disk_log_h</c></seealso>,
- for this.</p>
</item>
<tag><c>filesync_repeat_interval</c></tag>
<item>
@@ -73,12 +82,12 @@
a file sync operation to write buffered data to disk. The handler attempts
the operation repeatedly, but only performs a new sync if something has
actually been logged.</p>
- <p>Defaults to <c>5000</c> milliseconds.</p>
<p>If <c>no_repeat</c> is set as value, the repeated file sync operation
is disabled, and it is the operating system settings that determine
how quickly or slowly data is written to disk. The user can also call
the <seealso marker="logger_std_h#filesync-1"><c>filesync/1</c></seealso>
function to perform a file sync.</p>
+ <p>Defaults to <c>5000</c> milliseconds.</p>
</item>
</taglist>
<p>Other configuration parameters exist, to be used for customizing
diff --git a/lib/kernel/doc/src/net_kernel.xml b/lib/kernel/doc/src/net_kernel.xml
index d3bd7365e2..bfbe7a6470 100644
--- a/lib/kernel/doc/src/net_kernel.xml
+++ b/lib/kernel/doc/src/net_kernel.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2017</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml
index 5884f93878..8188ede6a2 100644
--- a/lib/kernel/doc/src/notes.xml
+++ b/lib/kernel/doc/src/notes.xml
@@ -31,6 +31,128 @@
</header>
<p>This document describes the changes made to the Kernel application.</p>
+<section><title>Kernel 6.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The values <c>all</c> and <c>none</c> are documented as
+ valid value for the Kernel configuration parameter
+ <c>logger_level</c>, but would cause a crash during node
+ start. This is now corrected.</p>
+ <p>
+ Own Id: OTP-15143</p>
+ </item>
+ <item>
+ <p>
+ Fix some potential buggy behavior in how ticks are sent
+ on inter node distribution connections. Tick is now sent
+ to c-node even if there are unsent buffered data, as
+ c-nodes need ticks in order to send reply ticks. The
+ amount of sent data was also calculated wrongly when
+ ticks were suppressed due to unsent buffered data.</p>
+ <p>
+ Own Id: OTP-15162 Aux Id: ERIERL-191 </p>
+ </item>
+ <item>
+ <p>
+ Non semantic change in dist_util.erl to silence dialyzer
+ warning.</p>
+ <p>
+ Own Id: OTP-15170</p>
+ </item>
+ <item>
+ <p>
+ Fixed <c>net_kernel:connect_node(node())</c> to return
+ <c>true</c> (and do nothing) as it always has before
+ OTP-21.0. Also documented this successful "self connect"
+ as the expected behavior.</p>
+ <p>
+ Own Id: OTP-15182 Aux Id: ERL-643 </p>
+ </item>
+ <item>
+ <p>
+ The single_line option on logger_formatter would in some
+ cases add an unwanted comma after the association arrows
+ in a map. This is now corrected.</p>
+ <p>
+ Own Id: OTP-15228</p>
+ </item>
+ <item>
+ <p>
+ Improved robustness of distribution connection setup. In
+ OTP-21.0 a truly asynchronous connection setup was
+ introduced. This is further improvement on that work to
+ make the emulator more robust and also be able to recover
+ in cases when involved Erlang processes misbehave.</p>
+ <p>
+ Own Id: OTP-15297 Aux Id: OTP-15279, OTP-15280 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ A new macro, <c>?LOG(Level,...)</c>, is added. This is
+ equivalent to the existing <c>?LOG_&lt;LEVEL&gt;(...)</c>
+ macros.</p>
+ <p>
+ A new variant of Logger report callback is added, which
+ takes an extra argument containing options for size
+ limiting and line breaks. Module <c>proc_lib</c> in
+ <c>STDLIB</c> uses this for crash reports.</p>
+ <p>
+ Logger configuration is now checked a bit more for
+ errors.</p>
+ <p>
+ Own Id: OTP-15132</p>
+ </item>
+ <item>
+ <p>
+ The socket options <c>recvtos</c>, <c>recvttl</c>,
+ <c>recvtclass</c> and <c>pktoptions</c> have been
+ implemented in the socket modules. See the documentation
+ for the <c>gen_tcp</c>, <c>gen_udp</c> and <c>inet</c>
+ modules. Note that support for these in the runtime
+ system is platform dependent. Especially for
+ <c>pktoptions</c> which is very Linux specific and
+ obsoleted by the RFCs that defined it.</p>
+ <p>
+ Own Id: OTP-15145 Aux Id: ERIERL-187 </p>
+ </item>
+ <item>
+ <p>
+ Add <c>logger:set_application_level/2</c> for setting the
+ logger level of all modules in one application.</p>
+ <p>
+ Own Id: OTP-15146</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Kernel 6.0.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed bug in <c>net_kernel</c> that could cause an
+ emulator crash if certain connection attempts failed. Bug
+ exists since kernel-6.0 (OTP-21.0).</p>
+ <p>
+ Own Id: OTP-15280 Aux Id: ERIERL-226, OTP-15279 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Kernel 6.0</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/kernel/src/error_logger.erl b/lib/kernel/src/error_logger.erl
index ad8c937882..e324be5290 100644
--- a/lib/kernel/src/error_logger.erl
+++ b/lib/kernel/src/error_logger.erl
@@ -147,14 +147,27 @@ do_log(Level,{report,Msg},#{?MODULE:=#{tag:=Tag}}=Meta) ->
_ ->
%% From logger call which added error_logger data to
%% obtain backwards compatibility with error_logger:*_msg/1,2
- RCBFun=maps:get(report_cb,Meta,fun logger:format_report/1),
- try RCBFun(Msg) of
- {F,A} when is_list(F), is_list(A) ->
- {F,A};
- Other ->
- {"REPORT_CB ERROR: ~tp; Returned: ~tp",[Msg,Other]}
- catch C:R ->
- {"REPORT_CB CRASH: ~tp; Reason: ~tp",[Msg,{C,R}]}
+ case maps:get(report_cb,Meta,fun logger:format_report/1) of
+ RCBFun when is_function(RCBFun,1) ->
+ try RCBFun(Msg) of
+ {F,A} when is_list(F), is_list(A) ->
+ {F,A};
+ Other ->
+ {"REPORT_CB ERROR: ~tp; Returned: ~tp",[Msg,Other]}
+ catch C:R ->
+ {"REPORT_CB CRASH: ~tp; Reason: ~tp",[Msg,{C,R}]}
+ end;
+ RCBFun when is_function(RCBFun,2) ->
+ try RCBFun(Msg,#{depth=>get_format_depth(),
+ chars_limit=>unlimited,
+ single_line=>false}) of
+ Chardata when ?IS_STRING(Chardata) ->
+ {"~ts",[Chardata]};
+ Other ->
+ {"REPORT_CB ERROR: ~tp; Returned: ~tp",[Msg,Other]}
+ catch C:R ->
+ {"REPORT_CB CRASH: ~tp; Reason: ~tp",[Msg,{C,R}]}
+ end
end
end,
notify(Level,Tag,Format,Args,Meta);
diff --git a/lib/kernel/src/gen_sctp.erl b/lib/kernel/src/gen_sctp.erl
index bf795ee9c6..d893d44079 100644
--- a/lib/kernel/src/gen_sctp.erl
+++ b/lib/kernel/src/gen_sctp.erl
@@ -66,7 +66,12 @@
{sctp_set_peer_primary_addr, #sctp_setpeerprim{}} |
{sctp_status, #sctp_status{}} |
{sndbuf, non_neg_integer()} |
- {tos, non_neg_integer()}.
+ {tos, non_neg_integer()} |
+ {tclass, non_neg_integer()} |
+ {ttl, non_neg_integer()} |
+ {recvtos, boolean()} |
+ {recvtclass, boolean()} |
+ {recvttl, boolean()}.
-type option_name() ::
active |
buffer |
@@ -97,7 +102,12 @@
sctp_set_peer_primary_addr |
sctp_status |
sndbuf |
- tos.
+ tos |
+ tclass |
+ ttl |
+ recvtos |
+ recvtclass |
+ recvttl.
-type sctp_socket() :: port().
-export_type([assoc_id/0, option/0, option_name/0, sctp_socket/0]).
@@ -365,7 +375,7 @@ send(S, AssocChange, Stream, Data) ->
Socket :: sctp_socket(),
FromIP :: inet:ip_address(),
FromPort :: inet:port_number(),
- AncData :: [#sctp_sndrcvinfo{}],
+ AncData :: [#sctp_sndrcvinfo{} | inet:ancillary_data()],
Data :: binary() | string() | #sctp_sndrcvinfo{}
| #sctp_assoc_change{} | #sctp_paddr_change{}
| #sctp_adaptation_event{},
@@ -382,7 +392,7 @@ recv(S) ->
Timeout :: timeout(),
FromIP :: inet:ip_address(),
FromPort :: inet:port_number(),
- AncData :: [#sctp_sndrcvinfo{}],
+ AncData :: [#sctp_sndrcvinfo{} | inet:ancillary_data()],
Data :: binary() | string() | #sctp_sndrcvinfo{}
| #sctp_assoc_change{} | #sctp_paddr_change{}
| #sctp_adaptation_event{},
diff --git a/lib/kernel/src/gen_tcp.erl b/lib/kernel/src/gen_tcp.erl
index c61411e814..7f7833ec23 100644
--- a/lib/kernel/src/gen_tcp.erl
+++ b/lib/kernel/src/gen_tcp.erl
@@ -62,7 +62,14 @@
{show_econnreset, boolean()} |
{sndbuf, non_neg_integer()} |
{tos, non_neg_integer()} |
+ {tclass, non_neg_integer()} |
+ {ttl, non_neg_integer()} |
+ {recvtos, boolean()} |
+ {recvtclass, boolean()} |
+ {recvttl, boolean()} |
{ipv6_v6only, boolean()}.
+-type pktoptions_value() ::
+ {pktoptions, inet:ancillary_data()}.
-type option_name() ::
active |
buffer |
@@ -81,6 +88,7 @@
nodelay |
packet |
packet_size |
+ pktoptions |
priority |
{raw,
Protocol :: non_neg_integer(),
@@ -94,6 +102,12 @@
show_econnreset |
sndbuf |
tos |
+ tclass |
+ ttl |
+ recvtos |
+ recvtclass |
+ recvttl |
+ pktoptions |
ipv6_v6only.
-type connect_option() ::
{ip, inet:socket_address()} |
@@ -119,7 +133,7 @@
-type socket() :: port().
-export_type([option/0, option_name/0, connect_option/0, listen_option/0,
- socket/0]).
+ socket/0, pktoptions_value/0]).
%%
%% Connect a socket
diff --git a/lib/kernel/src/gen_udp.erl b/lib/kernel/src/gen_udp.erl
index 44eef9f3c5..d6e8652e77 100644
--- a/lib/kernel/src/gen_udp.erl
+++ b/lib/kernel/src/gen_udp.erl
@@ -51,6 +51,11 @@
{reuseaddr, boolean()} |
{sndbuf, non_neg_integer()} |
{tos, non_neg_integer()} |
+ {tclass, non_neg_integer()} |
+ {ttl, non_neg_integer()} |
+ {recvtos, boolean()} |
+ {recvtclass, boolean()} |
+ {recvttl, boolean()} |
{ipv6_v6only, boolean()}.
-type option_name() ::
active |
@@ -76,6 +81,12 @@
reuseaddr |
sndbuf |
tos |
+ tclass |
+ ttl |
+ recvtos |
+ recvtclass |
+ recvttl |
+ pktoptions |
ipv6_v6only.
-type socket() :: port().
@@ -147,11 +158,13 @@ send(S, Packet) when is_port(S) ->
end.
-spec recv(Socket, Length) ->
- {ok, {Address, Port, Packet}} | {error, Reason} when
+ {ok, RecvData} | {error, Reason} when
Socket :: socket(),
Length :: non_neg_integer(),
+ RecvData :: {Address, Port, Packet} | {Address, Port, AncData, Packet},
Address :: inet:ip_address() | inet:returned_non_ip_address(),
Port :: inet:port_number(),
+ AncData :: inet:ancillary_data(),
Packet :: string() | binary(),
Reason :: not_owner | inet:posix().
@@ -164,12 +177,14 @@ recv(S,Len) when is_port(S), is_integer(Len) ->
end.
-spec recv(Socket, Length, Timeout) ->
- {ok, {Address, Port, Packet}} | {error, Reason} when
+ {ok, RecvData} | {error, Reason} when
Socket :: socket(),
Length :: non_neg_integer(),
Timeout :: timeout(),
+ RecvData :: {Address, Port, Packet} | {Address, Port, AncData, Packet},
Address :: inet:ip_address() | inet:returned_non_ip_address(),
Port :: inet:port_number(),
+ AncData :: inet:ancillary_data(),
Packet :: string() | binary(),
Reason :: not_owner | inet:posix().
diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl
index 73c53b9011..5dd68dc285 100644
--- a/lib/kernel/src/inet.erl
+++ b/lib/kernel/src/inet.erl
@@ -76,7 +76,7 @@
-export_type([address_family/0, socket_protocol/0, hostent/0, hostname/0, ip4_address/0,
ip6_address/0, ip_address/0, port_number/0,
local_address/0, socket_address/0, returned_non_ip_address/0,
- socket_setopt/0, socket_getopt/0,
+ socket_setopt/0, socket_getopt/0, ancillary_data/0,
posix/0, socket/0, stat_option/0]).
%% imports
-import(lists, [append/1, duplicate/2, filter/2, foldl/3]).
@@ -163,6 +163,9 @@
'recv_cnt' | 'recv_max' | 'recv_avg' | 'recv_oct' | 'recv_dvi' |
'send_cnt' | 'send_max' | 'send_avg' | 'send_oct' | 'send_pend'.
+-type ancillary_data() ::
+ [ {'tos', byte()} | {'tclass', byte()} | {'ttl', byte()} ].
+
%%% ---------------------------------
-spec get_rc() -> [{Par :: atom(), Val :: any()} |
@@ -302,7 +305,7 @@ setopts(Socket, Opts) ->
{'ok', OptionValues} | {'error', posix()} when
Socket :: socket(),
Options :: [socket_getopt()],
- OptionValues :: [socket_setopt()].
+ OptionValues :: [socket_setopt() | gen_tcp:pktoptions_value()].
getopts(Socket, Opts) ->
case prim_inet:getopts(Socket, Opts) of
@@ -722,6 +725,7 @@ stats() ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
connect_options() ->
[tos, tclass, priority, reuseaddr, keepalive, linger, sndbuf, recbuf, nodelay,
+ recvtos, recvtclass, ttl, recvttl,
header, active, packet, packet_size, buffer, mode, deliver, line_delimiter,
exit_on_close, high_watermark, low_watermark, high_msgq_watermark,
low_msgq_watermark, send_timeout, send_timeout_close, delay_send, raw,
@@ -790,6 +794,7 @@ con_add(Name, Val, #connect_opts{} = R, Opts, AllOpts) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
listen_options() ->
[tos, tclass, priority, reuseaddr, keepalive, linger, sndbuf, recbuf, nodelay,
+ recvtos, recvtclass, ttl, recvttl,
header, active, packet, buffer, mode, deliver, backlog, ipv6_v6only,
exit_on_close, high_watermark, low_watermark, high_msgq_watermark,
low_msgq_watermark, send_timeout, send_timeout_close, delay_send,
@@ -870,7 +875,7 @@ tcp_module_1(Opts, Address) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
udp_options() ->
[tos, tclass, priority, reuseaddr, sndbuf, recbuf, header, active, buffer, mode,
- deliver, ipv6_v6only,
+ recvtos, recvtclass, ttl, recvttl, deliver, ipv6_v6only,
broadcast, dontroute, multicast_if, multicast_ttl, multicast_loop,
add_membership, drop_membership, read_packets,raw,
high_msgq_watermark, low_msgq_watermark, bind_to_device].
@@ -940,8 +945,10 @@ udp_module(Opts) ->
% (*) passing of open FDs ("fdopen") is not supported.
sctp_options() ->
[ % The following are generic inet options supported for SCTP sockets:
- mode, active, buffer, tos, tclass, priority, dontroute, reuseaddr, linger, sndbuf,
- recbuf, ipv6_v6only, high_msgq_watermark, low_msgq_watermark,
+ mode, active, buffer, tos, tclass, ttl,
+ priority, dontroute, reuseaddr, linger,
+ recvtos, recvtclass, recvttl,
+ sndbuf, recbuf, ipv6_v6only, high_msgq_watermark, low_msgq_watermark,
bind_to_device,
% Other options are SCTP-specific (though they may be similar to their
diff --git a/lib/kernel/src/inet6_tcp.erl b/lib/kernel/src/inet6_tcp.erl
index a0d5d3df70..347b8b9a1b 100644
--- a/lib/kernel/src/inet6_tcp.erl
+++ b/lib/kernel/src/inet6_tcp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -167,7 +167,7 @@ listen(Port, Opts) ->
%% Accept
%%
accept(L) ->
- case prim_inet:accept(L) of
+ case prim_inet:accept(L, accept_family_opts()) of
{ok, S} ->
inet_db:register_socket(S, ?MODULE),
{ok,S};
@@ -175,13 +175,15 @@ accept(L) ->
end.
accept(L, Timeout) ->
- case prim_inet:accept(L, Timeout) of
+ case prim_inet:accept(L, Timeout, accept_family_opts()) of
{ok, S} ->
inet_db:register_socket(S, ?MODULE),
{ok,S};
Error -> Error
end.
+accept_family_opts() -> [tclass, recvtclass].
+
%%
%% Create a port/socket from a file descriptor
%%
diff --git a/lib/kernel/src/inet_int.hrl b/lib/kernel/src/inet_int.hrl
index 357e27826c..c8e09d18ad 100644
--- a/lib/kernel/src/inet_int.hrl
+++ b/lib/kernel/src/inet_int.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -157,6 +157,11 @@
-define(INET_LOPT_LINE_DELIM, 40).
-define(INET_OPT_TCLASS, 41).
-define(INET_OPT_BIND_TO_DEVICE, 42).
+-define(INET_OPT_RECVTOS, 43).
+-define(INET_OPT_RECVTCLASS, 44).
+-define(INET_OPT_PKTOPTIONS, 45).
+-define(INET_OPT_TTL, 46).
+-define(INET_OPT_RECVTTL, 47).
% Specific SCTP options: separate range:
-define(SCTP_OPT_RTOINFO, 100).
-define(SCTP_OPT_ASSOCINFO, 101).
diff --git a/lib/kernel/src/inet_tcp.erl b/lib/kernel/src/inet_tcp.erl
index dac6b3119d..f1e3116856 100644
--- a/lib/kernel/src/inet_tcp.erl
+++ b/lib/kernel/src/inet_tcp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -164,7 +164,7 @@ listen(Port, Opts) ->
%% Accept
%%
accept(L) ->
- case prim_inet:accept(L) of
+ case prim_inet:accept(L, accept_family_opts()) of
{ok, S} ->
inet_db:register_socket(S, ?MODULE),
{ok,S};
@@ -172,13 +172,15 @@ accept(L) ->
end.
accept(L, Timeout) ->
- case prim_inet:accept(L, Timeout) of
+ case prim_inet:accept(L, Timeout, accept_family_opts()) of
{ok, S} ->
inet_db:register_socket(S, ?MODULE),
{ok,S};
Error -> Error
end.
+accept_family_opts() -> [tos, ttl, recvtos, recvttl].
+
%%
%% Create a port/socket from a file descriptor
%%
diff --git a/lib/kernel/src/kernel.app.src b/lib/kernel/src/kernel.app.src
index 4933eae76f..fe073621c8 100644
--- a/lib/kernel/src/kernel.app.src
+++ b/lib/kernel/src/kernel.app.src
@@ -146,6 +146,6 @@
{logger_sasl_compatible, false}
]},
{mod, {kernel, []}},
- {runtime_dependencies, ["erts-10.0", "stdlib-3.5", "sasl-3.0"]}
+ {runtime_dependencies, ["erts-10.1", "stdlib-3.5", "sasl-3.0"]}
]
}.
diff --git a/lib/kernel/src/logger.erl b/lib/kernel/src/logger.erl
index 0020fe220b..752dd8d493 100644
--- a/lib/kernel/src/logger.erl
+++ b/lib/kernel/src/logger.erl
@@ -77,9 +77,9 @@
-type report() :: map() | [{atom(),term()}].
-type report_cb() :: fun((report()) -> {io:format(),[term()]}) |
fun((report(),report_cb_config()) -> unicode:chardata()).
--type report_cb_config() :: #{encoding := unicode:encoding(),
- depth := pos_integer() | unlimited,
- chars_limit := pos_integer() | unlimited}.
+-type report_cb_config() :: #{depth := pos_integer() | unlimited,
+ chars_limit := pos_integer() | unlimited,
+ single_line := boolean()}.
-type msg_fun() :: fun((term()) -> {io:format(),[term()]} |
report() |
unicode:chardata()).
@@ -116,6 +116,11 @@
-type config_handler() :: {handler, handler_id(), module(), handler_config()}.
+-type config_logger() :: [{handler,default,undefined} |
+ config_handler() |
+ {filters,log | stop,[{filter_id(),filter()}]} |
+ {module_level,level(),[module()]}].
+
-export_type([log_event/0,
level/0,
report/0,
@@ -434,12 +439,7 @@ get_primary_config() ->
HandlerId :: handler_id(),
Config :: handler_config().
get_handler_config(HandlerId) ->
- case logger_config:get(?LOGGER_TABLE,HandlerId) of
- {ok,{_,Config}} ->
- {ok,Config};
- Error ->
- Error
- end.
+ logger_config:get(?LOGGER_TABLE,HandlerId).
-spec get_handler_config() -> [Config] when
Config :: handler_config().
@@ -588,19 +588,21 @@ get_config() ->
%% tree is started.
internal_init_logger() ->
try
+ Env = get_logger_env(kernel),
+ check_logger_config(kernel,Env),
ok = logger:set_primary_config(level, get_logger_level()),
- ok = logger:set_primary_config(filter_default, get_primary_filter_default()),
+ ok = logger:set_primary_config(filter_default,
+ get_primary_filter_default(Env)),
[case logger:add_primary_filter(Id, Filter) of
ok -> ok;
{error, Reason} -> throw(Reason)
- end || {Id, Filter} <- get_primary_filters()],
+ end || {Id, Filter} <- get_primary_filters(Env)],
- _ = [[case logger:set_module_level(Module, Level) of
- ok -> ok;
- {error, Reason} -> throw(Reason)
- end || Module <- Modules]
- || {module_level, Level, Modules} <- get_logger_env()],
+ [case logger:set_module_level(Modules, Level) of
+ ok -> ok;
+ {error, Reason} -> throw(Reason)
+ end || {module_level, Level, Modules} <- Env],
case logger:set_handler_config(simple,filters,
get_default_handler_filters()) of
@@ -608,24 +610,24 @@ internal_init_logger() ->
{error,{not_found,simple}} -> ok
end,
- init_kernel_handlers()
+ init_kernel_handlers(Env)
catch throw:Reason ->
?LOG_ERROR("Invalid logger config: ~p", [Reason]),
{error, {bad_config, {kernel, Reason}}}
end.
--spec init_kernel_handlers() -> ok | {error,term()}.
+-spec init_kernel_handlers(config_logger()) -> ok | {error,term()}.
%% Setup the kernel environment variables to be correct
%% The actual handlers are started by a call to add_handlers.
-init_kernel_handlers() ->
+init_kernel_handlers(Env) ->
try
- case get_logger_type() of
+ case get_logger_type(Env) of
{ok,silent} ->
ok = logger:remove_handler(simple);
{ok,false} ->
ok;
{ok,Type} ->
- init_default_config(Type)
+ init_default_config(Type,Env)
end
catch throw:Reason ->
?LOG_ERROR("Invalid default handler config: ~p", [Reason]),
@@ -640,10 +642,13 @@ init_kernel_handlers() ->
%% and then starting the correct handlers. This is done after the
%% kernel supervisor tree has been started as it needs the logger_sup.
add_handlers(App) when is_atom(App) ->
- add_handlers(application:get_env(App, logger, []));
+ add_handlers(App,get_logger_env(App));
add_handlers(HandlerConfig) ->
+ add_handlers(application:get_application(),HandlerConfig).
+
+add_handlers(App,HandlerConfig) ->
try
- check_logger_config(HandlerConfig),
+ check_logger_config(App,HandlerConfig),
DefaultAdded =
lists:foldl(
fun({handler, default = Id, Module, Config}, _)
@@ -657,17 +662,22 @@ add_handlers(HandlerConfig) ->
({handler, Id, Module, Config}, Default) ->
setup_handler(Id, Module, Config),
Default orelse Id == default;
- (_, Default) -> Default
+ (_,Default) -> Default
end, false, HandlerConfig),
%% If a default handler was added we try to remove the simple_logger
%% If the simple logger exists it will replay its log events
%% to the handler(s) added in the fold above.
- _ = [case logger:remove_handler(simple) of
- ok -> ok;
- {error,{not_found,simple}} -> ok
- end || DefaultAdded],
+ [case logger:remove_handler(simple) of
+ ok -> ok;
+ {error,{not_found,simple}} -> ok
+ end || DefaultAdded],
ok
- catch throw:Reason ->
+ catch throw:Reason0 ->
+ Reason =
+ case App of
+ undefined -> Reason0;
+ _ -> {App,Reason0}
+ end,
?LOG_ERROR("Invalid logger handler config: ~p", [Reason]),
{error, {bad_config, {handler, Reason}}}
end.
@@ -678,26 +688,35 @@ setup_handler(Id, Module, Config) ->
{error, Reason} -> throw(Reason)
end.
-check_logger_config(_) ->
- ok.
-
--spec get_logger_type() -> {ok, standard_io | false | silent |
- {file, file:name_all()} |
- {file, file:name_all(), [file:mode()]}}.
-get_logger_type() ->
+check_logger_config(_,[]) ->
+ ok;
+check_logger_config(App,[{handler,_,_,_}|Env]) ->
+ check_logger_config(App,Env);
+check_logger_config(kernel,[{handler,default,undefined}|Env]) ->
+ check_logger_config(kernel,Env);
+check_logger_config(kernel,[{filters,_,_}|Env]) ->
+ check_logger_config(kernel,Env);
+check_logger_config(kernel,[{module_level,_,_}|Env]) ->
+ check_logger_config(kernel,Env);
+check_logger_config(_,Bad) ->
+ throw(Bad).
+
+-spec get_logger_type(config_logger()) ->
+ {ok, standard_io | false | silent |
+ {file, file:name_all()} |
+ {file, file:name_all(), [file:mode()]}}.
+get_logger_type(Env) ->
case application:get_env(kernel, error_logger) of
{ok, tty} ->
{ok, standard_io};
{ok, {file, File}} when is_list(File) ->
{ok, {file, File}};
- {ok, {file, File, Modes}} when is_list(File), is_list(Modes) ->
- {ok, {file, File, Modes}};
{ok, false} ->
{ok, false};
{ok, silent} ->
{ok, silent};
undefined ->
- case lists:member({handler,default,undefined}, get_logger_env()) of
+ case lists:member({handler,default,undefined}, Env) of
true ->
{ok, false};
false ->
@@ -715,56 +734,55 @@ get_logger_level() ->
throw({logger_level, Level})
end.
-get_primary_filter_default() ->
- case lists:keyfind(filters,1,get_logger_env()) of
+get_primary_filter_default(Env) ->
+ case lists:keyfind(filters,1,Env) of
{filters,Default,_} ->
Default;
false ->
log
end.
-get_primary_filters() ->
- lists:foldl(
- fun({filters, _, Filters}, _Acc) ->
- Filters;
- (_, Acc) ->
- Acc
- end, [], get_logger_env()).
+get_primary_filters(Env) ->
+ case [F || F={filters,_,_} <- Env] of
+ [{filters,_,Filters}] ->
+ case lists:all(fun({_,_}) -> true; (_) -> false end,Filters) of
+ true -> Filters;
+ false -> throw({invalid_filters,Filters})
+ end;
+ [] -> [];
+ _ -> throw({multiple_filters,Env})
+ end.
%% This function looks at the kernel logger environment
%% and updates it so that the correct logger is configured
-init_default_config(Type) when Type==standard_io;
- Type==standard_error;
- element(1,Type)==file ->
- Env = get_logger_env(),
+init_default_config(Type,Env) when Type==standard_io;
+ Type==standard_error;
+ element(1,Type)==file ->
DefaultFormatter = #{formatter=>{?DEFAULT_FORMATTER,?DEFAULT_FORMAT_CONFIG}},
DefaultConfig = DefaultFormatter#{config=>#{type=>Type}},
NewLoggerEnv =
case lists:keyfind(default, 2, Env) of
- {handler, default, Module, Config} ->
- lists:map(
- fun({handler, default, logger_std_h, _}) ->
- %% Only want to add the logger_std_h config
- %% if not configured by user AND the default
- %% handler is still the logger_std_h.
- {handler, default, Module, maps:merge(DefaultConfig,Config)};
- ({handler, default, logger_disk_log_h, _}) ->
- %% Add default formatter. The point of this
- %% is to get the expected formatter config
- %% for the default handler, since this
- %% differs from the default values that
- %% logger_formatter itself adds.
- {handler, default, logger_disk_log_h, maps:merge(DefaultFormatter,Config)};
- (Other) ->
- Other
- end, Env);
+ {handler, default, logger_std_h, Config} ->
+ %% Only want to add the logger_std_h config
+ %% if not configured by user AND the default
+ %% handler is still the logger_std_h.
+ lists:keyreplace(default, 2, Env,
+ {handler, default, logger_std_h,
+ maps:merge(DefaultConfig,Config)});
+ {handler, default, Module,Config} ->
+ %% Add default formatter. The point of this
+ %% is to get the expected formatter config
+ %% for the default handler, since this
+ %% differs from the default values that
+ %% logger_formatter itself adds.
+ lists:keyreplace(default, 2, Env,
+ {handler, default, Module,
+ maps:merge(DefaultFormatter,Config)});
_ ->
%% Nothing has been configured, use default
[{handler, default, logger_std_h, DefaultConfig} | Env]
end,
- application:set_env(kernel, logger, NewLoggerEnv, [{timeout,infinity}]);
-init_default_config(Type) ->
- throw({illegal_logger_type,Type}).
+ application:set_env(kernel, logger, NewLoggerEnv, [{timeout,infinity}]).
get_default_handler_filters() ->
case application:get_env(kernel, logger_sasl_compatible, false) of
@@ -774,8 +792,8 @@ get_default_handler_filters() ->
?DEFAULT_HANDLER_FILTERS([otp,sasl])
end.
-get_logger_env() ->
- application:get_env(kernel, logger, []).
+get_logger_env(App) ->
+ application:get_env(App, logger, []).
%%%-----------------------------------------------------------------
%%% Internal
diff --git a/lib/kernel/src/logger_backend.erl b/lib/kernel/src/logger_backend.erl
index 4d7bd6b2a0..432c671afd 100644
--- a/lib/kernel/src/logger_backend.erl
+++ b/lib/kernel/src/logger_backend.erl
@@ -41,7 +41,7 @@ log_allowed(Log, Tid) ->
call_handlers(#{level:=Level}=Log,[Id|Handlers],Tid) ->
case logger_config:get(Tid,Id,Level) of
- {ok,{Module,Config}} ->
+ {ok,#{module:=Module}=Config} ->
Filters = maps:get(filters,Config,[]),
case apply_filters(Id,Log,Filters,Config) of
stop ->
diff --git a/lib/kernel/src/logger_config.erl b/lib/kernel/src/logger_config.erl
index 55427dce5a..6bfe658552 100644
--- a/lib/kernel/src/logger_config.erl
+++ b/lib/kernel/src/logger_config.erl
@@ -22,8 +22,8 @@
-export([new/1,delete/2,
exist/2,
allow/2,allow/3,
- get/2, get/3, get/1,
- create/3, create/4, set/3,
+ get/2, get/3,
+ create/3, set/3,
set_module_level/3,unset_module_level/2,
get_module_level/1,cache_module_level/2,
level_to_int/1]).
@@ -64,27 +64,19 @@ get(Tid,What) ->
case ets:lookup(Tid,table_key(What)) of
[{_,_,Config}] ->
{ok,Config};
- [{_,_,Config,Module}] ->
- {ok,{Module,Config}};
[] ->
{error,{not_found,What}}
end.
get(Tid,What,Level) ->
- MS = [{{table_key(What),'$1','$2'}, % primary config
+ MS = [{{table_key(What),'$1','$2'},
[{'>=','$1',level_to_int(Level)}],
- ['$2']},
- {{table_key(What),'$1','$2','$3'}, % handler config
- [{'>=','$1',level_to_int(Level)}],
- [{{'$3','$2'}}]}],
+ ['$2']}],
case ets:select(Tid,MS) of
[] -> error;
[Data] -> {ok,Data}
end.
-create(Tid,What,Module,Config) ->
- LevelInt = level_to_int(maps:get(level,Config)),
- ets:insert(Tid,{table_key(What),LevelInt,Config,Module}).
create(Tid,What,Config) ->
LevelInt = level_to_int(maps:get(level,Config)),
ets:insert(Tid,{table_key(What),LevelInt,Config}).
@@ -129,13 +121,6 @@ cache_module_level(Tid,Module) ->
ets:insert_new(Tid,{Module,{GlobalLevelInt,cached}}),
ok.
-get(Tid) ->
- {ok,Primary} = get(Tid,primary),
- HMS = [{{table_key('$1'),'_','$2','$3'},[],[{{'$1','$3','$2'}}]}],
- Handlers = ets:select(Tid,HMS),
- Modules = get_module_level(Tid),
- {Primary,Handlers,Modules}.
-
level_to_int(none) -> ?LOG_NONE;
level_to_int(emergency) -> ?EMERGENCY;
level_to_int(alert) -> ?ALERT;
diff --git a/lib/kernel/src/logger_disk_log_h.erl b/lib/kernel/src/logger_disk_log_h.erl
index e56531c3cb..a8f141f135 100644
--- a/lib/kernel/src/logger_disk_log_h.erl
+++ b/lib/kernel/src/logger_disk_log_h.erl
@@ -225,7 +225,7 @@ removing_handler(#{id:=Name}) ->
%%%-----------------------------------------------------------------
%%% Log a string or report
--spec log(LogEvent, Config) -> ok | dropped when
+-spec log(LogEvent, Config) -> ok when
LogEvent :: logger:log_event(),
Config :: logger:handler_config().
@@ -294,7 +294,7 @@ init([Name,
%% initial start
ok
end,
- enter_loop(Config1, State1)
+ gen_server:enter_loop(?MODULE, [], State1)
catch
_:Error ->
unregister(RegName),
@@ -307,9 +307,6 @@ init([Name,
proc_lib:init_ack(Error)
end.
-enter_loop(_Config,State) ->
- gen_server:enter_loop(?MODULE,[],State).
-
%% This is the synchronous log event.
handle_call({log, Bin}, _From, State) ->
{Result,State1} = do_log(Bin, call, State),
@@ -429,8 +426,9 @@ terminate(Reason, State = #{id := Name}) ->
_ = logger_h_common:cancel_timer(maps:get(rep_sync_tref, State,
undefined)),
_ = close_disk_log(Name, normal),
+ ok = logger_h_common:stop_or_restart(Name, Reason, State),
unregister(?name_to_reg_name(?MODULE, Name)),
- logger_h_common:stop_or_restart(Name, Reason, State).
+ ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
diff --git a/lib/kernel/src/logger_formatter.erl b/lib/kernel/src/logger_formatter.erl
index b0d4adc14d..ded89bac9f 100644
--- a/lib/kernel/src/logger_formatter.erl
+++ b/lib/kernel/src/logger_formatter.erl
@@ -28,7 +28,6 @@
%%% Types
-type config() :: #{chars_limit => pos_integer() | unlimited,
depth => pos_integer() | unlimited,
- encoding => unicode:encoding(),
legacy_header => boolean(),
max_size => pos_integer() | unlimited,
report_cb => logger:report_cb(),
@@ -84,7 +83,7 @@ format(#{level:=Level,msg:=Msg0,meta:=Meta},Config0)
true ->
""
end,
- truncate(B ++ MsgStr ++ A,maps:get(max_size,Config)).
+ truncate([B,MsgStr,A],maps:get(max_size,Config)).
do_format(Level,Data,[level|Format],Config) ->
[to_string(level,Level,Config)|do_format(Level,Data,Format,Config)];
@@ -147,7 +146,7 @@ printable_list(X) ->
io_lib:printable_list(X).
format_msg({string,Chardata},Meta,Config) ->
- format_msg({s(Config),[Chardata]},Meta,Config);
+ format_msg({"~ts",[Chardata]},Meta,Config);
format_msg({report,_}=Msg,Meta,#{report_cb:=Fun}=Config)
when is_function(Fun,1); is_function(Fun,2) ->
format_msg(Msg,Meta#{report_cb=>Fun},maps:remove(report_cb,Config));
@@ -166,13 +165,13 @@ format_msg({report,Report},#{report_cb:=Fun}=Meta,Config) when is_function(Fun,1
Meta,Config)
end;
format_msg({report,Report},#{report_cb:=Fun}=Meta,Config) when is_function(Fun,2) ->
- try Fun(Report,maps:with([encoding,depth,chars_limit],Config)) of
- String when ?IS_STRING(String) ->
- try unicode:characters_to_list(String)
+ try Fun(Report,maps:with([depth,chars_limit,single_line],Config)) of
+ Chardata when ?IS_STRING(Chardata) ->
+ try chardata_to_list(Chardata) % already size limited by report_cb
catch _:_ ->
P = p(Config),
format_msg({"REPORT_CB/2 ERROR: "++P++"; Returned: "++P,
- [Report,String]},Meta,Config)
+ [Report,Chardata]},Meta,Config)
end;
Other ->
P = p(Config),
@@ -189,28 +188,27 @@ format_msg({report,Report},Meta,Config) ->
Meta#{report_cb=>fun logger:format_report/1},
Config);
format_msg(Msg,_Meta,#{depth:=Depth,chars_limit:=CharsLimit,
- encoding:=Enc,single_line:=Single}) ->
+ single_line:=Single}) ->
Opts = chars_limit_to_opts(CharsLimit),
- format_msg(Msg, Depth, Opts, Enc, Single).
+ format_msg(Msg, Depth, Opts, Single).
chars_limit_to_opts(unlimited) -> [];
chars_limit_to_opts(CharsLimit) -> [{chars_limit,CharsLimit}].
-format_msg({Format0,Args},Depth,Opts,Enc,Single) ->
+format_msg({Format0,Args},Depth,Opts,Single) ->
try
Format1 = io_lib:scan_format(Format0, Args),
Format = reformat(Format1, Depth, Single),
io_lib:build_text(Format,Opts)
catch C:R:S ->
- P = p(Enc,Single),
+ P = p(Single),
FormatError = "FORMAT ERROR: "++P++" - "++P,
case Format0 of
FormatError ->
%% already been here - avoid failing cyclically
erlang:raise(C,R,S);
_ ->
- format_msg({FormatError,[Format0,Args]},
- Depth,Opts,Enc,Single)
+ format_msg({FormatError,[Format0,Args]},Depth,Opts,Single)
end
end.
@@ -233,6 +231,14 @@ limit_depth(#{control_char:=C0, args:=Args}=M0, Depth) ->
C = C0 - ($a - $A), %To uppercase.
M0#{control_char:=C,args:=Args++[Depth]}.
+chardata_to_list(Chardata) ->
+ case unicode:characters_to_list(Chardata,unicode) of
+ List when is_list(List) ->
+ List;
+ Error ->
+ throw(Error)
+ end.
+
truncate(String,unlimited) ->
String;
truncate(String,Size) ->
@@ -278,12 +284,11 @@ maybe_add_legacy_header(Level,
#{time:=Timestamp}=Meta,
#{legacy_header:=true}=Config) ->
#{title:=Title}=MyMeta = add_legacy_title(Level,Meta,Config),
- {{Y,Mo,D},{H,Mi,Sec},Micro,UtcStr} =
+ {{Y,Mo,D},{H,Mi,S},Micro,UtcStr} =
timestamp_to_datetimemicro(Timestamp,Config),
- S = s(Config),
Header =
- io_lib:format("="++S++"==== ~w-~s-~4w::~2..0w:~2..0w:~2..0w.~6..0w ~s===",
- [Title,D,month(Mo),Y,H,Mi,Sec,Micro,UtcStr]),
+ io_lib:format("=~ts==== ~w-~s-~4w::~2..0w:~2..0w:~2..0w.~6..0w ~s===",
+ [Title,D,month(Mo),Y,H,Mi,S,Micro,UtcStr]),
Meta#{?MODULE=>MyMeta#{header=>Header}};
maybe_add_legacy_header(_,Meta,_) ->
Meta.
@@ -324,7 +329,6 @@ month(12) -> "Dec".
add_default_config(Config0) ->
Default =
#{chars_limit=>unlimited,
- encoding=>utf8,
error_logger_notice_header=>info,
legacy_header=>false,
single_line=>true,
@@ -502,25 +506,9 @@ check_timezone(Tz) ->
error
end.
-p(#{encoding:=Enc, single_line:=Single}) ->
- p(Enc,Single).
-
-p(Enc,Single) ->
- "~"++p_width(Single)++p_char(Enc).
-
-p_width(true) ->
- "0";
-p_width(false) ->
- "".
-
-p_char(latin1) ->
- "p";
-p_char(_) ->
- "tp".
-
-s(#{encoding:=Enc}) ->
- s(Enc);
-s(latin1) ->
- "~s";
-s(_) ->
- "~ts".
+p(#{single_line:=Single}) ->
+ p(Single);
+p(true) ->
+ "~0tp";
+p(false) ->
+ "~tp".
diff --git a/lib/kernel/src/logger_h_common.erl b/lib/kernel/src/logger_h_common.erl
index 854e5479b9..38ac7d8ffc 100644
--- a/lib/kernel/src/logger_h_common.erl
+++ b/lib/kernel/src/logger_h_common.erl
@@ -40,7 +40,7 @@
info_notify/1]).
%%%-----------------------------------------------------------------
-%%% Covert log data on any form to binary
+%%% Convert log data on any form to binary
-spec log_to_binary(LogEvent,Config) -> LogString when
LogEvent :: logger:log_event(),
Config :: logger:handler_config(),
@@ -57,13 +57,14 @@ do_log_to_binary(Log,Config) ->
{Formatter,FormatterConfig} =
maps:get(formatter,Config,{?DEFAULT_FORMATTER,?DEFAULT_FORMAT_CONFIG}),
String = try_format(Log,Formatter,FormatterConfig),
- try unicode:characters_to_binary(String)
- catch _:_ ->
+ try string_to_binary(String)
+ catch C2:R2:S2 ->
?LOG_INTERNAL(debug,[{formatter_error,Formatter},
{config,FormatterConfig},
{log_event,Log},
- {bad_return_value,String}]),
- <<"FORMATTER ERROR: bad_return_value">>
+ {bad_return_value,String},
+ {catched,{C2,R2,S2}}]),
+ <<"FORMATTER ERROR: bad return value">>
end.
try_format(Log,Formatter,FormatterConfig) ->
@@ -85,6 +86,15 @@ try_format(Log,Formatter,FormatterConfig) ->
end
end.
+string_to_binary(String) ->
+ case unicode:characters_to_binary(String) of
+ Binary when is_binary(Binary) ->
+ Binary;
+ Error ->
+ throw(Error)
+ end.
+
+
%%%-----------------------------------------------------------------
%%% Check that the configuration term is valid
check_common_config({mode_tab,_Tid}) ->
@@ -284,6 +294,7 @@ stop_or_restart(Name, {shutdown,Reason={overloaded,_Name,_QLen,_Mem}},
%% and set a restart timer. A separate process must perform this
%% in order to avoid deadlock.
HandlerPid = self(),
+ ConfigResult = logger:get_handler_config(Name),
RemoveAndRestart =
fun() ->
MRef = erlang:monitor(process, HandlerPid),
@@ -294,7 +305,7 @@ stop_or_restart(Name, {shutdown,Reason={overloaded,_Name,_QLen,_Mem}},
error_notify(Reason),
exit(HandlerPid, kill)
end,
- case logger:get_handler_config(Name) of
+ case ConfigResult of
{ok,#{module:=HMod}=HConfig} when is_integer(RestartAfter) ->
_ = logger:remove_handler(Name),
_ = timer:apply_after(RestartAfter, logger, add_handler,
diff --git a/lib/kernel/src/logger_server.erl b/lib/kernel/src/logger_server.erl
index 644fdd5af2..a1d40f1123 100644
--- a/lib/kernel/src/logger_server.erl
+++ b/lib/kernel/src/logger_server.erl
@@ -146,7 +146,7 @@ init([]) ->
filters=>?DEFAULT_HANDLER_FILTERS}),
%% If this fails, then the node should crash
{ok,SimpleConfig} = logger_simple_h:adding_handler(SimpleConfig0),
- logger_config:create(Tid,simple,logger_simple_h,SimpleConfig),
+ logger_config:create(Tid,simple,SimpleConfig),
{ok, #state{tid=Tid, async_req_queue = queue:new()}}.
handle_call({add_handler,Id,Module,HConfig}, From, #state{tid=Tid}=State) ->
@@ -165,11 +165,11 @@ handle_call({add_handler,Id,Module,HConfig}, From, #state{tid=Tid}=State) ->
%% to find out if this is a valid handler
case erlang:function_exported(Module, log, 2) of
true ->
- logger_config:create(Tid,Id,Module,HConfig1),
- {ok,Config} = do_get_config(Tid,primary),
+ logger_config:create(Tid,Id,HConfig1),
+ {ok,Config} = logger_config:get(Tid,primary),
Handlers = maps:get(handlers,Config,[]),
- do_set_config(Tid,primary,
- Config#{handlers=>[Id|Handlers]});
+ logger_config:set(Tid,primary,
+ Config#{handlers=>[Id|Handlers]});
false ->
{error,{invalid_handler,
{function_not_exported,
@@ -181,8 +181,8 @@ handle_call({add_handler,Id,Module,HConfig}, From, #state{tid=Tid}=State) ->
end;
handle_call({remove_handler,HandlerId}, From, #state{tid=Tid}=State) ->
case logger_config:get(Tid,HandlerId) of
- {ok,{Module,HConfig}} ->
- {ok,Config} = do_get_config(Tid,primary),
+ {ok,#{module:=Module}=HConfig} ->
+ {ok,Config} = logger_config:get(Tid,primary),
Handlers0 = maps:get(handlers,Config,[]),
Handlers = lists:delete(HandlerId,Handlers0),
call_h_async(
@@ -191,7 +191,7 @@ handle_call({remove_handler,HandlerId}, From, #state{tid=Tid}=State) ->
call_h(Module,removing_handler,[HConfig],ok)
end,
fun(_Res) ->
- do_set_config(Tid,primary,Config#{handlers=>Handlers}),
+ logger_config:set(Tid,primary,Config#{handlers=>Handlers}),
logger_config:delete(Tid,HandlerId),
ok
end,From,State);
@@ -204,25 +204,35 @@ handle_call({add_filter,Id,Filter}, _From,#state{tid=Tid}=State) ->
handle_call({remove_filter,Id,FilterId}, _From, #state{tid=Tid}=State) ->
Reply = do_remove_filter(Tid,Id,FilterId),
{reply,Reply,State};
-handle_call({update_config,Id,NewConfig}, From, #state{tid=Tid}=State) ->
- case logger_config:get(Tid,Id) of
- {ok,{_Module,OldConfig}} ->
- Config = maps:merge(OldConfig,NewConfig),
- handle_call({set_config,Id,Config}, From, State);
- {ok,OldConfig} ->
+handle_call({update_config,primary,NewConfig}, _From, #state{tid=Tid}=State) ->
+ {ok,OldConfig} = logger_config:get(Tid,primary),
+ Config = maps:merge(OldConfig,NewConfig),
+ {reply,logger_config:set(Tid,primary,Config),State};
+handle_call({update_config,HandlerId,NewConfig}, From, #state{tid=Tid}=State) ->
+ case logger_config:get(Tid,HandlerId) of
+ {ok,#{module:=Module}=OldConfig} ->
Config = maps:merge(OldConfig,NewConfig),
- {reply,do_set_config(Tid,Id,Config),State};
+ call_h_async(
+ fun() ->
+ call_h(Module,changing_config,[OldConfig,Config],
+ {ok,Config})
+ end,
+ fun({ok,Config1}) ->
+ logger_config:set(Tid,HandlerId,Config1);
+ (Error) ->
+ Error
+ end,From,State);
Error ->
{reply,Error,State}
end;
handle_call({set_config,primary,Config0}, _From, #state{tid=Tid}=State) ->
Config = maps:merge(default_config(primary),Config0),
{ok,#{handlers:=Handlers}} = logger_config:get(Tid,primary),
- Reply = do_set_config(Tid,primary,Config#{handlers=>Handlers}),
+ Reply = logger_config:set(Tid,primary,Config#{handlers=>Handlers}),
{reply,Reply,State};
handle_call({set_config,HandlerId,Config0}, From, #state{tid=Tid}=State) ->
case logger_config:get(Tid,HandlerId) of
- {ok,{Module,OldConfig}} ->
+ {ok,#{module:=Module}=OldConfig} ->
Config = maps:merge(default_config(HandlerId,Module),Config0),
call_h_async(
fun() ->
@@ -230,7 +240,7 @@ handle_call({set_config,HandlerId,Config0}, From, #state{tid=Tid}=State) ->
{ok,Config})
end,
fun({ok,Config1}) ->
- do_set_config(Tid,HandlerId,Config1);
+ logger_config:set(Tid,HandlerId,Config1);
(Error) ->
Error
end,From,State);
@@ -241,12 +251,12 @@ handle_call({update_formatter_config,HandlerId,NewFConfig},_From,
#state{tid=Tid}=State) ->
Reply =
case logger_config:get(Tid,HandlerId) of
- {ok,{_Mod,#{formatter:={FMod,OldFConfig}}=Config}} ->
+ {ok,#{formatter:={FMod,OldFConfig}}=Config} ->
try
FConfig = maps:merge(OldFConfig,NewFConfig),
check_formatter({FMod,FConfig}),
- do_set_config(Tid,HandlerId,
- Config#{formatter=>{FMod,FConfig}})
+ logger_config:set(Tid,HandlerId,
+ Config#{formatter=>{FMod,FConfig}})
catch throw:Reason -> {error,Reason}
end;
_ ->
@@ -309,6 +319,7 @@ call(Request) ->
case get(?LOGGER_SERVER_TAG) of
true when
Action == add_handler; Action == remove_handler;
+ Action == add_filter; Action == remove_filter;
Action == update_config; Action == set_config ->
{error,{attempting_syncronous_call_to_self,Request}};
_ ->
@@ -316,26 +327,26 @@ call(Request) ->
end.
do_add_filter(Tid,Id,{FId,_} = Filter) ->
- case do_get_config(Tid,Id) of
+ case logger_config:get(Tid,Id) of
{ok,Config} ->
Filters = maps:get(filters,Config,[]),
case lists:keymember(FId,1,Filters) of
true ->
{error,{already_exist,FId}};
false ->
- do_set_config(Tid,Id,Config#{filters=>[Filter|Filters]})
+ logger_config:set(Tid,Id,Config#{filters=>[Filter|Filters]})
end;
Error ->
Error
end.
do_remove_filter(Tid,Id,FilterId) ->
- case do_get_config(Tid,Id) of
+ case logger_config:get(Tid,Id) of
{ok,Config} ->
Filters0 = maps:get(filters,Config,[]),
case lists:keytake(FilterId,1,Filters0) of
{value,_,Filters} ->
- do_set_config(Tid,Id,Config#{filters=>Filters});
+ logger_config:set(Tid,Id,Config#{filters=>Filters});
false ->
{error,{not_found,FilterId}}
end;
@@ -343,20 +354,6 @@ do_remove_filter(Tid,Id,FilterId) ->
Error
end.
-do_get_config(Tid,Id) ->
- case logger_config:get(Tid,Id) of
- {ok,{_,Config}} ->
- {ok,Config};
- {ok,Config} ->
- {ok,Config};
- Error ->
- Error
- end.
-
-do_set_config(Tid,Id,Config) ->
- logger_config:set(Tid,Id,Config),
- ok.
-
default_config(primary) ->
#{level=>notice,
filters=>[],
@@ -376,7 +373,7 @@ sanity_check(Owner,Key,Value) ->
sanity_check(HandlerId,Config) when is_map(Config) ->
sanity_check_1(HandlerId,maps:to_list(Config));
sanity_check(_,Config) ->
- {error,{invalid_handler_config,Config}}.
+ {error,{invalid_config,Config}}.
sanity_check_1(Owner,Config) when is_list(Config) ->
try
@@ -421,8 +418,6 @@ check_mod(Mod) when is_atom(Mod) ->
check_mod(Mod) ->
throw({invalid_module,Mod}).
-check_level({LevelInt,cached}) when LevelInt>=?EMERGENCY, LevelInt=<?DEBUG ->
- ok;
check_level(Level) ->
case lists:member(Level,?LEVELS) of
true ->
diff --git a/lib/kernel/src/logger_std_h.erl b/lib/kernel/src/logger_std_h.erl
index 9a2a1443b3..66fa6b6ab6 100644
--- a/lib/kernel/src/logger_std_h.erl
+++ b/lib/kernel/src/logger_std_h.erl
@@ -210,7 +210,7 @@ removing_handler(#{id:=Name}) ->
%%%-----------------------------------------------------------------
%%% Log a string or report
--spec log(LogEvent, Config) -> ok | dropped when
+-spec log(LogEvent, Config) -> ok when
LogEvent :: logger:log_event(),
Config :: logger:handler_config().
@@ -259,7 +259,7 @@ init([Name, Config = #{config := HConfig},
mode_tab => ModeTab}},
proc_lib:init_ack({ok,self(),Config1}),
gen_server:cast(self(), repeated_filesync),
- enter_loop(Config1, State1)
+ gen_server:enter_loop(?MODULE, [], State1)
catch
_:Error ->
unregister(RegName),
@@ -290,9 +290,6 @@ do_init(Name, Type) ->
Error
end.
-enter_loop(_Config,State) ->
- gen_server:enter_loop(?MODULE,[],State).
-
%% This is the synchronous log event.
handle_call({log, Bin}, _From, State) ->
{Result,State1} = do_log(Bin, call, State),
@@ -418,8 +415,9 @@ terminate(Reason, State = #{id:=Name, file_ctrl_pid:=FWPid,
false ->
ok
end,
+ ok = logger_h_common:stop_or_restart(Name, Reason, State),
unregister(?name_to_reg_name(?MODULE, Name)),
- logger_h_common:stop_or_restart(Name, Reason, State).
+ ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
diff --git a/lib/kernel/src/net_kernel.erl b/lib/kernel/src/net_kernel.erl
index bea08242d8..3cf11fd7b1 100644
--- a/lib/kernel/src/net_kernel.erl
+++ b/lib/kernel/src/net_kernel.erl
@@ -279,24 +279,18 @@ passive_connect_monitor(From, Node) ->
ok = monitor_nodes(true,[{node_type,all}]),
Reply = case lists:member(Node,nodes([connected])) of
true ->
- io:format("~p: passive_connect_monitor ~p\n", [self(), ?LINE]),
true;
_ ->
receive
{nodeup,Node,_} ->
- io:format("~p: passive_connect_monitor ~p\n", [self(), ?LINE]),
true
after connecttime() ->
- io:format("~p: passive_connect_monitor ~p\n", [self(), ?LINE]),
false
end
end,
ok = monitor_nodes(false,[{node_type,all}]),
- io:format("~p: passive_connect_monitor ~p\n", [self(), ?LINE]),
{Pid, Tag} = From,
- io:format("~p: passive_connect_monitor ~p\n", [self(), ?LINE]),
- erlang:send(Pid, {Tag, Reply}),
- io:format("~p: passive_connect_monitor ~p\n", [self(), ?LINE]).
+ erlang:send(Pid, {Tag, Reply}).
%% If the net_kernel isn't running we ignore all requests to the
@@ -358,20 +352,34 @@ init({Name, LongOrShortNames, TickT, CleanHalt}) ->
{stop, Error}
end.
-
-do_auto_connect(Type, Node, ConnId, WaitForBarred, From, State) ->
- ConnLookup = ets:lookup(sys_dist, Node),
-
- case ConnLookup of
+do_auto_connect_1(Node, ConnId, From, State) ->
+ case ets:lookup(sys_dist, Node) of
[#barred_connection{}] ->
- case WaitForBarred of
- false ->
- {reply, false, State};
- true ->
+ case ConnId of
+ passive_cnct ->
spawn(?MODULE,passive_connect_monitor,[From,Node]),
- {noreply, State}
+ {noreply, State};
+ _ ->
+ erts_internal:abort_connection(Node, ConnId),
+ {reply, false, State}
end;
+ ConnLookup ->
+ do_auto_connect_2(Node, ConnId, From, State, ConnLookup)
+ end.
+
+do_auto_connect_2(Node, passive_cnct, From, State, ConnLookup) ->
+ try erts_internal:new_connection(Node) of
+ ConnId ->
+ do_auto_connect_2(Node, ConnId, From, State, ConnLookup)
+ catch
+ _:_ ->
+ error_logger:error_msg("~n** Cannot get connection id for node ~w~n",
+ [Node]),
+ {reply, false, State}
+ end;
+do_auto_connect_2(Node, ConnId, From, State, ConnLookup) ->
+ case ConnLookup of
[#connection{conn_id=ConnId, state = up}] ->
{reply, true, State};
[#connection{conn_id=ConnId, waiting=Waiting}=Conn] ->
@@ -385,6 +393,7 @@ do_auto_connect(Type, Node, ConnId, WaitForBarred, From, State) ->
case application:get_env(kernel, dist_auto_connect) of
{ok, never} ->
?connect_failure(Node,{dist_auto_connect,never}),
+ erts_internal:abort_connection(Node, ConnId),
{reply, false, State};
%% This might happen due to connection close
@@ -394,14 +403,16 @@ do_auto_connect(Type, Node, ConnId, WaitForBarred, From, State) ->
(hd(ConnLookup))#connection.state =:= up ->
?connect_failure(Node,{barred_connection,
ets:lookup(sys_dist, Node)}),
+ erts_internal:abort_connection(Node, ConnId),
{reply, false, State};
_ ->
- case setup(ConnLookup, Node,ConnId,Type,From,State) of
+ case setup(Node, ConnId, normal, From, State) of
{ok, SetupPid} ->
Owners = [{SetupPid, Node} | State#state.conn_owners],
{noreply,State#state{conn_owners=Owners}};
_Error ->
?connect_failure(Node, {setup_call, failed, _Error}),
+ erts_internal:abort_connection(Node, ConnId),
{reply, false, State}
end
end
@@ -419,8 +430,8 @@ do_explicit_connect([#connection{conn_id = ConnId}=Conn], _, _, ConnId, From, St
do_explicit_connect([#barred_connection{}], Type, Node, ConnId, From , State) ->
%% Barred connection only affects auto_connect, ignore it.
do_explicit_connect([], Type, Node, ConnId, From , State);
-do_explicit_connect(ConnLookup, Type, Node, ConnId, From , State) ->
- case setup(ConnLookup, Node,ConnId,Type,From,State) of
+do_explicit_connect(_ConnLookup, Type, Node, ConnId, From , State) ->
+ case setup(Node,ConnId,Type,From,State) of
{ok, SetupPid} ->
Owners = [{SetupPid, Node} | State#state.conn_owners],
{noreply,State#state{conn_owners=Owners}};
@@ -429,18 +440,6 @@ do_explicit_connect(ConnLookup, Type, Node, ConnId, From , State) ->
{reply, false, State}
end.
--define(ERTS_DIST_CON_ID_MASK, 16#ffffff). % also in external.h
-
-verify_new_conn_id([], {Nr,_DHandle})
- when (Nr band (bnot ?ERTS_DIST_CON_ID_MASK)) =:= 0 ->
- true;
-verify_new_conn_id([#connection{conn_id = {Old,_}}], {New,_})
- when New =:= ((Old+1) band ?ERTS_DIST_CON_ID_MASK) ->
- true;
-verify_new_conn_id(_, _) ->
- false.
-
-
%% ------------------------------------------------------------
%% handle_call.
@@ -454,18 +453,7 @@ handle_call({passive_cnct, Node}, From, State) when Node =:= node() ->
async_reply({reply, true, State}, From);
handle_call({passive_cnct, Node}, From, State) ->
verbose({passive_cnct, Node}, 1, State),
- Type = normal,
- WaitForBarred = true,
- R = case (catch erts_internal:new_connection(Node)) of
- {Nr,_DHandle}=ConnId when is_integer(Nr) ->
- do_auto_connect(Type, Node, ConnId, WaitForBarred, From, State);
-
- _Error ->
- error_logger:error_msg("~n** Cannot get connection id for node ~w~n",
- [Node]),
- {reply, false, State}
- end,
-
+ R = do_auto_connect_1(Node, passive_cnct, From, State),
return_call(R, From);
%%
@@ -477,11 +465,21 @@ handle_call({connect, _, Node}, From, State) when Node =:= node() ->
handle_call({connect, Type, Node}, From, State) ->
verbose({connect, Type, Node}, 1, State),
ConnLookup = ets:lookup(sys_dist, Node),
- R = case (catch erts_internal:new_connection(Node)) of
- {Nr,_DHandle}=ConnId when is_integer(Nr) ->
- do_explicit_connect(ConnLookup, Type, Node, ConnId, From, State);
+ R = try erts_internal:new_connection(Node) of
+ ConnId ->
+ R1 = do_explicit_connect(ConnLookup, Type, Node, ConnId, From, State),
+ case R1 of
+ {reply, true, _S} -> %% already connected
+ ok;
+ {noreply, _S} -> %% connection pending
+ ok;
+ {reply, false, _S} -> %% connection refused
+ erts_internal:abort_connection(Node, ConnId)
+ end,
+ R1
- _Error ->
+ catch
+ _:_ ->
error_logger:error_msg("~n** Cannot get connection id for node ~w~n",
[Node]),
{reply, false, State}
@@ -699,11 +697,11 @@ terminate(_Reason, State) ->
%%
%% Asynchronous auto connect request
%%
-handle_info({auto_connect,Node, Nr, DHandle}, State) ->
- verbose({auto_connect, Node, Nr, DHandle}, 1, State),
- ConnId = {Nr, DHandle},
+handle_info({auto_connect,Node, DHandle}, State) ->
+ verbose({auto_connect, Node, DHandle}, 1, State),
+ ConnId = DHandle,
NewState =
- case do_auto_connect(normal, Node, ConnId, false, noreply, State) of
+ case do_auto_connect_1(Node, ConnId, noreply, State) of
{noreply, S} -> %% Pending connection
S;
@@ -711,7 +709,6 @@ handle_info({auto_connect,Node, Nr, DHandle}, State) ->
S;
{reply, false, S} -> %% Connection refused
- erts_internal:abort_connection(Node, ConnId),
S
end,
{noreply, NewState};
@@ -796,8 +793,8 @@ handle_info({AcceptPid, {accept_pending,MyNode,Node,Address,Type}}, State) ->
AcceptPid ! {self(), {accept_pending, already_pending}},
{noreply, State};
_ ->
- case (catch erts_internal:new_connection(Node)) of
- {Nr,_DHandle}=ConnId when is_integer(Nr) ->
+ try erts_internal:new_connection(Node) of
+ ConnId ->
ets:insert(sys_dist, #connection{node = Node,
conn_id = ConnId,
state = pending,
@@ -806,9 +803,9 @@ handle_info({AcceptPid, {accept_pending,MyNode,Node,Address,Type}}, State) ->
type = Type}),
AcceptPid ! {self(),{accept_pending,ok}},
Owners = [{AcceptPid,Node} | State#state.conn_owners],
- {noreply, State#state{conn_owners = Owners}};
-
- _ ->
+ {noreply, State#state{conn_owners = Owners}}
+ catch
+ _:_ ->
error_logger:error_msg("~n** Cannot get connection id for node ~w~n",
[Node]),
AcceptPid ! {self(),{accept_pending,nok_pending}}
@@ -1275,8 +1272,8 @@ spawn_func(_,{From,Tag},M,F,A,Gleader) ->
%% Set up connection to a new node.
%% -----------------------------------------------------------
-setup(ConnLookup, Node,ConnId,Type,From,State) ->
- case setup_check(ConnLookup, Node, ConnId, State) of
+setup(Node, ConnId, Type, From, State) ->
+ case setup_check(Node, State) of
{ok, L} ->
Mod = L#listen.module,
LAddr = L#listen.address,
@@ -1305,7 +1302,7 @@ setup(ConnLookup, Node,ConnId,Type,From,State) ->
Error
end.
-setup_check(ConnLookup, Node, ConnId, State) ->
+setup_check(Node, State) ->
Allowed = State#state.allowed,
case lists:member(Node, Allowed) of
false when Allowed =/= [] ->
@@ -1313,16 +1310,9 @@ setup_check(ConnLookup, Node, ConnId, State) ->
"disallowed node ~w ** ~n", [Node]),
{error, bad_node};
_ ->
- case verify_new_conn_id(ConnLookup, ConnId) of
- false ->
- error_msg("** Connection attempt to ~w with "
- "bad connection id ~w ** ~n", [Node, ConnId]),
- {error, bad_conn_id};
- true ->
- case select_mod(Node, State#state.listen) of
- {ok, _L}=OK -> OK;
- Error -> Error
- end
+ case select_mod(Node, State#state.listen) of
+ {ok, _L}=OK -> OK;
+ Error -> Error
end
end.
diff --git a/lib/kernel/test/disk_log_SUITE.erl b/lib/kernel/test/disk_log_SUITE.erl
index 0709a6e766..9704c3b28c 100644
--- a/lib/kernel/test/disk_log_SUITE.erl
+++ b/lib/kernel/test/disk_log_SUITE.erl
@@ -1750,7 +1750,7 @@ block_queue(Conf) when is_list(Conf) ->
true = [{1,a},{2,b},{3,c},{4,d},{5,e},{6,f},{7,g},{8,h}] == Terms,
del(File, 2),
Q = qlen(),
- true = (P0 == pps()),
+ check_pps(P0),
ok.
%% OTP-4880. Blocked processes did not get disk_log_stopped message.
@@ -1782,7 +1782,7 @@ block_queue2(Conf) when is_list(Conf) ->
{ok,<<>>} = file:read_file(File ++ ".1"),
del(File, No),
Q = qlen(),
- true = (P0 == pps()),
+ check_pps(P0),
ok.
@@ -2119,7 +2119,7 @@ close_block(Conf) when is_list(Conf) ->
0 = sync_do(Pid2, users),
sync_do(Pid2, terminate),
{error, no_such_log} = disk_log:info(n),
- true = (P0 == pps()),
+ check_pps(P0),
%% Users terminate (no link...).
Pid3 = spawn_link(?MODULE, lserv, [n]),
@@ -2137,7 +2137,7 @@ close_block(Conf) when is_list(Conf) ->
disk_log:close(n),
disk_log:close(n),
{error, no_such_log} = disk_log:info(n),
- true = (P0 == pps()),
+ check_pps(P0),
%% Blocking owner terminates.
Pid5 = spawn_link(?MODULE, lserv, [n]),
@@ -2154,7 +2154,7 @@ close_block(Conf) when is_list(Conf) ->
1 = users(n),
ok = disk_log:close(n),
{error, no_such_log} = disk_log:info(n),
- true = (P0 == pps()),
+ check_pps(P0),
%% Blocking user terminates.
Pid6 = spawn_link(?MODULE, lserv, [n]),
@@ -2174,7 +2174,7 @@ close_block(Conf) when is_list(Conf) ->
1 = users(n),
ok = disk_log:close(n),
{error, no_such_log} = disk_log:info(n),
- true = (P0 == pps()),
+ check_pps(P0),
%% Blocking owner terminates.
Pid7 = spawn_link(?MODULE, lserv, [n]),
@@ -2192,7 +2192,7 @@ close_block(Conf) when is_list(Conf) ->
1 = users(n),
ok = disk_log:close(n),
{error, no_such_log} = disk_log:info(n),
- true = (P0 == pps()),
+ check_pps(P0),
%% Two owners, the blocking one terminates.
Pid8 = spawn_link(?MODULE, lserv, [n]),
@@ -2207,7 +2207,7 @@ close_block(Conf) when is_list(Conf) ->
0 = sync_do(Pid9, users),
sync_do(Pid9, terminate),
{error, no_such_log} = disk_log:info(n),
- true = (P0 == pps()),
+ check_pps(P0),
%% Blocking user closes.
Pid10 = spawn_link(?MODULE, lserv, [n]),
@@ -2225,7 +2225,7 @@ close_block(Conf) when is_list(Conf) ->
ok = disk_log:close(n),
sync_do(Pid10, terminate),
{error, no_such_log} = disk_log:info(n),
- true = (P0 == pps()),
+ check_pps(P0),
%% Blocking user unblocks and closes.
Pid11 = spawn_link(?MODULE, lserv, [n]),
@@ -2244,7 +2244,7 @@ close_block(Conf) when is_list(Conf) ->
ok = disk_log:close(n),
{error, no_such_log} = disk_log:info(n),
sync_do(Pid11, terminate),
- true = (P0 == pps()),
+ check_pps(P0),
%% Blocking owner closes.
Pid12 = spawn_link(?MODULE, lserv, [n]),
@@ -2263,7 +2263,7 @@ close_block(Conf) when is_list(Conf) ->
ok = disk_log:close(n),
{error, no_such_log} = disk_log:info(n),
sync_do(Pid12, terminate),
- true = (P0 == pps()),
+ check_pps(P0),
%% Blocking owner unblocks and closes.
Pid13 = spawn_link(?MODULE, lserv, [n]),
@@ -2283,7 +2283,7 @@ close_block(Conf) when is_list(Conf) ->
ok = disk_log:close(n),
{error, no_such_log} = disk_log:info(n),
sync_do(Pid13, terminate),
- true = (P0 == pps()),
+ check_pps(P0),
del(File, No), % cleanup
ok.
@@ -2487,7 +2487,7 @@ error_repair(Conf) when is_list(Conf) ->
P0 = pps(),
{error, {file_error, _, _}} =
disk_log:open([{name, n}, {file, File}, {type, wrap}, {size,{40,4}}]),
- true = (P0 == pps()),
+ check_pps(P0),
del(File, No),
ok = file:del_dir(Dir),
@@ -2506,7 +2506,7 @@ error_repair(Conf) when is_list(Conf) ->
disk_log:open([{name, n}, {file, File}, {type, wrap},
{format, internal}, {size, {40,No}}]),
ok = disk_log:close(n),
- true = (P1 == pps()),
+ check_pps(P1),
del(File, No),
receive {info_msg, _, "disk_log: repairing" ++ _, _} -> ok
after 1000 -> ct:fail(failed) end,
@@ -2524,7 +2524,7 @@ error_repair(Conf) when is_list(Conf) ->
disk_log:open([{name, n}, {file, File}, {type, wrap},
{format, internal}, {size, {4000,No}}]),
ok = disk_log:close(n),
- true = (P2 == pps()),
+ check_pps(P2),
del(File, No),
receive {info_msg, _, "disk_log: repairing" ++ _, _} -> ok
after 1000 -> ct:fail(failed) end,
@@ -2633,7 +2633,7 @@ error_log(Conf) when is_list(Conf) ->
{ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap},
{format, external},{size, {100, No}}]),
{error, {file_error, _, _}} = disk_log:truncate(n),
- true = (P0 == pps()),
+ check_pps(P0),
del(File, No),
%% OTP-4880.
@@ -2641,7 +2641,7 @@ error_log(Conf) when is_list(Conf) ->
{ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt},
{format, external},{size, 100000}]),
{error, {file_error, _, eisdir}} = disk_log:reopen(n, LDir),
- true = (P0 == pps()),
+ check_pps(P0),
file:delete(File),
B = mk_bytes(60),
@@ -3003,7 +3003,7 @@ error_index(Conf) when is_list(Conf) ->
{error, {invalid_index_file, _}} = disk_log:open(Args),
del(File, No),
- true = (P0 == pps()),
+ check_pps(P0),
true = (Q == qlen()),
ok.
@@ -4436,7 +4436,7 @@ dist_open2(Conf) when is_list(Conf) ->
timer:sleep(500),
file:delete(File),
- true = (P0 == pps()),
+ check_pps(P0),
%% This time the first process has a naughty head_func. This test
%% does not add very much. Perhaps it should be removed. However,
@@ -4482,7 +4482,7 @@ dist_open2(Conf) when is_list(Conf) ->
timer:sleep(100),
{error, no_such_log} = disk_log:close(Log),
file:delete(File),
- true = (P0 == pps()),
+ check_pps(P0),
No = 2,
Log2 = n2,
@@ -4511,7 +4511,7 @@ dist_open2(Conf) when is_list(Conf) ->
file:delete(File2),
del(File, No),
- true = (P0 == pps()),
+ check_pps(P0),
R.
@@ -4556,7 +4556,7 @@ dist_open2_1(Conf, Delay) ->
{error, no_such_log} = disk_log:info(Log),
file:delete(File),
- true = (P0 == pps()),
+ check_pps(P0),
ok.
@@ -4613,7 +4613,7 @@ dist_open2_2(Conf, Delay) ->
{[{Node1,{repaired,_,_,_}}],[]}} -> ok
end,
- true = (P0 == pps()),
+ check_pps(P0),
stop_node(Node1),
file:delete(File),
ok.
@@ -4791,10 +4791,59 @@ log(Name, N) ->
format_error(E) ->
lists:flatten(disk_log:format_error(E)).
+check_pps({Ports0,Procs0} = P0) ->
+ case pps() of
+ P0 ->
+ ok;
+ _ ->
+ timer:sleep(500),
+ case pps() of
+ P0 ->
+ ok;
+ {Ports1,Procs1} = P1 ->
+ case {Ports1 -- Ports0, Procs1 -- Procs0} of
+ {[], []} -> ok;
+ {PortsDiff,ProcsDiff} ->
+ io:format("failure, got ~p~n, expected ~p\n", [P1, P0]),
+ show("Old port", Ports0 -- Ports1),
+ show("New port", PortsDiff),
+ show("Old proc", Procs0 -- Procs1),
+ show("New proc", ProcsDiff),
+ ct:fail(failed)
+ end
+ end
+ end.
+
+show(_S, []) ->
+ ok;
+show(S, [{Pid, Name, InitCall}|Pids]) when is_pid(Pid) ->
+ io:format("~s: ~w (~w), ~w: ~p~n",
+ [S, Pid, proc_reg_name(Name), InitCall,
+ erlang:process_info(Pid)]),
+ show(S, Pids);
+show(S, [{Port, _}|Ports]) when is_port(Port)->
+ io:format("~s: ~w: ~p~n", [S, Port, erlang:port_info(Port)]),
+ show(S, Ports).
+
pps() ->
timer:sleep(100),
- {erlang:ports(), lists:filter(fun(P) -> erlang:is_process_alive(P) end,
- processes())}.
+ {port_list(), process_list()}.
+
+port_list() ->
+ [{P,safe_second_element(erlang:port_info(P, name))} ||
+ P <- erlang:ports()].
+
+process_list() ->
+ [{P,process_info(P, registered_name),
+ safe_second_element(process_info(P, initial_call))} ||
+ P <- processes(), erlang:is_process_alive(P)].
+
+proc_reg_name({registered_name, Name}) -> Name;
+proc_reg_name([]) -> no_reg_name.
+
+safe_second_element({_,Info}) -> Info;
+safe_second_element(Other) -> Other.
+
qlen() ->
{_, {_, N}} = lists:keysearch(message_queue_len, 1, process_info(self())),
diff --git a/lib/kernel/test/erl_distribution_SUITE.erl b/lib/kernel/test/erl_distribution_SUITE.erl
index 0e13f0383e..5a8bbd56c4 100644
--- a/lib/kernel/test/erl_distribution_SUITE.erl
+++ b/lib/kernel/test/erl_distribution_SUITE.erl
@@ -89,6 +89,7 @@ init_per_suite(Config) ->
Config.
end_per_suite(_Config) ->
+ [slave:stop(N) || N <- nodes()],
ok.
init_per_group(_GroupName, Config) ->
diff --git a/lib/kernel/test/gen_tcp_misc_SUITE.erl b/lib/kernel/test/gen_tcp_misc_SUITE.erl
index 950f5bea6f..358ca872f7 100644
--- a/lib/kernel/test/gen_tcp_misc_SUITE.erl
+++ b/lib/kernel/test/gen_tcp_misc_SUITE.erl
@@ -41,6 +41,7 @@
busy_send/1, busy_disconnect_passive/1, busy_disconnect_active/1,
fill_sendq/1, partial_recv_and_close/1,
partial_recv_and_close_2/1,partial_recv_and_close_3/1,so_priority/1,
+ recvtos/1, recvttl/1, recvtosttl/1, recvtclass/1,
%% Accept tests
primitive_accept/1,multi_accept_close_listen/1,accept_timeout/1,
accept_timeouts_in_order/1,accept_timeouts_in_order2/1,
@@ -83,7 +84,8 @@ all() ->
busy_disconnect_passive, busy_disconnect_active,
fill_sendq, partial_recv_and_close,
partial_recv_and_close_2, partial_recv_and_close_3,
- so_priority, primitive_accept,
+ so_priority, recvtos, recvttl, recvtosttl,
+ recvtclass, primitive_accept,
multi_accept_close_listen, accept_timeout,
accept_timeouts_in_order, accept_timeouts_in_order2,
accept_timeouts_in_order3, accept_timeouts_in_order4,
@@ -1914,6 +1916,232 @@ so_priority(Config) when is_list(Config) ->
end
end.
+
+
+%% IP_RECVTOS and IP_RECVTCLASS for IP_PKTOPTIONS
+%% does not seem to be implemented in Linux until kernel 3.1
+%%
+%% It seems pktoptions does not return valid values
+%% for IPv4 connect sockets. On the accept socket
+%% we get valid values, but on the connect socket we get
+%% the default values for TOS and TTL.
+%%
+%% Therefore the argument CheckConnect that enables
+%% checking the returned values for the connect socket.
+%% It is only used for recvtclass that is an IPv6 option
+%% and there we get valid values from both socket ends.
+
+recvtos(_Config) ->
+ test_pktoptions(
+ inet, [{recvtos,tos,96}],
+ fun recvtos_ok/2,
+ false).
+
+recvtosttl(_Config) ->
+ test_pktoptions(
+ inet, [{recvtos,tos,96},{recvttl,ttl,33}],
+ fun (OSType, OSVer) ->
+ recvtos_ok(OSType, OSVer) andalso recvttl_ok(OSType, OSVer)
+ end,
+ false).
+
+recvttl(_Config) ->
+ test_pktoptions(
+ inet, [{recvttl,ttl,33}],
+ fun recvttl_ok/2,
+ false).
+
+recvtclass(_Config) ->
+ {ok,IFs} = inet:getifaddrs(),
+ case
+ [Name ||
+ {Name,Opts} <- IFs,
+ lists:member({addr,{0,0,0,0,0,0,0,1}}, Opts)]
+ of
+ [_] ->
+ test_pktoptions(
+ inet6, [{recvtclass,tclass,224}],
+ fun recvtclass_ok/2,
+ true);
+ [] ->
+ {skip,{ipv6_not_supported,IFs}}
+ end.
+
+%% These version numbers are the highest noted in daily tests
+%% where the test fails for a plausible reason, so
+%% skip on that platform.
+%%
+%% On newer versions it might be fixed, but we'll see about that
+%% when machines with newer versions gets installed...
+%% If the test still fails for a plausible reason these
+%% version numbers simply should be increased.
+%% Or maybe we should change to only test on known good
+%% platforms - change {unix,_} to false?
+
+%% pktoptions is not supported for IPv4
+recvtos_ok({unix,openbsd}, OSVer) -> not semver_lt(OSVer, {6,4,0});
+recvtos_ok({unix,darwin}, OSVer) -> not semver_lt(OSVer, {17,6,0});
+recvtos_ok({unix,freebsd}, OSVer) -> not semver_lt(OSVer, {11,2,0});
+%% Using the option returns einval, so it is not implemented.
+recvtos_ok({unix,sunos}, OSVer) -> not semver_lt(OSVer, {5,12,0});
+%% Does not return any value - not implemented for pktoptions
+recvtos_ok({unix,linux}, OSVer) -> not semver_lt(OSVer, {3,1,0});
+%%
+recvtos_ok({unix,_}, _) -> true;
+recvtos_ok(_, _) -> false.
+
+%% pktoptions is not supported for IPv4
+recvttl_ok({unix,openbsd}, OSVer) -> not semver_lt(OSVer, {6,4,0});
+recvttl_ok({unix,darwin}, OSVer) -> not semver_lt(OSVer, {17,6,0});
+recvttl_ok({unix,freebsd}, OSVer) -> not semver_lt(OSVer, {11,2,0});
+%% Using the option returns einval, so it is not implemented.
+recvttl_ok({unix,sunos}, OSVer) -> not semver_lt(OSVer, {5,12,0});
+%%
+recvttl_ok({unix,linux}, _) -> true;
+recvttl_ok({unix,_}, _) -> true;
+recvttl_ok(_, _) -> false.
+
+%% pktoptions is not supported for IPv6
+recvtclass_ok({unix,openbsd}, OSVer) -> not semver_lt(OSVer, {6,4,0});
+recvtclass_ok({unix,darwin}, OSVer) -> not semver_lt(OSVer, {17,6,0});
+recvtclass_ok({unix,sunos}, OSVer) -> not semver_lt(OSVer, {5,12,0});
+%% Using the option returns einval, so it is not implemented.
+recvtclass_ok({unix,freebsd}, OSVer) -> not semver_lt(OSVer, {11,2,0});
+%% Does not return any value - not implemented for pktoptions
+recvtclass_ok({unix,linux}, OSVer) -> not semver_lt(OSVer, {3,1,0});
+%%
+recvtclass_ok({unix,_}, _) -> true;
+recvtclass_ok(_, _) -> false.
+
+semver_lt({X1,Y1,Z1}, {X2,Y2,Z2}) ->
+ if
+ X1 > X2 -> false;
+ X1 < X2 -> true;
+ Y1 > Y2 -> false;
+ Y1 < Y2 -> true;
+ Z1 > Z2 -> false;
+ Z1 < Z2 -> true;
+ true -> false
+ end;
+semver_lt(_, {_,_,_}) -> false.
+
+test_pktoptions(Family, Spec, OSFilter, CheckConnect) ->
+ OSType = os:type(),
+ OSVer = os:version(),
+ case OSFilter(OSType, OSVer) of
+ true ->
+ io:format("Os: ~p, ~p~n", [OSType,OSVer]),
+ test_pktoptions(Family, Spec, CheckConnect, OSType, OSVer);
+ false ->
+ {skip,{not_supported_for_os_version,{OSType,OSVer}}}
+ end.
+%%
+test_pktoptions(Family, Spec, CheckConnect, OSType, OSVer) ->
+ Timeout = 5000,
+ RecvOpts = [RecvOpt || {RecvOpt,_,_} <- Spec],
+ TrueRecvOpts = [{RecvOpt,true} || {RecvOpt,_,_} <- Spec],
+ FalseRecvOpts = [{RecvOpt,false} || {RecvOpt,_,_} <- Spec],
+ Opts = [Opt || {_,Opt,_} <- Spec],
+ OptsVals = [{Opt,Val} || {_,Opt,Val} <- Spec],
+ Address =
+ case Family of
+ inet ->
+ {127,0,0,1};
+ inet6 ->
+ {0,0,0,0,0,0,0,1}
+ end,
+ %%
+ %% Set RecvOpts on listen socket
+ {ok,L} =
+ gen_tcp:listen(
+ 0,
+ [Family,binary,{active,false},{send_timeout,Timeout}
+ |TrueRecvOpts]),
+ {ok,P} = inet:port(L),
+ {ok,TrueRecvOpts} = inet:getopts(L, RecvOpts),
+ {ok,OptsValsDefault} = inet:getopts(L, Opts),
+ %%
+ %% Set RecvOpts and Option values on connect socket
+ {ok,S2} =
+ gen_tcp:connect(
+ Address, P,
+ [Family,binary,{active,false},{send_timeout,Timeout}
+ |TrueRecvOpts ++ OptsVals],
+ Timeout),
+ {ok,TrueRecvOpts} = inet:getopts(S2, RecvOpts),
+ {ok,OptsVals} = inet:getopts(S2, Opts),
+ %%
+ %% Accept socket inherits the options from listen socket
+ {ok,S1} = gen_tcp:accept(L, Timeout),
+ {ok,TrueRecvOpts} = inet:getopts(S1, RecvOpts),
+ {ok,OptsValsDefault} = inet:getopts(S1, Opts),
+%%% %%
+%%% %% Handshake
+%%% ok = gen_tcp:send(S1, <<"hello">>),
+%%% {ok,<<"hello">>} = gen_tcp:recv(S2, 5, Timeout),
+%%% ok = gen_tcp:send(S2, <<"hi">>),
+%%% {ok,<<"hi">>} = gen_tcp:recv(S1, 2, Timeout),
+ %%
+ %% Verify returned remote options
+ {ok,[{pktoptions,OptsVals1}]} = inet:getopts(S1, [pktoptions]),
+ {ok,[{pktoptions,OptsVals2}]} = inet:getopts(S2, [pktoptions]),
+ (Result1 = sets_eq(OptsVals1, OptsVals))
+ orelse io:format(
+ "Accept differs: ~p neq ~p~n", [OptsVals1,OptsVals]),
+ (Result2 = sets_eq(OptsVals2, OptsValsDefault))
+ orelse io:format(
+ "Connect differs: ~p neq ~p~n",
+ [OptsVals2,OptsValsDefault]),
+ %%
+ ok = gen_tcp:close(S2),
+ ok = gen_tcp:close(S1),
+ %%
+ %%
+ %% Clear RecvOpts on listen socket and set Option values
+ ok = inet:setopts(L, FalseRecvOpts ++ OptsVals),
+ {ok,FalseRecvOpts} = inet:getopts(L, RecvOpts),
+ {ok,OptsVals} = inet:getopts(L, Opts),
+ %%
+ %% Set RecvOpts on connecting socket
+ %%
+ {ok,S4} =
+ gen_tcp:connect(
+ Address, P,
+ [Family,binary,{active,false},{send_timeout,Timeout}
+ |TrueRecvOpts],
+ Timeout),
+ {ok,TrueRecvOpts} = inet:getopts(S4, RecvOpts),
+ {ok,OptsValsDefault} = inet:getopts(S4, Opts),
+ %%
+ %% Accept socket inherits the options from listen socket
+ {ok,S3} = gen_tcp:accept(L, Timeout),
+ {ok,FalseRecvOpts} = inet:getopts(S3, RecvOpts),
+ {ok,OptsVals} = inet:getopts(S3, Opts),
+ %%
+ %% Verify returned remote options
+ {ok,[{pktoptions,[]}]} = inet:getopts(S3, [pktoptions]),
+ {ok,[{pktoptions,OptsVals4}]} = inet:getopts(S4, [pktoptions]),
+ (Result3 = sets_eq(OptsVals4, OptsVals))
+ orelse io:format(
+ "Accept2 differs: ~p neq ~p~n", [OptsVals4,OptsVals]),
+ %%
+ ok = gen_tcp:close(S4),
+ ok = gen_tcp:close(S3),
+ ok = gen_tcp:close(L),
+ (Result1 and ((not CheckConnect) or (Result2 and Result3)))
+ orelse
+ exit({failed,
+ [{OptsVals1,OptsVals4,OptsVals},
+ {OptsVals2,OptsValsDefault}],
+ {OSType,OSVer}}),
+%% exit({{OSType,OSVer},success}), % In search for the truth
+ ok.
+
+sets_eq(L1, L2) ->
+ lists:sort(L1) == lists:sort(L2).
+
+
+
%% Accept test utilities (suites are below)
millis() ->
@@ -2205,7 +2433,7 @@ wait_until_accepting(Proc,0) ->
exit({timeout_waiting_for_accepting,Proc});
wait_until_accepting(Proc,N) ->
case process_info(Proc,current_function) of
- {current_function,{prim_inet,accept0,2}} ->
+ {current_function,{prim_inet,accept0,3}} ->
case process_info(Proc,status) of
{status,waiting} ->
ok;
diff --git a/lib/kernel/test/gen_udp_SUITE.erl b/lib/kernel/test/gen_udp_SUITE.erl
index 3acfff929e..af9985de45 100644
--- a/lib/kernel/test/gen_udp_SUITE.erl
+++ b/lib/kernel/test/gen_udp_SUITE.erl
@@ -36,6 +36,7 @@
-export([send_to_closed/1, active_n/1,
buffer_size/1, binary_passive_recv/1, max_buffer_size/1, bad_address/1,
read_packets/1, open_fd/1, connect/1, implicit_inet6/1,
+ recvtos/1, recvtosttl/1, recvttl/1, recvtclass/1,
local_basic/1, local_unbound/1,
local_fdopen/1, local_fdopen_unbound/1, local_abstract/1]).
@@ -47,6 +48,7 @@ all() ->
[send_to_closed, buffer_size, binary_passive_recv, max_buffer_size,
bad_address, read_packets, open_fd, connect,
implicit_inet6, active_n,
+ recvtos, recvtosttl, recvttl, recvtclass,
{group, local}].
groups() ->
@@ -572,6 +574,168 @@ active_n(Config) when is_list(Config) ->
ok.
+
+recvtos(_Config) ->
+ test_recv_opts(
+ inet, [{recvtos,tos,96}],
+ fun recvtos_ok/2).
+
+recvtosttl(_Config) ->
+ test_recv_opts(
+ inet, [{recvtos,tos,96},{recvttl,ttl,33}],
+ fun (OSType, OSVer) ->
+ recvtos_ok(OSType, OSVer) andalso recvttl_ok(OSType, OSVer)
+ end).
+
+recvttl(_Config) ->
+ test_recv_opts(
+ inet, [{recvttl,ttl,33}],
+ fun recvttl_ok/2).
+
+recvtclass(_Config) ->
+ {ok,IFs} = inet:getifaddrs(),
+ case
+ [Name ||
+ {Name,Opts} <- IFs,
+ lists:member({addr,{0,0,0,0,0,0,0,1}}, Opts)]
+ of
+ [_] ->
+ test_recv_opts(
+ inet6, [{recvtclass,tclass,224}],
+ fun recvtclass_ok/2);
+ [] ->
+ {skip,ipv6_not_supported,IFs}
+ end.
+
+%% These version numbers are just above the highest noted in daily tests
+%% where the test fails for a plausible reason, that is the lowest
+%% where we can expect that the test mighe succeed, so
+%% skip on platforms lower than this.
+%%
+%% On newer versions it might be fixed, but we'll see about that
+%% when machines with newer versions gets installed...
+%% If the test still fails for a plausible reason these
+%% version numbers simply should be increased.
+%% Or maybe we should change to only test on known good platforms?
+
+%% Using the option returns einval, so it is not implemented.
+recvtos_ok({unix,darwin}, OSVer) -> not semver_lt(OSVer, {17,6,0});
+%% Using the option returns einval, so it is not implemented.
+recvtos_ok({unix,openbsd}, OSVer) -> not semver_lt(OSVer, {6,4,0});
+%% Using the option returns einval, so it is not implemented.
+recvtos_ok({unix,sunos}, OSVer) -> not semver_lt(OSVer, {5,12,0});
+%%
+recvtos_ok({unix,_}, _) -> true;
+recvtos_ok(_, _) -> false.
+
+recvttl_ok({unix,_}, _) -> true;
+recvttl_ok(_, _) -> false.
+
+%% Using the option returns einval, so it is not implemented.
+recvtclass_ok({unix,darwin}, OSVer) -> not semver_lt(OSVer, {9,9,0});
+recvtclass_ok({unix,linux}, OSVer) -> not semver_lt(OSVer, {2,6,11});
+%%
+recvtclass_ok({unix,_}, _) -> true;
+recvtclass_ok(_, _) -> false.
+
+semver_lt({X1,Y1,Z1}, {X2,Y2,Z2}) ->
+ if
+ X1 > X2 -> false;
+ X1 < X2 -> true;
+ Y1 > Y2 -> false;
+ Y1 < Y2 -> true;
+ Z1 > Z2 -> false;
+ Z1 < Z2 -> true;
+ true -> false
+ end;
+semver_lt(_, {_,_,_}) -> false.
+
+test_recv_opts(Family, Spec, OSFilter) ->
+ OSType = os:type(),
+ OSVer = os:version(),
+ case OSFilter(OSType, OSVer) of
+ true ->
+ io:format("Os: ~p, ~p~n", [OSType,OSVer]),
+ test_recv_opts(Family, Spec, OSType, OSVer);
+ false ->
+ {skip,{not_supported_for_os_version,{OSType,OSVer}}}
+ end.
+%%
+test_recv_opts(Family, Spec, _OSType, _OSVer) ->
+ Timeout = 5000,
+ RecvOpts = [RecvOpt || {RecvOpt,_,_} <- Spec],
+ TrueRecvOpts = [{RecvOpt,true} || {RecvOpt,_,_} <- Spec],
+ FalseRecvOpts = [{RecvOpt,false} || {RecvOpt,_,_} <- Spec],
+ Opts = [Opt || {_,Opt,_} <- Spec],
+ OptsVals = [{Opt,Val} || {_,Opt,Val} <- Spec],
+ TrueRecvOpts_OptsVals = TrueRecvOpts ++ OptsVals,
+ Addr =
+ case Family of
+ inet ->
+ {127,0,0,1};
+ inet6 ->
+ {0,0,0,0,0,0,0,1}
+ end,
+ %%
+ {ok,S1} =
+ gen_udp:open(0, [Family,binary,{active,false}|TrueRecvOpts]),
+ {ok,P1} = inet:port(S1),
+ {ok,TrueRecvOpts} = inet:getopts(S1, RecvOpts),
+ ok = inet:setopts(S1, FalseRecvOpts),
+ {ok,FalseRecvOpts} = inet:getopts(S1, RecvOpts),
+ ok = inet:setopts(S1, TrueRecvOpts_OptsVals),
+ {ok,TrueRecvOpts_OptsVals} = inet:getopts(S1, RecvOpts ++ Opts),
+ %%
+ {ok,S2} =
+ gen_udp:open(0, [Family,binary,{active,true}|FalseRecvOpts]),
+ {ok,P2} = inet:port(S2),
+ {ok,FalseRecvOpts_OptsVals2} = inet:getopts(S2, RecvOpts ++ Opts),
+ OptsVals2 = FalseRecvOpts_OptsVals2 -- FalseRecvOpts,
+ %%
+ ok = gen_udp:send(S2, Addr, P1, <<"abcde">>),
+ ok = gen_udp:send(S1, Addr, P2, <<"fghij">>),
+ {ok,{_,P2,OptsVals3,<<"abcde">>}} = gen_udp:recv(S1, 0, Timeout),
+ verify_sets_eq(OptsVals3, OptsVals2),
+ receive
+ {udp,S2,_,P1,<<"fghij">>} ->
+ ok;
+ Other1 ->
+ exit({unexpected,Other1})
+ after Timeout ->
+ exit(timeout)
+ end,
+ %%
+ ok = inet:setopts(S1, FalseRecvOpts),
+ {ok,FalseRecvOpts} = inet:getopts(S1, RecvOpts),
+ ok = inet:setopts(S2, TrueRecvOpts),
+ {ok,TrueRecvOpts} = inet:getopts(S2, RecvOpts),
+ %%
+ ok = gen_udp:send(S2, Addr, P1, <<"klmno">>),
+ ok = gen_udp:send(S1, Addr, P2, <<"pqrst">>),
+ {ok,{_,P2,<<"klmno">>}} = gen_udp:recv(S1, 0, Timeout),
+ receive
+ {udp,S2,_,P1,OptsVals4,<<"pqrst">>} ->
+ verify_sets_eq(OptsVals4, OptsVals);
+ Other2 ->
+ exit({unexpected,Other2})
+ after Timeout ->
+ exit(timeout)
+ end,
+ ok = gen_udp:close(S1),
+ ok = gen_udp:close(S2),
+%% exit({{OSType,OSVer},success}), % In search for the truth
+ ok.
+
+verify_sets_eq(L1, L2) ->
+ L = lists:sort(L1),
+ case lists:sort(L2) of
+ L ->
+ ok;
+ _ ->
+ exit({sets_neq,L1,L2})
+ end.
+
+
local_basic(_Config) ->
SFile = local_filename(server),
SAddr = {local,bin_filename(SFile)},
diff --git a/lib/kernel/test/global_SUITE.erl b/lib/kernel/test/global_SUITE.erl
index 0e7b7adc47..8eab36e308 100644
--- a/lib/kernel/test/global_SUITE.erl
+++ b/lib/kernel/test/global_SUITE.erl
@@ -1383,7 +1383,7 @@ ring(Config) when is_list(Config) ->
rpc_cast(Cp8, ?MODULE, single_node, [Time, Cp7, Config]),
%% sleep to make the partitioned net ready
- ct:sleep(Time - msec()),
+ sleep(Time - msec()),
pong = net_adm:ping(Cp0),
pong = net_adm:ping(Cp1),
@@ -1466,7 +1466,7 @@ simple_ring(Config) when is_list(Config) ->
rpc_cast(Cp5, ?MODULE, single_node, [Time, Cp4, Config]),
%% sleep to make the partitioned net ready
- ct:sleep(Time - msec()),
+ sleep(Time - msec()),
pong = net_adm:ping(Cp0),
pong = net_adm:ping(Cp1),
@@ -1542,7 +1542,7 @@ line(Config) when is_list(Config) ->
rpc_cast(Cp8, ?MODULE, single_node, [Time, Cp7, Config]),
%% Sleep to make the partitioned net ready
- ct:sleep(Time - msec()),
+ sleep(Time - msec()),
pong = net_adm:ping(Cp0),
pong = net_adm:ping(Cp1),
@@ -1626,7 +1626,7 @@ simple_line(Config) when is_list(Config) ->
rpc_cast(Cp5, ?MODULE, single_node, [Time, Cp4, Config]),
%% sleep to make the partitioned net ready
- ct:sleep(Time - msec()),
+ sleep(Time - msec()),
pong = net_adm:ping(Cp0),
pong = net_adm:ping(Cp1),
@@ -3555,7 +3555,7 @@ single_node(Time, Node, Config) ->
lists:foreach(fun(N) -> _ = erlang:disconnect_node(N) end, nodes()),
?UNTIL(get_known(node()) =:= [node()]),
spawn(?MODULE, init_2, []),
- ct:sleep(Time - msec()),
+ sleep(Time - msec()),
net_adm:ping(Node).
init_2() ->
@@ -4009,13 +4009,6 @@ collect_nodes(N, Max) ->
[Node | collect_nodes(N+1, Max)]
end.
-only_element(_E, []) ->
- true;
-only_element(E, [E|R]) ->
- only_element(E, R);
-only_element(_E, _) ->
- false.
-
exit_p(Pid) ->
Ref = erlang:monitor(process, Pid),
Pid ! die,
@@ -4038,6 +4031,11 @@ wait_for_exit_fast(Pid) ->
ok
end.
+sleep(Time) when Time > 0 ->
+ ct:sleep(Time);
+sleep(_Time) ->
+ ok.
+
check_everywhere(Nodes, Name, Config) ->
?UNTIL(begin
case rpc:multicall(Nodes, global, whereis_name, [Name]) of
@@ -4162,10 +4160,10 @@ rpc_cast(Node, Module, Function, Args, File) ->
%% The emulator now ensures that the node has been removed from
%% nodes().
-rpc_disconnect_node(Node, DisconnectedNode, _Config) ->
- True = rpc:call(Node, erlang, disconnect_node, [DisconnectedNode]),
- False = lists:member(DisconnectedNode, rpc:call(Node, erlang, nodes, [])),
- {true, false} = {True, False}.
+rpc_disconnect_node(Node, DisconnectedNode, Config) ->
+ true = rpc:call(Node, erlang, disconnect_node, [DisconnectedNode]),
+ ?UNTIL
+ (not lists:member(DisconnectedNode, rpc:call(Node, erlang, nodes, []))).
%%%
%%% Utility
diff --git a/lib/kernel/test/logger_SUITE.erl b/lib/kernel/test/logger_SUITE.erl
index 6bd9b20c35..b7ccba8e70 100644
--- a/lib/kernel/test/logger_SUITE.erl
+++ b/lib/kernel/test/logger_SUITE.erl
@@ -37,7 +37,8 @@
suite() ->
- [{timetrap,{seconds,30}}].
+ [{timetrap,{seconds,30}},
+ {ct_hooks,[logger_test_lib]}].
init_per_suite(Config) ->
case logger:get_handler_config(?STANDARD_HANDLER) of
@@ -98,7 +99,9 @@ all() ->
via_logger_process,
other_node,
compare_levels,
- process_metadata].
+ process_metadata,
+ app_config,
+ kernel_config].
start_stop(_Config) ->
S = whereis(logger),
@@ -211,6 +214,7 @@ add_remove_filter(cleanup,_Config) ->
change_config(_Config) ->
%% Overwrite handler config - check that defaults are added
+ {error,{not_found,h1}} = logger:set_handler_config(h1,#{}),
ok = logger:add_handler(h1,?MODULE,#{level=>notice,custom=>custom}),
{ok,#{module:=?MODULE,level:=notice,filter_default:=log,custom:=custom}} =
logger:get_handler_config(h1),
@@ -259,7 +263,7 @@ change_config(_Config) ->
logger:get_primary_config(),
3 = maps:size(PC1),
%% Check that internal 'handlers' field has not been changed
- MS = [{{{?HANDLER_KEY,'$1'},'_','_','_'},[],['$1']}],
+ MS = [{{{?HANDLER_KEY,'$1'},'_','_'},[],['$1']}],
HIds1 = lists:sort(ets:select(?LOGGER_TABLE,MS)), % dirty, internal data
HIds2 = lists:sort(logger:get_handler_ids()),
HIds1 = HIds2,
@@ -389,6 +393,8 @@ set_module_level(_Config) ->
{error,{invalid_level,bad}} = logger:set_module_level(?MODULE,bad),
{error,{not_a_list_of_modules,{bad}}} =
logger:set_module_level({bad},warning),
+ {error,{not_a_list_of_modules,[{bad}]}} =
+ logger:set_module_level([{bad}],warning),
ok = logger:set_module_level(?MODULE,warning),
[{?MODULE,warning}] = logger:get_module_level([?MODULE,other]),
[{?MODULE,warning}] = logger:get_module_level(?MODULE),
@@ -405,6 +411,7 @@ set_module_level(_Config) ->
ok = check_logged(notice,M2,?MY_LOC(1)),
{error,{not_a_list_of_modules,{bad}}} = logger:unset_module_level({bad}),
+ {error,{not_a_list_of_modules,[{bad}]}} = logger:unset_module_level([{bad}]),
ok = logger:unset_module_level(?MODULE),
[] = logger:get_module_level([?MODULE,other]),
[] = logger:get_module_level(?MODULE),
@@ -429,27 +436,32 @@ set_application_level(_Config) ->
{error,{not_loaded,mnesia}} = logger:set_application_level(mnesia, warning),
{error,{not_loaded,mnesia}} = logger:unset_application_level(mnesia),
- application:load(mnesia),
- {ok, Modules} = application:get_key(mnesia, modules),
- [] = logger:get_module_level(Modules),
+ case application:load(mnesia) of
+ ok ->
+ {ok, Modules} = application:get_key(mnesia, modules),
+ [] = logger:get_module_level(Modules),
- {error,{invalid_level,warn}} = logger:set_application_level(mnesia, warn),
+ {error,{invalid_level,warn}} =
+ logger:set_application_level(mnesia, warn),
- ok = logger:set_application_level(mnesia, debug),
- DebugModules = lists:sort([{M,debug} || M <- Modules]),
- DebugModules = lists:sort(logger:get_module_level(Modules)),
+ ok = logger:set_application_level(mnesia, debug),
+ DebugModules = lists:sort([{M,debug} || M <- Modules]),
+ DebugModules = lists:sort(logger:get_module_level(Modules)),
- ok = logger:set_application_level(mnesia, warning),
+ ok = logger:set_application_level(mnesia, warning),
- WarnModules = lists:sort([{M,warning} || M <- Modules]),
- WarnModules = lists:sort(logger:get_module_level(Modules)),
+ WarnModules = lists:sort([{M,warning} || M <- Modules]),
+ WarnModules = lists:sort(logger:get_module_level(Modules)),
- ok = logger:unset_application_level(mnesia),
- [] = logger:get_module_level(Modules).
+ ok = logger:unset_application_level(mnesia),
+ [] = logger:get_module_level(Modules);
+ {error,{"no such file or directory","mnesia.app"}} ->
+ {skip, "Cannot load mnesia, does not exist"}
+ end.
set_application_level(cleanup,_Config) ->
- ok = logger:unset_application_level(mnesia),
- ok = application:unload(mnesia),
+ _ = logger:unset_application_level(mnesia),
+ _ = application:unload(mnesia),
ok.
cache_module_level(_Config) ->
@@ -547,7 +559,7 @@ handler_failed(_Config) ->
register(callback_receiver,self()),
{error,{invalid_id,1}} = logger:add_handler(1,?MODULE,#{}),
{error,{invalid_module,"nomodule"}} = logger:add_handler(h1,"nomodule",#{}),
- {error,{invalid_handler_config,bad}} = logger:add_handler(h1,?MODULE,bad),
+ {error,{invalid_config,bad}} = logger:add_handler(h1,?MODULE,bad),
{error,{invalid_filters,false}} =
logger:add_handler(h1,?MODULE,#{filters=>false}),
{error,{invalid_filter_default,true}} =
@@ -622,7 +634,8 @@ handler_failed(cleanup,_Config) ->
ok.
config_sanity_check(_Config) ->
- %% Logger config
+ %% Primary config
+ {error,{invalid_config,bad}} = logger:set_primary_config(bad),
{error,{invalid_filter_default,bad}} =
logger:set_primary_config(filter_default,bad),
{error,{invalid_level,bad}} = logger:set_primary_config(level,bad),
@@ -895,12 +908,227 @@ process_metadata(_Config) ->
ok = logger:unset_process_metadata(),
undefined = logger:get_process_metadata(),
+ ok = logger:update_process_metadata(#{custom=>added_again}),
+ {error,badarg} = ?TRY(logger:update_process_metadata(bad)),
+ #{custom:=added_again} = logger:get_process_metadata(),
+
ok.
process_metadata(cleanup,_Config) ->
logger:remove_handler(h1),
ok.
+app_config(Config) ->
+ %% Start a node with default configuration
+ {ok,_,Node} = logger_test_lib:setup(Config,[]),
+
+ App1Name = app1,
+ App1 = {application, App1Name,
+ [{description, "Test of app with logger config"},
+ {applications, [kernel]}]},
+ ok = rpc:call(Node,application,load,[App1]),
+ ok = rpc:call(Node,application,set_env,
+ [App1Name,logger,[{handler,default,logger_std_h,#{}}]]),
+
+ %% Try to add an own default handler
+ {error,{bad_config,{handler,{app1,{already_exist,default}}}}} =
+ rpc:call(Node,logger,add_handlers,[App1Name]),
+
+ %% Add a different handler
+ ok = rpc:call(Node,application,set_env,[App1Name,logger,
+ [{handler,myh,logger_std_h,#{}}]]),
+ ok = rpc:call(Node,logger,add_handlers,[App1Name]),
+
+ {ok,#{filters:=DF}} = rpc:call(Node,logger,get_handler_config,[default]),
+ {ok,#{filters:=[]}} = rpc:call(Node,logger,get_handler_config,[myh]),
+
+ true = test_server:stop_node(Node),
+
+ %% Start a node with no default handler, then add an own default handler
+ {ok,#{handlers:=[#{id:=simple}]},Node} =
+ logger_test_lib:setup(Config,[{logger,[{handler,default,undefined}]}]),
+
+ ok = rpc:call(Node,application,load,[App1]),
+ ok = rpc:call(Node,application,set_env,
+ [App1Name,logger,[{handler,default,logger_std_h,#{}}]]),
+ ok = rpc:call(Node,logger,add_handlers,[App1Name]),
+
+ #{handlers:=[#{id:=default,filters:=DF}]} =
+ rpc:call(Node,logger,get_config,[]),
+
+ true = test_server:stop_node(Node),
+
+ %% Start a silent node, then add an own default handler
+ {ok,#{handlers:=[]},Node} =
+ logger_test_lib:setup(Config,[{error_logger,silent}]),
+
+ {error,{bad_config,{handler,[{some,bad,config}]}}} =
+ rpc:call(Node,logger,add_handlers,[[{some,bad,config}]]),
+ ok = rpc:call(Node,logger,add_handlers,
+ [[{handler,default,logger_std_h,#{}}]]),
+
+ #{handlers:=[#{id:=default,filters:=DF}]} =
+ rpc:call(Node,logger,get_config,[]),
+
+ ok.
+
+%% This test case is maintly to see code coverage. Note that
+%% logger_env_var_SUITE tests a lot of the same, and checks the
+%% functionality more thoroughly, but since it all happens at node
+%% start, it is not possible to see code coverage in that test.
+kernel_config(Config) ->
+ %% Start a node with simple handler only, then simulate kernel
+ %% start by calling internally exported
+ %% internal_init_logger(). This is to test all variants of kernel
+ %% config, including bad config, and see the code coverage.
+ {ok,#{handlers:=[#{id:=simple,filters:=DF}]}=LC,Node} =
+ logger_test_lib:setup(Config,[{error_logger,false}]),
+
+ %% Same once more, to get coverage
+ ok = rpc:call(Node,logger,internal_init_logger,[]),
+ ok = rpc:call(Node,logger,add_handlers,[kernel]),
+ LC = rpc:call(Node,logger,get_config,[]),
+
+ %% This shall mean the same as above, but using 'logger' parameter
+ %% instead of 'error_logger'
+ ok = rpc:call(Node,application,unset_env,[kernel,error_logger]),
+ ok = rpc:call(Node,application,set_env,
+ [kernel,logger,[{handler,default,undefined}]]),
+ ok = rpc:call(Node,logger,internal_init_logger,[]),
+ ok = rpc:call(Node,logger,add_handlers,[kernel]),
+ LC = rpc:call(Node,logger,get_config,[]),
+
+ %% Silent
+ ok = rpc:call(Node,application,unset_env,[kernel,logger]),
+ ok = rpc:call(Node,application,set_env,[kernel,error_logger,silent]),
+ ok = rpc:call(Node,logger,internal_init_logger,[]),
+ ok = rpc:call(Node,logger,add_handlers,[kernel]),
+ #{primary:=#{filter_default:=log,filters:=[]},
+ handlers:=[],
+ module_levels:=[]} = rpc:call(Node,logger,get_config,[]),
+
+ %% Default
+ ok = rpc:call(Node,application,unset_env,[kernel,error_logger]),
+ ok = rpc:call(Node,application,unset_env,[kernel,logger]),
+ ok = rpc:call(Node,logger,internal_init_logger,[]),
+ ok = rpc:call(Node,logger,add_handlers,[kernel]),
+ #{primary:=#{filter_default:=log,filters:=[]},
+ handlers:=[#{id:=default,filters:=DF,config:=#{type:=standard_io}}],
+ module_levels:=[]} = rpc:call(Node,logger,get_config,[]),
+
+ %% error_logger=tty (same as default)
+ ok = rpc:call(Node,logger,remove_handler,[default]),% so it can be added again
+ ok = rpc:call(Node,application,set_env,[kernel,error_logger,tty]),
+ ok = rpc:call(Node,application,unset_env,[kernel,logger]),
+ ok = rpc:call(Node,logger,internal_init_logger,[]),
+ ok = rpc:call(Node,logger,add_handlers,[kernel]),
+ #{primary:=#{filter_default:=log,filters:=[]},
+ handlers:=[#{id:=default,filters:=DF,config:=#{type:=standard_io}}],
+ module_levels:=[]} = rpc:call(Node,logger,get_config,[]),
+
+ %% error_logger={file,File}
+ ok = rpc:call(Node,logger,remove_handler,[default]),% so it can be added again
+ F = filename:join(?config(priv_dir,Config),
+ atom_to_list(?FUNCTION_NAME)++".log"),
+ ok = rpc:call(Node,application,set_env,[kernel,error_logger,{file,F}]),
+ ok = rpc:call(Node,application,unset_env,[kernel,logger]),
+ ok = rpc:call(Node,logger,internal_init_logger,[]),
+ ok = rpc:call(Node,logger,add_handlers,[kernel]),
+ #{primary:=#{filter_default:=log,filters:=[]},
+ handlers:=[#{id:=default,filters:=DF,config:=#{type:={file,F}}}],
+ module_levels:=[]} = rpc:call(Node,logger,get_config,[]),
+
+ %% Same, but using 'logger' parameter instead of 'error_logger'
+ ok = rpc:call(Node,logger,remove_handler,[default]),% so it can be added again
+ ok = rpc:call(Node,application,unset_env,[kernel,error_logger]),
+ ok = rpc:call(Node,application,set_env,[kernel,logger,
+ [{handler,default,logger_std_h,
+ #{config=>#{type=>{file,F}}}}]]),
+ ok = rpc:call(Node,logger,internal_init_logger,[]),
+ ok = rpc:call(Node,logger,add_handlers,[kernel]),
+ #{primary:=#{filter_default:=log,filters:=[]},
+ handlers:=[#{id:=default,filters:=DF,config:=#{type:={file,F}}}],
+ module_levels:=[]} = rpc:call(Node,logger,get_config,[]),
+
+ %% Same, but with type={file,File,Modes}
+ ok = rpc:call(Node,logger,remove_handler,[default]),% so it can be added again
+ ok = rpc:call(Node,application,unset_env,[kernel,error_logger]),
+ M = [raw,write,delayed_write],
+ ok = rpc:call(Node,application,set_env,[kernel,logger,
+ [{handler,default,logger_std_h,
+ #{config=>#{type=>{file,F,M}}}}]]),
+ ok = rpc:call(Node,logger,internal_init_logger,[]),
+ ok = rpc:call(Node,logger,add_handlers,[kernel]),
+ #{primary:=#{filter_default:=log,filters:=[]},
+ handlers:=[#{id:=default,filters:=DF,config:=#{type:={file,F,M}}}],
+ module_levels:=[]} = rpc:call(Node,logger,get_config,[]),
+
+ %% Same, but with disk_log handler
+ ok = rpc:call(Node,logger,remove_handler,[default]),% so it can be added again
+ ok = rpc:call(Node,application,unset_env,[kernel,error_logger]),
+ M = [raw,write,delayed_write],
+ ok = rpc:call(Node,application,set_env,[kernel,logger,
+ [{handler,default,logger_disk_log_h,
+ #{config=>#{file=>F}}}]]),
+ ok = rpc:call(Node,logger,internal_init_logger,[]),
+ ok = rpc:call(Node,logger,add_handlers,[kernel]),
+ #{primary:=#{filter_default:=log,filters:=[]},
+ handlers:=[#{id:=default,filters:=DF,config:=#{file:=F}}],
+ module_levels:=[]} = rpc:call(Node,logger,get_config,[]),
+
+ %% Set primary filters and module level. No default handler.
+ ok = rpc:call(Node,logger,remove_handler,[default]),% so it can be added again
+ ok = rpc:call(Node,application,unset_env,[kernel,error_logger]),
+ ok = rpc:call(Node,application,set_env,
+ [kernel,logger,[{handler,default,undefined},
+ {filters,stop,[{f1,{fun(_,_) -> log end,ok}}]},
+ {module_level,debug,[?MODULE]}]]),
+ ok = rpc:call(Node,logger,internal_init_logger,[]),
+ ok = rpc:call(Node,logger,add_handlers,[kernel]),
+ #{primary:=#{filter_default:=stop,filters:=[_]},
+ handlers:=[],
+ module_levels:=[{?MODULE,debug}]} = rpc:call(Node,logger,get_config,[]),
+
+ %% Bad config
+ ok = rpc:call(Node,application,unset_env,[kernel,logger]),
+
+ ok = rpc:call(Node,application,set_env,[kernel,error_logger,bad]),
+ {error,{bad_config,{kernel,{error_logger,bad}}}} =
+ rpc:call(Node,logger,internal_init_logger,[]),
+
+ ok = rpc:call(Node,application,unset_env,[kernel,error_logger]),
+ ok = rpc:call(Node,application,set_env,[kernel,logger_level,bad]),
+ {error,{bad_config,{kernel,{logger_level,bad}}}} =
+ rpc:call(Node,logger,internal_init_logger,[]),
+
+ ok = rpc:call(Node,application,unset_env,[kernel,logger_level]),
+ ok = rpc:call(Node,application,set_env,
+ [kernel,logger,[{filters,stop,[bad]}]]),
+ {error,{bad_config,{kernel,{invalid_filters,[bad]}}}} =
+ rpc:call(Node,logger,internal_init_logger,[]),
+
+ ok = rpc:call(Node,application,set_env,
+ [kernel,logger,[{filters,stop,[bad]}]]),
+ {error,{bad_config,{kernel,{invalid_filters,[bad]}}}} =
+ rpc:call(Node,logger,internal_init_logger,[]),
+
+ ok = rpc:call(Node,application,set_env,
+ [kernel,logger,[{filters,stop,[{f1,bad}]}]]),
+ {error,{bad_config,{kernel,{invalid_filter,{f1,bad}}}}} =
+ rpc:call(Node,logger,internal_init_logger,[]),
+
+ ok = rpc:call(Node,application,set_env,
+ [kernel,logger,MF=[{filters,stop,[]},{filters,log,[]}]]),
+ {error,{bad_config,{kernel,{multiple_filters,MF}}}} =
+ rpc:call(Node,logger,internal_init_logger,[]),
+
+ ok = rpc:call(Node,application,set_env,
+ [kernel,logger,[{module_level,bad,[?MODULE]}]]),
+ {error,{bad_config,{kernel,{invalid_level,bad}}}} =
+ rpc:call(Node,logger,internal_init_logger,[]),
+
+ ok.
+
%%%-----------------------------------------------------------------
%%% Internal
check_logged(Level,Format,Args,Meta) ->
diff --git a/lib/kernel/test/logger_disk_log_h_SUITE.erl b/lib/kernel/test/logger_disk_log_h_SUITE.erl
index a4b15c841b..a815db14e9 100644
--- a/lib/kernel/test/logger_disk_log_h_SUITE.erl
+++ b/lib/kernel/test/logger_disk_log_h_SUITE.erl
@@ -367,7 +367,7 @@ formatter_fail(Config) ->
ok = logger:set_handler_config(Name,formatter,{?MODULE,bad_return}),
logger:notice(?msg,?domain),
try_match_file(?log_no(LogFile,1),
- escape(Got3)++"FORMATTER ERROR: bad_return_value",
+ escape(Got3)++"FORMATTER ERROR: bad return value",
5000),
%% Check that handler is still alive and was never dead
@@ -524,27 +524,14 @@ sync(Config) ->
formatter=>{?MODULE,nl}}),
start_tracer([{disk_log,blog,2},
- {disk_log,sync,1}],
+ {logger_disk_log_h,disk_log_sync,2}],
[{disk_log,blog,<<"first\n">>},
- {disk_log,sync}]),
+ {logger_disk_log_h,disk_log_sync}]),
logger:notice("first", ?domain),
%% wait for automatic disk_log_sync
check_tracer(?FILESYNC_REPEAT_INTERVAL*2),
- start_tracer([{disk_log,blog,2},
- {disk_log,sync,1}],
- [{disk_log,blog,<<"second\n">>},
- {disk_log,blog,<<"third\n">>},
- {disk_log,sync}]),
- %% two log requests in fast succession will make the handler skip
- %% an automatic disk log sync
- logger:notice("second", ?domain),
- logger:notice("third", ?domain),
- %% do explicit sync
- logger_disk_log_h:filesync(?MODULE),
- check_tracer(100),
-
%% check that if there's no repeated disk_log_sync active,
%% a disk_log_sync is still performed when handler goes idle
{ok,#{config := HConfig}} = logger:get_handler_config(?MODULE),
@@ -553,20 +540,25 @@ sync(Config) ->
no_repeat = maps:get(filesync_repeat_interval,
logger_disk_log_h:info(?MODULE)),
+ %% The following timer is to make sure the time from last log
+ %% ("first") to next ("second") is long enough, so the a flush is
+ %% triggered by the idle timeout between "fourth" and "fifth".
+ timer:sleep(?IDLE_DETECT_TIME_MSEC*2),
start_tracer([{disk_log,blog,2},
- {disk_log,sync,1}],
- [{disk_log,blog,<<"fourth\n">>},
- {disk_log,blog,<<"fifth\n">>},
- {disk_log,sync}]),
+ {logger_disk_log_h,disk_log_sync,2}],
+ [{disk_log,blog,<<"second\n">>},
+ {logger_disk_log_h,disk_log_sync},
+ {disk_log,blog,<<"third\n">>},
+ {logger_disk_log_h,disk_log_sync}]),
- logger:notice("fourth", ?domain),
+ logger:notice("second", ?domain),
timer:sleep(?IDLE_DETECT_TIME_MSEC*2),
- logger:notice("fifth", ?domain),
+ logger:notice("third", ?domain),
%% wait for automatic disk_log_sync
check_tracer(?IDLE_DETECT_TIME_MSEC*2),
- try_read_file(Log, {ok,<<"first\nsecond\nthird\nfourth\nfifth\n">>}, 1000),
+ try_read_file(Log, {ok,<<"first\nsecond\nthird\n">>}, 1000),
%% switch repeated disk_log_sync on and verify that the looping works
SyncInt = 1000,
@@ -1194,7 +1186,7 @@ restart_after(cleanup, _Config) ->
%% during high load to verify that sync, dropping and flushing is
%% handled correctly.
handler_requests_under_load() ->
- [{timetrap,{minutes,3}}].
+ [{timetrap,{minutes,5}}].
handler_requests_under_load(Config) ->
{Log,HConfig,DLHConfig} = start_handler(?MODULE, ?FUNCTION_NAME, Config),
NewHConfig =
@@ -1494,7 +1486,7 @@ start_tracer(Trace,Expected) ->
ok.
tpl([{M,F,A}|Trace]) ->
- {ok,Match} = dbg:tpl(M,F,A,[]),
+ {ok,Match} = dbg:tpl(M,F,A,c),
case lists:keyfind(matched,1,Match) of
{_,_,1} ->
ok;
@@ -1507,23 +1499,23 @@ tpl([{M,F,A}|Trace]) ->
tpl([]) ->
ok.
-tracer({trace,_,call,{logger_disk_log_h,handle_cast,[Op|_]}},
+tracer({trace,_,call,{logger_disk_log_h,handle_cast,[Op|_]},Caller},
{Pid,[{Mod,Func,Op}|Expected]}) ->
- maybe_tracer_done(Pid,Expected,{Mod,Func,Op});
-tracer({trace,_,call,{Mod=disk_log,Func=blog,[_,Data]}}, {Pid,[{Mod,Func,Data}|Expected]}) ->
- maybe_tracer_done(Pid,Expected,{Mod,Func,Data});
-tracer({trace,_,call,{Mod,Func,_}}, {Pid,[{Mod,Func}|Expected]}) ->
- maybe_tracer_done(Pid,Expected,{Mod,Func});
-tracer({trace,_,call,Call}, {Pid,Expected}) ->
- ct:log("Tracer got unexpected: ~p~nExpected: ~p~n",[Call,Expected]),
+ maybe_tracer_done(Pid,Expected,{Mod,Func,Op},Caller);
+tracer({trace,_,call,{Mod=disk_log,Func=blog,[_,Data]},Caller}, {Pid,[{Mod,Func,Data}|Expected]}) ->
+ maybe_tracer_done(Pid,Expected,{Mod,Func,Data},Caller);
+tracer({trace,_,call,{Mod,Func,_},Caller}, {Pid,[{Mod,Func}|Expected]}) ->
+ maybe_tracer_done(Pid,Expected,{Mod,Func},Caller);
+tracer({trace,_,call,Call,Caller}, {Pid,Expected}) ->
+ ct:log("Tracer got unexpected: ~p~nCaller: ~p~nExpected: ~p~n",[Call,Caller,Expected]),
Pid ! {tracer_got_unexpected,Call,Expected},
{Pid,Expected}.
-maybe_tracer_done(Pid,[],Got) ->
- ct:log("Tracer got: ~p~n",[Got]),
+maybe_tracer_done(Pid,[],Got,Caller) ->
+ ct:log("Tracer got: ~p~nCaller: ~p~n",[Got,Caller]),
Pid ! tracer_done;
-maybe_tracer_done(Pid,Expected,Got) ->
- ct:log("Tracer got: ~p~n",[Got]),
+maybe_tracer_done(Pid,Expected,Got,Caller) ->
+ ct:log("Tracer got: ~p~nCaller: ~p~n",[Got,Caller]),
{Pid,Expected}.
check_tracer(T) ->
diff --git a/lib/kernel/test/logger_formatter_SUITE.erl b/lib/kernel/test/logger_formatter_SUITE.erl
index 2ec4b243cf..8c13f0f908 100644
--- a/lib/kernel/test/logger_formatter_SUITE.erl
+++ b/lib/kernel/test/logger_formatter_SUITE.erl
@@ -765,6 +765,8 @@ check_config(_Config) ->
%% Test that formatter config can be changed, and that the default
%% template is updated accordingly
update_config(_Config) ->
+ {error,{not_found,?MODULE}} = logger:update_formatter_config(?MODULE,#{}),
+
logger:add_handler_filter(default,silence,{fun(_,_) -> stop end,ok}),
ok = logger:add_handler(?MODULE,?MODULE,#{}),
D = lists:seq(1,1000),
@@ -817,6 +819,11 @@ update_config(_Config) ->
ct:log("~p",[C6]),
["=NOTICE REPORT==== "++_,_D6] = Lines6,
+ {error,{invalid_formatter_config,bad}} =
+ logger:update_formatter_config(?MODULE,bad),
+ {error,{invalid_formatter_config,logger_formatter,{depth,bad}}} =
+ logger:update_formatter_config(?MODULE,depth,bad),
+
ok.
update_config(cleanup,_Config) ->
diff --git a/lib/kernel/test/logger_simple_h_SUITE.erl b/lib/kernel/test/logger_simple_h_SUITE.erl
index 79e5c057ad..e0ad792bdb 100644
--- a/lib/kernel/test/logger_simple_h_SUITE.erl
+++ b/lib/kernel/test/logger_simple_h_SUITE.erl
@@ -117,8 +117,7 @@ replace_default(Config) ->
log(Node, critical, [?str,[?keyval_rep]]),
log(Node, notice, [["fake",string,"line:",?LINE]]),
- Env = rpc:call(Node, application, get_env, [kernel, logger, []]),
- ok = rpc:call(Node, logger, add_handlers, [Env]),
+ ok = rpc:call(Node, logger, add_handlers, [kernel]),
ok.
diff --git a/lib/kernel/test/logger_std_h_SUITE.erl b/lib/kernel/test/logger_std_h_SUITE.erl
index 0930cd4211..3426567bbf 100644
--- a/lib/kernel/test/logger_std_h_SUITE.erl
+++ b/lib/kernel/test/logger_std_h_SUITE.erl
@@ -280,7 +280,7 @@ formatter_fail(Config) ->
ok = logger:set_handler_config(?MODULE,formatter,{?MODULE,bad_return}),
logger:notice(?msg,?domain),
try_match_file(Log,
- escape(Got3)++"FORMATTER ERROR: bad_return_value",
+ escape(Got3)++"FORMATTER ERROR: bad return value",
5000),
%% Check that handler is still alive and was never dead
diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk
index aa8e4dc119..df95174c9f 100644
--- a/lib/kernel/vsn.mk
+++ b/lib/kernel/vsn.mk
@@ -1 +1 @@
-KERNEL_VSN = 6.0
+KERNEL_VSN = 6.1
diff --git a/lib/megaco/configure.in b/lib/megaco/configure.in
index eaa875d0a3..bae6144abe 100644
--- a/lib/megaco/configure.in
+++ b/lib/megaco/configure.in
@@ -22,10 +22,6 @@ dnl
dnl define([AC_CACHE_LOAD], )dnl
dnl define([AC_CACHE_SAVE], )dnl
-if test "x$no_recursion" != "xyes" -a "x$OVERRIDE_CONFIG_CACHE" = "x"; then
- # We do not want to use a common cache!
- cache_file=/dev/null
-fi
AC_INIT(vsn.mk)
@@ -42,11 +38,14 @@ else
host_os=win32
fi
-
dnl ----------------------------------------------------------------------
dnl Checks for programs.
dnl ----------------------------------------------------------------------
+AC_PROG_CC
+
+LM_WINDOWS_ENVIRONMENT
+
AC_DEFUN(ERL_REENTRANT_FLEX,
[flex_compile='$LEX -R -Pconftest -oconftest.c conftest.flex 1>&AC_FD_CC'
changequote(253, 273)dnl
@@ -188,111 +187,7 @@ CFLAGS="$CFLAGS $sanitizers"
LDFLAGS="$LDFLAGS $sanitizers"
])
-dnl
-dnl If ${ERL_TOP}/make/otp_ded.mk.in exists and contains DED_MK_VSN > 0,
-dnl every thing releted to compiling Dynamic Erlang Drivers can be found
-dnl in $(ERL_TOP)/make/$(TARGET)/ded.mk at compile time. If not, try to
-dnl figure these things out.
-dnl
-
-AC_MSG_CHECKING([for usable Dynamic Erlang Driver configuration])
-[
- ded_mk_in="${ERL_TOP}/make/otp_ded.mk.in"
- ded_mk_vsn=
- test -r "$ded_mk_in" &&
- ded_mk_vsn=`sed -n "s/^DED_MK_VSN[ ]*=[ ]*\(.*\)/\1/p" < "$ded_mk_in"`
- test "$ded_mk_vsn" != "" || ded_mk_vsn=0
-]
-
-if test $ded_mk_vsn -gt 0; then
-
-HAVE_USABLE_OTP_DED_MK=yes
-AC_MSG_RESULT([yes])
-
-CC=false
-AC_SUBST(CC)
-DED_LD=false
-AC_SUBST(DED_LD)
-
-else dnl --- begin no usable otp_ded.mk.in ---
-
-HAVE_USABLE_OTP_DED_MK=no
-AC_MSG_RESULT([no])
-
-dnl
-dnl C compiler (related) defs
-dnl
-
-AC_PROG_CC
-
-dnl
-dnl Flags to the C compiler
-dnl
-
-if test "X$host" = "Xwin32"; then
- DED_CFLAGS="$CFLAGS"
-else
- case $host_os in
- darwin*)
- CFLAGS="$CFLAGS -fno-common"
- ;;
- esac
-
- if test "x$GCC" = xyes; then
- DED_CFLAGS="$CFLAGS -fPIC $DED_CFLAGS"
- else
- DED_CFLAGS="$CFLAGS $DED_CFLAGS"
- fi
-fi
-
-dnl emulator includes needed
-DED_INCLUDES="-I${ERL_TOP}/erts/emulator/beam -I${ERL_TOP}/erts/include -I${ERL_TOP}/erts/include/$host -I${ERL_TOP}/erts/include/internal -I${ERL_TOP}/erts/include/internal/$host -I${ERL_TOP}/erts/emulator/sys/$ERLANG_OSTYPE"
-
-DED_THR_DEFS="-D_THREAD_SAFE -D_REENTRANT"
-
-case $host_os in
- win32)
- DED_LDFLAGS="-dll"
- ;;
- solaris2*|sysv4*)
- DED_LDFLAGS="-G"
- ;;
- aix4*)
- DED_LDFLAGS="-G -bnoentry -bexpall"
- ;;
- freebsd2*)
- # Non-ELF GNU linker
- DED_LDFLAGS="-Bshareable"
- ;;
- darwin*)
- # Mach-O linker, a shared lib and a loadable
- # object file is not the same thing.
- DED_LDFLAGS="-bundle -flat_namespace -undefined suppress"
- DED_LD="$CC"
- ;;
- *)
- # assume GNU linker and ELF
- DED_LDFLAGS="-shared"
- ;;
-esac
-
-AC_CHECK_PROGS(DED_LD, [$LD ld.sh])
-AC_CHECK_TOOL(DED_LD, ld, no_ld)
-if test "$DED_LD" = no_ld; then
- AC_MSG_ERROR([ld is required to build the flex scanner!])
-fi
-
-AC_MSG_CHECKING(for linker flags for loadable drivers)
-DED_LDFLAGS="$LDFLAGS $DED_LDFLAGS"
-AC_MSG_RESULT([$DED_LDFLAGS])
-
-fi dnl --- end no usable otp_ded.mk.in ---
-
-AC_SUBST(HAVE_USABLE_OTP_DED_MK)
-AC_SUBST(DED_CFLAGS)
-AC_SUBST(DED_INCLUDES)
-AC_SUBST(DED_THR_DEFS)
-AC_SUBST(DED_LDFLAGS)
+ERL_DED
AC_CHECK_PROG(PERL, perl, perl, no_perl)
if test "$PERL" = no_perl; then
diff --git a/lib/megaco/doc/src/Makefile b/lib/megaco/doc/src/Makefile
index 72feb9d2b3..5e085b60b0 100644
--- a/lib/megaco/doc/src/Makefile
+++ b/lib/megaco/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2000-2017. All Rights Reserved.
+# Copyright Ericsson AB 2000-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/lib/megaco/doc/src/book.xml b/lib/megaco/doc/src/book.xml
index 9c304d6cae..06ff315de7 100644
--- a/lib/megaco/doc/src/book.xml
+++ b/lib/megaco/doc/src/book.xml
@@ -4,7 +4,7 @@
<book xmlns:xi="http://www.w3.org/2001/XInclude">
<header titlestyle="normal">
<copyright>
- <year>2000</year><year>2016</year>
+ <year>2000</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/megaco/doc/src/notes.xml b/lib/megaco/doc/src/notes.xml
index 54e048a172..b697c3f631 100644
--- a/lib/megaco/doc/src/notes.xml
+++ b/lib/megaco/doc/src/notes.xml
@@ -37,7 +37,22 @@
section is the version number of Megaco.</p>
- <section><title>Megaco 3.18.3</title>
+ <section><title>Megaco 3.18.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Megaco 3.18.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/megaco/src/flex/Makefile.in b/lib/megaco/src/flex/Makefile.in
index c37ad4d702..26d2ddd44c 100644
--- a/lib/megaco/src/flex/Makefile.in
+++ b/lib/megaco/src/flex/Makefile.in
@@ -31,25 +31,6 @@ include ../../vsn.mk
VSN=$(MEGACO_VSN)
# ----------------------------------------------------
-# Dynamic Erlang Driver
-# ----------------------------------------------------
-HAVE_USABLE_OTP_DED_MK = @HAVE_USABLE_OTP_DED_MK@
-
-ifeq ($(HAVE_USABLE_OTP_DED_MK),yes)
-# otp_ded.mk will be used on R13B04 and later
-include $(ERL_TOP)/make/$(TARGET)/otp_ded.mk
-else
-# megacos configure provide the info instead
-DED_CC = @CC@
-DED__NOWARN_NOTHR_CFLAGS = @DED_CFLAGS@
-DED_THR_DEFS = @DED_THR_DEFS@
-DED_LD = @DED_LD@
-DED_LDFLAGS = @DED_LDFLAGS@
-DED_INCLUDES = @DED_INCLUDES@
-DED_EXT = so
-endif
-
-# ----------------------------------------------------
# The following variables differ on different systems, we set
# reasonable defaults, if something different is needed it should
# be set for that system only.
@@ -57,20 +38,19 @@ endif
FLEX_VSN = $(shell flex --version)
-TMP_CFLAGS = $(DED__NOWARN_NOTHR_CFLAGS) @OTP_EXTRA_FLAGS@
+TMP_CFLAGS = @DED_BASIC_CFLAGS@ @OTP_EXTRA_FLAGS@
ifeq ($(TYPE),valgrind)
CFLAGS = $(subst -O2, , $(TMP_CFLAGS)) -DVALGRIND
else
CFLAGS = $(TMP_CFLAGS)
endif
-CC = $(DED_CC)
-CFLAGS_MT = $(CFLAGS) $(DED_THR_DEFS)
-LD = $(DED_LD)
-LDFLAGS = $(DED_LDFLAGS)
+CC = @DED_CC@
+CFLAGS_MT = $(CFLAGS) @DED_THR_DEFS@
+LD = @DED_LD@
+LDFLAGS = @DED_LDFLAGS@
LEX = @LEX@
LEXLIB = @LEXLIB@
PERL = @PERL@
-ERLANG_OSTYPE = @ERLANG_OSTYPE@
# Shall we build the flex scanner or not.
# We assume that it does not exist on windows...
@@ -143,8 +123,8 @@ ifeq ($(findstring win32,$(TARGET)), win32)
FLEX_SCANNER_SO =
SOLIBS = $(FLEX_SCANNER_SO)
else
-FLEX_SCANNER_SO = $(LIBDIR)/$(STD_DRV).$(DED_EXT)
-FLEX_SCANNER_MT_SO = $(LIBDIR)/$(MT_DRV).$(DED_EXT)
+FLEX_SCANNER_SO = $(LIBDIR)/$(STD_DRV).@DED_EXT@
+FLEX_SCANNER_MT_SO = $(LIBDIR)/$(MT_DRV).@DED_EXT@
SOLIBS = $(FLEX_SCANNER_SO) $(FLEX_SCANNER_MT_SO)
endif
@@ -179,7 +159,7 @@ else
CFLAGS += -DMFS_FLEX_DEBUG=0
endif
-CFLAGS += $(DED_INCLUDES) -I$(ERL_TOP)/erts/$(TARGET) $(DRV_FLAGS) -funroll-loops -Wall
+CFLAGS += @DED_INCLUDE@ -I$(ERL_TOP)/erts/$(TARGET) $(DRV_FLAGS) -funroll-loops -Wall
#ifneq ($(FLEX_VSN),)
#CFLAGS += -DFLEX_VERSION="$(FLEX_VSN)"
@@ -398,10 +378,10 @@ $(OBJDIR)/$(MT_DRV).o: $(MT_DRV).c
# No need to link with -lfl as we have also defined %option noyywrap -
# and having -lfl doesn't work under Darwin for some reason. - Sean
-$(LIBDIR)/$(STD_DRV).$(DED_EXT): $(OBJDIR)/$(STD_DRV).o
+$(LIBDIR)/$(STD_DRV).@DED_EXT@: $(OBJDIR)/$(STD_DRV).o
$(V_colon)@echo "linking std driver:"
$(V_LD) $(LDFLAGS) -o $@ $<
-$(LIBDIR)/$(MT_DRV).$(DED_EXT): $(OBJDIR)/$(MT_DRV).o
+$(LIBDIR)/$(MT_DRV).@DED_EXT@: $(OBJDIR)/$(MT_DRV).o
$(V_colon)@echo "linking multi-threaded driver:"
$(V_LD) $(LDFLAGS) -o $@ $<
diff --git a/lib/megaco/vsn.mk b/lib/megaco/vsn.mk
index a4f7de7f07..f4c82c537a 100644
--- a/lib/megaco/vsn.mk
+++ b/lib/megaco/vsn.mk
@@ -19,6 +19,6 @@
# %CopyrightEnd%
APPLICATION = megaco
-MEGACO_VSN = 3.18.3
+MEGACO_VSN = 3.18.4
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(MEGACO_VSN)$(PRE_VSN)"
diff --git a/lib/mnesia/doc/src/mnesia_frag_hash.xml b/lib/mnesia/doc/src/mnesia_frag_hash.xml
index 2fae542c86..c233acdb05 100644
--- a/lib/mnesia/doc/src/mnesia_frag_hash.xml
+++ b/lib/mnesia/doc/src/mnesia_frag_hash.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2002</year>
- <year>2016</year>
+ <year>2018</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
diff --git a/lib/mnesia/doc/src/notes.xml b/lib/mnesia/doc/src/notes.xml
index 8a7dab739e..8fc3610bb6 100644
--- a/lib/mnesia/doc/src/notes.xml
+++ b/lib/mnesia/doc/src/notes.xml
@@ -39,7 +39,55 @@
thus constitutes one section in this document. The title of each
section is the version number of Mnesia.</p>
- <section><title>Mnesia 4.15.4</title>
+ <section><title>Mnesia 4.15.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed type spec for <c>mnesia:change_config/2</c>.</p>
+ <p>
+ Own Id: OTP-15201 Aux Id: PR-1881 </p>
+ </item>
+ <item>
+ <p>
+ When master node is set do not force a load from
+ ram_copies replica when there are no available
+ disc_copies, since that would load an empty table. Wait
+ until a disk replica is available or until user
+ explicitly force_loads the table.</p>
+ <p>
+ Own Id: OTP-15221 Aux Id: ERIERL-217 </p>
+ </item>
+ <item>
+ <p>
+ Allow to add replicas even if all other replicas are down
+ when the other replicas are not stored on disk.</p>
+ <p>
+ Own Id: OTP-15226 Aux Id: ERIERL-221 </p>
+ </item>
+ <item>
+ <p>
+ Fixed <c>mnesia:delete_object/1</c> bug, where
+ delete_object was deleting the record if it was written
+ in the same transaction even if it was written to a
+ different value.</p>
+ <p>
+ Own Id: OTP-15231 Aux Id: PR-1858 </p>
+ </item>
+ <item>
+ <p>
+ Fixed a bug where the bag table index data was not
+ deleted when objects were deleted.</p>
+ <p>
+ Own Id: OTP-15243</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Mnesia 4.15.4</title>
<section><title>Improvements and New Features</title>
<list>
diff --git a/lib/mnesia/src/mnesia_index.erl b/lib/mnesia/src/mnesia_index.erl
index 917ada65df..098265d5fc 100644
--- a/lib/mnesia/src/mnesia_index.erl
+++ b/lib/mnesia/src/mnesia_index.erl
@@ -155,7 +155,7 @@ del_object_bag_([IxK|IxKs], Found, Type, Tab, Key, Obj, Ixt) ->
bag ->
db_match_erase(Ixt, {IxK, Key});
ordered ->
- db_erase(Ixt, {{IxK, Key}})
+ db_erase(Ixt, {IxK, Key})
end;
_ ->
ok
diff --git a/lib/mnesia/test/mnesia_evil_coverage_test.erl b/lib/mnesia/test/mnesia_evil_coverage_test.erl
index 77236940d4..a451c8d0c8 100644
--- a/lib/mnesia/test/mnesia_evil_coverage_test.erl
+++ b/lib/mnesia/test/mnesia_evil_coverage_test.erl
@@ -35,7 +35,7 @@
replica_management/1, clear_table_during_load/1,
schema_availability/1, local_content/1,
replica_location/1, user_properties/1, unsupp_user_props/1,
- sorted_ets/1,
+ sorted_ets/1, index_cleanup/1,
change_table_access_mode/1, change_table_load_order/1,
set_master_nodes/1, offline_set_master_nodes/1,
dump_tables/1, dump_log/1, wait_for_tables/1, force_load_table/1,
@@ -49,7 +49,7 @@
record_name_dirty_access_disc_only/1,
record_name_dirty_access_xets/1]).
--export([info_check/8]).
+-export([info_check/8, index_size/1]).
-define(cleanup(N, Config),
mnesia_test_lib:prepare_test_case([{reload_appls, [mnesia]}],
@@ -73,7 +73,7 @@ all() ->
{group, table_sync}, user_properties, unsupp_user_props,
{group, record_name}, {group, snmp_access},
{group, subscriptions}, {group, iteration},
- {group, debug_support}, sorted_ets,
+ {group, debug_support}, sorted_ets, index_cleanup,
{mnesia_dirty_access_test, all},
{mnesia_trans_access_test, all},
{mnesia_evil_backup, all}].
@@ -2559,3 +2559,55 @@ sorted_ets(Config) when is_list(Config) ->
?match({atomic, [{rec,1,1}, {rec,2,1}]}, mnesia:transaction(TestIt)).
+index_cleanup(Config) when is_list(Config) ->
+ [N1, N2] = All = ?acquire_nodes(2, Config),
+ ?match({atomic, ok}, mnesia:create_table(i_set, [{type, set}, {ram_copies, [N1]}, {index, [val]},
+ {disc_only_copies, [N2]}])),
+ ?match({atomic, ok}, mnesia:create_table(i_bag, [{type, bag}, {ram_copies, [N1]}, {index, [val]},
+ {disc_only_copies, [N2]}])),
+ ?match({atomic, ok}, mnesia:create_table(i_oset, [{type, ordered_set}, {ram_copies, [N1, N2]},
+ {index, [val]}])),
+
+ Tabs = [i_set, i_bag, i_oset],
+
+ Add = fun(Tab) ->
+ Write = fun(Tab) ->
+ Recs = [{Tab, N, N rem 5} || N <- lists:seq(1,10)],
+ [ok = mnesia:write(Rec) || Rec <- Recs],
+ Recs
+ end,
+ {atomic, Recs} = mnesia:sync_transaction(Write, [Tab]),
+ lists:sort(Recs)
+ end,
+
+ IRead = fun(Tab) ->
+ Read = fun(Tab) ->
+ [mnesia:index_read(Tab, N, val) || N <- lists:seq(0,4)]
+ end,
+ {atomic, Recs} = mnesia:transaction(Read, [Tab]),
+ lists:sort(lists:flatten(Recs))
+ end,
+
+ Delete = fun(Rec) ->
+ Del = fun() -> mnesia:delete_object(Rec) end,
+ {atomic, ok} = mnesia:sync_transaction(Del),
+ ok
+ end,
+
+
+ Recs = [Add(Tab) || Tab <- Tabs],
+ ?match(Recs, [IRead(Tab) || Tab <- Tabs]),
+ [Delete(Rec) || Rec <- lists:flatten(Recs)],
+
+ [?match({Tab,0}, {Tab,mnesia:table_info(Tab, size)}) || Tab <- Tabs],
+
+ [?match({Tab,Node,0, _}, rpc:call(Node, ?MODULE, index_size, [Tab]))
+ || Node <- All, Tab <- Tabs],
+ ?verify_mnesia(All, []).
+
+index_size(Tab) ->
+ %% White box testing
+ case mnesia:table_info(Tab, index_info) of
+ {index, _, [{_, {ram, Ref}}=Dbg]} -> {Tab, node(), ets:info(Ref, size), Dbg};
+ {index, _, [{_, {dets, Ref}}=Dbg]} -> {Tab, node(), dets:info(Ref, size), Dbg}
+ end.
diff --git a/lib/mnesia/vsn.mk b/lib/mnesia/vsn.mk
index aaa1c3006f..1cfb35c774 100644
--- a/lib/mnesia/vsn.mk
+++ b/lib/mnesia/vsn.mk
@@ -1 +1 @@
-MNESIA_VSN = 4.15.4
+MNESIA_VSN = 4.15.5
diff --git a/lib/observer/doc/src/notes.xml b/lib/observer/doc/src/notes.xml
index 67bba37e39..4d1a9a4f55 100644
--- a/lib/observer/doc/src/notes.xml
+++ b/lib/observer/doc/src/notes.xml
@@ -32,6 +32,21 @@
<p>This document describes the changes made to the Observer
application.</p>
+<section><title>Observer 2.8.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Observer 2.8</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/observer/vsn.mk b/lib/observer/vsn.mk
index bf6fd2a421..21c8f4e6c9 100644
--- a/lib/observer/vsn.mk
+++ b/lib/observer/vsn.mk
@@ -1 +1 @@
-OBSERVER_VSN = 2.8
+OBSERVER_VSN = 2.8.1
diff --git a/lib/odbc/configure.in b/lib/odbc/configure.in
index 2dec6e5abf..c5cf2786ca 100644
--- a/lib/odbc/configure.in
+++ b/lib/odbc/configure.in
@@ -21,12 +21,6 @@ dnl
dnl define([AC_CACHE_LOAD], )dnl
dnl define([AC_CACHE_SAVE], )dnl
-if test "x$no_recursion" != "xyes" -a "x$OVERRIDE_CONFIG_CACHE" = "x"; then
- # We do not want to use a common cache!
- cache_file=/dev/null
-fi
-
-
dnl Process this file with autoconf to produce a configure script.
AC_INIT(c_src/odbcserver.c)
diff --git a/lib/odbc/doc/src/Makefile b/lib/odbc/doc/src/Makefile
index 553db8a9a4..a6311ceede 100644
--- a/lib/odbc/doc/src/Makefile
+++ b/lib/odbc/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2017. All Rights Reserved.
+# Copyright Ericsson AB 1999-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/lib/odbc/doc/src/notes.xml b/lib/odbc/doc/src/notes.xml
index 2aa55ca99c..dba7663bb9 100644
--- a/lib/odbc/doc/src/notes.xml
+++ b/lib/odbc/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2016</year>
+ <year>2004</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,7 +32,22 @@
<p>This document describes the changes made to the odbc application.
</p>
- <section><title>ODBC 2.12.1</title>
+ <section><title>ODBC 2.12.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>ODBC 2.12.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/odbc/vsn.mk b/lib/odbc/vsn.mk
index 3f7677a71d..bb21016fad 100644
--- a/lib/odbc/vsn.mk
+++ b/lib/odbc/vsn.mk
@@ -1 +1 @@
-ODBC_VSN = 2.12.1
+ODBC_VSN = 2.12.2
diff --git a/lib/os_mon/doc/src/notes.xml b/lib/os_mon/doc/src/notes.xml
index 4a878dd704..0910b3c0f3 100644
--- a/lib/os_mon/doc/src/notes.xml
+++ b/lib/os_mon/doc/src/notes.xml
@@ -31,6 +31,21 @@
</header>
<p>This document describes the changes made to the OS_Mon application.</p>
+<section><title>Os_Mon 2.4.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Os_Mon 2.4.5</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/os_mon/vsn.mk b/lib/os_mon/vsn.mk
index 4a327e5506..0c62c3db35 100644
--- a/lib/os_mon/vsn.mk
+++ b/lib/os_mon/vsn.mk
@@ -1 +1 @@
-OS_MON_VSN = 2.4.5
+OS_MON_VSN = 2.4.6
diff --git a/lib/otp_mibs/doc/src/Makefile b/lib/otp_mibs/doc/src/Makefile
index 143d9befb8..22c3c127ac 100644
--- a/lib/otp_mibs/doc/src/Makefile
+++ b/lib/otp_mibs/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2003-2017. All Rights Reserved.
+# Copyright Ericsson AB 2003-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/lib/otp_mibs/doc/src/notes.xml b/lib/otp_mibs/doc/src/notes.xml
index ac0777d225..443f08f1e1 100644
--- a/lib/otp_mibs/doc/src/notes.xml
+++ b/lib/otp_mibs/doc/src/notes.xml
@@ -32,6 +32,21 @@
<p>This document describes the changes made to the OTP_Mibs
application.</p>
+<section><title>Otp_Mibs 1.2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Otp_Mibs 1.2</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/otp_mibs/vsn.mk b/lib/otp_mibs/vsn.mk
index 2e9e367d98..1b0444afcd 100644
--- a/lib/otp_mibs/vsn.mk
+++ b/lib/otp_mibs/vsn.mk
@@ -1,4 +1,4 @@
-OTP_MIBS_VSN = 1.2
+OTP_MIBS_VSN = 1.2.1
# Note: The branch 'otp_mibs' is defunct as of otp_mibs-1.0.4 and
# should NOT be used again.
diff --git a/lib/parsetools/doc/src/Makefile b/lib/parsetools/doc/src/Makefile
index a40ccd0fe7..2e8b232902 100644
--- a/lib/parsetools/doc/src/Makefile
+++ b/lib/parsetools/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2017. All Rights Reserved.
+# Copyright Ericsson AB 1997-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/lib/parsetools/doc/src/notes.xml b/lib/parsetools/doc/src/notes.xml
index 3e999c8cd0..f8cd9b972d 100644
--- a/lib/parsetools/doc/src/notes.xml
+++ b/lib/parsetools/doc/src/notes.xml
@@ -31,6 +31,21 @@
</header>
<p>This document describes the changes made to the Parsetools application.</p>
+<section><title>Parsetools 2.1.8</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Parsetools 2.1.7</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/parsetools/vsn.mk b/lib/parsetools/vsn.mk
index 210723e449..1a5201ce5d 100644
--- a/lib/parsetools/vsn.mk
+++ b/lib/parsetools/vsn.mk
@@ -1 +1 @@
-PARSETOOLS_VSN = 2.1.7
+PARSETOOLS_VSN = 2.1.8
diff --git a/lib/public_key/doc/specs/.gitignore b/lib/public_key/doc/specs/.gitignore
new file mode 100644
index 0000000000..322eebcb06
--- /dev/null
+++ b/lib/public_key/doc/specs/.gitignore
@@ -0,0 +1 @@
+specs_*.xml
diff --git a/lib/public_key/doc/src/Makefile b/lib/public_key/doc/src/Makefile
index 03467e9783..c8647750af 100644
--- a/lib/public_key/doc/src/Makefile
+++ b/lib/public_key/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2008-2017. All Rights Reserved.
+# Copyright Ericsson AB 2008-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -77,12 +77,18 @@ HTML_REF_MAN_FILE = $(HTMLDIR)/index.html
TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf
+SPECS_FILES = $(XML_REF3_FILES:%.xml=$(SPECDIR)/specs_%.xml)
+
+TOP_SPECS_FILE = specs.xml
+
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
XML_FLAGS +=
DVIPS_FLAGS +=
+SPECS_FLAGS = -I../../include -I../../src -I../../..
+
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
@@ -103,6 +109,7 @@ clean clean_docs:
rm -f $(MAN3DIR)/*
rm -f $(MAN6DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
+ rm -f $(SPECS_FILES)
rm -f errs core *~
man: $(MAN3_FILES) $(MAN6_FILES)
diff --git a/lib/public_key/doc/src/notes.xml b/lib/public_key/doc/src/notes.xml
index 204520473a..62b4b4ca1b 100644
--- a/lib/public_key/doc/src/notes.xml
+++ b/lib/public_key/doc/src/notes.xml
@@ -35,6 +35,41 @@
<file>notes.xml</file>
</header>
+<section><title>Public_Key 1.6.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Removed <c>#DSAPrivateKey{}</c> as acceptable input to
+ <c>public_key:verify/5</c>.</p>
+ <p>
+ Own Id: OTP-15284</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The typing in the CRYPTO and PUBLIC_KEY applications are
+ reworked and a few mistakes are corrected.</p>
+ <p>
+ The documentation is now generated from the typing and
+ some clarifications are made.</p>
+ <p>
+ A new chapter on Algorithm Details such as key sizes and
+ availability is added to the CRYPTO User's Guide.</p>
+ <p>
+ Own Id: OTP-15134</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Public_Key 1.6.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/public_key/doc/src/public_key.xml b/lib/public_key/doc/src/public_key.xml
index aaccb5088b..1b588018e4 100644
--- a/lib/public_key/doc/src/public_key.xml
+++ b/lib/public_key/doc/src/public_key.xml
@@ -41,7 +41,7 @@
</description>
<section>
- <title>DATA TYPES</title>
+ <title>Common Records and ASN.1 Types</title>
<note><p>All records used in this Reference Manual
<!-- except #policy_tree_node{} -->
@@ -54,193 +54,132 @@
records and constant macros described here and in the User's Guide:</p>
<code> -include_lib("public_key/include/public_key.hrl").</code>
+ </section>
+
+ <datatypes>
+ <datatype>
+ <name name="oid"/>
+ <desc>
+ <p>Object identifier, a tuple of integers as generated by the <c>ASN.1</c> compiler.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="der_encoded"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="pki_asn1_type"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="asn1_type"/>
+ <desc>
+ <p>ASN.1 type present in the Public Key applications ASN.1 specifications.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="pem_entry"/>
+ <name name="der_or_encrypted_der"/>
+ <name name="cipher_info"/>
+ <name name="cipher"/>
+ <name name="salt"/>
+ <name name="cipher_info_params"/>
+ <desc>
+ <code>Cipher = "RC2-CBC" | "DES-CBC" | "DES-EDE3-CBC"</code>
+ <p><c>Salt</c> could be generated with
+ <seealso marker="crypto:crypto#strong_rand_bytes-1"><c>crypto:strong_rand_bytes(8)</c></seealso>.</p>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="public_key"/>
+ <name name="rsa_public_key"/>
+ <name name="dsa_public_key"/>
+ <name name="ec_public_key"/>
+ <name name="ecpk_parameters"/>
+ <name name="ecpk_parameters_api"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="private_key"/>
+ <name name="rsa_private_key"/>
+ <name name="dsa_private_key"/>
+ <name name="ec_private_key"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="key_params"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="digest_type"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="crl_reason"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="issuer_id"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="issuer_name"/>
+ <desc>
+ </desc>
+ </datatype>
+
+ <datatype>
+ <name name="ssh_file"/>
+ <desc>
+ </desc>
+ </datatype>
+
+
+
+ </datatypes>
- <p>The following data types are used in the functions for <c>public_key</c>:</p>
-
- <taglist>
- <tag><c>oid()</c></tag>
- <item><p>Object identifier, a tuple of integers as generated by the <c>ASN.1</c> compiler.</p></item>
-
- <tag><c>boolean() =</c></tag>
- <item><p><c>true | false</c></p></item>
-
- <tag><c>string() =</c></tag>
- <item><p><c>[bytes()]</c></p></item>
-
- <tag><c>der_encoded() =</c></tag>
- <item><p><c>binary()</c></p></item>
-
- <tag><c>pki_asn1_type() =</c></tag>
- <item>
- <p><c>'Certificate'</c></p>
- <p><c>| 'RSAPrivateKey'</c></p>
- <p><c>| 'RSAPublicKey'</c></p>
- <p><c>| 'DSAPrivateKey'</c></p>
- <p><c>| 'DSAPublicKey'</c></p>
- <p><c>| 'DHParameter'</c></p>
- <p><c>| 'SubjectPublicKeyInfo'</c></p>
- <p><c>| 'PrivateKeyInfo'</c></p>
- <p><c>| 'CertificationRequest'</c></p>
- <p><c>| 'CertificateList'</c></p>
- <p><c>| 'ECPrivateKey'</c></p>
- <p><c>| 'EcpkParameters'</c></p>
- </item>
-
- <tag><c>pem_entry () =</c></tag>
- <item><p><c>{pki_asn1_type(), binary(), %% DER or encrypted DER</c></p>
- <p><c> not_encrypted | cipher_info()}</c></p></item>
-
- <tag><c>cipher_info() = </c></tag>
- <item><p><c>{"RC2-CBC" | "DES-CBC" | "DES-EDE3-CBC", crypto:strong_rand_bytes(8)</c></p>
- <p><c>| {#'PBEParameter{}, digest_type()} | #'PBES2-params'{}}</c></p>
- </item>
-
- <tag><marker id="type-public_key"/>
- <c>public_key() =</c></tag>
- <item><p><c>rsa_public_key() | dsa_public_key() | ec_public_key()</c></p></item>
-
- <tag><marker id="type-private_key"/>
- <c>private_key() =</c></tag>
- <item><p><c>rsa_private_key() | dsa_private_key() | ec_private_key()</c></p></item>
-
- <tag><c>rsa_public_key() =</c></tag>
- <item><p><c>#'RSAPublicKey'{}</c></p></item>
-
- <tag><c>rsa_private_key() =</c></tag>
- <item><p><c>#'RSAPrivateKey'{}</c></p></item>
-
- <tag><c>dsa_public_key() =</c></tag>
- <item><p><c>{integer(), #'Dss-Parms'{}}</c></p></item>
-
- <tag><c>dsa_private_key() =</c></tag>
- <item><p><c>#'DSAPrivateKey'{}</c></p></item>
-
- <tag><c>ec_public_key()</c></tag>
- <item><p>= <c>{#'ECPoint'{}, #'ECParameters'{} | {namedCurve, oid()}}</c></p></item>
-
- <tag><c>ec_private_key() =</c></tag>
- <item><p><c>#'ECPrivateKey'{}</c></p></item>
-
- <tag><c>key_params() =</c></tag>
- <item><p> #'DHParameter'{} | {namedCurve, oid()} | #'ECParameters'{}
- | {rsa, Size::integer(), PubExp::integer()} </p></item>
-
- <tag><c>public_crypt_options() =</c></tag>
- <item><p><c>[{rsa_pad, rsa_padding()}]</c></p></item>
-
- <tag><c>rsa_padding() =</c></tag>
- <item>
- <p><c>'rsa_pkcs1_padding'</c></p>
- <p><c>| 'rsa_pkcs1_oaep_padding'</c></p>
- <p><c>| 'rsa_no_padding'</c></p>
- </item>
-
- <tag><c>public_sign_options() =</c></tag>
- <item><p><c>[{rsa_pad, rsa_sign_padding()} | {rsa_pss_saltlen, integer()}]</c></p></item>
-
- <tag><c>rsa_sign_padding() =</c></tag>
- <item>
- <p><c>'rsa_pkcs1_padding'</c></p>
- <p><c>| 'rsa_pkcs1_pss_padding'</c></p>
- </item>
-
- <tag><c>digest_type() = </c></tag>
- <item><p>Union of <c>rsa_digest_type()</c>, <c>dss_digest_type()</c>,
- and <c>ecdsa_digest_type()</c>.</p></item>
-
- <tag><c>rsa_digest_type() = </c></tag>
- <item><p><c>'md5' | 'ripemd160' | 'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512'</c></p></item>
-
- <tag><c>dss_digest_type() = </c></tag>
- <item><p><c>'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512'</c></p>
- <p>Note that the actual supported dss_digest_type depends on the underlying crypto library.
- In OpenSSL version >= 1.0.1 the listed digest are supported, while in 1.0.0 only
- sha, sha224 and sha256 are supported. In version 0.9.8 only sha is supported.</p>
- </item>
-
- <tag><c>ecdsa_digest_type() = </c></tag>
- <item><p><c>'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512'</c></p></item>
-
- <tag><c>crl_reason() = </c></tag>
- <item>
- <p><c>unspecified</c></p>
- <p><c>| keyCompromise</c></p>
- <p><c>| cACompromise</c></p>
- <p><c>| affiliationChanged</c></p>
- <p><c>| superseded</c></p>
- <p><c>| cessationOfOperation</c></p>
- <p><c>| certificateHold</c></p>
- <p><c>| privilegeWithdrawn</c></p>
- <p><c>| aACompromise</c></p>
- </item>
-
- <tag><c>issuer_name() =</c></tag>
- <item><p><c>{rdnSequence,[#'AttributeTypeAndValue'{}]}</c></p>
- </item>
-
- <tag><c>ssh_file() =</c></tag>
- <item>
- <p><c>openssh_public_key</c></p>
- <p><c>| rfc4716_public_key</c></p>
- <p><c>| known_hosts</c></p>
- <p><c>| auth_keys</c></p>
- </item>
- </taglist>
-
-
-<!-- <p><code>policy_tree() = [Root, Children]</code></p> -->
-
-<!-- <p><code>Root = #policy_tree_node{}</code></p> -->
-
-<!-- <p><code>Children = [] | policy_tree()</code></p> -->
-
-<!-- <p>The <c>policy_tree_node</c> record has the following fields:</p> -->
-
-<!-- <taglist> -->
-
-<!-- <tag>valid_policy</tag> -->
-<!-- <item>A single policy OID representing a -->
-<!-- valid policy for the path of length x.</item> -->
-
-<!-- <tag>qualifier_set</tag> -->
-<!-- <item>A set of policy qualifiers associated -->
-<!-- with the valid policy in certificate x.</item> -->
-
-<!-- <tag>critically_indicator</tag> -->
-<!-- <item>Indicates whether the -->
-<!-- certificate policy extension in certificate x was marked as -->
-<!-- critical.</item> -->
-
-<!-- <tag>expected_policy_set</tag> -->
-<!-- <item>Contains one or more policy OIDs -->
-<!-- that would satisfy this policy in the certificate x+1.</item> -->
-<!-- </taglist> -->
- </section>
<funcs>
<func>
- <name>compute_key(OthersKey, MyKey)-></name>
- <name>compute_key(OthersKey, MyKey, Params)-></name>
+ <name name="compute_key" arity="2"/>
+ <fsummary>Computes shared secret.</fsummary>
+ <desc>
+ <p>Computes shared secret.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="compute_key" arity="3"/>
<fsummary>Computes shared secret.</fsummary>
- <type>
- <v>OthersKey = #'ECPoint'{} | binary(), MyKey = #'ECPrivateKey'{} | binary()</v>
- <v>Params = #'DHParameter'{}</v>
- </type>
<desc>
<p>Computes shared secret.</p>
</desc>
</func>
<func>
- <name>decrypt_private(CipherText, Key) -> binary()</name>
- <name>decrypt_private(CipherText, Key, Options) -> binary()</name>
+ <name name="decrypt_private" arity="2"/>
+ <name name="decrypt_private" arity="3"/>
<fsummary>Public-key decryption.</fsummary>
- <type>
- <v>CipherText = binary()</v>
- <v>Key = rsa_private_key()</v>
- <v>Options = public_crypt_options()</v>
- </type>
<desc>
<p>Public-key decryption using the private key. See also <seealso
marker="crypto:crypto#private_decrypt/4">crypto:private_decrypt/4</seealso></p>
@@ -248,14 +187,9 @@
</func>
<func>
- <name>decrypt_public(CipherText, Key) - > binary()</name>
- <name>decrypt_public(CipherText, Key, Options) - > binary()</name>
+ <name name="decrypt_public" arity="2"/>
+ <name name="decrypt_public" arity="3"/>
<fsummary>Public-key decryption.</fsummary>
- <type>
- <v>CipherText = binary()</v>
- <v>Key = rsa_public_key()</v>
- <v>Options = public_crypt_options()</v>
- </type>
<desc>
<p>Public-key decryption using the public key. See also <seealso
marker="crypto:crypto#public_decrypt/4">crypto:public_decrypt/4</seealso></p>
@@ -263,47 +197,24 @@
</func>
<func>
- <name>der_decode(Asn1type, Der) -> term()</name>
+ <name name="der_decode" arity="2"/>
<fsummary>Decodes a public-key ASN.1 DER encoded entity.</fsummary>
- <type>
- <v>Asn1Type = atom()</v>
- <d>ASN.1 type present in the Public Key applications
- ASN.1 specifications.</d>
- <v>Der = der_encoded()</v>
- </type>
- <desc>
+ <desc>
<p>Decodes a public-key ASN.1 DER encoded entity.</p>
</desc>
</func>
-
+
<func>
- <name>der_encode(Asn1Type, Entity) -> der_encoded()</name>
+ <name name="der_encode" arity="2"/>
<fsummary>Encodes a public-key entity with ASN.1 DER encoding.</fsummary>
- <type>
- <v>Asn1Type = atom()</v>
- <d>ASN.1 type present in the Public Key applications
- ASN.1 specifications.</d>
- <v>Entity = term()</v>
- <d>Erlang representation of <c>Asn1Type</c></d>
- </type>
<desc>
<p>Encodes a public-key entity with ASN.1 DER encoding.</p>
</desc>
</func>
<func>
- <name>dh_gex_group(MinSize, SuggestedSize, MaxSize, Groups) -> {ok, {Size,Group}} | {error,Error}</name>
+ <name name="dh_gex_group" arity="4"/>
<fsummary>Selects a group for Diffie-Hellman key exchange</fsummary>
- <type>
- <v>MinSize = positive_integer()</v>
- <v>SuggestedSize = positive_integer()</v>
- <v>MaxSize = positive_integer()</v>
- <v>Groups = undefined | [{Size,[{G,P}]}]</v>
- <v>Size = positive_integer()</v>
- <v>Group = {G,P}</v>
- <v>G = positive_integer()</v>
- <v>P = positive_integer()</v>
- </type>
<desc>
<p>Selects a group for Diffie-Hellman key exchange with the key size in the range <c>MinSize...MaxSize</c>
and as close to <c>SuggestedSize</c> as possible. If <c>Groups == undefined</c> a default set will be
@@ -322,13 +233,10 @@
</desc>
</func>
- <func>
- <name>encrypt_private(PlainText, Key) -> binary()</name>
+ <func>
+ <name name="encrypt_private" arity="2"/>
+ <name name="encrypt_private" arity="3"/>
<fsummary>Public-key encryption using the private key.</fsummary>
- <type>
- <v>PlainText = binary()</v>
- <v>Key = rsa_private_key()</v>
- </type>
<desc>
<p>Public-key encryption using the private key.
See also <seealso
@@ -337,12 +245,9 @@
</func>
<func>
- <name>encrypt_public(PlainText, Key) -> binary()</name>
+ <name name="encrypt_public" arity="2"/>
+ <name name="encrypt_public" arity="3"/>
<fsummary>Public-key encryption using the public key.</fsummary>
- <type>
- <v>PlainText = binary()</v>
- <v>Key = rsa_public_key()</v>
- </type>
<desc>
<p>Public-key encryption using the public key. See also <seealso
marker="crypto:crypto#public_encrypt/4">crypto:public_encrypt/4</seealso>.</p>
@@ -350,11 +255,8 @@
</func>
<func>
- <name>generate_key(Params) -> {Public::binary(), Private::binary()} | #'ECPrivateKey'{} | #'RSAPrivateKey'{}</name>
+ <name name="generate_key" arity="1"/>
<fsummary>Generates a new keypair.</fsummary>
- <type>
- <v>Params = key_params()</v>
- </type>
<desc>
<p>Generates a new keypair. Note that except for Diffie-Hellman
the public key is included in the private key structure. See also
@@ -364,38 +266,27 @@
</func>
<func>
- <name>pem_decode(PemBin) -> [pem_entry()]</name>
+ <name name="pem_decode" arity="1"/>
<fsummary>Decodes PEM binary data and returns
entries as ASN.1 DER encoded entities.</fsummary>
- <type>
- <v>PemBin = binary()</v>
- <d>Example {ok, PemBin} = file:read_file("cert.pem").</d>
- </type>
<desc>
- <p>Decodes PEM binary data and returns
- entries as ASN.1 DER encoded entities.</p>
+ <p>Decodes PEM binary data and returns entries as ASN.1 DER encoded entities.</p>
+ <p>Example <c>{ok, PemBin} = file:read_file("cert.pem").</c></p>
</desc>
</func>
- <func>
- <name>pem_encode(PemEntries) -> binary()</name>
+ <func>
+ <name name="pem_encode" arity="1"/>
<fsummary>Creates a PEM binary.</fsummary>
- <type>
- <v> PemEntries = [pem_entry()] </v>
- </type>
- <desc>
- <p>Creates a PEM binary.</p>
- </desc>
+ <desc>
+ <p>Creates a PEM binary.</p>
+ </desc>
</func>
- <func>
- <name>pem_entry_decode(PemEntry) -> term()</name>
- <name>pem_entry_decode(PemEntry, Password) -> term()</name>
+ <func>
+ <name name="pem_entry_decode" arity="1"/>
+ <name name="pem_entry_decode" arity="2"/>
<fsummary>Decodes a PEM entry.</fsummary>
- <type>
- <v>PemEntry = pem_entry()</v>
- <v>Password = string()</v>
- </type>
<desc>
<p>Decodes a PEM entry. <c>pem_decode/1</c> returns a list of PEM
entries. Notice that if the PEM entry is of type
@@ -404,51 +295,36 @@
</desc>
</func>
- <func>
- <name>pem_entry_encode(Asn1Type, Entity) -> pem_entry()</name>
- <name>pem_entry_encode(Asn1Type, Entity, {CipherInfo, Password}) -> pem_entry()</name>
+ <func>
+ <name name="pem_entry_encode" arity="2"/>
+ <name name="pem_entry_encode" arity="3"/>
<fsummary>Creates a PEM entry that can be fed to <c>pem_encode/1</c>.</fsummary>
- <type>
- <v>Asn1Type = pki_asn1_type()</v>
- <v>Entity = term()</v>
- <d>Erlang representation of
- <c>Asn1Type</c>. If <c>Asn1Type</c> is 'SubjectPublicKeyInfo',
+ <desc>
+ <p>Creates a PEM entry that can be feed to <c>pem_encode/1</c>.</p>
+ <p>If <c>Asn1Type</c> is <c>'SubjectPublicKeyInfo'</c>,
<c>Entity</c> must be either an <c>rsa_public_key()</c>,
<c>dsa_public_key()</c> or an <c>ec_public_key()</c>
and this function creates the appropriate
- 'SubjectPublicKeyInfo' entry.
- </d>
- <v>CipherInfo = cipher_info()</v>
- <v>Password = string()</v>
- </type>
- <desc>
- <p>Creates a PEM entry that can be feed to <c>pem_encode/1</c>.</p>
- </desc>
+ <c>'SubjectPublicKeyInfo'</c> entry.
+ </p>
+ </desc>
</func>
-
+
<func>
- <name>pkix_decode_cert(Cert, otp|plain) -> #'Certificate'{} | #'OTPCertificate'{}</name>
+ <name name="pkix_decode_cert" arity="2"/>
<fsummary>Decodes an ASN.1 DER-encoded PKIX x509 certificate.</fsummary>
- <type>
- <v>Cert = der_encoded()</v>
- </type>
- <desc>
- <p>Decodes an ASN.1 DER-encoded PKIX certificate. Option <c>otp</c>
- uses the customized ASN.1 specification OTP-PKIX.asn1 for
- decoding and also recursively decode most of the standard
- parts.</p>
- </desc>
+ <desc>
+ <p>Decodes an ASN.1 DER-encoded PKIX certificate. Option <c>otp</c>
+ uses the customized ASN.1 specification OTP-PKIX.asn1 for
+ decoding and also recursively decode most of the standard
+ parts.</p>
+ </desc>
</func>
<func>
- <name>pkix_encode(Asn1Type, Entity, otp | plain) -> der_encoded()</name>
+ <name name="pkix_encode" arity="3"/>
<fsummary>DER encodes a PKIX x509 certificate or part of such a
certificate.</fsummary>
- <type>
- <v>Asn1Type = atom()</v>
- <d>The ASN.1 type can be 'Certificate', 'OTPCertificate' or a subtype of either.</d>
- <v>Entity = #'Certificate'{} | #'OTPCertificate'{} | a valid subtype</v>
- </type>
<desc>
<p>DER encodes a PKIX x509 certificate or part of such a
certificate. This function must be used for encoding certificates or parts of certificates
@@ -458,69 +334,47 @@
</func>
<func>
- <name>pkix_is_issuer(Cert, IssuerCert) -> boolean()</name>
- <fsummary>Checks if <c>IssuerCert</c> issued <c>Cert</c>.</fsummary>
- <type>
- <v>Cert = der_encoded() | #'OTPCertificate'{} | #'CertificateList'{}</v>
- <v>IssuerCert = der_encoded() | #'OTPCertificate'{}</v>
- </type>
- <desc>
- <p>Checks if <c>IssuerCert</c> issued <c>Cert</c>.</p>
- </desc>
- </func>
+ <name name="pkix_is_issuer" arity="2"/>
+ <fsummary>Checks if <c>IssuerCert</c> issued <c>Cert</c>.</fsummary>
+ <desc>
+ <p>Checks if <c>IssuerCert</c> issued <c>Cert</c>.</p>
+ </desc>
+ </func>
- <func>
- <name>pkix_is_fixed_dh_cert(Cert) -> boolean()</name>
- <fsummary>Checks if a certificate is a fixed Diffie-Hellman certificate.</fsummary>
- <type>
- <v>Cert = der_encoded() | #'OTPCertificate'{}</v>
- </type>
- <desc>
- <p>Checks if a certificate is a fixed Diffie-Hellman certificate.</p>
- </desc>
- </func>
+ <func>
+ <name name="pkix_is_fixed_dh_cert" arity="1"/>
+ <fsummary>Checks if a certificate is a fixed Diffie-Hellman certificate.</fsummary>
+ <desc>
+ <p>Checks if a certificate is a fixed Diffie-Hellman certificate.</p>
+ </desc>
+ </func>
- <func>
- <name>pkix_is_self_signed(Cert) -> boolean()</name>
- <fsummary>Checks if a certificate is self-signed.</fsummary>
- <type>
- <v>Cert = der_encoded() | #'OTPCertificate'{}</v>
- </type>
- <desc>
- <p>Checks if a certificate is self-signed.</p>
- </desc>
- </func>
+ <func>
+ <name name="pkix_is_self_signed" arity="1"/>
+ <fsummary>Checks if a certificate is self-signed.</fsummary>
+ <desc>
+ <p>Checks if a certificate is self-signed.</p>
+ </desc>
+ </func>
- <func>
- <name>pkix_issuer_id(Cert, IssuedBy) -> {ok, IssuerID} | {error, Reason}</name>
- <fsummary>Returns the issuer id.</fsummary>
- <type>
- <v>Cert = der_encoded() | #'OTPCertificate'{}</v>
- <v>IssuedBy = self | other</v>
- <v>IssuerID = {integer(), issuer_name()}</v>
- <d>The issuer id consists of the serial number and the issuers name.</d>
- <v>Reason = term()</v>
- </type>
- <desc>
- <p>Returns the issuer id.</p>
- </desc>
- </func>
-
+ <func>
+ <name name="pkix_issuer_id" arity="2"/>
+ <fsummary>Returns the issuer id.</fsummary>
+ <desc>
+ <p>Returns the issuer id.</p>
+ </desc>
+ </func>
- <func>
- <name>pkix_normalize_name(Issuer) -> Normalized</name>
- <fsummary>Normalizes an issuer name so that it can be easily
- compared to another issuer name.</fsummary>
- <type>
- <v>Issuer = issuer_name()</v>
- <v>Normalized = issuer_name()</v>
- </type>
- <desc>
- <p>Normalizes an issuer name so that it can be easily
- compared to another issuer name.</p>
- </desc>
- </func>
-
+ <func>
+ <name name="pkix_normalize_name" arity="1"/>
+ <fsummary>Normalizes an issuer name so that it can be easily
+ compared to another issuer name.</fsummary>
+ <desc>
+ <p>Normalizes an issuer name so that it can be easily
+ compared to another issuer name.</p>
+ </desc>
+ </func>
+
<func>
<name>pkix_path_validation(TrustedCert, CertChain, Options) -> {ok, {PublicKeyInfo, PolicyTree}} | {error, {bad_cert, Reason}} </name>
<fsummary>Performs a basic path validation according to RFC 5280.</fsummary>
@@ -622,26 +476,16 @@ fun(OtpCert :: #'OTPCertificate'{},
</func>
<func>
- <name>pkix_crl_issuer(CRL) -> issuer_name()</name>
+ <name name="pkix_crl_issuer" arity="1"/>
<fsummary>Returns the issuer of the <c>CRL</c>.</fsummary>
- <type>
- <v>CRL = der_encoded() | #'CertificateList'{} </v>
- </type>
<desc>
<p>Returns the issuer of the <c>CRL</c>.</p>
</desc>
</func>
<func>
- <name>pkix_crls_validate(OTPCertificate, DPAndCRLs, Options) -> CRLStatus()</name>
+ <name name="pkix_crls_validate" arity="3"/>
<fsummary>Performs CRL validation.</fsummary>
- <type>
- <v>OTPCertificate = #'OTPCertificate'{}</v>
- <v>DPAndCRLs = [{DP::#'DistributionPoint'{}, {DerCRL::der_encoded(), CRL::#'CertificateList'{}}}] </v>
- <v>Options = proplists:proplist()</v>
- <v>CRLStatus() = valid | {bad_cert, revocation_status_undetermined} | {bad_cert, {revocation_status_undetermined,
- {bad_crls, Details::term()}}} | {bad_cert, {revoked, crl_reason()}}</v>
- </type>
<desc>
<p>Performs CRL validation. It is intended to be called from
the verify fun of <seealso marker="#pkix_path_validation-3"> pkix_path_validation/3
@@ -692,24 +536,16 @@ fun(#'DistributionPoint'{}, #'CertificateList'{},
</func>
<func>
- <name>pkix_crl_verify(CRL, Cert) -> boolean()</name>
+ <name name="pkix_crl_verify" arity="2"/>
<fsummary> Verify that <c>Cert</c> is the <c> CRL</c> signer. </fsummary>
- <type>
- <v>CRL = der_encoded() | #'CertificateList'{} </v>
- <v>Cert = der_encoded() | #'OTPCertificate'{} </v>
- </type>
<desc>
<p>Verify that <c>Cert</c> is the <c>CRL</c> signer.</p>
</desc>
</func>
<func>
- <name>pkix_dist_point(Cert) -> DistPoint</name>
+ <name name="pkix_dist_point" arity="1"/>
<fsummary>Creates a distribution point for CRLs issued by the same issuer as <c>Cert</c>.</fsummary>
- <type>
- <v> Cert = der_encoded() | #'OTPCertificate'{} </v>
- <v> DistPoint = #'DistributionPoint'{}</v>
- </type>
<desc>
<p>Creates a distribution point for CRLs issued by the same issuer as <c>Cert</c>.
Can be used as input to <seealso
@@ -719,26 +555,17 @@ fun(#'DistributionPoint'{}, #'CertificateList'{},
</func>
<func>
- <name>pkix_dist_points(Cert) -> DistPoints</name>
+ <name name="pkix_dist_points" arity="1"/>
<fsummary> Extracts distribution points from the certificates extensions.</fsummary>
- <type>
- <v> Cert = der_encoded() | #'OTPCertificate'{} </v>
- <v> DistPoints = [#'DistributionPoint'{}]</v>
- </type>
<desc>
<p> Extracts distribution points from the certificates extensions.</p>
</desc>
</func>
<func>
- <name>pkix_match_dist_point(CRL, DistPoint) -> boolean()</name>
+ <name name="pkix_match_dist_point" arity="2"/>
<fsummary>Checks whether the given distribution point matches the
Issuing Distribution Point of the CRL.</fsummary>
-
- <type>
- <v>CRL = der_encoded() | #'CertificateList'{} </v>
- <v>DistPoint = #'DistributionPoint'{}</v>
- </type>
<desc>
<p>Checks whether the given distribution point matches the
Issuing Distribution Point of the CRL, as described in RFC 5280.
@@ -748,11 +575,8 @@ fun(#'DistributionPoint'{}, #'CertificateList'{},
</func>
<func>
- <name>pkix_sign(#'OTPTBSCertificate'{}, Key) -> der_encoded()</name>
+ <name name="pkix_sign" arity="2"/>
<fsummary>Signs certificate.</fsummary>
- <type>
- <v>Key = rsa_private_key() | dsa_private_key()</v>
- </type>
<desc>
<p>Signs an 'OTPTBSCertificate'. Returns the corresponding
DER-encoded certificate.</p>
@@ -760,17 +584,12 @@ fun(#'DistributionPoint'{}, #'CertificateList'{},
</func>
<func>
- <name>pkix_sign_types(AlgorithmId) -> {DigestType, SignatureType}</name>
+ <name name="pkix_sign_types" arity="1"/>
<fsummary>Translates signature algorithm OID to Erlang digest and signature algorithm types.</fsummary>
- <type>
- <v>AlgorithmId = oid()</v>
- <d>Signature OID from a certificate or a certificate revocation list.</d>
- <v>DigestType = rsa_digest_type() | dss_digest_type()</v>
- <v>SignatureType = rsa | dsa | ecdsa</v>
- </type>
<desc>
<p>Translates signature algorithm OID to Erlang digest and signature types.
</p>
+ <p>The <c>AlgorithmId</c> is the signature OID from a certificate or a certificate revocation list.</p>
</desc>
</func>
@@ -938,12 +757,8 @@ fun(#'DistributionPoint'{}, #'CertificateList'{},
</func>
<func>
- <name>pkix_verify(Cert, Key) -> boolean()</name>
+ <name name="pkix_verify" arity="2"/>
<fsummary>Verifies PKIX x.509 certificate signature.</fsummary>
- <type>
- <v>Cert = der_encoded()</v>
- <v>Key = rsa_public_key() | dsa_public_key() | ec_public_key()</v>
- </type>
<desc>
<p>Verifies PKIX x.509 certificate signature.</p>
</desc>
@@ -1059,41 +874,30 @@ end
<func>
- <name>sign(Msg, DigestType, Key) -> binary()</name>
- <name>sign(Msg, DigestType, Key, Options) -> binary()</name>
+ <name name="sign" arity="3"/>
+ <name name="sign" arity="4"/>
<fsummary>Creates a digital signature.</fsummary>
- <type>
- <v>Msg = binary() | {digest,binary()}</v>
- <d>The <c>Msg</c> is either the binary "plain text" data to be
- signed or it is the hashed value of "plain text", that is, the
- digest.</d>
- <v>DigestType = rsa_digest_type() | dss_digest_type() | ecdsa_digest_type()</v>
- <v>Key = rsa_private_key() | dsa_private_key() | ec_private_key()</v>
- <v>Options = public_sign_options()</v>
- </type>
<desc>
<p>Creates a digital signature.</p>
+ <p>The <c>Msg</c> is either the binary "plain text" data to be
+ signed or it is the hashed value of "plain text", that is, the
+ digest.</p>
</desc>
</func>
<func>
- <name>ssh_decode(SshBin, Type) -> [{public_key(), Attributes::list()}]</name>
+ <name name="ssh_decode" arity="2"/>
<fsummary>Decodes an SSH file-binary.</fsummary>
- <type>
- <v>SshBin = binary()</v>
- <d>Example <c>{ok, SshBin} = file:read_file("known_hosts")</c>.</d>
- <v>Type = public_key | ssh_file()</v>
- <d>If <c>Type</c> is <c>public_key</c> the binary can be either
- an RFC4716 public key or an OpenSSH public key.</d>
- </type>
- <desc>
- <p>Decodes an SSH file-binary. In the case of <c>known_hosts</c> or
- <c>auth_keys</c>, the binary can include one or more lines of the
- file. Returns a list of public keys and their attributes, possible
- attribute values depends on the file type represented by the
- binary.
- </p>
-
+ <desc>
+ <p>Decodes an SSH file-binary. In the case of <c>known_hosts</c> or
+ <c>auth_keys</c>, the binary can include one or more lines of the
+ file. Returns a list of public keys and their attributes, possible
+ attribute values depends on the file type represented by the
+ binary.
+ </p>
+ <p>If the <c>Type</c> is <c>ssh2_pubkey</c>, the result will be
+ <c>Decoded_ssh2_pubkey</c>. Otherwise it will be <c>Decoded_OtherType</c>.
+ </p>
<taglist>
<tag>RFC4716 attributes - see RFC 4716.</tag>
<item><p>{headers, [{string(), utf8_string()}]}</p></item>
@@ -1106,23 +910,25 @@ end
<item>{comment, string()}</item>
<item><p>{bits, integer()} - In SSH version 1 files.</p></item>
</taglist>
-
+ <p>Example: <c>{ok, SshBin} = file:read_file("known_hosts")</c>.
+ </p>
+ <p>If <c>Type</c> is <c>public_key</c> the binary can be either
+ an RFC4716 public key or an OpenSSH public key.</p>
</desc>
</func>
<func>
- <name>ssh_encode([{Key, Attributes}], Type) -> binary()</name>
+ <name name="ssh_encode" arity="2"/>
<fsummary>Encodes a list of SSH file entries to a binary.</fsummary>
- <type>
- <v>Key = public_key()</v>
- <v>Attributes = list()</v>
- <v>Type = ssh_file()</v>
- </type>
- <desc>
- <p>Encodes a list of SSH file entries (public keys and attributes) to a binary. Possible
- attributes depend on the file type, see <seealso
- marker="#ssh_decode-2"> ssh_decode/2 </seealso>.</p>
- </desc>
+ <desc>
+ <p>Encodes a list of SSH file entries (public keys and attributes) to a binary. Possible
+ attributes depend on the file type, see
+ <seealso marker="#ssh_decode-2"> ssh_decode/2 </seealso>.
+ </p>
+ <p>If the <c>Type</c> is <c>ssh2_pubkey</c>, the <c>InData</c> shall be
+ <c>InData_ssh2_pubkey</c>. Otherwise it shall be <c>OtherInData</c>.
+ </p>
+ </desc>
</func>
<func>
@@ -1131,8 +937,8 @@ end
<name>ssh_hostkey_fingerprint([DigestType], HostKey) -> [string()]</name>
<fsummary>Calculates a ssh fingerprint for a hostkey.</fsummary>
<type>
- <v>Key = public_key()</v>
- <v>DigestType = digest_type()</v>
+ <v>HostKey = <seealso marker="#type-public_key">public_key()</seealso></v>
+ <v>DigestType = <seealso marker="#type-digest_type">digest_type()</seealso></v>
</type>
<desc>
<p>Calculates a ssh fingerprint from a public host key as openssh does.</p>
@@ -1161,29 +967,19 @@ end
</func>
<func>
- <name>verify(Msg, DigestType, Signature, Key) -> boolean()</name>
- <name>verify(Msg, DigestType, Signature, Key, Options) -> boolean()</name>
+ <name name="verify" arity="4"/>
+ <name name="verify" arity="5"/>
<fsummary>Verifies a digital signature.</fsummary>
- <type>
- <v>Msg = binary() | {digest,binary()}</v>
- <d>The <c>Msg</c> is either the binary "plain text" data
- or it is the hashed value of "plain text", that is, the digest.</d>
- <v>DigestType = rsa_digest_type() | dss_digest_type() | ecdsa_digest_type()</v>
- <v>Signature = binary()</v>
- <v>Key = rsa_public_key() | dsa_public_key() | ec_public_key()</v>
- <v>Options = public_sign_options()</v>
- </type>
<desc>
<p>Verifies a digital signature.</p>
+ <p>The <c>Msg</c> is either the binary "plain text" data
+ or it is the hashed value of "plain text", that is, the digest.</p>
</desc>
</func>
<func>
- <name>short_name_hash(Name) -> string()</name>
+ <name name="short_name_hash" arity="1"/>
<fsummary>Generates a short hash of an issuer name.</fsummary>
- <type>
- <v>Name = issuer_name()</v>
- </type>
<desc>
<p>Generates a short hash of an issuer name. The hash is
returned as a string containing eight hexadecimal digits.</p>
diff --git a/lib/public_key/doc/src/specs.xml b/lib/public_key/doc/src/specs.xml
new file mode 100644
index 0000000000..e358ea1154
--- /dev/null
+++ b/lib/public_key/doc/src/specs.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<specs xmlns:xi="http://www.w3.org/2001/XInclude">
+ <xi:include href="../specs/specs_public_key.xml"/>
+</specs>
diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl
index b34f905fc3..3f609ce6c6 100644
--- a/lib/public_key/src/public_key.erl
+++ b/lib/public_key/src/public_key.erl
@@ -76,7 +76,7 @@
-type dsa_private_key() :: #'DSAPrivateKey'{}.
-type dsa_public_key() :: {integer(), #'Dss-Parms'{}}.
-type ecpk_parameters() :: {ecParameters, #'ECParameters'{}} | {namedCurve, Oid::tuple()}.
--type ecpk_parameters_api() :: ecpk_parameters() | #'ECParameters'{} | {namedCurve, Name::atom()}.
+-type ecpk_parameters_api() :: ecpk_parameters() | #'ECParameters'{} | {namedCurve, Name::crypto:ec_named_curve()}.
-type ec_public_key() :: {#'ECPoint'{}, ecpk_parameters_api()}.
-type ec_private_key() :: #'ECPrivateKey'{}.
-type key_params() :: #'DHParameter'{} | {namedCurve, oid()} | #'ECParameters'{} |
@@ -88,28 +88,41 @@
'CertificationRequest' | 'CertificateList' |
'ECPrivateKey' | 'EcpkParameters'.
-type pem_entry() :: {pki_asn1_type(),
- binary(), %% DER or Encrypted DER
- not_encrypted | {Cipher :: string(), Salt :: binary()} |
- {Cipher :: string(), #'PBES2-params'{}} |
- {Cipher :: string(), {#'PBEParameter'{}, atom()}} %% hash type
+ der_or_encrypted_der(),
+ not_encrypted | cipher_info()
}.
+-type der_or_encrypted_der() :: binary().
+-type cipher_info() :: {cipher(),
+ cipher_info_params()} .
+-type cipher() :: string() . % "RC2-CBC" | "DES-CBC" | "DES-EDE3-CBC",
+-type cipher_info_params() :: salt()
+ | {#'PBEParameter'{}, digest_type()}
+ | #'PBES2-params'{} .
+
+-type salt() :: binary(). % crypto:strong_rand_bytes(8)
+%% -type cipher_info() :: {Cipher :: string(), Salt :: binary()} |
+%% {Cipher :: string(), #'PBES2-params'{}} |
+%% {Cipher :: string(), {#'PBEParameter'{}, atom()}} %% hash type
+%% .
+
-type asn1_type() :: atom(). %% see "OTP-PUB-KEY.hrl
-type ssh_file() :: openssh_public_key | rfc4716_public_key | known_hosts |
auth_keys.
--type rsa_padding() :: 'rsa_pkcs1_padding' | 'rsa_pkcs1_oaep_padding'
- | 'rsa_no_padding'.
--type rsa_sign_padding() :: 'rsa_pkcs1_padding' | 'rsa_pkcs1_pss_padding'.
--type public_crypt_options() :: [{rsa_pad, rsa_padding()}].
--type rsa_digest_type() :: 'md5' | 'ripemd160' | 'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512'.
--type dss_digest_type() :: 'none' | 'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512'. %% None is for backwards compatibility
--type ecdsa_digest_type() :: 'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512'.
--type public_sign_options() :: [{rsa_pad, rsa_sign_padding()} | {rsa_pss_saltlen, integer()}].
--type digest_type() :: rsa_digest_type() | dss_digest_type() | ecdsa_digest_type().
+-type digest_type() :: none % None is for backwards compatibility
+ | crypto:rsa_digest_type()
+ | crypto:dss_digest_type()
+ | crypto:ecdsa_digest_type().
-type crl_reason() :: unspecified | keyCompromise | cACompromise | affiliationChanged | superseded
| cessationOfOperation | certificateHold | privilegeWithdrawn | aACompromise.
-type oid() :: tuple().
-type chain_type() :: server_chain | client_chain.
+-type issuer_id() :: {SerialNr::integer(), issuer_name()} .
+
+-type issuer_name() :: {rdnSequence,[#'AttributeTypeAndValue'{}]} .
+
+
+
-define(UINT32(X), X:32/unsigned-big-integer).
-define(DER_NULL, <<5, 0>>).
@@ -134,11 +147,11 @@ pem_encode(PemEntries) when is_list(PemEntries) ->
iolist_to_binary(pubkey_pem:encode(PemEntries)).
%%--------------------------------------------------------------------
--spec pem_entry_decode(pem_entry(), string()) -> term().
-%
%% Description: Decodes a pem entry. pem_decode/1 returns a list of
%% pem entries.
%%--------------------------------------------------------------------
+-spec pem_entry_decode(PemEntry) -> term() when PemEntry :: pem_entry() .
+
pem_entry_decode({'SubjectPublicKeyInfo', Der, _}) ->
{_, {'AlgorithmIdentifier', AlgId, Params}, Key0}
= der_decode('SubjectPublicKeyInfo', Der),
@@ -156,6 +169,9 @@ pem_entry_decode({'SubjectPublicKeyInfo', Der, _}) ->
pem_entry_decode({Asn1Type, Der, not_encrypted}) when is_atom(Asn1Type),
is_binary(Der) ->
der_decode(Asn1Type, Der).
+
+-spec pem_entry_decode(PemEntry, Password) -> term() when PemEntry :: pem_entry(),
+ Password :: string() .
pem_entry_decode({Asn1Type, Der, not_encrypted}, _) when is_atom(Asn1Type),
is_binary(Der) ->
der_decode(Asn1Type, Der);
@@ -181,11 +197,12 @@ pem_entry_decode({Asn1Type, CryptDer, {Cipher, Salt}} = PemEntry,
%%--------------------------------------------------------------------
--spec pem_entry_encode(pki_asn1_type(), term()) -> pem_entry().
--spec pem_entry_encode(pki_asn1_type(), term(), term()) -> pem_entry().
%%
%% Description: Creates a pem entry that can be feed to pem_encode/1.
%%--------------------------------------------------------------------
+-spec pem_entry_encode(Asn1Type, Entity) -> pem_entry() when Asn1Type :: pki_asn1_type(),
+ Entity :: term() .
+
pem_entry_encode('SubjectPublicKeyInfo', Entity=#'RSAPublicKey'{}) ->
Der = der_encode('RSAPublicKey', Entity),
Spki = {'SubjectPublicKeyInfo',
@@ -208,6 +225,13 @@ pem_entry_encode('SubjectPublicKeyInfo',
pem_entry_encode(Asn1Type, Entity) when is_atom(Asn1Type) ->
Der = der_encode(Asn1Type, Entity),
{Asn1Type, Der, not_encrypted}.
+
+-spec pem_entry_encode(Asn1Type, Entity, InfoPwd) ->
+ pem_entry() when Asn1Type :: pki_asn1_type(),
+ Entity :: term(),
+ InfoPwd :: {CipherInfo,Password},
+ CipherInfo :: cipher_info(),
+ Password :: string() .
pem_entry_encode(Asn1Type, Entity, {{Cipher, #'PBES2-params'{}} = CipherInfo,
Password}) when is_atom(Asn1Type) andalso
is_list(Password) andalso
@@ -229,7 +253,9 @@ pem_entry_encode(Asn1Type, Entity, {{Cipher, Salt} = CipherInfo,
do_pem_entry_encode(Asn1Type, Entity, CipherInfo, Password).
%%--------------------------------------------------------------------
--spec der_decode(asn1_type(), Der::binary()) -> term().
+-spec der_decode(Asn1Type, Der) -> Entity when Asn1Type :: asn1_type(),
+ Der :: binary(),
+ Entity :: term().
%%
%% Description: Decodes a public key asn1 der encoded entity.
%%--------------------------------------------------------------------
@@ -269,7 +295,9 @@ der_priv_key_decode(PKCS8Key) ->
PKCS8Key.
%%--------------------------------------------------------------------
--spec der_encode(asn1_type(), term()) -> Der::binary().
+-spec der_encode(Asn1Type, Entity) -> Der when Asn1Type :: asn1_type(),
+ Entity :: term(),
+ Der :: binary() .
%%
%% Description: Encodes a public key entity with asn1 DER encoding.
%%--------------------------------------------------------------------
@@ -311,8 +339,10 @@ der_encode(Asn1Type, Entity) when is_atom(Asn1Type) ->
end.
%%--------------------------------------------------------------------
--spec pkix_decode_cert(Cert::binary(), plain | otp) ->
- #'Certificate'{} | #'OTPCertificate'{}.
+-spec pkix_decode_cert(Cert, Type) ->
+ #'Certificate'{} | #'OTPCertificate'{}
+ when Cert :: der_encoded(),
+ Type :: plain | otp .
%%
%% Description: Decodes an asn1 der encoded pkix certificate. The otp
%% option will use the customized asn1 specification OTP-PKIX.asn1 for
@@ -332,7 +362,11 @@ pkix_decode_cert(DerCert, otp) when is_binary(DerCert) ->
end.
%%--------------------------------------------------------------------
--spec pkix_encode(asn1_type(), term(), otp | plain) -> Der::binary().
+-spec pkix_encode(Asn1Type, Entity, Type) -> Der
+ when Asn1Type :: asn1_type(),
+ Entity :: term(),
+ Type :: otp | plain,
+ Der :: der_encoded() .
%%
%% Description: Der encodes a certificate or part of a certificate.
%% This function must be used for encoding certificates or parts of certificates
@@ -347,16 +381,21 @@ pkix_encode(Asn1Type, Term0, otp) when is_atom(Asn1Type) ->
der_encode(Asn1Type, Term).
%%--------------------------------------------------------------------
--spec decrypt_private(CipherText :: binary(), rsa_private_key()) ->
- PlainText :: binary().
--spec decrypt_private(CipherText :: binary(), rsa_private_key(),
- public_crypt_options()) -> PlainText :: binary().
%%
%% Description: Public key decryption using the private key.
%%--------------------------------------------------------------------
+-spec decrypt_private(CipherText, Key) ->
+ PlainText when CipherText :: binary(),
+ Key :: rsa_private_key(),
+ PlainText :: binary() .
decrypt_private(CipherText, Key) ->
decrypt_private(CipherText, Key, []).
+-spec decrypt_private(CipherText, Key, Options) ->
+ PlainText when CipherText :: binary(),
+ Key :: rsa_private_key(),
+ Options :: crypto:pk_encrypt_decrypt_opts(),
+ PlainText :: binary() .
decrypt_private(CipherText,
#'RSAPrivateKey'{} = Key,
Options)
@@ -366,61 +405,69 @@ decrypt_private(CipherText,
crypto:private_decrypt(rsa, CipherText, format_rsa_private_key(Key), Padding).
%%--------------------------------------------------------------------
--spec decrypt_public(CipherText :: binary(), rsa_public_key() | rsa_private_key()) ->
- PlainText :: binary().
--spec decrypt_public(CipherText :: binary(), rsa_public_key() | rsa_private_key(),
- public_crypt_options()) -> PlainText :: binary().
-%% NOTE: The rsa_private_key() is not part of the documented API it is
-%% here for testing purposes, in a real situation this is not a relevant
-%% thing to do.
-%%
%% Description: Public key decryption using the public key.
%%--------------------------------------------------------------------
+-spec decrypt_public(CipherText, Key) ->
+ PlainText
+ when CipherText :: binary(),
+ Key :: rsa_public_key(),
+ PlainText :: binary() .
decrypt_public(CipherText, Key) ->
decrypt_public(CipherText, Key, []).
+-spec decrypt_public(CipherText, Key, Options) ->
+ PlainText
+ when CipherText :: binary(),
+ Key :: rsa_public_key(),
+ Options :: crypto:pk_encrypt_decrypt_opts(),
+ PlainText :: binary() .
decrypt_public(CipherText, #'RSAPublicKey'{modulus = N, publicExponent = E},
Options) when is_binary(CipherText), is_list(Options) ->
- decrypt_public(CipherText, N,E, Options);
-
-decrypt_public(CipherText,#'RSAPrivateKey'{modulus = N, publicExponent = E},
- Options) when is_binary(CipherText), is_list(Options) ->
- decrypt_public(CipherText, N,E, Options).
+ Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding),
+ crypto:public_decrypt(rsa, CipherText,[E, N], Padding).
%%--------------------------------------------------------------------
--spec encrypt_public(PlainText :: binary(), rsa_public_key() | rsa_private_key()) ->
- CipherText :: binary().
--spec encrypt_public(PlainText :: binary(), rsa_public_key() | rsa_private_key(),
- public_crypt_options()) -> CipherText :: binary().
-
-%% NOTE: The rsa_private_key() is not part of the documented API it is
-%% here for testing purposes, in a real situation this is not a relevant
-%% thing to do.
-%%
%% Description: Public key encryption using the public key.
%%--------------------------------------------------------------------
+-spec encrypt_public(PlainText, Key) ->
+ CipherText
+ when PlainText :: binary(),
+ Key :: rsa_public_key(),
+ CipherText :: binary() .
encrypt_public(PlainText, Key) ->
encrypt_public(PlainText, Key, []).
-encrypt_public(PlainText, #'RSAPublicKey'{modulus=N,publicExponent=E},
- Options) when is_binary(PlainText), is_list(Options) ->
- encrypt_public(PlainText, N,E, Options);
-encrypt_public(PlainText, #'RSAPrivateKey'{modulus=N,publicExponent=E},
+-spec encrypt_public(PlainText, Key, Options) ->
+ CipherText
+ when PlainText :: binary(),
+ Key :: rsa_public_key(),
+ Options :: crypto:pk_encrypt_decrypt_opts(),
+ CipherText :: binary() .
+encrypt_public(PlainText, #'RSAPublicKey'{modulus=N,publicExponent=E},
Options) when is_binary(PlainText), is_list(Options) ->
- encrypt_public(PlainText, N,E, Options).
+ Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding),
+ crypto:public_encrypt(rsa, PlainText, [E,N], Padding).
%%--------------------------------------------------------------------
--spec encrypt_private(PlainText :: binary(), rsa_private_key()) ->
- CipherText :: binary().
--spec encrypt_private(PlainText :: binary(), rsa_private_key(),
- public_crypt_options()) -> CipherText :: binary().
%%
%% Description: Public key encryption using the private key.
%%--------------------------------------------------------------------
+-spec encrypt_private(PlainText, Key) ->
+ CipherText
+ when PlainText :: binary(),
+ Key :: rsa_private_key(),
+ CipherText :: binary() .
encrypt_private(PlainText, Key) ->
encrypt_private(PlainText, Key, []).
+
+-spec encrypt_private(PlainText, Key, Options) ->
+ CipherText
+ when PlainText :: binary(),
+ Key :: rsa_private_key(),
+ Options :: crypto:pk_encrypt_decrypt_opts(),
+ CipherText :: binary() .
encrypt_private(PlainText,
#'RSAPrivateKey'{modulus = N, publicExponent = E,
privateExponent = D} = Key,
@@ -432,22 +479,42 @@ encrypt_private(PlainText,
crypto:private_encrypt(rsa, PlainText, format_rsa_private_key(Key), Padding).
%%--------------------------------------------------------------------
+%% Description: List available group sizes among the pre-computed dh groups
+%%--------------------------------------------------------------------
+-spec dh_gex_group_sizes() -> [pos_integer()].
dh_gex_group_sizes() ->
pubkey_ssh:dh_gex_group_sizes().
+%%--------------------------------------------------------------------
+%% Description: Select a precomputed group
+%%--------------------------------------------------------------------
+-spec dh_gex_group(MinSize, SuggestedSize, MaxSize, Groups) ->
+ {ok,{Size,Group}} | {error,term()}
+ when MinSize :: pos_integer(),
+ SuggestedSize :: pos_integer(),
+ MaxSize :: pos_integer(),
+ Groups :: undefined | [{Size,[Group]}],
+ Size :: pos_integer(),
+ Group :: {G,P},
+ G :: pos_integer(),
+ P :: pos_integer() .
dh_gex_group(Min, N, Max, Groups) ->
pubkey_ssh:dh_gex_group(Min, N, Max, Groups).
%%--------------------------------------------------------------------
--spec generate_key(#'DHParameter'{}) ->
- {Public::binary(), Private::binary()};
- (ecpk_parameters_api()) ->
- #'ECPrivateKey'{};
- ({rsa, Size::pos_integer(), PubExp::pos_integer()}) ->
- #'RSAPrivateKey'{}.
-
-%% Description: Generates a new keypair
+%% Description: Generate a new key pair
%%--------------------------------------------------------------------
+-spec generate_key(DHparams | ECparams | RSAparams) ->
+ DHkeys | ECkey | RSAkey
+ when DHparams :: #'DHParameter'{},
+ DHkeys :: {PublicDH::binary(), PrivateDH::binary()},
+ ECparams :: ecpk_parameters_api(),
+ ECkey :: #'ECPrivateKey'{},
+ RSAparams :: {rsa, Size, PubExp},
+ Size::pos_integer(),
+ PubExp::pos_integer(),
+ RSAkey :: #'RSAPrivateKey'{} .
+
generate_key(#'DHParameter'{prime = P, base = G}) ->
crypto:generate_key(dh, [P, G]);
generate_key({namedCurve, _} = Params) ->
@@ -494,24 +561,34 @@ generate_key({rsa, ModulusSize, PublicExponent}) ->
end.
%%--------------------------------------------------------------------
--spec compute_key(#'ECPoint'{} , #'ECPrivateKey'{}) -> binary().
--spec compute_key(OthersKey ::binary(), MyKey::binary(), #'DHParameter'{}) -> binary().
%% Description: Compute shared secret
%%--------------------------------------------------------------------
+-spec compute_key(OthersECDHkey, MyECDHkey) ->
+ SharedSecret
+ when OthersECDHkey :: #'ECPoint'{},
+ MyECDHkey :: #'ECPrivateKey'{},
+ SharedSecret :: binary().
compute_key(#'ECPoint'{point = Point}, #'ECPrivateKey'{privateKey = PrivKey,
parameters = Param}) ->
ECCurve = ec_curve_spec(Param),
crypto:compute_key(ecdh, Point, PrivKey, ECCurve).
+-spec compute_key(OthersDHkey, MyDHkey, DHparms) ->
+ SharedSecret
+ when OthersDHkey :: crypto:dh_public(), % Was: binary(),
+ MyDHkey :: crypto:dh_private(), % Was: binary(),
+ DHparms :: #'DHParameter'{},
+ SharedSecret :: binary().
compute_key(PubKey, PrivKey, #'DHParameter'{prime = P, base = G}) ->
crypto:compute_key(dh, PubKey, PrivKey, [P, G]).
%%--------------------------------------------------------------------
--spec pkix_sign_types(SignatureAlg::oid()) ->
- %% Relevant dsa digest type is subpart of rsa digest type
- { DigestType :: rsa_digest_type(),
- SignatureType :: rsa | dsa | ecdsa
- }.
+-spec pkix_sign_types(AlgorithmId) ->
+ {DigestType, SignatureType}
+ when AlgorithmId :: oid(),
+ %% Relevant dsa digest type is a subset of rsa_digest_type()
+ DigestType :: crypto:rsa_digest_type(),
+ SignatureType :: rsa | dsa | ecdsa .
%% Description:
%%--------------------------------------------------------------------
pkix_sign_types(?sha1WithRSAEncryption) ->
@@ -542,24 +619,24 @@ pkix_sign_types(?'ecdsa-with-SHA512') ->
{sha512, ecdsa}.
%%--------------------------------------------------------------------
--spec sign(binary() | {digest, binary()},
- rsa_digest_type() | dss_digest_type() | ecdsa_digest_type(),
- rsa_private_key() | dsa_private_key() | ec_private_key()
- ) -> Signature :: binary().
-
--spec sign(binary() | {digest, binary()},
- rsa_digest_type() | dss_digest_type() | ecdsa_digest_type(),
- rsa_private_key() | dsa_private_key() | ec_private_key(),
- public_sign_options()
- ) -> Signature :: binary().
-
%% Description: Create digital signature.
%%--------------------------------------------------------------------
+-spec sign(Msg, DigestType, Key) ->
+ Signature when Msg :: binary() | {digest,binary()},
+ DigestType :: digest_type(),
+ Key :: private_key(),
+ Signature :: binary() .
sign(DigestOrPlainText, DigestType, Key) ->
sign(DigestOrPlainText, DigestType, Key, []).
-%% Backwards compatible
+-spec sign(Msg, DigestType, Key, Options) ->
+ Signature when Msg :: binary() | {digest,binary()},
+ DigestType :: digest_type(),
+ Key :: private_key(),
+ Options :: crypto:pk_sign_verify_opts(),
+ Signature :: binary() .
sign(Digest, none, Key = #'DSAPrivateKey'{}, Options) when is_binary(Digest) ->
+ %% Backwards compatible
sign({digest, Digest}, sha, Key, Options);
sign(DigestOrPlainText, DigestType, Key, Options) ->
case format_sign_key(Key) of
@@ -570,30 +647,26 @@ sign(DigestOrPlainText, DigestType, Key, Options) ->
end.
%%--------------------------------------------------------------------
--spec verify(binary() | {digest, binary()},
- rsa_digest_type() | dss_digest_type() | ecdsa_digest_type(),
- Signature :: binary(),
- rsa_public_key() | dsa_public_key() | ec_public_key()
- | rsa_private_key() | dsa_private_key() | ec_private_key()
- ) -> boolean().
-
--spec verify(binary() | {digest, binary()},
- rsa_digest_type() | dss_digest_type() | ecdsa_digest_type(),
- Signature :: binary(),
- rsa_public_key() | dsa_public_key() | ec_public_key()
- | rsa_private_key() | dsa_private_key() | ec_private_key(),
- public_sign_options()
- ) -> boolean().
-
%% Description: Verifies a digital signature.
%%--------------------------------------------------------------------
+-spec verify(Msg, DigestType, Signature, Key) ->
+ boolean() when Msg :: binary() | {digest, binary()},
+ DigestType :: digest_type(),
+ Signature :: binary(),
+ Key :: public_key() .
+
verify(DigestOrPlainText, DigestType, Signature, Key) ->
verify(DigestOrPlainText, DigestType, Signature, Key, []).
-%% Backwards compatible
+-spec verify(Msg, DigestType, Signature, Key, Options) ->
+ boolean() when Msg :: binary() | {digest, binary()},
+ DigestType :: digest_type(),
+ Signature :: binary(),
+ Key :: public_key(),
+ Options :: crypto:pk_sign_verify_opts().
+
verify(Digest, none, Signature, Key = {_, #'Dss-Parms'{}}, Options) when is_binary(Digest) ->
- verify({digest, Digest}, sha, Signature, Key, Options);
-verify(Digest, none, Signature, Key = #'DSAPrivateKey'{}, Options) when is_binary(Digest) ->
+ %% Backwards compatible
verify({digest, Digest}, sha, Signature, Key, Options);
verify(DigestOrPlainText, DigestType, Signature, Key, Options) when is_binary(Signature) ->
case format_verify_key(Key) of
@@ -608,8 +681,8 @@ verify(_,_,_,_,_) ->
false.
%%--------------------------------------------------------------------
--spec pkix_dist_point(der_encoded() | #'OTPCertificate'{}) ->
- #'DistributionPoint'{}.
+-spec pkix_dist_point(Cert) -> DistPoint when Cert :: der_encoded() | #'OTPCertificate'{},
+ DistPoint :: #'DistributionPoint'{}.
%% Description: Creates a distribution point for CRLs issued by the same issuer as <c>Cert</c>.
%%--------------------------------------------------------------------
pkix_dist_point(OtpCert) when is_binary(OtpCert) ->
@@ -632,8 +705,8 @@ pkix_dist_point(OtpCert) ->
reasons = asn1_NOVALUE,
distributionPoint = Point}.
%%--------------------------------------------------------------------
--spec pkix_dist_points(der_encoded() | #'OTPCertificate'{}) ->
- [#'DistributionPoint'{}].
+-spec pkix_dist_points(Cert) -> DistPoints when Cert :: der_encoded() | #'OTPCertificate'{},
+ DistPoints :: [ #'DistributionPoint'{} ].
%% Description: Extracts distributionpoints specified in the certificates extensions.
%%--------------------------------------------------------------------
pkix_dist_points(OtpCert) when is_binary(OtpCert) ->
@@ -647,8 +720,10 @@ pkix_dist_points(OtpCert) ->
[], Value).
%%--------------------------------------------------------------------
--spec pkix_match_dist_point(der_encoded() | #'CertificateList'{},
- #'DistributionPoint'{}) -> boolean().
+-spec pkix_match_dist_point(CRL, DistPoint) ->
+ boolean()
+ when CRL :: der_encoded() | #'CertificateList'{},
+ DistPoint :: #'DistributionPoint'{}.
%% Description: Check whether the given distribution point matches
%% the "issuing distribution point" of the CRL.
%%--------------------------------------------------------------------
@@ -679,8 +754,9 @@ pkix_match_dist_point(#'CertificateList'{
end.
%%--------------------------------------------------------------------
--spec pkix_sign(#'OTPTBSCertificate'{},
- rsa_private_key() | dsa_private_key() | ec_private_key()) -> Der::binary().
+-spec pkix_sign(Cert, Key) -> Der when Cert :: #'OTPTBSCertificate'{},
+ Key :: private_key(),
+ Der :: der_encoded() .
%%
%% Description: Sign a pkix x.509 certificate. Returns the corresponding
%% der encoded 'Certificate'{}
@@ -699,8 +775,8 @@ pkix_sign(#'OTPTBSCertificate'{signature =
pkix_encode('OTPCertificate', Cert, otp).
%%--------------------------------------------------------------------
--spec pkix_verify(Cert::binary(), rsa_public_key()|
- dsa_public_key() | ec_public_key()) -> boolean().
+-spec pkix_verify(Cert, Key) -> boolean() when Cert :: der_encoded(),
+ Key :: public_key() .
%%
%% Description: Verify pkix x.509 certificate signature.
%%--------------------------------------------------------------------
@@ -720,7 +796,9 @@ pkix_verify(DerCert, Key = {#'ECPoint'{}, _})
verify(PlainText, DigestType, Signature, Key).
%%--------------------------------------------------------------------
--spec pkix_crl_verify(CRL::binary() | #'CertificateList'{}, Cert::binary() | #'OTPCertificate'{}) -> boolean().
+-spec pkix_crl_verify(CRL, Cert) -> boolean()
+ when CRL :: der_encoded() | #'CertificateList'{},
+ Cert :: der_encoded() | #'OTPCertificate'{} .
%%
%% Description: Verify that Cert is the CRL signer.
%%--------------------------------------------------------------------
@@ -739,9 +817,12 @@ pkix_crl_verify(#'CertificateList'{} = CRL, #'OTPCertificate'{} = Cert) ->
PublicKey, PublicKeyParams).
%%--------------------------------------------------------------------
--spec pkix_is_issuer(Cert :: der_encoded()| #'OTPCertificate'{} | #'CertificateList'{},
- IssuerCert :: der_encoded()|
- #'OTPCertificate'{}) -> boolean().
+-spec pkix_is_issuer(Cert, IssuerCert) ->
+ boolean() when Cert :: der_encoded()
+ | #'OTPCertificate'{}
+ | #'CertificateList'{},
+ IssuerCert :: der_encoded()
+ | #'OTPCertificate'{} .
%%
%% Description: Checks if <IssuerCert> issued <Cert>.
%%--------------------------------------------------------------------
@@ -761,7 +842,7 @@ pkix_is_issuer(#'CertificateList'{tbsCertList = TBSCRL},
pubkey_cert_records:transform(TBSCRL#'TBSCertList'.issuer, decode)).
%%--------------------------------------------------------------------
--spec pkix_is_self_signed(Cert::binary()| #'OTPCertificate'{}) -> boolean().
+-spec pkix_is_self_signed(Cert) -> boolean() when Cert::der_encoded()| #'OTPCertificate'{}.
%%
%% Description: Checks if a Certificate is self signed.
%%--------------------------------------------------------------------
@@ -772,7 +853,7 @@ pkix_is_self_signed(Cert) when is_binary(Cert) ->
pkix_is_self_signed(OtpCert).
%%--------------------------------------------------------------------
--spec pkix_is_fixed_dh_cert(Cert::binary()| #'OTPCertificate'{}) -> boolean().
+-spec pkix_is_fixed_dh_cert(Cert) -> boolean() when Cert::der_encoded()| #'OTPCertificate'{}.
%%
%% Description: Checks if a Certificate is a fixed Diffie-Hellman Cert.
%%--------------------------------------------------------------------
@@ -783,13 +864,12 @@ pkix_is_fixed_dh_cert(Cert) when is_binary(Cert) ->
pkix_is_fixed_dh_cert(OtpCert).
%%--------------------------------------------------------------------
--spec pkix_issuer_id(Cert::binary()| #'OTPCertificate'{},
- IssuedBy :: self | other) ->
- {ok, {SerialNr :: integer(),
- Issuer :: {rdnSequence,
- [#'AttributeTypeAndValue'{}]}}}
- | {error, Reason :: term()}.
-%
+-spec pkix_issuer_id(Cert, IssuedBy) ->
+ {ok, issuer_id()} | {error, Reason}
+ when Cert::der_encoded()| #'OTPCertificate'{},
+ IssuedBy :: self | other,
+ Reason :: term() .
+
%% Description: Returns the issuer id.
%%--------------------------------------------------------------------
pkix_issuer_id(#'OTPCertificate'{} = OtpCert, Signed) when (Signed == self) or
@@ -800,9 +880,9 @@ pkix_issuer_id(Cert, Signed) when is_binary(Cert) ->
pkix_issuer_id(OtpCert, Signed).
%%--------------------------------------------------------------------
--spec pkix_crl_issuer(CRL::binary()| #'CertificateList'{}) ->
- {rdnSequence,
- [#'AttributeTypeAndValue'{}]}.
+-spec pkix_crl_issuer(CRL| #'CertificateList'{}) ->
+ Issuer when CRL :: der_encoded(),
+ Issuer :: issuer_name() .
%
%% Description: Returns the issuer.
%%--------------------------------------------------------------------
@@ -813,10 +893,9 @@ pkix_crl_issuer(#'CertificateList'{} = CRL) ->
CRL#'CertificateList'.tbsCertList#'TBSCertList'.issuer, decode).
%%--------------------------------------------------------------------
--spec pkix_normalize_name({rdnSequence,
- [#'AttributeTypeAndValue'{}]}) ->
- {rdnSequence,
- [#'AttributeTypeAndValue'{}]}.
+-spec pkix_normalize_name(Issuer) -> Normalized
+ when Issuer :: issuer_name(),
+ Normalized :: issuer_name() .
%%
%% Description: Normalizes a issuer name so that it can be easily
%% compared to another issuer name.
@@ -827,7 +906,7 @@ pkix_normalize_name(Issuer) ->
%%--------------------------------------------------------------------
-spec pkix_path_validation(Cert::binary()| #'OTPCertificate'{} | atom(),
CertChain :: [binary()] ,
- Options :: proplists:proplist()) ->
+ Options :: [{atom(),term()}]) ->
{ok, {PublicKeyInfo :: term(),
PolicyTree :: term()}} |
{error, {bad_cert, Reason :: term()}}.
@@ -863,11 +942,19 @@ pkix_path_validation(#'OTPCertificate'{} = TrustedCert, CertChain, Options)
path_validation(CertChain, ValidationState).
%--------------------------------------------------------------------
--spec pkix_crls_validate(#'OTPCertificate'{},
- [{DP::#'DistributionPoint'{}, {DerCRL::binary(), CRL::#'CertificateList'{}}}],
- Options :: proplists:proplist()) -> valid | {bad_cert, revocation_status_undetermined} |
- {bad_cert, {revocation_status_undetermined, Reason::term()}} |
- {bad_cert, {revoked, crl_reason()}}.
+-spec pkix_crls_validate(OTPcertificate, DPandCRLs, Options) ->
+ CRLstatus when OTPcertificate :: #'OTPCertificate'{},
+ DPandCRLs :: [DPandCRL],
+ DPandCRL :: {DP, {DerCRL, CRL}},
+ DP :: #'DistributionPoint'{},
+ DerCRL :: der_encoded(),
+ CRL :: #'CertificateList'{},
+ Options :: [{atom(),term()}],
+ CRLstatus :: valid
+ | {bad_cert, BadCertReason},
+ BadCertReason :: revocation_status_undetermined
+ | {revocation_status_undetermined, Reason::term()}
+ | {revoked, crl_reason()}.
%% Description: Performs a CRL validation according to RFC 5280.
%%--------------------------------------------------------------------
@@ -884,20 +971,10 @@ pkix_crls_validate(OtpCert, DPAndCRLs0, Options) ->
Options, pubkey_crl:init_revokation_state()).
%--------------------------------------------------------------------
--spec pkix_verify_hostname(#'OTPCertificate'{} | binary(),
- referenceIDs()
- ) -> boolean().
-
--spec pkix_verify_hostname(#'OTPCertificate'{} | binary(),
- referenceIDs(),
- proplists:proplist()) -> boolean().
-
-type referenceIDs() :: [referenceID()] .
-type referenceID() :: {uri_id | dns_id | ip | srv_id | oid(), string()}
| {ip, inet:ip_address()} .
--spec pkix_verify_hostname_match_fun(high_level_alg()) -> match_fun() .
-
-type high_level_alg() :: https .
-type match_fun() :: fun((ReferenceID::referenceID() | string(),
PresentedID::{atom()|oid(),string()}) -> match_fun_result() ) .
@@ -905,9 +982,20 @@ pkix_crls_validate(OtpCert, DPAndCRLs0, Options) ->
%% Description: Validates a hostname to RFC 6125
%%--------------------------------------------------------------------
+-spec pkix_verify_hostname(Cert, ReferenceIDs) -> boolean()
+ when Cert :: der_encoded()
+ | #'OTPCertificate'{},
+ ReferenceIDs :: referenceIDs() .
pkix_verify_hostname(Cert, ReferenceIDs) ->
pkix_verify_hostname(Cert, ReferenceIDs, []).
+-spec pkix_verify_hostname(Cert, ReferenceIDs, Options) ->
+ boolean()
+ when Cert :: der_encoded()
+ | #'OTPCertificate'{},
+ ReferenceIDs :: referenceIDs(),
+ Options :: [{atom(),term()}] .
+
pkix_verify_hostname(BinCert, ReferenceIDs, Options) when is_binary(BinCert) ->
pkix_verify_hostname(pkix_decode_cert(BinCert,otp), ReferenceIDs, Options);
@@ -966,15 +1054,25 @@ pkix_verify_hostname(Cert = #'OTPCertificate'{tbsCertificate = TbsCert}, Referen
end
end.
+
+-spec pkix_verify_hostname_match_fun(high_level_alg()) -> match_fun() .
+
pkix_verify_hostname_match_fun(https) ->
fun({dns_id,FQDN=[_|_]}, {dNSName,Name=[_|_]}) -> verify_hostname_match_wildcard(FQDN, Name);
(_, _) -> default
end.
%%--------------------------------------------------------------------
--spec ssh_decode(binary(), public_key | ssh_file()) -> [{public_key(), Attributes::list()}]
- ; (binary(), ssh2_pubkey) -> public_key()
- .
+-spec ssh_decode(SshBin, Type) ->
+ Decoded
+ when SshBin :: binary(),
+ Type :: ssh2_pubkey | OtherType,
+ OtherType :: public_key | ssh_file(),
+ Decoded :: Decoded_ssh2_pubkey
+ | Decoded_OtherType,
+ Decoded_ssh2_pubkey :: public_key(),
+ Decoded_OtherType :: [{public_key(), Attributes}],
+ Attributes :: [{atom(),term()}] .
%%
%% Description: Decodes a ssh file-binary. In the case of know_hosts
%% or auth_keys the binary may include one or more lines of the
@@ -992,9 +1090,15 @@ ssh_decode(SshBin, Type) when is_binary(SshBin),
pubkey_ssh:decode(SshBin, Type).
%%--------------------------------------------------------------------
--spec ssh_encode([{public_key(), Attributes::list()}], ssh_file()) -> binary()
- ; (public_key(), ssh2_pubkey) -> binary()
- .
+-spec ssh_encode(InData, Type) ->
+ binary()
+ when Type :: ssh2_pubkey | OtherType,
+ OtherType :: public_key | ssh_file(),
+ InData :: InData_ssh2_pubkey | OtherInData,
+ InData_ssh2_pubkey :: public_key(),
+ OtherInData :: [{Key,Attributes}],
+ Key :: public_key(),
+ Attributes :: [{atom(),term()}] .
%%
%% Description: Encodes a list of ssh file entries (public keys and
%% attributes) to a binary. Possible attributes depends on the file
@@ -1029,13 +1133,14 @@ oid2ssh_curvename(?'secp521r1') -> <<"nistp521">>.
%%--------------------------------------------------------------------
-spec ssh_hostkey_fingerprint(public_key()) -> string().
--spec ssh_hostkey_fingerprint( digest_type(), public_key()) -> string()
- ; ([digest_type()], public_key()) -> [string()]
- .
ssh_hostkey_fingerprint(Key) ->
sshfp_string(md5, public_key:ssh_encode(Key,ssh2_pubkey) ).
+
+-spec ssh_hostkey_fingerprint( digest_type(), public_key()) -> string()
+ ; ([digest_type()], public_key()) -> [string()]
+ .
ssh_hostkey_fingerprint(HashAlgs, Key) when is_list(HashAlgs) ->
EncKey = public_key:ssh_encode(Key, ssh2_pubkey),
[sshfp_full_string(HashAlg,EncKey) || HashAlg <- HashAlgs];
@@ -1073,8 +1178,7 @@ fp_fmt(b64, Bin) ->
[lists:nth(C+1,B64Chars) || <<C:6>> <= <<Bin/binary,0:Padding>> ].
%%--------------------------------------------------------------------
--spec short_name_hash({rdnSequence, [#'AttributeTypeAndValue'{}]}) ->
- string().
+-spec short_name_hash(Name) -> string() when Name :: issuer_name() .
%% Description: Generates OpenSSL-style hash of a name.
%%--------------------------------------------------------------------
@@ -1105,10 +1209,11 @@ pkix_test_data(#{} = Chain) ->
pubkey_cert:gen_test_certs(maps:merge(Default, Chain)).
%%--------------------------------------------------------------------
--spec pkix_test_root_cert(
- Name :: string(), Opts :: [pubkey_cert:cert_opt()]) ->
- pubkey_cert:test_root_cert().
-
+-spec pkix_test_root_cert(Name, Options) ->
+ RootCert
+ when Name :: string(),
+ Options :: [{atom(),term()}], %[cert_opt()],
+ RootCert :: pubkey_cert:test_root_cert().
%% Description: Generates a root cert suitable for pkix_test_data/1
%%--------------------------------------------------------------------
@@ -1154,14 +1259,6 @@ do_pem_entry_decode({Asn1Type,_, _} = PemEntry, Password) ->
Der = pubkey_pem:decipher(PemEntry, Password),
der_decode(Asn1Type, Der).
-encrypt_public(PlainText, N, E, Options)->
- Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding),
- crypto:public_encrypt(rsa, PlainText, [E,N], Padding).
-
-decrypt_public(CipherText, N,E, Options) ->
- Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding),
- crypto:public_decrypt(rsa, CipherText,[E, N], Padding).
-
path_validation([], #path_validation_state{working_public_key_algorithm
= Algorithm,
working_public_key =
diff --git a/lib/public_key/test/public_key_SUITE.erl b/lib/public_key/test/public_key_SUITE.erl
index cfd8e7a34b..1955e9e119 100644
--- a/lib/public_key/test/public_key_SUITE.erl
+++ b/lib/public_key/test/public_key_SUITE.erl
@@ -718,12 +718,8 @@ encrypt_decrypt(Config) when is_list(Config) ->
Msg = list_to_binary(lists:duplicate(5, "Foo bar 100")),
RsaEncrypted = public_key:encrypt_private(Msg, PrivateKey),
Msg = public_key:decrypt_public(RsaEncrypted, PublicKey),
- Msg = public_key:decrypt_public(RsaEncrypted, PrivateKey),
RsaEncrypted2 = public_key:encrypt_public(Msg, PublicKey),
- RsaEncrypted3 = public_key:encrypt_public(Msg, PrivateKey),
Msg = public_key:decrypt_private(RsaEncrypted2, PrivateKey),
- Msg = public_key:decrypt_private(RsaEncrypted3, PrivateKey),
-
ok.
%%--------------------------------------------------------------------
diff --git a/lib/public_key/vsn.mk b/lib/public_key/vsn.mk
index 5e9e463323..4e52028c36 100644
--- a/lib/public_key/vsn.mk
+++ b/lib/public_key/vsn.mk
@@ -1 +1 @@
-PUBLIC_KEY_VSN = 1.6.1
+PUBLIC_KEY_VSN = 1.6.2
diff --git a/lib/reltool/doc/src/Makefile b/lib/reltool/doc/src/Makefile
index 8daafb7a2b..dce8059616 100644
--- a/lib/reltool/doc/src/Makefile
+++ b/lib/reltool/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2009-2016. All Rights Reserved.
+# Copyright Ericsson AB 2009-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/lib/reltool/doc/src/notes.xml b/lib/reltool/doc/src/notes.xml
index 52419259c6..e201ad4e23 100644
--- a/lib/reltool/doc/src/notes.xml
+++ b/lib/reltool/doc/src/notes.xml
@@ -38,7 +38,22 @@
thus constitutes one section in this document. The title of each
section is the version number of Reltool.</p>
- <section><title>Reltool 0.7.6</title>
+ <section><title>Reltool 0.7.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Reltool 0.7.6</title>
<section><title>Improvements and New Features</title>
<list>
diff --git a/lib/reltool/doc/src/reltool.xml b/lib/reltool/doc/src/reltool.xml
index 0da9279c80..874cda8369 100644
--- a/lib/reltool/doc/src/reltool.xml
+++ b/lib/reltool/doc/src/reltool.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2009</year>
- <year>2016</year>
+ <year>2018</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
diff --git a/lib/reltool/vsn.mk b/lib/reltool/vsn.mk
index c698790ede..6bfc8c60ea 100644
--- a/lib/reltool/vsn.mk
+++ b/lib/reltool/vsn.mk
@@ -1 +1 @@
-RELTOOL_VSN = 0.7.6
+RELTOOL_VSN = 0.7.7
diff --git a/lib/runtime_tools/c_src/Makefile.in b/lib/runtime_tools/c_src/Makefile.in
index 4530a83aee..75b3a98d56 100644
--- a/lib/runtime_tools/c_src/Makefile.in
+++ b/lib/runtime_tools/c_src/Makefile.in
@@ -36,7 +36,7 @@ CC = $(DED_CC)
CFLAGS = $(DED_CFLAGS) -I./
LD = $(DED_LD)
SHELL = /bin/sh
-LIBS = $(DED_LIBS)
+LIBS = $(DED_LIBS) @LIBS@
LDFLAGS += $(DED_LDFLAGS)
TRACE_LIBNAME = dyntrace trace_file_drv trace_ip_drv
@@ -58,7 +58,7 @@ TYPE_FLAGS = $(CFLAGS)
endif
endif
-ALL_CFLAGS = @DEFS@ $(TYPE_FLAGS) $(TRACE_DRV_INCLUDES) \
+ALL_CFLAGS = @DEFS@ @ERTS_CONFIG_H_IDIR@ $(TYPE_FLAGS) $(TRACE_DRV_INCLUDES) \
-I$(OBJDIR) -I$(ERL_TOP)/erts/emulator/$(TARGET)
ROOTDIR = $(ERL_TOP)/lib
@@ -75,7 +75,7 @@ RELSYSDIR = $(RELEASE_PATH)/lib/runtime_tools-$(VSN)
# Misc Macros
# ----------------------------------------------------
-TRACE_LIBS = $(foreach LIB, $(TRACE_LIBNAME), $(LIBDIR)/$(LIB)$(TYPEMARKER).@DED_EXT@)
+TRACE_LIBS = $(foreach LIB, $(TRACE_LIBNAME), $(LIBDIR)/$(LIB)$(TYPEMARKER).$(DED_EXT))
# ----------------------------------------------------
# Targets
@@ -94,7 +94,7 @@ $(LIBDIR):
$(OBJDIR)/%$(TYPEMARKER).o: %.c dyntrace_lttng.h
$(V_CC) -c -o $@ $(ALL_CFLAGS) $<
-$(LIBDIR)/%$(TYPEMARKER).@DED_EXT@: $(OBJDIR)/%$(TYPEMARKER).o
+$(LIBDIR)/%$(TYPEMARKER).$(DED_EXT): $(OBJDIR)/%$(TYPEMARKER).o
$(V_LD) $(LDFLAGS) -o $@ $^ $(LIBS)
clean:
diff --git a/lib/runtime_tools/doc/src/notes.xml b/lib/runtime_tools/doc/src/notes.xml
index 5692df2ab4..810bb8207c 100644
--- a/lib/runtime_tools/doc/src/notes.xml
+++ b/lib/runtime_tools/doc/src/notes.xml
@@ -32,6 +32,23 @@
<p>This document describes the changes made to the Runtime_Tools
application.</p>
+<section><title>Runtime_Tools 1.13.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Optimize <c>observer</c> by using new
+ <c>system_info(ets_count)</c> instead of more expensive
+ <c>length(ets:all())</c>.</p>
+ <p>
+ Own Id: OTP-15163 Aux Id: PR-1844 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Runtime_Tools 1.13</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/runtime_tools/vsn.mk b/lib/runtime_tools/vsn.mk
index 0a4ad61537..aa3d702997 100644
--- a/lib/runtime_tools/vsn.mk
+++ b/lib/runtime_tools/vsn.mk
@@ -1 +1 @@
-RUNTIME_TOOLS_VSN = 1.13
+RUNTIME_TOOLS_VSN = 1.13.1
diff --git a/lib/sasl/doc/src/notes.xml b/lib/sasl/doc/src/notes.xml
index 3dda5b06e8..fce032136d 100644
--- a/lib/sasl/doc/src/notes.xml
+++ b/lib/sasl/doc/src/notes.xml
@@ -31,6 +31,21 @@
</header>
<p>This document describes the changes made to the SASL application.</p>
+<section><title>SASL 3.2.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>SASL 3.2</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/sasl/test/sasl_report_SUITE.erl b/lib/sasl/test/sasl_report_SUITE.erl
index a03932133e..e639b55cee 100644
--- a/lib/sasl/test/sasl_report_SUITE.erl
+++ b/lib/sasl/test/sasl_report_SUITE.erl
@@ -106,6 +106,9 @@ gen_server_crash(Config, Encoding) ->
ok = rpc:call(Node,?MODULE,crash_me,[]),
+ ok = rpc:call(Node,logger_std_h,filesync,[default]),
+ ok = rpc:call(Node,logger_std_h,filesync,[sasl]),
+
test_server:stop_node(Node),
ok = logger:remove_primary_filter(no_remote),
diff --git a/lib/sasl/vsn.mk b/lib/sasl/vsn.mk
index 0972ae20ba..94b7f9dc56 100644
--- a/lib/sasl/vsn.mk
+++ b/lib/sasl/vsn.mk
@@ -1 +1 @@
-SASL_VSN = 3.2
+SASL_VSN = 3.2.1
diff --git a/lib/snmp/doc/src/Makefile b/lib/snmp/doc/src/Makefile
index a6a9477b05..e7ab491eef 100644
--- a/lib/snmp/doc/src/Makefile
+++ b/lib/snmp/doc/src/Makefile
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2017. All Rights Reserved.
+# Copyright Ericsson AB 1997-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/lib/snmp/doc/src/notes.xml b/lib/snmp/doc/src/notes.xml
index f64e0cca97..423d90fef6 100644
--- a/lib/snmp/doc/src/notes.xml
+++ b/lib/snmp/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1996</year><year>2017</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -34,7 +34,46 @@
</header>
- <section><title>SNMP 5.2.11</title>
+ <section><title>SNMP 5.2.12</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Conversion of (agent) Audit Trail Log (ATL) failed due
+ to invalid log entries.</p> <p>The conversion aborted
+ completely midway because the ATL contained invalid
+ entries. The conversion has been improved so that it now
+ firstly handles encountered errors and write an
+ informative message (into the converted stream) and
+ secondly keeps count of the number of successful or
+ failed entry conversions. See <seealso
+ marker="snmpa#log_to_txt">log_to_txt</seealso> for more
+ info. </p> <p>The reason the ATL contained invalid
+ entries have also been fixed. The reason was that for
+ some outgoing messages (not response):</p> <list
+ type="bulleted"> <item> <p>encrypted (v3 messages)</p>
+ <p>Was logged "as is" (encrypted) without the info to
+ decrypt, making conversion impossible (which was the
+ reason the log contained bad entries).</p> </item> <item>
+ <p>un-encrypted</p> <p>Was not logged at all. </p>
+ </item> </list>
+ <p>
+ Own Id: OTP-15287 Aux Id: ERIERL-206 </p>
+ </item>
+ <item>
+ <p>
+ [compiler] Spurious version message removed. The snmp mib
+ compiler printed an spurious version message if the
+ 'version' option was provided.</p>
+ <p>
+ Own Id: OTP-15290</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SNMP 5.2.11</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
@@ -48,7 +87,7 @@
</list>
</section>
-</section>
+ </section>
<section><title>SNMP 5.2.10</title>
diff --git a/lib/snmp/doc/src/snmp.xml b/lib/snmp/doc/src/snmp.xml
index 801193675c..480ed2e825 100644
--- a/lib/snmp/doc/src/snmp.xml
+++ b/lib/snmp/doc/src/snmp.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2016</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -341,10 +341,10 @@
</func>
<func>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block | Start) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Block | Stop) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Stop, Block) -> ok | {error, Reason}</name>
+ <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block | Start) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Block | Stop) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Stop, Block) -> ok | {ok, Cnt} | {error, Reason}</name>
<fsummary>Convert an Audit Trail Log to text format</fsummary>
<type>
<v>LogDir = string()</v>
@@ -355,6 +355,9 @@
<v>LogFile = string()</v>
<v>Start = Stop = null | datetime() | {local_time,datetime()} | {universal_time,datetime()} </v>
<v>Block = boolean()</v>
+ <v>Cnt = {NumOK, NumERR}</v>
+ <v>NumOK = non_neg_integer()</v>
+ <v>NumERR = pos_integer()</v>
<v>Reason = term()</v>
</type>
<desc>
@@ -394,16 +397,25 @@
and <c>Vsn</c> is the SNMP version. <c>PDU</c> is a textual
version of the protocol data unit. There is a new line
between <c>Vsn</c> and <c>PDU</c>.</p>
+
+ <p>If the entire log is successfully converted, the function
+ will return <c>ok</c>.
+ If one of more entries fail to convert, the function will instead
+ return <c>{ok, {NumOK, NumERR}}</c>, where the counters indicate
+ how many valid and erroneous entries where found.
+ If instead <c>{error, Reason}</c> is returned, the conversion
+ encountered a fatal error and where either never done of aborted
+ midway. </p>
<marker id="log_to_io"></marker>
</desc>
</func>
<func>
- <name>log_to_io(LogDir, Mibs, LogName, LogFile) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, LogFile, Block | Start) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, LogFile, Start, Block | Stop) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop, Block) -> ok | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile, Block | Start) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile, Start, Block | Stop) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop, Block) -> ok | {ok, Cnt} | {error, Reason}</name>
<fsummary>Convert an Audit Trail Log to text format</fsummary>
<type>
<v>LogDir = string()</v>
@@ -412,6 +424,9 @@
<v>LogName = string()</v>
<v>LogFile = string()</v>
<v>Start = Stop = null | datetime() | {local_time,datetime()} | {universal_time,datetime()} </v>
+ <v>Cnt = {NumOK, NumERR}</v>
+ <v>NumOK = non_neg_integer()</v>
+ <v>NumERR = pos_integer()</v>
<v>Reason = term()</v>
</type>
<desc>
diff --git a/lib/snmp/doc/src/snmp_impl_example_agent.xml b/lib/snmp/doc/src/snmp_impl_example_agent.xml
index e576fa51f3..7dda3dd5cd 100644
--- a/lib/snmp/doc/src/snmp_impl_example_agent.xml
+++ b/lib/snmp/doc/src/snmp_impl_example_agent.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1997</year><year>2016</year>
+ <year>1997</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/snmp/doc/src/snmpa.xml b/lib/snmp/doc/src/snmpa.xml
index d756ff7a65..b78f14da01 100644
--- a/lib/snmp/doc/src/snmpa.xml
+++ b/lib/snmp/doc/src/snmpa.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2004</year><year>2016</year>
+ <year>2004</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -559,13 +559,13 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
<func>
<name>log_to_txt(LogDir)</name>
<name>log_to_txt(LogDir, Block | Mibs)</name>
- <name>log_to_txt(LogDir, Mibs, Block | OutFile) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, Block | LogName) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, Block | LogFile) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block | Start) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block, Start) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Stop) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block, Start, Stop) -> ok | {error, Reason}</name>
+ <name>log_to_txt(LogDir, Mibs, Block | OutFile) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_txt(LogDir, Mibs, OutFile, Block | LogName) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_txt(LogDir, Mibs, OutFile, LogName, Block | LogFile) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block | Start) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block, Start) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Stop) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block, Start, Stop) -> ok | {ok, Cnt} | {error, Reason}</name>
<fsummary>Convert an Audit Trail Log to text format</fsummary>
<type>
<v>LogDir = string()</v>
@@ -576,6 +576,9 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
<v>LogName = string()</v>
<v>LogFile = string()</v>
<v>Start = Stop = null | calendar:datetime() | {local_time, calendar:datetime()} | {universal_time, calendar:datetime()} </v>
+ <v>Cnt = {NumOK, NumERR}</v>
+ <v>NumOK = non_neg_integer()</v>
+ <v>NumERR = pos_integer()</v>
<v>Reason = disk_log_open_error() | file_open_error() | term()</v>
<v>disk_log_open_error() = {LogName, term()}</v>
<v>file_open_error() = {OutFile, term()}</v>
@@ -597,14 +600,14 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
</func>
<func>
- <name>log_to_io(LogDir) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Block | Mibs) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, Block | LogName) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, Block | LogFile) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, LogFile, Block | Start) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, LogFile, Block, Start) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, LogFile, Block, Start, Stop) -> ok | {error, Reason}</name>
+ <name>log_to_io(LogDir) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_io(LogDir, Block | Mibs) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, Block | LogName) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, Block | LogFile) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile, Block | Start) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile, Block, Start) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile, Block, Start, Stop) -> ok | {ok, Cnt} | {error, Reason}</name>
<fsummary>Convert an Audit Trail Log to text format</fsummary>
<type>
<v>LogDir = string()</v>
@@ -614,6 +617,9 @@ notification_delivery_info() = #snmpa_notification_delivery_info{}
<v>LogName = string()</v>
<v>LogFile = string()</v>
<v>Start = Stop = null | calendar:datetime() | {local_time, calendar:datetime()} | {universal_time, calendar:datetime()} </v>
+ <v>Cnt = {NumOK, NumERR}</v>
+ <v>NumOK = non_neg_integer()</v>
+ <v>NumERR = pos_integer()</v>
<v>Reason = disk_log_open_error() | file_open_error() | term()</v>
<v>disk_log_open_error() = {LogName, term()}</v>
<v>file_open_error() = {OutFile, term()}</v>
diff --git a/lib/snmp/doc/src/snmpm.xml b/lib/snmp/doc/src/snmpm.xml
index 4818aeb697..be4cd58a1a 100644
--- a/lib/snmp/doc/src/snmpm.xml
+++ b/lib/snmp/doc/src/snmpm.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2004</year><year>2016</year>
+ <year>2004</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -1216,13 +1216,13 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
<func>
<name>log_to_txt(LogDir)</name>
<name>log_to_txt(LogDir, Block | Mibs)</name>
- <name>log_to_txt(LogDir, Mibs, Block | OutFile) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, Block | LogName) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, Block | LogFile) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block | Start) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block, Start) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Stop) -> ok | {error, Reason}</name>
- <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block, Start, Stop) -> ok | {error, Reason}</name>
+ <name>log_to_txt(LogDir, Mibs, Block | OutFile) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_txt(LogDir, Mibs, OutFile, Block | LogName) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_txt(LogDir, Mibs, OutFile, LogName, Block | LogFile) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block | Start) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block, Start) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Stop) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block, Start, Stop) -> ok | {ok, Cnt} | {error, Reason}</name>
<fsummary>Convert an Audit Trail Log to text format</fsummary>
<type>
<v>LogDir = string()</v>
@@ -1233,6 +1233,9 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
<v>LogName = string()</v>
<v>LogFile = string()</v>
<v>Start = Stop = null | calendar:datetime() | {local_time, calendar:datetime()} | {universal_time, calendar:datetime()} </v>
+ <v>Cnt = {NumOK, NumERR}</v>
+ <v>NumOK = non_neg_integer()</v>
+ <v>NumERR = pos_integer()</v>
<v>Reason = disk_log_open_error() | file_open_error() | term()</v>
<v>disk_log_open_error() = {LogName, term()}</v>
<v>file_open_error() = {OutFile, term()}</v>
@@ -1254,15 +1257,15 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
</func>
<func>
- <name>log_to_io(LogDir) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Block | Mibs) -> ok | {error, Reason}</name>
+ <name>log_to_io(LogDir) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_io(LogDir, Block | Mibs) -> ok | {ok, Cnt} | {error, Reason}</name>
<name>log_to_io(LogDir, Mibs) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, Block | LogName) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, Block | LogFile) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, LogFile, Block | Start) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, LogFile, Block, Start) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop) -> ok | {error, Reason}</name>
- <name>log_to_io(LogDir, Mibs, LogName, LogFile, Block, Start, Stop) -> ok | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, Block | LogName) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, Block | LogFile) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile, Block | Start) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile, Block, Start) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop) -> ok | {ok, Cnt} | {error, Reason}</name>
+ <name>log_to_io(LogDir, Mibs, LogName, LogFile, Block, Start, Stop) -> ok | {ok, Cnt} | {error, Reason}</name>
<fsummary>Convert an Audit Trail Log to text format</fsummary>
<type>
<v>LogDir = string()</v>
@@ -1272,6 +1275,9 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1
<v>LogName = string()</v>
<v>LogFile = string()</v>
<v>Start = Stop = null | calendar:datetime() | {local_time, calendar:datetime()} | {universal_time, calendar:datetime()} </v>
+ <v>Cnt = {NumOK, NumERR}</v>
+ <v>NumOK = non_neg_integer()</v>
+ <v>NumERR = pos_integer()</v>
<v>Reason = disk_log_open_error() | file_open_error() | term()</v>
<v>disk_log_open_error() = {LogName, term()}</v>
<v>file_open_error() = {OutFile, term()}</v>
diff --git a/lib/snmp/src/agent/snmpa_net_if.erl b/lib/snmp/src/agent/snmpa_net_if.erl
index ecf9498ca9..afed4482d2 100644
--- a/lib/snmp/src/agent/snmpa_net_if.erl
+++ b/lib/snmp/src/agent/snmpa_net_if.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -137,11 +137,10 @@ init(Prio, NoteStore, MasterAgent, Parent, Opts) ->
proc_lib:init_ack({ok, self()}),
try loop(State)
catch
- C:E when C =/= exit, E =/= shutdown ->
+ C:E:S when C =/= exit, E =/= shutdown ->
Fmt =
"loop/1 EXCEPTION ~w:~w~n"
" ~p",
- S = erlang:get_stacktrace(),
case C of
exit ->
%% Externally killed, root cause is elsewhere
@@ -647,10 +646,10 @@ maybe_handle_recv(
case
try FilterMod:accept_recv(From_1, From_2)
catch
- Class:Exception ->
+ Class:Exception:StackTrace ->
error_msg(
"FilterMod:accept_recv(~p, ~p) crashed: ~w:~w~n ~p",
- [From_1,From_2,Class,Exception,erlang:get_stacktrace()]),
+ [From_1, From_2, Class, Exception, StackTrace]),
true
end
of
@@ -753,12 +752,11 @@ maybe_handle_recv_pdu(
case
try FilterMod:accept_recv_pdu(From_1, From_2, Type)
catch
- Class:Exception ->
+ Class:Exception:StackTrace ->
error_msg(
"FilterMod:accept_recv_pdu(~p, ~p, ~p) crashed: ~w:~w~n"
" ~p",
- [From_1,From_2,Type,Class,Exception,
- erlang:get_stacktrace()]),
+ [From_1, From_2, Type, Class, Exception, StackTrace]),
true
end
of
@@ -834,11 +832,10 @@ maybe_handle_reply_pdu(
try
FilterMod:accept_send_pdu(Addresses, Type)
catch
- Class:Exception ->
+ Class:Exception:StackTrace ->
error_msg(
"FilterMod:accept_send_pdu(~p, ~p) crashed: ~w:~w~n ~p",
- [Addresses, Type, Class, Exception,
- erlang:get_stacktrace()]),
+ [Addresses, Type, Class, Exception, StackTrace]),
true
end
of
@@ -872,7 +869,7 @@ handle_reply_pdu(
ACMData, LogF)) of
{ok, Packet} ->
?vinfo("time in agent: ~w mysec", [time_in_agent()]),
- try maybe_udp_send(S, Transport, To, Packet)
+ try maybe_udp_send_wo_log(S, Transport, To, Packet)
catch
{Reason, Sz} ->
error_msg("Cannot send message "
@@ -917,11 +914,10 @@ maybe_handle_send_pdu(
case
try FilterMod:accept_send_pdu(AddressesToFilter, Type)
catch
- Class:Exception ->
+ Class:Exception:StackTrace ->
error_msg(
"FilterMod:accept_send_pdu(~p, ~p) crashed: ~w:~w~n ~p",
- [AddressesToFilter,Type,
- Class,Exception,erlang:get_stacktrace()]),
+ [AddressesToFilter, Type, Class, Exception, StackTrace]),
true
end
of
@@ -1049,46 +1045,36 @@ do_handle_send_pdu(S, Type, Pdu, Addresses) ->
[Sz, Reason, Pdu])
end.
-do_handle_send_pdu1(
- #state{transports = Transports} = S,
- Type, Addresses) ->
+do_handle_send_pdu1(S, Type, Addresses) ->
lists:foreach(
- fun ({Domain, Address, Packet}) when is_binary(Packet) ->
- ?vdebug(
- "[~w] sending packet:~n"
- " size: ~p~n"
- " to: ~p", [Domain, sz(Packet), Address]),
- To = {Domain, Address},
- case select_transport_from_domain(Domain, Transports) of
- false ->
- error_msg(
- "Can not find transport~n"
- " size: ~p~n"
- " to: ~s",
- [sz(Packet), format_address(To)]);
- Transport ->
- maybe_udp_send(S, Transport, To, Packet)
- end;
- ({Domain, Address, {Packet, LogData}}) when is_binary(Packet) ->
- ?vdebug(
- "[~w] sending encrypted packet:~n"
- " size: ~p~n"
- " to: ~p", [Domain, sz(Packet), Address]),
- To = {Domain, Address},
- case select_transport_from_domain(Domain, Transports) of
- false ->
- error_msg(
- "Can not find transport~n"
- " size: ~p~n"
- " to: ~s",
- [sz(Packet), format_address(To)]);
- Transport ->
- maybe_udp_send(S, Transport, To, Packet, Type, LogData)
- end
+ fun ({Domain, Address, Pkg}) when is_binary(Pkg) ->
+ do_handle_send_pdu2(S, Type, Domain, Address,
+ Pkg, Pkg, "");
+ ({Domain, Address, {Pkg, LogPkg}}) when is_binary(Pkg) ->
+ do_handle_send_pdu2(S, Type, Domain, Address,
+ Pkg, LogPkg, " encrypted")
end,
Addresses).
-maybe_udp_send(
+do_handle_send_pdu2(#state{transports = Transports} = S,
+ Type, Domain, Address, Pkg, LogPkg, EncrStr) ->
+ ?vdebug("[~w] sending~s packet:"
+ "~n size: ~p"
+ "~n to: ~p", [Domain, EncrStr, sz(Pkg), Address]),
+ To = {Domain, Address},
+ case select_transport_from_domain(Domain, Transports) of
+ false ->
+ error_msg("Can not find transport: "
+ "~n size: ~p"
+ "~n to: ~s",
+ [sz(Pkg), format_address(To)]);
+ Transport ->
+ maybe_udp_send_w_log(S, Transport, To, Pkg, LogPkg, Type)
+ end.
+
+
+%% This function is used when logging has already been done!
+maybe_udp_send_wo_log(
#state{filter = FilterMod, transports = Transports},
#transport{socket = Socket},
To, Packet) ->
@@ -1096,10 +1082,10 @@ maybe_udp_send(
case
try FilterMod:accept_send(To_1, To_2)
catch
- Class:Exception ->
+ Class:Exception:StackTrace ->
error_msg(
"FilterMod:accept_send(~p, ~p) crashed: ~w:~w~n ~p",
- [To_1,To_2,Class,Exception,erlang:get_stacktrace()]),
+ [To_1, To_2, Class, Exception, StackTrace]),
true
end
of
@@ -1118,18 +1104,18 @@ maybe_udp_send(
udp_send(Socket, To, Packet)
end.
-maybe_udp_send(
+maybe_udp_send_w_log(
#state{log = Log, filter = FilterMod, transports = Transports},
#transport{socket = Socket},
- To, Packet, Type, _LogData) ->
+ To, Pkg, LogPkg, Type) ->
{To_1, To_2} = fix_filter_address(Transports, To),
case
try FilterMod:accept_send(To_1, To_2)
catch
- Class:Exception ->
+ Class:Exception:StackTrace ->
error_msg(
"FilterMod:accept_send(~p, ~p) crashed for: ~w:~w~n ~p",
- [To_1, To_2, Class, Exception, erlang:get_stacktrace()]),
+ [To_1, To_2, Class, Exception, StackTrace]),
true
end
of
@@ -1143,10 +1129,10 @@ maybe_udp_send(
_ ->
error_msg(
"FilterMod:accept_send(~p, ~p) returned: ~p",
- [To_1,To_2,Other])
+ [To_1, To_2, Other])
end,
- log(Log, Type, Packet, To),
- udp_send(Socket, To, Packet)
+ log(Log, Type, LogPkg, To),
+ udp_send(Socket, To, Pkg)
end.
udp_send(Socket, To, B) ->
@@ -1168,11 +1154,10 @@ udp_send(Socket, To, B) ->
ok ->
ok
catch
- error:ExitReason ->
+ error:ExitReason:StackTrace ->
error_msg("[exit] cannot send message "
"(destination: ~p:~p, size: ~p, reason: ~p, at: ~p)",
- [IpAddr, IpPort, sz(B), ExitReason,
- erlang:get_stacktrace()])
+ [IpAddr, IpPort, sz(B), ExitReason, StackTrace])
end.
sz(L) when is_list(L) -> length(L);
diff --git a/lib/snmp/src/compile/snmpc.erl b/lib/snmp/src/compile/snmpc.erl
index 7f627d66d9..c810bfcd41 100644
--- a/lib/snmp/src/compile/snmpc.erl
+++ b/lib/snmp/src/compile/snmpc.erl
@@ -169,11 +169,7 @@ get_version() ->
MI = ?MODULE:module_info(),
Attr = get_info(attributes, MI),
Vsn = get_info(app_vsn, Attr),
- Comp = get_info(compile, MI),
- Time = get_info(time, Comp),
- {Year, Month, Day, Hour, Min, Sec} = Time,
- io_lib:format("~s [~.4w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w]",
- [Vsn, Year, Month, Day, Hour, Min, Sec]).
+ Vsn.
maybe_display_options(Opts) ->
case lists:member(options, Opts) of
diff --git a/lib/snmp/src/misc/snmp_log.erl b/lib/snmp/src/misc/snmp_log.erl
index 767d801eee..5713c14912 100644
--- a/lib/snmp/src/misc/snmp_log.erl
+++ b/lib/snmp/src/misc/snmp_log.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -649,13 +649,14 @@ do_log_to_file(Log, TextFile, Mibs, Start, Stop) ->
MiniMib = snmp_mini_mib:create(Mibs),
Write = fun(X) ->
case format_msg(X, MiniMib, Start, Stop) of
- {ok, S} ->
- io:format(Fd, "~s", [S]);
- _ ->
- ok
+ {Tag, S} when (Tag =:= ok) orelse (Tag =:= error) ->
+ io:format(Fd, "~s", [S]),
+ Tag;
+ Ignore ->
+ Ignore
end
end,
- Res = (catch loop(disk_log:chunk(Log, start), Log, Write)),
+ Res = (catch loop(Log, Write)),
snmp_mini_mib:delete(MiniMib),
file:close(Fd),
Res;
@@ -668,39 +669,63 @@ do_log_to_io(Log, Mibs, Start, Stop) ->
MiniMib = snmp_mini_mib:create(Mibs),
Write = fun(X) ->
case format_msg(X, MiniMib, Start, Stop) of
- {ok, S} ->
- io:format("~s", [S]);
- _ ->
- ok
+ {Tag, S} when (Tag =:= ok) orelse (Tag =:= error) ->
+ io:format("~s", [S]),
+ Tag;
+ X ->
+ X
end
end,
- (catch loop(disk_log:chunk(Log, start), Log, Write)),
+ Res = (catch loop(Log, Write)),
snmp_mini_mib:delete(MiniMib),
- ok.
+ Res.
+
+loop(Log, Write) ->
+ loop(disk_log:chunk(Log, start), Log, Write, 0, 0).
-loop(eof, _Log, _Write) ->
+loop(eof, _Log, _Write, _NumOK, 0 = _NumERR) ->
ok;
-loop({error, _} = Error, _Log, _Write) ->
+loop(eof, _Log, _Write, NumOK, NumERR) ->
+ {ok, {NumOK, NumERR}};
+loop({error, _} = Error, _Log, _Write, _NumOK, _NumERR) ->
Error;
-loop({Cont, Terms}, Log, Write) ->
- case (catch lists:foreach(Write, Terms)) of
- {'EXIT', Reason} ->
- {error, Reason};
- _ ->
- loop(disk_log:chunk(Log, Cont), Log, Write)
+loop({Cont, Terms}, Log, Write, NumOK, NumERR) ->
+ try loop_terms(Terms, Write) of
+ {ok, {AddedOK, AddedERR}} ->
+ loop(disk_log:chunk(Log, Cont), Log, Write,
+ NumOK+AddedOK, NumERR+AddedERR)
+ catch
+ C:E:S ->
+ {error, {C, E, S}}
end;
-loop({Cont, Terms, BadBytes}, Log, Write) ->
+loop({Cont, Terms, BadBytes}, Log, Write, NumOK, NumERR) ->
error_logger:error_msg("Skipping ~w bytes while converting ~p~n~n",
[BadBytes, Log]),
- case (catch lists:foreach(Write, Terms)) of
- {'EXIT', Reason} ->
- {error, Reason};
- _ ->
- loop(disk_log:chunk(Log, Cont), Log, Write)
- end;
-loop(Error, _Log, _Write) ->
- Error.
+ try loop_terms(Terms, Write) of
+ {ok, {AddedOK, AddedERR}} ->
+ loop(disk_log:chunk(Log, Cont), Log, Write,
+ NumOK+AddedOK, NumERR+AddedERR)
+ catch
+ C:E:S ->
+ {error, {C, E, S}}
+ end.
+
+
+loop_terms(Terms, Write) ->
+ loop_terms(Terms, Write, 0, 0).
+
+loop_terms([], _Write, NumOK, NumERR) ->
+ {ok, {NumOK, NumERR}};
+loop_terms([Term|Terms], Write, NumOK, NumERR) ->
+ case Write(Term) of
+ ok ->
+ loop_terms(Terms, Write, NumOK+1, NumERR);
+ error ->
+ loop_terms(Terms, Write, NumOK, NumERR+1);
+ _ ->
+ loop_terms(Terms, Write, NumOK, NumERR)
+ end.
format_msg(Entry, Mib, Start, Stop) ->
@@ -733,88 +758,149 @@ do_format_msg({Timestamp, SeqNo, Packet, Ip, Port}, Mib) ->
%% This is crap...
do_format_msg(_, _) ->
- format_tab("** unknown entry in log file\n\n", []).
+ {error, format_tab("** unknown entry in log file\n\n", [])}.
do_format_msg(TimeStamp, {V3Hdr, ScopedPdu}, AddrStr, Mib) ->
- case (catch snmp_pdus:dec_scoped_pdu(ScopedPdu)) of
+ try snmp_pdus:dec_scoped_pdu(ScopedPdu) of
ScopedPDU when is_record(ScopedPDU, scopedPdu) ->
Msg = #message{version = 'version-3',
vsn_hdr = V3Hdr,
data = ScopedPDU},
- f(ts2str(TimeStamp), "", Msg, AddrStr, Mib);
- {'EXIT', Reason} ->
- format_tab(
- "** error in log file at ~s from ~s ~p\n\n",
- [ts2str(TimeStamp), AddrStr, Reason])
+ try f(ts2str(TimeStamp), "", Msg, AddrStr, Mib) of
+ {ok, _} = OK ->
+ OK
+ catch
+ FormatT:FormatE ->
+ format_error("format scoped pdu",
+ TimeStamp, AddrStr, FormatT, FormatE)
+ end
+ catch
+ DecT:DecE ->
+ format_error("decode scoped pdu",
+ TimeStamp, AddrStr, DecT, DecE)
end;
do_format_msg(TimeStamp, Packet, AddrStr, Mib) ->
- case (catch snmp_pdus:dec_message(binary_to_list(Packet))) of
+ try snmp_pdus:dec_message(binary_to_list(Packet)) of
Msg when is_record(Msg, message) ->
- f(ts2str(TimeStamp), "", Msg, AddrStr, Mib);
- {'EXIT', Reason} ->
- format_tab("** error in log file ~p\n\n", [Reason])
+ try f(ts2str(TimeStamp), "", Msg, AddrStr, Mib) of
+ {ok, _} = OK ->
+ OK
+ catch
+ FormatT:FormatE ->
+ %% Provide info about the message
+ Extra =
+ case Msg#message.version of
+ 'version-3' ->
+ #v3_hdr{msgID = ID,
+ msgFlags = Flags,
+ msgSecurityModel = SecModel} =
+ Msg#message.vsn_hdr,
+ SecLevel = snmp_misc:get_sec_level(Flags),
+ f("msg-id: ~w, sec-level: ~w, sec-model: ~w",
+ [ID, SecLevel, sm2atom(SecModel)]);
+ _ -> %% Community
+ f("community: ~s", [Msg#message.vsn_hdr])
+ end,
+ format_error(f("format ~p message; ~s",
+ [Msg#message.version, Extra]),
+ TimeStamp, AddrStr, FormatT, FormatE)
+ end
+ catch
+ DecT:DecE ->
+ format_error("decode message",
+ TimeStamp, AddrStr, DecT, DecE)
+
end.
-
+
+sm2atom(?SEC_ANY) -> any;
+sm2atom(?SEC_V1) -> v1;
+sm2atom(?SEC_V2C) -> v2c;
+sm2atom(?SEC_USM) -> usm;
+sm2atom(_) -> unknown.
+
do_format_msg(TimeStamp, SeqNo, {V3Hdr, ScopedPdu}, AddrStr, Mib) ->
- case (catch snmp_pdus:dec_scoped_pdu(ScopedPdu)) of
+ try snmp_pdus:dec_scoped_pdu(ScopedPdu) of
ScopedPDU when is_record(ScopedPDU, scopedPdu) ->
Msg = #message{version = 'version-3',
vsn_hdr = V3Hdr,
data = ScopedPDU},
- f(ts2str(TimeStamp), sn2str(SeqNo), Msg, AddrStr, Mib);
- {'EXIT', Reason} ->
- format_tab(
- "** error in log file at ~s from ~s ~p\n\n",
- [ts2str(TimeStamp), sn2str(SeqNo), AddrStr, Reason])
+ try f(ts2str(TimeStamp), sn2str(SeqNo), Msg, AddrStr, Mib) of
+ {ok, _} = OK ->
+ OK
+ catch
+ FormatT:FormatE ->
+ format_error("format scoped pdu",
+ TimeStamp, SeqNo, AddrStr, FormatT, FormatE)
+ end
+ catch
+ DecT:DecE ->
+ format_error("decode scoped pdu",
+ TimeStamp, SeqNo, AddrStr, DecT, DecE)
end;
do_format_msg(TimeStamp, SeqNo, Packet, AddrStr, Mib) ->
- case (catch snmp_pdus:dec_message(binary_to_list(Packet))) of
+ try snmp_pdus:dec_message(binary_to_list(Packet)) of
Msg when is_record(Msg, message) ->
- f(ts2str(TimeStamp), sn2str(SeqNo), Msg, AddrStr, Mib);
- {'EXIT', Reason} ->
- format_tab(
- "** error in log file ~s from ~s ~p\n\n",
- [ts2str(TimeStamp), sn2str(SeqNo), AddrStr, Reason])
+ try f(ts2str(TimeStamp), sn2str(SeqNo), Msg, AddrStr, Mib) of
+ {ok, _} = OK ->
+ OK
+
+ catch
+ FormatT:FormatE ->
+ %% Provide info about the message
+ Extra =
+ case Msg#message.version of
+ 'version-3' ->
+ #v3_hdr{msgID = ID,
+ msgFlags = Flags,
+ msgSecurityModel = SecModel} =
+ Msg#message.vsn_hdr,
+ SecLevel = snmp_misc:get_sec_level(Flags),
+ f("msg-id: ~w, sec-level: ~w, sec-model: ~w",
+ [ID, SecLevel, sm2atom(SecModel)]);
+ _ -> %% Community
+ f("community: ~s", [Msg#message.vsn_hdr])
+ end,
+ format_error(f("format ~p message; ~s",
+ [Msg#message.version, Extra]),
+ TimeStamp, SeqNo, AddrStr, FormatT, FormatE)
+ end
+ catch
+ DecT:DecE ->
+ format_error("decode message",
+ TimeStamp, SeqNo, AddrStr, DecT, DecE)
end.
-
-
-%% format_msg({TimeStamp, {V3Hdr, ScopedPdu}, {Addr, Port}},
-%% Mib, Start, Stop) ->
-%% format_msg({TimeStamp, {V3Hdr, ScopedPdu}, Addr, Port},
-%% Mib, Start, Stop);
-%% format_msg({TimeStamp, {V3Hdr, ScopedPdu}, Addr, Port},
-%% Mib, Start, Stop) ->
-%% case timestamp_filter(TimeStamp, Start, Stop) of
-%% true ->
-%% case (catch snmp_pdus:dec_scoped_pdu(ScopedPdu)) of
-%% ScopedPDU when record(ScopedPDU, scopedPdu) ->
-%% Msg = #message{version = 'version-3',
-%% vsn_hdr = V3Hdr,
-%% data = ScopedPDU},
-%% f(ts2str(TimeStamp), Msg, Addr, Port, Mib);
-%% {'EXIT', Reason} ->
-%% format_tab("** error in log file at ~s from ~p:~w ~p\n\n",
-%% [ts2str(TimeStamp), ip(Addr), Port, Reason])
-%% end;
-%% false ->
-%% ignore
-%% end;
-%% format_msg({TimeStamp, Packet, {Addr, Port}}, Mib, Start, Stop) ->
-%% format_msg({TimeStamp, Packet, Addr, Port}, Mib, Start, Stop);
-%% format_msg({TimeStamp, Packet, Addr, Port}, Mib, Start, Stop) ->
-%% case timestamp_filter(TimeStamp, Start, Stop) of
-%% true ->
-%% case (catch snmp_pdus:dec_message(binary_to_list(Packet))) of
-%% Msg when record(Msg, message) ->
-%% f(ts2str(TimeStamp), Msg, Addr, Port, Mib);
-%% {'EXIT', Reason} ->
-%% format_tab("** error in log file ~p\n\n", [Reason])
-%% end;
-%% false ->
-%% ignore
-%% end;
-%% format_msg(_, _Mib, _Start, _Stop) ->
-%% format_tab("** unknown entry in log file\n\n", []).
+
+
+format_error(WhatStr, TimeStamp, AddrStr, throw, {error, Reason}) ->
+ {ok, Str} =
+ format_tab(
+ "** error (~s) in log file at ~s from ~s: "
+ "~n ~p\n\n",
+ [WhatStr, ts2str(TimeStamp), AddrStr, Reason]),
+ {error, Str};
+format_error(WhatStr, TimeStamp, AddrStr, T, E) ->
+ {ok, Str} =
+ format_tab(
+ "** error (~s) in log file at ~s from ~s: "
+ "~n ~w: ~p\n\n",
+ [WhatStr, ts2str(TimeStamp), AddrStr, T, E]),
+ {error, Str}.
+
+format_error(WhatStr, TimeStamp, SeqNo, AddrStr, throw, {error, Reason}) ->
+ {ok, Str} =
+ format_tab(
+ "** error (~s) in log file at ~s~s from ~s: "
+ "~n ~p\n\n",
+ [WhatStr, ts2str(TimeStamp), sn2str(SeqNo), AddrStr, Reason]),
+ {error, Str};
+format_error(WhatStr, TimeStamp, SeqNo, AddrStr, T, E) ->
+ {ok, Str} =
+ format_tab(
+ "** error (~s) in log file at ~s~s from ~s: "
+ "~n ~w, ~p\n\n",
+ [WhatStr, ts2str(TimeStamp), sn2str(SeqNo), AddrStr, T, E]),
+ {error, Str}.
+
f(TimeStamp, SeqNo,
#message{version = Vsn, vsn_hdr = VsnHdr, data = Data},
@@ -838,51 +924,21 @@ f(TimeStamp, SeqNo,
end,
format_tab(
"~w ~s - ~s [~s]~s ~w\n~s",
- [Class, AddrStr, HdrStr, TimeStamp, SeqNo, Vsn, Str]).
-
-%% f(TimeStamp, SeqNo,
-%% #message{version = Vsn, vsn_hdr = VsnHdr, data = Data},
-%% Addr, Port, Mib) ->
-%% Str = format_pdu(Data, Mib),
-%% HdrStr = format_header(Vsn, VsnHdr),
-%% case get_type(Data) of
-%% trappdu ->
-%% f_trap(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port);
-%% 'snmpv2-trap' ->
-%% f_trap(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port);
-%% 'inform-request' ->
-%% f_inform(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port);
-%% 'get-response' ->
-%% f_response(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port);
-%% report ->
-%% f_report(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port);
-%% _ ->
-%% f_request(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port)
-%% end.
-
-%% f_request(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port) ->
-%% format_tab("request ~s:~w - ~s [~s]~s ~w\n~s",
-%% [ip(Addr), Port, HdrStr, TimeStamp, SeqNo, Vsn, Str]).
-
-%% f_response(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port) ->
-%% format_tab("response ~s:~w - ~s [~s]~s ~w\n~s",
-%% [ip(Addr), Port, HdrStr, TimeStamp, SeqNo, Vsn, Str]).
-
-%% f_report(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port) ->
-%% format_tab("report ~s:~w - ~s [~s]~s ~w\n~s",
-%% [ip(Addr), Port, HdrStr, TimeStamp, SeqNo, Vsn, Str]).
+ [Class, AddrStr, HdrStr, TimeStamp, SeqNo, Vsn, Str]);
+f(TimeStamp, SeqNo, Msg, AddrStr, _Mib) ->
+ io:format("<ERROR> Unexpected data: "
+ "~n TimeStamp: ~s~s"
+ "~n Msg: ~p"
+ "~n AddrStr: ~p"
+ "~n", [TimeStamp, SeqNo, Msg, AddrStr]),
+ throw({error, 'invalid-message'}).
-%% f_trap(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port) ->
-%% format_tab("trap ~s:~w - ~s [~s]~s ~w\n~s",
-%% [ip(Addr), Port, HdrStr, TimeStamp, SeqNo, Vsn, Str]).
+f(F, A) ->
+ lists:flatten(io_lib:format(F, A)).
-%% f_inform(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port) ->
-%% format_tab("inform ~s:~w - ~s [~s]~s ~w\n~s",
-%% [ip(Addr), Port, HdrStr, TimeStamp, SeqNo, Vsn, Str]).
ipPort2Str(Ip, Port) ->
snmp_conf:mk_addr_string({Ip, Port}).
- %% io_lib:format("~s:~w", [ip(Ip), Port]).
%% Convert a timestamp 2-tupple to a printable string
%%
@@ -973,7 +1029,13 @@ format_pdu(#scopedPdu{contextName = Context, data = Pdu}, Mib) ->
io_lib:format("Context: \"~s\"\n~s",
[Context, snmp_misc:format_pdu(Pdu, Mib)]);
format_pdu(Pdu, Mib) ->
- snmp_misc:format_pdu(Pdu, Mib).
+ try snmp_misc:format_pdu(Pdu, Mib) of
+ Str ->
+ Str
+ catch
+ _:_ ->
+ throw({error, 'invalid-pdu'})
+ end.
get_type(#scopedPdu{data = Pdu}) ->
get_type(Pdu);
@@ -983,12 +1045,6 @@ get_type(#pdu{type = Type}) ->
Type.
-%% ip(Domain, Addr) ->
-%% snmp_conf:mk_addr_string(Domain, Addr).
-%% ip({A,B,C,D}) ->
-%% io_lib:format("~w.~w.~w.~w", [A,B,C,D]).
-
-
%% -------------------------------------------------------------------
%% Various utility functions
diff --git a/lib/snmp/test/snmp_agent_test.erl b/lib/snmp/test/snmp_agent_test.erl
index 2ed2c4580c..f9c18af6ea 100644
--- a/lib/snmp/test/snmp_agent_test.erl
+++ b/lib/snmp/test/snmp_agent_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/snmp/test/snmp_to_snmpnet_SUITE.erl b/lib/snmp/test/snmp_to_snmpnet_SUITE.erl
index 6a3466b6e4..b83c7461d1 100644
--- a/lib/snmp/test/snmp_to_snmpnet_SUITE.erl
+++ b/lib/snmp/test/snmp_to_snmpnet_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2014-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2014-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/snmp/vsn.mk b/lib/snmp/vsn.mk
index 96123f02f5..4d5a0fbce8 100644
--- a/lib/snmp/vsn.mk
+++ b/lib/snmp/vsn.mk
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2017. All Rights Reserved.
+# Copyright Ericsson AB 1997-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -19,6 +19,6 @@
# %CopyrightEnd%
APPLICATION = snmp
-SNMP_VSN = 5.2.11
+SNMP_VSN = 5.2.12
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(SNMP_VSN)$(PRE_VSN)"
diff --git a/lib/ssh/doc/src/notes.xml b/lib/ssh/doc/src/notes.xml
index 58e8c9ab5b..c9809ce1e3 100644
--- a/lib/ssh/doc/src/notes.xml
+++ b/lib/ssh/doc/src/notes.xml
@@ -30,6 +30,45 @@
<file>notes.xml</file>
</header>
+<section><title>Ssh 4.7.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Extended the undocumented <c>ssh_dbg</c> debug module
+ with an api for a circular trace buffer. This makes it
+ easy to record the last low-level events before an error
+ is detected. It is intended for solving difficult errors.</p>
+ <p>
+ Own Id: OTP-15020</p>
+ </item>
+ <item>
+ <p>
+ The key exchange methods
+ <c>'[email protected]'</c>,
+ <c>'curve25519-sha256'</c> and <c>'curve448-sha512'</c>
+ are implemented. The last two are defined in
+ https://tools.ietf.org/html/draft-ietf-curdle-ssh-curves</p>
+ <p>
+ They all depends on that OpenSSL 1.1.1 or higher is used
+ as cryptolib.</p>
+ <p>
+ Own Id: OTP-15133 Aux Id: OTP-15240 </p>
+ </item>
+ <item>
+ <p>
+ The cipher '<c>[email protected]</c>' is now
+ supported if OpenSSL 1.1.1 or higher is used as
+ cryptolib.</p>
+ <p>
+ Own Id: OTP-15209 Aux Id: OTP-15164 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Ssh 4.7</title>
<section><title>Fixed Bugs and Malfunctions</title>
<list>
diff --git a/lib/ssh/doc/src/ssh_app.xml b/lib/ssh/doc/src/ssh_app.xml
index 9ec909d733..e80bb1853d 100644
--- a/lib/ssh/doc/src/ssh_app.xml
+++ b/lib/ssh/doc/src/ssh_app.xml
@@ -151,6 +151,9 @@
<item>diffie-hellman-group16-sha512</item>
<item>diffie-hellman-group18-sha512</item>
<item>diffie-hellman-group14-sha256</item>
+ <item>curve25519-sha256</item>
+ <item>[email protected]</item>
+ <item>curve448-sha512</item>
<item>diffie-hellman-group14-sha1</item>
<item>diffie-hellman-group-exchange-sha1</item>
<item>(diffie-hellman-group1-sha1, retired: It can be enabled with the
@@ -186,6 +189,7 @@
<tag>Encryption algorithms (ciphers)</tag>
<item>
<list type="bulleted">
+ <item>[email protected]</item>
<item>[email protected]</item>
<item>aes256-ctr</item>
<item>aes192-ctr</item>
@@ -365,6 +369,10 @@
</list>
<p/>
</item>
+
+ <item>
+ <url href="https://tools.ietf.org/html/draft-ietf-curdle-ssh-curves">Secure Shell (SSH) Key Exchange Method using Curve25519 and Curve448 (work in progress)</url>
+ </item>
</list>
diff --git a/lib/ssh/src/ssh.hrl b/lib/ssh/src/ssh.hrl
index 01c44cb371..94b9f3a196 100644
--- a/lib/ssh/src/ssh.hrl
+++ b/lib/ssh/src/ssh.hrl
@@ -118,6 +118,9 @@
'diffie-hellman-group14-sha256' |
'diffie-hellman-group16-sha512' |
'diffie-hellman-group18-sha512' |
+ 'curve25519-sha256' |
+ 'curve448-sha512' |
'ecdh-sha2-nistp256' |
'ecdh-sha2-nistp384' |
'ecdh-sha2-nistp521'
@@ -140,7 +143,8 @@
'aes192-ctr' |
'aes256-ctr' |
.
-type mac_alg() :: 'AEAD_AES_128_GCM' |
@@ -256,13 +260,7 @@
| accept_callback()
| {HashAlgoSpec::fp_digest_alg(), accept_callback()}.
--type fp_digest_alg() :: 'md5' |
- 'sha' |
- 'sha224' |
- 'sha256' |
- 'sha384' |
- 'sha512'
- .
+-type fp_digest_alg() :: 'md5' | crypto:sha1() | crypto:sha2() .
-type accept_callback() :: fun((PeerName::string(), fingerprint() ) -> boolean()) .
-type fingerprint() :: string() | [string()].
diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl
index 8e4831a601..4b41c10cbb 100644
--- a/lib/ssh/src/ssh_connection_handler.erl
+++ b/lib/ssh/src/ssh_connection_handler.erl
@@ -356,6 +356,8 @@ alg(ConnectionHandler) ->
| undefined,
encrypted_data_buffer = <<>> :: binary()
| undefined,
+ aead_data = <<>> :: binary()
+ | undefined,
undecrypted_packet_length :: undefined | non_neg_integer(),
key_exchange_init_msg :: #ssh_msg_kexinit{}
| undefined,
@@ -1308,14 +1310,16 @@ handle_event(info, {Proto, Sock, NewData}, StateName, D0 = #data{socket = Sock,
try ssh_transport:handle_packet_part(
D0#data.decrypted_data_buffer,
<<(D0#data.encrypted_data_buffer)/binary, NewData/binary>>,
- D0#data.undecrypted_packet_length,
+ D0#data.aead_data,
+ D0#data.undecrypted_packet_length,
D0#data.ssh_params)
of
{packet_decrypted, DecryptedBytes, EncryptedDataRest, Ssh1} ->
D1 = D0#data{ssh_params =
Ssh1#ssh{recv_sequence = ssh_transport:next_seqnum(Ssh1#ssh.recv_sequence)},
decrypted_data_buffer = <<>>,
- undecrypted_packet_length = undefined,
+ undecrypted_packet_length = undefined,
+ aead_data = <<>>,
encrypted_data_buffer = EncryptedDataRest},
try
ssh_message:decode(set_kex_overload_prefix(DecryptedBytes,D1))
@@ -1353,14 +1357,15 @@ handle_event(info, {Proto, Sock, NewData}, StateName, D0 = #data{socket = Sock,
StateName, D1),
{stop, Shutdown, D}
end;
-
- {get_more, DecryptedBytes, EncryptedDataRest, RemainingSshPacketLen, Ssh1} ->
+
+ {get_more, DecryptedBytes, EncryptedDataRest, AeadData, RemainingSshPacketLen, Ssh1} ->
%% Here we know that there are not enough bytes in
%% EncryptedDataRest to use. We must wait for more.
inet:setopts(Sock, [{active, once}]),
{keep_state, D0#data{encrypted_data_buffer = EncryptedDataRest,
decrypted_data_buffer = DecryptedBytes,
- undecrypted_packet_length = RemainingSshPacketLen,
+ undecrypted_packet_length = RemainingSshPacketLen,
+ aead_data = AeadData,
ssh_params = Ssh1}};
{bad_mac, Ssh1} ->
diff --git a/lib/ssh/src/ssh_message.erl b/lib/ssh/src/ssh_message.erl
index 55c0548c9b..da4027a763 100644
--- a/lib/ssh/src/ssh_message.erl
+++ b/lib/ssh/src/ssh_message.erl
@@ -289,12 +289,12 @@ encode(#ssh_msg_kex_dh_gex_reply{
<<?Ebyte(?SSH_MSG_KEX_DH_GEX_REPLY), ?Ebinary(EncKey), ?Empint(F), ?Ebinary(EncSign)>>;
encode(#ssh_msg_kex_ecdh_init{q_c = Q_c}) ->
- <<?Ebyte(?SSH_MSG_KEX_ECDH_INIT), ?Empint(Q_c)>>;
+ <<?Ebyte(?SSH_MSG_KEX_ECDH_INIT), ?Ebinary(Q_c)>>;
encode(#ssh_msg_kex_ecdh_reply{public_host_key = {Key,SigAlg}, q_s = Q_s, h_sig = Sign}) ->
EncKey = public_key:ssh_encode(Key, ssh2_pubkey),
EncSign = encode_signature(Key, SigAlg, Sign),
- <<?Ebyte(?SSH_MSG_KEX_ECDH_REPLY), ?Ebinary(EncKey), ?Empint(Q_s), ?Ebinary(EncSign)>>;
+ <<?Ebyte(?SSH_MSG_KEX_ECDH_REPLY), ?Ebinary(EncKey), ?Ebinary(Q_s), ?Ebinary(EncSign)>>;
encode(#ssh_msg_ignore{data = Data}) ->
<<?Ebyte(?SSH_MSG_IGNORE), ?Estring_utf8(Data)>>;
@@ -504,13 +504,13 @@ decode(<<?BYTE(?SSH_MSG_KEX_DH_GEX_REPLY), ?DEC_BIN(Key,__0), ?DEC_MPINT(F,__1),
h_sig = decode_signature(Hashsign)
};
-decode(<<"ecdh",?BYTE(?SSH_MSG_KEX_ECDH_INIT), ?DEC_MPINT(Q_c,__0)>>) ->
+decode(<<"ecdh",?BYTE(?SSH_MSG_KEX_ECDH_INIT), ?DEC_BIN(Q_c,__0)>>) ->
#ssh_msg_kex_ecdh_init{
q_c = Q_c
};
decode(<<"ecdh",?BYTE(?SSH_MSG_KEX_ECDH_REPLY),
- ?DEC_BIN(Key,__1), ?DEC_MPINT(Q_s,__2), ?DEC_BIN(Sig,__3)>>) ->
+ ?DEC_BIN(Key,__1), ?DEC_BIN(Q_s,__2), ?DEC_BIN(Sig,__3)>>) ->
#ssh_msg_kex_ecdh_reply{
public_host_key = public_key:ssh_decode(Key, ssh2_pubkey),
q_s = Q_s,
diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl
index b6d7aa0b1b..c5b0704925 100644
--- a/lib/ssh/src/ssh_transport.erl
+++ b/lib/ssh/src/ssh_transport.erl
@@ -36,7 +36,7 @@
default_algorithms/0, default_algorithms/1,
algo_classes/0, algo_class/1,
algo_two_spec_classes/0, algo_two_spec_class/1,
- handle_packet_part/4,
+ handle_packet_part/5,
handle_hello_version/1,
key_exchange_init_msg/1,
key_init/3, new_keys_message/1,
@@ -104,17 +104,14 @@ algo_two_spec_class(_) -> false.
default_algorithms(kex) ->
supported_algorithms(kex, [
- %% Under devolpment:
- 'curve25519-sha256',
- 'curve448-sha512',
%% Gone in OpenSSH 7.3.p1:
'diffie-hellman-group1-sha1'
]);
default_algorithms(cipher) ->
supported_algorithms(cipher, same(['AEAD_AES_128_GCM',
- 'AEAD_AES_256_GCM']));
+ 'AEAD_AES_256_GCM'
+ ]));
default_algorithms(mac) ->
supported_algorithms(mac, same(['AEAD_AES_128_GCM',
'AEAD_AES_256_GCM']));
@@ -131,15 +128,15 @@ supported_algorithms(kex) ->
{'ecdh-sha2-nistp384', [{public_keys,ecdh}, {curves,secp384r1}, {hashs,sha384}]},
{'ecdh-sha2-nistp521', [{public_keys,ecdh}, {curves,secp521r1}, {hashs,sha512}]},
{'ecdh-sha2-nistp256', [{public_keys,ecdh}, {curves,secp256r1}, {hashs,sha256}]},
- %% https://tools.ietf.org/html/draft-ietf-curdle-ssh-curves
- %% Secure Shell (SSH) Key Exchange Method using Curve25519 and Curve448
- {'curve25519-sha256', [{public_keys,eddh}, {curves,x25519}, {hashs,sha256}]},
- {'[email protected]', [{public_keys,eddh}, {curves,x25519}, {hashs,sha256}]},
- {'curve448-sha512', [{public_keys,eddh}, {curves,x448}, {hashs,sha512}]},
{'diffie-hellman-group-exchange-sha256', [{public_keys,dh}, {hashs,sha256}]},
{'diffie-hellman-group16-sha512', [{public_keys,dh}, {hashs,sha512}]}, % In OpenSSH 7.3.p1
{'diffie-hellman-group18-sha512', [{public_keys,dh}, {hashs,sha512}]}, % In OpenSSH 7.3.p1
{'diffie-hellman-group14-sha256', [{public_keys,dh}, {hashs,sha256}]}, % In OpenSSH 7.3.p1
+ %% https://tools.ietf.org/html/draft-ietf-curdle-ssh-curves
+ %% Secure Shell (SSH) Key Exchange Method using Curve25519 and Curve448
+ {'curve25519-sha256', [{public_keys,ecdh}, {curves,x25519}, {hashs,sha256}]},
+ {'[email protected]', [{public_keys,ecdh}, {curves,x25519}, {hashs,sha256}]},
+ {'curve448-sha512', [{public_keys,ecdh}, {curves,x448}, {hashs,sha512}]},
{'diffie-hellman-group14-sha1', [{public_keys,dh}, {hashs,sha}]},
{'diffie-hellman-group-exchange-sha1', [{public_keys,dh}, {hashs,sha}]},
{'diffie-hellman-group1-sha1', [{public_keys,dh}, {hashs,sha}]}
@@ -160,6 +157,7 @@ supported_algorithms(cipher) ->
same(
select_crypto_supported(
[
+ {'[email protected]', [{ciphers,chacha20}, {macs,poly1305}]},
{'[email protected]', [{ciphers,{aes_gcm,256}}]},
{'aes256-ctr', [{ciphers,{aes_ctr,256}}]},
{'aes192-ctr', [{ciphers,{aes_ctr,192}}]},
@@ -982,13 +980,14 @@ select_algorithm(Role, Client, Server, Opts) ->
%%% the exchanged MAC algorithms are ignored and there doesn't have to be
%%% a matching MAC.
-aead_gcm_simultan('[email protected]', _) -> {'AEAD_AES_128_GCM', 'AEAD_AES_128_GCM'};
-aead_gcm_simultan('[email protected]', _) -> {'AEAD_AES_256_GCM', 'AEAD_AES_256_GCM'};
-aead_gcm_simultan('AEAD_AES_128_GCM', _) -> {'AEAD_AES_128_GCM', 'AEAD_AES_128_GCM'};
-aead_gcm_simultan('AEAD_AES_256_GCM', _) -> {'AEAD_AES_256_GCM', 'AEAD_AES_256_GCM'};
-aead_gcm_simultan(_, 'AEAD_AES_128_GCM') -> {'AEAD_AES_128_GCM', 'AEAD_AES_128_GCM'};
-aead_gcm_simultan(_, 'AEAD_AES_256_GCM') -> {'AEAD_AES_256_GCM', 'AEAD_AES_256_GCM'};
-aead_gcm_simultan(Cipher, Mac) -> {Cipher,Mac}.
+aead_gcm_simultan('[email protected]', _) -> {'AEAD_AES_128_GCM', 'AEAD_AES_128_GCM'};
+aead_gcm_simultan('[email protected]', _) -> {'AEAD_AES_256_GCM', 'AEAD_AES_256_GCM'};
+aead_gcm_simultan('AEAD_AES_128_GCM'=C, _) -> {C, C};
+aead_gcm_simultan('AEAD_AES_256_GCM'=C, _) -> {C, C};
+aead_gcm_simultan(_, 'AEAD_AES_128_GCM'=C) -> {C, C};
+aead_gcm_simultan(_, 'AEAD_AES_256_GCM'=C) -> {C, C};
+aead_gcm_simultan('[email protected]'=C, _)-> {C, C};
+aead_gcm_simultan(Cipher, Mac) -> {Cipher,Mac}.
select_encrypt_decrypt(client, Client, Server) ->
@@ -1136,7 +1135,7 @@ pack(PlainText,
encrypt = CryptoAlg} = Ssh0, PacketLenDeviationForTests) when is_binary(PlainText) ->
{Ssh1, CompressedPlainText} = compress(Ssh0, PlainText),
- {EcryptedPacket, MAC, Ssh3} =
+ {FinalPacket, Ssh3} =
case pkt_type(CryptoAlg) of
common ->
PaddingLen = padding_length(4+1+size(CompressedPlainText), Ssh0),
@@ -1145,16 +1144,15 @@ pack(PlainText,
PlainPacketData = <<?UINT32(PlainPacketLen),?BYTE(PaddingLen), CompressedPlainText/binary, Padding/binary>>,
{Ssh2, EcryptedPacket0} = encrypt(Ssh1, PlainPacketData),
MAC0 = mac(MacAlg, MacKey, SeqNum, PlainPacketData),
- {EcryptedPacket0, MAC0, Ssh2};
+ {<<EcryptedPacket0/binary,MAC0/binary>>, Ssh2};
aead ->
PaddingLen = padding_length(1+size(CompressedPlainText), Ssh0),
Padding = ssh_bits:random(PaddingLen),
PlainPacketLen = 1 + PaddingLen + size(CompressedPlainText) + PacketLenDeviationForTests,
PlainPacketData = <<?BYTE(PaddingLen), CompressedPlainText/binary, Padding/binary>>,
- {Ssh2, {EcryptedPacket0,MAC0}} = encrypt(Ssh1, {<<?UINT32(PlainPacketLen)>>,PlainPacketData}),
- {<<?UINT32(PlainPacketLen),EcryptedPacket0/binary>>, MAC0, Ssh2}
+ {Ssh2, {EcryptedPacket0,MAC0}} = encrypt(Ssh1, <<?UINT32(PlainPacketLen),PlainPacketData/binary>>),
+ {<<EcryptedPacket0/binary,MAC0/binary>>, Ssh2}
end,
- FinalPacket = [EcryptedPacket, MAC],
Ssh = Ssh3#ssh{send_sequence = (SeqNum+1) band 16#ffffffff},
{FinalPacket, Ssh}.
@@ -1174,31 +1172,31 @@ padding_length(Size, #ssh{encrypt_block_size = BlockSize,
-handle_packet_part(<<>>, Encrypted0, undefined, #ssh{decrypt = CryptoAlg} = Ssh0) ->
+handle_packet_part(<<>>, Encrypted0, AEAD0, undefined, #ssh{decrypt = CryptoAlg} = Ssh0) ->
%% New ssh packet
case get_length(pkt_type(CryptoAlg), Encrypted0, Ssh0) of
get_more ->
%% too short to get the length
- {get_more, <<>>, Encrypted0, undefined, Ssh0};
+ {get_more, <<>>, Encrypted0, AEAD0, undefined, Ssh0};
- {ok, PacketLen, _, _, _} when PacketLen > ?SSH_MAX_PACKET_SIZE ->
+ {ok, PacketLen, _, _, _, _} when PacketLen > ?SSH_MAX_PACKET_SIZE ->
%% far too long message than expected
{error, {exceeds_max_size,PacketLen}};
- {ok, PacketLen, Decrypted, Encrypted1,
+ {ok, PacketLen, Decrypted, Encrypted1, AEAD,
#ssh{recv_mac_size = MacSize} = Ssh1} ->
%% enough bytes so we got the length and can calculate how many
%% more bytes to expect for a full packet
TotalNeeded = (4 + PacketLen + MacSize),
- handle_packet_part(Decrypted, Encrypted1, TotalNeeded, Ssh1)
+ handle_packet_part(Decrypted, Encrypted1, AEAD, TotalNeeded, Ssh1)
end;
-handle_packet_part(DecryptedPfx, EncryptedBuffer, TotalNeeded, Ssh0)
+handle_packet_part(DecryptedPfx, EncryptedBuffer, AEAD, TotalNeeded, Ssh0)
when (size(DecryptedPfx)+size(EncryptedBuffer)) < TotalNeeded ->
%% need more bytes to finalize the packet
- {get_more, DecryptedPfx, EncryptedBuffer, TotalNeeded, Ssh0};
+ {get_more, DecryptedPfx, EncryptedBuffer, AEAD, TotalNeeded, Ssh0};
-handle_packet_part(DecryptedPfx, EncryptedBuffer, TotalNeeded,
+handle_packet_part(DecryptedPfx, EncryptedBuffer, AEAD, TotalNeeded,
#ssh{recv_mac_size = MacSize,
decrypt = CryptoAlg} = Ssh0) ->
%% enough bytes to decode the packet.
@@ -1216,8 +1214,7 @@ handle_packet_part(DecryptedPfx, EncryptedBuffer, TotalNeeded,
{packet_decrypted, DecompressedPayload, NextPacketBytes, Ssh}
end;
aead ->
- PacketLenBin = DecryptedPfx,
- case decrypt(Ssh0, {PacketLenBin,EncryptedSfx,Mac}) of
+ case decrypt(Ssh0, {AEAD,EncryptedSfx,Mac}) of
{Ssh1, error} ->
{bad_mac, Ssh1};
{Ssh1, DecryptedSfx} ->
@@ -1234,21 +1231,29 @@ get_length(common, EncryptedBuffer, #ssh{decrypt_block_size = BlockSize} = Ssh0)
<<EncBlock:BlockSize/binary, EncryptedRest/binary>> = EncryptedBuffer,
{Ssh,
<<?UINT32(PacketLen),_/binary>> = Decrypted} = decrypt(Ssh0, EncBlock),
- {ok, PacketLen, Decrypted, EncryptedRest, Ssh};
+ {ok, PacketLen, Decrypted, EncryptedRest, <<>>, Ssh};
false ->
get_more
end;
+
get_length(aead, EncryptedBuffer, Ssh) ->
- case size(EncryptedBuffer) >= 4 of
- true ->
+ case {size(EncryptedBuffer) >= 4, Ssh#ssh.decrypt} of
+ {true, '[email protected]'} ->
+ <<EncryptedLen:4/binary, EncryptedRest/binary>> = EncryptedBuffer,
+ {Ssh1, PacketLenBin} = decrypt(Ssh, {length,EncryptedLen}),
+ <<?UINT32(PacketLen)>> = PacketLenBin,
+ {ok, PacketLen, PacketLenBin, EncryptedRest, EncryptedLen, Ssh1};
+ {true, _} ->
<<?UINT32(PacketLen), EncryptedRest/binary>> = EncryptedBuffer,
- {ok, PacketLen, <<?UINT32(PacketLen)>>, EncryptedRest, Ssh};
- false ->
+ {ok, PacketLen, <<?UINT32(PacketLen)>>, EncryptedRest, <<?UINT32(PacketLen)>>, Ssh};
+ {false, _} ->
get_more
end.
+
pkt_type('AEAD_AES_128_GCM') -> aead;
pkt_type('AEAD_AES_256_GCM') -> aead;
+pkt_type('[email protected]') -> aead;
pkt_type(_) -> common.
payload(<<PacketLen:32, PaddingLen:8, PayloadAndPadding/binary>>) ->
@@ -1353,11 +1358,32 @@ cipher('aes192-ctr') ->
cipher('aes256-ctr') ->
#cipher_data{key_bytes = 32,
iv_bytes = 16,
- block_bytes = 16}.
+ block_bytes = 16};
+
+cipher('[email protected]') -> % FIXME: Verify!!
+ #cipher_data{key_bytes = 32,
+ iv_bytes = 12,
+ block_bytes = 8}.
+
encrypt_init(#ssh{encrypt = none} = Ssh) ->
{ok, Ssh};
+encrypt_init(#ssh{encrypt = '[email protected]', role = client} = Ssh) ->
+ %% [email protected] uses two independent crypto streams, one (chacha20)
+ %% for the length used in stream mode, and the other (chacha20-poly1305) as AEAD for
+ %% the payload and to MAC the length||payload.
+ %% See draft-josefsson-ssh-chacha20-poly1305-openssh-00
+ <<K2:32/binary,K1:32/binary>> = hash(Ssh, "C", 512),
+ {ok, Ssh#ssh{encrypt_keys = {K1,K2}
+ % encrypt_block_size = 16, %default = 8. What to set it to? 64 (openssl chacha.h)
+ % ctx and iv is setup for each packet
+ }};
+encrypt_init(#ssh{encrypt = '[email protected]', role = server} = Ssh) ->
+ <<K2:32/binary,K1:32/binary>> = hash(Ssh, "D", 512),
+ {ok, Ssh#ssh{encrypt_keys = {K1,K2}
+ % encrypt_block_size = 16, %default = 8. What to set it to?
+ }};
encrypt_init(#ssh{encrypt = 'AEAD_AES_128_GCM', role = client} = Ssh) ->
IV = hash(Ssh, "A", 12*8),
<<K:16/binary>> = hash(Ssh, "C", 128),
@@ -1458,18 +1484,40 @@ encrypt_final(Ssh) ->
encrypt(#ssh{encrypt = none} = Ssh, Data) ->
{Ssh, Data};
+encrypt(#ssh{encrypt = '[email protected]',
+ encrypt_keys = {K1,K2},
+ send_sequence = Seq} = Ssh,
+ <<LenData:4/binary, PayloadData/binary>>) ->
+ %% Encrypt length
+ IV1 = <<0:8/unit:8, Seq:8/unit:8>>,
+ {_,EncLen} = crypto:stream_encrypt(crypto:stream_init(chacha20, K1, IV1),
+ LenData),
+ %% Encrypt payload
+ IV2 = <<1:8/little-unit:8, Seq:8/unit:8>>,
+ {_,EncPayloadData} = crypto:stream_encrypt(crypto:stream_init(chacha20, K2, IV2),
+ PayloadData),
+
+ %% MAC tag
+ {_,PolyKey} = crypto:stream_encrypt(crypto:stream_init(chacha20, K2, <<0:8/unit:8,Seq:8/unit:8>>),
+ <<0:32/unit:8>>),
+ EncBytes = <<EncLen/binary,EncPayloadData/binary>>,
+ Ctag = crypto:poly1305(PolyKey, EncBytes),
+ %% Result
+ {Ssh, {EncBytes,Ctag}};
encrypt(#ssh{encrypt = 'AEAD_AES_128_GCM',
encrypt_keys = K,
- encrypt_ctx = IV0} = Ssh, Data={_AAD,_Ptext}) ->
- Enc = {_Ctext,_Ctag} = crypto:block_encrypt(aes_gcm, K, IV0, Data),
+ encrypt_ctx = IV0} = Ssh,
+ <<LenData:4/binary, PayloadData/binary>>) ->
+ {Ctext,Ctag} = crypto:block_encrypt(aes_gcm, K, IV0, {LenData,PayloadData}),
IV = next_gcm_iv(IV0),
- {Ssh#ssh{encrypt_ctx = IV}, Enc};
+ {Ssh#ssh{encrypt_ctx = IV}, {<<LenData/binary,Ctext/binary>>,Ctag}};
encrypt(#ssh{encrypt = 'AEAD_AES_256_GCM',
encrypt_keys = K,
- encrypt_ctx = IV0} = Ssh, Data={_AAD,_Ptext}) ->
- Enc = {_Ctext,_Ctag} = crypto:block_encrypt(aes_gcm, K, IV0, Data),
+ encrypt_ctx = IV0} = Ssh,
+ <<LenData:4/binary, PayloadData/binary>>) ->
+ {Ctext,Ctag} = crypto:block_encrypt(aes_gcm, K, IV0, {LenData,PayloadData}),
IV = next_gcm_iv(IV0),
- {Ssh#ssh{encrypt_ctx = IV}, Enc};
+ {Ssh#ssh{encrypt_ctx = IV}, {<<LenData/binary,Ctext/binary>>,Ctag}};
encrypt(#ssh{encrypt = '3des-cbc',
encrypt_keys = {K1,K2,K3},
encrypt_ctx = IV0} = Ssh, Data) ->
@@ -1502,6 +1550,14 @@ encrypt(#ssh{encrypt = 'aes256-ctr',
decrypt_init(#ssh{decrypt = none} = Ssh) ->
{ok, Ssh};
+decrypt_init(#ssh{decrypt = '[email protected]', role = client} = Ssh) ->
+ <<K2:32/binary,K1:32/binary>> = hash(Ssh, "D", 512),
+ {ok, Ssh#ssh{decrypt_keys = {K1,K2}
+ }};
+decrypt_init(#ssh{decrypt = '[email protected]', role = server} = Ssh) ->
+ <<K2:32/binary,K1:32/binary>> = hash(Ssh, "C", 512),
+ {ok, Ssh#ssh{decrypt_keys = {K1,K2}
+ }};
decrypt_init(#ssh{decrypt = 'AEAD_AES_128_GCM', role = client} = Ssh) ->
IV = hash(Ssh, "B", 12*8),
<<K:16/binary>> = hash(Ssh, "D", 128),
@@ -1602,6 +1658,31 @@ decrypt_final(Ssh) ->
decrypt(Ssh, <<>>) ->
{Ssh, <<>>};
+decrypt(#ssh{decrypt = '[email protected]',
+ decrypt_keys = {K1,_K2},
+ recv_sequence = Seq} = Ssh, {length,EncryptedLen}) ->
+ {_State,PacketLenBin} =
+ crypto:stream_decrypt(crypto:stream_init(chacha20, K1, <<0:8/unit:8, Seq:8/unit:8>>),
+ EncryptedLen),
+ {Ssh, PacketLenBin};
+decrypt(#ssh{decrypt = '[email protected]',
+ decrypt_keys = {_K1,K2},
+ recv_sequence = Seq} = Ssh, {AAD,Ctext,Ctag}) ->
+ %% The length is already decoded and used to divide the input
+ %% Check the mac (important that it is timing-safe):
+ {_,PolyKey} =
+ crypto:stream_encrypt(crypto:stream_init(chacha20, K2, <<0:8/unit:8,Seq:8/unit:8>>),
+ <<0:32/unit:8>>),
+ case equal_const_time(Ctag, crypto:poly1305(PolyKey, <<AAD/binary,Ctext/binary>>)) of
+ true ->
+ %% MAC is ok, decode
+ IV2 = <<1:8/little-unit:8, Seq:8/unit:8>>,
+ {_,PlainText} =
+ crypto:stream_decrypt(crypto:stream_init(chacha20,K2,IV2), Ctext),
+ {Ssh, PlainText};
+ false ->
+ {Ssh,error}
+ end;
decrypt(#ssh{decrypt = none} = Ssh, Data) ->
{Ssh, Data};
decrypt(#ssh{decrypt = 'AEAD_AES_128_GCM',
@@ -1744,7 +1825,7 @@ send_mac_init(SSH) ->
Key = hash(SSH, "F", KeySize),
{ok, SSH#ssh { send_mac_key = Key }}
end;
- aead ->
+ _ ->
%% Not applicable
{ok, SSH}
end.
@@ -1765,7 +1846,7 @@ recv_mac_init(SSH) ->
Key = hash(SSH, "E", 8*mac_key_bytes(SSH#ssh.recv_mac)),
{ok, SSH#ssh { recv_mac_key = Key }}
end;
- aead ->
+ _ ->
%% Not applicable
{ok, SSH}
end.
@@ -1812,6 +1893,7 @@ hash(K, H, Ki, N, HashAlg) ->
kex_hash(SSH, Key, HashAlg, Args) ->
crypto:hash(HashAlg, kex_plaintext(SSH,Key,Args)).
+
kex_plaintext(SSH, Key, Args) ->
EncodedKey = public_key:ssh_encode(Key, ssh2_pubkey),
<<?Estring(SSH#ssh.c_version), ?Estring(SSH#ssh.s_version),
@@ -1819,8 +1901,13 @@ kex_plaintext(SSH, Key, Args) ->
?Ebinary(EncodedKey),
(kex_alg_dependent(Args))/binary>>.
+
+kex_alg_dependent({Q_c, Q_s, K}) when is_binary(Q_c), is_binary(Q_s) ->
+ %% ecdh
+ <<?Ebinary(Q_c), ?Ebinary(Q_s), ?Empint(K)>>;
+
kex_alg_dependent({E, F, K}) ->
- %% diffie-hellman and ec diffie-hellman (with E = Q_c, F = Q_s)
+ %% diffie-hellman
<<?Empint(E), ?Empint(F), ?Empint(K)>>;
kex_alg_dependent({-1, NBits, -1, Prime, Gen, E, F, K}) ->
@@ -1905,6 +1992,7 @@ mac_key_bytes('hmac-sha2-256')-> 32;
mac_key_bytes('hmac-sha2-512')-> 64;
mac_key_bytes('AEAD_AES_128_GCM') -> 0;
mac_key_bytes('AEAD_AES_256_GCM') -> 0;
+mac_key_bytes('[email protected]') -> 0;
mac_key_bytes(none) -> 0.
mac_digest_size('hmac-sha1') -> 20;
@@ -1915,6 +2003,7 @@ mac_digest_size('hmac-sha2-256') -> 32;
mac_digest_size('hmac-sha2-512') -> 64;
mac_digest_size('AEAD_AES_128_GCM') -> 16;
mac_digest_size('AEAD_AES_256_GCM') -> 16;
+mac_digest_size('[email protected]') -> 16;
mac_digest_size(none) -> 0.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1937,11 +2026,13 @@ parallell_gen_key(Ssh = #ssh{keyex_key = {x, {G, P}},
Ssh#ssh{keyex_key = {{Private, Public}, {G, P}}}.
+generate_key(ecdh = Algorithm, Args) ->
+ crypto:generate_key(Algorithm, Args);
generate_key(Algorithm, Args) ->
{Public,Private} = crypto:generate_key(Algorithm, Args),
{crypto:bytes_to_integer(Public), crypto:bytes_to_integer(Private)}.
-
+
compute_key(Algorithm, OthersPublic, MyPrivate, Args) ->
Shared = crypto:compute_key(Algorithm, OthersPublic, MyPrivate, Args),
crypto:bytes_to_integer(Shared).
@@ -2026,6 +2117,20 @@ same(Algs) -> [{client2server,Algs}, {server2client,Algs}].
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%% Compare two binaries in a timing safe maner.
+%%% The time spent in comparing should not be different depending on where in the binaries they differ.
+%%% This is to avoid a certain side-channel attac.
+equal_const_time(X1, X2) -> equal_const_time(X1, X2, true).
+
+equal_const_time(<<B1,R1/binary>>, <<B2,R2/binary>>, Truth) ->
+ equal_const_time(R1, R2, Truth and (B1 == B2));
+equal_const_time(<<>>, <<>>, Truth) ->
+ Truth;
+equal_const_time(_, _, _) ->
+ false.
+
+%%%-------- Remove CR, LF and following characters from a line
+
trim_tail(Str) ->
lists:takewhile(fun(C) ->
C=/=$\r andalso C=/=$\n
diff --git a/lib/ssh/src/ssh_xfer.erl b/lib/ssh/src/ssh_xfer.erl
index 7bb9c2d101..1d77ccb311 100644
--- a/lib/ssh/src/ssh_xfer.erl
+++ b/lib/ssh/src/ssh_xfer.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/ssh/test/ssh_bench_SUITE.erl b/lib/ssh/test/ssh_bench_SUITE.erl
index b6c6147646..764c52b624 100644
--- a/lib/ssh/test/ssh_bench_SUITE.erl
+++ b/lib/ssh/test/ssh_bench_SUITE.erl
@@ -1,7 +1,7 @@
%%%-------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -65,10 +65,10 @@ init_per_suite(Config) ->
{preferred_algorithms, Algs},
{modify_algorithms,[{prepend,[{cipher,[none]},
{mac,[none]}
- ]},
- {rm, [{cipher,['[email protected]',
- ]}
+ ]}
+ %% ,{rm, [{cipher,['[email protected]',
+ %% ]}
]},
{max_random_length_padding, 0},
{subsystems, [{"/dev/null", {ssh_bench_dev_null,[DataSize]}}]}
@@ -152,7 +152,8 @@ transfer_text(Config) ->
|| {Crypto,Mac} <- [{ none, none},
{'aes128-ctr', 'hmac-sha1'},
{'aes256-ctr', 'hmac-sha1'},
-%% {'[email protected]', 'hmac-sha1'},
+{'[email protected]', 'hmac-sha1'},
+{'[email protected]', 'hmac-sha1'},
{'aes128-cbc', 'hmac-sha1'},
{'3des-cbc', 'hmac-sha1'},
{'aes128-ctr', 'hmac-sha2-256'},
@@ -182,29 +183,31 @@ gen_data(DataSz) ->
%% {suite, ?MODULE},
%% {name, mk_name(["Transfer 1M bytes ",Cipher,"/",Mac," [µs]"])}]);
connect_measure(Port, Cipher, Mac, Data, Options) ->
- AES_GCM = {cipher,['[email protected]',
+ AES_GCM = {cipher,
+ []},
AlgOpt = case {Cipher,Mac} of
{none,none} ->
[{modify_algorithms,[{prepend, [{cipher,[Cipher]},
- {mac,[Mac]}]},
- {rm,[AES_GCM]}
+ {mac,[Mac]}]}
+%%% ,{rm,[AES_GCM]}
]}];
{none,_} ->
- [{modify_algorithms,[{prepend, [{cipher,[Cipher]}]},
- {rm,[AES_GCM]}
+ [{modify_algorithms,[{prepend, [{cipher,[Cipher]}]}
+%%% ,{rm,[AES_GCM]}
]},
{preferred_algorithms, [{mac,[Mac]}]}];
{_,none} ->
- [{modify_algorithms,[{prepend, [{mac,[Mac]}]},
- {rm,[AES_GCM]}
+ [{modify_algorithms,[{prepend, [{mac,[Mac]}]}
+%%% ,{rm,[AES_GCM]}
]},
{preferred_algorithms, [{cipher,[Cipher]}]}];
_ ->
[{preferred_algorithms, [{cipher,[Cipher]},
- {mac,[Mac]}]},
- {modify_algorithms, [{rm,[AES_GCM]}]}
+ {mac,[Mac]}]}
+%%% ,{modify_algorithms, [{rm,[AES_GCM]}]}
]
end,
Times =
diff --git a/lib/ssh/vsn.mk b/lib/ssh/vsn.mk
index c3572b5b70..ae7b4cf3f2 100644
--- a/lib/ssh/vsn.mk
+++ b/lib/ssh/vsn.mk
@@ -1,4 +1,4 @@
#-*-makefile-*- ; force emacs to enter makefile-mode
-SSH_VSN = 4.7
+SSH_VSN = 4.7.1
APP_VSN = "ssh-$(SSH_VSN)"
diff --git a/lib/ssl/doc/src/Makefile b/lib/ssl/doc/src/Makefile
index d459463322..c72b6d6cc4 100644
--- a/lib/ssl/doc/src/Makefile
+++ b/lib/ssl/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1999-2017. All Rights Reserved.
+# Copyright Ericsson AB 1999-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml
index 87bf25452f..c54acfcf53 100644
--- a/lib/ssl/doc/src/notes.xml
+++ b/lib/ssl/doc/src/notes.xml
@@ -27,6 +27,140 @@
</header>
<p>This document describes the changes made to the SSL application.</p>
+<section><title>SSL 9.0.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Use separate processes for sending and receiving
+ application data for TLS connections to avoid potential
+ deadlock that was most likely to occur when using TLS for
+ Erlang distribution. Note does not change the API.</p>
+ <p>
+ Own Id: OTP-15122</p>
+ </item>
+ <item>
+ <p>
+ Correct handling of empty server SNI extension</p>
+ <p>
+ Own Id: OTP-15168</p>
+ </item>
+ <item>
+ <p>
+ Correct PSK cipher suite handling and add
+ selected_cipher_suite to connection information</p>
+ <p>
+ Own Id: OTP-15172</p>
+ </item>
+ <item>
+ <p>
+ Adopt to the fact that cipher suite sign restriction are
+ relaxed in TLS-1.2</p>
+ <p>
+ Own Id: OTP-15173</p>
+ </item>
+ <item>
+ <p>
+ Enhance error handling of non existing PEM files</p>
+ <p>
+ Own Id: OTP-15174</p>
+ </item>
+ <item>
+ <p>
+ Correct close handling of transport accepted sockets in
+ the error state</p>
+ <p>
+ Own Id: OTP-15216</p>
+ </item>
+ <item>
+ <p>
+ Correct PEM cache to not add references to empty entries
+ when PEM file does not exist.</p>
+ <p>
+ Own Id: OTP-15224</p>
+ </item>
+ <item>
+ <p>
+ Correct handling of all PSK cipher suites</p>
+ <p>
+ Before only some PSK suites would be correctly negotiated
+ and most PSK ciphers suites would fail the connection.</p>
+ <p>
+ Own Id: OTP-15285</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ TLS will now try to order certificate chains if they
+ appear to be unordered. That is prior to TLS 1.3,
+ “certificate_list” ordering was required to be
+ strict, however some implementations already allowed for
+ some flexibility. For maximum compatibility, all
+ implementations SHOULD be prepared to handle potentially
+ extraneous certificates and arbitrary orderings from any
+ TLS version.</p>
+ <p>
+ Own Id: OTP-12983</p>
+ </item>
+ <item>
+ <p>
+ TLS will now try to reconstructed an incomplete
+ certificate chains from its local CA-database and use
+ that data for the certificate path validation. This
+ especially makes sense for partial chains as then the
+ peer might not send an intermediate CA as it is
+ considered the trusted root in that case.</p>
+ <p>
+ Own Id: OTP-15060</p>
+ </item>
+ <item>
+ <p>
+ Option keyfile defaults to certfile and should be trumped
+ with key. This failed for engine keys.</p>
+ <p>
+ Own Id: OTP-15193</p>
+ </item>
+ <item>
+ <p>
+ Error message improvement when own certificate has
+ decoding issues, see also issue ERL-668.</p>
+ <p>
+ Own Id: OTP-15234</p>
+ </item>
+ <item>
+ <p>
+ Correct dialyzer spec for key option</p>
+ <p>
+ Own Id: OTP-15281</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>SSL 9.0.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Correct cipher suite handling for ECDHE_*, the incorrect
+ handling could cause an incorrrect suite to be selected
+ and most likly fail the handshake.</p>
+ <p>
+ Own Id: OTP-15203</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>SSL 9.0</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/ssl/examples/src/client_server.erl b/lib/ssl/examples/src/client_server.erl
index 7a266f544d..8d68da12d5 100644
--- a/lib/ssl/examples/src/client_server.erl
+++ b/lib/ssl/examples/src/client_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/ssl/src/Makefile b/lib/ssl/src/Makefile
index 1db18d4e5a..af36d04a99 100644
--- a/lib/ssl/src/Makefile
+++ b/lib/ssl/src/Makefile
@@ -44,8 +44,6 @@ BEHAVIOUR_MODULES= \
MODULES= \
ssl \
- tls \
- dtls \
ssl_alert \
ssl_app \
ssl_sup \
@@ -64,12 +62,15 @@ MODULES= \
ssl_certificate\
ssl_pkix_db\
ssl_cipher \
+ ssl_cipher_format \
ssl_srp_primes \
tls_connection \
dtls_connection \
+ tls_sender\
ssl_config \
ssl_connection \
tls_handshake \
+ tls_handshake_1_3\
dtls_handshake\
ssl_handshake\
ssl_manager \
@@ -92,8 +93,9 @@ MODULES= \
INTERNAL_HRL_FILES = \
ssl_alert.hrl ssl_cipher.hrl \
tls_connection.hrl dtls_connection.hrl ssl_connection.hrl \
- ssl_handshake.hrl tls_handshake.hrl dtls_handshake.hrl ssl_api.hrl ssl_internal.hrl \
- ssl_record.hrl tls_record.hrl dtls_record.hrl ssl_srp.hrl
+ ssl_handshake.hrl tls_handshake.hrl tls_handshake_1_3.hrl dtls_handshake.hrl \
+ ssl_api.hrl ssl_internal.hrl \
+ ssl_record.hrl tls_record.hrl dtls_record.hrl ssl_srp.hrl
ERL_FILES= \
$(MODULES:%=%.erl) \
@@ -170,6 +172,7 @@ $(EBIN)/tls_connection.$(EMULATOR): ssl_internal.hrl tls_connection.hrl tls_reco
$(EBIN)/dtls_connection.$(EMULATOR): ssl_internal.hrl dtls_connection.hrl dtls_record.hrl ssl_cipher.hrl dtls_handshake.hrl ssl_alert.hrl ../../public_key/include/public_key.hrl
$(EBIN)/tls_handshake.$(EMULATOR): ssl_internal.hrl tls_record.hrl ssl_cipher.hrl tls_handshake.hrl ssl_alert.hrl ../../public_key/include/public_key.hrl
$(EBIN)/tls_handshake.$(EMULATOR): ssl_internal.hrl ssl_connection.hrl ssl_record.hrl ssl_cipher.hrl ssl_handshake.hrl ssl_alert.hrl ../../public_key/include/public_key.hrl
+$(EBIN)/tls_handshake_1_3.$(EMULATOR): tls_handshake_1_3.hrl tls_handshake.hrl ssl_internal.hrl
$(EBIN)/ssl_manager.$(EMULATOR): ssl_internal.hrl ssl_handshake.hrl ../../kernel/include/file.hrl
$(EBIN)/ssl_record.$(EMULATOR): ssl_internal.hrl ssl_record.hrl ssl_cipher.hrl ssl_handshake.hrl ssl_alert.hrl
$(EBIN)/ssl_session.$(EMULATOR): ssl_internal.hrl ssl_handshake.hrl
diff --git a/lib/ssl/src/dtls.erl b/lib/ssl/src/dtls.erl
deleted file mode 100644
index cd705152a8..0000000000
--- a/lib/ssl/src/dtls.erl
+++ /dev/null
@@ -1,113 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-
-%%% Purpose : Reflect DTLS specific API options (fairly simple wrapper at the moment)
-%% First implementation will support DTLS connections only in a "TLS/TCP like way"
-
--module(dtls).
-
--include("ssl_api.hrl").
--include("ssl_internal.hrl").
-
--export([connect/2, connect/3, listen/2, accept/1, accept/2,
- handshake/1, handshake/2, handshake/3]).
-
-%%--------------------------------------------------------------------
-%%
-%% Description: Connect to a DTLS server.
-%%--------------------------------------------------------------------
-
--spec connect(host() | port(), [connect_option()]) -> {ok, #sslsocket{}} |
- {error, reason()}.
-
-connect(Socket, Options) when is_port(Socket) ->
- connect(Socket, Options, infinity).
-
--spec connect(host() | port(), [connect_option()] | inet:port_number(),
- timeout() | list()) ->
- {ok, #sslsocket{}} | {error, reason()}.
-
-connect(Socket, SslOptions, Timeout) when is_port(Socket) ->
- DTLSOpts = [{protocol, dtls} | SslOptions],
- ssl:connect(Socket, DTLSOpts, Timeout);
-connect(Host, Port, Options) ->
- connect(Host, Port, Options, infinity).
-
--spec connect(host() | port(), inet:port_number(), list(), timeout()) ->
- {ok, #sslsocket{}} | {error, reason()}.
-
-connect(Host, Port, Options, Timeout) ->
- DTLSOpts = [{protocol, dtls} | Options],
- ssl:connect(Host, Port, DTLSOpts, Timeout).
-
-%%--------------------------------------------------------------------
--spec listen(inet:port_number(), [listen_option()]) ->{ok, #sslsocket{}} | {error, reason()}.
-
-%%
-%% Description: Creates an ssl listen socket.
-%%--------------------------------------------------------------------
-listen(Port, Options) ->
- DTLSOpts = [{protocol, dtls} | Options],
- ssl:listen(Port, DTLSOpts).
-
-%%--------------------------------------------------------------------
-%%
-%% Description: Performs transport accept on an ssl listen socket
-%%--------------------------------------------------------------------
--spec accept(#sslsocket{}) -> {ok, #sslsocket{}} |
- {error, reason()}.
-accept(ListenSocket) ->
- accept(ListenSocket, infinity).
-
--spec accept(#sslsocket{}, timeout()) -> {ok, #sslsocket{}} |
- {error, reason()}.
-accept(Socket, Timeout) ->
- ssl:transport_accept(Socket, Timeout).
-
-%%--------------------------------------------------------------------
-%%
-%% Description: Performs accept on an ssl listen socket. e.i. performs
-%% ssl handshake.
-%%--------------------------------------------------------------------
-
--spec handshake(#sslsocket{}) -> ok | {error, reason()}.
-
-handshake(ListenSocket) ->
- handshake(ListenSocket, infinity).
-
-
--spec handshake(#sslsocket{} | port(), timeout()| [ssl_option()
- | transport_option()]) ->
- ok | {ok, #sslsocket{}} | {error, reason()}.
-
-handshake(#sslsocket{} = Socket, Timeout) ->
- ssl:ssl_accept(Socket, Timeout);
-
-handshake(ListenSocket, SslOptions) when is_port(ListenSocket) ->
- handshake(ListenSocket, SslOptions, infinity).
-
-
--spec handshake(port(), [ssl_option()| transport_option()], timeout()) ->
- {ok, #sslsocket{}} | {error, reason()}.
-
-handshake(Socket, SslOptions, Timeout) when is_port(Socket) ->
- ssl:ssl_accept(Socket, SslOptions, Timeout).
diff --git a/lib/ssl/src/dtls_connection.erl b/lib/ssl/src/dtls_connection.erl
index c0e81d6a28..b05e4b7f24 100644
--- a/lib/ssl/src/dtls_connection.erl
+++ b/lib/ssl/src/dtls_connection.erl
@@ -37,7 +37,7 @@
%% Internal application API
%% Setup
--export([start_fsm/8, start_link/7, init/1]).
+-export([start_fsm/8, start_link/7, init/1, pids/1]).
%% State transition handling
-export([next_record/1, next_event/3, next_event/4, handle_common_event/4]).
@@ -45,10 +45,10 @@
%% Handshake handling
-export([renegotiate/2, send_handshake/2,
queue_handshake/2, queue_change_cipher/2,
- reinit_handshake_data/1, select_sni_extension/1, empty_connection_state/2]).
+ reinit/1, reinit_handshake_data/1, select_sni_extension/1, empty_connection_state/2]).
%% Alert and close handling
--export([encode_alert/3,send_alert/2, close/5, protocol_name/0]).
+-export([encode_alert/3, send_alert/2, send_alert_in_connection/2, close/5, protocol_name/0]).
%% Data handling
-export([encode_data/3, passive_receive/2, next_record_if_active/1,
@@ -73,7 +73,7 @@ start_fsm(Role, Host, Port, Socket, {#ssl_options{erl_dist = false},_, Tracker}
try
{ok, Pid} = dtls_connection_sup:start_child([Role, Host, Port, Socket,
Opts, User, CbInfo]),
- {ok, SslSocket} = ssl_connection:socket_control(?MODULE, Socket, Pid, CbModule, Tracker),
+ {ok, SslSocket} = ssl_connection:socket_control(?MODULE, Socket, [Pid], CbModule, Tracker),
ssl_connection:handshake(SslSocket, Timeout)
catch
error:{badmatch, {error, _} = Error} ->
@@ -101,6 +101,10 @@ init([Role, Host, Port, Socket, Options, User, CbInfo]) ->
EState = State0#state{protocol_specific = Map#{error => Error}},
gen_statem:enter_loop(?MODULE, [], error, EState)
end.
+
+pids(_) ->
+ [self()].
+
%%====================================================================
%% State transition handling
%%====================================================================
@@ -329,10 +333,14 @@ queue_change_cipher(ChangeCipher, #state{flight_buffer = Flight,
dtls_record:next_epoch(ConnectionStates0, write),
State#state{flight_buffer = Flight#{change_cipher_spec => ChangeCipher},
connection_states = ConnectionStates}.
+
+reinit(State) ->
+ %% To be API compatible with TLS NOOP here
+ reinit_handshake_data(State).
reinit_handshake_data(#state{protocol_buffers = Buffers} = State) ->
State#state{premaster_secret = undefined,
public_key_info = undefined,
- tls_handshake_history = ssl_handshake:init_handshake_history(),
+ tls_handshake_history = ssl_handshake:init_handshake_history(),
flight_state = {retransmit, ?INITIAL_RETRANSMIT_TIMEOUT},
flight_buffer = new_flight(),
protocol_buffers =
@@ -366,6 +374,10 @@ send_alert(Alert, #state{negotiated_version = Version,
send(Transport, Socket, BinMsg),
State0#state{connection_states = ConnectionStates}.
+send_alert_in_connection(Alert, State) ->
+ _ = send_alert(Alert, State),
+ ok.
+
close(downgrade, _,_,_,_) ->
ok;
%% Other
@@ -711,6 +723,12 @@ connection(internal, #client_hello{}, #state{role = server, allow_renegotiate =
State1 = send_alert(Alert, State0),
{Record, State} = ssl_connection:prepare_connection(State1, ?MODULE),
next_event(?FUNCTION_NAME, Record, State);
+connection({call, From}, {application_data, Data}, State) ->
+ try
+ send_application_data(Data, From, ?FUNCTION_NAME, State)
+ catch throw:Error ->
+ ssl_connection:hibernate_after(?FUNCTION_NAME, State, [{reply, From, Error}])
+ end;
connection(Type, Event, State) ->
ssl_connection:?FUNCTION_NAME(Type, Event, State, ?MODULE).
@@ -1132,3 +1150,42 @@ log_ignore_alert(debug, StateName, Alert, Role) ->
[Role, StateName, Txt]);
log_ignore_alert(_, _, _, _) ->
ok.
+
+send_application_data(Data, From, _StateName,
+ #state{socket = Socket,
+ negotiated_version = Version,
+ protocol_cb = Connection,
+ transport_cb = Transport,
+ connection_states = ConnectionStates0,
+ ssl_options = #ssl_options{renegotiate_at = RenegotiateAt}} = State0) ->
+
+ case time_to_renegotiate(Data, ConnectionStates0, RenegotiateAt) of
+ true ->
+ renegotiate(State0#state{renegotiation = {true, internal}},
+ [{next_event, {call, From}, {application_data, Data}}]);
+ false ->
+ {Msgs, ConnectionStates} =
+ Connection:encode_data(Data, Version, ConnectionStates0),
+ State = State0#state{connection_states = ConnectionStates},
+ case Connection:send(Transport, Socket, Msgs) of
+ ok ->
+ ssl_connection:hibernate_after(connection, State, [{reply, From, ok}]);
+ Result ->
+ ssl_connection:hibernate_after(connection, State, [{reply, From, Result}])
+ end
+ end.
+
+time_to_renegotiate(_Data,
+ #{current_write := #{sequence_number := Num}},
+ RenegotiateAt) ->
+
+ %% We could do test:
+ %% is_time_to_renegotiate((erlang:byte_size(_Data) div
+ %% ?MAX_PLAIN_TEXT_LENGTH) + 1, RenegotiateAt), but we chose to
+ %% have a some what lower renegotiateAt and a much cheaper test
+ is_time_to_renegotiate(Num, RenegotiateAt).
+
+is_time_to_renegotiate(N, M) when N < M->
+ false;
+is_time_to_renegotiate(_,_) ->
+ true.
diff --git a/lib/ssl/src/dtls_handshake.erl b/lib/ssl/src/dtls_handshake.erl
index 35c213a182..3f70eaec8a 100644
--- a/lib/ssl/src/dtls_handshake.erl
+++ b/lib/ssl/src/dtls_handshake.erl
@@ -194,7 +194,7 @@ handle_client_hello(Version,
no_suite ->
?ALERT_REC(?FATAL, ?INSUFFICIENT_SECURITY);
_ ->
- #{key_exchange := KeyExAlg} = ssl_cipher:suite_definition(CipherSuite),
+ #{key_exchange := KeyExAlg} = ssl_cipher_format:suite_definition(CipherSuite),
case ssl_handshake:select_hashsign(ClientHashSigns, Cert, KeyExAlg,
SupportedHashSigns, TLSVersion) of
#alert{} = Alert ->
diff --git a/lib/ssl/src/dtls_handshake.hrl b/lib/ssl/src/dtls_handshake.hrl
index 50e92027d2..a16489bbd1 100644
--- a/lib/ssl/src/dtls_handshake.hrl
+++ b/lib/ssl/src/dtls_handshake.hrl
@@ -56,4 +56,11 @@
fragment
}).
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% RFC 7764 Datagram Transport Layer Security (DTLS) Extension to Establish Keys
+%% for the Secure Real-time Transport Protocol (SRTP)
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Not supported
+-define(USE_SRTP, 14).
+
-endif. % -ifdef(dtls_handshake).
diff --git a/lib/ssl/src/dtls_socket.erl b/lib/ssl/src/dtls_socket.erl
index b26d3ae41a..2001afd02f 100644
--- a/lib/ssl/src/dtls_socket.erl
+++ b/lib/ssl/src/dtls_socket.erl
@@ -48,7 +48,7 @@ accept(dtls, #config{transport_info = {Transport,_,_,_},
dtls_handler = {Listner, _}}, _Timeout) ->
case dtls_packet_demux:accept(Listner, self()) of
{ok, Pid, Socket} ->
- {ok, socket(Pid, Transport, {Listner, Socket}, ConnectionCb)};
+ {ok, socket([Pid], Transport, {Listner, Socket}, ConnectionCb)};
{error, Reason} ->
{error, Reason}
end.
@@ -73,12 +73,12 @@ close(gen_udp, {_Client, _Socket}) ->
close(Transport, {_Client, Socket}) ->
Transport:close(Socket).
-socket(Pid, gen_udp = Transport, {{_, _}, Socket}, ConnectionCb) ->
- #sslsocket{pid = Pid,
+socket(Pids, gen_udp = Transport, {{_, _}, Socket}, ConnectionCb) ->
+ #sslsocket{pid = Pids,
%% "The name "fd" is keept for backwards compatibility
fd = {Transport, Socket, ConnectionCb}};
-socket(Pid, Transport, Socket, ConnectionCb) ->
- #sslsocket{pid = Pid,
+socket(Pids, Transport, Socket, ConnectionCb) ->
+ #sslsocket{pid = Pids,
%% "The name "fd" is keept for backwards compatibility
fd = {Transport, Socket, ConnectionCb}}.
setopts(_, #sslsocket{pid = {dtls, #config{dtls_handler = {ListenPid, _}}}}, Options) ->
diff --git a/lib/ssl/src/dtls_v1.erl b/lib/ssl/src/dtls_v1.erl
index df687f579b..b365961a6a 100644
--- a/lib/ssl/src/dtls_v1.erl
+++ b/lib/ssl/src/dtls_v1.erl
@@ -27,22 +27,22 @@
-define(COOKIE_BASE_TIMEOUT, 30000).
--spec suites(Minor:: 253|255) -> [ssl_cipher:cipher_suite()].
+-spec suites(Minor:: 253|255) -> [ssl_cipher_format:cipher_suite()].
suites(Minor) ->
lists:filter(fun(Cipher) ->
- is_acceptable_cipher(ssl_cipher:suite_definition(Cipher))
+ is_acceptable_cipher(ssl_cipher_format:suite_definition(Cipher))
end,
tls_v1:suites(corresponding_minor_tls_version(Minor))).
all_suites(Version) ->
lists:filter(fun(Cipher) ->
- is_acceptable_cipher(ssl_cipher:suite_definition(Cipher))
+ is_acceptable_cipher(ssl_cipher_format:suite_definition(Cipher))
end,
ssl_cipher:all_suites(corresponding_tls_version(Version))).
anonymous_suites(Version) ->
lists:filter(fun(Cipher) ->
- is_acceptable_cipher(ssl_cipher:suite_definition(Cipher))
+ is_acceptable_cipher(ssl_cipher_format:suite_definition(Cipher))
end,
ssl_cipher:anonymous_suites(corresponding_tls_version(Version))).
diff --git a/lib/ssl/src/inet_tls_dist.erl b/lib/ssl/src/inet_tls_dist.erl
index 1194f4fc72..7f1a77f601 100644
--- a/lib/ssl/src/inet_tls_dist.erl
+++ b/lib/ssl/src/inet_tls_dist.erl
@@ -70,14 +70,14 @@ is_node_name(Node) ->
%% -------------------------------------------------------------------------
-hs_data_common(#sslsocket{pid = DistCtrl} = SslSocket) ->
+hs_data_common(#sslsocket{pid = [_, DistCtrl|_]} = SslSocket) ->
#hs_data{
f_send =
- fun (Ctrl, Packet) when Ctrl == DistCtrl ->
+ fun (_Ctrl, Packet) ->
f_send(SslSocket, Packet)
end,
f_recv =
- fun (Ctrl, Length, Timeout) when Ctrl == DistCtrl ->
+ fun (_, Length, Timeout) ->
f_recv(SslSocket, Length, Timeout)
end,
f_setopts_pre_nodeup =
@@ -176,8 +176,7 @@ mf_getopts(SslSocket, Opts) ->
ssl:getopts(SslSocket, Opts).
f_handshake_complete(DistCtrl, Node, DHandle) ->
- ssl_connection:handshake_complete(DistCtrl, Node, DHandle).
-
+ tls_sender:dist_handshake_complete(DistCtrl, Node, DHandle).
setopts_filter(Opts) ->
[Opt || {K,_} = Opt <- Opts,
@@ -245,7 +244,7 @@ accept_loop(Driver, Listen, Kernel, Socket) ->
trace([{active, false},{packet, 4}|Opts]),
net_kernel:connecttime())
of
- {ok, #sslsocket{pid = DistCtrl} = SslSocket} ->
+ {ok, #sslsocket{pid = [_, DistCtrl| _]} = SslSocket} ->
trace(
Kernel !
{accept, self(), DistCtrl,
@@ -405,7 +404,7 @@ gen_accept_connection(
do_accept(
_Driver, AcceptPid, DistCtrl, MyNode, Allowed, SetupTime, Kernel) ->
- SslSocket = ssl_connection:get_sslsocket(DistCtrl),
+ {ok, SslSocket} = tls_sender:dist_tls_socket(DistCtrl),
receive
{AcceptPid, controller} ->
Timer = dist_util:start_timer(SetupTime),
@@ -530,7 +529,7 @@ do_setup_connect(Driver, Kernel, Node, Address, Ip, TcpPort, Version, Type, MyNo
[binary, {active, false}, {packet, 4},
Driver:family(), nodelay()] ++ Opts,
net_kernel:connecttime()) of
- {ok, #sslsocket{pid = DistCtrl} = SslSocket} ->
+ {ok, #sslsocket{pid = [_, DistCtrl| _]} = SslSocket} ->
_ = monitor_pid(DistCtrl),
ok = ssl:controlling_process(SslSocket, self()),
HSData0 = hs_data_common(SslSocket),
diff --git a/lib/ssl/src/ssl.app.src b/lib/ssl/src/ssl.app.src
index 9679ea4687..17173d7c79 100644
--- a/lib/ssl/src/ssl.app.src
+++ b/lib/ssl/src/ssl.app.src
@@ -5,11 +5,13 @@
%% TLS/SSL
tls_connection,
tls_handshake,
+ tls_handshake_1_3,
tls_record,
tls_socket,
tls_v1,
ssl_v3,
tls_connection_sup,
+ tls_sender,
%% DTLS
dtls_connection,
dtls_handshake,
@@ -21,8 +23,6 @@
dtls_listener_sup,
%% API
ssl, %% Main API
- tls, %% TLS specific
- dtls, %% DTLS specific
ssl_session_cache_api,
%% Both TLS/SSL and DTLS
ssl_config,
@@ -30,6 +30,7 @@
ssl_handshake,
ssl_record,
ssl_cipher,
+ ssl_cipher_format,
ssl_srp_primes,
ssl_alert,
ssl_listen_tracker_sup, %% may be used by DTLS over SCTP
diff --git a/lib/ssl/src/ssl.appup.src b/lib/ssl/src/ssl.appup.src
index bfdd0c205b..ae4d60b6ed 100644
--- a/lib/ssl/src/ssl.appup.src
+++ b/lib/ssl/src/ssl.appup.src
@@ -1,6 +1,7 @@
%% -*- erlang -*-
{"%VSN%",
- [
+[
+ {<<"9\\..*">>, [{restart_application, ssl}]},
{<<"8\\..*">>, [{restart_application, ssl}]},
{<<"7\\..*">>, [{restart_application, ssl}]},
{<<"6\\..*">>, [{restart_application, ssl}]},
@@ -9,6 +10,7 @@
{<<"3\\..*">>, [{restart_application, ssl}]}
],
[
+ {<<"9\\..*">>, [{restart_application, ssl}]},
{<<"8\\..*">>, [{restart_application, ssl}]},
{<<"7\\..*">>, [{restart_application, ssl}]},
{<<"6\\..*">>, [{restart_application, ssl}]},
diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl
index 09953908ce..ef9aac34bf 100644
--- a/lib/ssl/src/ssl.erl
+++ b/lib/ssl/src/ssl.erl
@@ -241,7 +241,7 @@ handshake(#sslsocket{fd = {_, _, _, Tracker}} = Socket, SslOpts, Timeout) when
catch
Error = {error, _Reason} -> Error
end;
-handshake(#sslsocket{pid = Pid, fd = {_, _, _}} = Socket, SslOpts, Timeout) when
+handshake(#sslsocket{pid = [Pid|_], fd = {_, _, _}} = Socket, SslOpts, Timeout) when
(is_integer(Timeout) andalso Timeout >= 0) or (Timeout == infinity)->
try
{ok, EmOpts, _} = dtls_packet_demux:get_all_opts(Pid),
@@ -301,7 +301,7 @@ handshake_cancel(Socket) ->
%%
%% Description: Close an ssl connection
%%--------------------------------------------------------------------
-close(#sslsocket{pid = Pid}) when is_pid(Pid) ->
+close(#sslsocket{pid = [Pid|_]}) when is_pid(Pid) ->
ssl_connection:close(Pid, {close, ?DEFAULT_TIMEOUT});
close(#sslsocket{pid = {dtls, #config{dtls_handler = {Pid, _}}}}) ->
dtls_packet_demux:close(Pid);
@@ -313,12 +313,12 @@ close(#sslsocket{pid = {ListenSocket, #config{transport_info={Transport,_, _, _}
%%
%% Description: Close an ssl connection
%%--------------------------------------------------------------------
-close(#sslsocket{pid = TLSPid},
+close(#sslsocket{pid = [TLSPid|_]},
{Pid, Timeout} = DownGrade) when is_pid(TLSPid),
is_pid(Pid),
(is_integer(Timeout) andalso Timeout >= 0) or (Timeout == infinity) ->
ssl_connection:close(TLSPid, {close, DownGrade});
-close(#sslsocket{pid = TLSPid}, Timeout) when is_pid(TLSPid),
+close(#sslsocket{pid = [TLSPid|_]}, Timeout) when is_pid(TLSPid),
(is_integer(Timeout) andalso Timeout >= 0) or (Timeout == infinity) ->
ssl_connection:close(TLSPid, {close, Timeout});
close(#sslsocket{pid = {ListenSocket, #config{transport_info={Transport,_, _, _}}}}, _) ->
@@ -329,8 +329,10 @@ close(#sslsocket{pid = {ListenSocket, #config{transport_info={Transport,_, _, _}
%%
%% Description: Sends data over the ssl connection
%%--------------------------------------------------------------------
-send(#sslsocket{pid = Pid}, Data) when is_pid(Pid) ->
+send(#sslsocket{pid = [Pid]}, Data) when is_pid(Pid) ->
ssl_connection:send(Pid, Data);
+send(#sslsocket{pid = [_, Pid]}, Data) when is_pid(Pid) ->
+ tls_sender:send_data(Pid, erlang:iolist_to_binary(Data));
send(#sslsocket{pid = {_, #config{transport_info={_, udp, _, _}}}}, _) ->
{error,enotconn}; %% Emulate connection behaviour
send(#sslsocket{pid = {dtls,_}}, _) ->
@@ -346,7 +348,7 @@ send(#sslsocket{pid = {ListenSocket, #config{transport_info={Transport, _, _, _}
%%--------------------------------------------------------------------
recv(Socket, Length) ->
recv(Socket, Length, infinity).
-recv(#sslsocket{pid = Pid}, Length, Timeout) when is_pid(Pid),
+recv(#sslsocket{pid = [Pid|_]}, Length, Timeout) when is_pid(Pid),
(is_integer(Timeout) andalso Timeout >= 0) or (Timeout == infinity)->
ssl_connection:recv(Pid, Length, Timeout);
recv(#sslsocket{pid = {dtls,_}}, _, _) ->
@@ -361,7 +363,7 @@ recv(#sslsocket{pid = {Listen,
%% Description: Changes process that receives the messages when active = true
%% or once.
%%--------------------------------------------------------------------
-controlling_process(#sslsocket{pid = Pid}, NewOwner) when is_pid(Pid), is_pid(NewOwner) ->
+controlling_process(#sslsocket{pid = [Pid|_]}, NewOwner) when is_pid(Pid), is_pid(NewOwner) ->
ssl_connection:new_user(Pid, NewOwner);
controlling_process(#sslsocket{pid = {dtls, _}},
NewOwner) when is_pid(NewOwner) ->
@@ -379,7 +381,7 @@ controlling_process(#sslsocket{pid = {Listen,
%%
%% Description: Return SSL information for the connection
%%--------------------------------------------------------------------
-connection_information(#sslsocket{pid = Pid}) when is_pid(Pid) ->
+connection_information(#sslsocket{pid = [Pid|_]}) when is_pid(Pid) ->
case ssl_connection:connection_information(Pid, false) of
{ok, Info} ->
{ok, [Item || Item = {_Key, Value} <- Info, Value =/= undefined]};
@@ -396,7 +398,7 @@ connection_information(#sslsocket{pid = {dtls,_}}) ->
%%
%% Description: Return SSL information for the connection
%%--------------------------------------------------------------------
-connection_information(#sslsocket{pid = Pid}, Items) when is_pid(Pid) ->
+connection_information(#sslsocket{pid = [Pid|_]}, Items) when is_pid(Pid) ->
case ssl_connection:connection_information(Pid, include_security_info(Items)) of
{ok, Info} ->
{ok, [Item || Item = {Key, Value} <- Info, lists:member(Key, Items),
@@ -410,9 +412,9 @@ connection_information(#sslsocket{pid = Pid}, Items) when is_pid(Pid) ->
%%
%% Description: same as inet:peername/1.
%%--------------------------------------------------------------------
-peername(#sslsocket{pid = Pid, fd = {Transport, Socket, _}}) when is_pid(Pid)->
+peername(#sslsocket{pid = [Pid|_], fd = {Transport, Socket, _}}) when is_pid(Pid)->
dtls_socket:peername(Transport, Socket);
-peername(#sslsocket{pid = Pid, fd = {Transport, Socket, _, _}}) when is_pid(Pid)->
+peername(#sslsocket{pid = [Pid|_], fd = {Transport, Socket, _, _}}) when is_pid(Pid)->
tls_socket:peername(Transport, Socket);
peername(#sslsocket{pid = {dtls, #config{dtls_handler = {_Pid, _}}}}) ->
dtls_socket:peername(dtls, undefined);
@@ -426,7 +428,7 @@ peername(#sslsocket{pid = {dtls,_}}) ->
%%
%% Description: Returns the peercert.
%%--------------------------------------------------------------------
-peercert(#sslsocket{pid = Pid}) when is_pid(Pid) ->
+peercert(#sslsocket{pid = [Pid|_]}) when is_pid(Pid) ->
case ssl_connection:peer_certificate(Pid) of
{ok, undefined} ->
{error, no_peercert};
@@ -444,33 +446,33 @@ peercert(#sslsocket{pid = {Listen, _}}) when is_port(Listen) ->
%% Description: Returns the protocol that has been negotiated. If no
%% protocol has been negotiated will return {error, protocol_not_negotiated}
%%--------------------------------------------------------------------
-negotiated_protocol(#sslsocket{pid = Pid}) ->
+negotiated_protocol(#sslsocket{pid = [Pid|_]}) when is_pid(Pid) ->
ssl_connection:negotiated_protocol(Pid).
%%--------------------------------------------------------------------
--spec cipher_suites() -> [ssl_cipher:old_erl_cipher_suite()] | [string()].
+-spec cipher_suites() -> [ssl_cipher_format:old_erl_cipher_suite()] | [string()].
%%--------------------------------------------------------------------
cipher_suites() ->
cipher_suites(erlang).
%%--------------------------------------------------------------------
-spec cipher_suites(erlang | openssl | all) ->
- [ssl_cipher:old_erl_cipher_suite() | string()].
+ [ssl_cipher_format:old_erl_cipher_suite() | string()].
%% Description: Returns all supported cipher suites.
%%--------------------------------------------------------------------
cipher_suites(erlang) ->
- [ssl_cipher:erl_suite_definition(Suite) || Suite <- available_suites(default)];
+ [ssl_cipher_format:erl_suite_definition(Suite) || Suite <- available_suites(default)];
cipher_suites(openssl) ->
- [ssl_cipher:openssl_suite_name(Suite) ||
+ [ssl_cipher_format:openssl_suite_name(Suite) ||
Suite <- available_suites(default)];
cipher_suites(all) ->
- [ssl_cipher:erl_suite_definition(Suite) || Suite <- available_suites(all)].
+ [ssl_cipher_format:erl_suite_definition(Suite) || Suite <- available_suites(all)].
%%--------------------------------------------------------------------
-spec cipher_suites(default | all | anonymous, tls_record:tls_version() | dtls_record:dtls_version() |
tls_record:tls_atom_version() | dtls_record:dtls_atom_version()) ->
- [ssl_cipher:erl_cipher_suite()].
+ [ssl_cipher_format:erl_cipher_suite()].
%% Description: Returns all default and all supported cipher suites for a
%% TLS/DTLS version
%%--------------------------------------------------------------------
@@ -483,12 +485,12 @@ cipher_suites(Base, Version) when Version == 'dtlsv1.2';
Version == 'dtlsv1'->
cipher_suites(Base, dtls_record:protocol_version(Version));
cipher_suites(Base, Version) ->
- [ssl_cipher:suite_definition(Suite) || Suite <- supported_suites(Base, Version)].
+ [ssl_cipher_format:suite_definition(Suite) || Suite <- supported_suites(Base, Version)].
%%--------------------------------------------------------------------
--spec filter_cipher_suites([ssl_cipher:erl_cipher_suite()],
+-spec filter_cipher_suites([ssl_cipher_format:erl_cipher_suite()] | [ssl_cipher_format:cipher_suite()],
[{key_exchange | cipher | mac | prf, fun()}] | []) ->
- [ssl_cipher:erl_cipher_suite()].
+ [ssl_cipher_format:erl_cipher_suite() ] | [ssl_cipher_format:cipher_suite()].
%% Description: Removes cipher suites if any of the filter functions returns false
%% for any part of the cipher suite. This function also calls default filter functions
%% to make sure the cipher suite are supported by crypto.
@@ -505,10 +507,10 @@ filter_cipher_suites(Suites, Filters0) ->
prf_filters => add_filter(proplists:get_value(prf, Filters0), PrfF)},
ssl_cipher:filter_suites(Suites, Filters).
%%--------------------------------------------------------------------
--spec prepend_cipher_suites([ssl_cipher:erl_cipher_suite()] |
+-spec prepend_cipher_suites([ssl_cipher_format:erl_cipher_suite()] |
[{key_exchange | cipher | mac | prf, fun()}],
- [ssl_cipher:erl_cipher_suite()]) ->
- [ssl_cipher:erl_cipher_suite()].
+ [ssl_cipher_format:erl_cipher_suite()]) ->
+ [ssl_cipher_format:erl_cipher_suite()].
%% Description: Make <Preferred> suites become the most prefered
%% suites that is put them at the head of the cipher suite list
%% and remove them from <Suites> if present. <Preferred> may be a
@@ -523,10 +525,10 @@ prepend_cipher_suites(Filters, Suites) ->
Preferred = filter_cipher_suites(Suites, Filters),
Preferred ++ (Suites -- Preferred).
%%--------------------------------------------------------------------
--spec append_cipher_suites(Deferred :: [ssl_cipher:erl_cipher_suite()] |
+-spec append_cipher_suites(Deferred :: [ssl_cipher_format:erl_cipher_suite()] |
[{key_exchange | cipher | mac | prf, fun()}],
- [ssl_cipher:erl_cipher_suite()]) ->
- [ssl_cipher:erl_cipher_suite()].
+ [ssl_cipher_format:erl_cipher_suite()]) ->
+ [ssl_cipher_format:erl_cipher_suite()].
%% Description: Make <Deferred> suites suites become the
%% least prefered suites that is put them at the end of the cipher suite list
%% and removed them from <Suites> if present.
@@ -581,7 +583,7 @@ eccs_filter_supported(Curves) ->
%%
%% Description: Gets options
%%--------------------------------------------------------------------
-getopts(#sslsocket{pid = Pid}, OptionTags) when is_pid(Pid), is_list(OptionTags) ->
+getopts(#sslsocket{pid = [Pid|_]}, OptionTags) when is_pid(Pid), is_list(OptionTags) ->
ssl_connection:get_opts(Pid, OptionTags);
getopts(#sslsocket{pid = {dtls, #config{transport_info = {Transport,_,_,_}}}} = ListenSocket, OptionTags) when is_list(OptionTags) ->
try dtls_socket:getopts(Transport, ListenSocket, OptionTags) of
@@ -612,7 +614,7 @@ getopts(#sslsocket{}, OptionTags) ->
%%
%% Description: Sets options
%%--------------------------------------------------------------------
-setopts(#sslsocket{pid = Pid}, Options0) when is_pid(Pid), is_list(Options0) ->
+setopts(#sslsocket{pid = [Pid|_]}, Options0) when is_pid(Pid), is_list(Options0) ->
try proplists:expand([{binary, [{mode, binary}]},
{list, [{mode, list}]}], Options0) of
Options ->
@@ -667,7 +669,7 @@ getstat(Socket) ->
getstat(#sslsocket{pid = {Listen, #config{transport_info = {Transport, _, _, _}}}}, Options) when is_port(Listen), is_list(Options) ->
tls_socket:getstat(Transport, Listen, Options);
-getstat(#sslsocket{pid = Pid, fd = {Transport, Socket, _, _}}, Options) when is_pid(Pid), is_list(Options) ->
+getstat(#sslsocket{pid = [Pid|_], fd = {Transport, Socket, _, _}}, Options) when is_pid(Pid), is_list(Options) ->
tls_socket:getstat(Transport, Socket, Options).
%%---------------------------------------------------------------
@@ -680,7 +682,7 @@ shutdown(#sslsocket{pid = {Listen, #config{transport_info = {Transport,_, _, _}}
Transport:shutdown(Listen, How);
shutdown(#sslsocket{pid = {dtls,_}},_) ->
{error, enotconn};
-shutdown(#sslsocket{pid = Pid}, How) ->
+shutdown(#sslsocket{pid = [Pid|_]}, How) when is_pid(Pid) ->
ssl_connection:shutdown(Pid, How).
%%--------------------------------------------------------------------
@@ -692,9 +694,9 @@ sockname(#sslsocket{pid = {Listen, #config{transport_info = {Transport, _, _, _
tls_socket:sockname(Transport, Listen);
sockname(#sslsocket{pid = {dtls, #config{dtls_handler = {Pid, _}}}}) ->
dtls_packet_demux:sockname(Pid);
-sockname(#sslsocket{pid = Pid, fd = {Transport, Socket, _}}) when is_pid(Pid) ->
+sockname(#sslsocket{pid = [Pid|_], fd = {Transport, Socket, _}}) when is_pid(Pid) ->
dtls_socket:sockname(Transport, Socket);
-sockname(#sslsocket{pid = Pid, fd = {Transport, Socket, _, _}}) when is_pid(Pid) ->
+sockname(#sslsocket{pid = [Pid| _], fd = {Transport, Socket, _, _}}) when is_pid(Pid) ->
tls_socket:sockname(Transport, Socket).
%%---------------------------------------------------------------
@@ -723,7 +725,15 @@ versions() ->
%%
%% Description: Initiates a renegotiation.
%%--------------------------------------------------------------------
-renegotiate(#sslsocket{pid = Pid}) when is_pid(Pid) ->
+renegotiate(#sslsocket{pid = [Pid, Sender |_]}) when is_pid(Pid),
+ is_pid(Sender) ->
+ case tls_sender:renegotiate(Sender) of
+ {ok, Write} ->
+ tls_connection:renegotiation(Pid, Write);
+ Error ->
+ Error
+ end;
+renegotiate(#sslsocket{pid = [Pid |_]}) when is_pid(Pid) ->
ssl_connection:renegotiation(Pid);
renegotiate(#sslsocket{pid = {dtls,_}}) ->
{error, enotconn};
@@ -737,7 +747,7 @@ renegotiate(#sslsocket{pid = {Listen,_}}) when is_port(Listen) ->
%%
%% Description: use a ssl sessions TLS PRF to generate key material
%%--------------------------------------------------------------------
-prf(#sslsocket{pid = Pid},
+prf(#sslsocket{pid = [Pid|_]},
Secret, Label, Seed, WantedLength) when is_pid(Pid) ->
ssl_connection:prf(Pid, Secret, Label, Seed, WantedLength);
prf(#sslsocket{pid = {dtls,_}}, _,_,_,_) ->
@@ -794,12 +804,12 @@ tls_version({254, _} = Version) ->
%%--------------------------------------------------------------------
--spec suite_to_str(ssl_cipher:erl_cipher_suite()) -> string().
+-spec suite_to_str(ssl_cipher_format:erl_cipher_suite()) -> string().
%%
%% Description: Return the string representation of a cipher suite.
%%--------------------------------------------------------------------
suite_to_str(Cipher) ->
- ssl_cipher:suite_to_str(Cipher).
+ ssl_cipher_format:suite_to_str(Cipher).
%%--------------------------------------------------------------------
@@ -909,13 +919,14 @@ handle_options(Opts0, Role, Host) ->
CertFile = handle_option(certfile, Opts, <<>>),
RecordCb = record_cb(Opts),
- Versions = case handle_option(versions, Opts, []) of
- [] ->
- RecordCb:supported_protocol_versions();
- Vsns ->
- Versions0 = [RecordCb:protocol_version(Vsn) || Vsn <- Vsns],
- lists:sort(fun RecordCb:is_higher/2, Versions0)
- end,
+ [HighestVersion|_] = Versions =
+ case handle_option(versions, Opts, []) of
+ [] ->
+ RecordCb:supported_protocol_versions();
+ Vsns ->
+ Versions0 = [RecordCb:protocol_version(Vsn) || Vsn <- Vsns],
+ lists:sort(fun RecordCb:is_higher/2, Versions0)
+ end,
Protocol = handle_option(protocol, Opts, tls),
@@ -947,13 +958,28 @@ handle_options(Opts0, Role, Host) ->
psk_identity = handle_option(psk_identity, Opts, undefined),
srp_identity = handle_option(srp_identity, Opts, undefined),
ciphers = handle_cipher_option(proplists:get_value(ciphers, Opts, []),
- RecordCb:highest_protocol_version(Versions)),
+ HighestVersion),
eccs = handle_eccs_option(proplists:get_value(eccs, Opts, eccs()),
- RecordCb:highest_protocol_version(Versions)),
- signature_algs = handle_hashsigns_option(proplists:get_value(signature_algs, Opts,
- default_option_role(server,
- tls_v1:default_signature_algs(Versions), Role)),
- tls_version(RecordCb:highest_protocol_version(Versions))),
+ HighestVersion),
+ signature_algs =
+ handle_hashsigns_option(
+ proplists:get_value(
+ signature_algs,
+ Opts,
+ default_option_role(server,
+ tls_v1:default_signature_algs(HighestVersion),
+ Role)),
+ tls_version(HighestVersion)),
+ signature_algs_cert =
+ handle_signature_algorithms_option(
+ proplists:get_value(
+ signature_algs_cert,
+ Opts,
+ default_option_role(server,
+ tls_v1:default_signature_schemes(HighestVersion),
+ Role
+ )),
+ tls_version(HighestVersion)),
%% Server side option
reuse_session = handle_option(reuse_session, Opts, ReuseSessionFun),
reuse_sessions = handle_option(reuse_sessions, Opts, true),
@@ -1290,6 +1316,21 @@ handle_hashsigns_option(_, Version) when Version >= {3, 3} ->
handle_hashsigns_option(_, _Version) ->
undefined.
+handle_signature_algorithms_option(Value, Version) when is_list(Value)
+ andalso Version >= {3, 4} ->
+ case tls_v1:signature_schemes(Version, Value) of
+ [] ->
+ throw({error, {options,
+ no_supported_signature_schemes,
+ {signature_algs_cert, Value}}});
+ _ ->
+ Value
+ end;
+handle_signature_algorithms_option(_, Version) when Version >= {3, 4} ->
+ handle_signature_algorithms_option(tls_v1:default_signature_schemes(Version), Version);
+handle_signature_algorithms_option(_, _Version) ->
+ undefined.
+
validate_options([]) ->
[];
validate_options([{Opt, Value} | Tail]) ->
@@ -1379,10 +1420,10 @@ binary_cipher_suites(Version, []) ->
%% not require explicit configuration
default_binary_suites(Version);
binary_cipher_suites(Version, [Map|_] = Ciphers0) when is_map(Map) ->
- Ciphers = [ssl_cipher:suite(C) || C <- Ciphers0],
+ Ciphers = [ssl_cipher_format:suite(C) || C <- Ciphers0],
binary_cipher_suites(Version, Ciphers);
binary_cipher_suites(Version, [Tuple|_] = Ciphers0) when is_tuple(Tuple) ->
- Ciphers = [ssl_cipher:suite(tuple_to_map(C)) || C <- Ciphers0],
+ Ciphers = [ssl_cipher_format:suite(tuple_to_map(C)) || C <- Ciphers0],
binary_cipher_suites(Version, Ciphers);
binary_cipher_suites(Version, [Cipher0 | _] = Ciphers0) when is_binary(Cipher0) ->
All = ssl_cipher:all_suites(Version) ++
@@ -1397,11 +1438,11 @@ binary_cipher_suites(Version, [Cipher0 | _] = Ciphers0) when is_binary(Cipher0)
end;
binary_cipher_suites(Version, [Head | _] = Ciphers0) when is_list(Head) ->
%% Format: ["RC4-SHA","RC4-MD5"]
- Ciphers = [ssl_cipher:openssl_suite(C) || C <- Ciphers0],
+ Ciphers = [ssl_cipher_format:openssl_suite(C) || C <- Ciphers0],
binary_cipher_suites(Version, Ciphers);
binary_cipher_suites(Version, Ciphers0) ->
%% Format: "RC4-SHA:RC4-MD5"
- Ciphers = [ssl_cipher:openssl_suite(C) || C <- string:lexemes(Ciphers0, ":")],
+ Ciphers = [ssl_cipher_format:openssl_suite(C) || C <- string:lexemes(Ciphers0, ":")],
binary_cipher_suites(Version, Ciphers).
default_binary_suites(Version) ->
diff --git a/lib/ssl/src/ssl_alert.erl b/lib/ssl/src/ssl_alert.erl
index 34e9797f1f..ed8156e0be 100644
--- a/lib/ssl/src/ssl_alert.erl
+++ b/lib/ssl/src/ssl_alert.erl
@@ -163,6 +163,8 @@ description_txt(?USER_CANCELED) ->
"User Canceled";
description_txt(?NO_RENEGOTIATION) ->
"No Renegotiation";
+description_txt(?MISSING_EXTENSION) ->
+ "Missing extension";
description_txt(?UNSUPPORTED_EXTENSION) ->
"Unsupported Extension";
description_txt(?CERTIFICATE_UNOBTAINABLE) ->
@@ -177,6 +179,8 @@ description_txt(?UNKNOWN_PSK_IDENTITY) ->
"Unknown Psk Identity";
description_txt(?INAPPROPRIATE_FALLBACK) ->
"Inappropriate Fallback";
+description_txt(?CERTIFICATE_REQUIRED) ->
+ "Certificate required";
description_txt(?NO_APPLICATION_PROTOCOL) ->
"No application protocol";
description_txt(Enum) ->
diff --git a/lib/ssl/src/ssl_alert.hrl b/lib/ssl/src/ssl_alert.hrl
index b23123905e..9b2322da17 100644
--- a/lib/ssl/src/ssl_alert.hrl
+++ b/lib/ssl/src/ssl_alert.hrl
@@ -29,6 +29,9 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Alert protocol - RFC 2246 section 7.2
+%%% updated by RFC 8486 with
+%%% missing_extension(109),
+%%% certificate_required(116),
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% AlertLevel
@@ -100,12 +103,14 @@
-define(INAPPROPRIATE_FALLBACK, 86).
-define(USER_CANCELED, 90).
-define(NO_RENEGOTIATION, 100).
+-define(MISSING_EXTENSION, 109).
-define(UNSUPPORTED_EXTENSION, 110).
-define(CERTIFICATE_UNOBTAINABLE, 111).
-define(UNRECOGNISED_NAME, 112).
-define(BAD_CERTIFICATE_STATUS_RESPONSE, 113).
-define(BAD_CERTIFICATE_HASH_VALUE, 114).
-define(UNKNOWN_PSK_IDENTITY, 115).
+-define(CERTIFICATE_REQUIRED, 116).
-define(NO_APPLICATION_PROTOCOL, 120).
-define(ALERT_REC(Level,Desc), #alert{level=Level,description=Desc,where={?FILE, ?LINE}}).
diff --git a/lib/ssl/src/ssl_api.hrl b/lib/ssl/src/ssl_api.hrl
index 2bd51cf91e..7b7b1cbcd9 100644
--- a/lib/ssl/src/ssl_api.hrl
+++ b/lib/ssl/src/ssl_api.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -42,7 +42,8 @@
{verify, verify_type()} |
{verify_fun, {fun(), InitialUserState::term()}} |
{fail_if_no_peer_cert, boolean()} | {depth, integer()} |
- {cert, Der::binary()} | {certfile, path()} | {key, Der::binary()} |
+ {cert, Der::binary()} | {certfile, path()} |
+ {key, {private_key_type(), Der::binary()}} |
{keyfile, path()} | {password, string()} | {cacerts, [Der::binary()]} |
{cacertfile, path()} | {dh, Der::binary()} | {dhfile, path()} |
{user_lookup_fun, {fun(), InitialUserState::term()}} |
@@ -57,7 +58,7 @@
-type verify_type() :: verify_none | verify_peer.
-type path() :: string().
--type ciphers() :: [ssl_cipher:erl_cipher_suite()] |
+-type ciphers() :: [ssl_cipher_format:erl_cipher_suite()] |
string(). % (according to old API)
-type ssl_imp() :: new | old.
@@ -65,4 +66,11 @@
ClosedTag::atom(), ErrTag::atom()}}.
-type prf_random() :: client_random | server_random.
+-type private_key_type() :: rsa | %% Backwards compatibility
+ dsa | %% Backwards compatibility
+ 'RSAPrivateKey' |
+ 'DSAPrivateKey' |
+ 'ECPrivateKey' |
+ 'PrivateKeyInfo'.
+
-endif. % -ifdef(ssl_api).
diff --git a/lib/ssl/src/ssl_certificate.erl b/lib/ssl/src/ssl_certificate.erl
index 017d18ee2c..9997f5e0c8 100644
--- a/lib/ssl/src/ssl_certificate.erl
+++ b/lib/ssl/src/ssl_certificate.erl
@@ -33,6 +33,7 @@
-export([trusted_cert_and_path/4,
certificate_chain/3,
+ certificate_chain/4,
file_to_certificats/2,
file_to_crls/2,
validate/3,
@@ -40,7 +41,8 @@
is_valid_key_usage/2,
select_extension/2,
extensions_list/1,
- public_key_type/1
+ public_key_type/1,
+ foldl_db/3
]).
%%====================================================================
@@ -79,7 +81,8 @@ trusted_cert_and_path(CertChain, CertDbHandle, CertDbRef, PartialChainHandler) -
%% Trusted must be selfsigned or it is an incomplete chain
handle_path(Trusted, Path, PartialChainHandler);
_ ->
- %% Root CA could not be verified
+ %% Root CA could not be verified, but partial
+ %% chain handler may trusted a cert that we got
handle_incomplete_chain(Path, PartialChainHandler)
end
end.
@@ -94,10 +97,23 @@ certificate_chain(undefined, _, _) ->
{error, no_cert};
certificate_chain(OwnCert, CertDbHandle, CertsDbRef) when is_binary(OwnCert) ->
ErlCert = public_key:pkix_decode_cert(OwnCert, otp),
- certificate_chain(ErlCert, OwnCert, CertDbHandle, CertsDbRef, [OwnCert]);
+ certificate_chain(ErlCert, OwnCert, CertDbHandle, CertsDbRef, [OwnCert], []);
certificate_chain(OwnCert, CertDbHandle, CertsDbRef) ->
DerCert = public_key:pkix_encode('OTPCertificate', OwnCert, otp),
- certificate_chain(OwnCert, DerCert, CertDbHandle, CertsDbRef, [DerCert]).
+ certificate_chain(OwnCert, DerCert, CertDbHandle, CertsDbRef, [DerCert], []).
+
+%%--------------------------------------------------------------------
+-spec certificate_chain(undefined | binary() | #'OTPCertificate'{} , db_handle(), certdb_ref(), [der_cert()]) ->
+ {error, no_cert} | {ok, #'OTPCertificate'{} | undefined, [der_cert()]}.
+%%
+%% Description: Create certificate chain with certs from
+%%--------------------------------------------------------------------
+certificate_chain(Cert, CertDbHandle, CertsDbRef, Candidates) when is_binary(Cert) ->
+ ErlCert = public_key:pkix_decode_cert(Cert, otp),
+ certificate_chain(ErlCert, Cert, CertDbHandle, CertsDbRef, [Cert], Candidates);
+certificate_chain(Cert, CertDbHandle, CertsDbRef, Candidates) ->
+ DerCert = public_key:pkix_encode('OTPCertificate', Cert, otp),
+ certificate_chain(Cert, DerCert, CertDbHandle, CertsDbRef, [DerCert], Candidates).
%%--------------------------------------------------------------------
-spec file_to_certificats(binary(), term()) -> [der_cert()].
%%
@@ -187,9 +203,20 @@ public_key_type(?'id-ecPublicKey') ->
ec.
%%--------------------------------------------------------------------
+-spec foldl_db(fun(), db_handle() | {extracted, list()}, list()) ->
+ {ok, term()} | issuer_not_found.
+%%
+%% Description:
+%%--------------------------------------------------------------------
+foldl_db(IsIssuerFun, CertDbHandle, []) ->
+ ssl_pkix_db:foldl(IsIssuerFun, issuer_not_found, CertDbHandle);
+foldl_db(IsIssuerFun, _, [_|_] = ListDb) ->
+ lists:foldl(IsIssuerFun, issuer_not_found, ListDb).
+
+%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
-certificate_chain(OtpCert, BinCert, CertDbHandle, CertsDbRef, Chain) ->
+certificate_chain(OtpCert, BinCert, CertDbHandle, CertsDbRef, Chain, ListDb) ->
IssuerAndSelfSigned =
case public_key:pkix_is_self_signed(OtpCert) of
true ->
@@ -200,12 +227,12 @@ certificate_chain(OtpCert, BinCert, CertDbHandle, CertsDbRef, Chain) ->
case IssuerAndSelfSigned of
{_, true = SelfSigned} ->
- certificate_chain(CertDbHandle, CertsDbRef, Chain, ignore, ignore, SelfSigned);
+ do_certificate_chain(CertDbHandle, CertsDbRef, Chain, ignore, ignore, SelfSigned, ListDb);
{{error, issuer_not_found}, SelfSigned} ->
- case find_issuer(OtpCert, BinCert, CertDbHandle, CertsDbRef) of
+ case find_issuer(OtpCert, BinCert, CertDbHandle, CertsDbRef, ListDb) of
{ok, {SerialNr, Issuer}} ->
- certificate_chain(CertDbHandle, CertsDbRef, Chain,
- SerialNr, Issuer, SelfSigned);
+ do_certificate_chain(CertDbHandle, CertsDbRef, Chain,
+ SerialNr, Issuer, SelfSigned, ListDb);
_ ->
%% Guess the the issuer must be the root
%% certificate. The verification of the
@@ -214,19 +241,19 @@ certificate_chain(OtpCert, BinCert, CertDbHandle, CertsDbRef, Chain) ->
{ok, undefined, lists:reverse(Chain)}
end;
{{ok, {SerialNr, Issuer}}, SelfSigned} ->
- certificate_chain(CertDbHandle, CertsDbRef, Chain, SerialNr, Issuer, SelfSigned)
+ do_certificate_chain(CertDbHandle, CertsDbRef, Chain, SerialNr, Issuer, SelfSigned, ListDb)
end.
-certificate_chain(_, _, [RootCert | _] = Chain, _, _, true) ->
+do_certificate_chain(_, _, [RootCert | _] = Chain, _, _, true, _) ->
{ok, RootCert, lists:reverse(Chain)};
-certificate_chain(CertDbHandle, CertsDbRef, Chain, SerialNr, Issuer, _SelfSigned) ->
+do_certificate_chain(CertDbHandle, CertsDbRef, Chain, SerialNr, Issuer, _, ListDb) ->
case ssl_manager:lookup_trusted_cert(CertDbHandle, CertsDbRef,
SerialNr, Issuer) of
{ok, {IssuerCert, ErlCert}} ->
ErlCert = public_key:pkix_decode_cert(IssuerCert, otp),
certificate_chain(ErlCert, IssuerCert,
- CertDbHandle, CertsDbRef, [IssuerCert | Chain]);
+ CertDbHandle, CertsDbRef, [IssuerCert | Chain], ListDb);
_ ->
%% The trusted cert may be obmitted from the chain as the
%% counter part needs to have it anyway to be able to
@@ -234,7 +261,8 @@ certificate_chain(CertDbHandle, CertsDbRef, Chain, SerialNr, Issuer, _SelfSigned
{ok, undefined, lists:reverse(Chain)}
end.
-find_issuer(OtpCert, BinCert, CertDbHandle, CertsDbRef) ->
+
+find_issuer(OtpCert, BinCert, CertDbHandle, CertsDbRef, ListDb) ->
IsIssuerFun =
fun({_Key, {_Der, #'OTPCertificate'{} = ErlCertCandidate}}, Acc) ->
case public_key:pkix_is_issuer(OtpCert, ErlCertCandidate) of
@@ -252,26 +280,29 @@ find_issuer(OtpCert, BinCert, CertDbHandle, CertsDbRef) ->
Acc
end,
- if is_reference(CertsDbRef) -> % actual DB exists
- try ssl_pkix_db:foldl(IsIssuerFun, issuer_not_found, CertDbHandle) of
- issuer_not_found ->
- {error, issuer_not_found}
- catch
- {ok, _IssuerId} = Return ->
- Return
- end;
- is_tuple(CertsDbRef), element(1,CertsDbRef) =:= extracted -> % cache bypass byproduct
- {extracted, CertsData} = CertsDbRef,
- DB = [Entry || {decoded, Entry} <- CertsData],
- try lists:foldl(IsIssuerFun, issuer_not_found, DB) of
- issuer_not_found ->
- {error, issuer_not_found}
- catch
- {ok, _IssuerId} = Return ->
- Return
- end
+ Result = case is_reference(CertsDbRef) of
+ true ->
+ do_find_issuer(IsIssuerFun, CertDbHandle, ListDb);
+ false ->
+ {extracted, CertsData} = CertsDbRef,
+ DB = [Entry || {decoded, Entry} <- CertsData],
+ do_find_issuer(IsIssuerFun, CertDbHandle, DB)
+ end,
+ case Result of
+ issuer_not_found ->
+ {error, issuer_not_found};
+ Result ->
+ Result
end.
+do_find_issuer(IssuerFun, CertDbHandle, CertDb) ->
+ try
+ foldl_db(IssuerFun, CertDbHandle, CertDb)
+ catch
+ throw:{ok, _} = Return ->
+ Return
+ end.
+
is_valid_extkey_usage(KeyUse, client) ->
%% Client wants to verify server
is_valid_key_usage(KeyUse,?'id-kp-serverAuth');
@@ -300,7 +331,7 @@ other_issuer(OtpCert, BinCert, CertDbHandle, CertDbRef) ->
{ok, IssuerId} ->
{other, IssuerId};
{error, issuer_not_found} ->
- case find_issuer(OtpCert, BinCert, CertDbHandle, CertDbRef) of
+ case find_issuer(OtpCert, BinCert, CertDbHandle, CertDbRef, []) of
{ok, IssuerId} ->
{other, IssuerId};
Other ->
diff --git a/lib/ssl/src/ssl_cipher.erl b/lib/ssl/src/ssl_cipher.erl
index 07ec823829..9bb2beaebd 100644
--- a/lib/ssl/src/ssl_cipher.erl
+++ b/lib/ssl/src/ssl_cipher.erl
@@ -31,45 +31,27 @@
-include("ssl_cipher.hrl").
-include("ssl_handshake.hrl").
-include("ssl_alert.hrl").
+-include("tls_handshake_1_3.hrl").
-include_lib("public_key/include/public_key.hrl").
--export([security_parameters/2, security_parameters/3, suite_definition/1,
- erl_suite_definition/1,
+-export([security_parameters/2, security_parameters/3,
cipher_init/3, decipher/6, cipher/5, decipher_aead/6, cipher_aead/6,
- suite/1, suites/1, all_suites/1, crypto_support_filters/0,
+ suites/1, all_suites/1, crypto_support_filters/0,
chacha_suites/1, anonymous_suites/1, psk_suites/1, psk_suites_anon/1,
srp_suites/0, srp_suites_anon/0,
- rc4_suites/1, des_suites/1, rsa_suites/1, openssl_suite/1, openssl_suite_name/1,
+ rc4_suites/1, des_suites/1, rsa_suites/1,
filter/3, filter_suites/1, filter_suites/2,
hash_algorithm/1, sign_algorithm/1, is_acceptable_hash/2, is_fallback/1,
random_bytes/1, calc_mac_hash/4,
- is_stream_ciphersuite/1, suite_to_str/1]).
-
--export_type([cipher_suite/0,
- erl_cipher_suite/0, old_erl_cipher_suite/0, openssl_cipher_suite/0,
- hash/0, key_algo/0, sign_algo/0]).
-
--type cipher() :: null |rc4_128 | des_cbc | '3des_ede_cbc' | aes_128_cbc | aes_256_cbc | aes_128_gcm | aes_256_gcm | chacha20_poly1305.
--type hash() :: null | md5 | sha | sha224 | sha256 | sha384 | sha512.
--type sign_algo() :: rsa | dsa | ecdsa.
--type key_algo() :: null | rsa | dhe_rsa | dhe_dss | ecdhe_ecdsa| ecdh_ecdsa | ecdh_rsa| srp_rsa| srp_dss | psk | dhe_psk | rsa_psk | dh_anon | ecdh_anon | srp_anon.
--type erl_cipher_suite() :: #{key_exchange := key_algo(),
- cipher := cipher(),
- mac := hash() | aead,
- prf := hash() | default_prf %% Old cipher suites, version dependent
- }.
--type old_erl_cipher_suite() :: {key_algo(), cipher(), hash()} % Pre TLS 1.2
- %% TLS 1.2, internally PRE TLS 1.2 will use default_prf
- | {key_algo(), cipher(), hash(), hash() | default_prf}.
--type cipher_suite() :: binary().
--type cipher_enum() :: integer().
--type openssl_cipher_suite() :: string().
-
+ is_stream_ciphersuite/1, signature_scheme/1,
+ scheme_to_components/1]).
-compile(inline).
+-type cipher_enum() :: integer().
+
%%--------------------------------------------------------------------
--spec security_parameters(cipher_suite(), #security_parameters{}) ->
+-spec security_parameters(ssl_cipher_format:cipher_suite(), #security_parameters{}) ->
#security_parameters{}.
%% Only security_parameters/2 should call security_parameters/3 with undefined as
%% first argument.
@@ -79,7 +61,8 @@ security_parameters(?TLS_NULL_WITH_NULL_NULL = CipherSuite, SecParams) ->
security_parameters(undefined, CipherSuite, SecParams).
%%--------------------------------------------------------------------
--spec security_parameters(ssl_record:ssl_version() | undefined, cipher_suite(), #security_parameters{}) ->
+-spec security_parameters(ssl_record:ssl_version() | undefined,
+ ssl_cipher_format:cipher_suite(), #security_parameters{}) ->
#security_parameters{}.
%%
%% Description: Returns a security parameters record where the
@@ -87,7 +70,7 @@ security_parameters(?TLS_NULL_WITH_NULL_NULL = CipherSuite, SecParams) ->
%%-------------------------------------------------------------------
security_parameters(Version, CipherSuite, SecParams) ->
#{cipher := Cipher, mac := Hash,
- prf := PrfHashAlg} = suite_definition(CipherSuite),
+ prf := PrfHashAlg} = ssl_cipher_format:suite_definition(CipherSuite),
SecParams#security_parameters{
cipher_suite = CipherSuite,
bulk_cipher_algorithm = bulk_cipher_algorithm(Cipher),
@@ -309,7 +292,7 @@ aead_decipher(Type, #cipher_state{key = Key, iv = IV} = CipherState,
end.
%%--------------------------------------------------------------------
--spec suites(ssl_record:ssl_version()) -> [cipher_suite()].
+-spec suites(ssl_record:ssl_version()) -> [ssl_cipher_format:cipher_suite()].
%%
%% Description: Returns a list of supported cipher suites.
%%--------------------------------------------------------------------
@@ -320,8 +303,6 @@ suites({3, Minor}) ->
suites({_, Minor}) ->
dtls_v1:suites(Minor).
-all_suites({3, 4}) ->
- all_suites({3, 3});
all_suites({3, _} = Version) ->
suites(Version)
++ chacha_suites(Version)
@@ -334,7 +315,8 @@ all_suites({3, _} = Version) ->
all_suites(Version) ->
dtls_v1:all_suites(Version).
%%--------------------------------------------------------------------
--spec chacha_suites(ssl_record:ssl_version() | integer()) -> [cipher_suite()].
+-spec chacha_suites(ssl_record:ssl_version() | integer()) ->
+ [ssl_cipher_format:cipher_suite()].
%%
%% Description: Returns list of the chacha cipher suites, only supported
%% if explicitly set by user for now due to interop problems, proably need
@@ -348,7 +330,8 @@ chacha_suites(_) ->
[].
%%--------------------------------------------------------------------
--spec anonymous_suites(ssl_record:ssl_version() | integer()) -> [cipher_suite()].
+-spec anonymous_suites(ssl_record:ssl_version() | integer()) ->
+ [ssl_cipher_format:cipher_suite()].
%%
%% Description: Returns a list of the anonymous cipher suites, only supported
%% if explicitly set by user. Intended only for testing.
@@ -357,6 +340,8 @@ anonymous_suites({3, N}) ->
srp_suites_anon() ++ anonymous_suites(N);
anonymous_suites({254, _} = Version) ->
dtls_v1:anonymous_suites(Version);
+anonymous_suites(4) ->
+ []; %% Raw public key negotiation may be used instead
anonymous_suites(N)
when N >= 3 ->
psk_suites_anon(N) ++
@@ -384,13 +369,15 @@ anonymous_suites(N) when N == 0;
].
%%--------------------------------------------------------------------
--spec psk_suites(ssl_record:ssl_version() | integer()) -> [cipher_suite()].
+-spec psk_suites(ssl_record:ssl_version() | integer()) -> [ssl_cipher_format:cipher_suite()].
%%
%% Description: Returns a list of the PSK cipher suites, only supported
%% if explicitly set by user.
%%--------------------------------------------------------------------
psk_suites({3, N}) ->
psk_suites(N);
+psk_suites(4) ->
+ []; %% TODO Add new PSK, PSK_(EC)DHE suites
psk_suites(N)
when N >= 3 ->
[
@@ -406,7 +393,7 @@ psk_suites(_) ->
?TLS_RSA_PSK_WITH_RC4_128_SHA].
%%--------------------------------------------------------------------
--spec psk_suites_anon(ssl_record:ssl_version() | integer()) -> [cipher_suite()].
+-spec psk_suites_anon(ssl_record:ssl_version() | integer()) -> [ssl_cipher_format:cipher_suite()].
%%
%% Description: Returns a list of the anonymous PSK cipher suites, only supported
%% if explicitly set by user.
@@ -441,7 +428,7 @@ psk_suites_anon(_) ->
?TLS_DHE_PSK_WITH_RC4_128_SHA,
?TLS_PSK_WITH_RC4_128_SHA].
%%--------------------------------------------------------------------
--spec srp_suites() -> [cipher_suite()].
+-spec srp_suites() -> [ssl_cipher_format:cipher_suite()].
%%
%% Description: Returns a list of the SRP cipher suites, only supported
%% if explicitly set by user.
@@ -455,7 +442,7 @@ srp_suites() ->
?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA].
%%--------------------------------------------------------------------
--spec srp_suites_anon() -> [cipher_suite()].
+-spec srp_suites_anon() -> [ssl_cipher_format:cipher_suite()].
%%
%% Description: Returns a list of the SRP anonymous cipher suites, only supported
%% if explicitly set by user.
@@ -466,7 +453,8 @@ srp_suites_anon() ->
?TLS_SRP_SHA_WITH_AES_256_CBC_SHA].
%%--------------------------------------------------------------------
--spec rc4_suites(Version::ssl_record:ssl_version() | integer()) -> [cipher_suite()].
+-spec rc4_suites(Version::ssl_record:ssl_version() | integer()) ->
+ [ssl_cipher_format:cipher_suite()].
%%
%% Description: Returns a list of the RSA|(ECDH/RSA)| (ECDH/ECDSA)
%% with RC4 cipher suites, only supported if explicitly set by user.
@@ -487,7 +475,7 @@ rc4_suites(N) when N =< 4 ->
?TLS_ECDH_RSA_WITH_RC4_128_SHA].
%%--------------------------------------------------------------------
--spec des_suites(Version::ssl_record:ssl_version()) -> [cipher_suite()].
+-spec des_suites(Version::ssl_record:ssl_version()) -> [ssl_cipher_format:cipher_suite()].
%%
%% Description: Returns a list of the cipher suites
%% with DES cipher, only supported if explicitly set by user.
@@ -505,7 +493,7 @@ des_suites(_)->
].
%%--------------------------------------------------------------------
--spec rsa_suites(Version::ssl_record:ssl_version() | integer()) -> [cipher_suite()].
+-spec rsa_suites(Version::ssl_record:ssl_version() | integer()) -> [ssl_cipher_format:cipher_suite()].
%%
%% Description: Returns a list of the RSA key exchange
%% cipher suites, only supported if explicitly set by user.
@@ -529,1720 +517,8 @@ rsa_suites(N) when N =< 4 ->
].
%%--------------------------------------------------------------------
--spec suite_definition(cipher_suite()) -> erl_cipher_suite().
-%%
-%% Description: Return erlang cipher suite definition.
-%% Note: Currently not supported suites are commented away.
-%% They should be supported or removed in the future.
-%%-------------------------------------------------------------------
-%% TLS v1.1 suites
-suite_definition(?TLS_NULL_WITH_NULL_NULL) ->
- #{key_exchange => null,
- cipher => null,
- mac => null,
- prf => null};
-%% RFC 5746 - Not a real cipher suite used to signal empty "renegotiation_info" extension
-%% to avoid handshake failure from old servers that do not ignore
-%% hello extension data as they should.
-suite_definition(?TLS_EMPTY_RENEGOTIATION_INFO_SCSV) ->
- #{key_exchange => null,
- cipher => null,
- mac => null,
- prf => null};
-suite_definition(?TLS_RSA_WITH_RC4_128_MD5) ->
- #{key_exchange => rsa,
- cipher => rc4_128,
- mac => md5,
- prf => default_prf};
-suite_definition(?TLS_RSA_WITH_RC4_128_SHA) ->
- #{key_exchange => rsa,
- cipher => rc4_128,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_RSA_WITH_DES_CBC_SHA) ->
- #{key_exchange => rsa,
- cipher => des_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_RSA_WITH_3DES_EDE_CBC_SHA) ->
- #{key_exchange => rsa,
- cipher => '3des_ede_cbc',
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_DHE_DSS_WITH_DES_CBC_SHA) ->
- #{key_exchange => dhe_dss,
- cipher => des_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA) ->
- #{key_exchange => dhe_dss,
- cipher => '3des_ede_cbc',
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_DHE_RSA_WITH_DES_CBC_SHA) ->
- #{key_exchange => dhe_rsa,
- cipher => des_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA) ->
- #{key_exchange => dhe_rsa,
- cipher => '3des_ede_cbc',
- mac => sha,
- prf => default_prf};
-%%% TSL V1.1 AES suites
-suite_definition(?TLS_RSA_WITH_AES_128_CBC_SHA) ->
- #{key_exchange => rsa,
- cipher => aes_128_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_DHE_DSS_WITH_AES_128_CBC_SHA) ->
- #{key_exchange => dhe_dss,
- cipher => aes_128_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_DHE_RSA_WITH_AES_128_CBC_SHA) ->
- #{key_exchange => dhe_rsa,
- cipher => aes_128_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_RSA_WITH_AES_256_CBC_SHA) ->
- #{key_exchange => rsa,
- cipher => aes_256_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_DHE_DSS_WITH_AES_256_CBC_SHA) ->
- #{key_exchange => dhe_dss,
- cipher => aes_256_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_DHE_RSA_WITH_AES_256_CBC_SHA) ->
- #{key_exchange => dhe_rsa,
- cipher => aes_256_cbc,
- mac => sha,
- prf => default_prf};
-%% TLS v1.2 suites
-%% suite_definition(?TLS_RSA_WITH_NULL_SHA) ->
-%% {rsa, null, sha, default_prf};
-suite_definition(?TLS_RSA_WITH_AES_128_CBC_SHA256) ->
- #{key_exchange => rsa,
- cipher => aes_128_cbc,
- mac => sha256,
- prf => default_prf};
-suite_definition(?TLS_RSA_WITH_AES_256_CBC_SHA256) ->
- #{key_exchange => rsa,
- cipher => aes_256_cbc,
- mac => sha256,
- prf => default_prf};
-suite_definition(?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256) ->
- #{key_exchange => dhe_dss,
- cipher => aes_128_cbc,
- mac => sha256,
- prf => default_prf};
-suite_definition(?TLS_DHE_RSA_WITH_AES_128_CBC_SHA256) ->
- #{key_exchange => dhe_rsa,
- cipher => aes_128_cbc,
- mac => sha256,
- prf => default_prf};
-suite_definition(?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256) ->
- #{key_exchange => dhe_dss,
- cipher => aes_256_cbc,
- mac => sha256,
- prf => default_prf};
-suite_definition(?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256) ->
- #{key_exchange => dhe_rsa,
- cipher => aes_256_cbc,
- mac => sha256,
- prf => default_prf};
-%% not defined YET:
-%% TLS_DH_DSS_WITH_AES_128_CBC_SHA256 DH_DSS AES_128_CBC SHA256
-%% TLS_DH_RSA_WITH_AES_128_CBC_SHA256 DH_RSA AES_128_CBC SHA256
-%% TLS_DH_DSS_WITH_AES_256_CBC_SHA256 DH_DSS AES_256_CBC SHA256
-%% TLS_DH_RSA_WITH_AES_256_CBC_SHA256 DH_RSA AES_256_CBC SHA256
-%%% DH-ANON deprecated by TLS spec and not available
-%%% by default, but good for testing purposes.
-suite_definition(?TLS_DH_anon_WITH_RC4_128_MD5) ->
- #{key_exchange => dh_anon,
- cipher => rc4_128,
- mac => md5,
- prf => default_prf};
-suite_definition(?TLS_DH_anon_WITH_DES_CBC_SHA) ->
- #{key_exchange => dh_anon,
- cipher => des_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_DH_anon_WITH_3DES_EDE_CBC_SHA) ->
- #{key_exchange => dh_anon,
- cipher => '3des_ede_cbc',
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_DH_anon_WITH_AES_128_CBC_SHA) ->
- #{key_exchange => dh_anon,
- cipher => aes_128_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_DH_anon_WITH_AES_256_CBC_SHA) ->
- #{key_exchange => dh_anon,
- cipher => aes_256_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_DH_anon_WITH_AES_128_CBC_SHA256) ->
- #{key_exchange => dh_anon,
- cipher => aes_128_cbc,
- mac => sha256,
- prf => default_prf};
-suite_definition(?TLS_DH_anon_WITH_AES_256_CBC_SHA256) ->
- #{key_exchange => dh_anon,
- cipher => aes_256_cbc,
- mac => sha256,
- prf => default_prf};
-%%% PSK Cipher Suites RFC 4279
-suite_definition(?TLS_PSK_WITH_RC4_128_SHA) ->
- #{key_exchange => psk,
- cipher => rc4_128,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_PSK_WITH_3DES_EDE_CBC_SHA) ->
- #{key_exchange => psk,
- cipher => '3des_ede_cbc',
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_PSK_WITH_AES_128_CBC_SHA) ->
- #{key_exchange => psk,
- cipher => aes_128_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_PSK_WITH_AES_256_CBC_SHA) ->
- #{key_exchange => psk,
- cipher => aes_256_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_DHE_PSK_WITH_RC4_128_SHA) ->
- #{key_exchange => dhe_psk,
- cipher => rc4_128,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA) ->
- #{key_exchange => dhe_psk,
- cipher => '3des_ede_cbc',
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_DHE_PSK_WITH_AES_128_CBC_SHA) ->
- #{key_exchange => dhe_psk,
- cipher => aes_128_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_DHE_PSK_WITH_AES_256_CBC_SHA) ->
- #{key_exchange => dhe_psk,
- cipher => aes_256_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_RSA_PSK_WITH_RC4_128_SHA) ->
- #{key_exchange => rsa_psk,
- cipher => rc4_128,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA) ->
- #{key_exchange => rsa_psk,
- cipher => '3des_ede_cbc',
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_RSA_PSK_WITH_AES_128_CBC_SHA) ->
- #{key_exchange => rsa_psk,
- cipher => aes_128_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_RSA_PSK_WITH_AES_256_CBC_SHA) ->
- #{key_exchange => rsa_psk,
- cipher => aes_256_cbc,
- mac => sha,
- prf => default_prf};
-%%% PSK NULL Cipher Suites RFC 4785
-suite_definition(?TLS_PSK_WITH_NULL_SHA) ->
- #{key_exchange => psk,
- cipher => null,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_DHE_PSK_WITH_NULL_SHA) ->
- #{key_exchange => dhe_psk,
- cipher => null,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_RSA_PSK_WITH_NULL_SHA) ->
- #{key_exchange => rsa_psk,
- cipher => null,
- mac => sha,
- prf => default_prf};
-%%% TLS 1.2 PSK Cipher Suites RFC 5487
-suite_definition(?TLS_PSK_WITH_AES_128_GCM_SHA256) ->
- #{key_exchange => psk,
- cipher => aes_128_gcm,
- mac => aead,
- prf => sha256};
-suite_definition(?TLS_PSK_WITH_AES_256_GCM_SHA384) ->
- #{key_exchange => psk,
- cipher => aes_256_gcm,
- mac => aead,
- prf => sha384};
-suite_definition(?TLS_DHE_PSK_WITH_AES_128_GCM_SHA256) ->
- #{key_exchange => dhe_psk,
- cipher => aes_128_gcm,
- mac => aead,
- prf => sha256};
-suite_definition(?TLS_DHE_PSK_WITH_AES_256_GCM_SHA384) ->
- #{key_exchange => dhe_psk,
- cipher => aes_256_gcm,
- mac => aead,
- prf => sha384};
-suite_definition(?TLS_RSA_PSK_WITH_AES_128_GCM_SHA256) ->
- #{key_exchange => rsa_psk,
- cipher => aes_128_gcm,
- mac => aead,
- prf => sha256};
-suite_definition(?TLS_RSA_PSK_WITH_AES_256_GCM_SHA384) ->
- #{key_exchange => rsa_psk,
- cipher => aes_256_gcm,
- mac => aead,
- prf => sha384};
-suite_definition(?TLS_PSK_WITH_AES_128_CBC_SHA256) ->
- #{key_exchange => psk,
- cipher => aes_128_cbc,
- mac => sha256,
- prf => default_prf};
-suite_definition(?TLS_PSK_WITH_AES_256_CBC_SHA384) ->
- #{key_exchange => psk,
- cipher => aes_256_cbc,
- mac => sha384,
- prf => default_prf};
-suite_definition(?TLS_DHE_PSK_WITH_AES_128_CBC_SHA256) ->
- #{key_exchange => dhe_psk,
- cipher => aes_128_cbc,
- mac => sha256,
- prf => default_prf};
-suite_definition(?TLS_DHE_PSK_WITH_AES_256_CBC_SHA384) ->
- #{key_exchange => dhe_psk,
- cipher => aes_256_cbc,
- mac => sha384,
- prf => default_prf};
-suite_definition(?TLS_RSA_PSK_WITH_AES_128_CBC_SHA256) ->
- #{key_exchange => rsa_psk,
- cipher => aes_128_cbc,
- mac => sha256,
- prf => default_prf};
-suite_definition(?TLS_RSA_PSK_WITH_AES_256_CBC_SHA384) ->
- #{key_exchange => rsa_psk,
- cipher => aes_256_cbc,
- mac => sha384,
- prf => default_prf};
-suite_definition(?TLS_PSK_WITH_NULL_SHA256) ->
- #{key_exchange => psk,
- cipher => null,
- mac => sha256,
- prf => default_prf};
-suite_definition(?TLS_PSK_WITH_NULL_SHA384) ->
- #{key_exchange => psk,
- cipher => null,
- mac => sha384,
- prf => default_prf};
-suite_definition(?TLS_DHE_PSK_WITH_NULL_SHA256) ->
- #{key_exchange => dhe_psk,
- cipher => null,
- mac => sha256,
- prf => default_prf};
-suite_definition(?TLS_DHE_PSK_WITH_NULL_SHA384) ->
- #{key_exchange => dhe_psk,
- cipher => null,
- mac => sha384,
- prf => default_prf};
-suite_definition(?TLS_RSA_PSK_WITH_NULL_SHA256) ->
- #{key_exchange => rsa_psk,
- cipher => null,
- mac => sha256,
- prf => default_prf};
-suite_definition(?TLS_RSA_PSK_WITH_NULL_SHA384) ->
- #{key_exchange => rsa_psk,
- cipher => null,
- mac => sha384,
- prf => default_prf};
-%%% ECDHE PSK Cipher Suites RFC 5489
-suite_definition(?TLS_ECDHE_PSK_WITH_RC4_128_SHA) ->
- #{key_exchange => ecdhe_psk,
- cipher => rc4_128,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA) ->
- #{key_exchange => ecdhe_psk,
- cipher => '3des_ede_cbc',
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA) ->
- #{key_exchange => ecdhe_psk,
- cipher => aes_128_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA) ->
- #{key_exchange => ecdhe_psk,
- cipher => aes_256_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256) ->
- #{key_exchange => ecdhe_psk,
- cipher => aes_128_cbc,
- mac => sha256,
- prf => default_prf};
-suite_definition(?TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384) ->
- #{key_exchange => ecdhe_psk,
- cipher => aes_256_cbc,
- mac => sha384,
- prf => default_prf};
-suite_definition(?TLS_ECDHE_PSK_WITH_NULL_SHA256) ->
- #{key_exchange => ecdhe_psk,
- cipher => null,
- mac => sha256,
- prf => default_prf};
-suite_definition(?TLS_ECDHE_PSK_WITH_NULL_SHA384) ->
- #{key_exchange => ecdhe_psk,
- cipher => null, mac => sha384,
- prf => default_prf};
-%%% ECDHE_PSK with AES-GCM and AES-CCM Cipher Suites, draft-ietf-tls-ecdhe-psk-aead-05
-suite_definition(?TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256) ->
- #{key_exchange => ecdhe_psk,
- cipher => aes_128_gcm,
- mac => null,
- prf => sha256};
-suite_definition(?TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384) ->
- #{key_exchange => ecdhe_psk,
- cipher => aes_256_gcm,
- mac => null,
- prf => sha384};
-%% suite_definition(?TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256) ->
-%% #{key_exchange => ecdhe_psk,
-%% cipher => aes_128_ccm,
-%% mac => null,
-%% prf =>sha256};
-%% suite_definition(?TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256) ->
-%% #{key_exchange => ecdhe_psk,
-%% cipher => aes_256_ccm,
-%% mac => null,
-%% prf => sha256};
-%%% SRP Cipher Suites RFC 5054
-suite_definition(?TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA) ->
- #{key_exchange => srp_anon,
- cipher => '3des_ede_cbc',
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA) ->
- #{key_exchange => srp_rsa,
- cipher => '3des_ede_cbc',
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA) ->
- #{key_exchange => srp_dss,
- cipher => '3des_ede_cbc',
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_SRP_SHA_WITH_AES_128_CBC_SHA) ->
- #{key_exchange => srp_anon,
- cipher => aes_128_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA) ->
- #{key_exchange => srp_rsa,
- cipher => aes_128_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA) ->
- #{key_exchange => srp_dss,
- cipher => aes_128_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_SRP_SHA_WITH_AES_256_CBC_SHA) ->
- #{key_exchange => srp_anon,
- cipher => aes_256_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA) ->
- #{key_exchange => srp_rsa,
- cipher => aes_256_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA) ->
- #{key_exchange => srp_dss,
- cipher => aes_256_cbc,
- mac => sha,
- prf => default_prf};
-%% RFC 4492 EC TLS suites
-suite_definition(?TLS_ECDH_ECDSA_WITH_NULL_SHA) ->
- #{key_exchange => ecdh_ecdsa,
- cipher => null,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDH_ECDSA_WITH_RC4_128_SHA) ->
- #{key_exchange => ecdh_ecdsa,
- cipher => rc4_128,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA) ->
- #{key_exchange => ecdh_ecdsa,
- cipher => '3des_ede_cbc',
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA) ->
- #{key_exchange => ecdh_ecdsa,
- cipher => aes_128_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA) ->
- #{key_exchange => ecdh_ecdsa,
- cipher => aes_256_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDHE_ECDSA_WITH_NULL_SHA) ->
- #{key_exchange => ecdhe_ecdsa,
- cipher => null,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDHE_ECDSA_WITH_RC4_128_SHA) ->
- #{key_exchange => ecdhe_ecdsa,
- cipher => rc4_128,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA) ->
- #{key_exchange => ecdhe_ecdsa,
- cipher => '3des_ede_cbc',
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA) ->
- #{key_exchange => ecdhe_ecdsa,
- cipher => aes_128_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA) ->
- #{key_exchange => ecdhe_ecdsa,
- cipher => aes_256_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDH_RSA_WITH_NULL_SHA) ->
- #{key_exchange => ecdh_rsa,
- cipher => null,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDH_RSA_WITH_RC4_128_SHA) ->
- #{key_exchange => ecdh_rsa,
- cipher => rc4_128,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA) ->
- #{key_exchange => ecdh_rsa,
- cipher => '3des_ede_cbc',
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA) ->
- #{key_exchange => ecdh_rsa,
- cipher => aes_128_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA) ->
- #{key_exchange => ecdh_rsa,
- cipher => aes_256_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDHE_RSA_WITH_NULL_SHA) ->
- #{key_exchange => ecdhe_rsa,
- cipher => null,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDHE_RSA_WITH_RC4_128_SHA) ->
- #{key_exchange => ecdhe_rsa,
- cipher => rc4_128,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA) ->
- #{key_exchange => ecdhe_rsa,
- cipher => '3des_ede_cbc',
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) ->
- #{key_exchange => ecdhe_rsa,
- cipher => aes_128_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) ->
- #{key_exchange => ecdhe_rsa,
- cipher => aes_256_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDH_anon_WITH_NULL_SHA) ->
- #{key_exchange => ecdh_anon,
- cipher => null,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDH_anon_WITH_RC4_128_SHA) ->
- #{key_exchange => ecdh_anon,
- cipher => rc4_128,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA) ->
- #{key_exchange => ecdh_anon,
- cipher => '3des_ede_cbc',
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDH_anon_WITH_AES_128_CBC_SHA) ->
- #{key_exchange => ecdh_anon,
- cipher => aes_128_cbc,
- mac => sha,
- prf => default_prf};
-suite_definition(?TLS_ECDH_anon_WITH_AES_256_CBC_SHA) ->
- #{key_exchange => ecdh_anon,
- cipher => aes_256_cbc,
- mac => sha,
- prf => default_prf};
-%% RFC 5289 EC TLS suites
-suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256) ->
- #{key_exchange => ecdhe_ecdsa,
- cipher => aes_128_cbc,
- mac => sha256,
- prf => sha256};
-suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384) ->
- #{key_exchange => ecdhe_ecdsa,
- cipher => aes_256_cbc,
- mac => sha384,
- prf => sha384};
-suite_definition(?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256) ->
- #{key_exchange => ecdh_ecdsa,
- cipher => aes_128_cbc,
- mac => sha256,
- prf => sha256};
-suite_definition(?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384) ->
- #{key_exchange => ecdh_ecdsa,
- cipher => aes_256_cbc,
- mac => sha384,
- prf => sha384};
-suite_definition(?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) ->
- #{key_exchange => ecdhe_rsa,
- cipher => aes_128_cbc,
- mac => sha256,
- prf => sha256};
-suite_definition(?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) ->
- #{key_exchange => ecdhe_rsa,
- cipher => aes_256_cbc,
- mac => sha384,
- prf => sha384};
-suite_definition(?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256) ->
- #{key_exchange => ecdh_rsa,
- cipher => aes_128_cbc,
- mac => sha256,
- prf => sha256};
-suite_definition(?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384) ->
- #{key_exchange => ecdh_rsa,
- cipher => aes_256_cbc,
- mac => sha384,
- prf => sha384};
-%% RFC 5288 AES-GCM Cipher Suites
-suite_definition(?TLS_RSA_WITH_AES_128_GCM_SHA256) ->
- #{key_exchange => rsa,
- cipher => aes_128_gcm,
- mac => aead,
- prf => sha256};
-suite_definition(?TLS_RSA_WITH_AES_256_GCM_SHA384) ->
- #{key_exchange => rsa,
- cipher => aes_256_gcm,
- mac => aead,
- prf => sha384};
-suite_definition(?TLS_DHE_RSA_WITH_AES_128_GCM_SHA256) ->
- #{key_exchange => dhe_rsa,
- cipher => aes_128_gcm,
- mac => aead,
- prf => sha256};
-suite_definition(?TLS_DHE_RSA_WITH_AES_256_GCM_SHA384) ->
- #{key_exchange => dhe_rsa,
- cipher => aes_256_gcm,
- mac => aead,
- prf => sha384};
-suite_definition(?TLS_DH_RSA_WITH_AES_128_GCM_SHA256) ->
- #{key_exchange => dh_rsa,
- cipher => aes_128_gcm,
- mac => aead,
- prf => sha256};
-suite_definition(?TLS_DH_RSA_WITH_AES_256_GCM_SHA384) ->
- #{key_exchange => dh_rsa,
- cipher => aes_256_gcm,
- mac => aead,
- prf => sha384};
-suite_definition(?TLS_DHE_DSS_WITH_AES_128_GCM_SHA256) ->
- #{key_exchange => dhe_dss,
- cipher => aes_128_gcm,
- mac => aead,
- prf => sha256};
-suite_definition(?TLS_DHE_DSS_WITH_AES_256_GCM_SHA384) ->
- #{key_exchange => dhe_dss,
- cipher => aes_256_gcm,
- mac => aead,
- prf => sha384};
-suite_definition(?TLS_DH_DSS_WITH_AES_128_GCM_SHA256) ->
- #{key_exchange => dh_dss,
- cipher => aes_128_gcm,
- mac => null,
- prf => sha256};
-suite_definition(?TLS_DH_DSS_WITH_AES_256_GCM_SHA384) ->
- #{key_exchange => dh_dss,
- cipher => aes_256_gcm,
- mac => aead,
- prf => sha384};
-suite_definition(?TLS_DH_anon_WITH_AES_128_GCM_SHA256) ->
- #{key_exchange => dh_anon,
- cipher => aes_128_gcm,
- mac => aead,
- prf => sha256};
-suite_definition(?TLS_DH_anon_WITH_AES_256_GCM_SHA384) ->
- #{key_exchange => dh_anon,
- cipher => aes_256_gcm,
- mac => aead,
- prf => sha384};
-%% RFC 5289 ECC AES-GCM Cipher Suites
-suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) ->
- #{key_exchange => ecdhe_ecdsa,
- cipher => aes_128_gcm,
- mac => aead,
- prf => sha256};
-suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) ->
- #{key_exchange => ecdhe_ecdsa,
- cipher => aes_256_gcm,
- mac => aead,
- prf => sha384};
-suite_definition(?TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256) ->
- #{key_exchange => ecdh_ecdsa,
- cipher => aes_128_gcm,
- mac => aead,
- prf => sha256};
-suite_definition(?TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384) ->
- #{key_exchange => ecdh_ecdsa,
- cipher => aes_256_gcm,
- mac => aead,
- prf => sha384};
-suite_definition(?TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) ->
- #{key_exchange => ecdhe_rsa,
- cipher => aes_128_gcm,
- mac => aead,
- prf => sha256};
-suite_definition(?TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) ->
- #{key_exchange => ecdhe_rsa,
- cipher => aes_256_gcm,
- mac => aead,
- prf => sha384};
-suite_definition(?TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256) ->
- #{key_exchange => ecdh_rsa,
- cipher => aes_128_gcm,
- mac => aead,
- prf => sha256};
-suite_definition(?TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384) ->
- #{key_exchange => ecdh_rsa,
- cipher => aes_256_gcm,
- mac => aead,
- prf => sha384};
-%% draft-agl-tls-chacha20poly1305-04 Chacha20/Poly1305 Suites
-suite_definition(?TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256) ->
- #{key_exchange => ecdhe_rsa,
- cipher => chacha20_poly1305,
- mac => aead,
- prf => sha256};
-suite_definition(?TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256) ->
- #{key_exchange => ecdhe_ecdsa,
- cipher => chacha20_poly1305,
- mac => aead,
- prf => sha256};
-suite_definition(?TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256) ->
- #{key_exchange => dhe_rsa,
- cipher => chacha20_poly1305,
- mac => aead,
- prf => sha256}.
-
-%%--------------------------------------------------------------------
--spec erl_suite_definition(cipher_suite() | erl_cipher_suite()) -> old_erl_cipher_suite().
-%%
-%% Description: Return erlang cipher suite definition. Filters last value
-%% for now (compatibility reasons).
-%%--------------------------------------------------------------------
-erl_suite_definition(Bin) when is_binary(Bin) ->
- erl_suite_definition(suite_definition(Bin));
-erl_suite_definition(#{key_exchange := KeyExchange, cipher := Cipher,
- mac := Hash, prf := Prf}) ->
- case Prf of
- default_prf ->
- {KeyExchange, Cipher, Hash};
- _ ->
- {KeyExchange, Cipher, Hash, Prf}
- end.
-
-%%--------------------------------------------------------------------
--spec suite(erl_cipher_suite()) -> cipher_suite().
-%%
-%% Description: Return TLS cipher suite definition.
-%%--------------------------------------------------------------------
-%% TLS v1.1 suites
-suite(#{key_exchange := rsa,
- cipher := rc4_128,
- mac := md5}) ->
- ?TLS_RSA_WITH_RC4_128_MD5;
-suite(#{key_exchange := rsa,
- cipher := rc4_128,
- mac := sha}) ->
- ?TLS_RSA_WITH_RC4_128_SHA;
-suite(#{key_exchange := rsa,
- cipher := des_cbc,
- mac := sha}) ->
- ?TLS_RSA_WITH_DES_CBC_SHA;
-suite(#{key_exchange := rsa,
- cipher :='3des_ede_cbc',
- mac := sha}) ->
- ?TLS_RSA_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := dhe_dss,
- cipher:= des_cbc,
- mac := sha}) ->
- ?TLS_DHE_DSS_WITH_DES_CBC_SHA;
-suite(#{key_exchange := dhe_dss,
- cipher:= '3des_ede_cbc',
- mac := sha}) ->
- ?TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := dhe_rsa,
- cipher:= des_cbc,
- mac := sha}) ->
- ?TLS_DHE_RSA_WITH_DES_CBC_SHA;
-suite(#{key_exchange := dhe_rsa,
- cipher:= '3des_ede_cbc',
- mac := sha}) ->
- ?TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := dh_anon,
- cipher:= rc4_128,
- mac := md5}) ->
- ?TLS_DH_anon_WITH_RC4_128_MD5;
-suite(#{key_exchange := dh_anon,
- cipher:= des_cbc,
- mac := sha}) ->
- ?TLS_DH_anon_WITH_DES_CBC_SHA;
-suite(#{key_exchange := dh_anon,
- cipher:= '3des_ede_cbc',
- mac := sha}) ->
- ?TLS_DH_anon_WITH_3DES_EDE_CBC_SHA;
-%%% TSL V1.1 AES suites
-suite(#{key_exchange := rsa,
- cipher := aes_128_cbc,
- mac := sha}) ->
- ?TLS_RSA_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := dhe_dss,
- cipher := aes_128_cbc,
- mac := sha}) ->
- ?TLS_DHE_DSS_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := dhe_rsa,
- cipher := aes_128_cbc,
- mac := sha}) ->
- ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := dh_anon,
- cipher := aes_128_cbc,
- mac := sha}) ->
- ?TLS_DH_anon_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := rsa,
- cipher := aes_256_cbc,
- mac := sha}) ->
- ?TLS_RSA_WITH_AES_256_CBC_SHA;
-suite(#{key_exchange := dhe_dss,
- cipher := aes_256_cbc,
- mac := sha}) ->
- ?TLS_DHE_DSS_WITH_AES_256_CBC_SHA;
-suite(#{key_exchange := dhe_rsa,
- cipher := aes_256_cbc,
- mac := sha}) ->
- ?TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
-suite(#{key_exchange := dh_anon,
- cipher := aes_256_cbc,
- mac := sha}) ->
- ?TLS_DH_anon_WITH_AES_256_CBC_SHA;
-%% TLS v1.2 suites
-suite(#{key_exchange := rsa,
- cipher := aes_128_cbc,
- mac := sha256}) ->
- ?TLS_RSA_WITH_AES_128_CBC_SHA256;
-suite(#{key_exchange := rsa,
- cipher := aes_256_cbc,
- mac := sha256}) ->
- ?TLS_RSA_WITH_AES_256_CBC_SHA256;
-suite(#{key_exchange := dhe_dss,
- cipher := aes_128_cbc,
- mac := sha256}) ->
- ?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256;
-suite(#{key_exchange := dhe_rsa,
- cipher := aes_128_cbc,
- mac := sha256}) ->
- ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA256;
-suite(#{key_exchange := dhe_dss,
- cipher := aes_256_cbc,
- mac := sha256}) ->
- ?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256;
-suite(#{key_exchange := dhe_rsa,
- cipher := aes_256_cbc,
- mac := sha256}) ->
- ?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256;
-suite(#{key_exchange := dh_anon,
- cipher := aes_128_cbc,
- mac := sha256}) ->
- ?TLS_DH_anon_WITH_AES_128_CBC_SHA256;
-suite(#{key_exchange := dh_anon,
- cipher := aes_256_cbc,
- mac := sha256}) ->
- ?TLS_DH_anon_WITH_AES_256_CBC_SHA256;
-%%% PSK Cipher Suites RFC 4279
-suite(#{key_exchange := psk,
- cipher := rc4_128,
- mac := sha}) ->
- ?TLS_PSK_WITH_RC4_128_SHA;
-suite(#{key_exchange := psk,
- cipher := '3des_ede_cbc',
- mac := sha}) ->
- ?TLS_PSK_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := psk,
- cipher := aes_128_cbc,
- mac := sha}) ->
- ?TLS_PSK_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := psk,
- cipher := aes_256_cbc,
- mac := sha}) ->
- ?TLS_PSK_WITH_AES_256_CBC_SHA;
-suite(#{key_exchange := dhe_psk,
- cipher := rc4_128,
- mac := sha}) ->
- ?TLS_DHE_PSK_WITH_RC4_128_SHA;
-suite(#{key_exchange := dhe_psk,
- cipher := '3des_ede_cbc',
- mac := sha}) ->
- ?TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := dhe_psk,
- cipher := aes_128_cbc,
- mac := sha}) ->
- ?TLS_DHE_PSK_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := dhe_psk,
- cipher := aes_256_cbc,
- mac := sha}) ->
- ?TLS_DHE_PSK_WITH_AES_256_CBC_SHA;
-suite(#{key_exchange := rsa_psk,
- cipher := rc4_128,
- mac := sha}) ->
- ?TLS_RSA_PSK_WITH_RC4_128_SHA;
-suite(#{key_exchange := rsa_psk,
- cipher := '3des_ede_cbc',
- mac := sha}) ->
- ?TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := rsa_psk,
- cipher := aes_128_cbc,
- mac := sha}) ->
- ?TLS_RSA_PSK_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := rsa_psk,
- cipher := aes_256_cbc,
- mac := sha}) ->
- ?TLS_RSA_PSK_WITH_AES_256_CBC_SHA;
-%%% PSK NULL Cipher Suites RFC 4785
-suite(#{key_exchange := psk,
- cipher := null,
- mac := sha}) ->
- ?TLS_PSK_WITH_NULL_SHA;
-suite(#{key_exchange := dhe_psk,
- cipher := null,
- mac := sha}) ->
- ?TLS_DHE_PSK_WITH_NULL_SHA;
-suite(#{key_exchange := rsa_psk,
- cipher := null,
- mac := sha}) ->
- ?TLS_RSA_PSK_WITH_NULL_SHA;
-%%% TLS 1.2 PSK Cipher Suites RFC 5487
-suite(#{key_exchange := psk,
- cipher := aes_128_gcm,
- mac := aead,
- prf := sha256}) ->
- ?TLS_PSK_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := psk,
- cipher := aes_256_gcm,
- mac := aead,
- prf := sha384}) ->
- ?TLS_PSK_WITH_AES_256_GCM_SHA384;
-suite(#{key_exchange := dhe_psk,
- cipher := aes_128_gcm,
- mac := aead,
- prf := sha256}) ->
- ?TLS_DHE_PSK_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := dhe_psk,
- cipher := aes_256_gcm,
- mac := aead,
- prf := sha384}) ->
- ?TLS_DHE_PSK_WITH_AES_256_GCM_SHA384;
-suite(#{key_exchange := rsa_psk,
- cipher := aes_128_gcm,
- mac := aead,
- prf := sha256}) ->
- ?TLS_RSA_PSK_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := rsa_psk,
- cipher := aes_256_gcm,
- mac := aead,
- prf := sha384}) ->
- ?TLS_RSA_PSK_WITH_AES_256_GCM_SHA384;
-suite(#{key_exchange := psk,
- cipher := aes_128_cbc,
- mac := sha256}) ->
- ?TLS_PSK_WITH_AES_128_CBC_SHA256;
-suite(#{key_exchange := psk,
- cipher := aes_256_cbc,
- mac := sha384}) ->
- ?TLS_PSK_WITH_AES_256_CBC_SHA384;
-suite(#{key_exchange := dhe_psk,
- cipher := aes_128_cbc,
- mac := sha256}) ->
- ?TLS_DHE_PSK_WITH_AES_128_CBC_SHA256;
-suite(#{key_exchange := dhe_psk,
- cipher := aes_256_cbc,
- mac := sha384}) ->
- ?TLS_DHE_PSK_WITH_AES_256_CBC_SHA384;
-suite(#{key_exchange := rsa_psk,
- cipher := aes_128_cbc,
- mac := sha256}) ->
- ?TLS_RSA_PSK_WITH_AES_128_CBC_SHA256;
-suite(#{key_exchange := rsa_psk,
- cipher := aes_256_cbc,
- mac := sha384}) ->
- ?TLS_RSA_PSK_WITH_AES_256_CBC_SHA384;
-suite(#{key_exchange := psk,
- cipher := null,
- mac := sha256}) ->
- ?TLS_PSK_WITH_NULL_SHA256;
-suite(#{key_exchange := psk,
- cipher := null,
- mac := sha384}) ->
- ?TLS_PSK_WITH_NULL_SHA384;
-suite(#{key_exchange := dhe_psk,
- cipher := null,
- mac := sha256}) ->
- ?TLS_DHE_PSK_WITH_NULL_SHA256;
-suite(#{key_exchange := dhe_psk,
- cipher := null,
- mac := sha384}) ->
- ?TLS_DHE_PSK_WITH_NULL_SHA384;
-suite(#{key_exchange := rsa_psk,
- cipher := null,
- mac := sha256}) ->
- ?TLS_RSA_PSK_WITH_NULL_SHA256;
-suite(#{key_exchange := rsa_psk,
- cipher := null,
- mac := sha384}) ->
- ?TLS_RSA_PSK_WITH_NULL_SHA384;
-%%% ECDHE PSK Cipher Suites RFC 5489
-suite(#{key_exchange := ecdhe_psk,
- cipher := rc4_128,
- mac := sha}) ->
- ?TLS_ECDHE_PSK_WITH_RC4_128_SHA;
-suite(#{key_exchange := ecdhe_psk,
- cipher :='3des_ede_cbc',
- mac := sha}) ->
- ?TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := ecdhe_psk,
- cipher := aes_128_cbc,
- mac := sha}) ->
- ?TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := ecdhe_psk,
- cipher := aes_256_cbc,
- mac := sha}) ->
- ?TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA;
-suite(#{key_exchange := ecdhe_psk,
- cipher := aes_128_cbc,
- mac := sha256}) ->
- ?TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256;
-suite(#{key_exchange := ecdhe_psk,
- cipher := aes_256_cbc,
- mac := sha384}) ->
- ?TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384;
-suite(#{key_exchange := ecdhe_psk,
- cipher := null,
- mac := sha256}) ->
- ?TLS_ECDHE_PSK_WITH_NULL_SHA256;
-suite(#{key_exchange := ecdhe_psk,
- cipher := null,
- mac := sha384}) ->
- ?TLS_ECDHE_PSK_WITH_NULL_SHA384;
-%%% ECDHE_PSK with AES-GCM and AES-CCM Cipher Suites, draft-ietf-tls-ecdhe-psk-aead-05
-suite(#{key_exchange := ecdhe_psk,
- cipher := aes_128_gcm,
- mac := null,
- prf := sha256}) ->
- ?TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := ecdhe_psk,
- cipher := aes_256_gcm,
- mac := null,
- prf := sha384}) ->
- ?TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384;
- %% suite(#{key_exchange := ecdhe_psk,
- %% cipher := aes_128_ccm,
- %% mac := null,
- %% prf := sha256}) ->
- %% ?TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256;
- %% suite(#{key_exchange := ecdhe_psk,
- %% cipher := aes_256_ccm,
- %% mac := null,
- %% prf := sha256}) ->
- %% ?TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256;
-%%% SRP Cipher Suites RFC 5054
-suite(#{key_exchange := srp_anon,
- cipher := '3des_ede_cbc',
- mac := sha}) ->
- ?TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := srp_rsa,
- cipher := '3des_ede_cbc',
- mac := sha}) ->
- ?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := srp_dss,
- cipher := '3des_ede_cbc',
- mac := sha}) ->
- ?TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := srp_anon,
- cipher := aes_128_cbc,
- mac := sha}) ->
- ?TLS_SRP_SHA_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := srp_rsa,
- cipher := aes_128_cbc,
- mac := sha}) ->
- ?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := srp_dss,
- cipher := aes_128_cbc,
- mac := sha}) ->
- ?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := srp_anon,
- cipher := aes_256_cbc,
- mac := sha}) ->
- ?TLS_SRP_SHA_WITH_AES_256_CBC_SHA;
-suite(#{key_exchange := srp_rsa,
- cipher := aes_256_cbc,
- mac := sha}) ->
- ?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA;
-suite(#{key_exchange := srp_dss,
- cipher := aes_256_cbc,
- mac := sha}) ->
- ?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA;
-%%% RFC 4492 EC TLS suites
-suite(#{key_exchange := ecdh_ecdsa,
- cipher := null,
- mac := sha}) ->
- ?TLS_ECDH_ECDSA_WITH_NULL_SHA;
-suite(#{key_exchange := ecdh_ecdsa,
- cipher := rc4_128,
- mac := sha}) ->
- ?TLS_ECDH_ECDSA_WITH_RC4_128_SHA;
-suite(#{key_exchange := ecdh_ecdsa,
- cipher := '3des_ede_cbc',
- mac := sha}) ->
- ?TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := ecdh_ecdsa,
- cipher := aes_128_cbc,
- mac := sha}) ->
- ?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := ecdh_ecdsa,
- cipher := aes_256_cbc,
- mac := sha}) ->
- ?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA;
-suite(#{key_exchange := ecdhe_ecdsa,
- cipher := null,
- mac := sha}) ->
- ?TLS_ECDHE_ECDSA_WITH_NULL_SHA;
-suite(#{key_exchange := ecdhe_ecdsa,
- cipher := rc4_128,
- mac := sha}) ->
- ?TLS_ECDHE_ECDSA_WITH_RC4_128_SHA;
-suite(#{key_exchange := ecdhe_ecdsa,
- cipher := '3des_ede_cbc',
- mac := sha}) ->
- ?TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := ecdhe_ecdsa,
- cipher := aes_128_cbc,
- mac := sha}) ->
- ?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := ecdhe_ecdsa,
- cipher := aes_256_cbc,
- mac := sha}) ->
- ?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA;
-suite(#{key_exchange := ecdh_rsa,
- cipher := null,
- mac := sha}) ->
- ?TLS_ECDH_RSA_WITH_NULL_SHA;
-suite(#{key_exchange := ecdh_rsa,
- cipher := rc4_128,
- mac := sha}) ->
- ?TLS_ECDH_RSA_WITH_RC4_128_SHA;
-suite(#{key_exchange := ecdh_rsa,
- cipher := '3des_ede_cbc', mac := sha}) ->
- ?TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := ecdh_rsa,
- cipher := aes_128_cbc,
- mac := sha}) ->
- ?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := ecdh_rsa,
- cipher := aes_256_cbc,
- mac := sha}) ->
- ?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA;
-suite(#{key_exchange := ecdhe_rsa,
- cipher := null,
- mac := sha}) ->
- ?TLS_ECDHE_RSA_WITH_NULL_SHA;
-suite(#{key_exchange := ecdhe_rsa,
- cipher := rc4_128,
- mac := sha}) ->
- ?TLS_ECDHE_RSA_WITH_RC4_128_SHA;
-suite(#{key_exchange := ecdhe_rsa,
- cipher := '3des_ede_cbc',
- mac := sha}) ->
- ?TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := ecdhe_rsa,
- cipher := aes_128_cbc,
- mac := sha}) ->
- ?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := ecdhe_rsa,
- cipher := aes_256_cbc,
- mac := sha}) ->
- ?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA;
-suite(#{key_exchange := ecdh_anon,
- cipher := null,
- mac := sha}) ->
- ?TLS_ECDH_anon_WITH_NULL_SHA;
-suite(#{key_exchange := ecdh_anon,
- cipher := rc4_128,
- mac := sha}) ->
- ?TLS_ECDH_anon_WITH_RC4_128_SHA;
-suite(#{key_exchange := ecdh_anon,
- cipher := '3des_ede_cbc',
- mac := sha}) ->
- ?TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA;
-suite(#{key_exchange := ecdh_anon,
- cipher := aes_128_cbc,
- mac := sha}) ->
- ?TLS_ECDH_anon_WITH_AES_128_CBC_SHA;
-suite(#{key_exchange := ecdh_anon,
- cipher := aes_256_cbc,
- mac := sha}) ->
- ?TLS_ECDH_anon_WITH_AES_256_CBC_SHA;
-%%% RFC 5289 EC TLS suites
-suite(#{key_exchange := ecdhe_ecdsa,
- cipher := aes_128_cbc,
- mac:= sha256,
- prf := sha256}) ->
- ?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256;
-suite(#{key_exchange := ecdhe_ecdsa,
- cipher := aes_256_cbc,
- mac := sha384,
- prf := sha384}) ->
- ?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384;
-suite(#{key_exchange := ecdh_ecdsa,
- cipher := aes_128_cbc,
- mac := sha256,
- prf := sha256}) ->
- ?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256;
-suite(#{key_exchange := ecdh_ecdsa,
- cipher := aes_256_cbc,
- mac := sha384,
- prf := sha384}) ->
- ?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384;
-suite(#{key_exchange := ecdhe_rsa,
- cipher := aes_128_cbc,
- mac := sha256,
- prf := sha256}) ->
- ?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256;
-suite(#{key_exchange := ecdhe_rsa,
- cipher := aes_256_cbc,
- mac := sha384,
- prf := sha384}) ->
- ?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384;
-suite(#{key_exchange := ecdh_rsa,
- cipher := aes_128_cbc,
- mac := sha256,
- prf := sha256}) ->
- ?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256;
-suite(#{key_exchange := ecdh_rsa,
- cipher := aes_256_cbc,
- mac := sha384,
- prf := sha384}) ->
- ?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384;
-%% RFC 5288 AES-GCM Cipher Suites
-suite(#{key_exchange := rsa,
- cipher := aes_128_gcm,
- mac := aead,
- prf := sha256}) ->
- ?TLS_RSA_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := rsa,
- cipher := aes_256_gcm,
- mac := aead,
- prf := sha384}) ->
- ?TLS_RSA_WITH_AES_256_GCM_SHA384;
-suite(#{key_exchange := dhe_rsa,
- cipher := aes_128_gcm,
- mac := aead,
- prf := sha256}) ->
- ?TLS_DHE_RSA_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := dhe_rsa,
- cipher := aes_256_gcm,
- mac := aead,
- prf := sha384}) ->
- ?TLS_DHE_RSA_WITH_AES_256_GCM_SHA384;
-suite(#{key_exchange := dh_rsa,
- cipher := aes_128_gcm,
- mac := aead,
- prf := sha256}) ->
- ?TLS_DH_RSA_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := dh_rsa,
- cipher := aes_256_gcm,
- mac := aead,
- prf := sha384}) ->
- ?TLS_DH_RSA_WITH_AES_256_GCM_SHA384;
-suite(#{key_exchange := dhe_dss,
- cipher := aes_128_gcm,
- mac := aead,
- prf := sha256}) ->
- ?TLS_DHE_DSS_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := dhe_dss,
- cipher := aes_256_gcm,
- mac := aead,
- prf := sha384}) ->
- ?TLS_DHE_DSS_WITH_AES_256_GCM_SHA384;
-suite(#{key_exchange := dh_dss,
- cipher := aes_128_gcm,
- mac := aead,
- prf := sha256}) ->
- ?TLS_DH_DSS_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := dh_dss,
- cipher := aes_256_gcm,
- mac := aead,
- prf := sha384}) ->
- ?TLS_DH_DSS_WITH_AES_256_GCM_SHA384;
-suite(#{key_exchange := dh_anon,
- cipher := aes_128_gcm,
- mac := aead,
- prf := sha256}) ->
- ?TLS_DH_anon_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := dh_anon,
- cipher := aes_256_gcm,
- mac := aead,
- prf := sha384}) ->
- ?TLS_DH_anon_WITH_AES_256_GCM_SHA384;
-%% RFC 5289 ECC AES-GCM Cipher Suites
-suite(#{key_exchange := ecdhe_ecdsa,
- cipher := aes_128_gcm,
- mac := aead,
- prf := sha256}) ->
- ?TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := ecdhe_ecdsa,
- cipher := aes_256_gcm,
- mac := aead,
- prf := sha384}) ->
- ?TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384;
-suite(#{key_exchange := ecdh_ecdsa,
- cipher := aes_128_gcm,
- mac := aead,
- prf := sha256}) ->
- ?TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := ecdh_ecdsa,
- cipher := aes_256_gcm,
- mac := aead,
- prf := sha384}) ->
- ?TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384;
-suite(#{key_exchange := ecdhe_rsa,
- cipher := aes_128_gcm,
- mac := aead,
- prf := sha256}) ->
- ?TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := ecdhe_rsa,
- cipher := aes_256_gcm,
- mac := aead,
- prf := sha384}) ->
- ?TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384;
-suite(#{key_exchange := ecdh_rsa,
- cipher := aes_128_gcm,
- mac := aead,
- prf := sha256}) ->
- ?TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256;
-suite(#{key_exchange := ecdh_rsa,
- cipher := aes_256_gcm,
- mac := aead,
- prf := sha384}) ->
- ?TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384;
-%% draft-agl-tls-chacha20poly1305-04 Chacha20/Poly1305 Suites
-suite(#{key_exchange := ecdhe_rsa,
- cipher := chacha20_poly1305,
- mac := aead,
- prf := sha256}) ->
- ?TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256;
-suite(#{key_exchange := ecdhe_ecdsa,
- cipher := chacha20_poly1305,
- mac := aead,
- prf := sha256}) ->
- ?TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256;
-suite(#{key_exchange := dhe_rsa,
- cipher := chacha20_poly1305,
- mac := aead,
- prf := sha256}) ->
- ?TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256.
-
-
-%%--------------------------------------------------------------------
--spec suite_to_str(erl_cipher_suite()) -> string().
-%%
-%% Description: Return the string representation of a cipher suite.
-%%--------------------------------------------------------------------
-suite_to_str(#{key_exchange := null,
- cipher := null,
- mac := null,
- prf := null}) ->
- "TLS_EMPTY_RENEGOTIATION_INFO_SCSV";
-suite_to_str(#{key_exchange := Kex,
- cipher := Cipher,
- mac := aead,
- prf := PRF}) ->
- "TLS_" ++ string:to_upper(atom_to_list(Kex)) ++
- "_WITH_" ++ string:to_upper(atom_to_list(Cipher)) ++
- "_" ++ string:to_upper(atom_to_list(PRF));
-suite_to_str(#{key_exchange := Kex,
- cipher := Cipher,
- mac := Mac}) ->
- "TLS_" ++ string:to_upper(atom_to_list(Kex)) ++
- "_WITH_" ++ string:to_upper(atom_to_list(Cipher)) ++
- "_" ++ string:to_upper(atom_to_list(Mac)).
-
-
-%%--------------------------------------------------------------------
--spec openssl_suite(openssl_cipher_suite()) -> cipher_suite().
-%%
-%% Description: Return TLS cipher suite definition.
-%%--------------------------------------------------------------------
-%% translate constants <-> openssl-strings
-openssl_suite("DHE-RSA-AES256-SHA256") ->
- ?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256;
-openssl_suite("DHE-DSS-AES256-SHA256") ->
- ?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256;
-openssl_suite("AES256-SHA256") ->
- ?TLS_RSA_WITH_AES_256_CBC_SHA256;
-openssl_suite("DHE-RSA-AES128-SHA256") ->
- ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA256;
-openssl_suite("DHE-DSS-AES128-SHA256") ->
- ?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256;
-openssl_suite("AES128-SHA256") ->
- ?TLS_RSA_WITH_AES_128_CBC_SHA256;
-openssl_suite("DHE-RSA-AES256-SHA") ->
- ?TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
-openssl_suite("DHE-DSS-AES256-SHA") ->
- ?TLS_DHE_DSS_WITH_AES_256_CBC_SHA;
-openssl_suite("AES256-SHA") ->
- ?TLS_RSA_WITH_AES_256_CBC_SHA;
-openssl_suite("EDH-RSA-DES-CBC3-SHA") ->
- ?TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA;
-openssl_suite("EDH-DSS-DES-CBC3-SHA") ->
- ?TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA;
-openssl_suite("DES-CBC3-SHA") ->
- ?TLS_RSA_WITH_3DES_EDE_CBC_SHA;
-openssl_suite("DHE-RSA-AES128-SHA") ->
- ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
-openssl_suite("DHE-DSS-AES128-SHA") ->
- ?TLS_DHE_DSS_WITH_AES_128_CBC_SHA;
-openssl_suite("AES128-SHA") ->
- ?TLS_RSA_WITH_AES_128_CBC_SHA;
-openssl_suite("RC4-SHA") ->
- ?TLS_RSA_WITH_RC4_128_SHA;
-openssl_suite("RC4-MD5") ->
- ?TLS_RSA_WITH_RC4_128_MD5;
-openssl_suite("EDH-RSA-DES-CBC-SHA") ->
- ?TLS_DHE_RSA_WITH_DES_CBC_SHA;
-openssl_suite("DES-CBC-SHA") ->
- ?TLS_RSA_WITH_DES_CBC_SHA;
-
-%%% SRP Cipher Suites RFC 5054
-
-openssl_suite("SRP-DSS-AES-256-CBC-SHA") ->
- ?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA;
-openssl_suite("SRP-RSA-AES-256-CBC-SHA") ->
- ?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA;
-openssl_suite("SRP-DSS-3DES-EDE-CBC-SHA") ->
- ?TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA;
-openssl_suite("SRP-RSA-3DES-EDE-CBC-SHA") ->
- ?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA;
-openssl_suite("SRP-DSS-AES-128-CBC-SHA") ->
- ?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA;
-openssl_suite("SRP-RSA-AES-128-CBC-SHA") ->
- ?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA;
-
-%% RFC 4492 EC TLS suites
-openssl_suite("ECDH-ECDSA-RC4-SHA") ->
- ?TLS_ECDH_ECDSA_WITH_RC4_128_SHA;
-openssl_suite("ECDH-ECDSA-DES-CBC3-SHA") ->
- ?TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA;
-openssl_suite("ECDH-ECDSA-AES128-SHA") ->
- ?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA;
-openssl_suite("ECDH-ECDSA-AES256-SHA") ->
- ?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA;
-
-openssl_suite("ECDHE-ECDSA-RC4-SHA") ->
- ?TLS_ECDHE_ECDSA_WITH_RC4_128_SHA;
-openssl_suite("ECDHE-ECDSA-DES-CBC3-SHA") ->
- ?TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA;
-openssl_suite("ECDHE-ECDSA-AES128-SHA") ->
- ?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA;
-openssl_suite("ECDHE-ECDSA-AES256-SHA") ->
- ?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA;
-
-openssl_suite("ECDHE-RSA-RC4-SHA") ->
- ?TLS_ECDHE_RSA_WITH_RC4_128_SHA;
-openssl_suite("ECDHE-RSA-DES-CBC3-SHA") ->
- ?TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA;
-openssl_suite("ECDHE-RSA-AES128-SHA") ->
- ?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA;
-openssl_suite("ECDHE-RSA-AES256-SHA") ->
- ?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA;
-
-openssl_suite("ECDH-RSA-RC4-SHA") ->
- ?TLS_ECDH_RSA_WITH_RC4_128_SHA;
-openssl_suite("ECDH-RSA-DES-CBC3-SHA") ->
- ?TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA;
-openssl_suite("ECDH-RSA-AES128-SHA") ->
- ?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA;
-openssl_suite("ECDH-RSA-AES256-SHA") ->
- ?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA;
-
-%% RFC 5289 EC TLS suites
-openssl_suite("ECDHE-ECDSA-AES128-SHA256") ->
- ?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256;
-openssl_suite("ECDHE-ECDSA-AES256-SHA384") ->
- ?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384;
-openssl_suite("ECDH-ECDSA-AES128-SHA256") ->
- ?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256;
-openssl_suite("ECDH-ECDSA-AES256-SHA384") ->
- ?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384;
-openssl_suite("ECDHE-RSA-AES128-SHA256") ->
- ?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256;
-openssl_suite("ECDHE-RSA-AES256-SHA384") ->
- ?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384;
-openssl_suite("ECDH-RSA-AES128-SHA256") ->
- ?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256;
-openssl_suite("ECDH-RSA-AES256-SHA384") ->
- ?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384;
-
-%% RFC 5288 AES-GCM Cipher Suites
-openssl_suite("AES128-GCM-SHA256") ->
- ?TLS_RSA_WITH_AES_128_GCM_SHA256;
-openssl_suite("AES256-GCM-SHA384") ->
- ?TLS_RSA_WITH_AES_256_GCM_SHA384;
-openssl_suite("DHE-RSA-AES128-GCM-SHA256") ->
- ?TLS_DHE_RSA_WITH_AES_128_GCM_SHA256;
-openssl_suite("DHE-RSA-AES256-GCM-SHA384") ->
- ?TLS_DHE_RSA_WITH_AES_256_GCM_SHA384;
-openssl_suite("DH-RSA-AES128-GCM-SHA256") ->
- ?TLS_DH_RSA_WITH_AES_128_GCM_SHA256;
-openssl_suite("DH-RSA-AES256-GCM-SHA384") ->
- ?TLS_DH_RSA_WITH_AES_256_GCM_SHA384;
-openssl_suite("DHE-DSS-AES128-GCM-SHA256") ->
- ?TLS_DHE_DSS_WITH_AES_128_GCM_SHA256;
-openssl_suite("DHE-DSS-AES256-GCM-SHA384") ->
- ?TLS_DHE_DSS_WITH_AES_256_GCM_SHA384;
-openssl_suite("DH-DSS-AES128-GCM-SHA256") ->
- ?TLS_DH_DSS_WITH_AES_128_GCM_SHA256;
-openssl_suite("DH-DSS-AES256-GCM-SHA384") ->
- ?TLS_DH_DSS_WITH_AES_256_GCM_SHA384;
-
-%% RFC 5289 ECC AES-GCM Cipher Suites
-openssl_suite("ECDHE-ECDSA-AES128-GCM-SHA256") ->
- ?TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256;
-openssl_suite("ECDHE-ECDSA-AES256-GCM-SHA384") ->
- ?TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384;
-openssl_suite("ECDH-ECDSA-AES128-GCM-SHA256") ->
- ?TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256;
-openssl_suite("ECDH-ECDSA-AES256-GCM-SHA384") ->
- ?TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384;
-openssl_suite("ECDHE-RSA-AES128-GCM-SHA256") ->
- ?TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256;
-openssl_suite("ECDHE-RSA-AES256-GCM-SHA384") ->
- ?TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384;
-openssl_suite("ECDH-RSA-AES128-GCM-SHA256") ->
- ?TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256;
-openssl_suite("ECDH-RSA-AES256-GCM-SHA384") ->
- ?TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384.
-
-%%--------------------------------------------------------------------
--spec openssl_suite_name(cipher_suite()) -> openssl_cipher_suite() | erl_cipher_suite().
-%%
-%% Description: Return openssl cipher suite name if possible
-%%-------------------------------------------------------------------
-openssl_suite_name(?TLS_DHE_RSA_WITH_AES_256_CBC_SHA) ->
- "DHE-RSA-AES256-SHA";
-openssl_suite_name(?TLS_DHE_DSS_WITH_AES_256_CBC_SHA) ->
- "DHE-DSS-AES256-SHA";
-openssl_suite_name(?TLS_RSA_WITH_AES_256_CBC_SHA) ->
- "AES256-SHA";
-openssl_suite_name(?TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA) ->
- "EDH-RSA-DES-CBC3-SHA";
-openssl_suite_name(?TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA) ->
- "EDH-DSS-DES-CBC3-SHA";
-openssl_suite_name(?TLS_RSA_WITH_3DES_EDE_CBC_SHA) ->
- "DES-CBC3-SHA";
-openssl_suite_name( ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA) ->
- "DHE-RSA-AES128-SHA";
-openssl_suite_name(?TLS_DHE_DSS_WITH_AES_128_CBC_SHA) ->
- "DHE-DSS-AES128-SHA";
-openssl_suite_name(?TLS_RSA_WITH_AES_128_CBC_SHA) ->
- "AES128-SHA";
-openssl_suite_name(?TLS_RSA_WITH_RC4_128_SHA) ->
- "RC4-SHA";
-openssl_suite_name(?TLS_RSA_WITH_RC4_128_MD5) ->
- "RC4-MD5";
-openssl_suite_name(?TLS_DHE_RSA_WITH_DES_CBC_SHA) ->
- "EDH-RSA-DES-CBC-SHA";
-openssl_suite_name(?TLS_RSA_WITH_DES_CBC_SHA) ->
- "DES-CBC-SHA";
-openssl_suite_name(?TLS_RSA_WITH_NULL_SHA256) ->
- "NULL-SHA256";
-openssl_suite_name(?TLS_RSA_WITH_AES_128_CBC_SHA256) ->
- "AES128-SHA256";
-openssl_suite_name(?TLS_RSA_WITH_AES_256_CBC_SHA256) ->
- "AES256-SHA256";
-openssl_suite_name(?TLS_DH_DSS_WITH_AES_128_CBC_SHA256) ->
- "DH-DSS-AES128-SHA256";
-openssl_suite_name(?TLS_DH_RSA_WITH_AES_128_CBC_SHA256) ->
- "DH-RSA-AES128-SHA256";
-openssl_suite_name(?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256) ->
- "DHE-DSS-AES128-SHA256";
-openssl_suite_name(?TLS_DHE_RSA_WITH_AES_128_CBC_SHA256) ->
- "DHE-RSA-AES128-SHA256";
-openssl_suite_name(?TLS_DH_DSS_WITH_AES_256_CBC_SHA256) ->
- "DH-DSS-AES256-SHA256";
-openssl_suite_name(?TLS_DH_RSA_WITH_AES_256_CBC_SHA256) ->
- "DH-RSA-AES256-SHA256";
-openssl_suite_name(?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256) ->
- "DHE-DSS-AES256-SHA256";
-openssl_suite_name(?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256) ->
- "DHE-RSA-AES256-SHA256";
-
-%%% PSK Cipher Suites RFC 4279
-
-openssl_suite_name(?TLS_PSK_WITH_AES_256_CBC_SHA) ->
- "PSK-AES256-CBC-SHA";
-openssl_suite_name(?TLS_PSK_WITH_3DES_EDE_CBC_SHA) ->
- "PSK-3DES-EDE-CBC-SHA";
-openssl_suite_name(?TLS_PSK_WITH_AES_128_CBC_SHA) ->
- "PSK-AES128-CBC-SHA";
-openssl_suite_name(?TLS_PSK_WITH_RC4_128_SHA) ->
- "PSK-RC4-SHA";
-
-%%% SRP Cipher Suites RFC 5054
-
-openssl_suite_name(?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA) ->
- "SRP-RSA-3DES-EDE-CBC-SHA";
-openssl_suite_name(?TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA) ->
- "SRP-DSS-3DES-EDE-CBC-SHA";
-openssl_suite_name(?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA) ->
- "SRP-RSA-AES-128-CBC-SHA";
-openssl_suite_name(?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA) ->
- "SRP-DSS-AES-128-CBC-SHA";
-openssl_suite_name(?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA) ->
- "SRP-RSA-AES-256-CBC-SHA";
-openssl_suite_name(?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA) ->
- "SRP-DSS-AES-256-CBC-SHA";
-
-%% RFC 4492 EC TLS suites
-openssl_suite_name(?TLS_ECDH_ECDSA_WITH_RC4_128_SHA) ->
- "ECDH-ECDSA-RC4-SHA";
-openssl_suite_name(?TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA) ->
- "ECDH-ECDSA-DES-CBC3-SHA";
-openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA) ->
- "ECDH-ECDSA-AES128-SHA";
-openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA) ->
- "ECDH-ECDSA-AES256-SHA";
-
-openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_RC4_128_SHA) ->
- "ECDHE-ECDSA-RC4-SHA";
-openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA) ->
- "ECDHE-ECDSA-DES-CBC3-SHA";
-openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA) ->
- "ECDHE-ECDSA-AES128-SHA";
-openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA) ->
- "ECDHE-ECDSA-AES256-SHA";
-
-openssl_suite_name(?TLS_ECDH_RSA_WITH_RC4_128_SHA) ->
- "ECDH-RSA-RC4-SHA";
-openssl_suite_name(?TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA) ->
- "ECDH-RSA-DES-CBC3-SHA";
-openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA) ->
- "ECDH-RSA-AES128-SHA";
-openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA) ->
- "ECDH-RSA-AES256-SHA";
-
-openssl_suite_name(?TLS_ECDHE_RSA_WITH_RC4_128_SHA) ->
- "ECDHE-RSA-RC4-SHA";
-openssl_suite_name(?TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA) ->
- "ECDHE-RSA-DES-CBC3-SHA";
-openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) ->
- "ECDHE-RSA-AES128-SHA";
-openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) ->
- "ECDHE-RSA-AES256-SHA";
-
-%% RFC 5289 EC TLS suites
-openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256) ->
- "ECDHE-ECDSA-AES128-SHA256";
-openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384) ->
- "ECDHE-ECDSA-AES256-SHA384";
-openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256) ->
- "ECDH-ECDSA-AES128-SHA256";
-openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384) ->
- "ECDH-ECDSA-AES256-SHA384";
-openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) ->
- "ECDHE-RSA-AES128-SHA256";
-openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) ->
- "ECDHE-RSA-AES256-SHA384";
-openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256) ->
- "ECDH-RSA-AES128-SHA256";
-openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384) ->
- "ECDH-RSA-AES256-SHA384";
-
-%% RFC 5288 AES-GCM Cipher Suites
-openssl_suite_name(?TLS_RSA_WITH_AES_128_GCM_SHA256) ->
- "AES128-GCM-SHA256";
-openssl_suite_name(?TLS_RSA_WITH_AES_256_GCM_SHA384) ->
- "AES256-GCM-SHA384";
-openssl_suite_name(?TLS_DHE_RSA_WITH_AES_128_GCM_SHA256) ->
- "DHE-RSA-AES128-GCM-SHA256";
-openssl_suite_name(?TLS_DHE_RSA_WITH_AES_256_GCM_SHA384) ->
- "DHE-RSA-AES256-GCM-SHA384";
-openssl_suite_name(?TLS_DH_RSA_WITH_AES_128_GCM_SHA256) ->
- "DH-RSA-AES128-GCM-SHA256";
-openssl_suite_name(?TLS_DH_RSA_WITH_AES_256_GCM_SHA384) ->
- "DH-RSA-AES256-GCM-SHA384";
-openssl_suite_name(?TLS_DHE_DSS_WITH_AES_128_GCM_SHA256) ->
- "DHE-DSS-AES128-GCM-SHA256";
-openssl_suite_name(?TLS_DHE_DSS_WITH_AES_256_GCM_SHA384) ->
- "DHE-DSS-AES256-GCM-SHA384";
-openssl_suite_name(?TLS_DH_DSS_WITH_AES_128_GCM_SHA256) ->
- "DH-DSS-AES128-GCM-SHA256";
-openssl_suite_name(?TLS_DH_DSS_WITH_AES_256_GCM_SHA384) ->
- "DH-DSS-AES256-GCM-SHA384";
-
-%% RFC 5289 ECC AES-GCM Cipher Suites
-openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) ->
- "ECDHE-ECDSA-AES128-GCM-SHA256";
-openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) ->
- "ECDHE-ECDSA-AES256-GCM-SHA384";
-openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256) ->
- "ECDH-ECDSA-AES128-GCM-SHA256";
-openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384) ->
- "ECDH-ECDSA-AES256-GCM-SHA384";
-openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) ->
- "ECDHE-RSA-AES128-GCM-SHA256";
-openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) ->
- "ECDHE-RSA-AES256-GCM-SHA384";
-openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256) ->
- "ECDH-RSA-AES128-GCM-SHA256";
-openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384) ->
- "ECDH-RSA-AES256-GCM-SHA384";
-
-%% No oppenssl name
-openssl_suite_name(Cipher) ->
- suite_definition(Cipher).
-
-%%--------------------------------------------------------------------
--spec filter(undefined | binary(), [cipher_suite()], ssl_record:ssl_version()) -> [cipher_suite()].
+-spec filter(undefined | binary(), [ssl_cipher_format:cipher_suite()],
+ ssl_record:ssl_version()) -> [ssl_cipher_format:cipher_suite()].
%%
%% Description: Select the cipher suites that can be used together with the
%% supplied certificate. (Server side functionality)
@@ -2262,8 +538,8 @@ filter(DerCert, Ciphers0, Version) ->
filter_suites_signature(Sign, Ciphers, Version).
%%--------------------------------------------------------------------
--spec filter_suites([erl_cipher_suite()] | [cipher_suite()], map()) ->
- [erl_cipher_suite()] | [cipher_suite()].
+-spec filter_suites([ssl_cipher_format:erl_cipher_suite()] | [ssl_cipher_format:cipher_suite()], map()) ->
+ [ssl_cipher_format:erl_cipher_suite()] | [ssl_cipher_format:cipher_suite()].
%%
%% Description: Filter suites using supplied filter funs
%%-------------------------------------------------------------------
@@ -2286,11 +562,11 @@ filter_suite(#{key_exchange := KeyExchange,
all_filters(Hash, HashFilters) andalso
all_filters(Prf, PrfFilters);
filter_suite(Suite, Filters) ->
- filter_suite(suite_definition(Suite), Filters).
+ filter_suite(ssl_cipher_format:suite_definition(Suite), Filters).
%%--------------------------------------------------------------------
--spec filter_suites([erl_cipher_suite()] | [cipher_suite()]) ->
- [erl_cipher_suite()] | [cipher_suite()].
+-spec filter_suites([ssl_cipher_format:erl_cipher_suite()] | [ssl_cipher_format:cipher_suite()]) ->
+ [ssl_cipher_format:erl_cipher_suite()] | [ssl_cipher_format:cipher_suite()].
%%
%% Description: Filter suites for algorithms supported by crypto.
%%-------------------------------------------------------------------
@@ -2582,6 +858,61 @@ sign_algorithm(?ECDSA) -> ecdsa;
sign_algorithm(Other) when is_integer(Other) andalso ((Other >= 4) and (Other =< 223)) -> unassigned;
sign_algorithm(Other) when is_integer(Other) andalso ((Other >= 224) and (Other =< 255)) -> Other.
+
+signature_scheme(rsa_pkcs1_sha256) -> ?RSA_PKCS1_SHA256;
+signature_scheme(rsa_pkcs1_sha384) -> ?RSA_PKCS1_SHA384;
+signature_scheme(rsa_pkcs1_sha512) -> ?RSA_PKCS1_SHA512;
+signature_scheme(ecdsa_secp256r1_sha256) -> ?ECDSA_SECP256R1_SHA256;
+signature_scheme(ecdsa_secp384r1_sha384) -> ?ECDSA_SECP384R1_SHA384;
+signature_scheme(ecdsa_secp521r1_sha512) -> ?ECDSA_SECP521R1_SHA512;
+signature_scheme(rsa_pss_rsae_sha256) -> ?RSA_PSS_RSAE_SHA256;
+signature_scheme(rsa_pss_rsae_sha384) -> ?RSA_PSS_RSAE_SHA384;
+signature_scheme(rsa_pss_rsae_sha512) -> ?RSA_PSS_RSAE_SHA512;
+signature_scheme(ed25519) -> ?ED25519;
+signature_scheme(ed448) -> ?ED448;
+signature_scheme(rsa_pss_pss_sha256) -> ?RSA_PSS_PSS_SHA256;
+signature_scheme(rsa_pss_pss_sha384) -> ?RSA_PSS_PSS_SHA384;
+signature_scheme(rsa_pss_pss_sha512) -> ?RSA_PSS_PSS_SHA512;
+signature_scheme(rsa_pkcs1_sha1) -> ?RSA_PKCS1_SHA1;
+signature_scheme(ecdsa_sha1) -> ?ECDSA_SHA1;
+signature_scheme(?RSA_PKCS1_SHA256) -> rsa_pkcs1_sha256;
+signature_scheme(?RSA_PKCS1_SHA384) -> rsa_pkcs1_sha384;
+signature_scheme(?RSA_PKCS1_SHA512) -> rsa_pkcs1_sha512;
+signature_scheme(?ECDSA_SECP256R1_SHA256) -> ecdsa_secp256r1_sha256;
+signature_scheme(?ECDSA_SECP384R1_SHA384) -> ecdsa_secp384r1_sha384;
+signature_scheme(?ECDSA_SECP521R1_SHA512) -> ecdsa_secp521r1_sha512;
+signature_scheme(?RSA_PSS_RSAE_SHA256) -> rsa_pss_rsae_sha256;
+signature_scheme(?RSA_PSS_RSAE_SHA384) -> rsa_pss_rsae_sha384;
+signature_scheme(?RSA_PSS_RSAE_SHA512) -> rsa_pss_rsae_sha512;
+signature_scheme(?ED25519) -> ed25519;
+signature_scheme(?ED448) -> ed448;
+signature_scheme(?RSA_PSS_PSS_SHA256) -> rsa_pss_pss_sha256;
+signature_scheme(?RSA_PSS_PSS_SHA384) -> rsa_pss_pss_sha384;
+signature_scheme(?RSA_PSS_PSS_SHA512) -> rsa_pss_pss_sha512;
+signature_scheme(?RSA_PKCS1_SHA1) -> rsa_pkcs1_sha1;
+signature_scheme(?ECDSA_SHA1) -> ecdsa_sha1;
+signature_scheme(_) -> unassigned.
+%% TODO: reserved code points?
+
+scheme_to_components(rsa_pkcs1_sha256) -> {sha256, rsa_pkcs1, undefined};
+scheme_to_components(rsa_pkcs1_sha384) -> {sha384, rsa_pkcs1, undefined};
+scheme_to_components(rsa_pkcs1_sha512) -> {sha512, rsa_pkcs1, undefined};
+scheme_to_components(ecdsa_secp256r1_sha256) -> {sha256, ecdsa, secp256r1};
+scheme_to_components(ecdsa_secp384r1_sha384) -> {sha384, ecdsa, secp384r1};
+scheme_to_components(ecdsa_secp521r1_sha512) -> {sha512, ecdsa, secp521r1};
+scheme_to_components(rsa_pss_rsae_sha256) -> {sha256, rsa_pss_rsae, undefined};
+scheme_to_components(rsa_pss_rsae_sha384) -> {sha384, rsa_pss_rsae, undefined};
+scheme_to_components(rsa_pss_rsae_sha512) -> {sha512, rsa_pss_rsae, undefined};
+%% scheme_to_components(ed25519) -> {undefined, undefined, undefined};
+%% scheme_to_components(ed448) -> {undefined, undefined, undefined};
+scheme_to_components(rsa_pss_pss_sha256) -> {sha256, rsa_pss_pss, undefined};
+scheme_to_components(rsa_pss_pss_sha384) -> {sha384, rsa_pss_pss, undefined};
+scheme_to_components(rsa_pss_pss_sha512) -> {sha512, rsa_pss_pss, undefined};
+scheme_to_components(rsa_pkcs1_sha1) -> {sha1, rsa_pkcs1, undefined};
+scheme_to_components(ecdsa_sha1) -> {sha1, ecdsa, undefined}.
+
+
+
hash_size(null) ->
0;
%% The AEAD MAC hash size is not used in the context
diff --git a/lib/ssl/src/ssl_cipher.hrl b/lib/ssl/src/ssl_cipher.hrl
index ba6a98b92a..1febc52e43 100644
--- a/lib/ssl/src/ssl_cipher.hrl
+++ b/lib/ssl/src/ssl_cipher.hrl
@@ -610,4 +610,21 @@
%% TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = {0xcc, 0x15}
-define(TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, <<?BYTE(16#CC), ?BYTE(16#15)>>).
+%%% TLS 1.3 cipher suites RFC8446
+
+%% TLS_AES_128_GCM_SHA256 = {0x13,0x01}
+-define(TLS_AES_128_GCM_SHA256, <<?BYTE(16#13), ?BYTE(16#01)>>).
+
+%% TLS_AES_256_GCM_SHA384 = {0x13,0x02}
+-define(TLS_AES_256_GCM_SHA384, <<?BYTE(16#13),?BYTE(16#02)>>).
+
+%% TLS_CHACHA20_POLY1305_SHA256 = {0x13,0x03}
+-define(TLS_CHACHA20_POLY1305_SHA256, <<?BYTE(16#13),?BYTE(16#03)>>).
+
+%% %% TLS_AES_128_CCM_SHA256 = {0x13,0x04}
+%% -define(TLS_AES_128_CCM_SHA256, <<?BYTE(16#13), ?BYTE(16#04)>>).
+
+%% %% TLS_AES_128_CCM_8_SHA256 = {0x13,0x05}
+%% -define(TLS_AES_128_CCM_8_SHA256, <<?BYTE(16#13),?BYTE(16#05)>>).
+
-endif. % -ifdef(ssl_cipher).
diff --git a/lib/ssl/src/ssl_cipher_format.erl b/lib/ssl/src/ssl_cipher_format.erl
new file mode 100644
index 0000000000..6e480eef45
--- /dev/null
+++ b/lib/ssl/src/ssl_cipher_format.erl
@@ -0,0 +1,1854 @@
+%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose: Convert between diffrent cipher suite representations
+%%
+%%----------------------------------------------------------------------
+-module(ssl_cipher_format).
+
+-include("ssl_cipher.hrl").
+-include("ssl_internal.hrl").
+-include_lib("public_key/include/public_key.hrl").
+
+-export_type([cipher_suite/0,
+ erl_cipher_suite/0, old_erl_cipher_suite/0, openssl_cipher_suite/0,
+ hash/0, key_algo/0, sign_algo/0]).
+
+-type cipher() :: null |rc4_128 | des_cbc | '3des_ede_cbc' | aes_128_cbc | aes_256_cbc | aes_128_gcm | aes_256_gcm | chacha20_poly1305.
+-type hash() :: null | md5 | sha | sha224 | sha256 | sha384 | sha512.
+-type sign_algo() :: rsa | dsa | ecdsa.
+-type key_algo() :: null |
+ rsa |
+ dhe_rsa | dhe_dss |
+ ecdhe_ecdsa | ecdh_ecdsa | ecdh_rsa |
+ srp_rsa| srp_dss |
+ psk | dhe_psk | rsa_psk |
+ dh_anon | ecdh_anon | srp_anon |
+ any. %% TLS 1.3
+-type erl_cipher_suite() :: #{key_exchange := key_algo(),
+ cipher := cipher(),
+ mac := hash() | aead,
+ prf := hash() | default_prf %% Old cipher suites, version dependent
+ }.
+-type old_erl_cipher_suite() :: {key_algo(), cipher(), hash()} % Pre TLS 1.2
+ %% TLS 1.2, internally PRE TLS 1.2 will use default_prf
+ | {key_algo(), cipher(), hash(), hash() | default_prf}.
+-type cipher_suite() :: binary().
+-type openssl_cipher_suite() :: string().
+
+
+-export([suite_to_str/1, suite_definition/1, suite/1, erl_suite_definition/1,
+ openssl_suite/1, openssl_suite_name/1]).
+
+%%--------------------------------------------------------------------
+-spec suite_to_str(erl_cipher_suite()) -> string().
+%%
+%% Description: Return the string representation of a cipher suite.
+%%--------------------------------------------------------------------
+suite_to_str(#{key_exchange := null,
+ cipher := null,
+ mac := null,
+ prf := null}) ->
+ "TLS_EMPTY_RENEGOTIATION_INFO_SCSV";
+suite_to_str(#{key_exchange := any,
+ cipher := Cipher,
+ mac := aead,
+ prf := PRF}) ->
+ "TLS_" ++ string:to_upper(atom_to_list(Cipher)) ++
+ "_" ++ string:to_upper(atom_to_list(PRF));
+suite_to_str(#{key_exchange := Kex,
+ cipher := Cipher,
+ mac := aead,
+ prf := PRF}) ->
+ "TLS_" ++ string:to_upper(atom_to_list(Kex)) ++
+ "_WITH_" ++ string:to_upper(atom_to_list(Cipher)) ++
+ "_" ++ string:to_upper(atom_to_list(PRF));
+suite_to_str(#{key_exchange := Kex,
+ cipher := Cipher,
+ mac := Mac}) ->
+ "TLS_" ++ string:to_upper(atom_to_list(Kex)) ++
+ "_WITH_" ++ string:to_upper(atom_to_list(Cipher)) ++
+ "_" ++ string:to_upper(atom_to_list(Mac)).
+
+%%--------------------------------------------------------------------
+-spec suite_definition(cipher_suite()) -> erl_cipher_suite().
+%%
+%% Description: Return erlang cipher suite definition.
+%% Note: Currently not supported suites are commented away.
+%% They should be supported or removed in the future.
+%%-------------------------------------------------------------------
+%% TLS v1.1 suites
+suite_definition(?TLS_NULL_WITH_NULL_NULL) ->
+ #{key_exchange => null,
+ cipher => null,
+ mac => null,
+ prf => null};
+%% RFC 5746 - Not a real cipher suite used to signal empty "renegotiation_info" extension
+%% to avoid handshake failure from old servers that do not ignore
+%% hello extension data as they should.
+suite_definition(?TLS_EMPTY_RENEGOTIATION_INFO_SCSV) ->
+ #{key_exchange => null,
+ cipher => null,
+ mac => null,
+ prf => null};
+suite_definition(?TLS_RSA_WITH_RC4_128_MD5) ->
+ #{key_exchange => rsa,
+ cipher => rc4_128,
+ mac => md5,
+ prf => default_prf};
+suite_definition(?TLS_RSA_WITH_RC4_128_SHA) ->
+ #{key_exchange => rsa,
+ cipher => rc4_128,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_RSA_WITH_DES_CBC_SHA) ->
+ #{key_exchange => rsa,
+ cipher => des_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_RSA_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => rsa,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_DSS_WITH_DES_CBC_SHA) ->
+ #{key_exchange => dhe_dss,
+ cipher => des_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => dhe_dss,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_RSA_WITH_DES_CBC_SHA) ->
+ #{key_exchange => dhe_rsa,
+ cipher => des_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => dhe_rsa,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+%%% TSL V1.1 AES suites
+suite_definition(?TLS_RSA_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => rsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_DSS_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => dhe_dss,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_RSA_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => dhe_rsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_RSA_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => rsa,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_DSS_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => dhe_dss,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_RSA_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => dhe_rsa,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+%% TLS v1.2 suites
+%% suite_definition(?TLS_RSA_WITH_NULL_SHA) ->
+%% {rsa, null, sha, default_prf};
+suite_definition(?TLS_RSA_WITH_AES_128_CBC_SHA256) ->
+ #{key_exchange => rsa,
+ cipher => aes_128_cbc,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_RSA_WITH_AES_256_CBC_SHA256) ->
+ #{key_exchange => rsa,
+ cipher => aes_256_cbc,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256) ->
+ #{key_exchange => dhe_dss,
+ cipher => aes_128_cbc,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_DHE_RSA_WITH_AES_128_CBC_SHA256) ->
+ #{key_exchange => dhe_rsa,
+ cipher => aes_128_cbc,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256) ->
+ #{key_exchange => dhe_dss,
+ cipher => aes_256_cbc,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256) ->
+ #{key_exchange => dhe_rsa,
+ cipher => aes_256_cbc,
+ mac => sha256,
+ prf => default_prf};
+%% not defined YET:
+%% TLS_DH_DSS_WITH_AES_128_CBC_SHA256 DH_DSS AES_128_CBC SHA256
+%% TLS_DH_RSA_WITH_AES_128_CBC_SHA256 DH_RSA AES_128_CBC SHA256
+%% TLS_DH_DSS_WITH_AES_256_CBC_SHA256 DH_DSS AES_256_CBC SHA256
+%% TLS_DH_RSA_WITH_AES_256_CBC_SHA256 DH_RSA AES_256_CBC SHA256
+%%% DH-ANON deprecated by TLS spec and not available
+%%% by default, but good for testing purposes.
+suite_definition(?TLS_DH_anon_WITH_RC4_128_MD5) ->
+ #{key_exchange => dh_anon,
+ cipher => rc4_128,
+ mac => md5,
+ prf => default_prf};
+suite_definition(?TLS_DH_anon_WITH_DES_CBC_SHA) ->
+ #{key_exchange => dh_anon,
+ cipher => des_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DH_anon_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => dh_anon,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DH_anon_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => dh_anon,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DH_anon_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => dh_anon,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DH_anon_WITH_AES_128_CBC_SHA256) ->
+ #{key_exchange => dh_anon,
+ cipher => aes_128_cbc,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_DH_anon_WITH_AES_256_CBC_SHA256) ->
+ #{key_exchange => dh_anon,
+ cipher => aes_256_cbc,
+ mac => sha256,
+ prf => default_prf};
+%%% PSK Cipher Suites RFC 4279
+suite_definition(?TLS_PSK_WITH_RC4_128_SHA) ->
+ #{key_exchange => psk,
+ cipher => rc4_128,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_PSK_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => psk,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_PSK_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => psk,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_PSK_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => psk,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_PSK_WITH_RC4_128_SHA) ->
+ #{key_exchange => dhe_psk,
+ cipher => rc4_128,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => dhe_psk,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_PSK_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => dhe_psk,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_PSK_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => dhe_psk,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_RSA_PSK_WITH_RC4_128_SHA) ->
+ #{key_exchange => rsa_psk,
+ cipher => rc4_128,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => rsa_psk,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_RSA_PSK_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => rsa_psk,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_RSA_PSK_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => rsa_psk,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+%%% PSK NULL Cipher Suites RFC 4785
+suite_definition(?TLS_PSK_WITH_NULL_SHA) ->
+ #{key_exchange => psk,
+ cipher => null,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_DHE_PSK_WITH_NULL_SHA) ->
+ #{key_exchange => dhe_psk,
+ cipher => null,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_RSA_PSK_WITH_NULL_SHA) ->
+ #{key_exchange => rsa_psk,
+ cipher => null,
+ mac => sha,
+ prf => default_prf};
+%%% TLS 1.2 PSK Cipher Suites RFC 5487
+suite_definition(?TLS_PSK_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => psk,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_PSK_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => psk,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+suite_definition(?TLS_DHE_PSK_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => dhe_psk,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_DHE_PSK_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => dhe_psk,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+suite_definition(?TLS_RSA_PSK_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => rsa_psk,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_RSA_PSK_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => rsa_psk,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+suite_definition(?TLS_PSK_WITH_AES_128_CBC_SHA256) ->
+ #{key_exchange => psk,
+ cipher => aes_128_cbc,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_PSK_WITH_AES_256_CBC_SHA384) ->
+ #{key_exchange => psk,
+ cipher => aes_256_cbc,
+ mac => sha384,
+ prf => default_prf};
+suite_definition(?TLS_DHE_PSK_WITH_AES_128_CBC_SHA256) ->
+ #{key_exchange => dhe_psk,
+ cipher => aes_128_cbc,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_DHE_PSK_WITH_AES_256_CBC_SHA384) ->
+ #{key_exchange => dhe_psk,
+ cipher => aes_256_cbc,
+ mac => sha384,
+ prf => default_prf};
+suite_definition(?TLS_RSA_PSK_WITH_AES_128_CBC_SHA256) ->
+ #{key_exchange => rsa_psk,
+ cipher => aes_128_cbc,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_RSA_PSK_WITH_AES_256_CBC_SHA384) ->
+ #{key_exchange => rsa_psk,
+ cipher => aes_256_cbc,
+ mac => sha384,
+ prf => default_prf};
+suite_definition(?TLS_PSK_WITH_NULL_SHA256) ->
+ #{key_exchange => psk,
+ cipher => null,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_PSK_WITH_NULL_SHA384) ->
+ #{key_exchange => psk,
+ cipher => null,
+ mac => sha384,
+ prf => default_prf};
+suite_definition(?TLS_DHE_PSK_WITH_NULL_SHA256) ->
+ #{key_exchange => dhe_psk,
+ cipher => null,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_DHE_PSK_WITH_NULL_SHA384) ->
+ #{key_exchange => dhe_psk,
+ cipher => null,
+ mac => sha384,
+ prf => default_prf};
+suite_definition(?TLS_RSA_PSK_WITH_NULL_SHA256) ->
+ #{key_exchange => rsa_psk,
+ cipher => null,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_RSA_PSK_WITH_NULL_SHA384) ->
+ #{key_exchange => rsa_psk,
+ cipher => null,
+ mac => sha384,
+ prf => default_prf};
+%%% ECDHE PSK Cipher Suites RFC 5489
+suite_definition(?TLS_ECDHE_PSK_WITH_RC4_128_SHA) ->
+ #{key_exchange => ecdhe_psk,
+ cipher => rc4_128,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => ecdhe_psk,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => ecdhe_psk,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => ecdhe_psk,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256) ->
+ #{key_exchange => ecdhe_psk,
+ cipher => aes_128_cbc,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384) ->
+ #{key_exchange => ecdhe_psk,
+ cipher => aes_256_cbc,
+ mac => sha384,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_PSK_WITH_NULL_SHA256) ->
+ #{key_exchange => ecdhe_psk,
+ cipher => null,
+ mac => sha256,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_PSK_WITH_NULL_SHA384) ->
+ #{key_exchange => ecdhe_psk,
+ cipher => null, mac => sha384,
+ prf => default_prf};
+%%% ECDHE_PSK with AES-GCM and AES-CCM Cipher Suites, draft-ietf-tls-ecdhe-psk-aead-05
+suite_definition(?TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => ecdhe_psk,
+ cipher => aes_128_gcm,
+ mac => null,
+ prf => sha256};
+suite_definition(?TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => ecdhe_psk,
+ cipher => aes_256_gcm,
+ mac => null,
+ prf => sha384};
+%% suite_definition(?TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256) ->
+%% #{key_exchange => ecdhe_psk,
+%% cipher => aes_128_ccm,
+%% mac => null,
+%% prf =>sha256};
+%% suite_definition(?TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256) ->
+%% #{key_exchange => ecdhe_psk,
+%% cipher => aes_256_ccm,
+%% mac => null,
+%% prf => sha256};
+%%% SRP Cipher Suites RFC 5054
+suite_definition(?TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => srp_anon,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => srp_rsa,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => srp_dss,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_SRP_SHA_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => srp_anon,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => srp_rsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => srp_dss,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_SRP_SHA_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => srp_anon,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => srp_rsa,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => srp_dss,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+%% RFC 4492 EC TLS suites
+suite_definition(?TLS_ECDH_ECDSA_WITH_NULL_SHA) ->
+ #{key_exchange => ecdh_ecdsa,
+ cipher => null,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_ECDSA_WITH_RC4_128_SHA) ->
+ #{key_exchange => ecdh_ecdsa,
+ cipher => rc4_128,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => ecdh_ecdsa,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => ecdh_ecdsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => ecdh_ecdsa,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_ECDSA_WITH_NULL_SHA) ->
+ #{key_exchange => ecdhe_ecdsa,
+ cipher => null,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_ECDSA_WITH_RC4_128_SHA) ->
+ #{key_exchange => ecdhe_ecdsa,
+ cipher => rc4_128,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => ecdhe_ecdsa,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => ecdhe_ecdsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => ecdhe_ecdsa,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_RSA_WITH_NULL_SHA) ->
+ #{key_exchange => ecdh_rsa,
+ cipher => null,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_RSA_WITH_RC4_128_SHA) ->
+ #{key_exchange => ecdh_rsa,
+ cipher => rc4_128,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => ecdh_rsa,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => ecdh_rsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => ecdh_rsa,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_RSA_WITH_NULL_SHA) ->
+ #{key_exchange => ecdhe_rsa,
+ cipher => null,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_RSA_WITH_RC4_128_SHA) ->
+ #{key_exchange => ecdhe_rsa,
+ cipher => rc4_128,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => ecdhe_rsa,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => ecdhe_rsa,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => ecdhe_rsa,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_anon_WITH_NULL_SHA) ->
+ #{key_exchange => ecdh_anon,
+ cipher => null,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_anon_WITH_RC4_128_SHA) ->
+ #{key_exchange => ecdh_anon,
+ cipher => rc4_128,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA) ->
+ #{key_exchange => ecdh_anon,
+ cipher => '3des_ede_cbc',
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_anon_WITH_AES_128_CBC_SHA) ->
+ #{key_exchange => ecdh_anon,
+ cipher => aes_128_cbc,
+ mac => sha,
+ prf => default_prf};
+suite_definition(?TLS_ECDH_anon_WITH_AES_256_CBC_SHA) ->
+ #{key_exchange => ecdh_anon,
+ cipher => aes_256_cbc,
+ mac => sha,
+ prf => default_prf};
+%% RFC 5289 EC TLS suites
+suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256) ->
+ #{key_exchange => ecdhe_ecdsa,
+ cipher => aes_128_cbc,
+ mac => sha256,
+ prf => sha256};
+suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384) ->
+ #{key_exchange => ecdhe_ecdsa,
+ cipher => aes_256_cbc,
+ mac => sha384,
+ prf => sha384};
+suite_definition(?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256) ->
+ #{key_exchange => ecdh_ecdsa,
+ cipher => aes_128_cbc,
+ mac => sha256,
+ prf => sha256};
+suite_definition(?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384) ->
+ #{key_exchange => ecdh_ecdsa,
+ cipher => aes_256_cbc,
+ mac => sha384,
+ prf => sha384};
+suite_definition(?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) ->
+ #{key_exchange => ecdhe_rsa,
+ cipher => aes_128_cbc,
+ mac => sha256,
+ prf => sha256};
+suite_definition(?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) ->
+ #{key_exchange => ecdhe_rsa,
+ cipher => aes_256_cbc,
+ mac => sha384,
+ prf => sha384};
+suite_definition(?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256) ->
+ #{key_exchange => ecdh_rsa,
+ cipher => aes_128_cbc,
+ mac => sha256,
+ prf => sha256};
+suite_definition(?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384) ->
+ #{key_exchange => ecdh_rsa,
+ cipher => aes_256_cbc,
+ mac => sha384,
+ prf => sha384};
+%% RFC 5288 AES-GCM Cipher Suites
+suite_definition(?TLS_RSA_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => rsa,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_RSA_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => rsa,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+suite_definition(?TLS_DHE_RSA_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => dhe_rsa,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_DHE_RSA_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => dhe_rsa,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+suite_definition(?TLS_DH_RSA_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => dh_rsa,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_DH_RSA_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => dh_rsa,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+suite_definition(?TLS_DHE_DSS_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => dhe_dss,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_DHE_DSS_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => dhe_dss,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+suite_definition(?TLS_DH_DSS_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => dh_dss,
+ cipher => aes_128_gcm,
+ mac => null,
+ prf => sha256};
+suite_definition(?TLS_DH_DSS_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => dh_dss,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+suite_definition(?TLS_DH_anon_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => dh_anon,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_DH_anon_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => dh_anon,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+%% RFC 5289 ECC AES-GCM Cipher Suites
+suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => ecdhe_ecdsa,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => ecdhe_ecdsa,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+suite_definition(?TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => ecdh_ecdsa,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => ecdh_ecdsa,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+suite_definition(?TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => ecdhe_rsa,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => ecdhe_rsa,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+suite_definition(?TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256) ->
+ #{key_exchange => ecdh_rsa,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384) ->
+ #{key_exchange => ecdh_rsa,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+%% draft-agl-tls-chacha20poly1305-04 Chacha20/Poly1305 Suites
+suite_definition(?TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256) ->
+ #{key_exchange => ecdhe_rsa,
+ cipher => chacha20_poly1305,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256) ->
+ #{key_exchange => ecdhe_ecdsa,
+ cipher => chacha20_poly1305,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256) ->
+ #{key_exchange => dhe_rsa,
+ cipher => chacha20_poly1305,
+ mac => aead,
+ prf => sha256};
+%% TLS 1.3 Cipher Suites RFC8446
+suite_definition(?TLS_AES_128_GCM_SHA256) ->
+ #{key_exchange => any,
+ cipher => aes_128_gcm,
+ mac => aead,
+ prf => sha256};
+suite_definition(?TLS_AES_256_GCM_SHA384) ->
+ #{key_exchange => any,
+ cipher => aes_256_gcm,
+ mac => aead,
+ prf => sha384};
+suite_definition(?TLS_CHACHA20_POLY1305_SHA256) ->
+ #{key_exchange => any,
+ cipher => chacha20_poly1305,
+ mac => aead,
+ prf => sha256}.
+%% suite_definition(?TLS_AES_128_CCM_SHA256) ->
+%% #{key_exchange => any,
+%% cipher => aes_128_ccm,
+%% mac => aead,
+%% prf => sha256};
+%% suite_definition(?TLS_AES_128_CCM_8_SHA256) ->
+%% #{key_exchange => any,
+%% cipher => aes_128_ccm_8,
+%% mac => aead,
+%% prf => sha256}.
+
+
+%%--------------------------------------------------------------------
+-spec erl_suite_definition(cipher_suite() | erl_cipher_suite()) -> old_erl_cipher_suite().
+%%
+%% Description: Return erlang cipher suite definition. Filters last value
+%% for now (compatibility reasons).
+%%--------------------------------------------------------------------
+erl_suite_definition(Bin) when is_binary(Bin) ->
+ erl_suite_definition(suite_definition(Bin));
+erl_suite_definition(#{key_exchange := KeyExchange, cipher := Cipher,
+ mac := Hash, prf := Prf}) ->
+ case Prf of
+ default_prf ->
+ {KeyExchange, Cipher, Hash};
+ _ ->
+ {KeyExchange, Cipher, Hash, Prf}
+ end.
+
+%%--------------------------------------------------------------------
+-spec suite(erl_cipher_suite()) -> cipher_suite().
+%%
+%% Description: Return TLS cipher suite definition.
+%%--------------------------------------------------------------------
+%% TLS v1.1 suites
+suite(#{key_exchange := rsa,
+ cipher := rc4_128,
+ mac := md5}) ->
+ ?TLS_RSA_WITH_RC4_128_MD5;
+suite(#{key_exchange := rsa,
+ cipher := rc4_128,
+ mac := sha}) ->
+ ?TLS_RSA_WITH_RC4_128_SHA;
+suite(#{key_exchange := rsa,
+ cipher := des_cbc,
+ mac := sha}) ->
+ ?TLS_RSA_WITH_DES_CBC_SHA;
+suite(#{key_exchange := rsa,
+ cipher :='3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_RSA_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := dhe_dss,
+ cipher:= des_cbc,
+ mac := sha}) ->
+ ?TLS_DHE_DSS_WITH_DES_CBC_SHA;
+suite(#{key_exchange := dhe_dss,
+ cipher:= '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := dhe_rsa,
+ cipher:= des_cbc,
+ mac := sha}) ->
+ ?TLS_DHE_RSA_WITH_DES_CBC_SHA;
+suite(#{key_exchange := dhe_rsa,
+ cipher:= '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := dh_anon,
+ cipher:= rc4_128,
+ mac := md5}) ->
+ ?TLS_DH_anon_WITH_RC4_128_MD5;
+suite(#{key_exchange := dh_anon,
+ cipher:= des_cbc,
+ mac := sha}) ->
+ ?TLS_DH_anon_WITH_DES_CBC_SHA;
+suite(#{key_exchange := dh_anon,
+ cipher:= '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_DH_anon_WITH_3DES_EDE_CBC_SHA;
+%%% TSL V1.1 AES suites
+suite(#{key_exchange := rsa,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_RSA_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := dhe_dss,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_DHE_DSS_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := dhe_rsa,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := dh_anon,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_DH_anon_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := rsa,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_RSA_WITH_AES_256_CBC_SHA;
+suite(#{key_exchange := dhe_dss,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_DHE_DSS_WITH_AES_256_CBC_SHA;
+suite(#{key_exchange := dhe_rsa,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
+suite(#{key_exchange := dh_anon,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_DH_anon_WITH_AES_256_CBC_SHA;
+%% TLS v1.2 suites
+suite(#{key_exchange := rsa,
+ cipher := aes_128_cbc,
+ mac := sha256}) ->
+ ?TLS_RSA_WITH_AES_128_CBC_SHA256;
+suite(#{key_exchange := rsa,
+ cipher := aes_256_cbc,
+ mac := sha256}) ->
+ ?TLS_RSA_WITH_AES_256_CBC_SHA256;
+suite(#{key_exchange := dhe_dss,
+ cipher := aes_128_cbc,
+ mac := sha256}) ->
+ ?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256;
+suite(#{key_exchange := dhe_rsa,
+ cipher := aes_128_cbc,
+ mac := sha256}) ->
+ ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA256;
+suite(#{key_exchange := dhe_dss,
+ cipher := aes_256_cbc,
+ mac := sha256}) ->
+ ?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256;
+suite(#{key_exchange := dhe_rsa,
+ cipher := aes_256_cbc,
+ mac := sha256}) ->
+ ?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256;
+suite(#{key_exchange := dh_anon,
+ cipher := aes_128_cbc,
+ mac := sha256}) ->
+ ?TLS_DH_anon_WITH_AES_128_CBC_SHA256;
+suite(#{key_exchange := dh_anon,
+ cipher := aes_256_cbc,
+ mac := sha256}) ->
+ ?TLS_DH_anon_WITH_AES_256_CBC_SHA256;
+%%% PSK Cipher Suites RFC 4279
+suite(#{key_exchange := psk,
+ cipher := rc4_128,
+ mac := sha}) ->
+ ?TLS_PSK_WITH_RC4_128_SHA;
+suite(#{key_exchange := psk,
+ cipher := '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_PSK_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := psk,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_PSK_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := psk,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_PSK_WITH_AES_256_CBC_SHA;
+suite(#{key_exchange := dhe_psk,
+ cipher := rc4_128,
+ mac := sha}) ->
+ ?TLS_DHE_PSK_WITH_RC4_128_SHA;
+suite(#{key_exchange := dhe_psk,
+ cipher := '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := dhe_psk,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_DHE_PSK_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := dhe_psk,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_DHE_PSK_WITH_AES_256_CBC_SHA;
+suite(#{key_exchange := rsa_psk,
+ cipher := rc4_128,
+ mac := sha}) ->
+ ?TLS_RSA_PSK_WITH_RC4_128_SHA;
+suite(#{key_exchange := rsa_psk,
+ cipher := '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := rsa_psk,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_RSA_PSK_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := rsa_psk,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_RSA_PSK_WITH_AES_256_CBC_SHA;
+%%% PSK NULL Cipher Suites RFC 4785
+suite(#{key_exchange := psk,
+ cipher := null,
+ mac := sha}) ->
+ ?TLS_PSK_WITH_NULL_SHA;
+suite(#{key_exchange := dhe_psk,
+ cipher := null,
+ mac := sha}) ->
+ ?TLS_DHE_PSK_WITH_NULL_SHA;
+suite(#{key_exchange := rsa_psk,
+ cipher := null,
+ mac := sha}) ->
+ ?TLS_RSA_PSK_WITH_NULL_SHA;
+%%% TLS 1.2 PSK Cipher Suites RFC 5487
+suite(#{key_exchange := psk,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_PSK_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := psk,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_PSK_WITH_AES_256_GCM_SHA384;
+suite(#{key_exchange := dhe_psk,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_DHE_PSK_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := dhe_psk,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_DHE_PSK_WITH_AES_256_GCM_SHA384;
+suite(#{key_exchange := rsa_psk,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_RSA_PSK_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := rsa_psk,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_RSA_PSK_WITH_AES_256_GCM_SHA384;
+suite(#{key_exchange := psk,
+ cipher := aes_128_cbc,
+ mac := sha256}) ->
+ ?TLS_PSK_WITH_AES_128_CBC_SHA256;
+suite(#{key_exchange := psk,
+ cipher := aes_256_cbc,
+ mac := sha384}) ->
+ ?TLS_PSK_WITH_AES_256_CBC_SHA384;
+suite(#{key_exchange := dhe_psk,
+ cipher := aes_128_cbc,
+ mac := sha256}) ->
+ ?TLS_DHE_PSK_WITH_AES_128_CBC_SHA256;
+suite(#{key_exchange := dhe_psk,
+ cipher := aes_256_cbc,
+ mac := sha384}) ->
+ ?TLS_DHE_PSK_WITH_AES_256_CBC_SHA384;
+suite(#{key_exchange := rsa_psk,
+ cipher := aes_128_cbc,
+ mac := sha256}) ->
+ ?TLS_RSA_PSK_WITH_AES_128_CBC_SHA256;
+suite(#{key_exchange := rsa_psk,
+ cipher := aes_256_cbc,
+ mac := sha384}) ->
+ ?TLS_RSA_PSK_WITH_AES_256_CBC_SHA384;
+suite(#{key_exchange := psk,
+ cipher := null,
+ mac := sha256}) ->
+ ?TLS_PSK_WITH_NULL_SHA256;
+suite(#{key_exchange := psk,
+ cipher := null,
+ mac := sha384}) ->
+ ?TLS_PSK_WITH_NULL_SHA384;
+suite(#{key_exchange := dhe_psk,
+ cipher := null,
+ mac := sha256}) ->
+ ?TLS_DHE_PSK_WITH_NULL_SHA256;
+suite(#{key_exchange := dhe_psk,
+ cipher := null,
+ mac := sha384}) ->
+ ?TLS_DHE_PSK_WITH_NULL_SHA384;
+suite(#{key_exchange := rsa_psk,
+ cipher := null,
+ mac := sha256}) ->
+ ?TLS_RSA_PSK_WITH_NULL_SHA256;
+suite(#{key_exchange := rsa_psk,
+ cipher := null,
+ mac := sha384}) ->
+ ?TLS_RSA_PSK_WITH_NULL_SHA384;
+%%% ECDHE PSK Cipher Suites RFC 5489
+suite(#{key_exchange := ecdhe_psk,
+ cipher := rc4_128,
+ mac := sha}) ->
+ ?TLS_ECDHE_PSK_WITH_RC4_128_SHA;
+suite(#{key_exchange := ecdhe_psk,
+ cipher :='3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := ecdhe_psk,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := ecdhe_psk,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA;
+suite(#{key_exchange := ecdhe_psk,
+ cipher := aes_128_cbc,
+ mac := sha256}) ->
+ ?TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256;
+suite(#{key_exchange := ecdhe_psk,
+ cipher := aes_256_cbc,
+ mac := sha384}) ->
+ ?TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384;
+suite(#{key_exchange := ecdhe_psk,
+ cipher := null,
+ mac := sha256}) ->
+ ?TLS_ECDHE_PSK_WITH_NULL_SHA256;
+suite(#{key_exchange := ecdhe_psk,
+ cipher := null,
+ mac := sha384}) ->
+ ?TLS_ECDHE_PSK_WITH_NULL_SHA384;
+%%% ECDHE_PSK with AES-GCM and AES-CCM Cipher Suites, draft-ietf-tls-ecdhe-psk-aead-05
+suite(#{key_exchange := ecdhe_psk,
+ cipher := aes_128_gcm,
+ mac := null,
+ prf := sha256}) ->
+ ?TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := ecdhe_psk,
+ cipher := aes_256_gcm,
+ mac := null,
+ prf := sha384}) ->
+ ?TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384;
+ %% suite(#{key_exchange := ecdhe_psk,
+ %% cipher := aes_128_ccm,
+ %% mac := null,
+ %% prf := sha256}) ->
+ %% ?TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256;
+ %% suite(#{key_exchange := ecdhe_psk,
+ %% cipher := aes_256_ccm,
+ %% mac := null,
+ %% prf := sha256}) ->
+ %% ?TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256;
+%%% SRP Cipher Suites RFC 5054
+suite(#{key_exchange := srp_anon,
+ cipher := '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := srp_rsa,
+ cipher := '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := srp_dss,
+ cipher := '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := srp_anon,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_SRP_SHA_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := srp_rsa,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := srp_dss,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := srp_anon,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_SRP_SHA_WITH_AES_256_CBC_SHA;
+suite(#{key_exchange := srp_rsa,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA;
+suite(#{key_exchange := srp_dss,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA;
+%%% RFC 4492 EC TLS suites
+suite(#{key_exchange := ecdh_ecdsa,
+ cipher := null,
+ mac := sha}) ->
+ ?TLS_ECDH_ECDSA_WITH_NULL_SHA;
+suite(#{key_exchange := ecdh_ecdsa,
+ cipher := rc4_128,
+ mac := sha}) ->
+ ?TLS_ECDH_ECDSA_WITH_RC4_128_SHA;
+suite(#{key_exchange := ecdh_ecdsa,
+ cipher := '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := ecdh_ecdsa,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := ecdh_ecdsa,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA;
+suite(#{key_exchange := ecdhe_ecdsa,
+ cipher := null,
+ mac := sha}) ->
+ ?TLS_ECDHE_ECDSA_WITH_NULL_SHA;
+suite(#{key_exchange := ecdhe_ecdsa,
+ cipher := rc4_128,
+ mac := sha}) ->
+ ?TLS_ECDHE_ECDSA_WITH_RC4_128_SHA;
+suite(#{key_exchange := ecdhe_ecdsa,
+ cipher := '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := ecdhe_ecdsa,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := ecdhe_ecdsa,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA;
+suite(#{key_exchange := ecdh_rsa,
+ cipher := null,
+ mac := sha}) ->
+ ?TLS_ECDH_RSA_WITH_NULL_SHA;
+suite(#{key_exchange := ecdh_rsa,
+ cipher := rc4_128,
+ mac := sha}) ->
+ ?TLS_ECDH_RSA_WITH_RC4_128_SHA;
+suite(#{key_exchange := ecdh_rsa,
+ cipher := '3des_ede_cbc', mac := sha}) ->
+ ?TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := ecdh_rsa,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := ecdh_rsa,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA;
+suite(#{key_exchange := ecdhe_rsa,
+ cipher := null,
+ mac := sha}) ->
+ ?TLS_ECDHE_RSA_WITH_NULL_SHA;
+suite(#{key_exchange := ecdhe_rsa,
+ cipher := rc4_128,
+ mac := sha}) ->
+ ?TLS_ECDHE_RSA_WITH_RC4_128_SHA;
+suite(#{key_exchange := ecdhe_rsa,
+ cipher := '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := ecdhe_rsa,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := ecdhe_rsa,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA;
+suite(#{key_exchange := ecdh_anon,
+ cipher := null,
+ mac := sha}) ->
+ ?TLS_ECDH_anon_WITH_NULL_SHA;
+suite(#{key_exchange := ecdh_anon,
+ cipher := rc4_128,
+ mac := sha}) ->
+ ?TLS_ECDH_anon_WITH_RC4_128_SHA;
+suite(#{key_exchange := ecdh_anon,
+ cipher := '3des_ede_cbc',
+ mac := sha}) ->
+ ?TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA;
+suite(#{key_exchange := ecdh_anon,
+ cipher := aes_128_cbc,
+ mac := sha}) ->
+ ?TLS_ECDH_anon_WITH_AES_128_CBC_SHA;
+suite(#{key_exchange := ecdh_anon,
+ cipher := aes_256_cbc,
+ mac := sha}) ->
+ ?TLS_ECDH_anon_WITH_AES_256_CBC_SHA;
+%%% RFC 5289 EC TLS suites
+suite(#{key_exchange := ecdhe_ecdsa,
+ cipher := aes_128_cbc,
+ mac:= sha256,
+ prf := sha256}) ->
+ ?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256;
+suite(#{key_exchange := ecdhe_ecdsa,
+ cipher := aes_256_cbc,
+ mac := sha384,
+ prf := sha384}) ->
+ ?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384;
+suite(#{key_exchange := ecdh_ecdsa,
+ cipher := aes_128_cbc,
+ mac := sha256,
+ prf := sha256}) ->
+ ?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256;
+suite(#{key_exchange := ecdh_ecdsa,
+ cipher := aes_256_cbc,
+ mac := sha384,
+ prf := sha384}) ->
+ ?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384;
+suite(#{key_exchange := ecdhe_rsa,
+ cipher := aes_128_cbc,
+ mac := sha256,
+ prf := sha256}) ->
+ ?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256;
+suite(#{key_exchange := ecdhe_rsa,
+ cipher := aes_256_cbc,
+ mac := sha384,
+ prf := sha384}) ->
+ ?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384;
+suite(#{key_exchange := ecdh_rsa,
+ cipher := aes_128_cbc,
+ mac := sha256,
+ prf := sha256}) ->
+ ?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256;
+suite(#{key_exchange := ecdh_rsa,
+ cipher := aes_256_cbc,
+ mac := sha384,
+ prf := sha384}) ->
+ ?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384;
+%% RFC 5288 AES-GCM Cipher Suites
+suite(#{key_exchange := rsa,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_RSA_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := rsa,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_RSA_WITH_AES_256_GCM_SHA384;
+suite(#{key_exchange := dhe_rsa,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_DHE_RSA_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := dhe_rsa,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_DHE_RSA_WITH_AES_256_GCM_SHA384;
+suite(#{key_exchange := dh_rsa,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_DH_RSA_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := dh_rsa,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_DH_RSA_WITH_AES_256_GCM_SHA384;
+suite(#{key_exchange := dhe_dss,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_DHE_DSS_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := dhe_dss,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_DHE_DSS_WITH_AES_256_GCM_SHA384;
+suite(#{key_exchange := dh_dss,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_DH_DSS_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := dh_dss,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_DH_DSS_WITH_AES_256_GCM_SHA384;
+suite(#{key_exchange := dh_anon,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_DH_anon_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := dh_anon,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_DH_anon_WITH_AES_256_GCM_SHA384;
+%% RFC 5289 ECC AES-GCM Cipher Suites
+suite(#{key_exchange := ecdhe_ecdsa,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := ecdhe_ecdsa,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384;
+suite(#{key_exchange := ecdh_ecdsa,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := ecdh_ecdsa,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384;
+suite(#{key_exchange := ecdhe_rsa,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := ecdhe_rsa,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384;
+suite(#{key_exchange := ecdh_rsa,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256;
+suite(#{key_exchange := ecdh_rsa,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384;
+%% draft-agl-tls-chacha20poly1305-04 Chacha20/Poly1305 Suites
+suite(#{key_exchange := ecdhe_rsa,
+ cipher := chacha20_poly1305,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256;
+suite(#{key_exchange := ecdhe_ecdsa,
+ cipher := chacha20_poly1305,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256;
+suite(#{key_exchange := dhe_rsa,
+ cipher := chacha20_poly1305,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256;
+%% TLS 1.3 Cipher Suites RFC8446
+suite(#{key_exchange := any,
+ cipher := aes_128_gcm,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_AES_128_GCM_SHA256;
+suite(#{key_exchange := any,
+ cipher := aes_256_gcm,
+ mac := aead,
+ prf := sha384}) ->
+ ?TLS_AES_256_GCM_SHA384;
+suite(#{key_exchange := any,
+ cipher := chacha20_poly1305,
+ mac := aead,
+ prf := sha256}) ->
+ ?TLS_CHACHA20_POLY1305_SHA256.
+%% suite(#{key_exchange := any,
+%% cipher := aes_128_ccm,
+%% mac := aead,
+%% prf := sha256}) ->
+%% ?TLS_AES_128_CCM_SHA256;
+%% suite(#{key_exchange := any,
+%% cipher := aes_128_ccm_8,
+%% mac := aead,
+%% prf := sha256}) ->
+%% ?TLS_AES_128_CCM_8_SHA256.
+%%--------------------------------------------------------------------
+-spec openssl_suite(openssl_cipher_suite()) -> cipher_suite().
+%%
+%% Description: Return TLS cipher suite definition.
+%%--------------------------------------------------------------------
+%% translate constants <-> openssl-strings
+openssl_suite("DHE-RSA-AES256-SHA256") ->
+ ?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256;
+openssl_suite("DHE-DSS-AES256-SHA256") ->
+ ?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256;
+openssl_suite("AES256-SHA256") ->
+ ?TLS_RSA_WITH_AES_256_CBC_SHA256;
+openssl_suite("DHE-RSA-AES128-SHA256") ->
+ ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA256;
+openssl_suite("DHE-DSS-AES128-SHA256") ->
+ ?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256;
+openssl_suite("AES128-SHA256") ->
+ ?TLS_RSA_WITH_AES_128_CBC_SHA256;
+openssl_suite("DHE-RSA-AES256-SHA") ->
+ ?TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
+openssl_suite("DHE-DSS-AES256-SHA") ->
+ ?TLS_DHE_DSS_WITH_AES_256_CBC_SHA;
+openssl_suite("AES256-SHA") ->
+ ?TLS_RSA_WITH_AES_256_CBC_SHA;
+openssl_suite("EDH-RSA-DES-CBC3-SHA") ->
+ ?TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA;
+openssl_suite("EDH-DSS-DES-CBC3-SHA") ->
+ ?TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA;
+openssl_suite("DES-CBC3-SHA") ->
+ ?TLS_RSA_WITH_3DES_EDE_CBC_SHA;
+openssl_suite("DHE-RSA-AES128-SHA") ->
+ ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
+openssl_suite("DHE-DSS-AES128-SHA") ->
+ ?TLS_DHE_DSS_WITH_AES_128_CBC_SHA;
+openssl_suite("AES128-SHA") ->
+ ?TLS_RSA_WITH_AES_128_CBC_SHA;
+openssl_suite("RC4-SHA") ->
+ ?TLS_RSA_WITH_RC4_128_SHA;
+openssl_suite("RC4-MD5") ->
+ ?TLS_RSA_WITH_RC4_128_MD5;
+openssl_suite("EDH-RSA-DES-CBC-SHA") ->
+ ?TLS_DHE_RSA_WITH_DES_CBC_SHA;
+openssl_suite("DES-CBC-SHA") ->
+ ?TLS_RSA_WITH_DES_CBC_SHA;
+
+%%% SRP Cipher Suites RFC 5054
+
+openssl_suite("SRP-DSS-AES-256-CBC-SHA") ->
+ ?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA;
+openssl_suite("SRP-RSA-AES-256-CBC-SHA") ->
+ ?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA;
+openssl_suite("SRP-DSS-3DES-EDE-CBC-SHA") ->
+ ?TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA;
+openssl_suite("SRP-RSA-3DES-EDE-CBC-SHA") ->
+ ?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA;
+openssl_suite("SRP-DSS-AES-128-CBC-SHA") ->
+ ?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA;
+openssl_suite("SRP-RSA-AES-128-CBC-SHA") ->
+ ?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA;
+
+%% RFC 4492 EC TLS suites
+openssl_suite("ECDH-ECDSA-RC4-SHA") ->
+ ?TLS_ECDH_ECDSA_WITH_RC4_128_SHA;
+openssl_suite("ECDH-ECDSA-DES-CBC3-SHA") ->
+ ?TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA;
+openssl_suite("ECDH-ECDSA-AES128-SHA") ->
+ ?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA;
+openssl_suite("ECDH-ECDSA-AES256-SHA") ->
+ ?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA;
+
+openssl_suite("ECDHE-ECDSA-RC4-SHA") ->
+ ?TLS_ECDHE_ECDSA_WITH_RC4_128_SHA;
+openssl_suite("ECDHE-ECDSA-DES-CBC3-SHA") ->
+ ?TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA;
+openssl_suite("ECDHE-ECDSA-AES128-SHA") ->
+ ?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA;
+openssl_suite("ECDHE-ECDSA-AES256-SHA") ->
+ ?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA;
+
+openssl_suite("ECDHE-RSA-RC4-SHA") ->
+ ?TLS_ECDHE_RSA_WITH_RC4_128_SHA;
+openssl_suite("ECDHE-RSA-DES-CBC3-SHA") ->
+ ?TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA;
+openssl_suite("ECDHE-RSA-AES128-SHA") ->
+ ?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA;
+openssl_suite("ECDHE-RSA-AES256-SHA") ->
+ ?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA;
+
+openssl_suite("ECDH-RSA-RC4-SHA") ->
+ ?TLS_ECDH_RSA_WITH_RC4_128_SHA;
+openssl_suite("ECDH-RSA-DES-CBC3-SHA") ->
+ ?TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA;
+openssl_suite("ECDH-RSA-AES128-SHA") ->
+ ?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA;
+openssl_suite("ECDH-RSA-AES256-SHA") ->
+ ?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA;
+
+%% RFC 5289 EC TLS suites
+openssl_suite("ECDHE-ECDSA-AES128-SHA256") ->
+ ?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256;
+openssl_suite("ECDHE-ECDSA-AES256-SHA384") ->
+ ?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384;
+openssl_suite("ECDH-ECDSA-AES128-SHA256") ->
+ ?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256;
+openssl_suite("ECDH-ECDSA-AES256-SHA384") ->
+ ?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384;
+openssl_suite("ECDHE-RSA-AES128-SHA256") ->
+ ?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256;
+openssl_suite("ECDHE-RSA-AES256-SHA384") ->
+ ?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384;
+openssl_suite("ECDH-RSA-AES128-SHA256") ->
+ ?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256;
+openssl_suite("ECDH-RSA-AES256-SHA384") ->
+ ?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384;
+
+%% RFC 5288 AES-GCM Cipher Suites
+openssl_suite("AES128-GCM-SHA256") ->
+ ?TLS_RSA_WITH_AES_128_GCM_SHA256;
+openssl_suite("AES256-GCM-SHA384") ->
+ ?TLS_RSA_WITH_AES_256_GCM_SHA384;
+openssl_suite("DHE-RSA-AES128-GCM-SHA256") ->
+ ?TLS_DHE_RSA_WITH_AES_128_GCM_SHA256;
+openssl_suite("DHE-RSA-AES256-GCM-SHA384") ->
+ ?TLS_DHE_RSA_WITH_AES_256_GCM_SHA384;
+openssl_suite("DH-RSA-AES128-GCM-SHA256") ->
+ ?TLS_DH_RSA_WITH_AES_128_GCM_SHA256;
+openssl_suite("DH-RSA-AES256-GCM-SHA384") ->
+ ?TLS_DH_RSA_WITH_AES_256_GCM_SHA384;
+openssl_suite("DHE-DSS-AES128-GCM-SHA256") ->
+ ?TLS_DHE_DSS_WITH_AES_128_GCM_SHA256;
+openssl_suite("DHE-DSS-AES256-GCM-SHA384") ->
+ ?TLS_DHE_DSS_WITH_AES_256_GCM_SHA384;
+openssl_suite("DH-DSS-AES128-GCM-SHA256") ->
+ ?TLS_DH_DSS_WITH_AES_128_GCM_SHA256;
+openssl_suite("DH-DSS-AES256-GCM-SHA384") ->
+ ?TLS_DH_DSS_WITH_AES_256_GCM_SHA384;
+
+%% RFC 5289 ECC AES-GCM Cipher Suites
+openssl_suite("ECDHE-ECDSA-AES128-GCM-SHA256") ->
+ ?TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256;
+openssl_suite("ECDHE-ECDSA-AES256-GCM-SHA384") ->
+ ?TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384;
+openssl_suite("ECDH-ECDSA-AES128-GCM-SHA256") ->
+ ?TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256;
+openssl_suite("ECDH-ECDSA-AES256-GCM-SHA384") ->
+ ?TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384;
+openssl_suite("ECDHE-RSA-AES128-GCM-SHA256") ->
+ ?TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256;
+openssl_suite("ECDHE-RSA-AES256-GCM-SHA384") ->
+ ?TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384;
+openssl_suite("ECDH-RSA-AES128-GCM-SHA256") ->
+ ?TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256;
+openssl_suite("ECDH-RSA-AES256-GCM-SHA384") ->
+ ?TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384;
+
+%% TLS 1.3 Cipher Suites RFC8446
+openssl_suite("TLS_AES_128_GCM_SHA256") ->
+ ?TLS_AES_128_GCM_SHA256;
+openssl_suite("TLS_AES_256_GCM_SHA384") ->
+ ?TLS_AES_256_GCM_SHA384;
+openssl_suite("TLS_CHACHA20_POLY1305_SHA256") ->
+ ?TLS_CHACHA20_POLY1305_SHA256.
+%% openssl_suite("TLS_AES_128_CCM_SHA256") ->
+%% ?TLS_AES_128_CCM_SHA256;
+%% openssl_suite("TLS_AES_128_CCM_8_SHA256") ->
+%% ?TLS_AES_128_CCM_8_SHA256.
+
+
+%%--------------------------------------------------------------------
+-spec openssl_suite_name(cipher_suite()) -> openssl_cipher_suite() | erl_cipher_suite().
+%%
+%% Description: Return openssl cipher suite name if possible
+%%-------------------------------------------------------------------
+openssl_suite_name(?TLS_DHE_RSA_WITH_AES_256_CBC_SHA) ->
+ "DHE-RSA-AES256-SHA";
+openssl_suite_name(?TLS_DHE_DSS_WITH_AES_256_CBC_SHA) ->
+ "DHE-DSS-AES256-SHA";
+openssl_suite_name(?TLS_RSA_WITH_AES_256_CBC_SHA) ->
+ "AES256-SHA";
+openssl_suite_name(?TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA) ->
+ "EDH-RSA-DES-CBC3-SHA";
+openssl_suite_name(?TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA) ->
+ "EDH-DSS-DES-CBC3-SHA";
+openssl_suite_name(?TLS_RSA_WITH_3DES_EDE_CBC_SHA) ->
+ "DES-CBC3-SHA";
+openssl_suite_name( ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA) ->
+ "DHE-RSA-AES128-SHA";
+openssl_suite_name(?TLS_DHE_DSS_WITH_AES_128_CBC_SHA) ->
+ "DHE-DSS-AES128-SHA";
+openssl_suite_name(?TLS_RSA_WITH_AES_128_CBC_SHA) ->
+ "AES128-SHA";
+openssl_suite_name(?TLS_RSA_WITH_RC4_128_SHA) ->
+ "RC4-SHA";
+openssl_suite_name(?TLS_RSA_WITH_RC4_128_MD5) ->
+ "RC4-MD5";
+openssl_suite_name(?TLS_DHE_RSA_WITH_DES_CBC_SHA) ->
+ "EDH-RSA-DES-CBC-SHA";
+openssl_suite_name(?TLS_RSA_WITH_DES_CBC_SHA) ->
+ "DES-CBC-SHA";
+openssl_suite_name(?TLS_RSA_WITH_NULL_SHA256) ->
+ "NULL-SHA256";
+openssl_suite_name(?TLS_RSA_WITH_AES_128_CBC_SHA256) ->
+ "AES128-SHA256";
+openssl_suite_name(?TLS_RSA_WITH_AES_256_CBC_SHA256) ->
+ "AES256-SHA256";
+openssl_suite_name(?TLS_DH_DSS_WITH_AES_128_CBC_SHA256) ->
+ "DH-DSS-AES128-SHA256";
+openssl_suite_name(?TLS_DH_RSA_WITH_AES_128_CBC_SHA256) ->
+ "DH-RSA-AES128-SHA256";
+openssl_suite_name(?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256) ->
+ "DHE-DSS-AES128-SHA256";
+openssl_suite_name(?TLS_DHE_RSA_WITH_AES_128_CBC_SHA256) ->
+ "DHE-RSA-AES128-SHA256";
+openssl_suite_name(?TLS_DH_DSS_WITH_AES_256_CBC_SHA256) ->
+ "DH-DSS-AES256-SHA256";
+openssl_suite_name(?TLS_DH_RSA_WITH_AES_256_CBC_SHA256) ->
+ "DH-RSA-AES256-SHA256";
+openssl_suite_name(?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256) ->
+ "DHE-DSS-AES256-SHA256";
+openssl_suite_name(?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256) ->
+ "DHE-RSA-AES256-SHA256";
+
+%%% PSK Cipher Suites RFC 4279
+
+openssl_suite_name(?TLS_PSK_WITH_AES_256_CBC_SHA) ->
+ "PSK-AES256-CBC-SHA";
+openssl_suite_name(?TLS_PSK_WITH_3DES_EDE_CBC_SHA) ->
+ "PSK-3DES-EDE-CBC-SHA";
+openssl_suite_name(?TLS_PSK_WITH_AES_128_CBC_SHA) ->
+ "PSK-AES128-CBC-SHA";
+openssl_suite_name(?TLS_PSK_WITH_RC4_128_SHA) ->
+ "PSK-RC4-SHA";
+
+%%% SRP Cipher Suites RFC 5054
+
+openssl_suite_name(?TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA) ->
+ "SRP-RSA-3DES-EDE-CBC-SHA";
+openssl_suite_name(?TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA) ->
+ "SRP-DSS-3DES-EDE-CBC-SHA";
+openssl_suite_name(?TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA) ->
+ "SRP-RSA-AES-128-CBC-SHA";
+openssl_suite_name(?TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA) ->
+ "SRP-DSS-AES-128-CBC-SHA";
+openssl_suite_name(?TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA) ->
+ "SRP-RSA-AES-256-CBC-SHA";
+openssl_suite_name(?TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA) ->
+ "SRP-DSS-AES-256-CBC-SHA";
+
+%% RFC 4492 EC TLS suites
+openssl_suite_name(?TLS_ECDH_ECDSA_WITH_RC4_128_SHA) ->
+ "ECDH-ECDSA-RC4-SHA";
+openssl_suite_name(?TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA) ->
+ "ECDH-ECDSA-DES-CBC3-SHA";
+openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA) ->
+ "ECDH-ECDSA-AES128-SHA";
+openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA) ->
+ "ECDH-ECDSA-AES256-SHA";
+
+openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_RC4_128_SHA) ->
+ "ECDHE-ECDSA-RC4-SHA";
+openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA) ->
+ "ECDHE-ECDSA-DES-CBC3-SHA";
+openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA) ->
+ "ECDHE-ECDSA-AES128-SHA";
+openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA) ->
+ "ECDHE-ECDSA-AES256-SHA";
+
+openssl_suite_name(?TLS_ECDH_RSA_WITH_RC4_128_SHA) ->
+ "ECDH-RSA-RC4-SHA";
+openssl_suite_name(?TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA) ->
+ "ECDH-RSA-DES-CBC3-SHA";
+openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA) ->
+ "ECDH-RSA-AES128-SHA";
+openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA) ->
+ "ECDH-RSA-AES256-SHA";
+
+openssl_suite_name(?TLS_ECDHE_RSA_WITH_RC4_128_SHA) ->
+ "ECDHE-RSA-RC4-SHA";
+openssl_suite_name(?TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA) ->
+ "ECDHE-RSA-DES-CBC3-SHA";
+openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) ->
+ "ECDHE-RSA-AES128-SHA";
+openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) ->
+ "ECDHE-RSA-AES256-SHA";
+
+%% RFC 5289 EC TLS suites
+openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256) ->
+ "ECDHE-ECDSA-AES128-SHA256";
+openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384) ->
+ "ECDHE-ECDSA-AES256-SHA384";
+openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256) ->
+ "ECDH-ECDSA-AES128-SHA256";
+openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384) ->
+ "ECDH-ECDSA-AES256-SHA384";
+openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) ->
+ "ECDHE-RSA-AES128-SHA256";
+openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) ->
+ "ECDHE-RSA-AES256-SHA384";
+openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256) ->
+ "ECDH-RSA-AES128-SHA256";
+openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384) ->
+ "ECDH-RSA-AES256-SHA384";
+
+%% RFC 5288 AES-GCM Cipher Suites
+openssl_suite_name(?TLS_RSA_WITH_AES_128_GCM_SHA256) ->
+ "AES128-GCM-SHA256";
+openssl_suite_name(?TLS_RSA_WITH_AES_256_GCM_SHA384) ->
+ "AES256-GCM-SHA384";
+openssl_suite_name(?TLS_DHE_RSA_WITH_AES_128_GCM_SHA256) ->
+ "DHE-RSA-AES128-GCM-SHA256";
+openssl_suite_name(?TLS_DHE_RSA_WITH_AES_256_GCM_SHA384) ->
+ "DHE-RSA-AES256-GCM-SHA384";
+openssl_suite_name(?TLS_DH_RSA_WITH_AES_128_GCM_SHA256) ->
+ "DH-RSA-AES128-GCM-SHA256";
+openssl_suite_name(?TLS_DH_RSA_WITH_AES_256_GCM_SHA384) ->
+ "DH-RSA-AES256-GCM-SHA384";
+openssl_suite_name(?TLS_DHE_DSS_WITH_AES_128_GCM_SHA256) ->
+ "DHE-DSS-AES128-GCM-SHA256";
+openssl_suite_name(?TLS_DHE_DSS_WITH_AES_256_GCM_SHA384) ->
+ "DHE-DSS-AES256-GCM-SHA384";
+openssl_suite_name(?TLS_DH_DSS_WITH_AES_128_GCM_SHA256) ->
+ "DH-DSS-AES128-GCM-SHA256";
+openssl_suite_name(?TLS_DH_DSS_WITH_AES_256_GCM_SHA384) ->
+ "DH-DSS-AES256-GCM-SHA384";
+
+%% RFC 5289 ECC AES-GCM Cipher Suites
+openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) ->
+ "ECDHE-ECDSA-AES128-GCM-SHA256";
+openssl_suite_name(?TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) ->
+ "ECDHE-ECDSA-AES256-GCM-SHA384";
+openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256) ->
+ "ECDH-ECDSA-AES128-GCM-SHA256";
+openssl_suite_name(?TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384) ->
+ "ECDH-ECDSA-AES256-GCM-SHA384";
+openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) ->
+ "ECDHE-RSA-AES128-GCM-SHA256";
+openssl_suite_name(?TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) ->
+ "ECDHE-RSA-AES256-GCM-SHA384";
+openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256) ->
+ "ECDH-RSA-AES128-GCM-SHA256";
+openssl_suite_name(?TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384) ->
+ "ECDH-RSA-AES256-GCM-SHA384";
+
+%% TLS 1.3 Cipher Suites RFC8446
+openssl_suite_name(?TLS_AES_128_GCM_SHA256) ->
+ "TLS_AES_128_GCM_SHA256";
+openssl_suite_name(?TLS_AES_256_GCM_SHA384) ->
+ "TLS_AES_256_GCM_SHA384";
+openssl_suite_name(?TLS_CHACHA20_POLY1305_SHA256) ->
+ "TLS_CHACHA20_POLY1305_SHA256";
+%% openssl_suite(?TLS_AES_128_CCM_SHA256) ->
+%% "TLS_AES_128_CCM_SHA256";
+%% openssl_suite(?TLS_AES_128_CCM_8_SHA256) ->
+%% "TLS_AES_128_CCM_8_SHA256";
+
+%% No oppenssl name
+openssl_suite_name(Cipher) ->
+ suite_definition(Cipher).
diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl
index 6e98baf984..66e96f8da5 100644
--- a/lib/ssl/src/ssl_connection.erl
+++ b/lib/ssl/src/ssl_connection.erl
@@ -56,7 +56,7 @@
]).
%% Data handling
--export([write_application_data/3, read_application_data/2]).
+-export([read_application_data/2, internal_renegotiation/2]).
%% Help functions for tls|dtls_connection.erl
-export([handle_session/7, ssl_config/3,
@@ -65,13 +65,13 @@
%% General gen_statem state functions with extra callback argument
%% to determine if it is an SSL/TLS or DTLS gen_statem machine
-export([init/4, error/4, hello/4, user_hello/4, abbreviated/4, certify/4, cipher/4,
- connection/4, death_row/4, downgrade/4]).
+ connection/4, downgrade/4]).
%% gen_statem callbacks
-export([terminate/3, format_status/2]).
%% Erlang Distribution export
--export([get_sslsocket/1, handshake_complete/3]).
+-export([get_sslsocket/1, dist_handshake_complete/2]).
%%====================================================================
%% Setup
@@ -119,7 +119,7 @@ handshake(Connection, Port, Socket, Opts, User, CbInfo, Timeout) ->
%%
%% Description: Starts ssl handshake.
%%--------------------------------------------------------------------
-handshake(#sslsocket{pid = Pid} = Socket, Timeout) ->
+handshake(#sslsocket{pid = [Pid|_]} = Socket, Timeout) ->
case call(Pid, {start, Timeout}) of
connected ->
{ok, Socket};
@@ -135,7 +135,7 @@ handshake(#sslsocket{pid = Pid} = Socket, Timeout) ->
%%
%% Description: Starts ssl handshake with some new options
%%--------------------------------------------------------------------
-handshake(#sslsocket{pid = Pid} = Socket, SslOptions, Timeout) ->
+handshake(#sslsocket{pid = [Pid|_]} = Socket, SslOptions, Timeout) ->
case call(Pid, {start, SslOptions, Timeout}) of
connected ->
{ok, Socket};
@@ -149,7 +149,7 @@ handshake(#sslsocket{pid = Pid} = Socket, SslOptions, Timeout) ->
%%
%% Description: Continues handshake with new options
%%--------------------------------------------------------------------
-handshake_continue(#sslsocket{pid = Pid} = Socket, SslOptions, Timeout) ->
+handshake_continue(#sslsocket{pid = [Pid|_]} = Socket, SslOptions, Timeout) ->
case call(Pid, {handshake_continue, SslOptions, Timeout}) of
connected ->
{ok, Socket};
@@ -161,7 +161,7 @@ handshake_continue(#sslsocket{pid = Pid} = Socket, SslOptions, Timeout) ->
%%
%% Description: Cancels connection
%%--------------------------------------------------------------------
-handshake_cancel(#sslsocket{pid = Pid}) ->
+handshake_cancel(#sslsocket{pid = [Pid|_]}) ->
case call(Pid, cancel) of
closed ->
ok;
@@ -169,7 +169,7 @@ handshake_cancel(#sslsocket{pid = Pid}) ->
Error
end.
%--------------------------------------------------------------------
--spec socket_control(tls_connection | dtls_connection, port(), pid(), atom()) ->
+-spec socket_control(tls_connection | dtls_connection, port(), [pid()], atom()) ->
{ok, #sslsocket{}} | {error, reason()}.
%%
%% Description: Set the ssl process to own the accept socket
@@ -178,24 +178,24 @@ socket_control(Connection, Socket, Pid, Transport) ->
socket_control(Connection, Socket, Pid, Transport, undefined).
%--------------------------------------------------------------------
--spec socket_control(tls_connection | dtls_connection, port(), pid(), atom(), pid()| undefined) ->
+-spec socket_control(tls_connection | dtls_connection, port(), [pid()], atom(), pid()| atom()) ->
{ok, #sslsocket{}} | {error, reason()}.
%%--------------------------------------------------------------------
-socket_control(Connection, Socket, Pid, Transport, udp_listener) ->
+socket_control(Connection, Socket, Pids, Transport, udp_listener) ->
%% dtls listener process must have the socket control
- {ok, Connection:socket(Pid, Transport, Socket, Connection, undefined)};
+ {ok, Connection:socket(Pids, Transport, Socket, Connection, undefined)};
-socket_control(tls_connection = Connection, Socket, Pid, Transport, ListenTracker) ->
+socket_control(tls_connection = Connection, Socket, [Pid|_] = Pids, Transport, ListenTracker) ->
case Transport:controlling_process(Socket, Pid) of
ok ->
- {ok, Connection:socket(Pid, Transport, Socket, Connection, ListenTracker)};
+ {ok, Connection:socket(Pids, Transport, Socket, Connection, ListenTracker)};
{error, Reason} ->
{error, Reason}
end;
-socket_control(dtls_connection = Connection, {_, Socket}, Pid, Transport, ListenTracker) ->
+socket_control(dtls_connection = Connection, {_, Socket}, [Pid|_] = Pids, Transport, ListenTracker) ->
case Transport:controlling_process(Socket, Pid) of
ok ->
- {ok, Connection:socket(Pid, Transport, Socket, Connection, ListenTracker)};
+ {ok, Connection:socket(Pids, Transport, Socket, Connection, ListenTracker)};
{error, Reason} ->
{error, Reason}
end.
@@ -307,12 +307,20 @@ peer_certificate(ConnectionPid) ->
renegotiation(ConnectionPid) ->
call(ConnectionPid, renegotiate).
+%%--------------------------------------------------------------------
+-spec internal_renegotiation(pid(), ssl_record:connection_states()) ->
+ ok.
+%%
+%% Description: Starts a renegotiation of the ssl session.
+%%--------------------------------------------------------------------
+internal_renegotiation(ConnectionPid, #{current_write := WriteState}) ->
+ gen_statem:cast(ConnectionPid, {internal_renegotiate, WriteState}).
get_sslsocket(ConnectionPid) ->
call(ConnectionPid, get_sslsocket).
-handshake_complete(ConnectionPid, Node, DHandle) ->
- call(ConnectionPid, {handshake_complete, Node, DHandle}).
+dist_handshake_complete(ConnectionPid, DHandle) ->
+ gen_statem:cast(ConnectionPid, {dist_handshake_complete, DHandle}).
%%--------------------------------------------------------------------
-spec prf(pid(), binary() | 'master_secret', binary(),
@@ -335,9 +343,9 @@ handle_own_alert(Alert, Version, StateName,
connection_states = ConnectionStates,
ssl_options = SslOpts} = State) ->
try %% Try to tell the other side
- {BinMsg, _} =
+ {BinMsg, _} =
Connection:encode_alert(Alert, Version, ConnectionStates),
- Connection:send(Transport, Socket, BinMsg),
+ Connection:send(Transport, Socket, BinMsg),
Report = #{direction => outbound,
protocol => 'tls_record',
message => BinMsg},
@@ -360,8 +368,9 @@ handle_normal_shutdown(Alert, _, #state{socket = Socket,
protocol_cb = Connection,
start_or_recv_from = StartFrom,
tracker = Tracker,
- role = Role, renegotiation = {false, first}}) ->
- alert_user(Transport, Tracker,Socket, StartFrom, Alert, Role, Connection);
+ role = Role, renegotiation = {false, first}} = State) ->
+ Pids = Connection:pids(State),
+ alert_user(Pids, Transport, Tracker,Socket, StartFrom, Alert, Role, Connection);
handle_normal_shutdown(Alert, StateName, #state{socket = Socket,
socket_options = Opts,
@@ -369,20 +378,22 @@ handle_normal_shutdown(Alert, StateName, #state{socket = Socket,
protocol_cb = Connection,
user_application = {_Mon, Pid},
tracker = Tracker,
- start_or_recv_from = RecvFrom, role = Role}) ->
- alert_user(Transport, Tracker, Socket, StateName, Opts, Pid, RecvFrom, Alert, Role, Connection).
+ start_or_recv_from = RecvFrom, role = Role} = State) ->
+ Pids = Connection:pids(State),
+ alert_user(Pids, Transport, Tracker, Socket, StateName, Opts, Pid, RecvFrom, Alert, Role, Connection).
handle_alert(#alert{level = ?FATAL} = Alert, StateName,
#state{socket = Socket, transport_cb = Transport,
protocol_cb = Connection,
ssl_options = SslOpts, start_or_recv_from = From, host = Host,
port = Port, session = Session, user_application = {_Mon, Pid},
- role = Role, socket_options = Opts, tracker = Tracker} = State) ->
+ role = Role, socket_options = Opts,
+ tracker = Tracker} = State) ->
invalidate_session(Role, Host, Port, Session),
- log_alert(SslOpts#ssl_options.log_level, Role,
- Connection:protocol_name(), StateName,
- Alert#alert{role = opposite_role(Role)}),
- alert_user(Transport, Tracker, Socket, StateName, Opts, Pid, From, Alert, Role, Connection),
+ log_alert(SslOpts#ssl_options.log_level, Role, Connection:protocol_name(),
+ StateName, Alert#alert{role = opposite_role(Role)}),
+ Pids = Connection:pids(State),
+ alert_user(Pids, Transport, Tracker, Socket, StateName, Opts, Pid, From, Alert, Role, Connection),
stop(normal, State);
handle_alert(#alert{level = ?WARNING, description = ?CLOSE_NOTIFY} = Alert,
@@ -391,13 +402,24 @@ handle_alert(#alert{level = ?WARNING, description = ?CLOSE_NOTIFY} = Alert,
stop({shutdown, peer_close}, State);
handle_alert(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert, StateName,
- #state{role = Role, ssl_options = SslOpts, protocol_cb = Connection, renegotiation = {true, internal}} = State) ->
- log_alert(SslOpts#ssl_options.log_level, Role,
- Connection:protocol_name(), StateName,
- Alert#alert{role = opposite_role(Role)}),
+ #state{role = Role, ssl_options = SslOpts, protocol_cb = Connection,
+ renegotiation = {true, internal}} = State) ->
+ log_alert(SslOpts#ssl_options.log_level, Role,
+ Connection:protocol_name(), StateName, Alert#alert{role = opposite_role(Role)}),
handle_normal_shutdown(Alert, StateName, State),
stop({shutdown, peer_close}, State);
+handle_alert(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert, connection = StateName,
+ #state{role = Role,
+ ssl_options = SslOpts, renegotiation = {true, From},
+ protocol_cb = Connection} = State0) ->
+ log_alert(SslOpts#ssl_options.log_level, Role,
+ Connection:protocol_name(), StateName, Alert#alert{role = opposite_role(Role)}),
+ gen_statem:reply(From, {error, renegotiation_rejected}),
+ State1 = Connection:reinit_handshake_data(State0),
+ {Record, State} = Connection:next_record(State1#state{renegotiation = undefined}),
+ Connection:next_event(connection, Record, State);
+
handle_alert(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert, StateName,
#state{role = Role,
ssl_options = SslOpts, renegotiation = {true, From},
@@ -408,7 +430,7 @@ handle_alert(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert,
gen_statem:reply(From, {error, renegotiation_rejected}),
{Record, State1} = Connection:next_record(State0),
%% Go back to connection!
- State = Connection:reinit_handshake_data(State1#state{renegotiation = undefined}),
+ State = Connection:reinit(State1#state{renegotiation = undefined}),
Connection:next_event(connection, Record, State);
%% Gracefully log and ignore all other warning alerts
@@ -423,41 +445,6 @@ handle_alert(#alert{level = ?WARNING} = Alert, StateName,
%%====================================================================
%% Data handling
%%====================================================================
-write_application_data(Data0, {FromPid, _} = From,
- #state{socket = Socket,
- negotiated_version = Version,
- protocol_cb = Connection,
- transport_cb = Transport,
- connection_states = ConnectionStates0,
- socket_options = SockOpts,
- ssl_options = #ssl_options{renegotiate_at = RenegotiateAt} = SslOpts} = State) ->
- Data = encode_packet(Data0, SockOpts),
-
- case time_to_renegotiate(Data, ConnectionStates0, RenegotiateAt) of
- true ->
- Connection:renegotiate(State#state{renegotiation = {true, internal}},
- [{next_event, {call, From}, {application_data, Data0}}]);
- false ->
- {Msgs, ConnectionStates} =
- Connection:encode_data(Data, Version, ConnectionStates0),
- NewState = State#state{connection_states = ConnectionStates},
- RetVal = case Connection:send(Transport, Socket, Msgs) of
- ok when FromPid =:= self() ->
- hibernate_after(connection, NewState, []);
- Error when FromPid =:= self() ->
- stop({shutdown, Error}, NewState);
- ok ->
- hibernate_after(connection, NewState, [{reply, From, ok}]);
- Result ->
- hibernate_after(connection, NewState, [{reply, From, Result}])
- end,
- Report = #{direction => outbound,
- protocol => 'tls_record',
- message => Msgs},
- ssl_logger:debug(SslOpts#ssl_options.log_level, Report, #{domain => [otp,ssl,tls_record]}),
- RetVal
- end.
-
read_application_data(Data, #state{user_application = {_Mon, Pid},
socket = Socket,
protocol_cb = Connection,
@@ -475,58 +462,74 @@ read_application_data(Data, #state{user_application = {_Mon, Pid},
end,
case get_data(SOpts, BytesToRead, Buffer1) of
{ok, ClientData, Buffer} -> % Send data
- case State0 of
- #state{
- ssl_options = #ssl_options{erl_dist = true},
- protocol_specific = #{d_handle := DHandle}} ->
- State =
- State0#state{
- user_data_buffer = Buffer,
- bytes_to_read = undefined},
- try erlang:dist_ctrl_put_data(DHandle, ClientData) of
- _
- when SOpts#socket_options.active =:= false;
- Buffer =:= <<>> ->
- %% Passive mode, wait for active once or recv
- %% Active and empty, get more data
- Connection:next_record_if_active(State);
- _ -> %% We have more data
- read_application_data(<<>>, State)
- catch error:_ ->
- death_row(State, disconnect)
- end;
- _ ->
- SocketOpt =
- deliver_app_data(
- Transport, Socket, SOpts,
- ClientData, Pid, RecvFrom, Tracker, Connection),
- cancel_timer(Timer),
- State =
- State0#state{
- user_data_buffer = Buffer,
+ #state{ssl_options = #ssl_options{erl_dist = Dist},
+ erl_dist_data = DistData} = State0,
+ case Dist andalso is_dist_up(DistData) of
+ true ->
+ dist_app_data(ClientData, State0#state{user_data_buffer = Buffer,
+ bytes_to_read = undefined});
+ _ ->
+ SocketOpt =
+ deliver_app_data(Connection:pids(State0),
+ Transport, Socket, SOpts,
+ ClientData, Pid, RecvFrom, Tracker, Connection),
+ cancel_timer(Timer),
+ State =
+ State0#state{
+ user_data_buffer = Buffer,
start_or_recv_from = undefined,
timer = undefined,
bytes_to_read = undefined,
socket_options = SocketOpt
- },
- if
- SocketOpt#socket_options.active =:= false;
- Buffer =:= <<>> ->
- %% Passive mode, wait for active once or recv
+ },
+ if
+ SocketOpt#socket_options.active =:= false;
+ Buffer =:= <<>> ->
+ %% Passive mode, wait for active once or recv
%% Active and empty, get more data
- Connection:next_record_if_active(State);
- true -> %% We have more data
- read_application_data(<<>>, State)
- end
- end;
+ Connection:next_record_if_active(State);
+ true -> %% We have more data
+ read_application_data(<<>>, State)
+ end
+ end;
{more, Buffer} -> % no reply, we need more data
Connection:next_record(State0#state{user_data_buffer = Buffer});
{passive, Buffer} ->
Connection:next_record_if_active(State0#state{user_data_buffer = Buffer});
{error,_Reason} -> %% Invalid packet in packet mode
- deliver_packet_error(Transport, Socket, SOpts, Buffer1, Pid, RecvFrom, Tracker, Connection),
+ deliver_packet_error(Connection:pids(State0),
+ Transport, Socket, SOpts, Buffer1, Pid, RecvFrom, Tracker, Connection),
stop(normal, State0)
end.
+
+dist_app_data(ClientData, #state{protocol_cb = Connection,
+ erl_dist_data = #{dist_handle := undefined,
+ dist_buffer := DistBuff} = DistData} = State) ->
+ Connection:next_record_if_active(State#state{erl_dist_data = DistData#{dist_buffer => [ClientData, DistBuff]}});
+dist_app_data(ClientData, #state{erl_dist_data = #{dist_handle := DHandle,
+ dist_buffer := DistBuff} = ErlDistData,
+ protocol_cb = Connection,
+ user_data_buffer = Buffer,
+ socket_options = SOpts} = State) ->
+ Data = merge_dist_data(DistBuff, ClientData),
+ try erlang:dist_ctrl_put_data(DHandle, Data) of
+ _ when SOpts#socket_options.active =:= false;
+ Buffer =:= <<>> ->
+ %% Passive mode, wait for active once or recv
+ %% Active and empty, get more data
+ Connection:next_record_if_active(State#state{erl_dist_data = ErlDistData#{dist_buffer => <<>>}});
+ _ -> %% We have more data
+ read_application_data(<<>>, State)
+ catch error:_ ->
+ stop(State, disconnect)
+ end.
+
+merge_dist_data(<<>>, ClientData) ->
+ ClientData;
+merge_dist_data(DistBuff, <<>>) ->
+ DistBuff;
+merge_dist_data(DistBuff, ClientData) ->
+ [DistBuff, ClientData].
%%====================================================================
%% Help functions for tls|dtls_connection.erl
%%====================================================================
@@ -542,7 +545,7 @@ handle_session(#server_hello{cipher_suite = CipherSuite,
negotiated_version = ReqVersion,
negotiated_protocol = CurrentProtocol} = State0) ->
#{key_exchange := KeyAlgorithm} =
- ssl_cipher:suite_definition(CipherSuite),
+ ssl_cipher_format:suite_definition(CipherSuite),
PremasterSecret = make_premaster_secret(ReqVersion, KeyAlgorithm),
@@ -626,12 +629,6 @@ init({call, From}, {start, {Opts, EmOpts}, Timeout},
socket_options = SockOpts} = State0, Connection) ->
try
SslOpts = ssl:handle_options(Opts, OrigSSLOptions),
- case SslOpts of
- #ssl_options{erl_dist = true} ->
- process_flag(priority, max);
- _ ->
- ok
- end,
State = ssl_config(SslOpts, Role, State0),
init({call, From}, {start, Timeout},
State#state{ssl_options = SslOpts,
@@ -744,8 +741,8 @@ abbreviated(internal, #next_protocol{selected_protocol = SelectedProtocol},
Connection:next_event(?FUNCTION_NAME, Record,
State#state{expecting_next_protocol_negotiation = false});
abbreviated(internal,
- #change_cipher_spec{type = <<1>>}, #state{connection_states = ConnectionStates0} =
- State0, Connection) ->
+ #change_cipher_spec{type = <<1>>},
+ #state{connection_states = ConnectionStates0} = State0, Connection) ->
ConnectionStates1 =
ssl_record:activate_pending_connection_state(ConnectionStates0, read, Connection),
{Record, State} = Connection:next_record(State0#state{connection_states =
@@ -1041,22 +1038,6 @@ cipher(Type, Msg, State, Connection) ->
#state{}, tls_connection | dtls_connection) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
-connection({call, {FromPid, _} = From}, {application_data, Data},
- #state{protocol_cb = Connection} = State, Connection) ->
- %% We should look into having a worker process to do this to
- %% parallize send and receive decoding and not block the receiver
- %% if sending is overloading the socket.
- try
- write_application_data(Data, From, State)
- catch throw:Error ->
- case self() of
- FromPid ->
- stop({shutdown, Error}, State);
- _ ->
- hibernate_after(
- ?FUNCTION_NAME, State, [{reply, From, Error}])
- end
- end;
connection({call, RecvFrom}, {recv, N, Timeout},
#state{protocol_cb = Connection, socket_options =
#socket_options{active = false}} = State0, Connection) ->
@@ -1083,64 +1064,25 @@ connection({call, From}, negotiated_protocol,
#state{negotiated_protocol = SelectedProtocol} = State, _) ->
hibernate_after(?FUNCTION_NAME, State,
[{reply, From, {ok, SelectedProtocol}}]);
-connection(
- {call, From}, {handshake_complete, _Node, DHandle},
- #state{
- ssl_options = #ssl_options{erl_dist = true},
- socket_options = SockOpts,
- protocol_specific = ProtocolSpecific} = State,
- Connection) ->
- %% From now on we execute on normal priority
- process_flag(priority, normal),
- try erlang:dist_ctrl_get_data_notification(DHandle) of
- _ ->
- NewState =
- State#state{
- socket_options =
- SockOpts#socket_options{active = true},
- protocol_specific =
- ProtocolSpecific#{d_handle => DHandle}},
- {Record, NewerState} = Connection:next_record_if_active(NewState),
- Connection:next_event(connection, Record, NewerState, [{reply, From, ok}])
- catch error:_ ->
- death_row(State, disconnect)
- end;
connection({call, From}, Msg, State, Connection) ->
handle_call(Msg, From, ?FUNCTION_NAME, State, Connection);
-connection(
- info, dist_data = Msg,
- #state{
- ssl_options = #ssl_options{erl_dist = true},
- protocol_specific = #{d_handle := DHandle}} = State,
- _) ->
- eat_msgs(Msg),
- try send_dist_data(?FUNCTION_NAME, State, DHandle, [])
- catch error:_ ->
- death_row(State, disconnect)
- end;
-connection(
- info, {send, From, Ref, Data},
- #state{
- ssl_options = #ssl_options{erl_dist = true},
- protocol_specific = #{d_handle := _}},
- _) ->
- %% This is for testing only!
- %%
- %% Needed by some OTP distribution
- %% test suites...
- From ! {Ref, ok},
- {keep_state_and_data,
- [{next_event, {call, {self(), undefined}},
- {application_data, iolist_to_binary(Data)}}]};
-connection(
- info, tick = Msg,
- #state{
- ssl_options = #ssl_options{erl_dist = true},
- protocol_specific = #{d_handle := _}},
- _) ->
- eat_msgs(Msg),
- {keep_state_and_data,
- [{next_event, {call, {self(), undefined}}, {application_data, <<>>}}]};
+connection(cast, {internal_renegotiate, WriteState}, #state{protocol_cb = Connection,
+ connection_states = ConnectionStates}
+ = State, Connection) ->
+ Connection:renegotiate(State#state{renegotiation = {true, internal},
+ connection_states = ConnectionStates#{current_write => WriteState}}, []);
+connection(cast, {dist_handshake_complete, DHandle},
+ #state{ssl_options = #ssl_options{erl_dist = true},
+ erl_dist_data = ErlDistData,
+ socket_options = SockOpts} = State0, Connection) ->
+ process_flag(priority, normal),
+ State1 =
+ State0#state{
+ socket_options =
+ SockOpts#socket_options{active = true},
+ erl_dist_data = ErlDistData#{dist_handle => DHandle}},
+ {Record, State} = dist_app_data(<<>>, State1),
+ Connection:next_event(connection, Record, State);
connection(info, Msg, State, _) ->
handle_info(Msg, ?FUNCTION_NAME, State);
connection(internal, {recv, _}, State, Connection) ->
@@ -1149,32 +1091,6 @@ connection(Type, Msg, State, Connection) ->
handle_common_event(Type, Msg, ?FUNCTION_NAME, State, Connection).
%%--------------------------------------------------------------------
--spec death_row(gen_statem:event_type(), term(),
- #state{}, tls_connection | dtls_connection) ->
- gen_statem:state_function_result().
-%%--------------------------------------------------------------------
-%% We just wait for the owner to die which triggers the monitor,
-%% or the socket may die too
-death_row(
- info, {'DOWN', MonitorRef, _, _, Reason},
- #state{user_application={MonitorRef,_Pid}},
- _) ->
- {stop, {shutdown, Reason}};
-death_row(
- info, {'EXIT', Socket, Reason}, #state{socket = Socket}, _) ->
- {stop, {shutdown, Reason}};
-death_row(state_timeout, Reason, _State, _Connection) ->
- {stop, {shutdown,Reason}};
-death_row(_Type, _Msg, _State, _Connection) ->
- %% Waste all other events
- keep_state_and_data.
-
-%% State entry function
-death_row(State, Reason) ->
- {next_state, death_row, State,
- [{state_timeout, 5000, Reason}]}.
-
-%%--------------------------------------------------------------------
-spec downgrade(gen_statem:event_type(), term(),
#state{}, tls_connection | dtls_connection) ->
gen_statem:state_function_result().
@@ -1224,7 +1140,14 @@ handle_common_event(internal, {application_data, Data}, StateName, State0, Conne
{stop, _, _} = Stop->
Stop;
{Record, State} ->
- Connection:next_event(StateName, Record, State)
+ case Connection:next_event(StateName, Record, State) of
+ {next_state, StateName, State} ->
+ hibernate_after(StateName, State, []);
+ {next_state, StateName, State, Actions} ->
+ hibernate_after(StateName, State, Actions);
+ {stop, _, _} = Stop ->
+ Stop
+ end
end;
handle_common_event(internal, #change_cipher_spec{type = <<1>>}, StateName,
#state{negotiated_version = Version} = State, _) ->
@@ -1310,12 +1233,8 @@ handle_call({set_opts, Opts0}, From, StateName,
handle_call(renegotiate, From, StateName, _, _) when StateName =/= connection ->
{keep_state_and_data, [{reply, From, {error, already_renegotiating}}]};
-handle_call(
- get_sslsocket, From, _StateName,
- #state{transport_cb = Transport, socket = Socket, tracker = Tracker},
- Connection) ->
- SslSocket =
- Connection:socket(self(), Transport, Socket, Connection, Tracker),
+handle_call(get_sslsocket, From, _StateName, State, Connection) ->
+ SslSocket = Connection:socket(State),
{keep_state_and_data, [{reply, From, SslSocket}]};
handle_call({prf, Secret, Label, Seed, WantedLength}, From, _,
@@ -1352,7 +1271,8 @@ handle_info({ErrorTag, Socket, econnaborted}, StateName,
start_or_recv_from = StartFrom, role = Role,
error_tag = ErrorTag,
tracker = Tracker} = State) when StateName =/= connection ->
- alert_user(Transport, Tracker,Socket,
+ Pids = Connection:pids(State),
+ alert_user(Pids, Transport, Tracker,Socket,
StartFrom, ?ALERT_REC(?FATAL, ?CLOSE_NOTIFY), Role, Connection),
stop(normal, State);
@@ -1363,23 +1283,18 @@ handle_info({ErrorTag, Socket, Reason}, StateName, #state{socket = Socket,
handle_normal_shutdown(?ALERT_REC(?FATAL, ?CLOSE_NOTIFY), StateName, State),
stop(normal, State);
-handle_info(
- {'DOWN', MonitorRef, _, _, Reason}, _,
- #state{
- user_application = {MonitorRef, _Pid},
- ssl_options = #ssl_options{erl_dist = true}}) ->
+handle_info({'DOWN', MonitorRef, _, _, Reason}, _,
+ #state{user_application = {MonitorRef, _Pid},
+ ssl_options = #ssl_options{erl_dist = true}}) ->
{stop, {shutdown, Reason}};
-handle_info(
- {'DOWN', MonitorRef, _, _, _}, _,
- #state{user_application = {MonitorRef, _Pid}}) ->
+handle_info({'DOWN', MonitorRef, _, _, _}, _,
+ #state{user_application = {MonitorRef, _Pid}}) ->
{stop, normal};
-handle_info(
- {'EXIT', Pid, _Reason}, StateName,
- #state{user_application = {_MonitorRef, Pid}} = State) ->
+handle_info({'EXIT', Pid, _Reason}, StateName,
+ #state{user_application = {_MonitorRef, Pid}} = State) ->
%% It seems the user application has linked to us
%% - ignore that and let the monitor handle this
{next_state, StateName, State};
-
%%% So that terminate will be run when supervisor issues shutdown
handle_info({'EXIT', _Sup, shutdown}, _StateName, State) ->
stop(shutdown, State);
@@ -1427,7 +1342,7 @@ terminate({shutdown, transport_closed} = Reason,
socket = Socket, transport_cb = Transport} = State) ->
handle_trusted_certs_db(State),
Connection:close(Reason, Socket, Transport, undefined, undefined);
-terminate({shutdown, own_alert}, _StateName, #state{%%send_queue = SendQueue,
+terminate({shutdown, own_alert}, _StateName, #state{
protocol_cb = Connection,
socket = Socket,
transport_cb = Transport} = State) ->
@@ -1438,15 +1353,14 @@ terminate({shutdown, own_alert}, _StateName, #state{%%send_queue = SendQueue,
_ ->
Connection:close({timeout, ?DEFAULT_TIMEOUT}, Socket, Transport, undefined, undefined)
end;
-terminate(Reason, connection, #state{negotiated_version = Version,
- protocol_cb = Connection,
- connection_states = ConnectionStates0,
+terminate(Reason, connection, #state{protocol_cb = Connection,
+ connection_states = ConnectionStates,
ssl_options = #ssl_options{padding_check = Check},
transport_cb = Transport, socket = Socket
} = State) ->
handle_trusted_certs_db(State),
- {BinAlert, ConnectionStates} = terminate_alert(Reason, Version, ConnectionStates0, Connection),
- Connection:send(Transport, Socket, BinAlert),
+ Alert = terminate_alert(Reason),
+ ok = Connection:send_alert_in_connection(Alert, State),
Connection:close(Reason, Socket, Transport, ConnectionStates, Check);
terminate(Reason, _StateName, #state{transport_cb = Transport, protocol_cb = Connection,
socket = Socket
@@ -1490,7 +1404,7 @@ connection_info(#state{sni_hostname = SNIHostname,
negotiated_version = {_,_} = Version,
ssl_options = Opts}) ->
RecordCB = record_cb(Connection),
- CipherSuiteDef = #{key_exchange := KexAlg} = ssl_cipher:suite_definition(CipherSuite),
+ CipherSuiteDef = #{key_exchange := KexAlg} = ssl_cipher_format:suite_definition(CipherSuite),
IsNamedCurveSuite = lists:member(KexAlg,
[ecdh_ecdsa, ecdhe_ecdsa, ecdh_rsa, ecdhe_rsa, ecdh_anon]),
CurveInfo = case ECCCurve of
@@ -1501,7 +1415,7 @@ connection_info(#state{sni_hostname = SNIHostname,
end,
[{protocol, RecordCB:protocol_version(Version)},
{session_id, SessionId},
- {cipher_suite, ssl_cipher:erl_suite_definition(CipherSuiteDef)},
+ {cipher_suite, ssl_cipher_format:erl_suite_definition(CipherSuiteDef)},
{selected_cipher_suite, CipherSuiteDef},
{sni_hostname, SNIHostname} | CurveInfo] ++ ssl_options_list(Opts).
@@ -1629,7 +1543,7 @@ resumed_server_hello(#state{session = Session,
server_hello(ServerHello, State0, Connection) ->
CipherSuite = ServerHello#server_hello.cipher_suite,
- #{key_exchange := KeyAlgorithm} = ssl_cipher:suite_definition(CipherSuite),
+ #{key_exchange := KeyAlgorithm} = ssl_cipher_format:suite_definition(CipherSuite),
State = Connection:queue_handshake(ServerHello, State0),
State#state{key_algorithm = KeyAlgorithm}.
@@ -1643,7 +1557,7 @@ handle_peer_cert(Role, PeerCert, PublicKeyInfo,
State1 = State0#state{session =
Session#session{peer_certificate = PeerCert},
public_key_info = PublicKeyInfo},
- #{key_exchange := KeyAlgorithm} = ssl_cipher:suite_definition(CipherSuite),
+ #{key_exchange := KeyAlgorithm} = ssl_cipher_format:suite_definition(CipherSuite),
State2 = handle_peer_cert_key(Role, PeerCert, PublicKeyInfo, KeyAlgorithm, State1),
{Record, State} = Connection:next_record(State2),
@@ -2250,22 +2164,24 @@ generate_srp_server_keys(_SrpParams, 10) ->
generate_srp_server_keys(SrpParams =
#srp_user{generator = Generator, prime = Prime,
verifier = Verifier}, N) ->
- case crypto:generate_key(srp, {host, [Verifier, Generator, Prime, '6a']}) of
- error ->
- generate_srp_server_keys(SrpParams, N+1);
+ try crypto:generate_key(srp, {host, [Verifier, Generator, Prime, '6a']}) of
Keys ->
Keys
+ catch
+ error:_ ->
+ generate_srp_server_keys(SrpParams, N+1)
end.
generate_srp_client_keys(_Generator, _Prime, 10) ->
?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER);
generate_srp_client_keys(Generator, Prime, N) ->
- case crypto:generate_key(srp, {user, [Generator, Prime, '6a']}) of
- error ->
- generate_srp_client_keys(Generator, Prime, N+1);
+ try crypto:generate_key(srp, {user, [Generator, Prime, '6a']}) of
Keys ->
Keys
+ catch
+ error:_ ->
+ generate_srp_client_keys(Generator, Prime, N+1)
end.
handle_srp_identity(Username, {Fun, UserState}) ->
@@ -2452,18 +2368,13 @@ map_extensions(#hello_extensions{renegotiation_info = RenegotiationInfo,
elliptic_curves => ssl_handshake:extension_value(ECCCurves),
sni => ssl_handshake:extension_value(SNI)}.
-terminate_alert(normal, Version, ConnectionStates, Connection) ->
- Connection:encode_alert(?ALERT_REC(?WARNING, ?CLOSE_NOTIFY),
- Version, ConnectionStates);
-terminate_alert({Reason, _}, Version, ConnectionStates, Connection) when Reason == close;
- Reason == shutdown ->
- Connection:encode_alert(?ALERT_REC(?WARNING, ?CLOSE_NOTIFY),
- Version, ConnectionStates);
-
-terminate_alert(_, Version, ConnectionStates, Connection) ->
- {BinAlert, _} = Connection:encode_alert(?ALERT_REC(?FATAL, ?INTERNAL_ERROR),
- Version, ConnectionStates),
- BinAlert.
+terminate_alert(normal) ->
+ ?ALERT_REC(?WARNING, ?CLOSE_NOTIFY);
+terminate_alert({Reason, _}) when Reason == close;
+ Reason == shutdown ->
+ ?ALERT_REC(?WARNING, ?CLOSE_NOTIFY);
+terminate_alert(_) ->
+ ?ALERT_REC(?FATAL, ?INTERNAL_ERROR).
handle_trusted_certs_db(#state{ssl_options =
#ssl_options{cacertfile = <<>>, cacerts = []}}) ->
@@ -2493,16 +2404,15 @@ prepare_connection(#state{renegotiation = Renegotiate,
start_or_recv_from = RecvFrom} = State0, Connection)
when Renegotiate =/= {false, first},
RecvFrom =/= undefined ->
- State1 = Connection:reinit_handshake_data(State0),
+ State1 = Connection:reinit(State0),
{Record, State} = Connection:next_record(State1),
{Record, ack_connection(State)};
prepare_connection(State0, Connection) ->
- State = Connection:reinit_handshake_data(State0),
+ State = Connection:reinit(State0),
{no_record, ack_connection(State)}.
-ack_connection(#state{renegotiation = {true, Initiater}} = State)
- when Initiater == internal;
- Initiater == peer ->
+ack_connection(#state{renegotiation = {true, Initiater}} = State) when Initiater == peer;
+ Initiater == internal ->
State#state{renegotiation = undefined};
ack_connection(#state{renegotiation = {true, From}} = State) ->
gen_statem:reply(From, ok),
@@ -2608,7 +2518,7 @@ ssl_options_list([ciphers = Key | Keys], [Value | Values], Acc) ->
ssl_options_list(Keys, Values,
[{Key, lists:map(
fun(Suite) ->
- ssl_cipher:suite_definition(Suite)
+ ssl_cipher_format:suite_definition(Suite)
end, Value)}
| Acc]);
ssl_options_list([Key | Keys], [Value | Values], Acc) ->
@@ -2651,35 +2561,6 @@ handle_active_option(_, StateName0, To, Reply, #state{protocol_cb = Connection}
end
end.
-encode_packet(Data, #socket_options{packet=Packet}) ->
- case Packet of
- 1 -> encode_size_packet(Data, 8, (1 bsl 8) - 1);
- 2 -> encode_size_packet(Data, 16, (1 bsl 16) - 1);
- 4 -> encode_size_packet(Data, 32, (1 bsl 32) - 1);
- _ -> Data
- end.
-
-encode_size_packet(Bin, Size, Max) ->
- Len = erlang:byte_size(Bin),
- case Len > Max of
- true -> throw({error, {badarg, {packet_to_large, Len, Max}}});
- false -> <<Len:Size, Bin/binary>>
- end.
-
-time_to_renegotiate(_Data,
- #{current_write := #{sequence_number := Num}},
- RenegotiateAt) ->
-
- %% We could do test:
- %% is_time_to_renegotiate((erlang:byte_size(_Data) div ?MAX_PLAIN_TEXT_LENGTH) + 1, RenegotiateAt),
- %% but we chose to have a some what lower renegotiateAt and a much cheaper test
- is_time_to_renegotiate(Num, RenegotiateAt).
-
-is_time_to_renegotiate(N, M) when N < M->
- false;
-is_time_to_renegotiate(_,_) ->
- true.
-
%% Picks ClientData
get_data(_, _, <<>>) ->
@@ -2726,9 +2607,10 @@ decode_packet(Type, Buffer, PacketOpts) ->
%% Note that if the user has explicitly configured the socket to expect
%% HTTP headers using the {packet, httph} option, we don't do any automatic
%% switching of states.
-deliver_app_data(Transport, Socket, SOpts = #socket_options{active=Active, packet=Type},
+deliver_app_data(CPids, Transport, Socket, SOpts = #socket_options{active=Active, packet=Type},
Data, Pid, From, Tracker, Connection) ->
- send_or_reply(Active, Pid, From, format_reply(Transport, Socket, SOpts, Data, Tracker, Connection)),
+ send_or_reply(Active, Pid, From,
+ format_reply(CPids, Transport, Socket, SOpts, Data, Tracker, Connection)),
SO = case Data of
{P, _, _, _} when ((P =:= http_request) or (P =:= http_response)),
((Type =:= http) or (Type =:= http_bin)) ->
@@ -2747,21 +2629,24 @@ deliver_app_data(Transport, Socket, SOpts = #socket_options{active=Active, packe
SO
end.
-format_reply(_, _,#socket_options{active = false, mode = Mode, packet = Packet,
+format_reply(_, _, _,#socket_options{active = false, mode = Mode, packet = Packet,
header = Header}, Data, _, _) ->
{ok, do_format_reply(Mode, Packet, Header, Data)};
-format_reply(Transport, Socket, #socket_options{active = _, mode = Mode, packet = Packet,
+format_reply(CPids, Transport, Socket, #socket_options{active = _, mode = Mode, packet = Packet,
header = Header}, Data, Tracker, Connection) ->
- {ssl, Connection:socket(self(), Transport, Socket, Connection, Tracker),
+ {ssl, Connection:socket(CPids, Transport, Socket, Connection, Tracker),
do_format_reply(Mode, Packet, Header, Data)}.
-deliver_packet_error(Transport, Socket, SO= #socket_options{active = Active}, Data, Pid, From, Tracker, Connection) ->
- send_or_reply(Active, Pid, From, format_packet_error(Transport, Socket, SO, Data, Tracker, Connection)).
+deliver_packet_error(CPids, Transport, Socket,
+ SO= #socket_options{active = Active}, Data, Pid, From, Tracker, Connection) ->
+ send_or_reply(Active, Pid, From, format_packet_error(CPids,
+ Transport, Socket, SO, Data, Tracker, Connection)).
-format_packet_error(_, _,#socket_options{active = false, mode = Mode}, Data, _, _) ->
+format_packet_error(_, _, _,#socket_options{active = false, mode = Mode}, Data, _, _) ->
{error, {invalid_packet, do_format_reply(Mode, raw, 0, Data)}};
-format_packet_error(Transport, Socket, #socket_options{active = _, mode = Mode}, Data, Tracker, Connection) ->
- {ssl_error, Connection:socket(self(), Transport, Socket, Connection, Tracker),
+format_packet_error(CPids, Transport, Socket, #socket_options{active = _, mode = Mode},
+ Data, Tracker, Connection) ->
+ {ssl_error, Connection:socket(CPids, Transport, Socket, Connection, Tracker),
{invalid_packet, do_format_reply(Mode, raw, 0, Data)}}.
do_format_reply(binary, _, N, Data) when N > 0 -> % Header mode
@@ -2799,29 +2684,29 @@ send_user(Pid, Msg) ->
Pid ! Msg,
ok.
-alert_user(Transport, Tracker, Socket, connection, Opts, Pid, From, Alert, Role, Connection) ->
- alert_user(Transport, Tracker, Socket, Opts#socket_options.active, Pid, From, Alert, Role, Connection);
-alert_user(Transport, Tracker, Socket,_, _, _, From, Alert, Role, Connection) ->
- alert_user(Transport, Tracker, Socket, From, Alert, Role, Connection).
+alert_user(Pids, Transport, Tracker, Socket, connection, Opts, Pid, From, Alert, Role, Connection) ->
+ alert_user(Pids, Transport, Tracker, Socket, Opts#socket_options.active, Pid, From, Alert, Role, Connection);
+alert_user(Pids, Transport, Tracker, Socket,_, _, _, From, Alert, Role, Connection) ->
+ alert_user(Pids, Transport, Tracker, Socket, From, Alert, Role, Connection).
-alert_user(Transport, Tracker, Socket, From, Alert, Role, Connection) ->
- alert_user(Transport, Tracker, Socket, false, no_pid, From, Alert, Role, Connection).
+alert_user(Pids, Transport, Tracker, Socket, From, Alert, Role, Connection) ->
+ alert_user(Pids, Transport, Tracker, Socket, false, no_pid, From, Alert, Role, Connection).
-alert_user(_, _, _, false = Active, Pid, From, Alert, Role, _) when From =/= undefined ->
+alert_user(_, _, _, _, false = Active, Pid, From, Alert, Role, _) when From =/= undefined ->
%% If there is an outstanding ssl_accept | recv
%% From will be defined and send_or_reply will
%% send the appropriate error message.
ReasonCode = ssl_alert:reason_code(Alert, Role),
send_or_reply(Active, Pid, From, {error, ReasonCode});
-alert_user(Transport, Tracker, Socket, Active, Pid, From, Alert, Role, Connection) ->
+alert_user(Pids, Transport, Tracker, Socket, Active, Pid, From, Alert, Role, Connection) ->
case ssl_alert:reason_code(Alert, Role) of
closed ->
send_or_reply(Active, Pid, From,
- {ssl_closed, Connection:socket(self(),
+ {ssl_closed, Connection:socket(Pids,
Transport, Socket, Connection, Tracker)});
ReasonCode ->
send_or_reply(Active, Pid, From,
- {ssl_error, Connection:socket(self(),
+ {ssl_error, Connection:socket(Pids,
Transport, Socket, Connection, Tracker), ReasonCode})
end.
@@ -2890,42 +2775,14 @@ new_emulated([], EmOpts) ->
EmOpts;
new_emulated(NewEmOpts, _) ->
NewEmOpts.
-%%---------------Erlang distribution --------------------------------------
-
-send_dist_data(StateName, State, DHandle, Acc) ->
- case erlang:dist_ctrl_get_data(DHandle) of
- none ->
- erlang:dist_ctrl_get_data_notification(DHandle),
- hibernate_after(StateName, State, lists:reverse(Acc));
- Data ->
- send_dist_data(
- StateName, State, DHandle,
- [{next_event, {call, {self(), undefined}}, {application_data, Data}}
- |Acc])
- end.
-
-%% Overload mitigation
-eat_msgs(Msg) ->
- receive Msg -> eat_msgs(Msg)
- after 0 -> ok
- end.
-%% When acting as distribution controller map the exit reason
-%% to follow the documented nodedown_reason for net_kernel
stop(Reason, State) ->
- {stop, erl_dist_stop_reason(Reason, State), State}.
+ {stop, Reason, State}.
stop_and_reply(Reason, Replies, State) ->
- {stop_and_reply, erl_dist_stop_reason(Reason, State), Replies, State}.
-
-erl_dist_stop_reason(
- Reason, #state{ssl_options = #ssl_options{erl_dist = true}}) ->
- case Reason of
- normal ->
- %% We cannot exit with normal since that will not bring
- %% down the rest of the distribution processes
- {shutdown, normal};
- _ -> Reason
- end;
-erl_dist_stop_reason(Reason, _State) ->
- Reason.
+ {stop_and_reply, Reason, Replies, State}.
+
+is_dist_up(#{dist_handle := Handle}) when Handle =/= undefined ->
+ true;
+is_dist_up(_) ->
+ false.
diff --git a/lib/ssl/src/ssl_connection.hrl b/lib/ssl/src/ssl_connection.hrl
index 811aa779d5..66e3182313 100644
--- a/lib/ssl/src/ssl_connection.hrl
+++ b/lib/ssl/src/ssl_connection.hrl
@@ -44,6 +44,7 @@
host :: string() | inet:ip_address(),
port :: integer(),
socket :: port() | tuple(), %% TODO: dtls socket
+ sender :: pid() | undefined,
ssl_options :: #ssl_options{},
socket_options :: #socket_options{},
connection_states :: ssl_record:connection_states() | secret_printout(),
@@ -59,7 +60,7 @@
negotiated_version :: ssl_record:ssl_version() | 'undefined',
client_hello_version :: ssl_record:ssl_version() | 'undefined',
client_certificate_requested = false :: boolean(),
- key_algorithm :: ssl_cipher:key_algo(),
+ key_algorithm :: ssl_cipher_format:key_algo(),
hashsign_algorithm = {undefined, undefined},
cert_hashsign_algorithm = {undefined, undefined},
public_key_info :: ssl_handshake:public_key_info() | 'undefined',
@@ -74,6 +75,7 @@
cert_db_ref :: certdb_ref() | 'undefined',
bytes_to_read :: undefined | integer(), %% bytes to read in passive mode
user_data_buffer :: undefined | binary() | secret_printout(),
+ erl_dist_data = #{} :: map(),
renegotiation :: undefined | {boolean(), From::term() | internal | peer},
start_or_recv_from :: term(),
timer :: undefined | reference(), % start_or_recive_timer
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl
index 73757e6b65..ced3c2675e 100644
--- a/lib/ssl/src/ssl_handshake.erl
+++ b/lib/ssl/src/ssl_handshake.erl
@@ -169,14 +169,14 @@ client_certificate_verify(OwnCert, MasterSecret, Version,
end.
%%--------------------------------------------------------------------
--spec certificate_request(ssl_cipher:cipher_suite(), db_handle(),
+-spec certificate_request(ssl_cipher_format:cipher_suite(), db_handle(),
certdb_ref(), #hash_sign_algos{}, ssl_record:ssl_version()) ->
#certificate_request{}.
%%
%% Description: Creates a certificate_request message, called by the server.
%%--------------------------------------------------------------------
certificate_request(CipherSuite, CertDbHandle, CertDbRef, HashSigns, Version) ->
- Types = certificate_types(ssl_cipher:suite_definition(CipherSuite), Version),
+ Types = certificate_types(ssl_cipher_format:suite_definition(CipherSuite), Version),
Authorities = certificate_authorities(CertDbHandle, CertDbRef),
#certificate_request{
certificate_types = Types,
@@ -338,7 +338,7 @@ certify(#certificate{asn1_certificates = ASN1Certs}, CertDbHandle, CertDbRef,
Opts, CRLDbHandle, Role, Host) ->
ServerName = server_name(Opts#ssl_options.server_name_indication, Host, Role),
- [PeerCert | _] = ASN1Certs,
+ [PeerCert | ChainCerts ] = ASN1Certs,
try
{TrustedCert, CertPath} =
ssl_certificate:trusted_cert_and_path(ASN1Certs, CertDbHandle, CertDbRef,
@@ -347,14 +347,14 @@ certify(#certificate{asn1_certificates = ASN1Certs}, CertDbHandle, CertDbRef,
CertDbHandle, CertDbRef, ServerName,
Opts#ssl_options.customize_hostname_check,
Opts#ssl_options.crl_check, CRLDbHandle, CertPath),
- case public_key:pkix_path_validation(TrustedCert,
- CertPath,
- [{max_path_length, Opts#ssl_options.depth},
- {verify_fun, ValidationFunAndState}]) of
+ Options = [{max_path_length, Opts#ssl_options.depth},
+ {verify_fun, ValidationFunAndState}],
+ case public_key:pkix_path_validation(TrustedCert, CertPath, Options) of
{ok, {PublicKeyInfo,_}} ->
{PeerCert, PublicKeyInfo};
{error, Reason} ->
- path_validation_alert(Reason)
+ handle_path_validation_error(Reason, PeerCert, ChainCerts, Opts, Options,
+ CertDbHandle, CertDbRef)
end
catch
error:{badmatch,{asn1, Asn1Reason}} ->
@@ -363,7 +363,6 @@ certify(#certificate{asn1_certificates = ASN1Certs}, CertDbHandle, CertDbRef,
error:OtherReason ->
?ALERT_REC(?FATAL, ?INTERNAL_ERROR, {unexpected_error, OtherReason})
end.
-
%%--------------------------------------------------------------------
-spec certificate_verify(binary(), public_key_info(), ssl_record:ssl_version(), term(),
binary(), ssl_handshake_history()) -> valid | #alert{}.
@@ -636,6 +635,14 @@ encode_hello_extensions([#hash_sign_algos{hash_sign_algos = HashSignAlgos} | Res
Len = ListLen + 2,
encode_hello_extensions(Rest, <<?UINT16(?SIGNATURE_ALGORITHMS_EXT),
?UINT16(Len), ?UINT16(ListLen), SignAlgoList/binary, Acc/binary>>);
+encode_hello_extensions([#signature_scheme_list{
+ signature_scheme_list = SignatureSchemes} | Rest], Acc) ->
+ SignSchemeList = << <<(ssl_cipher:signature_scheme(SignatureScheme)):16 >> ||
+ SignatureScheme <- SignatureSchemes >>,
+ ListLen = byte_size(SignSchemeList),
+ Len = ListLen + 2,
+ encode_hello_extensions(Rest, <<?UINT16(?SIGNATURE_ALGORITHMS_CERT_EXT),
+ ?UINT16(Len), ?UINT16(ListLen), SignSchemeList/binary, Acc/binary>>);
encode_hello_extensions([#sni{hostname = Hostname} | Rest], Acc) ->
HostLen = length(Hostname),
HostnameBin = list_to_binary(Hostname),
@@ -758,7 +765,7 @@ decode_hello_extensions(Extensions) ->
dec_hello_extensions(Extensions, #hello_extensions{}).
%%--------------------------------------------------------------------
--spec decode_server_key(binary(), ssl_cipher:key_algo(), ssl_record:ssl_version()) ->
+-spec decode_server_key(binary(), ssl_cipher_format:key_algo(), ssl_record:ssl_version()) ->
#server_key_params{}.
%%
%% Description: Decode server_key data and return appropriate type
@@ -767,7 +774,7 @@ decode_server_key(ServerKey, Type, Version) ->
dec_server_key(ServerKey, key_exchange_alg(Type), Version).
%%--------------------------------------------------------------------
--spec decode_client_key(binary(), ssl_cipher:key_algo(), ssl_record:ssl_version()) ->
+-spec decode_client_key(binary(), ssl_cipher_format:key_algo(), ssl_record:ssl_version()) ->
#encrypted_premaster_secret{}
| #client_diffie_hellman_public{}
| #client_ec_diffie_hellman_public{}
@@ -805,7 +812,7 @@ available_suites(ServerCert, UserSuites, Version, undefined, Curve) ->
filter_unavailable_ecc_suites(Curve, Suites);
available_suites(ServerCert, UserSuites, Version, HashSigns, Curve) ->
Suites = available_suites(ServerCert, UserSuites, Version, undefined, Curve),
- filter_hashsigns(Suites, [ssl_cipher:suite_definition(Suite) || Suite <- Suites], HashSigns,
+ filter_hashsigns(Suites, [ssl_cipher_format:suite_definition(Suite) || Suite <- Suites], HashSigns,
Version, []).
available_signature_algs(undefined, _) ->
@@ -887,22 +894,24 @@ premaster_secret(PublicDhKey, PrivateDhKey, #server_dh_params{dh_p = Prime, dh_g
end;
premaster_secret(#client_srp_public{srp_a = ClientPublicKey}, ServerKey, #srp_user{prime = Prime,
verifier = Verifier}) ->
- case crypto:compute_key(srp, ClientPublicKey, ServerKey, {host, [Verifier, Prime, '6a']}) of
- error ->
- throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER));
+ try crypto:compute_key(srp, ClientPublicKey, ServerKey, {host, [Verifier, Prime, '6a']}) of
PremasterSecret ->
PremasterSecret
+ catch
+ error:_ ->
+ throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER))
end;
premaster_secret(#server_srp_params{srp_n = Prime, srp_g = Generator, srp_s = Salt, srp_b = Public},
ClientKeys, {Username, Password}) ->
case ssl_srp_primes:check_srp_params(Generator, Prime) of
ok ->
DerivedKey = crypto:hash(sha, [Salt, crypto:hash(sha, [Username, <<$:>>, Password])]),
- case crypto:compute_key(srp, Public, ClientKeys, {user, [DerivedKey, Prime, Generator, '6a']}) of
- error ->
- throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER));
+ try crypto:compute_key(srp, Public, ClientKeys, {user, [DerivedKey, Prime, Generator, '6a']}) of
PremasterSecret ->
PremasterSecret
+ catch
+ error ->
+ throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER))
end;
_ ->
throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER))
@@ -958,10 +967,11 @@ premaster_secret(EncSecret, #'RSAPrivateKey'{} = RSAPrivateKey) ->
%%====================================================================
client_hello_extensions(Version, CipherSuites,
#ssl_options{signature_algs = SupportedHashSigns,
+ signature_algs_cert = SignatureSchemes,
eccs = SupportedECCs,
versions = Versions} = SslOpts, ConnectionStates, Renegotiation) ->
{EcPointFormats, EllipticCurves} =
- case advertises_ec_ciphers(lists:map(fun ssl_cipher:suite_definition/1, CipherSuites)) of
+ case advertises_ec_ciphers(lists:map(fun ssl_cipher_format:suite_definition/1, CipherSuites)) of
true ->
client_ecc_extensions(SupportedECCs);
false ->
@@ -988,7 +998,9 @@ client_hello_extensions(Version, CipherSuites,
{3,4} ->
HelloExtensions#hello_extensions{
client_hello_versions = #client_hello_versions{
- versions = Versions}};
+ versions = Versions},
+ signature_algs_cert = #signature_scheme_list{
+ signature_scheme_list = SignatureSchemes}};
_Else ->
HelloExtensions
end.
@@ -1096,7 +1108,9 @@ select_curve(undefined, _, _) ->
select_hashsign(_, _, KeyExAlgo, _, _Version) when KeyExAlgo == dh_anon;
KeyExAlgo == ecdh_anon;
KeyExAlgo == srp_anon;
- KeyExAlgo == psk ->
+ KeyExAlgo == psk;
+ KeyExAlgo == dhe_psk;
+ KeyExAlgo == ecdhe_psk ->
{null, anon};
%% The signature_algorithms extension was introduced with TLS 1.2. Ignore it if we have
%% negotiated a lower version.
@@ -1348,6 +1362,45 @@ apply_user_fun(Fun, OtpCert, ExtensionOrError, UserState0, SslState, _CertPath)
{unknown, {SslState, UserState}}
end.
+handle_path_validation_error({bad_cert, unknown_ca} = Reason, PeerCert, Chain,
+ Opts, Options, CertDbHandle, CertsDbRef) ->
+ handle_incomplete_chain(PeerCert, Chain, Opts, Options, CertDbHandle, CertsDbRef, Reason);
+handle_path_validation_error({bad_cert, invalid_issuer} = Reason, PeerCert, Chain0,
+ Opts, Options, CertDbHandle, CertsDbRef) ->
+ case ssl_certificate:certificate_chain(PeerCert, CertDbHandle, CertsDbRef, Chain0) of
+ {ok, _, [PeerCert | Chain] = OrdedChain} when Chain =/= Chain0 -> %% Chain appaears to be unorded
+ {Trusted, Path} = ssl_certificate:trusted_cert_and_path(OrdedChain,
+ CertDbHandle, CertsDbRef,
+ Opts#ssl_options.partial_chain),
+ case public_key:pkix_path_validation(Trusted, Path, Options) of
+ {ok, {PublicKeyInfo,_}} ->
+ {PeerCert, PublicKeyInfo};
+ {error, PathError} ->
+ handle_path_validation_error(PathError, PeerCert, Path,
+ Opts, Options, CertDbHandle, CertsDbRef)
+ end;
+ _ ->
+ path_validation_alert(Reason)
+ end;
+handle_path_validation_error(Reason, _, _, _, _,_, _) ->
+ path_validation_alert(Reason).
+
+handle_incomplete_chain(PeerCert, Chain0, Opts, Options, CertDbHandle, CertsDbRef, PathError0) ->
+ case ssl_certificate:certificate_chain(PeerCert, CertDbHandle, CertsDbRef) of
+ {ok, _, [PeerCert | _] = Chain} when Chain =/= Chain0 -> %% Chain candidate found
+ {Trusted, Path} = ssl_certificate:trusted_cert_and_path(Chain,
+ CertDbHandle, CertsDbRef,
+ Opts#ssl_options.partial_chain),
+ case public_key:pkix_path_validation(Trusted, Path, Options) of
+ {ok, {PublicKeyInfo,_}} ->
+ {PeerCert, PublicKeyInfo};
+ {error, PathError} ->
+ path_validation_alert(PathError)
+ end;
+ _ ->
+ path_validation_alert(PathError0)
+ end.
+
path_validation_alert({bad_cert, cert_expired}) ->
?ALERT_REC(?FATAL, ?CERTIFICATE_EXPIRED);
path_validation_alert({bad_cert, invalid_issuer}) ->
@@ -1360,8 +1413,6 @@ path_validation_alert({bad_cert, unknown_critical_extension}) ->
?ALERT_REC(?FATAL, ?UNSUPPORTED_CERTIFICATE);
path_validation_alert({bad_cert, {revoked, _}}) ->
?ALERT_REC(?FATAL, ?CERTIFICATE_REVOKED);
-%%path_validation_alert({bad_cert, revocation_status_undetermined}) ->
-%% ?ALERT_REC(?FATAL, ?BAD_CERTIFICATE);
path_validation_alert({bad_cert, {revocation_status_undetermined, Details}}) ->
Alert = ?ALERT_REC(?FATAL, ?BAD_CERTIFICATE),
Alert#alert{reason = Details};
@@ -1775,6 +1826,7 @@ encode_versions([{M,N}|T], Acc) ->
hello_extensions_list(#hello_extensions{renegotiation_info = RenegotiationInfo,
srp = SRP,
signature_algs = HashSigns,
+ signature_algs_cert = SignatureSchemes,
ec_point_formats = EcPointFormats,
elliptic_curves = EllipticCurves,
alpn = ALPN,
@@ -1782,7 +1834,7 @@ hello_extensions_list(#hello_extensions{renegotiation_info = RenegotiationInfo,
sni = Sni,
client_hello_versions = Versions,
server_hello_selected_version = Version}) ->
- [Ext || Ext <- [RenegotiationInfo, SRP, HashSigns,
+ [Ext || Ext <- [RenegotiationInfo, SRP, HashSigns, SignatureSchemes,
EcPointFormats, EllipticCurves, ALPN,
NextProtocolNegotiation, Sni,
Versions, Version], Ext =/= undefined].
@@ -1960,6 +2012,16 @@ dec_hello_extensions(<<?UINT16(?SIGNATURE_ALGORITHMS_EXT), ?UINT16(Len),
dec_hello_extensions(Rest, Acc#hello_extensions{signature_algs =
#hash_sign_algos{hash_sign_algos = HashSignAlgos}});
+dec_hello_extensions(<<?UINT16(?SIGNATURE_ALGORITHMS_CERT_EXT), ?UINT16(Len),
+ ExtData:Len/binary, Rest/binary>>, Acc) ->
+ SignSchemeListLen = Len - 2,
+ <<?UINT16(SignSchemeListLen), SignSchemeList/binary>> = ExtData,
+ SignSchemes = [ssl_cipher:signature_scheme(SignScheme) ||
+ <<?UINT16(SignScheme)>> <= SignSchemeList],
+ dec_hello_extensions(Rest, Acc#hello_extensions{signature_algs_cert =
+ #signature_scheme_list{
+ signature_scheme_list = SignSchemes}});
+
dec_hello_extensions(<<?UINT16(?ELLIPTIC_CURVES_EXT), ?UINT16(Len),
ExtData:Len/binary, Rest/binary>>, Acc) ->
<<?UINT16(_), EllipticCurveList/binary>> = ExtData,
@@ -2501,7 +2563,7 @@ handle_renegotiation_info(_RecordCB, ConnectionStates, SecureRenegotation) ->
cert_curve(_, _, no_suite) ->
{no_curve, no_suite};
cert_curve(Cert, ECCCurve0, CipherSuite) ->
- case ssl_cipher:suite_definition(CipherSuite) of
+ case ssl_cipher_format:suite_definition(CipherSuite) of
#{key_exchange := Kex} when Kex == ecdh_ecdsa;
Kex == ecdh_rsa ->
OtpCert = public_key:pkix_decode_cert(Cert, otp),
diff --git a/lib/ssl/src/ssl_handshake.hrl b/lib/ssl/src/ssl_handshake.hrl
index 9cc6f570fc..36aefd5e22 100644
--- a/lib/ssl/src/ssl_handshake.hrl
+++ b/lib/ssl/src/ssl_handshake.hrl
@@ -107,7 +107,8 @@
elliptic_curves,
sni,
client_hello_versions,
- server_hello_selected_version
+ server_hello_selected_version,
+ signature_algs_cert
}).
-record(server_hello, {
@@ -320,7 +321,7 @@
}).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Application-Layer Protocol Negotiation RFC 7301
+%% RFC 7301 Application-Layer Protocol Negotiation
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-define(ALPN_EXT, 16).
@@ -340,7 +341,7 @@
-record(next_protocol, {selected_protocol}).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% ECC Extensions RFC 4492 section 4 and 5
+%% ECC Extensions RFC 8422 section 4 and 5 (RFC 7919 not supported)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-define(ELLIPTIC_CURVES_EXT, 10).
@@ -367,10 +368,11 @@
-define(NAMED_CURVE, 3).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Server name indication RFC 6066 section 3
+%% RFC 6066 Server name indication
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--define(SNI_EXT, 16#0000).
+%% section 3
+-define(SNI_EXT, 0).
%% enum { host_name(0), (255) } NameType;
-define(SNI_NAMETYPE_HOST_NAME, 0).
@@ -379,8 +381,43 @@
hostname = undefined
}).
+%% Other possible values from RFC 6066, not supported
+-define(MAX_FRAGMENT_LENGTH, 1).
+-define(CLIENT_CERTIFICATE_URL, 2).
+-define(TRUSTED_CA_KEYS, 3).
+-define(TRUNCATED_HMAC, 4).
+-define(STATUS_REQUEST, 5).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% RFC 7250 Using Raw Public Keys in Transport Layer Security (TLS)
+%% and Datagram Transport Layer Security (DTLS)
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Not supported
+-define(CLIENT_CERTIFICATE_TYPE, 19).
+-define(SERVER_CERTIFICATE_TYPE, 20).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% RFC 6520 Transport Layer Security (TLS) and
+%% Datagram Transport Layer Security (DTLS) Heartbeat Extension
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Not supported
+-define(HEARTBEAT, 15).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% RFC 6962 Certificate Transparency
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Not supported
+-define(SIGNED_CERTIFICATE_TIMESTAMP, 18).
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Supported Versions TLS 1.3 section 4.2.1
+%% RFC 7685 A Transport Layer Security (TLS) ClientHello Padding Extension
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Not supported
+-define(PADDING, 21).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Supported Versions RFC 8446 (TLS 1.3) section 4.2.1 also affects TLS-1.2
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-define(SUPPORTED_VERSIONS_EXT, 43).
@@ -388,4 +425,12 @@
-record(client_hello_versions, {versions}).
-record(server_hello_selected_version, {selected_version}).
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Signature Algorithms RFC 8446 (TLS 1.3) section 4.2.3 also affects TLS-1.2
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+-define(SIGNATURE_ALGORITHMS_CERT_EXT, 50).
+
+-record(signature_scheme_list, {signature_scheme_list}).
+
-endif. % -ifdef(ssl_handshake).
diff --git a/lib/ssl/src/ssl_internal.hrl b/lib/ssl/src/ssl_internal.hrl
index 0d3093c1ae..5a18f6aa99 100644
--- a/lib/ssl/src/ssl_internal.hrl
+++ b/lib/ssl/src/ssl_internal.hrl
@@ -146,7 +146,7 @@
%% undefined if not hibernating, or number of ms of
%% inactivity after which ssl_connection will go into
%% hibernation
- hibernate_after :: timeout(),
+ hibernate_after :: timeout(),
%% This option should only be set to true by inet_tls_dist
erl_dist = false :: boolean(),
alpn_advertised_protocols = undefined :: [binary()] | undefined ,
@@ -168,6 +168,7 @@
crl_check :: boolean() | peer | best_effort,
crl_cache,
signature_algs,
+ signature_algs_cert,
eccs,
honor_ecc_order :: boolean(),
max_handshake_size :: integer(),
diff --git a/lib/ssl/src/ssl_manager.erl b/lib/ssl/src/ssl_manager.erl
index b3a425b2fe..c938772bc1 100644
--- a/lib/ssl/src/ssl_manager.erl
+++ b/lib/ssl/src/ssl_manager.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/ssl/src/ssl_pem_cache.erl b/lib/ssl/src/ssl_pem_cache.erl
index a952e20133..b7d23ef01e 100644
--- a/lib/ssl/src/ssl_pem_cache.erl
+++ b/lib/ssl/src/ssl_pem_cache.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 20016-2017. All Rights Reserved.
+%% Copyright Ericsson AB 20016-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/ssl/src/ssl_pkix_db.erl b/lib/ssl/src/ssl_pkix_db.erl
index e7e4af942a..dec48fa914 100644
--- a/lib/ssl/src/ssl_pkix_db.erl
+++ b/lib/ssl/src/ssl_pkix_db.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/ssl/src/ssl_record.erl b/lib/ssl/src/ssl_record.erl
index 659e1485ac..446bb6c56a 100644
--- a/lib/ssl/src/ssl_record.erl
+++ b/lib/ssl/src/ssl_record.erl
@@ -278,13 +278,12 @@ compress(?NULL, Data, CS) ->
{Data, CS}.
%%--------------------------------------------------------------------
--spec compressions() -> [binary()].
+-spec compressions() -> [integer()].
%%
%% Description: return a list of compressions supported (currently none)
%%--------------------------------------------------------------------
compressions() ->
- [?byte(?NULL)].
-
+ [?NULL].
%%====================================================================
%% Payload encryption/decryption
diff --git a/lib/ssl/src/ssl_v3.erl b/lib/ssl/src/ssl_v3.erl
index 82d165f995..4eab60b440 100644
--- a/lib/ssl/src/ssl_v3.erl
+++ b/lib/ssl/src/ssl_v3.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -131,7 +131,7 @@ setup_keys(MasterSecret, ServerRandom, ClientRandom, HS, KML, _EKML, IVS) ->
{ClientWriteMacSecret, ServerWriteMacSecret, ClientWriteKey,
ServerWriteKey, ClientIV, ServerIV}.
--spec suites() -> [ssl_cipher:cipher_suite()].
+-spec suites() -> [ssl_cipher_format:cipher_suite()].
suites() ->
[
diff --git a/lib/ssl/src/tls.erl b/lib/ssl/src/tls.erl
deleted file mode 100644
index aa41cd1ba6..0000000000
--- a/lib/ssl/src/tls.erl
+++ /dev/null
@@ -1,112 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%
-
-%%% Purpose : Reflect TLS specific API options (fairly simple wrapper at the moment)
-
--module(tls).
-
--include("ssl_api.hrl").
--include("ssl_internal.hrl").
-
--export([connect/2, connect/3, listen/2, accept/1, accept/2,
- handshake/1, handshake/2, handshake/3]).
-
-%%--------------------------------------------------------------------
-%%
-%% Description: Connect to an TLS server.
-%%--------------------------------------------------------------------
-
--spec connect(host() | port(), [connect_option()]) -> {ok, #sslsocket{}} |
- {error, reason()}.
-
-connect(Socket, Options) when is_port(Socket) ->
- connect(Socket, Options, infinity).
-
--spec connect(host() | port(), [connect_option()] | inet:port_number(),
- timeout() | list()) ->
- {ok, #sslsocket{}} | {error, reason()}.
-
-connect(Socket, SslOptions, Timeout) when is_port(Socket) ->
- TLSOpts = [{protocol, tls} | SslOptions],
- ssl:connect(Socket, TLSOpts, Timeout);
-connect(Host, Port, Options) ->
- connect(Host, Port, Options, infinity).
-
--spec connect(host() | port(), inet:port_number(), list(), timeout()) ->
- {ok, #sslsocket{}} | {error, reason()}.
-
-connect(Host, Port, Options, Timeout) ->
- TLSOpts = [{protocol, tls} | Options],
- ssl:connect(Host, Port, TLSOpts, Timeout).
-
-%%--------------------------------------------------------------------
--spec listen(inet:port_number(), [listen_option()]) ->{ok, #sslsocket{}} | {error, reason()}.
-
-%%
-%% Description: Creates an ssl listen socket.
-%%--------------------------------------------------------------------
-listen(Port, Options) ->
- TLSOpts = [{protocol, tls} | Options],
- ssl:listen(Port, TLSOpts).
-
-%%--------------------------------------------------------------------
-%%
-%% Description: Performs transport accept on an ssl listen socket
-%%--------------------------------------------------------------------
--spec accept(#sslsocket{}) -> {ok, #sslsocket{}} |
- {error, reason()}.
-accept(ListenSocket) ->
- accept(ListenSocket, infinity).
-
--spec accept(#sslsocket{}, timeout()) -> {ok, #sslsocket{}} |
- {error, reason()}.
-accept(Socket, Timeout) ->
- ssl:transport_accept(Socket, Timeout).
-
-%%--------------------------------------------------------------------
-%%
-%% Description: Performs accept on an ssl listen socket. e.i. performs
-%% ssl handshake.
-%%--------------------------------------------------------------------
-
--spec handshake(#sslsocket{}) -> ok | {error, reason()}.
-
-handshake(ListenSocket) ->
- handshake(ListenSocket, infinity).
-
-
--spec handshake(#sslsocket{} | port(), timeout()| [ssl_option()
- | transport_option()]) ->
- ok | {ok, #sslsocket{}} | {error, reason()}.
-
-handshake(#sslsocket{} = Socket, Timeout) ->
- ssl:ssl_accept(Socket, Timeout);
-
-handshake(ListenSocket, SslOptions) when is_port(ListenSocket) ->
- handshake(ListenSocket, SslOptions, infinity).
-
-
--spec handshake(port(), [ssl_option()| transport_option()], timeout()) ->
- {ok, #sslsocket{}} | {error, reason()}.
-
-handshake(Socket, SslOptions, Timeout) when is_port(Socket) ->
- ssl:ssl_accept(Socket, SslOptions, Timeout).
diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl
index 8320d3f7f3..94a4fa511d 100644
--- a/lib/ssl/src/tls_connection.erl
+++ b/lib/ssl/src/tls_connection.erl
@@ -44,30 +44,35 @@
%% Internal application API
%% Setup
--export([start_fsm/8, start_link/7, init/1]).
+-export([start_fsm/8, start_link/8, init/1, pids/1]).
%% State transition handling
--export([next_record/1, next_event/3, next_event/4, handle_common_event/4]).
+-export([next_record/1, next_event/3, next_event/4,
+ handle_common_event/4]).
%% Handshake handling
--export([renegotiate/2, send_handshake/2,
+-export([renegotiation/2, renegotiate/2, send_handshake/2,
queue_handshake/2, queue_change_cipher/2,
- reinit_handshake_data/1, select_sni_extension/1, empty_connection_state/2]).
+ reinit/1, reinit_handshake_data/1, select_sni_extension/1,
+ empty_connection_state/2]).
%% Alert and close handling
--export([encode_alert/3, send_alert/2, close/5, protocol_name/0]).
+-export([send_alert/2, send_alert_in_connection/2, encode_alert/3, close/5, protocol_name/0]).
%% Data handling
--export([encode_data/3, passive_receive/2, next_record_if_active/1, send/3,
- socket/5, setopts/3, getopts/3]).
+-export([encode_data/3, passive_receive/2, next_record_if_active/1,
+ send/3, socket/5, setopts/3, getopts/3]).
%% gen_statem state functions
-export([init/3, error/3, downgrade/3, %% Initiation and take down states
hello/3, user_hello/3, certify/3, cipher/3, abbreviated/3, %% Handshake states
- connection/3, death_row/3]).
+ connection/3]).
%% gen_statem callbacks
-export([callback_mode/0, terminate/3, code_change/4, format_status/2]).
+
+-define(DIST_CNTRL_SPAWN_OPTS, [{priority, max}]).
+
%%====================================================================
%% Internal application API
%%====================================================================
@@ -78,9 +83,10 @@ start_fsm(Role, Host, Port, Socket, {#ssl_options{erl_dist = false},_, Tracker}
User, {CbModule, _,_, _} = CbInfo,
Timeout) ->
try
- {ok, Pid} = tls_connection_sup:start_child([Role, Host, Port, Socket,
+ {ok, Sender} = tls_sender:start(),
+ {ok, Pid} = tls_connection_sup:start_child([Role, Sender, Host, Port, Socket,
Opts, User, CbInfo]),
- {ok, SslSocket} = ssl_connection:socket_control(?MODULE, Socket, Pid, CbModule, Tracker),
+ {ok, SslSocket} = ssl_connection:socket_control(?MODULE, Socket, [Pid, Sender], CbModule, Tracker),
ssl_connection:handshake(SslSocket, Timeout)
catch
error:{badmatch, {error, _} = Error} ->
@@ -91,9 +97,10 @@ start_fsm(Role, Host, Port, Socket, {#ssl_options{erl_dist = true},_, Tracker} =
User, {CbModule, _,_, _} = CbInfo,
Timeout) ->
try
- {ok, Pid} = tls_connection_sup:start_child_dist([Role, Host, Port, Socket,
+ {ok, Sender} = tls_sender:start([{spawn_opt, ?DIST_CNTRL_SPAWN_OPTS}]),
+ {ok, Pid} = tls_connection_sup:start_child_dist([Role, Sender, Host, Port, Socket,
Opts, User, CbInfo]),
- {ok, SslSocket} = ssl_connection:socket_control(?MODULE, Socket, Pid, CbModule, Tracker),
+ {ok, SslSocket} = ssl_connection:socket_control(?MODULE, Socket, [Pid, Sender], CbModule, Tracker),
ssl_connection:handshake(SslSocket, Timeout)
catch
error:{badmatch, {error, _} = Error} ->
@@ -101,25 +108,38 @@ start_fsm(Role, Host, Port, Socket, {#ssl_options{erl_dist = true},_, Tracker} =
end.
%%--------------------------------------------------------------------
--spec start_link(atom(), host(), inet:port_number(), port(), list(), pid(), tuple()) ->
+-spec start_link(atom(), pid(), host(), inet:port_number(), port(), list(), pid(), tuple()) ->
{ok, pid()} | ignore | {error, reason()}.
%%
%% Description: Creates a gen_statem process which calls Module:init/1 to
%% initialize.
%%--------------------------------------------------------------------
-start_link(Role, Host, Port, Socket, Options, User, CbInfo) ->
- {ok, proc_lib:spawn_link(?MODULE, init, [[Role, Host, Port, Socket, Options, User, CbInfo]])}.
+start_link(Role, Sender, Host, Port, Socket, Options, User, CbInfo) ->
+ {ok, proc_lib:spawn_link(?MODULE, init, [[Role, Sender, Host, Port, Socket, Options, User, CbInfo]])}.
-init([Role, Host, Port, Socket, Options, User, CbInfo]) ->
+init([Role, Sender, Host, Port, Socket, {SslOpts, _, _} = Options, User, CbInfo]) ->
process_flag(trap_exit, true),
- State0 = #state{protocol_specific = Map} = initial_state(Role, Host, Port, Socket, Options, User, CbInfo),
+ link(Sender),
+ case SslOpts#ssl_options.erl_dist of
+ true ->
+ process_flag(priority, max);
+ _ ->
+ ok
+ end,
+ State0 = #state{protocol_specific = Map} = initial_state(Role, Sender,
+ Host, Port, Socket, Options, User, CbInfo),
try
State = ssl_connection:ssl_config(State0#state.ssl_options, Role, State0),
- gen_statem:enter_loop(?MODULE, [], init, State)
+ initialize_tls_sender(State),
+ gen_statem:enter_loop(?MODULE, [], init, State)
catch throw:Error ->
EState = State0#state{protocol_specific = Map#{error => Error}},
gen_statem:enter_loop(?MODULE, [], error, EState)
end.
+
+pids(#state{protocol_specific = #{sender := Sender}}) ->
+ [self(), Sender].
+
%%====================================================================
%% State transition handling
%%====================================================================
@@ -237,13 +257,15 @@ handle_common_event(internal, #ssl_tls{type = _Unknown}, StateName, State) ->
%%====================================================================
%% Handshake handling
%%====================================================================
+renegotiation(Pid, WriteState) ->
+ gen_statem:call(Pid, {user_renegotiate, WriteState}).
+
renegotiate(#state{role = client} = State, Actions) ->
%% Handle same way as if server requested
%% the renegotiation
Hs0 = ssl_handshake:init_handshake_history(),
{next_state, connection, State#state{tls_handshake_history = Hs0},
[{next_event, internal, #hello_request{}} | Actions]};
-
renegotiate(#state{role = server,
socket = Socket,
transport_cb = Transport,
@@ -303,6 +325,12 @@ queue_change_cipher(Msg, #state{negotiated_version = Version,
State0#state{connection_states = ConnectionStates,
flight_buffer = Flight0 ++ [BinChangeCipher]}.
+reinit(#state{protocol_specific = #{sender := Sender},
+ negotiated_version = Version,
+ connection_states = #{current_write := Write}} = State) ->
+ tls_sender:update_connection_state(Sender, Write, Version),
+ reinit_handshake_data(State).
+
reinit_handshake_data(State) ->
%% premaster_secret, public_key_info and tls_handshake_info
%% are only needed during the handshake phase.
@@ -324,20 +352,6 @@ empty_connection_state(ConnectionEnd, BeastMitigation) ->
%%====================================================================
%% Alert and close handling
%%====================================================================
-send_alert(Alert, #state{negotiated_version = Version,
- socket = Socket,
- transport_cb = Transport,
- connection_states = ConnectionStates0,
- ssl_options = SslOpts} = State0) ->
- {BinMsg, ConnectionStates} =
- encode_alert(Alert, Version, ConnectionStates0),
-
- send(Transport, Socket, BinMsg),
- Report = #{direction => outbound,
- protocol => 'tls_record',
- message => BinMsg},
- ssl_logger:debug(SslOpts#ssl_options.log_level, Report, #{domain => [otp,ssl,tls_record]}),
- State0#state{connection_states = ConnectionStates}.
%%--------------------------------------------------------------------
-spec encode_alert(#alert{}, ssl_record:ssl_version(), ssl_record:connection_states()) ->
@@ -347,6 +361,25 @@ send_alert(Alert, #state{negotiated_version = Version,
%%--------------------------------------------------------------------
encode_alert(#alert{} = Alert, Version, ConnectionStates) ->
tls_record:encode_alert_record(Alert, Version, ConnectionStates).
+
+send_alert(Alert, #state{negotiated_version = Version,
+ socket = Socket,
+ protocol_cb = Connection,
+ transport_cb = Transport,
+ connection_states = ConnectionStates0,
+ ssl_options = SslOpts} = StateData0) ->
+ {BinMsg, ConnectionStates} =
+ Connection:encode_alert(Alert, Version, ConnectionStates0),
+ Connection:send(Transport, Socket, BinMsg),
+ Report = #{direction => outbound,
+ protocol => 'tls_record',
+ message => BinMsg},
+ ssl_logger:debug(SslOpts#ssl_options.log_level, Report, #{domain => [otp,ssl,tls_record]}),
+ StateData0#state{connection_states = ConnectionStates}.
+
+send_alert_in_connection(Alert, #state{protocol_specific = #{sender := Sender}}) ->
+ tls_sender:send_alert(Sender, Alert).
+
%% User closes or recursive call!
close({close, Timeout}, Socket, Transport = gen_tcp, _,_) ->
tls_socket:setopts(Transport, Socket, [{active, false}]),
@@ -401,8 +434,8 @@ next_record_if_active(State) ->
send(Transport, Socket, Data) ->
tls_socket:send(Transport, Socket, Data).
-socket(Pid, Transport, Socket, Connection, Tracker) ->
- tls_socket:socket(Pid, Transport, Socket, Connection, Tracker).
+socket(Pids, Transport, Socket, Connection, Tracker) ->
+ tls_socket:socket(Pids, Transport, Socket, Connection, Tracker).
setopts(Transport, Socket, Other) ->
tls_socket:setopts(Transport, Socket, Other).
@@ -479,15 +512,17 @@ error(_, _, _) ->
#state{}) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
-hello(internal, #client_hello{extensions = Extensions} = Hello, #state{ssl_options = #ssl_options{handshake = hello},
- start_or_recv_from = From} = State) ->
- {next_state, user_hello, State#state{start_or_recv_from = undefined,
+hello(internal, #client_hello{extensions = Extensions} = Hello,
+ #state{ssl_options = #ssl_options{handshake = hello},
+ start_or_recv_from = From} = State) ->
+ {next_state, user_hello, State#state{start_or_recv_from = undefined,
hello = Hello},
[{reply, From, {ok, ssl_connection:map_extensions(Extensions)}}]};
-hello(internal, #server_hello{extensions = Extensions} = Hello, #state{ssl_options = #ssl_options{handshake = hello},
- start_or_recv_from = From} = State) ->
+hello(internal, #server_hello{extensions = Extensions} = Hello,
+ #state{ssl_options = #ssl_options{handshake = hello},
+ start_or_recv_from = From} = State) ->
{next_state, user_hello, State#state{start_or_recv_from = undefined,
- hello = Hello},
+ hello = Hello},
[{reply, From, {ok, ssl_connection:map_extensions(Extensions)}}]};
hello(internal, #client_hello{client_version = ClientVersion} = Hello,
#state{connection_states = ConnectionStates0,
@@ -571,14 +606,19 @@ cipher(Type, Event, State) ->
%%--------------------------------------------------------------------
connection(info, Event, State) ->
gen_info(Event, ?FUNCTION_NAME, State);
+connection({call, From}, {user_renegotiate, WriteState},
+ #state{connection_states = ConnectionStates} = State) ->
+ {next_state, ?FUNCTION_NAME, State#state{connection_states = ConnectionStates#{current_write => WriteState}},
+ [{next_event,{call, From}, renegotiate}]};
connection(internal, #hello_request{},
- #state{role = client, host = Host, port = Port,
+ #state{role = client,
+ renegotiation = {Renegotiation, _},
+ host = Host, port = Port,
session = #session{own_certificate = Cert} = Session0,
session_cache = Cache, session_cache_cb = CacheCb,
- ssl_options = SslOpts,
- connection_states = ConnectionStates0,
- renegotiation = {Renegotiation, _}} = State0) ->
- Hello = tls_handshake:client_hello(Host, Port, ConnectionStates0, SslOpts,
+ ssl_options = SslOpts,
+ connection_states = ConnectionStates} = State0) ->
+ Hello = tls_handshake:client_hello(Host, Port, ConnectionStates, SslOpts,
Cache, CacheCb, Renegotiation, Cert),
{State1, Actions} = send_handshake(Hello, State0),
{Record, State} =
@@ -587,7 +627,10 @@ connection(internal, #hello_request{},
= Hello#client_hello.session_id}}),
next_event(hello, Record, State, Actions);
connection(internal, #client_hello{} = Hello,
- #state{role = server, allow_renegotiate = true} = State0) ->
+ #state{role = server, allow_renegotiate = true, connection_states = CS,
+ %%protocol_cb = Connection,
+ protocol_specific = #{sender := Sender}
+ } = State0) ->
%% Mitigate Computational DoS attack
%% http://www.educatedguesswork.org/2011/10/ssltls_and_computational_dos.html
%% http://www.thc.org/thc-ssl-dos/ Rather than disabling client
@@ -596,24 +639,21 @@ connection(internal, #client_hello{} = Hello,
erlang:send_after(?WAIT_TO_ALLOW_RENEGOTIATION, self(), allow_renegotiate),
{Record, State} = next_record(State0#state{allow_renegotiate = false,
renegotiation = {true, peer}}),
- next_event(hello, Record, State, [{next_event, internal, Hello}]);
+ {ok, Write} = tls_sender:renegotiate(Sender),
+ next_event(hello, Record, State#state{connection_states = CS#{current_write => Write}},
+ [{next_event, internal, Hello}]);
connection(internal, #client_hello{},
- #state{role = server, allow_renegotiate = false} = State0) ->
+ #state{role = server, allow_renegotiate = false,
+ protocol_cb = Connection} = State0) ->
Alert = ?ALERT_REC(?WARNING, ?NO_RENEGOTIATION),
- State1 = send_alert(Alert, State0),
- {Record, State} = ssl_connection:prepare_connection(State1, ?MODULE),
+ send_alert_in_connection(Alert, State0),
+ State1 = Connection:reinit_handshake_data(State0),
+ {Record, State} = next_record(State1),
next_event(?FUNCTION_NAME, Record, State);
connection(Type, Event, State) ->
ssl_connection:?FUNCTION_NAME(Type, Event, State, ?MODULE).
%%--------------------------------------------------------------------
--spec death_row(gen_statem:event_type(), term(), #state{}) ->
- gen_statem:state_function_result().
-%%--------------------------------------------------------------------
-death_row(Type, Event, State) ->
- ssl_connection:death_row(Type, Event, State, ?MODULE).
-
-%%--------------------------------------------------------------------
-spec downgrade(gen_statem:event_type(), term(), #state{}) ->
gen_statem:state_function_result().
%%--------------------------------------------------------------------
@@ -627,6 +667,7 @@ callback_mode() ->
state_functions.
terminate(Reason, StateName, State) ->
+ ensure_sender_terminate(Reason, State),
catch ssl_connection:terminate(Reason, StateName, State).
format_status(Type, Data) ->
@@ -638,11 +679,13 @@ code_change(_OldVsn, StateName, State, _) ->
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
-initial_state(Role, Host, Port, Socket, {SSLOptions, SocketOptions, Tracker}, User,
+initial_state(Role, Sender, Host, Port, Socket, {SSLOptions, SocketOptions, Tracker}, User,
{CbModule, DataTag, CloseTag, ErrorTag}) ->
- #ssl_options{beast_mitigation = BeastMitigation} = SSLOptions,
+ #ssl_options{beast_mitigation = BeastMitigation,
+ erl_dist = IsErlDist} = SSLOptions,
ConnectionStates = tls_record:init_connection_states(Role, BeastMitigation),
+ ErlDistData = erl_dist_data(IsErlDist),
SessionCacheCb = case application:get_env(ssl, session_cb) of
{ok, Cb} when is_atom(Cb) ->
Cb;
@@ -650,7 +693,7 @@ initial_state(Role, Host, Port, Socket, {SSLOptions, SocketOptions, Tracker}, Us
ssl_session_cache
end,
- Monitor = erlang:monitor(process, User),
+ UserMonitor = erlang:monitor(process, User),
#state{socket_options = SocketOptions,
ssl_options = SSLOptions,
@@ -663,9 +706,10 @@ initial_state(Role, Host, Port, Socket, {SSLOptions, SocketOptions, Tracker}, Us
host = Host,
port = Port,
socket = Socket,
+ erl_dist_data = ErlDistData,
connection_states = ConnectionStates,
protocol_buffers = #protocol_buffers{},
- user_application = {Monitor, User},
+ user_application = {UserMonitor, User},
user_data_buffer = <<>>,
session_cache_cb = SessionCacheCb,
renegotiation = {false, first},
@@ -673,9 +717,37 @@ initial_state(Role, Host, Port, Socket, {SSLOptions, SocketOptions, Tracker}, Us
start_or_recv_from = undefined,
protocol_cb = ?MODULE,
tracker = Tracker,
- flight_buffer = []
+ flight_buffer = [],
+ protocol_specific = #{sender => Sender}
}.
+erl_dist_data(true) ->
+ #{dist_handle => undefined,
+ dist_buffer => <<>>};
+erl_dist_data(false) ->
+ #{}.
+
+initialize_tls_sender(#state{role = Role,
+ socket = Socket,
+ socket_options = SockOpts,
+ tracker = Tracker,
+ protocol_cb = Connection,
+ transport_cb = Transport,
+ negotiated_version = Version,
+ ssl_options = #ssl_options{renegotiate_at = RenegotiateAt},
+ connection_states = #{current_write := ConnectionWriteState},
+ protocol_specific = #{sender := Sender}}) ->
+ Init = #{current_write => ConnectionWriteState,
+ role => Role,
+ socket => Socket,
+ socket_options => SockOpts,
+ tracker => Tracker,
+ protocol_cb => Connection,
+ transport_cb => Transport,
+ negotiated_version => Version,
+ renegotiate_at => RenegotiateAt},
+ tls_sender:initialize(Sender, Init).
+
next_tls_record(Data, StateName, #state{protocol_buffers =
#protocol_buffers{tls_record_buffer = Buf0,
tls_cipher_texts = CT0} = Buffers,
@@ -755,6 +827,9 @@ handle_info({CloseTag, Socket}, StateName,
%% and then receive the final message.
next_event(StateName, no_record, State)
end;
+handle_info({'EXIT', Pid, Reason}, _,
+ #state{protocol_specific = Pid} = State) ->
+ {stop, {shutdown, sender_died, Reason}, State};
handle_info(Msg, StateName, State) ->
ssl_connection:StateName(info, Msg, State, ?MODULE).
@@ -823,7 +898,8 @@ unprocessed_events(Events) ->
erlang:length(Events)-1.
-assert_buffer_sanity(<<?BYTE(_Type), ?UINT24(Length), Rest/binary>>, #ssl_options{max_handshake_size = Max}) when
+assert_buffer_sanity(<<?BYTE(_Type), ?UINT24(Length), Rest/binary>>,
+ #ssl_options{max_handshake_size = Max}) when
Length =< Max ->
case size(Rest) of
N when N < Length ->
@@ -843,3 +919,16 @@ assert_buffer_sanity(Bin, _) ->
throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE,
malformed_handshake_data))
end.
+
+ensure_sender_terminate(downgrade, _) ->
+ ok; %% Do not terminate sender during downgrade phase
+ensure_sender_terminate(_, #state{protocol_specific = #{sender := Sender}}) ->
+ %% Make sure TLS sender dies when connection process is terminated normally
+ %% This is needed if the tls_sender is blocked in prim_inet:send
+ Kill = fun() ->
+ receive
+ after 5000 ->
+ catch (exit(Sender, kill))
+ end
+ end,
+ spawn(Kill).
diff --git a/lib/ssl/src/tls_handshake.erl b/lib/ssl/src/tls_handshake.erl
index 2ad1386900..82ed2e8d14 100644
--- a/lib/ssl/src/tls_handshake.erl
+++ b/lib/ssl/src/tls_handshake.erl
@@ -94,13 +94,13 @@ client_hello(Host, Port, ConnectionStates,
-spec hello(#server_hello{} | #client_hello{}, #ssl_options{},
ssl_record:connection_states() | {inet:port_number(), #session{}, db_handle(),
atom(), ssl_record:connection_states(),
- binary() | undefined, ssl_cipher:key_algo()},
+ binary() | undefined, ssl_cipher_format:key_algo()},
boolean()) ->
{tls_record:tls_version(), session_id(),
ssl_record:connection_states(), alpn | npn, binary() | undefined}|
{tls_record:tls_version(), {resumed | new, #session{}},
ssl_record:connection_states(), binary() | undefined,
- #hello_extensions{}, {ssl_cipher:hash(), ssl_cipher:sign_algo()} |
+ #hello_extensions{}, {ssl_cipher_format:hash(), ssl_cipher_format:sign_algo()} |
undefined} | #alert{}.
%%
%% Description: Handles a received hello message
@@ -291,7 +291,7 @@ handle_client_hello(Version,
no_suite ->
?ALERT_REC(?FATAL, ?INSUFFICIENT_SECURITY, no_suitable_ciphers);
_ ->
- #{key_exchange := KeyExAlg} = ssl_cipher:suite_definition(CipherSuite),
+ #{key_exchange := KeyExAlg} = ssl_cipher_format:suite_definition(CipherSuite),
case ssl_handshake:select_hashsign(ClientHashSigns, Cert, KeyExAlg,
SupportedHashSigns, Version) of
#alert{} = Alert ->
@@ -362,7 +362,7 @@ do_hello(Version, Versions, CipherSuites, Hello, SslOpts, Info, Renegotiation) -
%%--------------------------------------------------------------------
-enc_handshake(#hello_request{}, _Version) ->
+enc_handshake(#hello_request{}, {3, N}) when N < 4 ->
{?HELLO_REQUEST, <<>>};
enc_handshake(#client_hello{client_version = {Major, Minor},
random = Random,
@@ -381,7 +381,8 @@ enc_handshake(#client_hello{client_version = {Major, Minor},
?BYTE(SIDLength), SessionID/binary,
?UINT16(CsLength), BinCipherSuites/binary,
?BYTE(CmLength), BinCompMethods/binary, ExtensionsBin/binary>>};
-
+enc_handshake(HandshakeMsg, {3, 4}) ->
+ tls_handshake_1_3:encode_handshake(HandshakeMsg);
enc_handshake(HandshakeMsg, Version) ->
ssl_handshake:encode_handshake(HandshakeMsg, Version).
@@ -404,7 +405,7 @@ get_tls_handshake_aux(Version, <<?BYTE(Type), ?UINT24(Length),
get_tls_handshake_aux(_Version, Data, _, Acc) ->
{lists:reverse(Acc), Data}.
-decode_handshake(_, ?HELLO_REQUEST, <<>>) ->
+decode_handshake({3, N}, ?HELLO_REQUEST, <<>>) when N < 4 ->
#hello_request{};
decode_handshake(_Version, ?CLIENT_HELLO,
<<?BYTE(Major), ?BYTE(Minor), Random:32/binary,
@@ -418,9 +419,11 @@ decode_handshake(_Version, ?CLIENT_HELLO,
random = Random,
session_id = Session_ID,
cipher_suites = ssl_handshake:decode_suites('2_bytes', CipherSuites),
- compression_methods = Comp_methods,
+ compression_methods = erlang:binary_to_list(Comp_methods),
extensions = DecodedExtensions
};
+decode_handshake({3, 4}, Tag, Msg) ->
+ tls_handshake_1_3:decode_handshake(Tag, Msg);
decode_handshake(Version, Tag, Msg) ->
ssl_handshake:decode_handshake(Version, Tag, Msg).
diff --git a/lib/ssl/src/tls_handshake_1_3.erl b/lib/ssl/src/tls_handshake_1_3.erl
new file mode 100644
index 0000000000..2957e3a5b4
--- /dev/null
+++ b/lib/ssl/src/tls_handshake_1_3.erl
@@ -0,0 +1,149 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%----------------------------------------------------------------------
+%% Purpose: Help funtions for handling the TLS 1.3 (specific parts of)
+%%% TLS handshake protocol
+%%----------------------------------------------------------------------
+
+-module(tls_handshake_1_3).
+
+-include("tls_handshake_1_3.hrl").
+-include("ssl_alert.hrl").
+-include("ssl_internal.hrl").
+-include_lib("public_key/include/public_key.hrl").
+
+%% Encode
+-export([encode_handshake/1, decode_handshake/2]).
+
+encode_handshake(#certificate_request_1_3{
+ certificate_request_context = Context,
+ extensions = Exts})->
+ EncContext = encode_cert_req_context(Context),
+ BinExts = encode_extensions(Exts),
+ {?CERTIFICATE_REQUEST, <<EncContext/binary, BinExts/binary>>};
+encode_handshake(#certificate_1_3{
+ certificate_request_context = Context,
+ entries = Entries}) ->
+ EncContext = encode_cert_req_context(Context),
+ EncEntries = encode_cert_entries(Entries),
+ {?CERTIFICATE, <<EncContext/binary, EncEntries/binary>>};
+encode_handshake(#encrypted_extensions{extensions = Exts})->
+ {?ENCRYPTED_EXTENSIONS, encode_extensions(Exts)};
+encode_handshake(#new_session_ticket{
+ ticket_lifetime = LifeTime,
+ ticket_age_add = Age,
+ ticket_nonce = Nonce,
+ ticket = Ticket,
+ extensions = Exts}) ->
+ TicketSize = byte_size(Ticket),
+ BinExts = encode_extensions(Exts),
+ {?NEW_SESSION_TICKET, <<?UINT32(LifeTime), ?UINT32(Age),
+ ?BYTE(Nonce), ?UINT16(TicketSize), Ticket/binary,
+ BinExts/binary>>};
+encode_handshake(#end_of_early_data{}) ->
+ {?END_OF_EARLY_DATA, <<>>};
+encode_handshake(#key_update{request_update = Update}) ->
+ {?KEY_UPDATE, <<?BYTE(Update)>>};
+encode_handshake(HandshakeMsg) ->
+ ssl_handshake:encode_handshake(HandshakeMsg, {3,4}).
+
+decode_handshake(?CERTIFICATE_REQUEST, <<?BYTE(0), ?UINT16(Size), EncExts:Size/binary>>) ->
+ Exts = decode_extensions(EncExts),
+ #certificate_request_1_3{
+ certificate_request_context = <<>>,
+ extensions = Exts};
+decode_handshake(?CERTIFICATE_REQUEST, <<?BYTE(CSize), Context:CSize/binary,
+ ?UINT16(Size), EncExts:Size/binary>>) ->
+ Exts = decode_extensions(EncExts),
+ #certificate_request_1_3{
+ certificate_request_context = Context,
+ extensions = Exts};
+decode_handshake(?CERTIFICATE, <<?BYTE(0), ?UINT24(Size), Certs:Size/binary>>) ->
+ CertList = decode_cert_entries(Certs),
+ #certificate_1_3{
+ certificate_request_context = <<>>,
+ entries = CertList
+ };
+decode_handshake(?CERTIFICATE, <<?BYTE(CSize), Context:CSize/binary,
+ ?UINT24(Size), Certs:Size/binary>>) ->
+ CertList = decode_cert_entries(Certs),
+ #certificate_1_3{
+ certificate_request_context = Context,
+ entries = CertList
+ };
+decode_handshake(?ENCRYPTED_EXTENSIONS, EncExts) ->
+ #encrypted_extensions{
+ extensions = decode_extensions(EncExts)
+ };
+decode_handshake(?NEW_SESSION_TICKET, <<?UINT32(LifeTime), ?UINT32(Age),
+ ?BYTE(Nonce), ?UINT16(TicketSize), Ticket:TicketSize/binary,
+ BinExts/binary>>) ->
+ Exts = decode_extensions(BinExts),
+ #new_session_ticket{ticket_lifetime = LifeTime,
+ ticket_age_add = Age,
+ ticket_nonce = Nonce,
+ ticket = Ticket,
+ extensions = Exts};
+decode_handshake(?END_OF_EARLY_DATA, _) ->
+ #end_of_early_data{};
+decode_handshake(?KEY_UPDATE, <<?BYTE(Update)>>) ->
+ #key_update{request_update = Update};
+decode_handshake(Tag, HandshakeMsg) ->
+ ssl_handshake:decode_handshake({3,4}, Tag, HandshakeMsg).
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+encode_cert_req_context(<<>>) ->
+ <<?BYTE(0)>>;
+encode_cert_req_context(Bin) ->
+ Size = byte_size(Bin),
+ <<?BYTE(Size), Bin/binary>>.
+
+encode_cert_entries(Entries) ->
+ CertEntryList = encode_cert_entries(Entries, []),
+ Size = byte_size(CertEntryList),
+ <<?UINT24(Size), CertEntryList/binary>>.
+
+encode_cert_entries([], Acc) ->
+ iolist_to_binary(lists:reverse(Acc));
+encode_cert_entries([#certificate_entry{data = Data,
+ extensions = Exts} | Rest], Acc) ->
+ BinExts = encode_extensions(Exts),
+ Size = byte_size(Data),
+ encode_cert_entries(Rest,
+ [<<?UINT24(Size), Data/binary, BinExts/binary>> | Acc]).
+
+decode_cert_entries(Entries) ->
+ decode_cert_entries(Entries, []).
+
+decode_cert_entries(<<>>, Acc) ->
+ lists:reverse(Acc);
+decode_cert_entries(<<?UINT24(DSize), Data:DSize/binary, ?UINT24(Esize), BinExts:Esize/binary,
+ Rest/binary>>, Acc) ->
+ Exts = decode_extensions(BinExts),
+ decode_cert_entries(Rest, [#certificate_entry{data = Data,
+ extensions = Exts} | Acc]).
+
+encode_extensions(Exts)->
+ ssl_handshake:encode_hello_extensions(Exts).
+decode_extensions(Exts) ->
+ ssl_handshake:decode_hello_extensions(Exts).
diff --git a/lib/ssl/src/tls_handshake_1_3.hrl b/lib/ssl/src/tls_handshake_1_3.hrl
new file mode 100644
index 0000000000..9ee0e0f845
--- /dev/null
+++ b/lib/ssl/src/tls_handshake_1_3.hrl
@@ -0,0 +1,226 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+%%----------------------------------------------------------------------
+%% Purpose: Record and constant defenitions for the TLS-handshake protocol
+%% see RFC 8446. Also includes supported hello extensions.
+%%----------------------------------------------------------------------
+
+-ifndef(tls_handshake_1_3).
+-define(tls_handshake_1_3, true).
+
+%% Common to TLS-1.3 and previous TLS versions
+%% Some defenitions may not exist in TLS-1.3 this is
+%% handled elsewhere
+-include("tls_handshake.hrl").
+
+%% New handshake types in TLS-1.3 RFC 8446 B.3
+-define(NEW_SESSION_TICKET, 4).
+-define(END_OF_EARLY_DATA, 5).
+-define(ENCRYPTED_EXTENSIONS, 8).
+-define(KEY_UPDATE, 24).
+%% %% Not really a message but special way to handle handshake hashes
+%% %% when a "hello-retry-request" (special server_hello) is sent
+-define(MESSAGE_HASH, 254).
+
+%% %% RFC 8446 B.3.1.
+%% %% New extension types in TLS-1.3
+-define(PRE_SHARED_KEY_EXT, 41).
+-define(EARLY_DATA_EXT, 42).
+%%-define(SUPPORTED_VERSIONS_EXT, 43). %% Updates TLS 1.2 so defined in ssl_handshake.hrl
+-define(COOKIE_EXT, 44).
+-define(PSK_KEY_EXCHANGE_MODES_EXT, 45).
+-define(CERTIFICATE_AUTHORITIES_EXT, 47).
+-define(OID_FILTERS_EXT, 48).
+-define(POST_HANDSHAKE_AUTH_EXT, 49).
+%% -define(SIGNATURE_ALGORITHMS_CERT_EXT, 50). %% Updates TLS 1.2 so defined in ssl_handshake.hrl
+-define(KEY_SHARE_EXT, 51).
+
+%% RFC 8446 B.3.1
+-record(key_share_entry, {
+ group, %NamedGroup
+ key_exchange %key_exchange<1..2^16-1>;
+ }).
+-record(key_share_client_hello, {
+ entries %% KeyShareEntry client_shares<0..2^16-1>;
+ }).
+-record(key_share_hello_retry_request, {
+ selected_group %% NamedGroup
+ }).
+-record(key_share_server_hello, {
+ server_share %% KeyShareEntry server_share;
+ }).
+
+-record(uncompressed_point_representation, {
+ legacy_form = 4, % uint8 legacy_form = 4;
+ x, % opaque X[coordinate_length];
+ y % opaque Y[coordinate_length];
+ }).
+
+-define(PSK_KE, 0).
+-define(PSK_DHE_KE, 1).
+
+-record(psk_keyexchange_modes, {
+ ke_modes % ke_modes<1..255>
+ }).
+-record(empty, {
+ }).
+-record(early_data_indication, {
+ indication % uint32 max_early_data_size (new_session_ticket) |
+ %% #empty{} (client_hello, encrypted_extensions)
+ }).
+-record(psk_identity, {
+ identity, % opaque identity<1..2^16-1>
+ obfuscated_ticket_age % uint32
+ }).
+-record(offered_psks, {
+ psk_identity, %identities<7..2^16-1>;
+ psk_binder_entry %binders<33..2^16-1>, opaque PskBinderEntry<32..255>
+ }).
+-record(pre_shared_keyextension,{
+ extension %OfferedPsks (client_hello) | uint16 selected_identity (server_hello)
+ }).
+
+%% RFC 8446 B.3.1.2.
+-record(cookie, {
+ cookie %cookie<1..2^16-1>;
+ }).
+
+%%% RFC 8446 B.3.1.3. Signature Algorithm Extension
+%% Signature Schemes
+%% RSASSA-PKCS1-v1_5 algorithms
+-define(RSA_PKCS1_SHA256, 16#0401).
+-define(RSA_PKCS1_SHA384, 16#0501).
+-define(RSA_PKCS1_SHA512, 16#0601).
+
+%% ECDSA algorithms
+-define(ECDSA_SECP256R1_SHA256, 16#0403).
+-define(ECDSA_SECP384R1_SHA384, 16#0503).
+-define(ECDSA_SECP521R1_SHA512, 16#0603).
+
+%% RSASSA-PSS algorithms with public key OID rsaEncryption
+-define(RSA_PSS_RSAE_SHA256, 16#0804).
+-define(RSA_PSS_RSAE_SHA384, 16#0805).
+-define(RSA_PSS_RSAE_SHA512, 16#0806).
+
+%% EdDSA algorithms
+-define(ED25519, 16#0807).
+-define(ED448, 16#0808).
+
+%% RSASSA-PSS algorithms with public key OID RSASSA-PSS
+-define(RSA_PSS_PSS_SHA256, 16#0809).
+-define(RSA_PSS_PSS_SHA384, 16#080a).
+-define(RSA_PSS_PSS_SHA512, 16#080b).
+
+%% Legacy algorithms
+-define(RSA_PKCS1_SHA1, 16#201).
+-define(ECDSA_SHA1, 16#0203).
+
+%% RFC 8446 B.3.1.4. Supported Groups Extension
+%% Elliptic Curve Groups (ECDHE)
+-define(SECP256R1, 16#0017).
+-define(SECP384R1, 16#0018).
+-define(SECP521R1, 16#0019).
+-define(X25519, 16#001D).
+-define(X448, 16#001E).
+
+%% RFC 8446 Finite Field Groups (DHE)
+-define(FFDHE2048, 16#0100).
+-define(FFDHE3072, 16#0101).
+-define(FFDHE4096, 16#0102).
+-define(FFDHE6144, 16#0103).
+-define(FFDHE8192 ,16#0104).
+
+-record(named_group_list, {
+ named_group_list %named_group_list<2..2^16-1>;
+ }).
+
+%% RFC 8446 B.3.2 Server Parameters Messages
+%% opaque DistinguishedName<1..2^16-1>;XS
+-record(certificate_authoritie_sextension, {
+ authorities %DistinguishedName authorities<3..2^16-1>;
+ }).
+
+-record(oid_filter, {
+ certificate_extension_oid, % opaque certificate_extension_oid<1..2^8-1>;
+ certificate_extension_values % opaque certificate_extension_values<0..2^16-1>;
+ }).
+
+-record(oid_filter_extension, {
+ filters %OIDFilter filters<0..2^16-1>;
+ }).
+-record(post_handshake_auth, {
+ }).
+
+-record(encrypted_extensions, {
+ extensions %extensions<0..2^16-1>;
+ }).
+
+-record(certificate_request_1_3, {
+ certificate_request_context, % opaque certificate_request_context<0..2^8-1>;
+ extensions %Extension extensions<2..2^16-1>;
+ }).
+
+%% RFC 8446 B.3.3 Authentication Messages
+
+%% Certificate Type
+-define(X509, 0).
+-define(OpenPGP_RESERVED, 1).
+-define(RawPublicKey, 2).
+
+-record(certificate_entry, {
+ data,
+ %% select (certificate_type) {
+ %% case RawPublicKey:
+ %% /* From RFC 7250 ASN.1_subjectPublicKeyInfo */
+ %% opaque ASN1_subjectPublicKeyInfo<1..2^24-1>;
+
+ %% case X509:
+ %% opaque cert_data<1..2^24-1>;
+ %% };
+ extensions %% Extension extensions<0..2^16-1>;
+ }).
+
+-record(certificate_1_3, {
+ certificate_request_context, % opaque certificate_request_context<0..2^8-1>;
+ entries % CertificateEntry certificate_list<0..2^24-1>;
+ }).
+
+%% RFC 8446 B.3.4. Ticket Establishment
+-record(new_session_ticket, {
+ ticket_lifetime, %unit32
+ ticket_age_add, %unit32
+ ticket_nonce, %opaque ticket_nonce<0..255>;
+ ticket, %opaque ticket<1..2^16-1>
+ extensions %extensions<0..2^16-2>
+ }).
+
+%% RFC 8446 B.3.5. Updating Keys
+-record(end_of_early_data, {
+ }).
+
+-define(UPDATE_NOT_REQUESTED, 0).
+-define(UPDATE_REQUESTED, 1).
+
+-record(key_update, {
+ request_update
+ }).
+
+-endif. % -ifdef(tls_handshake_1_3).
diff --git a/lib/ssl/src/tls_sender.erl b/lib/ssl/src/tls_sender.erl
new file mode 100644
index 0000000000..db67d7ddff
--- /dev/null
+++ b/lib/ssl/src/tls_sender.erl
@@ -0,0 +1,397 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2018-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(tls_sender).
+
+-behaviour(gen_statem).
+
+-include("ssl_internal.hrl").
+-include("ssl_alert.hrl").
+-include("ssl_handshake.hrl").
+-include("ssl_api.hrl").
+
+%% API
+-export([start/0, start/1, initialize/2, send_data/2, send_alert/2, renegotiate/1,
+ update_connection_state/3, dist_tls_socket/1, dist_handshake_complete/3]).
+
+%% gen_statem callbacks
+-export([callback_mode/0, init/1, terminate/3, code_change/4]).
+-export([init/3, connection/3, handshake/3, death_row/3]).
+
+-define(SERVER, ?MODULE).
+
+-record(data, {connection_pid,
+ connection_states = #{},
+ role,
+ socket,
+ socket_options,
+ tracker,
+ protocol_cb,
+ transport_cb,
+ negotiated_version,
+ renegotiate_at,
+ connection_monitor,
+ dist_handle
+ }).
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+%%--------------------------------------------------------------------
+-spec start() -> {ok, Pid :: pid()} |
+ ignore |
+ {error, Error :: term()}.
+-spec start(list()) -> {ok, Pid :: pid()} |
+ ignore |
+ {error, Error :: term()}.
+
+%% Description: Start sender process to avoid dead lock that
+%% may happen when a socket is busy (busy port) and the
+%% same process is sending and receiving
+%%--------------------------------------------------------------------
+start() ->
+ gen_statem:start(?MODULE, [], []).
+start(SpawnOpts) ->
+ gen_statem:start(?MODULE, [], SpawnOpts).
+
+%%--------------------------------------------------------------------
+-spec initialize(pid(), map()) -> ok.
+%% Description: So TLS connection process can initialize it sender
+%% process.
+%%--------------------------------------------------------------------
+initialize(Pid, InitMsg) ->
+ gen_statem:call(Pid, {self(), InitMsg}).
+
+%%--------------------------------------------------------------------
+-spec send_data(pid(), iodata()) -> ok.
+%% Description: Send application data
+%%--------------------------------------------------------------------
+send_data(Pid, AppData) ->
+ %% Needs error handling for external API
+ call(Pid, {application_data, AppData}).
+
+%%--------------------------------------------------------------------
+-spec send_alert(pid(), #alert{}) -> _.
+%% Description: TLS connection process wants to end an Alert
+%% in the connection state.
+%%--------------------------------------------------------------------
+send_alert(Pid, Alert) ->
+ gen_statem:cast(Pid, Alert).
+
+%%--------------------------------------------------------------------
+-spec renegotiate(pid()) -> {ok, WriteState::map()} | {error, closed}.
+%% Description: So TLS connection process can synchronize the
+%% encryption state to be used when handshaking.
+%%--------------------------------------------------------------------
+renegotiate(Pid) ->
+ %% Needs error handling for external API
+ call(Pid, renegotiate).
+%%--------------------------------------------------------------------
+-spec update_connection_state(pid(), WriteState::map(), tls_record:tls_version()) -> ok.
+%% Description: So TLS connection process can synchronize the
+%% encryption state to be used when sending application data.
+%%--------------------------------------------------------------------
+update_connection_state(Pid, NewState, Version) ->
+ gen_statem:cast(Pid, {new_write, NewState, Version}).
+%%--------------------------------------------------------------------
+-spec dist_handshake_complete(pid(), node(), term()) -> ok.
+%% Description: Erlang distribution callback
+%%--------------------------------------------------------------------
+dist_handshake_complete(ConnectionPid, Node, DHandle) ->
+ gen_statem:call(ConnectionPid, {dist_handshake_complete, Node, DHandle}).
+%%--------------------------------------------------------------------
+-spec dist_tls_socket(pid()) -> {ok, #sslsocket{}}.
+%% Description: To enable distribution startup to get a proper "#sslsocket{}"
+%%--------------------------------------------------------------------
+dist_tls_socket(Pid) ->
+ gen_statem:call(Pid, dist_get_tls_socket).
+
+%%%===================================================================
+%%% gen_statem callbacks
+%%%===================================================================
+%%--------------------------------------------------------------------
+-spec callback_mode() -> gen_statem:callback_mode_result().
+%%--------------------------------------------------------------------
+callback_mode() ->
+ state_functions.
+
+%%--------------------------------------------------------------------
+-spec init(Args :: term()) ->
+ gen_statem:init_result(atom()).
+%%--------------------------------------------------------------------
+init(_) ->
+ %% Note: Should not trap exits so that this process
+ %% will be terminated if tls_connection process is
+ %% killed brutally
+ {ok, init, #data{}}.
+
+%%--------------------------------------------------------------------
+-spec init(gen_statem:event_type(),
+ Msg :: term(),
+ StateData :: term()) ->
+ gen_statem:event_handler_result(atom()).
+%%--------------------------------------------------------------------
+init({call, From}, {Pid, #{current_write := WriteState,
+ role := Role,
+ socket := Socket,
+ socket_options := SockOpts,
+ tracker := Tracker,
+ protocol_cb := Connection,
+ transport_cb := Transport,
+ negotiated_version := Version,
+ renegotiate_at := RenegotiateAt}},
+ #data{connection_states = ConnectionStates} = StateData0) ->
+ Monitor = erlang:monitor(process, Pid),
+ StateData =
+ StateData0#data{connection_pid = Pid,
+ connection_monitor = Monitor,
+ connection_states =
+ ConnectionStates#{current_write => WriteState},
+ role = Role,
+ socket = Socket,
+ socket_options = SockOpts,
+ tracker = Tracker,
+ protocol_cb = Connection,
+ transport_cb = Transport,
+ negotiated_version = Version,
+ renegotiate_at = RenegotiateAt},
+ {next_state, handshake, StateData, [{reply, From, ok}]};
+init(info, Msg, StateData) ->
+ handle_info(Msg, ?FUNCTION_NAME, StateData).
+%%--------------------------------------------------------------------
+-spec connection(gen_statem:event_type(),
+ Msg :: term(),
+ StateData :: term()) ->
+ gen_statem:event_handler_result(atom()).
+%%--------------------------------------------------------------------
+connection({call, From}, renegotiate,
+ #data{connection_states = #{current_write := Write}} = StateData) ->
+ {next_state, handshake, StateData, [{reply, From, {ok, Write}}]};
+connection({call, From}, {application_data, AppData},
+ #data{socket_options = SockOpts} = StateData) ->
+ case encode_packet(AppData, SockOpts) of
+ {error, _} = Error ->
+ {next_state, ?FUNCTION_NAME, StateData, [{reply, From, Error}]};
+ Data ->
+ send_application_data(Data, From, ?FUNCTION_NAME, StateData)
+ end;
+connection({call, From}, dist_get_tls_socket,
+ #data{protocol_cb = Connection,
+ transport_cb = Transport,
+ socket = Socket,
+ connection_pid = Pid,
+ tracker = Tracker} = StateData) ->
+ TLSSocket = Connection:socket([Pid, self()], Transport, Socket, Connection, Tracker),
+ {next_state, ?FUNCTION_NAME, StateData, [{reply, From, {ok, TLSSocket}}]};
+connection({call, From}, {dist_handshake_complete, _Node, DHandle}, #data{connection_pid = Pid} = StateData) ->
+ ok = erlang:dist_ctrl_input_handler(DHandle, Pid),
+ ok = ssl_connection:dist_handshake_complete(Pid, DHandle),
+ %% From now on we execute on normal priority
+ process_flag(priority, normal),
+ Events = dist_data_events(DHandle, []),
+ {next_state, ?FUNCTION_NAME, StateData#data{dist_handle = DHandle}, [{reply, From, ok} | Events]};
+connection(cast, #alert{} = Alert, StateData0) ->
+ StateData = send_tls_alert(Alert, StateData0),
+ {next_state, ?FUNCTION_NAME, StateData};
+connection(cast, {new_write, WritesState, Version},
+ #data{connection_states = ConnectionStates0} = StateData) ->
+ {next_state, connection,
+ StateData#data{connection_states =
+ ConnectionStates0#{current_write => WritesState},
+ negotiated_version = Version}};
+connection(info, dist_data, #data{dist_handle = DHandle} = StateData) ->
+ Events = dist_data_events(DHandle, []),
+ {next_state, ?FUNCTION_NAME, StateData, Events};
+connection(info, tick, StateData) ->
+ consume_ticks(),
+ {next_state, ?FUNCTION_NAME, StateData,
+ [{next_event, {call, {self(), undefined}},
+ {application_data, <<>>}}]};
+connection(info, {send, From, Ref, Data}, _StateData) ->
+ %% This is for testing only!
+ %%
+ %% Needed by some OTP distribution
+ %% test suites...
+ From ! {Ref, ok},
+ {keep_state_and_data,
+ [{next_event, {call, {self(), undefined}},
+ {application_data, iolist_to_binary(Data)}}]};
+connection(info, Msg, StateData) ->
+ handle_info(Msg, ?FUNCTION_NAME, StateData).
+%%--------------------------------------------------------------------
+-spec handshake(gen_statem:event_type(),
+ Msg :: term(),
+ StateData :: term()) ->
+ gen_statem:event_handler_result(atom()).
+%%--------------------------------------------------------------------
+handshake({call, _}, _, _) ->
+ {keep_state_and_data, [postpone]};
+handshake(cast, {new_write, WritesState, Version},
+ #data{connection_states = ConnectionStates0} = StateData) ->
+ {next_state, connection,
+ StateData#data{connection_states =
+ ConnectionStates0#{current_write => WritesState},
+ negotiated_version = Version}};
+handshake(info, Msg, StateData) ->
+ handle_info(Msg, ?FUNCTION_NAME, StateData).
+
+%%--------------------------------------------------------------------
+-spec death_row(gen_statem:event_type(),
+ Msg :: term(),
+ StateData :: term()) ->
+ gen_statem:event_handler_result(atom()).
+%%--------------------------------------------------------------------
+death_row(state_timeout, Reason, _State) ->
+ {stop, {shutdown, Reason}};
+death_row(_Type, _Msg, _State) ->
+ %% Waste all other events
+ keep_state_and_data.
+
+%%--------------------------------------------------------------------
+-spec terminate(Reason :: term(), State :: term(), Data :: term()) ->
+ any().
+%%--------------------------------------------------------------------
+terminate(_Reason, _State, _Data) ->
+ void.
+
+%%--------------------------------------------------------------------
+-spec code_change(
+ OldVsn :: term() | {down,term()},
+ State :: term(), Data :: term(), Extra :: term()) ->
+ {ok, NewState :: term(), NewData :: term()} |
+ (Reason :: term()).
+%% Convert process state when code is changed
+%%--------------------------------------------------------------------
+code_change(_OldVsn, State, Data, _Extra) ->
+ {ok, State, Data}.
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+handle_info({'DOWN', Monitor, _, _, Reason}, _,
+ #data{connection_monitor = Monitor,
+ dist_handle = Handle} = StateData) when Handle =/= undefined->
+ {next_state, death_row, StateData, [{state_timeout, 5000, Reason}]};
+handle_info({'DOWN', Monitor, _, _, _}, _,
+ #data{connection_monitor = Monitor} = StateData) ->
+ {stop, normal, StateData};
+handle_info(_,_,_) ->
+ {keep_state_and_data}.
+
+send_tls_alert(Alert, #data{negotiated_version = Version,
+ socket = Socket,
+ protocol_cb = Connection,
+ transport_cb = Transport,
+ connection_states = ConnectionStates0} = StateData0) ->
+ {BinMsg, ConnectionStates} =
+ Connection:encode_alert(Alert, Version, ConnectionStates0),
+ Connection:send(Transport, Socket, BinMsg),
+ StateData0#data{connection_states = ConnectionStates}.
+
+send_application_data(Data, From, StateName,
+ #data{connection_pid = Pid,
+ socket = Socket,
+ dist_handle = DistHandle,
+ negotiated_version = Version,
+ protocol_cb = Connection,
+ transport_cb = Transport,
+ connection_states = ConnectionStates0,
+ renegotiate_at = RenegotiateAt} = StateData0) ->
+ case time_to_renegotiate(Data, ConnectionStates0, RenegotiateAt) of
+ true ->
+ ssl_connection:internal_renegotiation(Pid, ConnectionStates0),
+ {next_state, handshake, StateData0,
+ [{next_event, {call, From}, {application_data, Data}}]};
+ false ->
+ {Msgs, ConnectionStates} =
+ Connection:encode_data(Data, Version, ConnectionStates0),
+ StateData = StateData0#data{connection_states = ConnectionStates},
+ case Connection:send(Transport, Socket, Msgs) of
+ ok when DistHandle =/= undefined ->
+ {next_state, StateName, StateData, []};
+ Reason when DistHandle =/= undefined ->
+ {next_state, death_row, StateData, [{state_timeout, 5000, Reason}]};
+ ok ->
+ {next_state, StateName, StateData, [{reply, From, ok}]};
+ Result ->
+ {next_state, StateName, StateData, [{reply, From, Result}]}
+ end
+ end.
+
+encode_packet(Data, #socket_options{packet=Packet}) ->
+ case Packet of
+ 1 -> encode_size_packet(Data, 8, (1 bsl 8) - 1);
+ 2 -> encode_size_packet(Data, 16, (1 bsl 16) - 1);
+ 4 -> encode_size_packet(Data, 32, (1 bsl 32) - 1);
+ _ -> Data
+ end.
+
+encode_size_packet(Bin, Size, Max) ->
+ Len = erlang:byte_size(Bin),
+ case Len > Max of
+ true ->
+ {error, {badarg, {packet_to_large, Len, Max}}};
+ false ->
+ <<Len:Size, Bin/binary>>
+ end.
+time_to_renegotiate(_Data,
+ #{current_write := #{sequence_number := Num}},
+ RenegotiateAt) ->
+
+ %% We could do test:
+ %% is_time_to_renegotiate((erlang:byte_size(_Data) div
+ %% ?MAX_PLAIN_TEXT_LENGTH) + 1, RenegotiateAt), but we chose to
+ %% have a some what lower renegotiateAt and a much cheaper test
+ is_time_to_renegotiate(Num, RenegotiateAt).
+
+is_time_to_renegotiate(N, M) when N < M->
+ false;
+is_time_to_renegotiate(_,_) ->
+ true.
+
+call(FsmPid, Event) ->
+ try gen_statem:call(FsmPid, Event)
+ catch
+ exit:{noproc, _} ->
+ {error, closed};
+ exit:{normal, _} ->
+ {error, closed};
+ exit:{{shutdown, _},_} ->
+ {error, closed}
+ end.
+
+%%---------------Erlang distribution --------------------------------------
+
+dist_data_events(DHandle, Events) ->
+ case erlang:dist_ctrl_get_data(DHandle) of
+ none ->
+ erlang:dist_ctrl_get_data_notification(DHandle),
+ lists:reverse(Events);
+ Data ->
+ Event = {next_event, {call, {self(), undefined}}, {application_data, Data}},
+ dist_data_events(DHandle, [Event | Events])
+ end.
+
+consume_ticks() ->
+ receive tick ->
+ consume_ticks()
+ after 0 ->
+ ok
+ end.
diff --git a/lib/ssl/src/tls_socket.erl b/lib/ssl/src/tls_socket.erl
index 154281f1c2..a391bc53de 100644
--- a/lib/ssl/src/tls_socket.erl
+++ b/lib/ssl/src/tls_socket.erl
@@ -64,11 +64,12 @@ accept(ListenSocket, #config{transport_info = {Transport,_,_,_} = CbInfo,
{ok, Socket} ->
{ok, EmOpts} = get_emulated_opts(Tracker),
{ok, Port} = tls_socket:port(Transport, Socket),
- ConnArgs = [server, "localhost", Port, Socket,
+ {ok, Sender} = tls_sender:start(),
+ ConnArgs = [server, Sender, "localhost", Port, Socket,
{SslOpts, emulated_socket_options(EmOpts, #socket_options{}), Tracker}, self(), CbInfo],
case tls_connection_sup:start_child(ConnArgs) of
{ok, Pid} ->
- ssl_connection:socket_control(ConnectionCb, Socket, Pid, Transport, Tracker);
+ ssl_connection:socket_control(ConnectionCb, Socket, [Pid, Sender], Transport, Tracker);
{error, Reason} ->
{error, Reason}
end;
@@ -112,8 +113,8 @@ connect(Address, Port,
{error, {options, {socket_options, UserOpts}}}
end.
-socket(Pid, Transport, Socket, ConnectionCb, Tracker) ->
- #sslsocket{pid = Pid,
+socket(Pids, Transport, Socket, ConnectionCb, Tracker) ->
+ #sslsocket{pid = Pids,
%% "The name "fd" is keept for backwards compatibility
fd = {Transport, Socket, ConnectionCb, Tracker}}.
setopts(gen_tcp, #sslsocket{pid = {ListenSocket, #config{emulated = Tracker}}}, Options) ->
diff --git a/lib/ssl/src/tls_v1.erl b/lib/ssl/src/tls_v1.erl
index 6ef6040761..7d28962d2d 100644
--- a/lib/ssl/src/tls_v1.erl
+++ b/lib/ssl/src/tls_v1.erl
@@ -32,7 +32,8 @@
-export([master_secret/4, finished/5, certificate_verify/3, mac_hash/7, hmac_hash/3,
setup_keys/8, suites/1, prf/5,
ecc_curves/1, ecc_curves/2, oid_to_enum/1, enum_to_oid/1,
- default_signature_algs/1, signature_algs/2]).
+ default_signature_algs/1, signature_algs/2,
+ default_signature_schemes/1, signature_schemes/2]).
-type named_curve() :: sect571r1 | sect571k1 | secp521r1 | brainpoolP512r1 |
sect409k1 | sect409r1 | brainpoolP384r1 | secp384r1 |
@@ -193,7 +194,7 @@ mac_hash(Method, Mac_write_secret, Seq_num, Type, {Major, Minor},
Fragment]),
Mac.
--spec suites(1|2|3|4) -> [ssl_cipher:cipher_suite()].
+-spec suites(1|2|3|4) -> [ssl_cipher_format:cipher_suite()].
suites(Minor) when Minor == 1; Minor == 2 ->
[
@@ -247,10 +248,14 @@ suites(3) ->
%% ?TLS_DH_DSS_WITH_AES_128_GCM_SHA256
] ++ suites(2);
-
suites(4) ->
- suites(3).
-
+ [?TLS_AES_256_GCM_SHA384,
+ ?TLS_AES_128_GCM_SHA256,
+ ?TLS_CHACHA20_POLY1305_SHA256
+ %% Not supported
+ %% ?TLS_AES_128_CCM_SHA256,
+ %% ?TLS_AES_128_CCM_8_SHA256
+ ] ++ suites(3).
signature_algs({3, 4}, HashSigns) ->
signature_algs({3, 3}, HashSigns);
@@ -301,6 +306,64 @@ default_signature_algs({3, 3} = Version) ->
default_signature_algs(_) ->
undefined.
+
+signature_schemes(Version, SignatureSchemes) when is_tuple(Version)
+ andalso Version >= {3, 3} ->
+ CryptoSupports = crypto:supports(),
+ Hashes = proplists:get_value(hashs, CryptoSupports),
+ PubKeys = proplists:get_value(public_keys, CryptoSupports),
+ Curves = proplists:get_value(curves, CryptoSupports),
+ Fun = fun (Scheme, Acc) ->
+ {Hash0, Sign0, Curve} =
+ ssl_cipher:scheme_to_components(Scheme),
+ Sign = case Sign0 of
+ rsa_pkcs1 -> rsa;
+ S -> S
+ end,
+ Hash = case Hash0 of
+ sha1 -> sha;
+ H -> H
+ end,
+ case proplists:get_bool(Sign, PubKeys)
+ andalso proplists:get_bool(Hash, Hashes)
+ andalso (Curve =:= undefined orelse
+ proplists:get_bool(Curve, Curves))
+ andalso is_pair(Hash, Sign, Hashes)
+ of
+ true ->
+ [Scheme | Acc];
+ false ->
+ Acc
+ end
+ end,
+ Supported = lists:foldl(Fun, [], SignatureSchemes),
+ lists:reverse(Supported);
+signature_schemes(_, _) ->
+ [].
+
+
+default_signature_schemes(Version) ->
+ Default = [
+ rsa_pkcs1_sha256,
+ rsa_pkcs1_sha384,
+ rsa_pkcs1_sha512,
+ ecdsa_secp256r1_sha256,
+ ecdsa_secp384r1_sha384,
+ ecdsa_secp521r1_sha512,
+ rsa_pss_rsae_sha256,
+ rsa_pss_rsae_sha384,
+ rsa_pss_rsae_sha512,
+ %% ed25519,
+ %% ed448,
+ rsa_pss_pss_sha256,
+ rsa_pss_pss_sha384,
+ rsa_pss_pss_sha512,
+ rsa_pkcs1_sha1,
+ ecdsa_sha1
+ ],
+ signature_schemes(Version, Default).
+
+
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
diff --git a/lib/ssl/test/Makefile b/lib/ssl/test/Makefile
index 9dfb2eba53..d5ba105478 100644
--- a/lib/ssl/test/Makefile
+++ b/lib/ssl/test/Makefile
@@ -61,6 +61,7 @@ MODULES = \
ssl_ECC\
ssl_upgrade_SUITE\
ssl_sni_SUITE \
+ ssl_eqc_SUITE \
make_certs\
x509_test
@@ -144,7 +145,7 @@ release_tests_spec: opt
$(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(HRL_FILES_NEEDED_IN_TEST) $(COVER_FILE) "$(RELSYSDIR)"
$(INSTALL_DATA) ssl.spec ssl_bench.spec ssl.cover "$(RELSYSDIR)"
chmod -R u+w "$(RELSYSDIR)"
- @tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -)
+ @tar cf - *_SUITE_data property_test | (cd "$(RELSYSDIR)"; tar xf -)
release_docs_spec:
diff --git a/lib/ssl/test/property_test/ssl_eqc_handshake.erl b/lib/ssl/test/property_test/ssl_eqc_handshake.erl
new file mode 100644
index 0000000000..88046f7386
--- /dev/null
+++ b/lib/ssl/test/property_test/ssl_eqc_handshake.erl
@@ -0,0 +1,192 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2015. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+
+-module(ssl_eqc_handshake).
+
+-compile(export_all).
+
+-proptest(eqc).
+-proptest([triq,proper]).
+
+-ifndef(EQC).
+-ifndef(PROPER).
+-ifndef(TRIQ).
+-define(EQC,true).
+-endif.
+-endif.
+-endif.
+
+-ifdef(EQC).
+-include_lib("eqc/include/eqc.hrl").
+-define(MOD_eqc,eqc).
+
+-else.
+-ifdef(PROPER).
+-include_lib("proper/include/proper.hrl").
+-define(MOD_eqc,proper).
+
+-else.
+-ifdef(TRIQ).
+-define(MOD_eqc,triq).
+-include_lib("triq/include/triq.hrl").
+
+-endif.
+-endif.
+-endif.
+
+-include_lib("ssl/src/tls_handshake_1_3.hrl").
+-include_lib("ssl/src/tls_handshake.hrl").
+-include_lib("ssl/src/ssl_handshake.hrl").
+-include_lib("ssl/src/ssl_alert.hrl").
+-include_lib("ssl/src/ssl_internal.hrl").
+
+-define('TLS_v1.3', {3,4}).
+-define('TLS_v1.2', {3,3}).
+-define('TLS_v1.1', {3,2}).
+-define('TLS_v1', {3,1}).
+-define('SSL_v3', {3,0}).
+
+%%--------------------------------------------------------------------
+%% Properties --------------------------------------------------------
+%%--------------------------------------------------------------------
+
+prop_tls_hs_encode_decode() ->
+ ?FORALL({Handshake, TLSVersion}, ?LET(Version, tls_version(), {tls_msg(Version), Version}),
+ try
+ [Type, _Length, Data] = tls_handshake:encode_handshake(Handshake, TLSVersion),
+ case tls_handshake:decode_handshake(TLSVersion, Type, Data) of
+ Handshake ->
+ true;
+ _ ->
+ false
+ end
+ catch
+ throw:#alert{} ->
+ true
+ end
+ ).
+
+tls_version() ->
+ oneof([?'TLS_v1.2', ?'TLS_v1.1', ?'TLS_v1', ?'SSL_v3']).
+
+tls_msg(?'TLS_v1.3'= Version) ->
+ oneof([client_hello(Version),
+ %%server_hello(Version)
+ %%new_session_ticket()
+ #end_of_early_data{},
+ %%encrypted_extensions()
+ %%certificate_1_3(),
+ %%certificate_request()
+ %%certificate_verify()
+ %%finished()
+ key_update()
+ %%message_hash()
+ ]);
+tls_msg(Version) ->
+ oneof([#hello_request{},
+ client_hello(Version),
+ %%server_hello(Version)
+ %%certificate(),
+ %%server_key_exchange()
+ %%certificate_request()
+ #server_hello_done{}
+ %%certificate_verify()
+ %%client_key_exchange()
+ %%finished()
+ ]).
+
+client_hello(?'TLS_v1.3' = Version) ->
+ #client_hello{session_id = session_id(),
+ client_version = ?'TLS_v1.2',
+ cipher_suites = ssl_cipher:suites(Version),
+ compression_methods = compressions(Version),
+ random = client_random(Version),
+ extensions = client_extensions(Version)
+ };
+client_hello(Version) ->
+ #client_hello{session_id = session_id(),
+ client_version = Version,
+ cipher_suites = ssl_cipher:suites(Version),
+ compression_methods = compressions(Version),
+ random = client_random(Version),
+ extensions = client_extensions(Version)
+ }.
+session_id() ->
+ crypto:strong_rand_bytes(?NUM_OF_SESSION_ID_BYTES).
+
+compressions(_) ->
+ ssl_record:compressions().
+client_random(_) ->
+ crypto:strong_rand_bytes(32).
+
+client_extensions(?'TLS_v1.3' = Version) ->
+ #hello_extensions{
+ client_hello_versions =
+ #client_hello_versions{
+ versions = supported_versions(Version)
+ },
+ signature_algs_cert =
+ #signature_scheme_list{
+ signature_scheme_list = signature_scheme_list()
+ }
+ };
+client_extensions(Version) ->
+ #hello_extensions{
+ client_hello_versions =
+ #client_hello_versions{
+ versions = supported_versions(Version)
+ }
+ }.
+
+signature_scheme_list() ->
+ oneof([[rsa_pkcs1_sha256],
+ [rsa_pkcs1_sha256, ecdsa_sha1],
+ [rsa_pkcs1_sha256,
+ rsa_pkcs1_sha384,
+ rsa_pkcs1_sha512,
+ ecdsa_secp256r1_sha256,
+ ecdsa_secp384r1_sha384,
+ ecdsa_secp521r1_sha512,
+ rsa_pss_rsae_sha256,
+ rsa_pss_rsae_sha384,
+ rsa_pss_rsae_sha512,
+ rsa_pss_pss_sha256,
+ rsa_pss_pss_sha384,
+ rsa_pss_pss_sha512,
+ rsa_pkcs1_sha1,
+ ecdsa_sha1]
+ ]).
+
+supported_versions(?'TLS_v1.3') ->
+ oneof([[{3,4}],
+ [{3,3},{3,4}],
+ [{3,4},{3,3},{3,2},{3,1},{3,0}]
+ ]);
+supported_versions(_) ->
+ oneof([[{3,3}],
+ [{3,3},{3,2}],
+ [{3,3},{3,2},{3,1},{3,0}]
+ ]).
+
+key_update() ->
+ #key_update{request_update = request_update()}.
+
+request_update() ->
+ oneof([?UPDATE_NOT_REQUESTED, ?UPDATE_REQUESTED]).
diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl
index 480988b6e4..1970c16f1d 100644
--- a/lib/ssl/test/ssl_basic_SUITE.erl
+++ b/lib/ssl/test/ssl_basic_SUITE.erl
@@ -3270,7 +3270,7 @@ no_reuses_session_server_restart_new_cert(Config) when is_list(Config) ->
ssl_test_lib:start_server([{node, ServerNode}, {port, Port},
{from, self()},
{mfa, {ssl_test_lib, no_result, []}},
- {options, DsaServerOpts}]),
+ {options, [{reuseaddr, true} | DsaServerOpts]}]),
Client1 =
ssl_test_lib:start_client([{node, ClientNode},
@@ -3331,7 +3331,7 @@ no_reuses_session_server_restart_new_cert_file(Config) when is_list(Config) ->
ssl_test_lib:start_server([{node, ServerNode}, {port, Port},
{from, self()},
{mfa, {ssl_test_lib, no_result, []}},
- {options, NewServerOpts1}]),
+ {options, [{reuseaddr, true} | NewServerOpts1]}]),
Client1 =
ssl_test_lib:start_client([{node, ClientNode},
{port, Port}, {host, Hostname},
@@ -3674,7 +3674,7 @@ hibernate(Config) ->
{mfa, {ssl_test_lib, send_recv_result_active, []}},
{options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
- {Client, #sslsocket{pid=Pid}} = ssl_test_lib:start_client([return_socket,
+ {Client, #sslsocket{pid=[Pid|_]}} = ssl_test_lib:start_client([return_socket,
{node, ClientNode}, {port, Port},
{host, Hostname},
{from, self()},
@@ -3717,7 +3717,7 @@ hibernate_right_away(Config) ->
Server1 = ssl_test_lib:start_server(StartServerOpts),
Port1 = ssl_test_lib:inet_port(Server1),
- {Client1, #sslsocket{pid = Pid1}} = ssl_test_lib:start_client(StartClientOpts ++
+ {Client1, #sslsocket{pid = [Pid1|_]}} = ssl_test_lib:start_client(StartClientOpts ++
[{port, Port1}, {options, [{hibernate_after, 0}|ClientOpts]}]),
ssl_test_lib:check_result(Server1, ok, Client1, ok),
@@ -3729,7 +3729,7 @@ hibernate_right_away(Config) ->
Server2 = ssl_test_lib:start_server(StartServerOpts),
Port2 = ssl_test_lib:inet_port(Server2),
- {Client2, #sslsocket{pid = Pid2}} = ssl_test_lib:start_client(StartClientOpts ++
+ {Client2, #sslsocket{pid = [Pid2|_]}} = ssl_test_lib:start_client(StartClientOpts ++
[{port, Port2}, {options, [{hibernate_after, 1}|ClientOpts]}]),
ssl_test_lib:check_result(Server2, ok, Client2, ok),
@@ -3965,13 +3965,13 @@ tls_tcp_error_propagation_in_active_mode(Config) when is_list(Config) ->
{mfa, {ssl_test_lib, no_result, []}},
{options, ServerOpts}]),
Port = ssl_test_lib:inet_port(Server),
- {Client, #sslsocket{pid=Pid} = SslSocket} = ssl_test_lib:start_client([return_socket,
- {node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
- {mfa, {?MODULE, receive_msg, []}},
- {options, ClientOpts}]),
-
+ {Client, #sslsocket{pid=[Pid|_]} = SslSocket} = ssl_test_lib:start_client([return_socket,
+ {node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {?MODULE, receive_msg, []}},
+ {options, ClientOpts}]),
+
{status, _, _, StatusInfo} = sys:get_status(Pid),
[_, _,_, _, Prop] = StatusInfo,
State = ssl_test_lib:state(Prop),
@@ -4645,6 +4645,7 @@ renegotiate_rejected(Socket) ->
ok;
%% Handle 1/n-1 splitting countermeasure Rizzo/Duong-Beast
{ssl, Socket, "H"} ->
+
receive
{ssl, Socket, "ello world"} ->
ok
@@ -5032,20 +5033,24 @@ run_suites(Ciphers, Config, Type) ->
[{ciphers, Ciphers} |
ssl_test_lib:ssl_options(server_ecdsa_opts, Config)]}
end,
- ct:pal("ssl_test_lib:filter_suites(~p ~p) -> ~p ", [Ciphers, Version, ssl_test_lib:filter_suites(Ciphers, Version)]),
- Result = lists:map(fun(Cipher) ->
- cipher(Cipher, Version, Config, ClientOpts, ServerOpts) end,
- ssl_test_lib:filter_suites(Ciphers, Version)),
- case lists:flatten(Result) of
- [] ->
- ok;
- Error ->
- ct:log("Cipher suite errors: ~p~n", [Error]),
- ct:fail(cipher_suite_failed_see_test_case_log)
- end.
-
+ Suites = ssl_test_lib:filter_suites(Ciphers, Version),
+ ct:pal("ssl_test_lib:filter_suites(~p ~p) -> ~p ", [Ciphers, Version, Suites]),
+ Results0 = lists:map(fun(Cipher) ->
+ cipher(Cipher, Version, Config, ClientOpts, ServerOpts) end,
+ ssl_test_lib:filter_suites(Ciphers, Version)),
+ Results = lists:flatten(Results0),
+ true = length(Results) == length(Suites),
+ check_cipher_result(Results).
+
+check_cipher_result([]) ->
+ ok;
+check_cipher_result([ok | Rest]) ->
+ check_cipher_result(Rest);
+check_cipher_result([_ |_] = Error) ->
+ ct:fail(Error).
+
erlang_cipher_suite(Suite) when is_list(Suite)->
- ssl_cipher:suite_definition(ssl_cipher:openssl_suite(Suite));
+ ssl_cipher_format:suite_definition(ssl_cipher_format:openssl_suite(Suite));
erlang_cipher_suite(Suite) ->
Suite.
@@ -5080,7 +5085,7 @@ cipher(CipherSuite, Version, Config, ClientOpts, ServerOpts) ->
case Result of
ok ->
- [];
+ [ok];
Error ->
[{ErlangCipherSuite, Error}]
end.
diff --git a/lib/ssl/test/ssl_certificate_verify_SUITE.erl b/lib/ssl/test/ssl_certificate_verify_SUITE.erl
index c0981a9eaf..f677bf8a6e 100644
--- a/lib/ssl/test/ssl_certificate_verify_SUITE.erl
+++ b/lib/ssl/test/ssl_certificate_verify_SUITE.erl
@@ -88,7 +88,8 @@ tests() ->
critical_extension_verify_client,
critical_extension_verify_server,
critical_extension_verify_none,
- customize_hostname_check
+ customize_hostname_check,
+ incomplete_chain
].
error_handling_tests()->
@@ -1198,6 +1199,39 @@ customize_hostname_check(Config) when is_list(Config) ->
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
+incomplete_chain() ->
+ [{doc,"Test option verify_peer"}].
+incomplete_chain(Config) when is_list(Config) ->
+ DefConf = ssl_test_lib:default_cert_chain_conf(),
+ CertChainConf = ssl_test_lib:gen_conf(rsa, rsa, DefConf, DefConf),
+ #{server_config := ServerConf,
+ client_config := ClientConf} = public_key:pkix_test_data(CertChainConf),
+ [ServerRoot| _] = ServerCas = proplists:get_value(cacerts, ServerConf),
+ ClientCas = proplists:get_value(cacerts, ClientConf),
+
+ Active = proplists:get_value(active, Config),
+ ReceiveFunction = proplists:get_value(receive_function, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib, ReceiveFunction, []}},
+ {options, [{active, Active}, {verify, verify_peer},
+ {cacerts, [ServerRoot]} |
+ proplists:delete(cacerts, ServerConf)]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, ReceiveFunction, []}},
+ {options, [{active, Active},
+ {verify, verify_peer},
+ {cacerts, ServerCas ++ ClientCas} |
+ proplists:delete(cacerts, ClientConf)]}]),
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+
%%--------------------------------------------------------------------
%% Internal functions ------------------------------------------------
%%--------------------------------------------------------------------
diff --git a/lib/ssl/test/ssl_eqc_SUITE.erl b/lib/ssl/test/ssl_eqc_SUITE.erl
new file mode 100644
index 0000000000..bd36d35c02
--- /dev/null
+++ b/lib/ssl/test/ssl_eqc_SUITE.erl
@@ -0,0 +1,58 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2015-2015. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%%
+
+-module(ssl_eqc_SUITE).
+
+-compile(export_all).
+%%--------------------------------------------------------------------
+%% Common Test interface functions -----------------------------------
+%%--------------------------------------------------------------------
+
+all() ->
+ [
+ tls_handshake_encoding
+ ].
+
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ ct_property_test:init_per_suite(Config).
+end_per_suite(Config) ->
+ Config.
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_,Config) ->
+ Config.
+
+init_per_testcase(_, Config0) ->
+ Config0.
+
+end_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Test Cases --------------------------------------------------------
+%%--------------------------------------------------------------------
+
+tls_handshake_encoding(Config) when is_list(Config) ->
+ %% manual test: proper:quickcheck(ssl_eqc_handshake:prop_tls_hs_encode_decode()).
+ true = ct_property_test:quickcheck(ssl_eqc_handshake:prop_tls_hs_encode_decode(),
+ Config).
diff --git a/lib/ssl/test/ssl_handshake_SUITE.erl b/lib/ssl/test/ssl_handshake_SUITE.erl
index 9ae04184e2..b8b9989d30 100644
--- a/lib/ssl/test/ssl_handshake_SUITE.erl
+++ b/lib/ssl/test/ssl_handshake_SUITE.erl
@@ -40,7 +40,8 @@ all() -> [decode_hello_handshake,
decode_single_hello_sni_extension_correctly,
decode_empty_server_sni_correctly,
select_proper_tls_1_2_rsa_default_hashsign,
- ignore_hassign_extension_pre_tls_1_2].
+ ignore_hassign_extension_pre_tls_1_2,
+ unorded_chain].
%%--------------------------------------------------------------------
init_per_suite(Config) ->
@@ -173,6 +174,29 @@ ignore_hassign_extension_pre_tls_1_2(Config) ->
{md5sha, rsa} = ssl_handshake:select_hashsign(HashSigns, Cert, ecdhe_rsa, tls_v1:default_signature_algs({3,2}), {3,2}),
{md5sha, rsa} = ssl_handshake:select_hashsign(HashSigns, Cert, ecdhe_rsa, tls_v1:default_signature_algs({3,0}), {3,0}).
+unorded_chain(Config) when is_list(Config) ->
+ DefConf = ssl_test_lib:default_cert_chain_conf(),
+ CertChainConf = ssl_test_lib:gen_conf(rsa, rsa, DefConf, DefConf),
+ #{server_config := ServerConf,
+ client_config := _ClientConf} = public_key:pkix_test_data(CertChainConf),
+ PeerCert = proplists:get_value(cert, ServerConf),
+ CaCerts = [_, C1, C2] = proplists:get_value(cacerts, ServerConf),
+ {ok, ExtractedCerts} = ssl_pkix_db:extract_trusted_certs({der, CaCerts}),
+ UnordedChain = case public_key:pkix_is_self_signed(C1) of
+ true ->
+ [C1, C2];
+ false ->
+ [C2, C1]
+ end,
+ OrderedChain = [PeerCert | lists:reverse(UnordedChain)],
+ {ok, _, OrderedChain} =
+ ssl_certificate:certificate_chain(PeerCert, ets:new(foo, []), ExtractedCerts, UnordedChain).
+
+
+%%--------------------------------------------------------------------
+%% Internal functions ------------------------------------------------
+%%--------------------------------------------------------------------
+
is_supported(Hash) ->
Algos = crypto:supports(),
Hashs = proplists:get_value(hashs, Algos),
diff --git a/lib/ssl/test/ssl_pem_cache_SUITE.erl b/lib/ssl/test/ssl_pem_cache_SUITE.erl
index 3b79780974..25d2cb300d 100644
--- a/lib/ssl/test/ssl_pem_cache_SUITE.erl
+++ b/lib/ssl/test/ssl_pem_cache_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/ssl/test/ssl_session_cache_SUITE.erl b/lib/ssl/test/ssl_session_cache_SUITE.erl
index 9862b3ce64..a0fab58b9d 100644
--- a/lib/ssl/test/ssl_session_cache_SUITE.erl
+++ b/lib/ssl/test/ssl_session_cache_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -487,8 +487,8 @@ test_copts(_, 0, ClientOpts) ->
ClientOpts;
test_copts(max_table_size, N, ClientOpts) ->
Version = tls_record:highest_protocol_version([]),
- CipherSuites = %%lists:map(fun(X) -> ssl_cipher:suite_definition(X) end, ssl_cipher:filter_suites(ssl_cipher:suites(Version))),
-[ Y|| Y = {Alg,_, _, _} <- lists:map(fun(X) -> ssl_cipher:suite_definition(X) end, ssl_cipher:filter_suites(ssl_cipher:suites(Version))), Alg =/= ecdhe_ecdsa, Alg =/= ecdh_ecdsa, Alg =/= ecdh_rsa, Alg =/= ecdhe_rsa, Alg =/= dhe_dss, Alg =/= dss],
+ CipherSuites = %%lists:map(fun(X) -> ssl_cipher_format:suite_definition(X) end, ssl_cipher:filter_suites(ssl_cipher:suites(Version))),
+[ Y|| Y = {Alg,_, _, _} <- lists:map(fun(X) -> ssl_cipher_format:suite_definition(X) end, ssl_cipher:filter_suites(ssl_cipher:suites(Version))), Alg =/= ecdhe_ecdsa, Alg =/= ecdh_ecdsa, Alg =/= ecdh_rsa, Alg =/= ecdhe_rsa, Alg =/= dhe_dss, Alg =/= dss],
case length(CipherSuites) of
M when M >= N ->
Cipher = lists:nth(N, CipherSuites),
diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl
index 7202e3662c..f3235f5614 100644
--- a/lib/ssl/test/ssl_test_lib.erl
+++ b/lib/ssl/test/ssl_test_lib.erl
@@ -1221,13 +1221,13 @@ common_ciphers(crypto) ->
common_ciphers(openssl) ->
OpenSslSuites =
string:tokens(string:strip(os:cmd("openssl ciphers"), right, $\n), ":"),
- [ssl_cipher:suite_definition(S)
+ [ssl_cipher_format:suite_definition(S)
|| S <- ssl_cipher:suites(tls_record:highest_protocol_version([])),
- lists:member(ssl_cipher:openssl_suite_name(S), OpenSslSuites)
+ lists:member(ssl_cipher_format:openssl_suite_name(S), OpenSslSuites)
].
available_suites(Version) ->
- [ssl_cipher:suite_definition(Suite) ||
+ [ssl_cipher_format:suite_definition(Suite) ||
Suite <- ssl_cipher:filter_suites(ssl_cipher:suites(Version))].
@@ -1300,7 +1300,7 @@ string_regex_filter(_Str, _Search) ->
false.
ecdh_dh_anonymous_suites(Version) ->
- ssl:filter_cipher_suites([ssl_cipher:suite_definition(S) || S <- ssl_cipher:anonymous_suites(Version)],
+ ssl:filter_cipher_suites([ssl_cipher_format:suite_definition(S) || S <- ssl_cipher:anonymous_suites(Version)],
[{key_exchange,
fun(dh_anon) ->
true;
@@ -1310,7 +1310,7 @@ ecdh_dh_anonymous_suites(Version) ->
false
end}]).
psk_suites({3,_} = Version) ->
- ssl:filter_cipher_suites([ssl_cipher:suite_definition(S) || S <- ssl_cipher:psk_suites(Version)], []);
+ ssl:filter_cipher_suites([ssl_cipher_format:suite_definition(S) || S <- ssl_cipher:psk_suites(Version)], []);
psk_suites(Version) ->
ssl:filter_cipher_suites(psk_suites(dtls_v1:corresponding_tls_version(Version)),
[{cipher,
@@ -1321,11 +1321,13 @@ psk_suites(Version) ->
end}]).
psk_anon_suites({3,_} = Version) ->
- ssl:filter_cipher_suites([ssl_cipher:suite_definition(S) || S <- ssl_cipher:psk_suites_anon(Version)],
+ ssl:filter_cipher_suites([ssl_cipher_format:suite_definition(S) || S <- ssl_cipher:psk_suites_anon(Version)],
[{key_exchange,
fun(psk) ->
true;
- (psk_dhe) ->
+ (dhe_psk) ->
+ true;
+ (ecdhe_psk) ->
true;
(_) ->
false
@@ -1342,7 +1344,7 @@ psk_anon_suites(Version) ->
srp_suites() ->
- ssl:filter_cipher_suites([ssl_cipher:suite_definition(S) || S <- ssl_cipher:srp_suites()],
+ ssl:filter_cipher_suites([ssl_cipher_format:suite_definition(S) || S <- ssl_cipher:srp_suites()],
[{key_exchange,
fun(srp_rsa) ->
true;
@@ -1350,10 +1352,10 @@ srp_suites() ->
false
end}]).
srp_anon_suites() ->
- ssl:filter_cipher_suites([ssl_cipher:suite_definition(S) || S <- ssl_cipher:srp_suites_anon()],
+ ssl:filter_cipher_suites([ssl_cipher_format:suite_definition(S) || S <- ssl_cipher:srp_suites_anon()],
[]).
srp_dss_suites() ->
- ssl:filter_cipher_suites([ssl_cipher:suite_definition(S) || S <- ssl_cipher:srp_suites()],
+ ssl:filter_cipher_suites([ssl_cipher_format:suite_definition(S) || S <- ssl_cipher:srp_suites()],
[{key_exchange,
fun(srp_dss) ->
true;
@@ -1361,14 +1363,14 @@ srp_dss_suites() ->
false
end}]).
chacha_suites(Version) ->
- [ssl_cipher:suite_definition(S) || S <- ssl_cipher:filter_suites(ssl_cipher:chacha_suites(Version))].
+ [ssl_cipher_format:suite_definition(S) || S <- ssl_cipher:filter_suites(ssl_cipher:chacha_suites(Version))].
rc4_suites(Version) ->
- ssl:filter_cipher_suites([ssl_cipher:suite_definition(S) || S <-ssl_cipher:rc4_suites(Version)], []).
+ ssl:filter_cipher_suites([ssl_cipher_format:suite_definition(S) || S <-ssl_cipher:rc4_suites(Version)], []).
des_suites(Version) ->
- ssl:filter_cipher_suites([ssl_cipher:suite_definition(S) || S <-ssl_cipher:des_suites(Version)], []).
+ ssl:filter_cipher_suites([ssl_cipher_format:suite_definition(S) || S <-ssl_cipher:des_suites(Version)], []).
tuple_to_map({Kex, Cipher, Mac}) ->
#{key_exchange => Kex,
@@ -1642,6 +1644,8 @@ openssl_dsa_support() ->
true;
"LibreSSL" ++ _ ->
false;
+ "OpenSSL 1.1" ++ Rest ->
+ false;
"OpenSSL 1.0.1" ++ Rest ->
hd(Rest) >= s;
_ ->
@@ -1762,10 +1766,10 @@ version_flag('dtlsv1') ->
"-dtls1".
filter_suites([Cipher | _] = Ciphers, AtomVersion) when is_list(Cipher)->
- filter_suites([ssl_cipher:openssl_suite(S) || S <- Ciphers],
+ filter_suites([ssl_cipher_format:openssl_suite(S) || S <- Ciphers],
AtomVersion);
filter_suites([Cipher | _] = Ciphers, AtomVersion) when is_binary(Cipher)->
- filter_suites([ssl_cipher:suite_definition(S) || S <- Ciphers],
+ filter_suites([ssl_cipher_format:suite_definition(S) || S <- Ciphers],
AtomVersion);
filter_suites(Ciphers0, AtomVersion) ->
Version = tls_version(AtomVersion),
@@ -1777,7 +1781,7 @@ filter_suites(Ciphers0, AtomVersion) ->
++ ssl_cipher:srp_suites_anon()
++ ssl_cipher:rc4_suites(Version),
Supported1 = ssl_cipher:filter_suites(Supported0),
- Supported2 = [ssl_cipher:suite_definition(S) || S <- Supported1],
+ Supported2 = [ssl_cipher_format:suite_definition(S) || S <- Supported1],
[Cipher || Cipher <- Ciphers0, lists:member(Cipher, Supported2)].
-define(OPENSSL_QUIT, "Q\n").
@@ -1852,13 +1856,11 @@ do_supports_ssl_tls_version(Port, Acc) ->
case Acc ++ Data of
"unknown option" ++ _ ->
false;
- Error when length(Error) >= 11 ->
- case lists:member("error", string:tokens(Data, ":")) of
- true ->
- false;
- false ->
- do_supports_ssl_tls_version(Port, Error)
- end;
+ "s_client: Option unknown" ++ _->
+ false;
+ Info when length(Info) >= 24 ->
+ ct:pal("~p", [Info]),
+ true;
_ ->
do_supports_ssl_tls_version(Port, Acc ++ Data)
end
diff --git a/lib/ssl/test/ssl_to_openssl_SUITE.erl b/lib/ssl/test/ssl_to_openssl_SUITE.erl
index 7fc5e13400..5a38f5f9c1 100644
--- a/lib/ssl/test/ssl_to_openssl_SUITE.erl
+++ b/lib/ssl/test/ssl_to_openssl_SUITE.erl
@@ -598,73 +598,84 @@ erlang_client_openssl_server_anon(Config) when is_list(Config) ->
VersionTuple = ssl_test_lib:protocol_version(Config, tuple),
Ciphers = ssl_test_lib:ecdh_dh_anonymous_suites(VersionTuple),
- {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
-
- Data = "From openssl to erlang",
-
- Port = ssl_test_lib:inet_port(node()),
- CertFile = proplists:get_value(certfile, ServerOpts),
- KeyFile = proplists:get_value(keyfile, ServerOpts),
- Version = ssl_test_lib:protocol_version(Config),
- Exe = "openssl",
- Args = ["s_server", "-accept", integer_to_list(Port),
- ssl_test_lib:version_flag(Version),
- "-cert", CertFile, "-key", KeyFile,
- "-cipher", "aNULL", "-msg"],
-
- OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
-
- ssl_test_lib:wait_for_openssl_server(Port, proplists:get_value(protocol, Config)),
-
- Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
- {host, Hostname},
- {from, self()},
+ case openssl_has_common_ciphers(Ciphers) of
+ false ->
+ {skip, not_supported_by_openssl};
+ true ->
+
+ {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config),
+
+ Data = "From openssl to erlang",
+
+ Port = ssl_test_lib:inet_port(node()),
+ CertFile = proplists:get_value(certfile, ServerOpts),
+ KeyFile = proplists:get_value(keyfile, ServerOpts),
+ Version = ssl_test_lib:protocol_version(Config),
+ Exe = "openssl",
+ Args = ["s_server", "-accept", integer_to_list(Port),
+ ssl_test_lib:version_flag(Version),
+ "-cert", CertFile, "-key", KeyFile,
+ "-cipher", "aNULL", "-msg"],
+
+ OpensslPort = ssl_test_lib:portable_open_port(Exe, Args),
+
+ ssl_test_lib:wait_for_openssl_server(Port, proplists:get_value(protocol, Config)),
+
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
{mfa, {?MODULE,
erlang_ssl_receive, [Data]}},
- {options, [{ciphers, Ciphers} | ClientOpts]}]),
-
- true = port_command(OpensslPort, Data),
-
- ssl_test_lib:check_result(Client, ok),
-
- %% Clean close down! Server needs to be closed first !!
- ssl_test_lib:close_port(OpensslPort),
- ssl_test_lib:close(Client),
- process_flag(trap_exit, false),
- ok.
+ {options, [{ciphers, Ciphers} | ClientOpts]}]),
+
+ true = port_command(OpensslPort, Data),
+
+ ssl_test_lib:check_result(Client, ok),
+
+ %% Clean close down! Server needs to be closed first !!
+ ssl_test_lib:close_port(OpensslPort),
+ ssl_test_lib:close(Client),
+ process_flag(trap_exit, false)
+ end.
%%--------------------------------------------------------------------
erlang_server_openssl_client_anon() ->
[{doc,"Test erlang server with openssl client, anonymous"}].
erlang_server_openssl_client_anon(Config) when is_list(Config) ->
+
process_flag(trap_exit, true),
ServerOpts = ssl_test_lib:ssl_options(server_anon_opts, Config),
VersionTuple = ssl_test_lib:protocol_version(Config, tuple),
Ciphers = ssl_test_lib:ecdh_dh_anonymous_suites(VersionTuple),
- {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- Data = "From openssl to erlang",
-
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
+ case openssl_has_common_ciphers(Ciphers) of
+ false ->
+ {skip, not_supported_by_openssl};
+ true ->
+ {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Data = "From openssl to erlang",
+
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
{mfa, {?MODULE, erlang_ssl_receive, [Data]}},
- {options, [{ciphers, Ciphers} | ServerOpts]}]),
- Port = ssl_test_lib:inet_port(Server),
- Version = ssl_test_lib:protocol_version(Config),
- Exe = "openssl",
- Args = ["s_client", "-connect", hostname_format(Hostname) ++ ":" ++ integer_to_list(Port),
- ssl_test_lib:version_flag(Version),
- "-cipher", "aNULL", "-msg"],
-
- OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
- true = port_command(OpenSslPort, Data),
-
- ssl_test_lib:check_result(Server, ok),
-
- %% Clean close down! Server needs to be closed first !!
- ssl_test_lib:close(Server),
- ssl_test_lib:close_port(OpenSslPort),
- process_flag(trap_exit, false).
+ {options, [{ciphers, Ciphers} | ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Version = ssl_test_lib:protocol_version(Config),
+ Exe = "openssl",
+ Args = ["s_client", "-connect", hostname_format(Hostname) ++ ":" ++ integer_to_list(Port),
+ ssl_test_lib:version_flag(Version),
+ "-cipher", "aNULL", "-msg"],
+
+ OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
+ true = port_command(OpenSslPort, Data),
+
+ ssl_test_lib:check_result(Server, ok),
+
+ %% Clean close down! Server needs to be closed first !!
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close_port(OpenSslPort),
+ process_flag(trap_exit, false)
+ end.
%%--------------------------------------------------------------------
erlang_server_openssl_client_anon_with_cert() ->
@@ -675,30 +686,35 @@ erlang_server_openssl_client_anon_with_cert(Config) when is_list(Config) ->
VersionTuple = ssl_test_lib:protocol_version(Config, tuple),
Ciphers = ssl_test_lib:ecdh_dh_anonymous_suites(VersionTuple),
- {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
-
- Data = "From openssl to erlang",
-
- Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
- {from, self()},
+ case openssl_has_common_ciphers(Ciphers) of
+ false ->
+ {skip, not_supported_by_openssl};
+ true ->
+ {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+
+ Data = "From openssl to erlang",
+
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
{mfa, {?MODULE, erlang_ssl_receive, [Data]}},
- {options, [{ciphers, Ciphers} | ServerOpts]}]),
- Port = ssl_test_lib:inet_port(Server),
- Version = ssl_test_lib:protocol_version(Config),
- Exe = "openssl",
- Args = ["s_client", "-connect", hostname_format(Hostname) ++ ":" ++ integer_to_list(Port),
- ssl_test_lib:version_flag(Version),
- "-cipher", "aNULL", "-msg"],
-
- OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
- true = port_command(OpenSslPort, Data),
-
- ssl_test_lib:check_result(Server, ok),
-
- %% Clean close down! Server needs to be closed first !!
- ssl_test_lib:close(Server),
- ssl_test_lib:close_port(OpenSslPort),
- process_flag(trap_exit, false).
+ {options, [{ciphers, Ciphers} | ServerOpts]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Version = ssl_test_lib:protocol_version(Config),
+ Exe = "openssl",
+ Args = ["s_client", "-connect", hostname_format(Hostname) ++ ":" ++ integer_to_list(Port),
+ ssl_test_lib:version_flag(Version),
+ "-cipher", "aNULL", "-msg"],
+
+ OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args),
+ true = port_command(OpenSslPort, Data),
+
+ ssl_test_lib:check_result(Server, ok),
+
+ %% Clean close down! Server needs to be closed first !!
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close_port(OpenSslPort),
+ process_flag(trap_exit, false)
+ end.
%%--------------------------------------------------------------------
erlang_server_openssl_client_reuse_session() ->
@@ -2012,3 +2028,18 @@ no_low_flag("-no_ssl2" = Flag) ->
end;
no_low_flag(Flag) ->
Flag.
+
+
+openssl_has_common_ciphers(Ciphers) ->
+ OCiphers = ssl_test_lib:common_ciphers(openssl),
+ has_common_ciphers(Ciphers, OCiphers).
+
+has_common_ciphers([], OCiphers) ->
+ false;
+has_common_ciphers([Cipher | Rest], OCiphers) ->
+ case lists:member(Cipher, OCiphers) of
+ true ->
+ true;
+ _ ->
+ has_common_ciphers(Rest, OCiphers)
+ end.
diff --git a/lib/stdlib/doc/src/ets.xml b/lib/stdlib/doc/src/ets.xml
index f8c54fb79a..57a19ef2ca 100644
--- a/lib/stdlib/doc/src/ets.xml
+++ b/lib/stdlib/doc/src/ets.xml
@@ -1023,7 +1023,7 @@ ets:select(Table, MatchSpec),</code>
be used in subsequent operations. The table identifier can be
sent to other processes so that a table can be shared between
different processes within a node.</p>
- <p>Parameter <c><anno>Options</anno></c> is a list of atoms that
+ <p>Parameter <c><anno>Options</anno></c> is a list of options that
specifies table type, access rights, key position, and whether the
table is named. Default values are used for omitted options.
This means that not specifying any options (<c>[]</c>) is the same
@@ -1135,11 +1135,22 @@ ets:select(Table, MatchSpec),</code>
Functions that makes such promises over many objects (like
<seealso marker="#insert/2"><c>insert/2</c></seealso>)
gain less (or nothing) from this option.</p>
- <p>Table type <c>ordered_set</c> is not affected by this option.
- Also, the memory consumption inflicted by
- both <c>write_concurrency</c> and <c>read_concurrency</c> is a
- constant overhead per table. This overhead can be especially
- large when both options are combined.</p>
+ <p>The memory consumption inflicted by both <c>write_concurrency</c>
+ and <c>read_concurrency</c> is a constant overhead per table for
+ <c>set</c>, <c>bag</c> and <c>duplicate_bag</c>. For
+ <c>ordered_set</c> the memory overhead depends on the number
+ of inserted objects and the amount of actual detected
+ concurrency. The memory overhead can be especially large when both
+ options are combined.</p>
+ <note>
+ <p>Prior to stdlib-3.7 (OTP-22.0) <c>write_concurrency</c> had no
+ effect on <c>ordered_set</c>.</p>
+ <p>The current implementation of <c>write_concurrency</c> for
+ <c>ordered_set</c> does only improve explicit single key
+ operations. Mixing single key operations with operations
+ potentially accessing multiple keys may even yield worse
+ performance with <c>write_concurrency</c> on <c>ordered_set</c>.</p>
+ </note>
<marker id="new_2_read_concurrency"></marker>
</item>
<tag><c>{read_concurrency,boolean()}</c></tag>
diff --git a/lib/stdlib/doc/src/filename.xml b/lib/stdlib/doc/src/filename.xml
index ce19f70df0..36254c2d00 100644
--- a/lib/stdlib/doc/src/filename.xml
+++ b/lib/stdlib/doc/src/filename.xml
@@ -84,11 +84,6 @@
reject such filenames.
</p></warning>
</description>
- <datatypes>
- <datatype>
- <name name="basedir_type"/>
- </datatype>
- </datatypes>
<funcs>
<func>
@@ -149,18 +144,37 @@
</func>
<func>
- <name name="basedir" arity="2"/>
- <fsummary>Equivalent to <c>basedir(<anno>Type</anno>,<anno>Application</anno>,#{})</c>.</fsummary>
+ <name name="basedir" arity="2" clause_i="1"/>
+ <name name="basedir" arity="2" clause_i="2"/>
+ <fsummary>Equivalent to <c>basedir(<anno>PathType</anno>,
+ <anno>Application</anno>,#{})</c> or
+ <c>basedir(<anno>PathsType</anno>, <anno>Application</anno>,#{})</c>.
+ </fsummary>
+ <type variable="PathType" name_i="1"/>
+ <type name="basedir_path_type"/>
+ <type variable="PathsType" name_i="2"/>
+ <type name="basedir_paths_type"/>
+ <type variable="Application"/>
<desc>
<p>
- Equivalent to <seealso marker="#basedir-3">
- basedir(<anno>Type</anno>, <anno>Application</anno>, #{})</seealso>.
+ Equivalent to <seealso marker="#basedir_3_1">
+ basedir(<anno>PathType</anno>, <anno>Application</anno>, #{})</seealso>
+ or <seealso marker="#basedir_3_2">
+basedir(<anno>PathsType</anno>, <anno>Application</anno>, #{})</seealso>.
</p>
</desc>
</func>
<func>
- <name name="basedir" arity="3"/>
+ <name name="basedir" arity="3" clause_i="1" anchor="basedir_3_1"/>
+ <name name="basedir" arity="3" clause_i="2" anchor="basedir_3_2"/>
<fsummary></fsummary>
+ <type variable="PathType" name_i="1"/>
+ <type name="basedir_path_type"/>
+ <type variable="PathsType" name_i="2"/>
+ <type name="basedir_paths_type"/>
+ <type variable="Application"/>
+ <type variable="Opts"/>
+ <type name="basedir_opts"/>
<desc><marker id="basedir-3"/>
<p>
Returns a suitable path, or paths, for a given type. If
diff --git a/lib/stdlib/doc/src/gen_statem.xml b/lib/stdlib/doc/src/gen_statem.xml
index eb0f7d24f0..dfecd235c9 100644
--- a/lib/stdlib/doc/src/gen_statem.xml
+++ b/lib/stdlib/doc/src/gen_statem.xml
@@ -167,7 +167,7 @@ erlang:'!' -----> Module:StateName/3
</p>
<marker id="state callback"/>
<p>
- The "<em>state callback</em>" for a specific
+ The <em>state callback</em> for a specific
<seealso marker="#type-state">state</seealso>
in a <c>gen_statem</c> is the callback function that is called
for all events in this state. It is selected depending on which
@@ -179,7 +179,7 @@ erlang:'!' -----> Module:StateName/3
When the
<seealso marker="#type-callback_mode"><em>callback mode</em></seealso>
is <c>state_functions</c>, the state must be an atom and
- is used as the state callback name; see
+ is used as the <em>state callback</em> name; see
<seealso marker="#Module:StateName/3"><c>Module:StateName/3</c></seealso>.
This co-locates all code for a specific state
in one function as the <c>gen_statem</c> engine
@@ -192,7 +192,7 @@ erlang:'!' -----> Module:StateName/3
When the
<seealso marker="#type-callback_mode"><em>callback mode</em></seealso>
is <c>handle_event_function</c>, the state can be any term
- and the state callback name is
+ and the <em>state callback</em> name is
<seealso marker="#Module:handle_event/4"><c>Module:handle_event/4</c></seealso>.
This makes it easy to branch depending on state or event as you desire.
Be careful about which events you handle in which
@@ -200,12 +200,36 @@ erlang:'!' -----> Module:StateName/3
forever creating an infinite busy loop.
</p>
<p>
- The <c>gen_statem</c> enqueues incoming events in order of arrival
- and presents these to the
- <seealso marker="#state callback">state callback</seealso>
- in that order. The state callback can postpone an event
- so it is not retried in the current state.
- After a state change the queue restarts with the postponed events.
+ When <c>gen_statem</c> receives a process message it is
+ converted into an event and the
+ <seealso marker="#state callback"><em>state callback</em></seealso>
+ is called with the event as two arguments: type and content.
+ When the
+ <seealso marker="#state callback"><em>state callback</em></seealso>
+ has processed the event it returns to <c>gen_statem</c>
+ which does a <em>state transition</em>.
+ If this <em>state transition</em> is to a different state,
+ that is: <c>NextState =/= State</c>, it is a <em>state change</em>.
+ </p>
+ <p>
+ The
+ <seealso marker="#state callback"><em>state callback</em></seealso>
+ may return
+ <seealso marker="#type-action"><em>transition actions</em></seealso>
+ for <c>gen_statem</c>
+ to execute during the <em>state transition</em>,
+ for example to reply to a
+ <seealso marker="#call/2"><c>gen_statem:call/2,3</c></seealso>.
+ </p>
+ <p>
+ One of the possible <em>transition actions</em>
+ is to postpone the current event.
+ Then it is not retried in the current state.
+ The <c>gen_statem</c> engine keeps a queue of events
+ divided into the postponed events
+ and the events still to process.
+ After a <em>state change</em> the queue restarts
+ with the postponed events.
</p>
<p>
The <c>gen_statem</c> event queue model is sufficient
@@ -215,13 +239,17 @@ erlang:'!' -----> Module:StateName/3
to entering a new receive statement.
</p>
<p>
- The <seealso marker="#state callback">state callback</seealso>
+ The
+ <seealso marker="#state callback"><em>state callback</em></seealso>
can insert events using the
- <seealso marker="#type-action"><c>action()</c></seealso>
+ <seealso marker="#type-action"><em>transition actions</em></seealso>
<c>next_event</c>
- and such an event is inserted as the next to present
- to the state callback. That is, as if it is
- the oldest incoming event. A dedicated
+ and such an event is inserted in the event queue
+ as the next to call the
+ <seealso marker="#state callback"><em>state callback</em></seealso>
+ with.
+ That is, as if it is the oldest incoming event.
+ A dedicated
<seealso marker="#type-event_type"><c>event_type()</c></seealso>
<c>internal</c> can be used for such events making them impossible
to mistake for external events.
@@ -236,24 +264,26 @@ erlang:'!' -----> Module:StateName/3
<p>
The <c>gen_statem</c> engine can automatically
make a specialized call to the
- <seealso marker="#state callback">state callback</seealso>
+ <seealso marker="#state callback"><em>state callback</em></seealso>
whenever a new state is entered; see
<seealso marker="#type-state_enter"><c>state_enter()</c></seealso>.
This is for writing code common to all state entries.
- Another way to do it is to insert an event at the state transition,
- and/or to use a dedicated state transition function,
+ Another way to do it is to explicitly insert an event
+ at the <em>state transition</em>,
+ and/or to use a dedicated <em>state transition</em> function,
but that is something you will have to remember
- at every state transition to the state(s) that need it.
+ at every <em>state transition</em> to the state(s) that need it.
</p>
<note>
<p>If you in <c>gen_statem</c>, for example, postpone
- an event in one state and then call another state callback
- of yours, you have not changed states and hence the postponed event
- is not retried, which is logical but can be confusing.
+ an event in one state and then call another <em>state callback</em>
+ of yours, you have not done a <em>state change</em>
+ and hence the postponed event is not retried,
+ which is logical but can be confusing.
</p>
</note>
<p>
- For the details of a state transition, see type
+ For the details of a <em>state transition</em>, see type
<seealso marker="#type-transition_option"><c>transition_option()</c></seealso>.
</p>
<p>
@@ -276,7 +306,8 @@ erlang:'!' -----> Module:StateName/3
The <c>gen_statem</c> process can go into hibernation; see
<seealso marker="proc_lib#hibernate/3"><c>proc_lib:hibernate/3</c></seealso>.
It is done when a
- <seealso marker="#state callback">state callback</seealso> or
+ <seealso marker="#state callback"><em>state callback</em></seealso>
+ or
<seealso marker="#Module:init/1"><c>Module:init/1</c></seealso>
specifies <c>hibernate</c> in the returned
<seealso marker="#type-action"><c>Actions</c></seealso>
@@ -551,7 +582,7 @@ handle_event(_, _, State, Data) ->
<seealso marker="#type-callback_mode"><em>callback mode</em></seealso>
is <c>handle_event_function</c>,
the state can be any term.
- After a state change (<c>NextState =/= State</c>),
+ After a <em>state change</em> (<c>NextState =/= State</c>),
all postponed events are retried.
</p>
</desc>
@@ -564,7 +595,7 @@ handle_event(_, _, State, Data) ->
<seealso marker="#type-callback_mode"><em>callback mode</em></seealso>
is <c>state_functions</c>,
the state must be of this type.
- After a state change (<c>NextState =/= State</c>),
+ After a <em>state change</em> (<c>NextState =/= State</c>),
all postponed events are retried.
</p>
</desc>
@@ -595,7 +626,7 @@ handle_event(_, _, State, Data) ->
</p>
<p>
<c>internal</c> events can only be generated by the
- state machine itself through the state transition action
+ state machine itself through the <em>transition action</em>
<seealso marker="#type-action"><c>next_event</c></seealso>.
</p>
</desc>
@@ -633,9 +664,9 @@ handle_event(_, _, State, Data) ->
This is the return type from
<seealso marker="#Module:callback_mode/0"><c>Module:callback_mode/0</c></seealso>
and selects
- <seealso marker="#type-callback_mode">callback mode</seealso>
+ <seealso marker="#type-callback_mode"><em>callback mode</em></seealso>
and whether to do
- <seealso marker="#type-state_enter">state enter calls</seealso>,
+ <seealso marker="#type-state_enter"><em>state enter calls</em></seealso>,
or not.
</p>
</desc>
@@ -684,13 +715,15 @@ handle_event(_, _, State, Data) ->
If
<seealso marker="#Module:callback_mode/0"><c>Module:callback_mode/0</c></seealso>
returns a list containing <c>state_enter</c>,
- the <c>gen_statem</c> engine will, at every state change,
+ the <c>gen_statem</c> engine will, at every <em>state change</em>,
call the
<seealso marker="#state callback">state callback</seealso>
with arguments <c>(enter, OldState, Data)</c>.
This may look like an event but is really a call
- performed after the previous state callback returned
- and before any event is delivered to the new state callback.
+ performed after the previous
+ <seealso marker="#state callback"><em>state callback</em></seealso>
+ returned and before any event is delivered to the new
+ <seealso marker="#state callback"><em>state callback</em></seealso>.
See
<seealso marker="#Module:StateName/3"><c>Module:StateName/3</c></seealso>
and
@@ -703,27 +736,27 @@ handle_event(_, _, State, Data) ->
<seealso marker="#type-state_callback_result">
<c>repeat_state_and_data</c>
</seealso>
- tuple from the state callback.
+ tuple from the <em>state callback</em>.
</p>
<p>
If
<seealso marker="#Module:callback_mode/0"><c>Module:callback_mode/0</c></seealso>
- does not return such a list, no state enter calls are done.
+ does not return such a list, no <em>state enter calls</em> are done.
</p>
<p>
If
<seealso marker="#Module:code_change/4"><c>Module:code_change/4</c></seealso>
should transform the state,
- it is regarded as a state rename and not a state change,
- which will not cause a state enter call.
+ it is regarded as a state rename and not a <em>state change</em>,
+ which will not cause a <em>state enter call</em>.
</p>
<p>
- Note that a state enter call <em>will</em> be done
+ Note that a <em>state enter call</em> <em>will</em> be done
right before entering the initial state even though this
- formally is not a state change.
- In this case <c>OldState</c> will be the same as <c>State</c>,
- which cannot happen for a subsequent state change,
- but will happen when repeating the state enter call.
+ actually is not a <em>state change</em>.
+ In this case <c>OldState =:= State</c>,
+ which can not happen for a subsequent state change,
+ but will happen when repeating the <em>state enter call</em>.
</p>
</desc>
</datatype>
@@ -733,8 +766,11 @@ handle_event(_, _, State, Data) ->
<p>
Transition options can be set by
<seealso marker="#type-action">actions</seealso>
- and modify the state transition.
- Here are the sequence of steps for a state transition:
+ and modify the <em>state transition</em>.
+ The <em>state transition</em> takes place when the
+ <seealso marker="#state callback"><em>state callback</em></seealso>
+ has processed an event and returns.
+ Here are the sequence of steps for a <em>state transition</em>:
</p>
<list type="ordered">
<item>
@@ -765,7 +801,7 @@ handle_event(_, _, State, Data) ->
returned by the state callback that caused the state entry.
</p>
<p>
- Should this state enter call return any of
+ Should this <em>state enter call</em> return any of
the mentioned <c>repeat_*</c> callback results
it is repeated again, with the updated <c>Data</c>.
</p>
@@ -787,7 +823,8 @@ handle_event(_, _, State, Data) ->
</item>
<item>
<p>
- If the state changes, the queue of incoming events
+ If this is a <em>state change</em>,
+ the queue of incoming events
is reset to start with the oldest postponed.
</p>
</item>
@@ -821,7 +858,7 @@ handle_event(_, _, State, Data) ->
if the event queue is empty.
</p>
<p>
- A state change cancels a
+ A <em>state change</em> cancels a
<seealso marker="#type-state_timeout"><c>state_timeout()</c></seealso>
and any new transition option of this type
belongs to the new state.
@@ -830,7 +867,7 @@ handle_event(_, _, State, Data) ->
<item>
<p>
If there are enqueued events the
- <seealso marker="#state callback">state callback</seealso>
+ <seealso marker="#state callback"><em>state callback</em></seealso>
for the possibly new state
is called with the oldest enqueued event,
and we start again from the top of this list.
@@ -848,7 +885,7 @@ handle_event(_, _, State, Data) ->
the next incoming message awakens the <c>gen_statem</c>,
but if it is a system event it goes right back into hibernation.
When a new message arrives the
- <seealso marker="#state callback">state callback</seealso>
+ <seealso marker="#state callback"><em>state callback</em></seealso>
is called with the corresponding event,
and we start again from the top of this sequence.
</p>
@@ -861,7 +898,7 @@ handle_event(_, _, State, Data) ->
<desc>
<p>
If <c>true</c>, postpones the current event and retries
- it when the state changes
+ it after a <em>state change</em>
(<c>NextState =/= State</c>).
</p>
</desc>
@@ -1021,9 +1058,9 @@ handle_event(_, _, State, Data) ->
<name name="action"/>
<desc>
<p>
- These state transition actions can be invoked by
+ These <em>transition actions</em> can be invoked by
returning them from the
- <seealso marker="#state callback">state callback</seealso>
+ <seealso marker="#state callback"><em>state callback</em></seealso>
when it is called with an
<seealso marker="#type-event_type">event</seealso>,
from
@@ -1054,7 +1091,7 @@ handle_event(_, _, State, Data) ->
<c>transition_option()</c>
</seealso>
<seealso marker="#type-postpone"><c>postpone()</c></seealso>
- for this state transition.
+ for this <em>state transition</em>.
This action is ignored when returned from
<seealso marker="#Module:init/1"><c>Module:init/1</c></seealso>
or given to
@@ -1093,9 +1130,9 @@ handle_event(_, _, State, Data) ->
<name name="enter_action"/>
<desc>
<p>
- These state transition actions can be invoked by
+ These <em>transition actions</em> can be invoked by
returning them from the
- <seealso marker="#state callback">state callback</seealso>, from
+ <seealso marker="#state callback"><em>state callback</em></seealso>, from
<seealso marker="#Module:init/1"><c>Module:init/1</c></seealso>
or by giving them to
<seealso marker="#enter_loop/5"><c>enter_loop/5,6</c></seealso>.
@@ -1119,7 +1156,7 @@ handle_event(_, _, State, Data) ->
Sets the
<seealso marker="#type-transition_option"><c>transition_option()</c></seealso>
<seealso marker="#type-hibernate"><c>hibernate()</c></seealso>
- for this state transition.
+ for this <em>state transition</em>.
</p>
</item>
</taglist>
@@ -1129,9 +1166,9 @@ handle_event(_, _, State, Data) ->
<name name="timeout_action"/>
<desc>
<p>
- These state transition actions can be invoked by
+ These <em>transition actions</em> can be invoked by
returning them from the
- <seealso marker="#state callback">state callback</seealso>, from
+ <seealso marker="#state callback"><em>state callback</em></seealso>, from
<seealso marker="#Module:init/1"><c>Module:init/1</c></seealso>
or by giving them to
<seealso marker="#enter_loop/5"><c>enter_loop/5,6</c></seealso>.
@@ -1147,7 +1184,7 @@ handle_event(_, _, State, Data) ->
Short for <c>{timeout,Time,Time}</c>, that is,
the time-out message is the time-out time.
This form exists to make the
- <seealso marker="#state callback">state callback</seealso>
+ <seealso marker="#state callback"><em>state callback</em></seealso>
return value <c>{next_state,NextState,NewData,Time}</c>
allowed like for <c>gen_fsm</c>.
</p>
@@ -1193,9 +1230,9 @@ handle_event(_, _, State, Data) ->
<name name="reply_action"/>
<desc>
<p>
- This state transition action can be invoked by
+ This <em>transition action</em> can be invoked by
returning it from the
- <seealso marker="#state callback">state callback</seealso>, from
+ <seealso marker="#state callback"><em>state callback</em></seealso>, from
<seealso marker="#Module:init/1"><c>Module:init/1</c></seealso>
or by giving it to
<seealso marker="#enter_loop/5"><c>enter_loop/5,6</c></seealso>.
@@ -1210,7 +1247,7 @@ handle_event(_, _, State, Data) ->
<c><anno>From</anno></c> must be the term from argument
<seealso marker="#type-event_type"><c>{call,<anno>From</anno>}</c></seealso>
in a call to a
- <seealso marker="#state callback">state callback</seealso>.
+ <seealso marker="#state callback"><em>state callback</em></seealso>.
</p>
<p>
Note that using this action from
@@ -1219,7 +1256,7 @@ handle_event(_, _, State, Data) ->
<seealso marker="#enter_loop/5"><c>enter_loop/5,6</c></seealso>
would be weird on the border of witchcraft
since there has been no earlier call to a
- <seealso marker="#state callback">state callback</seealso>
+ <seealso marker="#state callback"><em>state callback</em></seealso>
in this server.
</p>
</desc>
@@ -1239,7 +1276,7 @@ handle_event(_, _, State, Data) ->
The <seealso marker="#type-action"><c>Actions</c></seealso>
are executed when entering the first
<seealso marker="#type-state">state</seealso> just as for a
- <seealso marker="#state callback">state callback</seealso>,
+ <seealso marker="#state callback"><em>state callback</em></seealso>,
except that the action <c>postpone</c> is forced to
<c>false</c> since there is no event to postpone.
</p>
@@ -1292,11 +1329,13 @@ handle_event(_, _, State, Data) ->
<tag><c>next_state</c></tag>
<item>
<p>
- The <c>gen_statem</c> does a state transition to
+ The <c>gen_statem</c> does a <em>state transition</em> to
<c><anno>NextState</anno></c>
(which can be the same as the current state),
sets <c><anno>NewData</anno></c>,
and executes all <c><anno>Actions</anno></c>.
+ If <c><anno>NextState</anno> =/= CurrentState</c>
+ the <em>state transition</em> is a <em>state change</em>.
</p>
</item>
</taglist>
@@ -1318,54 +1357,33 @@ handle_event(_, _, State, Data) ->
<tag><c>keep_state</c></tag>
<item>
<p>
- The <c>gen_statem</c> keeps the current state, or
- does a state transition to the current state if you like,
- sets <c><anno>NewData</anno></c>,
- and executes all <c><anno>Actions</anno></c>.
- This is the same as
+ The same as
<c>{next_state,CurrentState,<anno>NewData</anno>,<anno>Actions</anno>}</c>.
</p>
</item>
<tag><c>keep_state_and_data</c></tag>
<item>
<p>
- The <c>gen_statem</c> keeps the current state or
- does a state transition to the current state if you like,
- keeps the current server data,
- and executes all <c><anno>Actions</anno></c>.
- This is the same as
- <c>{next_state,CurrentState,CurrentData,<anno>Actions</anno>}</c>.
+ The same as
+ <c>{keep_state,CurrentData,<anno>Actions</anno>}</c>.
</p>
</item>
<tag><c>repeat_state</c></tag>
<item>
<p>
- The <c>gen_statem</c> keeps the current state, or
- does a state transition to the current state if you like,
- sets <c><anno>NewData</anno></c>,
- and executes all <c><anno>Actions</anno></c>.
If the <c>gen_statem</c> runs with
<seealso marker="#type-state_enter"><em>state enter calls</em></seealso>,
- the state enter call is repeated, see type
+ the <em>state enter call</em> is repeated, see type
<seealso marker="#type-transition_option"><c>transition_option()</c></seealso>,
- otherwise <c>repeat_state</c> is the same as
+ other than that <c>repeat_state</c> is the same as
<c>keep_state</c>.
</p>
</item>
<tag><c>repeat_state_and_data</c></tag>
<item>
<p>
- The <c>gen_statem</c> keeps the current state and data, or
- does a state transition to the current state if you like,
- and executes all <c><anno>Actions</anno></c>.
- This is the same as
+ The same as
<c>{repeat_state,CurrentData,<anno>Actions</anno>}</c>.
- If the <c>gen_statem</c> runs with
- <seealso marker="#type-state_enter"><em>state enter calls</em></seealso>,
- the state enter call is repeated, see type
- <seealso marker="#type-transition_option"><c>transition_option()</c></seealso>,
- otherwise <c>repeat_state_and_data</c> is the same as
- <c>keep_state_and_data</c>.
</p>
</item>
<tag><c>stop</c></tag>
@@ -1408,14 +1426,15 @@ handle_event(_, _, State, Data) ->
by sending a request
and waiting until its reply arrives.
The <c>gen_statem</c> calls the
- <seealso marker="#state callback">state callback</seealso> with
+ <seealso marker="#state callback"><em>state callback</em></seealso>
+ with
<seealso marker="#type-event_type"><c>event_type()</c></seealso>
<c>{call,From}</c> and event content
<c><anno>Request</anno></c>.
</p>
<p>
A <c><anno>Reply</anno></c> is generated when a
- <seealso marker="#state callback">state callback</seealso>
+ <seealso marker="#state callback"><em>state callback</em></seealso>
returns with
<c>{reply,From,<anno>Reply</anno>}</c> as one
<seealso marker="#type-action"><c>action()</c></seealso>,
@@ -1484,7 +1503,8 @@ handle_event(_, _, State, Data) ->
ignoring if the destination node or <c>gen_statem</c>
does not exist.
The <c>gen_statem</c> calls the
- <seealso marker="#state callback">state callback</seealso> with
+ <seealso marker="#state callback"><em>state callback</em></seealso>
+ with
<seealso marker="#type-event_type"><c>event_type()</c></seealso>
<c>cast</c> and event content
<c><anno>Msg</anno></c>.
@@ -1598,18 +1618,18 @@ handle_event(_, _, State, Data) ->
<seealso marker="#call/2"><c>call/2</c></seealso>
when the reply cannot be defined in
the return value of a
- <seealso marker="#state callback">state callback</seealso>.
+ <seealso marker="#state callback"><em>state callback</em></seealso>.
</p>
<p>
<c><anno>From</anno></c> must be the term from argument
<seealso marker="#type-event_type"><c>{call,<anno>From</anno>}</c></seealso>
to the
- <seealso marker="#state callback">state callback</seealso>.
+ <seealso marker="#state callback"><em>state callback</em></seealso>.
A reply or multiple replies canalso be sent
using one or several
<seealso marker="#type-reply_action"><c>reply_action()</c></seealso>s
from a
- <seealso marker="#state callback">state callback</seealso>.
+ <seealso marker="#state callback"><em>state callback</em></seealso>.
</p>
<note>
<p>
@@ -1826,7 +1846,7 @@ handle_event(_, _, State, Data) ->
for efficiency reasons, so this function is only called
once after server start and after code change,
but before the first
- <seealso marker="#state callback">state callback</seealso>
+ <seealso marker="#state callback"><em>state callback</em></seealso>
in the current code version is called.
More occasions may be added in future versions
of <c>gen_statem</c>.
@@ -1883,7 +1903,7 @@ handle_event(_, _, State, Data) ->
<p>
This callback is optional, so callback modules need not export it.
If a release upgrade/downgrade with
- <c>Change={advanced,Extra}</c>
+ <c>Change = {advanced,Extra}</c>
specified in the <c>.appup</c> file is made
when <c>code_change/4</c> is not implemented
the process will crash with exit reason <c>undef</c>.
@@ -1893,7 +1913,7 @@ handle_event(_, _, State, Data) ->
This function is called by a <c>gen_statem</c> when it is to
update its internal state during a release upgrade/downgrade,
that is, when the instruction <c>{update,Module,Change,...}</c>,
- where <c>Change={advanced,Extra}</c>, is specified in the
+ where <c>Change = {advanced,Extra}</c>, is specified in the
<seealso marker="sasl:appup"><c>appup</c></seealso>
file. For more information, see
<seealso marker="doc/design_principles:release_handling#instr">OTP Design Principles</seealso>.
@@ -1933,13 +1953,13 @@ handle_event(_, _, State, Data) ->
<p>
Also note when upgrading a <c>gen_statem</c>,
this function and hence
- the <c>Change={advanced,Extra}</c> parameter in the
+ the <c>Change = {advanced,Extra}</c> parameter in the
<seealso marker="sasl:appup"><c>appup</c></seealso> file
is not only needed to update the internal state
or to act on the <c>Extra</c> argument.
It is also needed if an upgrade or downgrade should change
<seealso marker="#type-callback_mode"><em>callback mode</em></seealso>,
- or else the callback mode after the code change
+ or else the <em>callback mode</em> after the code change
will not be honoured,
most probably causing a server crash.
</p>
@@ -2148,7 +2168,7 @@ init(Args) -> erlang:error(not_implemented, [Args]).</pre>
<seealso marker="#type-event_type"><c>{call,From}</c></seealso>,
the caller waits for a reply. The reply can be sent
from this or from any other
- <seealso marker="#state callback">state callback</seealso>
+ <seealso marker="#state callback"><em>state callback</em></seealso>
by returning with <c>{reply,From,Reply}</c> in
<seealso marker="#type-action"><c>Actions</c></seealso>, in
<seealso marker="#type-reply_action"><c>Replies</c></seealso>,
@@ -2173,9 +2193,9 @@ init(Args) -> erlang:error(not_implemented, [Args]).</pre>
</p>
<p>
When the <c>gen_statem</c> runs with
- <seealso marker="#type-state_enter">state enter calls</seealso>,
+ <seealso marker="#type-state_enter"><em>state enter calls</em></seealso>,
these functions are also called with arguments
- <c>(enter, OldState, ...)</c> whenever the state changes.
+ <c>(enter, OldState, ...)</c> during every <em>state change</em>.
In this case there are some restrictions on the
<seealso marker="#type-enter_action">actions</seealso>
that may be returned:
diff --git a/lib/stdlib/doc/src/notes.xml b/lib/stdlib/doc/src/notes.xml
index 8b6de03f5f..318643aef8 100644
--- a/lib/stdlib/doc/src/notes.xml
+++ b/lib/stdlib/doc/src/notes.xml
@@ -31,6 +31,41 @@
</header>
<p>This document describes the changes made to the STDLIB application.</p>
+<section><title>STDLIB 3.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>The specs of <c>filename:basedir/2,3</c> are
+ corrected.</p>
+ <p>
+ Own Id: OTP-15252 Aux Id: ERL-667 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> Let <c>dets:open_file()</c> exit with a <c>badarg</c>
+ message if given a raw file name (a binary). </p>
+ <p>
+ Own Id: OTP-15253 Aux Id: OTP-13229, ERL-55 </p>
+ </item>
+ <item>
+ <p> The <c>Format</c> argument of the formatting
+ functions in modules <c>io</c> and <c>io_lib</c> is
+ accepted even if it is, for example, a list of binaries.
+ This is how it used to be before Erlang/OTP 21.0. </p>
+ <p>
+ Own Id: OTP-15304</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>STDLIB 3.5.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/stdlib/doc/src/rand.xml b/lib/stdlib/doc/src/rand.xml
index 21f680a0ee..25eec216ef 100644
--- a/lib/stdlib/doc/src/rand.xml
+++ b/lib/stdlib/doc/src/rand.xml
@@ -67,6 +67,26 @@
<p>Xorshift1024*, 64 bits precision and a period of 2^1024-1</p>
<p>Jump function: equivalent to 2^512 calls</p>
</item>
+ <tag><c>exro928ss</c></tag>
+ <item>
+ <p>Xoroshiro928**, 58 bits precision and a period of 2^928-1</p>
+ <p>Jump function: equivalent to 2^512 calls</p>
+ <p>
+ This is a 58 bit version of Xoroshiro1024**,
+ from the 2018 paper by David Blackman and Sebastiano Vigna:
+ <url href="http://vigna.di.unimi.it/ftp/papers/ScrambledLinear.pdf">
+ Scrambled Linear Pseudorandom Number Generators
+ </url>
+ that on a 64 bit Erlang system executes only about 30% slower than
+ the default <c>exrop</c> algorithm but with much longer period
+ and better statistical properties, and on the flip side
+ a larger state.
+ </p>
+ <p>
+ Many thanks to Sebastiano Vigna for his help with
+ the 58 bit adaption.
+ </p>
+ </item>
<tag><c>exsp</c></tag>
<item>
<p>Xorshift116+, 58 bits precision and period of 2^116-1</p>
@@ -195,8 +215,8 @@ SND0 = math:sqrt(-2 * math:log(R5)) * math:cos(math:pi() * R6)</pre>
</note>
<p>
- For all these generators the lowest bit(s) has got
- a slightly less random behaviour than all other bits.
+ For all these generators except <c>exro928ss</c> the lowest bit(s)
+ has got a slightly less random behaviour than all other bits.
1 bit for <c>exrop</c> (and <c>exsp</c>),
and 3 bits for <c>exs1024s</c>.
See for example the explanation in the
@@ -254,11 +274,32 @@ tests. We suggest to use a sign test to extract a random Boolean value.</pre>
</desc>
</datatype>
<datatype>
- <name name="exs64_state"/>
- <desc><p>Algorithm specific internal state</p></desc>
+ <name name="seed"/>
+ <desc>
+ <p>
+ A seed value for the generator.
+ </p>
+ <p>
+ A list of integers sets the generator's internal state directly,
+ after algorithm-dependent checks of the value
+ and masking to the proper word size.
+ </p>
+ <p>
+ An integer is used as the initial state for a SplitMix64 generator.
+ The output values of that is then used for setting
+ the generator's internal state
+ after masking to the proper word size
+ and if needed avoiding zero values.
+ </p>
+ <p>
+ A traditional 3-tuple of integers seed is passed through
+ algorithm-dependent hashing functions to create
+ the generator's initial state.
+ </p>
+ </desc>
</datatype>
<datatype>
- <name name="exsplus_state"/>
+ <name name="exrop_state"/>
<desc><p>Algorithm specific internal state</p></desc>
</datatype>
<datatype>
@@ -266,7 +307,15 @@ tests. We suggest to use a sign test to extract a random Boolean value.</pre>
<desc><p>Algorithm specific internal state</p></desc>
</datatype>
<datatype>
- <name name="exrop_state"/>
+ <name name="exro928_state"/>
+ <desc><p>Algorithm specific internal state</p></desc>
+ </datatype>
+ <datatype>
+ <name name="exsplus_state"/>
+ <desc><p>Algorithm specific internal state</p></desc>
+ </datatype>
+ <datatype>
+ <name name="exs64_state"/>
<desc><p>Algorithm specific internal state</p></desc>
</datatype>
</datatypes>
diff --git a/lib/stdlib/doc/src/supervisor.xml b/lib/stdlib/doc/src/supervisor.xml
index 6d5065ca02..5fd5760499 100644
--- a/lib/stdlib/doc/src/supervisor.xml
+++ b/lib/stdlib/doc/src/supervisor.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2017</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -208,8 +208,16 @@ child_spec() = #{id => child_id(), % mandatory
the child process is unconditionally terminated using
<c>exit(Child,kill)</c>.</p>
<p>If the child process is another supervisor, the shutdown time
- is to be set to <c>infinity</c> to give the subtree ample
- time to shut down. It is also allowed to set it to <c>infinity</c>,
+ must be set to <c>infinity</c> to give the subtree ample
+ time to shut down.</p>
+ <warning>
+ <p>Setting the shutdown time to anything other
+ than <c>infinity</c> for a child of type <c>supervisor</c>
+ can cause a race condition where the child in question
+ unlinks its own children, but fails to terminate them
+ before it is killed.</p>
+ </warning>
+ <p>It is also allowed to set it to <c>infinity</c>,
if the child process is a worker.</p>
<warning>
<p>Be careful when setting the shutdown time to
diff --git a/lib/stdlib/src/dets.erl b/lib/stdlib/src/dets.erl
index e016d5a80e..0488c2bef2 100644
--- a/lib/stdlib/src/dets.erl
+++ b/lib/stdlib/src/dets.erl
@@ -616,12 +616,18 @@ next(Tab, Key) ->
%% Assuming that a file already exists, open it with the
%% parameters as already specified in the file itself.
%% Return a ref leading to the file.
-open_file(File) ->
- case dets_server:open_file(to_list(File)) of
- badarg -> % Should not happen.
- erlang:error(dets_process_died, [File]);
- Reply ->
- einval(Reply, [File])
+open_file(File0) ->
+ File = to_list(File0),
+ case is_list(File) of
+ true ->
+ case dets_server:open_file(File) of
+ badarg -> % Should not happen.
+ erlang:error(dets_process_died, [File]);
+ Reply ->
+ einval(Reply, [File])
+ end;
+ false ->
+ erlang:error(badarg, [File0])
end.
-spec open_file(Name, Args) -> {'ok', Name} | {'error', Reason} when
@@ -1088,6 +1094,7 @@ defaults(Tab, Args) ->
debug = false},
Fun = fun repl/2,
Defaults = lists:foldl(Fun, Defaults0, Args),
+ true = is_list(Defaults#open_args.file),
is_comp_min_max(Defaults).
to_list(T) when is_atom(T) -> atom_to_list(T);
@@ -1112,9 +1119,7 @@ repl({delayed_write, {Delay,Size} = C}, Defs)
Defs#open_args{delayed_write = C};
repl({estimated_no_objects, I}, Defs) ->
repl({min_no_slots, I}, Defs);
-repl({file, File}, Defs) when is_list(File) ->
- Defs#open_args{file = File};
-repl({file, File}, Defs) when is_atom(File) ->
+repl({file, File}, Defs) ->
Defs#open_args{file = to_list(File)};
repl({keypos, P}, Defs) when is_integer(P), P > 0 ->
Defs#open_args{keypos =P};
diff --git a/lib/stdlib/src/filename.erl b/lib/stdlib/src/filename.erl
index a322bd002d..b7b7b562ab 100644
--- a/lib/stdlib/src/filename.erl
+++ b/lib/stdlib/src/filename.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -1012,24 +1012,33 @@ filename_string_to_binary(List) ->
%% basedir
%% http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
--type basedir_type() :: 'user_cache' | 'user_config' | 'user_data'
- | 'user_log'
- | 'site_config' | 'site_data'.
+-type basedir_path_type() :: 'user_cache' | 'user_config' | 'user_data'
+ | 'user_log'.
+-type basedir_paths_type() :: 'site_config' | 'site_data'.
--spec basedir(Type,Application) -> file:filename_all() when
- Type :: basedir_type(),
+-type basedir_opts() :: #{author => string() | binary(),
+ os => 'windows' | 'darwin' | 'linux',
+ version => string() | binary()}.
+
+-spec basedir(PathType,Application) -> file:filename_all() when
+ PathType :: basedir_path_type(),
+ Application :: string() | binary();
+ (PathsType,Application) -> [file:filename_all()] when
+ PathsType :: basedir_paths_type(),
Application :: string() | binary().
basedir(Type,Application) when is_atom(Type), is_list(Application) orelse
is_binary(Application) ->
basedir(Type, Application, #{}).
--spec basedir(Type,Application,Opts) -> file:filename_all() when
- Type :: basedir_type(),
+-spec basedir(PathType,Application,Opts) -> file:filename_all() when
+ PathType :: basedir_path_type(),
+ Application :: string() | binary(),
+ Opts :: basedir_opts();
+ (PathsType,Application,Opts) -> [file:filename_all()] when
+ PathsType :: basedir_paths_type(),
Application :: string() | binary(),
- Opts :: #{author => string() | binary(),
- os => 'windows' | 'darwin' | 'linux',
- version => string() | binary()}.
+ Opts :: basedir_opts().
basedir(Type,Application,Opts) when is_atom(Type), is_map(Opts),
is_list(Application) orelse
diff --git a/lib/stdlib/src/gen_statem.erl b/lib/stdlib/src/gen_statem.erl
index faa43fbc1e..24b268cd38 100644
--- a/lib/stdlib/src/gen_statem.erl
+++ b/lib/stdlib/src/gen_statem.erl
@@ -330,6 +330,7 @@
%% Type validation functions
+%% - return true if the value is of the type, false otherwise
-compile(
{inline,
[callback_mode/1, state_enter/1,
@@ -1277,7 +1278,7 @@ parse_actions(StateCall, Debug, S, [Action|Actions], TransOpts) ->
end.
parse_actions_reply(
- StateCall, ?not_sys_debug, S, Actions, TransOpts,
+ StateCall, ?not_sys_debug = Debug, S, Actions, TransOpts,
From, Reply) ->
%%
case from(From) of
@@ -1287,8 +1288,7 @@ parse_actions_reply(
false ->
[error,
{bad_action_from_state_function,{reply,From,Reply}},
- ?STACKTRACE(),
- ?not_sys_debug]
+ ?STACKTRACE(), Debug]
end;
parse_actions_reply(
StateCall, Debug, #state{name = Name, state = State} = S,
@@ -1302,12 +1302,11 @@ parse_actions_reply(
false ->
[error,
{bad_action_from_state_function,{reply,From,Reply}},
- ?STACKTRACE(),
- Debug]
+ ?STACKTRACE(), Debug]
end.
parse_actions_next_event(
- StateCall, ?not_sys_debug, S,
+ StateCall, ?not_sys_debug = Debug, S,
Actions, TransOpts, Type, Content) ->
case event_type(Type) of
true when StateCall ->
@@ -1320,8 +1319,7 @@ parse_actions_next_event(
[error,
{bad_state_enter_action_from_state_function,
{next_event,Type,Content}},
- ?STACKTRACE(),
- ?not_sys_debug]
+ ?STACKTRACE(), Debug]
end;
parse_actions_next_event(
StateCall, Debug, #state{name = Name, state = State} = S,
@@ -1403,13 +1401,13 @@ parse_actions_timeout_add(
loop_event_done(
Parent, ?not_sys_debug,
#state{postponed = P} = S,
+%% #state{postponed = will_not_happen = P} = S,
Events, Event, NextState, NewData,
#trans_opts{
postpone = Postpone, hibernate = Hibernate,
- timeouts_r = [], next_events_r = []}) ->
+ timeouts_r = [], next_events_r = NextEventsR}) ->
%%
- %% Optimize the simple cases
- %% i.e no timer changes, no inserted events and no debug,
+ %% Optimize the simple cases i.e no debug and no timer changes,
%% by duplicate stripped down code
%%
%% Fast path
@@ -1417,14 +1415,12 @@ loop_event_done(
case Postpone of
true ->
loop_event_done_fast(
- Parent, Hibernate,
- S,
- Events, [Event|P], NextState, NewData);
+ Parent, Hibernate, S,
+ Events, [Event|P], NextState, NewData, NextEventsR);
false ->
loop_event_done_fast(
- Parent, Hibernate,
- S,
- Events, P, NextState, NewData)
+ Parent, Hibernate, S,
+ Events, P, NextState, NewData, NextEventsR)
end;
loop_event_done(
Parent, Debug_0,
@@ -1456,26 +1452,23 @@ loop_event_done(
{S#state.name,State},
{consume,Event_0,NextState})|P_0]
end,
- {Events_2,P_2,Timers_2} =
- %% Move all postponed events to queue,
- %% cancel the event timer,
- %% and cancel the state timeout if the state changes
- if
- NextState =:= State ->
- {Events_0,P_1,
+ {Events_2,P_2,
+ Timers_2} =
+ %% Cancel the event timeout
+ if
+ NextState =:= State ->
+ {Events_0,P_1,
cancel_timer_by_type(
timeout, {TimerTypes_0,CancelTimers_0})};
- true ->
- {lists:reverse(P_1, Events_0),
- [],
- cancel_timer_by_type(
- state_timeout,
+ true ->
+ %% Move all postponed events to queue
+ %% and cancel the state timeout
+ {lists:reverse(P_1, Events_0),[],
+ cancel_timer_by_type(
+ state_timeout,
cancel_timer_by_type(
timeout, {TimerTypes_0,CancelTimers_0}))}
- %% The state timer is removed from TimerTypes
- %% but remains in TimerRefs until we get
- %% the cancel_timer msg
- end,
+ end,
{TimerRefs_3,{TimerTypes_3,CancelTimers_3},TimeoutEvents} =
%% Stop and start timers
parse_timers(TimerRefs_0, Timers_2, TimeoutsR),
@@ -1495,114 +1488,144 @@ loop_event_done(
hibernate = Hibernate},
lists:reverse(Events_4R)).
+loop_event_done(Parent, Debug, S, Q) ->
+%% io:format(
+%% "loop_event_done:~n"
+%% " state = ~p, data = ~p, postponed = ~p~n "
+%% " timer_refs = ~p, timer_types = ~p, cancel_timers = ~p.~n"
+%% " Q = ~p.~n",
+%% [S#state.state,S#state.data,S#state.postponed,
+%% S#state.timer_refs,S#state.timer_types,S#state.cancel_timers,
+%% Q]),
+ case Q of
+ [] ->
+ %% Get a new event
+ loop(Parent, Debug, S);
+ [{Type,Content}|Events] ->
+ %% Loop until out of enqueued events
+ loop_event(Parent, Debug, S, Events, Type, Content)
+ end.
+
+
%% Fast path
%%
+%% Cancel event timer and state timer only if running
loop_event_done_fast(
Parent, Hibernate,
#state{
state = NextState,
- timer_types = #{timeout := _} = TimerTypes,
+ timer_types = TimerTypes,
cancel_timers = CancelTimers} = S,
- Events, P, NextState, NewData) ->
- %%
- %% Same state, event timeout active
- %%
- loop_event_done_fast(
- Parent, Hibernate, S,
- Events, P, NextState, NewData,
- cancel_timer_by_type(
- timeout, {TimerTypes,CancelTimers}));
-loop_event_done_fast(
- Parent, Hibernate,
- #state{state = NextState} = S,
- Events, P, NextState, NewData) ->
- %%
+ Events, P, NextState, NewData, NextEventsR) ->
%% Same state
- %%
- loop_event_done(
- Parent, ?not_sys_debug,
- S#state{
- data = NewData,
- postponed = P,
- hibernate = Hibernate},
- Events);
-loop_event_done_fast(
- Parent, Hibernate,
- #state{
- timer_types = #{timeout := _} = TimerTypes,
- cancel_timers = CancelTimers} = S,
- Events, P, NextState, NewData) ->
- %%
- %% State change, event timeout active
- %%
- loop_event_done_fast(
- Parent, Hibernate, S,
- lists:reverse(P, Events), [], NextState, NewData,
- cancel_timer_by_type(
- state_timeout,
- cancel_timer_by_type(
- timeout, {TimerTypes,CancelTimers})));
+ case TimerTypes of
+ #{timeout := _} ->
+ %% Event timeout active
+ loop_event_done_fast_2(
+ Parent, Hibernate, S,
+ Events, P, NextState, NewData, NextEventsR,
+ cancel_timer_by_type(
+ timeout, {TimerTypes,CancelTimers}));
+ _ ->
+ %% No event timeout active
+ loop_event_done_fast_2(
+ Parent, Hibernate, S,
+ Events, P, NextState, NewData, NextEventsR,
+ {TimerTypes,CancelTimers})
+ end;
loop_event_done_fast(
Parent, Hibernate,
#state{
- timer_types = #{state_timeout := _} = TimerTypes,
+ timer_types = TimerTypes,
cancel_timers = CancelTimers} = S,
- Events, P, NextState, NewData) ->
- %%
- %% State change, state timeout active
- %%
- loop_event_done_fast(
- Parent, Hibernate, S,
- lists:reverse(P, Events), [], NextState, NewData,
- cancel_timer_by_type(
- state_timeout,
- cancel_timer_by_type(
- timeout, {TimerTypes,CancelTimers})));
+ Events, P, NextState, NewData, NextEventsR) ->
+ %% State change
+ case TimerTypes of
+ #{timeout := _} ->
+ %% Event timeout active
+ %% - cancel state_timeout too since it is faster than inspecting
+ loop_event_done_fast(
+ Parent, Hibernate, S,
+ Events, P, NextState, NewData, NextEventsR,
+ cancel_timer_by_type(
+ state_timeout,
+ cancel_timer_by_type(
+ timeout, {TimerTypes,CancelTimers})));
+ #{state_timeout := _} ->
+ %% State_timeout active but not event timeout
+ loop_event_done_fast(
+ Parent, Hibernate, S,
+ Events, P, NextState, NewData, NextEventsR,
+ cancel_timer_by_type(
+ state_timeout, {TimerTypes,CancelTimers}));
+ _ ->
+ %% No event nor state_timeout active
+ loop_event_done_fast(
+ Parent, Hibernate, S,
+ Events, P, NextState, NewData, NextEventsR,
+ {TimerTypes,CancelTimers})
+ end.
+%%
+%% Retry postponed events
loop_event_done_fast(
- Parent, Hibernate,
- #state{} = S,
- Events, P, NextState, NewData) ->
- %%
- %% State change, no timeout to automatically cancel
- %%
- loop_event_done(
- Parent, ?not_sys_debug,
- S#state{
- state = NextState,
- data = NewData,
- postponed = [],
- hibernate = Hibernate},
- lists:reverse(P, Events)).
+ Parent, Hibernate, S,
+ Events, P, NextState, NewData, NextEventsR, TimerTypes_CancelTimers) ->
+ case P of
+ %% Handle 0..2 postponed events without list reversal since
+ %% that will move out all live registers and back again
+ [] ->
+ loop_event_done_fast_2(
+ Parent, Hibernate, S,
+ Events, [], NextState, NewData, NextEventsR,
+ TimerTypes_CancelTimers);
+ [E] ->
+ loop_event_done_fast_2(
+ Parent, Hibernate, S,
+ [E|Events], [], NextState, NewData, NextEventsR,
+ TimerTypes_CancelTimers);
+ [E1,E2] ->
+ loop_event_done_fast_2(
+ Parent, Hibernate, S,
+ [E2,E1|Events], [], NextState, NewData, NextEventsR,
+ TimerTypes_CancelTimers);
+ _ ->
+ %% A bit slower path
+ loop_event_done_fast_2(
+ Parent, Hibernate, S,
+ lists:reverse(P, Events), [], NextState, NewData, NextEventsR,
+ TimerTypes_CancelTimers)
+ end.
%%
%% Fast path
%%
-loop_event_done_fast(
+loop_event_done_fast_2(
Parent, Hibernate, S,
- Events, P, NextState, NewData,
+ Events, P, NextState, NewData, NextEventsR,
{TimerTypes,CancelTimers}) ->
%%
- loop_event_done(
- Parent, ?not_sys_debug,
- S#state{
- state = NextState,
- data = NewData,
- postponed = P,
- timer_types = TimerTypes,
- cancel_timers = CancelTimers,
- hibernate = Hibernate},
- Events).
-
-loop_event_done(Parent, Debug, S, Q) ->
- case Q of
+ NewS =
+ S#state{
+ state = NextState,
+ data = NewData,
+ postponed = P,
+ timer_types = TimerTypes,
+ cancel_timers = CancelTimers,
+ hibernate = Hibernate},
+ case NextEventsR of
+ %% Handle 0..2 next events without list reversal since
+ %% that will move out all live registers and back again
[] ->
- %% Get a new event
- loop(Parent, Debug, S);
- [{Type,Content}|Events] ->
- %% Loop until out of enqueued events
- loop_event(Parent, Debug, S, Events, Type, Content)
+ loop_event_done(Parent, ?not_sys_debug, NewS, Events);
+ [E] ->
+ loop_event_done(Parent, ?not_sys_debug, NewS, [E|Events]);
+ [E2,E1] ->
+ loop_event_done(Parent, ?not_sys_debug, NewS, [E1,E2|Events]);
+ _ ->
+ %% A bit slower path
+ loop_event_done(
+ Parent, ?not_sys_debug, NewS, lists:reverse(NextEventsR, Events))
end.
-
%%---------------------------------------------------------------------------
%% Server loop helpers
diff --git a/lib/stdlib/src/io_lib.erl b/lib/stdlib/src/io_lib.erl
index 3a5aba60b4..8223a52873 100644
--- a/lib/stdlib/src/io_lib.erl
+++ b/lib/stdlib/src/io_lib.erl
@@ -178,11 +178,11 @@ fread(Cont, Chars, Format) ->
Data :: [term()].
format(Format, Args) ->
- case catch io_lib_format:fwrite(Format, Args) of
- {'EXIT',_} ->
- erlang:error(badarg, [Format, Args]);
- Other ->
- Other
+ try io_lib_format:fwrite(Format, Args)
+ catch
+ C:R:S ->
+ test_modules_loaded(C, R, S),
+ erlang:error(badarg, [Format, Args])
end.
-spec format(Format, Data, Options) -> chars() when
@@ -193,11 +193,11 @@ format(Format, Args) ->
CharsLimit :: chars_limit().
format(Format, Args, Options) ->
- case catch io_lib_format:fwrite(Format, Args, Options) of
- {'EXIT',_} ->
- erlang:error(badarg, [Format, Args, Options]);
- Other ->
- Other
+ try io_lib_format:fwrite(Format, Args, Options)
+ catch
+ C:R:S ->
+ test_modules_loaded(C, R, S),
+ erlang:error(badarg, [Format, Args])
end.
-spec scan_format(Format, Data) -> FormatList when
@@ -208,7 +208,9 @@ format(Format, Args, Options) ->
scan_format(Format, Args) ->
try io_lib_format:scan(Format, Args)
catch
- _:_ -> erlang:error(badarg, [Format, Args])
+ C:R:S ->
+ test_modules_loaded(C, R, S),
+ erlang:error(badarg, [Format, Args])
end.
-spec unscan_format(FormatList) -> {Format, Data} when
@@ -223,7 +225,12 @@ unscan_format(FormatList) ->
FormatList :: [char() | format_spec()].
build_text(FormatList) ->
- io_lib_format:build(FormatList).
+ try io_lib_format:build(FormatList)
+ catch
+ C:R:S ->
+ test_modules_loaded(C, R, S),
+ erlang:error(badarg, [FormatList])
+ end.
-spec build_text(FormatList, Options) -> chars() when
FormatList :: [char() | format_spec()],
@@ -232,7 +239,23 @@ build_text(FormatList) ->
CharsLimit :: chars_limit().
build_text(FormatList, Options) ->
- io_lib_format:build(FormatList, Options).
+ try io_lib_format:build(FormatList, Options)
+ catch
+ C:R:S ->
+ test_modules_loaded(C, R, S),
+ erlang:error(badarg, [FormatList, Options])
+ end.
+
+%% Failure to load a module must not be labeled as badarg.
+%% C, R, and S are included so that the original error, which could be
+%% a bug in io_lib_format, can be found by tracing on
+%% test_modules_loaded/3.
+test_modules_loaded(_C, _R, _S) ->
+ Modules = [io_lib_format, io_lib_pretty, string, unicode],
+ case code:ensure_modules_loaded(Modules) of
+ ok -> ok;
+ Error -> erlang:error(Error)
+ end.
-spec print(Term) -> chars() when
Term :: term().
diff --git a/lib/stdlib/src/io_lib_format.erl b/lib/stdlib/src/io_lib_format.erl
index c814ab50d4..ab9031573b 100644
--- a/lib/stdlib/src/io_lib_format.erl
+++ b/lib/stdlib/src/io_lib_format.erl
@@ -38,18 +38,16 @@
%% and it also splits the handling of the control characters into two
%% parts.
--spec fwrite(Format, Data) -> FormatList when
+-spec fwrite(Format, Data) -> io_lib:chars() when
Format :: io:format(),
- Data :: [term()],
- FormatList :: [char() | io_lib:format_spec()].
+ Data :: [term()].
fwrite(Format, Args) ->
build(scan(Format, Args)).
--spec fwrite(Format, Data, Options) -> FormatList when
+-spec fwrite(Format, Data, Options) -> io_lib:chars() when
Format :: io:format(),
Data :: [term()],
- FormatList :: [char() | io_lib:format_spec()],
Options :: [Option],
Option :: {'chars_limit', CharsLimit},
CharsLimit :: io_lib:chars_limit().
@@ -248,7 +246,8 @@ count_small([#{control_char := $W}|Cs], #{w := W} = Cnts) ->
count_small(Cs, Cnts#{w := W + 1});
count_small([#{control_char := $s}|Cs], #{w := W} = Cnts) ->
count_small(Cs, Cnts#{w := W + 1});
-count_small([S|Cs], #{other := Other} = Cnts) when is_list(S) ->
+count_small([S|Cs], #{other := Other} = Cnts) when is_list(S);
+ is_binary(S) ->
count_small(Cs, Cnts#{other := Other + string:length(S)});
count_small([C|Cs], #{other := Other} = Cnts) when is_integer(C) ->
count_small(Cs, Cnts#{other := Other + 1});
diff --git a/lib/stdlib/src/ms_transform.erl b/lib/stdlib/src/ms_transform.erl
index d117481d2e..3845e35e9b 100644
--- a/lib/stdlib/src/ms_transform.erl
+++ b/lib/stdlib/src/ms_transform.erl
@@ -224,10 +224,12 @@ transform_from_shell(Dialect, Clauses, BoundEnvironment) ->
%% Called when translating during compiling
%%
--spec parse_transform(Forms, Options) -> Forms2 when
+-spec parse_transform(Forms, Options) -> Forms2 | Errors | Warnings when
Forms :: [erl_parse:abstract_form() | erl_parse:form_info()],
Forms2 :: [erl_parse:abstract_form() | erl_parse:form_info()],
- Options :: term().
+ Options :: term(),
+ Errors :: {error, ErrInfo :: [tuple()], WarnInfo :: []},
+ Warnings :: {warning, Forms2, WarnInfo :: [tuple()]}.
parse_transform(Forms, _Options) ->
SaveFilename = setup_filename(),
diff --git a/lib/stdlib/src/proc_lib.erl b/lib/stdlib/src/proc_lib.erl
index d07c62500b..cfbaf8b242 100644
--- a/lib/stdlib/src/proc_lib.erl
+++ b/lib/stdlib/src/proc_lib.erl
@@ -757,7 +757,8 @@ check(Res) -> Res.
report_cb(#{label:={proc_lib,crash}, report:=CrashReport}, Extra) ->
Default = #{chars_limit => unlimited,
depth => unlimited,
- encoding => latin1},
+ single_line => false,
+ encoding => utf8},
do_format(CrashReport, maps:merge(Default,Extra)).
-spec format(CrashReport) -> string() when
@@ -780,33 +781,48 @@ format(CrashReport, Encoding) ->
format(CrashReport, Encoding, Depth) ->
do_format(CrashReport, #{chars_limit => unlimited,
depth => Depth,
- encoding => Encoding}).
-
-do_format([OwnReport,LinkReport], Extra) ->
- MyIndent = " ",
+ encoding => Encoding,
+ single_line => false}).
+
+do_format([OwnReport,LinkReport], #{single_line:=Single}=Extra) ->
+ Indent = if Single -> "";
+ true -> " "
+ end,
+ MyIndent = Indent ++ Indent,
+ Sep = nl(Single,"; "),
OwnFormat = format_report(OwnReport, MyIndent, Extra),
- LinkFormat = format_link_report(LinkReport, MyIndent, Extra),
- Str = io_lib:format(" crasher:~n~ts neighbours:~n~ts",
- [OwnFormat, LinkFormat]),
+ LinkFormat = lists:join(Sep,format_link_report(LinkReport, MyIndent, Extra)),
+ Nl = nl(Single," "),
+ Str = io_lib:format("~scrasher:"++Nl++"~ts"++Sep++"~sneighbours:"++Nl++"~ts",
+ [Indent,OwnFormat,Indent,LinkFormat]),
lists:flatten(Str).
-format_link_report([Link|Reps], Indent, Extra) ->
+format_link_report([Link|Reps], Indent0, #{single_line:=Single}=Extra) ->
Rep = case Link of
{neighbour,Rep0} -> Rep0;
_ -> Link
end,
+ Indent = if Single -> "";
+ true -> Indent0
+ end,
LinkIndent = [" ",Indent],
- [Indent,"neighbour:\n",format_report(Rep, LinkIndent, Extra)|
+ [[Indent,"neighbour:",nl(Single," "),format_report(Rep, LinkIndent, Extra)]|
format_link_report(Reps, Indent, Extra)];
format_link_report(Rep, Indent, Extra) ->
format_report(Rep, Indent, Extra).
-format_report(Rep, Indent, Extra) when is_list(Rep) ->
- format_rep(Rep, Indent, Extra);
-format_report(Rep, Indent, #{encoding:=Enc,depth:=unlimited}) ->
- io_lib:format("~s~"++modifier(Enc)++"p~n", [Indent, Rep]);
-format_report(Rep, Indent, #{encoding:=Enc,depth:=Depth}) ->
- io_lib:format("~s~"++modifier(Enc)++"P~n", [Indent, Rep, Depth]).
+format_report(Rep, Indent, #{single_line:=Single}=Extra) when is_list(Rep) ->
+ lists:join(nl(Single,", "),format_rep(Rep, Indent, Extra));
+format_report(Rep, Indent0, #{encoding:=Enc,depth:=Depth,
+ chars_limit:=Limit,single_line:=Single}) ->
+ {P,Tl} = p(Enc,Depth),
+ {Indent,Width} = if Single -> {"","0"};
+ true -> {Indent0,""}
+ end,
+ Opts = if is_integer(Limit) -> [{chars_limit,Limit}];
+ true -> []
+ end,
+ io_lib:format("~s~"++Width++P, [Indent, Rep | Tl], Opts).
format_rep([{initial_call,InitialCall}|Rep], Indent, Extra) ->
[format_mfa(Indent, InitialCall, Extra)|format_rep(Rep, Indent, Extra)];
@@ -818,19 +834,32 @@ format_rep([{Tag,Data}|Rep], Indent, Extra) ->
format_rep(_, _, _Extra) ->
[].
-format_exception(Class, Reason, StackTrace, #{encoding:=Enc}=Extra) ->
+format_exception(Class, Reason, StackTrace,
+ #{encoding:=Enc,depth:=Depth,chars_limit:=Limit,
+ single_line:=Single}=Extra) ->
PF = pp_fun(Extra),
StackFun = fun(M, _F, _A) -> (M =:= erl_eval) or (M =:= ?MODULE) end,
- %% EI = " exception: ",
- EI = " ",
- [EI, erl_error:format_exception(1+length(EI), Class, Reason,
- StackTrace, StackFun, PF, Enc), "\n"].
+ if Single ->
+ {P,Tl} = p(Enc,Depth),
+ Opts = if is_integer(Limit) -> [{chars_limit,Limit}];
+ true -> []
+ end,
+ [atom_to_list(Class), ": ",
+ io_lib:format("~0"++P,[{Reason,StackTrace}|Tl],Opts)];
+ true ->
+ EI = " ",
+ [EI, erl_error:format_exception(1+length(EI), Class, Reason,
+ StackTrace, StackFun, PF, Enc)]
+ end.
-format_mfa(Indent, {M,F,Args}=StartF, #{encoding:=Enc}=Extra) ->
+format_mfa(Indent0, {M,F,Args}=StartF, #{encoding:=Enc,single_line:=Single}=Extra) ->
+ Indent = if Single -> "";
+ true -> Indent0
+ end,
try
A = length(Args),
[Indent,"initial call: ",atom_to_list(M),$:,to_string(F, Enc),$/,
- integer_to_list(A),"\n"]
+ integer_to_list(A)]
catch
error:_ ->
format_tag(Indent, initial_call, StartF, Extra)
@@ -841,21 +870,29 @@ to_string(A, latin1) ->
to_string(A, _) ->
io_lib:write_atom(A).
-pp_fun(#{encoding:=Enc,depth:=Depth,chars_limit:=Limit}) ->
+pp_fun(#{encoding:=Enc,depth:=Depth,chars_limit:=Limit,single_line:=Single}) ->
{P,Tl} = p(Enc, Depth),
+ Width = if Single -> "0";
+ true -> ""
+ end,
Opts = if is_integer(Limit) -> [{chars_limit,Limit}];
true -> []
end,
fun(Term, I) ->
- io_lib:format("~." ++ integer_to_list(I) ++ P, [Term|Tl], Opts)
+ io_lib:format("~" ++ Width ++ "." ++ integer_to_list(I) ++ P,
+ [Term|Tl], Opts)
end.
-format_tag(Indent, Tag, Data, #{encoding:=Enc,depth:=Depth,chars_limit:=Limit}) ->
+format_tag(Indent0, Tag, Data, #{encoding:=Enc,depth:=Depth,chars_limit:=Limit,single_line:=Single}) ->
{P,Tl} = p(Enc, Depth),
+ {Indent,Width} = if Single -> {"","0"};
+ true -> {Indent0,""}
+ end,
Opts = if is_integer(Limit) -> [{chars_limit,Limit}];
true -> []
end,
- io_lib:format("~s~p: ~80.18" ++ P ++ "\n", [Indent, Tag, Data|Tl], Opts).
+ io_lib:format("~s~" ++ Width ++ "p: ~" ++ Width ++ ".18" ++ P,
+ [Indent, Tag, Data|Tl], Opts).
p(Encoding, Depth) ->
{Letter, Tl} = case Depth of
@@ -868,6 +905,8 @@ p(Encoding, Depth) ->
modifier(latin1) -> "";
modifier(_) -> "t".
+nl(true,Else) -> Else;
+nl(false,_) -> "\n".
%%% -----------------------------------------------------------
%%% Stop a process and wait for it to terminate
diff --git a/lib/stdlib/src/rand.erl b/lib/stdlib/src/rand.erl
index 4951dc727b..9854c778a1 100644
--- a/lib/stdlib/src/rand.erl
+++ b/lib/stdlib/src/rand.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -32,14 +32,20 @@
uniform/0, uniform/1, uniform_s/1, uniform_s/2,
uniform_real/0, uniform_real_s/1,
jump/0, jump/1,
- normal/0, normal/2, normal_s/1, normal_s/3
+ normal/0, normal/2, normal_s/1, normal_s/3
]).
+%% Test, dev and internal
+-export([exro928_jump_2pow512/1, exro928_jump_2pow20/1,
+ exro928_seed/1, exro928_next/1, exro928_next_state/1,
+ format_jumpconst58/1, seed58/2]).
+
%% Debug
-export([make_float/3, float2str/1, bc64/1]).
-compile({inline, [exs64_next/1, exsplus_next/1,
exs1024_next/1, exs1024_calc/2,
+ exro928_next_state/4,
exrop_next/1, exrop_next_s/2,
get_52/1, normal_kiwi/1]}).
@@ -80,8 +86,8 @@
%% This depends on the algorithm handler function
-type alg_state() ::
- exs64_state() | exsplus_state() | exs1024_state() |
- exrop_state() | term().
+ exrop_state() | exs1024_state() | exro928_state() | exsplus_state() |
+ exs64_state() | term().
%% This is the algorithm handling definition within this module,
%% and the type to use for plugins.
@@ -124,14 +130,17 @@
%% Algorithm state
-type state() :: {alg_handler(), alg_state()}.
--type builtin_alg() :: exs64 | exsplus | exsp | exs1024 | exs1024s | exrop.
+-type builtin_alg() ::
+ exrop | exs1024s | exro928ss | exsp | exs64 | exsplus | exs1024.
-type alg() :: builtin_alg() | atom().
-type export_state() :: {alg(), alg_state()}.
+-type seed() :: [integer()] | integer() | {integer(), integer(), integer()}.
-export_type(
[builtin_alg/0, alg/0, alg_handler/0, alg_state/0,
- state/0, export_state/0]).
+ state/0, export_state/0, seed/0]).
-export_type(
- [exs64_state/0, exsplus_state/0, exs1024_state/0, exrop_state/0]).
+ [exrop_state/0, exs1024_state/0, exro928_state/0, exsplus_state/0,
+ exs64_state/0]).
%% =====================================================================
%% Range macro and helper
@@ -229,12 +238,12 @@ export_seed() ->
end.
-spec export_seed_s(State :: state()) -> export_state().
-export_seed_s({#{type:=Alg}, Seed}) -> {Alg, Seed}.
+export_seed_s({#{type:=Alg}, AlgState}) -> {Alg, AlgState}.
%% seed(Alg) seeds RNG with runtime dependent values
%% and return the NEW state
-%% seed({Alg,Seed}) setup RNG with a previously exported seed
+%% seed({Alg,AlgState}) setup RNG with a previously exported seed
%% and return the NEW state
-spec seed(
@@ -246,11 +255,11 @@ seed(Alg) ->
-spec seed_s(
AlgOrStateOrExpState :: builtin_alg() | state() | export_state()) ->
state().
-seed_s({AlgHandler, _Seed} = State) when is_map(AlgHandler) ->
+seed_s({AlgHandler, _AlgState} = State) when is_map(AlgHandler) ->
State;
-seed_s({Alg0, Seed}) ->
- {Alg,_SeedFun} = mk_alg(Alg0),
- {Alg, Seed};
+seed_s({Alg, AlgState}) when is_atom(Alg) ->
+ {AlgHandler,_SeedFun} = mk_alg(Alg),
+ {AlgHandler,AlgState};
seed_s(Alg) ->
seed_s(Alg, {erlang:phash2([{node(),self()}]),
erlang:system_time(),
@@ -259,19 +268,15 @@ seed_s(Alg) ->
%% seed/2: seeds RNG with the algorithm and given values
%% and returns the NEW state.
--spec seed(
- Alg :: builtin_alg(), Seed :: {integer(), integer(), integer()}) ->
- state().
-seed(Alg0, S0) ->
- seed_put(seed_s(Alg0, S0)).
+-spec seed(Alg :: builtin_alg(), Seed :: seed()) -> state().
+seed(Alg, Seed) ->
+ seed_put(seed_s(Alg, Seed)).
--spec seed_s(
- Alg :: builtin_alg(), Seed :: {integer(), integer(), integer()}) ->
- state().
-seed_s(Alg0, S0 = {_, _, _}) ->
- {Alg, Seed} = mk_alg(Alg0),
- AS = Seed(S0),
- {Alg, AS}.
+-spec seed_s(Alg :: builtin_alg(), Seed :: seed()) -> state().
+seed_s(Alg, Seed) ->
+ {AlgHandler,SeedFun} = mk_alg(Alg),
+ AlgState = SeedFun(Seed),
+ {AlgHandler,AlgState}.
%%% uniform/0, uniform/1, uniform_s/1, uniform_s/2 are all
%%% uniformly distributed random numbers.
@@ -281,8 +286,8 @@ seed_s(Alg0, S0 = {_, _, _}) ->
-spec uniform() -> X :: float().
uniform() ->
- {X, Seed} = uniform_s(seed_get()),
- _ = seed_put(Seed),
+ {X, State} = uniform_s(seed_get()),
+ _ = seed_put(State),
X.
%% uniform/1: given an integer N >= 1,
@@ -291,8 +296,8 @@ uniform() ->
-spec uniform(N :: pos_integer()) -> X :: pos_integer().
uniform(N) ->
- {X, Seed} = uniform_s(N, seed_get()),
- _ = seed_put(Seed),
+ {X, State} = uniform_s(N, seed_get()),
+ _ = seed_put(State),
X.
%% uniform_s/1: given a state, uniform_s/1
@@ -625,7 +630,13 @@ mk_alg(exrop) ->
{#{type=>exrop, bits=>58, weak_low_bits=>1, next=>fun exrop_next/1,
uniform=>fun exrop_uniform/1, uniform_n=>fun exrop_uniform/2,
jump=>fun exrop_jump/1},
- fun exrop_seed/1}.
+ fun exrop_seed/1};
+mk_alg(exro928ss) ->
+ {#{type=>exro928ss, bits=>58, next=>fun exro928ss_next/1,
+ uniform=>fun exro928ss_uniform/1,
+ uniform_n=>fun exro928ss_uniform/2,
+ jump=>fun exro928_jump/1},
+ fun exro928_seed/1}.
%% =====================================================================
%% exs64 PRNG: Xorshift64*
@@ -635,6 +646,14 @@ mk_alg(exrop) ->
-opaque exs64_state() :: uint64().
+exs64_seed(L) when is_list(L) ->
+ [R] = seed64_nz(1, L),
+ R;
+exs64_seed(A) when is_integer(A) ->
+ [R] = seed64(1, ?MASK(64, A)),
+ R;
+%%
+%% Traditional integer triplet seed
exs64_seed({A1, A2, A3}) ->
{V1, _} = exs64_next((?MASK(32, A1) * 4294967197 + 1)),
{V2, _} = exs64_next((?MASK(32, A2) * 4294967231 + 1)),
@@ -661,6 +680,14 @@ exs64_next(R) ->
-dialyzer({no_improper_lists, exsplus_seed/1}).
+exsplus_seed(L) when is_list(L) ->
+ [S0,S1] = seed58_nz(2, L),
+ [S0|S1];
+exsplus_seed(X) when is_integer(X) ->
+ [S0,S1] = seed58(2, ?MASK(64, X)),
+ [S0|S1];
+%%
+%% Traditional integer triplet seed
exsplus_seed({A1, A2, A3}) ->
{_, R1} = exsplus_next(
[?MASK(58, (A1 * 4294967197) + 1)|
@@ -708,7 +735,8 @@ exsp_uniform(Range, {Alg, R}) ->
-define(JUMPELEMLEN, 58).
-dialyzer({no_improper_lists, exsplus_jump/1}).
--spec exsplus_jump(state()) -> state().
+-spec exsplus_jump({alg_handler(), exsplus_state()}) ->
+ {alg_handler(), exsplus_state()}.
exsplus_jump({Alg, S}) ->
{S1, AS1} = exsplus_jump(S, [0|0], ?JUMPCONST1, ?JUMPELEMLEN),
{_, AS2} = exsplus_jump(S1, AS1, ?JUMPCONST2, ?JUMPELEMLEN),
@@ -735,6 +763,12 @@ exsplus_jump(S, [AS0|AS1], J, N) ->
-opaque exs1024_state() :: {list(uint64()), list(uint64())}.
+exs1024_seed(L) when is_list(L) ->
+ {seed64_nz(16, L), []};
+exs1024_seed(X) when is_integer(X) ->
+ {seed64(16, ?MASK(64, X)), []};
+%%
+%% Seed from traditional triple, remain backwards compatible
exs1024_seed({A1, A2, A3}) ->
B1 = ?MASK(21, (?MASK(21, A1) + 1) * 2097131),
B2 = ?MASK(21, (?MASK(21, A2) + 1) * 2097133),
@@ -806,8 +840,8 @@ exs1024_next({[H], RL}) ->
-define(JUMPTOTALLEN, 1024).
-define(RINGLEN, 16).
--spec exs1024_jump(state()) -> state().
-
+-spec exs1024_jump({alg_handler(), exs1024_state()}) ->
+ {alg_handler(), exs1024_state()}.
exs1024_jump({Alg, {L, RL}}) ->
P = length(RL),
AS = exs1024_jump({L, RL},
@@ -832,6 +866,194 @@ exs1024_jump({L, RL}, AS, JL, J, N, TN) ->
end.
%% =====================================================================
+%% exro928ss PRNG: Xoroshiro928**
+%%
+%% Reference URL: http://vigna.di.unimi.it/ftp/papers/ScrambledLinear.pdf
+%% i.e the Xoroshiro1024 generator with ** scrambler
+%% with {S, R, T} = {5, 7, 9} as recommended in the paper.
+%%
+%% {A, B, C} were tried out and selected as {44, 9, 45}
+%% and the jump coefficients calculated.
+%%
+%% Standard jump function pseudocode:
+%%
+%% Jump constant j = 0xb10773cb...44085302f77130ca
+%% Generator state: s
+%% New generator state: t = 0
+%% foreach bit in j, low to high:
+%% if the bit is one:
+%% t ^= s
+%% next s
+%% s = t
+%%
+%% Generator used for reference value calculation:
+%%
+%% #include <stdint.h>
+%% #include <stdio.h>
+%%
+%% int p = 0;
+%% uint64_t s[16];
+%%
+%% #define MASK(x) ((x) & ((UINT64_C(1) << 58) - 1))
+%% static __inline uint64_t rotl(uint64_t x, int n) {
+%% return MASK(x << n) | (x >> (58 - n));
+%% }
+%%
+%% uint64_t next() {
+%% const int q = p;
+%% const uint64_t s0 = s[p = (p + 1) & 15];
+%% uint64_t s15 = s[q];
+%%
+%% const uint64_t result_starstar = MASK(rotl(MASK(s0 * 5), 7) * 9);
+%%
+%% s15 ^= s0;
+%% s[q] = rotl(s0, 44) ^ s15 ^ MASK(s15 << 9);
+%% s[p] = rotl(s15, 45);
+%%
+%% return result_starstar;
+%% }
+%%
+%% static const uint64_t jump_2pow512[15] =
+%% { 0x44085302f77130ca, 0xba05381fdfd14902, 0x10a1de1d7d6813d2,
+%% 0xb83fe51a1eb3be19, 0xa81b0090567fd9f0, 0x5ac26d5d20f9b49f,
+%% 0x4ddd98ee4be41e01, 0x0657e19f00d4b358, 0xf02f778573cf0f0a,
+%% 0xb45a3a8a3cef3cc0, 0x6e62a33cc2323831, 0xbcb3b7c4cc049c53,
+%% 0x83f240c6007e76ce, 0xe19f5fc1a1504acd, 0x00000000b10773cb };
+%%
+%% static const uint64_t jump_2pow20[15] =
+%% { 0xbdb966a3daf905e6, 0x644807a56270cf78, 0xda90f4a806c17e9e,
+%% 0x4a426866bfad3c77, 0xaf699c306d8e7566, 0x8ebc73c700b8b091,
+%% 0xc081a7bf148531fb, 0xdc4d3af15f8a4dfd, 0x90627c014098f4b6,
+%% 0x06df2eb1feaf0fb6, 0x5bdeb1a5a90f2e6b, 0xa480c5878c3549bd,
+%% 0xff45ef33c82f3d48, 0xa30bebc15fefcc78, 0x00000000cb3d181c };
+%%
+%% void jump(const uint64_t *jump) {
+%% uint64_t j, t[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+%% int m, n, k;
+%% for (m = 0; m < 15; m++, jump++) {
+%% for (n = 0, j = *jump; n < 64; n++, j >>= 1) {
+%% if ((j & 1) != 0) {
+%% for (k = 0; k < 16; k++) {
+%% t[k] ^= s[(p + k) & 15];
+%% }
+%% }
+%% next();
+%% }
+%% }
+%% for (k = 0; k < 16; k++) {
+%% s[(p + k) & 15] = t[k];
+%% }
+%% }
+%%
+%% =====================================================================
+
+-opaque exro928_state() :: {list(uint58()), list(uint58())}.
+
+-spec exro928_seed(
+ list(uint58()) | integer() | {integer(), integer(), integer()}) ->
+ exro928_state().
+exro928_seed(L) when is_list(L) ->
+ {seed58_nz(16, L), []};
+exro928_seed(X) when is_integer(X) ->
+ {seed58(16, ?MASK(64, X)), []};
+%%
+%% Seed from traditional integer triple - mix into splitmix
+exro928_seed({A1, A2, A3}) ->
+ {S0, X0} = seed58(?MASK(64, A1)),
+ {S1, X1} = seed58(?MASK(64, A2) bxor X0),
+ {S2, X2} = seed58(?MASK(64, A3) bxor X1),
+ {[S0,S1,S2|seed58(13, X2)], []}.
+
+
+%% Update the state and calculate output word
+-spec exro928ss_next(exro928_state()) -> {uint58(), exro928_state()}.
+exro928ss_next({[S15,S0|Ss], Rs}) ->
+ SR = exro928_next_state(Ss, Rs, S15, S0),
+ %%
+ %% {S, R, T} = {5, 7, 9}
+ %% const uint64_t result_starstar = rotl(s0 * S, R) * T;
+ %%
+ %% The multiply by add shifted trick avoids creating bignums
+ %% which improves performance significantly
+ %%
+ V0 = ?MASK(58, S0 + ?BSL(58, S0, 2)), % V0 = S0 * 5
+ V1 = ?ROTL(58, V0, 7),
+ V = ?MASK(58, V1 + ?BSL(58, V1, 3)), % V = V1 * 9
+ {V, SR};
+exro928ss_next({[S15], Rs}) ->
+ exro928ss_next({[S15|lists:reverse(Rs)], []}).
+
+-spec exro928_next(exro928_state()) -> {{uint58(),uint58()}, exro928_state()}.
+exro928_next({[S15,S0|Ss], Rs}) ->
+ SR = exro928_next_state(Ss, Rs, S15, S0),
+ {{S15,S0}, SR};
+exro928_next({[S15], Rs}) ->
+ exro928_next({[S15|lists:reverse(Rs)], []}).
+
+%% Just update the state
+-spec exro928_next_state(exro928_state()) -> exro928_state().
+exro928_next_state({[S15,S0|Ss], Rs}) ->
+ exro928_next_state(Ss, Rs, S15, S0);
+exro928_next_state({[S15], Rs}) ->
+ [S0|Ss] = lists:reverse(Rs),
+ exro928_next_state(Ss, [], S15, S0).
+
+exro928_next_state(Ss, Rs, S15, S0) ->
+ %% {A, B, C} = {44, 9, 45},
+ %% s15 ^= s0;
+ %% NewS15: s[q] = rotl(s0, A) ^ s15 ^ (s15 << B);
+ %% NewS0: s[p] = rotl(s15, C);
+ %%
+ Q = S15 bxor S0,
+ NewS15 = ?ROTL(58, S0, 44) bxor Q bxor ?BSL(58, Q, 9),
+ NewS0 = ?ROTL(58, Q, 45),
+ {[NewS0|Ss], [NewS15|Rs]}.
+
+
+exro928ss_uniform({Alg, SR}) ->
+ {V, NewSR} = exro928ss_next(SR),
+ {(V bsr (58-53)) * ?TWO_POW_MINUS53, {Alg, NewSR}}.
+
+exro928ss_uniform(Range, {Alg, SR}) ->
+ {V, NewSR} = exro928ss_next(SR),
+ MaxMinusRange = ?BIT(58) - Range,
+ ?uniform_range(Range, Alg, NewSR, V, MaxMinusRange, I).
+
+
+-spec exro928_jump({alg_handler(), exro928_state()}) ->
+ {alg_handler(), exro928_state()}.
+exro928_jump({Alg, SR}) ->
+ {Alg,exro928_jump_2pow512(SR)}.
+
+-spec exro928_jump_2pow512(exro928_state()) -> exro928_state().
+exro928_jump_2pow512(SR) ->
+ polyjump(
+ SR, fun exro928_next_state/1,
+ %% 2^512
+ [16#4085302F77130CA, 16#54E07F7F4524091,
+ 16#5E1D7D6813D2BA0, 16#4687ACEF8644287,
+ 16#4567FD9F0B83FE5, 16#43E6D27EA06C024,
+ 16#641E015AC26D5D2, 16#6CD61377663B92F,
+ 16#70A0657E19F00D4, 16#43C0BDDE15CF3C3,
+ 16#745A3A8A3CEF3CC, 16#58A8CF308C8E0C6,
+ 16#7B7C4CC049C536E, 16#431801F9DB3AF2C,
+ 16#41A1504ACD83F24, 16#6C41DCF2F867D7F]).
+
+-spec exro928_jump_2pow20(exro928_state()) -> exro928_state().
+exro928_jump_2pow20(SR) ->
+ polyjump(
+ SR, fun exro928_next_state/1,
+ %% 2^20
+ [16#5B966A3DAF905E6, 16#601E9589C33DE2F,
+ 16#74A806C17E9E644, 16#59AFEB4F1DF6A43,
+ 16#46D8E75664A4268, 16#42E2C246BDA670C,
+ 16#4531FB8EBC73C70, 16#537F702069EFC52,
+ 16#4B6DC4D3AF15F8A, 16#5A4189F0050263D,
+ 16#46DF2EB1FEAF0FB, 16#77AC696A43CB9AC,
+ 16#4C5878C3549BD5B, 16#7CCF20BCF522920,
+ 16#415FEFCC78FF45E, 16#72CF460728C2FAF]).
+
+%% =====================================================================
%% exrop PRNG: Xoroshiro116+
%%
%% Reference URL: http://xorshift.di.unimi.it/
@@ -899,6 +1121,15 @@ exs1024_jump({L, RL}, AS, JL, J, N, TN) ->
-opaque exrop_state() :: nonempty_improper_list(uint58(), uint58()).
-dialyzer({no_improper_lists, exrop_seed/1}).
+
+exrop_seed(L) when is_list(L) ->
+ [S0,S1] = seed58_nz(2, L),
+ [S0|S1];
+exrop_seed(X) when is_integer(X) ->
+ [S0,S1] = seed58(2, ?MASK(64, X)),
+ [S0|S1];
+%%
+%% Traditional integer triplet seed
exrop_seed({A1, A2, A3}) ->
[_|S1] =
exrop_next_s(
@@ -962,6 +1193,142 @@ exrop_jump([S__0|S__1] = _S, S0, S1, J, Js) ->
end.
%% =====================================================================
+%% Mask and fill state list, ensure not all zeros
+%% =====================================================================
+
+seed58_nz(N, Ss) ->
+ seed_nz(N, Ss, 58, false).
+
+seed64_nz(N, Ss) ->
+ seed_nz(N, Ss, 64, false).
+
+seed_nz(_N, [], _M, false) ->
+ erlang:error(zero_seed);
+seed_nz(0, [_|_], _M, _NZ) ->
+ erlang:error(too_many_seed_integers);
+seed_nz(0, [], _M, _NZ) ->
+ [];
+seed_nz(N, [], M, true) ->
+ [0|seed_nz(N - 1, [], M, true)];
+seed_nz(N, [S|Ss], M, NZ) ->
+ if
+ is_integer(S) ->
+ R = ?MASK(M, S),
+ [R|seed_nz(N - 1, Ss, M, NZ orelse R =/= 0)];
+ true ->
+ erlang:error(non_integer_seed)
+ end.
+
+%% =====================================================================
+%% Splitmix seeders, lowest bits of SplitMix64, zeros skipped
+%% =====================================================================
+
+-spec seed58(non_neg_integer(), uint64()) -> list(uint58()).
+seed58(0, _X) ->
+ [];
+seed58(N, X) ->
+ {Z,NewX} = seed58(X),
+ [Z|seed58(N - 1, NewX)].
+%%
+seed58(X_0) ->
+ {Z0,X} = splitmix64_next(X_0),
+ case ?MASK(58, Z0) of
+ 0 ->
+ seed58(X);
+ Z ->
+ {Z,X}
+ end.
+
+-spec seed64(non_neg_integer(), uint64()) -> list(uint64()).
+seed64(0, _X) ->
+ [];
+seed64(N, X) ->
+ {Z,NewX} = seed64(X),
+ [Z|seed64(N - 1, NewX)].
+%%
+seed64(X_0) ->
+ {Z,X} = ZX = splitmix64_next(X_0),
+ if
+ Z =:= 0 ->
+ seed64(X);
+ true ->
+ ZX
+ end.
+
+%% The SplitMix64 generator:
+%%
+%% uint64_t splitmix64_next() {
+%% uint64_t z = (x += 0x9e3779b97f4a7c15);
+%% z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
+%% z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
+%% return z ^ (z >> 31);
+%% }
+%%
+splitmix64_next(X_0) ->
+ X = ?MASK(64, X_0 + 16#9e3779b97f4a7c15),
+ Z_0 = ?MASK(64, (X bxor (X bsr 30)) * 16#bf58476d1ce4e5b9),
+ Z_1 = ?MASK(64, (Z_0 bxor (Z_0 bsr 27)) * 16#94d049bb133111eb),
+ {?MASK(64, Z_1 bxor (Z_1 bsr 31)),X}.
+
+%% =====================================================================
+%% Polynomial jump with a jump constant word list,
+%% high bit in each word marking top of word,
+%% SR is a {Forward, Reverse} queue tuple with Forward never empty
+%% =====================================================================
+
+polyjump({Ss, Rs} = SR, NextState, JumpConst) ->
+ %% Create new state accumulator T
+ Ts = lists:duplicate(length(Ss) + length(Rs), 0),
+ polyjump(SR, NextState, JumpConst, Ts).
+%%
+%% Foreach jump word
+polyjump(_SR, _NextState, [], Ts) ->
+ %% Return new calculated state
+ {Ts, []};
+polyjump(SR, NextState, [J|Js], Ts) ->
+ polyjump(SR, NextState, Js, Ts, J).
+%%
+%% Foreach bit in jump word until top bit
+polyjump(SR, NextState, Js, Ts, 1) ->
+ polyjump(SR, NextState, Js, Ts);
+polyjump({Ss, Rs} = SR, NextState, Js, Ts, J) when J =/= 0 ->
+ NewSR = NextState(SR),
+ NewJ = J bsr 1,
+ case ?MASK(1, J) of
+ 0 ->
+ polyjump(NewSR, NextState, Js, Ts, NewJ);
+ 1 ->
+ %% Xor this state onto T
+ polyjump(NewSR, NextState, Js, xorzip_sr(Ts, Ss, Rs), NewJ)
+ end.
+
+xorzip_sr([], [], undefined) ->
+ [];
+xorzip_sr(Ts, [], Rs) ->
+ xorzip_sr(Ts, lists:reverse(Rs), undefined);
+xorzip_sr([T|Ts], [S|Ss], Rs) ->
+ [T bxor S|xorzip_sr(Ts, Ss, Rs)].
+
+%% =====================================================================
+
+format_jumpconst58(String) ->
+ ReOpts = [{newline,any},{capture,all_but_first,binary},global],
+ {match,Matches} = re:run(String, "0x([a-zA-Z0-9]+)", ReOpts),
+ format_jumcons58_matches(lists:reverse(Matches), 0).
+
+format_jumcons58_matches([], J) ->
+ format_jumpconst58_value(J);
+format_jumcons58_matches([[Bin]|Matches], J) ->
+ NewJ = (J bsl 64) bor binary_to_integer(Bin, 16),
+ format_jumcons58_matches(Matches, NewJ).
+
+format_jumpconst58_value(0) ->
+ ok;
+format_jumpconst58_value(J) ->
+ io:format("16#~s,~n", [integer_to_list(?MASK(58, J) bor ?BIT(58), 16)]),
+ format_jumpconst58_value(J bsr 58).
+
+%% =====================================================================
%% Ziggurat cont
%% =====================================================================
-define(NOR_R, 3.6541528853610087963519472518).
diff --git a/lib/stdlib/test/beam_lib_SUITE.erl b/lib/stdlib/test/beam_lib_SUITE.erl
index 3597d6d94b..6418dc7eb6 100644
--- a/lib/stdlib/test/beam_lib_SUITE.erl
+++ b/lib/stdlib/test/beam_lib_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2017. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/stdlib/test/dets_SUITE.erl b/lib/stdlib/test/dets_SUITE.erl
index fe324391af..65977a764a 100644
--- a/lib/stdlib/test/dets_SUITE.erl
+++ b/lib/stdlib/test/dets_SUITE.erl
@@ -3417,6 +3417,7 @@ otp_11709(Config) when is_list(Config) ->
ok.
%% OTP-13229. open_file() exits with badarg when given binary file name.
+%% Also OTP-15253.
otp_13229(_Config) ->
F = <<"binfile.tab">>,
try dets:open_file(name, [{file, F}]) of
@@ -3425,6 +3426,20 @@ otp_13229(_Config) ->
catch
error:badarg ->
ok
+ end,
+ try dets:open_file(F, []) of % OTP-15253
+ R2 ->
+ exit({open_succeeded, R2})
+ catch
+ error:badarg ->
+ ok
+ end,
+ try dets:open_file(F) of
+ R3 ->
+ exit({open_succeeded, R3})
+ catch
+ error:badarg ->
+ ok
end.
%% OTP-13260. Race when opening a table.
diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl
index fee8b204f4..8940f0b58c 100644
--- a/lib/stdlib/test/ets_SUITE.erl
+++ b/lib/stdlib/test/ets_SUITE.erl
@@ -66,7 +66,8 @@
meta_lookup_named_read/1, meta_lookup_named_write/1,
meta_newdel_unnamed/1, meta_newdel_named/1]).
-export([smp_insert/1, smp_fixed_delete/1, smp_unfix_fix/1, smp_select_delete/1,
- smp_select_replace/1, otp_8166/1, otp_8732/1]).
+ smp_select_replace/1, otp_8166/1, otp_8732/1, delete_unfix_race/1]).
+-export([throughput_benchmark/0, test_throughput_benchmark/1]).
-export([exit_large_table_owner/1,
exit_many_large_table_owner/1,
exit_many_tables_owner/1,
@@ -142,7 +143,9 @@ all() ->
ets_all,
massive_ets_all,
take,
- whereis_table].
+ whereis_table,
+ delete_unfix_race,
+ test_throughput_benchmark].
groups() ->
[{new, [],
@@ -741,7 +744,7 @@ select_bound_chunk(_Config) ->
repeat_for_opts(fun select_bound_chunk_do/1, [all_types]).
select_bound_chunk_do(Opts) ->
- T = ets:new(x, Opts),
+ T = ets_new(x, Opts),
ets:insert(T, [{key, 1}]),
{[{key, 1}], '$end_of_table'} = ets:select(T, [{{key,1},[],['$_']}], 100000),
ok.
@@ -787,7 +790,7 @@ check_badarg({'EXIT', {badarg, [{M,F,A,_} | _]}}, M, F, Args) ->
%% Test ets:delete_all_objects/1.
t_delete_all_objects(Config) when is_list(Config) ->
EtsMem = etsmem(),
- repeat_for_opts(fun t_delete_all_objects_do/1),
+ repeat_for_opts_all_set_table_types(fun t_delete_all_objects_do/1),
verify_etsmem(EtsMem).
get_kept_objects(T) ->
@@ -807,7 +810,10 @@ t_delete_all_objects_do(Opts) ->
true = ets:delete_all_objects(T),
'$end_of_table' = ets:next(T,O),
0 = ets:info(T,size),
- 4000 = get_kept_objects(T),
+ case ets:info(T,type) of
+ ordered_set -> ok;
+ _ -> 4000 = get_kept_objects(T)
+ end,
ets:safe_fixtable(T,false),
0 = ets:info(T,size),
0 = get_kept_objects(T),
@@ -818,7 +824,7 @@ t_delete_all_objects_do(Opts) ->
ets:delete(T),
%% Test delete_all_objects is atomic
- T2 = ets:new(t_delete_all_objects, [public | Opts]),
+ T2 = ets_new(t_delete_all_objects, [public | Opts]),
Self = self(),
Inserters = [spawn_link(fun() -> inserter(T2, 100*1000, 1, Self) end) || _ <- [1,2,3,4]],
[receive {Ipid, running} -> ok end || Ipid <- Inserters],
@@ -2351,17 +2357,29 @@ write_concurrency(Config) when is_list(Config) ->
Yes6 = ets_new(foo,[duplicate_bag,protected,{write_concurrency,true}]),
No3 = ets_new(foo,[duplicate_bag,private,{write_concurrency,true}]),
- No4 = ets_new(foo,[ordered_set,public,{write_concurrency,true}]),
- No5 = ets_new(foo,[ordered_set,protected,{write_concurrency,true}]),
- No6 = ets_new(foo,[ordered_set,private,{write_concurrency,true}]),
-
- No7 = ets_new(foo,[public,{write_concurrency,false}]),
- No8 = ets_new(foo,[protected,{write_concurrency,false}]),
+ Yes7 = ets_new(foo,[ordered_set,public,{write_concurrency,true}]),
+ Yes8 = ets_new(foo,[ordered_set,protected,{write_concurrency,true}]),
+ Yes9 = ets_new(foo,[ordered_set,{write_concurrency,true}]),
+ Yes10 = ets_new(foo,[{write_concurrency,true},ordered_set,public]),
+ Yes11 = ets_new(foo,[{write_concurrency,true},ordered_set,protected]),
+ Yes12 = ets_new(foo,[set,{write_concurrency,false},
+ {write_concurrency,true},ordered_set,public]),
+ Yes13 = ets_new(foo,[private,public,set,{write_concurrency,false},
+ {write_concurrency,true},ordered_set]),
+ No4 = ets_new(foo,[ordered_set,private,{write_concurrency,true}]),
+ No5 = ets_new(foo,[ordered_set,public,{write_concurrency,false}]),
+ No6 = ets_new(foo,[ordered_set,protected,{write_concurrency,false}]),
+ No7 = ets_new(foo,[ordered_set,private,{write_concurrency,false}]),
+
+ No8 = ets_new(foo,[public,{write_concurrency,false}]),
+ No9 = ets_new(foo,[protected,{write_concurrency,false}]),
YesMem = ets:info(Yes1,memory),
NoHashMem = ets:info(No1,memory),
+ YesTreeMem = ets:info(Yes7,memory),
NoTreeMem = ets:info(No4,memory),
- io:format("YesMem=~p NoHashMem=~p NoTreeMem=~p\n",[YesMem,NoHashMem,NoTreeMem]),
+ io:format("YesMem=~p NoHashMem=~p NoTreeMem=~p YesTreeMem=~p\n",[YesMem,NoHashMem,
+ NoTreeMem,YesTreeMem]),
YesMem = ets:info(Yes2,memory),
YesMem = ets:info(Yes3,memory),
@@ -2370,13 +2388,24 @@ write_concurrency(Config) when is_list(Config) ->
YesMem = ets:info(Yes6,memory),
NoHashMem = ets:info(No2,memory),
NoHashMem = ets:info(No3,memory),
+ YesTreeMem = ets:info(Yes7,memory),
+ YesTreeMem = ets:info(Yes8,memory),
+ YesTreeMem = ets:info(Yes9,memory),
+ YesTreeMem = ets:info(Yes10,memory),
+ YesTreeMem = ets:info(Yes11,memory),
+ YesTreeMem = ets:info(Yes12,memory),
+ YesTreeMem = ets:info(Yes13,memory),
+ NoTreeMem = ets:info(No4,memory),
NoTreeMem = ets:info(No5,memory),
NoTreeMem = ets:info(No6,memory),
- NoHashMem = ets:info(No7,memory),
+ NoTreeMem = ets:info(No7,memory),
NoHashMem = ets:info(No8,memory),
+ NoHashMem = ets:info(No9,memory),
true = YesMem > NoHashMem,
true = YesMem > NoTreeMem,
+ true = YesMem > YesTreeMem,
+ true = YesTreeMem < NoTreeMem,
{'EXIT',{badarg,_}} = (catch ets_new(foo,[public,{write_concurrency,foo}])),
{'EXIT',{badarg,_}} = (catch ets_new(foo,[public,{write_concurrency}])),
@@ -2384,8 +2413,8 @@ write_concurrency(Config) when is_list(Config) ->
{'EXIT',{badarg,_}} = (catch ets_new(foo,[public,write_concurrency])),
lists:foreach(fun(T) -> ets:delete(T) end,
- [Yes1,Yes2,Yes3,Yes4,Yes5,Yes6,
- No1,No2,No3,No4,No5,No6,No7,No8]),
+ [Yes1,Yes2,Yes3,Yes4,Yes5,Yes6,Yes7,Yes8,Yes9,Yes10,Yes11,Yes12,Yes13,
+ No1,No2,No3,No4,No5,No6,No7,No8,No9]),
verify_etsmem(EtsMem),
ok.
@@ -3030,24 +3059,26 @@ pick_all_backwards(T) ->
%% Small test case for both set and bag type ets tables.
setbag(Config) when is_list(Config) ->
EtsMem = etsmem(),
- Set = ets_new(set,[set]),
- Bag = ets_new(bag,[bag]),
- Key = {foo,bar},
-
- %% insert some value
- ets:insert(Set,{Key,val1}),
- ets:insert(Bag,{Key,val1}),
-
- %% insert new value for same key again
- ets:insert(Set,{Key,val2}),
- ets:insert(Bag,{Key,val2}),
-
- %% check
- [{Key,val2}] = ets:lookup(Set,Key),
- [{Key,val1},{Key,val2}] = ets:lookup(Bag,Key),
-
- true = ets:delete(Set),
- true = ets:delete(Bag),
+ lists:foreach(fun(SetType) ->
+ Set = ets_new(SetType,[SetType]),
+ Bag = ets_new(bag,[bag]),
+ Key = {foo,bar},
+
+ %% insert some value
+ ets:insert(Set,{Key,val1}),
+ ets:insert(Bag,{Key,val1}),
+
+ %% insert new value for same key again
+ ets:insert(Set,{Key,val2}),
+ ets:insert(Bag,{Key,val2}),
+
+ %% check
+ [{Key,val2}] = ets:lookup(Set,Key),
+ [{Key,val1},{Key,val2}] = ets:lookup(Bag,Key),
+
+ true = ets:delete(Set),
+ true = ets:delete(Bag)
+ end, [set, cat_ord_set,stim_cat_ord_set,ordered_set]),
verify_etsmem(EtsMem).
%% Test case to check proper return values for illegal ets_new() calls.
@@ -3080,11 +3111,13 @@ named(Config) when is_list(Config) ->
%% Test case to check if specified keypos works.
keypos2(Config) when is_list(Config) ->
EtsMem = etsmem(),
- Tab = make_table(foo,
- [set,{keypos,2}],
- [{val,key}, {val2,key}]),
- [{val2,key}] = ets:lookup(Tab,key),
- true = ets:delete(Tab),
+ lists:foreach(fun(SetType) ->
+ Tab = make_table(foo,
+ [SetType,{keypos,2}],
+ [{val,key}, {val2,key}]),
+ [{val2,key}] = ets:lookup(Tab,key),
+ true = ets:delete(Tab)
+ end, [set, cat_ord_set,stim_cat_ord_set,ordered_set]),
verify_etsmem(EtsMem).
%% Privacy check. Check that a named(public/private/protected) table
@@ -3176,7 +3209,7 @@ rotate_tuple(Tuple, N) ->
%% Check lookup in an empty table and lookup of a non-existing key.
empty(Config) when is_list(Config) ->
- repeat_for_opts(fun empty_do/1).
+ repeat_for_opts_all_table_types(fun empty_do/1).
empty_do(Opts) ->
EtsMem = etsmem(),
@@ -3189,7 +3222,7 @@ empty_do(Opts) ->
%% Check proper return values for illegal insert operations.
badinsert(Config) when is_list(Config) ->
- repeat_for_opts(fun badinsert_do/1).
+ repeat_for_opts_all_table_types(fun badinsert_do/1).
badinsert_do(Opts) ->
EtsMem = etsmem(),
@@ -3213,7 +3246,7 @@ badinsert_do(Opts) ->
time_lookup(Config) when is_list(Config) ->
%% just for timing, really
EtsMem = etsmem(),
- Values = repeat_for_opts(fun time_lookup_do/1),
+ Values = repeat_for_opts_all_table_types(fun time_lookup_do/1),
verify_etsmem(EtsMem),
{comment,lists:flatten(io_lib:format(
"~p ets lookups/s",[Values]))}.
@@ -3410,7 +3443,7 @@ delete_tab_do(Opts) ->
%% Check that ets:delete/1 works and that other processes can run.
delete_large_tab(Config) when is_list(Config) ->
- ct:timetrap({minutes,30}), %% valgrind needs a lot
+ ct:timetrap({minutes,60}), %% valgrind needs a lot
Data = [{erlang:phash2(I, 16#ffffff),I} || I <- lists:seq(1, 200000)],
EtsMem = etsmem(),
repeat_for_opts(fun(Opts) -> delete_large_tab_do(Opts,Data) end),
@@ -3419,7 +3452,8 @@ delete_large_tab(Config) when is_list(Config) ->
delete_large_tab_do(Opts,Data) ->
delete_large_tab_1(foo_hash, Opts, Data, false),
delete_large_tab_1(foo_tree, [ordered_set | Opts], Data, false),
- delete_large_tab_1(foo_hash, Opts, Data, true).
+ delete_large_tab_1(foo_tree, [stim_cat_ord_set | Opts], Data, false),
+ delete_large_tab_1(foo_hash_fix, Opts, Data, true).
delete_large_tab_1(Name, Flags, Data, Fix) ->
@@ -3490,6 +3524,7 @@ delete_large_named_table(Config) when is_list(Config) ->
delete_large_named_table_do(Opts,Data) ->
delete_large_named_table_1(foo_hash, [named_table | Opts], Data, false),
delete_large_named_table_1(foo_tree, [ordered_set,named_table | Opts], Data, false),
+ delete_large_named_table_1(foo_tree, [stim_cat_ord_set,named_table | Opts], Data, false),
delete_large_named_table_1(foo_hash, [named_table | Opts], Data, true).
delete_large_named_table_1(Name, Flags, Data, Fix) ->
@@ -3527,14 +3562,18 @@ evil_delete_do(Opts,Data) ->
verify_etsmem(EtsMem),
evil_delete_owner(foo_tree, [ordered_set | Opts], Data, false),
verify_etsmem(EtsMem),
+ evil_delete_owner(foo_catree, [stim_cat_ord_set | Opts], Data, false),
+ verify_etsmem(EtsMem),
TabA = evil_delete_not_owner(foo_hash, Opts, Data, false),
verify_etsmem(EtsMem),
TabB = evil_delete_not_owner(foo_hash, Opts, Data, true),
verify_etsmem(EtsMem),
TabC = evil_delete_not_owner(foo_tree, [ordered_set | Opts], Data, false),
verify_etsmem(EtsMem),
+ TabD = evil_delete_not_owner(foo_catree, [stim_cat_ord_set | Opts], Data, false),
+ verify_etsmem(EtsMem),
lists:foreach(fun(T) -> undefined = ets:info(T) end,
- [TabA,TabB,TabC]).
+ [TabA,TabB,TabC,TabD]).
evil_delete_not_owner(Name, Flags, Data, Fix) ->
io:format("Not owner: ~p, fix = ~p", [Name,Fix]),
@@ -3749,7 +3788,7 @@ verify_rescheduling_exit(Config, ForEachData, Flags, Fix, NOTabs, NOProcs) ->
%% Make sure that slots for ets tables are cleared properly.
table_leak(Config) when is_list(Config) ->
- repeat_for_opts(fun(Opts) -> table_leak_1(Opts,20000) end).
+ repeat_for_opts_all_non_stim_table_types(fun(Opts) -> table_leak_1(Opts,20000) end).
table_leak_1(_,0) -> ok;
table_leak_1(Opts,N) ->
@@ -3812,7 +3851,7 @@ match_delete3_do(Opts) ->
%% Test ets:first/1 & ets:next/2.
firstnext(Config) when is_list(Config) ->
- repeat_for_opts(fun firstnext_do/1).
+ repeat_for_opts_all_set_table_types(fun firstnext_do/1).
firstnext_do(Opts) ->
EtsMem = etsmem(),
@@ -3834,15 +3873,20 @@ firstnext_collect(Tab,Key,List) ->
%% Tests ets:first/1 & ets:next/2.
firstnext_concurrent(Config) when is_list(Config) ->
- register(master, self()),
- ets_init(?MODULE, 20),
- [dynamic_go() || _ <- lists:seq(1, 2)],
- receive
- after 5000 -> ok
- end.
+ lists:foreach(
+ fun(TableType) ->
+ register(master, self()),
+ TableName = list_to_atom(atom_to_list(?MODULE) ++ atom_to_list(TableType)),
+ ets_init(TableName, 20, TableType),
+ [dynamic_go(TableName) || _ <- lists:seq(1, 2)],
+ receive
+ after 5000 -> ok
+ end,
+ unregister(master)
+ end, repeat_for_opts_atom2list(ord_set_types)).
-ets_init(Tab, N) ->
- ets_new(Tab, [named_table,public,ordered_set]),
+ets_init(Tab, N, TableType) ->
+ ets_new(Tab, [named_table,public,TableType]),
cycle(Tab, lists:seq(1,N+1)).
cycle(_Tab, [H|T]) when H > length(T)-> ok;
@@ -3850,9 +3894,9 @@ cycle(Tab, L) ->
ets:insert(Tab,list_to_tuple(L)),
cycle(Tab, tl(L)++[hd(L)]).
-dynamic_go() -> my_spawn_link(fun dynamic_init/0).
+dynamic_go(TableName) -> my_spawn_link(fun() -> dynamic_init(TableName) end).
-dynamic_init() -> [dyn_lookup(?MODULE) || _ <- lists:seq(1, 10)].
+dynamic_init(TableName) -> [dyn_lookup(TableName) || _ <- lists:seq(1, 10)].
dyn_lookup(T) -> dyn_lookup(T, ets:first(T)).
@@ -3870,7 +3914,7 @@ dyn_lookup(T, K) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
slot(Config) when is_list(Config) ->
- repeat_for_opts(fun slot_do/1).
+ repeat_for_opts_all_set_table_types(fun slot_do/1).
slot_do(Opts) ->
EtsMem = etsmem(),
@@ -3895,7 +3939,7 @@ slot_loop(Tab,SlotNo,EltsSoFar) ->
match1(Config) when is_list(Config) ->
- repeat_for_opts(fun match1_do/1).
+ repeat_for_opts_all_set_table_types(fun match1_do/1).
match1_do(Opts) ->
EtsMem = etsmem(),
@@ -3958,7 +4002,7 @@ match2_do(Opts) ->
%% Some ets:match_object tests.
match_object(Config) when is_list(Config) ->
- repeat_for_opts(fun match_object_do/1).
+ repeat_for_opts_all_set_table_types(fun match_object_do/1).
match_object_do(Opts) ->
EtsMem = etsmem(),
@@ -4058,7 +4102,7 @@ match_object_do(Opts) ->
%% Tests that db_match_object does not generate a `badarg' when
%% resuming a search with no previous matches.
match_object2(Config) when is_list(Config) ->
- repeat_for_opts(fun match_object2_do/1).
+ repeat_for_opts_all_table_types(fun match_object2_do/1).
match_object2_do(Opts) ->
EtsMem = etsmem(),
@@ -4083,18 +4127,21 @@ match_object2_do(Opts) ->
%% OTP-3319. Test tab2list.
tab2list(Config) when is_list(Config) ->
- EtsMem = etsmem(),
- Tab = make_table(foo,
- [ordered_set],
- [{a,b}, {c,b}, {b,b}, {a,c}]),
- [{a,c},{b,b},{c,b}] = ets:tab2list(Tab),
- true = ets:delete(Tab),
- verify_etsmem(EtsMem).
+ repeat_for_all_ord_set_table_types(
+ fun(Opts) ->
+ EtsMem = etsmem(),
+ Tab = make_table(foo,
+ Opts,
+ [{a,b}, {c,b}, {b,b}, {a,c}]),
+ [{a,c},{b,b},{c,b}] = ets:tab2list(Tab),
+ true = ets:delete(Tab),
+ verify_etsmem(EtsMem)
+ end).
%% Simple general small test. If this fails, ets is in really bad
%% shape.
misc1(Config) when is_list(Config) ->
- repeat_for_opts(fun misc1_do/1).
+ repeat_for_opts_all_table_types(fun misc1_do/1).
misc1_do(Opts) ->
EtsMem = etsmem(),
@@ -4112,7 +4159,7 @@ misc1_do(Opts) ->
%% Check the safe_fixtable function.
safe_fixtable(Config) when is_list(Config) ->
- repeat_for_opts(fun safe_fixtable_do/1).
+ repeat_for_opts_all_table_types(fun safe_fixtable_do/1).
safe_fixtable_do(Opts) ->
EtsMem = etsmem(),
@@ -4170,10 +4217,42 @@ safe_fixtable_do(Opts) ->
%% Tests ets:info result for required tuples.
info(Config) when is_list(Config) ->
- repeat_for_opts(fun info_do/1).
+ repeat_for_opts_all_table_types(fun info_do/1).
info_do(Opts) ->
EtsMem = etsmem(),
+ TableType = lists:foldl(
+ fun(Item, Curr) ->
+ case Item of
+ set -> set;
+ ordered_set -> ordered_set;
+ cat_ord_set -> ordered_set;
+ stim_cat_ord_set -> ordered_set;
+ bag -> bag;
+ duplicate_bag -> duplicate_bag;
+ _ -> Curr
+ end
+ end, set, Opts),
+ PublicOrCurr =
+ fun(Curr) ->
+ case lists:member({write_concurrency, false}, Opts) or
+ lists:member(private, Opts) or
+ lists:member(protected, Opts) of
+ true -> Curr;
+ false -> public
+ end
+ end,
+ Protection = lists:foldl(
+ fun(Item, Curr) ->
+ case Item of
+ public -> public;
+ protected -> protected;
+ private -> private;
+ cat_ord_set -> PublicOrCurr(Curr); %% Special items
+ stim_cat_ord_set -> PublicOrCurr(Curr);
+ _ -> Curr
+ end
+ end, protected, Opts),
MeMyselfI=self(),
ThisNode=node(),
Tab = ets_new(foobar, [{keypos, 2} | Opts]),
@@ -4187,9 +4266,9 @@ info_do(Opts) ->
{value, {size, 0}} = lists:keysearch(size, 1, Res),
{value, {node, ThisNode}} = lists:keysearch(node, 1, Res),
{value, {named_table, false}} = lists:keysearch(named_table, 1, Res),
- {value, {type, set}} = lists:keysearch(type, 1, Res),
+ {value, {type, TableType}} = lists:keysearch(type, 1, Res),
{value, {keypos, 2}} = lists:keysearch(keypos, 1, Res),
- {value, {protection, protected}} =
+ {value, {protection, Protection}} =
lists:keysearch(protection, 1, Res),
{value, {id, Tab}} = lists:keysearch(id, 1, Res),
true = ets:delete(Tab),
@@ -4234,20 +4313,29 @@ dups_do(Opts) ->
%% Test the ets:tab2file function on an empty ets table.
tab2file(Config) when is_list(Config) ->
FName = filename:join([proplists:get_value(priv_dir, Config),"tab2file_case"]),
- tab2file_do(FName, []),
- tab2file_do(FName, [{sync,true}]),
- tab2file_do(FName, [{sync,false}]),
- {'EXIT',{{badmatch,{error,_}},_}} = (catch tab2file_do(FName, [{sync,yes}])),
- {'EXIT',{{badmatch,{error,_}},_}} = (catch tab2file_do(FName, [sync])),
+ tab2file_do(FName, [], set),
+ tab2file_do(FName, [], ordered_set),
+ tab2file_do(FName, [], cat_ord_set),
+ tab2file_do(FName, [], stim_cat_ord_set),
+ tab2file_do(FName, [{sync,true}], set),
+ tab2file_do(FName, [{sync,false}], set),
+ {'EXIT',{{badmatch,{error,_}},_}} = (catch tab2file_do(FName, [{sync,yes}], set)),
+ {'EXIT',{{badmatch,{error,_}},_}} = (catch tab2file_do(FName, [sync], set)),
ok.
-tab2file_do(FName, Opts) ->
+tab2file_do(FName, Opts, TableType) ->
%% Write an empty ets table to a file, read back and check properties.
- Tab = ets_new(ets_SUITE_foo_tab, [named_table, set, public,
+ Tab = ets_new(ets_SUITE_foo_tab, [named_table, TableType, public,
{keypos, 2},
compressed,
{write_concurrency,true},
{read_concurrency,true}]),
+ ActualTableType =
+ case TableType of
+ cat_ord_set -> ordered_set;
+ stim_cat_ord_set -> ordered_set;
+ _ -> TableType
+ end,
catch file:delete(FName),
Res = ets:tab2file(Tab, FName, Opts),
true = ets:delete(Tab),
@@ -4258,7 +4346,7 @@ tab2file_do(FName, Opts) ->
public = ets:info(Tab2, protection),
true = ets:info(Tab2, named_table),
2 = ets:info(Tab2, keypos),
- set = ets:info(Tab2, type),
+ ActualTableType = ets:info(Tab2, type),
true = ets:info(Tab2, compressed),
Smp = erlang:system_info(smp_support),
Smp = ets:info(Tab2, read_concurrency),
@@ -4271,7 +4359,7 @@ tab2file_do(FName, Opts) ->
tab2file2(Config) when is_list(Config) ->
repeat_for_opts(fun(Opts) ->
tab2file2_do(Opts, Config)
- end, [[set,bag],compressed]).
+ end, [[stim_cat_ord_set,cat_ord_set,set,bag],compressed]).
tab2file2_do(Opts, Config) ->
EtsMem = etsmem(),
@@ -4332,7 +4420,7 @@ fill_tab2(Tab, Val, Num) ->
%% Test verification of tables with object count extended_info.
tabfile_ext1(Config) when is_list(Config) ->
- repeat_for_opts(fun(Opts) -> tabfile_ext1_do(Opts, Config) end).
+ repeat_for_opts_all_set_table_types(fun(Opts) -> tabfile_ext1_do(Opts, Config) end).
tabfile_ext1_do(Opts,Config) ->
FName = filename:join([proplists:get_value(priv_dir, Config),"nisse.dat"]),
@@ -4370,7 +4458,7 @@ tabfile_ext1_do(Opts,Config) ->
%% Test verification of tables with md5sum extended_info.
tabfile_ext2(Config) when is_list(Config) ->
- repeat_for_opts(fun(Opts) -> tabfile_ext2_do(Opts,Config) end).
+ repeat_for_opts_all_set_table_types(fun(Opts) -> tabfile_ext2_do(Opts,Config) end).
tabfile_ext2_do(Opts,Config) ->
FName = filename:join([proplists:get_value(priv_dir, Config),"olle.dat"]),
@@ -4407,71 +4495,77 @@ tabfile_ext2_do(Opts,Config) ->
%% Test verification of (named) tables without extended info.
tabfile_ext3(Config) when is_list(Config) ->
- FName = filename:join([proplists:get_value(priv_dir, Config),"namn.dat"]),
- FName2 = filename:join([proplists:get_value(priv_dir, Config),"ncountflip.dat"]),
- L = lists:seq(1,10),
- Name = make_ref(),
- ?MODULE = ets_new(?MODULE,[named_table]),
- [ets:insert(?MODULE,{X,integer_to_list(X)}) || X <- L],
- ets:tab2file(?MODULE,FName),
- {error,cannot_create_table} = ets:file2tab(FName),
- true = ets:delete(?MODULE),
- {ok,?MODULE} = ets:file2tab(FName),
- true = ets:delete(?MODULE),
- disk_log:open([{name,Name},{file,FName}]),
- {_,[H2|T2]} = disk_log:chunk(Name,start),
- disk_log:close(Name),
- NewT2=lists:keydelete(8,1,T2),
- file:delete(FName2),
- disk_log:open([{name,Name},{file,FName2},{mode,read_write}]),
- disk_log:log_terms(Name,[H2|NewT2]),
- disk_log:close(Name),
- 9 = length(ets:tab2list(element(2,ets:file2tab(FName2)))),
- true = ets:delete(?MODULE),
- {error,invalid_object_count} = ets:file2tab(FName2,[{verify,true}]),
- {'EXIT',_} = (catch ets:delete(?MODULE)),
- {ok,_} = ets:tabfile_info(FName2),
- {ok,_} = ets:tabfile_info(FName),
- file:delete(FName),
- file:delete(FName2),
+ repeat_for_all_set_table_types(
+ fun(Opts) ->
+ FName = filename:join([proplists:get_value(priv_dir, Config),"namn.dat"]),
+ FName2 = filename:join([proplists:get_value(priv_dir, Config),"ncountflip.dat"]),
+ L = lists:seq(1,10),
+ Name = make_ref(),
+ ?MODULE = ets_new(?MODULE,[named_table|Opts]),
+ [ets:insert(?MODULE,{X,integer_to_list(X)}) || X <- L],
+ ets:tab2file(?MODULE,FName),
+ {error,cannot_create_table} = ets:file2tab(FName),
+ true = ets:delete(?MODULE),
+ {ok,?MODULE} = ets:file2tab(FName),
+ true = ets:delete(?MODULE),
+ disk_log:open([{name,Name},{file,FName}]),
+ {_,[H2|T2]} = disk_log:chunk(Name,start),
+ disk_log:close(Name),
+ NewT2=lists:keydelete(8,1,T2),
+ file:delete(FName2),
+ disk_log:open([{name,Name},{file,FName2},{mode,read_write}]),
+ disk_log:log_terms(Name,[H2|NewT2]),
+ disk_log:close(Name),
+ 9 = length(ets:tab2list(element(2,ets:file2tab(FName2)))),
+ true = ets:delete(?MODULE),
+ {error,invalid_object_count} = ets:file2tab(FName2,[{verify,true}]),
+ {'EXIT',_} = (catch ets:delete(?MODULE)),
+ {ok,_} = ets:tabfile_info(FName2),
+ {ok,_} = ets:tabfile_info(FName),
+ file:delete(FName),
+ file:delete(FName2)
+ end),
ok.
%% Tests verification of large table with md5 sum.
tabfile_ext4(Config) when is_list(Config) ->
- FName = filename:join([proplists:get_value(priv_dir, Config),"bauta.dat"]),
- LL = lists:seq(1,10000),
- TL = ets_new(x,[]),
- Name2 = make_ref(),
- [ets:insert(TL,{X,integer_to_list(X)}) || X <- LL],
- ok = ets:tab2file(TL,FName,[{extended_info,[md5sum]}]),
- {ok, Name2} = disk_log:open([{name, Name2}, {file, FName},
- {mode, read_only}]),
- {C,[_|_]} = disk_log:chunk(Name2,start),
- {_,[_|_]} = disk_log:chunk(Name2,C),
- disk_log:close(Name2),
- true = lists:sort(ets:tab2list(TL)) =:=
- lists:sort(ets:tab2list(element(2,ets:file2tab(FName)))),
- Res = [begin
- {ok,FD} = file:open(FName,[binary,read,write]),
- {ok, Bin} = file:pread(FD,0,1000),
- <<B1:N/binary,Ch:8,B2/binary>> = Bin,
- Ch2 = (Ch + 1) rem 255,
- Bin2 = <<B1/binary,Ch2:8,B2/binary>>,
- ok = file:pwrite(FD,0,Bin2),
- ok = file:close(FD),
- X = case ets:file2tab(FName) of
- {ok,TL2} ->
- true = lists:sort(ets:tab2list(TL)) =/=
- lists:sort(ets:tab2list(TL2));
- _ ->
- totally_broken
- end,
- {error,Y} = ets:file2tab(FName,[{verify,true}]),
- ets:tab2file(TL,FName,[{extended_info,[md5sum]}]),
- {X,Y}
- end || N <- lists:seq(500,600)],
- io:format("~p~n",[Res]),
- file:delete(FName),
+ repeat_for_all_set_table_types(
+ fun(Opts) ->
+ FName = filename:join([proplists:get_value(priv_dir, Config),"bauta.dat"]),
+ LL = lists:seq(1,10000),
+ TL = ets_new(x,Opts),
+ Name2 = make_ref(),
+ [ets:insert(TL,{X,integer_to_list(X)}) || X <- LL],
+ ok = ets:tab2file(TL,FName,[{extended_info,[md5sum]}]),
+ {ok, Name2} = disk_log:open([{name, Name2}, {file, FName},
+ {mode, read_only}]),
+ {C,[_|_]} = disk_log:chunk(Name2,start),
+ {_,[_|_]} = disk_log:chunk(Name2,C),
+ disk_log:close(Name2),
+ true = lists:sort(ets:tab2list(TL)) =:=
+ lists:sort(ets:tab2list(element(2,ets:file2tab(FName)))),
+ Res = [begin
+ {ok,FD} = file:open(FName,[binary,read,write]),
+ {ok, Bin} = file:pread(FD,0,1000),
+ <<B1:N/binary,Ch:8,B2/binary>> = Bin,
+ Ch2 = (Ch + 1) rem 255,
+ Bin2 = <<B1/binary,Ch2:8,B2/binary>>,
+ ok = file:pwrite(FD,0,Bin2),
+ ok = file:close(FD),
+ X = case ets:file2tab(FName) of
+ {ok,TL2} ->
+ true = lists:sort(ets:tab2list(TL)) =/=
+ lists:sort(ets:tab2list(TL2));
+ _ ->
+ totally_broken
+ end,
+ {error,Y} = ets:file2tab(FName,[{verify,true}]),
+ ets:tab2file(TL,FName,[{extended_info,[md5sum]}]),
+ {X,Y}
+ end || N <- lists:seq(500,600)],
+ io:format("~p~n",[Res]),
+ file:delete(FName)
+ end),
ok.
%% Test that no disk_log is left open when file has been corrupted.
@@ -4535,11 +4629,11 @@ make_sub_binary(List, Num) when is_list(List) ->
%% Perform multiple lookups for every key in a large table.
heavy_lookup(Config) when is_list(Config) ->
- repeat_for_opts(fun heavy_lookup_do/1).
+ repeat_for_opts_all_set_table_types(fun heavy_lookup_do/1).
heavy_lookup_do(Opts) ->
EtsMem = etsmem(),
- Tab = ets_new(foobar_table, [set, protected, {keypos, 2} | Opts]),
+ Tab = ets_new(foobar_table, [{keypos, 2} | Opts]),
ok = fill_tab2(Tab, 0, 7000),
_ = [do_lookup(Tab, 6999) || _ <- lists:seq(1, 50)],
true = ets:delete(Tab),
@@ -4558,11 +4652,11 @@ do_lookup(Tab, N) ->
%% Perform multiple lookups for every element in a large table.
heavy_lookup_element(Config) when is_list(Config) ->
- repeat_for_opts(fun heavy_lookup_element_do/1).
+ repeat_for_opts_all_set_table_types(fun heavy_lookup_element_do/1).
heavy_lookup_element_do(Opts) ->
EtsMem = etsmem(),
- Tab = ets_new(foobar_table, [set, protected, {keypos, 2} | Opts]),
+ Tab = ets_new(foobar_table, [{keypos, 2} | Opts]),
ok = fill_tab2(Tab, 0, 7000),
%% lookup ALL elements 50 times
Laps = 50 div syrup_factor(),
@@ -4585,14 +4679,14 @@ do_lookup_element(Tab, N, M) ->
heavy_concurrent(Config) when is_list(Config) ->
- ct:timetrap({minutes,30}), %% valgrind needs a lot of time
- repeat_for_opts(fun do_heavy_concurrent/1).
+ ct:timetrap({minutes,120}), %% valgrind needs a lot of time
+ repeat_for_opts_all_set_table_types(fun do_heavy_concurrent/1).
do_heavy_concurrent(Opts) ->
Size = 10000,
Laps = 10000 div syrup_factor(),
EtsMem = etsmem(),
- Tab = ets_new(blupp, [set, public, {keypos, 2} | Opts]),
+ Tab = ets_new(blupp, [public, {keypos, 2} | Opts]),
ok = fill_tab2(Tab, 0, Size),
Procs = lists:map(
fun (N) ->
@@ -4626,48 +4720,68 @@ do_heavy_concurrent_proc(Tab, N, Offs) ->
fold_empty(Config) when is_list(Config) ->
- EtsMem = etsmem(),
- Tab = make_table(a, [], []),
- [] = ets:foldl(fun(_X) -> exit(hej) end, [], Tab),
- [] = ets:foldr(fun(_X) -> exit(hej) end, [], Tab),
- true = ets:delete(Tab),
- verify_etsmem(EtsMem).
+ repeat_for_opts_all_set_table_types(
+ fun(Opts) ->
+ EtsMem = etsmem(),
+ Tab = make_table(a, Opts, []),
+ [] = ets:foldl(fun(_X) -> exit(hej) end, [], Tab),
+ [] = ets:foldr(fun(_X) -> exit(hej) end, [], Tab),
+ true = ets:delete(Tab),
+ verify_etsmem(EtsMem)
+ end),
+ ok.
foldl(Config) when is_list(Config) ->
- EtsMem = etsmem(),
- L = [{a,1}, {c,3}, {b,2}],
- LS = lists:sort(L),
- Tab = make_table(a, [bag], L),
- LS = lists:sort(ets:foldl(fun(E,A) -> [E|A] end, [], Tab)),
- true = ets:delete(Tab),
- verify_etsmem(EtsMem).
+ repeat_for_opts_all_table_types(
+ fun(Opts) ->
+ EtsMem = etsmem(),
+ L = [{a,1}, {c,3}, {b,2}],
+ LS = lists:sort(L),
+ Tab = make_table(a, Opts, L),
+ LS = lists:sort(ets:foldl(fun(E,A) -> [E|A] end, [], Tab)),
+ true = ets:delete(Tab),
+ verify_etsmem(EtsMem)
+ end),
+ ok.
foldr(Config) when is_list(Config) ->
- EtsMem = etsmem(),
- L = [{a,1}, {c,3}, {b,2}],
- LS = lists:sort(L),
- Tab = make_table(a, [bag], L),
- LS = lists:sort(ets:foldr(fun(E,A) -> [E|A] end, [], Tab)),
- true = ets:delete(Tab),
- verify_etsmem(EtsMem).
+ repeat_for_opts_all_table_types(
+ fun(Opts) ->
+ EtsMem = etsmem(),
+ L = [{a,1}, {c,3}, {b,2}],
+ LS = lists:sort(L),
+ Tab = make_table(a, Opts, L),
+ LS = lists:sort(ets:foldr(fun(E,A) -> [E|A] end, [], Tab)),
+ true = ets:delete(Tab),
+ verify_etsmem(EtsMem)
+ end),
+ ok.
foldl_ordered(Config) when is_list(Config) ->
- EtsMem = etsmem(),
- L = [{a,1}, {c,3}, {b,2}],
- LS = lists:sort(L),
- Tab = make_table(a, [ordered_set], L),
- LS = lists:reverse(ets:foldl(fun(E,A) -> [E|A] end, [], Tab)),
- true = ets:delete(Tab),
- verify_etsmem(EtsMem).
+ repeat_for_opts_all_ord_set_table_types(
+ fun(Opts) ->
+ EtsMem = etsmem(),
+ L = [{a,1}, {c,3}, {b,2}],
+ LS = lists:sort(L),
+ Tab = make_table(a, Opts, L),
+ LS = lists:reverse(ets:foldl(fun(E,A) -> [E|A] end, [], Tab)),
+ true = ets:delete(Tab),
+ verify_etsmem(EtsMem)
+ end),
+ ok.
foldr_ordered(Config) when is_list(Config) ->
- EtsMem = etsmem(),
- L = [{a,1}, {c,3}, {b,2}],
- LS = lists:sort(L),
- Tab = make_table(a, [ordered_set], L),
- LS = ets:foldr(fun(E,A) -> [E|A] end, [], Tab),
- true = ets:delete(Tab),
- verify_etsmem(EtsMem).
+ repeat_for_opts_all_ord_set_table_types(
+ fun(Opts) ->
+ EtsMem = etsmem(),
+ L = [{a,1}, {c,3}, {b,2}],
+ LS = lists:sort(L),
+ Tab = make_table(a, Opts, L),
+ LS = ets:foldr(fun(E,A) -> [E|A] end, [], Tab),
+ true = ets:delete(Tab),
+ verify_etsmem(EtsMem)
+ end),
+ ok.
%% Test ets:member BIF.
member(Config) when is_list(Config) ->
@@ -5066,27 +5180,30 @@ gen_dets_filename(Config,N) ->
"testdets_" ++ integer_to_list(N) ++ ".dets").
otp_6842_select_1000(Config) when is_list(Config) ->
- Tab = ets_new(xxx,[ordered_set]),
- [ets:insert(Tab,{X,X}) || X <- lists:seq(1,10000)],
- AllTrue = lists:duplicate(10,true),
- AllTrue =
- [ length(
- element(1,
- ets:select(Tab,[{'_',[],['$_']}],X*1000))) =:=
- X*1000 || X <- lists:seq(1,10) ],
- Sequences = [[1000,1000,1000,1000,1000,1000,1000,1000,1000,1000],
- [2000,2000,2000,2000,2000],
- [3000,3000,3000,1000],
- [4000,4000,2000],
- [5000,5000],
- [6000,4000],
- [7000,3000],
- [8000,2000],
- [9000,1000],
- [10000]],
- AllTrue = [ check_seq(Tab, ets:select(Tab,[{'_',[],['$_']}],hd(L)),L) ||
- L <- Sequences ],
- ets:delete(Tab),
+ repeat_for_opts_all_ord_set_table_types(
+ fun(Opts) ->
+ Tab = ets_new(xxx,Opts),
+ [ets:insert(Tab,{X,X}) || X <- lists:seq(1,10000)],
+ AllTrue = lists:duplicate(10,true),
+ AllTrue =
+ [ length(
+ element(1,
+ ets:select(Tab,[{'_',[],['$_']}],X*1000))) =:=
+ X*1000 || X <- lists:seq(1,10) ],
+ Sequences = [[1000,1000,1000,1000,1000,1000,1000,1000,1000,1000],
+ [2000,2000,2000,2000,2000],
+ [3000,3000,3000,1000],
+ [4000,4000,2000],
+ [5000,5000],
+ [6000,4000],
+ [7000,3000],
+ [8000,2000],
+ [9000,1000],
+ [10000]],
+ AllTrue = [ check_seq(Tab, ets:select(Tab,[{'_',[],['$_']}],hd(L)),L) ||
+ L <- Sequences ],
+ ets:delete(Tab)
+ end),
ok.
check_seq(_,'$end_of_table',[]) ->
@@ -5098,17 +5215,21 @@ check_seq(A,B,C) ->
false.
otp_6338(Config) when is_list(Config) ->
- L = binary_to_term(<<131,108,0,0,0,2,104,2,108,0,0,0,2,103,100,0,19,112,112,
- 98,49,95,98,115,49,50,64,98,108,97,100,101,95,48,95,53,
- 0,0,33,50,0,0,0,4,1,98,0,0,23,226,106,100,0,4,101,120,
- 105,116,104,2,108,0,0,0,2,104,2,100,0,3,115,98,109,100,
- 0,19,112,112,98,50,95,98,115,49,50,64,98,108,97,100,
- 101,95,48,95,56,98,0,0,18,231,106,100,0,4,114,101,99,
- 118,106>>),
- T = ets_new(xxx,[ordered_set]),
- lists:foreach(fun(X) -> ets:insert(T,X) end,L),
- [[4839,recv]] = ets:match(T,{[{sbm,ppb2_bs12@blade_0_8},'$1'],'$2'}),
- ets:delete(T).
+ repeat_for_opts_all_ord_set_table_types(
+ fun(Opts) ->
+ L = binary_to_term(<<131,108,0,0,0,2,104,2,108,0,0,0,2,103,100,0,19,112,112,
+ 98,49,95,98,115,49,50,64,98,108,97,100,101,95,48,95,53,
+ 0,0,33,50,0,0,0,4,1,98,0,0,23,226,106,100,0,4,101,120,
+ 105,116,104,2,108,0,0,0,2,104,2,100,0,3,115,98,109,100,
+ 0,19,112,112,98,50,95,98,115,49,50,64,98,108,97,100,
+ 101,95,48,95,56,98,0,0,18,231,106,100,0,4,114,101,99,
+ 118,106>>),
+ T = ets_new(xxx,Opts),
+ lists:foreach(fun(X) -> ets:insert(T,X) end,L),
+ [[4839,recv]] = ets:match(T,{[{sbm,ppb2_bs12@blade_0_8},'$1'],'$2'}),
+ ets:delete(T)
+ end),
+ ok.
%% Elements could come in the wrong order in a bag if a rehash occurred.
otp_5340(Config) when is_list(Config) ->
@@ -5178,7 +5299,7 @@ otp_7665_act(Tab,Min,Max,DelNr) ->
%% Whitebox testing of meta name table hashing.
meta_wb(Config) when is_list(Config) ->
EtsMem = etsmem(),
- repeat_for_opts(fun meta_wb_do/1),
+ repeat_for_opts_all_table_types(fun meta_wb_do/1),
verify_etsmem(EtsMem).
@@ -5247,13 +5368,16 @@ colliding_names(Name) ->
%% OTP_6913: Grow and shrink.
grow_shrink(Config) when is_list(Config) ->
- EtsMem = etsmem(),
-
- Set = ets_new(a, [set]),
- grow_shrink_0(0, 3071, 3000, 5000, Set),
- ets:delete(Set),
-
- verify_etsmem(EtsMem).
+ repeat_for_all_set_table_types(
+ fun(Opts) ->
+ EtsMem = etsmem(),
+
+ Set = ets_new(a, Opts),
+ grow_shrink_0(0, 3071, 3000, 5000, Set),
+ ets:delete(Set),
+
+ verify_etsmem(EtsMem)
+ end).
grow_shrink_0(N, _, _, Max, _) when N >= Max ->
ok;
@@ -5283,7 +5407,8 @@ grow_pseudo_deleted(Config) when is_list(Config) ->
grow_pseudo_deleted_do() ->
lists:foreach(fun(Type) -> grow_pseudo_deleted_do(Type) end,
- [set,bag,duplicate_bag]).
+ [set,cat_ord_set,stim_cat_ord_set,
+ ordered_set,bag,duplicate_bag]).
grow_pseudo_deleted_do(Type) ->
process_flag(scheduler,1),
@@ -5298,7 +5423,12 @@ grow_pseudo_deleted_do(Type) ->
[true]}]),
Left = Mult*(Mod-1),
Left = ets:info(T,size),
- Mult = get_kept_objects(T),
+ case Type of
+ cat_ord_set -> ok;
+ stim_cat_ord_set -> ok;
+ ordered_set -> ok;
+ _ -> Mult = get_kept_objects(T)
+ end,
filltabstr(T,Mult),
my_spawn_opt(
fun() ->
@@ -5336,7 +5466,8 @@ shrink_pseudo_deleted(Config) when is_list(Config) ->
shrink_pseudo_deleted_do() ->
lists:foreach(fun(Type) -> shrink_pseudo_deleted_do(Type) end,
- [set,bag,duplicate_bag]).
+ [set,cat_ord_set,stim_cat_ord_set,
+ ordered_set,bag,duplicate_bag]).
shrink_pseudo_deleted_do(Type) ->
process_flag(scheduler,1),
@@ -5350,7 +5481,12 @@ shrink_pseudo_deleted_do(Type) ->
[{'>', '$1', Half}],
[true]}]),
Half = ets:info(T,size),
- Half = get_kept_objects(T),
+ case Type of
+ cat_ord_set -> ok;
+ stim_cat_ord_set -> ok;
+ ordered_set -> ok;
+ _ -> Half = get_kept_objects(T)
+ end,
my_spawn_opt(
fun()-> true = ets:info(T,fixed),
Self ! start,
@@ -5450,47 +5586,101 @@ meta_newdel_named(Config) when is_list(Config) ->
%% Concurrent insert's on same table.
smp_insert(Config) when is_list(Config) ->
- ets_new(smp_insert,[named_table,public,{write_concurrency,true}]),
- InitF = fun(_) -> ok end,
- ExecF = fun(_) -> true = ets:insert(smp_insert,{rand:uniform(10000)})
- end,
- FiniF = fun(_) -> ok end,
- run_smp_workers(InitF,ExecF,FiniF,100000),
- verify_table_load(smp_insert),
- ets:delete(smp_insert).
+ repeat_for_all_set_table_types(
+ fun(Opts) ->
+ ets_new(smp_insert,[named_table,public,{write_concurrency,true}|Opts]),
+ InitF = fun(_) -> ok end,
+ ExecF = fun(_) -> true = ets:insert(smp_insert,{rand:uniform(10000)})
+ end,
+ FiniF = fun(_) -> ok end,
+ run_smp_workers(InitF,ExecF,FiniF,100000),
+ verify_table_load(smp_insert),
+ ets:delete(smp_insert)
+ end).
%% Concurrent deletes on same fixated table.
smp_fixed_delete(Config) when is_list(Config) ->
only_if_smp(fun()->smp_fixed_delete_do() end).
smp_fixed_delete_do() ->
- T = ets_new(foo,[public,{write_concurrency,true}]),
- %%Mem = ets:info(T,memory),
- NumOfObjs = 100000,
- filltabint(T,NumOfObjs),
- ets:safe_fixtable(T,true),
- Buckets = num_of_buckets(T),
- InitF = fun([ProcN,NumOfProcs|_]) -> {ProcN,NumOfProcs} end,
- ExecF = fun({Key,_}) when Key > NumOfObjs ->
- [end_of_work];
- ({Key,Increment}) ->
- true = ets:delete(T,Key),
- {Key+Increment,Increment}
- end,
- FiniF = fun(_) -> ok end,
- run_sched_workers(InitF,ExecF,FiniF,NumOfObjs),
- 0 = ets:info(T,size),
- true = ets:info(T,fixed),
- Buckets = num_of_buckets(T),
- NumOfObjs = get_kept_objects(T),
- ets:safe_fixtable(T,false),
- %% Will fail as unfix does not shrink the table:
- %%Mem = ets:info(T,memory),
- %%verify_table_load(T),
- ets:delete(T).
+ repeat_for_opts_all_set_table_types(
+ fun(Opts) ->
+ T = ets_new(foo,[public,{write_concurrency,true}|Opts]),
+ %%Mem = ets:info(T,memory),
+ NumOfObjs = 100000,
+ filltabint(T,NumOfObjs),
+ ets:safe_fixtable(T,true),
+ Buckets = num_of_buckets(T),
+ InitF = fun([ProcN,NumOfProcs|_]) -> {ProcN,NumOfProcs} end,
+ ExecF = fun({Key,_}) when Key > NumOfObjs ->
+ [end_of_work];
+ ({Key,Increment}) ->
+ true = ets:delete(T,Key),
+ {Key+Increment,Increment}
+ end,
+ FiniF = fun(_) -> ok end,
+ run_sched_workers(InitF,ExecF,FiniF,NumOfObjs),
+ 0 = ets:info(T,size),
+ true = ets:info(T,fixed),
+ Buckets = num_of_buckets(T),
+ case ets:info(T,type) of
+ set -> NumOfObjs = get_kept_objects(T);
+ _ -> ok
+ end,
+ ets:safe_fixtable(T,false),
+ %% Will fail as unfix does not shrink the table:
+ %%Mem = ets:info(T,memory),
+ %%verify_table_load(T),
+ ets:delete(T)
+ end).
+
+%% ERL-720
+%% Provoke race between ets:delete and table unfix (by select_count)
+%% that caused ets_misc memory counter to indicate false leak.
+delete_unfix_race(Config) when is_list(Config) ->
+ EtsMem = etsmem(),
+ Table = ets:new(t,[set,public,{write_concurrency,true}]),
+ InsertOp =
+ fun() ->
+ receive stop ->
+ false
+ after 0 ->
+ ets:insert(Table, {rand:uniform(10)}),
+ true
+ end
+ end,
+ DeleteOp =
+ fun() ->
+ receive stop ->
+ false
+ after 0 ->
+ ets:delete(Table, rand:uniform(10)),
+ true
+ end
+ end,
+ SelectOp =
+ fun() ->
+ ets:select_count(Table, ets:fun2ms(fun(X) -> true end))
+ end,
+ Main = self(),
+ Ins = spawn(fun()-> repeat_while(InsertOp), Main ! self() end),
+ Del = spawn(fun()-> repeat_while(DeleteOp), Main ! self() end),
+ spawn(fun()->
+ repeat(SelectOp, 10000),
+ Del ! stop,
+ Ins ! stop
+ end),
+ [receive Pid -> ok end || Pid <- [Ins,Del]],
+ ets:delete(Table),
+ verify_etsmem(EtsMem).
num_of_buckets(T) ->
- element(1,ets:info(T,stats)).
+ case ets:info(T,type) of
+ set -> element(1,ets:info(T,stats));
+ bag -> element(1,ets:info(T,stats));
+ duplicate_bag -> element(1,ets:info(T,stats));
+ _ -> ok
+ end.
%% Fixate hash table while other process is busy doing unfix.
smp_unfix_fix(Config) when is_list(Config) ->
@@ -5655,98 +5845,109 @@ otp_8166_zombie_creator(T,Deleted) ->
verify_table_load(T) ->
- Stats = ets:info(T,stats),
- {Buckets,AvgLen,StdDev,ExpSD,_MinLen,_MaxLen,_} = Stats,
- ok = if
- AvgLen > 1.2 ->
- io:format("Table overloaded: Stats=~p\n~p\n",
- [Stats, ets:info(T)]),
- false;
-
- Buckets>256, AvgLen < 0.47 ->
- io:format("Table underloaded: Stats=~p\n~p\n",
- [Stats, ets:info(T)]),
- false;
-
- StdDev > ExpSD*2 ->
- io:format("Too large standard deviation (poor hashing?),"
- " stats=~p\n~p\n",[Stats, ets:info(T)]),
- false;
-
- true ->
- io:format("Stats = ~p\n",[Stats]),
- ok
- end.
+ case ets:info(T,type) of
+ ordered_set -> ok;
+ _ ->
+ Stats = ets:info(T,stats),
+ {Buckets,AvgLen,StdDev,ExpSD,_MinLen,_MaxLen,_} = Stats,
+ ok = if
+ AvgLen > 1.2 ->
+ io:format("Table overloaded: Stats=~p\n~p\n",
+ [Stats, ets:info(T)]),
+ false;
+
+ Buckets>256, AvgLen < 0.47 ->
+ io:format("Table underloaded: Stats=~p\n~p\n",
+ [Stats, ets:info(T)]),
+ false;
+
+ StdDev > ExpSD*2 ->
+ io:format("Too large standard deviation (poor hashing?),"
+ " stats=~p\n~p\n",[Stats, ets:info(T)]),
+ false;
+
+ true ->
+ io:format("Stats = ~p\n",[Stats]),
+ ok
+ end
+ end.
%% ets:select on a tree with NIL key object.
otp_8732(Config) when is_list(Config) ->
- Tab = ets_new(noname,[ordered_set]),
- filltabstr(Tab,999),
- ets:insert(Tab,{[],"nasty NIL object"}),
- [] = ets:match(Tab,{'_',nomatch}), %% Will hang if bug not fixed
+ repeat_for_all_ord_set_table_types(
+ fun(Opts) ->
+ Tab = ets_new(noname,Opts),
+ filltabstr(Tab,999),
+ ets:insert(Tab,{[],"nasty NIL object"}),
+ [] = ets:match(Tab,{'_',nomatch}) %% Will hang if bug not fixed
+ end),
ok.
%% Run concurrent select_delete (and inserts) on same table.
smp_select_delete(Config) when is_list(Config) ->
- T = ets_new(smp_select_delete,[named_table,public,{write_concurrency,true}]),
- Mod = 17,
- Zeros = erlang:make_tuple(Mod,0),
- InitF = fun(_) -> Zeros end,
- ExecF = fun(Diffs0) ->
- case rand:uniform(20) of
- 1 ->
- Mod = 17,
- Eq = rand:uniform(Mod) - 1,
- Deleted = ets:select_delete(T,
- [{{'_', '$1'},
- [{'=:=', {'rem', '$1', Mod}, Eq}],
- [true]}]),
- Diffs1 = setelement(Eq+1, Diffs0,
- element(Eq+1,Diffs0) - Deleted),
- Diffs1;
- _ ->
- Key = rand:uniform(10000),
- Eq = Key rem Mod,
- case ets:insert_new(T,{Key,Key}) of
- true ->
- Diffs1 = setelement(Eq+1, Diffs0,
- element(Eq+1,Diffs0)+1),
- Diffs1;
- false -> Diffs0
- end
- end
- end,
- FiniF = fun(Result) -> Result end,
- Results = run_sched_workers(InitF,ExecF,FiniF,20000),
- TotCnts = lists:foldl(fun(Diffs, Sum) -> add_lists(Sum,tuple_to_list(Diffs)) end,
- lists:duplicate(Mod, 0), Results),
- io:format("TotCnts = ~p\n",[TotCnts]),
- LeftInTab = lists:foldl(fun(N,Sum) -> Sum+N end,
- 0, TotCnts),
- io:format("LeftInTab = ~p\n",[LeftInTab]),
- LeftInTab = ets:info(T,size),
- lists:foldl(fun(Cnt,Eq) ->
- WasCnt = ets:select_count(T,
- [{{'_', '$1'},
- [{'=:=', {'rem', '$1', Mod}, Eq}],
- [true]}]),
- io:format("~p: ~p =?= ~p\n",[Eq,Cnt,WasCnt]),
- Cnt = WasCnt,
- Eq+1
- end,
- 0, TotCnts),
- %% May fail as select_delete does not shrink table (enough)
- %%verify_table_load(T),
- LeftInTab = ets:select_delete(T, [{{'$1','$1'}, [], [true]}]),
- 0 = ets:info(T,size),
- false = ets:info(T,fixed),
- ets:delete(T).
+ repeat_for_opts_all_set_table_types(
+ fun(Opts) ->
+ T = ets_new(smp_select_delete,[named_table,public,{write_concurrency,true}|Opts]),
+ Mod = 17,
+ Zeros = erlang:make_tuple(Mod,0),
+ InitF = fun(_) -> Zeros end,
+ ExecF = fun(Diffs0) ->
+ case rand:uniform(20) of
+ 1 ->
+ Mod = 17,
+ Eq = rand:uniform(Mod) - 1,
+ Deleted = ets:select_delete(T,
+ [{{'_', '$1'},
+ [{'=:=', {'rem', '$1', Mod}, Eq}],
+ [true]}]),
+ Diffs1 = setelement(Eq+1, Diffs0,
+ element(Eq+1,Diffs0) - Deleted),
+ Diffs1;
+ _ ->
+ Key = rand:uniform(10000),
+ Eq = Key rem Mod,
+ case ets:insert_new(T,{Key,Key}) of
+ true ->
+ Diffs1 = setelement(Eq+1, Diffs0,
+ element(Eq+1,Diffs0)+1),
+ Diffs1;
+ false -> Diffs0
+ end
+ end
+ end,
+ FiniF = fun(Result) -> Result end,
+ Results = run_sched_workers(InitF,ExecF,FiniF,20000),
+ TotCnts = lists:foldl(fun(Diffs, Sum) -> add_lists(Sum,tuple_to_list(Diffs)) end,
+ lists:duplicate(Mod, 0), Results),
+ io:format("TotCnts = ~p\n",[TotCnts]),
+ LeftInTab = lists:foldl(fun(N,Sum) -> Sum+N end,
+ 0, TotCnts),
+ io:format("LeftInTab = ~p\n",[LeftInTab]),
+ LeftInTab = ets:info(T,size),
+ lists:foldl(fun(Cnt,Eq) ->
+ WasCnt = ets:select_count(T,
+ [{{'_', '$1'},
+ [{'=:=', {'rem', '$1', Mod}, Eq}],
+ [true]}]),
+ io:format("~p: ~p =?= ~p\n",[Eq,Cnt,WasCnt]),
+ Cnt = WasCnt,
+ Eq+1
+ end,
+ 0, TotCnts),
+ %% May fail as select_delete does not shrink table (enough)
+ %%verify_table_load(T),
+ LeftInTab = ets:select_delete(T, [{{'$1','$1'}, [], [true]}]),
+ 0 = ets:info(T,size),
+ false = ets:info(T,fixed),
+ ets:delete(T)
+ end),
+ ok.
smp_select_replace(Config) when is_list(Config) ->
repeat_for_opts(fun smp_select_replace_do/1,
- [[set,ordered_set,duplicate_bag]]).
+ [[set,ordered_set,stim_cat_ord_set,duplicate_bag]]).
smp_select_replace_do(Opts) ->
T = ets_new(smp_select_replace,
@@ -5786,7 +5987,8 @@ smp_select_replace_do(Opts) ->
%% Test different types.
types(Config) when is_list(Config) ->
init_externals(),
- repeat_for_opts(fun types_do/1, [[set,ordered_set],compressed]).
+ repeat_for_opts(fun types_do/1, [repeat_for_opts_atom2list(set_types),
+ compressed]).
types_do(Opts) ->
EtsMem = etsmem(),
@@ -5813,7 +6015,7 @@ types_do(Opts) ->
%% OTP-9932: Memory overwrite when inserting large integers in compressed bag.
%% Will crash with segv on 64-bit opt if not fixed.
otp_9932(Config) when is_list(Config) ->
- T = ets:new(xxx, [bag, compressed]),
+ T = ets_new(xxx, [bag, compressed]),
Fun = fun(N) ->
Key = {1316110174588445 bsl N,1316110174588583 bsl N},
S = {Key, Key},
@@ -5829,48 +6031,56 @@ otp_9932(Config) when is_list(Config) ->
%% vm-deadlock caused by race between ets:delete and others on
%% write_concurrency table.
otp_9423(Config) when is_list(Config) ->
- InitF = fun(_) -> {0,0} end,
- ExecF = fun({S,F}) ->
- receive
- stop ->
- io:format("~p got stop\n", [self()]),
- [end_of_work | {"Succeded=",S,"Failed=",F}]
- after 0 ->
- %%io:format("~p (~p) doing lookup\n", [self(), {S,F}]),
- try ets:lookup(otp_9423, key) of
- [] -> {S+1,F}
- catch
- error:badarg -> {S,F+1}
- end
- end
- end,
- FiniF = fun(R) -> R end,
- case run_smp_workers(InitF, ExecF, FiniF, infinite, 1) of
- Pids when is_list(Pids) ->
- %%[P ! start || P <- Pids],
- repeat(fun() -> ets:new(otp_9423, [named_table, public, {write_concurrency,true}]),
- ets:delete(otp_9423)
- end, 10000),
- [P ! stop || P <- Pids],
- wait_pids(Pids),
- ok;
+ repeat_for_all_non_stim_set_table_types(
+ fun(Opts) ->
+ InitF = fun(_) -> {0,0} end,
+ ExecF = fun({S,F}) ->
+ receive
+ stop ->
+ io:format("~p got stop\n", [self()]),
+ [end_of_work | {"Succeded=",S,"Failed=",F}]
+ after 0 ->
+ %%io:format("~p (~p) doing lookup\n", [self(), {S,F}]),
+ try ets:lookup(otp_9423, key) of
+ [] -> {S+1,F}
+ catch
+ error:badarg -> {S,F+1}
+ end
+ end
+ end,
+ FiniF = fun(R) -> R end,
+ case run_smp_workers(InitF, ExecF, FiniF, infinite, 1) of
+ Pids when is_list(Pids) ->
+ %%[P ! start || P <- Pids],
+ repeat(fun() -> ets_new(otp_9423, [named_table, public,
+ {write_concurrency,true}|Opts]),
+ ets:delete(otp_9423)
+ end, 10000),
+ [P ! stop || P <- Pids],
+ wait_pids(Pids),
+ ok;
+
+ Skipped -> Skipped
+ end
+ end).
- Skipped -> Skipped
- end.
%% Corrupted binary in compressed table
otp_10182(Config) when is_list(Config) ->
- Bin = <<"aHR0cDovL2hvb3RzdWl0ZS5jb20vYy9wcm8tYWRyb2xsLWFi">>,
- Key = {test, Bin},
- Value = base64:decode(Bin),
- In = {Key,Value},
- Db = ets:new(undefined, [set, protected, {read_concurrency, true}, compressed]),
- ets:insert(Db, In),
- [Out] = ets:lookup(Db, Key),
- io:format("In : ~p\nOut: ~p\n", [In,Out]),
- ets:delete(Db),
- In = Out.
+ repeat_for_opts_all_table_types(
+ fun(Opts) ->
+ Bin = <<"aHR0cDovL2hvb3RzdWl0ZS5jb20vYy9wcm8tYWRyb2xsLWFi">>,
+ Key = {test, Bin},
+ Value = base64:decode(Bin),
+ In = {Key,Value},
+ Db = ets_new(undefined, Opts),
+ ets:insert(Db, In),
+ [Out] = ets:lookup(Db, Key),
+ io:format("In : ~p\nOut: ~p\n", [In,Out]),
+ ets:delete(Db),
+ In = Out
+ end).
%% Test that ets:all include/exclude tables that we know are created/deleted
ets_all(Config) when is_list(Config) ->
@@ -5961,19 +6171,23 @@ take(Config) when is_list(Config) ->
ets:insert(T1, {{'not',<<"immediate">>},ok}),
[{{'not',<<"immediate">>},ok}] = ets:take(T1, {'not',<<"immediate">>}),
%% Same with ordered tables.
- T2 = ets_new(b, [ordered_set]),
- [] = ets:take(T2, foo),
- ets:insert(T2, {foo,bar}),
- [] = ets:take(T2, bar),
- [{foo,bar}] = ets:take(T2, foo),
- [] = ets:tab2list(T2),
- ets:insert(T2, {{'not',<<"immediate">>},ok}),
- [{{'not',<<"immediate">>},ok}] = ets:take(T2, {'not',<<"immediate">>}),
- %% Arithmetically-equal keys.
- ets:insert(T2, [{1.0,float},{2,integer}]),
- [{1.0,float}] = ets:take(T2, 1),
- [{2,integer}] = ets:take(T2, 2.0),
- [] = ets:tab2list(T2),
+ repeat_for_all_ord_set_table_types(
+ fun(Opts) ->
+ T2 = ets_new(b, Opts),
+ [] = ets:take(T2, foo),
+ ets:insert(T2, {foo,bar}),
+ [] = ets:take(T2, bar),
+ [{foo,bar}] = ets:take(T2, foo),
+ [] = ets:tab2list(T2),
+ ets:insert(T2, {{'not',<<"immediate">>},ok}),
+ [{{'not',<<"immediate">>},ok}] = ets:take(T2, {'not',<<"immediate">>}),
+ %% Arithmetically-equal keys.
+ ets:insert(T2, [{1.0,float},{2,integer}]),
+ [{1.0,float}] = ets:take(T2, 1),
+ [{2,integer}] = ets:take(T2, 2.0),
+ [] = ets:tab2list(T2),
+ ets:delete(T2)
+ end),
%% Same with bag.
T3 = ets_new(c, [bag]),
ets:insert(T3, [{1,1},{1,2},{3,3}]),
@@ -5981,7 +6195,6 @@ take(Config) when is_list(Config) ->
[{3,3}] = ets:take(T3, 3),
[] = ets:tab2list(T3),
ets:delete(T1),
- ets:delete(T2),
ets:delete(T3),
ok.
@@ -6016,9 +6229,366 @@ whereis_table(Config) when is_list(Config) ->
ok.
-%%
-%% Utility functions:
-%%
+
+%% The following work functions are used by
+%% throughput_benchmark/4. They are declared on the top level beacuse
+%% declaring them as function local funs cause a scalability issue.
+get_op([{_,O}], _RandNum) ->
+ O;
+get_op([{Prob,O}|Rest], RandNum) ->
+ case RandNum < Prob of
+ true -> O;
+ false -> get_op(Rest, RandNum)
+ end.
+do_op(Table, ProbHelpTab, Range, Operations) ->
+ RandNum = rand:uniform(),
+ Op = get_op(ProbHelpTab, RandNum),
+ #{ Op := TheOp} = Operations,
+ TheOp(Table, Range).
+do_work(WorksDoneSoFar, Table, ProbHelpTab, Range, Operations) ->
+ receive
+ stop -> WorksDoneSoFar
+ after
+ 0 -> do_op(Table, ProbHelpTab, Range, Operations),
+ do_work(WorksDoneSoFar + 1, Table, ProbHelpTab, Range, Operations)
+ end.
+
+
+throughput_benchmark() ->
+ throughput_benchmark(false, not_set, not_set).
+
+throughput_benchmark(TestMode, BenchmarkRunMs, RecoverTimeMs) ->
+ NrOfSchedulers = erlang:system_info(schedulers),
+ %% Definitions of operations that are supported by the benchmark
+ NextSeqOp =
+ fun (T, KeyRange, SeqSize) ->
+ Start = rand:uniform(KeyRange),
+ Last =
+ lists:foldl(
+ fun(_, Prev) ->
+ case Prev of
+ '$end_of_table'-> ok;
+ _ ->
+ try ets:next(T, Prev) of
+ Normal -> Normal
+ catch
+ error:badarg ->
+ % sets (not ordered_sets) cannot handle when the argument
+ % to next is not in the set
+ rand:uniform(KeyRange)
+ end
+ end
+ end,
+ Start,
+ lists:seq(1, SeqSize)),
+ case Last =:= -1 of
+ true -> io:format("Will never be printed");
+ false -> ok
+ end
+ end,
+ PartialSelectOp =
+ fun (T, KeyRange, SeqSize) ->
+ Start = rand:uniform(KeyRange),
+ Last = Start + SeqSize,
+ case -1 =:= ets:select_count(T,
+ ets:fun2ms(fun({X}) when X > Start andalso X =< Last -> true end)) of
+ true -> io:format("Will never be printed");
+ false -> ok
+ end
+
+ end,
+ %% Mapping benchmark operation names to their corresponding functions that do them
+ Operations =
+ #{insert =>
+ fun(T,KeyRange) ->
+ Num = rand:uniform(KeyRange),
+ ets:insert(T, {Num})
+ end,
+ delete =>
+ fun(T,KeyRange) ->
+ Num = rand:uniform(KeyRange),
+ ets:delete(T, Num)
+ end,
+ lookup =>
+ fun(T,KeyRange) ->
+ Num = rand:uniform(KeyRange),
+ ets:lookup(T, Num)
+ end,
+ nextseq10 =>
+ fun(T,KeyRange) -> NextSeqOp(T,KeyRange,10) end,
+ nextseq100 =>
+ fun(T,KeyRange) -> NextSeqOp(T,KeyRange,100) end,
+ nextseq1000 =>
+ fun(T,KeyRange) -> NextSeqOp(T,KeyRange,1000) end,
+ selectAll =>
+ fun(T,_KeyRange) ->
+ case -1 =:= ets:select_count(T, ets:fun2ms(fun(X) -> true end)) of
+ true -> io:format("Will never be printed");
+ false -> ok
+ end
+ end,
+ partial_select1000 =>
+ fun(T,KeyRange) -> PartialSelectOp(T,KeyRange,1000) end
+ },
+ %% Helper functions
+ CalculateThreadCounts = fun Calculate([Count|Rest]) ->
+ case Count > NrOfSchedulers of
+ true -> lists:reverse(Rest);
+ false -> Calculate([Count*2,Count|Rest])
+ end
+ end,
+ PrefillTable = fun Prefill(T, KeyRange) ->
+ Size = ets:info(T, size),
+ case Size > KeyRange / 2 of
+ true -> ok;
+ false -> ets:insert(T, {rand:uniform(KeyRange)}),
+ Prefill(T, KeyRange)
+ end
+ end,
+ CalculateOpsProbHelpTab =
+ fun Calculate([{_, OpName}], _) ->
+ [{1.0, OpName}];
+ Calculate([{OpPropability, OpName}|Res], Current) ->
+ NewCurrent = Current + OpPropability,
+ [{NewCurrent, OpName}| Calculate(Res, NewCurrent)]
+ end,
+ RenderScenario =
+ fun R([], StringSoFar) ->
+ StringSoFar;
+ R([{Fraction, Operation}], StringSoFar) ->
+ io_lib:format("~s ~f% ~p",[StringSoFar, Fraction * 100.0, Operation]);
+ R([{Fraction, Operation}|Rest], StringSoFar) ->
+ R(Rest,
+ io_lib:format("~s ~f% ~p, ",[StringSoFar, Fraction * 100.0, Operation]))
+ end,
+ SafeFixTableIfRequired =
+ fun(Table, Scenario, On) ->
+ case set =:= ets:info(Table, type) of
+ true ->
+ HasNotRequiringOp =
+ lists:search(
+ fun({_,nextseq10}) -> true;
+ ({_,nextseq100}) -> true;
+ ({_,nextseq1000}) -> true;
+ (_) -> false
+ end, Scenario),
+ case HasNotRequiringOp of
+ false -> ok;
+ _ -> ets:safe_fixtable(Table, On)
+ end;
+ false -> ok
+ end
+ end,
+ %% Function that runs a benchmark instance and returns the number
+ %% of operations that were performed
+ RunBenchmark =
+ fun(NrOfProcs, TableConfig, Scenario,
+ Range, Duration, RecoverTime) ->
+ ProbHelpTab = CalculateOpsProbHelpTab(Scenario, 0),
+ Table = ets:new(t, TableConfig),
+ PrefillTable(Table, Range),
+ SafeFixTableIfRequired(Table, Scenario, true),
+ ParentPid = self(),
+ ChildPids =
+ lists:map(
+ fun(_N) ->
+ spawn(fun() ->
+ receive start -> ok end,
+ WorksDone =
+ do_work(0, Table, ProbHelpTab, Range, Operations),
+ ParentPid ! WorksDone
+ end)
+ end, lists:seq(1, NrOfProcs)),
+ lists:foreach(fun(Pid) -> Pid ! start end, ChildPids),
+ timer:sleep(Duration),
+ lists:foreach(fun(Pid) -> Pid ! stop end, ChildPids),
+ TotalWorksDone = lists:foldl(
+ fun(_, Sum) ->
+ receive
+ Count -> Sum + Count
+ end
+ end, 0, ChildPids),
+ SafeFixTableIfRequired(Table, Scenario, false),
+ ets:delete(Table),
+ timer:sleep(RecoverTime),
+ TotalWorksDone
+ end,
+ %%
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %%%% Benchmark Configuration %%%%%%%%%%%%%%%%%%%%%%%%
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %%
+ %% Change the following variables to configure the benchmark runs
+ ThreadCounts =
+ case TestMode of
+ true -> [1, NrOfSchedulers];
+ false -> CalculateThreadCounts([1])
+ end,
+ KeyRanges = % Sizes of the key ranges
+ case TestMode of
+ true -> [100000];
+ false -> [1000000]
+ end,
+ Duration =
+ case BenchmarkRunMs of % Duration of a benchmark run in milliseconds
+ not_set -> 30000;
+ _ -> BenchmarkRunMs
+ end,
+ TimeMsToSleepAfterEachBenchmarkRun =
+ case RecoverTimeMs of
+ not_set -> 1000;
+ _ -> RecoverTimeMs
+ end,
+ TableTypes = % The table types that will be benchmarked
+ [
+ [ordered_set, public],
+ [ordered_set, public, {write_concurrency, true}],
+ [ordered_set, public, {read_concurrency, true}],
+ [ordered_set, public, {write_concurrency, true}, {read_concurrency, true}],
+ [set, public],
+ [set, public, {write_concurrency, true}],
+ [set, public, {read_concurrency, true}],
+ [set, public, {write_concurrency, true}, {read_concurrency, true}]
+ ],
+ Scenarios = % Benchmark scenarios (the fractions should add up to approximately 1.0)
+ [
+ [
+ {0.5, insert},
+ {0.5, delete}
+ ],
+ [
+ {0.1, insert},
+ {0.1, delete},
+ {0.8, lookup}
+ ],
+ [
+ {0.01, insert},
+ {0.01, delete},
+ {0.98, lookup}
+ ],
+ [
+ {1.0, lookup}
+ ],
+ [
+ {0.1, insert},
+ {0.1, delete},
+ {0.4, lookup},
+ {0.4, nextseq10}
+ ],
+ [
+ {0.1, insert},
+ {0.1, delete},
+ {0.4, lookup},
+ {0.4, nextseq100}
+ ],
+ [
+ {0.1, insert},
+ {0.1, delete},
+ {0.4, lookup},
+ {0.4, nextseq1000}
+ ],
+ [
+ {1.0, nextseq1000}
+ ],
+ [
+ {0.1, insert},
+ {0.1, delete},
+ {0.79, lookup},
+ {0.01, selectAll}
+ ],
+ [
+ {0.1, insert},
+ {0.1, delete},
+ {0.7999, lookup},
+ {0.0001, selectAll}
+ ],
+ [
+ {0.1, insert},
+ {0.1, delete},
+ {0.799999, lookup},
+ {0.000001, selectAll}
+ ],
+ [
+ {0.1, insert},
+ {0.1, delete},
+ {0.79, lookup},
+ {0.01, partial_select1000}
+ ],
+ [
+ {0.1, insert},
+ {0.1, delete},
+ {0.7999, lookup},
+ {0.0001, partial_select1000}
+ ],
+ [
+ {0.1, insert},
+ {0.1, delete},
+ {0.799999, lookup},
+ {0.000001, partial_select1000}
+ ]
+ ],
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %%%% End of Benchmark Configuration %%%%%%%%%%%%%%%%
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ %% Prepare for memory check
+ EtsMem = case TestMode of
+ true -> etsmem();
+ false -> ok
+ end,
+ %% Run the benchmark
+ io:format("# Each instance of the benchmark runs for ~w seconds:~n", [Duration/1000]),
+ io:format("# The result of a benchmark instance is presented as a number representing~n"),
+ io:format("# the number of operations performed per second:~n~n~n"),
+ io:format("# To plot graphs for the results below:~n"),
+ io:format("# 1. Open \"$ERL_TOP/lib/stdlib/test/ets_SUITE_data/visualize_throughput.html\" in a web browser~n"),
+ io:format("# 2. Copy the lines between \"#BENCHMARK STARTED$\" and \"#BENCHMARK ENDED$\" below~n"),
+ io:format("# 3. Paste the lines copied in step 2 to the text box in the browser window opened in~n"),
+ io:format("# step 1 and press the Render button~n~n"),
+ io:format("#BENCHMARK STARTED$~n"),
+ %% The following loop runs all benchmark scenarios and prints the results (i.e, operations/second)
+ lists:foreach(
+ fun(KeyRange) ->
+ lists:foreach(
+ fun(Scenario) ->
+ io:format("Scenario: ~s | Key Range Size: ~w$~n",
+ [RenderScenario(Scenario, ""),
+ KeyRange]),
+ lists:foreach(
+ fun(ThreadCount) ->
+ io:format("; ~w",[ThreadCount])
+ end,
+ ThreadCounts),
+ io:format("$~n",[]),
+ lists:foreach(
+ fun(TableType) ->
+ io:format("~w ",[TableType]),
+ lists:foreach(
+ fun(ThreadCount) ->
+ Result = RunBenchmark(ThreadCount,
+ TableType,
+ Scenario,
+ KeyRange,
+ Duration,
+ TimeMsToSleepAfterEachBenchmarkRun),
+ io:format("; ~f",[Result/(Duration/1000.0)])
+ end,
+ ThreadCounts),
+ io:format("$~n",[])
+ end,
+ TableTypes)
+ end,
+ Scenarios)
+ end,
+ KeyRanges),
+ io:format("~n#BENCHMARK ENDED$~n~n"),
+ case TestMode of
+ true -> verify_etsmem(EtsMem);
+ false -> ok
+ end.
+
+test_throughput_benchmark(Config) when is_list(Config) ->
+ throughput_benchmark(true, 100, 0).
+
add_lists(L1,L2) ->
add_lists(L1,L2,[]).
@@ -6079,8 +6649,11 @@ wait_pids(Pids, Acc) ->
{Pid,Result} ->
true = lists:member(Pid,Pids),
Others = lists:delete(Pid,Pids),
- io:format("wait_pid got ~p from ~p, still waiting for ~p\n",[Result,Pid,Others]),
+ %%io:format("wait_pid got ~p from ~p\n",[Result,Pid]),
wait_pids(Others,[Result | Acc])
+ after 60*1000 ->
+ io:format("Still waiting for workers ~p\n",[Pids]),
+ wait_pids(Pids, Acc)
end.
@@ -6104,19 +6677,25 @@ wait_for_memory_deallocations() ->
wait_for_memory_deallocations()
end.
-
etsmem() ->
- wait_for_memory_deallocations(),
+ % The following is done twice to avoid an inconsistent memory
+ % "snapshot" (see verify_etsmem/2).
+ lists:foldl(
+ fun(_,_) ->
+ wait_for_memory_deallocations(),
- AllTabs = lists:map(fun(T) -> {T,ets:info(T,name),ets:info(T,size),
- ets:info(T,memory),ets:info(T,type)}
- end, ets:all()),
+ AllTabs = lists:map(fun(T) -> {T,ets:info(T,name),ets:info(T,size),
+ ets:info(T,memory),ets:info(T,type)}
+ end, ets:all()),
- EtsAllocSize = erts_debug:alloc_blocks_size(ets_alloc),
- ErlangMemoryEts = try erlang:memory(ets) catch error:notsup -> notsup end,
+ EtsAllocSize = erts_debug:alloc_blocks_size(ets_alloc),
+ ErlangMemoryEts = try erlang:memory(ets) catch error:notsup -> notsup end,
- Mem = {ErlangMemoryEts, EtsAllocSize},
- {Mem, AllTabs}.
+ Mem = {ErlangMemoryEts, EtsAllocSize},
+ {Mem, AllTabs}
+ end,
+ not_used,
+ lists:seq(1,2)).
verify_etsmem(MI) ->
wait_for_test_procs(),
@@ -6137,15 +6716,15 @@ verify_etsmem({MemInfo,AllTabs}, Try) ->
end;
{MemInfo2, AllTabs2} ->
- io:format("Expected: ~p", [MemInfo]),
- io:format("Actual: ~p", [MemInfo2]),
- io:format("Changed tables before: ~p\n",[AllTabs -- AllTabs2]),
- io:format("Changed tables after: ~p\n", [AllTabs2 -- AllTabs]),
+ io:format("#Expected: ~p", [MemInfo]),
+ io:format("#Actual: ~p", [MemInfo2]),
+ io:format("#Changed tables before: ~p\n",[AllTabs -- AllTabs2]),
+ io:format("#Changed tables after: ~p\n", [AllTabs2 -- AllTabs]),
case Try < 2 of
true ->
- io:format("\nThis discrepancy could be caused by an "
+ io:format("\n#This discrepancy could be caused by an "
"inconsistent memory \"snapshot\""
- "\nTry again...\n", []),
+ "\n#Try again...\n", []),
verify_etsmem({MemInfo, AllTabs}, Try+1);
false ->
ct:fail("Failed memory check")
@@ -6619,6 +7198,27 @@ make_unaligned_sub_binary(List) ->
repeat_for_opts(F) ->
repeat_for_opts(F, [write_concurrency, read_concurrency, compressed]).
+repeat_for_opts_all_table_types(F) ->
+ repeat_for_opts(F, [all_types, write_concurrency, read_concurrency, compressed]).
+
+repeat_for_opts_all_non_stim_table_types(F) ->
+ repeat_for_opts(F, [all_non_stim_types, write_concurrency, read_concurrency, compressed]).
+
+repeat_for_opts_all_set_table_types(F) ->
+ repeat_for_opts(F, [set_types, write_concurrency, read_concurrency, compressed]).
+
+repeat_for_all_set_table_types(F) ->
+ repeat_for_opts(F, [set_types]).
+
+repeat_for_all_ord_set_table_types(F) ->
+ repeat_for_opts(F, [ord_set_types]).
+
+repeat_for_all_non_stim_set_table_types(F) ->
+ repeat_for_opts(F, [all_non_stim_set_types]).
+
+repeat_for_opts_all_ord_set_table_types(F) ->
+ repeat_for_opts(F, [ord_set_types, write_concurrency, read_concurrency, compressed]).
+
repeat_for_opts(F, OptGenList) when is_function(F, 1) ->
repeat_for_opts(F, OptGenList, []).
@@ -6642,14 +7242,112 @@ repeat_for_opts(F, [OptList | Tail], AccList) when is_list(OptList) ->
repeat_for_opts(F, [Atom | Tail], AccList) when is_atom(Atom) ->
repeat_for_opts(F, [repeat_for_opts_atom2list(Atom) | Tail ], AccList).
-repeat_for_opts_atom2list(all_types) -> [set,ordered_set,bag,duplicate_bag];
+repeat_for_opts_atom2list(set_types) -> [void,set,ordered_set,stim_cat_ord_set,cat_ord_set];
+repeat_for_opts_atom2list(ord_set_types) -> [ordered_set,stim_cat_ord_set,cat_ord_set];
+repeat_for_opts_atom2list(all_types) -> [void,set,ordered_set,stim_cat_ord_set,cat_ord_set,bag,duplicate_bag];
+repeat_for_opts_atom2list(all_non_stim_types) -> [void,set,ordered_set,cat_ord_set,bag,duplicate_bag];
+repeat_for_opts_atom2list(all_non_stim_set_types) -> [void,set,ordered_set,cat_ord_set];
repeat_for_opts_atom2list(write_concurrency) -> [{write_concurrency,false},{write_concurrency,true}];
repeat_for_opts_atom2list(read_concurrency) -> [{read_concurrency,false},{read_concurrency,true}];
repeat_for_opts_atom2list(compressed) -> [compressed,void].
+
ets_new(Name, Opts) ->
- %%ets:new(Name, [compressed | Opts]).
- ets:new(Name, Opts).
+ ReplaceStimOrdSetHelper =
+ fun (MOpts) ->
+ lists:map(fun (I) ->
+ case I of
+ stim_cat_ord_set -> ordered_set;
+ cat_ord_set -> ordered_set;
+ _ -> I
+ end
+ end, MOpts)
+ end,
+ EtsNewHelper =
+ fun (MOpts) ->
+ UseOpts = ReplaceStimOrdSetHelper(MOpts),
+ case get(ets_new_opts) of
+ UseOpts ->
+ silence; %% suppress identical table opts spam
+ _ ->
+ put(ets_new_opts, UseOpts),
+ io:format("ets:new(~p, ~p)~n", [Name, UseOpts])
+ end,
+ ets:new(Name, UseOpts)
+ end,
+ case (lists:member(stim_cat_ord_set, Opts) or
+ lists:member(cat_ord_set, Opts)) andalso
+ (not lists:member({write_concurrency, false}, Opts)) andalso
+ (not lists:member(private, Opts)) andalso
+ (not lists:member(protected, Opts)) of
+ true ->
+ NewOpts1 =
+ case lists:member({write_concurrency, true}, Opts) of
+ true -> Opts;
+ false -> [{write_concurrency, true}|Opts]
+ end,
+ NewOpts2 =
+ case lists:member(public, NewOpts1) of
+ true -> NewOpts1;
+ false -> [public|NewOpts1]
+ end,
+ T = EtsNewHelper(NewOpts2),
+ case lists:member(stim_cat_ord_set, Opts) of
+ true -> stimulate_contention(T);
+ false -> ok
+ end,
+ T;
+ false ->
+ EtsNewHelper(Opts)
+ end.
+
+% This function do the following to the input ETS table:
+% 1. Perform a number of concurrent insert operations
+% 2. Remove all inserted items
+%
+% The purpose of this function is to stimulate fine grained locking in
+% tables of types ordered_set with the write_concurrency options
+% turned on. Such tables are implemented as CA trees* and thus
+% activates fine grained locking only when lock contention is
+% detected.
+%
+% A Contention Adapting Approach to Concurrent Ordered Sets
+% Journal of Parallel and Distributed Computing, 2018
+% Kjell Winblad and Konstantinos Sagonas
+% https://doi.org/10.1016/j.jpdc.2017.11.007
+stimulate_contention(T) ->
+ NrOfSchedulers = erlang:system_info(schedulers),
+ ParentPid = self(),
+ KeyRange = 100000,
+ ChildPids =
+ lists:map(fun(_N) ->
+ spawn(fun() ->
+ receive start -> ok end,
+ stimulate_contention_do_inserts(T, KeyRange, 0),
+ ParentPid ! done
+ end)
+ end, lists:seq(1, NrOfSchedulers)),
+ lists:foreach(fun(Pid) -> Pid ! start end, ChildPids),
+ timer:sleep(100),
+ lists:foreach(fun(Pid) -> Pid ! stop end, ChildPids),
+ lists:foreach(fun(_P) -> receive done -> ok end end, ChildPids),
+ lists:foreach(fun(N) -> ets:delete(T, N) end, lists:seq(0, KeyRange)).
+
+
+
+stimulate_contention_do_inserts(T, KeyRange, 0) ->
+ OpsBetweenStopCheck = 10000,
+ receive
+ stop -> ok
+ after
+ 0 -> stimulate_contention_do_inserts(T, KeyRange, OpsBetweenStopCheck)
+ end;
+stimulate_contention_do_inserts(T, KeyRange, OpsToNextStopCheck) ->
+ R = trunc(KeyRange * rand:uniform()),
+ ets:insert(T,{R,R,R}),
+ stimulate_contention_do_inserts(T, KeyRange, OpsToNextStopCheck - 1).
+
+
do_tc(Do, Report) ->
T1 = erlang:monotonic_time(),
diff --git a/lib/stdlib/test/ets_SUITE_data/visualize_throughput.html b/lib/stdlib/test/ets_SUITE_data/visualize_throughput.html
new file mode 100644
index 0000000000..a2c61aa938
--- /dev/null
+++ b/lib/stdlib/test/ets_SUITE_data/visualize_throughput.html
@@ -0,0 +1,253 @@
+<!doctype html>
+<html lang="en">
+
+<!-- %% -->
+<!-- %% %CopyrightBegin% -->
+<!-- %% -->
+<!-- %% Copyright Ericsson AB and Kjell Winblad 1996-2018. All Rights Reserved. -->
+<!-- %% -->
+<!-- %% Licensed under the Apache License, Version 2.0 (the "License"); -->
+<!-- %% you may not use this file except in compliance with the License. -->
+<!-- %% You may obtain a copy of the License at -->
+<!-- %% -->
+<!-- %% http://www.apache.org/licenses/LICENSE-2.0 -->
+<!-- %% -->
+<!-- %% Unless required by applicable law or agreed to in writing, software -->
+<!-- %% distributed under the License is distributed on an "AS IS" BASIS, -->
+<!-- %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -->
+<!-- %% See the License for the specific language governing permissions and -->
+<!-- %% limitations under the License. -->
+<!-- %% -->
+<!-- %% %CopyrightEnd% -->
+<!-- %% -->
+<!-- %% Author: Kjell Winblad -->
+<!-- %% -->
+
+ <head>
+ <meta charset="utf-8">
+ <title>ETS Benchmark Result Viewer</title>
+ </head>
+
+ <body>
+ <div id="insertPlaceholder"></div>
+ <h1>ETS Benchmark Result Viewer</h1>
+ <p>
+ This page generates graphs from data produced by the ETS benchmark which is defined in the function <code>ets_SUITE:throughput_benchmark/0</code> (see "<code>$ERL_TOP/lib/stdlib/test/ets_SUITE.erl</code>").
+ </p>
+ <p>
+ Note that one can paste results from several benchmark runs into the field below. Results from the same scenario but from different benchmark runs will be relabeled and ploted in the same graph automatically. This makes comparisons of different ETS versions easy.
+ </p>
+ <p>
+ Note also that that lines can be hidden by clicking on the corresponding label.
+ </p>
+ Paste the generated data in the field below and press the Render button:
+ <br>
+ <textarea id="dataField" rows="4" cols="50"></textarea>
+ <br>
+ <input type="checkbox" id="barPlot"> Bar Plot
+ <br>
+ <input type="checkbox" id="sameSpacing" checked> Same X Spacing Between Points
+ <br>
+ <input type="checkbox" class="showCheck" value="[ordered_set,public]" checked> Show <code>[ordered_set,public]</code>
+ <br>
+ <input type="checkbox" class="showCheck" value="[ordered_set,public,{write_concurrency,true}]" checked> Show <code>[ordered_set,public,{write_concurrency,true}]</code>
+ <br>
+ <input type="checkbox" class="showCheck" value="[ordered_set,public,{read_concurrency,true}]" checked> Show <code>[ordered_set,public,{read_concurrency,true}]</code>
+ <br>
+ <input type="checkbox" class="showCheck" value="[ordered_set,public,{write_concurrency,true},{read_concurrency,true}]" checked> Show <code>[ordered_set,public,{write_concurrency,true},{read_concurrency,true}]</code>
+ <br>
+ <input type="checkbox" class="showCheck" value="[set,public]"> Show <code>[set,public]</code>
+ <br>
+ <input type="checkbox" class="showCheck" value="[set,public,{write_concurrency,true}]"> Show <code>[set,public,{write_concurrency,true}]</code>
+ <br>
+ <input type="checkbox" class="showCheck" value="[set,public,{read_concurrency,true}]"> Show <code>[set,public,{read_concurrency,true}]</code>
+ <br>
+ <input type="checkbox" class="showCheck" value="[set,public,{write_concurrency,true},{read_concurrency,true}]"> Show <code>[set,public,{write_concurrency,true},{read_concurrency,true}]</code>
+ <br>
+ <button id="renderButton" type="button">Render</button>
+
+ <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
+ integrity="sha256-3edrmyuQ0w65f8gfBsqowzjJe2iM6n0nKciPUp8y+7E="
+ crossorigin="anonymous"></script>
+ <script>
+ var loading = false;
+ function toggleLoadingScreen(){
+ if(loading){
+ $("#loading").remove();
+ loading = false;
+ }else{
+ $('<div id="loading">'+
+ '<span style="position: fixed; top: 50%;left: 50%;color: white;"><b>Loading...</b></span>'+
+ '</div>')
+ .css({position: "fixed",
+ top: 0,
+ left: 0,
+ width: "100%",
+ height: "100%",
+ 'background-color': "#000",
+ filter:"alpha(opacity=50)",
+ '-moz-opacity':"0.5",
+ '-khtml-opacity': "0.5",
+ opacity: "0.5",
+ 'z-index': "10000"})
+ .appendTo(document.body);
+ loading = true;
+
+ }
+ }
+ //Start loading screen before downloading plotly which is quite large
+ toggleLoadingScreen();
+ </script>
+ <script src="https://cdn.plot.ly/plotly-1.5.0.min.js"></script>
+ <script>
+ String.prototype.replaceAll = function(search, replacement) {
+ var target = this;
+ return target.split(search).join(replacement);
+ };
+ String.prototype.myTrim = function() {
+ var target = this;
+ return target.replace(/^\s+|\s+$/g, '');
+ };
+ function plotGraph(lines, sameSpacing, barPlot, prefix) {
+ var xvals = null;
+ var data = [];
+ while(lines.length > 0 &&
+ (lines[0].myTrim() == "" ||
+ lines[0].myTrim().indexOf(";") !== -1)){
+ var line = lines.shift().myTrim();
+ if(line == "" || line.startsWith("#")){
+ continue;
+ } else if(line.startsWith(";")) {
+ xvals = line.split(";")
+ xvals.shift(); // Remove first
+ xvals = $.map(xvals, function (i){
+ if(sameSpacing){
+ return "_"+i.myTrim();
+ }else{
+ return parseInt(i.myTrim(), 10);
+ }
+ });
+ }else{
+ line = line.split(";")
+ var label = prefix + line.shift().myTrim();
+ var yvals = $.map(line, function (i){
+ return parseFloat(i.myTrim(), 10);
+ });
+ var trace = {
+ x: xvals,
+ y: yvals,
+ mode: 'lines+markers',
+ name: label
+ };
+ if(barPlot){
+ trace['type'] = "bar";
+ }
+ data.push(trace);
+ }
+
+ }
+ return data;
+ }
+ function plotGraphs(){
+ var insertPlaceholder = $("#insertPlaceholder");
+ var sameSpacing = $('#sameSpacing').is(":checked");
+ var barPlot = $('#barPlot').is(":checked");
+ var lines = $("#dataField").val();
+ $('.showCheck').each(function() {
+ var item = $(this);
+ if(!item.is(":checked")){
+ lines = lines.replaceAll(item.val(), "#"+item.val())
+ }
+ });
+ lines = lines.split("$");
+ var nrOfGraphs = 0;
+ var scenarioDataMap = {};
+ var scenarioNrOfVersionsMap = {};
+ var scenarioList = [];
+ while(lines.length > 0){
+ var line = lines.shift().myTrim();
+ if(line == ""){
+ continue;
+ } else if(line.startsWith("Scenario:")) {
+ nrOfGraphs = nrOfGraphs + 1;
+ var name = line;
+ if(scenarioDataMap[name] === undefined){
+ scenarioDataMap[name] = [];
+ scenarioNrOfVersionsMap[name] = 0;
+ scenarioList.push(line);
+ }
+ scenarioNrOfVersionsMap[name] = scenarioNrOfVersionsMap[name] + 1;
+ var prefix = undefined;
+ if(scenarioNrOfVersionsMap[name] === 1){
+ prefix = "";
+ }else{
+ prefix = "Ver: " + scenarioNrOfVersionsMap[name] + " ";
+ }
+ scenarioDataMap[name] =
+ scenarioDataMap[name].concat(
+ plotGraph(lines, sameSpacing, barPlot, prefix));
+ }
+ }
+ $.each(scenarioList,
+ function( index, name ) {
+ var nrOfGraphs = index + 1;
+ var data = scenarioDataMap[name];
+ $( "<div class='added' id='graph"+nrOfGraphs+"'>")
+ .insertBefore( insertPlaceholder );
+ $( "<button type='button' class='added' id='fullscreenButton"+nrOfGraphs+"'>Fill screen</button>")
+ .insertBefore( insertPlaceholder );
+ $( "<span class='added'><br><hr><br></span>")
+ .insertBefore( insertPlaceholder );
+ var layout = {
+ title:name,
+ xaxis: {
+ title: '# of Processes'
+ },
+ yaxis: {
+ title: 'Operations/Second'
+ }
+
+ };
+
+ $("#fullscreenButton"+nrOfGraphs).click(
+ function(){
+ $('#graph'+nrOfGraphs).replaceWith(
+ $("<div class='added' id='graph"+nrOfGraphs+"'>"));
+ layout = $.extend({}, layout, {
+ width:$(window).width()-40,
+ height:$(window).height()-40
+ });
+ Plotly.newPlot('graph'+nrOfGraphs, data, layout);
+ });
+ Plotly.newPlot('graph'+nrOfGraphs, data, layout);
+
+ });
+
+
+ }
+ $(document).ready(function(){
+ $('#renderButton').click(
+ function(){
+ toggleLoadingScreen();
+ setTimeout(function(){
+ try {
+ $( ".added" ).remove();
+ plotGraphs();
+ toggleLoadingScreen();
+ } catch(e){
+ toggleLoadingScreen();
+ console.log(e);
+ alert("Error happened when parsing data.\n" +
+ "See console for more info");
+ }
+ }, 10);
+ });
+ setTimeout(function(){
+ $( ".added" ).remove();
+ plotGraphs();
+ toggleLoadingScreen();
+ }, 10);
+ });
+ </script>
+ </body>
+</html>
diff --git a/lib/stdlib/test/gen_statem_SUITE.erl b/lib/stdlib/test/gen_statem_SUITE.erl
index 053233df9b..017939fdd6 100644
--- a/lib/stdlib/test/gen_statem_SUITE.erl
+++ b/lib/stdlib/test/gen_statem_SUITE.erl
@@ -121,7 +121,8 @@ end_per_testcase(_CaseName, Config) ->
start1(Config) ->
%%OldFl = process_flag(trap_exit, true),
- {ok,Pid0} = gen_statem:start_link(?MODULE, start_arg(Config, []), []),
+ {ok,Pid0} =
+ gen_statem:start_link(?MODULE, start_arg(Config, []), [{debug,[trace]}]),
ok = do_func_test(Pid0),
ok = do_sync_func_test(Pid0),
stop_it(Pid0),
@@ -135,7 +136,8 @@ start1(Config) ->
%% anonymous w. shutdown
start2(Config) ->
%% Dont link when shutdown
- {ok,Pid0} = gen_statem:start(?MODULE, start_arg(Config, []), []),
+ {ok,Pid0} =
+ gen_statem:start(?MODULE, start_arg(Config, []), []),
ok = do_func_test(Pid0),
ok = do_sync_func_test(Pid0),
stopped = gen_statem:call(Pid0, {stop,shutdown}),
@@ -641,51 +643,72 @@ state_enter(_Config) ->
end,
start =>
fun (enter, Prev, N) ->
- Self ! {enter,start,Prev,N},
+ Self ! {N,enter,start,Prev},
{keep_state,N + 1};
(internal, Prev, N) ->
- Self ! {internal,start,Prev,N},
+ Self ! {N,internal,start,Prev},
{keep_state,N + 1};
+ (timeout, M, N) ->
+ {keep_state, N + 1,
+ {reply, {Self,N}, {timeout,M}}};
({call,From}, repeat, N) ->
{repeat_state,N + 1,
- [{reply,From,{repeat,start,N}}]};
+ [{reply,From,{N,repeat,start}}]};
({call,From}, echo, N) ->
{next_state,wait,N + 1,
- {reply,From,{echo,start,N}}};
+ [{reply,From,{N,echo,start}},{timeout,0,N}]};
({call,From}, {stop,Reason}, N) ->
{stop_and_reply,Reason,
- [{reply,From,{stop,N}}],N + 1}
+ [{reply,From,{N,stop}}],N + 1}
end,
wait =>
fun (enter, Prev, N) when N < 5 ->
{repeat_state,N + 1,
- {reply,{Self,N},{enter,Prev}}};
+ [{reply,{Self,N},{enter,Prev}},
+ {timeout,0,N},
+ {state_timeout,0,N}]};
(enter, Prev, N) ->
- Self ! {enter,wait,Prev,N},
- {keep_state,N + 1};
+ Self ! {N,enter,wait,Prev},
+ {keep_state,N + 1,
+ [{timeout,0,N},
+ {state_timeout,0,N}]};
+ (timeout, M, N) ->
+ {keep_state, N + 1,
+ {reply, {Self,N}, {timeout,M}}};
+ (state_timeout, M, N) ->
+ {keep_state, N + 1,
+ {reply, {Self,N}, {state_timeout,M}}};
({call,From}, repeat, N) ->
{repeat_state_and_data,
- [{reply,From,{repeat,wait,N}}]};
+ [{reply,From,{N,repeat,wait}},
+ {timeout,0,N}]};
({call,From}, echo, N) ->
{next_state,start,N + 1,
[{next_event,internal,wait},
- {reply,From,{echo,wait,N}}]}
+ {reply,From,{N,echo,wait}}]}
end},
{ok,STM} =
gen_statem:start_link(
- ?MODULE, {map_statem,Machine,[state_enter]}, []),
-
- [{enter,start,start,1}] = flush(),
- {echo,start,2} = gen_statem:call(STM, echo),
- [{3,{enter,start}},{4,{enter,start}},{enter,wait,start,5}] = flush(),
- {wait,[6|_]} = sys:get_state(STM),
- {repeat,wait,6} = gen_statem:call(STM, repeat),
- [{enter,wait,wait,6}] = flush(),
- {echo,wait,7} = gen_statem:call(STM, echo),
- [{enter,start,wait,8},{internal,start,wait,9}] = flush(),
- {repeat,start,10} = gen_statem:call(STM, repeat),
- [{enter,start,start,11}] = flush(),
- {stop,12} = gen_statem:call(STM, {stop,bye}),
+ ?MODULE, {map_statem,Machine,[state_enter]}, [{debug,[trace]}]),
+
+ [{1,enter,start,start}] = flush(),
+ {2,echo,start} = gen_statem:call(STM, echo),
+ [{3,{enter,start}},
+ {4,{enter,start}},
+ {5,enter,wait,start},
+ {6,{timeout,5}},
+ {7,{state_timeout,5}}] = flush(),
+ {wait,[8|_]} = sys:get_state(STM),
+ {8,repeat,wait} = gen_statem:call(STM, repeat),
+ [{8,enter,wait,wait},
+ {9,{timeout,8}},
+ {10,{state_timeout,8}}] = flush(),
+ {11,echo,wait} = gen_statem:call(STM, echo),
+ [{12,enter,start,wait},
+ {13,internal,start,wait}] = flush(),
+ {14,repeat,start} = gen_statem:call(STM, repeat),
+ [{15,enter,start,start}] = flush(),
+ {16,stop} = gen_statem:call(STM, {stop,bye}),
[{'EXIT',STM,bye}] = flush(),
{noproc,_} =
diff --git a/lib/stdlib/test/io_SUITE.erl b/lib/stdlib/test/io_SUITE.erl
index 79cee54335..f097552e8c 100644
--- a/lib/stdlib/test/io_SUITE.erl
+++ b/lib/stdlib/test/io_SUITE.erl
@@ -31,7 +31,7 @@
otp_10836/1, io_lib_width_too_small/1,
io_with_huge_message_queue/1, format_string/1,
maps/1, coverage/1, otp_14178_unicode_atoms/1, otp_14175/1,
- otp_14285/1, limit_term/1, otp_14983/1, otp_15103/1,
+ otp_14285/1, limit_term/1, otp_14983/1, otp_15103/1, otp_15076/1,
otp_15159/1]).
-export([pretty/2, trf/3]).
@@ -64,7 +64,7 @@ all() ->
io_lib_print_binary_depth_one, otp_10302, otp_10755, otp_10836,
io_lib_width_too_small, io_with_huge_message_queue,
format_string, maps, coverage, otp_14178_unicode_atoms, otp_14175,
- otp_14285, limit_term, otp_14983, otp_15103, otp_15159].
+ otp_14285, limit_term, otp_14983, otp_15103, otp_15076, otp_15159].
%% Error cases for output.
error_1(Config) when is_list(Config) ->
@@ -2639,3 +2639,11 @@ otp_15159(_Config) ->
"[atom]" =
lists:flatten(io_lib:format("~p", [[atom]], [{chars_limit,5}])),
ok.
+
+otp_15076(_Config) ->
+ {'EXIT', {badarg, _}} = (catch io_lib:format("~c", [a])),
+ L = io_lib:scan_format("~c", [a]),
+ {"~c", [a]} = io_lib:unscan_format(L),
+ {'EXIT', {badarg, _}} = (catch io_lib:build_text(L)),
+ {'EXIT', {badarg, _}} = (catch io_lib:build_text(L, [])),
+ ok.
diff --git a/lib/stdlib/test/rand_SUITE.erl b/lib/stdlib/test/rand_SUITE.erl
index d753d929f5..4cb1c0b13d 100644
--- a/lib/stdlib/test/rand_SUITE.erl
+++ b/lib/stdlib/test/rand_SUITE.erl
@@ -21,24 +21,7 @@
-compile({nowarn_deprecated_function,[{random,seed,1},
{random,uniform_s,1},
{random,uniform_s,2}]}).
-
--export([all/0, suite/0, groups/0, group/1]).
-
--export([interval_int/1, interval_float/1, seed/1,
- api_eq/1, reference/1,
- basic_stats_uniform_1/1, basic_stats_uniform_2/1,
- basic_stats_standard_normal/1,
- basic_stats_normal/1,
- stats_standard_normal_box_muller/1,
- stats_standard_normal_box_muller_2/1,
- stats_standard_normal/1,
- uniform_real_conv/1,
- plugin/1, measure/1,
- reference_jump_state/1, reference_jump_procdict/1]).
-
--export([test/0, gen/1]).
-
--export([uniform_real_gen/1, uniform_gen/2]).
+-compile([export_all, nowarn_export_all]).
-include_lib("common_test/include/ct.hrl").
@@ -56,7 +39,8 @@ all() ->
{group, distr_stats},
uniform_real_conv,
plugin, measure,
- {group, reference_jump}
+ {group, reference_jump},
+ short_jump
].
groups() ->
@@ -95,7 +79,7 @@ test() ->
end, Tests).
algs() ->
- [exrop, exsp, exs1024s, exs64, exsplus, exs1024].
+ [exrop, exsp, exs1024s, exs64, exsplus, exs1024, exro928ss].
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -125,7 +109,7 @@ seed_1(Alg) ->
S0 = get(rand_seed),
S0 = rand:seed_s(Alg, {0, 0, 0}),
%% Check that process_dict should not be used for seed_s functionality
- _ = rand:seed_s(Alg, {1, 0, 0}),
+ _ = rand:seed_s(Alg, 4711),
S0 = get(rand_seed),
%% Test export
ES0 = rand:export_seed(),
@@ -262,31 +246,43 @@ reference(Config) when is_list(Config) ->
ok.
reference_1(Alg) ->
- Refval = reference_val(Alg),
- Testval = gen(Alg),
- case Refval =:= Testval of
- true -> ok;
- false when Refval =:= not_implemented ->
- exit({not_implemented,Alg});
- false ->
- io:format("Failed: ~p~n",[Alg]),
- io:format("Length ~p ~p~n",[length(Refval), length(Testval)]),
- io:format("Head ~p ~p~n",[hd(Refval), hd(Testval)]),
- exit(wrong_value)
+ Refval = reference_val(Alg),
+ if
+ Refval =:= not_implemented -> Refval;
+ true ->
+ case gen(Alg) of
+ Refval ->
+ io:format("Ok: ~p~n",[Alg]),
+ ok;
+ Testval ->
+ io:format("Failed: ~p~n",[Alg]),
+ io:format("Length ~p ~p~n",[length(Refval), length(Testval)]),
+ io:format("Head ~p ~p~n",[hd(Refval), hd(Testval)]),
+ show_wrong(Refval, Testval),
+ exit(wrong_value)
+ end
end.
+show_wrong([], []) ->
+ ok;
+show_wrong([H|T1], [H|T2]) ->
+ show_wrong(T1, T2);
+show_wrong([H1|_], [H2|_]) ->
+ io:format("Wrong ~p ~p~n",[H1,H2]).
+
+
gen(Algo) ->
State =
- case Algo of
- exs64 -> %% Printed with orig 'C' code and this seed
- rand:seed_s({exs64, 12345678});
- _ when Algo =:= exsplus; Algo =:= exsp; Algo =:= exrop ->
+ if
+ Algo =:= exs64 -> %% Printed with orig 'C' code and this seed
+ rand:seed_s(exs64, [12345678]);
+ Algo =:= exsplus; Algo =:= exsp; Algo =:= exrop ->
%% Printed with orig 'C' code and this seed
- rand:seed_s({Algo, [12345678|12345678]});
- _ when Algo =:= exs1024; Algo =:= exs1024s ->
+ rand:seed_s(Algo, [12345678,12345678]);
+ Algo =:= exs1024; Algo =:= exs1024s; Algo =:= exro928ss ->
%% Printed with orig 'C' code and this seed
- rand:seed_s({Algo, {lists:duplicate(16, 12345678), []}});
- _ ->
+ rand:seed_s(Algo, lists:duplicate(16, 12345678));
+ true ->
rand:seed(Algo, {100, 200, 300})
end,
Max = range(State),
@@ -852,7 +848,8 @@ do_measure(_Config) ->
Algs =
algs() ++
try crypto:strong_rand_bytes(1) of
- <<_>> -> [crypto64, crypto_cache, crypto]
+ <<_>> ->
+ [crypto64, crypto_cache, crypto_aes, crypto]
catch
error:low_entropy -> [];
error:undef -> []
@@ -1101,6 +1098,10 @@ measure_1(RangeFun, Fun, Alg, TMark) ->
{rand, crypto:rand_seed_alg(crypto_cache)};
crypto ->
{rand, crypto:rand_seed_s()};
+ crypto_aes ->
+ {rand,
+ crypto:rand_seed_alg(
+ crypto_aes, crypto:strong_rand_bytes(256))};
random ->
{random, random:seed(os:timestamp()), get(random_seed)};
_ ->
@@ -1116,7 +1117,7 @@ measure_1(RangeFun, Fun, Alg, TMark) ->
_ -> (Time * 100 + 50) div TMark
end,
io:format(
- "~.12w: ~p ns ~p% [16#~.16b]~n",
+ "~.20w: ~p ns ~p% [16#~.16b]~n",
[Alg, (Time * 1000 + 500) div ?LOOP_MEASURE,
Percent, Range]),
Parent ! {self(), Time},
@@ -1141,104 +1142,156 @@ reference_jump_state(Config) when is_list(Config) ->
ok.
reference_jump_1(Alg) ->
- Refval = reference_jump_val(Alg),
- Testval = gen_jump_1(Alg),
- case Refval =:= Testval of
- true -> ok;
- false ->
- io:format("Failed: ~p~n",[Alg]),
- io:format("Length ~p ~p~n",[length(Refval), length(Testval)]),
- io:format("Head ~p ~p~n",[hd(Refval), hd(Testval)]),
- io:format("Vals ~p ~p~n",[Refval, Testval]),
- exit(wrong_value)
+ Refval = reference_jump_val(Alg),
+ if
+ Refval =:= not_implemented -> Refval;
+ true ->
+ case gen_jump_1(Alg) of
+ Refval -> ok;
+ Testval ->
+ io:format(
+ "Failed: ~p~n",[Alg]),
+ io:format(
+ "Length ~p ~p~n",
+ [length(Refval), length(Testval)]),
+ io:format(
+ "Head ~p ~p~n",[hd(Refval), hd(Testval)]),
+ io:format(
+ "Vals ~p ~p~n",[Refval, Testval]),
+ exit(wrong_value)
+ end
end.
gen_jump_1(Algo) ->
- State =
- case Algo of
- exs64 -> %% Test exception of not_implemented notice
- try rand:jump(rand:seed_s(exs64))
- catch
- error:not_implemented -> not_implemented
- end;
- _ when Algo =:= exsplus; Algo =:= exsp; Algo =:= exrop ->
- %% Printed with orig 'C' code and this seed
- rand:seed_s({Algo, [12345678|12345678]});
- _ when Algo =:= exs1024; Algo =:= exs1024s ->
- %% Printed with orig 'C' code and this seed
- rand:seed_s({Algo, {lists:duplicate(16, 12345678), []}});
- _ -> % unimplemented
- not_implemented
- end,
- case State of
- not_implemented -> [not_implemented];
- _ ->
- Max = range(State),
- gen_jump_1(?LOOP_JUMP, State, Max, [])
+ case Algo of
+ exs64 -> %% Test exception of not_implemented notice
+ try rand:jump(rand:seed_s(exs64))
+ catch
+ error:not_implemented -> [error_not_implemented]
+ end;
+ _ when Algo =:= exsplus; Algo =:= exsp; Algo =:= exrop ->
+ %% Printed with orig 'C' code and this seed
+ gen_jump_2(
+ rand:seed_s(Algo, [12345678,12345678]));
+ _ when Algo =:= exs1024; Algo =:= exs1024s; Algo =:= exro928ss ->
+ %% Printed with orig 'C' code and this seed
+ gen_jump_2(
+ rand:seed_s(Algo, lists:duplicate(16, 12345678)))
end.
-gen_jump_1(N, State0, Max, Acc) when N > 0 ->
+gen_jump_2(State) ->
+ Max = range(State),
+ gen_jump_3(?LOOP_JUMP, State, Max, []).
+
+gen_jump_3(N, State0, Max, Acc) when N > 0 ->
{_, State1} = rand:uniform_s(Max, State0),
{Random, State2} = rand:uniform_s(Max, rand:jump(State1)),
case N rem (?LOOP_JUMP div 100) of
- 0 -> gen_jump_1(N-1, State2, Max, [Random|Acc]);
- _ -> gen_jump_1(N-1, State2, Max, Acc)
+ 0 -> gen_jump_3(N-1, State2, Max, [Random|Acc]);
+ _ -> gen_jump_3(N-1, State2, Max, Acc)
end;
-gen_jump_1(_, _, _, Acc) -> lists:reverse(Acc).
+gen_jump_3(_, _, _, Acc) -> lists:reverse(Acc).
%% Check if each algorithm generates the proper jump sequence
%% with the internal state in the process dictionary.
reference_jump_procdict(Config) when is_list(Config) ->
- [reference_jump_0(Alg) || Alg <- algs()],
+ [reference_jump_p1(Alg) || Alg <- algs()],
ok.
-reference_jump_0(Alg) ->
+reference_jump_p1(Alg) ->
Refval = reference_jump_val(Alg),
- Testval = gen_jump_0(Alg),
- case Refval =:= Testval of
- true -> ok;
- false ->
- io:format("Failed: ~p~n",[Alg]),
- io:format("Length ~p ~p~n",[length(Refval), length(Testval)]),
- io:format("Head ~p ~p~n",[hd(Refval), hd(Testval)]),
- exit(wrong_value)
+ if
+ Refval =:= not_implemented -> Refval;
+ true ->
+ case gen_jump_p1(Alg) of
+ Refval -> ok;
+ Testval ->
+ io:format("Failed: ~p~n",[Alg]),
+ io:format("Length ~p ~p~n",[length(Refval), length(Testval)]),
+ io:format("Head ~p ~p~n",[hd(Refval), hd(Testval)]),
+ exit(wrong_value)
+ end
end.
-gen_jump_0(Algo) ->
- Seed = case Algo of
- exs64 -> %% Test exception of not_implemented notice
- try
- _ = rand:seed(exs64),
- rand:jump()
- catch
- error:not_implemented -> not_implemented
- end;
- _ when Algo =:= exsplus; Algo =:= exsp; Algo =:= exrop ->
- %% Printed with orig 'C' code and this seed
- rand:seed({Algo, [12345678|12345678]});
- _ when Algo =:= exs1024; Algo =:= exs1024s ->
- %% Printed with orig 'C' code and this seed
- rand:seed({Algo, {lists:duplicate(16, 12345678), []}});
- _ -> % unimplemented
- not_implemented
- end,
- case Seed of
- not_implemented -> [not_implemented];
- _ ->
- Max = range(Seed),
- gen_jump_0(?LOOP_JUMP, Max, [])
+gen_jump_p1(Algo) ->
+ case Algo of
+ exs64 -> %% Test exception of not_implemented notice
+ try
+ _ = rand:seed(exs64),
+ rand:jump()
+ catch
+ error:not_implemented -> [error_not_implemented]
+ end;
+ _ when Algo =:= exsplus; Algo =:= exsp; Algo =:= exrop ->
+ %% Printed with orig 'C' code and this seed
+ gen_jump_p2(
+ rand:seed(Algo, [12345678,12345678]));
+ _ when Algo =:= exs1024; Algo =:= exs1024s; Algo =:= exro928ss ->
+ %% Printed with orig 'C' code and this seed
+ gen_jump_p2(
+ rand:seed(Algo, lists:duplicate(16, 12345678)))
end.
-gen_jump_0(N, Max, Acc) when N > 0 ->
+gen_jump_p2(Seed) ->
+ Max = range(Seed),
+ gen_jump_p3(?LOOP_JUMP, Max, []).
+
+gen_jump_p3(N, Max, Acc) when N > 0 ->
_ = rand:uniform(Max),
_ = rand:jump(),
Random = rand:uniform(Max),
case N rem (?LOOP_JUMP div 100) of
- 0 -> gen_jump_0(N-1, Max, [Random|Acc]);
- _ -> gen_jump_0(N-1, Max, Acc)
+ 0 -> gen_jump_p3(N-1, Max, [Random|Acc]);
+ _ -> gen_jump_p3(N-1, Max, Acc)
end;
-gen_jump_0(_, _, Acc) -> lists:reverse(Acc).
+gen_jump_p3(_, _, Acc) -> lists:reverse(Acc).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+short_jump(Config) when is_list(Config) ->
+ Seed = erlang:system_time(),
+ short_jump(
+ rand:seed_s(exro928ss, Seed),
+ fun ({Alg,AlgState}) ->
+ {Alg,rand:exro928_jump_2pow20(AlgState)}
+ end),
+ short_jump(
+ crypto:rand_seed_alg_s(crypto_aes, integer_to_list(Seed)),
+ fun ({Alg,AlgState}) ->
+ {Alg,crypto:rand_plugin_aes_jump_2pow20(AlgState)}
+ end),
+ ok.
+
+short_jump({#{bits := Bits},_} = State_0, Jump2Pow20) ->
+ Range = 1 bsl Bits,
+ State_1 = repeat(7, Range, State_0),
+ %%
+ State_2a = repeat(1 bsl 20, Range, State_1),
+ State_2b = Jump2Pow20(State_1),
+ check(17, Range, State_2a, State_2b),
+ %%
+ {_,State_3a} = rand:uniform_s(Range, State_2a),
+ State_4a = Jump2Pow20(State_3a),
+ State_4b = repeat((1 bsl 20) + 1, Range, State_2b),
+ check(17, Range, State_4a, State_4b).
+
+repeat(0, _Range, State) ->
+ State;
+repeat(N, Range, State) ->
+ {_, NewState} = rand:uniform_s(Range, State),
+ repeat(N - 1, Range, NewState).
+
+check(0, _Range, _StateA, _StateB) ->
+ ok;
+check(N, Range, StateA, StateB) ->
+ {V,NewStateA} = rand:uniform_s(Range, StateA),
+ case rand:uniform_s(Range, StateB) of
+ {V,NewStateB} ->
+ check(N - 1, Range, NewStateA, NewStateB);
+ {Wrong,_} ->
+ ct:fail({Wrong,neq,V,for,N})
+ end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Data
@@ -1389,7 +1442,50 @@ reference_val(exrop) ->
250789092615679985,78848633178610658,72059442721196128,
98223942961505519,191144652663779840,
102425686803727694,89058927716079076,80721467542933080,
- 8462479817391645,2774921106204163].
+ 8462479817391645,2774921106204163];
+
+reference_val(exro928ss) ->
+%% Same as for exrop, but this state init:
+%% for (n = 0; n < 16; n++) {
+%% s[n] = 12345678;
+ [16#000000108e8d5b01,16#03604028f2769dff,16#007f92f60bc7170c,
+ 16#035ea81a9898a5e2,16#0104c90c5a0c8178,16#0313514025cca717,
+ 16#03c5506b2a2e98cf,16#0098a5405961552e,16#004ad29eabb785a0,
+ 16#033ea8ec4efb8058,16#00b21545e62bef1c,16#0333fc5320703482,
+ 16#02c3c650e51a8d47,16#03a3b7fc848c9cda,16#03775adea6cddff5,
+ 16#01ae5499c9049973,16#03d3c90e5504e16b,16#0383cd6b6cb852e6,
+ 16#009c8d0996ef543a,16#0059cf671371af60,16#03dfd68ed980b719,
+ 16#0290f2a0acf2c5b0,16#029061df18d63b55,16#02e702ea4b45137b,
+ 16#029a0ccca604d848,16#01664c7cd31f0fa6,16#00dced83e60ccddc,
+ 16#008764d2c9a05f3e,16#02b9ca5f6a80c4ba,16#02daf93d2c566750,
+ 16#0147d326ead18ace,16#014b452efc19297f,16#0242d3f7a7237eca,
+ 16#0141bb68c2abce39,16#02d798e1230baf45,16#0216bf8f25c1ec2d,
+ 16#003a43ea733f1e1f,16#036c75390db736f3,16#028cca5f5f48c6f9,
+ 16#0186e4a17174d6cf,16#02152679dfa4c25c,16#01429b9f15e3b9d6,
+ 16#0134a61411d22bb0,16#01593f7d970d1c94,16#0205a7d8a305490f,
+ 16#01dd092272595a9c,16#0028c95208aad2d4,16#016347c25cc24162,
+ 16#025306acfb891309,16#0207a07e2bebef2f,16#024ee78d86ff5288,
+ 16#030b53192db97613,16#03f765cb9e98e611,16#025ec35a1e237377,
+ 16#03d81fd73102ef6f,16#0242dc8fea9a68b2,16#00abb876c1d4ea1b,
+ 16#00871ffd2b7e45fb,16#03593ff73c9be08d,16#00b96b2b8aca3688,
+ 16#0174aba957b7cf7b,16#012b7a5d4cf4a5b7,16#032a5260f2123db8,
+ 16#00f9374d88ee0080,16#030df39bec2ad657,16#00dce0cb81d006c4,
+ 16#038213b806303c76,16#03940aafdbfabf84,16#0398dbb26aeba037,
+ 16#01eb28d61951587f,16#00fed3d2aacfeef4,16#03499587547d6e40,
+ 16#01b192fe6e979e3c,16#00e974bf5f0a26d0,16#012ed94f76459c83,
+ 16#02d76859e7a82587,16#00d1d2c7b791f51b,16#03988058017a031b,
+ 16#00bbcf4b59d8e86d,16#015ed8b73a1b767c,16#0277283ea6a5ee74,
+ 16#002211460dd6d422,16#001ad62761ee9fbd,16#037311b44518b067,
+ 16#02b5ed61bf70904e,16#011862a05c1929fa,16#014be68683c3bab4,
+ 16#025c29aa5c508b07,16#00895c6106f97378,16#026ce91a3d671c7f,
+ 16#02591f4c74784293,16#02f0ed2a70bc1853,16#00a2762ff614bfbc,
+ 16#008f4e354f0c20d4,16#038b66fb587ed430,16#00636296e188de89,
+ 16#0278fadd143e74f5,16#029697ccf1b3a4c2,16#011eccb273404458,
+ 16#03f204064a9fe0c0];
+
+reference_val(_) ->
+ not_implemented.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1451,7 +1547,7 @@ reference_jump_val(exsp) ->
reference_jump_val(exsplus);
reference_jump_val(exs1024s) ->
reference_jump_val(exs1024);
-reference_jump_val(exs64) -> [not_implemented];
+reference_jump_val(exs64) -> [error_not_implemented];
reference_jump_val(exrop) ->
%% #include <stdint.h>
%% #include <stdio.h>
@@ -1516,7 +1612,50 @@ reference_jump_val(exrop) ->
250227633882474729,171181147785250210,55437891969696407,
241227318715885854,77323084015890802,
1663590009695191,234064400749487599,222983191707424780,
- 254956809144783896,203898972156838252].
+ 254956809144783896,203898972156838252];
+
+reference_jump_val(exro928ss) ->
+%% Same as for exrop, but this state init:
+%% for (n = 0; n < 16; n++) {
+%% s[n] = 12345678;
+ [16#031ee449e53b6689,16#001afeee12813137,16#005e2172711df36b,
+ 16#02850aea3a595d36,16#0029705187e891c7,16#001794badd489667,
+ 16#00ab621be15be56c,16#024b663a6924786b,16#03cab70b8ab854bf,
+ 16#01daa37601285320,16#02db955a53c40e89,16#01fbef51d5c65891,
+ 16#02fecf4116ed5f77,16#0349c2057246ac5d,16#01217f257c4fa148,
+ 16#0367ee84d020697d,16#01d5cf647fe23335,16#020941838adfb750,
+ 16#02c2da26b1d7b3e5,16#00d1583d34cea6c0,16#038be9cb5b527f50,
+ 16#00bfa93c1d7f4864,16#03778912a4f56b14,16#037fcabc483fa5c5,
+ 16#00a3c9de6aaf5fc7,16#03600b883b2f2b42,16#03797a99ffddfdfb,
+ 16#0189fead429945b7,16#0103ac90cd912508,16#03e3d872fd950d64,
+ 16#0214fc3e77dc2f02,16#02a084f4f0e580ca,16#035d2fe72266a7f3,
+ 16#02887c49ae7e41a4,16#0011dc026af83c51,16#02d28bfd32c2c517,
+ 16#022e4165c33ad4f3,16#01f053cf0687b052,16#035315e6e53c8918,
+ 16#01255312da07b572,16#0237f1da11ec9221,16#02faf2e282fb1fb1,
+ 16#0227423ec1787ebc,16#011fa5eb1505571c,16#0275ff9eaaa1abdd,
+ 16#03e2d032c3981cb4,16#0181bb32d51d3072,16#01b1d3939b9f16ec,
+ 16#0259f09f55d1112f,16#0396464a2767e428,16#039777c0368bdb9e,
+ 16#0320925f35f36c5f,16#02a35289e0af1248,16#02e80bd4bc72254b,
+ 16#00a8b11af1674d68,16#027735036100a69e,16#03c8c268ded7f254,
+ 16#03de80aa57c65217,16#00f2247754d24000,16#005582a42b467f89,
+ 16#0031906569729477,16#00fd523f2ca4fefe,16#00ad223113d1e336,
+ 16#0238ddf026cbfca9,16#028b98211cfed876,16#0354353ebcc0de9a,
+ 16#009ee370c1e154f4,16#033131af3b8a7f88,16#032291baa45801e3,
+ 16#00941fc2b45eb217,16#035d6a61fa101647,16#03fdb51f736f1bbc,
+ 16#0232f7b98539faa0,16#0311b35319e3a61e,16#0048356b17860eb5,
+ 16#01a205b2554ce71e,16#03f873ea136e29d6,16#003c67d5c3df5ffd,
+ 16#00cd19e7a8641648,16#0149a8c54e4ba45e,16#0329498d134d2f6a,
+ 16#03b69421ae65ee2b,16#01a8d20b59447429,16#006b2292571032a2,
+ 16#00c193b17da22ba5,16#01faa7ab62181249,16#00acd401cd596a00,
+ 16#005b5086c3531402,16#0259113d5d3d058d,16#00bef3f3ce4a43b2,
+ 16#014837a4070b893c,16#00460a26ac2eeec1,16#026219a8b8c63d7e,
+ 16#03c7b8ed032cf5a6,16#004da912a1fff131,16#0297de3716215741,
+ 16#0079fb9b4c715466,16#00a73bad4ae5a356,16#0072e606c0d4ab86,
+ 16#02374382d5f9bd2e];
+
+reference_jump_val(_) ->
+ not_implemented.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/lib/stdlib/test/rand_Xoroshiro928ss_dev.txt b/lib/stdlib/test/rand_Xoroshiro928ss_dev.txt
new file mode 100644
index 0000000000..150f37fcfa
--- /dev/null
+++ b/lib/stdlib/test/rand_Xoroshiro928ss_dev.txt
@@ -0,0 +1,343 @@
+%CopyrightBegin%
+
+Copyright Ericsson AB 2015-2017. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+%CopyrightEnd%
+
+
+Memorable facts from designing the Xoroshiro928** generator
+===========================================================
+AKA: exro928ss in the rand module
+
+Author: Raimo Niskanen, for the Erlang/OTP team @ Ericsson.
+
+Reference URL: http://vigna.di.unimi.it/ftp/papers/ScrambledLinear.pdf
+i.e the Xoroshiro1024 generator with ** scrambler:
+
+ int p;
+ uint64_t s[16];
+
+ const int q = p;
+ const uint64_t s0 = s[p = (p + 1) & 15];
+
+ uint64_t s15 = s[q];
+
+ const uint64_t result_starstar = rotl(s0 * S, R) * T;
+
+ s15 ^= s0;
+ s[q] = rotl(s0, A) ^ s15 ^ (s15 << B);
+ s[p] = rotl(s15, C);
+
+Where {S, R, T} = {5, 7, 9} as recommended in the paper.
+
+We want to scale down to 58 bit words (16 of them)
+so we get a generator with period 2^928 - 1.
+
+{A, B, C} were deduced as follows
+---------------------------------
+
+First, to find which triplets that give a full period generator
+one have to factor 2^928 - 1.
+
+https://www.alpertron.com.ar/ECM.HTM actually could do that
+and gave the result:
+
+ Value
+ 2^928 - 1
+
+ 2269 007733 883335 972287 082669 296112 915239 349672 942191 252221 331572
+ 442536 403137 824056 312817 862695 551072 066953 619064 625508 194663
+ 368599 769448 406663 254670 871573 830845 597595 897613 333042 429214
+ 224697 474472 410882 236254 024057 110212 260250 671521 235807 709272
+ 244389 361641 091086 035023 229622 419455 (280 digits) = 3 × 5 × 17 × 59 ×
+ 233 × 257 × 929 × 1103 × 2089 × 5569 × 8353 × 59393 × 65537 × 3 033169 ×
+ 39 594977 × 107 367629 × 536 903681 × 748 264961 × 2245 984577 × 239
+ 686663 718401 × 15 929619 591127 520827 829953 × 82280 195167 144119
+ 832390 568177 × 6033 312171 721035 031651 315652 130497 (34 digits) × 18
+ 774318 450142 955120 650303 957350 521748 903233 (44 digits) × 15 694604
+ 006012 505869 851221 169365 594050 637743 819041 (50 digits)
+
+Sebastiano Vigna from that calculated all full period triplets, at the
+end of this document, and the ones with the highest degree were:
+
+ 23-25-12 411
+ 36-2-35 411
+ 55-5-54 411
+ 14-19-11 415
+ 34-37-5 415
+ 37-3-56 415
+ 55-11-54 417
+ 30-3-41 419
+ 11-45-50 423
+ 50-19-47 423
+ 52-27-13 427
+ 54-9-25 433
+ 56-43-35 433
+ 44-9-45 441
+
+All these candidates were tested with TestU01-1.2.3:
+
+ http://simul.iro.umontreal.ca/testu01/tu01.html
+
+A plugin was created with parameters for {A, B, C} and, since
+TestU01 is a 32-bit test tool, with parameters to reverse
+the generated bits or not, and to take the 32 highest or lowest
+bits from the reversed or non-reversed 58 bit output.
+
+The generators were seeded with a SplitMix64 generator like the
+one used for seeding this generator in the rand module,
+taking the 58 lowest bits and wasting all zero values.
+
+3 runs were made with all candidates and all four bit selection variants.
+For these runs the seeder was initialized with 12345678, 876543212345678
+and 1234567890.
+
+After all these runs the candidate with the highest degree: 44-9-45
+had not gotten any suspicious p-value at all. All the other
+got p-values around 5.0e-4 worst 9.8e-6 suggesting only random
+failures, so they would probably have worked about as well.
+
+Finally 44-9-45 was run through PractRand-0.93:
+
+ http://pracrand.sourceforge.net/
+
+Again, all 4 bit selection variants of 32 bits were run.
+Random failures with p-values around e-3..e-4 for the "smaller"
+tests, but for 8, 16 and 32 TB tests no anomalies were found
+(with the internal seeder masked to 58 bits):
+
+ Xoroshiro928High seed: 0x3178ec5d
+ Xoroshiro928Low seed: 0xa9a04fb9
+ Xoroshiro928ReverseHigh seed: 0xfa0bdbab
+ Xoroshiro928ReverseLow seed: 0xada51705
+
+
+Then, S. Vigna calculated the 2^512 jump coefficient as well
+as a 2^20 jump coefficient (for testing purposes) for 44-9-45.
+
+2^512:
+ { 0x44085302f77130ca, 0xba05381fdfd14902, 0x10a1de1d7d6813d2,
+ 0xb83fe51a1eb3be19, 0xa81b0090567fd9f0, 0x5ac26d5d20f9b49f,
+ 0x4ddd98ee4be41e01, 0x0657e19f00d4b358, 0xf02f778573cf0f0a,
+ 0xb45a3a8a3cef3cc0, 0x6e62a33cc2323831, 0xbcb3b7c4cc049c53,
+ 0x83f240c6007e76ce, 0xe19f5fc1a1504acd, 0x00000000b10773cb }
+
+2^20:
+ { 0xbdb966a3daf905e6, 0x644807a56270cf78, 0xda90f4a806c17e9e,
+ 0x4a426866bfad3c77, 0xaf699c306d8e7566, 0x8ebc73c700b8b091,
+ 0xc081a7bf148531fb, 0xdc4d3af15f8a4dfd, 0x90627c014098f4b6,
+ 0x06df2eb1feaf0fb6, 0x5bdeb1a5a90f2e6b, 0xa480c5878c3549bd,
+ 0xff45ef33c82f3d48, 0xa30bebc15fefcc78, 0x00000000cb3d181c }
+
+Standard jump function pseudocode:
+
+ Jump constant j = 0xb10773cb...44085302f77130ca
+ Generator state: s
+ New generator state: t = 0
+ foreach bit in j, low to high:
+ if the bit is one:
+ t ^= s
+ next s
+ s = t
+
+
+The complete list of full period constants
+------------------------------------------
+
+29-48-54 27 x^928 + x^874 + x^870 + x^840 + x^814 + x^784 + x^759 + x^750 + x^724 + x^720 + x^634 + x^630 + x^600 + x^574 + x^544 + x^519 + x^510 + x^484 + x^480 + x^390 + x^360 + x^270 + x^240 + x^150 + x^120 + x^30 + 1
+
+29-18-56 65 x^928 + x^870 + x^850 + x^840 + x^832 + x^821 + x^802 + x^791 + x^761 + x^750 + x^734 + x^731 + x^720 + x^712 + x^701 + x^686 + x^674 + x^671 + x^663 + x^641 + x^630 + x^611 + x^610 + x^603 + x^600 + x^596 + x^577 + x^566 + x^547 + x^524 + x^517 + x^510 + x^487 + x^480 + x^476 + x^464 + x^457 + x^446 + x^427 + x^423 + x^397 + x^390 + x^367 + x^363 + x^360 + x^356 + x^352 + x^341 + x^326 + x^322 + x^311 + x^281 + x^270 + x^251 + x^240 + x^236 + x^232 + x^221 + x^191 + x^161 + x^150 + x^131 + x^120 + x^30 + 1
+
+29-32-36 81 x^928 + x^874 + x^870 + x^840 + x^820 + x^819 + x^794 + x^790 + x^770 + x^765 + x^764 + x^760 + x^754 + x^750 + x^740 + x^739 + x^735 + x^734 + x^730 + x^709 + x^704 + x^674 + x^670 + x^665 + x^660 + x^650 + x^649 + x^635 + x^634 + x^619 + x^614 + x^605 + x^595 + x^585 + x^584 + x^579 + x^564 + x^555 + x^545 + x^540 + x^524 + x^515 + x^514 + x^495 + x^490 + x^485 + x^460 + x^455 + x^435 + x^425 + x^400 + x^395 + x^375 + x^370 + x^365 + x^340 + x^315 + x^310 + x^305 + x^300 + x^290 + x^285 + x^275 + x^260 + x^250 + x^245 + x^240 + x^215 + x^190 + x^180 + x^170 + x^150 + x^130 + x^120 + x^115 + x^105 + x^100 + x^75 + x^40 + x^30 + 1
+
+39-10-20 105 x^928 + x^898 + x^870 + x^841 + x^840 + x^808 + x^783 + x^782 + x^781 + x^780 + x^778 + x^754 + x^752 + x^724 + x^721 + x^720 + x^696 + x^692 + x^688 + x^667 + x^666 + x^661 + x^660 + x^658 + x^638 + x^636 + x^632 + x^609 + x^607 + x^606 + x^605 + x^604 + x^601 + x^600 + x^580 + x^578 + x^576 + x^572 + x^568 + x^549 + x^548 + x^541 + x^540 + x^538 + x^516 + x^512 + x^489 + x^485 + x^484 + x^481 + x^480 + x^456 + x^452 + x^448 + x^429 + x^428 + x^421 + x^420 + x^418 + x^400 + x^398 + x^396 + x^392 + x^368 + x^365 + x^364 + x^336 + x^328 + x^319 + x^318 + x^315 + x^314 + x^298 + x^286 + x^278 + x^276 + x^274 + x^255 + x^254 + x^249 + x^245 + x^228 + x^226 + x^220 + x^208 + x^199 + x^198 + x^189 + x^188 + x^178 + x^168 + x^166 + x^160 + x^129 + x^128 + x^108 + x^100 + x^88 + x^79 + x^78 + x^69 + x^68 + x^58 + x^40 + 1
+
+4-4-9 149 x^928 + x^898 + x^886 + x^870 + x^856 + x^826 + x^823 + x^808 + x^796 + x^793 + x^784 + x^778 + x^772 + x^766 + x^760 + x^754 + x^751 + x^742 + x^736 + x^734 + x^724 + x^713 + x^709 + x^706 + x^703 + x^694 + x^691 + x^688 + x^676 + x^674 + x^673 + x^664 + x^662 + x^658 + x^653 + x^641 + x^640 + x^634 + x^632 + x^631 + x^620 + x^614 + x^611 + x^608 + x^604 + x^602 + x^599 + x^590 + x^583 + x^581 + x^578 + x^574 + x^572 + x^571 + x^569 + x^568 + x^561 + x^554 + x^553 + x^551 + x^544 + x^542 + x^540 + x^538 + x^532 + x^531 + x^518 + x^514 + x^512 + x^502 + x^498 + x^489 + x^488 + x^484 + x^482 + x^480 + x^479 + x^468 + x^463 + x^456 + x^454 + x^452 + x^449 + x^448 + x^438 + x^433 + x^429 + x^424 + x^422 + x^420 + x^418 + x^408 + x^406 + x^401 + x^396 + x^394 + x^392 + x^380 + x^378 + x^376 + x^371 + x^367 + x^364 + x^362 + x^360 + x^350 + x^348 + x^346 + x^341 + x^334 + x^332 + x^328 + x^318 + x^311 + x^307 + x^304 + x^302 + x^300 + x^298 + x^288 + x^274 + x^272 + x^254 + x^249 + x^242 + x^240 + x^233 + x^212 + x^208 + x^189 + x^180 + x^178 + x^166 + x^152 + x^143 + x^136 + x^127 + x^122 + x^120 + x^113 + x^106 + x^88 + x^83 + x^81 + x^67 + x^58 + x^51 + x^14 + 1
+
+44-44-45 157 x^928 + x^898 + x^870 + x^850 + x^830 + x^820 + x^808 + x^800 + x^790 + x^782 + x^778 + x^777 + x^760 + x^757 + x^752 + x^747 + x^742 + x^727 + x^702 + x^694 + x^689 + x^688 + x^679 + x^674 + x^659 + x^658 + x^657 + x^644 + x^642 + x^637 + x^634 + x^627 + x^619 + x^612 + x^607 + x^606 + x^601 + x^596 + x^594 + x^591 + x^590 + x^584 + x^576 + x^568 + x^566 + x^561 + x^560 + x^556 + x^554 + x^546 + x^541 + x^539 + x^538 + x^518 + x^516 + x^511 + x^509 + x^503 + x^502 + x^499 + x^496 + x^488 + x^476 + x^471 + x^468 + x^466 + x^464 + x^448 + x^446 + x^441 + x^436 + x^421 + x^420 + x^415 + x^411 + x^408 + x^404 + x^400 + x^388 + x^383 + x^381 + x^379 + x^376 + x^363 + x^358 + x^356 + x^354 + x^346 + x^344 + x^340 + x^333 + x^330 + x^328 + x^325 + x^316 + x^312 + x^307 + x^305 + x^302 + x^284 + x^282 + x^277 + x^270 + x^268 + x^267 + x^256 + x^252 + x^249 + x^245 + x^244 + x^239 + x^238 + x^236 + x^231 + x^228 + x^226 + x^224 + x^222 + x^215 + x^208 + x^207 + x^205 + x^203 + x^201 + x^199 + x^196 + x^194 + x^192 + x^189 + x^185 + x^184 + x^182 + x^180 + x^175 + x^171 + x^168 + x^166 + x^162 + x^161 + x^155 + x^152 + x^150 + x^141 + x^134 + x^132 + x^131 + x^127 + x^122 + x^111 + x^104 + x^92 + x^90 + x^83 + x^81 + x^58 + x^37 + 1
+
+40-40-7 167 x^928 + x^898 + x^870 + x^866 + x^838 + x^836 + x^807 + x^806 + x^804 + x^778 + x^777 + x^774 + x^745 + x^744 + x^742 + x^718 + x^714 + x^713 + x^712 + x^687 + x^658 + x^657 + x^656 + x^655 + x^654 + x^626 + x^620 + x^619 + x^598 + x^596 + x^592 + x^591 + x^589 + x^566 + x^564 + x^563 + x^562 + x^560 + x^558 + x^538 + x^534 + x^530 + x^529 + x^504 + x^503 + x^502 + x^500 + x^499 + x^498 + x^496 + x^478 + x^474 + x^470 + x^469 + x^443 + x^442 + x^441 + x^439 + x^438 + x^436 + x^434 + x^432 + x^418 + x^416 + x^414 + x^410 + x^409 + x^407 + x^406 + x^405 + x^402 + x^386 + x^383 + x^380 + x^374 + x^373 + x^372 + x^370 + x^356 + x^350 + x^349 + x^348 + x^347 + x^346 + x^345 + x^340 + x^328 + x^326 + x^324 + x^323 + x^321 + x^316 + x^314 + x^308 + x^298 + x^296 + x^294 + x^289 + x^285 + x^283 + x^282 + x^281 + x^280 + x^278 + x^263 + x^262 + x^259 + x^257 + x^255 + x^251 + x^249 + x^248 + x^246 + x^233 + x^232 + x^229 + x^220 + x^218 + x^217 + x^216 + x^208 + x^202 + x^201 + x^199 + x^195 + x^190 + x^188 + x^187 + x^186 + x^178 + x^172 + x^169 + x^167 + x^162 + x^161 + x^159 + x^158 + x^157 + x^146 + x^142 + x^139 + x^135 + x^125 + x^123 + x^116 + x^112 + x^107 + x^105 + x^94 + x^93 + x^88 + x^86 + x^84 + x^82 + x^75 + x^73 + x^69 + x^64 + x^58 + x^56 + x^54 + x^52 + x^43 + x^41 + x^39 + x^32 + 1
+
+47-47-18 217 x^928 + x^898 + x^871 + x^870 + x^843 + x^842 + x^841 + x^813 + x^812 + x^811 + x^808 + x^787 + x^786 + x^785 + x^783 + x^781 + x^778 + x^759 + x^757 + x^754 + x^753 + x^751 + x^729 + x^727 + x^726 + x^723 + x^721 + x^701 + x^700 + x^699 + x^697 + x^693 + x^691 + x^688 + x^673 + x^672 + x^670 + x^667 + x^663 + x^661 + x^658 + x^647 + x^644 + x^641 + x^637 + x^633 + x^631 + x^618 + x^617 + x^614 + x^613 + x^612 + x^611 + x^610 + x^607 + x^603 + x^601 + x^586 + x^585 + x^582 + x^581 + x^580 + x^577 + x^573 + x^571 + x^568 + x^562 + x^560 + x^556 + x^555 + x^554 + x^553 + x^551 + x^547 + x^543 + x^541 + x^538 + x^532 + x^530 + x^528 + x^524 + x^522 + x^521 + x^517 + x^513 + x^511 + x^506 + x^504 + x^502 + x^500 + x^497 + x^495 + x^491 + x^487 + x^483 + x^481 + x^478 + x^474 + x^472 + x^467 + x^466 + x^465 + x^461 + x^457 + x^453 + x^451 + x^444 + x^438 + x^437 + x^436 + x^435 + x^431 + x^427 + x^423 + x^412 + x^408 + x^407 + x^405 + x^401 + x^397 + x^390 + x^384 + x^377 + x^375 + x^371 + x^367 + x^366 + x^365 + x^363 + x^362 + x^360 + x^358 + x^356 + x^352 + x^350 + x^347 + x^345 + x^341 + x^337 + x^336 + x^334 + x^332 + x^324 + x^317 + x^315 + x^311 + x^307 + x^306 + x^305 + x^304 + x^302 + x^300 + x^298 + x^296 + x^287 + x^285 + x^281 + x^279 + x^277 + x^276 + x^274 + x^268 + x^266 + x^257 + x^255 + x^247 + x^244 + x^242 + x^240 + x^238 + x^234 + x^227 + x^221 + x^219 + x^216 + x^214 + x^206 + x^197 + x^195 + x^193 + x^182 + x^176 + x^161 + x^156 + x^152 + x^146 + x^139 + x^133 + x^116 + x^111 + x^109 + x^107 + x^96 + x^94 + x^92 + x^90 + x^88 + x^85 + x^81 + x^79 + x^77 + x^73 + x^66 + x^64 + x^62 + x^60 + x^53 + x^51 + x^47 + x^45 + x^36 + x^34 + x^32 + x^19 + x^17 + x^15 + 1
+
+31-52-54 249 x^928 + x^898 + x^872 + x^870 + x^842 + x^841 + x^838 + x^836 + x^812 + x^810 + x^782 + x^781 + x^779 + x^778 + x^774 + x^753 + x^752 + x^750 + x^748 + x^723 + x^722 + x^721 + x^719 + x^717 + x^714 + x^712 + x^694 + x^690 + x^689 + x^688 + x^686 + x^684 + x^664 + x^663 + x^662 + x^661 + x^660 + x^658 + x^657 + x^656 + x^655 + x^654 + x^653 + x^652 + x^650 + x^634 + x^633 + x^631 + x^630 + x^629 + x^628 + x^622 + x^604 + x^599 + x^597 + x^596 + x^593 + x^592 + x^590 + x^588 + x^570 + x^567 + x^566 + x^562 + x^560 + x^536 + x^534 + x^533 + x^531 + x^530 + x^526 + x^513 + x^512 + x^510 + x^509 + x^508 + x^507 + x^506 + x^505 + x^504 + x^502 + x^498 + x^483 + x^482 + x^481 + x^479 + x^478 + x^476 + x^466 + x^464 + x^454 + x^445 + x^438 + x^424 + x^423 + x^422 + x^421 + x^419 + x^418 + x^411 + x^404 + x^402 + x^394 + x^393 + x^392 + x^391 + x^390 + x^387 + x^386 + x^383 + x^380 + x^379 + x^378 + x^377 + x^376 + x^374 + x^364 + x^362 + x^361 + x^359 + x^357 + x^356 + x^355 + x^354 + x^351 + x^349 + x^348 + x^347 + x^345 + x^342 + x^340 + x^332 + x^330 + x^329 + x^328 + x^327 + x^325 + x^324 + x^323 + x^321 + x^319 + x^318 + x^316 + x^314 + x^312 + x^302 + x^301 + x^300 + x^296 + x^295 + x^294 + x^291 + x^289 + x^287 + x^286 + x^283 + x^278 + x^266 + x^265 + x^264 + x^263 + x^262 + x^260 + x^259 + x^255 + x^250 + x^234 + x^232 + x^229 + x^227 + x^226 + x^225 + x^222 + x^218 + x^216 + x^208 + x^204 + x^200 + x^198 + x^197 + x^195 + x^194 + x^193 + x^190 + x^188 + x^178 + x^174 + x^173 + x^172 + x^171 + x^170 + x^169 + x^168 + x^166 + x^165 + x^164 + x^162 + x^161 + x^160 + x^159 + x^158 + x^157 + x^156 + x^154 + x^142 + x^141 + x^139 + x^138 + x^135 + x^131 + x^128 + x^126 + x^116 + x^112 + x^110 + x^107 + x^106 + x^105 + x^104 + x^102 + x^100 + x^98 + x^96 + x^95 + x^94 + x^92 + x^88 + x^80 + x^79 + x^76 + x^74 + x^73 + x^71 + x^70 + x^69 + x^66 + x^65 + x^64 + x^56 + x^54 + x^48 + x^46 + x^45 + x^43 + x^38 + x^35 + x^33 + x^30 + 1
+
+57-54-32 249 x^928 + x^898 + x^870 + x^855 + x^848 + x^834 + x^826 + x^825 + x^808 + x^806 + x^805 + x^804 + x^798 + x^796 + x^788 + x^778 + x^776 + x^775 + x^766 + x^763 + x^756 + x^752 + x^745 + x^742 + x^736 + x^735 + x^734 + x^731 + x^715 + x^714 + x^713 + x^705 + x^703 + x^694 + x^688 + x^684 + x^682 + x^671 + x^660 + x^658 + x^652 + x^642 + x^641 + x^639 + x^634 + x^630 + x^621 + x^620 + x^616 + x^612 + x^609 + x^604 + x^602 + x^593 + x^591 + x^584 + x^579 + x^570 + x^568 + x^566 + x^565 + x^562 + x^558 + x^554 + x^550 + x^544 + x^536 + x^535 + x^533 + x^530 + x^529 + x^528 + x^524 + x^522 + x^517 + x^512 + x^505 + x^496 + x^494 + x^492 + x^491 + x^489 + x^480 + x^478 + x^475 + x^471 + x^464 + x^461 + x^454 + x^452 + x^450 + x^446 + x^445 + x^441 + x^438 + x^437 + x^436 + x^434 + x^430 + x^429 + x^427 + x^425 + x^420 + x^418 + x^416 + x^415 + x^413 + x^411 + x^409 + x^402 + x^397 + x^394 + x^392 + x^388 + x^386 + x^384 + x^377 + x^375 + x^371 + x^368 + x^367 + x^365 + x^364 + x^363 + x^362 + x^360 + x^358 + x^356 + x^353 + x^351 + x^346 + x^342 + x^341 + x^338 + x^335 + x^333 + x^330 + x^328 + x^326 + x^325 + x^317 + x^307 + x^304 + x^300 + x^296 + x^295 + x^293 + x^292 + x^288 + x^286 + x^285 + x^284 + x^283 + x^278 + x^277 + x^276 + x^273 + x^271 + x^270 + x^262 + x^261 + x^255 + x^253 + x^249 + x^248 + x^246 + x^245 + x^240 + x^236 + x^232 + x^231 + x^227 + x^224 + x^223 + x^221 + x^220 + x^217 + x^216 + x^212 + x^208 + x^205 + x^204 + x^198 + x^196 + x^192 + x^191 + x^190 + x^189 + x^187 + x^186 + x^178 + x^176 + x^175 + x^171 + x^169 + x^165 + x^160 + x^159 + x^158 + x^154 + x^152 + x^150 + x^148 + x^146 + x^144 + x^141 + x^134 + x^132 + x^131 + x^129 + x^127 + x^125 + x^123 + x^120 + x^118 + x^114 + x^113 + x^111 + x^106 + x^104 + x^103 + x^102 + x^101 + x^100 + x^99 + x^97 + x^95 + x^93 + x^88 + x^85 + x^77 + x^67 + x^62 + x^60 + x^55 + x^54 + x^53 + x^52 + x^51 + x^50 + x^48 + x^46 + x^40 + x^37 + x^33 + x^28 + x^27 + x^24 + 1
+
+1-38-28 251 x^928 + x^898 + x^870 + x^866 + x^836 + x^834 + x^832 + x^818 + x^808 + x^806 + x^804 + x^797 + x^788 + x^778 + x^776 + x^770 + x^767 + x^765 + x^738 + x^736 + x^733 + x^724 + x^717 + x^708 + x^706 + x^703 + x^701 + x^690 + x^688 + x^685 + x^678 + x^677 + x^676 + x^674 + x^672 + x^664 + x^658 + x^656 + x^652 + x^647 + x^645 + x^640 + x^626 + x^624 + x^621 + x^620 + x^616 + x^610 + x^608 + x^604 + x^600 + x^594 + x^593 + x^592 + x^590 + x^580 + x^578 + x^576 + x^575 + x^574 + x^572 + x^568 + x^566 + x^565 + x^564 + x^562 + x^560 + x^558 + x^552 + x^550 + x^549 + x^548 + x^544 + x^541 + x^538 + x^536 + x^533 + x^532 + x^529 + x^526 + x^522 + x^520 + x^519 + x^517 + x^514 + x^513 + x^509 + x^508 + x^504 + x^501 + x^494 + x^493 + x^484 + x^482 + x^469 + x^468 + x^466 + x^461 + x^453 + x^452 + x^448 + x^447 + x^436 + x^428 + x^424 + x^422 + x^420 + x^416 + x^414 + x^413 + x^412 + x^409 + x^408 + x^406 + x^405 + x^404 + x^400 + x^399 + x^397 + x^393 + x^391 + x^388 + x^385 + x^382 + x^381 + x^376 + x^374 + x^372 + x^370 + x^368 + x^366 + x^365 + x^360 + x^350 + x^349 + x^344 + x^341 + x^340 + x^336 + x^335 + x^334 + x^333 + x^332 + x^328 + x^326 + x^322 + x^319 + x^318 + x^308 + x^304 + x^300 + x^298 + x^293 + x^292 + x^290 + x^289 + x^287 + x^284 + x^281 + x^279 + x^278 + x^272 + x^271 + x^269 + x^264 + x^263 + x^261 + x^256 + x^254 + x^253 + x^250 + x^240 + x^238 + x^234 + x^229 + x^228 + x^226 + x^223 + x^221 + x^218 + x^213 + x^210 + x^208 + x^204 + x^198 + x^197 + x^196 + x^194 + x^191 + x^188 + x^186 + x^180 + x^176 + x^174 + x^172 + x^170 + x^169 + x^167 + x^165 + x^161 + x^159 + x^157 + x^153 + x^150 + x^149 + x^148 + x^145 + x^136 + x^135 + x^134 + x^133 + x^132 + x^130 + x^128 + x^127 + x^125 + x^122 + x^120 + x^118 + x^113 + x^110 + x^109 + x^108 + x^100 + x^96 + x^94 + x^92 + x^90 + x^88 + x^86 + x^85 + x^84 + x^81 + x^80 + x^72 + x^70 + x^66 + x^58 + x^53 + x^45 + x^36 + x^34 + x^32 + x^30 + x^24 + x^20 + x^16 + x^12 + x^8 + x^2 + 1
+
+47-57-20 279 x^928 + x^898 + x^880 + x^870 + x^864 + x^851 + x^850 + x^846 + x^830 + x^821 + x^820 + x^817 + x^812 + x^808 + x^807 + x^804 + x^796 + x^790 + x^783 + x^782 + x^777 + x^773 + x^762 + x^757 + x^753 + x^744 + x^743 + x^739 + x^731 + x^728 + x^714 + x^713 + x^710 + x^709 + x^705 + x^701 + x^694 + x^692 + x^688 + x^684 + x^683 + x^675 + x^672 + x^671 + x^668 + x^662 + x^660 + x^654 + x^653 + x^646 + x^642 + x^641 + x^637 + x^626 + x^624 + x^623 + x^608 + x^607 + x^603 + x^598 + x^593 + x^592 + x^590 + x^585 + x^578 + x^577 + x^574 + x^573 + x^572 + x^569 + x^568 + x^567 + x^563 + x^559 + x^558 + x^555 + x^551 + x^548 + x^547 + x^542 + x^539 + x^538 + x^537 + x^536 + x^535 + x^532 + x^530 + x^529 + x^525 + x^524 + x^521 + x^518 + x^517 + x^506 + x^505 + x^501 + x^496 + x^491 + x^490 + x^487 + x^471 + x^467 + x^462 + x^456 + x^452 + x^448 + x^446 + x^441 + x^440 + x^437 + x^433 + x^428 + x^420 + x^412 + x^411 + x^404 + x^403 + x^402 + x^401 + x^399 + x^398 + x^396 + x^394 + x^381 + x^378 + x^376 + x^371 + x^370 + x^366 + x^365 + x^360 + x^355 + x^354 + x^351 + x^348 + x^346 + x^344 + x^342 + x^340 + x^339 + x^337 + x^335 + x^333 + x^331 + x^330 + x^329 + x^328 + x^327 + x^320 + x^318 + x^313 + x^307 + x^299 + x^298 + x^297 + x^296 + x^295 + x^294 + x^293 + x^291 + x^283 + x^282 + x^281 + x^280 + x^279 + x^277 + x^276 + x^266 + x^265 + x^264 + x^263 + x^262 + x^261 + x^259 + x^258 + x^257 + x^256 + x^251 + x^248 + x^247 + x^242 + x^240 + x^235 + x^234 + x^233 + x^231 + x^230 + x^229 + x^227 + x^225 + x^224 + x^219 + x^214 + x^212 + x^210 + x^206 + x^204 + x^203 + x^200 + x^196 + x^195 + x^194 + x^192 + x^191 + x^190 + x^188 + x^185 + x^182 + x^178 + x^176 + x^173 + x^159 + x^158 + x^157 + x^156 + x^151 + x^146 + x^144 + x^143 + x^142 + x^140 + x^138 + x^136 + x^131 + x^130 + x^128 + x^127 + x^126 + x^123 + x^122 + x^118 + x^117 + x^115 + x^114 + x^113 + x^108 + x^105 + x^99 + x^98 + x^94 + x^90 + x^88 + x^87 + x^86 + x^84 + x^82 + x^81 + x^80 + x^79 + x^78 + x^75 + x^74 + x^72 + x^71 + x^70 + x^65 + x^64 + x^58 + x^57 + x^56 + x^55 + x^52 + x^50 + x^48 + x^47 + x^46 + x^45 + x^42 + x^39 + x^26 + x^24 + x^23 + x^22 + x^20 + x^18 + x^15 + x^8 + x^4 + 1
+
+3-16-56 281 x^928 + x^898 + x^882 + x^870 + x^836 + x^820 + x^816 + x^808 + x^803 + x^802 + x^799 + x^778 + x^773 + x^770 + x^762 + x^757 + x^754 + x^753 + x^750 + x^737 + x^733 + x^720 + x^717 + x^713 + x^700 + x^688 + x^683 + x^680 + x^679 + x^674 + x^660 + x^658 + x^656 + x^654 + x^653 + x^650 + x^646 + x^644 + x^641 + x^640 + x^637 + x^634 + x^633 + x^623 + x^618 + x^617 + x^616 + x^613 + x^597 + x^590 + x^585 + x^584 + x^581 + x^577 + x^574 + x^572 + x^563 + x^562 + x^560 + x^555 + x^554 + x^553 + x^551 + x^547 + x^544 + x^537 + x^536 + x^533 + x^525 + x^521 + x^520 + x^519 + x^517 + x^515 + x^513 + x^510 + x^508 + x^505 + x^502 + x^501 + x^498 + x^493 + x^490 + x^485 + x^480 + x^477 + x^476 + x^475 + x^472 + x^469 + x^461 + x^458 + x^453 + x^449 + x^448 + x^445 + x^444 + x^442 + x^435 + x^433 + x^432 + x^431 + x^426 + x^425 + x^422 + x^420 + x^418 + x^412 + x^411 + x^409 + x^405 + x^403 + x^401 + x^400 + x^397 + x^393 + x^385 + x^381 + x^368 + x^366 + x^365 + x^362 + x^361 + x^359 + x^356 + x^353 + x^350 + x^346 + x^341 + x^338 + x^335 + x^334 + x^333 + x^332 + x^328 + x^326 + x^325 + x^323 + x^322 + x^320 + x^319 + x^317 + x^316 + x^315 + x^313 + x^312 + x^310 + x^309 + x^307 + x^305 + x^300 + x^295 + x^293 + x^291 + x^290 + x^289 + x^288 + x^286 + x^285 + x^282 + x^277 + x^274 + x^273 + x^266 + x^265 + x^263 + x^261 + x^259 + x^255 + x^253 + x^251 + x^248 + x^247 + x^246 + x^242 + x^241 + x^239 + x^234 + x^233 + x^232 + x^230 + x^229 + x^228 + x^226 + x^225 + x^224 + x^222 + x^218 + x^217 + x^215 + x^212 + x^210 + x^208 + x^206 + x^205 + x^203 + x^201 + x^200 + x^194 + x^193 + x^191 + x^189 + x^183 + x^181 + x^180 + x^178 + x^177 + x^176 + x^174 + x^172 + x^171 + x^169 + x^167 + x^166 + x^163 + x^162 + x^159 + x^157 + x^155 + x^151 + x^150 + x^149 + x^147 + x^140 + x^139 + x^138 + x^137 + x^136 + x^134 + x^131 + x^128 + x^127 + x^126 + x^121 + x^119 + x^118 + x^117 + x^111 + x^106 + x^104 + x^102 + x^101 + x^99 + x^98 + x^91 + x^90 + x^88 + x^86 + x^85 + x^81 + x^79 + x^75 + x^74 + x^73 + x^72 + x^71 + x^69 + x^68 + x^65 + x^64 + x^63 + x^62 + x^61 + x^58 + x^57 + x^56 + x^55 + x^51 + x^50 + x^49 + x^41 + x^38 + x^36 + x^34 + x^33 + x^32 + x^24 + x^21 + x^9 + x^6 + 1
+
+10-38-9 285 x^928 + x^898 + x^870 + x^841 + x^840 + x^838 + x^836 + x^811 + x^810 + x^781 + x^777 + x^774 + x^751 + x^748 + x^723 + x^721 + x^720 + x^719 + x^718 + x^717 + x^716 + x^714 + x^712 + x^694 + x^692 + x^691 + x^688 + x^686 + x^664 + x^663 + x^661 + x^660 + x^659 + x^657 + x^652 + x^650 + x^632 + x^631 + x^630 + x^628 + x^627 + x^625 + x^624 + x^623 + x^605 + x^604 + x^603 + x^599 + x^597 + x^594 + x^593 + x^591 + x^590 + x^588 + x^576 + x^575 + x^574 + x^572 + x^571 + x^570 + x^569 + x^567 + x^565 + x^560 + x^544 + x^543 + x^542 + x^540 + x^539 + x^537 + x^535 + x^531 + x^526 + x^514 + x^510 + x^509 + x^507 + x^506 + x^505 + x^504 + x^503 + x^502 + x^498 + x^485 + x^484 + x^478 + x^474 + x^471 + x^470 + x^468 + x^466 + x^464 + x^458 + x^455 + x^452 + x^450 + x^449 + x^448 + x^445 + x^441 + x^439 + x^428 + x^419 + x^416 + x^415 + x^411 + x^407 + x^406 + x^405 + x^404 + x^402 + x^398 + x^392 + x^388 + x^385 + x^384 + x^383 + x^382 + x^381 + x^380 + x^379 + x^376 + x^374 + x^364 + x^359 + x^357 + x^356 + x^355 + x^354 + x^353 + x^351 + x^349 + x^346 + x^345 + x^343 + x^340 + x^338 + x^334 + x^328 + x^326 + x^325 + x^324 + x^321 + x^320 + x^319 + x^318 + x^315 + x^314 + x^312 + x^306 + x^298 + x^297 + x^295 + x^294 + x^293 + x^291 + x^288 + x^287 + x^286 + x^285 + x^283 + x^282 + x^281 + x^278 + x^276 + x^274 + x^270 + x^269 + x^268 + x^263 + x^261 + x^256 + x^255 + x^254 + x^244 + x^242 + x^237 + x^236 + x^235 + x^234 + x^233 + x^232 + x^229 + x^225 + x^222 + x^219 + x^216 + x^214 + x^212 + x^210 + x^209 + x^208 + x^207 + x^206 + x^202 + x^198 + x^194 + x^193 + x^192 + x^191 + x^190 + x^184 + x^182 + x^178 + x^176 + x^175 + x^174 + x^173 + x^168 + x^166 + x^164 + x^160 + x^159 + x^157 + x^154 + x^152 + x^151 + x^150 + x^145 + x^144 + x^142 + x^136 + x^135 + x^134 + x^129 + x^128 + x^122 + x^121 + x^119 + x^118 + x^116 + x^114 + x^113 + x^112 + x^111 + x^108 + x^105 + x^103 + x^100 + x^98 + x^97 + x^95 + x^94 + x^92 + x^89 + x^88 + x^87 + x^85 + x^84 + x^83 + x^78 + x^76 + x^74 + x^73 + x^71 + x^70 + x^69 + x^67 + x^66 + x^64 + x^61 + x^59 + x^57 + x^56 + x^54 + x^53 + x^51 + x^49 + x^48 + x^46 + x^45 + x^43 + x^42 + x^41 + x^40 + x^38 + x^37 + x^36 + x^35 + x^34 + x^33 + x^32 + x^30 + x^4 + 1
+
+15-22-28 289 x^928 + x^898 + x^870 + x^838 + x^821 + x^806 + x^805 + x^792 + x^790 + x^778 + x^774 + x^762 + x^745 + x^744 + x^718 + x^697 + x^682 + x^672 + x^670 + x^667 + x^666 + x^658 + x^656 + x^653 + x^652 + x^651 + x^650 + x^642 + x^641 + x^638 + x^637 + x^623 + x^608 + x^607 + x^598 + x^594 + x^588 + x^575 + x^574 + x^573 + x^566 + x^565 + x^564 + x^563 + x^562 + x^557 + x^548 + x^547 + x^542 + x^538 + x^533 + x^531 + x^529 + x^526 + x^517 + x^516 + x^514 + x^513 + x^505 + x^504 + x^503 + x^502 + x^501 + x^499 + x^498 + x^497 + x^488 + x^487 + x^484 + x^483 + x^482 + x^474 + x^470 + x^468 + x^467 + x^466 + x^464 + x^457 + x^454 + x^453 + x^449 + x^447 + x^444 + x^443 + x^442 + x^441 + x^440 + x^439 + x^437 + x^436 + x^435 + x^428 + x^427 + x^426 + x^425 + x^422 + x^418 + x^417 + x^414 + x^409 + x^406 + x^405 + x^392 + x^391 + x^389 + x^388 + x^387 + x^386 + x^379 + x^378 + x^374 + x^372 + x^371 + x^368 + x^367 + x^362 + x^361 + x^358 + x^357 + x^354 + x^350 + x^349 + x^347 + x^342 + x^341 + x^340 + x^334 + x^333 + x^332 + x^331 + x^330 + x^329 + x^328 + x^327 + x^324 + x^323 + x^320 + x^319 + x^313 + x^308 + x^307 + x^305 + x^303 + x^302 + x^301 + x^300 + x^299 + x^298 + x^297 + x^296 + x^295 + x^294 + x^293 + x^292 + x^288 + x^287 + x^286 + x^283 + x^282 + x^280 + x^279 + x^278 + x^277 + x^276 + x^271 + x^269 + x^268 + x^267 + x^266 + x^265 + x^255 + x^254 + x^253 + x^249 + x^247 + x^241 + x^238 + x^237 + x^236 + x^235 + x^226 + x^225 + x^224 + x^223 + x^220 + x^219 + x^215 + x^214 + x^212 + x^210 + x^209 + x^205 + x^202 + x^201 + x^200 + x^199 + x^197 + x^190 + x^186 + x^182 + x^181 + x^180 + x^177 + x^174 + x^173 + x^172 + x^171 + x^170 + x^169 + x^168 + x^165 + x^163 + x^161 + x^160 + x^158 + x^155 + x^153 + x^151 + x^150 + x^146 + x^143 + x^142 + x^137 + x^136 + x^135 + x^131 + x^130 + x^128 + x^127 + x^126 + x^125 + x^124 + x^123 + x^122 + x^120 + x^119 + x^117 + x^114 + x^113 + x^111 + x^105 + x^104 + x^103 + x^102 + x^101 + x^99 + x^97 + x^93 + x^90 + x^89 + x^88 + x^87 + x^86 + x^84 + x^83 + x^82 + x^81 + x^80 + x^79 + x^77 + x^75 + x^72 + x^71 + x^70 + x^69 + x^68 + x^65 + x^60 + x^59 + x^58 + x^55 + x^54 + x^52 + x^51 + x^50 + x^48 + x^43 + x^42 + x^40 + x^39 + x^30 + x^28 + x^27 + x^24 + x^23 + x^19 + x^16 + x^15 + 1
+
+12-41-35 291 x^928 + x^898 + x^886 + x^873 + x^870 + x^860 + x^856 + x^847 + x^844 + x^834 + x^830 + x^826 + x^818 + x^817 + x^805 + x^804 + x^796 + x^795 + x^791 + x^784 + x^782 + x^779 + x^769 + x^765 + x^762 + x^758 + x^756 + x^753 + x^752 + x^743 + x^739 + x^736 + x^735 + x^732 + x^731 + x^730 + x^727 + x^726 + x^723 + x^722 + x^717 + x^713 + x^710 + x^705 + x^701 + x^700 + x^692 + x^685 + x^683 + x^680 + x^676 + x^671 + x^663 + x^659 + x^657 + x^654 + x^653 + x^645 + x^642 + x^637 + x^632 + x^628 + x^624 + x^623 + x^619 + x^616 + x^615 + x^612 + x^610 + x^607 + x^606 + x^603 + x^598 + x^597 + x^594 + x^593 + x^590 + x^589 + x^585 + x^580 + x^577 + x^576 + x^572 + x^567 + x^564 + x^560 + x^559 + x^556 + x^550 + x^545 + x^543 + x^538 + x^537 + x^534 + x^533 + x^532 + x^528 + x^520 + x^516 + x^513 + x^508 + x^507 + x^506 + x^504 + x^499 + x^496 + x^491 + x^490 + x^487 + x^486 + x^485 + x^481 + x^477 + x^474 + x^466 + x^465 + x^457 + x^452 + x^448 + x^447 + x^446 + x^438 + x^436 + x^435 + x^434 + x^430 + x^425 + x^422 + x^421 + x^417 + x^413 + x^409 + x^404 + x^395 + x^393 + x^392 + x^388 + x^387 + x^386 + x^384 + x^382 + x^380 + x^379 + x^374 + x^373 + x^370 + x^367 + x^366 + x^362 + x^361 + x^358 + x^357 + x^354 + x^353 + x^352 + x^350 + x^349 + x^345 + x^344 + x^343 + x^340 + x^337 + x^336 + x^332 + x^331 + x^328 + x^324 + x^323 + x^317 + x^315 + x^314 + x^313 + x^311 + x^305 + x^302 + x^298 + x^297 + x^296 + x^295 + x^292 + x^291 + x^288 + x^283 + x^280 + x^276 + x^275 + x^272 + x^268 + x^266 + x^262 + x^259 + x^258 + x^255 + x^251 + x^250 + x^242 + x^241 + x^240 + x^232 + x^227 + x^225 + x^224 + x^223 + x^216 + x^214 + x^212 + x^211 + x^210 + x^206 + x^203 + x^198 + x^189 + x^188 + x^177 + x^176 + x^175 + x^173 + x^168 + x^164 + x^162 + x^160 + x^159 + x^156 + x^155 + x^154 + x^152 + x^149 + x^147 + x^146 + x^145 + x^142 + x^139 + x^138 + x^137 + x^134 + x^132 + x^130 + x^124 + x^123 + x^122 + x^115 + x^113 + x^112 + x^111 + x^110 + x^108 + x^106 + x^103 + x^102 + x^98 + x^97 + x^96 + x^95 + x^94 + x^92 + x^91 + x^90 + x^88 + x^85 + x^80 + x^78 + x^77 + x^76 + x^73 + x^71 + x^70 + x^69 + x^68 + x^67 + x^65 + x^64 + x^63 + x^54 + x^53 + x^52 + x^51 + x^50 + x^49 + x^48 + x^47 + x^44 + x^43 + x^42 + x^40 + x^39 + x^31 + x^30 + x^29 + x^21 + x^13 + 1
+
+35-54-56 293 x^928 + x^898 + x^870 + x^862 + x^832 + x^826 + x^808 + x^796 + x^794 + x^790 + x^778 + x^765 + x^758 + x^754 + x^734 + x^729 + x^728 + x^722 + x^718 + x^715 + x^706 + x^700 + x^699 + x^698 + x^693 + x^686 + x^682 + x^676 + x^673 + x^672 + x^669 + x^668 + x^662 + x^658 + x^656 + x^655 + x^652 + x^650 + x^649 + x^646 + x^645 + x^642 + x^639 + x^638 + x^636 + x^630 + x^622 + x^614 + x^613 + x^612 + x^610 + x^608 + x^607 + x^600 + x^596 + x^595 + x^592 + x^590 + x^589 + x^587 + x^582 + x^574 + x^571 + x^568 + x^566 + x^560 + x^558 + x^554 + x^553 + x^552 + x^548 + x^544 + x^542 + x^538 + x^536 + x^534 + x^530 + x^528 + x^527 + x^524 + x^523 + x^522 + x^520 + x^518 + x^516 + x^515 + x^511 + x^506 + x^499 + x^497 + x^493 + x^492 + x^490 + x^487 + x^482 + x^478 + x^474 + x^467 + x^462 + x^461 + x^452 + x^445 + x^442 + x^439 + x^437 + x^436 + x^433 + x^428 + x^427 + x^422 + x^418 + x^413 + x^412 + x^410 + x^409 + x^407 + x^406 + x^403 + x^401 + x^398 + x^396 + x^392 + x^390 + x^386 + x^384 + x^383 + x^382 + x^380 + x^378 + x^377 + x^373 + x^372 + x^371 + x^366 + x^365 + x^362 + x^353 + x^352 + x^350 + x^348 + x^346 + x^344 + x^342 + x^340 + x^338 + x^336 + x^335 + x^334 + x^332 + x^331 + x^328 + x^326 + x^320 + x^318 + x^317 + x^316 + x^313 + x^312 + x^311 + x^310 + x^308 + x^304 + x^300 + x^299 + x^298 + x^296 + x^295 + x^293 + x^290 + x^288 + x^284 + x^282 + x^275 + x^271 + x^269 + x^268 + x^266 + x^265 + x^264 + x^263 + x^262 + x^260 + x^259 + x^253 + x^250 + x^247 + x^246 + x^244 + x^242 + x^240 + x^239 + x^238 + x^235 + x^233 + x^232 + x^228 + x^227 + x^226 + x^224 + x^221 + x^220 + x^218 + x^216 + x^214 + x^212 + x^208 + x^203 + x^199 + x^198 + x^196 + x^195 + x^194 + x^193 + x^192 + x^189 + x^187 + x^182 + x^178 + x^176 + x^175 + x^173 + x^168 + x^167 + x^166 + x^163 + x^161 + x^160 + x^156 + x^152 + x^150 + x^148 + x^146 + x^140 + x^138 + x^135 + x^133 + x^131 + x^130 + x^129 + x^128 + x^127 + x^126 + x^125 + x^123 + x^122 + x^120 + x^118 + x^116 + x^115 + x^113 + x^112 + x^109 + x^106 + x^105 + x^104 + x^103 + x^101 + x^100 + x^95 + x^94 + x^92 + x^84 + x^82 + x^80 + x^79 + x^77 + x^76 + x^74 + x^71 + x^69 + x^68 + x^66 + x^65 + x^64 + x^63 + x^55 + x^54 + x^53 + x^49 + x^48 + x^46 + x^45 + x^43 + x^42 + x^41 + x^40 + x^38 + x^36 + x^34 + x^24 + x^18 + x^6 + 1
+
+44-42-5 307 x^928 + x^898 + x^880 + x^870 + x^856 + x^850 + x^839 + x^832 + x^826 + x^820 + x^816 + x^815 + x^808 + x^792 + x^791 + x^790 + x^784 + x^779 + x^778 + x^768 + x^762 + x^760 + x^756 + x^754 + x^753 + x^747 + x^744 + x^738 + x^737 + x^736 + x^731 + x^726 + x^723 + x^720 + x^719 + x^717 + x^713 + x^707 + x^696 + x^693 + x^689 + x^688 + x^682 + x^678 + x^677 + x^670 + x^666 + x^665 + x^663 + x^660 + x^658 + x^657 + x^653 + x^646 + x^633 + x^630 + x^628 + x^624 + x^617 + x^616 + x^612 + x^611 + x^606 + x^605 + x^604 + x^603 + x^600 + x^599 + x^597 + x^594 + x^592 + x^588 + x^587 + x^586 + x^582 + x^580 + x^576 + x^575 + x^568 + x^563 + x^556 + x^552 + x^546 + x^544 + x^542 + x^540 + x^539 + x^537 + x^534 + x^533 + x^526 + x^522 + x^521 + x^520 + x^518 + x^517 + x^516 + x^514 + x^511 + x^510 + x^508 + x^505 + x^503 + x^494 + x^492 + x^488 + x^485 + x^481 + x^475 + x^474 + x^470 + x^467 + x^464 + x^463 + x^462 + x^454 + x^452 + x^449 + x^447 + x^446 + x^444 + x^443 + x^442 + x^439 + x^438 + x^437 + x^432 + x^431 + x^430 + x^427 + x^426 + x^424 + x^422 + x^419 + x^418 + x^413 + x^410 + x^409 + x^406 + x^404 + x^401 + x^398 + x^396 + x^393 + x^392 + x^391 + x^390 + x^389 + x^385 + x^383 + x^380 + x^379 + x^376 + x^374 + x^372 + x^370 + x^368 + x^367 + x^366 + x^365 + x^364 + x^363 + x^361 + x^358 + x^355 + x^354 + x^353 + x^349 + x^348 + x^347 + x^344 + x^343 + x^342 + x^341 + x^338 + x^337 + x^336 + x^334 + x^332 + x^329 + x^328 + x^318 + x^317 + x^312 + x^310 + x^308 + x^307 + x^306 + x^305 + x^304 + x^299 + x^296 + x^294 + x^293 + x^291 + x^289 + x^281 + x^280 + x^278 + x^277 + x^276 + x^274 + x^272 + x^270 + x^267 + x^265 + x^264 + x^263 + x^260 + x^253 + x^252 + x^251 + x^250 + x^247 + x^242 + x^241 + x^239 + x^234 + x^233 + x^231 + x^230 + x^229 + x^224 + x^223 + x^222 + x^217 + x^214 + x^212 + x^210 + x^209 + x^208 + x^203 + x^200 + x^199 + x^198 + x^196 + x^195 + x^192 + x^191 + x^186 + x^185 + x^184 + x^181 + x^180 + x^179 + x^178 + x^177 + x^176 + x^175 + x^172 + x^171 + x^170 + x^169 + x^168 + x^166 + x^165 + x^161 + x^160 + x^159 + x^151 + x^146 + x^144 + x^143 + x^142 + x^141 + x^139 + x^137 + x^136 + x^135 + x^133 + x^131 + x^130 + x^120 + x^116 + x^114 + x^113 + x^108 + x^107 + x^106 + x^104 + x^101 + x^98 + x^97 + x^96 + x^91 + x^90 + x^89 + x^87 + x^82 + x^80 + x^78 + x^73 + x^72 + x^67 + x^62 + x^58 + x^56 + x^55 + x^53 + x^49 + x^46 + x^44 + x^39 + x^32 + x^26 + x^17 + 1
+
+18-7-29 311 x^928 + x^926 + x^920 + x^918 + x^912 + x^910 + x^904 + x^902 + x^898 + x^896 + x^894 + x^890 + x^888 + x^886 + x^882 + x^880 + x^878 + x^874 + x^872 + x^870 + x^866 + x^858 + x^850 + x^842 + x^808 + x^806 + x^792 + x^790 + x^778 + x^776 + x^774 + x^762 + x^760 + x^758 + x^746 + x^730 + x^688 + x^686 + x^680 + x^678 + x^669 + x^667 + x^661 + x^659 + x^658 + x^656 + x^655 + x^654 + x^651 + x^650 + x^648 + x^647 + x^646 + x^643 + x^626 + x^618 + x^611 + x^605 + x^595 + x^589 + x^587 + x^575 + x^569 + x^568 + x^566 + x^561 + x^553 + x^541 + x^539 + x^538 + x^537 + x^536 + x^534 + x^533 + x^515 + x^511 + x^509 + x^507 + x^506 + x^503 + x^501 + x^497 + x^495 + x^493 + x^489 + x^485 + x^483 + x^481 + x^479 + x^475 + x^473 + x^471 + x^469 + x^457 + x^455 + x^453 + x^451 + x^449 + x^448 + x^447 + x^446 + x^443 + x^440 + x^439 + x^438 + x^437 + x^435 + x^433 + x^432 + x^431 + x^429 + x^426 + x^425 + x^424 + x^421 + x^418 + x^417 + x^416 + x^415 + x^414 + x^412 + x^409 + x^408 + x^406 + x^405 + x^404 + x^401 + x^398 + x^396 + x^395 + x^393 + x^392 + x^390 + x^388 + x^387 + x^380 + x^379 + x^377 + x^376 + x^372 + x^371 + x^370 + x^369 + x^367 + x^364 + x^363 + x^362 + x^361 + x^359 + x^358 + x^354 + x^352 + x^350 + x^349 + x^348 + x^341 + x^340 + x^337 + x^336 + x^335 + x^331 + x^330 + x^328 + x^326 + x^320 + x^319 + x^318 + x^317 + x^315 + x^314 + x^313 + x^312 + x^310 + x^308 + x^307 + x^302 + x^301 + x^299 + x^297 + x^295 + x^293 + x^291 + x^287 + x^284 + x^283 + x^282 + x^281 + x^280 + x^279 + x^278 + x^274 + x^271 + x^267 + x^266 + x^264 + x^263 + x^257 + x^256 + x^255 + x^252 + x^251 + x^250 + x^246 + x^241 + x^240 + x^239 + x^234 + x^233 + x^231 + x^230 + x^229 + x^226 + x^225 + x^224 + x^223 + x^222 + x^218 + x^216 + x^214 + x^212 + x^211 + x^206 + x^203 + x^202 + x^199 + x^198 + x^197 + x^193 + x^191 + x^190 + x^188 + x^185 + x^183 + x^181 + x^180 + x^179 + x^176 + x^171 + x^169 + x^167 + x^158 + x^156 + x^155 + x^154 + x^153 + x^151 + x^150 + x^148 + x^145 + x^143 + x^142 + x^141 + x^138 + x^133 + x^132 + x^130 + x^127 + x^125 + x^123 + x^121 + x^118 + x^109 + x^108 + x^105 + x^104 + x^103 + x^102 + x^100 + x^97 + x^95 + x^94 + x^92 + x^90 + x^85 + x^84 + x^82 + x^80 + x^76 + x^74 + x^73 + x^71 + x^70 + x^68 + x^67 + x^66 + x^65 + x^64 + x^61 + x^59 + x^57 + x^55 + x^53 + x^52 + x^48 + x^47 + x^45 + x^41 + x^38 + x^36 + x^34 + x^31 + x^28 + x^26 + x^24 + x^22 + x^18 + x^16 + x^12 + x^10 + x^2 + 1
+
+48-55-49 313 x^928 + x^898 + x^894 + x^893 + x^870 + x^864 + x^860 + x^858 + x^838 + x^836 + x^832 + x^831 + x^830 + x^828 + x^804 + x^802 + x^796 + x^794 + x^778 + x^774 + x^773 + x^770 + x^769 + x^768 + x^741 + x^740 + x^737 + x^736 + x^734 + x^732 + x^731 + x^718 + x^712 + x^711 + x^706 + x^704 + x^702 + x^701 + x^684 + x^681 + x^679 + x^678 + x^676 + x^675 + x^672 + x^671 + x^669 + x^658 + x^656 + x^654 + x^653 + x^652 + x^651 + x^647 + x^646 + x^645 + x^621 + x^618 + x^617 + x^616 + x^615 + x^614 + x^611 + x^610 + x^609 + x^598 + x^596 + x^592 + x^590 + x^589 + x^583 + x^582 + x^580 + x^579 + x^576 + x^561 + x^559 + x^558 + x^557 + x^554 + x^548 + x^547 + x^545 + x^538 + x^534 + x^533 + x^531 + x^529 + x^527 + x^526 + x^524 + x^522 + x^521 + x^515 + x^512 + x^500 + x^497 + x^486 + x^484 + x^478 + x^474 + x^470 + x^469 + x^468 + x^467 + x^466 + x^465 + x^464 + x^462 + x^460 + x^458 + x^456 + x^454 + x^453 + x^450 + x^444 + x^438 + x^436 + x^435 + x^434 + x^433 + x^432 + x^429 + x^424 + x^422 + x^421 + x^418 + x^416 + x^413 + x^412 + x^407 + x^406 + x^405 + x^404 + x^402 + x^399 + x^398 + x^397 + x^396 + x^394 + x^392 + x^391 + x^388 + x^384 + x^380 + x^378 + x^377 + x^375 + x^373 + x^372 + x^371 + x^364 + x^359 + x^356 + x^354 + x^353 + x^352 + x^351 + x^350 + x^347 + x^343 + x^342 + x^340 + x^339 + x^334 + x^331 + x^328 + x^327 + x^325 + x^324 + x^322 + x^316 + x^312 + x^311 + x^310 + x^308 + x^306 + x^305 + x^304 + x^302 + x^301 + x^300 + x^298 + x^297 + x^295 + x^294 + x^292 + x^291 + x^290 + x^289 + x^288 + x^282 + x^280 + x^279 + x^278 + x^277 + x^276 + x^275 + x^273 + x^271 + x^268 + x^264 + x^261 + x^258 + x^256 + x^254 + x^253 + x^251 + x^249 + x^248 + x^246 + x^245 + x^244 + x^242 + x^241 + x^240 + x^239 + x^237 + x^236 + x^232 + x^231 + x^229 + x^228 + x^227 + x^226 + x^224 + x^223 + x^219 + x^216 + x^215 + x^211 + x^210 + x^207 + x^206 + x^204 + x^203 + x^199 + x^198 + x^194 + x^188 + x^187 + x^186 + x^182 + x^181 + x^180 + x^174 + x^171 + x^170 + x^168 + x^165 + x^164 + x^160 + x^152 + x^151 + x^150 + x^149 + x^148 + x^147 + x^144 + x^143 + x^142 + x^141 + x^139 + x^134 + x^129 + x^127 + x^124 + x^121 + x^119 + x^115 + x^108 + x^107 + x^105 + x^104 + x^103 + x^102 + x^95 + x^94 + x^90 + x^89 + x^88 + x^86 + x^84 + x^79 + x^77 + x^73 + x^72 + x^69 + x^66 + x^64 + x^63 + x^62 + x^60 + x^57 + x^56 + x^55 + x^54 + x^53 + x^52 + x^50 + x^49 + x^48 + x^46 + x^45 + x^41 + x^36 + x^34 + x^31 + x^29 + x^28 + x^26 + x^25 + 1
+
+40-44-57 319 x^928 + x^898 + x^870 + x^846 + x^822 + x^819 + x^808 + x^800 + x^794 + x^792 + x^786 + x^778 + x^770 + x^764 + x^759 + x^748 + x^746 + x^740 + x^732 + x^716 + x^713 + x^697 + x^696 + x^691 + x^686 + x^674 + x^664 + x^661 + x^658 + x^650 + x^648 + x^645 + x^644 + x^636 + x^629 + x^626 + x^624 + x^623 + x^621 + x^620 + x^618 + x^615 + x^594 + x^593 + x^591 + x^590 + x^586 + x^583 + x^580 + x^579 + x^577 + x^575 + x^574 + x^572 + x^571 + x^568 + x^564 + x^563 + x^561 + x^558 + x^556 + x^555 + x^553 + x^550 + x^547 + x^545 + x^544 + x^542 + x^541 + x^538 + x^536 + x^533 + x^528 + x^526 + x^525 + x^522 + x^519 + x^513 + x^512 + x^510 + x^509 + x^508 + x^507 + x^504 + x^503 + x^501 + x^495 + x^488 + x^487 + x^485 + x^484 + x^483 + x^482 + x^480 + x^479 + x^474 + x^473 + x^471 + x^470 + x^466 + x^463 + x^460 + x^458 + x^457 + x^454 + x^453 + x^450 + x^449 + x^446 + x^444 + x^443 + x^441 + x^440 + x^439 + x^436 + x^434 + x^433 + x^432 + x^431 + x^430 + x^427 + x^425 + x^424 + x^422 + x^420 + x^417 + x^416 + x^415 + x^413 + x^412 + x^411 + x^410 + x^409 + x^408 + x^407 + x^406 + x^405 + x^403 + x^398 + x^397 + x^395 + x^392 + x^390 + x^387 + x^386 + x^385 + x^383 + x^375 + x^370 + x^369 + x^368 + x^367 + x^365 + x^364 + x^363 + x^360 + x^359 + x^357 + x^356 + x^353 + x^351 + x^349 + x^342 + x^340 + x^339 + x^336 + x^335 + x^329 + x^327 + x^326 + x^324 + x^323 + x^320 + x^319 + x^318 + x^317 + x^316 + x^315 + x^312 + x^311 + x^307 + x^306 + x^302 + x^299 + x^298 + x^297 + x^295 + x^294 + x^293 + x^291 + x^290 + x^287 + x^285 + x^284 + x^283 + x^282 + x^281 + x^279 + x^277 + x^276 + x^275 + x^272 + x^271 + x^268 + x^266 + x^263 + x^262 + x^261 + x^255 + x^251 + x^249 + x^248 + x^245 + x^244 + x^243 + x^240 + x^239 + x^238 + x^236 + x^235 + x^234 + x^230 + x^229 + x^228 + x^227 + x^226 + x^224 + x^221 + x^217 + x^214 + x^212 + x^209 + x^208 + x^204 + x^202 + x^201 + x^197 + x^194 + x^193 + x^192 + x^191 + x^189 + x^188 + x^185 + x^184 + x^182 + x^181 + x^178 + x^176 + x^173 + x^172 + x^171 + x^169 + x^166 + x^163 + x^161 + x^160 + x^158 + x^156 + x^155 + x^154 + x^152 + x^151 + x^149 + x^148 + x^146 + x^145 + x^144 + x^142 + x^141 + x^134 + x^132 + x^129 + x^122 + x^121 + x^119 + x^117 + x^116 + x^113 + x^112 + x^110 + x^109 + x^103 + x^102 + x^101 + x^100 + x^97 + x^95 + x^94 + x^93 + x^92 + x^91 + x^87 + x^86 + x^85 + x^84 + x^81 + x^80 + x^75 + x^74 + x^71 + x^70 + x^68 + x^66 + x^63 + x^52 + x^51 + x^50 + x^47 + x^45 + x^44 + x^43 + x^39 + x^38 + x^34 + x^24 + x^16 + x^8 + 1
+
+21-52-12 321 x^928 + x^898 + x^870 + x^868 + x^856 + x^838 + x^828 + x^826 + x^816 + x^815 + x^808 + x^804 + x^786 + x^784 + x^778 + x^748 + x^744 + x^736 + x^734 + x^733 + x^732 + x^731 + x^726 + x^722 + x^718 + x^710 + x^706 + x^704 + x^703 + x^694 + x^692 + x^691 + x^688 + x^683 + x^680 + x^679 + x^678 + x^674 + x^672 + x^668 + x^664 + x^660 + x^658 + x^656 + x^653 + x^649 + x^648 + x^644 + x^643 + x^638 + x^632 + x^630 + x^625 + x^623 + x^619 + x^618 + x^616 + x^615 + x^613 + x^610 + x^607 + x^606 + x^602 + x^601 + x^600 + x^595 + x^593 + x^589 + x^588 + x^586 + x^585 + x^580 + x^579 + x^578 + x^571 + x^570 + x^566 + x^565 + x^564 + x^563 + x^560 + x^559 + x^555 + x^554 + x^550 + x^548 + x^547 + x^546 + x^544 + x^543 + x^541 + x^539 + x^538 + x^537 + x^535 + x^531 + x^530 + x^529 + x^522 + x^520 + x^514 + x^513 + x^509 + x^507 + x^504 + x^501 + x^500 + x^499 + x^498 + x^496 + x^495 + x^494 + x^492 + x^491 + x^490 + x^486 + x^483 + x^480 + x^479 + x^476 + x^473 + x^469 + x^466 + x^463 + x^460 + x^459 + x^457 + x^451 + x^449 + x^443 + x^441 + x^440 + x^436 + x^433 + x^432 + x^431 + x^424 + x^420 + x^418 + x^416 + x^414 + x^411 + x^410 + x^409 + x^408 + x^406 + x^404 + x^403 + x^401 + x^400 + x^398 + x^393 + x^390 + x^388 + x^385 + x^384 + x^381 + x^375 + x^372 + x^366 + x^365 + x^361 + x^358 + x^356 + x^354 + x^352 + x^347 + x^346 + x^341 + x^340 + x^338 + x^335 + x^334 + x^333 + x^331 + x^330 + x^326 + x^323 + x^320 + x^319 + x^318 + x^317 + x^315 + x^312 + x^311 + x^309 + x^305 + x^303 + x^301 + x^299 + x^297 + x^296 + x^295 + x^290 + x^289 + x^283 + x^282 + x^277 + x^276 + x^273 + x^268 + x^267 + x^266 + x^264 + x^262 + x^261 + x^260 + x^256 + x^254 + x^251 + x^250 + x^247 + x^245 + x^244 + x^243 + x^240 + x^238 + x^235 + x^234 + x^233 + x^231 + x^229 + x^225 + x^224 + x^217 + x^212 + x^211 + x^209 + x^208 + x^205 + x^204 + x^202 + x^200 + x^198 + x^196 + x^195 + x^191 + x^190 + x^188 + x^187 + x^186 + x^182 + x^181 + x^180 + x^175 + x^174 + x^172 + x^171 + x^170 + x^169 + x^166 + x^164 + x^158 + x^154 + x^153 + x^152 + x^149 + x^148 + x^147 + x^146 + x^144 + x^142 + x^141 + x^140 + x^138 + x^137 + x^136 + x^135 + x^133 + x^131 + x^127 + x^125 + x^123 + x^122 + x^121 + x^120 + x^119 + x^115 + x^113 + x^112 + x^111 + x^106 + x^102 + x^101 + x^100 + x^98 + x^96 + x^95 + x^93 + x^92 + x^91 + x^90 + x^89 + x^88 + x^87 + x^81 + x^79 + x^76 + x^72 + x^71 + x^70 + x^64 + x^60 + x^57 + x^56 + x^55 + x^54 + x^50 + x^49 + x^48 + x^47 + x^43 + x^39 + x^38 + x^30 + x^29 + x^26 + x^25 + x^14 + x^10 + 1
+
+25-44-4 331 x^928 + x^898 + x^870 + x^866 + x^862 + x^859 + x^836 + x^834 + x^829 + x^822 + x^808 + x^806 + x^804 + x^800 + x^799 + x^798 + x^797 + x^795 + x^778 + x^776 + x^770 + x^769 + x^767 + x^762 + x^753 + x^739 + x^735 + x^734 + x^731 + x^721 + x^713 + x^709 + x^708 + x^706 + x^705 + x^703 + x^701 + x^698 + x^688 + x^679 + x^677 + x^676 + x^674 + x^670 + x^669 + x^667 + x^666 + x^661 + x^659 + x^658 + x^649 + x^647 + x^645 + x^643 + x^642 + x^638 + x^635 + x^633 + x^629 + x^626 + x^624 + x^620 + x^618 + x^617 + x^614 + x^611 + x^605 + x^603 + x^598 + x^596 + x^594 + x^593 + x^590 + x^587 + x^581 + x^580 + x^579 + x^571 + x^570 + x^568 + x^566 + x^562 + x^558 + x^557 + x^551 + x^550 + x^548 + x^547 + x^546 + x^544 + x^542 + x^541 + x^539 + x^536 + x^533 + x^532 + x^530 + x^527 + x^526 + x^525 + x^524 + x^523 + x^521 + x^520 + x^519 + x^518 + x^517 + x^515 + x^514 + x^513 + x^507 + x^506 + x^504 + x^501 + x^497 + x^493 + x^492 + x^490 + x^488 + x^483 + x^482 + x^481 + x^478 + x^477 + x^476 + x^475 + x^473 + x^467 + x^466 + x^465 + x^463 + x^462 + x^461 + x^460 + x^456 + x^454 + x^453 + x^452 + x^450 + x^448 + x^446 + x^444 + x^443 + x^442 + x^433 + x^426 + x^423 + x^422 + x^420 + x^419 + x^416 + x^413 + x^412 + x^411 + x^410 + x^406 + x^404 + x^403 + x^402 + x^401 + x^400 + x^398 + x^396 + x^395 + x^392 + x^391 + x^389 + x^387 + x^386 + x^385 + x^380 + x^372 + x^366 + x^365 + x^363 + x^362 + x^359 + x^357 + x^354 + x^353 + x^352 + x^348 + x^346 + x^345 + x^342 + x^340 + x^338 + x^335 + x^334 + x^333 + x^332 + x^325 + x^324 + x^323 + x^320 + x^319 + x^318 + x^314 + x^312 + x^309 + x^308 + x^303 + x^302 + x^301 + x^299 + x^295 + x^294 + x^292 + x^291 + x^290 + x^289 + x^286 + x^284 + x^279 + x^278 + x^274 + x^273 + x^268 + x^266 + x^265 + x^263 + x^261 + x^257 + x^256 + x^255 + x^254 + x^253 + x^248 + x^245 + x^244 + x^241 + x^240 + x^237 + x^235 + x^234 + x^233 + x^232 + x^230 + x^229 + x^228 + x^226 + x^223 + x^222 + x^220 + x^218 + x^214 + x^212 + x^211 + x^209 + x^207 + x^206 + x^203 + x^202 + x^201 + x^200 + x^199 + x^198 + x^196 + x^191 + x^189 + x^184 + x^178 + x^177 + x^176 + x^175 + x^172 + x^171 + x^169 + x^166 + x^165 + x^162 + x^161 + x^159 + x^157 + x^156 + x^155 + x^150 + x^149 + x^148 + x^147 + x^143 + x^142 + x^141 + x^140 + x^137 + x^136 + x^135 + x^133 + x^131 + x^130 + x^129 + x^127 + x^126 + x^125 + x^124 + x^123 + x^120 + x^113 + x^112 + x^108 + x^105 + x^104 + x^98 + x^96 + x^92 + x^90 + x^82 + x^81 + x^80 + x^78 + x^76 + x^74 + x^73 + x^68 + x^66 + x^64 + x^62 + x^60 + x^58 + x^54 + x^42 + x^38 + x^36 + x^32 + x^26 + x^18 + x^16 + x^10 + x^8 + x^2 + 1
+
+16-8-37 341 x^928 + x^898 + x^870 + x^842 + x^814 + x^808 + x^788 + x^786 + x^784 + x^778 + x^777 + x^775 + x^773 + x^762 + x^756 + x^751 + x^745 + x^736 + x^723 + x^721 + x^717 + x^715 + x^713 + x^710 + x^700 + x^697 + x^693 + x^691 + x^688 + x^685 + x^678 + x^674 + x^673 + x^672 + x^667 + x^654 + x^650 + x^647 + x^645 + x^644 + x^643 + x^642 + x^641 + x^635 + x^634 + x^632 + x^631 + x^630 + x^622 + x^621 + x^618 + x^615 + x^614 + x^612 + x^608 + x^605 + x^604 + x^603 + x^601 + x^596 + x^595 + x^592 + x^590 + x^589 + x^588 + x^587 + x^586 + x^585 + x^584 + x^583 + x^581 + x^579 + x^578 + x^576 + x^575 + x^573 + x^571 + x^569 + x^565 + x^564 + x^561 + x^560 + x^557 + x^556 + x^555 + x^554 + x^552 + x^544 + x^543 + x^540 + x^535 + x^533 + x^530 + x^528 + x^527 + x^524 + x^522 + x^520 + x^519 + x^517 + x^516 + x^515 + x^514 + x^513 + x^510 + x^509 + x^508 + x^507 + x^503 + x^502 + x^500 + x^497 + x^496 + x^493 + x^491 + x^490 + x^486 + x^480 + x^477 + x^476 + x^475 + x^474 + x^473 + x^472 + x^471 + x^467 + x^464 + x^463 + x^461 + x^458 + x^457 + x^453 + x^446 + x^444 + x^441 + x^439 + x^436 + x^434 + x^433 + x^432 + x^430 + x^427 + x^426 + x^422 + x^418 + x^417 + x^416 + x^414 + x^412 + x^411 + x^410 + x^405 + x^404 + x^401 + x^399 + x^396 + x^395 + x^392 + x^391 + x^390 + x^388 + x^387 + x^386 + x^385 + x^384 + x^383 + x^378 + x^377 + x^375 + x^373 + x^372 + x^371 + x^366 + x^364 + x^358 + x^357 + x^356 + x^352 + x^348 + x^345 + x^342 + x^340 + x^339 + x^338 + x^336 + x^335 + x^331 + x^330 + x^329 + x^327 + x^324 + x^323 + x^322 + x^321 + x^320 + x^317 + x^316 + x^315 + x^314 + x^310 + x^307 + x^306 + x^303 + x^297 + x^295 + x^294 + x^293 + x^292 + x^291 + x^290 + x^288 + x^286 + x^284 + x^283 + x^282 + x^278 + x^276 + x^275 + x^274 + x^269 + x^268 + x^267 + x^263 + x^262 + x^261 + x^260 + x^259 + x^258 + x^256 + x^251 + x^249 + x^248 + x^247 + x^245 + x^242 + x^241 + x^239 + x^238 + x^236 + x^235 + x^234 + x^233 + x^232 + x^230 + x^229 + x^225 + x^224 + x^223 + x^222 + x^220 + x^218 + x^216 + x^214 + x^213 + x^212 + x^211 + x^209 + x^206 + x^201 + x^200 + x^199 + x^197 + x^196 + x^194 + x^193 + x^190 + x^186 + x^184 + x^181 + x^180 + x^179 + x^178 + x^177 + x^176 + x^175 + x^169 + x^168 + x^166 + x^164 + x^160 + x^158 + x^157 + x^156 + x^153 + x^152 + x^147 + x^146 + x^136 + x^134 + x^132 + x^129 + x^126 + x^125 + x^124 + x^123 + x^122 + x^120 + x^119 + x^116 + x^114 + x^112 + x^108 + x^107 + x^106 + x^104 + x^102 + x^98 + x^95 + x^91 + x^85 + x^84 + x^82 + x^81 + x^80 + x^79 + x^77 + x^76 + x^73 + x^72 + x^70 + x^62 + x^60 + x^59 + x^58 + x^56 + x^55 + x^53 + x^49 + x^44 + x^42 + x^41 + x^39 + x^38 + x^35 + x^34 + x^32 + x^28 + x^26 + x^24 + x^22 + 1
+
+17-12-36 341 x^928 + x^898 + x^870 + x^868 + x^860 + x^848 + x^838 + x^830 + x^829 + x^806 + x^798 + x^797 + x^789 + x^788 + x^772 + x^770 + x^767 + x^762 + x^761 + x^756 + x^751 + x^749 + x^748 + x^746 + x^742 + x^740 + x^738 + x^730 + x^726 + x^721 + x^718 + x^716 + x^714 + x^710 + x^709 + x^707 + x^706 + x^705 + x^696 + x^688 + x^684 + x^681 + x^677 + x^676 + x^674 + x^669 + x^666 + x^664 + x^659 + x^658 + x^657 + x^656 + x^655 + x^654 + x^651 + x^650 + x^647 + x^645 + x^639 + x^637 + x^636 + x^634 + x^631 + x^627 + x^625 + x^624 + x^622 + x^621 + x^619 + x^615 + x^614 + x^608 + x^605 + x^601 + x^599 + x^597 + x^596 + x^594 + x^593 + x^592 + x^591 + x^588 + x^587 + x^586 + x^585 + x^583 + x^582 + x^580 + x^578 + x^577 + x^576 + x^575 + x^574 + x^573 + x^572 + x^569 + x^568 + x^567 + x^565 + x^564 + x^561 + x^560 + x^559 + x^558 + x^557 + x^554 + x^553 + x^546 + x^545 + x^543 + x^542 + x^541 + x^539 + x^538 + x^536 + x^533 + x^530 + x^529 + x^527 + x^526 + x^525 + x^521 + x^520 + x^513 + x^509 + x^508 + x^504 + x^501 + x^500 + x^499 + x^498 + x^497 + x^496 + x^494 + x^488 + x^486 + x^484 + x^480 + x^479 + x^478 + x^475 + x^471 + x^469 + x^466 + x^463 + x^458 + x^456 + x^455 + x^452 + x^450 + x^449 + x^445 + x^437 + x^436 + x^433 + x^432 + x^430 + x^428 + x^426 + x^425 + x^423 + x^417 + x^416 + x^415 + x^413 + x^401 + x^400 + x^395 + x^394 + x^392 + x^391 + x^387 + x^386 + x^385 + x^384 + x^383 + x^379 + x^375 + x^373 + x^372 + x^371 + x^368 + x^366 + x^361 + x^360 + x^359 + x^358 + x^357 + x^354 + x^352 + x^350 + x^349 + x^348 + x^347 + x^345 + x^344 + x^343 + x^340 + x^334 + x^332 + x^330 + x^328 + x^327 + x^325 + x^323 + x^321 + x^318 + x^317 + x^316 + x^315 + x^314 + x^311 + x^310 + x^309 + x^308 + x^307 + x^306 + x^304 + x^299 + x^298 + x^296 + x^295 + x^294 + x^292 + x^291 + x^288 + x^287 + x^286 + x^282 + x^281 + x^280 + x^272 + x^271 + x^268 + x^267 + x^262 + x^256 + x^253 + x^252 + x^250 + x^244 + x^242 + x^241 + x^240 + x^238 + x^234 + x^233 + x^232 + x^231 + x^229 + x^228 + x^227 + x^226 + x^223 + x^222 + x^221 + x^220 + x^219 + x^218 + x^217 + x^215 + x^214 + x^212 + x^211 + x^208 + x^206 + x^203 + x^201 + x^199 + x^198 + x^195 + x^194 + x^193 + x^192 + x^189 + x^185 + x^182 + x^180 + x^179 + x^177 + x^176 + x^173 + x^172 + x^170 + x^164 + x^163 + x^160 + x^157 + x^155 + x^153 + x^152 + x^150 + x^147 + x^146 + x^139 + x^137 + x^132 + x^131 + x^127 + x^126 + x^125 + x^123 + x^122 + x^120 + x^115 + x^113 + x^111 + x^109 + x^107 + x^106 + x^104 + x^103 + x^101 + x^100 + x^99 + x^98 + x^97 + x^94 + x^88 + x^85 + x^78 + x^77 + x^76 + x^71 + x^68 + x^66 + x^64 + x^51 + x^47 + x^45 + x^39 + x^38 + x^36 + x^31 + x^30 + x^26 + x^24 + x^22 + x^20 + x^15 + 1
+
+2-30-27 343 x^928 + x^898 + x^881 + x^870 + x^868 + x^866 + x^851 + x^838 + x^819 + x^817 + x^808 + x^806 + x^804 + x^778 + x^776 + x^774 + x^772 + x^761 + x^759 + x^755 + x^753 + x^748 + x^742 + x^740 + x^731 + x^725 + x^718 + x^716 + x^712 + x^710 + x^706 + x^695 + x^693 + x^691 + x^689 + x^688 + x^682 + x^678 + x^674 + x^665 + x^663 + x^661 + x^658 + x^657 + x^652 + x^646 + x^644 + x^642 + x^641 + x^637 + x^629 + x^628 + x^627 + x^626 + x^625 + x^618 + x^616 + x^614 + x^612 + x^611 + x^610 + x^607 + x^601 + x^598 + x^597 + x^593 + x^592 + x^588 + x^580 + x^579 + x^577 + x^575 + x^573 + x^571 + x^569 + x^568 + x^566 + x^564 + x^563 + x^562 + x^561 + x^560 + x^554 + x^552 + x^550 + x^548 + x^543 + x^539 + x^538 + x^536 + x^534 + x^531 + x^530 + x^529 + x^528 + x^524 + x^521 + x^519 + x^517 + x^515 + x^513 + x^509 + x^508 + x^507 + x^505 + x^502 + x^500 + x^499 + x^498 + x^497 + x^492 + x^491 + x^487 + x^486 + x^484 + x^479 + x^478 + x^477 + x^476 + x^473 + x^470 + x^468 + x^466 + x^465 + x^464 + x^458 + x^454 + x^450 + x^448 + x^447 + x^446 + x^445 + x^439 + x^436 + x^435 + x^434 + x^433 + x^432 + x^428 + x^426 + x^422 + x^420 + x^416 + x^415 + x^413 + x^411 + x^409 + x^407 + x^406 + x^404 + x^399 + x^396 + x^392 + x^389 + x^384 + x^383 + x^382 + x^381 + x^379 + x^377 + x^376 + x^374 + x^372 + x^370 + x^367 + x^359 + x^355 + x^352 + x^347 + x^346 + x^344 + x^342 + x^341 + x^339 + x^338 + x^336 + x^335 + x^334 + x^328 + x^327 + x^324 + x^320 + x^318 + x^316 + x^314 + x^313 + x^309 + x^308 + x^304 + x^303 + x^300 + x^298 + x^297 + x^296 + x^294 + x^292 + x^287 + x^286 + x^284 + x^283 + x^282 + x^278 + x^276 + x^272 + x^269 + x^266 + x^265 + x^264 + x^261 + x^256 + x^252 + x^250 + x^248 + x^247 + x^245 + x^244 + x^243 + x^242 + x^239 + x^238 + x^237 + x^236 + x^235 + x^234 + x^233 + x^231 + x^229 + x^226 + x^225 + x^224 + x^220 + x^219 + x^216 + x^213 + x^212 + x^210 + x^205 + x^204 + x^203 + x^201 + x^199 + x^197 + x^194 + x^192 + x^191 + x^190 + x^189 + x^188 + x^186 + x^184 + x^183 + x^182 + x^178 + x^177 + x^176 + x^175 + x^173 + x^171 + x^170 + x^169 + x^166 + x^165 + x^163 + x^162 + x^161 + x^157 + x^156 + x^155 + x^153 + x^152 + x^150 + x^148 + x^147 + x^146 + x^144 + x^143 + x^141 + x^139 + x^137 + x^134 + x^133 + x^129 + x^128 + x^127 + x^126 + x^125 + x^123 + x^119 + x^117 + x^116 + x^115 + x^114 + x^113 + x^111 + x^110 + x^102 + x^101 + x^100 + x^99 + x^97 + x^96 + x^94 + x^93 + x^89 + x^88 + x^84 + x^83 + x^81 + x^78 + x^74 + x^72 + x^71 + x^69 + x^67 + x^62 + x^61 + x^59 + x^57 + x^56 + x^55 + x^53 + x^51 + x^47 + x^44 + x^42 + x^39 + x^37 + x^36 + x^35 + x^33 + x^30 + x^26 + x^24 + x^23 + x^21 + x^19 + x^18 + x^17 + x^16 + x^10 + x^8 + x^2 + 1
+
+26-55-39 345 x^928 + x^904 + x^898 + x^870 + x^861 + x^856 + x^851 + x^850 + x^831 + x^821 + x^820 + x^818 + x^813 + x^802 + x^796 + x^794 + x^790 + x^788 + x^783 + x^778 + x^775 + x^772 + x^770 + x^765 + x^760 + x^754 + x^746 + x^745 + x^741 + x^740 + x^736 + x^735 + x^734 + x^732 + x^731 + x^729 + x^727 + x^723 + x^722 + x^721 + x^716 + x^715 + x^710 + x^708 + x^705 + x^701 + x^699 + x^686 + x^685 + x^684 + x^681 + x^679 + x^678 + x^676 + x^674 + x^673 + x^672 + x^668 + x^664 + x^663 + x^661 + x^660 + x^658 + x^656 + x^650 + x^648 + x^645 + x^643 + x^641 + x^638 + x^637 + x^636 + x^632 + x^622 + x^621 + x^618 + x^616 + x^615 + x^614 + x^612 + x^608 + x^603 + x^600 + x^598 + x^595 + x^594 + x^593 + x^591 + x^590 + x^589 + x^588 + x^585 + x^582 + x^581 + x^576 + x^574 + x^571 + x^569 + x^568 + x^564 + x^562 + x^557 + x^556 + x^553 + x^550 + x^549 + x^548 + x^547 + x^546 + x^545 + x^544 + x^543 + x^538 + x^535 + x^530 + x^525 + x^520 + x^517 + x^515 + x^514 + x^510 + x^509 + x^506 + x^501 + x^497 + x^495 + x^489 + x^486 + x^484 + x^483 + x^482 + x^480 + x^479 + x^476 + x^474 + x^473 + x^471 + x^470 + x^469 + x^467 + x^464 + x^462 + x^460 + x^453 + x^452 + x^450 + x^449 + x^448 + x^446 + x^444 + x^443 + x^441 + x^436 + x^435 + x^434 + x^433 + x^432 + x^429 + x^428 + x^427 + x^424 + x^419 + x^418 + x^417 + x^416 + x^413 + x^412 + x^410 + x^407 + x^404 + x^403 + x^401 + x^399 + x^398 + x^397 + x^396 + x^394 + x^393 + x^392 + x^390 + x^386 + x^385 + x^383 + x^379 + x^378 + x^377 + x^376 + x^375 + x^373 + x^372 + x^366 + x^362 + x^359 + x^357 + x^355 + x^354 + x^351 + x^350 + x^347 + x^346 + x^344 + x^340 + x^339 + x^338 + x^337 + x^333 + x^332 + x^331 + x^330 + x^328 + x^326 + x^325 + x^323 + x^319 + x^315 + x^314 + x^313 + x^311 + x^310 + x^308 + x^307 + x^306 + x^304 + x^301 + x^300 + x^298 + x^296 + x^294 + x^293 + x^292 + x^291 + x^290 + x^286 + x^283 + x^280 + x^277 + x^274 + x^272 + x^265 + x^264 + x^263 + x^261 + x^260 + x^258 + x^255 + x^252 + x^251 + x^250 + x^249 + x^247 + x^245 + x^244 + x^241 + x^238 + x^235 + x^234 + x^230 + x^228 + x^225 + x^221 + x^218 + x^212 + x^211 + x^210 + x^208 + x^206 + x^204 + x^203 + x^202 + x^199 + x^198 + x^196 + x^195 + x^193 + x^188 + x^186 + x^184 + x^183 + x^177 + x^176 + x^167 + x^166 + x^165 + x^163 + x^161 + x^160 + x^158 + x^156 + x^153 + x^151 + x^146 + x^144 + x^141 + x^140 + x^134 + x^133 + x^129 + x^128 + x^127 + x^124 + x^123 + x^121 + x^119 + x^117 + x^115 + x^114 + x^113 + x^112 + x^111 + x^110 + x^109 + x^105 + x^104 + x^103 + x^100 + x^99 + x^93 + x^92 + x^91 + x^86 + x^84 + x^81 + x^80 + x^77 + x^75 + x^72 + x^71 + x^70 + x^68 + x^66 + x^65 + x^64 + x^61 + x^54 + x^53 + x^47 + x^45 + x^36 + x^35 + x^34 + x^32 + x^29 + x^18 + x^7 + 1
+
+40-36-23 345 x^928 + x^898 + x^886 + x^870 + x^862 + x^844 + x^838 + x^826 + x^820 + x^816 + x^814 + x^808 + x^797 + x^792 + x^791 + x^790 + x^784 + x^778 + x^777 + x^772 + x^768 + x^767 + x^766 + x^762 + x^761 + x^756 + x^753 + x^749 + x^747 + x^744 + x^742 + x^738 + x^735 + x^734 + x^726 + x^724 + x^723 + x^720 + x^712 + x^702 + x^701 + x^695 + x^689 + x^684 + x^683 + x^681 + x^677 + x^675 + x^670 + x^669 + x^664 + x^663 + x^660 + x^659 + x^658 + x^653 + x^648 + x^646 + x^644 + x^634 + x^629 + x^628 + x^627 + x^626 + x^625 + x^622 + x^621 + x^617 + x^616 + x^611 + x^609 + x^605 + x^604 + x^603 + x^602 + x^597 + x^595 + x^594 + x^593 + x^592 + x^586 + x^585 + x^584 + x^578 + x^575 + x^574 + x^573 + x^572 + x^571 + x^569 + x^565 + x^563 + x^561 + x^559 + x^557 + x^555 + x^554 + x^547 + x^545 + x^543 + x^539 + x^537 + x^536 + x^535 + x^534 + x^529 + x^528 + x^527 + x^525 + x^524 + x^521 + x^520 + x^519 + x^518 + x^517 + x^515 + x^514 + x^512 + x^510 + x^509 + x^508 + x^507 + x^506 + x^504 + x^503 + x^501 + x^499 + x^496 + x^494 + x^490 + x^489 + x^487 + x^485 + x^484 + x^482 + x^481 + x^480 + x^479 + x^478 + x^477 + x^475 + x^473 + x^470 + x^466 + x^465 + x^464 + x^463 + x^460 + x^457 + x^456 + x^454 + x^453 + x^452 + x^447 + x^446 + x^442 + x^441 + x^439 + x^436 + x^434 + x^432 + x^430 + x^428 + x^427 + x^423 + x^421 + x^416 + x^415 + x^414 + x^413 + x^411 + x^408 + x^405 + x^402 + x^401 + x^399 + x^396 + x^394 + x^393 + x^391 + x^390 + x^389 + x^388 + x^387 + x^386 + x^384 + x^381 + x^379 + x^378 + x^377 + x^375 + x^374 + x^372 + x^369 + x^367 + x^366 + x^364 + x^363 + x^361 + x^360 + x^359 + x^358 + x^356 + x^355 + x^354 + x^353 + x^352 + x^349 + x^345 + x^343 + x^342 + x^338 + x^336 + x^335 + x^334 + x^333 + x^331 + x^329 + x^328 + x^327 + x^320 + x^318 + x^317 + x^316 + x^312 + x^307 + x^304 + x^303 + x^300 + x^298 + x^296 + x^295 + x^294 + x^293 + x^291 + x^290 + x^288 + x^287 + x^286 + x^285 + x^284 + x^276 + x^275 + x^274 + x^273 + x^272 + x^271 + x^269 + x^268 + x^266 + x^263 + x^262 + x^259 + x^257 + x^255 + x^254 + x^251 + x^248 + x^246 + x^244 + x^240 + x^238 + x^237 + x^235 + x^234 + x^232 + x^228 + x^226 + x^225 + x^224 + x^222 + x^220 + x^217 + x^213 + x^212 + x^211 + x^209 + x^208 + x^207 + x^202 + x^200 + x^199 + x^198 + x^192 + x^190 + x^187 + x^183 + x^182 + x^180 + x^175 + x^172 + x^171 + x^170 + x^169 + x^167 + x^166 + x^165 + x^164 + x^163 + x^160 + x^157 + x^154 + x^153 + x^152 + x^150 + x^149 + x^148 + x^147 + x^146 + x^144 + x^142 + x^140 + x^137 + x^136 + x^134 + x^132 + x^129 + x^128 + x^124 + x^119 + x^117 + x^116 + x^115 + x^110 + x^108 + x^106 + x^103 + x^98 + x^88 + x^82 + x^76 + x^75 + x^74 + x^69 + x^68 + x^64 + x^62 + x^51 + x^47 + x^46 + x^39 + x^32 + x^23 + x^22 + 1
+
+24-36-37 347 x^928 + x^898 + x^878 + x^870 + x^854 + x^830 + x^824 + x^821 + x^818 + x^816 + x^813 + x^808 + x^806 + x^800 + x^792 + x^791 + x^789 + x^783 + x^780 + x^778 + x^776 + x^768 + x^765 + x^759 + x^753 + x^750 + x^747 + x^745 + x^744 + x^741 + x^740 + x^736 + x^734 + x^729 + x^721 + x^717 + x^715 + x^714 + x^708 + x^705 + x^704 + x^702 + x^699 + x^694 + x^690 + x^688 + x^684 + x^682 + x^681 + x^680 + x^679 + x^670 + x^669 + x^666 + x^664 + x^663 + x^660 + x^652 + x^649 + x^646 + x^645 + x^643 + x^639 + x^636 + x^634 + x^633 + x^631 + x^629 + x^627 + x^622 + x^621 + x^620 + x^614 + x^613 + x^612 + x^611 + x^610 + x^609 + x^605 + x^603 + x^601 + x^600 + x^599 + x^596 + x^593 + x^590 + x^587 + x^586 + x^585 + x^584 + x^583 + x^582 + x^581 + x^579 + x^577 + x^573 + x^565 + x^564 + x^563 + x^562 + x^561 + x^560 + x^559 + x^558 + x^557 + x^554 + x^550 + x^549 + x^546 + x^545 + x^544 + x^543 + x^542 + x^539 + x^538 + x^536 + x^535 + x^534 + x^529 + x^527 + x^525 + x^524 + x^523 + x^521 + x^519 + x^518 + x^516 + x^515 + x^512 + x^510 + x^505 + x^504 + x^503 + x^501 + x^500 + x^499 + x^493 + x^492 + x^488 + x^484 + x^483 + x^479 + x^474 + x^472 + x^470 + x^465 + x^464 + x^459 + x^457 + x^455 + x^454 + x^450 + x^440 + x^435 + x^434 + x^433 + x^427 + x^426 + x^424 + x^421 + x^420 + x^419 + x^414 + x^413 + x^412 + x^409 + x^407 + x^406 + x^405 + x^403 + x^401 + x^400 + x^399 + x^398 + x^395 + x^393 + x^391 + x^390 + x^388 + x^383 + x^381 + x^376 + x^374 + x^370 + x^367 + x^365 + x^363 + x^359 + x^356 + x^355 + x^353 + x^352 + x^348 + x^347 + x^346 + x^345 + x^344 + x^343 + x^342 + x^339 + x^336 + x^330 + x^327 + x^326 + x^325 + x^324 + x^323 + x^321 + x^318 + x^316 + x^315 + x^314 + x^312 + x^311 + x^310 + x^302 + x^300 + x^298 + x^295 + x^294 + x^292 + x^284 + x^282 + x^279 + x^278 + x^277 + x^276 + x^271 + x^268 + x^267 + x^266 + x^265 + x^264 + x^262 + x^260 + x^256 + x^253 + x^250 + x^249 + x^248 + x^244 + x^243 + x^242 + x^239 + x^236 + x^235 + x^232 + x^231 + x^229 + x^227 + x^226 + x^222 + x^220 + x^219 + x^216 + x^215 + x^214 + x^213 + x^211 + x^209 + x^208 + x^204 + x^202 + x^200 + x^199 + x^198 + x^196 + x^193 + x^191 + x^190 + x^189 + x^188 + x^187 + x^186 + x^179 + x^178 + x^177 + x^176 + x^175 + x^174 + x^170 + x^169 + x^167 + x^163 + x^162 + x^161 + x^160 + x^153 + x^150 + x^149 + x^147 + x^145 + x^140 + x^138 + x^136 + x^135 + x^133 + x^131 + x^130 + x^128 + x^127 + x^119 + x^117 + x^113 + x^111 + x^110 + x^108 + x^104 + x^103 + x^102 + x^101 + x^100 + x^99 + x^97 + x^96 + x^93 + x^88 + x^87 + x^86 + x^85 + x^84 + x^83 + x^82 + x^80 + x^78 + x^77 + x^72 + x^71 + x^70 + x^67 + x^66 + x^64 + x^63 + x^62 + x^61 + x^59 + x^58 + x^56 + x^54 + x^53 + x^50 + x^47 + x^46 + x^38 + x^24 + x^16 + 1
+
+26-38-9 353 x^928 + x^898 + x^875 + x^870 + x^848 + x^822 + x^808 + x^806 + x^800 + x^798 + x^797 + x^795 + x^792 + x^788 + x^778 + x^776 + x^769 + x^767 + x^765 + x^762 + x^758 + x^756 + x^747 + x^741 + x^732 + x^730 + x^728 + x^727 + x^723 + x^719 + x^714 + x^712 + x^711 + x^709 + x^706 + x^703 + x^700 + x^697 + x^695 + x^689 + x^688 + x^686 + x^684 + x^682 + x^680 + x^678 + x^676 + x^674 + x^673 + x^667 + x^666 + x^664 + x^661 + x^658 + x^653 + x^652 + x^649 + x^648 + x^646 + x^645 + x^635 + x^634 + x^633 + x^629 + x^626 + x^625 + x^620 + x^616 + x^614 + x^612 + x^611 + x^610 + x^607 + x^606 + x^604 + x^603 + x^599 + x^595 + x^594 + x^591 + x^583 + x^580 + x^578 + x^577 + x^572 + x^569 + x^568 + x^567 + x^566 + x^564 + x^559 + x^558 + x^555 + x^554 + x^550 + x^549 + x^548 + x^543 + x^542 + x^541 + x^539 + x^533 + x^532 + x^531 + x^528 + x^527 + x^526 + x^523 + x^519 + x^518 + x^515 + x^514 + x^513 + x^512 + x^511 + x^510 + x^509 + x^508 + x^507 + x^506 + x^502 + x^497 + x^495 + x^491 + x^488 + x^487 + x^485 + x^483 + x^482 + x^481 + x^478 + x^477 + x^476 + x^475 + x^473 + x^469 + x^466 + x^463 + x^462 + x^460 + x^458 + x^457 + x^456 + x^451 + x^447 + x^444 + x^443 + x^442 + x^440 + x^438 + x^437 + x^435 + x^433 + x^432 + x^430 + x^427 + x^424 + x^418 + x^417 + x^416 + x^414 + x^410 + x^409 + x^403 + x^401 + x^398 + x^397 + x^396 + x^394 + x^393 + x^391 + x^389 + x^388 + x^386 + x^385 + x^384 + x^382 + x^381 + x^380 + x^375 + x^374 + x^368 + x^364 + x^363 + x^359 + x^358 + x^357 + x^356 + x^354 + x^350 + x^349 + x^347 + x^346 + x^339 + x^337 + x^336 + x^334 + x^332 + x^330 + x^329 + x^328 + x^327 + x^326 + x^325 + x^324 + x^320 + x^318 + x^317 + x^315 + x^313 + x^309 + x^307 + x^305 + x^304 + x^303 + x^300 + x^299 + x^295 + x^293 + x^290 + x^288 + x^286 + x^285 + x^281 + x^279 + x^277 + x^274 + x^273 + x^269 + x^267 + x^266 + x^265 + x^263 + x^262 + x^257 + x^256 + x^255 + x^251 + x^249 + x^247 + x^246 + x^243 + x^241 + x^237 + x^236 + x^233 + x^230 + x^228 + x^227 + x^226 + x^225 + x^224 + x^223 + x^222 + x^221 + x^220 + x^212 + x^211 + x^210 + x^209 + x^208 + x^205 + x^204 + x^202 + x^201 + x^200 + x^197 + x^192 + x^191 + x^186 + x^184 + x^183 + x^181 + x^177 + x^175 + x^174 + x^170 + x^167 + x^165 + x^164 + x^162 + x^156 + x^154 + x^149 + x^148 + x^147 + x^144 + x^143 + x^142 + x^141 + x^139 + x^138 + x^137 + x^133 + x^131 + x^130 + x^128 + x^127 + x^126 + x^120 + x^116 + x^115 + x^113 + x^111 + x^108 + x^107 + x^105 + x^101 + x^99 + x^97 + x^95 + x^91 + x^90 + x^88 + x^87 + x^85 + x^81 + x^79 + x^78 + x^75 + x^72 + x^71 + x^70 + x^69 + x^66 + x^65 + x^63 + x^59 + x^57 + x^55 + x^54 + x^52 + x^51 + x^50 + x^49 + x^46 + x^44 + x^43 + x^39 + x^36 + x^34 + x^33 + x^32 + x^31 + x^30 + x^26 + x^24 + x^22 + x^16 + x^14 + x^8 + x^6 + 1
+
+31-6-30 353 x^928 + x^898 + x^870 + x^834 + x^814 + x^796 + x^790 + x^788 + x^784 + x^774 + x^772 + x^770 + x^762 + x^760 + x^756 + x^748 + x^740 + x^734 + x^732 + x^728 + x^727 + x^726 + x^718 + x^716 + x^712 + x^707 + x^701 + x^700 + x^697 + x^692 + x^688 + x^686 + x^684 + x^682 + x^681 + x^678 + x^677 + x^676 + x^674 + x^671 + x^670 + x^668 + x^665 + x^660 + x^658 + x^655 + x^652 + x^651 + x^650 + x^649 + x^646 + x^642 + x^641 + x^639 + x^638 + x^637 + x^636 + x^635 + x^630 + x^625 + x^624 + x^623 + x^622 + x^621 + x^620 + x^619 + x^617 + x^612 + x^611 + x^610 + x^609 + x^608 + x^607 + x^606 + x^604 + x^601 + x^598 + x^597 + x^593 + x^592 + x^591 + x^590 + x^582 + x^579 + x^578 + x^572 + x^570 + x^567 + x^566 + x^565 + x^563 + x^561 + x^559 + x^558 + x^555 + x^554 + x^544 + x^543 + x^542 + x^540 + x^539 + x^536 + x^533 + x^529 + x^528 + x^525 + x^522 + x^517 + x^516 + x^512 + x^511 + x^510 + x^507 + x^505 + x^502 + x^501 + x^499 + x^494 + x^492 + x^491 + x^489 + x^488 + x^487 + x^486 + x^484 + x^483 + x^481 + x^480 + x^476 + x^473 + x^469 + x^468 + x^466 + x^465 + x^464 + x^457 + x^451 + x^449 + x^448 + x^445 + x^444 + x^441 + x^440 + x^438 + x^436 + x^435 + x^433 + x^432 + x^431 + x^428 + x^425 + x^422 + x^420 + x^418 + x^414 + x^413 + x^412 + x^411 + x^410 + x^406 + x^405 + x^402 + x^401 + x^400 + x^394 + x^390 + x^389 + x^387 + x^384 + x^382 + x^380 + x^376 + x^375 + x^372 + x^371 + x^370 + x^369 + x^366 + x^363 + x^362 + x^361 + x^359 + x^357 + x^356 + x^354 + x^352 + x^351 + x^349 + x^347 + x^346 + x^344 + x^343 + x^342 + x^341 + x^340 + x^338 + x^337 + x^336 + x^334 + x^333 + x^331 + x^328 + x^323 + x^322 + x^318 + x^315 + x^313 + x^312 + x^310 + x^309 + x^308 + x^307 + x^301 + x^300 + x^298 + x^296 + x^295 + x^294 + x^292 + x^287 + x^285 + x^284 + x^283 + x^282 + x^279 + x^276 + x^275 + x^272 + x^270 + x^269 + x^268 + x^267 + x^263 + x^261 + x^259 + x^258 + x^256 + x^250 + x^248 + x^247 + x^246 + x^245 + x^244 + x^240 + x^239 + x^238 + x^237 + x^236 + x^235 + x^232 + x^231 + x^230 + x^229 + x^226 + x^223 + x^220 + x^217 + x^216 + x^213 + x^212 + x^210 + x^208 + x^205 + x^204 + x^201 + x^195 + x^194 + x^192 + x^191 + x^189 + x^188 + x^182 + x^181 + x^177 + x^175 + x^174 + x^173 + x^171 + x^169 + x^167 + x^162 + x^161 + x^159 + x^158 + x^154 + x^153 + x^148 + x^146 + x^145 + x^144 + x^143 + x^142 + x^141 + x^140 + x^139 + x^138 + x^135 + x^134 + x^133 + x^122 + x^119 + x^118 + x^115 + x^111 + x^110 + x^108 + x^107 + x^106 + x^105 + x^101 + x^99 + x^97 + x^96 + x^95 + x^94 + x^93 + x^92 + x^90 + x^87 + x^84 + x^83 + x^80 + x^74 + x^73 + x^71 + x^70 + x^67 + x^66 + x^63 + x^55 + x^53 + x^52 + x^51 + x^49 + x^45 + x^44 + x^43 + x^40 + x^35 + x^34 + x^33 + x^32 + x^27 + x^25 + x^24 + x^22 + x^21 + x^20 + x^17 + x^16 + x^11 + x^4 + 1
+
+54-21-7 353 x^928 + x^898 + x^870 + x^861 + x^860 + x^859 + x^858 + x^846 + x^842 + x^837 + x^836 + x^835 + x^831 + x^830 + x^829 + x^828 + x^822 + x^818 + x^811 + x^810 + x^808 + x^807 + x^804 + x^798 + x^792 + x^788 + x^781 + x^778 + x^758 + x^756 + x^751 + x^750 + x^746 + x^745 + x^740 + x^739 + x^738 + x^722 + x^720 + x^716 + x^703 + x^701 + x^696 + x^695 + x^688 + x^686 + x^674 + x^666 + x^659 + x^658 + x^656 + x^655 + x^654 + x^649 + x^644 + x^643 + x^641 + x^637 + x^632 + x^630 + x^629 + x^626 + x^623 + x^621 + x^620 + x^618 + x^614 + x^613 + x^606 + x^601 + x^599 + x^597 + x^595 + x^592 + x^591 + x^589 + x^588 + x^586 + x^584 + x^582 + x^577 + x^576 + x^575 + x^568 + x^567 + x^565 + x^564 + x^562 + x^558 + x^556 + x^553 + x^551 + x^550 + x^548 + x^547 + x^541 + x^540 + x^535 + x^534 + x^528 + x^527 + x^526 + x^522 + x^521 + x^520 + x^517 + x^514 + x^512 + x^510 + x^504 + x^503 + x^502 + x^498 + x^497 + x^496 + x^487 + x^482 + x^474 + x^473 + x^469 + x^468 + x^466 + x^463 + x^462 + x^459 + x^454 + x^453 + x^452 + x^451 + x^447 + x^442 + x^441 + x^433 + x^431 + x^430 + x^429 + x^426 + x^424 + x^423 + x^422 + x^421 + x^419 + x^417 + x^415 + x^412 + x^411 + x^409 + x^405 + x^402 + x^397 + x^396 + x^393 + x^392 + x^391 + x^385 + x^384 + x^382 + x^381 + x^380 + x^370 + x^369 + x^367 + x^365 + x^364 + x^361 + x^359 + x^356 + x^355 + x^351 + x^350 + x^349 + x^343 + x^342 + x^341 + x^340 + x^339 + x^338 + x^336 + x^335 + x^333 + x^332 + x^331 + x^330 + x^326 + x^325 + x^324 + x^323 + x^318 + x^317 + x^315 + x^313 + x^310 + x^309 + x^306 + x^301 + x^300 + x^298 + x^295 + x^294 + x^293 + x^292 + x^291 + x^290 + x^289 + x^288 + x^282 + x^281 + x^278 + x^277 + x^276 + x^275 + x^273 + x^271 + x^268 + x^266 + x^265 + x^263 + x^261 + x^260 + x^259 + x^257 + x^252 + x^249 + x^247 + x^244 + x^243 + x^238 + x^236 + x^232 + x^231 + x^229 + x^228 + x^227 + x^226 + x^225 + x^224 + x^221 + x^220 + x^219 + x^215 + x^214 + x^211 + x^209 + x^207 + x^204 + x^201 + x^198 + x^196 + x^195 + x^194 + x^193 + x^191 + x^189 + x^186 + x^185 + x^182 + x^181 + x^179 + x^178 + x^174 + x^173 + x^172 + x^170 + x^168 + x^166 + x^164 + x^162 + x^160 + x^159 + x^156 + x^155 + x^154 + x^152 + x^151 + x^149 + x^148 + x^147 + x^146 + x^145 + x^143 + x^140 + x^134 + x^133 + x^130 + x^129 + x^128 + x^126 + x^124 + x^123 + x^122 + x^121 + x^119 + x^118 + x^117 + x^116 + x^115 + x^113 + x^110 + x^107 + x^106 + x^105 + x^104 + x^103 + x^102 + x^101 + x^99 + x^97 + x^96 + x^95 + x^94 + x^93 + x^92 + x^91 + x^90 + x^89 + x^86 + x^85 + x^82 + x^81 + x^80 + x^79 + x^78 + x^76 + x^73 + x^71 + x^69 + x^65 + x^63 + x^60 + x^58 + x^57 + x^56 + x^55 + x^54 + x^52 + x^49 + x^47 + x^46 + x^45 + x^43 + x^42 + x^40 + x^39 + x^38 + x^36 + x^33 + x^32 + x^28 + x^25 + x^19 + x^18 + x^7 + 1
+
+8-36-47 355 x^928 + x^898 + x^870 + x^860 + x^856 + x^830 + x^818 + x^814 + x^813 + x^808 + x^800 + x^797 + x^796 + x^792 + x^788 + x^783 + x^778 + x^776 + x^772 + x^771 + x^770 + x^767 + x^766 + x^762 + x^755 + x^750 + x^740 + x^737 + x^736 + x^734 + x^730 + x^729 + x^724 + x^719 + x^711 + x^710 + x^707 + x^706 + x^698 + x^693 + x^692 + x^690 + x^688 + x^687 + x^680 + x^676 + x^674 + x^673 + x^672 + x^669 + x^665 + x^663 + x^662 + x^658 + x^657 + x^656 + x^653 + x^651 + x^650 + x^648 + x^647 + x^642 + x^635 + x^632 + x^631 + x^630 + x^627 + x^625 + x^624 + x^623 + x^622 + x^620 + x^619 + x^618 + x^609 + x^600 + x^595 + x^593 + x^592 + x^591 + x^589 + x^587 + x^583 + x^582 + x^579 + x^578 + x^577 + x^574 + x^570 + x^566 + x^565 + x^561 + x^559 + x^558 + x^557 + x^556 + x^555 + x^552 + x^550 + x^548 + x^544 + x^542 + x^541 + x^540 + x^537 + x^536 + x^534 + x^533 + x^532 + x^531 + x^528 + x^527 + x^525 + x^524 + x^521 + x^519 + x^518 + x^517 + x^516 + x^515 + x^514 + x^513 + x^512 + x^511 + x^509 + x^507 + x^505 + x^504 + x^502 + x^501 + x^497 + x^496 + x^493 + x^492 + x^491 + x^490 + x^488 + x^486 + x^485 + x^480 + x^478 + x^476 + x^475 + x^473 + x^469 + x^468 + x^467 + x^466 + x^463 + x^462 + x^453 + x^452 + x^451 + x^449 + x^447 + x^446 + x^445 + x^444 + x^443 + x^440 + x^438 + x^437 + x^436 + x^435 + x^427 + x^426 + x^423 + x^421 + x^419 + x^416 + x^411 + x^410 + x^409 + x^408 + x^406 + x^405 + x^404 + x^403 + x^402 + x^400 + x^398 + x^397 + x^395 + x^391 + x^390 + x^389 + x^385 + x^384 + x^380 + x^378 + x^377 + x^374 + x^373 + x^372 + x^370 + x^367 + x^366 + x^365 + x^363 + x^361 + x^360 + x^354 + x^352 + x^351 + x^350 + x^347 + x^342 + x^339 + x^337 + x^334 + x^333 + x^330 + x^328 + x^326 + x^324 + x^323 + x^315 + x^314 + x^309 + x^306 + x^304 + x^302 + x^298 + x^297 + x^296 + x^295 + x^293 + x^291 + x^289 + x^284 + x^282 + x^281 + x^279 + x^275 + x^274 + x^273 + x^269 + x^267 + x^265 + x^263 + x^261 + x^260 + x^259 + x^257 + x^256 + x^254 + x^252 + x^248 + x^247 + x^246 + x^244 + x^243 + x^242 + x^241 + x^238 + x^235 + x^234 + x^232 + x^229 + x^227 + x^225 + x^224 + x^223 + x^219 + x^217 + x^215 + x^211 + x^208 + x^206 + x^205 + x^203 + x^200 + x^197 + x^195 + x^190 + x^189 + x^187 + x^185 + x^176 + x^174 + x^172 + x^169 + x^165 + x^160 + x^159 + x^158 + x^156 + x^155 + x^154 + x^153 + x^152 + x^150 + x^146 + x^141 + x^139 + x^137 + x^135 + x^132 + x^131 + x^130 + x^127 + x^124 + x^120 + x^119 + x^116 + x^114 + x^111 + x^110 + x^109 + x^108 + x^105 + x^102 + x^99 + x^98 + x^95 + x^94 + x^93 + x^92 + x^90 + x^87 + x^86 + x^76 + x^75 + x^74 + x^72 + x^70 + x^68 + x^67 + x^65 + x^64 + x^63 + x^60 + x^59 + x^58 + x^57 + x^54 + x^51 + x^50 + x^48 + x^46 + x^45 + x^44 + x^43 + x^41 + x^39 + x^38 + x^36 + x^30 + x^27 + x^26 + x^24 + x^18 + x^14 + x^12 + 1
+
+44-14-41 357 x^928 + x^898 + x^870 + x^856 + x^852 + x^847 + x^831 + x^822 + x^817 + x^814 + x^808 + x^796 + x^795 + x^792 + x^784 + x^778 + x^777 + x^775 + x^772 + x^771 + x^766 + x^763 + x^756 + x^754 + x^747 + x^746 + x^745 + x^744 + x^742 + x^736 + x^733 + x^732 + x^730 + x^727 + x^726 + x^724 + x^721 + x^717 + x^716 + x^715 + x^714 + x^711 + x^705 + x^704 + x^694 + x^693 + x^691 + x^684 + x^682 + x^678 + x^674 + x^670 + x^664 + x^662 + x^655 + x^653 + x^647 + x^645 + x^644 + x^643 + x^637 + x^636 + x^635 + x^633 + x^631 + x^627 + x^626 + x^625 + x^624 + x^620 + x^618 + x^605 + x^604 + x^603 + x^601 + x^597 + x^588 + x^585 + x^583 + x^578 + x^575 + x^574 + x^569 + x^568 + x^567 + x^566 + x^565 + x^563 + x^558 + x^556 + x^554 + x^553 + x^552 + x^551 + x^550 + x^548 + x^544 + x^543 + x^542 + x^539 + x^538 + x^537 + x^535 + x^533 + x^532 + x^530 + x^528 + x^525 + x^523 + x^521 + x^520 + x^516 + x^515 + x^514 + x^513 + x^510 + x^509 + x^506 + x^504 + x^502 + x^497 + x^496 + x^491 + x^487 + x^485 + x^484 + x^482 + x^481 + x^480 + x^473 + x^471 + x^470 + x^468 + x^466 + x^464 + x^463 + x^462 + x^461 + x^459 + x^458 + x^455 + x^452 + x^450 + x^449 + x^447 + x^446 + x^443 + x^442 + x^440 + x^438 + x^436 + x^435 + x^432 + x^429 + x^428 + x^423 + x^420 + x^418 + x^417 + x^416 + x^413 + x^412 + x^411 + x^410 + x^407 + x^406 + x^405 + x^403 + x^402 + x^401 + x^400 + x^397 + x^396 + x^393 + x^392 + x^391 + x^390 + x^389 + x^386 + x^385 + x^384 + x^382 + x^380 + x^378 + x^376 + x^371 + x^370 + x^369 + x^368 + x^365 + x^364 + x^363 + x^359 + x^358 + x^357 + x^356 + x^353 + x^351 + x^350 + x^349 + x^348 + x^346 + x^345 + x^343 + x^342 + x^340 + x^339 + x^338 + x^335 + x^333 + x^332 + x^327 + x^324 + x^322 + x^317 + x^316 + x^315 + x^313 + x^311 + x^308 + x^307 + x^306 + x^304 + x^303 + x^301 + x^300 + x^299 + x^296 + x^294 + x^293 + x^292 + x^291 + x^290 + x^289 + x^284 + x^281 + x^279 + x^278 + x^276 + x^275 + x^273 + x^272 + x^271 + x^269 + x^266 + x^264 + x^260 + x^258 + x^256 + x^255 + x^251 + x^250 + x^248 + x^247 + x^244 + x^243 + x^241 + x^240 + x^239 + x^236 + x^235 + x^233 + x^232 + x^230 + x^226 + x^224 + x^223 + x^221 + x^220 + x^218 + x^217 + x^216 + x^215 + x^211 + x^210 + x^209 + x^208 + x^206 + x^204 + x^201 + x^200 + x^197 + x^196 + x^192 + x^187 + x^185 + x^183 + x^182 + x^181 + x^179 + x^178 + x^177 + x^175 + x^173 + x^170 + x^169 + x^168 + x^166 + x^159 + x^158 + x^157 + x^155 + x^154 + x^150 + x^149 + x^146 + x^144 + x^139 + x^138 + x^134 + x^132 + x^131 + x^128 + x^125 + x^123 + x^122 + x^120 + x^119 + x^116 + x^115 + x^111 + x^110 + x^109 + x^108 + x^101 + x^100 + x^99 + x^97 + x^96 + x^93 + x^92 + x^90 + x^87 + x^77 + x^74 + x^71 + x^70 + x^63 + x^58 + x^56 + x^54 + x^53 + x^52 + x^51 + x^50 + x^46 + x^42 + x^40 + x^38 + x^37 + x^36 + x^30 + x^28 + x^26 + x^14 + x^12 + 1
+
+22-40-11 359 x^928 + x^898 + x^870 + x^829 + x^816 + x^814 + x^808 + x^803 + x^799 + x^786 + x^784 + x^778 + x^777 + x^773 + x^764 + x^762 + x^743 + x^738 + x^736 + x^734 + x^725 + x^723 + x^719 + x^713 + x^710 + x^708 + x^699 + x^691 + x^688 + x^686 + x^684 + x^682 + x^673 + x^672 + x^665 + x^661 + x^657 + x^656 + x^654 + x^652 + x^650 + x^648 + x^645 + x^644 + x^642 + x^639 + x^637 + x^633 + x^631 + x^630 + x^626 + x^624 + x^622 + x^621 + x^620 + x^619 + x^618 + x^615 + x^614 + x^612 + x^611 + x^609 + x^606 + x^605 + x^604 + x^603 + x^601 + x^600 + x^599 + x^598 + x^594 + x^591 + x^587 + x^586 + x^585 + x^582 + x^580 + x^578 + x^577 + x^576 + x^572 + x^562 + x^561 + x^559 + x^558 + x^557 + x^556 + x^554 + x^553 + x^552 + x^550 + x^549 + x^548 + x^545 + x^543 + x^541 + x^540 + x^537 + x^535 + x^534 + x^533 + x^531 + x^530 + x^528 + x^527 + x^526 + x^522 + x^521 + x^518 + x^517 + x^516 + x^515 + x^514 + x^512 + x^511 + x^510 + x^509 + x^508 + x^507 + x^501 + x^499 + x^494 + x^491 + x^490 + x^489 + x^488 + x^486 + x^484 + x^483 + x^481 + x^480 + x^479 + x^478 + x^476 + x^475 + x^474 + x^472 + x^471 + x^469 + x^468 + x^466 + x^465 + x^464 + x^463 + x^461 + x^459 + x^457 + x^450 + x^449 + x^448 + x^446 + x^445 + x^439 + x^438 + x^437 + x^436 + x^435 + x^433 + x^431 + x^430 + x^429 + x^427 + x^426 + x^423 + x^418 + x^417 + x^415 + x^413 + x^403 + x^402 + x^401 + x^399 + x^398 + x^397 + x^395 + x^394 + x^393 + x^386 + x^382 + x^379 + x^378 + x^377 + x^368 + x^367 + x^366 + x^364 + x^363 + x^362 + x^360 + x^359 + x^356 + x^354 + x^352 + x^344 + x^343 + x^342 + x^341 + x^340 + x^337 + x^336 + x^331 + x^330 + x^325 + x^323 + x^321 + x^320 + x^319 + x^318 + x^315 + x^313 + x^311 + x^310 + x^308 + x^306 + x^303 + x^302 + x^300 + x^298 + x^297 + x^296 + x^294 + x^293 + x^292 + x^291 + x^290 + x^288 + x^286 + x^285 + x^283 + x^278 + x^277 + x^275 + x^274 + x^273 + x^271 + x^269 + x^268 + x^267 + x^265 + x^261 + x^260 + x^259 + x^257 + x^256 + x^255 + x^254 + x^251 + x^249 + x^248 + x^245 + x^244 + x^242 + x^240 + x^238 + x^237 + x^236 + x^231 + x^229 + x^227 + x^225 + x^224 + x^223 + x^222 + x^221 + x^216 + x^215 + x^213 + x^211 + x^205 + x^202 + x^196 + x^194 + x^193 + x^192 + x^191 + x^190 + x^184 + x^180 + x^179 + x^178 + x^177 + x^176 + x^175 + x^174 + x^171 + x^169 + x^164 + x^162 + x^161 + x^160 + x^155 + x^153 + x^149 + x^143 + x^142 + x^139 + x^138 + x^135 + x^134 + x^133 + x^132 + x^130 + x^128 + x^127 + x^126 + x^124 + x^123 + x^120 + x^118 + x^117 + x^115 + x^114 + x^113 + x^112 + x^111 + x^109 + x^108 + x^107 + x^104 + x^103 + x^101 + x^98 + x^95 + x^93 + x^92 + x^89 + x^88 + x^86 + x^82 + x^80 + x^76 + x^75 + x^69 + x^67 + x^65 + x^64 + x^60 + x^58 + x^57 + x^55 + x^53 + x^50 + x^49 + x^47 + x^46 + x^45 + x^44 + x^43 + x^42 + x^39 + x^37 + x^36 + x^35 + x^34 + x^32 + x^24 + x^22 + x^20 + 1
+
+33-20-8 359 x^928 + x^898 + x^874 + x^870 + x^845 + x^840 + x^824 + x^808 + x^794 + x^790 + x^787 + x^786 + x^780 + x^778 + x^764 + x^762 + x^761 + x^760 + x^756 + x^752 + x^741 + x^737 + x^736 + x^734 + x^731 + x^729 + x^728 + x^726 + x^720 + x^716 + x^712 + x^710 + x^707 + x^706 + x^703 + x^700 + x^697 + x^696 + x^688 + x^686 + x^683 + x^682 + x^681 + x^675 + x^671 + x^669 + x^667 + x^666 + x^660 + x^658 + x^657 + x^654 + x^653 + x^652 + x^649 + x^647 + x^646 + x^640 + x^639 + x^637 + x^636 + x^634 + x^629 + x^628 + x^627 + x^625 + x^624 + x^618 + x^613 + x^609 + x^608 + x^607 + x^600 + x^598 + x^597 + x^596 + x^595 + x^594 + x^593 + x^592 + x^591 + x^589 + x^587 + x^586 + x^585 + x^583 + x^582 + x^581 + x^580 + x^579 + x^577 + x^570 + x^567 + x^562 + x^554 + x^553 + x^550 + x^549 + x^548 + x^547 + x^546 + x^545 + x^544 + x^542 + x^539 + x^537 + x^535 + x^533 + x^531 + x^530 + x^524 + x^523 + x^521 + x^520 + x^517 + x^516 + x^512 + x^511 + x^504 + x^503 + x^502 + x^501 + x^497 + x^494 + x^492 + x^490 + x^489 + x^486 + x^480 + x^478 + x^477 + x^476 + x^475 + x^472 + x^467 + x^465 + x^463 + x^462 + x^461 + x^460 + x^459 + x^458 + x^456 + x^452 + x^449 + x^447 + x^446 + x^442 + x^440 + x^439 + x^438 + x^437 + x^436 + x^435 + x^434 + x^433 + x^432 + x^431 + x^430 + x^429 + x^426 + x^425 + x^423 + x^422 + x^421 + x^420 + x^415 + x^414 + x^413 + x^412 + x^411 + x^410 + x^408 + x^404 + x^402 + x^400 + x^399 + x^398 + x^395 + x^394 + x^392 + x^390 + x^387 + x^386 + x^385 + x^383 + x^379 + x^377 + x^376 + x^374 + x^373 + x^372 + x^371 + x^368 + x^366 + x^365 + x^362 + x^361 + x^360 + x^359 + x^358 + x^350 + x^347 + x^342 + x^341 + x^338 + x^337 + x^335 + x^331 + x^330 + x^326 + x^325 + x^322 + x^321 + x^320 + x^319 + x^318 + x^317 + x^312 + x^311 + x^308 + x^307 + x^305 + x^303 + x^301 + x^298 + x^295 + x^292 + x^289 + x^286 + x^282 + x^280 + x^277 + x^273 + x^271 + x^270 + x^265 + x^263 + x^262 + x^261 + x^260 + x^257 + x^253 + x^252 + x^251 + x^249 + x^248 + x^247 + x^246 + x^245 + x^243 + x^240 + x^239 + x^236 + x^234 + x^230 + x^228 + x^226 + x^225 + x^224 + x^222 + x^220 + x^219 + x^218 + x^215 + x^214 + x^213 + x^210 + x^205 + x^203 + x^201 + x^195 + x^194 + x^192 + x^191 + x^187 + x^185 + x^184 + x^183 + x^181 + x^178 + x^176 + x^174 + x^173 + x^172 + x^171 + x^170 + x^168 + x^165 + x^164 + x^163 + x^160 + x^157 + x^155 + x^154 + x^153 + x^152 + x^151 + x^150 + x^149 + x^148 + x^139 + x^138 + x^135 + x^134 + x^132 + x^131 + x^129 + x^128 + x^127 + x^126 + x^125 + x^122 + x^121 + x^119 + x^118 + x^115 + x^114 + x^111 + x^110 + x^106 + x^103 + x^101 + x^99 + x^98 + x^95 + x^91 + x^90 + x^89 + x^83 + x^78 + x^77 + x^75 + x^74 + x^70 + x^65 + x^64 + x^61 + x^56 + x^55 + x^52 + x^51 + x^49 + x^46 + x^41 + x^38 + x^36 + x^35 + x^34 + x^32 + x^29 + x^28 + x^27 + x^23 + x^16 + x^12 + x^8 + x^4 + 1
+
+6-42-43 359 x^928 + x^898 + x^877 + x^870 + x^847 + x^846 + x^844 + x^822 + x^808 + x^799 + x^794 + x^793 + x^790 + x^786 + x^778 + x^775 + x^774 + x^772 + x^771 + x^769 + x^766 + x^764 + x^750 + x^749 + x^748 + x^747 + x^744 + x^743 + x^742 + x^739 + x^736 + x^724 + x^721 + x^718 + x^715 + x^712 + x^710 + x^706 + x^702 + x^699 + x^695 + x^693 + x^692 + x^689 + x^687 + x^685 + x^684 + x^683 + x^682 + x^679 + x^674 + x^671 + x^670 + x^668 + x^667 + x^664 + x^662 + x^653 + x^652 + x^650 + x^649 + x^645 + x^644 + x^642 + x^639 + x^638 + x^637 + x^634 + x^633 + x^630 + x^624 + x^622 + x^619 + x^618 + x^616 + x^614 + x^613 + x^611 + x^610 + x^609 + x^608 + x^603 + x^601 + x^598 + x^595 + x^592 + x^589 + x^587 + x^586 + x^585 + x^584 + x^583 + x^582 + x^578 + x^574 + x^572 + x^568 + x^567 + x^565 + x^562 + x^561 + x^559 + x^558 + x^557 + x^555 + x^554 + x^550 + x^549 + x^547 + x^545 + x^541 + x^534 + x^528 + x^527 + x^523 + x^520 + x^518 + x^515 + x^510 + x^503 + x^502 + x^501 + x^500 + x^499 + x^498 + x^497 + x^496 + x^495 + x^494 + x^492 + x^489 + x^486 + x^483 + x^482 + x^479 + x^476 + x^475 + x^473 + x^472 + x^468 + x^467 + x^465 + x^464 + x^463 + x^461 + x^459 + x^458 + x^455 + x^452 + x^451 + x^450 + x^449 + x^448 + x^446 + x^445 + x^444 + x^443 + x^441 + x^440 + x^437 + x^434 + x^431 + x^430 + x^429 + x^425 + x^423 + x^422 + x^421 + x^419 + x^418 + x^417 + x^411 + x^408 + x^406 + x^405 + x^403 + x^401 + x^398 + x^397 + x^396 + x^393 + x^390 + x^382 + x^378 + x^376 + x^373 + x^372 + x^370 + x^369 + x^366 + x^361 + x^359 + x^358 + x^356 + x^354 + x^352 + x^351 + x^350 + x^349 + x^348 + x^347 + x^344 + x^340 + x^339 + x^336 + x^335 + x^333 + x^332 + x^329 + x^325 + x^324 + x^322 + x^321 + x^317 + x^316 + x^311 + x^310 + x^309 + x^303 + x^302 + x^301 + x^299 + x^298 + x^295 + x^294 + x^290 + x^289 + x^288 + x^287 + x^283 + x^282 + x^280 + x^279 + x^278 + x^277 + x^272 + x^271 + x^270 + x^268 + x^263 + x^261 + x^260 + x^259 + x^257 + x^256 + x^254 + x^250 + x^248 + x^247 + x^245 + x^244 + x^243 + x^241 + x^239 + x^238 + x^237 + x^235 + x^231 + x^230 + x^229 + x^228 + x^226 + x^225 + x^224 + x^221 + x^219 + x^217 + x^214 + x^210 + x^209 + x^208 + x^205 + x^204 + x^202 + x^199 + x^196 + x^191 + x^190 + x^189 + x^186 + x^184 + x^183 + x^180 + x^179 + x^178 + x^177 + x^175 + x^174 + x^170 + x^168 + x^167 + x^166 + x^165 + x^164 + x^162 + x^161 + x^160 + x^159 + x^157 + x^154 + x^153 + x^151 + x^143 + x^137 + x^135 + x^134 + x^129 + x^127 + x^126 + x^122 + x^121 + x^119 + x^118 + x^113 + x^111 + x^106 + x^104 + x^101 + x^100 + x^99 + x^98 + x^96 + x^92 + x^91 + x^90 + x^83 + x^82 + x^81 + x^79 + x^75 + x^74 + x^72 + x^71 + x^68 + x^64 + x^63 + x^60 + x^57 + x^56 + x^54 + x^52 + x^51 + x^49 + x^48 + x^46 + x^45 + x^43 + x^42 + x^39 + x^38 + x^37 + x^36 + x^32 + x^28 + x^26 + x^24 + x^16 + x^14 + 1
+
+33-22-4 361 x^928 + x^898 + x^870 + x^832 + x^822 + x^812 + x^808 + x^805 + x^802 + x^792 + x^784 + x^778 + x^775 + x^774 + x^762 + x^757 + x^756 + x^754 + x^746 + x^744 + x^740 + x^738 + x^736 + x^732 + x^728 + x^726 + x^720 + x^716 + x^711 + x^701 + x^697 + x^692 + x^684 + x^682 + x^680 + x^678 + x^673 + x^672 + x^671 + x^670 + x^658 + x^655 + x^653 + x^652 + x^651 + x^644 + x^637 + x^636 + x^630 + x^626 + x^622 + x^615 + x^613 + x^612 + x^611 + x^610 + x^608 + x^607 + x^606 + x^600 + x^599 + x^594 + x^593 + x^592 + x^590 + x^589 + x^588 + x^587 + x^586 + x^585 + x^583 + x^580 + x^578 + x^577 + x^574 + x^569 + x^567 + x^564 + x^562 + x^561 + x^559 + x^554 + x^553 + x^552 + x^549 + x^548 + x^544 + x^543 + x^538 + x^537 + x^536 + x^535 + x^533 + x^530 + x^525 + x^524 + x^523 + x^522 + x^521 + x^519 + x^517 + x^516 + x^515 + x^514 + x^511 + x^507 + x^506 + x^500 + x^499 + x^498 + x^496 + x^494 + x^487 + x^486 + x^485 + x^483 + x^480 + x^473 + x^468 + x^466 + x^465 + x^464 + x^463 + x^461 + x^460 + x^454 + x^452 + x^448 + x^447 + x^445 + x^441 + x^440 + x^439 + x^438 + x^436 + x^435 + x^434 + x^433 + x^429 + x^427 + x^425 + x^423 + x^421 + x^420 + x^418 + x^416 + x^415 + x^413 + x^411 + x^410 + x^409 + x^408 + x^404 + x^402 + x^401 + x^399 + x^397 + x^396 + x^393 + x^391 + x^390 + x^388 + x^387 + x^386 + x^383 + x^381 + x^380 + x^379 + x^376 + x^375 + x^374 + x^371 + x^370 + x^369 + x^368 + x^366 + x^364 + x^363 + x^361 + x^359 + x^356 + x^355 + x^354 + x^353 + x^350 + x^349 + x^344 + x^341 + x^338 + x^337 + x^336 + x^335 + x^332 + x^330 + x^329 + x^328 + x^327 + x^323 + x^322 + x^319 + x^318 + x^315 + x^314 + x^313 + x^309 + x^308 + x^307 + x^306 + x^304 + x^303 + x^301 + x^300 + x^298 + x^296 + x^295 + x^294 + x^292 + x^290 + x^289 + x^288 + x^286 + x^284 + x^282 + x^280 + x^279 + x^278 + x^275 + x^273 + x^271 + x^268 + x^266 + x^262 + x^261 + x^259 + x^258 + x^256 + x^255 + x^254 + x^253 + x^250 + x^245 + x^241 + x^240 + x^239 + x^237 + x^235 + x^234 + x^232 + x^231 + x^229 + x^226 + x^225 + x^221 + x^220 + x^218 + x^217 + x^215 + x^213 + x^211 + x^209 + x^206 + x^205 + x^201 + x^200 + x^196 + x^195 + x^192 + x^189 + x^188 + x^187 + x^186 + x^184 + x^183 + x^181 + x^180 + x^178 + x^177 + x^176 + x^175 + x^174 + x^172 + x^171 + x^169 + x^166 + x^165 + x^162 + x^160 + x^157 + x^154 + x^152 + x^150 + x^149 + x^145 + x^141 + x^138 + x^137 + x^133 + x^131 + x^129 + x^127 + x^125 + x^124 + x^123 + x^120 + x^118 + x^117 + x^115 + x^114 + x^112 + x^109 + x^108 + x^105 + x^102 + x^100 + x^99 + x^97 + x^96 + x^91 + x^90 + x^88 + x^87 + x^86 + x^85 + x^82 + x^80 + x^79 + x^77 + x^75 + x^74 + x^70 + x^66 + x^65 + x^63 + x^62 + x^61 + x^60 + x^59 + x^54 + x^52 + x^50 + x^49 + x^46 + x^42 + x^41 + x^40 + x^39 + x^38 + x^37 + x^36 + x^35 + x^33 + x^31 + x^27 + x^26 + x^22 + x^21 + x^19 + x^16 + x^14 + x^12 + 1
+
+46-48-7 361 x^928 + x^898 + x^870 + x^862 + x^848 + x^837 + x^829 + x^820 + x^815 + x^808 + x^807 + x^806 + x^802 + x^799 + x^798 + x^795 + x^790 + x^788 + x^787 + x^785 + x^776 + x^769 + x^765 + x^762 + x^760 + x^756 + x^755 + x^740 + x^739 + x^737 + x^732 + x^730 + x^727 + x^725 + x^717 + x^715 + x^714 + x^710 + x^709 + x^706 + x^704 + x^695 + x^688 + x^687 + x^686 + x^684 + x^682 + x^680 + x^679 + x^678 + x^676 + x^675 + x^667 + x^664 + x^661 + x^658 + x^657 + x^655 + x^654 + x^653 + x^652 + x^650 + x^649 + x^647 + x^646 + x^644 + x^643 + x^638 + x^637 + x^636 + x^634 + x^633 + x^627 + x^624 + x^623 + x^622 + x^620 + x^619 + x^618 + x^615 + x^612 + x^611 + x^606 + x^604 + x^601 + x^594 + x^591 + x^590 + x^589 + x^588 + x^587 + x^585 + x^583 + x^580 + x^575 + x^574 + x^572 + x^571 + x^569 + x^568 + x^567 + x^564 + x^563 + x^558 + x^557 + x^556 + x^552 + x^551 + x^546 + x^544 + x^542 + x^541 + x^535 + x^534 + x^532 + x^531 + x^530 + x^529 + x^528 + x^526 + x^525 + x^523 + x^521 + x^519 + x^518 + x^516 + x^514 + x^513 + x^506 + x^505 + x^504 + x^499 + x^498 + x^497 + x^496 + x^495 + x^493 + x^491 + x^490 + x^488 + x^487 + x^486 + x^485 + x^484 + x^481 + x^480 + x^477 + x^476 + x^473 + x^472 + x^471 + x^466 + x^465 + x^463 + x^462 + x^461 + x^460 + x^459 + x^455 + x^451 + x^449 + x^448 + x^447 + x^446 + x^444 + x^443 + x^441 + x^440 + x^439 + x^437 + x^431 + x^429 + x^428 + x^426 + x^424 + x^421 + x^420 + x^419 + x^418 + x^417 + x^416 + x^414 + x^411 + x^410 + x^408 + x^407 + x^406 + x^405 + x^403 + x^402 + x^401 + x^400 + x^397 + x^394 + x^392 + x^390 + x^388 + x^382 + x^381 + x^379 + x^378 + x^377 + x^376 + x^374 + x^367 + x^364 + x^363 + x^360 + x^357 + x^356 + x^354 + x^353 + x^352 + x^351 + x^350 + x^348 + x^343 + x^342 + x^341 + x^337 + x^334 + x^333 + x^330 + x^326 + x^316 + x^313 + x^309 + x^306 + x^305 + x^300 + x^299 + x^296 + x^294 + x^293 + x^292 + x^287 + x^285 + x^282 + x^281 + x^278 + x^276 + x^275 + x^271 + x^269 + x^267 + x^263 + x^262 + x^261 + x^260 + x^257 + x^256 + x^255 + x^253 + x^249 + x^248 + x^244 + x^243 + x^242 + x^240 + x^239 + x^238 + x^236 + x^235 + x^234 + x^231 + x^226 + x^224 + x^221 + x^217 + x^216 + x^214 + x^211 + x^210 + x^209 + x^208 + x^206 + x^205 + x^202 + x^200 + x^197 + x^196 + x^195 + x^190 + x^186 + x^184 + x^183 + x^181 + x^176 + x^172 + x^171 + x^167 + x^166 + x^165 + x^164 + x^159 + x^157 + x^154 + x^153 + x^151 + x^150 + x^146 + x^145 + x^144 + x^142 + x^141 + x^140 + x^139 + x^137 + x^136 + x^134 + x^131 + x^130 + x^129 + x^125 + x^124 + x^123 + x^120 + x^118 + x^117 + x^111 + x^110 + x^108 + x^107 + x^106 + x^105 + x^98 + x^96 + x^95 + x^94 + x^92 + x^88 + x^83 + x^81 + x^78 + x^76 + x^72 + x^71 + x^67 + x^66 + x^65 + x^63 + x^60 + x^58 + x^57 + x^56 + x^52 + x^51 + x^49 + x^48 + x^46 + x^44 + x^40 + x^38 + x^34 + x^33 + x^32 + x^31 + x^30 + x^28 + x^20 + 1
+
+49-44-52 361 x^928 + x^898 + x^870 + x^864 + x^842 + x^837 + x^834 + x^812 + x^810 + x^808 + x^804 + x^788 + x^786 + x^783 + x^782 + x^780 + x^778 + x^774 + x^758 + x^756 + x^753 + x^752 + x^734 + x^732 + x^729 + x^727 + x^724 + x^723 + x^722 + x^717 + x^704 + x^702 + x^699 + x^696 + x^693 + x^692 + x^690 + x^680 + x^678 + x^672 + x^667 + x^665 + x^663 + x^662 + x^661 + x^660 + x^650 + x^646 + x^637 + x^636 + x^633 + x^631 + x^626 + x^621 + x^618 + x^616 + x^614 + x^612 + x^611 + x^610 + x^609 + x^605 + x^603 + x^602 + x^601 + x^599 + x^597 + x^596 + x^594 + x^589 + x^588 + x^586 + x^576 + x^575 + x^573 + x^572 + x^571 + x^569 + x^568 + x^565 + x^562 + x^561 + x^560 + x^558 + x^557 + x^555 + x^554 + x^551 + x^549 + x^548 + x^543 + x^542 + x^539 + x^536 + x^532 + x^529 + x^528 + x^527 + x^526 + x^525 + x^518 + x^517 + x^514 + x^513 + x^512 + x^511 + x^509 + x^508 + x^506 + x^505 + x^499 + x^496 + x^495 + x^493 + x^492 + x^491 + x^489 + x^486 + x^483 + x^482 + x^479 + x^477 + x^476 + x^474 + x^468 + x^467 + x^462 + x^461 + x^457 + x^456 + x^454 + x^453 + x^452 + x^451 + x^449 + x^444 + x^442 + x^441 + x^439 + x^438 + x^437 + x^436 + x^432 + x^431 + x^429 + x^428 + x^427 + x^425 + x^424 + x^423 + x^422 + x^420 + x^419 + x^418 + x^416 + x^414 + x^413 + x^409 + x^407 + x^406 + x^404 + x^403 + x^402 + x^401 + x^395 + x^394 + x^393 + x^392 + x^390 + x^389 + x^387 + x^386 + x^384 + x^380 + x^378 + x^377 + x^376 + x^372 + x^371 + x^370 + x^369 + x^365 + x^363 + x^362 + x^361 + x^358 + x^357 + x^356 + x^355 + x^352 + x^351 + x^350 + x^347 + x^346 + x^344 + x^343 + x^342 + x^340 + x^339 + x^338 + x^332 + x^331 + x^328 + x^326 + x^325 + x^323 + x^322 + x^321 + x^319 + x^317 + x^316 + x^314 + x^313 + x^309 + x^305 + x^303 + x^301 + x^300 + x^299 + x^298 + x^297 + x^294 + x^292 + x^290 + x^285 + x^284 + x^282 + x^280 + x^279 + x^278 + x^276 + x^272 + x^267 + x^266 + x^265 + x^264 + x^263 + x^262 + x^259 + x^256 + x^254 + x^253 + x^251 + x^250 + x^249 + x^248 + x^247 + x^245 + x^243 + x^241 + x^240 + x^238 + x^234 + x^231 + x^229 + x^228 + x^227 + x^224 + x^222 + x^221 + x^215 + x^214 + x^211 + x^210 + x^209 + x^207 + x^206 + x^205 + x^204 + x^197 + x^196 + x^194 + x^192 + x^191 + x^189 + x^188 + x^187 + x^186 + x^182 + x^180 + x^178 + x^175 + x^172 + x^168 + x^167 + x^166 + x^163 + x^162 + x^158 + x^154 + x^153 + x^150 + x^148 + x^146 + x^145 + x^144 + x^138 + x^136 + x^132 + x^131 + x^130 + x^129 + x^124 + x^122 + x^120 + x^116 + x^115 + x^113 + x^112 + x^109 + x^108 + x^107 + x^106 + x^103 + x^102 + x^101 + x^99 + x^98 + x^97 + x^96 + x^94 + x^92 + x^90 + x^86 + x^85 + x^84 + x^83 + x^82 + x^80 + x^79 + x^77 + x^76 + x^65 + x^60 + x^59 + x^57 + x^54 + x^52 + x^47 + x^45 + x^44 + x^42 + x^38 + x^37 + x^34 + x^33 + x^31 + x^29 + x^26 + x^25 + x^24 + x^22 + x^21 + x^19 + x^18 + x^17 + x^15 + x^14 + x^12 + x^10 + 1
+
+34-42-39 365 x^928 + x^898 + x^870 + x^860 + x^850 + x^840 + x^831 + x^830 + x^811 + x^808 + x^801 + x^800 + x^792 + x^790 + x^780 + x^778 + x^771 + x^770 + x^762 + x^753 + x^744 + x^742 + x^740 + x^734 + x^720 + x^715 + x^712 + x^710 + x^703 + x^702 + x^694 + x^693 + x^691 + x^688 + x^685 + x^682 + x^680 + x^676 + x^674 + x^672 + x^664 + x^663 + x^662 + x^660 + x^658 + x^657 + x^656 + x^653 + x^652 + x^650 + x^647 + x^646 + x^645 + x^643 + x^637 + x^634 + x^628 + x^627 + x^623 + x^622 + x^618 + x^617 + x^615 + x^614 + x^608 + x^607 + x^604 + x^603 + x^600 + x^597 + x^593 + x^592 + x^589 + x^588 + x^587 + x^586 + x^585 + x^584 + x^579 + x^578 + x^577 + x^574 + x^570 + x^567 + x^565 + x^563 + x^562 + x^560 + x^558 + x^555 + x^550 + x^549 + x^547 + x^544 + x^542 + x^541 + x^536 + x^533 + x^532 + x^529 + x^527 + x^526 + x^521 + x^520 + x^518 + x^517 + x^516 + x^514 + x^510 + x^509 + x^508 + x^506 + x^504 + x^503 + x^502 + x^501 + x^497 + x^496 + x^489 + x^488 + x^487 + x^486 + x^484 + x^481 + x^480 + x^476 + x^475 + x^473 + x^472 + x^471 + x^470 + x^467 + x^466 + x^463 + x^462 + x^459 + x^458 + x^457 + x^456 + x^453 + x^451 + x^450 + x^446 + x^445 + x^444 + x^443 + x^442 + x^439 + x^438 + x^437 + x^436 + x^433 + x^432 + x^430 + x^428 + x^427 + x^425 + x^421 + x^420 + x^413 + x^412 + x^411 + x^408 + x^406 + x^405 + x^404 + x^403 + x^401 + x^399 + x^398 + x^396 + x^391 + x^388 + x^385 + x^381 + x^378 + x^376 + x^375 + x^374 + x^372 + x^370 + x^368 + x^364 + x^363 + x^360 + x^359 + x^357 + x^354 + x^353 + x^350 + x^349 + x^348 + x^347 + x^346 + x^344 + x^343 + x^342 + x^340 + x^339 + x^337 + x^335 + x^334 + x^333 + x^331 + x^330 + x^329 + x^327 + x^326 + x^325 + x^324 + x^323 + x^321 + x^320 + x^317 + x^312 + x^310 + x^309 + x^303 + x^300 + x^298 + x^296 + x^295 + x^292 + x^291 + x^290 + x^288 + x^287 + x^286 + x^285 + x^284 + x^282 + x^278 + x^277 + x^275 + x^274 + x^273 + x^267 + x^266 + x^265 + x^264 + x^263 + x^262 + x^261 + x^260 + x^257 + x^254 + x^250 + x^249 + x^244 + x^243 + x^242 + x^239 + x^238 + x^237 + x^236 + x^231 + x^230 + x^229 + x^228 + x^226 + x^224 + x^223 + x^222 + x^221 + x^220 + x^217 + x^214 + x^213 + x^212 + x^211 + x^208 + x^207 + x^206 + x^205 + x^204 + x^202 + x^198 + x^197 + x^195 + x^194 + x^192 + x^189 + x^187 + x^186 + x^185 + x^181 + x^180 + x^179 + x^178 + x^175 + x^173 + x^170 + x^168 + x^167 + x^166 + x^165 + x^164 + x^157 + x^155 + x^154 + x^150 + x^149 + x^148 + x^144 + x^143 + x^140 + x^138 + x^137 + x^135 + x^134 + x^132 + x^126 + x^124 + x^123 + x^120 + x^119 + x^117 + x^115 + x^113 + x^105 + x^104 + x^102 + x^100 + x^97 + x^96 + x^94 + x^91 + x^88 + x^87 + x^85 + x^84 + x^83 + x^82 + x^80 + x^79 + x^77 + x^76 + x^69 + x^68 + x^64 + x^61 + x^60 + x^55 + x^53 + x^51 + x^50 + x^48 + x^45 + x^44 + x^43 + x^40 + x^39 + x^38 + x^37 + x^36 + x^34 + x^33 + x^30 + x^22 + x^20 + x^19 + x^18 + x^16 + x^14 + 1
+
+34-2-25 367 x^928 + x^898 + x^870 + x^868 + x^866 + x^850 + x^838 + x^832 + x^822 + x^820 + x^808 + x^804 + x^802 + x^797 + x^792 + x^790 + x^788 + x^786 + x^778 + x^770 + x^768 + x^767 + x^760 + x^754 + x^748 + x^747 + x^746 + x^744 + x^738 + x^736 + x^735 + x^728 + x^726 + x^720 + x^717 + x^712 + x^708 + x^696 + x^694 + x^692 + x^690 + x^688 + x^687 + x^685 + x^684 + x^678 + x^677 + x^675 + x^673 + x^669 + x^667 + x^662 + x^658 + x^657 + x^654 + x^652 + x^647 + x^643 + x^642 + x^640 + x^639 + x^638 + x^637 + x^634 + x^633 + x^624 + x^613 + x^612 + x^611 + x^610 + x^609 + x^607 + x^606 + x^603 + x^600 + x^598 + x^597 + x^593 + x^591 + x^590 + x^588 + x^587 + x^586 + x^584 + x^583 + x^582 + x^581 + x^577 + x^576 + x^574 + x^571 + x^570 + x^568 + x^567 + x^564 + x^563 + x^562 + x^560 + x^558 + x^557 + x^554 + x^553 + x^551 + x^549 + x^548 + x^547 + x^546 + x^545 + x^539 + x^538 + x^535 + x^533 + x^531 + x^530 + x^529 + x^527 + x^525 + x^524 + x^523 + x^522 + x^520 + x^517 + x^515 + x^514 + x^511 + x^510 + x^507 + x^506 + x^504 + x^503 + x^500 + x^499 + x^498 + x^496 + x^493 + x^491 + x^490 + x^489 + x^487 + x^485 + x^483 + x^482 + x^480 + x^478 + x^477 + x^474 + x^473 + x^471 + x^469 + x^468 + x^465 + x^464 + x^460 + x^459 + x^457 + x^455 + x^451 + x^450 + x^449 + x^447 + x^446 + x^442 + x^441 + x^438 + x^430 + x^428 + x^427 + x^426 + x^425 + x^421 + x^420 + x^417 + x^416 + x^415 + x^414 + x^411 + x^410 + x^409 + x^406 + x^405 + x^404 + x^402 + x^396 + x^394 + x^393 + x^390 + x^389 + x^388 + x^386 + x^384 + x^382 + x^381 + x^380 + x^379 + x^378 + x^377 + x^376 + x^374 + x^373 + x^372 + x^371 + x^369 + x^366 + x^365 + x^364 + x^363 + x^356 + x^354 + x^352 + x^351 + x^344 + x^342 + x^338 + x^336 + x^335 + x^334 + x^327 + x^323 + x^321 + x^319 + x^318 + x^317 + x^312 + x^308 + x^305 + x^303 + x^302 + x^301 + x^299 + x^298 + x^297 + x^289 + x^286 + x^285 + x^283 + x^277 + x^276 + x^275 + x^272 + x^271 + x^269 + x^268 + x^267 + x^266 + x^263 + x^258 + x^255 + x^254 + x^252 + x^251 + x^247 + x^246 + x^235 + x^233 + x^232 + x^229 + x^226 + x^225 + x^223 + x^220 + x^219 + x^216 + x^212 + x^210 + x^209 + x^208 + x^206 + x^205 + x^204 + x^202 + x^201 + x^200 + x^198 + x^196 + x^193 + x^190 + x^187 + x^185 + x^184 + x^182 + x^180 + x^179 + x^174 + x^173 + x^172 + x^171 + x^169 + x^167 + x^166 + x^165 + x^164 + x^159 + x^158 + x^156 + x^155 + x^154 + x^151 + x^150 + x^149 + x^148 + x^147 + x^146 + x^144 + x^143 + x^141 + x^137 + x^133 + x^132 + x^131 + x^130 + x^129 + x^126 + x^124 + x^123 + x^122 + x^118 + x^112 + x^111 + x^109 + x^108 + x^107 + x^105 + x^104 + x^103 + x^102 + x^99 + x^96 + x^93 + x^92 + x^91 + x^89 + x^86 + x^84 + x^83 + x^82 + x^81 + x^79 + x^77 + x^76 + x^75 + x^71 + x^70 + x^67 + x^65 + x^63 + x^53 + x^49 + x^44 + x^40 + x^38 + x^37 + x^36 + x^35 + x^34 + x^32 + x^31 + x^28 + x^26 + x^25 + x^24 + x^22 + x^18 + x^16 + x^10 + x^8 + x^4 + 1
+
+34-39-1 367 x^928 + x^898 + x^894 + x^874 + x^870 + x^864 + x^855 + x^844 + x^840 + x^835 + x^834 + x^825 + x^820 + x^815 + x^814 + x^808 + x^805 + x^804 + x^801 + x^800 + x^796 + x^790 + x^785 + x^784 + x^778 + x^776 + x^770 + x^766 + x^761 + x^760 + x^756 + x^754 + x^751 + x^750 + x^746 + x^741 + x^740 + x^735 + x^732 + x^731 + x^730 + x^727 + x^724 + x^722 + x^721 + x^720 + x^716 + x^715 + x^712 + x^706 + x^705 + x^700 + x^697 + x^694 + x^692 + x^688 + x^686 + x^685 + x^682 + x^677 + x^676 + x^672 + x^667 + x^664 + x^657 + x^655 + x^653 + x^651 + x^650 + x^648 + x^642 + x^638 + x^632 + x^631 + x^630 + x^628 + x^627 + x^625 + x^622 + x^620 + x^618 + x^617 + x^616 + x^612 + x^611 + x^602 + x^600 + x^598 + x^597 + x^591 + x^588 + x^586 + x^582 + x^581 + x^579 + x^578 + x^577 + x^574 + x^573 + x^572 + x^568 + x^566 + x^564 + x^560 + x^552 + x^541 + x^538 + x^537 + x^535 + x^534 + x^532 + x^531 + x^529 + x^528 + x^523 + x^522 + x^521 + x^519 + x^518 + x^516 + x^515 + x^510 + x^509 + x^508 + x^506 + x^504 + x^500 + x^499 + x^498 + x^497 + x^495 + x^492 + x^490 + x^489 + x^488 + x^484 + x^482 + x^477 + x^475 + x^474 + x^472 + x^471 + x^470 + x^469 + x^467 + x^466 + x^465 + x^464 + x^462 + x^461 + x^460 + x^457 + x^455 + x^454 + x^453 + x^448 + x^447 + x^446 + x^444 + x^443 + x^442 + x^441 + x^440 + x^437 + x^431 + x^430 + x^429 + x^426 + x^424 + x^423 + x^421 + x^419 + x^418 + x^417 + x^416 + x^412 + x^411 + x^409 + x^408 + x^407 + x^406 + x^405 + x^403 + x^402 + x^397 + x^395 + x^394 + x^389 + x^388 + x^384 + x^383 + x^382 + x^380 + x^379 + x^377 + x^376 + x^375 + x^374 + x^373 + x^372 + x^370 + x^369 + x^368 + x^367 + x^366 + x^361 + x^360 + x^359 + x^357 + x^355 + x^353 + x^350 + x^349 + x^344 + x^342 + x^341 + x^340 + x^338 + x^337 + x^336 + x^335 + x^334 + x^333 + x^332 + x^331 + x^329 + x^328 + x^326 + x^321 + x^320 + x^318 + x^317 + x^316 + x^313 + x^311 + x^310 + x^309 + x^306 + x^303 + x^302 + x^300 + x^299 + x^296 + x^295 + x^294 + x^293 + x^292 + x^291 + x^288 + x^287 + x^286 + x^284 + x^279 + x^276 + x^274 + x^270 + x^269 + x^268 + x^265 + x^264 + x^262 + x^259 + x^257 + x^256 + x^255 + x^251 + x^248 + x^247 + x^245 + x^244 + x^243 + x^240 + x^237 + x^234 + x^232 + x^230 + x^227 + x^224 + x^223 + x^219 + x^214 + x^212 + x^206 + x^204 + x^201 + x^198 + x^197 + x^194 + x^192 + x^190 + x^189 + x^186 + x^185 + x^182 + x^179 + x^178 + x^174 + x^172 + x^171 + x^168 + x^166 + x^163 + x^162 + x^161 + x^159 + x^158 + x^154 + x^153 + x^152 + x^151 + x^149 + x^148 + x^146 + x^143 + x^142 + x^140 + x^138 + x^137 + x^135 + x^134 + x^133 + x^132 + x^131 + x^128 + x^126 + x^125 + x^124 + x^123 + x^119 + x^118 + x^116 + x^115 + x^109 + x^108 + x^106 + x^105 + x^103 + x^100 + x^98 + x^91 + x^89 + x^86 + x^84 + x^83 + x^81 + x^79 + x^78 + x^70 + x^69 + x^67 + x^66 + x^65 + x^59 + x^58 + x^56 + x^48 + x^45 + x^43 + x^42 + x^38 + x^37 + x^34 + x^29 + x^26 + x^21 + x^10 + 1
+
+8-38-53 367 x^928 + x^898 + x^870 + x^843 + x^838 + x^833 + x^830 + x^820 + x^816 + x^811 + x^808 + x^800 + x^786 + x^781 + x^778 + x^773 + x^768 + x^760 + x^756 + x^752 + x^750 + x^743 + x^742 + x^738 + x^733 + x^732 + x^730 + x^728 + x^726 + x^723 + x^720 + x^718 + x^711 + x^710 + x^708 + x^700 + x^699 + x^698 + x^696 + x^695 + x^693 + x^691 + x^690 + x^688 + x^686 + x^685 + x^683 + x^681 + x^672 + x^670 + x^667 + x^666 + x^665 + x^664 + x^663 + x^662 + x^661 + x^658 + x^657 + x^655 + x^654 + x^650 + x^648 + x^646 + x^645 + x^644 + x^642 + x^640 + x^639 + x^638 + x^636 + x^634 + x^626 + x^622 + x^620 + x^617 + x^615 + x^614 + x^613 + x^612 + x^606 + x^605 + x^603 + x^600 + x^597 + x^596 + x^592 + x^591 + x^590 + x^589 + x^588 + x^585 + x^584 + x^581 + x^578 + x^577 + x^576 + x^575 + x^574 + x^572 + x^569 + x^568 + x^564 + x^562 + x^561 + x^556 + x^554 + x^551 + x^549 + x^544 + x^543 + x^542 + x^540 + x^539 + x^538 + x^533 + x^532 + x^530 + x^529 + x^527 + x^526 + x^524 + x^521 + x^520 + x^517 + x^515 + x^514 + x^510 + x^507 + x^504 + x^503 + x^502 + x^501 + x^500 + x^499 + x^498 + x^497 + x^495 + x^493 + x^489 + x^487 + x^486 + x^483 + x^482 + x^480 + x^477 + x^474 + x^471 + x^469 + x^468 + x^463 + x^461 + x^459 + x^456 + x^453 + x^450 + x^447 + x^443 + x^442 + x^441 + x^439 + x^438 + x^437 + x^436 + x^435 + x^431 + x^424 + x^422 + x^415 + x^411 + x^410 + x^409 + x^407 + x^406 + x^405 + x^404 + x^401 + x^400 + x^396 + x^395 + x^392 + x^391 + x^389 + x^388 + x^385 + x^382 + x^381 + x^380 + x^379 + x^377 + x^374 + x^369 + x^368 + x^367 + x^366 + x^365 + x^364 + x^359 + x^357 + x^353 + x^351 + x^349 + x^345 + x^344 + x^342 + x^341 + x^340 + x^339 + x^337 + x^335 + x^334 + x^333 + x^331 + x^330 + x^329 + x^327 + x^326 + x^324 + x^323 + x^322 + x^320 + x^319 + x^318 + x^314 + x^313 + x^312 + x^311 + x^309 + x^307 + x^304 + x^303 + x^300 + x^298 + x^294 + x^288 + x^285 + x^284 + x^281 + x^280 + x^279 + x^277 + x^276 + x^275 + x^273 + x^271 + x^270 + x^269 + x^268 + x^266 + x^261 + x^254 + x^253 + x^251 + x^250 + x^249 + x^248 + x^247 + x^245 + x^244 + x^242 + x^240 + x^238 + x^236 + x^233 + x^231 + x^230 + x^227 + x^226 + x^224 + x^223 + x^222 + x^221 + x^220 + x^219 + x^218 + x^216 + x^215 + x^213 + x^212 + x^209 + x^208 + x^207 + x^202 + x^198 + x^195 + x^189 + x^186 + x^183 + x^182 + x^180 + x^179 + x^177 + x^175 + x^172 + x^170 + x^168 + x^167 + x^159 + x^158 + x^154 + x^153 + x^150 + x^149 + x^144 + x^141 + x^140 + x^138 + x^136 + x^135 + x^134 + x^133 + x^132 + x^130 + x^129 + x^126 + x^125 + x^124 + x^123 + x^122 + x^121 + x^117 + x^116 + x^114 + x^113 + x^112 + x^111 + x^110 + x^108 + x^106 + x^105 + x^102 + x^98 + x^97 + x^96 + x^95 + x^92 + x^91 + x^90 + x^87 + x^79 + x^77 + x^74 + x^73 + x^72 + x^69 + x^64 + x^61 + x^60 + x^59 + x^58 + x^57 + x^56 + x^55 + x^53 + x^50 + x^49 + x^47 + x^46 + x^44 + x^43 + x^36 + x^35 + x^30 + x^29 + x^22 + x^16 + 1
+
+40-6-51 369 x^928 + x^898 + x^870 + x^859 + x^840 + x^830 + x^819 + x^790 + x^780 + x^779 + x^771 + x^770 + x^768 + x^761 + x^760 + x^757 + x^752 + x^750 + x^748 + x^742 + x^741 + x^740 + x^739 + x^738 + x^732 + x^728 + x^727 + x^721 + x^719 + x^718 + x^717 + x^712 + x^709 + x^708 + x^702 + x^699 + x^692 + x^690 + x^687 + x^684 + x^678 + x^677 + x^673 + x^672 + x^671 + x^668 + x^666 + x^659 + x^658 + x^657 + x^655 + x^654 + x^653 + x^652 + x^651 + x^648 + x^647 + x^645 + x^644 + x^643 + x^637 + x^636 + x^634 + x^632 + x^631 + x^624 + x^622 + x^621 + x^620 + x^616 + x^614 + x^613 + x^612 + x^611 + x^609 + x^608 + x^607 + x^598 + x^596 + x^594 + x^593 + x^592 + x^591 + x^588 + x^585 + x^583 + x^579 + x^578 + x^576 + x^575 + x^574 + x^573 + x^572 + x^571 + x^570 + x^567 + x^566 + x^563 + x^562 + x^560 + x^557 + x^555 + x^554 + x^549 + x^547 + x^546 + x^544 + x^542 + x^538 + x^537 + x^535 + x^534 + x^533 + x^531 + x^529 + x^527 + x^526 + x^522 + x^520 + x^518 + x^517 + x^515 + x^514 + x^513 + x^511 + x^510 + x^509 + x^508 + x^505 + x^504 + x^500 + x^497 + x^496 + x^494 + x^492 + x^481 + x^477 + x^475 + x^473 + x^471 + x^470 + x^468 + x^467 + x^466 + x^465 + x^464 + x^463 + x^462 + x^460 + x^457 + x^456 + x^453 + x^451 + x^450 + x^449 + x^447 + x^446 + x^444 + x^443 + x^441 + x^436 + x^435 + x^434 + x^429 + x^428 + x^427 + x^423 + x^422 + x^421 + x^419 + x^418 + x^416 + x^414 + x^413 + x^412 + x^410 + x^408 + x^406 + x^405 + x^402 + x^401 + x^400 + x^399 + x^398 + x^396 + x^395 + x^394 + x^393 + x^391 + x^390 + x^388 + x^385 + x^384 + x^382 + x^381 + x^379 + x^378 + x^377 + x^376 + x^375 + x^374 + x^373 + x^372 + x^371 + x^370 + x^367 + x^366 + x^365 + x^363 + x^360 + x^358 + x^355 + x^354 + x^353 + x^352 + x^350 + x^347 + x^344 + x^342 + x^340 + x^339 + x^338 + x^335 + x^334 + x^331 + x^330 + x^328 + x^324 + x^323 + x^322 + x^321 + x^318 + x^316 + x^315 + x^313 + x^307 + x^306 + x^304 + x^303 + x^301 + x^300 + x^299 + x^298 + x^297 + x^290 + x^287 + x^285 + x^283 + x^282 + x^281 + x^280 + x^279 + x^278 + x^276 + x^275 + x^274 + x^270 + x^264 + x^263 + x^262 + x^261 + x^259 + x^258 + x^254 + x^253 + x^252 + x^244 + x^242 + x^241 + x^240 + x^239 + x^237 + x^236 + x^235 + x^230 + x^228 + x^224 + x^220 + x^217 + x^214 + x^210 + x^209 + x^208 + x^206 + x^203 + x^202 + x^201 + x^200 + x^199 + x^196 + x^195 + x^194 + x^192 + x^189 + x^188 + x^186 + x^185 + x^184 + x^181 + x^176 + x^175 + x^173 + x^172 + x^171 + x^170 + x^165 + x^163 + x^161 + x^159 + x^156 + x^154 + x^153 + x^144 + x^143 + x^137 + x^135 + x^134 + x^132 + x^130 + x^129 + x^126 + x^125 + x^122 + x^120 + x^118 + x^114 + x^113 + x^110 + x^109 + x^108 + x^107 + x^98 + x^97 + x^95 + x^92 + x^88 + x^87 + x^86 + x^85 + x^84 + x^83 + x^80 + x^76 + x^74 + x^71 + x^70 + x^69 + x^64 + x^63 + x^62 + x^61 + x^57 + x^53 + x^52 + x^50 + x^46 + x^40 + x^38 + x^37 + x^34 + x^33 + x^32 + x^31 + x^28 + x^25 + x^22 + x^18 + x^6 + 1
+
+48-40-25 371 x^928 + x^898 + x^878 + x^870 + x^851 + x^844 + x^832 + x^828 + x^818 + x^809 + x^808 + x^802 + x^790 + x^782 + x^779 + x^772 + x^755 + x^751 + x^749 + x^744 + x^742 + x^740 + x^738 + x^732 + x^731 + x^728 + x^725 + x^719 + x^718 + x^714 + x^713 + x^712 + x^708 + x^705 + x^695 + x^691 + x^690 + x^688 + x^687 + x^686 + x^684 + x^683 + x^679 + x^676 + x^674 + x^671 + x^668 + x^665 + x^663 + x^662 + x^661 + x^656 + x^655 + x^652 + x^650 + x^649 + x^648 + x^647 + x^646 + x^641 + x^640 + x^638 + x^636 + x^635 + x^633 + x^630 + x^627 + x^626 + x^625 + x^624 + x^621 + x^620 + x^619 + x^618 + x^617 + x^614 + x^613 + x^608 + x^607 + x^606 + x^605 + x^604 + x^603 + x^602 + x^599 + x^597 + x^596 + x^591 + x^589 + x^586 + x^585 + x^584 + x^582 + x^578 + x^576 + x^572 + x^569 + x^566 + x^564 + x^558 + x^555 + x^553 + x^550 + x^549 + x^548 + x^545 + x^543 + x^541 + x^540 + x^538 + x^537 + x^533 + x^530 + x^527 + x^524 + x^523 + x^521 + x^520 + x^519 + x^517 + x^516 + x^515 + x^513 + x^510 + x^504 + x^503 + x^501 + x^500 + x^498 + x^497 + x^496 + x^494 + x^492 + x^491 + x^488 + x^485 + x^482 + x^478 + x^476 + x^474 + x^473 + x^471 + x^469 + x^468 + x^464 + x^461 + x^460 + x^459 + x^454 + x^450 + x^449 + x^448 + x^444 + x^439 + x^438 + x^437 + x^436 + x^435 + x^433 + x^431 + x^428 + x^426 + x^424 + x^420 + x^417 + x^416 + x^413 + x^411 + x^408 + x^407 + x^406 + x^403 + x^400 + x^399 + x^398 + x^397 + x^396 + x^392 + x^390 + x^389 + x^388 + x^387 + x^386 + x^385 + x^381 + x^378 + x^374 + x^370 + x^369 + x^368 + x^367 + x^365 + x^364 + x^359 + x^356 + x^354 + x^350 + x^348 + x^346 + x^344 + x^343 + x^342 + x^340 + x^338 + x^337 + x^334 + x^332 + x^330 + x^329 + x^327 + x^322 + x^317 + x^316 + x^314 + x^311 + x^308 + x^307 + x^301 + x^300 + x^299 + x^296 + x^295 + x^292 + x^291 + x^290 + x^286 + x^284 + x^282 + x^279 + x^278 + x^276 + x^273 + x^270 + x^269 + x^265 + x^263 + x^259 + x^258 + x^257 + x^256 + x^255 + x^253 + x^251 + x^249 + x^247 + x^245 + x^244 + x^243 + x^242 + x^241 + x^240 + x^238 + x^236 + x^231 + x^230 + x^229 + x^228 + x^226 + x^223 + x^221 + x^220 + x^219 + x^218 + x^217 + x^215 + x^214 + x^212 + x^211 + x^210 + x^208 + x^207 + x^206 + x^205 + x^202 + x^200 + x^198 + x^193 + x^192 + x^191 + x^187 + x^186 + x^184 + x^182 + x^179 + x^173 + x^171 + x^169 + x^168 + x^164 + x^163 + x^162 + x^161 + x^157 + x^156 + x^155 + x^154 + x^153 + x^151 + x^149 + x^147 + x^146 + x^145 + x^143 + x^140 + x^137 + x^136 + x^133 + x^127 + x^122 + x^121 + x^119 + x^115 + x^114 + x^112 + x^111 + x^110 + x^108 + x^104 + x^103 + x^101 + x^98 + x^94 + x^88 + x^87 + x^85 + x^83 + x^81 + x^80 + x^79 + x^78 + x^77 + x^75 + x^74 + x^73 + x^70 + x^69 + x^68 + x^67 + x^65 + x^63 + x^62 + x^60 + x^59 + x^58 + x^57 + x^56 + x^54 + x^53 + x^52 + x^50 + x^49 + x^47 + x^46 + x^45 + x^41 + x^39 + x^36 + x^34 + x^33 + x^32 + x^31 + x^30 + x^29 + x^28 + x^26 + x^25 + x^21 + x^16 + x^14 + x^4 + 1
+
+19-22-10 373 x^928 + x^898 + x^870 + x^866 + x^842 + x^836 + x^834 + x^821 + x^808 + x^807 + x^806 + x^804 + x^802 + x^794 + x^792 + x^782 + x^778 + x^777 + x^776 + x^770 + x^766 + x^761 + x^757 + x^753 + x^748 + x^743 + x^739 + x^738 + x^736 + x^735 + x^734 + x^732 + x^728 + x^725 + x^722 + x^721 + x^718 + x^716 + x^713 + x^711 + x^710 + x^709 + x^708 + x^705 + x^703 + x^702 + x^693 + x^686 + x^681 + x^680 + x^677 + x^664 + x^662 + x^659 + x^652 + x^651 + x^649 + x^646 + x^644 + x^643 + x^641 + x^638 + x^636 + x^629 + x^627 + x^625 + x^623 + x^622 + x^619 + x^617 + x^616 + x^615 + x^614 + x^612 + x^611 + x^609 + x^606 + x^605 + x^600 + x^597 + x^596 + x^595 + x^592 + x^591 + x^590 + x^586 + x^582 + x^580 + x^577 + x^576 + x^574 + x^572 + x^570 + x^569 + x^567 + x^565 + x^563 + x^562 + x^560 + x^557 + x^556 + x^555 + x^554 + x^552 + x^549 + x^548 + x^546 + x^545 + x^544 + x^542 + x^540 + x^538 + x^536 + x^534 + x^533 + x^532 + x^530 + x^528 + x^525 + x^520 + x^519 + x^518 + x^516 + x^514 + x^513 + x^511 + x^509 + x^504 + x^501 + x^497 + x^496 + x^495 + x^488 + x^487 + x^485 + x^482 + x^481 + x^480 + x^479 + x^478 + x^476 + x^475 + x^474 + x^472 + x^470 + x^468 + x^466 + x^465 + x^463 + x^458 + x^453 + x^451 + x^449 + x^448 + x^447 + x^446 + x^445 + x^444 + x^443 + x^439 + x^438 + x^437 + x^436 + x^433 + x^428 + x^424 + x^418 + x^417 + x^414 + x^412 + x^411 + x^408 + x^407 + x^406 + x^404 + x^403 + x^401 + x^400 + x^399 + x^396 + x^395 + x^393 + x^390 + x^389 + x^388 + x^387 + x^386 + x^385 + x^384 + x^382 + x^380 + x^379 + x^375 + x^371 + x^370 + x^369 + x^365 + x^363 + x^362 + x^357 + x^355 + x^354 + x^351 + x^348 + x^346 + x^345 + x^344 + x^342 + x^340 + x^338 + x^336 + x^334 + x^331 + x^328 + x^327 + x^326 + x^324 + x^323 + x^322 + x^320 + x^315 + x^308 + x^306 + x^298 + x^295 + x^292 + x^287 + x^286 + x^285 + x^284 + x^282 + x^281 + x^280 + x^279 + x^278 + x^276 + x^274 + x^273 + x^272 + x^270 + x^269 + x^268 + x^267 + x^265 + x^262 + x^258 + x^256 + x^253 + x^252 + x^251 + x^250 + x^246 + x^245 + x^244 + x^243 + x^242 + x^240 + x^239 + x^238 + x^237 + x^235 + x^232 + x^228 + x^226 + x^224 + x^217 + x^215 + x^213 + x^211 + x^210 + x^208 + x^206 + x^201 + x^199 + x^196 + x^195 + x^192 + x^190 + x^187 + x^186 + x^185 + x^184 + x^182 + x^180 + x^178 + x^175 + x^174 + x^173 + x^172 + x^165 + x^160 + x^159 + x^158 + x^157 + x^155 + x^154 + x^153 + x^148 + x^146 + x^145 + x^143 + x^142 + x^137 + x^135 + x^133 + x^132 + x^131 + x^128 + x^127 + x^124 + x^123 + x^122 + x^121 + x^117 + x^115 + x^114 + x^113 + x^112 + x^108 + x^107 + x^106 + x^105 + x^103 + x^102 + x^101 + x^100 + x^94 + x^93 + x^92 + x^89 + x^87 + x^86 + x^85 + x^83 + x^80 + x^79 + x^78 + x^77 + x^75 + x^74 + x^72 + x^70 + x^67 + x^66 + x^62 + x^61 + x^59 + x^58 + x^57 + x^55 + x^51 + x^50 + x^49 + x^42 + x^41 + x^39 + x^36 + x^34 + x^32 + x^30 + x^26 + x^24 + x^23 + x^22 + x^21 + x^18 + x^16 + x^14 + x^10 + x^9 + x^8 + x^2 + 1
+
+52-17-25 375 x^928 + x^898 + x^870 + x^861 + x^860 + x^859 + x^858 + x^849 + x^848 + x^847 + x^846 + x^842 + x^836 + x^835 + x^831 + x^830 + x^829 + x^828 + x^823 + x^822 + x^811 + x^810 + x^808 + x^807 + x^806 + x^804 + x^800 + x^799 + x^793 + x^792 + x^789 + x^788 + x^786 + x^780 + x^778 + x^777 + x^775 + x^774 + x^770 + x^769 + x^768 + x^764 + x^763 + x^762 + x^758 + x^757 + x^756 + x^755 + x^751 + x^750 + x^744 + x^740 + x^739 + x^738 + x^733 + x^731 + x^728 + x^721 + x^720 + x^716 + x^715 + x^714 + x^713 + x^710 + x^709 + x^702 + x^701 + x^697 + x^696 + x^695 + x^692 + x^688 + x^686 + x^684 + x^683 + x^680 + x^679 + x^678 + x^677 + x^674 + x^673 + x^672 + x^665 + x^662 + x^658 + x^654 + x^647 + x^643 + x^636 + x^635 + x^631 + x^628 + x^626 + x^625 + x^622 + x^621 + x^619 + x^618 + x^617 + x^614 + x^613 + x^612 + x^611 + x^609 + x^608 + x^598 + x^595 + x^591 + x^589 + x^588 + x^587 + x^586 + x^584 + x^582 + x^576 + x^574 + x^571 + x^569 + x^567 + x^564 + x^563 + x^560 + x^557 + x^550 + x^549 + x^548 + x^547 + x^546 + x^544 + x^539 + x^537 + x^536 + x^529 + x^527 + x^526 + x^523 + x^522 + x^521 + x^516 + x^513 + x^512 + x^509 + x^508 + x^505 + x^503 + x^502 + x^499 + x^493 + x^492 + x^491 + x^487 + x^486 + x^484 + x^482 + x^479 + x^478 + x^477 + x^475 + x^474 + x^471 + x^468 + x^467 + x^465 + x^463 + x^462 + x^461 + x^460 + x^455 + x^452 + x^445 + x^443 + x^442 + x^437 + x^433 + x^432 + x^429 + x^427 + x^426 + x^424 + x^423 + x^422 + x^421 + x^417 + x^411 + x^410 + x^408 + x^407 + x^403 + x^402 + x^400 + x^399 + x^393 + x^391 + x^390 + x^389 + x^386 + x^384 + x^381 + x^379 + x^375 + x^373 + x^372 + x^369 + x^367 + x^366 + x^364 + x^363 + x^362 + x^361 + x^360 + x^357 + x^356 + x^353 + x^352 + x^348 + x^345 + x^344 + x^342 + x^341 + x^340 + x^335 + x^332 + x^330 + x^329 + x^328 + x^327 + x^322 + x^321 + x^319 + x^318 + x^317 + x^315 + x^312 + x^311 + x^310 + x^308 + x^305 + x^302 + x^300 + x^299 + x^298 + x^297 + x^296 + x^292 + x^290 + x^289 + x^288 + x^286 + x^284 + x^283 + x^282 + x^281 + x^278 + x^277 + x^276 + x^274 + x^272 + x^269 + x^267 + x^263 + x^262 + x^260 + x^259 + x^256 + x^254 + x^253 + x^251 + x^250 + x^249 + x^248 + x^242 + x^241 + x^240 + x^235 + x^234 + x^231 + x^226 + x^225 + x^221 + x^219 + x^214 + x^212 + x^211 + x^209 + x^207 + x^206 + x^205 + x^202 + x^199 + x^198 + x^195 + x^190 + x^189 + x^187 + x^185 + x^182 + x^181 + x^180 + x^179 + x^177 + x^176 + x^175 + x^174 + x^171 + x^169 + x^165 + x^164 + x^163 + x^162 + x^161 + x^160 + x^155 + x^154 + x^153 + x^152 + x^146 + x^145 + x^142 + x^139 + x^137 + x^136 + x^128 + x^127 + x^124 + x^121 + x^120 + x^119 + x^117 + x^114 + x^113 + x^112 + x^110 + x^109 + x^108 + x^104 + x^102 + x^101 + x^99 + x^97 + x^87 + x^85 + x^84 + x^83 + x^82 + x^78 + x^76 + x^73 + x^72 + x^69 + x^64 + x^62 + x^59 + x^52 + x^51 + x^50 + x^49 + x^46 + x^45 + x^44 + x^42 + x^41 + x^40 + x^36 + x^35 + x^33 + x^28 + x^26 + x^25 + x^21 + x^19 + x^13 + x^12 + x^7 + x^6 + 1
+
+35-28-44 377 x^928 + x^898 + x^894 + x^870 + x^859 + x^829 + x^828 + x^825 + x^808 + x^804 + x^800 + x^799 + x^795 + x^794 + x^789 + x^778 + x^774 + x^769 + x^768 + x^759 + x^758 + x^755 + x^754 + x^748 + x^744 + x^739 + x^735 + x^734 + x^727 + x^726 + x^722 + x^718 + x^714 + x^713 + x^709 + x^708 + x^705 + x^704 + x^700 + x^694 + x^691 + x^690 + x^688 + x^687 + x^685 + x^682 + x^681 + x^675 + x^668 + x^665 + x^659 + x^657 + x^656 + x^655 + x^653 + x^652 + x^651 + x^649 + x^647 + x^644 + x^640 + x^638 + x^635 + x^634 + x^631 + x^630 + x^629 + x^628 + x^625 + x^624 + x^619 + x^617 + x^614 + x^613 + x^612 + x^611 + x^610 + x^608 + x^602 + x^599 + x^598 + x^593 + x^592 + x^591 + x^590 + x^586 + x^585 + x^583 + x^582 + x^581 + x^580 + x^579 + x^578 + x^576 + x^575 + x^573 + x^569 + x^566 + x^560 + x^559 + x^558 + x^557 + x^553 + x^552 + x^551 + x^549 + x^542 + x^536 + x^535 + x^533 + x^524 + x^522 + x^521 + x^520 + x^518 + x^517 + x^516 + x^515 + x^512 + x^509 + x^507 + x^506 + x^504 + x^502 + x^500 + x^499 + x^498 + x^497 + x^496 + x^491 + x^489 + x^485 + x^484 + x^483 + x^482 + x^481 + x^480 + x^477 + x^476 + x^474 + x^467 + x^466 + x^465 + x^462 + x^460 + x^459 + x^454 + x^450 + x^447 + x^446 + x^445 + x^443 + x^439 + x^434 + x^433 + x^432 + x^431 + x^430 + x^429 + x^428 + x^427 + x^426 + x^425 + x^424 + x^423 + x^421 + x^419 + x^417 + x^413 + x^412 + x^411 + x^409 + x^408 + x^407 + x^406 + x^405 + x^404 + x^403 + x^401 + x^400 + x^394 + x^389 + x^386 + x^383 + x^381 + x^380 + x^379 + x^378 + x^376 + x^375 + x^373 + x^372 + x^371 + x^369 + x^368 + x^367 + x^366 + x^365 + x^364 + x^362 + x^359 + x^356 + x^349 + x^347 + x^346 + x^345 + x^343 + x^342 + x^341 + x^340 + x^339 + x^338 + x^337 + x^336 + x^335 + x^332 + x^331 + x^330 + x^329 + x^325 + x^324 + x^320 + x^319 + x^318 + x^317 + x^316 + x^315 + x^311 + x^309 + x^307 + x^304 + x^303 + x^301 + x^300 + x^298 + x^297 + x^296 + x^295 + x^294 + x^292 + x^291 + x^289 + x^288 + x^285 + x^283 + x^282 + x^281 + x^274 + x^272 + x^271 + x^269 + x^262 + x^261 + x^260 + x^258 + x^257 + x^252 + x^251 + x^250 + x^249 + x^247 + x^246 + x^244 + x^241 + x^236 + x^234 + x^231 + x^230 + x^227 + x^226 + x^219 + x^218 + x^216 + x^215 + x^213 + x^206 + x^205 + x^204 + x^203 + x^202 + x^201 + x^200 + x^198 + x^196 + x^195 + x^194 + x^193 + x^192 + x^190 + x^186 + x^185 + x^184 + x^182 + x^176 + x^174 + x^167 + x^166 + x^164 + x^163 + x^162 + x^161 + x^159 + x^155 + x^154 + x^153 + x^151 + x^150 + x^146 + x^145 + x^143 + x^140 + x^138 + x^135 + x^131 + x^130 + x^129 + x^125 + x^124 + x^123 + x^118 + x^116 + x^113 + x^110 + x^107 + x^101 + x^100 + x^99 + x^95 + x^94 + x^93 + x^92 + x^91 + x^88 + x^86 + x^82 + x^81 + x^80 + x^79 + x^78 + x^76 + x^75 + x^73 + x^72 + x^71 + x^70 + x^69 + x^68 + x^67 + x^65 + x^63 + x^62 + x^60 + x^58 + x^57 + x^56 + x^55 + x^52 + x^50 + x^48 + x^46 + x^44 + x^42 + x^40 + x^39 + x^38 + x^33 + x^31 + x^30 + x^29 + x^28 + x^27 + x^24 + x^21 + x^16 + x^13 + x^8 + 1
+
+45-7-6 377 x^928 + x^898 + x^897 + x^870 + x^868 + x^854 + x^853 + x^850 + x^836 + x^835 + x^832 + x^821 + x^810 + x^809 + x^808 + x^807 + x^805 + x^803 + x^802 + x^801 + x^798 + x^794 + x^792 + x^791 + x^790 + x^780 + x^778 + x^775 + x^770 + x^767 + x^766 + x^765 + x^764 + x^760 + x^754 + x^750 + x^743 + x^740 + x^737 + x^735 + x^732 + x^726 + x^723 + x^722 + x^721 + x^720 + x^716 + x^714 + x^710 + x^707 + x^706 + x^703 + x^701 + x^700 + x^699 + x^695 + x^691 + x^689 + x^687 + x^686 + x^685 + x^683 + x^680 + x^676 + x^675 + x^672 + x^671 + x^670 + x^668 + x^667 + x^666 + x^665 + x^662 + x^658 + x^655 + x^653 + x^652 + x^648 + x^644 + x^643 + x^642 + x^637 + x^629 + x^628 + x^627 + x^626 + x^624 + x^621 + x^617 + x^616 + x^612 + x^610 + x^609 + x^608 + x^607 + x^603 + x^602 + x^600 + x^595 + x^594 + x^592 + x^591 + x^589 + x^586 + x^585 + x^582 + x^578 + x^576 + x^574 + x^573 + x^571 + x^570 + x^566 + x^563 + x^561 + x^560 + x^558 + x^557 + x^556 + x^555 + x^554 + x^553 + x^552 + x^551 + x^549 + x^548 + x^545 + x^538 + x^533 + x^530 + x^524 + x^520 + x^519 + x^512 + x^509 + x^508 + x^505 + x^503 + x^502 + x^497 + x^495 + x^493 + x^492 + x^486 + x^485 + x^484 + x^482 + x^480 + x^479 + x^477 + x^472 + x^470 + x^469 + x^466 + x^464 + x^462 + x^460 + x^459 + x^458 + x^456 + x^455 + x^454 + x^452 + x^451 + x^448 + x^446 + x^442 + x^441 + x^440 + x^437 + x^431 + x^430 + x^427 + x^426 + x^425 + x^424 + x^423 + x^420 + x^417 + x^415 + x^414 + x^413 + x^412 + x^410 + x^408 + x^406 + x^405 + x^404 + x^403 + x^401 + x^399 + x^395 + x^393 + x^392 + x^384 + x^381 + x^375 + x^370 + x^368 + x^367 + x^364 + x^363 + x^361 + x^360 + x^356 + x^355 + x^354 + x^353 + x^351 + x^349 + x^346 + x^343 + x^341 + x^340 + x^339 + x^335 + x^334 + x^333 + x^330 + x^328 + x^326 + x^325 + x^324 + x^323 + x^319 + x^318 + x^316 + x^315 + x^312 + x^306 + x^303 + x^302 + x^301 + x^299 + x^294 + x^292 + x^291 + x^290 + x^289 + x^283 + x^281 + x^276 + x^275 + x^274 + x^273 + x^271 + x^270 + x^269 + x^268 + x^267 + x^265 + x^264 + x^263 + x^262 + x^261 + x^260 + x^259 + x^258 + x^257 + x^255 + x^254 + x^253 + x^252 + x^250 + x^247 + x^246 + x^245 + x^243 + x^241 + x^240 + x^239 + x^235 + x^228 + x^224 + x^223 + x^220 + x^217 + x^216 + x^215 + x^209 + x^205 + x^204 + x^203 + x^202 + x^197 + x^196 + x^195 + x^192 + x^191 + x^189 + x^187 + x^183 + x^181 + x^180 + x^179 + x^178 + x^173 + x^172 + x^170 + x^165 + x^163 + x^161 + x^159 + x^156 + x^155 + x^153 + x^148 + x^146 + x^141 + x^138 + x^134 + x^133 + x^131 + x^130 + x^127 + x^126 + x^125 + x^123 + x^122 + x^119 + x^117 + x^116 + x^110 + x^109 + x^108 + x^107 + x^106 + x^95 + x^93 + x^92 + x^91 + x^88 + x^87 + x^86 + x^84 + x^82 + x^80 + x^79 + x^76 + x^75 + x^73 + x^72 + x^69 + x^68 + x^64 + x^63 + x^61 + x^59 + x^57 + x^55 + x^54 + x^53 + x^51 + x^49 + x^46 + x^43 + x^41 + x^40 + x^36 + x^35 + x^34 + x^33 + x^31 + x^27 + x^25 + x^23 + x^22 + x^21 + x^19 + x^15 + x^13 + x^12 + x^11 + x^10 + x^9 + x^8 + 1
+
+23-49-24 379 x^928 + x^898 + x^872 + x^870 + x^856 + x^843 + x^842 + x^827 + x^826 + x^824 + x^818 + x^813 + x^812 + x^811 + x^797 + x^796 + x^795 + x^792 + x^789 + x^788 + x^781 + x^780 + x^772 + x^767 + x^765 + x^759 + x^757 + x^752 + x^743 + x^742 + x^741 + x^740 + x^737 + x^735 + x^730 + x^729 + x^728 + x^727 + x^724 + x^722 + x^721 + x^720 + x^718 + x^714 + x^712 + x^710 + x^707 + x^706 + x^704 + x^703 + x^702 + x^700 + x^699 + x^698 + x^696 + x^694 + x^692 + x^691 + x^690 + x^689 + x^688 + x^686 + x^682 + x^681 + x^679 + x^677 + x^675 + x^674 + x^665 + x^663 + x^661 + x^660 + x^657 + x^656 + x^655 + x^651 + x^649 + x^647 + x^646 + x^644 + x^642 + x^640 + x^637 + x^635 + x^633 + x^625 + x^622 + x^620 + x^619 + x^617 + x^616 + x^615 + x^613 + x^612 + x^610 + x^609 + x^607 + x^606 + x^605 + x^601 + x^600 + x^597 + x^596 + x^595 + x^593 + x^592 + x^590 + x^588 + x^584 + x^583 + x^582 + x^579 + x^578 + x^574 + x^571 + x^570 + x^567 + x^566 + x^564 + x^561 + x^560 + x^559 + x^558 + x^554 + x^553 + x^547 + x^543 + x^539 + x^536 + x^535 + x^534 + x^533 + x^529 + x^527 + x^526 + x^525 + x^518 + x^516 + x^515 + x^510 + x^509 + x^508 + x^506 + x^505 + x^504 + x^503 + x^499 + x^498 + x^497 + x^495 + x^493 + x^491 + x^489 + x^488 + x^487 + x^486 + x^485 + x^484 + x^482 + x^479 + x^475 + x^473 + x^472 + x^469 + x^468 + x^464 + x^463 + x^462 + x^459 + x^457 + x^455 + x^453 + x^448 + x^446 + x^444 + x^443 + x^442 + x^438 + x^435 + x^431 + x^429 + x^427 + x^424 + x^423 + x^418 + x^416 + x^414 + x^406 + x^404 + x^403 + x^401 + x^397 + x^396 + x^390 + x^387 + x^384 + x^380 + x^377 + x^375 + x^373 + x^369 + x^366 + x^365 + x^364 + x^358 + x^356 + x^355 + x^354 + x^353 + x^352 + x^348 + x^346 + x^340 + x^338 + x^336 + x^334 + x^329 + x^326 + x^325 + x^322 + x^320 + x^318 + x^312 + x^307 + x^305 + x^302 + x^301 + x^299 + x^297 + x^296 + x^294 + x^293 + x^291 + x^288 + x^287 + x^286 + x^281 + x^278 + x^277 + x^276 + x^274 + x^273 + x^272 + x^271 + x^269 + x^268 + x^267 + x^266 + x^262 + x^261 + x^258 + x^256 + x^255 + x^253 + x^251 + x^250 + x^249 + x^248 + x^247 + x^243 + x^240 + x^237 + x^236 + x^235 + x^233 + x^231 + x^230 + x^223 + x^222 + x^220 + x^218 + x^216 + x^212 + x^211 + x^208 + x^207 + x^205 + x^203 + x^202 + x^201 + x^200 + x^199 + x^198 + x^197 + x^195 + x^193 + x^192 + x^191 + x^187 + x^186 + x^183 + x^181 + x^180 + x^179 + x^176 + x^174 + x^173 + x^169 + x^166 + x^161 + x^159 + x^158 + x^157 + x^156 + x^154 + x^152 + x^151 + x^149 + x^145 + x^144 + x^143 + x^142 + x^141 + x^139 + x^136 + x^135 + x^131 + x^128 + x^127 + x^126 + x^125 + x^123 + x^122 + x^120 + x^118 + x^117 + x^116 + x^114 + x^111 + x^110 + x^108 + x^107 + x^106 + x^103 + x^100 + x^99 + x^97 + x^96 + x^95 + x^93 + x^92 + x^91 + x^90 + x^87 + x^84 + x^81 + x^80 + x^79 + x^78 + x^77 + x^74 + x^73 + x^71 + x^67 + x^64 + x^61 + x^59 + x^58 + x^54 + x^49 + x^47 + x^44 + x^43 + x^41 + x^38 + x^37 + x^33 + x^30 + x^25 + x^17 + x^16 + x^15 + x^14 + x^12 + x^11 + x^8 + x^7 + x^4 + 1
+
+19-18-26 381 x^928 + x^898 + x^870 + x^844 + x^836 + x^832 + x^820 + x^814 + x^808 + x^802 + x^798 + x^794 + x^791 + x^790 + x^784 + x^778 + x^774 + x^770 + x^769 + x^766 + x^764 + x^761 + x^754 + x^748 + x^743 + x^734 + x^732 + x^731 + x^727 + x^726 + x^724 + x^723 + x^721 + x^718 + x^716 + x^715 + x^713 + x^711 + x^709 + x^706 + x^704 + x^703 + x^702 + x^701 + x^700 + x^699 + x^697 + x^696 + x^695 + x^693 + x^692 + x^691 + x^690 + x^685 + x^684 + x^676 + x^674 + x^667 + x^664 + x^663 + x^658 + x^657 + x^656 + x^654 + x^653 + x^651 + x^650 + x^646 + x^645 + x^644 + x^643 + x^639 + x^638 + x^637 + x^633 + x^631 + x^630 + x^627 + x^626 + x^625 + x^624 + x^620 + x^611 + x^610 + x^607 + x^606 + x^604 + x^603 + x^598 + x^597 + x^595 + x^593 + x^590 + x^589 + x^588 + x^586 + x^585 + x^584 + x^582 + x^580 + x^577 + x^575 + x^570 + x^569 + x^568 + x^563 + x^562 + x^561 + x^558 + x^557 + x^556 + x^555 + x^552 + x^551 + x^550 + x^548 + x^547 + x^546 + x^545 + x^542 + x^541 + x^540 + x^539 + x^538 + x^537 + x^535 + x^534 + x^533 + x^531 + x^530 + x^528 + x^523 + x^522 + x^521 + x^517 + x^515 + x^514 + x^512 + x^510 + x^509 + x^508 + x^506 + x^497 + x^494 + x^493 + x^490 + x^487 + x^486 + x^483 + x^481 + x^479 + x^476 + x^474 + x^472 + x^471 + x^467 + x^465 + x^464 + x^463 + x^462 + x^460 + x^456 + x^454 + x^452 + x^450 + x^449 + x^448 + x^447 + x^445 + x^444 + x^440 + x^439 + x^438 + x^437 + x^436 + x^432 + x^431 + x^430 + x^429 + x^428 + x^427 + x^425 + x^424 + x^422 + x^420 + x^419 + x^418 + x^416 + x^414 + x^413 + x^409 + x^407 + x^405 + x^404 + x^402 + x^397 + x^396 + x^392 + x^391 + x^389 + x^386 + x^385 + x^384 + x^381 + x^377 + x^376 + x^373 + x^371 + x^368 + x^366 + x^364 + x^362 + x^360 + x^359 + x^357 + x^355 + x^354 + x^353 + x^352 + x^351 + x^350 + x^349 + x^348 + x^346 + x^343 + x^341 + x^340 + x^338 + x^337 + x^336 + x^334 + x^331 + x^329 + x^328 + x^327 + x^325 + x^324 + x^323 + x^320 + x^316 + x^314 + x^313 + x^311 + x^309 + x^307 + x^306 + x^305 + x^304 + x^302 + x^301 + x^299 + x^297 + x^291 + x^289 + x^288 + x^285 + x^283 + x^282 + x^280 + x^279 + x^272 + x^271 + x^270 + x^269 + x^268 + x^264 + x^263 + x^260 + x^259 + x^257 + x^249 + x^245 + x^242 + x^241 + x^238 + x^234 + x^233 + x^232 + x^230 + x^229 + x^227 + x^226 + x^225 + x^223 + x^221 + x^214 + x^211 + x^210 + x^209 + x^206 + x^205 + x^204 + x^203 + x^201 + x^200 + x^199 + x^197 + x^195 + x^188 + x^186 + x^181 + x^180 + x^177 + x^174 + x^173 + x^171 + x^160 + x^159 + x^158 + x^157 + x^154 + x^148 + x^147 + x^144 + x^142 + x^141 + x^140 + x^139 + x^135 + x^134 + x^129 + x^124 + x^123 + x^120 + x^118 + x^117 + x^116 + x^113 + x^112 + x^110 + x^109 + x^108 + x^107 + x^106 + x^104 + x^103 + x^100 + x^97 + x^95 + x^94 + x^89 + x^86 + x^84 + x^83 + x^79 + x^76 + x^75 + x^73 + x^72 + x^70 + x^67 + x^66 + x^65 + x^63 + x^61 + x^60 + x^59 + x^58 + x^56 + x^53 + x^52 + x^51 + x^50 + x^45 + x^41 + x^40 + x^39 + x^37 + x^36 + x^35 + x^29 + x^26 + x^22 + x^19 + x^18 + x^17 + x^16 + x^13 + x^11 + x^6 + 1
+
+26-3-47 381 x^928 + x^898 + x^878 + x^870 + x^869 + x^860 + x^859 + x^858 + x^850 + x^849 + x^848 + x^840 + x^839 + x^838 + x^830 + x^820 + x^818 + x^810 + x^808 + x^807 + x^798 + x^788 + x^780 + x^778 + x^777 + x^769 + x^767 + x^758 + x^750 + x^740 + x^730 + x^729 + x^728 + x^727 + x^721 + x^720 + x^719 + x^717 + x^716 + x^711 + x^701 + x^700 + x^696 + x^690 + x^689 + x^687 + x^686 + x^681 + x^679 + x^678 + x^676 + x^670 + x^668 + x^667 + x^661 + x^660 + x^657 + x^656 + x^652 + x^650 + x^649 + x^648 + x^647 + x^646 + x^641 + x^638 + x^637 + x^636 + x^632 + x^629 + x^627 + x^625 + x^622 + x^620 + x^619 + x^617 + x^616 + x^610 + x^607 + x^606 + x^602 + x^601 + x^600 + x^599 + x^597 + x^596 + x^592 + x^591 + x^590 + x^588 + x^587 + x^586 + x^585 + x^581 + x^578 + x^576 + x^572 + x^571 + x^570 + x^567 + x^562 + x^560 + x^559 + x^558 + x^557 + x^555 + x^551 + x^550 + x^549 + x^548 + x^546 + x^542 + x^541 + x^536 + x^534 + x^531 + x^530 + x^528 + x^525 + x^523 + x^522 + x^520 + x^519 + x^518 + x^515 + x^514 + x^511 + x^510 + x^509 + x^508 + x^505 + x^504 + x^502 + x^501 + x^500 + x^499 + x^494 + x^493 + x^485 + x^484 + x^481 + x^480 + x^479 + x^477 + x^476 + x^475 + x^473 + x^466 + x^464 + x^462 + x^461 + x^460 + x^458 + x^457 + x^453 + x^447 + x^444 + x^442 + x^441 + x^440 + x^439 + x^438 + x^433 + x^432 + x^429 + x^428 + x^426 + x^425 + x^424 + x^422 + x^421 + x^420 + x^419 + x^418 + x^414 + x^412 + x^411 + x^407 + x^404 + x^401 + x^398 + x^396 + x^393 + x^392 + x^391 + x^389 + x^387 + x^385 + x^383 + x^382 + x^381 + x^380 + x^378 + x^377 + x^374 + x^372 + x^371 + x^368 + x^365 + x^363 + x^362 + x^359 + x^357 + x^356 + x^355 + x^354 + x^350 + x^347 + x^344 + x^343 + x^341 + x^338 + x^337 + x^335 + x^334 + x^333 + x^331 + x^330 + x^329 + x^328 + x^324 + x^322 + x^319 + x^317 + x^314 + x^310 + x^306 + x^300 + x^299 + x^295 + x^294 + x^291 + x^290 + x^289 + x^288 + x^287 + x^286 + x^285 + x^284 + x^282 + x^281 + x^279 + x^278 + x^275 + x^272 + x^271 + x^270 + x^269 + x^266 + x^264 + x^262 + x^260 + x^259 + x^258 + x^254 + x^250 + x^249 + x^247 + x^246 + x^244 + x^243 + x^241 + x^239 + x^237 + x^236 + x^233 + x^232 + x^231 + x^229 + x^227 + x^226 + x^221 + x^220 + x^218 + x^217 + x^216 + x^215 + x^214 + x^213 + x^212 + x^210 + x^209 + x^207 + x^206 + x^202 + x^201 + x^200 + x^199 + x^198 + x^197 + x^195 + x^193 + x^192 + x^189 + x^188 + x^180 + x^176 + x^174 + x^173 + x^172 + x^170 + x^167 + x^165 + x^164 + x^162 + x^160 + x^157 + x^155 + x^153 + x^152 + x^151 + x^149 + x^148 + x^147 + x^144 + x^142 + x^140 + x^139 + x^136 + x^134 + x^133 + x^128 + x^127 + x^124 + x^123 + x^122 + x^121 + x^119 + x^117 + x^115 + x^113 + x^112 + x^110 + x^107 + x^105 + x^101 + x^100 + x^99 + x^98 + x^94 + x^92 + x^91 + x^90 + x^89 + x^87 + x^85 + x^83 + x^81 + x^80 + x^78 + x^77 + x^74 + x^72 + x^71 + x^70 + x^69 + x^65 + x^64 + x^63 + x^62 + x^61 + x^57 + x^56 + x^55 + x^54 + x^53 + x^49 + x^48 + x^42 + x^41 + x^39 + x^36 + x^34 + x^32 + x^31 + x^24 + x^23 + x^21 + x^14 + x^10 + 1
+
+37-33-14 381 x^928 + x^898 + x^874 + x^870 + x^849 + x^845 + x^841 + x^837 + x^836 + x^832 + x^824 + x^820 + x^812 + x^811 + x^804 + x^802 + x^794 + x^789 + x^785 + x^783 + x^781 + x^777 + x^775 + x^771 + x^770 + x^764 + x^761 + x^757 + x^754 + x^751 + x^746 + x^742 + x^741 + x^740 + x^738 + x^736 + x^734 + x^733 + x^731 + x^727 + x^726 + x^725 + x^724 + x^723 + x^721 + x^720 + x^718 + x^717 + x^716 + x^715 + x^714 + x^713 + x^712 + x^711 + x^709 + x^705 + x^704 + x^703 + x^701 + x^695 + x^692 + x^691 + x^690 + x^688 + x^687 + x^686 + x^685 + x^684 + x^682 + x^680 + x^679 + x^676 + x^671 + x^670 + x^665 + x^663 + x^662 + x^661 + x^660 + x^659 + x^653 + x^652 + x^651 + x^650 + x^648 + x^644 + x^643 + x^642 + x^641 + x^637 + x^635 + x^634 + x^631 + x^630 + x^629 + x^627 + x^626 + x^623 + x^622 + x^621 + x^619 + x^617 + x^616 + x^614 + x^613 + x^611 + x^610 + x^603 + x^601 + x^600 + x^599 + x^597 + x^596 + x^594 + x^593 + x^592 + x^591 + x^589 + x^587 + x^585 + x^583 + x^582 + x^579 + x^575 + x^573 + x^571 + x^570 + x^567 + x^566 + x^560 + x^557 + x^556 + x^554 + x^553 + x^552 + x^551 + x^548 + x^546 + x^541 + x^540 + x^538 + x^535 + x^534 + x^531 + x^527 + x^526 + x^525 + x^524 + x^523 + x^517 + x^516 + x^511 + x^509 + x^507 + x^499 + x^496 + x^493 + x^491 + x^490 + x^485 + x^482 + x^481 + x^479 + x^477 + x^475 + x^474 + x^470 + x^469 + x^468 + x^465 + x^462 + x^461 + x^459 + x^458 + x^453 + x^451 + x^446 + x^444 + x^441 + x^436 + x^435 + x^434 + x^432 + x^429 + x^420 + x^419 + x^416 + x^414 + x^411 + x^410 + x^409 + x^407 + x^405 + x^404 + x^403 + x^402 + x^401 + x^397 + x^395 + x^393 + x^392 + x^390 + x^388 + x^384 + x^381 + x^379 + x^376 + x^374 + x^368 + x^367 + x^365 + x^362 + x^361 + x^360 + x^359 + x^357 + x^355 + x^351 + x^349 + x^346 + x^345 + x^344 + x^342 + x^341 + x^339 + x^337 + x^336 + x^335 + x^333 + x^331 + x^326 + x^320 + x^318 + x^316 + x^315 + x^314 + x^313 + x^312 + x^311 + x^310 + x^309 + x^306 + x^304 + x^303 + x^302 + x^301 + x^300 + x^298 + x^297 + x^296 + x^295 + x^294 + x^293 + x^292 + x^290 + x^289 + x^288 + x^284 + x^283 + x^282 + x^278 + x^277 + x^274 + x^273 + x^272 + x^270 + x^266 + x^265 + x^261 + x^258 + x^256 + x^255 + x^254 + x^248 + x^246 + x^245 + x^239 + x^237 + x^234 + x^230 + x^229 + x^225 + x^224 + x^222 + x^221 + x^217 + x^215 + x^214 + x^213 + x^212 + x^208 + x^206 + x^204 + x^203 + x^202 + x^201 + x^199 + x^198 + x^195 + x^194 + x^191 + x^189 + x^188 + x^186 + x^184 + x^182 + x^181 + x^179 + x^177 + x^176 + x^175 + x^171 + x^169 + x^168 + x^162 + x^161 + x^159 + x^157 + x^156 + x^151 + x^150 + x^148 + x^146 + x^145 + x^142 + x^140 + x^139 + x^138 + x^135 + x^134 + x^131 + x^129 + x^126 + x^124 + x^119 + x^118 + x^117 + x^116 + x^108 + x^106 + x^105 + x^103 + x^99 + x^97 + x^93 + x^92 + x^91 + x^90 + x^87 + x^86 + x^84 + x^83 + x^78 + x^76 + x^73 + x^66 + x^65 + x^64 + x^62 + x^61 + x^58 + x^53 + x^52 + x^51 + x^48 + x^47 + x^46 + x^45 + x^44 + x^42 + x^41 + x^38 + x^34 + x^29 + x^28 + x^26 + x^23 + x^16 + x^8 + x^6 + 1
+
+36-46-33 383 x^928 + x^898 + x^870 + x^857 + x^828 + x^827 + x^816 + x^815 + x^809 + x^808 + x^804 + x^797 + x^792 + x^786 + x^785 + x^780 + x^778 + x^775 + x^773 + x^768 + x^767 + x^762 + x^755 + x^751 + x^750 + x^737 + x^734 + x^732 + x^728 + x^727 + x^725 + x^722 + x^716 + x^715 + x^714 + x^710 + x^708 + x^707 + x^704 + x^703 + x^701 + x^698 + x^697 + x^695 + x^689 + x^688 + x^685 + x^681 + x^680 + x^679 + x^678 + x^677 + x^674 + x^665 + x^658 + x^656 + x^651 + x^650 + x^649 + x^648 + x^647 + x^640 + x^637 + x^635 + x^634 + x^633 + x^631 + x^628 + x^626 + x^624 + x^620 + x^619 + x^617 + x^616 + x^610 + x^607 + x^605 + x^603 + x^602 + x^601 + x^598 + x^591 + x^590 + x^587 + x^584 + x^582 + x^580 + x^577 + x^574 + x^573 + x^571 + x^567 + x^563 + x^562 + x^560 + x^559 + x^558 + x^557 + x^555 + x^553 + x^551 + x^550 + x^549 + x^548 + x^547 + x^544 + x^542 + x^540 + x^539 + x^538 + x^537 + x^535 + x^534 + x^533 + x^531 + x^528 + x^527 + x^525 + x^519 + x^517 + x^516 + x^515 + x^510 + x^509 + x^508 + x^507 + x^505 + x^500 + x^499 + x^496 + x^495 + x^494 + x^493 + x^489 + x^488 + x^487 + x^486 + x^485 + x^484 + x^482 + x^480 + x^479 + x^477 + x^475 + x^473 + x^470 + x^468 + x^467 + x^466 + x^465 + x^463 + x^461 + x^460 + x^455 + x^451 + x^450 + x^448 + x^444 + x^443 + x^442 + x^439 + x^438 + x^437 + x^435 + x^434 + x^433 + x^427 + x^426 + x^425 + x^423 + x^421 + x^420 + x^419 + x^418 + x^416 + x^413 + x^411 + x^410 + x^408 + x^407 + x^404 + x^402 + x^400 + x^399 + x^398 + x^397 + x^396 + x^395 + x^394 + x^393 + x^387 + x^386 + x^382 + x^379 + x^378 + x^377 + x^376 + x^375 + x^374 + x^372 + x^371 + x^370 + x^369 + x^366 + x^364 + x^363 + x^362 + x^361 + x^359 + x^358 + x^357 + x^356 + x^355 + x^354 + x^352 + x^347 + x^346 + x^345 + x^344 + x^343 + x^341 + x^340 + x^336 + x^335 + x^332 + x^330 + x^329 + x^328 + x^325 + x^324 + x^323 + x^322 + x^321 + x^320 + x^318 + x^316 + x^315 + x^312 + x^302 + x^301 + x^298 + x^295 + x^288 + x^287 + x^286 + x^285 + x^280 + x^279 + x^278 + x^275 + x^273 + x^272 + x^270 + x^267 + x^266 + x^264 + x^261 + x^259 + x^258 + x^255 + x^253 + x^252 + x^250 + x^249 + x^248 + x^247 + x^244 + x^243 + x^242 + x^241 + x^240 + x^237 + x^236 + x^235 + x^231 + x^230 + x^228 + x^225 + x^224 + x^222 + x^220 + x^218 + x^217 + x^216 + x^215 + x^212 + x^211 + x^205 + x^204 + x^203 + x^201 + x^196 + x^194 + x^193 + x^192 + x^191 + x^190 + x^187 + x^186 + x^184 + x^183 + x^182 + x^180 + x^179 + x^178 + x^174 + x^173 + x^172 + x^164 + x^163 + x^162 + x^161 + x^160 + x^159 + x^158 + x^156 + x^154 + x^153 + x^150 + x^149 + x^148 + x^146 + x^144 + x^143 + x^140 + x^134 + x^131 + x^127 + x^125 + x^124 + x^120 + x^119 + x^118 + x^116 + x^115 + x^113 + x^112 + x^109 + x^108 + x^107 + x^106 + x^103 + x^100 + x^99 + x^97 + x^96 + x^95 + x^94 + x^91 + x^87 + x^86 + x^83 + x^81 + x^80 + x^78 + x^77 + x^75 + x^74 + x^72 + x^71 + x^69 + x^68 + x^66 + x^64 + x^63 + x^59 + x^57 + x^55 + x^53 + x^48 + x^47 + x^44 + x^42 + x^41 + x^40 + x^37 + x^28 + x^27 + x^26 + x^20 + x^18 + x^16 + 1
+
+40-1-13 383 x^928 + x^898 + x^870 + x^864 + x^861 + x^858 + x^855 + x^852 + x^837 + x^834 + x^825 + x^808 + x^804 + x^801 + x^798 + x^792 + x^791 + x^788 + x^785 + x^778 + x^777 + x^774 + x^773 + x^758 + x^755 + x^752 + x^743 + x^740 + x^738 + x^737 + x^735 + x^734 + x^725 + x^721 + x^719 + x^718 + x^716 + x^715 + x^713 + x^710 + x^707 + x^705 + x^704 + x^703 + x^698 + x^695 + x^691 + x^689 + x^686 + x^682 + x^680 + x^678 + x^677 + x^676 + x^674 + x^673 + x^671 + x^668 + x^667 + x^664 + x^662 + x^661 + x^659 + x^658 + x^656 + x^652 + x^650 + x^648 + x^647 + x^645 + x^644 + x^643 + x^642 + x^641 + x^640 + x^636 + x^633 + x^630 + x^629 + x^628 + x^627 + x^626 + x^623 + x^621 + x^618 + x^615 + x^612 + x^608 + x^607 + x^605 + x^603 + x^602 + x^600 + x^598 + x^596 + x^594 + x^593 + x^588 + x^583 + x^582 + x^579 + x^574 + x^573 + x^569 + x^568 + x^567 + x^565 + x^564 + x^562 + x^558 + x^557 + x^556 + x^555 + x^552 + x^551 + x^548 + x^545 + x^544 + x^542 + x^540 + x^537 + x^535 + x^534 + x^533 + x^532 + x^531 + x^530 + x^526 + x^525 + x^524 + x^523 + x^521 + x^520 + x^519 + x^518 + x^517 + x^515 + x^513 + x^509 + x^508 + x^507 + x^502 + x^500 + x^499 + x^496 + x^495 + x^491 + x^489 + x^488 + x^485 + x^482 + x^480 + x^478 + x^476 + x^474 + x^471 + x^468 + x^466 + x^463 + x^462 + x^461 + x^460 + x^459 + x^457 + x^456 + x^453 + x^451 + x^450 + x^447 + x^443 + x^440 + x^439 + x^436 + x^435 + x^434 + x^433 + x^432 + x^426 + x^425 + x^424 + x^422 + x^421 + x^419 + x^417 + x^416 + x^410 + x^409 + x^408 + x^406 + x^405 + x^402 + x^401 + x^399 + x^398 + x^396 + x^389 + x^388 + x^387 + x^385 + x^383 + x^382 + x^381 + x^379 + x^378 + x^377 + x^376 + x^375 + x^373 + x^371 + x^368 + x^366 + x^364 + x^363 + x^360 + x^358 + x^356 + x^355 + x^353 + x^350 + x^349 + x^346 + x^345 + x^344 + x^340 + x^339 + x^338 + x^332 + x^331 + x^329 + x^326 + x^324 + x^323 + x^321 + x^316 + x^315 + x^313 + x^312 + x^310 + x^309 + x^307 + x^306 + x^305 + x^303 + x^302 + x^300 + x^299 + x^296 + x^294 + x^293 + x^292 + x^289 + x^288 + x^286 + x^285 + x^283 + x^282 + x^279 + x^277 + x^274 + x^273 + x^272 + x^270 + x^269 + x^268 + x^267 + x^265 + x^264 + x^261 + x^259 + x^256 + x^251 + x^249 + x^245 + x^241 + x^240 + x^239 + x^238 + x^236 + x^235 + x^234 + x^232 + x^230 + x^226 + x^222 + x^220 + x^217 + x^215 + x^211 + x^210 + x^208 + x^203 + x^200 + x^199 + x^197 + x^195 + x^194 + x^193 + x^190 + x^187 + x^186 + x^184 + x^183 + x^182 + x^178 + x^176 + x^174 + x^169 + x^168 + x^167 + x^164 + x^162 + x^161 + x^160 + x^159 + x^158 + x^154 + x^153 + x^147 + x^142 + x^138 + x^137 + x^129 + x^128 + x^127 + x^126 + x^124 + x^123 + x^121 + x^119 + x^116 + x^115 + x^112 + x^110 + x^109 + x^107 + x^106 + x^103 + x^101 + x^100 + x^99 + x^98 + x^95 + x^94 + x^93 + x^92 + x^91 + x^89 + x^85 + x^83 + x^80 + x^79 + x^77 + x^75 + x^73 + x^72 + x^71 + x^63 + x^61 + x^59 + x^58 + x^57 + x^55 + x^51 + x^48 + x^47 + x^46 + x^45 + x^39 + x^38 + x^37 + x^34 + x^33 + x^32 + x^29 + x^28 + x^25 + x^23 + x^20 + x^17 + x^11 + x^10 + x^7 + 1
+
+46-53-31 383 x^928 + x^898 + x^896 + x^875 + x^870 + x^864 + x^856 + x^854 + x^848 + x^845 + x^834 + x^833 + x^827 + x^817 + x^814 + x^812 + x^808 + x^807 + x^806 + x^804 + x^801 + x^796 + x^794 + x^791 + x^787 + x^786 + x^778 + x^777 + x^776 + x^774 + x^773 + x^772 + x^770 + x^767 + x^765 + x^764 + x^761 + x^757 + x^756 + x^754 + x^746 + x^745 + x^744 + x^741 + x^735 + x^734 + x^730 + x^727 + x^725 + x^723 + x^716 + x^715 + x^714 + x^713 + x^712 + x^705 + x^704 + x^703 + x^702 + x^697 + x^696 + x^692 + x^688 + x^685 + x^684 + x^683 + x^682 + x^681 + x^674 + x^673 + x^672 + x^671 + x^670 + x^667 + x^666 + x^664 + x^663 + x^661 + x^660 + x^658 + x^655 + x^654 + x^653 + x^652 + x^651 + x^650 + x^645 + x^639 + x^637 + x^634 + x^631 + x^630 + x^626 + x^625 + x^624 + x^621 + x^620 + x^618 + x^615 + x^610 + x^608 + x^607 + x^606 + x^605 + x^604 + x^602 + x^596 + x^594 + x^588 + x^586 + x^584 + x^582 + x^580 + x^578 + x^574 + x^573 + x^571 + x^570 + x^568 + x^567 + x^560 + x^553 + x^551 + x^548 + x^545 + x^543 + x^542 + x^538 + x^537 + x^536 + x^534 + x^533 + x^532 + x^530 + x^529 + x^528 + x^523 + x^521 + x^513 + x^512 + x^509 + x^508 + x^505 + x^502 + x^491 + x^490 + x^489 + x^487 + x^481 + x^479 + x^468 + x^466 + x^465 + x^464 + x^461 + x^460 + x^459 + x^457 + x^455 + x^454 + x^453 + x^451 + x^450 + x^444 + x^442 + x^440 + x^438 + x^431 + x^430 + x^429 + x^428 + x^427 + x^426 + x^425 + x^424 + x^423 + x^422 + x^421 + x^416 + x^415 + x^414 + x^412 + x^410 + x^409 + x^408 + x^402 + x^400 + x^399 + x^398 + x^396 + x^395 + x^393 + x^392 + x^391 + x^388 + x^385 + x^384 + x^381 + x^380 + x^379 + x^377 + x^376 + x^374 + x^373 + x^371 + x^368 + x^366 + x^365 + x^364 + x^362 + x^358 + x^357 + x^356 + x^351 + x^348 + x^345 + x^342 + x^339 + x^338 + x^336 + x^334 + x^331 + x^330 + x^328 + x^327 + x^323 + x^320 + x^319 + x^318 + x^312 + x^311 + x^307 + x^306 + x^305 + x^304 + x^303 + x^302 + x^301 + x^298 + x^295 + x^293 + x^292 + x^291 + x^287 + x^286 + x^285 + x^284 + x^283 + x^280 + x^279 + x^278 + x^276 + x^275 + x^271 + x^269 + x^266 + x^264 + x^263 + x^262 + x^260 + x^257 + x^255 + x^254 + x^253 + x^252 + x^251 + x^250 + x^248 + x^242 + x^241 + x^238 + x^234 + x^231 + x^225 + x^223 + x^222 + x^221 + x^220 + x^219 + x^218 + x^217 + x^214 + x^211 + x^209 + x^208 + x^207 + x^206 + x^204 + x^200 + x^196 + x^194 + x^191 + x^188 + x^186 + x^185 + x^182 + x^181 + x^178 + x^176 + x^175 + x^174 + x^169 + x^168 + x^166 + x^164 + x^160 + x^159 + x^158 + x^155 + x^154 + x^153 + x^151 + x^149 + x^147 + x^145 + x^143 + x^138 + x^135 + x^132 + x^131 + x^130 + x^128 + x^127 + x^124 + x^123 + x^121 + x^120 + x^119 + x^117 + x^116 + x^115 + x^112 + x^111 + x^110 + x^109 + x^106 + x^105 + x^104 + x^101 + x^99 + x^96 + x^87 + x^85 + x^84 + x^83 + x^81 + x^80 + x^79 + x^75 + x^73 + x^70 + x^69 + x^68 + x^67 + x^66 + x^63 + x^61 + x^60 + x^58 + x^56 + x^54 + x^53 + x^51 + x^49 + x^47 + x^45 + x^44 + x^43 + x^42 + x^41 + x^39 + x^36 + x^34 + x^31 + x^30 + x^29 + x^27 + x^24 + x^22 + x^14 + x^13 + x^12 + 1
+
+1-41-10 385 x^928 + x^898 + x^879 + x^870 + x^855 + x^850 + x^849 + x^831 + x^826 + x^825 + x^819 + x^816 + x^808 + x^807 + x^802 + x^801 + x^800 + x^796 + x^792 + x^789 + x^777 + x^776 + x^768 + x^766 + x^762 + x^758 + x^756 + x^754 + x^748 + x^746 + x^744 + x^742 + x^738 + x^736 + x^735 + x^733 + x^729 + x^728 + x^725 + x^720 + x^716 + x^710 + x^705 + x^704 + x^701 + x^700 + x^696 + x^688 + x^686 + x^682 + x^681 + x^680 + x^679 + x^678 + x^677 + x^676 + x^675 + x^674 + x^671 + x^670 + x^669 + x^666 + x^665 + x^661 + x^660 + x^658 + x^655 + x^653 + x^652 + x^649 + x^648 + x^645 + x^640 + x^637 + x^633 + x^629 + x^628 + x^624 + x^623 + x^621 + x^620 + x^619 + x^618 + x^617 + x^616 + x^610 + x^609 + x^607 + x^605 + x^604 + x^601 + x^600 + x^595 + x^591 + x^589 + x^586 + x^584 + x^581 + x^579 + x^575 + x^573 + x^569 + x^568 + x^561 + x^559 + x^556 + x^555 + x^546 + x^542 + x^540 + x^538 + x^537 + x^534 + x^533 + x^531 + x^530 + x^528 + x^526 + x^525 + x^523 + x^518 + x^517 + x^513 + x^511 + x^507 + x^497 + x^496 + x^494 + x^493 + x^491 + x^489 + x^488 + x^487 + x^485 + x^484 + x^483 + x^482 + x^479 + x^477 + x^476 + x^475 + x^474 + x^471 + x^470 + x^468 + x^466 + x^465 + x^464 + x^463 + x^462 + x^461 + x^459 + x^458 + x^454 + x^453 + x^452 + x^451 + x^449 + x^447 + x^446 + x^442 + x^441 + x^440 + x^434 + x^431 + x^428 + x^427 + x^426 + x^424 + x^421 + x^418 + x^417 + x^416 + x^414 + x^412 + x^411 + x^408 + x^405 + x^401 + x^400 + x^399 + x^398 + x^395 + x^394 + x^393 + x^392 + x^391 + x^388 + x^386 + x^385 + x^381 + x^380 + x^379 + x^378 + x^376 + x^375 + x^373 + x^372 + x^370 + x^367 + x^366 + x^365 + x^364 + x^361 + x^360 + x^359 + x^356 + x^354 + x^353 + x^349 + x^348 + x^346 + x^344 + x^340 + x^335 + x^332 + x^330 + x^325 + x^324 + x^321 + x^318 + x^316 + x^315 + x^314 + x^312 + x^310 + x^309 + x^307 + x^304 + x^301 + x^300 + x^299 + x^298 + x^297 + x^295 + x^291 + x^290 + x^289 + x^288 + x^287 + x^286 + x^285 + x^284 + x^281 + x^280 + x^276 + x^274 + x^269 + x^268 + x^267 + x^265 + x^264 + x^261 + x^260 + x^259 + x^257 + x^256 + x^255 + x^254 + x^251 + x^250 + x^245 + x^242 + x^239 + x^236 + x^233 + x^229 + x^227 + x^225 + x^223 + x^222 + x^219 + x^217 + x^214 + x^213 + x^210 + x^207 + x^205 + x^204 + x^203 + x^202 + x^201 + x^200 + x^199 + x^198 + x^197 + x^196 + x^195 + x^192 + x^190 + x^189 + x^181 + x^180 + x^178 + x^177 + x^175 + x^174 + x^173 + x^172 + x^169 + x^168 + x^165 + x^162 + x^159 + x^158 + x^154 + x^153 + x^152 + x^150 + x^148 + x^144 + x^143 + x^142 + x^141 + x^139 + x^138 + x^137 + x^133 + x^132 + x^128 + x^127 + x^124 + x^123 + x^122 + x^121 + x^118 + x^116 + x^106 + x^102 + x^101 + x^98 + x^96 + x^92 + x^91 + x^90 + x^89 + x^88 + x^86 + x^85 + x^84 + x^83 + x^81 + x^80 + x^78 + x^76 + x^73 + x^72 + x^71 + x^69 + x^67 + x^66 + x^65 + x^63 + x^58 + x^54 + x^53 + x^52 + x^51 + x^50 + x^47 + x^46 + x^45 + x^44 + x^43 + x^40 + x^39 + x^38 + x^37 + x^34 + x^33 + x^32 + x^30 + x^25 + x^23 + x^21 + x^20 + x^19 + x^17 + x^16 + x^15 + x^12 + x^9 + x^8 + x^4 + 1
+
+11-33-48 385 x^928 + x^898 + x^882 + x^870 + x^860 + x^853 + x^844 + x^835 + x^828 + x^827 + x^822 + x^819 + x^815 + x^811 + x^808 + x^806 + x^805 + x^794 + x^793 + x^786 + x^784 + x^781 + x^778 + x^773 + x^772 + x^769 + x^765 + x^762 + x^760 + x^759 + x^756 + x^755 + x^748 + x^746 + x^743 + x^739 + x^735 + x^734 + x^733 + x^731 + x^729 + x^727 + x^723 + x^718 + x^713 + x^709 + x^707 + x^706 + x^704 + x^702 + x^699 + x^696 + x^693 + x^692 + x^691 + x^686 + x^685 + x^683 + x^679 + x^677 + x^673 + x^670 + x^669 + x^666 + x^657 + x^656 + x^655 + x^649 + x^648 + x^646 + x^641 + x^639 + x^638 + x^635 + x^633 + x^632 + x^630 + x^628 + x^627 + x^625 + x^620 + x^616 + x^614 + x^613 + x^611 + x^610 + x^609 + x^607 + x^606 + x^600 + x^595 + x^593 + x^592 + x^589 + x^587 + x^584 + x^581 + x^580 + x^579 + x^577 + x^572 + x^570 + x^568 + x^567 + x^566 + x^564 + x^560 + x^559 + x^557 + x^555 + x^554 + x^552 + x^551 + x^546 + x^542 + x^538 + x^535 + x^534 + x^533 + x^531 + x^530 + x^528 + x^526 + x^524 + x^523 + x^520 + x^519 + x^511 + x^509 + x^506 + x^504 + x^503 + x^502 + x^501 + x^500 + x^499 + x^498 + x^495 + x^494 + x^491 + x^490 + x^489 + x^488 + x^487 + x^485 + x^484 + x^479 + x^475 + x^473 + x^466 + x^459 + x^457 + x^456 + x^455 + x^454 + x^451 + x^450 + x^449 + x^448 + x^447 + x^446 + x^444 + x^443 + x^442 + x^441 + x^440 + x^433 + x^432 + x^430 + x^428 + x^427 + x^425 + x^423 + x^419 + x^418 + x^417 + x^414 + x^409 + x^408 + x^406 + x^404 + x^402 + x^400 + x^398 + x^397 + x^396 + x^395 + x^393 + x^389 + x^388 + x^385 + x^379 + x^377 + x^375 + x^374 + x^369 + x^365 + x^364 + x^363 + x^362 + x^361 + x^359 + x^355 + x^354 + x^350 + x^348 + x^345 + x^344 + x^339 + x^336 + x^335 + x^334 + x^333 + x^332 + x^331 + x^330 + x^329 + x^328 + x^326 + x^319 + x^318 + x^316 + x^315 + x^314 + x^313 + x^312 + x^309 + x^308 + x^304 + x^303 + x^302 + x^299 + x^298 + x^297 + x^295 + x^294 + x^293 + x^292 + x^291 + x^290 + x^288 + x^285 + x^282 + x^281 + x^279 + x^277 + x^276 + x^274 + x^272 + x^271 + x^270 + x^269 + x^268 + x^267 + x^265 + x^264 + x^262 + x^261 + x^260 + x^257 + x^253 + x^251 + x^250 + x^247 + x^246 + x^243 + x^242 + x^241 + x^240 + x^237 + x^236 + x^233 + x^232 + x^230 + x^229 + x^226 + x^223 + x^222 + x^221 + x^220 + x^217 + x^215 + x^211 + x^210 + x^209 + x^207 + x^206 + x^205 + x^203 + x^201 + x^200 + x^198 + x^196 + x^195 + x^193 + x^189 + x^188 + x^186 + x^184 + x^180 + x^179 + x^177 + x^176 + x^170 + x^168 + x^163 + x^162 + x^160 + x^159 + x^158 + x^157 + x^156 + x^154 + x^151 + x^149 + x^148 + x^145 + x^144 + x^141 + x^140 + x^138 + x^137 + x^136 + x^135 + x^134 + x^133 + x^132 + x^131 + x^130 + x^129 + x^125 + x^124 + x^121 + x^117 + x^116 + x^110 + x^109 + x^108 + x^106 + x^104 + x^103 + x^102 + x^99 + x^98 + x^96 + x^95 + x^93 + x^92 + x^90 + x^89 + x^88 + x^85 + x^83 + x^81 + x^78 + x^76 + x^72 + x^71 + x^70 + x^68 + x^67 + x^66 + x^62 + x^59 + x^58 + x^56 + x^51 + x^48 + x^46 + x^45 + x^44 + x^43 + x^41 + x^40 + x^38 + x^37 + x^35 + x^34 + x^33 + x^32 + x^27 + x^22 + x^19 + x^13 + 1
+
+19-8-4 387 x^928 + x^898 + x^870 + x^844 + x^838 + x^834 + x^828 + x^818 + x^814 + x^806 + x^804 + x^803 + x^797 + x^782 + x^778 + x^776 + x^774 + x^773 + x^772 + x^768 + x^767 + x^764 + x^752 + x^751 + x^745 + x^744 + x^742 + x^740 + x^738 + x^736 + x^733 + x^730 + x^721 + x^718 + x^715 + x^714 + x^710 + x^707 + x^704 + x^702 + x^700 + x^699 + x^698 + x^697 + x^694 + x^692 + x^691 + x^688 + x^686 + x^685 + x^682 + x^676 + x^673 + x^671 + x^670 + x^669 + x^666 + x^662 + x^661 + x^658 + x^656 + x^655 + x^654 + x^652 + x^649 + x^648 + x^647 + x^645 + x^644 + x^642 + x^640 + x^638 + x^636 + x^632 + x^631 + x^630 + x^623 + x^622 + x^621 + x^616 + x^614 + x^612 + x^611 + x^606 + x^605 + x^602 + x^598 + x^597 + x^594 + x^593 + x^591 + x^590 + x^588 + x^587 + x^586 + x^584 + x^582 + x^581 + x^579 + x^577 + x^574 + x^572 + x^571 + x^568 + x^567 + x^566 + x^563 + x^562 + x^560 + x^559 + x^558 + x^556 + x^553 + x^551 + x^550 + x^549 + x^546 + x^545 + x^543 + x^542 + x^538 + x^536 + x^535 + x^534 + x^533 + x^531 + x^530 + x^529 + x^527 + x^525 + x^524 + x^522 + x^521 + x^520 + x^518 + x^517 + x^513 + x^512 + x^510 + x^509 + x^507 + x^506 + x^505 + x^504 + x^501 + x^500 + x^499 + x^493 + x^492 + x^491 + x^489 + x^488 + x^486 + x^485 + x^484 + x^480 + x^479 + x^478 + x^477 + x^474 + x^473 + x^472 + x^470 + x^468 + x^464 + x^462 + x^458 + x^456 + x^455 + x^454 + x^453 + x^452 + x^451 + x^450 + x^449 + x^447 + x^446 + x^445 + x^441 + x^439 + x^438 + x^437 + x^436 + x^434 + x^433 + x^432 + x^431 + x^429 + x^426 + x^425 + x^424 + x^423 + x^421 + x^419 + x^418 + x^416 + x^414 + x^412 + x^410 + x^407 + x^405 + x^404 + x^398 + x^397 + x^394 + x^393 + x^392 + x^391 + x^387 + x^386 + x^385 + x^382 + x^381 + x^379 + x^377 + x^375 + x^374 + x^369 + x^368 + x^365 + x^364 + x^363 + x^362 + x^361 + x^359 + x^358 + x^356 + x^355 + x^352 + x^351 + x^350 + x^345 + x^343 + x^341 + x^340 + x^338 + x^333 + x^331 + x^330 + x^329 + x^328 + x^327 + x^325 + x^324 + x^323 + x^322 + x^318 + x^315 + x^312 + x^310 + x^308 + x^305 + x^304 + x^303 + x^299 + x^296 + x^295 + x^294 + x^290 + x^289 + x^288 + x^285 + x^284 + x^281 + x^280 + x^275 + x^274 + x^273 + x^271 + x^268 + x^266 + x^264 + x^263 + x^262 + x^261 + x^260 + x^258 + x^256 + x^255 + x^254 + x^251 + x^245 + x^240 + x^237 + x^236 + x^231 + x^230 + x^229 + x^228 + x^223 + x^221 + x^219 + x^218 + x^215 + x^210 + x^208 + x^207 + x^206 + x^204 + x^202 + x^197 + x^196 + x^195 + x^194 + x^193 + x^192 + x^187 + x^186 + x^184 + x^183 + x^182 + x^180 + x^178 + x^177 + x^175 + x^174 + x^169 + x^168 + x^166 + x^165 + x^163 + x^160 + x^159 + x^156 + x^155 + x^152 + x^150 + x^145 + x^140 + x^138 + x^137 + x^136 + x^135 + x^134 + x^133 + x^131 + x^128 + x^127 + x^126 + x^122 + x^121 + x^118 + x^117 + x^114 + x^109 + x^105 + x^102 + x^101 + x^100 + x^99 + x^96 + x^94 + x^93 + x^91 + x^90 + x^89 + x^88 + x^87 + x^81 + x^79 + x^76 + x^74 + x^71 + x^70 + x^64 + x^63 + x^61 + x^59 + x^56 + x^55 + x^49 + x^47 + x^46 + x^44 + x^43 + x^40 + x^35 + x^34 + x^33 + x^31 + x^28 + x^26 + x^23 + x^21 + x^18 + x^13 + 1
+
+36-23-57 387 x^928 + x^898 + x^897 + x^890 + x^870 + x^860 + x^859 + x^854 + x^853 + x^846 + x^836 + x^835 + x^824 + x^816 + x^810 + x^809 + x^808 + x^804 + x^802 + x^792 + x^791 + x^785 + x^784 + x^780 + x^778 + x^777 + x^776 + x^775 + x^774 + x^773 + x^765 + x^755 + x^753 + x^748 + x^747 + x^744 + x^742 + x^733 + x^732 + x^728 + x^725 + x^724 + x^721 + x^716 + x^714 + x^713 + x^703 + x^701 + x^700 + x^699 + x^697 + x^693 + x^692 + x^691 + x^690 + x^689 + x^680 + x^679 + x^675 + x^673 + x^672 + x^666 + x^663 + x^662 + x^661 + x^658 + x^656 + x^655 + x^653 + x^652 + x^649 + x^647 + x^645 + x^642 + x^641 + x^639 + x^638 + x^637 + x^633 + x^630 + x^629 + x^625 + x^620 + x^619 + x^614 + x^613 + x^612 + x^611 + x^610 + x^606 + x^605 + x^604 + x^603 + x^601 + x^600 + x^599 + x^597 + x^593 + x^591 + x^589 + x^587 + x^586 + x^584 + x^583 + x^581 + x^579 + x^576 + x^572 + x^571 + x^566 + x^565 + x^563 + x^559 + x^554 + x^552 + x^549 + x^548 + x^545 + x^544 + x^543 + x^540 + x^535 + x^534 + x^533 + x^531 + x^529 + x^524 + x^522 + x^517 + x^516 + x^513 + x^512 + x^511 + x^509 + x^507 + x^506 + x^505 + x^503 + x^502 + x^496 + x^495 + x^494 + x^492 + x^491 + x^490 + x^489 + x^487 + x^478 + x^477 + x^475 + x^474 + x^472 + x^471 + x^470 + x^469 + x^466 + x^463 + x^461 + x^459 + x^458 + x^457 + x^456 + x^455 + x^454 + x^453 + x^452 + x^448 + x^447 + x^446 + x^444 + x^442 + x^440 + x^439 + x^438 + x^437 + x^434 + x^431 + x^428 + x^427 + x^426 + x^425 + x^424 + x^423 + x^414 + x^409 + x^408 + x^407 + x^403 + x^401 + x^400 + x^396 + x^395 + x^394 + x^390 + x^389 + x^388 + x^387 + x^386 + x^379 + x^378 + x^377 + x^375 + x^374 + x^370 + x^366 + x^360 + x^359 + x^358 + x^357 + x^356 + x^355 + x^353 + x^351 + x^350 + x^349 + x^348 + x^347 + x^345 + x^343 + x^342 + x^341 + x^340 + x^339 + x^338 + x^336 + x^335 + x^330 + x^329 + x^327 + x^325 + x^324 + x^323 + x^322 + x^319 + x^318 + x^315 + x^313 + x^309 + x^305 + x^304 + x^302 + x^300 + x^298 + x^296 + x^291 + x^289 + x^286 + x^285 + x^284 + x^283 + x^282 + x^281 + x^279 + x^275 + x^274 + x^272 + x^271 + x^265 + x^264 + x^263 + x^259 + x^258 + x^257 + x^253 + x^252 + x^249 + x^246 + x^245 + x^244 + x^242 + x^239 + x^233 + x^232 + x^231 + x^230 + x^229 + x^228 + x^221 + x^217 + x^216 + x^212 + x^211 + x^209 + x^208 + x^205 + x^202 + x^201 + x^200 + x^199 + x^198 + x^197 + x^196 + x^195 + x^193 + x^192 + x^191 + x^189 + x^187 + x^186 + x^183 + x^182 + x^181 + x^177 + x^174 + x^172 + x^170 + x^166 + x^164 + x^163 + x^162 + x^160 + x^156 + x^155 + x^152 + x^151 + x^147 + x^144 + x^143 + x^142 + x^141 + x^138 + x^137 + x^135 + x^133 + x^130 + x^129 + x^126 + x^125 + x^123 + x^121 + x^120 + x^117 + x^114 + x^112 + x^107 + x^106 + x^103 + x^102 + x^100 + x^98 + x^95 + x^94 + x^93 + x^91 + x^90 + x^89 + x^87 + x^85 + x^84 + x^82 + x^81 + x^80 + x^78 + x^76 + x^75 + x^71 + x^70 + x^69 + x^68 + x^66 + x^65 + x^61 + x^60 + x^59 + x^58 + x^56 + x^55 + x^51 + x^49 + x^48 + x^46 + x^44 + x^42 + x^36 + x^34 + x^33 + x^32 + x^29 + x^24 + x^23 + x^20 + x^14 + x^13 + x^12 + x^11 + x^10 + 1
+
+44-4-19 389 x^928 + x^898 + x^874 + x^870 + x^836 + x^832 + x^824 + x^812 + x^809 + x^802 + x^794 + x^793 + x^789 + x^785 + x^781 + x^766 + x^764 + x^763 + x^762 + x^759 + x^758 + x^751 + x^750 + x^746 + x^744 + x^742 + x^738 + x^734 + x^733 + x^732 + x^729 + x^721 + x^719 + x^716 + x^715 + x^714 + x^713 + x^710 + x^706 + x^705 + x^703 + x^702 + x^700 + x^699 + x^698 + x^696 + x^693 + x^691 + x^690 + x^689 + x^688 + x^684 + x^680 + x^678 + x^677 + x^674 + x^672 + x^669 + x^667 + x^665 + x^663 + x^662 + x^660 + x^659 + x^658 + x^656 + x^652 + x^651 + x^649 + x^646 + x^645 + x^642 + x^641 + x^640 + x^633 + x^632 + x^630 + x^627 + x^626 + x^622 + x^617 + x^612 + x^611 + x^610 + x^606 + x^605 + x^604 + x^603 + x^602 + x^601 + x^599 + x^597 + x^596 + x^594 + x^593 + x^592 + x^591 + x^582 + x^581 + x^580 + x^578 + x^577 + x^575 + x^574 + x^573 + x^568 + x^567 + x^564 + x^560 + x^559 + x^558 + x^556 + x^554 + x^550 + x^548 + x^547 + x^545 + x^544 + x^541 + x^540 + x^539 + x^538 + x^536 + x^535 + x^534 + x^532 + x^531 + x^529 + x^523 + x^521 + x^518 + x^517 + x^516 + x^514 + x^511 + x^510 + x^508 + x^507 + x^505 + x^504 + x^499 + x^498 + x^495 + x^494 + x^492 + x^491 + x^489 + x^488 + x^487 + x^486 + x^484 + x^483 + x^482 + x^481 + x^478 + x^477 + x^476 + x^475 + x^471 + x^470 + x^468 + x^465 + x^464 + x^460 + x^459 + x^455 + x^454 + x^453 + x^451 + x^445 + x^438 + x^434 + x^432 + x^431 + x^430 + x^429 + x^428 + x^427 + x^424 + x^423 + x^419 + x^418 + x^417 + x^416 + x^415 + x^413 + x^411 + x^409 + x^408 + x^406 + x^405 + x^404 + x^403 + x^402 + x^400 + x^397 + x^395 + x^390 + x^389 + x^387 + x^386 + x^385 + x^384 + x^382 + x^380 + x^379 + x^377 + x^376 + x^374 + x^373 + x^370 + x^369 + x^366 + x^365 + x^364 + x^362 + x^360 + x^359 + x^357 + x^356 + x^355 + x^354 + x^352 + x^349 + x^345 + x^342 + x^341 + x^340 + x^338 + x^334 + x^333 + x^326 + x^324 + x^322 + x^321 + x^319 + x^318 + x^317 + x^315 + x^312 + x^311 + x^309 + x^305 + x^304 + x^302 + x^298 + x^297 + x^296 + x^294 + x^293 + x^290 + x^289 + x^287 + x^286 + x^285 + x^279 + x^277 + x^275 + x^273 + x^268 + x^265 + x^264 + x^263 + x^260 + x^258 + x^254 + x^251 + x^249 + x^248 + x^247 + x^245 + x^244 + x^242 + x^241 + x^240 + x^239 + x^232 + x^229 + x^226 + x^225 + x^223 + x^222 + x^220 + x^219 + x^218 + x^215 + x^214 + x^213 + x^212 + x^210 + x^209 + x^206 + x^203 + x^202 + x^199 + x^197 + x^195 + x^194 + x^192 + x^191 + x^189 + x^188 + x^185 + x^184 + x^181 + x^177 + x^176 + x^175 + x^174 + x^172 + x^171 + x^170 + x^169 + x^167 + x^164 + x^162 + x^160 + x^159 + x^157 + x^156 + x^154 + x^153 + x^152 + x^150 + x^148 + x^145 + x^144 + x^139 + x^138 + x^137 + x^136 + x^133 + x^126 + x^124 + x^123 + x^122 + x^121 + x^120 + x^119 + x^113 + x^111 + x^108 + x^105 + x^104 + x^103 + x^102 + x^101 + x^98 + x^97 + x^96 + x^95 + x^92 + x^86 + x^85 + x^83 + x^81 + x^80 + x^77 + x^74 + x^73 + x^72 + x^71 + x^70 + x^68 + x^67 + x^66 + x^64 + x^62 + x^61 + x^60 + x^59 + x^57 + x^53 + x^51 + x^43 + x^41 + x^40 + x^39 + x^35 + x^30 + x^29 + x^27 + x^26 + x^24 + x^20 + x^18 + x^14 + x^6 + 1
+
+8-3-35 389 x^928 + x^898 + x^895 + x^870 + x^865 + x^835 + x^832 + x^824 + x^821 + x^812 + x^810 + x^808 + x^807 + x^805 + x^804 + x^794 + x^791 + x^788 + x^778 + x^777 + x^774 + x^772 + x^771 + x^763 + x^755 + x^752 + x^750 + x^747 + x^746 + x^742 + x^739 + x^733 + x^731 + x^728 + x^725 + x^722 + x^721 + x^720 + x^719 + x^716 + x^714 + x^713 + x^712 + x^711 + x^708 + x^705 + x^704 + x^701 + x^700 + x^698 + x^695 + x^694 + x^692 + x^689 + x^683 + x^680 + x^675 + x^674 + x^670 + x^668 + x^667 + x^664 + x^662 + x^661 + x^658 + x^656 + x^654 + x^651 + x^650 + x^645 + x^643 + x^640 + x^639 + x^637 + x^635 + x^634 + x^633 + x^631 + x^630 + x^628 + x^621 + x^620 + x^616 + x^615 + x^614 + x^613 + x^608 + x^605 + x^604 + x^602 + x^601 + x^598 + x^597 + x^591 + x^590 + x^588 + x^587 + x^581 + x^579 + x^578 + x^577 + x^576 + x^573 + x^572 + x^571 + x^570 + x^569 + x^568 + x^566 + x^564 + x^563 + x^562 + x^559 + x^557 + x^553 + x^550 + x^549 + x^547 + x^546 + x^540 + x^537 + x^536 + x^534 + x^530 + x^527 + x^526 + x^525 + x^524 + x^522 + x^521 + x^520 + x^519 + x^518 + x^510 + x^509 + x^505 + x^504 + x^498 + x^496 + x^493 + x^492 + x^490 + x^489 + x^488 + x^487 + x^484 + x^483 + x^482 + x^481 + x^480 + x^479 + x^477 + x^475 + x^474 + x^472 + x^470 + x^468 + x^465 + x^464 + x^463 + x^461 + x^458 + x^457 + x^455 + x^454 + x^453 + x^452 + x^451 + x^450 + x^448 + x^447 + x^445 + x^441 + x^440 + x^437 + x^435 + x^434 + x^433 + x^432 + x^431 + x^425 + x^421 + x^418 + x^415 + x^413 + x^412 + x^411 + x^410 + x^409 + x^408 + x^404 + x^403 + x^402 + x^399 + x^398 + x^394 + x^393 + x^391 + x^390 + x^389 + x^384 + x^383 + x^381 + x^380 + x^379 + x^378 + x^375 + x^374 + x^372 + x^370 + x^369 + x^367 + x^365 + x^364 + x^363 + x^362 + x^358 + x^357 + x^355 + x^354 + x^353 + x^351 + x^349 + x^347 + x^343 + x^342 + x^338 + x^337 + x^336 + x^334 + x^332 + x^329 + x^328 + x^327 + x^326 + x^323 + x^321 + x^320 + x^319 + x^317 + x^315 + x^311 + x^308 + x^305 + x^304 + x^303 + x^300 + x^298 + x^294 + x^293 + x^292 + x^290 + x^283 + x^281 + x^280 + x^279 + x^276 + x^274 + x^273 + x^269 + x^268 + x^267 + x^266 + x^264 + x^263 + x^259 + x^256 + x^248 + x^247 + x^246 + x^245 + x^244 + x^243 + x^242 + x^241 + x^240 + x^239 + x^235 + x^234 + x^231 + x^228 + x^227 + x^226 + x^225 + x^224 + x^220 + x^219 + x^218 + x^217 + x^216 + x^213 + x^211 + x^210 + x^206 + x^203 + x^200 + x^197 + x^196 + x^195 + x^193 + x^192 + x^191 + x^185 + x^184 + x^180 + x^178 + x^176 + x^175 + x^173 + x^170 + x^169 + x^167 + x^166 + x^165 + x^164 + x^162 + x^161 + x^160 + x^159 + x^154 + x^153 + x^152 + x^147 + x^141 + x^140 + x^138 + x^135 + x^133 + x^132 + x^131 + x^129 + x^127 + x^126 + x^125 + x^119 + x^115 + x^112 + x^111 + x^108 + x^106 + x^99 + x^97 + x^95 + x^94 + x^93 + x^92 + x^91 + x^89 + x^87 + x^84 + x^82 + x^81 + x^78 + x^76 + x^74 + x^69 + x^68 + x^67 + x^65 + x^63 + x^61 + x^58 + x^57 + x^56 + x^55 + x^54 + x^53 + x^51 + x^49 + x^48 + x^47 + x^46 + x^43 + x^40 + x^39 + x^35 + x^34 + x^32 + x^30 + x^28 + x^27 + x^25 + x^24 + x^21 + x^20 + x^15 + x^14 + x^10 + 1
+
+1-12-46 393 x^928 + x^898 + x^896 + x^870 + x^866 + x^836 + x^834 + x^828 + x^826 + x^808 + x^806 + x^804 + x^802 + x^796 + x^794 + x^778 + x^774 + x^767 + x^766 + x^758 + x^756 + x^744 + x^742 + x^740 + x^738 + x^736 + x^732 + x^731 + x^730 + x^727 + x^726 + x^718 + x^712 + x^710 + x^708 + x^707 + x^706 + x^704 + x^703 + x^701 + x^700 + x^699 + x^698 + x^697 + x^696 + x^695 + x^692 + x^686 + x^685 + x^680 + x^676 + x^672 + x^669 + x^668 + x^665 + x^664 + x^662 + x^661 + x^657 + x^656 + x^655 + x^653 + x^647 + x^646 + x^643 + x^640 + x^639 + x^638 + x^635 + x^628 + x^626 + x^623 + x^622 + x^621 + x^615 + x^612 + x^610 + x^609 + x^608 + x^607 + x^605 + x^604 + x^603 + x^602 + x^600 + x^599 + x^598 + x^597 + x^590 + x^589 + x^587 + x^586 + x^584 + x^583 + x^582 + x^581 + x^579 + x^578 + x^577 + x^576 + x^574 + x^573 + x^571 + x^567 + x^563 + x^561 + x^560 + x^559 + x^556 + x^554 + x^550 + x^548 + x^545 + x^544 + x^542 + x^535 + x^530 + x^529 + x^528 + x^526 + x^524 + x^522 + x^521 + x^519 + x^517 + x^516 + x^515 + x^512 + x^508 + x^507 + x^506 + x^505 + x^504 + x^499 + x^498 + x^497 + x^496 + x^495 + x^494 + x^489 + x^488 + x^487 + x^486 + x^484 + x^483 + x^481 + x^477 + x^476 + x^475 + x^474 + x^473 + x^471 + x^469 + x^466 + x^465 + x^464 + x^461 + x^460 + x^459 + x^457 + x^455 + x^452 + x^451 + x^449 + x^448 + x^447 + x^446 + x^445 + x^443 + x^442 + x^440 + x^439 + x^438 + x^433 + x^427 + x^425 + x^424 + x^422 + x^421 + x^419 + x^416 + x^415 + x^414 + x^413 + x^412 + x^408 + x^405 + x^404 + x^403 + x^402 + x^399 + x^398 + x^397 + x^396 + x^394 + x^393 + x^392 + x^391 + x^389 + x^388 + x^387 + x^386 + x^384 + x^381 + x^380 + x^376 + x^375 + x^374 + x^373 + x^366 + x^363 + x^362 + x^359 + x^358 + x^357 + x^356 + x^355 + x^353 + x^352 + x^351 + x^347 + x^344 + x^343 + x^342 + x^341 + x^339 + x^337 + x^336 + x^333 + x^331 + x^329 + x^328 + x^327 + x^326 + x^325 + x^321 + x^320 + x^317 + x^316 + x^315 + x^312 + x^311 + x^310 + x^307 + x^306 + x^303 + x^300 + x^298 + x^296 + x^295 + x^292 + x^291 + x^290 + x^287 + x^283 + x^279 + x^278 + x^277 + x^276 + x^273 + x^272 + x^271 + x^270 + x^269 + x^263 + x^262 + x^257 + x^256 + x^255 + x^254 + x^252 + x^249 + x^247 + x^245 + x^242 + x^241 + x^240 + x^235 + x^234 + x^233 + x^232 + x^231 + x^230 + x^229 + x^227 + x^225 + x^224 + x^223 + x^222 + x^219 + x^218 + x^217 + x^216 + x^215 + x^214 + x^213 + x^211 + x^206 + x^205 + x^203 + x^200 + x^199 + x^196 + x^194 + x^191 + x^186 + x^185 + x^183 + x^180 + x^179 + x^177 + x^176 + x^175 + x^174 + x^172 + x^171 + x^170 + x^169 + x^167 + x^160 + x^159 + x^158 + x^157 + x^156 + x^155 + x^154 + x^152 + x^146 + x^145 + x^144 + x^143 + x^142 + x^141 + x^139 + x^138 + x^137 + x^134 + x^133 + x^129 + x^126 + x^125 + x^124 + x^122 + x^121 + x^119 + x^118 + x^117 + x^113 + x^111 + x^110 + x^109 + x^108 + x^99 + x^98 + x^97 + x^95 + x^93 + x^92 + x^90 + x^85 + x^78 + x^76 + x^75 + x^70 + x^69 + x^65 + x^64 + x^63 + x^62 + x^59 + x^56 + x^54 + x^53 + x^51 + x^50 + x^49 + x^45 + x^44 + x^42 + x^41 + x^39 + x^36 + x^35 + x^34 + x^32 + x^31 + x^30 + x^23 + x^20 + x^16 + x^13 + x^12 + 1
+
+21-29-14 393 x^928 + x^898 + x^885 + x^870 + x^858 + x^856 + x^855 + x^831 + x^829 + x^828 + x^826 + x^815 + x^813 + x^812 + x^808 + x^804 + x^802 + x^801 + x^799 + x^798 + x^796 + x^788 + x^785 + x^778 + x^777 + x^775 + x^774 + x^772 + x^769 + x^768 + x^766 + x^765 + x^758 + x^752 + x^748 + x^747 + x^742 + x^741 + x^739 + x^738 + x^736 + x^735 + x^732 + x^728 + x^726 + x^725 + x^721 + x^718 + x^717 + x^714 + x^712 + x^709 + x^708 + x^706 + x^705 + x^702 + x^701 + x^699 + x^698 + x^694 + x^691 + x^687 + x^685 + x^684 + x^682 + x^681 + x^680 + x^679 + x^676 + x^675 + x^674 + x^671 + x^667 + x^664 + x^658 + x^657 + x^655 + x^653 + x^652 + x^650 + x^649 + x^648 + x^647 + x^646 + x^644 + x^641 + x^640 + x^637 + x^635 + x^632 + x^627 + x^625 + x^623 + x^622 + x^619 + x^618 + x^617 + x^613 + x^610 + x^608 + x^601 + x^595 + x^593 + x^592 + x^586 + x^585 + x^583 + x^582 + x^577 + x^572 + x^571 + x^570 + x^568 + x^565 + x^563 + x^561 + x^559 + x^557 + x^555 + x^553 + x^550 + x^548 + x^545 + x^544 + x^538 + x^537 + x^534 + x^532 + x^529 + x^526 + x^525 + x^521 + x^520 + x^518 + x^512 + x^511 + x^510 + x^508 + x^507 + x^503 + x^501 + x^500 + x^499 + x^498 + x^497 + x^496 + x^494 + x^489 + x^486 + x^485 + x^481 + x^480 + x^477 + x^476 + x^475 + x^466 + x^464 + x^462 + x^461 + x^460 + x^459 + x^458 + x^454 + x^452 + x^451 + x^449 + x^447 + x^446 + x^444 + x^441 + x^440 + x^439 + x^433 + x^431 + x^430 + x^429 + x^427 + x^425 + x^424 + x^422 + x^416 + x^414 + x^412 + x^408 + x^406 + x^403 + x^402 + x^401 + x^399 + x^398 + x^395 + x^393 + x^390 + x^389 + x^387 + x^386 + x^385 + x^384 + x^383 + x^381 + x^380 + x^378 + x^375 + x^374 + x^372 + x^371 + x^370 + x^368 + x^367 + x^362 + x^361 + x^358 + x^356 + x^354 + x^353 + x^351 + x^350 + x^347 + x^346 + x^343 + x^340 + x^339 + x^337 + x^335 + x^331 + x^330 + x^329 + x^328 + x^326 + x^325 + x^323 + x^322 + x^319 + x^318 + x^316 + x^315 + x^311 + x^310 + x^309 + x^308 + x^306 + x^304 + x^303 + x^298 + x^296 + x^295 + x^294 + x^292 + x^291 + x^290 + x^289 + x^287 + x^284 + x^281 + x^280 + x^276 + x^274 + x^272 + x^271 + x^270 + x^268 + x^267 + x^259 + x^258 + x^257 + x^256 + x^255 + x^254 + x^249 + x^248 + x^247 + x^246 + x^244 + x^243 + x^241 + x^240 + x^236 + x^234 + x^233 + x^232 + x^229 + x^224 + x^221 + x^220 + x^217 + x^216 + x^215 + x^213 + x^211 + x^210 + x^208 + x^207 + x^200 + x^199 + x^198 + x^197 + x^196 + x^195 + x^193 + x^192 + x^191 + x^190 + x^185 + x^184 + x^183 + x^181 + x^179 + x^176 + x^173 + x^170 + x^169 + x^168 + x^164 + x^162 + x^160 + x^157 + x^155 + x^154 + x^152 + x^151 + x^150 + x^149 + x^146 + x^144 + x^143 + x^142 + x^140 + x^136 + x^134 + x^132 + x^130 + x^129 + x^128 + x^126 + x^123 + x^120 + x^117 + x^112 + x^111 + x^108 + x^107 + x^105 + x^103 + x^100 + x^99 + x^96 + x^95 + x^91 + x^90 + x^89 + x^87 + x^86 + x^84 + x^83 + x^81 + x^79 + x^78 + x^76 + x^69 + x^68 + x^67 + x^66 + x^62 + x^61 + x^57 + x^56 + x^55 + x^53 + x^52 + x^51 + x^49 + x^48 + x^46 + x^43 + x^40 + x^38 + x^37 + x^36 + x^35 + x^34 + x^33 + x^31 + x^30 + x^29 + x^28 + x^27 + x^26 + x^24 + x^21 + x^20 + x^17 + x^13 + 1
+
+37-29-44 393 x^928 + x^898 + x^885 + x^870 + x^858 + x^856 + x^855 + x^831 + x^829 + x^828 + x^826 + x^815 + x^813 + x^812 + x^808 + x^804 + x^802 + x^801 + x^799 + x^798 + x^796 + x^788 + x^785 + x^778 + x^777 + x^775 + x^774 + x^772 + x^769 + x^768 + x^766 + x^765 + x^758 + x^752 + x^748 + x^747 + x^742 + x^741 + x^739 + x^738 + x^736 + x^735 + x^732 + x^728 + x^726 + x^725 + x^721 + x^718 + x^717 + x^714 + x^712 + x^709 + x^708 + x^706 + x^705 + x^702 + x^701 + x^699 + x^698 + x^694 + x^691 + x^687 + x^685 + x^684 + x^682 + x^681 + x^680 + x^679 + x^676 + x^675 + x^674 + x^671 + x^667 + x^664 + x^658 + x^657 + x^655 + x^653 + x^652 + x^650 + x^649 + x^648 + x^647 + x^646 + x^644 + x^641 + x^640 + x^637 + x^635 + x^632 + x^627 + x^625 + x^623 + x^622 + x^619 + x^618 + x^617 + x^613 + x^610 + x^608 + x^601 + x^595 + x^593 + x^592 + x^586 + x^585 + x^583 + x^582 + x^577 + x^572 + x^571 + x^570 + x^568 + x^565 + x^563 + x^561 + x^559 + x^557 + x^555 + x^553 + x^550 + x^548 + x^545 + x^544 + x^538 + x^537 + x^534 + x^532 + x^529 + x^526 + x^525 + x^521 + x^520 + x^518 + x^512 + x^511 + x^510 + x^508 + x^507 + x^503 + x^501 + x^500 + x^499 + x^498 + x^497 + x^496 + x^494 + x^489 + x^486 + x^485 + x^481 + x^480 + x^477 + x^476 + x^475 + x^466 + x^464 + x^462 + x^461 + x^460 + x^459 + x^458 + x^454 + x^452 + x^451 + x^449 + x^447 + x^446 + x^444 + x^441 + x^440 + x^439 + x^433 + x^431 + x^430 + x^429 + x^427 + x^425 + x^424 + x^422 + x^416 + x^414 + x^412 + x^408 + x^406 + x^403 + x^402 + x^401 + x^399 + x^398 + x^395 + x^393 + x^390 + x^389 + x^387 + x^386 + x^385 + x^384 + x^383 + x^381 + x^380 + x^378 + x^375 + x^374 + x^372 + x^371 + x^370 + x^368 + x^367 + x^362 + x^361 + x^358 + x^356 + x^354 + x^353 + x^351 + x^350 + x^347 + x^346 + x^343 + x^340 + x^339 + x^337 + x^335 + x^331 + x^330 + x^329 + x^328 + x^326 + x^325 + x^323 + x^322 + x^319 + x^318 + x^316 + x^315 + x^311 + x^310 + x^309 + x^308 + x^306 + x^304 + x^303 + x^298 + x^296 + x^295 + x^294 + x^292 + x^291 + x^290 + x^289 + x^287 + x^284 + x^281 + x^280 + x^276 + x^274 + x^272 + x^271 + x^270 + x^268 + x^267 + x^259 + x^258 + x^257 + x^256 + x^255 + x^254 + x^249 + x^248 + x^247 + x^246 + x^244 + x^243 + x^241 + x^240 + x^236 + x^234 + x^233 + x^232 + x^229 + x^224 + x^221 + x^220 + x^217 + x^216 + x^215 + x^213 + x^211 + x^210 + x^208 + x^207 + x^200 + x^199 + x^198 + x^197 + x^196 + x^195 + x^193 + x^192 + x^191 + x^190 + x^185 + x^184 + x^183 + x^181 + x^179 + x^176 + x^173 + x^170 + x^169 + x^168 + x^164 + x^162 + x^160 + x^157 + x^155 + x^154 + x^152 + x^151 + x^150 + x^149 + x^146 + x^144 + x^143 + x^142 + x^140 + x^136 + x^134 + x^132 + x^130 + x^129 + x^128 + x^126 + x^123 + x^120 + x^117 + x^112 + x^111 + x^108 + x^107 + x^105 + x^103 + x^100 + x^99 + x^96 + x^95 + x^91 + x^90 + x^89 + x^87 + x^86 + x^84 + x^83 + x^81 + x^79 + x^78 + x^76 + x^69 + x^68 + x^67 + x^66 + x^62 + x^61 + x^57 + x^56 + x^55 + x^53 + x^52 + x^51 + x^49 + x^48 + x^46 + x^43 + x^40 + x^38 + x^37 + x^36 + x^35 + x^34 + x^33 + x^31 + x^30 + x^29 + x^28 + x^27 + x^26 + x^24 + x^21 + x^20 + x^17 + x^13 + 1
+
+7-48-42 393 x^928 + x^898 + x^892 + x^870 + x^862 + x^843 + x^820 + x^813 + x^808 + x^800 + x^794 + x^784 + x^783 + x^780 + x^778 + x^774 + x^771 + x^770 + x^767 + x^760 + x^757 + x^753 + x^750 + x^748 + x^743 + x^741 + x^740 + x^737 + x^731 + x^727 + x^724 + x^723 + x^718 + x^713 + x^707 + x^705 + x^704 + x^701 + x^700 + x^697 + x^695 + x^693 + x^688 + x^684 + x^683 + x^682 + x^681 + x^678 + x^677 + x^674 + x^671 + x^669 + x^667 + x^664 + x^663 + x^660 + x^653 + x^652 + x^651 + x^650 + x^649 + x^645 + x^644 + x^641 + x^639 + x^638 + x^637 + x^634 + x^633 + x^630 + x^628 + x^625 + x^623 + x^621 + x^620 + x^619 + x^615 + x^612 + x^611 + x^608 + x^607 + x^605 + x^604 + x^603 + x^599 + x^595 + x^593 + x^585 + x^584 + x^581 + x^580 + x^578 + x^577 + x^575 + x^573 + x^572 + x^569 + x^568 + x^565 + x^564 + x^563 + x^561 + x^558 + x^557 + x^551 + x^550 + x^548 + x^547 + x^544 + x^538 + x^537 + x^534 + x^533 + x^532 + x^530 + x^529 + x^524 + x^522 + x^521 + x^519 + x^518 + x^516 + x^515 + x^514 + x^513 + x^512 + x^510 + x^508 + x^506 + x^505 + x^502 + x^501 + x^500 + x^499 + x^496 + x^493 + x^492 + x^491 + x^488 + x^487 + x^483 + x^482 + x^481 + x^479 + x^478 + x^476 + x^475 + x^474 + x^473 + x^472 + x^471 + x^470 + x^469 + x^467 + x^463 + x^460 + x^458 + x^453 + x^452 + x^451 + x^447 + x^446 + x^445 + x^439 + x^435 + x^434 + x^433 + x^432 + x^431 + x^430 + x^428 + x^427 + x^425 + x^421 + x^420 + x^419 + x^417 + x^415 + x^413 + x^412 + x^410 + x^407 + x^406 + x^405 + x^404 + x^402 + x^400 + x^397 + x^395 + x^394 + x^393 + x^392 + x^391 + x^390 + x^388 + x^385 + x^381 + x^378 + x^377 + x^376 + x^374 + x^373 + x^370 + x^369 + x^368 + x^366 + x^365 + x^364 + x^363 + x^361 + x^358 + x^356 + x^355 + x^354 + x^351 + x^350 + x^348 + x^347 + x^344 + x^341 + x^340 + x^337 + x^335 + x^334 + x^329 + x^326 + x^325 + x^324 + x^322 + x^321 + x^319 + x^318 + x^314 + x^312 + x^311 + x^310 + x^309 + x^308 + x^307 + x^303 + x^302 + x^301 + x^298 + x^293 + x^292 + x^291 + x^288 + x^281 + x^280 + x^279 + x^278 + x^275 + x^271 + x^270 + x^267 + x^265 + x^264 + x^263 + x^262 + x^261 + x^260 + x^259 + x^258 + x^257 + x^256 + x^253 + x^252 + x^251 + x^250 + x^249 + x^248 + x^247 + x^244 + x^243 + x^242 + x^240 + x^237 + x^236 + x^233 + x^227 + x^226 + x^224 + x^222 + x^221 + x^220 + x^219 + x^218 + x^217 + x^216 + x^213 + x^212 + x^210 + x^208 + x^207 + x^206 + x^205 + x^202 + x^201 + x^200 + x^197 + x^195 + x^194 + x^193 + x^192 + x^191 + x^190 + x^189 + x^186 + x^184 + x^183 + x^182 + x^181 + x^178 + x^177 + x^176 + x^170 + x^168 + x^167 + x^166 + x^162 + x^159 + x^157 + x^149 + x^148 + x^147 + x^143 + x^141 + x^139 + x^138 + x^136 + x^135 + x^131 + x^127 + x^121 + x^119 + x^117 + x^114 + x^110 + x^109 + x^107 + x^103 + x^99 + x^98 + x^96 + x^95 + x^94 + x^92 + x^90 + x^89 + x^88 + x^87 + x^86 + x^85 + x^84 + x^82 + x^80 + x^79 + x^78 + x^77 + x^76 + x^74 + x^71 + x^69 + x^68 + x^66 + x^64 + x^62 + x^61 + x^58 + x^57 + x^53 + x^50 + x^46 + x^44 + x^43 + x^42 + x^41 + x^40 + x^37 + x^35 + x^34 + x^32 + x^31 + x^29 + x^27 + x^26 + x^25 + x^22 + x^20 + x^16 + x^12 + x^10 + 1
+
+57-51-22 397 x^928 + x^898 + x^895 + x^870 + x^866 + x^865 + x^862 + x^860 + x^857 + x^835 + x^833 + x^832 + x^828 + x^822 + x^819 + x^810 + x^808 + x^805 + x^797 + x^796 + x^791 + x^790 + x^789 + x^786 + x^784 + x^782 + x^781 + x^778 + x^777 + x^773 + x^767 + x^766 + x^762 + x^757 + x^752 + x^743 + x^742 + x^737 + x^734 + x^717 + x^715 + x^713 + x^708 + x^707 + x^706 + x^705 + x^703 + x^702 + x^701 + x^698 + x^696 + x^690 + x^688 + x^685 + x^683 + x^682 + x^680 + x^677 + x^673 + x^671 + x^668 + x^667 + x^666 + x^663 + x^662 + x^661 + x^656 + x^654 + x^653 + x^649 + x^647 + x^646 + x^645 + x^643 + x^637 + x^635 + x^632 + x^630 + x^629 + x^627 + x^626 + x^625 + x^624 + x^622 + x^619 + x^613 + x^610 + x^608 + x^602 + x^597 + x^594 + x^593 + x^591 + x^590 + x^587 + x^586 + x^584 + x^583 + x^582 + x^580 + x^577 + x^575 + x^574 + x^573 + x^570 + x^569 + x^568 + x^562 + x^556 + x^553 + x^552 + x^551 + x^550 + x^547 + x^546 + x^545 + x^543 + x^541 + x^539 + x^538 + x^535 + x^534 + x^533 + x^528 + x^527 + x^526 + x^524 + x^522 + x^521 + x^515 + x^512 + x^509 + x^505 + x^503 + x^502 + x^501 + x^500 + x^499 + x^498 + x^497 + x^493 + x^491 + x^483 + x^480 + x^477 + x^474 + x^473 + x^472 + x^471 + x^470 + x^468 + x^467 + x^463 + x^459 + x^458 + x^457 + x^455 + x^453 + x^452 + x^451 + x^448 + x^447 + x^446 + x^445 + x^444 + x^443 + x^440 + x^439 + x^436 + x^435 + x^434 + x^432 + x^430 + x^429 + x^428 + x^427 + x^426 + x^423 + x^422 + x^421 + x^420 + x^417 + x^416 + x^415 + x^414 + x^413 + x^411 + x^410 + x^407 + x^406 + x^403 + x^401 + x^400 + x^391 + x^390 + x^387 + x^386 + x^385 + x^381 + x^380 + x^379 + x^377 + x^374 + x^373 + x^370 + x^369 + x^362 + x^359 + x^357 + x^356 + x^355 + x^354 + x^349 + x^346 + x^345 + x^344 + x^343 + x^340 + x^339 + x^338 + x^337 + x^336 + x^334 + x^331 + x^330 + x^328 + x^323 + x^322 + x^321 + x^319 + x^318 + x^317 + x^316 + x^314 + x^313 + x^312 + x^311 + x^310 + x^305 + x^303 + x^299 + x^295 + x^294 + x^293 + x^290 + x^289 + x^286 + x^285 + x^284 + x^281 + x^280 + x^278 + x^275 + x^272 + x^271 + x^269 + x^267 + x^266 + x^263 + x^262 + x^261 + x^260 + x^258 + x^257 + x^256 + x^255 + x^254 + x^253 + x^252 + x^251 + x^247 + x^246 + x^241 + x^240 + x^239 + x^238 + x^236 + x^233 + x^232 + x^230 + x^228 + x^224 + x^223 + x^220 + x^216 + x^215 + x^213 + x^212 + x^211 + x^208 + x^206 + x^205 + x^204 + x^201 + x^199 + x^197 + x^195 + x^194 + x^193 + x^191 + x^189 + x^188 + x^187 + x^186 + x^185 + x^184 + x^182 + x^179 + x^178 + x^176 + x^172 + x^171 + x^170 + x^169 + x^168 + x^167 + x^166 + x^163 + x^162 + x^161 + x^160 + x^157 + x^156 + x^155 + x^153 + x^152 + x^148 + x^145 + x^142 + x^140 + x^139 + x^137 + x^134 + x^133 + x^131 + x^123 + x^119 + x^118 + x^114 + x^112 + x^111 + x^110 + x^108 + x^107 + x^105 + x^104 + x^102 + x^99 + x^98 + x^95 + x^94 + x^93 + x^89 + x^88 + x^86 + x^84 + x^82 + x^80 + x^78 + x^76 + x^73 + x^71 + x^70 + x^68 + x^67 + x^66 + x^64 + x^62 + x^60 + x^59 + x^57 + x^53 + x^52 + x^49 + x^48 + x^47 + x^46 + x^40 + x^37 + x^36 + x^35 + x^34 + x^32 + x^31 + x^28 + x^26 + x^25 + x^24 + x^22 + x^20 + x^19 + x^18 + x^15 + x^10 + x^8 + x^5 + 1
+
+41-40-20 399 x^928 + x^898 + x^870 + x^846 + x^844 + x^821 + x^820 + x^816 + x^814 + x^808 + x^804 + x^801 + x^800 + x^798 + x^795 + x^778 + x^771 + x^770 + x^769 + x^768 + x^765 + x^760 + x^749 + x^748 + x^744 + x^743 + x^741 + x^738 + x^734 + x^729 + x^726 + x^719 + x^717 + x^716 + x^715 + x^714 + x^713 + x^712 + x^711 + x^710 + x^709 + x^706 + x^704 + x^703 + x^702 + x^701 + x^694 + x^693 + x^691 + x^690 + x^685 + x^684 + x^682 + x^681 + x^680 + x^678 + x^677 + x^676 + x^675 + x^674 + x^673 + x^671 + x^669 + x^667 + x^665 + x^661 + x^660 + x^659 + x^658 + x^656 + x^652 + x^651 + x^649 + x^648 + x^643 + x^642 + x^639 + x^637 + x^634 + x^631 + x^629 + x^628 + x^624 + x^620 + x^619 + x^618 + x^617 + x^616 + x^615 + x^614 + x^613 + x^611 + x^610 + x^605 + x^604 + x^603 + x^601 + x^599 + x^598 + x^595 + x^594 + x^593 + x^590 + x^589 + x^585 + x^584 + x^583 + x^579 + x^577 + x^575 + x^573 + x^572 + x^571 + x^570 + x^569 + x^566 + x^564 + x^562 + x^561 + x^560 + x^557 + x^555 + x^554 + x^553 + x^552 + x^551 + x^550 + x^549 + x^547 + x^545 + x^542 + x^540 + x^539 + x^538 + x^537 + x^536 + x^535 + x^533 + x^532 + x^530 + x^529 + x^524 + x^518 + x^516 + x^514 + x^513 + x^512 + x^510 + x^509 + x^504 + x^503 + x^501 + x^493 + x^490 + x^489 + x^487 + x^486 + x^485 + x^484 + x^481 + x^479 + x^478 + x^475 + x^473 + x^471 + x^470 + x^468 + x^467 + x^466 + x^462 + x^460 + x^455 + x^454 + x^451 + x^450 + x^449 + x^447 + x^446 + x^445 + x^444 + x^443 + x^442 + x^441 + x^440 + x^439 + x^438 + x^436 + x^430 + x^429 + x^424 + x^423 + x^420 + x^419 + x^418 + x^415 + x^414 + x^413 + x^410 + x^409 + x^408 + x^407 + x^406 + x^405 + x^403 + x^402 + x^400 + x^398 + x^397 + x^396 + x^395 + x^394 + x^392 + x^391 + x^389 + x^387 + x^386 + x^385 + x^383 + x^382 + x^381 + x^379 + x^375 + x^374 + x^369 + x^367 + x^366 + x^365 + x^363 + x^360 + x^359 + x^358 + x^357 + x^355 + x^354 + x^351 + x^339 + x^338 + x^337 + x^336 + x^335 + x^334 + x^332 + x^330 + x^329 + x^323 + x^320 + x^317 + x^315 + x^312 + x^311 + x^309 + x^305 + x^302 + x^301 + x^300 + x^299 + x^298 + x^297 + x^296 + x^295 + x^292 + x^291 + x^288 + x^286 + x^285 + x^284 + x^283 + x^282 + x^280 + x^279 + x^278 + x^273 + x^268 + x^267 + x^264 + x^263 + x^258 + x^257 + x^256 + x^255 + x^254 + x^253 + x^250 + x^249 + x^248 + x^244 + x^243 + x^242 + x^238 + x^237 + x^236 + x^234 + x^233 + x^231 + x^230 + x^222 + x^218 + x^215 + x^214 + x^211 + x^208 + x^206 + x^205 + x^201 + x^200 + x^198 + x^197 + x^195 + x^194 + x^193 + x^191 + x^189 + x^185 + x^182 + x^179 + x^176 + x^174 + x^173 + x^164 + x^163 + x^162 + x^159 + x^158 + x^156 + x^155 + x^152 + x^150 + x^148 + x^142 + x^140 + x^139 + x^138 + x^137 + x^135 + x^134 + x^133 + x^132 + x^131 + x^128 + x^124 + x^122 + x^121 + x^120 + x^119 + x^117 + x^116 + x^114 + x^111 + x^110 + x^108 + x^107 + x^105 + x^104 + x^103 + x^101 + x^95 + x^94 + x^93 + x^91 + x^89 + x^88 + x^87 + x^84 + x^83 + x^82 + x^81 + x^80 + x^79 + x^78 + x^77 + x^76 + x^74 + x^73 + x^72 + x^66 + x^65 + x^64 + x^59 + x^57 + x^56 + x^53 + x^49 + x^47 + x^44 + x^43 + x^39 + x^38 + x^37 + x^34 + x^33 + x^32 + x^31 + x^28 + x^23 + x^22 + x^19 + x^12 + x^8 + 1
+
+55-27-24 399 x^928 + x^898 + x^864 + x^847 + x^846 + x^834 + x^824 + x^818 + x^817 + x^816 + x^812 + x^810 + x^808 + x^806 + x^801 + x^800 + x^795 + x^794 + x^788 + x^783 + x^781 + x^777 + x^776 + x^775 + x^771 + x^765 + x^764 + x^753 + x^750 + x^749 + x^747 + x^746 + x^745 + x^743 + x^742 + x^741 + x^737 + x^734 + x^731 + x^728 + x^726 + x^725 + x^724 + x^721 + x^719 + x^717 + x^716 + x^714 + x^712 + x^706 + x^704 + x^703 + x^702 + x^701 + x^699 + x^698 + x^697 + x^695 + x^694 + x^691 + x^690 + x^688 + x^687 + x^684 + x^683 + x^681 + x^680 + x^673 + x^672 + x^670 + x^667 + x^666 + x^664 + x^663 + x^661 + x^659 + x^657 + x^655 + x^650 + x^649 + x^647 + x^640 + x^639 + x^637 + x^636 + x^634 + x^630 + x^626 + x^625 + x^623 + x^622 + x^620 + x^618 + x^617 + x^615 + x^612 + x^611 + x^609 + x^608 + x^607 + x^605 + x^604 + x^602 + x^600 + x^599 + x^596 + x^594 + x^592 + x^590 + x^587 + x^581 + x^578 + x^576 + x^575 + x^574 + x^570 + x^567 + x^566 + x^565 + x^564 + x^563 + x^561 + x^560 + x^555 + x^554 + x^553 + x^552 + x^551 + x^550 + x^549 + x^548 + x^543 + x^537 + x^536 + x^533 + x^532 + x^531 + x^529 + x^528 + x^527 + x^525 + x^524 + x^523 + x^522 + x^519 + x^518 + x^516 + x^515 + x^514 + x^513 + x^512 + x^511 + x^509 + x^507 + x^505 + x^500 + x^498 + x^497 + x^496 + x^494 + x^489 + x^486 + x^481 + x^480 + x^479 + x^476 + x^471 + x^469 + x^467 + x^466 + x^463 + x^459 + x^455 + x^451 + x^450 + x^449 + x^448 + x^447 + x^445 + x^444 + x^441 + x^440 + x^432 + x^430 + x^429 + x^428 + x^426 + x^424 + x^420 + x^418 + x^416 + x^415 + x^413 + x^411 + x^408 + x^406 + x^405 + x^404 + x^400 + x^398 + x^392 + x^390 + x^387 + x^386 + x^382 + x^379 + x^378 + x^377 + x^376 + x^374 + x^373 + x^371 + x^370 + x^368 + x^367 + x^365 + x^364 + x^363 + x^362 + x^360 + x^358 + x^351 + x^350 + x^344 + x^343 + x^341 + x^340 + x^339 + x^338 + x^337 + x^332 + x^331 + x^329 + x^327 + x^323 + x^321 + x^320 + x^318 + x^317 + x^314 + x^313 + x^312 + x^311 + x^309 + x^308 + x^306 + x^304 + x^301 + x^300 + x^299 + x^296 + x^295 + x^294 + x^291 + x^290 + x^287 + x^286 + x^285 + x^280 + x^275 + x^274 + x^271 + x^270 + x^268 + x^264 + x^263 + x^258 + x^257 + x^256 + x^254 + x^252 + x^249 + x^248 + x^246 + x^245 + x^242 + x^241 + x^239 + x^238 + x^236 + x^233 + x^231 + x^228 + x^226 + x^225 + x^222 + x^219 + x^218 + x^217 + x^216 + x^215 + x^213 + x^210 + x^209 + x^207 + x^205 + x^203 + x^202 + x^198 + x^197 + x^196 + x^193 + x^192 + x^189 + x^188 + x^187 + x^184 + x^183 + x^182 + x^181 + x^179 + x^178 + x^177 + x^175 + x^172 + x^171 + x^170 + x^169 + x^164 + x^162 + x^161 + x^160 + x^159 + x^155 + x^154 + x^152 + x^151 + x^148 + x^147 + x^143 + x^140 + x^139 + x^137 + x^134 + x^133 + x^132 + x^131 + x^126 + x^125 + x^120 + x^119 + x^118 + x^117 + x^113 + x^111 + x^110 + x^108 + x^104 + x^102 + x^101 + x^100 + x^97 + x^96 + x^90 + x^89 + x^85 + x^82 + x^81 + x^77 + x^76 + x^73 + x^69 + x^68 + x^67 + x^65 + x^64 + x^63 + x^62 + x^61 + x^55 + x^54 + x^53 + x^52 + x^49 + x^47 + x^46 + x^40 + x^39 + x^37 + x^36 + x^35 + x^34 + x^33 + x^32 + x^31 + x^29 + x^26 + x^25 + x^24 + x^23 + x^22 + x^19 + x^17 + x^16 + x^12 + x^9 + x^8 + x^5 + 1
+
+39-32-32 401 x^928 + x^898 + x^870 + x^867 + x^842 + x^837 + x^836 + x^832 + x^807 + x^806 + x^805 + x^802 + x^801 + x^780 + x^778 + x^775 + x^773 + x^771 + x^770 + x^768 + x^766 + x^758 + x^752 + x^749 + x^747 + x^740 + x^730 + x^724 + x^721 + x^719 + x^717 + x^716 + x^715 + x^714 + x^713 + x^711 + x^709 + x^708 + x^707 + x^704 + x^702 + x^700 + x^696 + x^693 + x^691 + x^689 + x^687 + x^686 + x^685 + x^683 + x^682 + x^680 + x^679 + x^677 + x^676 + x^674 + x^670 + x^669 + x^668 + x^665 + x^663 + x^661 + x^660 + x^659 + x^655 + x^653 + x^652 + x^651 + x^648 + x^647 + x^646 + x^645 + x^644 + x^642 + x^641 + x^640 + x^639 + x^638 + x^637 + x^635 + x^634 + x^633 + x^632 + x^631 + x^630 + x^625 + x^624 + x^620 + x^618 + x^615 + x^613 + x^611 + x^606 + x^605 + x^604 + x^602 + x^599 + x^597 + x^596 + x^593 + x^592 + x^591 + x^590 + x^589 + x^585 + x^584 + x^583 + x^580 + x^578 + x^577 + x^576 + x^575 + x^574 + x^572 + x^571 + x^570 + x^568 + x^567 + x^566 + x^563 + x^562 + x^560 + x^556 + x^554 + x^552 + x^549 + x^548 + x^547 + x^546 + x^544 + x^538 + x^536 + x^535 + x^534 + x^533 + x^530 + x^529 + x^528 + x^527 + x^526 + x^525 + x^524 + x^521 + x^519 + x^517 + x^516 + x^514 + x^513 + x^512 + x^510 + x^509 + x^507 + x^506 + x^504 + x^502 + x^500 + x^499 + x^498 + x^497 + x^493 + x^492 + x^490 + x^489 + x^485 + x^484 + x^481 + x^476 + x^475 + x^473 + x^467 + x^463 + x^462 + x^461 + x^459 + x^456 + x^453 + x^450 + x^449 + x^448 + x^445 + x^443 + x^442 + x^440 + x^438 + x^436 + x^433 + x^432 + x^431 + x^430 + x^429 + x^427 + x^421 + x^420 + x^419 + x^416 + x^415 + x^414 + x^413 + x^411 + x^410 + x^408 + x^407 + x^406 + x^405 + x^403 + x^400 + x^398 + x^397 + x^396 + x^394 + x^390 + x^389 + x^388 + x^385 + x^384 + x^383 + x^379 + x^376 + x^374 + x^373 + x^372 + x^370 + x^369 + x^368 + x^364 + x^362 + x^358 + x^355 + x^354 + x^353 + x^351 + x^348 + x^347 + x^344 + x^343 + x^339 + x^337 + x^336 + x^334 + x^333 + x^329 + x^328 + x^323 + x^321 + x^320 + x^319 + x^318 + x^317 + x^315 + x^314 + x^311 + x^309 + x^307 + x^306 + x^304 + x^302 + x^300 + x^297 + x^295 + x^294 + x^291 + x^289 + x^287 + x^285 + x^284 + x^283 + x^282 + x^281 + x^280 + x^278 + x^277 + x^276 + x^270 + x^269 + x^268 + x^267 + x^263 + x^261 + x^259 + x^257 + x^255 + x^253 + x^252 + x^250 + x^248 + x^247 + x^245 + x^244 + x^242 + x^241 + x^240 + x^238 + x^234 + x^233 + x^230 + x^227 + x^226 + x^224 + x^220 + x^219 + x^217 + x^216 + x^215 + x^209 + x^208 + x^207 + x^206 + x^205 + x^204 + x^203 + x^201 + x^199 + x^198 + x^197 + x^196 + x^193 + x^191 + x^187 + x^184 + x^183 + x^182 + x^173 + x^172 + x^169 + x^167 + x^166 + x^165 + x^162 + x^161 + x^160 + x^158 + x^157 + x^156 + x^155 + x^154 + x^152 + x^151 + x^149 + x^147 + x^141 + x^138 + x^137 + x^136 + x^135 + x^134 + x^131 + x^129 + x^126 + x^125 + x^122 + x^121 + x^117 + x^116 + x^113 + x^110 + x^109 + x^108 + x^104 + x^102 + x^101 + x^100 + x^98 + x^97 + x^95 + x^94 + x^87 + x^83 + x^82 + x^78 + x^77 + x^74 + x^73 + x^72 + x^70 + x^69 + x^66 + x^65 + x^62 + x^60 + x^55 + x^54 + x^52 + x^51 + x^49 + x^46 + x^45 + x^41 + x^40 + x^37 + x^33 + x^31 + x^29 + x^27 + x^26 + x^24 + x^20 + x^18 + x^17 + x^15 + x^6 + 1
+
+40-7-11 401 x^928 + x^898 + x^897 + x^882 + x^870 + x^866 + x^860 + x^854 + x^852 + x^851 + x^836 + x^832 + x^830 + x^829 + x^826 + x^824 + x^820 + x^814 + x^812 + x^811 + x^808 + x^806 + x^804 + x^800 + x^796 + x^793 + x^792 + x^790 + x^786 + x^780 + x^778 + x^777 + x^774 + x^770 + x^769 + x^767 + x^762 + x^761 + x^760 + x^756 + x^749 + x^748 + x^746 + x^742 + x^736 + x^733 + x^730 + x^728 + x^726 + x^725 + x^724 + x^723 + x^719 + x^718 + x^717 + x^716 + x^715 + x^712 + x^709 + x^708 + x^707 + x^705 + x^701 + x^700 + x^699 + x^698 + x^695 + x^689 + x^688 + x^687 + x^684 + x^683 + x^680 + x^678 + x^675 + x^672 + x^670 + x^669 + x^666 + x^664 + x^663 + x^656 + x^655 + x^654 + x^651 + x^647 + x^641 + x^639 + x^638 + x^636 + x^635 + x^633 + x^632 + x^631 + x^630 + x^629 + x^627 + x^626 + x^625 + x^623 + x^621 + x^620 + x^619 + x^617 + x^613 + x^611 + x^610 + x^609 + x^608 + x^607 + x^606 + x^604 + x^603 + x^600 + x^598 + x^596 + x^595 + x^592 + x^591 + x^590 + x^587 + x^586 + x^585 + x^584 + x^582 + x^581 + x^578 + x^577 + x^576 + x^575 + x^574 + x^569 + x^566 + x^565 + x^564 + x^560 + x^558 + x^557 + x^556 + x^554 + x^552 + x^550 + x^549 + x^548 + x^545 + x^539 + x^538 + x^536 + x^535 + x^534 + x^533 + x^532 + x^527 + x^524 + x^523 + x^522 + x^520 + x^518 + x^517 + x^514 + x^513 + x^512 + x^510 + x^507 + x^504 + x^501 + x^499 + x^497 + x^496 + x^494 + x^492 + x^491 + x^490 + x^489 + x^487 + x^485 + x^483 + x^479 + x^478 + x^477 + x^476 + x^475 + x^473 + x^472 + x^470 + x^469 + x^468 + x^465 + x^464 + x^462 + x^460 + x^457 + x^452 + x^449 + x^448 + x^447 + x^445 + x^443 + x^441 + x^440 + x^436 + x^434 + x^432 + x^430 + x^428 + x^426 + x^424 + x^420 + x^416 + x^415 + x^410 + x^408 + x^407 + x^406 + x^404 + x^397 + x^395 + x^394 + x^390 + x^389 + x^387 + x^384 + x^382 + x^380 + x^374 + x^370 + x^368 + x^366 + x^365 + x^364 + x^362 + x^360 + x^359 + x^358 + x^356 + x^352 + x^350 + x^349 + x^347 + x^346 + x^344 + x^342 + x^341 + x^337 + x^336 + x^332 + x^331 + x^327 + x^325 + x^323 + x^322 + x^320 + x^317 + x^316 + x^315 + x^314 + x^312 + x^309 + x^307 + x^306 + x^305 + x^304 + x^303 + x^301 + x^300 + x^298 + x^296 + x^294 + x^293 + x^290 + x^289 + x^287 + x^285 + x^282 + x^281 + x^279 + x^277 + x^273 + x^265 + x^264 + x^259 + x^258 + x^257 + x^255 + x^254 + x^253 + x^251 + x^250 + x^249 + x^248 + x^247 + x^246 + x^244 + x^237 + x^235 + x^233 + x^232 + x^231 + x^230 + x^229 + x^228 + x^227 + x^225 + x^221 + x^215 + x^214 + x^211 + x^208 + x^206 + x^204 + x^200 + x^199 + x^198 + x^196 + x^192 + x^188 + x^186 + x^185 + x^184 + x^183 + x^181 + x^179 + x^176 + x^175 + x^173 + x^171 + x^170 + x^168 + x^165 + x^164 + x^160 + x^158 + x^155 + x^154 + x^152 + x^151 + x^149 + x^147 + x^144 + x^141 + x^140 + x^139 + x^137 + x^136 + x^133 + x^131 + x^130 + x^128 + x^127 + x^126 + x^125 + x^123 + x^122 + x^121 + x^120 + x^119 + x^117 + x^116 + x^115 + x^112 + x^109 + x^106 + x^102 + x^101 + x^98 + x^92 + x^89 + x^87 + x^86 + x^81 + x^74 + x^72 + x^71 + x^69 + x^65 + x^61 + x^57 + x^55 + x^53 + x^51 + x^50 + x^47 + x^45 + x^44 + x^43 + x^42 + x^40 + x^39 + x^38 + x^37 + x^35 + x^31 + x^30 + x^29 + x^27 + x^24 + x^22 + x^21 + x^20 + x^19 + 1
+
+44-24-27 401 x^928 + x^898 + x^870 + x^858 + x^824 + x^821 + x^820 + x^798 + x^792 + x^791 + x^790 + x^789 + x^784 + x^776 + x^771 + x^770 + x^768 + x^764 + x^762 + x^761 + x^760 + x^759 + x^755 + x^754 + x^751 + x^742 + x^738 + x^735 + x^734 + x^731 + x^730 + x^729 + x^728 + x^725 + x^722 + x^721 + x^715 + x^711 + x^710 + x^706 + x^705 + x^701 + x^700 + x^698 + x^695 + x^692 + x^691 + x^689 + x^686 + x^685 + x^681 + x^676 + x^675 + x^674 + x^672 + x^671 + x^669 + x^668 + x^667 + x^666 + x^665 + x^658 + x^656 + x^654 + x^653 + x^651 + x^650 + x^648 + x^646 + x^644 + x^642 + x^635 + x^634 + x^633 + x^629 + x^626 + x^625 + x^624 + x^622 + x^621 + x^620 + x^618 + x^616 + x^614 + x^612 + x^608 + x^607 + x^606 + x^605 + x^604 + x^603 + x^602 + x^594 + x^593 + x^590 + x^589 + x^588 + x^586 + x^585 + x^584 + x^583 + x^582 + x^580 + x^577 + x^576 + x^575 + x^574 + x^569 + x^568 + x^566 + x^565 + x^564 + x^561 + x^559 + x^556 + x^554 + x^553 + x^552 + x^547 + x^543 + x^542 + x^541 + x^540 + x^539 + x^538 + x^536 + x^535 + x^534 + x^531 + x^530 + x^529 + x^527 + x^526 + x^524 + x^519 + x^514 + x^512 + x^511 + x^507 + x^504 + x^503 + x^502 + x^499 + x^498 + x^494 + x^493 + x^491 + x^489 + x^488 + x^486 + x^485 + x^483 + x^482 + x^480 + x^478 + x^476 + x^473 + x^468 + x^465 + x^463 + x^461 + x^460 + x^459 + x^458 + x^457 + x^455 + x^454 + x^453 + x^452 + x^451 + x^450 + x^449 + x^447 + x^446 + x^445 + x^443 + x^442 + x^439 + x^437 + x^436 + x^435 + x^433 + x^432 + x^429 + x^424 + x^423 + x^421 + x^418 + x^416 + x^412 + x^411 + x^406 + x^404 + x^403 + x^401 + x^400 + x^399 + x^398 + x^397 + x^394 + x^390 + x^388 + x^384 + x^383 + x^382 + x^381 + x^380 + x^378 + x^377 + x^376 + x^374 + x^373 + x^372 + x^368 + x^367 + x^366 + x^363 + x^361 + x^360 + x^359 + x^355 + x^353 + x^351 + x^350 + x^349 + x^348 + x^347 + x^345 + x^344 + x^342 + x^341 + x^340 + x^338 + x^337 + x^334 + x^329 + x^328 + x^326 + x^325 + x^319 + x^316 + x^314 + x^312 + x^311 + x^310 + x^308 + x^307 + x^305 + x^300 + x^296 + x^292 + x^291 + x^290 + x^287 + x^286 + x^284 + x^282 + x^280 + x^279 + x^277 + x^275 + x^274 + x^273 + x^272 + x^269 + x^268 + x^265 + x^264 + x^263 + x^262 + x^261 + x^258 + x^257 + x^256 + x^255 + x^254 + x^253 + x^252 + x^250 + x^249 + x^244 + x^242 + x^239 + x^238 + x^237 + x^235 + x^234 + x^232 + x^231 + x^228 + x^226 + x^225 + x^224 + x^221 + x^220 + x^219 + x^218 + x^216 + x^214 + x^213 + x^211 + x^210 + x^207 + x^205 + x^204 + x^203 + x^202 + x^200 + x^199 + x^198 + x^194 + x^186 + x^185 + x^184 + x^183 + x^182 + x^180 + x^179 + x^177 + x^174 + x^171 + x^169 + x^168 + x^165 + x^164 + x^163 + x^161 + x^159 + x^158 + x^157 + x^154 + x^152 + x^151 + x^148 + x^146 + x^145 + x^144 + x^142 + x^141 + x^139 + x^136 + x^135 + x^134 + x^132 + x^131 + x^130 + x^129 + x^128 + x^127 + x^124 + x^123 + x^120 + x^119 + x^117 + x^116 + x^114 + x^112 + x^106 + x^103 + x^101 + x^100 + x^98 + x^94 + x^93 + x^91 + x^86 + x^83 + x^82 + x^78 + x^76 + x^74 + x^73 + x^71 + x^69 + x^66 + x^65 + x^61 + x^60 + x^59 + x^58 + x^57 + x^56 + x^55 + x^54 + x^47 + x^45 + x^44 + x^43 + x^42 + x^40 + x^39 + x^38 + x^34 + x^31 + x^29 + x^28 + x^19 + x^16 + x^12 + x^6 + 1
+
+10-49-23 403 x^928 + x^900 + x^898 + x^893 + x^872 + x^870 + x^865 + x^858 + x^842 + x^840 + x^835 + x^833 + x^826 + x^823 + x^821 + x^816 + x^814 + x^809 + x^808 + x^807 + x^805 + x^802 + x^796 + x^793 + x^782 + x^780 + x^778 + x^775 + x^772 + x^770 + x^767 + x^766 + x^765 + x^760 + x^758 + x^756 + x^754 + x^753 + x^751 + x^747 + x^744 + x^740 + x^739 + x^738 + x^736 + x^735 + x^732 + x^728 + x^724 + x^723 + x^722 + x^720 + x^718 + x^717 + x^714 + x^712 + x^709 + x^708 + x^707 + x^706 + x^705 + x^702 + x^701 + x^700 + x^698 + x^697 + x^696 + x^694 + x^693 + x^691 + x^689 + x^688 + x^684 + x^682 + x^681 + x^680 + x^679 + x^677 + x^676 + x^674 + x^673 + x^672 + x^670 + x^668 + x^667 + x^666 + x^664 + x^661 + x^658 + x^657 + x^655 + x^652 + x^649 + x^646 + x^645 + x^643 + x^641 + x^640 + x^639 + x^638 + x^636 + x^635 + x^634 + x^632 + x^631 + x^628 + x^623 + x^622 + x^620 + x^619 + x^615 + x^612 + x^610 + x^607 + x^604 + x^602 + x^599 + x^598 + x^596 + x^593 + x^590 + x^588 + x^587 + x^585 + x^582 + x^581 + x^578 + x^576 + x^575 + x^573 + x^571 + x^570 + x^569 + x^568 + x^567 + x^565 + x^564 + x^563 + x^559 + x^557 + x^556 + x^552 + x^550 + x^549 + x^548 + x^546 + x^545 + x^543 + x^537 + x^536 + x^535 + x^534 + x^533 + x^532 + x^529 + x^526 + x^525 + x^523 + x^521 + x^520 + x^518 + x^515 + x^513 + x^512 + x^511 + x^508 + x^503 + x^502 + x^499 + x^498 + x^495 + x^494 + x^493 + x^492 + x^491 + x^480 + x^479 + x^475 + x^474 + x^472 + x^470 + x^469 + x^466 + x^465 + x^460 + x^453 + x^452 + x^451 + x^447 + x^444 + x^443 + x^438 + x^436 + x^431 + x^428 + x^426 + x^424 + x^423 + x^421 + x^420 + x^418 + x^417 + x^414 + x^413 + x^411 + x^410 + x^404 + x^401 + x^396 + x^395 + x^390 + x^389 + x^386 + x^384 + x^380 + x^378 + x^377 + x^376 + x^373 + x^372 + x^371 + x^369 + x^364 + x^361 + x^360 + x^359 + x^357 + x^356 + x^354 + x^353 + x^348 + x^347 + x^346 + x^342 + x^341 + x^339 + x^338 + x^333 + x^332 + x^331 + x^329 + x^328 + x^324 + x^322 + x^320 + x^315 + x^314 + x^312 + x^311 + x^310 + x^307 + x^306 + x^303 + x^295 + x^294 + x^292 + x^289 + x^288 + x^283 + x^281 + x^279 + x^274 + x^272 + x^271 + x^270 + x^268 + x^267 + x^266 + x^265 + x^264 + x^261 + x^258 + x^257 + x^256 + x^255 + x^252 + x^251 + x^248 + x^245 + x^243 + x^242 + x^238 + x^237 + x^236 + x^235 + x^233 + x^232 + x^231 + x^229 + x^228 + x^226 + x^225 + x^224 + x^222 + x^221 + x^220 + x^216 + x^215 + x^213 + x^212 + x^210 + x^209 + x^208 + x^202 + x^200 + x^199 + x^197 + x^194 + x^193 + x^192 + x^191 + x^190 + x^189 + x^187 + x^186 + x^184 + x^183 + x^181 + x^179 + x^178 + x^177 + x^176 + x^174 + x^173 + x^172 + x^171 + x^169 + x^166 + x^164 + x^163 + x^160 + x^158 + x^157 + x^155 + x^152 + x^151 + x^150 + x^148 + x^146 + x^145 + x^143 + x^142 + x^137 + x^133 + x^129 + x^126 + x^118 + x^116 + x^114 + x^113 + x^112 + x^110 + x^106 + x^102 + x^99 + x^98 + x^97 + x^96 + x^92 + x^91 + x^88 + x^86 + x^85 + x^83 + x^82 + x^81 + x^79 + x^78 + x^77 + x^76 + x^73 + x^71 + x^67 + x^66 + x^65 + x^64 + x^63 + x^61 + x^60 + x^58 + x^53 + x^52 + x^51 + x^48 + x^47 + x^44 + x^43 + x^42 + x^41 + x^39 + x^37 + x^36 + x^35 + x^34 + x^33 + x^31 + x^26 + x^21 + x^20 + x^16 + x^10 + x^5 + 1
+
+16-2-49 403 x^928 + x^898 + x^870 + x^858 + x^855 + x^846 + x^831 + x^828 + x^822 + x^818 + x^808 + x^800 + x^798 + x^795 + x^788 + x^786 + x^784 + x^783 + x^776 + x^775 + x^770 + x^768 + x^764 + x^759 + x^753 + x^751 + x^750 + x^746 + x^743 + x^740 + x^736 + x^735 + x^734 + x^724 + x^723 + x^719 + x^712 + x^708 + x^706 + x^703 + x^699 + x^698 + x^696 + x^695 + x^694 + x^693 + x^691 + x^690 + x^688 + x^686 + x^684 + x^683 + x^676 + x^675 + x^673 + x^672 + x^671 + x^670 + x^668 + x^664 + x^663 + x^662 + x^660 + x^655 + x^654 + x^652 + x^649 + x^644 + x^642 + x^636 + x^634 + x^633 + x^623 + x^622 + x^620 + x^619 + x^616 + x^614 + x^613 + x^611 + x^609 + x^608 + x^606 + x^604 + x^603 + x^602 + x^601 + x^600 + x^599 + x^598 + x^596 + x^595 + x^594 + x^592 + x^591 + x^588 + x^586 + x^585 + x^584 + x^583 + x^579 + x^578 + x^577 + x^576 + x^575 + x^574 + x^572 + x^569 + x^562 + x^560 + x^555 + x^553 + x^550 + x^549 + x^548 + x^547 + x^546 + x^545 + x^544 + x^543 + x^542 + x^538 + x^536 + x^533 + x^532 + x^531 + x^530 + x^529 + x^528 + x^527 + x^526 + x^523 + x^518 + x^516 + x^515 + x^511 + x^509 + x^507 + x^503 + x^501 + x^500 + x^498 + x^497 + x^496 + x^494 + x^491 + x^490 + x^487 + x^485 + x^484 + x^483 + x^482 + x^478 + x^477 + x^475 + x^474 + x^472 + x^470 + x^468 + x^467 + x^466 + x^465 + x^464 + x^462 + x^461 + x^460 + x^458 + x^457 + x^456 + x^455 + x^454 + x^453 + x^448 + x^446 + x^444 + x^443 + x^442 + x^441 + x^440 + x^437 + x^436 + x^435 + x^434 + x^433 + x^432 + x^431 + x^430 + x^429 + x^428 + x^427 + x^426 + x^425 + x^422 + x^421 + x^420 + x^419 + x^417 + x^414 + x^413 + x^411 + x^410 + x^406 + x^405 + x^400 + x^399 + x^397 + x^395 + x^394 + x^393 + x^392 + x^391 + x^389 + x^387 + x^382 + x^380 + x^379 + x^377 + x^375 + x^371 + x^370 + x^366 + x^365 + x^364 + x^363 + x^362 + x^358 + x^356 + x^354 + x^353 + x^351 + x^348 + x^346 + x^344 + x^343 + x^342 + x^340 + x^339 + x^337 + x^334 + x^333 + x^332 + x^331 + x^328 + x^327 + x^326 + x^325 + x^324 + x^323 + x^322 + x^321 + x^320 + x^318 + x^317 + x^316 + x^315 + x^314 + x^312 + x^310 + x^306 + x^304 + x^303 + x^301 + x^297 + x^295 + x^293 + x^290 + x^285 + x^283 + x^282 + x^273 + x^271 + x^268 + x^266 + x^262 + x^260 + x^259 + x^258 + x^253 + x^252 + x^251 + x^249 + x^248 + x^246 + x^245 + x^244 + x^243 + x^242 + x^241 + x^240 + x^239 + x^238 + x^237 + x^234 + x^233 + x^231 + x^229 + x^228 + x^227 + x^223 + x^222 + x^217 + x^216 + x^214 + x^213 + x^211 + x^209 + x^208 + x^203 + x^202 + x^201 + x^198 + x^197 + x^196 + x^194 + x^193 + x^189 + x^188 + x^187 + x^183 + x^182 + x^181 + x^177 + x^176 + x^174 + x^170 + x^166 + x^163 + x^162 + x^161 + x^160 + x^158 + x^157 + x^155 + x^153 + x^152 + x^151 + x^149 + x^148 + x^147 + x^146 + x^144 + x^142 + x^141 + x^140 + x^138 + x^132 + x^131 + x^129 + x^128 + x^126 + x^125 + x^123 + x^122 + x^120 + x^119 + x^117 + x^116 + x^115 + x^112 + x^109 + x^107 + x^105 + x^101 + x^97 + x^95 + x^94 + x^92 + x^91 + x^90 + x^87 + x^86 + x^85 + x^83 + x^82 + x^81 + x^79 + x^78 + x^77 + x^73 + x^72 + x^71 + x^68 + x^67 + x^65 + x^64 + x^63 + x^60 + x^58 + x^54 + x^50 + x^45 + x^44 + x^43 + x^42 + x^39 + x^37 + x^26 + x^24 + x^20 + x^16 + x^14 + x^10 + 1
+
+17-2-46 405 x^928 + x^898 + x^870 + x^860 + x^848 + x^831 + x^830 + x^818 + x^812 + x^808 + x^804 + x^801 + x^800 + x^792 + x^791 + x^790 + x^784 + x^780 + x^778 + x^775 + x^774 + x^770 + x^763 + x^762 + x^761 + x^760 + x^756 + x^754 + x^750 + x^748 + x^746 + x^745 + x^736 + x^733 + x^732 + x^731 + x^729 + x^728 + x^726 + x^720 + x^719 + x^712 + x^710 + x^706 + x^703 + x^702 + x^701 + x^700 + x^690 + x^686 + x^682 + x^679 + x^676 + x^675 + x^673 + x^672 + x^671 + x^669 + x^668 + x^666 + x^664 + x^663 + x^658 + x^652 + x^651 + x^648 + x^647 + x^646 + x^645 + x^644 + x^643 + x^642 + x^638 + x^633 + x^628 + x^626 + x^624 + x^623 + x^621 + x^617 + x^616 + x^614 + x^613 + x^611 + x^610 + x^609 + x^607 + x^606 + x^604 + x^599 + x^595 + x^594 + x^593 + x^592 + x^590 + x^589 + x^588 + x^584 + x^580 + x^579 + x^578 + x^577 + x^576 + x^574 + x^573 + x^569 + x^568 + x^567 + x^566 + x^564 + x^563 + x^561 + x^560 + x^559 + x^558 + x^557 + x^555 + x^549 + x^548 + x^547 + x^544 + x^543 + x^542 + x^540 + x^535 + x^534 + x^532 + x^531 + x^530 + x^528 + x^527 + x^526 + x^525 + x^520 + x^519 + x^516 + x^513 + x^510 + x^509 + x^500 + x^499 + x^498 + x^497 + x^496 + x^493 + x^492 + x^490 + x^489 + x^487 + x^484 + x^482 + x^480 + x^479 + x^476 + x^473 + x^471 + x^470 + x^468 + x^467 + x^465 + x^464 + x^463 + x^462 + x^461 + x^460 + x^457 + x^453 + x^452 + x^450 + x^448 + x^447 + x^443 + x^440 + x^439 + x^438 + x^437 + x^431 + x^430 + x^429 + x^428 + x^427 + x^426 + x^424 + x^423 + x^420 + x^418 + x^416 + x^415 + x^408 + x^407 + x^406 + x^405 + x^404 + x^403 + x^397 + x^395 + x^391 + x^389 + x^388 + x^386 + x^384 + x^382 + x^381 + x^380 + x^379 + x^378 + x^375 + x^374 + x^373 + x^372 + x^371 + x^369 + x^368 + x^365 + x^364 + x^363 + x^362 + x^360 + x^359 + x^358 + x^357 + x^353 + x^351 + x^350 + x^345 + x^341 + x^338 + x^336 + x^335 + x^334 + x^332 + x^331 + x^329 + x^328 + x^327 + x^323 + x^321 + x^320 + x^319 + x^317 + x^316 + x^314 + x^313 + x^312 + x^310 + x^308 + x^307 + x^304 + x^303 + x^300 + x^297 + x^295 + x^293 + x^291 + x^289 + x^288 + x^287 + x^285 + x^284 + x^282 + x^280 + x^279 + x^277 + x^273 + x^272 + x^269 + x^268 + x^267 + x^266 + x^265 + x^264 + x^262 + x^260 + x^259 + x^256 + x^255 + x^254 + x^253 + x^249 + x^247 + x^245 + x^243 + x^241 + x^240 + x^239 + x^238 + x^237 + x^236 + x^235 + x^234 + x^232 + x^228 + x^226 + x^225 + x^224 + x^223 + x^220 + x^219 + x^217 + x^209 + x^207 + x^206 + x^204 + x^203 + x^202 + x^201 + x^200 + x^199 + x^195 + x^194 + x^189 + x^187 + x^186 + x^185 + x^184 + x^182 + x^180 + x^178 + x^174 + x^173 + x^172 + x^170 + x^167 + x^166 + x^165 + x^164 + x^162 + x^161 + x^160 + x^159 + x^158 + x^157 + x^156 + x^155 + x^154 + x^153 + x^152 + x^151 + x^147 + x^143 + x^141 + x^138 + x^131 + x^130 + x^129 + x^127 + x^122 + x^121 + x^120 + x^118 + x^117 + x^114 + x^111 + x^109 + x^106 + x^105 + x^104 + x^103 + x^102 + x^101 + x^100 + x^99 + x^98 + x^97 + x^93 + x^92 + x^91 + x^90 + x^88 + x^87 + x^86 + x^82 + x^81 + x^80 + x^79 + x^78 + x^77 + x^75 + x^74 + x^73 + x^72 + x^71 + x^68 + x^59 + x^58 + x^51 + x^50 + x^43 + x^42 + x^40 + x^39 + x^34 + x^27 + x^25 + x^24 + x^23 + x^19 + x^18 + x^17 + x^15 + x^14 + x^13 + x^11 + x^10 + 1
+
+55-23-24 407 x^928 + x^898 + x^894 + x^870 + x^865 + x^849 + x^846 + x^842 + x^834 + x^833 + x^830 + x^826 + x^820 + x^819 + x^816 + x^813 + x^808 + x^804 + x^803 + x^794 + x^782 + x^778 + x^772 + x^769 + x^767 + x^765 + x^764 + x^762 + x^760 + x^759 + x^756 + x^751 + x^745 + x^743 + x^740 + x^739 + x^737 + x^733 + x^730 + x^729 + x^728 + x^726 + x^722 + x^720 + x^718 + x^717 + x^716 + x^713 + x^710 + x^709 + x^708 + x^707 + x^702 + x^699 + x^697 + x^694 + x^692 + x^691 + x^688 + x^687 + x^682 + x^680 + x^679 + x^678 + x^676 + x^675 + x^674 + x^670 + x^668 + x^666 + x^662 + x^661 + x^657 + x^652 + x^651 + x^649 + x^647 + x^646 + x^643 + x^640 + x^639 + x^637 + x^635 + x^634 + x^633 + x^630 + x^618 + x^616 + x^614 + x^613 + x^611 + x^610 + x^609 + x^608 + x^604 + x^603 + x^602 + x^597 + x^593 + x^591 + x^590 + x^585 + x^582 + x^579 + x^575 + x^574 + x^573 + x^572 + x^569 + x^567 + x^566 + x^564 + x^562 + x^561 + x^560 + x^557 + x^556 + x^555 + x^554 + x^551 + x^550 + x^547 + x^545 + x^542 + x^541 + x^539 + x^537 + x^534 + x^531 + x^530 + x^529 + x^528 + x^526 + x^525 + x^523 + x^522 + x^521 + x^520 + x^519 + x^518 + x^517 + x^515 + x^514 + x^513 + x^511 + x^510 + x^509 + x^508 + x^506 + x^505 + x^500 + x^498 + x^492 + x^485 + x^484 + x^480 + x^479 + x^478 + x^477 + x^476 + x^471 + x^470 + x^469 + x^467 + x^465 + x^464 + x^462 + x^458 + x^457 + x^454 + x^453 + x^452 + x^451 + x^450 + x^445 + x^444 + x^443 + x^441 + x^439 + x^437 + x^436 + x^435 + x^433 + x^431 + x^430 + x^429 + x^425 + x^424 + x^421 + x^419 + x^414 + x^411 + x^410 + x^409 + x^408 + x^407 + x^406 + x^405 + x^396 + x^395 + x^394 + x^390 + x^388 + x^385 + x^383 + x^381 + x^379 + x^378 + x^377 + x^376 + x^375 + x^373 + x^371 + x^369 + x^368 + x^367 + x^360 + x^358 + x^353 + x^351 + x^350 + x^348 + x^347 + x^346 + x^344 + x^343 + x^341 + x^338 + x^336 + x^335 + x^334 + x^331 + x^330 + x^329 + x^327 + x^326 + x^324 + x^322 + x^318 + x^314 + x^313 + x^311 + x^307 + x^305 + x^304 + x^302 + x^299 + x^295 + x^294 + x^293 + x^289 + x^284 + x^282 + x^281 + x^277 + x^272 + x^271 + x^270 + x^268 + x^265 + x^262 + x^259 + x^257 + x^254 + x^252 + x^251 + x^250 + x^249 + x^244 + x^243 + x^240 + x^239 + x^237 + x^235 + x^234 + x^233 + x^231 + x^230 + x^227 + x^224 + x^223 + x^220 + x^219 + x^218 + x^217 + x^215 + x^214 + x^213 + x^212 + x^211 + x^210 + x^209 + x^208 + x^207 + x^205 + x^203 + x^201 + x^200 + x^197 + x^193 + x^190 + x^187 + x^185 + x^184 + x^181 + x^180 + x^179 + x^178 + x^177 + x^176 + x^175 + x^173 + x^172 + x^169 + x^168 + x^166 + x^165 + x^162 + x^159 + x^157 + x^156 + x^155 + x^154 + x^153 + x^152 + x^150 + x^146 + x^145 + x^143 + x^142 + x^141 + x^139 + x^138 + x^137 + x^136 + x^135 + x^134 + x^132 + x^129 + x^123 + x^119 + x^115 + x^114 + x^112 + x^108 + x^107 + x^102 + x^100 + x^98 + x^97 + x^95 + x^93 + x^91 + x^90 + x^87 + x^86 + x^85 + x^83 + x^80 + x^79 + x^78 + x^77 + x^75 + x^74 + x^72 + x^69 + x^68 + x^65 + x^64 + x^61 + x^60 + x^59 + x^58 + x^57 + x^56 + x^55 + x^52 + x^51 + x^50 + x^45 + x^44 + x^43 + x^42 + x^41 + x^40 + x^39 + x^38 + x^37 + x^34 + x^33 + x^31 + x^30 + x^29 + x^26 + x^25 + x^23 + x^21 + x^20 + x^19 + x^18 + x^17 + x^13 + x^12 + x^10 + x^8 + x^7 + 1
+
+15-3-26 409 x^928 + x^898 + x^892 + x^870 + x^863 + x^862 + x^858 + x^856 + x^852 + x^833 + x^828 + x^827 + x^826 + x^824 + x^823 + x^820 + x^818 + x^816 + x^812 + x^808 + x^803 + x^801 + x^799 + x^798 + x^797 + x^795 + x^794 + x^792 + x^791 + x^790 + x^788 + x^787 + x^784 + x^783 + x^782 + x^773 + x^772 + x^771 + x^768 + x^767 + x^763 + x^760 + x^757 + x^753 + x^750 + x^746 + x^744 + x^737 + x^732 + x^731 + x^730 + x^729 + x^728 + x^726 + x^725 + x^724 + x^721 + x^717 + x^716 + x^713 + x^711 + x^710 + x^707 + x^706 + x^705 + x^703 + x^702 + x^699 + x^698 + x^697 + x^696 + x^694 + x^692 + x^691 + x^690 + x^689 + x^688 + x^681 + x^678 + x^673 + x^668 + x^666 + x^662 + x^658 + x^657 + x^656 + x^653 + x^651 + x^650 + x^648 + x^644 + x^643 + x^642 + x^641 + x^640 + x^638 + x^636 + x^635 + x^634 + x^633 + x^632 + x^630 + x^628 + x^626 + x^625 + x^623 + x^622 + x^620 + x^618 + x^617 + x^616 + x^614 + x^611 + x^609 + x^607 + x^605 + x^603 + x^596 + x^595 + x^593 + x^592 + x^590 + x^587 + x^586 + x^585 + x^584 + x^583 + x^582 + x^580 + x^577 + x^576 + x^571 + x^569 + x^568 + x^567 + x^565 + x^564 + x^562 + x^561 + x^560 + x^559 + x^558 + x^557 + x^556 + x^555 + x^554 + x^553 + x^552 + x^548 + x^547 + x^546 + x^545 + x^544 + x^542 + x^538 + x^537 + x^534 + x^533 + x^532 + x^529 + x^527 + x^526 + x^524 + x^523 + x^518 + x^517 + x^509 + x^505 + x^503 + x^501 + x^494 + x^493 + x^492 + x^488 + x^485 + x^484 + x^483 + x^480 + x^479 + x^477 + x^475 + x^474 + x^473 + x^472 + x^471 + x^469 + x^467 + x^466 + x^465 + x^464 + x^461 + x^458 + x^456 + x^453 + x^449 + x^446 + x^445 + x^444 + x^443 + x^442 + x^441 + x^440 + x^436 + x^435 + x^432 + x^431 + x^427 + x^426 + x^423 + x^418 + x^415 + x^413 + x^412 + x^411 + x^410 + x^407 + x^406 + x^403 + x^400 + x^398 + x^396 + x^385 + x^383 + x^382 + x^381 + x^375 + x^374 + x^373 + x^364 + x^363 + x^362 + x^360 + x^358 + x^357 + x^355 + x^353 + x^352 + x^350 + x^349 + x^345 + x^344 + x^343 + x^342 + x^340 + x^337 + x^331 + x^329 + x^328 + x^325 + x^324 + x^323 + x^322 + x^315 + x^314 + x^312 + x^311 + x^308 + x^304 + x^303 + x^299 + x^297 + x^295 + x^289 + x^284 + x^282 + x^281 + x^279 + x^278 + x^275 + x^274 + x^273 + x^272 + x^271 + x^270 + x^264 + x^263 + x^262 + x^260 + x^259 + x^258 + x^256 + x^253 + x^252 + x^251 + x^250 + x^248 + x^247 + x^246 + x^245 + x^243 + x^242 + x^240 + x^238 + x^237 + x^234 + x^233 + x^232 + x^231 + x^230 + x^228 + x^221 + x^220 + x^218 + x^213 + x^212 + x^211 + x^210 + x^204 + x^201 + x^200 + x^196 + x^195 + x^194 + x^191 + x^190 + x^189 + x^185 + x^183 + x^181 + x^180 + x^178 + x^176 + x^175 + x^170 + x^168 + x^167 + x^165 + x^164 + x^163 + x^160 + x^159 + x^158 + x^157 + x^156 + x^153 + x^151 + x^150 + x^149 + x^146 + x^145 + x^141 + x^139 + x^138 + x^137 + x^133 + x^132 + x^131 + x^130 + x^129 + x^128 + x^127 + x^125 + x^124 + x^122 + x^121 + x^120 + x^116 + x^115 + x^114 + x^112 + x^110 + x^106 + x^103 + x^101 + x^100 + x^97 + x^96 + x^94 + x^93 + x^92 + x^89 + x^88 + x^87 + x^86 + x^85 + x^84 + x^82 + x^80 + x^77 + x^73 + x^72 + x^71 + x^70 + x^68 + x^67 + x^65 + x^61 + x^60 + x^59 + x^56 + x^55 + x^48 + x^47 + x^42 + x^41 + x^36 + x^35 + x^33 + x^29 + x^27 + x^26 + x^25 + x^18 + x^14 + x^12 + x^10 + x^8 + x^4 + 1
+
+33-51-22 409 x^928 + x^898 + x^886 + x^870 + x^859 + x^858 + x^857 + x^844 + x^842 + x^832 + x^831 + x^830 + x^826 + x^815 + x^812 + x^808 + x^805 + x^804 + x^803 + x^799 + x^798 + x^789 + x^787 + x^786 + x^785 + x^782 + x^777 + x^776 + x^775 + x^771 + x^769 + x^766 + x^763 + x^758 + x^756 + x^752 + x^749 + x^745 + x^744 + x^743 + x^741 + x^739 + x^738 + x^735 + x^734 + x^731 + x^730 + x^721 + x^720 + x^715 + x^714 + x^711 + x^708 + x^705 + x^704 + x^703 + x^700 + x^698 + x^695 + x^693 + x^692 + x^690 + x^689 + x^684 + x^682 + x^681 + x^680 + x^677 + x^676 + x^673 + x^672 + x^671 + x^667 + x^666 + x^662 + x^661 + x^658 + x^656 + x^653 + x^652 + x^650 + x^649 + x^647 + x^646 + x^645 + x^644 + x^642 + x^641 + x^640 + x^638 + x^636 + x^634 + x^633 + x^632 + x^631 + x^629 + x^625 + x^624 + x^623 + x^621 + x^620 + x^619 + x^616 + x^615 + x^614 + x^612 + x^611 + x^609 + x^606 + x^605 + x^602 + x^601 + x^599 + x^596 + x^595 + x^592 + x^591 + x^588 + x^587 + x^586 + x^583 + x^582 + x^578 + x^577 + x^576 + x^574 + x^572 + x^570 + x^566 + x^562 + x^560 + x^555 + x^552 + x^550 + x^546 + x^545 + x^544 + x^543 + x^542 + x^539 + x^537 + x^535 + x^534 + x^533 + x^532 + x^531 + x^530 + x^528 + x^525 + x^524 + x^523 + x^519 + x^516 + x^513 + x^511 + x^509 + x^508 + x^507 + x^506 + x^504 + x^500 + x^499 + x^497 + x^495 + x^494 + x^491 + x^488 + x^487 + x^484 + x^480 + x^479 + x^476 + x^474 + x^472 + x^471 + x^470 + x^469 + x^468 + x^464 + x^463 + x^462 + x^460 + x^459 + x^458 + x^457 + x^456 + x^455 + x^454 + x^451 + x^449 + x^448 + x^447 + x^446 + x^445 + x^441 + x^440 + x^439 + x^437 + x^436 + x^435 + x^431 + x^430 + x^427 + x^423 + x^421 + x^419 + x^412 + x^410 + x^407 + x^406 + x^405 + x^404 + x^402 + x^400 + x^398 + x^396 + x^395 + x^394 + x^392 + x^389 + x^387 + x^386 + x^384 + x^382 + x^381 + x^379 + x^378 + x^377 + x^375 + x^372 + x^370 + x^369 + x^363 + x^361 + x^360 + x^351 + x^350 + x^347 + x^343 + x^342 + x^340 + x^336 + x^328 + x^327 + x^326 + x^325 + x^323 + x^322 + x^321 + x^319 + x^318 + x^315 + x^314 + x^313 + x^312 + x^311 + x^308 + x^307 + x^305 + x^301 + x^299 + x^298 + x^295 + x^293 + x^292 + x^290 + x^289 + x^288 + x^286 + x^284 + x^283 + x^282 + x^280 + x^279 + x^275 + x^273 + x^272 + x^269 + x^266 + x^265 + x^264 + x^255 + x^251 + x^249 + x^248 + x^246 + x^244 + x^243 + x^242 + x^238 + x^237 + x^235 + x^234 + x^232 + x^230 + x^229 + x^228 + x^226 + x^224 + x^222 + x^221 + x^218 + x^213 + x^210 + x^209 + x^208 + x^206 + x^203 + x^200 + x^195 + x^193 + x^189 + x^187 + x^186 + x^185 + x^182 + x^181 + x^179 + x^177 + x^174 + x^173 + x^170 + x^163 + x^160 + x^159 + x^155 + x^154 + x^153 + x^152 + x^151 + x^147 + x^146 + x^143 + x^141 + x^133 + x^130 + x^128 + x^125 + x^123 + x^118 + x^116 + x^115 + x^114 + x^110 + x^108 + x^106 + x^105 + x^104 + x^102 + x^100 + x^98 + x^97 + x^96 + x^95 + x^94 + x^93 + x^92 + x^91 + x^89 + x^85 + x^84 + x^83 + x^82 + x^81 + x^80 + x^78 + x^77 + x^74 + x^72 + x^71 + x^69 + x^67 + x^65 + x^64 + x^63 + x^61 + x^58 + x^56 + x^55 + x^53 + x^52 + x^51 + x^50 + x^48 + x^47 + x^46 + x^45 + x^44 + x^43 + x^40 + x^39 + x^37 + x^36 + x^35 + x^33 + x^32 + x^30 + x^29 + x^28 + x^27 + x^25 + x^23 + x^21 + x^16 + x^13 + x^11 + x^10 + x^8 + 1
+
+23-25-12 411 x^928 + x^898 + x^873 + x^870 + x^852 + x^847 + x^844 + x^842 + x^838 + x^836 + x^831 + x^828 + x^822 + x^821 + x^818 + x^817 + x^816 + x^814 + x^813 + x^812 + x^811 + x^801 + x^800 + x^798 + x^797 + x^796 + x^792 + x^791 + x^790 + x^787 + x^780 + x^776 + x^774 + x^770 + x^768 + x^766 + x^765 + x^762 + x^761 + x^759 + x^758 + x^757 + x^756 + x^755 + x^752 + x^749 + x^748 + x^747 + x^744 + x^741 + x^740 + x^739 + x^737 + x^735 + x^731 + x^730 + x^729 + x^728 + x^726 + x^725 + x^722 + x^720 + x^718 + x^714 + x^712 + x^711 + x^709 + x^708 + x^707 + x^706 + x^705 + x^704 + x^698 + x^694 + x^693 + x^691 + x^689 + x^686 + x^685 + x^682 + x^676 + x^674 + x^670 + x^669 + x^668 + x^667 + x^666 + x^665 + x^662 + x^661 + x^658 + x^655 + x^653 + x^652 + x^650 + x^647 + x^644 + x^643 + x^640 + x^638 + x^637 + x^635 + x^634 + x^632 + x^629 + x^627 + x^626 + x^625 + x^624 + x^619 + x^618 + x^614 + x^612 + x^611 + x^606 + x^604 + x^602 + x^601 + x^595 + x^592 + x^591 + x^590 + x^589 + x^586 + x^585 + x^581 + x^579 + x^578 + x^575 + x^574 + x^573 + x^568 + x^567 + x^565 + x^564 + x^562 + x^560 + x^559 + x^558 + x^555 + x^554 + x^553 + x^552 + x^549 + x^548 + x^546 + x^544 + x^543 + x^542 + x^541 + x^538 + x^533 + x^532 + x^529 + x^527 + x^526 + x^523 + x^522 + x^521 + x^517 + x^511 + x^508 + x^507 + x^506 + x^505 + x^504 + x^502 + x^497 + x^496 + x^494 + x^490 + x^489 + x^486 + x^485 + x^483 + x^482 + x^481 + x^477 + x^475 + x^473 + x^472 + x^471 + x^468 + x^464 + x^462 + x^461 + x^460 + x^459 + x^455 + x^454 + x^453 + x^449 + x^448 + x^447 + x^446 + x^438 + x^437 + x^435 + x^432 + x^429 + x^427 + x^426 + x^424 + x^423 + x^421 + x^419 + x^418 + x^416 + x^415 + x^413 + x^412 + x^410 + x^409 + x^407 + x^406 + x^405 + x^402 + x^401 + x^399 + x^397 + x^396 + x^394 + x^393 + x^390 + x^385 + x^384 + x^383 + x^380 + x^379 + x^378 + x^376 + x^375 + x^374 + x^372 + x^370 + x^368 + x^367 + x^366 + x^365 + x^363 + x^359 + x^357 + x^356 + x^355 + x^354 + x^353 + x^352 + x^351 + x^350 + x^348 + x^345 + x^341 + x^337 + x^335 + x^334 + x^333 + x^325 + x^319 + x^317 + x^316 + x^314 + x^305 + x^301 + x^298 + x^294 + x^293 + x^292 + x^289 + x^284 + x^281 + x^279 + x^272 + x^271 + x^269 + x^268 + x^267 + x^266 + x^264 + x^263 + x^262 + x^261 + x^256 + x^255 + x^254 + x^252 + x^251 + x^249 + x^248 + x^244 + x^242 + x^239 + x^235 + x^234 + x^233 + x^227 + x^226 + x^223 + x^221 + x^220 + x^216 + x^214 + x^211 + x^209 + x^207 + x^205 + x^204 + x^200 + x^198 + x^197 + x^196 + x^193 + x^188 + x^187 + x^185 + x^183 + x^182 + x^181 + x^179 + x^177 + x^175 + x^173 + x^172 + x^170 + x^169 + x^167 + x^163 + x^162 + x^158 + x^157 + x^156 + x^155 + x^154 + x^152 + x^151 + x^150 + x^149 + x^145 + x^144 + x^143 + x^142 + x^140 + x^139 + x^138 + x^136 + x^135 + x^133 + x^131 + x^130 + x^127 + x^126 + x^124 + x^122 + x^120 + x^118 + x^116 + x^114 + x^111 + x^110 + x^106 + x^105 + x^103 + x^102 + x^101 + x^100 + x^99 + x^98 + x^97 + x^95 + x^94 + x^93 + x^92 + x^91 + x^90 + x^86 + x^85 + x^82 + x^81 + x^78 + x^75 + x^70 + x^66 + x^64 + x^63 + x^61 + x^60 + x^55 + x^54 + x^53 + x^52 + x^50 + x^49 + x^46 + x^45 + x^44 + x^41 + x^38 + x^37 + x^36 + x^32 + x^30 + x^29 + x^27 + x^22 + x^18 + x^16 + x^13 + x^9 + x^8 + x^7 + x^5 + 1
+
+36-2-35 411 x^928 + x^898 + x^870 + x^860 + x^850 + x^842 + x^830 + x^824 + x^822 + x^812 + x^808 + x^806 + x^804 + x^794 + x^792 + x^790 + x^786 + x^782 + x^778 + x^776 + x^772 + x^768 + x^764 + x^754 + x^752 + x^747 + x^746 + x^745 + x^742 + x^738 + x^737 + x^736 + x^729 + x^728 + x^725 + x^724 + x^722 + x^721 + x^720 + x^718 + x^716 + x^715 + x^714 + x^712 + x^707 + x^706 + x^704 + x^703 + x^701 + x^699 + x^693 + x^691 + x^689 + x^688 + x^687 + x^684 + x^682 + x^680 + x^674 + x^672 + x^671 + x^669 + x^668 + x^663 + x^662 + x^661 + x^660 + x^659 + x^658 + x^654 + x^652 + x^651 + x^650 + x^649 + x^648 + x^644 + x^642 + x^640 + x^639 + x^638 + x^635 + x^633 + x^632 + x^624 + x^623 + x^620 + x^619 + x^618 + x^617 + x^611 + x^607 + x^606 + x^604 + x^602 + x^601 + x^600 + x^598 + x^596 + x^594 + x^593 + x^589 + x^585 + x^583 + x^580 + x^579 + x^577 + x^576 + x^575 + x^569 + x^568 + x^567 + x^565 + x^564 + x^563 + x^560 + x^558 + x^556 + x^555 + x^553 + x^552 + x^551 + x^549 + x^548 + x^545 + x^542 + x^541 + x^539 + x^536 + x^534 + x^533 + x^530 + x^528 + x^526 + x^524 + x^521 + x^519 + x^517 + x^515 + x^511 + x^510 + x^508 + x^506 + x^505 + x^504 + x^503 + x^502 + x^501 + x^500 + x^499 + x^498 + x^496 + x^494 + x^493 + x^492 + x^491 + x^490 + x^488 + x^487 + x^484 + x^480 + x^478 + x^474 + x^472 + x^471 + x^466 + x^465 + x^464 + x^463 + x^461 + x^459 + x^458 + x^457 + x^454 + x^453 + x^446 + x^445 + x^441 + x^440 + x^439 + x^438 + x^437 + x^436 + x^435 + x^433 + x^428 + x^427 + x^426 + x^425 + x^414 + x^407 + x^406 + x^405 + x^403 + x^402 + x^401 + x^399 + x^398 + x^397 + x^395 + x^393 + x^392 + x^391 + x^390 + x^387 + x^385 + x^384 + x^383 + x^382 + x^379 + x^378 + x^376 + x^374 + x^373 + x^371 + x^370 + x^369 + x^367 + x^365 + x^364 + x^363 + x^359 + x^357 + x^355 + x^354 + x^353 + x^350 + x^346 + x^345 + x^344 + x^343 + x^340 + x^338 + x^337 + x^336 + x^335 + x^330 + x^322 + x^321 + x^320 + x^317 + x^316 + x^311 + x^310 + x^309 + x^308 + x^307 + x^306 + x^305 + x^303 + x^299 + x^296 + x^295 + x^294 + x^293 + x^292 + x^289 + x^288 + x^284 + x^283 + x^282 + x^281 + x^280 + x^278 + x^277 + x^275 + x^269 + x^265 + x^263 + x^260 + x^258 + x^256 + x^255 + x^254 + x^253 + x^252 + x^250 + x^247 + x^246 + x^245 + x^242 + x^241 + x^240 + x^239 + x^234 + x^233 + x^232 + x^230 + x^226 + x^224 + x^222 + x^218 + x^217 + x^216 + x^215 + x^214 + x^213 + x^212 + x^211 + x^208 + x^204 + x^203 + x^202 + x^201 + x^200 + x^199 + x^198 + x^197 + x^194 + x^192 + x^191 + x^184 + x^181 + x^180 + x^178 + x^177 + x^176 + x^175 + x^174 + x^173 + x^171 + x^170 + x^168 + x^166 + x^161 + x^160 + x^157 + x^156 + x^153 + x^149 + x^148 + x^147 + x^145 + x^144 + x^143 + x^139 + x^137 + x^136 + x^134 + x^132 + x^131 + x^130 + x^129 + x^128 + x^127 + x^126 + x^125 + x^118 + x^117 + x^116 + x^115 + x^114 + x^113 + x^111 + x^107 + x^105 + x^104 + x^103 + x^101 + x^99 + x^98 + x^97 + x^96 + x^92 + x^91 + x^90 + x^89 + x^87 + x^86 + x^85 + x^84 + x^83 + x^82 + x^81 + x^79 + x^78 + x^76 + x^72 + x^70 + x^69 + x^68 + x^67 + x^65 + x^64 + x^62 + x^61 + x^58 + x^54 + x^53 + x^52 + x^50 + x^49 + x^48 + x^46 + x^44 + x^43 + x^40 + x^39 + x^38 + x^35 + x^32 + x^31 + x^30 + x^29 + x^28 + x^27 + x^25 + x^24 + x^18 + x^14 + x^10 + 1
+
+55-5-54 411 x^928 + x^898 + x^883 + x^870 + x^867 + x^854 + x^853 + x^840 + x^838 + x^837 + x^836 + x^834 + x^824 + x^822 + x^820 + x^812 + x^811 + x^810 + x^808 + x^807 + x^800 + x^797 + x^796 + x^795 + x^793 + x^792 + x^783 + x^779 + x^777 + x^776 + x^774 + x^770 + x^769 + x^768 + x^764 + x^762 + x^760 + x^754 + x^753 + x^752 + x^751 + x^749 + x^747 + x^746 + x^741 + x^740 + x^739 + x^738 + x^735 + x^734 + x^733 + x^732 + x^730 + x^728 + x^723 + x^721 + x^717 + x^715 + x^712 + x^711 + x^710 + x^709 + x^708 + x^707 + x^706 + x^704 + x^702 + x^701 + x^698 + x^697 + x^696 + x^694 + x^692 + x^690 + x^687 + x^683 + x^682 + x^681 + x^675 + x^674 + x^670 + x^669 + x^667 + x^666 + x^664 + x^663 + x^662 + x^657 + x^655 + x^654 + x^653 + x^652 + x^650 + x^646 + x^645 + x^644 + x^642 + x^637 + x^636 + x^635 + x^630 + x^629 + x^627 + x^626 + x^620 + x^615 + x^614 + x^612 + x^611 + x^610 + x^607 + x^606 + x^605 + x^604 + x^603 + x^601 + x^597 + x^594 + x^592 + x^591 + x^586 + x^584 + x^583 + x^582 + x^579 + x^577 + x^574 + x^573 + x^568 + x^565 + x^564 + x^563 + x^562 + x^557 + x^554 + x^553 + x^552 + x^550 + x^548 + x^546 + x^544 + x^543 + x^542 + x^540 + x^537 + x^536 + x^532 + x^531 + x^530 + x^524 + x^521 + x^520 + x^519 + x^517 + x^516 + x^515 + x^513 + x^512 + x^510 + x^509 + x^507 + x^505 + x^503 + x^502 + x^501 + x^500 + x^497 + x^496 + x^488 + x^486 + x^484 + x^481 + x^480 + x^478 + x^476 + x^475 + x^467 + x^465 + x^464 + x^463 + x^459 + x^458 + x^457 + x^455 + x^453 + x^452 + x^446 + x^445 + x^444 + x^441 + x^440 + x^439 + x^438 + x^434 + x^433 + x^432 + x^431 + x^427 + x^425 + x^421 + x^414 + x^412 + x^411 + x^409 + x^407 + x^406 + x^405 + x^403 + x^401 + x^400 + x^399 + x^398 + x^397 + x^396 + x^395 + x^394 + x^389 + x^385 + x^383 + x^380 + x^377 + x^376 + x^375 + x^374 + x^373 + x^372 + x^370 + x^367 + x^366 + x^365 + x^364 + x^363 + x^362 + x^360 + x^358 + x^356 + x^352 + x^351 + x^350 + x^349 + x^346 + x^342 + x^340 + x^338 + x^336 + x^335 + x^330 + x^329 + x^325 + x^324 + x^323 + x^321 + x^317 + x^314 + x^312 + x^307 + x^304 + x^303 + x^301 + x^298 + x^296 + x^295 + x^294 + x^293 + x^290 + x^289 + x^288 + x^287 + x^286 + x^285 + x^278 + x^277 + x^274 + x^273 + x^272 + x^270 + x^267 + x^265 + x^261 + x^260 + x^259 + x^258 + x^257 + x^256 + x^255 + x^254 + x^252 + x^249 + x^243 + x^241 + x^240 + x^239 + x^238 + x^235 + x^232 + x^231 + x^230 + x^227 + x^226 + x^224 + x^222 + x^221 + x^220 + x^219 + x^215 + x^214 + x^213 + x^211 + x^210 + x^209 + x^207 + x^206 + x^205 + x^200 + x^198 + x^195 + x^193 + x^192 + x^190 + x^186 + x^185 + x^181 + x^178 + x^176 + x^175 + x^172 + x^170 + x^169 + x^168 + x^166 + x^164 + x^158 + x^153 + x^152 + x^150 + x^149 + x^148 + x^147 + x^146 + x^143 + x^142 + x^140 + x^139 + x^136 + x^134 + x^133 + x^128 + x^125 + x^122 + x^121 + x^120 + x^116 + x^115 + x^114 + x^112 + x^111 + x^107 + x^106 + x^103 + x^101 + x^100 + x^99 + x^98 + x^96 + x^95 + x^94 + x^93 + x^92 + x^89 + x^88 + x^87 + x^86 + x^85 + x^84 + x^81 + x^79 + x^77 + x^76 + x^74 + x^72 + x^71 + x^70 + x^69 + x^65 + x^64 + x^62 + x^55 + x^53 + x^49 + x^48 + x^46 + x^44 + x^43 + x^39 + x^38 + x^37 + x^35 + x^33 + x^32 + x^31 + x^29 + x^27 + x^26 + x^24 + x^23 + x^22 + x^20 + x^18 + x^17 + x^8 + 1
+
+14-19-11 415 x^928 + x^898 + x^882 + x^870 + x^863 + x^862 + x^860 + x^854 + x^852 + x^844 + x^843 + x^833 + x^832 + x^825 + x^822 + x^819 + x^817 + x^816 + x^813 + x^811 + x^802 + x^798 + x^797 + x^795 + x^794 + x^790 + x^789 + x^787 + x^786 + x^781 + x^778 + x^776 + x^773 + x^772 + x^771 + x^768 + x^759 + x^754 + x^749 + x^746 + x^744 + x^743 + x^741 + x^740 + x^735 + x^734 + x^733 + x^730 + x^729 + x^725 + x^722 + x^717 + x^714 + x^711 + x^706 + x^705 + x^698 + x^697 + x^695 + x^691 + x^687 + x^686 + x^683 + x^681 + x^675 + x^674 + x^673 + x^672 + x^671 + x^670 + x^667 + x^665 + x^662 + x^661 + x^660 + x^658 + x^657 + x^656 + x^655 + x^654 + x^652 + x^649 + x^648 + x^645 + x^643 + x^642 + x^638 + x^636 + x^635 + x^634 + x^633 + x^632 + x^630 + x^629 + x^627 + x^626 + x^625 + x^624 + x^623 + x^622 + x^620 + x^617 + x^616 + x^615 + x^613 + x^612 + x^611 + x^608 + x^604 + x^603 + x^602 + x^599 + x^598 + x^597 + x^595 + x^594 + x^593 + x^592 + x^591 + x^590 + x^587 + x^586 + x^585 + x^584 + x^582 + x^580 + x^579 + x^578 + x^577 + x^570 + x^569 + x^568 + x^567 + x^566 + x^563 + x^562 + x^560 + x^558 + x^552 + x^550 + x^549 + x^546 + x^544 + x^543 + x^540 + x^537 + x^536 + x^535 + x^533 + x^532 + x^531 + x^530 + x^529 + x^527 + x^526 + x^522 + x^521 + x^519 + x^517 + x^514 + x^513 + x^512 + x^511 + x^510 + x^509 + x^507 + x^506 + x^504 + x^503 + x^502 + x^501 + x^500 + x^499 + x^498 + x^496 + x^494 + x^492 + x^491 + x^489 + x^488 + x^487 + x^485 + x^480 + x^479 + x^478 + x^475 + x^472 + x^463 + x^458 + x^455 + x^453 + x^452 + x^448 + x^443 + x^438 + x^436 + x^435 + x^432 + x^429 + x^428 + x^427 + x^421 + x^420 + x^419 + x^418 + x^417 + x^416 + x^414 + x^412 + x^411 + x^410 + x^406 + x^405 + x^404 + x^402 + x^401 + x^400 + x^399 + x^393 + x^388 + x^387 + x^386 + x^385 + x^384 + x^380 + x^379 + x^378 + x^376 + x^375 + x^373 + x^370 + x^368 + x^367 + x^365 + x^363 + x^362 + x^359 + x^358 + x^357 + x^356 + x^353 + x^350 + x^347 + x^343 + x^342 + x^341 + x^339 + x^338 + x^334 + x^333 + x^327 + x^325 + x^323 + x^321 + x^318 + x^317 + x^314 + x^310 + x^309 + x^308 + x^307 + x^306 + x^305 + x^304 + x^301 + x^300 + x^298 + x^295 + x^292 + x^288 + x^286 + x^285 + x^283 + x^282 + x^281 + x^278 + x^277 + x^275 + x^270 + x^269 + x^263 + x^260 + x^256 + x^254 + x^253 + x^250 + x^249 + x^248 + x^245 + x^244 + x^241 + x^239 + x^237 + x^233 + x^227 + x^225 + x^223 + x^222 + x^220 + x^219 + x^218 + x^216 + x^214 + x^212 + x^207 + x^203 + x^201 + x^200 + x^198 + x^197 + x^196 + x^195 + x^191 + x^189 + x^188 + x^184 + x^183 + x^181 + x^180 + x^179 + x^176 + x^174 + x^173 + x^170 + x^169 + x^168 + x^167 + x^165 + x^164 + x^163 + x^162 + x^161 + x^159 + x^158 + x^157 + x^155 + x^154 + x^152 + x^151 + x^150 + x^147 + x^144 + x^143 + x^142 + x^140 + x^139 + x^138 + x^134 + x^131 + x^130 + x^129 + x^124 + x^123 + x^122 + x^121 + x^120 + x^116 + x^115 + x^114 + x^111 + x^110 + x^108 + x^106 + x^104 + x^103 + x^99 + x^98 + x^95 + x^93 + x^91 + x^87 + x^84 + x^83 + x^80 + x^77 + x^76 + x^75 + x^74 + x^73 + x^70 + x^65 + x^64 + x^63 + x^62 + x^61 + x^57 + x^56 + x^55 + x^53 + x^51 + x^50 + x^49 + x^47 + x^46 + x^45 + x^43 + x^42 + x^41 + x^39 + x^37 + x^36 + x^33 + x^31 + x^29 + x^28 + x^24 + x^23 + x^22 + x^21 + x^18 + x^17 + x^16 + x^11 + x^10 + 1
+
+34-37-5 415 x^928 + x^898 + x^889 + x^874 + x^870 + x^861 + x^846 + x^844 + x^839 + x^835 + x^833 + x^831 + x^818 + x^816 + x^812 + x^809 + x^808 + x^805 + x^804 + x^794 + x^792 + x^790 + x^788 + x^787 + x^784 + x^783 + x^778 + x^776 + x^775 + x^773 + x^772 + x^770 + x^769 + x^768 + x^764 + x^760 + x^759 + x^757 + x^756 + x^755 + x^754 + x^749 + x^748 + x^744 + x^740 + x^737 + x^735 + x^730 + x^729 + x^728 + x^727 + x^726 + x^725 + x^721 + x^720 + x^719 + x^718 + x^716 + x^715 + x^713 + x^712 + x^710 + x^709 + x^706 + x^699 + x^695 + x^689 + x^686 + x^682 + x^681 + x^680 + x^677 + x^674 + x^673 + x^672 + x^671 + x^665 + x^664 + x^663 + x^662 + x^661 + x^660 + x^657 + x^656 + x^651 + x^649 + x^646 + x^640 + x^639 + x^635 + x^634 + x^633 + x^632 + x^629 + x^628 + x^624 + x^623 + x^621 + x^620 + x^616 + x^615 + x^614 + x^613 + x^611 + x^610 + x^609 + x^607 + x^606 + x^605 + x^604 + x^601 + x^599 + x^597 + x^596 + x^595 + x^593 + x^591 + x^590 + x^585 + x^584 + x^583 + x^582 + x^580 + x^577 + x^576 + x^573 + x^569 + x^567 + x^564 + x^560 + x^559 + x^558 + x^557 + x^556 + x^555 + x^552 + x^551 + x^550 + x^547 + x^545 + x^544 + x^542 + x^541 + x^540 + x^539 + x^538 + x^535 + x^534 + x^533 + x^526 + x^523 + x^520 + x^518 + x^517 + x^515 + x^514 + x^513 + x^511 + x^510 + x^509 + x^504 + x^503 + x^502 + x^501 + x^496 + x^495 + x^494 + x^493 + x^492 + x^489 + x^485 + x^484 + x^482 + x^481 + x^478 + x^475 + x^472 + x^469 + x^468 + x^467 + x^465 + x^464 + x^462 + x^460 + x^455 + x^453 + x^452 + x^451 + x^449 + x^448 + x^447 + x^446 + x^445 + x^443 + x^442 + x^441 + x^438 + x^435 + x^434 + x^432 + x^431 + x^430 + x^427 + x^424 + x^423 + x^422 + x^419 + x^412 + x^411 + x^409 + x^408 + x^406 + x^405 + x^404 + x^403 + x^401 + x^400 + x^399 + x^393 + x^390 + x^389 + x^387 + x^385 + x^384 + x^380 + x^378 + x^376 + x^374 + x^372 + x^371 + x^370 + x^369 + x^366 + x^365 + x^360 + x^359 + x^357 + x^350 + x^349 + x^347 + x^346 + x^345 + x^344 + x^342 + x^341 + x^340 + x^337 + x^335 + x^334 + x^332 + x^331 + x^330 + x^328 + x^327 + x^325 + x^323 + x^322 + x^321 + x^320 + x^316 + x^314 + x^310 + x^308 + x^306 + x^305 + x^304 + x^301 + x^300 + x^295 + x^291 + x^290 + x^289 + x^288 + x^287 + x^283 + x^281 + x^280 + x^279 + x^277 + x^274 + x^272 + x^271 + x^268 + x^266 + x^264 + x^263 + x^261 + x^259 + x^255 + x^254 + x^253 + x^250 + x^249 + x^246 + x^244 + x^242 + x^241 + x^237 + x^233 + x^230 + x^229 + x^227 + x^223 + x^222 + x^217 + x^216 + x^208 + x^207 + x^206 + x^205 + x^204 + x^203 + x^198 + x^196 + x^192 + x^191 + x^190 + x^189 + x^188 + x^187 + x^186 + x^185 + x^182 + x^181 + x^180 + x^178 + x^175 + x^171 + x^166 + x^165 + x^164 + x^163 + x^162 + x^161 + x^159 + x^157 + x^156 + x^149 + x^148 + x^146 + x^145 + x^143 + x^142 + x^141 + x^140 + x^139 + x^138 + x^136 + x^135 + x^131 + x^130 + x^129 + x^127 + x^125 + x^124 + x^117 + x^115 + x^113 + x^110 + x^108 + x^107 + x^106 + x^105 + x^103 + x^99 + x^98 + x^95 + x^93 + x^90 + x^87 + x^84 + x^83 + x^81 + x^80 + x^79 + x^78 + x^77 + x^72 + x^71 + x^68 + x^65 + x^64 + x^63 + x^62 + x^59 + x^58 + x^56 + x^55 + x^54 + x^53 + x^52 + x^51 + x^46 + x^45 + x^44 + x^43 + x^40 + x^39 + x^36 + x^35 + x^33 + x^32 + x^31 + x^30 + x^27 + x^25 + x^24 + x^22 + x^18 + x^17 + x^14 + x^13 + x^12 + x^10 + 1
+
+37-3-56 415 x^928 + x^898 + x^878 + x^870 + x^862 + x^860 + x^849 + x^840 + x^831 + x^822 + x^819 + x^818 + x^811 + x^802 + x^801 + x^796 + x^795 + x^794 + x^793 + x^790 + x^789 + x^784 + x^781 + x^780 + x^777 + x^775 + x^772 + x^766 + x^760 + x^758 + x^755 + x^753 + x^752 + x^747 + x^745 + x^744 + x^743 + x^740 + x^738 + x^737 + x^736 + x^732 + x^730 + x^729 + x^728 + x^726 + x^721 + x^716 + x^715 + x^713 + x^712 + x^711 + x^710 + x^709 + x^706 + x^705 + x^702 + x^700 + x^699 + x^698 + x^697 + x^696 + x^693 + x^692 + x^690 + x^687 + x^686 + x^684 + x^683 + x^682 + x^681 + x^680 + x^678 + x^675 + x^674 + x^673 + x^672 + x^670 + x^669 + x^667 + x^664 + x^662 + x^661 + x^660 + x^658 + x^657 + x^656 + x^654 + x^653 + x^652 + x^650 + x^649 + x^648 + x^645 + x^644 + x^641 + x^639 + x^635 + x^634 + x^631 + x^630 + x^629 + x^628 + x^622 + x^621 + x^620 + x^617 + x^616 + x^614 + x^610 + x^609 + x^608 + x^606 + x^604 + x^601 + x^600 + x^598 + x^597 + x^596 + x^593 + x^592 + x^590 + x^588 + x^587 + x^586 + x^585 + x^584 + x^583 + x^579 + x^578 + x^575 + x^574 + x^573 + x^569 + x^568 + x^566 + x^564 + x^563 + x^561 + x^559 + x^557 + x^556 + x^553 + x^552 + x^550 + x^548 + x^546 + x^543 + x^542 + x^541 + x^540 + x^538 + x^537 + x^536 + x^533 + x^532 + x^529 + x^528 + x^527 + x^525 + x^522 + x^520 + x^519 + x^518 + x^517 + x^515 + x^514 + x^513 + x^509 + x^507 + x^506 + x^504 + x^503 + x^502 + x^499 + x^495 + x^494 + x^493 + x^492 + x^490 + x^486 + x^482 + x^481 + x^480 + x^479 + x^477 + x^476 + x^475 + x^474 + x^473 + x^472 + x^470 + x^468 + x^467 + x^463 + x^457 + x^453 + x^451 + x^448 + x^446 + x^445 + x^440 + x^438 + x^437 + x^434 + x^433 + x^432 + x^431 + x^430 + x^425 + x^424 + x^423 + x^417 + x^414 + x^409 + x^407 + x^406 + x^405 + x^402 + x^400 + x^399 + x^398 + x^397 + x^396 + x^395 + x^394 + x^391 + x^389 + x^387 + x^386 + x^384 + x^383 + x^379 + x^377 + x^372 + x^371 + x^369 + x^368 + x^366 + x^365 + x^364 + x^361 + x^359 + x^357 + x^354 + x^351 + x^348 + x^347 + x^340 + x^339 + x^337 + x^336 + x^334 + x^329 + x^327 + x^326 + x^325 + x^322 + x^320 + x^318 + x^315 + x^314 + x^313 + x^312 + x^310 + x^309 + x^308 + x^306 + x^305 + x^301 + x^300 + x^298 + x^294 + x^293 + x^292 + x^291 + x^288 + x^285 + x^284 + x^282 + x^279 + x^275 + x^272 + x^271 + x^270 + x^269 + x^268 + x^266 + x^259 + x^257 + x^254 + x^253 + x^251 + x^250 + x^248 + x^246 + x^244 + x^243 + x^242 + x^238 + x^237 + x^234 + x^233 + x^232 + x^231 + x^230 + x^227 + x^223 + x^222 + x^221 + x^219 + x^216 + x^215 + x^212 + x^207 + x^205 + x^203 + x^200 + x^199 + x^198 + x^196 + x^195 + x^193 + x^191 + x^187 + x^185 + x^183 + x^181 + x^179 + x^178 + x^177 + x^174 + x^171 + x^170 + x^168 + x^166 + x^165 + x^163 + x^160 + x^156 + x^155 + x^154 + x^151 + x^150 + x^149 + x^146 + x^145 + x^142 + x^141 + x^136 + x^135 + x^134 + x^132 + x^128 + x^127 + x^125 + x^121 + x^118 + x^117 + x^116 + x^113 + x^112 + x^111 + x^108 + x^106 + x^105 + x^104 + x^102 + x^101 + x^100 + x^99 + x^96 + x^95 + x^94 + x^89 + x^85 + x^83 + x^81 + x^80 + x^79 + x^69 + x^65 + x^63 + x^62 + x^61 + x^59 + x^58 + x^57 + x^56 + x^52 + x^49 + x^46 + x^45 + x^43 + x^42 + x^41 + x^40 + x^39 + x^38 + x^37 + x^36 + x^33 + x^32 + x^28 + x^24 + x^23 + x^20 + x^18 + x^17 + x^14 + x^11 + x^10 + x^9 + x^8 + 1
+
+55-11-54 417 x^928 + x^898 + x^896 + x^870 + x^867 + x^866 + x^864 + x^853 + x^846 + x^837 + x^836 + x^835 + x^828 + x^826 + x^824 + x^823 + x^817 + x^814 + x^812 + x^810 + x^808 + x^807 + x^806 + x^805 + x^804 + x^803 + x^802 + x^800 + x^796 + x^791 + x^789 + x^786 + x^784 + x^781 + x^780 + x^777 + x^772 + x^771 + x^770 + x^767 + x^762 + x^761 + x^757 + x^753 + x^747 + x^742 + x^740 + x^739 + x^737 + x^736 + x^735 + x^734 + x^733 + x^731 + x^730 + x^725 + x^723 + x^722 + x^717 + x^715 + x^708 + x^707 + x^705 + x^704 + x^703 + x^699 + x^698 + x^695 + x^690 + x^689 + x^686 + x^685 + x^684 + x^682 + x^681 + x^680 + x^678 + x^677 + x^675 + x^669 + x^667 + x^666 + x^665 + x^664 + x^663 + x^662 + x^661 + x^660 + x^658 + x^657 + x^656 + x^655 + x^654 + x^651 + x^650 + x^646 + x^645 + x^643 + x^641 + x^640 + x^639 + x^637 + x^634 + x^633 + x^632 + x^631 + x^627 + x^624 + x^622 + x^620 + x^617 + x^616 + x^615 + x^614 + x^613 + x^608 + x^601 + x^600 + x^599 + x^595 + x^592 + x^591 + x^590 + x^586 + x^580 + x^579 + x^578 + x^577 + x^576 + x^575 + x^571 + x^570 + x^569 + x^567 + x^566 + x^565 + x^564 + x^563 + x^562 + x^561 + x^560 + x^558 + x^557 + x^555 + x^554 + x^553 + x^552 + x^551 + x^550 + x^549 + x^545 + x^543 + x^542 + x^539 + x^537 + x^532 + x^530 + x^526 + x^525 + x^520 + x^519 + x^517 + x^515 + x^513 + x^511 + x^510 + x^508 + x^504 + x^502 + x^501 + x^498 + x^493 + x^492 + x^490 + x^489 + x^488 + x^487 + x^485 + x^484 + x^483 + x^481 + x^480 + x^479 + x^477 + x^475 + x^473 + x^472 + x^469 + x^468 + x^467 + x^466 + x^463 + x^462 + x^461 + x^459 + x^455 + x^453 + x^451 + x^450 + x^449 + x^445 + x^444 + x^443 + x^442 + x^441 + x^440 + x^437 + x^435 + x^434 + x^431 + x^430 + x^429 + x^427 + x^426 + x^422 + x^421 + x^420 + x^413 + x^410 + x^409 + x^408 + x^407 + x^405 + x^403 + x^402 + x^401 + x^397 + x^396 + x^393 + x^389 + x^386 + x^384 + x^380 + x^379 + x^376 + x^373 + x^372 + x^370 + x^369 + x^367 + x^365 + x^364 + x^363 + x^358 + x^356 + x^355 + x^354 + x^353 + x^349 + x^345 + x^342 + x^334 + x^332 + x^331 + x^329 + x^325 + x^324 + x^322 + x^316 + x^315 + x^314 + x^312 + x^310 + x^307 + x^306 + x^298 + x^297 + x^296 + x^294 + x^293 + x^292 + x^288 + x^285 + x^284 + x^283 + x^282 + x^279 + x^273 + x^271 + x^267 + x^262 + x^257 + x^255 + x^253 + x^252 + x^251 + x^250 + x^248 + x^247 + x^245 + x^244 + x^243 + x^240 + x^238 + x^237 + x^236 + x^234 + x^232 + x^229 + x^224 + x^223 + x^222 + x^221 + x^218 + x^216 + x^215 + x^213 + x^211 + x^210 + x^209 + x^207 + x^205 + x^203 + x^202 + x^201 + x^198 + x^195 + x^194 + x^193 + x^192 + x^190 + x^189 + x^187 + x^186 + x^185 + x^184 + x^183 + x^182 + x^181 + x^179 + x^177 + x^176 + x^175 + x^174 + x^172 + x^170 + x^167 + x^160 + x^157 + x^156 + x^153 + x^151 + x^150 + x^149 + x^143 + x^140 + x^137 + x^136 + x^134 + x^133 + x^129 + x^128 + x^124 + x^123 + x^120 + x^118 + x^117 + x^116 + x^115 + x^114 + x^112 + x^111 + x^110 + x^108 + x^105 + x^104 + x^102 + x^101 + x^100 + x^98 + x^97 + x^93 + x^92 + x^91 + x^90 + x^88 + x^87 + x^85 + x^81 + x^79 + x^77 + x^76 + x^74 + x^73 + x^72 + x^70 + x^65 + x^63 + x^62 + x^61 + x^59 + x^55 + x^53 + x^51 + x^50 + x^47 + x^46 + x^45 + x^44 + x^43 + x^40 + x^38 + x^34 + x^32 + x^30 + x^29 + x^28 + x^27 + x^24 + x^22 + x^21 + x^18 + x^17 + x^14 + x^11 + x^4 + 1
+
+30-3-41 419 x^928 + x^906 + x^898 + x^884 + x^879 + x^876 + x^870 + x^862 + x^854 + x^852 + x^849 + x^844 + x^835 + x^832 + x^829 + x^825 + x^822 + x^819 + x^818 + x^813 + x^812 + x^807 + x^805 + x^803 + x^802 + x^798 + x^795 + x^794 + x^792 + x^790 + x^789 + x^788 + x^786 + x^785 + x^778 + x^777 + x^769 + x^768 + x^762 + x^760 + x^753 + x^751 + x^748 + x^747 + x^746 + x^742 + x^738 + x^735 + x^734 + x^733 + x^731 + x^729 + x^726 + x^725 + x^723 + x^719 + x^718 + x^716 + x^713 + x^706 + x^703 + x^702 + x^701 + x^700 + x^699 + x^696 + x^693 + x^690 + x^687 + x^686 + x^685 + x^684 + x^682 + x^679 + x^677 + x^673 + x^672 + x^671 + x^670 + x^664 + x^659 + x^656 + x^653 + x^651 + x^650 + x^647 + x^643 + x^642 + x^639 + x^637 + x^635 + x^633 + x^630 + x^627 + x^625 + x^624 + x^621 + x^616 + x^615 + x^614 + x^613 + x^612 + x^607 + x^604 + x^603 + x^600 + x^597 + x^596 + x^595 + x^593 + x^592 + x^591 + x^588 + x^586 + x^583 + x^581 + x^580 + x^578 + x^575 + x^574 + x^571 + x^569 + x^568 + x^567 + x^566 + x^565 + x^564 + x^562 + x^560 + x^559 + x^558 + x^557 + x^555 + x^554 + x^553 + x^552 + x^550 + x^546 + x^545 + x^543 + x^542 + x^537 + x^535 + x^534 + x^532 + x^530 + x^527 + x^525 + x^523 + x^521 + x^520 + x^512 + x^506 + x^505 + x^504 + x^503 + x^501 + x^500 + x^499 + x^498 + x^497 + x^495 + x^494 + x^493 + x^489 + x^487 + x^485 + x^484 + x^479 + x^478 + x^477 + x^475 + x^474 + x^471 + x^470 + x^469 + x^468 + x^467 + x^466 + x^464 + x^462 + x^459 + x^458 + x^457 + x^456 + x^451 + x^449 + x^448 + x^447 + x^446 + x^443 + x^441 + x^440 + x^439 + x^437 + x^435 + x^434 + x^433 + x^432 + x^431 + x^430 + x^427 + x^425 + x^424 + x^423 + x^420 + x^419 + x^418 + x^417 + x^416 + x^414 + x^412 + x^410 + x^409 + x^405 + x^404 + x^402 + x^401 + x^400 + x^396 + x^394 + x^393 + x^391 + x^390 + x^389 + x^388 + x^387 + x^386 + x^385 + x^380 + x^379 + x^369 + x^368 + x^363 + x^362 + x^361 + x^360 + x^359 + x^355 + x^354 + x^351 + x^347 + x^346 + x^345 + x^342 + x^337 + x^336 + x^332 + x^328 + x^324 + x^322 + x^321 + x^319 + x^318 + x^317 + x^315 + x^312 + x^310 + x^309 + x^307 + x^303 + x^302 + x^300 + x^298 + x^295 + x^289 + x^288 + x^287 + x^286 + x^285 + x^284 + x^283 + x^282 + x^281 + x^276 + x^275 + x^273 + x^272 + x^271 + x^268 + x^265 + x^263 + x^262 + x^260 + x^259 + x^255 + x^254 + x^253 + x^252 + x^249 + x^245 + x^244 + x^243 + x^242 + x^241 + x^240 + x^239 + x^236 + x^235 + x^233 + x^232 + x^231 + x^230 + x^224 + x^223 + x^222 + x^221 + x^218 + x^215 + x^214 + x^213 + x^209 + x^206 + x^204 + x^199 + x^197 + x^196 + x^194 + x^190 + x^186 + x^185 + x^183 + x^182 + x^181 + x^180 + x^179 + x^178 + x^177 + x^176 + x^175 + x^174 + x^173 + x^168 + x^167 + x^166 + x^165 + x^164 + x^163 + x^162 + x^161 + x^159 + x^158 + x^156 + x^155 + x^153 + x^151 + x^148 + x^144 + x^143 + x^142 + x^141 + x^139 + x^136 + x^135 + x^131 + x^129 + x^128 + x^127 + x^126 + x^125 + x^124 + x^123 + x^121 + x^119 + x^118 + x^116 + x^113 + x^111 + x^109 + x^107 + x^106 + x^103 + x^102 + x^100 + x^99 + x^98 + x^96 + x^93 + x^92 + x^90 + x^86 + x^85 + x^83 + x^82 + x^80 + x^76 + x^73 + x^72 + x^71 + x^70 + x^67 + x^66 + x^64 + x^61 + x^60 + x^59 + x^56 + x^53 + x^50 + x^49 + x^45 + x^44 + x^42 + x^39 + x^36 + x^35 + x^30 + x^28 + x^25 + x^22 + x^19 + x^18 + x^17 + x^15 + x^14 + x^11 + x^10 + x^5 + 1
+
+11-45-50 423 x^928 + x^898 + x^891 + x^870 + x^862 + x^861 + x^858 + x^857 + x^854 + x^851 + x^828 + x^825 + x^824 + x^822 + x^818 + x^814 + x^811 + x^808 + x^802 + x^800 + x^798 + x^797 + x^787 + x^786 + x^785 + x^783 + x^782 + x^781 + x^776 + x^772 + x^771 + x^770 + x^768 + x^765 + x^760 + x^758 + x^756 + x^754 + x^750 + x^749 + x^746 + x^742 + x^738 + x^737 + x^736 + x^735 + x^734 + x^732 + x^729 + x^723 + x^719 + x^718 + x^716 + x^715 + x^714 + x^713 + x^708 + x^707 + x^705 + x^704 + x^703 + x^702 + x^701 + x^700 + x^698 + x^697 + x^696 + x^694 + x^692 + x^688 + x^684 + x^683 + x^681 + x^680 + x^678 + x^666 + x^664 + x^663 + x^662 + x^660 + x^659 + x^658 + x^656 + x^654 + x^653 + x^652 + x^651 + x^650 + x^649 + x^647 + x^645 + x^642 + x^641 + x^639 + x^638 + x^637 + x^636 + x^634 + x^632 + x^631 + x^626 + x^625 + x^623 + x^620 + x^617 + x^616 + x^614 + x^612 + x^610 + x^609 + x^607 + x^605 + x^603 + x^601 + x^600 + x^598 + x^597 + x^596 + x^595 + x^594 + x^591 + x^589 + x^588 + x^586 + x^585 + x^584 + x^581 + x^579 + x^578 + x^577 + x^576 + x^575 + x^573 + x^572 + x^570 + x^569 + x^568 + x^566 + x^561 + x^559 + x^558 + x^557 + x^554 + x^552 + x^551 + x^550 + x^549 + x^548 + x^546 + x^544 + x^543 + x^541 + x^540 + x^538 + x^533 + x^531 + x^529 + x^528 + x^523 + x^519 + x^515 + x^512 + x^511 + x^510 + x^508 + x^507 + x^506 + x^501 + x^498 + x^497 + x^496 + x^495 + x^494 + x^492 + x^490 + x^489 + x^488 + x^487 + x^486 + x^485 + x^483 + x^477 + x^476 + x^474 + x^472 + x^470 + x^469 + x^467 + x^465 + x^462 + x^460 + x^458 + x^452 + x^451 + x^449 + x^447 + x^446 + x^445 + x^442 + x^441 + x^440 + x^437 + x^436 + x^434 + x^433 + x^431 + x^428 + x^427 + x^426 + x^425 + x^423 + x^422 + x^420 + x^419 + x^418 + x^417 + x^415 + x^414 + x^413 + x^412 + x^411 + x^409 + x^407 + x^404 + x^403 + x^402 + x^399 + x^398 + x^396 + x^395 + x^392 + x^391 + x^389 + x^388 + x^387 + x^386 + x^385 + x^384 + x^381 + x^379 + x^378 + x^377 + x^375 + x^373 + x^369 + x^367 + x^365 + x^364 + x^362 + x^359 + x^358 + x^357 + x^355 + x^351 + x^348 + x^347 + x^346 + x^345 + x^344 + x^343 + x^335 + x^334 + x^332 + x^328 + x^325 + x^324 + x^321 + x^319 + x^318 + x^316 + x^314 + x^312 + x^311 + x^310 + x^304 + x^300 + x^297 + x^296 + x^294 + x^293 + x^292 + x^291 + x^289 + x^288 + x^285 + x^283 + x^277 + x^276 + x^274 + x^271 + x^270 + x^269 + x^268 + x^265 + x^264 + x^260 + x^259 + x^258 + x^257 + x^256 + x^252 + x^251 + x^249 + x^248 + x^247 + x^246 + x^244 + x^242 + x^238 + x^236 + x^233 + x^232 + x^231 + x^230 + x^229 + x^228 + x^227 + x^222 + x^220 + x^218 + x^214 + x^212 + x^209 + x^208 + x^207 + x^204 + x^203 + x^202 + x^200 + x^193 + x^190 + x^189 + x^188 + x^186 + x^185 + x^183 + x^178 + x^176 + x^174 + x^171 + x^169 + x^168 + x^166 + x^165 + x^163 + x^162 + x^161 + x^158 + x^156 + x^155 + x^154 + x^153 + x^150 + x^147 + x^146 + x^145 + x^141 + x^136 + x^134 + x^132 + x^128 + x^127 + x^126 + x^123 + x^120 + x^119 + x^114 + x^112 + x^111 + x^105 + x^104 + x^101 + x^100 + x^98 + x^97 + x^96 + x^95 + x^94 + x^92 + x^91 + x^88 + x^87 + x^85 + x^84 + x^83 + x^80 + x^78 + x^77 + x^76 + x^74 + x^73 + x^72 + x^68 + x^64 + x^62 + x^61 + x^60 + x^56 + x^55 + x^54 + x^53 + x^50 + x^46 + x^42 + x^41 + x^40 + x^39 + x^36 + x^32 + x^31 + x^30 + x^28 + x^25 + x^24 + x^16 + x^15 + x^14 + x^13 + x^10 + x^9 + x^6 + x^3 + 1
+
+50-19-47 423 x^928 + x^906 + x^898 + x^897 + x^884 + x^876 + x^870 + x^862 + x^854 + x^840 + x^836 + x^835 + x^832 + x^831 + x^830 + x^821 + x^814 + x^813 + x^812 + x^810 + x^808 + x^805 + x^803 + x^796 + x^794 + x^792 + x^791 + x^786 + x^785 + x^783 + x^777 + x^774 + x^773 + x^767 + x^766 + x^764 + x^762 + x^761 + x^760 + x^759 + x^758 + x^754 + x^750 + x^748 + x^747 + x^746 + x^743 + x^742 + x^739 + x^734 + x^732 + x^728 + x^727 + x^724 + x^722 + x^720 + x^718 + x^716 + x^714 + x^713 + x^712 + x^711 + x^709 + x^708 + x^705 + x^704 + x^702 + x^699 + x^698 + x^695 + x^694 + x^693 + x^692 + x^691 + x^688 + x^686 + x^683 + x^682 + x^681 + x^679 + x^676 + x^674 + x^672 + x^671 + x^668 + x^664 + x^663 + x^661 + x^659 + x^657 + x^656 + x^654 + x^652 + x^646 + x^645 + x^641 + x^638 + x^635 + x^634 + x^632 + x^629 + x^628 + x^619 + x^618 + x^617 + x^615 + x^613 + x^612 + x^610 + x^609 + x^607 + x^606 + x^605 + x^604 + x^603 + x^602 + x^598 + x^597 + x^596 + x^595 + x^593 + x^591 + x^590 + x^589 + x^584 + x^583 + x^582 + x^581 + x^580 + x^579 + x^576 + x^575 + x^573 + x^569 + x^568 + x^567 + x^565 + x^564 + x^562 + x^556 + x^554 + x^552 + x^551 + x^550 + x^548 + x^547 + x^546 + x^545 + x^542 + x^541 + x^540 + x^539 + x^537 + x^535 + x^534 + x^532 + x^528 + x^526 + x^525 + x^524 + x^522 + x^521 + x^519 + x^515 + x^513 + x^510 + x^508 + x^507 + x^506 + x^505 + x^504 + x^502 + x^501 + x^500 + x^499 + x^496 + x^495 + x^494 + x^492 + x^490 + x^489 + x^486 + x^485 + x^484 + x^483 + x^481 + x^479 + x^478 + x^476 + x^474 + x^471 + x^469 + x^467 + x^465 + x^463 + x^458 + x^456 + x^455 + x^454 + x^451 + x^449 + x^448 + x^443 + x^442 + x^440 + x^439 + x^437 + x^436 + x^433 + x^432 + x^431 + x^430 + x^428 + x^427 + x^426 + x^425 + x^424 + x^421 + x^420 + x^416 + x^415 + x^413 + x^412 + x^411 + x^410 + x^409 + x^408 + x^406 + x^405 + x^403 + x^400 + x^399 + x^398 + x^396 + x^395 + x^393 + x^391 + x^388 + x^387 + x^386 + x^381 + x^380 + x^377 + x^376 + x^375 + x^374 + x^373 + x^371 + x^370 + x^369 + x^368 + x^361 + x^359 + x^358 + x^357 + x^355 + x^352 + x^350 + x^348 + x^347 + x^346 + x^343 + x^342 + x^339 + x^337 + x^335 + x^334 + x^332 + x^329 + x^325 + x^324 + x^323 + x^322 + x^318 + x^317 + x^315 + x^314 + x^311 + x^310 + x^306 + x^304 + x^300 + x^299 + x^297 + x^295 + x^294 + x^289 + x^286 + x^283 + x^279 + x^278 + x^276 + x^275 + x^273 + x^269 + x^268 + x^266 + x^264 + x^260 + x^258 + x^257 + x^254 + x^252 + x^250 + x^248 + x^247 + x^246 + x^245 + x^241 + x^239 + x^237 + x^236 + x^235 + x^234 + x^232 + x^228 + x^227 + x^226 + x^225 + x^218 + x^215 + x^214 + x^212 + x^211 + x^210 + x^208 + x^206 + x^205 + x^204 + x^203 + x^201 + x^198 + x^196 + x^193 + x^192 + x^190 + x^189 + x^188 + x^184 + x^181 + x^180 + x^178 + x^177 + x^176 + x^175 + x^174 + x^173 + x^171 + x^169 + x^168 + x^166 + x^165 + x^164 + x^162 + x^160 + x^159 + x^158 + x^153 + x^150 + x^148 + x^147 + x^146 + x^143 + x^142 + x^139 + x^136 + x^135 + x^134 + x^133 + x^132 + x^126 + x^124 + x^121 + x^118 + x^116 + x^112 + x^109 + x^108 + x^107 + x^104 + x^101 + x^98 + x^97 + x^95 + x^93 + x^88 + x^86 + x^85 + x^84 + x^83 + x^78 + x^77 + x^73 + x^70 + x^69 + x^68 + x^66 + x^64 + x^63 + x^62 + x^58 + x^57 + x^53 + x^52 + x^50 + x^48 + x^45 + x^43 + x^42 + x^41 + x^40 + x^39 + x^38 + x^33 + x^26 + x^22 + x^21 + x^20 + x^18 + x^17 + x^10 + x^8 + 1
+
+52-27-13 427 x^928 + x^898 + x^870 + x^866 + x^858 + x^855 + x^854 + x^847 + x^844 + x^836 + x^833 + x^832 + x^829 + x^828 + x^825 + x^822 + x^818 + x^817 + x^814 + x^811 + x^808 + x^807 + x^800 + x^799 + x^798 + x^796 + x^795 + x^792 + x^789 + x^781 + x^777 + x^774 + x^770 + x^769 + x^768 + x^767 + x^765 + x^762 + x^759 + x^756 + x^755 + x^754 + x^752 + x^751 + x^748 + x^746 + x^745 + x^744 + x^740 + x^739 + x^738 + x^736 + x^735 + x^734 + x^732 + x^730 + x^729 + x^728 + x^724 + x^721 + x^719 + x^718 + x^717 + x^716 + x^713 + x^712 + x^710 + x^709 + x^706 + x^705 + x^704 + x^702 + x^701 + x^699 + x^698 + x^697 + x^695 + x^693 + x^690 + x^689 + x^687 + x^686 + x^685 + x^683 + x^682 + x^681 + x^680 + x^677 + x^676 + x^675 + x^674 + x^671 + x^669 + x^668 + x^667 + x^666 + x^665 + x^663 + x^660 + x^659 + x^655 + x^654 + x^653 + x^652 + x^650 + x^648 + x^647 + x^643 + x^642 + x^640 + x^639 + x^638 + x^635 + x^634 + x^633 + x^632 + x^630 + x^629 + x^628 + x^626 + x^624 + x^620 + x^618 + x^617 + x^616 + x^615 + x^612 + x^610 + x^607 + x^606 + x^604 + x^603 + x^602 + x^598 + x^597 + x^593 + x^589 + x^588 + x^587 + x^585 + x^583 + x^581 + x^580 + x^579 + x^578 + x^570 + x^569 + x^566 + x^565 + x^564 + x^563 + x^561 + x^559 + x^558 + x^557 + x^556 + x^555 + x^551 + x^550 + x^548 + x^547 + x^545 + x^544 + x^540 + x^539 + x^538 + x^537 + x^536 + x^535 + x^534 + x^532 + x^529 + x^528 + x^527 + x^526 + x^525 + x^524 + x^523 + x^522 + x^519 + x^517 + x^516 + x^515 + x^513 + x^512 + x^511 + x^507 + x^504 + x^502 + x^495 + x^493 + x^492 + x^491 + x^490 + x^489 + x^484 + x^483 + x^481 + x^480 + x^478 + x^466 + x^464 + x^463 + x^460 + x^459 + x^457 + x^455 + x^454 + x^451 + x^450 + x^448 + x^447 + x^435 + x^434 + x^433 + x^432 + x^431 + x^428 + x^424 + x^423 + x^422 + x^421 + x^420 + x^419 + x^414 + x^413 + x^412 + x^411 + x^410 + x^409 + x^407 + x^404 + x^401 + x^396 + x^395 + x^394 + x^391 + x^390 + x^389 + x^388 + x^385 + x^382 + x^379 + x^377 + x^372 + x^370 + x^367 + x^365 + x^362 + x^361 + x^357 + x^355 + x^354 + x^351 + x^349 + x^348 + x^345 + x^343 + x^342 + x^340 + x^338 + x^334 + x^330 + x^328 + x^324 + x^323 + x^320 + x^319 + x^318 + x^317 + x^315 + x^313 + x^310 + x^309 + x^307 + x^303 + x^302 + x^301 + x^300 + x^299 + x^298 + x^297 + x^296 + x^295 + x^292 + x^289 + x^288 + x^287 + x^285 + x^283 + x^280 + x^274 + x^273 + x^271 + x^267 + x^265 + x^264 + x^261 + x^259 + x^258 + x^256 + x^254 + x^253 + x^248 + x^247 + x^244 + x^239 + x^238 + x^237 + x^233 + x^232 + x^230 + x^229 + x^228 + x^227 + x^224 + x^221 + x^217 + x^216 + x^215 + x^214 + x^209 + x^207 + x^206 + x^205 + x^203 + x^201 + x^200 + x^199 + x^196 + x^195 + x^194 + x^192 + x^191 + x^190 + x^189 + x^187 + x^186 + x^182 + x^180 + x^177 + x^176 + x^174 + x^173 + x^170 + x^169 + x^168 + x^167 + x^164 + x^160 + x^154 + x^153 + x^152 + x^148 + x^144 + x^143 + x^142 + x^141 + x^140 + x^139 + x^135 + x^134 + x^133 + x^132 + x^129 + x^125 + x^124 + x^122 + x^121 + x^120 + x^118 + x^117 + x^116 + x^115 + x^112 + x^111 + x^110 + x^109 + x^108 + x^107 + x^106 + x^104 + x^103 + x^101 + x^96 + x^95 + x^93 + x^90 + x^87 + x^86 + x^82 + x^79 + x^77 + x^75 + x^70 + x^68 + x^67 + x^66 + x^62 + x^60 + x^57 + x^54 + x^53 + x^52 + x^51 + x^49 + x^46 + x^45 + x^43 + x^42 + x^41 + x^40 + x^39 + x^38 + x^36 + x^33 + x^31 + x^30 + x^29 + x^27 + x^26 + x^24 + x^22 + x^18 + x^7 + x^6 + 1
+
+54-9-25 433 x^928 + x^898 + x^875 + x^870 + x^860 + x^850 + x^847 + x^840 + x^835 + x^832 + x^822 + x^819 + x^815 + x^812 + x^808 + x^807 + x^805 + x^804 + x^800 + x^797 + x^794 + x^792 + x^791 + x^790 + x^787 + x^785 + x^782 + x^778 + x^777 + x^776 + x^771 + x^770 + x^767 + x^766 + x^764 + x^763 + x^760 + x^759 + x^757 + x^755 + x^754 + x^753 + x^752 + x^748 + x^743 + x^742 + x^739 + x^738 + x^737 + x^735 + x^734 + x^733 + x^731 + x^730 + x^729 + x^725 + x^724 + x^723 + x^720 + x^719 + x^717 + x^716 + x^714 + x^713 + x^711 + x^710 + x^709 + x^706 + x^705 + x^700 + x^699 + x^697 + x^696 + x^695 + x^693 + x^692 + x^691 + x^688 + x^687 + x^686 + x^685 + x^683 + x^682 + x^680 + x^676 + x^671 + x^670 + x^664 + x^663 + x^662 + x^661 + x^660 + x^658 + x^657 + x^656 + x^654 + x^653 + x^649 + x^648 + x^646 + x^645 + x^642 + x^637 + x^635 + x^633 + x^632 + x^630 + x^627 + x^624 + x^623 + x^621 + x^620 + x^619 + x^617 + x^615 + x^614 + x^613 + x^610 + x^609 + x^608 + x^607 + x^604 + x^602 + x^601 + x^600 + x^599 + x^593 + x^592 + x^591 + x^589 + x^585 + x^584 + x^580 + x^576 + x^575 + x^574 + x^570 + x^569 + x^566 + x^565 + x^564 + x^563 + x^562 + x^561 + x^559 + x^558 + x^554 + x^552 + x^551 + x^547 + x^546 + x^545 + x^543 + x^541 + x^540 + x^535 + x^532 + x^531 + x^530 + x^529 + x^525 + x^524 + x^523 + x^521 + x^520 + x^519 + x^518 + x^517 + x^516 + x^515 + x^513 + x^512 + x^510 + x^509 + x^504 + x^503 + x^502 + x^501 + x^500 + x^497 + x^496 + x^494 + x^493 + x^488 + x^487 + x^486 + x^484 + x^482 + x^481 + x^480 + x^479 + x^475 + x^472 + x^465 + x^464 + x^462 + x^461 + x^460 + x^457 + x^456 + x^455 + x^454 + x^452 + x^451 + x^450 + x^449 + x^448 + x^446 + x^445 + x^444 + x^443 + x^441 + x^438 + x^437 + x^436 + x^434 + x^432 + x^430 + x^427 + x^425 + x^424 + x^421 + x^420 + x^419 + x^418 + x^417 + x^414 + x^413 + x^410 + x^409 + x^407 + x^404 + x^403 + x^402 + x^401 + x^400 + x^399 + x^398 + x^396 + x^393 + x^392 + x^391 + x^390 + x^389 + x^385 + x^382 + x^381 + x^380 + x^379 + x^378 + x^375 + x^373 + x^372 + x^367 + x^366 + x^362 + x^358 + x^356 + x^355 + x^354 + x^353 + x^349 + x^348 + x^347 + x^342 + x^340 + x^339 + x^336 + x^334 + x^331 + x^329 + x^328 + x^327 + x^326 + x^325 + x^323 + x^319 + x^317 + x^316 + x^314 + x^313 + x^312 + x^310 + x^309 + x^308 + x^307 + x^302 + x^299 + x^298 + x^297 + x^296 + x^293 + x^291 + x^289 + x^288 + x^286 + x^285 + x^284 + x^282 + x^279 + x^274 + x^272 + x^271 + x^268 + x^266 + x^263 + x^261 + x^258 + x^255 + x^252 + x^251 + x^249 + x^248 + x^247 + x^246 + x^243 + x^242 + x^240 + x^237 + x^236 + x^234 + x^233 + x^232 + x^231 + x^228 + x^226 + x^223 + x^222 + x^221 + x^220 + x^219 + x^217 + x^216 + x^215 + x^213 + x^212 + x^210 + x^205 + x^203 + x^202 + x^199 + x^197 + x^195 + x^194 + x^193 + x^191 + x^189 + x^188 + x^187 + x^184 + x^182 + x^178 + x^173 + x^172 + x^170 + x^169 + x^167 + x^165 + x^162 + x^159 + x^158 + x^157 + x^156 + x^154 + x^149 + x^148 + x^145 + x^144 + x^141 + x^140 + x^135 + x^134 + x^133 + x^131 + x^130 + x^129 + x^127 + x^126 + x^123 + x^120 + x^119 + x^118 + x^117 + x^115 + x^110 + x^108 + x^106 + x^105 + x^104 + x^99 + x^97 + x^95 + x^89 + x^86 + x^84 + x^82 + x^78 + x^75 + x^71 + x^70 + x^69 + x^68 + x^65 + x^63 + x^62 + x^61 + x^59 + x^58 + x^51 + x^50 + x^49 + x^48 + x^47 + x^44 + x^43 + x^42 + x^39 + x^38 + x^37 + x^35 + x^30 + x^27 + x^25 + x^21 + x^19 + x^17 + x^16 + x^13 + x^12 + x^10 + x^8 + x^6 + 1
+
+56-43-35 433 x^928 + x^898 + x^896 + x^871 + x^870 + x^864 + x^848 + x^847 + x^846 + x^841 + x^840 + x^834 + x^833 + x^832 + x^829 + x^821 + x^814 + x^811 + x^808 + x^806 + x^803 + x^798 + x^797 + x^796 + x^792 + x^788 + x^786 + x^784 + x^783 + x^781 + x^779 + x^777 + x^776 + x^774 + x^773 + x^770 + x^769 + x^766 + x^762 + x^760 + x^756 + x^754 + x^752 + x^751 + x^749 + x^746 + x^745 + x^740 + x^737 + x^736 + x^734 + x^730 + x^727 + x^723 + x^721 + x^720 + x^718 + x^716 + x^714 + x^712 + x^709 + x^707 + x^706 + x^705 + x^704 + x^703 + x^702 + x^701 + x^700 + x^699 + x^697 + x^696 + x^695 + x^690 + x^689 + x^687 + x^685 + x^684 + x^682 + x^678 + x^675 + x^672 + x^670 + x^669 + x^668 + x^666 + x^665 + x^663 + x^662 + x^661 + x^659 + x^657 + x^655 + x^651 + x^650 + x^648 + x^646 + x^641 + x^639 + x^634 + x^632 + x^631 + x^630 + x^629 + x^626 + x^625 + x^623 + x^620 + x^619 + x^614 + x^612 + x^610 + x^609 + x^608 + x^607 + x^606 + x^604 + x^603 + x^602 + x^601 + x^600 + x^597 + x^596 + x^595 + x^594 + x^593 + x^591 + x^588 + x^585 + x^584 + x^583 + x^582 + x^581 + x^580 + x^578 + x^576 + x^574 + x^573 + x^572 + x^571 + x^570 + x^569 + x^563 + x^561 + x^560 + x^558 + x^556 + x^553 + x^552 + x^551 + x^550 + x^549 + x^546 + x^545 + x^544 + x^543 + x^542 + x^539 + x^538 + x^537 + x^536 + x^534 + x^532 + x^531 + x^529 + x^523 + x^519 + x^518 + x^517 + x^515 + x^514 + x^513 + x^512 + x^510 + x^509 + x^508 + x^503 + x^502 + x^501 + x^500 + x^499 + x^498 + x^496 + x^495 + x^494 + x^491 + x^490 + x^489 + x^487 + x^486 + x^484 + x^482 + x^481 + x^473 + x^471 + x^468 + x^466 + x^465 + x^464 + x^461 + x^460 + x^457 + x^456 + x^455 + x^453 + x^450 + x^448 + x^444 + x^442 + x^436 + x^435 + x^434 + x^433 + x^432 + x^431 + x^430 + x^429 + x^422 + x^421 + x^420 + x^419 + x^418 + x^417 + x^416 + x^414 + x^413 + x^412 + x^411 + x^409 + x^408 + x^407 + x^406 + x^404 + x^403 + x^402 + x^401 + x^398 + x^395 + x^392 + x^391 + x^389 + x^387 + x^385 + x^380 + x^377 + x^374 + x^372 + x^371 + x^369 + x^366 + x^363 + x^362 + x^361 + x^359 + x^358 + x^356 + x^355 + x^354 + x^353 + x^352 + x^350 + x^349 + x^348 + x^347 + x^345 + x^344 + x^343 + x^336 + x^334 + x^331 + x^330 + x^327 + x^325 + x^324 + x^322 + x^317 + x^310 + x^308 + x^307 + x^304 + x^301 + x^300 + x^299 + x^298 + x^297 + x^293 + x^290 + x^286 + x^284 + x^283 + x^282 + x^281 + x^279 + x^277 + x^275 + x^274 + x^270 + x^269 + x^267 + x^264 + x^262 + x^259 + x^254 + x^253 + x^248 + x^247 + x^245 + x^243 + x^242 + x^241 + x^237 + x^236 + x^232 + x^231 + x^230 + x^229 + x^228 + x^226 + x^225 + x^224 + x^223 + x^221 + x^218 + x^215 + x^214 + x^213 + x^212 + x^210 + x^208 + x^204 + x^202 + x^201 + x^199 + x^196 + x^195 + x^193 + x^192 + x^191 + x^190 + x^186 + x^184 + x^179 + x^178 + x^177 + x^176 + x^175 + x^174 + x^173 + x^171 + x^169 + x^167 + x^166 + x^165 + x^160 + x^158 + x^155 + x^154 + x^153 + x^152 + x^151 + x^150 + x^149 + x^148 + x^147 + x^145 + x^143 + x^140 + x^139 + x^138 + x^134 + x^132 + x^130 + x^129 + x^128 + x^127 + x^120 + x^118 + x^117 + x^115 + x^113 + x^112 + x^109 + x^108 + x^107 + x^106 + x^105 + x^101 + x^100 + x^96 + x^95 + x^94 + x^93 + x^91 + x^89 + x^88 + x^87 + x^85 + x^84 + x^83 + x^82 + x^81 + x^79 + x^77 + x^75 + x^74 + x^73 + x^72 + x^70 + x^68 + x^67 + x^65 + x^64 + x^63 + x^60 + x^58 + x^57 + x^56 + x^54 + x^53 + x^52 + x^50 + x^45 + x^44 + x^43 + x^41 + x^35 + x^30 + x^23 + x^20 + x^18 + x^15 + x^6 + 1
+
+44-9-45 441 x^928 + x^898 + x^890 + x^885 + x^880 + x^872 + x^870 + x^867 + x^860 + x^850 + x^847 + x^842 + x^837 + x^834 + x^830 + x^825 + x^824 + x^817 + x^816 + x^811 + x^808 + x^806 + x^802 + x^800 + x^798 + x^797 + x^794 + x^792 + x^790 + x^787 + x^786 + x^782 + x^778 + x^777 + x^776 + x^774 + x^773 + x^772 + x^771 + x^769 + x^768 + x^767 + x^765 + x^760 + x^759 + x^758 + x^757 + x^754 + x^750 + x^749 + x^747 + x^746 + x^745 + x^743 + x^741 + x^738 + x^737 + x^736 + x^734 + x^732 + x^725 + x^724 + x^722 + x^721 + x^720 + x^717 + x^716 + x^714 + x^713 + x^710 + x^708 + x^707 + x^705 + x^704 + x^702 + x^701 + x^699 + x^698 + x^696 + x^694 + x^692 + x^691 + x^690 + x^686 + x^683 + x^681 + x^679 + x^676 + x^674 + x^673 + x^672 + x^671 + x^668 + x^667 + x^665 + x^664 + x^663 + x^662 + x^661 + x^659 + x^658 + x^657 + x^655 + x^654 + x^652 + x^651 + x^648 + x^644 + x^643 + x^641 + x^640 + x^635 + x^634 + x^633 + x^632 + x^631 + x^630 + x^629 + x^628 + x^624 + x^621 + x^619 + x^618 + x^617 + x^616 + x^614 + x^611 + x^610 + x^608 + x^607 + x^599 + x^598 + x^596 + x^594 + x^590 + x^589 + x^588 + x^587 + x^586 + x^584 + x^581 + x^579 + x^578 + x^577 + x^575 + x^573 + x^572 + x^570 + x^569 + x^568 + x^567 + x^565 + x^564 + x^563 + x^562 + x^561 + x^559 + x^558 + x^554 + x^553 + x^552 + x^551 + x^549 + x^546 + x^544 + x^541 + x^537 + x^536 + x^535 + x^532 + x^531 + x^529 + x^526 + x^517 + x^516 + x^514 + x^511 + x^509 + x^507 + x^502 + x^501 + x^498 + x^497 + x^495 + x^494 + x^493 + x^491 + x^487 + x^486 + x^485 + x^484 + x^483 + x^482 + x^481 + x^480 + x^477 + x^474 + x^473 + x^470 + x^469 + x^467 + x^466 + x^465 + x^463 + x^462 + x^461 + x^460 + x^459 + x^457 + x^455 + x^454 + x^453 + x^451 + x^449 + x^448 + x^446 + x^443 + x^442 + x^440 + x^437 + x^436 + x^435 + x^434 + x^433 + x^431 + x^430 + x^427 + x^423 + x^419 + x^418 + x^414 + x^412 + x^411 + x^410 + x^409 + x^407 + x^406 + x^405 + x^402 + x^397 + x^395 + x^394 + x^389 + x^388 + x^384 + x^381 + x^380 + x^379 + x^378 + x^376 + x^373 + x^372 + x^371 + x^370 + x^368 + x^367 + x^366 + x^365 + x^364 + x^362 + x^361 + x^355 + x^354 + x^352 + x^350 + x^347 + x^345 + x^344 + x^343 + x^342 + x^339 + x^337 + x^335 + x^333 + x^332 + x^329 + x^327 + x^323 + x^322 + x^321 + x^320 + x^319 + x^316 + x^312 + x^310 + x^309 + x^308 + x^307 + x^305 + x^303 + x^302 + x^301 + x^298 + x^294 + x^293 + x^283 + x^282 + x^276 + x^275 + x^274 + x^271 + x^267 + x^264 + x^262 + x^261 + x^259 + x^258 + x^257 + x^256 + x^253 + x^252 + x^251 + x^250 + x^246 + x^245 + x^244 + x^243 + x^242 + x^241 + x^240 + x^238 + x^237 + x^236 + x^235 + x^233 + x^232 + x^229 + x^228 + x^225 + x^224 + x^223 + x^220 + x^216 + x^211 + x^210 + x^207 + x^205 + x^204 + x^202 + x^201 + x^200 + x^197 + x^196 + x^195 + x^194 + x^190 + x^189 + x^185 + x^183 + x^182 + x^181 + x^180 + x^179 + x^177 + x^176 + x^174 + x^173 + x^172 + x^171 + x^168 + x^167 + x^164 + x^163 + x^157 + x^156 + x^152 + x^151 + x^150 + x^148 + x^147 + x^146 + x^143 + x^142 + x^141 + x^140 + x^139 + x^138 + x^137 + x^135 + x^134 + x^133 + x^132 + x^129 + x^128 + x^127 + x^125 + x^122 + x^120 + x^119 + x^113 + x^112 + x^110 + x^109 + x^108 + x^107 + x^106 + x^105 + x^104 + x^101 + x^98 + x^97 + x^96 + x^93 + x^92 + x^91 + x^87 + x^83 + x^80 + x^78 + x^77 + x^74 + x^72 + x^66 + x^64 + x^63 + x^60 + x^59 + x^56 + x^51 + x^50 + x^49 + x^46 + x^43 + x^42 + x^41 + x^39 + x^38 + x^32 + x^31 + x^29 + x^28 + x^26 + x^24 + x^23 + x^21 + x^20 + x^19 + x^18 + x^15 + x^10 + 1
diff --git a/lib/stdlib/test/re_SUITE_data/testoutput2 b/lib/stdlib/test/re_SUITE_data/testoutput2
index 811bbefc84..61ed8d9d4e 100644
--- a/lib/stdlib/test/re_SUITE_data/testoutput2
+++ b/lib/stdlib/test/re_SUITE_data/testoutput2
@@ -14705,4 +14705,20 @@ No options
No first char
No need char
+"(?<=(a))\1?b"
+ ab
+ 0: b
+ 1: a
+ aaab
+ 0: ab
+ 1: a
+
+"(?=(a))\1?b"
+ ab
+ 0: ab
+ 1: a
+ aaab
+ 0: ab
+ 1: a
+
/-- End of testinput2 --/
diff --git a/lib/stdlib/test/re_SUITE_data/testoutput5 b/lib/stdlib/test/re_SUITE_data/testoutput5
index bab989ca7e..090e1e1c85 100644
--- a/lib/stdlib/test/re_SUITE_data/testoutput5
+++ b/lib/stdlib/test/re_SUITE_data/testoutput5
@@ -1942,4 +1942,12 @@ Need char = 'z'
0: \x{17f}
0+
+/\C[^\v]+\x80/8
+ [AΏBŀC]
+No match
+
+/\C[^\d]+\x80/8
+ [AΏBŀC]
+No match
+
/-- End of testinput5 --/
diff --git a/lib/stdlib/test/supervisor_SUITE.erl b/lib/stdlib/test/supervisor_SUITE.erl
index ed7dd04171..9370067910 100644
--- a/lib/stdlib/test/supervisor_SUITE.erl
+++ b/lib/stdlib/test/supervisor_SUITE.erl
@@ -2339,6 +2339,13 @@ order_of_children(_Config) ->
%% Test that a non-simple supervisor scales well for starting and
%% stopping many children.
scale_start_stop_many_children(_Config) ->
+ case erlang:system_info(build_type) of
+ opt -> scale_start_stop_many_children();
+ Other -> {skip,"Run on build type 'opt' only (current: '" ++
+ atom_to_list(Other)++"')"}
+ end.
+
+scale_start_stop_many_children() ->
process_flag(trap_exit, true),
{ok, _Pid} = start_link({ok, {{one_for_one, 2, 3600}, []}}),
N1 = 1000,
diff --git a/lib/stdlib/vsn.mk b/lib/stdlib/vsn.mk
index 1d833430f1..caf5ecdbb4 100644
--- a/lib/stdlib/vsn.mk
+++ b/lib/stdlib/vsn.mk
@@ -1 +1 @@
-STDLIB_VSN = 3.5.1
+STDLIB_VSN = 3.6
diff --git a/lib/syntax_tools/doc/src/notes.xml b/lib/syntax_tools/doc/src/notes.xml
index 44944e57c3..dc13fe474b 100644
--- a/lib/syntax_tools/doc/src/notes.xml
+++ b/lib/syntax_tools/doc/src/notes.xml
@@ -32,6 +32,44 @@
<p>This document describes the changes made to the Syntax_Tools
application.</p>
+<section><title>Syntax_Tools 2.1.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix the <c>TypeName</c> type in erl_syntax_lib.</p>
+ <p>
+ Own Id: OTP-15207 Aux Id: PR-1888 </p>
+ </item>
+ <item>
+ <p> Correct unfolding of the stacktrace variable. </p>
+ <p>
+ Own Id: OTP-15291 Aux Id: ERL-719 </p>
+ </item>
+ <item>
+ <p> Correct <c>erl_syntax:revert/1</c> bug regarding the
+ types <c>map()</c> and <c>tuple()</c>. </p>
+ <p>
+ Own Id: OTP-15294</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> Support bitstrings as literals in module
+ <c>erl_syntax</c>. </p>
+ <p>
+ Own Id: OTP-15165 Aux Id: PR-1842 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Syntax_Tools 2.1.5</title>
<section><title>Improvements and New Features</title>
<list>
diff --git a/lib/syntax_tools/src/erl_syntax.erl b/lib/syntax_tools/src/erl_syntax.erl
index 758aff32fd..1be644c620 100644
--- a/lib/syntax_tools/src/erl_syntax.erl
+++ b/lib/syntax_tools/src/erl_syntax.erl
@@ -3897,7 +3897,7 @@ unfold_try_clauses(Cs) ->
unfold_try_clause({clause, Pos, [{tuple, _, [{atom, _, throw},
V,
- [{var, _, '_'}]]}],
+ {var, _, '_'}]}],
Guard, Body}) ->
{clause, Pos, [V], Guard, Body};
unfold_try_clause({clause, Pos, [{tuple, _, [C, V, Stacktrace]}],
@@ -5455,8 +5455,12 @@ map_type(Fields) ->
revert_map_type(Node) ->
Pos = get_pos(Node),
- {type, Pos, map, map_type_fields(Node)}.
-
+ case map_type_fields(Node) of
+ any_size ->
+ {type, Pos, map, any};
+ Fields ->
+ {type, Pos, map, Fields}
+ end.
%% =====================================================================
%% @doc Returns the list of field subtrees of a `map_type' node.
@@ -5714,7 +5718,12 @@ tuple_type(Elements) ->
revert_tuple_type(Node) ->
Pos = get_pos(Node),
- {type, Pos, tuple, tuple_type_elements(Node)}.
+ case tuple_type_elements(Node) of
+ any_size ->
+ {type, Pos, tuple, any};
+ TypeElements ->
+ {type, Pos, tuple, TypeElements}
+ end.
%% =====================================================================
diff --git a/lib/syntax_tools/test/merl_SUITE.erl b/lib/syntax_tools/test/merl_SUITE.erl
index 52bbd9b3b8..6389ad7738 100644
--- a/lib/syntax_tools/test/merl_SUITE.erl
+++ b/lib/syntax_tools/test/merl_SUITE.erl
@@ -30,13 +30,14 @@
%% Test cases
-export([merl_smoke_test/1,
- transform_parse_error_test/1]).
+ transform_parse_error_test/1, otp_15291/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[merl_smoke_test,
- transform_parse_error_test].
+ transform_parse_error_test,
+ otp_15291].
groups() ->
[].
@@ -101,6 +102,15 @@ transform_parse_error_test(_Config) ->
[?Q("merl:qquote(2, \"{\", [{var, V}])")], []))),
ok.
+otp_15291(_Config) ->
+ C0 = merl:quote("() -> ok"),
+ {clause,1,[],[],[{atom,1,ok}]} = C0,
+ C2 = merl:quote("(_,_) -> ok"),
+ {clause,1,[{var,1,'_'},{var,1,'_'}],[],[{atom,1,ok}]} = C2,
+ C1 = merl:quote("(_) -> ok"),
+ {clause,1,[{var,1,'_'}],[],[{atom,1,ok}]} = C1,
+ ok.
+
%% utilities
f(Ts) when is_list(Ts) ->
diff --git a/lib/syntax_tools/test/syntax_tools_SUITE.erl b/lib/syntax_tools/test/syntax_tools_SUITE.erl
index 4cddf8f0c3..9dbd0e302a 100644
--- a/lib/syntax_tools/test/syntax_tools_SUITE.erl
+++ b/lib/syntax_tools/test/syntax_tools_SUITE.erl
@@ -25,14 +25,14 @@
%% Test cases
-export([app_test/1,appup_test/1,smoke_test/1,revert/1,revert_map/1,
revert_map_type/1,
- t_abstract_type/1,t_erl_parse_type/1,t_epp_dodger/1,
+ t_abstract_type/1,t_erl_parse_type/1,t_type/1, t_epp_dodger/1,
t_comment_scan/1,t_igor/1,t_erl_tidy/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[app_test,appup_test,smoke_test,revert,revert_map,revert_map_type,
- t_abstract_type,t_erl_parse_type,t_epp_dodger,
+ t_abstract_type,t_erl_parse_type,t_type,t_epp_dodger,
t_comment_scan,t_igor,t_erl_tidy].
groups() ->
@@ -145,6 +145,74 @@ revert_map_type(Config) when is_list(Config) ->
%% api tests
+t_type(Config) when is_list(Config) ->
+ F0 = fun validate_basic_type/1,
+ Appl0 = fun(Name) ->
+ Atom = erl_syntax:atom(Name),
+ erl_syntax:type_application(none, Atom, [])
+ end,
+ User0 = fun(Name) ->
+ Atom = erl_syntax:atom(Name),
+ erl_syntax:user_type_application(Atom, [])
+ end,
+ ok = validate(F0,[{"tuple()", erl_syntax:tuple_type()}
+ ,{"{}", erl_syntax:tuple_type([])}
+ ,{"integer()", Appl0(integer)}
+ ,{"foo()", User0(foo)}
+ ,{"map()", erl_syntax:map_type()}
+ ,{"#{}", erl_syntax:map_type([])}
+ ,{"1..2", erl_syntax:integer_range_type
+ (erl_syntax:integer(1), erl_syntax:integer(2))}
+ ,{"<<_:1,_:_*2>>", erl_syntax:bitstring_type
+ (erl_syntax:integer(1), erl_syntax:integer(2))}
+ ,{"fun()", erl_syntax:fun_type()}
+ ]),
+
+ F = fun validate_type/1,
+ ok = validate(F,[{"{}", tuple_type, false}
+ ,{"tuple()", tuple_type, true}
+ ,{"{atom()}", tuple_type, false}
+ ,{"{atom(),integer()}", tuple_type, false}
+ ,{"integer()", type_application, false}
+ ,{"foo()", user_type_application, false}
+ ,{"foo(integer())", user_type_application, false}
+ ,{"module:function()", type_application, false}
+ ,{"map()", map_type, true}
+ ,{"#{}", map_type, false}
+ ,{"#{atom() => integer()}", map_type, false}
+ ,{"#{atom() := integer()}", map_type, false}
+ ,{"#r{}", record_type, false}
+ ,{"#r{a :: integer()}", record_type, false}
+ ,{"[]", type_application, false}
+ ,{"nil()", type_application, false}
+ ,{"[atom()]", type_application, false}
+ ,{"1..2", integer_range_type, false}
+ ,{"<<_:1,_:_*2>>", bitstring_type, false}
+ ,{"fun()", fun_type, true}
+ ,{"integer() | atom()", type_union, false}
+ ,{"A :: fun()", annotated_type, false}
+ ,{"fun((...) -> atom())", function_type, false}
+ ,{"fun((integer()) -> atom())", function_type, false}
+ ,{"V", variable, true}
+ ]),
+ ok.
+
+validate_basic_type({String, Tree}) ->
+ ErlT = string_to_type(String),
+ ErlT = erl_syntax:revert(Tree),
+ ok.
+
+validate_type({String, Type, Leaf}) ->
+ ErlT = string_to_type(String),
+ Type = erl_syntax:type(ErlT),
+ Leaf = erl_syntax:is_leaf(ErlT),
+ Tree = erl_syntax_lib:map(fun(Node) -> Node end, ErlT),
+ Type = erl_syntax:type(Tree),
+ _ = erl_syntax:meta(Tree),
+ RevT = erl_syntax:revert(Tree),
+ Type = erl_syntax:type(RevT),
+ ok.
+
t_abstract_type(Config) when is_list(Config) ->
F = fun validate_abstract_type/1,
ok = validate(F,[{hi,atom},
@@ -451,6 +519,13 @@ string_to_expr(String) ->
{ok,[Expr]} = erl_parse:parse_exprs(Ts),
Expr.
+string_to_type(String) ->
+ io:format("Str: ~p~n", [String]),
+ {ok,Ts,_} = erl_scan:string("-type foo() :: "++String++".", 0),
+ {ok,Form} = erl_parse:parse_form(Ts),
+ {attribute,_,type,{foo,Type,_NoParms=[]}} = Form,
+ Type.
+
p_run(Test, List) ->
N = erlang:system_info(schedulers),
diff --git a/lib/syntax_tools/vsn.mk b/lib/syntax_tools/vsn.mk
index 4d13267f16..8959ebbd04 100644
--- a/lib/syntax_tools/vsn.mk
+++ b/lib/syntax_tools/vsn.mk
@@ -1 +1 @@
-SYNTAX_TOOLS_VSN = 2.1.5
+SYNTAX_TOOLS_VSN = 2.1.6
diff --git a/lib/tftp/doc/src/notes.xml b/lib/tftp/doc/src/notes.xml
index 3a4d97a008..ff6113a89d 100644
--- a/lib/tftp/doc/src/notes.xml
+++ b/lib/tftp/doc/src/notes.xml
@@ -33,7 +33,22 @@
<file>notes.xml</file>
</header>
- <section><title>TFTP 1.0</title>
+ <section><title>Tftp 1.0.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>TFTP 1.0</title>
<section><title>First released version</title>
<list>
diff --git a/lib/tftp/src/tftp.app.src b/lib/tftp/src/tftp.app.src
index 2a87d39ada..9e79fe32bf 100644
--- a/lib/tftp/src/tftp.app.src
+++ b/lib/tftp/src/tftp.app.src
@@ -1,6 +1,6 @@
{application, tftp,
[{description, "TFTP application"},
- {vsn, "1.0"},
+ {vsn, "%VSN%"},
{registered, []},
{mod, { tftp_app, []}},
{applications,
diff --git a/lib/tftp/vsn.mk b/lib/tftp/vsn.mk
index f1b0851a8f..1a547fbe9b 100644
--- a/lib/tftp/vsn.mk
+++ b/lib/tftp/vsn.mk
@@ -19,6 +19,6 @@
# %CopyrightEnd%
APPLICATION = tftp
-TFTP_VSN = 1.0
+TFTP_VSN = 1.0.1
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(TFTP_VSN)$(PRE_VSN)"
diff --git a/lib/tools/doc/src/notes.xml b/lib/tools/doc/src/notes.xml
index 8b0a2ca283..f10953774f 100644
--- a/lib/tools/doc/src/notes.xml
+++ b/lib/tools/doc/src/notes.xml
@@ -31,6 +31,28 @@
</header>
<p>This document describes the changes made to the Tools application.</p>
+<section><title>Tools 3.0.1</title>
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ The HTML pages generated by cover:analyse_to_file/1 and
+ related functions is improved for readability.</p>
+ <p>
+ Own Id: OTP-15213 Aux Id: PR-1807 </p>
+ </item>
+ <item>
+ <p>
+ Add alignment functionality in emacs.</p>
+ <p>
+ Own Id: OTP-15239 Aux Id: PR-1728 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Tools 3.0</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/tools/emacs/erlang.el b/lib/tools/emacs/erlang.el
index 242a5abe72..82e5c2222d 100644
--- a/lib/tools/emacs/erlang.el
+++ b/lib/tools/emacs/erlang.el
@@ -77,7 +77,7 @@
;;; Code:
(eval-when-compile (require 'cl))
-(eval-when-compile (require 'align))
+(require 'align)
;; Variables:
diff --git a/lib/tools/src/Makefile b/lib/tools/src/Makefile
index a869ae6a00..cc5bee9a8f 100644
--- a/lib/tools/src/Makefile
+++ b/lib/tools/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1996-2016. All Rights Reserved.
+# Copyright Ericsson AB 1996-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/lib/tools/src/cover.erl b/lib/tools/src/cover.erl
index 337d9d637a..d7269e3f27 100644
--- a/lib/tools/src/cover.erl
+++ b/lib/tools/src/cover.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2001-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2001-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/tools/test/xref_SUITE.erl b/lib/tools/test/xref_SUITE.erl
index 4ec75f7962..da4f56c09b 100644
--- a/lib/tools/test/xref_SUITE.erl
+++ b/lib/tools/test/xref_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/tools/vsn.mk b/lib/tools/vsn.mk
index bb3f4c66c0..1bebb1c421 100644
--- a/lib/tools/vsn.mk
+++ b/lib/tools/vsn.mk
@@ -1 +1 @@
-TOOLS_VSN = 3.0
+TOOLS_VSN = 3.0.1
diff --git a/lib/wx/c_src/wxe_driver.h b/lib/wx/c_src/wxe_driver.h
index 8b4ce2b804..6d6a67fa85 100644
--- a/lib/wx/c_src/wxe_driver.h
+++ b/lib/wx/c_src/wxe_driver.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2008-2016. All Rights Reserved.
+ * Copyright Ericsson AB 2008-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/lib/wx/doc/src/notes.xml b/lib/wx/doc/src/notes.xml
index 45638dff35..a925cf30d4 100644
--- a/lib/wx/doc/src/notes.xml
+++ b/lib/wx/doc/src/notes.xml
@@ -32,6 +32,21 @@
<p>This document describes the changes made to the wxErlang
application.</p>
+<section><title>Wx 1.8.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed compilation warning on Darwin.</p>
+ <p>
+ Own Id: OTP-15230 Aux Id: PR-1860 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Wx 1.8.4</title>
<section><title>Improvements and New Features</title>
diff --git a/lib/wx/test/wxt b/lib/wx/test/wxt
index 1343542366..94513e88e9 100755
--- a/lib/wx/test/wxt
+++ b/lib/wx/test/wxt
@@ -2,7 +2,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2008-2016. All Rights Reserved.
+# Copyright Ericsson AB 2008-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/lib/wx/vsn.mk b/lib/wx/vsn.mk
index 37a5477631..e539ad36f6 100644
--- a/lib/wx/vsn.mk
+++ b/lib/wx/vsn.mk
@@ -1 +1 @@
-WX_VSN = 1.8.4
+WX_VSN = 1.8.5
diff --git a/lib/xmerl/doc/src/notes.xml b/lib/xmerl/doc/src/notes.xml
index b7d1db7dfc..a97036127e 100644
--- a/lib/xmerl/doc/src/notes.xml
+++ b/lib/xmerl/doc/src/notes.xml
@@ -32,6 +32,21 @@
<p>This document describes the changes made to the Xmerl application.</p>
+<section><title>Xmerl 1.3.18</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Improved documentation.</p>
+ <p>
+ Own Id: OTP-15190</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Xmerl 1.3.17</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/xmerl/src/xmerl_scan.erl b/lib/xmerl/src/xmerl_scan.erl
index a7538180e6..e543a5a11e 100644
--- a/lib/xmerl/src/xmerl_scan.erl
+++ b/lib/xmerl/src/xmerl_scan.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
diff --git a/lib/xmerl/vsn.mk b/lib/xmerl/vsn.mk
index be11935f2f..3a266a56bd 100644
--- a/lib/xmerl/vsn.mk
+++ b/lib/xmerl/vsn.mk
@@ -1 +1 @@
-XMERL_VSN = 1.3.17
+XMERL_VSN = 1.3.18