From 8345e52541cbe80d976ceae3f936d3f577f46dc9 Mon Sep 17 00:00:00 2001 From: Krzysztof Kwiatkowski Date: Sun, 4 Oct 2015 01:20:40 +0200 Subject: [PATCH] PKCS7 padding improved --- prj/Matasano.sublime-workspace | 405 ++++++++++++++++----------------- sol/set2.c | 182 ++++++++++++++- sol/set2.h | 4 + src/common.c | 1 + src/common.h | 6 + src/enc_modes.c | 36 ++- src/pkcs7.c | 80 ++++++- src/pkcs7.h | 17 +- 8 files changed, 504 insertions(+), 227 deletions(-) diff --git a/prj/Matasano.sublime-workspace b/prj/Matasano.sublime-workspace index bbdca5f..3eda336 100644 --- a/prj/Matasano.sublime-workspace +++ b/prj/Matasano.sublime-workspace @@ -4,29 +4,77 @@ "selected_items": [ [ - "test", - "test_text" + "i_buf", + "i_padded_buf" ], [ - "inpu", - "input" + "Re", + "Result_OK" ], [ - "TCASE", - "TCASE_E" + "Resu", + "Result_t" ], [ - "out", - "output_len" + "padded", + "padded_input_len" ], [ - "Resu", - "Result_OK" + "inpu", + "input_len" + ], + [ + "unp", + "unpad_len" + ], + [ + "padd", + "padding_value" ], [ "inp", "input_len" ], + [ + "Res", + "Result_Error" + ], + [ + "random", + "random_bytes" + ], + [ + "uint", + "uint8_t" + ], + [ + "uin", + "uint8_t" + ], + [ + "u", + "uint32_t" + ], + [ + "at", + "attribs_openssl_enc" + ], + [ + "out", + "out_len" + ], + [ + "attri", + "attribs" + ], + [ + "test", + "test_text" + ], + [ + "TCASE", + "TCASE_E" + ], [ "ou", "output_len" @@ -99,10 +147,6 @@ "co", "concatenated_blocks" ], - [ - "uint", - "uint8_t" - ], [ "o_", "o_buff_ptr" @@ -470,50 +514,6 @@ [ "aMappingBy", "aMappingByNumber" - ], - [ - "ConnectionHan", - "ConnectionHandlerInterfacePtr" - ], - [ - "CCNa", - "CCNBackRoutingKeyStorage::Value::Value" - ], - [ - "ConvI", - "CMG_ConvIndex" - ], - [ - "AMD_UIN", - "AMD_UInt16" - ], - [ - "AMD_UI", - "AMD_UInt16" - ], - [ - "AMD_U", - "AMD_UInt16" - ], - [ - "Excep", - "Exception" - ], - [ - "getOrigin", - "getOriginConvID" - ], - [ - "SEI_TRACE_", - "SEI_TRACE_WARNING" - ], - [ - "isCon", - "isCloseOnReply" - ], - [ - "TrafficEve", - "TrafficEventHandlerBase" ] ] }, @@ -536,74 +536,75 @@ } }, { - "file": "/home/flowher/repos/MatasanoCrypto/src/main.cpp", + "file": "/home/flowher/repos/MatasanoCrypto/src/enc_modes.c", "settings": { - "buffer_size": 378, + "buffer_size": 5568, "line_ending": "Unix" } }, { - "file": "/home/flowher/repos/MatasanoCrypto/sol/set2.c", + "file": "/home/flowher/repos/MatasanoCrypto/src/pkcs7.h", "settings": { - "buffer_size": 7514, + "buffer_size": 406, "line_ending": "Unix" } }, { - "file": "/home/flowher/repos/MatasanoCrypto/src/enc_modes.c", + "file": "/home/flowher/repos/MatasanoCrypto/sol/set2.c", "settings": { - "buffer_size": 6138, + "buffer_size": 13542, "line_ending": "Unix" } }, { - "contents": "\n\n\n /// TO NIE DZIALA\n\n\n\n printf(\"DUPA\");\n CryptoAttribs_t attr;\n CryptoAttribs_t::Init(&attr);\n attr.input = (uint8_t*)malloc(16);\n memcpy(attr.input, out, 16);\n assert( ecb_decrypt(&attr, key) == Result_OK );\n printf(\"%s \\n %d\\n\", attr.output, attr.output_len);\n printf(\"DUPA\");\n\n\n\n\n\n", + "file": "/home/flowher/repos/MatasanoCrypto/src/pkcs7.c", "settings": { - "buffer_size": 313, + "buffer_size": 907, "line_ending": "Unix" } }, { - "file": "/home/flowher/repos/MatasanoCrypto/sol/set2.h", + "file": "/home/flowher/repos/MatasanoCrypto/src/common.h", "settings": { - "buffer_size": 427, + "buffer_size": 2851, "line_ending": "Unix" } }, { - "file": "/home/flowher/repos/MatasanoCrypto/src/common.c", + "file": "/home/flowher/konto/list.txt", "settings": { - "buffer_size": 2941, - "line_ending": "Unix" + "buffer_size": 99, + "line_ending": "Unix", + "name": "OK 1. BPCE" } }, { - "file": "/home/flowher/repos/MatasanoCrypto/sol/set1.cpp", + "file": "/home/flowher/repos/MatasanoCrypto/src/enc_modes.h", "settings": { - "buffer_size": 12515, + "buffer_size": 459, "line_ending": "Unix" } }, { - "file": "/home/flowher/repos/MatasanoCrypto/src/common.h", + "file": "/home/flowher/repos/MatasanoCrypto/src/common.c", "settings": { - "buffer_size": 2279, + "buffer_size": 2975, "line_ending": "Unix" } }, { - "file": "/home/flowher/test.cpp", + "file": "/home/flowher/repos/MatasanoCrypto/sol/set1.cpp", "settings": { - "buffer_size": 282, + "buffer_size": 12514, "line_ending": "Unix" } }, @@ -645,7 +646,7 @@ [ [ "comme", - "Toggle Comment" + "Snippet: comment-simple" ], [ "comm", @@ -1051,18 +1052,24 @@ ], "file_history": [ + "/home/flowher/repos/MatasanoCrypto/test.c", + "/home/flowher/repos/MatasanoCrypto/src/pkcs7.h", + "/home/flowher/repos/MatasanoCrypto/sol/set2.h", + "/home/flowher/repos/OpenCrypto/util/incore", + "/home/flowher/test.cpp", + "/home/flowher/Work/goldfish_env/usr/bin/mkbootimg", + "/home/flowher/repos/MatasanoCrypto/src/common.h", + "/home/flowher/repos/MatasanoCrypto/src/main.cpp", + "/home/flowher/repos/MatasanoCrypto/sol/set2.c", + "/home/flowher/repos/MatasanoCrypto/src/enc_modes.c", "/home/flowher/repos/MatasanoCrypto/out", "/home/flowher/repos/MatasanoCrypto/Makefile", - "/home/flowher/repos/MatasanoCrypto/src/enc_modes.c", "/home/flowher/repos/OpenCrypto/crypto/evp/evp_enc.c", "/home/flowher/repos/OpenCrypto/crypto/err/err.c", "/home/flowher/repos/MatasanoCrypto/src/base64.cpp", "/home/flowher/repos/MatasanoCrypto/sol/set1.cpp", "/home/flowher/repos/MatasanoCrypto/src/xor.c", - "/home/flowher/repos/MatasanoCrypto/sol/set2.h", - "/home/flowher/repos/MatasanoCrypto/src/common.h", "/home/flowher/repos/MatasanoCrypto/src/common.c", - "/home/flowher/repos/MatasanoCrypto/sol/set2.c", "/home/flowher/ripi_pass", "/home/flowher/repos/notes/french/words/words.md", "/home/flowher/Work/zshrc", @@ -1076,11 +1083,9 @@ "/home/flowher/repos/MatasanoCrypto/suppressions.valgrind", "/home/flowher/repos/MatasanoCrypto/tst/utils.h", "/home/flowher/repos/MatasanoCrypto/src/ecb.c", - "/home/flowher/test.cpp", "/home/flowher/test.c", "/home/flowher/.config/sublime-text-3/Packages/User/Preferences.sublime-settings", "/home/flowher/repos/MatasanoCrypto/prj/Matasano.sublime-project", - "/home/flowher/repos/MatasanoCrypto/src/main.cpp", "/home/flowher/repos/notes/french/words/words", "/home/flowher/repos/MatasanoCrypto/sol/main.cpp", "/home/flowher/repos/notes/crypto/eliptic.md", @@ -1174,11 +1179,7 @@ "/home/kkwiatkowski/amadeus_workdir/repos/03_Components/acf_ssl/br_12-0-1/include/acf/ssl/SSLOptions.h", "/home/kkwiatkowski/amadeus_workdir/repos/03_Components/acf_ssl/br_12-0-1/.bms/bmsrc", "/home/kkwiatkowski/valgrind.suppr", - "/home/kkwiatkowski/storage/91_Repositories/openssl101j/ssl/ssl.h", - "/home/kkwiatkowski/storage/91_Repositories/openssl101j/crypto/s390xcpuid.S", - "/home/kkwiatkowski/storage/91_Repositories/srp_client_server_implementation_with_openssl/server.cpp", - "/home/kkwiatkowski/storage/91_Repositories/openssl101j/include/openssl/symhacks.h", - "/home/kkwiatkowski/storage/91_Repositories/openssl101j/crypto/symhacks.h" + "/home/kkwiatkowski/storage/91_Repositories/openssl101j/ssl/ssl.h" ], "find": { @@ -1253,6 +1254,32 @@ "case_sensitive": false, "find_history": [ + "aes", + "pkcs7_pad", + "pkcs7", + "mode", + "ciphetext", + "Result_Ok", + "Result_OK", + "Result_Ok", + "bs", + "crypt", + "crypt(", + "OZAP", + "cbc_enc_dec_test", + "attribs_enc", + " (", + "attribs_enc", + "cbc_attribs", + "attribs_openssl_dec", + "attribs_openssl_enc", + "attribs", + "attribs.", + "attribs", + "key", + "ctx", + "_ecb_H_", + "ecb_encrypt", "==29586==", "TCASE_E", "getline", @@ -1354,33 +1381,7 @@ "ENGINE_CMD_DEFN", "plaintext", "xor_repeatedly", - " k", - " ", - " ", - "base64_to_hex", - "void", - "VOLUME_GROUPE", - "count", - " ", - " ", - "i_len", - "set2_pkcs7_test", - "__set1_runner__", - "o_buf", - "hex_str4", - "img", - ".jpg", - "amongbits", - "printable_ascii", - "char_in_array", - "set2_ch", - "read_file_to_buffer", - "hex_to_base64_tex", - "hex_to_base64_test", - "hex_to_base64_text", - "run(", - "read_file", - "read_file_to_buffer" + " k" ], "highlight": true, "in_selection": false, @@ -1446,7 +1447,7 @@ "groups": [ { - "selected": 8, + "selected": 4, "sheets": [ { @@ -1476,7 +1477,7 @@ "translation.y": 0.0, "zoom_level": 1.0 }, - "stack_index": 9, + "stack_index": 5, "type": "text" }, { @@ -1504,98 +1505,82 @@ "translation.y": 0.0, "zoom_level": 1.0 }, - "stack_index": 12, + "stack_index": 10, "type": "text" }, { "buffer": 2, - "file": "/home/flowher/repos/MatasanoCrypto/src/main.cpp", + "file": "/home/flowher/repos/MatasanoCrypto/src/enc_modes.c", "semi_transient": false, "settings": { - "buffer_size": 378, + "buffer_size": 5568, "regions": { }, "selection": [ [ - 244, - 244 + 3505, + 3505 ] ], "settings": { - "syntax": "Packages/C++/C++.tmLanguage" + "syntax": "Packages/C Improved/C Improved.tmLanguage", + "tab_size": 4, + "translate_tabs_to_spaces": true }, "translation.x": 0.0, - "translation.y": 0.0, + "translation.y": 1716.0, "zoom_level": 1.0 }, - "stack_index": 4, + "stack_index": 3, "type": "text" }, { "buffer": 3, - "file": "/home/flowher/repos/MatasanoCrypto/sol/set2.c", + "file": "/home/flowher/repos/MatasanoCrypto/src/pkcs7.h", "semi_transient": false, "settings": { - "buffer_size": 7514, + "buffer_size": 406, "regions": { }, "selection": [ [ - 1120, - 1120 - ], - [ - 1762, - 1762 - ], - [ - 3085, - 3085 - ], - [ - 4035, - 4035 - ], - [ - 5686, - 5686 + 61, + 81 ] ], "settings": { - "syntax": "Packages/C Improved/C Improved.tmLanguage", - "tab_size": 4, - "translate_tabs_to_spaces": true + "syntax": "Packages/C Improved/C Improved.tmLanguage" }, "translation.x": 0.0, - "translation.y": 1423.0, + "translation.y": 0.0, "zoom_level": 1.0 }, - "stack_index": 1, + "stack_index": 2, "type": "text" }, { "buffer": 4, - "file": "/home/flowher/repos/MatasanoCrypto/src/enc_modes.c", + "file": "/home/flowher/repos/MatasanoCrypto/sol/set2.c", "semi_transient": false, "settings": { - "buffer_size": 6138, + "buffer_size": 13542, "regions": { }, "selection": [ [ - 5822, - 5822 + 13408, + 13408 ] ], "settings": @@ -1605,26 +1590,27 @@ "translate_tabs_to_spaces": true }, "translation.x": 0.0, - "translation.y": 2579.0, + "translation.y": 6561.0, "zoom_level": 1.0 }, - "stack_index": 5, + "stack_index": 0, "type": "text" }, { "buffer": 5, + "file": "/home/flowher/repos/MatasanoCrypto/src/pkcs7.c", "semi_transient": false, "settings": { - "buffer_size": 313, + "buffer_size": 907, "regions": { }, "selection": [ [ - 313, - 313 + 292, + 292 ] ], "settings": @@ -1635,148 +1621,151 @@ "translation.y": 0.0, "zoom_level": 1.0 }, - "stack_index": 7, + "stack_index": 1, "type": "text" }, { "buffer": 6, - "file": "/home/flowher/repos/MatasanoCrypto/sol/set2.h", + "file": "/home/flowher/repos/MatasanoCrypto/src/common.h", "semi_transient": false, "settings": { - "buffer_size": 427, + "buffer_size": 2851, "regions": { }, "selection": [ [ - 352, - 352 + 2418, + 2418 ] ], "settings": { - "syntax": "Packages/C Improved/C Improved.tmLanguage" + "syntax": "Packages/C Improved/C Improved.tmLanguage", + "tab_size": 2, + "translate_tabs_to_spaces": true }, "translation.x": 0.0, - "translation.y": 0.0, + "translation.y": 685.0, "zoom_level": 1.0 }, - "stack_index": 6, + "stack_index": 7, "type": "text" }, { "buffer": 7, - "file": "/home/flowher/repos/MatasanoCrypto/src/common.c", + "file": "/home/flowher/konto/list.txt", "semi_transient": false, "settings": { - "buffer_size": 2941, + "buffer_size": 99, "regions": { }, "selection": [ [ - 1027, - 1027 + 33, + 33 ] ], "settings": { - "syntax": "Packages/C Improved/C Improved.tmLanguage" + "auto_name": "OK 1. BPCE", + "syntax": "Packages/MarkdownEditing/Markdown.tmLanguage" }, "translation.x": 0.0, - "translation.y": 465.0, + "translation.y": 0.0, "zoom_level": 1.0 }, - "stack_index": 3, + "stack_index": 11, "type": "text" }, { "buffer": 8, - "file": "/home/flowher/repos/MatasanoCrypto/sol/set1.cpp", + "file": "/home/flowher/repos/MatasanoCrypto/src/enc_modes.h", "semi_transient": false, "settings": { - "buffer_size": 12515, + "buffer_size": 459, "regions": { }, "selection": [ [ - 5301, - 5301 + 78, + 78 ] ], "settings": { - "syntax": "Packages/C++/C++.tmLanguage", - "translate_tabs_to_spaces": false + "syntax": "Packages/C Improved/C Improved.tmLanguage" }, "translation.x": 0.0, - "translation.y": 2360.0, + "translation.y": 0.0, "zoom_level": 1.0 }, - "stack_index": 0, + "stack_index": 4, "type": "text" }, { "buffer": 9, - "file": "/home/flowher/repos/MatasanoCrypto/src/common.h", + "file": "/home/flowher/repos/MatasanoCrypto/src/common.c", "semi_transient": false, "settings": { - "buffer_size": 2279, + "buffer_size": 2975, "regions": { }, "selection": [ [ - 279, - 279 + 2461, + 2461 ] ], "settings": { "syntax": "Packages/C Improved/C Improved.tmLanguage" }, - "translation.x": -0.0, - "translation.y": 0.0, + "translation.x": 0.0, + "translation.y": 1461.0, "zoom_level": 1.0 }, - "stack_index": 2, + "stack_index": 6, "type": "text" }, { "buffer": 10, - "file": "/home/flowher/test.cpp", + "file": "/home/flowher/repos/MatasanoCrypto/sol/set1.cpp", "semi_transient": false, "settings": { - "buffer_size": 282, + "buffer_size": 12514, "regions": { }, "selection": [ [ - 133, - 133 + 12514, + 12514 ] ], "settings": { - "syntax": "Packages/C++/C++.tmLanguage" + "syntax": "Packages/C++/C++.tmLanguage", + "translate_tabs_to_spaces": false }, "translation.x": 0.0, - "translation.y": 0.0, + "translation.y": 4111.0, "zoom_level": 1.0 }, - "stack_index": 13, + "stack_index": 9, "type": "text" }, { @@ -1805,7 +1794,7 @@ "translation.y": 0.0, "zoom_level": 1.0 }, - "stack_index": 10, + "stack_index": 8, "type": "text" }, { @@ -1834,7 +1823,7 @@ "translation.y": 1014.0, "zoom_level": 1.0 }, - "stack_index": 8, + "stack_index": 12, "type": "text" }, { @@ -1862,7 +1851,7 @@ "translation.y": 0.0, "zoom_level": 1.0 }, - "stack_index": 11, + "stack_index": 13, "type": "text" } ] @@ -1911,6 +1900,10 @@ { "height": 100.0 }, + "output.git-commit": + { + "height": 112.0 + }, "output.hex_viewer_inspector": { "height": 94.0 @@ -1931,7 +1924,7 @@ "project": "Matasano.sublime-project", "replace": { - "height": 46.0 + "height": 64.0 }, "save_all_on_build": true, "select_file": @@ -1940,6 +1933,10 @@ "last_filter": "", "selected_items": [ + [ + "common", + "MatasanoCrypto/src/common.c" + ], [ "common.c", "MatasanoCrypto/src/common.c" @@ -2447,10 +2444,6 @@ [ "timer", "HPT-13/src/TimersManager.cpp" - ], - [ - "cmdnewsetdelbasepeakversiontest", - "SI/masteragent/test/src/CmdNewSetDelBasePeakVersionTest.cpp" ] ], "width": 0.0 @@ -2757,7 +2750,7 @@ "show_open_files": true, "show_tabs": false, "side_bar_visible": true, - "side_bar_width": 207.0, + "side_bar_width": 198.0, "status_bar_visible": true, "template_settings": { diff --git a/sol/set2.c b/sol/set2.c index 7d3bf1e..b05a5cb 100644 --- a/sol/set2.c +++ b/sol/set2.c @@ -3,7 +3,10 @@ #include "src/enc_modes.h" #include #include +#include +#include #include +#include #include #include #include @@ -42,6 +45,8 @@ struct OpenSSL } }; + + TCASE(ecb_encrypt_decrypt_single_block) { static const uint8_t expected_result[17] = "0123456789123456"; @@ -77,21 +82,28 @@ TCASE_E TCASE(pkcs7_test) { - // int pkcs7_pad(const char* i_buff, const size_t i_len, char* o_buff ); - const char text1[] = "Text1"; - const char text2[] = "Text2ToPad"; + const uint8_t text1[] = "Text1"; + uint8_t unpadded[32] = {0}; + uint8_t* p_unpadded = &unpadded[0]; + int ret; - char buff1[32]; + uint8_t buff1[32]; + uint8_t* p_buff1 = &buff1[0]; char buff2[10]; - ret = pkcs7_pad(text1, 5, buff1, 32); - CHECK(ret==0, (const unsigned char* const) "Padding operation failed"); + ret = pkcs7_pad(text1, 5, &p_buff1, 32); + CHECK(ret==true, (const unsigned char* const) "Padding operation failed"); ret = memcmp(text1, buff1, 5); CHECK(ret==0, (const unsigned char* const) "Content differs"); for(int i=5; i<32; i++) { CHECK(buff1[i] == 27, (const unsigned char* const) "Wrong padding"); } + + size_t unpad_len = 0; + CHECK( true == 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) ); } TCASE_E @@ -250,3 +262,161 @@ TCASE(encode_decode_openssl) } } TCASE_E + +/* ------------------------------------------------------------------------- + Checks if ciphertext is encrypted with ECB or CBC. + Requirement: In order to work, plaintext must encrypt to 6 blocks + and all the letters in the PT must be exactly the same. + Returns: + * 0 : if ciphertext encrypted with ECB + * 1 : if ciphertext encrypted with CBC + * 0xFF: in case wrong input parameters provided + -------------------------------------------------------------------------*/ +uint8_t check_ciphertext(const uint8_t* ciphertext, uint32_t len ) +{ + uint32_t bs = 16; + if( (len < 6*bs) || (len>7*bs) ) + return 0xFF; + + for(uint32_t i=1; i<6; ++i) + { + if( memcmp(ciphertext+(bs*i), ciphertext+(bs*(i+1)), bs) != 0) + return 1; // Two blocks differ -> must be CBC + } + 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) +{ + uint8_t iv1[16] = {0}; + uint8_t key[16] = {0}; + uint8_t prepend_byte_size; + uint8_t append_byte_size; + uint8_t random_bytes[10]; + uint8_t encryption_mode = 0xFF; + struct timespec tv; + CryptoAttribs_t attribs; + Key_t keyObj; + + // seed randomnes + clock_gettime(CLOCK_MONOTONIC, &tv); + srand((unsigned int)tv.tv_nsec); + + // choose random sizes and enc mode (0 ECB, 1 CBC) + prepend_byte_size = 5+(rand() % 6); + append_byte_size = 5+(rand() % 6); + encryption_mode = rand() % 2; + + // generate rando data + RAND_bytes(iv1, 16); + RAND_bytes(key, 16); + + // 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.output = (uint8_t*)malloc(7*16); + attribs.padding = kPadding_PKCS7; + + // copy input to the input buffer + RAND_bytes(random_bytes, prepend_byte_size); + int tmplen=0; + memcpy(attribs.input+tmplen, random_bytes, prepend_byte_size); + tmplen+=prepend_byte_size; + memcpy(attribs.input+tmplen, pt, pt_len); + tmplen+=pt_len; + RAND_bytes(random_bytes, append_byte_size); + memcpy(attribs.input+tmplen, random_bytes, append_byte_size); + tmplen+=append_byte_size; + + // 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 + { + if( Result_OK!=ecb_encrypt(&attribs, &keyObj) ) + return Result_Error; + } + + // Copy results + memcpy(ct, attribs.output, attribs.output_len); + *ct_len = attribs.output_len; + *mode = encryption_mode; + + CryptoAttribs_t::Free(&attribs); + return Result_OK; +} + +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); +} +TCASE_E + +TCASE(encrypt_padding_pkcs7) +{ +/* char text[] = "ABC"; + char iv[16] = {0}; + + CryptoAttribs_t attribs_enc; + CryptoAttribs_t::Init(&attribs_enc); + attribs_enc.input = &text[0]; + attribs_enc.input_len = sizeof(text); + attribs_enc.iv = &iv1[0]; + attribs_enc.iv_len = sizeof(iv1); + attribs_enc.operation = kEncrypt; + attribs_enc.padding = kPadding_PKCS7; + CHECK( Result_OK == cbc_encrypt(&attribs_enc, &keyObj) ); + + CryptoAttribs_t attribs_openssl_dec; + CryptoAttribs_t::Init(&attribs_openssl_dec); + attribs_openssl_dec.input = attribs_enc.output; + attribs_openssl_dec.input_len = attribs_enc.output_len; + attribs_openssl_dec.iv = &iv1[0]; + attribs_openssl_dec.iv_len = sizeof(iv1); + attribs_openssl_dec.operation = kDecrypt; + CHECK(OpenSSL::Cbc(&attribs_openssl_dec, &keyObj)==Result_OK); + CHECK(attribs_openssl_dec.output_len==48, (uint8_t*)"Ciphertext has wrong size"); + CHECK( + memcmp( concatenated_blocks, + attribs_openssl_dec.output, + attribs_openssl_dec.output_len) == 0, + (uint8_t*)"Input/Output differs"); + ::free(attribs_enc.output); + ::free(attribs_openssl_dec.output); +*/ +} +TCASE_E \ No newline at end of file diff --git a/sol/set2.h b/sol/set2.h index f24c3ee..e19ca3d 100644 --- a/sol/set2.h +++ b/sol/set2.h @@ -6,6 +6,8 @@ void cbc_decrypt_test(); void cbc_enc_dec_test(); void ecb_encrypt_decrypt_single_block(); void encode_decode_openssl(); +void encode_oracle_test(); +void encrypt_padding_pkcs7(); struct SET2 { @@ -16,6 +18,8 @@ struct SET2 encode_decode_openssl(); cbc_decrypt_test(); cbc_enc_dec_test(); + encode_oracle_test(); + encrypt_padding_pkcs7(); } }; diff --git a/src/common.c b/src/common.c index 7fc291c..c02656f 100644 --- a/src/common.c +++ b/src/common.c @@ -115,6 +115,7 @@ void CryptoAttribs_t::Init(CryptoAttribs_t* ctx) ctx->input = NULL; ctx->input_len = 0; ctx->operation = kEncrypt; + ctx->padding = kPadding_None; } void CryptoAttribs_t::Free(CryptoAttribs_t* ctx) diff --git a/src/common.h b/src/common.h index 20a9963..abf9554 100644 --- a/src/common.h +++ b/src/common.h @@ -42,6 +42,11 @@ typedef enum { kDecrypt = 1 } CryptoOperation; +typedef enum { + kPadding_None = 0, + kPadding_PKCS7 +} PaddingType; + /* ------------------------------------------------------------------------- Struct used for symmetric encryption -------------------------------------------------------------------------*/ @@ -53,6 +58,7 @@ struct CryptoAttribs_t { uint8_t* iv; size_t iv_len; CryptoOperation operation; + PaddingType padding; static void Init(CryptoAttribs_t* ctx); static void Free(CryptoAttribs_t* ctx); diff --git a/src/enc_modes.c b/src/enc_modes.c index 911ad2d..2f79a0c 100644 --- a/src/enc_modes.c +++ b/src/enc_modes.c @@ -7,6 +7,7 @@ #include "xor.h" #include "base64.h" // to del #include +#include "pkcs7.h" static Result_t crypt( CryptoAttribs_t* attribs, const Key_t* const key) @@ -33,8 +34,10 @@ static Result_t crypt( CryptoAttribs_t* attribs, (attribs->operation == kEncrypt ? 1 : 0)) ); OP_CHECK( EVP_CIPHER_CTX_iv_length(&ctx) == 0); EVP_CIPHER_CTX_set_padding(&ctx, 0); + // printf("ZZ %d\n", ret); OP_CHECK( EVP_CipherUpdate(&ctx, &out[ret], &ret, attribs->input, attribs->input_len) ); attribs->output_len = ret; + // printf("OO %d\n", ret); OP_CHECK( EVP_CipherFinal_ex(&ctx, &out[ret], &ret) ); attribs->output_len += ret; EVP_CIPHER_CTX_cleanup(&ctx); @@ -105,18 +108,32 @@ Result_t cbc_encrypt( CryptoAttribs_t* attribs, const Key_t* const key) { - - if((attribs->input_len % key->len) != 0 ) - return Result_Error; - if( attribs->iv_len != key->len ) return Result_Error; if( key->len == 0 ) return Result_Error; - const size_t bc = attribs->input_len / key->len; + uint8_t* padded_input = NULL; + size_t new_buf_len = 0; + if( attribs->padding == kPadding_PKCS7 ) + { + new_buf_len = ROUNDUP_16_BYTES(attribs->input_len); + // one block extra if size aligned + if(new_buf_len == attribs->input_len) + new_buf_len += 16; + pkcs7_pad(attribs->input, attribs->input_len, &padded_input, new_buf_len); + } + else + { + if((attribs->input_len % key->len) != 0 ) + return Result_Error; + } + + const size_t bc_without_last = (size_t)( attribs->input_len / key->len ); + const size_t bc = bc_without_last + 1; const size_t bs = key->len; + const size_t last_bs = attribs->input_len % bs; if( attribs->output == NULL) { @@ -133,6 +150,7 @@ Result_t cbc_encrypt( ecb_attribs.input_len = 0; ecb_attribs.output = (uint8_t*)malloc(bs); ecb_attribs.output_len = 0; + Result_t ret = Result_OK; for(int i=0; iinput)+(bs*i); @@ -147,7 +165,10 @@ Result_t cbc_encrypt( // 2. Encrypt ecb_attribs.operation = kEncrypt; if( crypt(&ecb_attribs, key) != Result_OK ) - return Result_Error; + { + ret = Result_Error; + break; + } // Encrypted block is my new IV iv = ecb_attribs.output; @@ -159,7 +180,8 @@ Result_t cbc_encrypt( attribs->output_len += ecb_attribs.output_len; } CryptoAttribs_t::Free(&ecb_attribs); - return Result_OK; + ::free(padded_input); + return ret; } Result_t ecb_encrypt( CryptoAttribs_t* attribs, const Key_t* const key ) diff --git a/src/pkcs7.c b/src/pkcs7.c index a7e63ca..41c7787 100644 --- a/src/pkcs7.c +++ b/src/pkcs7.c @@ -1,17 +1,83 @@ #include #include #include +#include -int pkcs7_pad(const char* i_buff, size_t i_len, char* o_buff, size_t i_obuff_len ) + +/* ----------------------------------------------------------------------------- + * @brief Produces PKCS7 padded buffer from unpadded buffer + * + * @param i_buff: unpadded buffer + * i_len : length of unpadded buffer + * o_buff: padded output. If pointer *o_buff NULL then memory is allocated + * i_obuff_len: requested size of the output buffer + * + * @returns false if: + * * pad value is bigger then 0xFF. In such case o_buff is unchanged. + * * i_obuff_len < i_len + * * o_buff: NULL + * Otherwise true. + * +-------------------------------------------------------------------------------- */ +bool pkcs7_pad(const uint8_t* i_buff, size_t i_len, uint8_t** o_buff, size_t i_obuff_len ) { - if(i_obuff_len < i_len ) + if( (i_obuff_len < i_len ) || + (i_obuff_len - i_len > 0xFF) || + (o_buff == NULL) ) { - return -1; + return false; + } + if(NULL == *o_buff ) + { + *o_buff = (uint8_t*) malloc(i_obuff_len); } - const unsigned pad_value = i_obuff_len - i_len; - memset(o_buff, pad_value, i_obuff_len); - memcpy(o_buff, i_buff, i_len); + memset(*o_buff, pad_value, i_obuff_len); + memcpy(*o_buff, i_buff, i_len); + + return true; +} + +/* ----------------------------------------------------------------------------- + * @brief Removes padding from PKCS7 padded buffer + * + * @param i_padded_buf: padded buffer + * i_len : length of padded buffer + * o_unpad_buf: unpadded output. If pointer *o_buff NULL then memory is allocated + * unpad_len: length of unpadded buffer + * + * @returns false if: + * * any of pointers NULL + * * i_len == 0 + * * pad_value > 0xFF + * Otherwise true. + * +-------------------------------------------------------------------------------- */ +bool pkcs7_unpad( const uint8_t* i_padded_buf, + size_t i_len, + uint8_t** o_unpad_buf, + size_t* unpad_len) +{ + if( i_padded_buf== NULL || + unpad_len == NULL || + o_unpad_buf == NULL || + i_len == 0) + { + return false; + } + + const unsigned pad_val = i_padded_buf[i_len - 1]; + if(pad_val > 0xFF) + { + return false; + } + + *unpad_len = i_len - pad_val; + if(*o_unpad_buf == NULL) + { + *o_unpad_buf = (uint8_t*) malloc(*unpad_len); + } - return 0; + memcpy(*o_unpad_buf, i_padded_buf, *unpad_len); + return true; } \ No newline at end of file diff --git a/src/pkcs7.h b/src/pkcs7.h index 164e7f7..57aebb9 100644 --- a/src/pkcs7.h +++ b/src/pkcs7.h @@ -1,2 +1,17 @@ +#ifndef __pkcs7_h__ +#define __pkcs7_h__ + #include -int pkcs7_pad(const char* i_buff, size_t i_len, char* o_buff, size_t i_obuff_len ); \ No newline at end of file +#include + +bool pkcs7_pad( const uint8_t* i_buff, + size_t i_len, + uint8_t** o_buff, + size_t i_obuff_len ); + +bool pkcs7_unpad( const uint8_t* i_padded_buf, + size_t i_len, + uint8_t** o_unpad_buf, + size_t* unpad_len); + +#endif // __pkcs7_h__