Keep aligned buffers around, instead of allocing on each packet
Fixes #238 github issue. Also fixes armel "Bad alignment" problem.
This commit is contained in:
+29
-24
@@ -139,7 +139,10 @@ string Base64Key::printable_key( void ) const
|
|||||||
|
|
||||||
Session::Session( Base64Key s_key )
|
Session::Session( Base64Key s_key )
|
||||||
: key( s_key ), ctx_buf( ae_ctx_sizeof() ),
|
: key( s_key ), ctx_buf( ae_ctx_sizeof() ),
|
||||||
ctx( (ae_ctx *)ctx_buf.data() ), blocks_encrypted( 0 )
|
ctx( (ae_ctx *)ctx_buf.data() ), blocks_encrypted( 0 ),
|
||||||
|
plaintext_buffer( RECEIVE_MTU ),
|
||||||
|
ciphertext_buffer( RECEIVE_MTU ),
|
||||||
|
nonce_buffer( Nonce::NONCE_LEN )
|
||||||
{
|
{
|
||||||
if ( AE_SUCCESS != ae_init( ctx, key.data(), 16, 12, 16 ) ) {
|
if ( AE_SUCCESS != ae_init( ctx, key.data(), 16, 12, 16 ) ) {
|
||||||
throw CryptoException( "Could not initialize AES-OCB context." );
|
throw CryptoException( "Could not initialize AES-OCB context." );
|
||||||
@@ -194,20 +197,19 @@ string Session::encrypt( Message plaintext )
|
|||||||
const size_t pt_len = plaintext.text.size();
|
const size_t pt_len = plaintext.text.size();
|
||||||
const int ciphertext_len = pt_len + 16;
|
const int ciphertext_len = pt_len + 16;
|
||||||
|
|
||||||
AlignedBuffer ciphertext( ciphertext_len );
|
assert( (size_t)ciphertext_len <= ciphertext_buffer.len() );
|
||||||
AlignedBuffer pt( pt_len, plaintext.text.data() );
|
assert( pt_len <= plaintext_buffer.len() );
|
||||||
|
|
||||||
if ( (uint64_t( plaintext.nonce.data() ) & 0xf) != 0 ) {
|
memcpy( plaintext_buffer.data(), plaintext.text.data(), pt_len );
|
||||||
throw CryptoException( "Bad alignment." );
|
memcpy( nonce_buffer.data(), plaintext.nonce.data(), Nonce::NONCE_LEN );
|
||||||
}
|
|
||||||
|
|
||||||
if ( ciphertext_len != ae_encrypt( ctx, /* ctx */
|
if ( ciphertext_len != ae_encrypt( ctx, /* ctx */
|
||||||
plaintext.nonce.data(), /* nonce */
|
nonce_buffer.data(), /* nonce */
|
||||||
pt.data(), /* pt */
|
plaintext_buffer.data(), /* pt */
|
||||||
pt.len(), /* pt_len */
|
pt_len, /* pt_len */
|
||||||
NULL, /* ad */
|
NULL, /* ad */
|
||||||
0, /* ad_len */
|
0, /* ad_len */
|
||||||
ciphertext.data(), /* ct */
|
ciphertext_buffer.data(), /* ct */
|
||||||
NULL, /* tag */
|
NULL, /* tag */
|
||||||
AE_FINALIZE ) ) { /* final */
|
AE_FINALIZE ) ) { /* final */
|
||||||
throw CryptoException( "ae_encrypt() returned error." );
|
throw CryptoException( "ae_encrypt() returned error." );
|
||||||
@@ -235,7 +237,7 @@ string Session::encrypt( Message plaintext )
|
|||||||
throw CryptoException( "Encrypted 2^47 blocks.", true );
|
throw CryptoException( "Encrypted 2^47 blocks.", true );
|
||||||
}
|
}
|
||||||
|
|
||||||
string text( ciphertext.data(), ciphertext.len() );
|
string text( ciphertext_buffer.data(), ciphertext_len );
|
||||||
|
|
||||||
return plaintext.nonce.cc_str() + text;
|
return plaintext.nonce.cc_str() + text;
|
||||||
}
|
}
|
||||||
@@ -256,23 +258,26 @@ Message Session::decrypt( string ciphertext )
|
|||||||
exit( 1 );
|
exit( 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
Nonce __attribute__((__aligned__ (16))) nonce( str, 8 );
|
assert( (size_t)body_len <= ciphertext_buffer.len() );
|
||||||
AlignedBuffer body( body_len, str + 8 );
|
assert( (size_t)pt_len <= plaintext_buffer.len() );
|
||||||
AlignedBuffer plaintext( pt_len );
|
|
||||||
|
|
||||||
if ( pt_len != ae_decrypt( ctx, /* ctx */
|
Nonce nonce( str, 8 );
|
||||||
nonce.data(), /* nonce */
|
memcpy( ciphertext_buffer.data(), str + 8, body_len );
|
||||||
body.data(), /* ct */
|
memcpy( nonce_buffer.data(), nonce.data(), Nonce::NONCE_LEN );
|
||||||
body.len(), /* ct_len */
|
|
||||||
NULL, /* ad */
|
if ( pt_len != ae_decrypt( ctx, /* ctx */
|
||||||
0, /* ad_len */
|
nonce_buffer.data(), /* nonce */
|
||||||
plaintext.data(), /* pt */
|
ciphertext_buffer.data(), /* ct */
|
||||||
NULL, /* tag */
|
body_len, /* ct_len */
|
||||||
AE_FINALIZE ) ) { /* final */
|
NULL, /* ad */
|
||||||
|
0, /* ad_len */
|
||||||
|
plaintext_buffer.data(), /* pt */
|
||||||
|
NULL, /* tag */
|
||||||
|
AE_FINALIZE ) ) { /* final */
|
||||||
throw CryptoException( "Packet failed integrity check." );
|
throw CryptoException( "Packet failed integrity check." );
|
||||||
}
|
}
|
||||||
|
|
||||||
Message ret( nonce, string( plaintext.data(), plaintext.len() ) );
|
Message ret( nonce, string( plaintext_buffer.data(), pt_len ) );
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-1
@@ -73,8 +73,11 @@ namespace Crypto {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class Nonce {
|
class Nonce {
|
||||||
|
public:
|
||||||
|
static const int NONCE_LEN = 12;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char bytes[ 12 ] __attribute__((__aligned__ (16)));
|
char bytes[ NONCE_LEN ];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Nonce( uint64_t val );
|
Nonce( uint64_t val );
|
||||||
@@ -101,8 +104,14 @@ namespace Crypto {
|
|||||||
AlignedBuffer ctx_buf;
|
AlignedBuffer ctx_buf;
|
||||||
ae_ctx *ctx;
|
ae_ctx *ctx;
|
||||||
uint64_t blocks_encrypted;
|
uint64_t blocks_encrypted;
|
||||||
|
|
||||||
|
AlignedBuffer plaintext_buffer;
|
||||||
|
AlignedBuffer ciphertext_buffer;
|
||||||
|
AlignedBuffer nonce_buffer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
static const int RECEIVE_MTU = 2048;
|
||||||
|
|
||||||
Session( Base64Key s_key );
|
Session( Base64Key s_key );
|
||||||
~Session();
|
~Session();
|
||||||
|
|
||||||
|
|||||||
@@ -276,20 +276,20 @@ string Connection::recv( void )
|
|||||||
{
|
{
|
||||||
struct sockaddr_in packet_remote_addr;
|
struct sockaddr_in packet_remote_addr;
|
||||||
|
|
||||||
char buf[ RECEIVE_MTU ];
|
char buf[ Session::RECEIVE_MTU ];
|
||||||
|
|
||||||
socklen_t addrlen = sizeof( packet_remote_addr );
|
socklen_t addrlen = sizeof( packet_remote_addr );
|
||||||
|
|
||||||
ssize_t received_len = recvfrom( sock, buf, RECEIVE_MTU, 0, (sockaddr *)&packet_remote_addr, &addrlen );
|
ssize_t received_len = recvfrom( sock, buf, Session::RECEIVE_MTU, 0, (sockaddr *)&packet_remote_addr, &addrlen );
|
||||||
|
|
||||||
if ( received_len < 0 ) {
|
if ( received_len < 0 ) {
|
||||||
throw NetworkException( "recvfrom", errno );
|
throw NetworkException( "recvfrom", errno );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( received_len > RECEIVE_MTU ) {
|
if ( received_len > Session::RECEIVE_MTU ) {
|
||||||
char buffer[ 2048 ];
|
char buffer[ 2048 ];
|
||||||
snprintf( buffer, 2048, "Received oversize datagram (size %d) and limit is %d\n",
|
snprintf( buffer, 2048, "Received oversize datagram (size %d) and limit is %d\n",
|
||||||
static_cast<int>( received_len ), RECEIVE_MTU );
|
static_cast<int>( received_len ), Session::RECEIVE_MTU );
|
||||||
throw NetworkException( buffer, errno );
|
throw NetworkException( buffer, errno );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,6 @@ namespace Network {
|
|||||||
|
|
||||||
class Connection {
|
class Connection {
|
||||||
private:
|
private:
|
||||||
static const int RECEIVE_MTU = 2048;
|
|
||||||
static const int SEND_MTU = 1400;
|
static const int SEND_MTU = 1400;
|
||||||
static const uint64_t MIN_RTO = 50; /* ms */
|
static const uint64_t MIN_RTO = 50; /* ms */
|
||||||
static const uint64_t MAX_RTO = 1000; /* ms */
|
static const uint64_t MAX_RTO = 1000; /* ms */
|
||||||
|
|||||||
Reference in New Issue
Block a user