@@ -5498,6 +5498,112 @@ do
54985498 } \
54995499} while(0)
55005500
5501+ static void test_crypto_aead_vectors ()
5502+ {
5503+ // Known-answer test for the two AEAD primitives netcode relies on, exercising
5504+ // whichever implementation the running CPU selects (reference / SSSE3 / AVX2 for
5505+ // ChaCha20, donna / SSE2 for Poly1305). Expected ciphertext was generated from
5506+ // libsodium reference output and is unchanged across 1.0.20 -> 1.0.22. Do not
5507+ // edit these arrays by hand: a golden failure here means the vendored crypto no
5508+ // longer agrees with upstream, which would break every other netcode
5509+ // implementation on the wire.
5510+ //
5511+ // Declared static on purpose. yojimbo vendors this file and compiles it with
5512+ // NETCODE_ENABLE_TESTS=1 while defining its own test_crypto_aead_vectors in
5513+ // test.cpp; internal linkage keeps the two from colliding.
5514+
5515+ static const uint8_t kat_key [32 ] = {
5516+ 0x40 ,0x41 ,0x42 ,0x43 ,0x44 ,0x45 ,0x46 ,0x47 ,0x48 ,0x49 ,0x4a ,0x4b ,
5517+ 0x4c ,0x4d ,0x4e ,0x4f ,0x50 ,0x51 ,0x52 ,0x53 ,0x54 ,0x55 ,0x56 ,0x57 ,
5518+ 0x58 ,0x59 ,0x5a ,0x5b ,0x5c ,0x5d ,0x5e ,0x5f ,
5519+ };
5520+ static const uint8_t kat_ad [12 ] = {
5521+ 0xc0 ,0xc1 ,0xc2 ,0xc3 ,0xc4 ,0xc5 ,0xc6 ,0xc7 ,0xc8 ,0xc9 ,0xca ,0xcb ,
5522+ };
5523+ static const uint8_t kat_msg [58 ] = {
5524+ 0x79 ,0x6f ,0x6a ,0x69 ,0x6d ,0x62 ,0x6f ,0x20 ,0x76 ,0x65 ,0x6e ,0x64 ,0x6f ,0x72 ,0x65 ,0x64 ,0x20 ,0x6c ,0x69 ,0x62 ,
5525+ 0x73 ,0x6f ,0x64 ,0x69 ,0x75 ,0x6d ,0x20 ,0x41 ,0x45 ,0x41 ,0x44 ,0x20 ,0x6b ,0x6e ,0x6f ,0x77 ,0x6e ,0x2d ,0x61 ,0x6e ,
5526+ 0x73 ,0x77 ,0x65 ,0x72 ,0x20 ,0x74 ,0x65 ,0x73 ,0x74 ,0x20 ,0x76 ,0x65 ,0x63 ,0x74 ,0x6f ,0x72 ,0x21 ,0x21 ,
5527+ };
5528+ static const uint8_t kat_npub_ietf [12 ] = {
5529+ 0xa0 ,0xa1 ,0xa2 ,0xa3 ,0xa4 ,0xa5 ,0xa6 ,0xa7 ,0xa8 ,0xa9 ,0xaa ,0xab ,
5530+ };
5531+ static const uint8_t kat_ct_ietf [74 ] = {
5532+ 0xd5 ,0xae ,0xb1 ,0x85 ,0x15 ,0x8b ,0x07 ,0xb3 ,0x01 ,0x15 ,0xf0 ,0x59 ,
5533+ 0xb4 ,0x4e ,0x9d ,0x45 ,0x91 ,0x58 ,0xab ,0xff ,0xaf ,0xbd ,0x81 ,0x4f ,
5534+ 0xbf ,0x52 ,0xc2 ,0x4c ,0xa1 ,0x5e ,0x60 ,0x5f ,0x58 ,0x63 ,0x31 ,0x96 ,
5535+ 0xda ,0x90 ,0x07 ,0x63 ,0xb9 ,0x0c ,0x21 ,0x46 ,0xf2 ,0xe4 ,0x65 ,0x96 ,
5536+ 0x7a ,0x81 ,0x7f ,0xa2 ,0x5d ,0xd1 ,0x79 ,0xf6 ,0x9b ,0x18 ,0x5d ,0xe0 ,
5537+ 0xb6 ,0x57 ,0x93 ,0xbe ,0x8c ,0xb5 ,0xa9 ,0x75 ,0x98 ,0xa4 ,0x6f ,0xd5 ,
5538+ 0xbe ,0x9d ,
5539+ };
5540+ static const uint8_t kat_npub_xchacha [24 ] = {
5541+ 0x10 ,0x11 ,0x12 ,0x13 ,0x14 ,0x15 ,0x16 ,0x17 ,0x18 ,0x19 ,0x1a ,0x1b ,
5542+ 0x1c ,0x1d ,0x1e ,0x1f ,0x20 ,0x21 ,0x22 ,0x23 ,0x24 ,0x25 ,0x26 ,0x27 ,
5543+ };
5544+ static const uint8_t kat_ct_xchacha [74 ] = {
5545+ 0x2b ,0x24 ,0x83 ,0x2a ,0x6c ,0x9e ,0x21 ,0x02 ,0x2a ,0x14 ,0x32 ,0x56 ,
5546+ 0x4b ,0x27 ,0x37 ,0x92 ,0x24 ,0x40 ,0xa9 ,0x92 ,0xd3 ,0x53 ,0xa7 ,0xa5 ,
5547+ 0x64 ,0xd3 ,0x8e ,0x0c ,0x75 ,0x79 ,0x75 ,0x3f ,0xca ,0x82 ,0xfa ,0x85 ,
5548+ 0xf0 ,0xa6 ,0xac ,0x08 ,0x9a ,0x25 ,0xf1 ,0x8f ,0x42 ,0x20 ,0x70 ,0x8e ,
5549+ 0x38 ,0x25 ,0xd1 ,0x08 ,0x45 ,0x81 ,0x75 ,0x18 ,0xe4 ,0xd1 ,0x88 ,0xbd ,
5550+ 0x92 ,0xfa ,0x84 ,0xdc ,0xd6 ,0xa3 ,0x9a ,0x67 ,0x52 ,0x91 ,0x62 ,0xf4 ,
5551+ 0x86 ,0x7b ,
5552+ };
5553+
5554+ uint8_t c [128 ];
5555+ uint8_t m [128 ];
5556+ unsigned long long clen = 0 ;
5557+ unsigned long long mlen = 0 ;
5558+
5559+ // ChaCha20-Poly1305 (IETF) -- the construction netcode uses on the wire
5560+
5561+ check ( crypto_aead_chacha20poly1305_ietf_encrypt ( c , & clen , kat_msg , sizeof ( kat_msg ), kat_ad , sizeof ( kat_ad ), NULL , kat_npub_ietf , kat_key ) == 0 );
5562+ check ( clen == sizeof ( kat_ct_ietf ) );
5563+ check ( memcmp ( c , kat_ct_ietf , (size_t ) clen ) == 0 );
5564+ check ( crypto_aead_chacha20poly1305_ietf_decrypt ( m , & mlen , NULL , c , clen , kat_ad , sizeof ( kat_ad ), kat_npub_ietf , kat_key ) == 0 );
5565+ check ( mlen == sizeof ( kat_msg ) );
5566+ check ( memcmp ( m , kat_msg , (size_t ) mlen ) == 0 );
5567+
5568+ // a tampered tag must be rejected. this is the path ACQUIRE_FENCE guards: the
5569+ // plaintext must not be produced before authentication has completed.
5570+
5571+ c [0 ] ^= 0x01 ;
5572+ check ( crypto_aead_chacha20poly1305_ietf_decrypt ( m , & mlen , NULL , c , clen , kat_ad , sizeof ( kat_ad ), kat_npub_ietf , kat_key ) != 0 );
5573+
5574+ // XChaCha20-Poly1305
5575+
5576+ check ( crypto_aead_xchacha20poly1305_ietf_encrypt ( c , & clen , kat_msg , sizeof ( kat_msg ), kat_ad , sizeof ( kat_ad ), NULL , kat_npub_xchacha , kat_key ) == 0 );
5577+ check ( clen == sizeof ( kat_ct_xchacha ) );
5578+ check ( memcmp ( c , kat_ct_xchacha , (size_t ) clen ) == 0 );
5579+ check ( crypto_aead_xchacha20poly1305_ietf_decrypt ( m , & mlen , NULL , c , clen , kat_ad , sizeof ( kat_ad ), kat_npub_xchacha , kat_key ) == 0 );
5580+ check ( mlen == sizeof ( kat_msg ) );
5581+ check ( memcmp ( m , kat_msg , (size_t ) mlen ) == 0 );
5582+ c [0 ] ^= 0x01 ;
5583+ check ( crypto_aead_xchacha20poly1305_ietf_decrypt ( m , & mlen , NULL , c , clen , kat_ad , sizeof ( kat_ad ), kat_npub_xchacha , kat_key ) != 0 );
5584+
5585+ // the constant-time comparison that checks the Poly1305 tag. libsodium 1.0.21
5586+ // hardened crypto_verify_n against the compiler optimising it into something
5587+ // branchy; these assertions pin its contract.
5588+
5589+ uint8_t a [64 ], b [64 ];
5590+ int i ;
5591+ for ( i = 0 ; i < 64 ; i ++ ) { a [i ] = (uint8_t ) i ; b [i ] = (uint8_t ) i ; }
5592+ check ( crypto_verify_16 ( a , b ) == 0 );
5593+ check ( crypto_verify_32 ( a , b ) == 0 );
5594+ check ( crypto_verify_64 ( a , b ) == 0 );
5595+ for ( i = 0 ; i < 8 ; i ++ )
5596+ {
5597+ b [0 ] = (uint8_t ) ( a [0 ] ^ ( 1u << i ) );
5598+ check ( crypto_verify_16 ( a , b ) == -1 );
5599+ check ( crypto_verify_32 ( a , b ) == -1 );
5600+ check ( crypto_verify_64 ( a , b ) == -1 );
5601+ }
5602+ b [0 ] = a [0 ];
5603+ b [63 ] = (uint8_t ) ( a [63 ] ^ 0x80 );
5604+ check ( crypto_verify_64 ( a , b ) == -1 );
5605+ }
5606+
55015607static void test_queue ()
55025608{
55035609 struct netcode_packet_queue_t queue ;
@@ -9511,6 +9617,7 @@ void netcode_test()
95119617{
95129618 //while ( 1 )
95139619 {
9620+ RUN_TEST ( test_crypto_aead_vectors );
95149621 RUN_TEST ( test_queue );
95159622 RUN_TEST ( test_endian );
95169623 RUN_TEST ( test_address );
0 commit comments