Преглед на файлове

Encryption oracle

master
Krzysztof Kwiatkowski преди 9 години
родител
ревизия
422624b93d
променени са 8 файла, в които са добавени 191 реда и са изтрити 114 реда
  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 Целия файл

@@ -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)


+ 13
- 13
prj/Matasano.sublime-workspace Целия файл

@@ -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"
},
{


+ 90
- 82
sol/set2.c Целия файл

@@ -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



+ 13
- 4
sol/set2.h Целия файл

@@ -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();
}
};



+ 1
- 1
src/common.h Целия файл

@@ -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; \
} \
} \


+ 70
- 9
src/enc_modes.c Целия файл

@@ -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;
}

+ 2
- 3
src/main.cpp Целия файл

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


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

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

/* Clean up */
EVP_cleanup();


+ 1
- 1
src/pkcs7.c Целия файл

@@ -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);
}


Зареждане…
Отказ
Запис