aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Keegan McAllister <mcallister.keegan@gmail.com>2012-03-28 04:53:11 -0400
committerGravatar Keith Winstein <keithw@mit.edu>2012-04-06 23:43:42 -0400
commitc354a69ee6a9c991d07914c0290433ec3bc05607 (patch)
treeb14b44794e66acdaa5b290a7ab7babc476074a51 /src
parentd1c4b0a5d7c8b12e62be5917369278b46fe92e3c (diff)
Test the Mosh crypto layer
Diffstat (limited to 'src')
-rw-r--r--src/crypto/prng.h6
-rw-r--r--src/tests/.gitignore1
-rw-r--r--src/tests/Makefile.am6
-rw-r--r--src/tests/encrypt-decrypt.cc139
-rw-r--r--src/tests/test_utils.cc4
-rw-r--r--src/tests/test_utils.h3
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