Test the Mosh crypto layer

This commit is contained in:
Keegan McAllister
2012-03-28 04:53:11 -04:00
committed by Keith Winstein
parent d1c4b0a5d7
commit c354a69ee6
7 changed files with 159 additions and 2 deletions
+1
View File
@@ -1 +1,2 @@
/ocb-aes
/encrypt-decrypt
+5 -1
View File
@@ -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
+139
View File
@@ -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;
}
+4
View File
@@ -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 );
}
+3
View File
@@ -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