diff --git a/.travis.yml b/.travis.yml index 2bf2a01..b29f23b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,7 +26,7 @@ before_script: - cd .. - git clone --depth 1 -b ${OPENSSL_BRANCH} https://github.com/openssl/openssl.git - cd openssl - - git apply ../bee2evp/btls/openssl111i.patch + - git apply ../bee2evp/btls/patch/${OPENSSL_BRANCH}.patch - cp ../bee2evp/btls/btls.c ./ssl/ - cp ../bee2evp/btls/btls.h ./ssl/ - mkdir build diff --git a/btls/README.md b/btls/README.md new file mode 100644 index 0000000..58a255b --- /dev/null +++ b/btls/README.md @@ -0,0 +1,33 @@ +# OpenSSL patching + +There are two patching methods available: +1. Using a patch generated by git diff. +2. Using a slightly smarter patch that doesn't depend on line numbers and can be +applied to different versions of openssl. + +## Option 1 + +Can only be used for **OpenSSL_1_1_1i** version . + +## Option 2 + +| version | test results | +| :--- | :---: | +| OpenSSL_1_1_1i | :heavy_check_mark: | +| OpenSSL_1_1_1j | :heavy_check_mark: | +| OpenSSL_1_1_1k | :heavy_check_mark: | +| OpenSSL_1_1_1l | :heavy_check_mark: | +| OpenSSL_1_1_1m | :heavy_check_mark: | +| OpenSSL_1_1_1n | :heavy_multiplication_x: (see [issue](https://github.com/bcrypto/bee2evp/issues/11#issue-1179528056))| + +## Build script + +Run script build.sh. Usage: +```text +"Script for patching OpenSSL." + +"Syntax: build [-v|m]" + "options:" + "v OpenSSL version" + "m Mode: 0 (simple patching) or 1 (smart patching)" +``` diff --git a/btls/build.sh b/btls/build.sh new file mode 100755 index 0000000..e2d1740 --- /dev/null +++ b/btls/build.sh @@ -0,0 +1,138 @@ +#!/bin/bash +############################################################ +# help # +############################################################ +help() +{ + # Display Help + echo "Script for patching openssl." + echo + echo "Syntax: build [-v|m|h]" + echo "options:" + echo "v OpenSSL version" + echo "m Mode: 0 (simple patching) or 1 (smart patching)" + echo +} + +############################################################ +# Process the input options. Add options as needed. # +############################################################ +# Get the options +while getopts 'hv:m:' flag ; do + case "$flag" in + h) + help + exit;; + v) + openssl_branch=$OPTARG + ;; + m) + mode=$OPTARG; + ;; + \?) # Invalid option + echo "Error: Invalid option" + exit;; + esac +done + +echo "version=$openssl_branch" +echo "mode=${mode}" + +bee2evp=$(pwd)/.. +build_root=$bee2evp/build_$openssl_branch +bee2=$bee2evp/bee2 +openssl=$bee2evp/openssl +build_bee2evp=$build_root/build_bee2evp +build_bee2=$build_root/build_bee2 +build_openssl=$build_root/build_openssl +local=$build_root/local +# openssl_branch=OpenSSL_1_1_1i +openssl_patch=$openssl_branch.patch + +install_prereq(){ + sudo apt-get update + sudo apt-get install git gcc cmake python3 python3-pip +} + +clean(){ + rm -rf $build_root + rm -rf $openssl +} + +update_repos(){ + echo $openssl_branch + git submodule update --init + git clone -b $openssl_branch --depth 1 https://github.com/openssl/openssl $openssl +} + +patch_openssl(){ + cd $openssl + cp $bee2evp/btls/btls.c ./ssl/ + cp $bee2evp/btls/btls.h ./ssl/ +if [[ $mode -eq "1" ]] +then + cp $bee2evp/btls/patch/patching.py ./ + cp $bee2evp/btls/patch/patch.json ./ + pip3 install multiline + python3 patching.py +else + git apply $bee2evp/btls/patch/$openssl_patch +fi +} + +build_bee2(){ + mkdir -p $build_bee2 && mkdir -p $local && cd $build_bee2 + cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_PIC=ON -DCMAKE_INSTALL_PREFIX=$local $bee2 + make -j$(nproc) && ctest && make install + ls -la $local/lib/libbee2_static.a +} + +build_openssl(){ + mkdir -p $build_openssl && mkdir -p $local && cd $build_openssl + $openssl/config shared -d --prefix=$local --openssldir=$local + make -j$(nproc) all + make install > build.log 2>&1 || (cat build.log && exit 1) + ls -la $local/lib/libcrypto.a + ls -la $local/lib/libssl.a + ls -la $local/lib/libcrypto.so + ls -la $local/lib/libssl.so +} + +build_bee2evp(){ + mkdir -p $build_bee2evp && cd $build_bee2evp + cmake -DCMAKE_BUILD_TYPE=Release \ + -DBEE2_LIBRARY_DIRS=$local/lib -DBEE2_INCLUDE_DIRS=$local/include \ + -DOPENSSL_LIBRARY_DIRS=$local/lib -DOPENSSL_INCLUDE_DIRS=$local/include \ + -DLIB_INSTALL_DIR=$local/lib -DCMAKE_INSTALL_PREFIX=$local $bee2evp + make -j$(nproc) && make install + ls -la $local/lib/libbee2evp.so +} + +attach_bee2evp(){ + #cp $bee2evp/doc/bee2evp.cnf $local/openssl.cnf + #sed -i "s|#path/to/bee2evp|$local/lib/libbee2evp.so|g" $local/openssl.cnf + mv $local/openssl.cnf.dist $local/openssl.cnf + sed -i "/\[ new\_oids\ ]/i openssl_conf = openssl_init\n[ openssl_init ]\nengines = engine_section\n[ engine_section ]\nbee2evp = bee2evp_section\n[ bee2evp_section ]\nengine_id = bee2evp\ndynamic_path = $local/lib/libbee2evp.so\ndefault_algorithms = ALL" $local/openssl.cnf +} + +test_bee2evp(){ + export LD_LIBRARY_PATH="$local/lib:${LD_LIBRARY_PATH:-}" + cd $local/bin || exit + ./openssl version + ./openssl engine -c -t bee2evp +} + +if [ "$#" -eq 0 ]; +then + help +else + install_prereq + clean + update_repos + patch_openssl + build_bee2 + build_openssl + build_bee2evp + attach_bee2evp + test_bee2evp +fi diff --git a/btls/openssl111i.patch b/btls/patch/OpenSSL_1_1_1i.patch similarity index 100% rename from btls/openssl111i.patch rename to btls/patch/OpenSSL_1_1_1i.patch diff --git a/btls/patch/patch.json b/btls/patch/patch.json new file mode 100644 index 0000000..1c14f98 --- /dev/null +++ b/btls/patch/patch.json @@ -0,0 +1,674 @@ +{ + "ssl/ssl_ciph.c" : + { + "macros" : + { + "1" : + { + "macro_name" : "SSL_ENC_NUM_IDX", + "new_value" : "SSL_ENC_NUM_IDX\t24" + } + }, + "static_arrays" : + { + "1" : + { + "array_name" : "ssl_cipher_table_cipher", + "values" : { + "1" : "{SSL_BELTCTR, NID_belt_ctrt},", + "2" : "{SSL_BELTDWP, NID_belt_dwpt},"} + }, + "2" : + { + "array_name" : "ssl_cipher_table_mac", + "values" : { + "1" : ",{SSL_BELTMAC, NID_belt_mac256},", + "2" : "{SSL_HBELT, NID_belt_hash},", + "3" : "{SSL_BASH384, NID_bash384},", + "4" : "{SSL_BASH512, NID_bash512}"} + }, + "3" : + { + "array_name" : "ssl_digest_methods", + "values" : { + "1" : ",NULL,NULL,", + "2" : "NULL,NULL"} + }, + "4" : + { + "array_name" : "ssl_cipher_table_kx", + "values" : { + "1" : ",{SSL_kBDHE, NID_kxbdhe},", + "2" : "{SSL_kBDHT, NID_kxbdht},", + "3" : "{SSL_kBDHEPSK, NID_kxbdhe_psk},", + "4" : "{SSL_kBDHTPSK, NID_kxbdht_psk},"} + }, + "5" : + { + "array_name" : "ssl_mac_pkey_id", + "values" : { + "1" : ",NID_undef,", + "2" : "NID_undef"} + }, + "6" : + { + "array_name" : "cipher_aliases", + "values" : { + "1" : "{0, SSL_TXT_kBDHE, NULL, 0, SSL_kBDHE},", + "2" : "{0, SSL_TXT_kBDHT, NULL, 0, SSL_kBDHT},", + "3" : "{0, SSL_TXT_kBDHEPSK, NULL, 0, SSL_kBDHEPSK},", + "4" : "{0, SSL_TXT_kBDHTPSK, NULL, 0, SSL_kBDHTPSK},", + "5" : "{0, SSL_TXT_aBIGN, NULL, 0, SSL_aBIGN},", + "6" : "{0, SSL_TXT_BELTCTR, NULL, 0, 0, 0, SSL_BELTCTR},", + "7" : "{0, SSL_TXT_BELTDWP, NULL, 0, 0, 0, SSL_BELTDWP},", + "8" : "{0, SSL_TXT_BELTMAC, NULL, 0, 0, 0, 0, SSL_BELTMAC},"} + } + }, + "functions" : + { + "1" : + { + "func_name" : "ssl_load_ciphers", + "to_end" : "1", + "code" : +" + ssl_mac_pkey_id[SSL_MD_BELTMAC_IDX] = get_optional_pkey_id(\"belt-mac256\"); + if (ssl_mac_pkey_id[SSL_MD_BELTMAC_IDX]) + ssl_mac_secret_size[SSL_MD_BELTMAC_IDX] = 32; + if (!get_optional_pkey_id(\"BIGN\")){ + disabled_auth_mask |= SSL_aBIGN; + disabled_mkey_mask |= SSL_kBDHE | SSL_kBDHT | SSL_kBDHEPSK | SSL_kBDHTPSK; + }" + }, + "2" : + { + "func_name" : "SSL_CIPHER_description", + "switch_name" : "alg_mkey", + "code" : +" +\tcase SSL_kBDHE: +\t\tkx = \"BDHE\"; +\t\tbreak; +\tcase SSL_kBDHT: +\t\tkx = \"BDHT\"; +\t\tbreak; +\tcase SSL_kBDHEPSK: +\t\tkx = \"BDHEPSK\"; +\t\tbreak; +\tcase SSL_kBDHTPSK: +\t\tkx = \"BDHTPSK\";\n\t" + }, + "3" : + { + "func_name" : "SSL_CIPHER_description", + "switch_name" : "alg_enc", + "code" : +" +\tcase SSL_BELTCTR: +\t\tenc = \"BELTCTR\"; +\t\tbreak; +\tcase SSL_BELTDWP: +\t\tenc = \"BELTDWP\"; +\t\tbreak;\n +\t" + }, + "4" : + { + "func_name" : "SSL_CIPHER_description", + "switch_name" : "alg_auth", + "code" : +" +\tcase SSL_aBIGN: +\t\tau = \"BIGN\"; +\t\tbreak;\n\t" + }, + "5" : + { + "func_name" : "SSL_CIPHER_description", + "switch_name" : "alg_mac", + "code" : +" +\tcase SSL_BELTMAC: +\t\tmac = \"BELTMAC\"; +\t\tbreak;\n\t +\t" + } + } + }, + "ssl/s3_lib.c" : + { + "static_arrays" : + { + "1" : + { + "array_name" : "ssl3_ciphers", + "values" : { + "1" : +" + { + 1, + BTLS1_TXT_DHE_BIGN_WITH_BELT_CTR_MAC_HBELT, + BTLS1_RFC_DHE_BIGN_WITH_BELT_CTR_MAC_HBELT, + 0x0300ff15, + SSL_kBDHE, + SSL_aBIGN, + SSL_BELTCTR, + SSL_BELTMAC, + TLS1_2_VERSION, TLS1_2_VERSION, + 0, 0, + SSL_HIGH, + SSL_HANDSHAKE_MAC_HBELT | TLS1_PRF_HBELT, + 256, + 256, + },", + "2" : +" + { + 1, + BTLS1_TXT_DHE_BIGN_WITH_BELT_DWP_HBELT, + BTLS1_RFC_DHE_BIGN_WITH_BELT_DWP_HBELT, + 0x0300ff16, + SSL_kBDHE, + SSL_aBIGN, + SSL_BELTDWP, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + 0, 0, + SSL_HIGH, + SSL_HANDSHAKE_MAC_HBELT | TLS1_PRF_HBELT, + 256, + 256, + },", + "3" : +" + { + 1, + BTLS1_TXT_DHT_BIGN_WITH_BELT_CTR_MAC_HBELT, + BTLS1_RFC_DHT_BIGN_WITH_BELT_CTR_MAC_HBELT, + 0x0300ff17, + SSL_kBDHT, + SSL_aBIGN, + SSL_BELTCTR, + SSL_BELTMAC, + TLS1_2_VERSION, TLS1_2_VERSION, + 0, 0, + SSL_HIGH, + SSL_HANDSHAKE_MAC_HBELT | TLS1_PRF_HBELT, + 256, + 256, + },", + "4" : +" + { + 1, + BTLS1_TXT_DHT_BIGN_WITH_BELT_DWP_HBELT, + BTLS1_RFC_DHT_BIGN_WITH_BELT_DWP_HBELT, + 0x0300ff18, + SSL_kBDHT, + SSL_aBIGN, + SSL_BELTDWP, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + 0, 0, + SSL_HIGH, + SSL_HANDSHAKE_MAC_HBELT | TLS1_PRF_HBELT, + 256, + 256, + },", + "5" : +" + { + 1, + BTLS1_TXT_DHE_PSK_BIGN_WITH_BELT_CTR_MAC_HBELT, + BTLS1_RFC_DHE_PSK_BIGN_WITH_BELT_CTR_MAC_HBELT, + 0x0300ff19, + SSL_kBDHEPSK, + SSL_aPSK, + SSL_BELTCTR, + SSL_BELTMAC, + TLS1_2_VERSION, TLS1_2_VERSION, + 0, 0, + SSL_HIGH, + SSL_HANDSHAKE_MAC_HBELT | TLS1_PRF_HBELT, + 256, + 256, + },", + "6" : +" + { + 1, + BTLS1_TXT_DHE_PSK_BIGN_WITH_BELT_DWP_HBELT, + BTLS1_RFC_DHE_PSK_BIGN_WITH_BELT_DWP_HBELT, + 0x0300ff1a, + SSL_kBDHEPSK, + SSL_aPSK, + SSL_BELTDWP, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + 0, 0, + SSL_HIGH, + SSL_HANDSHAKE_MAC_HBELT | TLS1_PRF_HBELT, + 256, + 256, + },", + "7" : +" + { + 1, + BTLS1_TXT_DHT_PSK_BIGN_WITH_BELT_CTR_MAC_HBELT, + BTLS1_RFC_DHT_PSK_BIGN_WITH_BELT_CTR_MAC_HBELT, + 0x0300ff1b, + SSL_kBDHTPSK, + SSL_aBIGN, + SSL_BELTCTR, + SSL_BELTMAC, + TLS1_2_VERSION, TLS1_2_VERSION, + 0, 0, + SSL_HIGH, + SSL_HANDSHAKE_MAC_HBELT | TLS1_PRF_HBELT, + 256, + 256, + },", + "8" : +" + { + 1, + BTLS1_TXT_DHT_PSK_BIGN_WITH_BELT_DWP_HBELT, + BTLS1_RFC_DHT_PSK_BIGN_WITH_BELT_DWP_HBELT, + 0x0300ff1c, + SSL_kBDHTPSK, + SSL_aBIGN, + SSL_BELTDWP, + SSL_AEAD, + TLS1_2_VERSION, TLS1_2_VERSION, + 0, 0, + SSL_HIGH, + SSL_HANDSHAKE_MAC_HBELT | TLS1_PRF_HBELT, + 256, + 256, + }" + } + } + } + }, + "ssl/ssl_init.c" : + { + "functions" : + { + "1" : + { + "func_name" : "OPENSSL_init_ssl", + "insert_before" : +" + if (!OPENSSL_init_crypto(opts, settings)) +", + "code" : +" + if (!btls_init()) + return 0; +" + } + } + }, + "ssl/ssl_lib.c" : + { + "functions" : + { + "1" : + { + "func_name" : "ssl_set_masks", + "code" : +" + if (ssl_has_cert(s, SSL_PKEY_BIGN)){ + mask_k |= SSL_kBDHE | SSL_kBDHT | SSL_kBDHTPSK; + mask_a |= SSL_aBIGN; + } +", + "insert_before" : +" + if (rsa_enc) + mask_k |= SSL_kRSA; +" + }, + "2" : + { + "func_name" : "ssl_set_mask", + "code" : + " mask_k |= SSL_kBDHEPSK;\n", + "insert_before" : + "#ifndef OPENSSL_NO_PSK" + } + } + }, + "ssl/ssl_local.h" : + { + "macros" : + { + "1" : + { + "macro_name" : "SSL_PSK", + "new_value" : "SSL_PSK\t(SSL_kPSK | SSL_kRSAPSK | SSL_kECDHEPSK | SSL_kDHEPSK | SSL_kBDHEPSK | SSL_kBDHTPSK)" + }, + "2" : + { + "macro_name" : "SSL_aCERT", + "new_value" : "SSL_aCERT (SSL_aRSA | SSL_aDSS | SSL_aECDSA | SSL_aGOST01 | SSL_aGOST12 | SSL_aBIGN)" + }, + "3" : + { + "macro_name" : "SSL_MAX_DIGEST", + "new_value" : "SSL_MAX_DIGEST\t16" + }, + "4" : + { + "macro_name" : "SSL_PKEY_NUM", + "new_value" : "SSL_PKEY_NUM\t10" + } + } + }, + "ssl/statem/extensions_clnt.c" : + { + "functions" : + { + "1" : + { + "func_name" : "use_ecc", + "code" : "((alg_k & (SSL_kECDHE | SSL_kECDHEPSK | SSL_kBDHEPSK))", + "change_if" : "((alg_k & (SSL_kECDHE | SSL_kECDHEPSK))" + } + } + }, + "ssl/statem/extensions_srvr.c" : + { + "functions" : + { + "1" : + { + "func_name" : "tls_construct_stoc_etm", + "code" : "(s->s3->tmp.new_cipher->algorithm_mac == SSL_AEAD + || s->s3->tmp.new_cipher->algorithm_enc == SSL_RC4 + || s->s3->tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT + || s->s3->tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT12 + || s->s3->tmp.new_cipher->algorithm_enc == SSL_BELTCTR)", + "change_if" : "(s->s3->tmp.new_cipher->algorithm_mac == SSL_AEAD + || s->s3->tmp.new_cipher->algorithm_enc == SSL_RC4 + || s->s3->tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT + || s->s3->tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT12)" + } + } + }, + "ssl/statem/statem_clnt.c" : + { + "functions" : + { + "1" : + { + "func_name" : "key_exchange_expected", + "code" : "(alg_k & (SSL_kDHE | SSL_kECDHE | SSL_kDHEPSK | SSL_kECDHEPSK + | SSL_kSRP | SSL_kBDHE | SSL_kBDHEPSK | SSL_kBDHTPSK))", + "change_if" : +"(alg_k & (SSL_kDHE | SSL_kECDHE | SSL_kDHEPSK | SSL_kECDHEPSK + | SSL_kSRP))" + }, + "2" : + { + "func_name" : "tls_process_key_exchange", + "code" : "(alg_k & (SSL_kPSK | SSL_kRSAPSK | SSL_kBDHTPSK))", + "change_if" : "(alg_k & (SSL_kPSK | SSL_kRSAPSK))" + }, + "3" : + { + "func_name" : "tls_process_key_exchange", + "code" : +" + } else if (alg_k & (SSL_kBDHE)) { + if (!btls_process_ske_bign_dhe(s, pkt, &pkey)) { + /* SSLfatal() already called */ + goto err; + } + } else if (alg_k & SSL_kBDHEPSK) { + if (!btls_process_ske_psk_bign_dhe(s, pkt, &pkey)) { + /* SSLfatal() already called */ + goto err; + } +", + "insert_before" : +" + } else if (alg_k) { +" + }, + "4" : + { + "func_name" : "tls_construct_client_key_exchange", + "code" : +" + } else if (alg_k & (SSL_kBDHE | SSL_kBDHEPSK)) { + if (!tls_construct_cke_ecdhe(s, pkt)) + goto err; + } else if (alg_k & (SSL_kBDHT | SSL_kBDHTPSK)) { + if (!btls_construct_cke_bign_dht(s, pkt)) + goto err; +", + "insert_before" : +" + } else if (!(alg_k & SSL_kPSK)) { +" + }, + "5" : + { + "func_name" : "ssl3_check_cert_and_algorithm", + "code" : +" + if ((alg_k & SSL_kBDHE) && (s->s3->peer_tmp == NULL)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, + ERR_R_INTERNAL_ERROR); + return 0; + } +", + "to_end" : "1" + } + } + }, + "ssl/statem/statem_srvr.c" : + { + "functions" : + { + "1" : + { + "func_name" : "send_server_key_exchange", + "code" : +"(alg_k & (SSL_kDHE | SSL_kECDHE) + /* + * PSK: send ServerKeyExchange if PSK identity hint if + * provided + */ +#ifndef OPENSSL_NO_PSK + /* Only send SKE if we have identity hint for plain PSK or BDHTPSK */ + || ((alg_k & (SSL_kPSK | SSL_kRSAPSK | SSL_kBDHTPSK)) + && s->cert->psk_identity_hint) + /* For other PSK always send SKE */ + || (alg_k & (SSL_PSK & (SSL_kDHEPSK | SSL_kECDHEPSK | SSL_kBDHEPSK))) +#endif +#ifndef OPENSSL_NO_SRP + /* SRP: send ServerKeyExchange */ + || (alg_k & SSL_kSRP) +#endif + || (alg_k & SSL_kBDHE) + ) { + return 1; + }", + "change_if" : +"(alg_k & (SSL_kDHE | SSL_kECDHE) + /* + * PSK: send ServerKeyExchange if PSK identity hint if + * provided + */ +#ifndef OPENSSL_NO_PSK + /* Only send SKE if we have identity hint for plain PSK */ + || ((alg_k & (SSL_kPSK | SSL_kRSAPSK)) + && s->cert->psk_identity_hint) + /* For other PSK always send SKE */ + || (alg_k & (SSL_PSK & (SSL_kDHEPSK | SSL_kECDHEPSK))) +#endif +#ifndef OPENSSL_NO_SRP + /* SRP: send ServerKeyExchange */ + || (alg_k & SSL_kSRP) +#endif + ) { + return 1; + }" + }, + "2" : + { + "func_name" : "tls_construct_server_key_exchange", + "code" : "(type & (SSL_kPSK | SSL_kRSAPSK | SSL_kBDHTPSK))", + "change_if" : "(type & (SSL_kPSK | SSL_kRSAPSK))" + }, + "3" : + { + "func_name" : "tls_construct_server_key_exchange", + "code" : +" + if (type & (SSL_kBDHE)) { + if(!btls_construct_ske_bign_dhe(s, pkt)) + goto err; + } else + if (type & SSL_kBDHEPSK) { + if(!btls_construct_ske_psk_bign_dhe(s, pkt)) + goto err; + } else +", + "insert_before" : +" +#ifndef OPENSSL_NO_SRP + if (type & SSL_kSRP) { +" + }, + "4" : + { + "func_name" : "tls_construct_server_key_exchange", + "code" : "((type & SSL_PSK) && (s->s3->tmp.new_cipher->algorithm_mkey != SSL_kBDHEPSK))", + "change_if" : "(type & SSL_PSK)" + }, + "5" : + { + "func_name" : "tls_process_client_key_exchange", + "code" : +" } else if (alg_k & (SSL_kBDHE | SSL_kBDHEPSK)) { + if (!tls_process_cke_ecdhe(s, pkt)) { + /* SSLfatal() already called */ + goto err; + } + } else if (alg_k & (SSL_kBDHT | SSL_kBDHTPSK)) { + if (!btls_process_cke_bign_dht(s, pkt)) { + /* SSLfatal() already called */ + goto err; + } +", + "insert_before" : +" } else { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, + SSL_R_UNKNOWN_CIPHER_TYPE); + goto err; + }" + } + } + }, + "ssl/t1_lib.c" : + { + "static_arrays" : + { + "1" : + { + "array_name" : "nid_list", + "values" : { + "1" : "{NID_bign_curve256v1, 128, TLS_CURVE_CUSTOM},", + "2" : "{NID_bign_curve384v1, 192, TLS_CURVE_CUSTOM},", + "3" : "{NID_bign_curve512v1, 256, TLS_CURVE_CUSTOM}," + } + }, + "2" : + { + "array_name" : "tls12_sigalgs", + "values" : { + "1" : " TLSEXT_SIGALG_bign_sign_128,", + "2" : " TLSEXT_SIGALG_bign_sign_192,", + "3" : " TLSEXT_SIGALG_bign_sign_256" + } + }, + "3" : + { + "array_name" : "sigalg_lookup_tbl", + "values" : { + "1" : +" {NULL, TLSEXT_SIGALG_bign_sign_128, + NID_belt_hash, SSL_MD_HBELT_IDX, + NID_bign_pubkey, SSL_PKEY_BIGN, + NID_bign_with_hbelt, NID_bign_curve256v1},", + "2" : +" {NULL, TLSEXT_SIGALG_bign_sign_192, + NID_bash384, SSL_MD_BASH384_IDX, + NID_bign_pubkey, SSL_PKEY_BIGN, + NID_bign_with_bash384, NID_bign_curve384v1},", + "3" : +" {NULL, TLSEXT_SIGALG_bign_sign_256, + NID_bash512, SSL_MD_BASH512_IDX, + NID_bign_pubkey, SSL_PKEY_BIGN, + NID_bign_with_bash512, NID_bign_curve512v1}," + } + } + }, + "functions" : + { + "1" : + { + "func_name" : "tls1_set_cert_validity", + "code" : " tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_BIGN);", + "insert_before" : "}" + } + } + }, + "ssl/t1_trce.c" : + { + "static_arrays" : + { + "1" : + { + "array_name" : "ssl_ciphers_tbl", + "values" : { + "1" : "{0xFF15, \"BDHE-BIGN_WITH-BELT-CTR-MAC-HBELT\"},", + "2" : "{0xFF16, \"BDHE-BIGN_WITH-BELT-DWP-HBELT\"},", + "3" : "{0xFF17, \"BDHT-BIGN_WITH-BELT-CTR-MAC-HBELT\"},", + "4" : "{0xFF18, \"BDHT-BIGN_WITH-BELT-DWP-HBELT\"},", + "5" : "{0xFF19, \"BDHE-PSK-BIGN_WITH-BELT-CTR-MAC-HBELT\"},", + "6" : "{0xFF1A, \"BDHE-PSK-BIGN_WITH-BELT-DWP-HBELT\"},", + "7" : "{0xFF1B, \"BDHT-PSK-BIGN_WITH-BELT-CTR-MAC-HBELT\"},", + "8" : "{0xFF1C, \"BDHT-PSK-BIGN_WITH-BELT-DWP-HBELT\"}," + } + }, + "2" : + { + "array_name" : "ssl_sigalg_tbl", + "values" : { + "1" : "{TLSEXT_SIGALG_bign_sign_128, \"bign_auth128\"},", + "2" : "{TLSEXT_SIGALG_bign_sign_192, \"bign_auth192\"},", + "3" : "{TLSEXT_SIGALG_bign_sign_256, \"bign_auth256\"}," + } + } + } + }, + "ssl/ssl_cert_table.h" : + { + "static_arrays" : + { + "1" : + { + "array_name" : "ssl_cert_info", + "values" : { + "1" : ",{NID_bign_pubkey, SSL_aBIGN}" + } + } + } + } +} diff --git a/btls/patch/patching.py b/btls/patch/patching.py new file mode 100644 index 0000000..aa23ba3 --- /dev/null +++ b/btls/patch/patching.py @@ -0,0 +1,205 @@ +# ***************************************************************************** +# \file patching.py +# \project bee2evp [EVP-interfaces over bee2 / engine of OpenSSL] +# \brief OpenSSL patching to support BTLS ciphersuites +# \created 2022.03.22 +# \version 2022.04.26 +# \license This program is released under the GNU General Public License +# version 3 with the additional exemption that compiling, linking, +# and/or using OpenSSL is allowed. See Copyright Notices in bee2evp/info.h. +# ***************************************************************************** + +import os +import re +import json +import multiline + + +def search_array(content, array_name): + start_idx = re.search(rf"static.*{array_name}", content).start() + end_idx = content.find('};', start_idx) + return content[start_idx:end_idx + 1] + + +def search_macro(content, macro_name): + macro_code = re.search(rf"#(\s*)define.*{macro_name}(\s+[\w\s|()\\]+\\?\n)+\n", + content) + return macro_code[0] + + +def search_func(content, func_name): + start_idx = re.search(rf"\w+\s\**{func_name}[^\;^\n]*\n", content).start() + end_idx = re.search(r"\n\}\n", content[start_idx:]).end() + + return content[start_idx:end_idx + start_idx + 1] + + +class Patch: + def __init__(self, patch_file): + with open("ssl/build.info", 'r') as f: + info_lines = f.readlines() + with open("ssl/build.info", 'w') as f: + info_lines[-1] = info_lines[-1][:-1] + " btls.c\n" + f.writelines(info_lines) + + with open(patch_file, 'r') as f: + patch = f.read() + + res = multiline.loads(patch, multiline=True) + + files = res.keys() + for file in files: + print(file) + static_arrays_dict = res[file].get('static_arrays') + static_arrays = {} + if static_arrays_dict: + static_arrays = static_arrays_dict.values() + + functions_dict = res[file].get('functions') + functions = {} + if functions_dict: + functions = functions_dict.values() + + macros_dict = res[file].get("macros") + macros = {} + if macros_dict: + macros = macros_dict.values() + + with open(file, 'r') as f: + content = f.read() + + if file in ["ssl/s3_lib.c", "ssl/ssl_ciph.c", "ssl/ssl_cert_table.h", + "ssl/ssl_lib.c", "ssl/t1_lib.c"]: + content = '# include "btls.h"\n' + content + if file in ["ssl/ssl_local.h"]: + pos = content.find("# include") + content = content[:pos] + '# include "btls.h"\n' + content[pos:] + + for array in static_arrays: + arr_code = search_array(content, array['array_name']) + arr_obj = StaticArray(arr_code) + for value in array['values'].values(): + arr_obj.append2c(value) + content = content.replace(arr_code, arr_obj.p2c()) + + for func in functions: + f = func['func_name'] + f_code = search_func(content, f) + f_obj = Function(f_code) + code2add = func.get('code') + end_flag = func.get('to_end') + if code2add != '' and end_flag: + f_obj.add_to_end(code2add) + + switch_cond = func.get('switch_name') + if code2add != '' and switch_cond: + f_obj.add_to_switch(switch_cond, code2add) + + insert_before = func.get('insert_before') + if code2add != '' and insert_before: + f_obj.insert_before(insert_before, code2add) + + change_if = func.get("change_if") + if code2add != '' and change_if: + f_obj.add_to_if_cond(change_if, code2add) + + content = content.replace(f_code, f_obj.get_code()) + + for macro in macros: + m = macro['macro_name'] + m_code = search_macro(content, m) + m_obj = Macro(m_code) + new_value = macro.get('new_value') + if new_value != '': + m_obj.set_value(new_value) + + content = content.replace(m_code, m_obj.p2c()) + + with open(file, "w") as f: + f.write(content) + + +class Macro: + def __init__(self, c): + self.c = c + tmp = self.c.split(' ', maxsplit=2) + self.value = tmp[1] if tmp[0] == '#' else tmp[2] + + def p2c(self): + return '# define ' + self.value + '\n' + + def set_value(self, value): + self.value = value + + +class Function: + def __init__(self, c): + self.c = c + + def add_to_end(self, code): + start_pos = self.c.rfind("return") + self.c = self.c[:start_pos] + code + '\n\t' + self.c[start_pos:] + + def add_to_switch(self, switch_cond, new_case): + start_pos = re.search(rf"switch\s*\({switch_cond}\)", self.c).start() + start_pos = self.c.find("case", start_pos) + self.c = self.c[:start_pos] + new_case + self.c[start_pos:] + + def add_to_if_cond(self, cond, new_cond): + p = re.escape(cond) + self.c = re.sub(rf"if\s*{p}", "if " + new_cond, self.c) + + def insert_before(self, before_line, new_code): + start_pos = self.c.find(before_line) + self.c = self.c[:start_pos] + new_code + self.c[start_pos:] + + def add_if(self, code_before, new_if): + start_pos = self.c.find(code_before) + self.c = self.c[:start_pos] + '\n' + new_if + '\n\t' + self.c[start_pos:] + + def get_code(self): + return self.c + + +class StaticArray: + def __init__(self, c): + self.c = c + self.c_array_def = c[:c.find('\n') + 1] + self.ended_by_comma = False + + start_pos = self.c.find('\n') + end_pos = len(c) - 1 + self.list = self.c[start_pos + 1:end_pos - 1].split('\n') + while self.list[-1] == '': + self.list.pop() + + last_idx = -1 + if self.list[last_idx][0] == '#': + last_idx = -2 + res = re.search(r'\s*\{*([\w\d\s\|\n])+(([,\s])*([\w\d\|\n\s]*))+\}*', self.list[last_idx]) + + if ((self.list[last_idx].find(',', res.end())) == -1 and + ((self.c_array_def == "static const ssl_trace_tbl ssl_sigalg_tbl[] = {\n") or + (self.c_array_def == "static const SIGALG_LOOKUP sigalg_lookup_tbl[] = {\n"))): + self.list[last_idx] = self.list[last_idx] + ',' + + self.spaces_before_item = c[start_pos + 1:re.search(r'[\S]', + c[start_pos + 1:]).start() + start_pos + 1] + + def p2c(self): + items = ''.join([x + '\n' for x in self.list[:-1]]) + items += self.list[-1] + '\n' + '}' + return self.c_array_def + items + + def append2c(self, item): + self.list.append(self.spaces_before_item + item) + + def insert_before(self, item_before, item): + self.list.insert(self.list.index(item_before), item) + + +def patch_ssl_ciph(): + Patch('patch.json') + +if __name__ == '__main__': + patch_ssl_ciph() diff --git a/doc/build.sh b/doc/build.sh deleted file mode 100644 index 77a7e93..0000000 --- a/doc/build.sh +++ /dev/null @@ -1,81 +0,0 @@ -#!/bin/bash - -bee2evp=`pwd`/.. -build_root=$bee2evp/build -bee2=$bee2evp/bee2 -openssl=$bee2evp/openssl -build_bee2evp=$build_root/build_bee2evp -build_bee2=$build_root/build_bee2 -build_openssl=$build_root/build_openssl -local=$build_root/local -openssl_branch=OpenSSL_1_1_1i -openssl_patch=openssl111i.patch - -install_prereq(){ - sudo apt-get update - sudo apt-get install git gcc cmake python3 -} - -clean(){ - rm -rf $build_root - rm -rf $openssl -} - -update_repos(){ - git submodule update --init - git clone -b $openssl_branch --depth 1 https://github.com/openssl/openssl $openssl - cd $openssl - git apply $bee2evp/btls/$openssl_patch - cp $bee2evp/btls/btls.c ./ssl/ - cp $bee2evp/btls/btls.h ./ssl/ -} - -build_bee2(){ - mkdir -p $build_bee2 && mkdir -p $local && cd $build_bee2 - cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_PIC=ON -DCMAKE_INSTALL_PREFIX=$local $bee2 - make -j$(nproc) && ctest && make install - ls -la $local/lib/libbee2_static.a -} - -build_openssl(){ - mkdir -p $build_openssl && mkdir -p $local && cd $build_openssl - $openssl/config shared -d --prefix=$local --openssldir=$local - make -j$(nproc) all - make install > build.log 2>&1 || (cat build.log && exit 1) - ls -la $local/lib/libcrypto.a - ls -la $local/lib/libssl.a - ls -la $local/lib/libcrypto.so - ls -la $local/lib/libssl.so -} - -build_bee2evp(){ - mkdir -p $build_bee2evp && cd $build_bee2evp - cmake -DCMAKE_BUILD_TYPE=Release \ - -DBEE2_LIBRARY_DIRS=$local/lib -DBEE2_INCLUDE_DIRS=$local/include \ - -DOPENSSL_LIBRARY_DIRS=$local/lib -DOPENSSL_INCLUDE_DIRS=$local/include \ - -DLIB_INSTALL_DIR=$local/lib -DCMAKE_INSTALL_PREFIX=$local $bee2evp - make -j$(nproc) && make install - ls -la $local/lib/libbee2evp.so -} - -attach_bee2evp(){ - cp $bee2evp/doc/bee2evp.cnf $local/openssl.cnf - sed -i "s|#path/to/bee2evp|$local/lib/libbee2evp.so|g" $local/openssl.cnf -} - -test_bee2evp(){ - export LD_LIBRARY_PATH="$local/lib:${LD_LIBRARY_PATH:-}" - cd $local/bin - ./openssl version - ./openssl engine -c -t bee2evp -} - -install_prereq - -clean -update_repos -build_bee2 -build_openssl -build_bee2evp -attach_bee2evp -test_bee2evp diff --git a/src/bee2evp.c b/src/bee2evp.c index 7ae1894..357439a 100644 --- a/src/bee2evp.c +++ b/src/bee2evp.c @@ -77,6 +77,17 @@ static err_t rngReadOpenssl(size_t* read, void* buf, size_t count, void* file) ******************************************************************************* */ +/*static err_t rngReadOpenssl(size_t* read, void* buf, size_t count, void* file) +{ + ASSERT(memIsValid(read, O_PER_S)); + ASSERT(memIsValid(buf, count)); + if ((size_t)(int)count == count && RAND_priv_bytes(buf, (int)count)) + *read = count; + else + *read = 0; + return ERR_OK; +}*/ + static int bee2evp_init(ENGINE* e) { if (rngCreate(0, 0) != ERR_OK) diff --git a/test/test.py b/test/test.py index 1e2b963..7389696 100644 --- a/test/test.py +++ b/test/test.py @@ -455,63 +455,6 @@ def btls_issue_cert(privfile, certfile): .format(privfile, certfile)) retcode, block, er__ = openssl(cmd) -'''def btls_server256_nopsk(tmpdirname, server_log_file): - priv256 = os.path.join(tmpdirname, 'priv256.key') - btls_gen_privkey(priv256, 'bign-curve256v1') - - cert = os.path.join(tmpdirname, 'cert.pem') - btls_issue_cert(priv256, cert) - - cmd = ('s_server -key {} -cert {} -tls1_2 >> {}' - .format(priv256, cert, server_log_file)) - global server_nopsk - server_nopsk = openssl(cmd, type_=1)''' - -'''def btls_server_dhepsk(tmpdirname, server_log_file): - priv256 = os.path.join(tmpdirname, 'priv256.key') - btls_gen_privkey(priv256) - - cert = os.path.join(tmpdirname, 'cert.pem') - btls_issue_cert(priv256, cert) - - cmd = ('s_server -tls1_2 -psk 123456 -psk_hint 123 -nocert >> {}' - .format(server_log_file)) - global server_dhepsk - server_dhepsk = openssl(cmd, type_=1)''' - -'''def btls_server_dhtpsk(tmpdirname, server_log_file): - priv256 = os.path.join(tmpdirname, 'priv256.key') - btls_gen_privkey(priv256) - - cert = os.path.join(tmpdirname, 'cert.pem') - btls_issue_cert(priv256, cert) - - cmd = ('s_server -tls1_2 -key {} -cert {} -psk 123456 -psk_hint 123 >> {}' - .format(priv256, cert, server_log_file)) - global server_dhtpsk - server_dhtpsk = openssl(cmd, type_=1)''' - -'''def btls_server(tmpdirname, server_log_file, curves, psk=False, bdhtpsk=False): - if bdhtpsk: - cmd = ('s_server -tls1_2 -psk 123456 -psk_hint 123 -nocert >> {}' - .format(server_log_file)) - else: - priv = os.path.join(tmpdirname, '{}.key'.format(curves)) - btls_gen_privkey(priv) - - cert = os.path.join(tmpdirname, 'cert.pem') - btls_issue_cert(priv, cert) - - if psk: - cmd = ('s_server -tls1_2 -key {} -cert {} -psk 123456 -psk_hint 123 >> {}' - .format(priv, cert, server_log_file)) - else: - cmd = ('s_server -key {} -cert {} -tls1_2 >> {}' - .format(priv, cert, server_log_file)) - - global server - server = openssl(cmd, type_=1)''' - def btls_server_cert(tmpdirname, server_log_file, curve, psk=False): priv = os.path.join(tmpdirname, '{}.key'.format(curve)) btls_gen_privkey(priv, curve)