Browse Source

Encryption oracle

master
Krzysztof Kwiatkowski 9 years ago
parent
commit
422624b93d
8 changed files with 191 additions and 114 deletions
  1. +1
    -1
      Makefile
  2. +13
    -13
      prj/Matasano.sublime-workspace
  3. +90
    -82
      sol/set2.c
  4. +13
    -4
      sol/set2.h
  5. +1
    -1
      src/common.h
  6. +70
    -9
      src/enc_modes.c
  7. +2
    -3
      src/main.cpp
  8. +1
    -1
      src/pkcs7.c

+ 1
- 1
Makefile View File

@@ -1,6 +1,6 @@
INC=. INC=.
LIBS=-lcrypto -lssl LIBS=-lcrypto -lssl
CFLAGS=-g
CFLAGS=-g -fno-inline


SRC_C_FILES := $(wildcard src/*.c) SRC_C_FILES := $(wildcard src/*.c)
SRC_CPP_FILES := $(wildcard src/*.cpp) SRC_CPP_FILES := $(wildcard src/*.cpp)


+ 13
- 13
prj/Matasano.sublime-workspace View File

@@ -539,7 +539,7 @@
"file": "/home/flowher/repos/MatasanoCrypto/sol/set2.c", "file": "/home/flowher/repos/MatasanoCrypto/sol/set2.c",
"settings": "settings":
{ {
"buffer_size": 14912,
"buffer_size": 15030,
"line_ending": "Unix" "line_ending": "Unix"
} }
}, },
@@ -547,7 +547,7 @@
"file": "/home/flowher/repos/MatasanoCrypto/src/enc_modes.c", "file": "/home/flowher/repos/MatasanoCrypto/src/enc_modes.c",
"settings": "settings":
{ {
"buffer_size": 6097,
"buffer_size": 6483,
"line_ending": "Unix" "line_ending": "Unix"
} }
}, },
@@ -1438,7 +1438,7 @@
"groups": "groups":
[ [
{ {
"selected": 2,
"selected": 3,
"sheets": "sheets":
[ [
{ {
@@ -1505,15 +1505,15 @@
"semi_transient": false, "semi_transient": false,
"settings": "settings":
{ {
"buffer_size": 14912,
"buffer_size": 15030,
"regions": "regions":
{ {
}, },
"selection": "selection":
[ [
[ [
1293,
1293
7854,
7854
] ]
], ],
"settings": "settings":
@@ -1523,10 +1523,10 @@
"translate_tabs_to_spaces": true "translate_tabs_to_spaces": true
}, },
"translation.x": 0.0, "translation.x": 0.0,
"translation.y": 0.0,
"translation.y": 2856.0,
"zoom_level": 1.0 "zoom_level": 1.0
}, },
"stack_index": 0,
"stack_index": 1,
"type": "text" "type": "text"
}, },
{ {
@@ -1535,15 +1535,15 @@
"semi_transient": false, "semi_transient": false,
"settings": "settings":
{ {
"buffer_size": 6097,
"buffer_size": 6483,
"regions": "regions":
{ {
}, },
"selection": "selection":
[ [
[ [
2901,
2901
6003,
6003
] ]
], ],
"settings": "settings":
@@ -1553,10 +1553,10 @@
"translate_tabs_to_spaces": true "translate_tabs_to_spaces": true
}, },
"translation.x": 0.0, "translation.x": 0.0,
"translation.y": 753.0,
"translation.y": 1821.0,
"zoom_level": 1.0 "zoom_level": 1.0
}, },
"stack_index": 1,
"stack_index": 0,
"type": "text" "type": "text"
}, },
{ {


+ 90
- 82
sol/set2.c View File

@@ -10,42 +10,38 @@
#include <openssl/evp.h> #include <openssl/evp.h>
#include <openssl/rand.h> #include <openssl/rand.h>
#include <assert.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) TCASE(ecb_encrypt_decrypt_single_block)
{ {
@@ -101,7 +97,7 @@ TCASE(pkcs7_test)
} }


size_t unpad_len = 0; 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(unpad_len == 5, (const uint8_t*) "Unpadded length wrong");
CHECK( 0==memcmp(text1, unpadded, unpad_len) ); CHECK( 0==memcmp(text1, unpadded, unpad_len) );
} }
@@ -189,11 +185,6 @@ TCASE(encode_decode_openssl)
uint8_t concatenated_blocks[16*3]; uint8_t concatenated_blocks[16*3];
uint8_t iv1[16] = {0}; uint8_t iv1[16] = {0};
uint8_t key[17] = "YELLOW SUBMARINE"; // 16+'\0' = 17 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, 2, 16);
memset(&concatenated_blocks[16], 5, 16); memset(&concatenated_blocks[16], 5, 16);
memset(&concatenated_blocks[32], 9, 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.iv_len = sizeof(iv1);
attribs_openssl_enc.operation = kEncrypt; attribs_openssl_enc.operation = kEncrypt;
CHECK(OpenSSL::Cbc(&attribs_openssl_enc, &keyObj)==Result_OK); 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 cbc_attribs;
CryptoAttribs_t::Init(&cbc_attribs); CryptoAttribs_t::Init(&cbc_attribs);
cbc_attribs.input = attribs_openssl_enc.output; cbc_attribs.input = attribs_openssl_enc.output;
@@ -242,6 +232,8 @@ TCASE(encode_decode_openssl)
attribs_enc.iv_len = sizeof(iv1); attribs_enc.iv_len = sizeof(iv1);
attribs_enc.operation = kEncrypt; attribs_enc.operation = kEncrypt;
CHECK( Result_OK == cbc_encrypt(&attribs_enc, &keyObj) ); 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 attribs_openssl_dec;
CryptoAttribs_t::Init(&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 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 iv1[16] = {0};
uint8_t key[16] = {0}; uint8_t key[16] = {0};
@@ -303,7 +294,7 @@ Result_t encryption_oracle(
CryptoAttribs_t attribs; CryptoAttribs_t attribs;
Key_t keyObj; Key_t keyObj;


// seed randomnes
// get seed for good randomnes
clock_gettime(CLOCK_MONOTONIC, &tv); clock_gettime(CLOCK_MONOTONIC, &tv);
srand((unsigned int)tv.tv_nsec); srand((unsigned int)tv.tv_nsec);


@@ -319,9 +310,9 @@ Result_t encryption_oracle(
// initialize encryption attribs // initialize encryption attribs
CryptoAttribs_t::Init(&attribs); CryptoAttribs_t::Init(&attribs);
attribs.operation = kEncrypt; 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.output = (uint8_t*)malloc(7*16);
attribs.padding = kPadding_PKCS7; attribs.padding = kPadding_PKCS7;


@@ -335,54 +326,71 @@ Result_t encryption_oracle(
RAND_bytes(random_bytes, append_byte_size); RAND_bytes(random_bytes, append_byte_size);
memcpy(attribs.input+tmplen, random_bytes, append_byte_size); memcpy(attribs.input+tmplen, random_bytes, append_byte_size);
tmplen+=append_byte_size; tmplen+=append_byte_size;
attribs.input_len = tmplen;


// key // key
Key_t::Init(&keyObj); Key_t::Init(&keyObj);
keyObj.key = key; keyObj.key = key;
keyObj.len = 16; 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); CryptoAttribs_t::Free(&attribs);
return Result_OK;
return ret;
} }


TCASE(encode_oracle_test) 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 TCASE_E




+ 13
- 4
sol/set2.h View File

@@ -1,6 +1,9 @@
#ifndef __set2_runner__ #ifndef __set2_runner__
#define __set2_runner__ #define __set2_runner__


#include "src/common.h"


void pkcs7_test(); void pkcs7_test();
void cbc_decrypt_test(); void cbc_decrypt_test();
void cbc_enc_dec_test(); void cbc_enc_dec_test();
@@ -9,17 +12,23 @@ void encode_decode_openssl();
void encode_oracle_test(); void encode_oracle_test();
void encrypt_padding_pkcs7(); void encrypt_padding_pkcs7();


struct OpenSSL
{
static Result_t Cbc(CryptoAttribs_t* i_attribs,
const Key_t* const i_key);
};

struct SET2 struct SET2
{ {
static void run() static void run()
{ {
encode_oracle_test();
ecb_encrypt_decrypt_single_block(); ecb_encrypt_decrypt_single_block();
pkcs7_test(); pkcs7_test();
encode_decode_openssl(); 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();
} }
}; };




+ 1
- 1
src/common.h View File

@@ -25,7 +25,7 @@ void __CheckFunc__(bool iFlag, const char* const file, int line, const uint8_t*
#define OP_CHECK(exp) \ #define OP_CHECK(exp) \
do { \ do { \
if(!exp) { \ 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; \ goto end; \
} \ } \
} \ } \


+ 70
- 9
src/enc_modes.c View File

@@ -16,7 +16,7 @@ static Result_t crypt( CryptoAttribs_t* attribs,
assert(attribs != NULL); assert(attribs != NULL);
assert(key->len == 16); assert(key->len == 16);
size_t max_size = ROUNDUP_16_BYTES(attribs->input_len) ; 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 output is NULL then allocate same size as input rounded to block size
if(attribs->output == NULL) if(attribs->output == NULL)
{ {
@@ -36,15 +36,21 @@ static Result_t crypt( CryptoAttribs_t* attribs,
if(ret > max_size ) if(ret > max_size )
{ {
printf("ERROR %d %lu \n", ret, attribs->output_len); printf("ERROR %d %lu \n", ret, attribs->output_len);
res = Result_Error;
goto end; goto end;
} }
OP_CHECK( EVP_CipherFinal_ex(&ctx, &attribs->output[ret], &ret) ); OP_CHECK( EVP_CipherFinal_ex(&ctx, &attribs->output[ret], &ret) );
attribs->output_len += 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: end:
return Result_Error;
EVP_CIPHER_CTX_cleanup(&ctx);
return res;
} }


Result_t cbc_decrypt( Result_t cbc_decrypt(
@@ -80,7 +86,7 @@ Result_t cbc_decrypt(
CryptoAttribs_t ecb_attribs; CryptoAttribs_t ecb_attribs;
CryptoAttribs_t::Init(&ecb_attribs); CryptoAttribs_t::Init(&ecb_attribs);
ecb_attribs.output = (uint8_t*) malloc(key->len); 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) for(int i=0; i<bc; ++i)
{ {
@@ -102,6 +108,7 @@ Result_t cbc_decrypt(
// 3. Change iv with block // 3. Change iv with block
iv = ecb_attribs.input; iv = ecb_attribs.input;
attribs->output_len += key->len; attribs->output_len += key->len;
ecb_attribs.output_len = 0;
} }
::free(ecb_attribs.output); ::free(ecb_attribs.output);


@@ -112,6 +119,7 @@ Result_t cbc_decrypt(
pkcs7_unpad(attribs->output, attribs->output_len, &unpadded, &length); pkcs7_unpad(attribs->output, attribs->output_len, &unpadded, &length);
memcpy(attribs->output, unpadded, length); memcpy(attribs->output, unpadded, length);
attribs->output_len = length; attribs->output_len = length;
::free(unpadded);
} }


return Result_OK; 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 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) if( attribs->output == NULL)
{ {
@@ -184,7 +193,7 @@ Result_t cbc_encrypt(
ret = Result_Error; ret = Result_Error;
break; break;
} }
assert(ecb_attribs.output != NULL);
// Encrypted block is my new IV // Encrypted block is my new IV
iv = ecb_attribs.output; iv = ecb_attribs.output;


@@ -192,7 +201,9 @@ Result_t cbc_encrypt(
memcpy((attribs->output)+(bs*i), memcpy((attribs->output)+(bs*i),
ecb_attribs.output, ecb_attribs.output,
ecb_attribs.output_len); ecb_attribs.output_len);
assert(ecb_attribs.output_len == 16);
attribs->output_len += ecb_attribs.output_len; attribs->output_len += ecb_attribs.output_len;
ecb_attribs.output_len = 0;
} }
CryptoAttribs_t::Free(&ecb_attribs); CryptoAttribs_t::Free(&ecb_attribs);
::free(local_input); ::free(local_input);
@@ -202,11 +213,61 @@ Result_t cbc_encrypt(
Result_t ecb_encrypt( CryptoAttribs_t* attribs, const Key_t* const key ) Result_t ecb_encrypt( CryptoAttribs_t* attribs, const Key_t* const key )
{ {
attribs->operation = kEncrypt; 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 ecb_decrypt( CryptoAttribs_t* attribs, const Key_t* const key )
{ {
Result_t res = Result_OK;
attribs->operation = kDecrypt; 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;
} }

+ 2
- 3
src/main.cpp View File

@@ -14,10 +14,9 @@ int main()
OpenSSL_add_all_algorithms(); OpenSSL_add_all_algorithms();




// UTILS::run();
SET1::run();
SET2::run(); SET2::run();

SET1::run();
UTILS::run();


/* Clean up */ /* Clean up */
EVP_cleanup(); EVP_cleanup();


+ 1
- 1
src/pkcs7.c View File

@@ -73,7 +73,7 @@ bool pkcs7_unpad( const uint8_t* i_padded_buf,
} }


*unpad_len = i_len - pad_val; *unpad_len = i_len - pad_val;
if(*o_unpad_buf == NULL)
if(NULL==*o_unpad_buf)
{ {
*o_unpad_buf = (uint8_t*) malloc(*unpad_len); *o_unpad_buf = (uint8_t*) malloc(*unpad_len);
} }


Loading…
Cancel
Save