First pass at switching to AES256 GCM authenticated encryption

This commit is contained in:
Nick Thomas
2013-08-08 18:15:58 +01:00
parent 15fe01c368
commit f1f623f18e

View File

@@ -550,7 +550,7 @@ ssize_t rlocs_encrypt( struct rlocs *reg, struct rloc *x, struct rloc *y, unsign
// FIXME: I don't know that this is good. It could be terrible.
// We use a PRNG to generate an IV per message, and put it at the start of
// the encrypted blob. Since we're using aes256 (hardcoded), IV is 128 bits
// the encrypted blob. Since we're using aes256 (hardcoded), IV is 128 bits.
if ( dest_len < 48 ) {
warn( "dest_len must be at least 48 bytes, maybe more");
goto fail;
@@ -558,20 +558,33 @@ ssize_t rlocs_encrypt( struct rlocs *reg, struct rloc *x, struct rloc *y, unsign
unsigned char *iv = dest;
unsigned char *secret = (unsigned char *)&entry->secret[0];
size_t written = 16;
int outl = dest_len - written;
RAND_pseudo_bytes( iv, 16 );
if ( !EVP_EncryptInit_ex( &entry->ctx, EVP_aes_256_cbc(), NULL, secret, iv ) ) {
warn( "EVP_EncryptInit_ex() failed" );
if ( !EVP_EncryptInit_ex( &entry->ctx, EVP_aes_256_gcm(), NULL, NULL, NULL ) ) {
warn( "EVP_EncryptInit_ex() (1) failed" );
goto fail;
}
if ( !EVP_CIPHER_CTX_ctrl( &entry->ctx, EVP_CTRL_GCM_SET_IVLEN, 16, NULL)) {
warn ("Setting IV len to 16 failed" );
goto fail;
}
if ( !EVP_EncryptInit_ex( &entry->ctx, NULL, NULL, secret, iv ) ) {
warn( "EVP_EncryptInit_ex() (2) failed" );
goto fail;
}
if ( !EVP_EncryptUpdate( &entry->ctx, dest + written, &outl, data, data_len ) ) {
warn( "EVP_EncryptUpdate() failed" );
goto fail;
}
// TODO: Add the encapsulating IP header as AAD data?
written += outl;
outl = dest_len - written;
@@ -580,8 +593,16 @@ ssize_t rlocs_encrypt( struct rlocs *reg, struct rloc *x, struct rloc *y, unsign
warn( "EVP_EncryptFinal_ex() failed" );
goto fail;
}
written += outl;
/* Get the tag */
if( !EVP_CIPHER_CTX_ctrl( &entry->ctx, EVP_CTRL_GCM_GET_TAG, 16, dest + written ) ) {
warn( "Getting GCM tag for our encrypted data failed" );
goto fail;
}
return written + outl;
return written + 16;
fail:
show_ssl_errors();
@@ -599,15 +620,31 @@ ssize_t rlocs_decrypt( struct rlocs *reg, struct rloc *x, struct rloc *y, unsign
unsigned char *iv = data;
unsigned char *secret = (unsigned char *)&entry->secret[0];
size_t written = 0;
int outl = dest_len;
if ( !EVP_DecryptInit_ex( &entry->ctx, EVP_aes_256_cbc(), NULL, secret, iv ) ) {
warn( "EVP_DecrypttInit_ex() failed" );
if ( data_len < 32 ) {
warn( "data_len not large enough to contain tag and IV" );
goto fail;
}
if ( !EVP_DecryptUpdate( &entry->ctx, dest, &outl, data + 16, data_len - 16 ) ) {
if ( !EVP_DecryptInit_ex( &entry->ctx, EVP_aes_256_gcm(), NULL, NULL, NULL ) ) {
warn( "EVP_DecryptInit_ex() (1) failed" );
goto fail;
}
if ( !EVP_CIPHER_CTX_ctrl(&entry->ctx, EVP_CTRL_GCM_SET_IVLEN, 16, NULL)) {
warn ("Setting IV len to 16 failed" );
goto fail;
}
if ( !EVP_DecryptInit_ex( &entry->ctx, NULL, NULL, secret, iv ) ) {
warn( "EVP_DecryptInit_ex() (2) failed" );
goto fail;
}
if ( !EVP_DecryptUpdate( &entry->ctx, dest, &outl, data + 16, data_len - 32 ) ) {
warn( "EVP_DecryptUpdate() failed" );
goto fail;
}
@@ -615,8 +652,13 @@ ssize_t rlocs_decrypt( struct rlocs *reg, struct rloc *x, struct rloc *y, unsign
written += outl;
outl = dest_len - written;
if( !EVP_CIPHER_CTX_ctrl(&entry->ctx, EVP_CTRL_GCM_SET_TAG, 16, data + (data_len - 16 ) ) ) {
warn( "Failed to provide GCM tag to decrypt routine" );
goto fail;
}
if ( !EVP_DecryptFinal_ex( &entry->ctx, dest + written, &outl ) ) {
warn( "EVP_DecryptFinal_ex() failed" );
warn( "EVP_DecryptFinal_ex() failed - bad tag?" );
goto fail;
}