blob: a8262b8e7a2358ae9fb2baf69d3c5687e477f43d [file] [log] [blame]
#!/bin/bash
# Copyright 2018 Google LLC
#
# Use of this source code is governed by an MIT-style
# license that can be found in the LICENSE file or at
# https://opensource.org/licenses/MIT.
set -e
# cd to the directory this script lives in
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"
if [ $# -ne 3 ]; then
echo "Usage: $0 <major> <minor> <patch>" >&2
exit 1
fi
MAJOR="$1"
MINOR="$2"
PATCH="$3"
# TODO(joshlf):
# - Use the --use-core flag once std isn't required (see
# https://github.com/rust-lang-nursery/rust-bindgen/issues/1015)
# Only include the symbols we want. It's important that we take the minimum
# dependency on BoringSSL so that we provide the minimum burden for them. The
# more symbols we depend on, the more likely it is that a change that they want
# to make will affect us, which they will care about, making them either expend
# effort in a graceful transition or decide to abandon the change. Thus, instead
# of whitelisting broad classes of symbols, we explicitly whitelist the exact
# list of symbols that Mundane depends on.
# TODO(inejge):
# - When https://github.com/rust-lang-nursery/rust-bindgen/issues/1375 is resolved,
# go back to a single whitelist
# Split the whitelist into function names and other symbols, in order to use the
# former for a consistency check of the postprocessing step which adds the
# #[link_name...] attributes. Any change of the whitelist must be made to the
# appropriate sub-list.
WHITELIST_FUNCS="BN_free|\
BN_init|\
BN_set_u64|\
CBS_init|\
CBS_len|\
CBB_init|\
CBB_cleanup|\
CBB_data|\
CBB_len|\
ED25519_keypair|\
ED25519_sign|\
ED25519_verify|\
ED25519_keypair_from_seed|\
EC_GROUP_new_by_curve_name|\
EC_GROUP_get_curve_name|\
EC_curve_nid2nist|\
EC_KEY_new|\
EC_KEY_free|\
EC_KEY_up_ref|\
EC_KEY_get0_group|\
EC_KEY_set_group|\
EC_KEY_generate_key|\
EC_KEY_parse_private_key|\
EC_KEY_marshal_private_key|\
ECDSA_sign|\
ECDSA_verify|\
ECDSA_size|\
ERR_print_errors_cb|\
EVP_sha1|\
EVP_sha256|\
EVP_sha384|\
EVP_sha512|\
EVP_PKEY_new|\
EVP_PKEY_free|\
EVP_PKEY_up_ref|\
EVP_PKEY_assign_EC_KEY|\
EVP_PKEY_assign_RSA|\
EVP_PKEY_get1_EC_KEY|\
EVP_PKEY_get1_RSA|\
EVP_parse_public_key|\
EVP_marshal_public_key|\
PKCS5_PBKDF2_HMAC|\
EVP_PBE_scrypt|\
HMAC_CTX_init|\
HMAC_CTX_cleanup|\
HMAC_Init_ex|\
HMAC_Update|\
HMAC_Final|\
HMAC_size|\
CRYPTO_memcmp|\
RAND_bytes|\
RSA_bits|\
RSA_free|\
RSA_generate_key_ex|\
RSA_marshal_private_key|\
RSA_new|\
RSA_parse_private_key|\
RSA_sign|\
RSA_sign_pss_mgf1|\
RSA_size|\
RSA_up_ref|\
RSA_verify|\
RSA_verify_pss_mgf1|\
SHA1_Init|\
SHA1_Update|\
SHA1_Final|\
SHA256_Init|\
SHA256_Update|\
SHA256_Final|\
SHA384_Init|\
SHA384_Update|\
SHA384_Final|\
SHA512_Init|\
SHA512_Update|\
SHA512_Final"
WHITELIST_OTHERS="BIGNUM|\
BN_GENCB|\
CBB|\
CBS|\
EC_GROUP|\
EC_KEY|\
ED25519_PRIVATE_KEY_LEN|\
ED25519_PUBLIC_KEY_LEN|\
ED25519_SIGNATURE_LEN|\
EVP_MD|\
EVP_PKEY|\
HMAC_CTX|\
NID_X9_62_prime256v1|\
NID_secp384r1|\
NID_secp521r1|\
NID_sha1|\
NID_sha256|\
NID_sha384|\
NID_sha512|\
RSA|\
RSA_F4|\
SHA_CTX|\
SHA_DIGEST_LENGTH|\
SHA256_CTX|\
SHA256_DIGEST_LENGTH|\
SHA512_CTX|\
SHA384_DIGEST_LENGTH|\
SHA512_CTX|\
SHA512_DIGEST_LENGTH"
WHITELIST="(${WHITELIST_FUNCS}|${WHITELIST_OTHERS})"
# NOTE(joshlf): Currently, we don't pass --target since none of the symbols
# we're linking against are architecture-specific (TODO: are any of them
# word-size-specific?). If this ever becomes a problem, then the thing to do is
# probably to generate different files for different platforms
# (boringssl_x86_64.rs, boringssl_arm64.rs, etc) and conditionally compile them
# depending on target.
bindgen bindgen.h --whitelist-function "$WHITELIST" --whitelist-type "$WHITELIST" \
--whitelist-var "$WHITELIST" -o boringssl.rs -- -I ./boringssl/include
TMP="$(mktemp)"
# Prepend copyright comment, #[allow] for various warnings we don't care about,
# and a line telling Rust to link against libcrypto.
(cat <<'EOF'
// Copyright 2018 Google LLC
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.
// Some symbols are only used with certain features enabled, so we need to
// suppress the unused warning when those features aren't enabled.
#![allow(unused)]
// Only necessary for test_symbol_conflict.sh, which exposes these symbols
// through Mundane's public interface.
#![allow(missing_docs)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
EOF
# Do this on a separate line because we need string interpolation, but we can't
# use string interpolation in the preceding 'cat' command, or else the !
# characters would be interpreted.
echo "#[link(name = \"crypto_${MAJOR}_${MINOR}_${PATCH}\")] extern {}"
echo
cat boringssl.rs) \
| rustfmt \
| (
# Postprocess the generated bindings, adding the "#[link_name ...]"
# attribute to exported functions. Since the function sites are matched
# lexically, check the consistency of matches against the list of function
# names defined above. An error will be returned if a) a matched function
# is not in the whitelist, b) a name from the whitelist wasn't matched
# in the input, or c) a name was matched more than once (which should
# never happen).
awk -v "vers=${MAJOR}_${MINOR}_${PATCH}_" -v "funcs=${WHITELIST_FUNCS}" '
BEGIN {
split(funcs, fa, "[|]")
for (fn in fa)
f[fa[fn]]
}
/extern "C" {/ {
print
getline
if ($0 ~ "#[[]link_name")
getline
if ($0 ~ "pub fn") {
fn = $3
sub("[(].*", "", fn)
if (!(fn in f)) {
print "fatal: fn not in whitelist: " fn | "cat >&2"
exit 1
} else
f[fn]++
print " #[link_name = \"__RUST_MUNDANE_" vers fn "\"]"
}
}
{ print }
END {
for (fn in f)
if (f[fn] != 1) {
print "fatal: fn match count = " f[fn] + 0 ", should be 1: " fn | "cat >&2"
exit 1
}
}') > "$TMP"
mv "$TMP" boringssl.rs