Przez ostatnie kilka dni siedziałem głęboko w budowaniu różnych tuneli i VPN'ów między serwerami. Po drodze musiałem przebrnąć przez różne zakamarki linux'ów, wiele poczytać i pozgłębiać tematykę różnych rodzajów komunikacji. Podczas tej ciekawej przygody natknąłem się na oprogramowanie o nazwie WireGuard ... Nie zgłębiając do czego służy bo nie o tym chcę pisać doszło do sytuacji, w której wyniknęła potrzeba pobrania jego źródeł. Zacząłem je przeglądać i naszła mnie pewna refleksja ...
Czy to Oprogramowanie pisali amatorzy czy profesjonaliści?
Jeszcze kilak dni temu był na forum gorący temat o długości funkcji, w którym niektórzy z mocą "domestosa" głosili jakie to funkcje muszą być krótkie bo inne to się źle odpluskwia, źle czyta i w ogóle samo zło z tego wynika ... Tymczasem
https://git.zx2c4.com/wireguard-linux/tree/drivers/net/wireguard/noise.c
albo w pliku main na dzień dobry używają Go to :
Toż to trzeba tam natychmiast inkwizycję wysłać. Cóż za antywzorce. Jak z tym żyć ?
Tymczasem sam Pan Linus Torvalds powiedział, że ten kod to "dzieło sztuki" - no ale on to się pewnie na pisaniu w c nie zna tak jak forumowi ewangeliści.
"WireGuard's design seeks to reduce these issues, aiming to make the tunnel more secure and easier to manage by default. By using versioning of cryptography packages, it focuses on ciphers believed to be among the most secure current encryption methods, and at the time of the Ars Technica review had a codebase of around 4000 lines of kernel code, about 1% of either OpenVPN or IPsec, making security audits easier, and praised by the Linux kernel creator Linus Torvalds compared to OpenVPN and IPsec as a "work of art"." ( https://en.wikipedia.org/wiki/WireGuard )
Moje zdanie na ten temat jest takie jak zawsze ... Bezmyślne stosowanie nawet najlepszych wzorców tylko dlatego, że są popularne to przejaw amatorszczyzny a nie profesjonalizmu. Dobry programista ma myśleć i pisać z dobrze i z wyobraźnią a nie wg szablonu. Wg szablonu to pracuje się "od 6 rano na taśmie w fabryce azbestu" :-)
Przykłady:
/* This is Hugo Krawczyk's HKDF:
* - https://eprint.iacr.org/2010/264.pdf
* - https://tools.ietf.org/html/rfc5869
*/
static void kdf(u8 *first_dst, u8 *second_dst, u8 *third_dst, const u8 *data,
size_t first_len, size_t second_len, size_t third_len,
size_t data_len, const u8 chaining_key[NOISE_HASH_LEN])
{
u8 output[BLAKE2S_HASH_SIZE + 1];
u8 secret[BLAKE2S_HASH_SIZE];
WARN_ON(IS_ENABLED(DEBUG) &&
(first_len > BLAKE2S_HASH_SIZE ||
second_len > BLAKE2S_HASH_SIZE ||
third_len > BLAKE2S_HASH_SIZE ||
((second_len || second_dst || third_len || third_dst) &&
(!first_len || !first_dst)) ||
((third_len || third_dst) && (!second_len || !second_dst))));
/* Extract entropy from data into secret */
blake2s256_hmac(secret, data, chaining_key, data_len, NOISE_HASH_LEN);
if (!first_dst || !first_len)
goto out;
/* Expand first key: key = secret, data = 0x1 */
output[0] = 1;
blake2s256_hmac(output, output, secret, 1, BLAKE2S_HASH_SIZE);
memcpy(first_dst, output, first_len);
if (!second_dst || !second_len)
goto out;
/* Expand second key: key = secret, data = first-key || 0x2 */
output[BLAKE2S_HASH_SIZE] = 2;
blake2s256_hmac(output, output, secret, BLAKE2S_HASH_SIZE + 1,
BLAKE2S_HASH_SIZE);
memcpy(second_dst, output, second_len);
if (!third_dst || !third_len)
goto out;
/* Expand third key: key = secret, data = second-key || 0x3 */
output[BLAKE2S_HASH_SIZE] = 3;
blake2s256_hmac(output, output, secret, BLAKE2S_HASH_SIZE + 1,
BLAKE2S_HASH_SIZE);
memcpy(third_dst, output, third_len);
out:
/* Clear sensitive data from stack */
memzero_explicit(secret, BLAKE2S_HASH_SIZE);
memzero_explicit(output, BLAKE2S_HASH_SIZE + 1);
}