From fa36dae8169ac27210c64c6c03fbc4b01c4acd0a Mon Sep 17 00:00:00 2001 From: Brian Gix Date: Fri, 30 Aug 2019 12:15:27 -0700 Subject: [PATCH] mesh: test AEAD at startup to check kernel support One time test at startup to ensure either kernel version v4.9 or later, *or* that required AES-CCM support has been back-ported. If support not there, daemon will run without providing D-Bus service or attaching to controllers (prevents systemd thrashing). Change-Id: Id54fe45cf7c1c3c1ce52a91d8f515dbd2e868a09 Signed-off-by: Anupam Roy --- mesh/crypto.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ mesh/crypto.h | 1 + mesh/main.c | 7 +++++++ 3 files changed, 62 insertions(+) diff --git a/mesh/crypto.c b/mesh/crypto.c index 406011a..6292c1d 100644 --- a/mesh/crypto.c +++ b/mesh/crypto.c @@ -1129,3 +1129,57 @@ bool mesh_crypto_check_fcs(const uint8_t *packet, uint8_t packet_len, return fcs == 0xcf; } + +/* This function performs a quick-check of ELL and Kernel AEAD encryption. + * Some kernel versions before v4.9 have a known AEAD bug. If the system + * running this test is using a v4.8 or earlier kernel, a failure here is + * likely unless AEAD encryption has been backported. + */ +static const uint8_t crypto_test_result[] = { + 0x75, 0x03, 0x7e, 0xe2, 0x89, 0x81, 0xbe, 0x59, + 0xbc, 0xe6, 0xdd, 0x23, 0x63, 0x5b, 0x16, 0x61, + 0xb7, 0x23, 0x92, 0xd4, 0x86, 0xee, 0x84, 0x29, + 0x9a, 0x2a, 0xbf, 0x96 +}; + +bool mesh_crypto_check_avail() +{ + void *cipher; + bool result; + uint8_t i; + union { + struct { + uint8_t key[16]; + uint8_t aad[16]; + uint8_t nonce[13]; + uint8_t data[20]; + uint8_t mic[8]; + } crypto; + uint8_t bytes[0]; + } u; + uint8_t out_msg[sizeof(u.crypto.data) + sizeof(u.crypto.mic)]; + + l_debug("Testing Crypto"); + for (i = 0; i < sizeof(u); i++) { + u.bytes[i] = 0x60 + i; + } + + cipher = l_aead_cipher_new(L_AEAD_CIPHER_AES_CCM, u.crypto.key, + sizeof(u.crypto.key), sizeof(u.crypto.mic)); + + if (!cipher) + return false; + + result = l_aead_cipher_encrypt(cipher, + u.crypto.data, sizeof(u.crypto.data), + u.crypto.aad, sizeof(u.crypto.aad), + u.crypto.nonce, sizeof(u.crypto.nonce), + out_msg, sizeof(out_msg)); + + if (result) + result = !memcmp(out_msg, crypto_test_result, sizeof(out_msg)); + + l_aead_cipher_free(cipher); + + return result; +} diff --git a/mesh/crypto.h b/mesh/crypto.h index 1a73bca..e5ce840 100644 --- a/mesh/crypto.h +++ b/mesh/crypto.h @@ -161,3 +161,4 @@ bool mesh_crypto_check_fcs(const uint8_t *packet, uint8_t packet_len, uint8_t received_fcs); bool mesh_crypto_aes_cmac(const uint8_t key[16], const uint8_t *msg, size_t msg_len, uint8_t res[16]); +bool mesh_crypto_check_avail(void); diff --git a/mesh/main.c b/mesh/main.c index 6854e5d..6082443 100644 --- a/mesh/main.c +++ b/mesh/main.c @@ -33,6 +33,7 @@ #include "lib/mgmt.h" #include "mesh/mesh.h" +#include "mesh/crypto.h" #include "mesh/dbus.h" #include "mesh/mesh-io.h" @@ -120,6 +121,12 @@ int main(int argc, char *argv[]) l_log_set_stderr(); + if (!mesh_crypto_check_avail()) { + l_error("Mesh Crypto functions unavailable"); + status = l_main_run_with_signal(signal_handler, NULL); + goto done; + } + for (;;) { int opt; const char *str; -- 2.7.4