@@ -1,6 +1,6 @@ | |||
INC=. | |||
LIBS=-lcrypto -lssl | |||
CFLAGS=-g | |||
CFLAGS=-g -fno-inline | |||
SRC_C_FILES := $(wildcard src/*.c) | |||
SRC_CPP_FILES := $(wildcard src/*.cpp) | |||
@@ -539,7 +539,7 @@ | |||
"file": "/home/flowher/repos/MatasanoCrypto/sol/set2.c", | |||
"settings": | |||
{ | |||
"buffer_size": 14912, | |||
"buffer_size": 15030, | |||
"line_ending": "Unix" | |||
} | |||
}, | |||
@@ -547,7 +547,7 @@ | |||
"file": "/home/flowher/repos/MatasanoCrypto/src/enc_modes.c", | |||
"settings": | |||
{ | |||
"buffer_size": 6097, | |||
"buffer_size": 6483, | |||
"line_ending": "Unix" | |||
} | |||
}, | |||
@@ -1438,7 +1438,7 @@ | |||
"groups": | |||
[ | |||
{ | |||
"selected": 2, | |||
"selected": 3, | |||
"sheets": | |||
[ | |||
{ | |||
@@ -1505,15 +1505,15 @@ | |||
"semi_transient": false, | |||
"settings": | |||
{ | |||
"buffer_size": 14912, | |||
"buffer_size": 15030, | |||
"regions": | |||
{ | |||
}, | |||
"selection": | |||
[ | |||
[ | |||
1293, | |||
1293 | |||
7854, | |||
7854 | |||
] | |||
], | |||
"settings": | |||
@@ -1523,10 +1523,10 @@ | |||
"translate_tabs_to_spaces": true | |||
}, | |||
"translation.x": 0.0, | |||
"translation.y": 0.0, | |||
"translation.y": 2856.0, | |||
"zoom_level": 1.0 | |||
}, | |||
"stack_index": 0, | |||
"stack_index": 1, | |||
"type": "text" | |||
}, | |||
{ | |||
@@ -1535,15 +1535,15 @@ | |||
"semi_transient": false, | |||
"settings": | |||
{ | |||
"buffer_size": 6097, | |||
"buffer_size": 6483, | |||
"regions": | |||
{ | |||
}, | |||
"selection": | |||
[ | |||
[ | |||
2901, | |||
2901 | |||
6003, | |||
6003 | |||
] | |||
], | |||
"settings": | |||
@@ -1553,10 +1553,10 @@ | |||
"translate_tabs_to_spaces": true | |||
}, | |||
"translation.x": 0.0, | |||
"translation.y": 753.0, | |||
"translation.y": 1821.0, | |||
"zoom_level": 1.0 | |||
}, | |||
"stack_index": 1, | |||
"stack_index": 0, | |||
"type": "text" | |||
}, | |||
{ | |||
@@ -10,42 +10,38 @@ | |||
#include <openssl/evp.h> | |||
#include <openssl/rand.h> | |||
#include <assert.h> | |||
#include "set2.h" | |||
struct OpenSSL | |||
Result_t OpenSSL::Cbc(CryptoAttribs_t* i_attribs, | |||
const Key_t* const i_key) | |||
{ | |||
static Result_t Cbc(CryptoAttribs_t* i_attribs, | |||
const Key_t* const i_key) | |||
if(NULL==i_attribs->output) | |||
{ | |||
if(NULL==i_attribs->output) | |||
{ | |||
i_attribs->output = (uint8_t*) malloc(i_attribs->input_len) + 1; | |||
} | |||
int ret=0; | |||
EVP_CIPHER_CTX ctx; | |||
EVP_CIPHER_CTX_init(&ctx); | |||
OP_CHECK( | |||
EVP_CipherInit_ex(&ctx, EVP_aes_128_cbc(), NULL, i_key->key, i_attribs->iv, | |||
i_attribs->operation==kEncrypt ? 1 : 0)); | |||
EVP_CIPHER_CTX_set_padding(&ctx, 0); | |||
EVP_CIPHER_CTX_set_key_length(&ctx, i_key->len); | |||
OP_CHECK( | |||
EVP_CipherUpdate(&ctx, &i_attribs->output[ret], &ret, i_attribs->input, | |||
i_attribs->input_len)); | |||
i_attribs->output_len = ret; | |||
OP_CHECK( | |||
EVP_CipherFinal_ex(&ctx, &i_attribs->output[ret], &ret)); | |||
i_attribs->output_len += ret; | |||
EVP_CIPHER_CTX_cleanup(&ctx); | |||
return Result_OK; | |||
end: | |||
return Result_Error; | |||
i_attribs->output = (uint8_t*) malloc(i_attribs->input_len); | |||
} | |||
}; | |||
int ret=0; | |||
EVP_CIPHER_CTX ctx; | |||
EVP_CIPHER_CTX_init(&ctx); | |||
OP_CHECK( | |||
EVP_CipherInit_ex(&ctx, EVP_aes_128_cbc(), NULL, i_key->key, i_attribs->iv, | |||
i_attribs->operation==kEncrypt ? 1 : 0)); | |||
EVP_CIPHER_CTX_set_padding(&ctx, 0); | |||
EVP_CIPHER_CTX_set_key_length(&ctx, i_key->len); | |||
OP_CHECK( | |||
EVP_CipherUpdate(&ctx, i_attribs->output, &ret, i_attribs->input, | |||
i_attribs->input_len)); | |||
i_attribs->output_len = ret; | |||
OP_CHECK( | |||
EVP_CipherFinal_ex(&ctx, &i_attribs->output[ret], &ret)); | |||
i_attribs->output_len += ret; | |||
EVP_CIPHER_CTX_cleanup(&ctx); | |||
return Result_OK; | |||
end: | |||
return Result_Error; | |||
} | |||
TCASE(ecb_encrypt_decrypt_single_block) | |||
{ | |||
@@ -101,7 +97,7 @@ TCASE(pkcs7_test) | |||
} | |||
size_t unpad_len = 0; | |||
CHECK( true == pkcs7_unpad(&buff1[0], 32, &p_unpadded, &unpad_len) ); | |||
CHECK( pkcs7_unpad(&buff1[0], 32, &p_unpadded, &unpad_len) ); | |||
CHECK(unpad_len == 5, (const uint8_t*) "Unpadded length wrong"); | |||
CHECK( 0==memcmp(text1, unpadded, unpad_len) ); | |||
} | |||
@@ -189,11 +185,6 @@ TCASE(encode_decode_openssl) | |||
uint8_t concatenated_blocks[16*3]; | |||
uint8_t iv1[16] = {0}; | |||
uint8_t key[17] = "YELLOW SUBMARINE"; // 16+'\0' = 17 | |||
uint8_t* ciphertext = NULL; | |||
size_t ciphertext_len = 0; | |||
uint8_t* out = NULL; | |||
size_t out_len = 0; | |||
Result_t res = Result_Error; | |||
memset(concatenated_blocks, 2, 16); | |||
memset(&concatenated_blocks[16], 5, 16); | |||
memset(&concatenated_blocks[32], 9, 16); | |||
@@ -215,8 +206,7 @@ TCASE(encode_decode_openssl) | |||
attribs_openssl_enc.iv_len = sizeof(iv1); | |||
attribs_openssl_enc.operation = kEncrypt; | |||
CHECK(OpenSSL::Cbc(&attribs_openssl_enc, &keyObj)==Result_OK); | |||
CHECK(attribs_openssl_enc.output_len==48, (uint8_t*)"Ciphertext has wrong size"); | |||
CHECK(attribs_openssl_enc.output_len==48, (uint8_t*)"Ciphertext has wrong size");// | |||
CryptoAttribs_t cbc_attribs; | |||
CryptoAttribs_t::Init(&cbc_attribs); | |||
cbc_attribs.input = attribs_openssl_enc.output; | |||
@@ -242,6 +232,8 @@ TCASE(encode_decode_openssl) | |||
attribs_enc.iv_len = sizeof(iv1); | |||
attribs_enc.operation = kEncrypt; | |||
CHECK( Result_OK == cbc_encrypt(&attribs_enc, &keyObj) ); | |||
CHECK( 48 == attribs_enc.output_len ); | |||
CHECK( NULL != attribs_enc.output ); | |||
CryptoAttribs_t attribs_openssl_dec; | |||
CryptoAttribs_t::Init(&attribs_openssl_dec); | |||
@@ -286,12 +278,11 @@ uint8_t check_ciphertext(const uint8_t* ciphertext, uint32_t len ) | |||
return 0; // All checked blocks are the same -> ECB | |||
} | |||
Result_t encryption_oracle( | |||
const uint8_t* pt, | |||
uint32_t pt_len, | |||
uint8_t* ct, | |||
uint32_t* ct_len, | |||
uint8_t* mode) | |||
Result_t encryption_oracle( const uint8_t* pt, | |||
uint32_t pt_len, | |||
uint8_t* ct, | |||
uint32_t* ct_len, | |||
uint8_t* mode) | |||
{ | |||
uint8_t iv1[16] = {0}; | |||
uint8_t key[16] = {0}; | |||
@@ -303,7 +294,7 @@ Result_t encryption_oracle( | |||
CryptoAttribs_t attribs; | |||
Key_t keyObj; | |||
// seed randomnes | |||
// get seed for good randomnes | |||
clock_gettime(CLOCK_MONOTONIC, &tv); | |||
srand((unsigned int)tv.tv_nsec); | |||
@@ -319,9 +310,9 @@ Result_t encryption_oracle( | |||
// initialize encryption attribs | |||
CryptoAttribs_t::Init(&attribs); | |||
attribs.operation = kEncrypt; | |||
attribs.input_len = (5*16) + prepend_byte_size + append_byte_size; | |||
attribs.input = (uint8_t*)malloc(attribs.input_len); | |||
attribs.output_len = 7*16; | |||
attribs.input_len = 0; | |||
attribs.input = (uint8_t*)malloc(7*16); | |||
attribs.output_len = 0; | |||
attribs.output = (uint8_t*)malloc(7*16); | |||
attribs.padding = kPadding_PKCS7; | |||
@@ -335,54 +326,71 @@ Result_t encryption_oracle( | |||
RAND_bytes(random_bytes, append_byte_size); | |||
memcpy(attribs.input+tmplen, random_bytes, append_byte_size); | |||
tmplen+=append_byte_size; | |||
attribs.input_len = tmplen; | |||
// key | |||
Key_t::Init(&keyObj); | |||
keyObj.key = key; | |||
keyObj.len = 16; | |||
if(encryption_mode) | |||
{ | |||
attribs.iv = (uint8_t*)malloc(16); | |||
attribs.iv_len = 16; | |||
RAND_bytes(attribs.iv, 16); | |||
if( Result_OK!=cbc_encrypt(&attribs, &keyObj) ) | |||
return Result_Error; | |||
} | |||
else | |||
Result_t ret = Result_OK; | |||
do | |||
{ | |||
if( Result_OK!=ecb_encrypt(&attribs, &keyObj) ) | |||
return Result_Error; | |||
} | |||
if(encryption_mode) | |||
{ | |||
attribs.iv = (uint8_t*)malloc(16); | |||
attribs.iv_len = 16; | |||
RAND_bytes(attribs.iv, 16); | |||
if( Result_OK!=cbc_encrypt(&attribs, &keyObj) ) | |||
{ | |||
ret = Result_Error; | |||
break; | |||
} | |||
} | |||
else | |||
{ | |||
if( Result_OK!=ecb_encrypt(&attribs, &keyObj) ) | |||
{ | |||
ret = Result_Error; | |||
break; | |||
} | |||
} | |||
// Copy results | |||
memcpy(ct, attribs.output, attribs.output_len); | |||
*ct_len = attribs.output_len; | |||
*mode = encryption_mode; | |||
// Copy results | |||
memcpy(ct, attribs.output, attribs.output_len); | |||
*ct_len = attribs.output_len; | |||
*mode = encryption_mode; | |||
ret = Result_OK; | |||
} while(false); | |||
CryptoAttribs_t::Free(&attribs); | |||
return Result_OK; | |||
return ret; | |||
} | |||
TCASE(encode_oracle_test) | |||
{ | |||
uint8_t plaintext[5*16] = {0}; | |||
uint8_t ciphertext[7*16] = {0}; | |||
uint8_t mode = 0xFF; | |||
uint8_t guessed_mode = 0xFF; | |||
uint32_t ciphertext_len = 7*16; | |||
// set data in blocks so that | |||
// first block will be filled with 111... | |||
// second block with 2222... | |||
// ... | |||
memset(plaintext, 1, 5*16); | |||
Result_t ret = encryption_oracle(plaintext, 5*16, ciphertext, &ciphertext_len, &mode); | |||
CHECK(ret == Result_OK, (uint8_t*)"Error occured on encryption"); | |||
CHECK(mode != 0xFF); | |||
guessed_mode = check_ciphertext(ciphertext, ciphertext_len); | |||
CHECK(mode == guessed_mode); | |||
for(size_t i=0; i<100; ++i) | |||
{ | |||
printf("Round: %u\n",i); | |||
uint8_t plaintext[5*16] = {0}; | |||
uint8_t ciphertext[7*16] = {0}; | |||
uint8_t mode = 0xFF; | |||
uint8_t guessed_mode = 0xFF; | |||
uint32_t ciphertext_len = 7*16; | |||
// set data in blocks so that | |||
// first block will be filled with 111... | |||
// second block with 2222... | |||
// ... | |||
memset(plaintext, 1, 5*16); | |||
Result_t ret = encryption_oracle(plaintext, 5*16, ciphertext, &ciphertext_len, &mode); | |||
CHECK(ret == Result_OK, (uint8_t*)"Error occured on encryption"); | |||
CHECK(mode != 0xFF); | |||
guessed_mode = check_ciphertext(ciphertext, ciphertext_len); | |||
CHECK(mode == guessed_mode); | |||
} | |||
} | |||
TCASE_E | |||
@@ -1,6 +1,9 @@ | |||
#ifndef __set2_runner__ | |||
#define __set2_runner__ | |||
#include "src/common.h" | |||
void pkcs7_test(); | |||
void cbc_decrypt_test(); | |||
void cbc_enc_dec_test(); | |||
@@ -9,17 +12,23 @@ void encode_decode_openssl(); | |||
void encode_oracle_test(); | |||
void encrypt_padding_pkcs7(); | |||
struct OpenSSL | |||
{ | |||
static Result_t Cbc(CryptoAttribs_t* i_attribs, | |||
const Key_t* const i_key); | |||
}; | |||
struct SET2 | |||
{ | |||
static void run() | |||
{ | |||
encode_oracle_test(); | |||
ecb_encrypt_decrypt_single_block(); | |||
pkcs7_test(); | |||
encode_decode_openssl(); | |||
//cbc_decrypt_test(); | |||
//cbc_enc_dec_test(); | |||
//encode_oracle_test(); | |||
//encrypt_padding_pkcs7(); | |||
cbc_decrypt_test(); | |||
cbc_enc_dec_test(); | |||
encrypt_padding_pkcs7(); | |||
} | |||
}; | |||
@@ -25,7 +25,7 @@ void __CheckFunc__(bool iFlag, const char* const file, int line, const uint8_t* | |||
#define OP_CHECK(exp) \ | |||
do { \ | |||
if(!exp) { \ | |||
printf("Error with expression %s %d\n", #exp, exp); \ | |||
printf("%s:%d Error with expression %s %d\n", __FILE__, __LINE__, #exp, exp); \ | |||
goto end; \ | |||
} \ | |||
} \ | |||
@@ -16,7 +16,7 @@ static Result_t crypt( CryptoAttribs_t* attribs, | |||
assert(attribs != NULL); | |||
assert(key->len == 16); | |||
size_t max_size = ROUNDUP_16_BYTES(attribs->input_len) ; | |||
Result_t res = Result_OK; | |||
// if output is NULL then allocate same size as input rounded to block size | |||
if(attribs->output == NULL) | |||
{ | |||
@@ -36,15 +36,21 @@ static Result_t crypt( CryptoAttribs_t* attribs, | |||
if(ret > max_size ) | |||
{ | |||
printf("ERROR %d %lu \n", ret, attribs->output_len); | |||
res = Result_Error; | |||
goto end; | |||
} | |||
OP_CHECK( EVP_CipherFinal_ex(&ctx, &attribs->output[ret], &ret) ); | |||
attribs->output_len += ret; | |||
EVP_CIPHER_CTX_cleanup(&ctx); | |||
return Result_OK; | |||
if(attribs->output_len > max_size ) | |||
{ | |||
printf("ERROR %d %lu \n", ret, attribs->output_len); | |||
res = Result_Error; | |||
goto end; | |||
} | |||
end: | |||
return Result_Error; | |||
EVP_CIPHER_CTX_cleanup(&ctx); | |||
return res; | |||
} | |||
Result_t cbc_decrypt( | |||
@@ -80,7 +86,7 @@ Result_t cbc_decrypt( | |||
CryptoAttribs_t ecb_attribs; | |||
CryptoAttribs_t::Init(&ecb_attribs); | |||
ecb_attribs.output = (uint8_t*) malloc(key->len); | |||
ecb_attribs.output_len = key->len; | |||
ecb_attribs.output_len = 0; | |||
for(int i=0; i<bc; ++i) | |||
{ | |||
@@ -102,6 +108,7 @@ Result_t cbc_decrypt( | |||
// 3. Change iv with block | |||
iv = ecb_attribs.input; | |||
attribs->output_len += key->len; | |||
ecb_attribs.output_len = 0; | |||
} | |||
::free(ecb_attribs.output); | |||
@@ -112,6 +119,7 @@ Result_t cbc_decrypt( | |||
pkcs7_unpad(attribs->output, attribs->output_len, &unpadded, &length); | |||
memcpy(attribs->output, unpadded, length); | |||
attribs->output_len = length; | |||
::free(unpadded); | |||
} | |||
return Result_OK; | |||
@@ -148,7 +156,8 @@ Result_t cbc_encrypt( | |||
} | |||
const size_t bc = (size_t)( local_input_len / key->len ); | |||
const size_t bs = key->len; | |||
const size_t bs = attribs->iv_len; | |||
assert(bs == 16); | |||
if( attribs->output == NULL) | |||
{ | |||
@@ -184,7 +193,7 @@ Result_t cbc_encrypt( | |||
ret = Result_Error; | |||
break; | |||
} | |||
assert(ecb_attribs.output != NULL); | |||
// Encrypted block is my new IV | |||
iv = ecb_attribs.output; | |||
@@ -192,7 +201,9 @@ Result_t cbc_encrypt( | |||
memcpy((attribs->output)+(bs*i), | |||
ecb_attribs.output, | |||
ecb_attribs.output_len); | |||
assert(ecb_attribs.output_len == 16); | |||
attribs->output_len += ecb_attribs.output_len; | |||
ecb_attribs.output_len = 0; | |||
} | |||
CryptoAttribs_t::Free(&ecb_attribs); | |||
::free(local_input); | |||
@@ -202,11 +213,61 @@ Result_t cbc_encrypt( | |||
Result_t ecb_encrypt( CryptoAttribs_t* attribs, const Key_t* const key ) | |||
{ | |||
attribs->operation = kEncrypt; | |||
return crypt(attribs, key); | |||
Result_t res = Result_OK; | |||
if( kPadding_PKCS7==attribs->padding ) | |||
{ | |||
CryptoAttribs_t padded_attribs; | |||
CryptoAttribs_t::Init(&padded_attribs); | |||
do | |||
{ | |||
// TODO: it should round up to key length not necsairlly 16 | |||
padded_attribs.input_len = ROUNDUP_16_BYTES(attribs->input_len); | |||
// one block extra if size aligned | |||
if(padded_attribs.input_len == attribs->input_len) | |||
padded_attribs.input_len += 16; | |||
if( !pkcs7_pad(attribs->input, attribs->input_len, &padded_attribs.input, padded_attribs.input_len) ) | |||
{ | |||
res = Result_Error; | |||
break; | |||
} | |||
padded_attribs.padding = kPadding_None; | |||
res = crypt(&padded_attribs, key); | |||
if(NULL==attribs->output) | |||
{ | |||
attribs->output = (uint8_t*)malloc(padded_attribs.output_len); | |||
} | |||
memcpy(attribs->output, padded_attribs.output, padded_attribs.output_len); | |||
attribs->output_len = padded_attribs.output_len; | |||
} while(false); | |||
CryptoAttribs_t::Free(&padded_attribs); | |||
} | |||
else | |||
{ | |||
res = crypt(attribs, key); | |||
} | |||
return res; | |||
} | |||
Result_t ecb_decrypt( CryptoAttribs_t* attribs, const Key_t* const key ) | |||
{ | |||
Result_t res = Result_OK; | |||
attribs->operation = kDecrypt; | |||
return crypt(attribs, key); | |||
res = crypt(attribs, key); | |||
if( kPadding_PKCS7==attribs->padding ) | |||
{ | |||
size_t output_len=0; | |||
uint8_t* output=NULL; | |||
if(!pkcs7_unpad(attribs->output, attribs->output_len, &output, &output_len)) | |||
{ | |||
return Result_Error; | |||
} | |||
memcpy(attribs->output, output, output_len); | |||
attribs->output_len=output_len; | |||
} | |||
return res; | |||
} |
@@ -14,10 +14,9 @@ int main() | |||
OpenSSL_add_all_algorithms(); | |||
// UTILS::run(); | |||
SET1::run(); | |||
SET2::run(); | |||
SET1::run(); | |||
UTILS::run(); | |||
/* Clean up */ | |||
EVP_cleanup(); | |||
@@ -73,7 +73,7 @@ bool pkcs7_unpad( const uint8_t* i_padded_buf, | |||
} | |||
*unpad_len = i_len - pad_val; | |||
if(*o_unpad_buf == NULL) | |||
if(NULL==*o_unpad_buf) | |||
{ | |||
*o_unpad_buf = (uint8_t*) malloc(*unpad_len); | |||
} | |||