diff options
author | Keegan McAllister <mcallister.keegan@gmail.com> | 2012-03-28 04:53:11 -0400 |
---|---|---|
committer | Keith Winstein <keithw@mit.edu> | 2012-04-06 23:43:42 -0400 |
commit | c354a69ee6a9c991d07914c0290433ec3bc05607 (patch) | |
tree | b14b44794e66acdaa5b290a7ab7babc476074a51 /src | |
parent | d1c4b0a5d7c8b12e62be5917369278b46fe92e3c (diff) |
Test the Mosh crypto layer
Diffstat (limited to 'src')
-rw-r--r-- | src/crypto/prng.h | 6 | ||||
-rw-r--r-- | src/tests/.gitignore | 1 | ||||
-rw-r--r-- | src/tests/Makefile.am | 6 | ||||
-rw-r--r-- | src/tests/encrypt-decrypt.cc | 139 | ||||
-rw-r--r-- | src/tests/test_utils.cc | 4 | ||||
-rw-r--r-- | src/tests/test_utils.h | 3 |
6 files changed, 158 insertions, 1 deletions
diff --git a/src/crypto/prng.h b/src/crypto/prng.h index ef435bd..2f0287c 100644 --- a/src/crypto/prng.h +++ b/src/crypto/prng.h @@ -78,6 +78,12 @@ class PRNG { fill( &x, 4 ); return x; } + + uint64_t uint64() { + uint64_t x; + fill( &x, 8 ); + return x; + } }; #endif diff --git a/src/tests/.gitignore b/src/tests/.gitignore index c24b293..0d56ed6 100644 --- a/src/tests/.gitignore +++ b/src/tests/.gitignore @@ -1 +1,2 @@ /ocb-aes +/encrypt-decrypt diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am index 8489aa6..6108f05 100644 --- a/src/tests/Makefile.am +++ b/src/tests/Makefile.am @@ -1,9 +1,13 @@ AM_CXXFLAGS = $(WARNING_CXXFLAGS) $(PICKY_CXXFLAGS) -fno-default-inline -pipe if BUILD_TESTS - noinst_PROGRAMS = ocb-aes + noinst_PROGRAMS = ocb-aes encrypt-decrypt endif ocb_aes_SOURCES = ocb-aes.cc test_utils.cc ocb_aes_CPPFLAGS = -I$(srcdir)/../crypto -I$(srcdir)/../util ocb_aes_LDADD = ../crypto/libmoshcrypto.a ../util/libmoshutil.a + +encrypt_decrypt_SOURCES = encrypt-decrypt.cc test_utils.cc +encrypt_decrypt_CPPFLAGS = -I$(srcdir)/../crypto -I$(srcdir)/../util +encrypt_decrypt_LDADD = ../crypto/libmoshcrypto.a ../util/libmoshutil.a diff --git a/src/tests/encrypt-decrypt.cc b/src/tests/encrypt-decrypt.cc new file mode 100644 index 0000000..196ad95 --- /dev/null +++ b/src/tests/encrypt-decrypt.cc @@ -0,0 +1,139 @@ +/* + Mosh: the mobile shell + Copyright 2012 Keith Winstein + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/* Tests the Mosh crypto layer by encrypting and decrypting a bunch of random + messages, interspersed with some random bad ciphertexts which we need to + reject. */ + +#include <stdio.h> + +#define __STDC_FORMAT_MACROS +#include <inttypes.h> + +#include "crypto.h" +#include "prng.h" +#include "fatal_assert.h" +#include "test_utils.h" + +using namespace Crypto; + +PRNG prng; + +const size_t MESSAGE_SIZE_MAX = 4096; +const size_t MESSAGES_PER_SESSION = 256; +const size_t NUM_SESSIONS = 64; + +bool verbose = true; + +#define NONCE_FMT "%016"PRIx64 + +std::string random_payload( void ) { + const size_t len = prng.uint32() % MESSAGE_SIZE_MAX; + char *buf = new char[len]; + prng.fill( buf, len ); + + std::string payload( buf, len ); + delete [] buf; + return payload; +} + +void test_bad_decrypt( Session &decryption_session ) { + std::string bad_ct = random_payload(); + + bool got_exn = false; + try { + decryption_session.decrypt( bad_ct ); + } catch ( CryptoException e ) { + got_exn = true; + + /* The "bad decrypt" exception needs to be non-fatal, otherwise we are + vulnerable to an easy DoS. */ + fatal_assert( ! e.fatal ); + } + + if ( verbose ) { + hexdump( bad_ct, "bad ct" ); + } + fatal_assert( got_exn ); +} + +/* Generate a single key and initial nonce, then perform some encryptions. */ +void test_one_session( void ) { + Base64Key key; + Session encryption_session( key ); + Session decryption_session( key ); + + uint64_t nonce_int = prng.uint64(); + + if ( verbose ) { + hexdump( key.data(), 16, "key" ); + } + + for ( size_t i=0; i<MESSAGES_PER_SESSION; i++ ) { + Nonce nonce( nonce_int ); + fatal_assert( nonce.val() == nonce_int ); + + std::string plaintext = random_payload(); + if ( verbose ) { + printf( DUMP_NAME_FMT NONCE_FMT "\n", "nonce", nonce_int ); + hexdump( plaintext, "pt" ); + } + + std::string ciphertext = encryption_session.encrypt( Message( nonce, plaintext ) ); + if ( verbose ) { + hexdump( ciphertext, "ct" ); + } + + Message decrypted = decryption_session.decrypt( ciphertext ); + if ( verbose ) { + printf( DUMP_NAME_FMT NONCE_FMT "\n", "dec nonce", decrypted.nonce.val() ); + hexdump( decrypted.text, "dec pt" ); + } + + fatal_assert( decrypted.nonce.val() == nonce_int ); + fatal_assert( decrypted.text == plaintext ); + + nonce_int++; + + if ( ! ( prng.uint8() % 16 ) ) { + test_bad_decrypt( decryption_session ); + } + + if ( verbose ) { + printf( "\n" ); + } + } +} + +int main( int argc, char *argv[] ) { + if ( ( argc >= 2 ) && !strcmp( argv[ 1 ], "-q" ) ) { + verbose = false; + } + + for ( size_t i=0; i<NUM_SESSIONS; i++ ) { + try { + test_one_session(); + } catch ( CryptoException e ) { + fprintf( stderr, "Crypto exception: %s\r\n", + e.text.c_str() ); + fatal_assert( false ); + } + } + + return 0; +} diff --git a/src/tests/test_utils.cc b/src/tests/test_utils.cc index 8656532..3d16e71 100644 --- a/src/tests/test_utils.cc +++ b/src/tests/test_utils.cc @@ -32,3 +32,7 @@ void hexdump( const void *buf, size_t len, const char *name ) { void hexdump( const Crypto::AlignedBuffer &buf, const char *name ) { hexdump( buf.data(), buf.len(), name ); } + +void hexdump( const std::string &buf, const char *name ) { + hexdump( buf.data(), buf.size(), name ); +} diff --git a/src/tests/test_utils.h b/src/tests/test_utils.h index b32fcd5..9711d4a 100644 --- a/src/tests/test_utils.h +++ b/src/tests/test_utils.h @@ -19,11 +19,14 @@ #ifndef TEST_UTILS_HPP #define TEST_UTILS_HPP +#include <string> + #include "crypto.h" #define DUMP_NAME_FMT "%-10s " void hexdump( const void *buf, size_t len, const char *name ); void hexdump( const Crypto::AlignedBuffer &buf, const char *name ); +void hexdump( const std::string &buf, const char *name ); #endif |