From 82c6d450a695da9f6b409cb1dd1fb631b804a992 Mon Sep 17 00:00:00 2001 From: Axel Kenzo <axelkenzo@mail.ru> Date: Sat, 27 Jun 2020 17:36:52 +0300 Subject: [PATCH] =?UTF-8?q?=D0=92=D0=BE=D1=81=D1=81=D1=82=D0=B0=D0=BD?= =?UTF-8?q?=D0=BE=D0=B2=D0=BB=D0=B5=D0=BD=D0=B0=20=D1=80=D0=B5=D0=B0=D0=BB?= =?UTF-8?q?=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8F=20=D1=80=D0=B5=D0=B6=D0=B8?= =?UTF-8?q?=D0=BC=D0=B0=20acpkm=20=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B0=20=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8?= =?UTF-8?q?=D1=8F=20=D1=81=D0=BE=D1=85=D1=80=D0=B0=D0=BD=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20=D0=B2=20pem-?= =?UTF-8?q?=D1=84=D0=B0=D0=B9=D0=BB=D0=B5=20=D0=98=D1=81=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=B0=20=D1=80=D0=B5=D0=B0=D0=BB=D0=B8?= =?UTF-8?q?=D0=B7=D0=B0=D1=86=D0=B8=D1=8F=20=D1=80=D0=B5=D0=B6=D0=B8=D0=BC?= =?UTF-8?q?=D0=B0=20cfb?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 1 + Changelog.md | 2 + TODO | 4 +- aktool/Readme.md | 56 +++--- aktool/aktool.1 | 56 +++--- aktool/aktool.template.in | 3 +- doc/Doxyfile.in | 8 +- source/ak_acpkm.c | 370 ++++++++++++++++++++++++++++++++++++++ source/ak_asn1.c | 76 ++++---- source/ak_bckey.c | 140 ++++++++++++++- source/ak_bckey.h | 19 +- source/ak_kuznechik.c | 122 ++++++++++++- source/ak_libakrypt.c | 10 +- source/ak_magma.c | 133 +++++++++++++- source/ak_sign.c | 4 +- source/ak_tools.c | 30 ++++ source/ak_tools.h | 4 +- tests/test-asn1-build.c | 2 + tests/test-bckey04.c | 32 +++- tests/test-bckey05-cfb.c | 4 +- 20 files changed, 939 insertions(+), 137 deletions(-) create mode 100644 source/ak_acpkm.c diff --git a/CMakeLists.txt b/CMakeLists.txt index c2e38c3b..71eec3a4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -109,6 +109,7 @@ if( LIBAKRYPT_CRYPTO_FUNCTIONS ) source/ak_bckey.c source/ak_magma.c source/ak_kuznechik.c + source/ak_acpkm.c source/ak_context_manager.c source/ak_sign.c source/ak_asn1_keys.c diff --git a/Changelog.md b/Changelog.md index 35ddebf0..2dedfe06 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,6 +4,8 @@ ## Рзменения РІ версии 0.8.5 - Рзменена внутренняя структура ak_oid Рё реализация функций РїРѕРёСЃРєР° идентификаторов + - Восстановлена реализация потеряных РєРѕРіРґР°-то Р·Р° ненадобностью режимов шифрования ofb, cfb Рё acpkm + - Рзменена реализация функции сохранения файлов РІ pem-формате - Р’ утилиту aktool добавлен СЂСЏРґ функций тестирования работоспособности библиотеки Рё скорости выполнения криптографических алгоритмов diff --git a/TODO b/TODO index bbbf16a2..81edd052 100644 --- a/TODO +++ b/TODO @@ -1,11 +1,13 @@ План работ РґРѕ завершения версии 0.8 + вернуть handle + режимы шифрования - вернуть acpkm режимы имитозащиты - - сделать acpkm-omac - сделать СЃmac (как отдельный ключ имитовставки) + - сделать acpkm-omac - сделать acpkm-omac (как отдельный ключ имитовставки) режимы aead diff --git a/aktool/Readme.md b/aktool/Readme.md index 41890c04..df58a5af 100644 --- a/aktool/Readme.md +++ b/aktool/Readme.md @@ -551,7 +551,7 @@ der-последовательностей, закодированных РІ РєРѕ \-o, \--output \<файл\> : Опция позволяет РІ СЏРІРЅРѕРј РІРёРґРµ определить -РёРјСЏ файла РІ который Р±СѓРґСѓС‚ помещены конверированные или объединенные данные. +РёРјСЏ файла РІ который Р±СѓРґСѓС‚ помещены конвертированные или объединенные данные. Данную опцию имеет смысл использовать совместно СЃ опциями `--convert` Рё `--join`. \--to \<формат\> @@ -591,33 +591,33 @@ der-последовательностей, закодированных РІ РєРѕ в”ЊSEQUENCEв”ђ - в”њSEQUENCEв”ђ - в”‚ в”њINTEGER 0x0 - в”‚ в”њSEQUENCEв”ђ - в”‚ в”‚ в””SETв”ђ - в”‚ в”‚ в””SEQUENCEв”ђ - в”‚ в”‚ в”њOBJECT IDENTIFIER 2.5.4.3 - в”‚ в”‚ в””PRINTABLE STRING Example - в”‚ в”њSEQUENCEв”ђ - в”‚ в”‚ в”њSEQUENCEв”ђ - в”‚ в”‚ в”‚ в”њOBJECT IDENTIFIER 1.2.643.7.1.1.1.1 - в”‚ в”‚ в”‚ в””SEQUENCEв”ђ - в”‚ в”‚ в”‚ в””OBJECT IDENTIFIER 1.2.643.7.1.2.1.1.1 - в”‚ в”‚ в””BIT STRING - в”‚ в”‚ 04 40 74 27 95 D4 BE E8 84 DD F2 85 0F EC 03 EA - в”‚ в”‚ 3F AF 18 44 E0 1D 9D A6 0B 64 50 93 A5 5E 26 DF - в”‚ в”‚ C3 99 78 F5 96 CF 4D 4D 0C 6C F1 D1 89 43 D9 44 - в”‚ в”‚ 93 D1 6B 9E C0 A1 6D 51 2D 2E 12 7C C4 69 1A 63 - в”‚ в”‚ 18 E2 - в”‚ в””[0]в”ђ - в”‚ (null) - в”њSEQUENCEв”ђ - в”‚ в””OBJECT IDENTIFIER 1.2.643.7.1.1.3.2 - в””BIT STRING - 1B DC 2A 13 17 67 9B 66 23 2F 63 EA 16 FF 7C 64 - CC AA B9 AD 85 5F C6 E1 80 91 66 1D B7 9D 48 12 - 1D 0E 1D A5 BE 34 7C 6F 1B 52 56 C7 AE AC 20 0A - D6 4A C7 7A 6F 5B 3A 0E 09 73 18 E7 AE 6E E7 69 + в”њSEQUENCEв”ђ + в”‚ в”њINTEGER 0x0 + в”‚ в”њSEQUENCEв”ђ + в”‚ в”‚ в””SETв”ђ + в”‚ в”‚ в””SEQUENCEв”ђ + в”‚ в”‚ в”њOBJECT IDENTIFIER 2.5.4.3 + в”‚ в”‚ в””PRINTABLE STRING Example + в”‚ в”њSEQUENCEв”ђ + в”‚ в”‚ в”њSEQUENCEв”ђ + в”‚ в”‚ в”‚ в”њOBJECT IDENTIFIER 1.2.643.7.1.1.1.1 + в”‚ в”‚ в”‚ в””SEQUENCEв”ђ + в”‚ в”‚ в”‚ в””OBJECT IDENTIFIER 1.2.643.7.1.2.1.1.1 + в”‚ в”‚ в””BIT STRING + в”‚ в”‚ 04 40 74 27 95 D4 BE E8 84 DD F2 85 0F EC 03 EA + в”‚ в”‚ 3F AF 18 44 E0 1D 9D A6 0B 64 50 93 A5 5E 26 DF + в”‚ в”‚ C3 99 78 F5 96 CF 4D 4D 0C 6C F1 D1 89 43 D9 44 + в”‚ в”‚ 93 D1 6B 9E C0 A1 6D 51 2D 2E 12 7C C4 69 1A 63 + в”‚ в”‚ 18 E2 + в”‚ в””[0]в”ђ + в”‚ (null) + в”њSEQUENCEв”ђ + в”‚ в””OBJECT IDENTIFIER 1.2.643.7.1.1.3.2 + в””BIT STRING + 1B DC 2A 13 17 67 9B 66 23 2F 63 EA 16 FF 7C 64 + CC AA B9 AD 85 5F C6 E1 80 91 66 1D B7 9D 48 12 + 1D 0E 1D A5 BE 34 7C 6F 1B 52 56 C7 AE AC 20 0A + D6 4A C7 7A 6F 5B 3A 0E 09 73 18 E7 AE 6E E7 69 Следующий вызов демонстрирует diff --git a/aktool/aktool.1 b/aktool/aktool.1 index 1f4558ae..42d9c9ae 100644 --- a/aktool/aktool.1 +++ b/aktool/aktool.1 @@ -1996,7 +1996,7 @@ ASN.1 \[u0434]\[u0435]\[u0440]\[u0435]\[u0432]\[u043E] \[u043D]\[u0430] \[u0432] \[u043A]\[u043E]\[u0442]\[u043E]\[u0440]\[u044B]\[u0439] \[u0431]\[u0443]\[u0434]\[u0443]\[u0442] \[u043F]\[u043E]\[u043C]\[u0435]\[u0449]\[u0435]\[u043D]\[u044B] -\[u043A]\[u043E]\[u043D]\[u0432]\[u0435]\[u0440]\[u0438]\[u0440]\[u043E]\[u0432]\[u0430]\[u043D]\[u043D]\[u044B]\[u0435] +\[u043A]\[u043E]\[u043D]\[u0432]\[u0435]\[u0440]\[u0442]\[u0438]\[u0440]\[u043E]\[u0432]\[u0430]\[u043D]\[u043D]\[u044B]\[u0435] \[u0438]\[u043B]\[u0438] \[u043E]\[u0431]\[u044A]\[u0435]\[u0434]\[u0438]\[u043D]\[u0435]\[u043D]\[u043D]\[u044B]\[u0435] \[u0434]\[u0430]\[u043D]\[u043D]\[u044B]\[u0435]. @@ -2122,33 +2122,33 @@ aktool a request_edw.pem .nf \f[C] \[u250C]SEQUENCE\[u2510] - \[u251C]SEQUENCE\[u2510] - \[br] \[u251C]INTEGER 0x0 - \[br] \[u251C]SEQUENCE\[u2510] - \[br] \[br] \[u2514]SET\[u2510] - \[br] \[br] \[u2514]SEQUENCE\[u2510] - \[br] \[br] \[u251C]OBJECT IDENTIFIER 2.5.4.3 - \[br] \[br] \[u2514]PRINTABLE STRING Example - \[br] \[u251C]SEQUENCE\[u2510] - \[br] \[br] \[u251C]SEQUENCE\[u2510] - \[br] \[br] \[br] \[u251C]OBJECT IDENTIFIER 1.2.643.7.1.1.1.1 - \[br] \[br] \[br] \[u2514]SEQUENCE\[u2510] - \[br] \[br] \[br] \[u2514]OBJECT IDENTIFIER 1.2.643.7.1.2.1.1.1 - \[br] \[br] \[u2514]BIT STRING - \[br] \[br] 04 40 74 27 95 D4 BE E8 84 DD F2 85 0F EC 03 EA - \[br] \[br] 3F AF 18 44 E0 1D 9D A6 0B 64 50 93 A5 5E 26 DF - \[br] \[br] C3 99 78 F5 96 CF 4D 4D 0C 6C F1 D1 89 43 D9 44 - \[br] \[br] 93 D1 6B 9E C0 A1 6D 51 2D 2E 12 7C C4 69 1A 63 - \[br] \[br] 18 E2 - \[br] \[u2514][0]\[u2510] - \[br] (null) - \[u251C]SEQUENCE\[u2510] - \[br] \[u2514]OBJECT IDENTIFIER 1.2.643.7.1.1.3.2 - \[u2514]BIT STRING - 1B DC 2A 13 17 67 9B 66 23 2F 63 EA 16 FF 7C 64 - CC AA B9 AD 85 5F C6 E1 80 91 66 1D B7 9D 48 12 - 1D 0E 1D A5 BE 34 7C 6F 1B 52 56 C7 AE AC 20 0A - D6 4A C7 7A 6F 5B 3A 0E 09 73 18 E7 AE 6E E7 69 + \[u251C]SEQUENCE\[u2510] + \[br] \[u251C]INTEGER 0x0 + \[br] \[u251C]SEQUENCE\[u2510] + \[br] \[br] \[u2514]SET\[u2510] + \[br] \[br] \[u2514]SEQUENCE\[u2510] + \[br] \[br] \[u251C]OBJECT IDENTIFIER 2.5.4.3 + \[br] \[br] \[u2514]PRINTABLE STRING Example + \[br] \[u251C]SEQUENCE\[u2510] + \[br] \[br] \[u251C]SEQUENCE\[u2510] + \[br] \[br] \[br] \[u251C]OBJECT IDENTIFIER 1.2.643.7.1.1.1.1 + \[br] \[br] \[br] \[u2514]SEQUENCE\[u2510] + \[br] \[br] \[br] \[u2514]OBJECT IDENTIFIER 1.2.643.7.1.2.1.1.1 + \[br] \[br] \[u2514]BIT STRING + \[br] \[br] 04 40 74 27 95 D4 BE E8 84 DD F2 85 0F EC 03 EA + \[br] \[br] 3F AF 18 44 E0 1D 9D A6 0B 64 50 93 A5 5E 26 DF + \[br] \[br] C3 99 78 F5 96 CF 4D 4D 0C 6C F1 D1 89 43 D9 44 + \[br] \[br] 93 D1 6B 9E C0 A1 6D 51 2D 2E 12 7C C4 69 1A 63 + \[br] \[br] 18 E2 + \[br] \[u2514][0]\[u2510] + \[br] (null) + \[u251C]SEQUENCE\[u2510] + \[br] \[u2514]OBJECT IDENTIFIER 1.2.643.7.1.1.3.2 + \[u2514]BIT STRING + 1B DC 2A 13 17 67 9B 66 23 2F 63 EA 16 FF 7C 64 + CC AA B9 AD 85 5F C6 E1 80 91 66 1D B7 9D 48 12 + 1D 0E 1D A5 BE 34 7C 6F 1B 52 56 C7 AE AC 20 0A + D6 4A C7 7A 6F 5B 3A 0E 09 73 18 E7 AE 6E E7 69 \f[R] .fi .PP diff --git a/aktool/aktool.template.in b/aktool/aktool.template.in index d8bb304b..cb894313 100644 --- a/aktool/aktool.template.in +++ b/aktool/aktool.template.in @@ -14,7 +14,6 @@ \setsansfont{CMU Sans Serif} \setmonofont{CMU Typewriter Text} - % ---------------------------------------------------------------------------------------------- % % \providecommand{\tightlist}{% @@ -52,7 +51,7 @@ $endif$ {\bfseries\textsc{Рнструкция РїРѕ применению}}\\[1\baselineskip] \vspace{0.5\textheight} -{\small\textsc{Axel Kenzo \& The Company Of Belles Lettres~~\copyright~~2014 -- 2020}}\\[1\baselineskip] +{\small\textsc{Axel Kenzo Рё <<Компания изящной словесности>>~~\copyright~~2020}}\\[1\baselineskip] } % end vbox } % end parbox diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index 41cdb4fc..06adfb0b 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -2076,7 +2076,7 @@ XML_NS_MEMB_FILE_SCOPE = NO # that can be used to generate PDF. # The default value is: NO. -GENERATE_DOCBOOK = NO +GENERATE_DOCBOOK = YES # The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be put in @@ -2419,7 +2419,7 @@ INCLUDED_BY_GRAPH = YES # The default value is: NO. # This tag requires that the tag HAVE_DOT is set to YES. -CALL_GRAPH = NO +CALL_GRAPH = YES # If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller # dependency graph for every global function or class method. @@ -2431,7 +2431,7 @@ CALL_GRAPH = NO # The default value is: NO. # This tag requires that the tag HAVE_DOT is set to YES. -CALLER_GRAPH = NO +CALLER_GRAPH = YES # If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical # hierarchy of all classes instead of a textual one. @@ -2531,7 +2531,7 @@ PLANTUML_INCLUDE_PATH = # Minimum value: 0, maximum value: 10000, default value: 50. # This tag requires that the tag HAVE_DOT is set to YES. -DOT_GRAPH_MAX_NODES = 50 +DOT_GRAPH_MAX_NODES = 25 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs # generated by dot. A depth value of 3 means that only nodes reachable from the diff --git a/source/ak_acpkm.c b/source/ak_acpkm.c new file mode 100644 index 00000000..788ecc75 --- /dev/null +++ b/source/ak_acpkm.c @@ -0,0 +1,370 @@ +/* ----------------------------------------------------------------------------------------------- */ +/* Copyright (c) 2019 by Petr Mikhalitsyn, myprettycapybara@gmail.com */ +/* Axel Kenzo, axelkenzo@mail.ru */ +/* */ +/* Файл ak_acpkm.h */ +/* - содержит реализацию криптографических алгоритмов семейства ACPKM РёР· Р 1323565.1.017—2018 */ +/* ----------------------------------------------------------------------------------------------- */ + #include <ak_tools.h> + #include <ak_bckey.h> + +/* ----------------------------------------------------------------------------------------------- */ +/*! \details Функция вычисляет РЅРѕРІРѕРµ значение секретного ключа РІ соответствии СЃ соотношениями + РёР· раздела 4.1, СЃРј. Р 1323565.1.017—2018. + После выработки РЅРѕРІРѕРµ значение помещается вместо старого. + Одновременно, изменяется ресурс РЅРѕРІРѕРіРѕ ключа: его тип принимает значение - \ref key_using_resource, + Р° счетчик принимает значение, определяемое РѕРґРЅРѕР№ РёР· опций + + - `ackpm_section_magma_block_count`, + - `ackpm_section_kuznechik_block_count`. + + @param bkey Контекст ключа алгоритма блочного шифрования, для которого вычисляется + РЅРѕРІРѕРµ значение. Контекст должен быть инициализирован Рё содержать ключевое значение. + @return Р’ случае возникновения ошибки функция возвращает ее РєРѕРґ, РІ противном случае + возвращается \ref ak_error_ok (ноль) */ +/* ----------------------------------------------------------------------------------------------- */ + int ak_bckey_context_next_acpkm_key( ak_bckey bkey ) +{ + ssize_t counter = 0; + int error = ak_error_ok; + ak_uint8 new_key[32], acpkm[32] = { + 0x9f, 0x9e, 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96, 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, + 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80 }; + + /* проверки */ + if( bkey == NULL ) return ak_error_message( ak_error_null_pointer, __func__, + "using null pointer to block cipher key" ); + if( bkey->key.key_size != 32 ) return ak_error_message_fmt( ak_error_wrong_length, __func__, + "using block cipher key with unexpected length %u", bkey->bsize ); + /* целостность ключа */ + if( bkey->key.check_icode( &bkey->key ) != ak_true ) + return ak_error_message( ak_error_wrong_key_icode, + __func__, "incorrect integrity code of secret key value" ); + /* выработка РЅРѕРІРѕРіРѕ значения */ + switch( bkey->bsize ) { + case 8: /* шифр СЃ длиной блока 64 бита */ + bkey->encrypt( &bkey->key, acpkm, new_key ); + bkey->encrypt( &bkey->key, acpkm +8, new_key +8 ); + bkey->encrypt( &bkey->key, acpkm +16, new_key +16 ); + bkey->encrypt( &bkey->key, acpkm +24, new_key +24 ); + counter = ak_libakrypt_get_option( "acpkm_section_magma_block_count" ); + break; + case 16: /* шифр СЃ длиной блока 128 Р±РёС‚ */ + bkey->encrypt( &bkey->key, acpkm, new_key ); + bkey->encrypt( &bkey->key, acpkm +16, new_key +16 ); + counter = ak_libakrypt_get_option( "acpkm_section_kuznechik_block_count" ); + break; + default: return ak_error_message( ak_error_wrong_block_cipher, + __func__ , "incorrect block size of block cipher key" ); + } + + /* присваиваем ключу значение */ + if(( error = ak_bckey_context_set_key( bkey, new_key, bkey->key.key_size )) != ak_error_ok ) + ak_error_message( error, __func__ , "can't replace key by new using acpkm" ); + else { + bkey->key.resource.value.type = key_using_resource; + bkey->key.resource.value.counter = counter; + } + ak_ptr_context_wipe( new_key, sizeof( new_key ), &bkey->key.generator ); + return error; +} + +/* ----------------------------------------------------------------------------------------------- */ +#ifdef LIBAKRYPT_LITTLE_ENDIAN + #define acpkm_block64 {\ + nkey.encrypt( &nkey.key, ctr, yaout );\ + ctr[0] += 1;\ + ((ak_uint64 *) outptr)[0] = yaout[0] ^ ((ak_uint64 *) inptr)[0];\ + outptr++; inptr++;\ + } + + #define acpkm_block128 {\ + nkey.encrypt( &nkey.key, ctr, yaout );\ + if(( ctr[0] += 1 ) == 0 ) ctr[1]++;\ + ((ak_uint64 *) outptr)[0] = yaout[0] ^ ((ak_uint64 *) inptr)[0];\ + ((ak_uint64 *) outptr)[1] = yaout[1] ^ ((ak_uint64 *) inptr)[1];\ + outptr += 2; inptr += 2;\ + } + +#else + #define acpkm_block64 {\ + nkey.encrypt( &nkey.key, ctr, yaout );\ + ctr[0] = bswap_64( ctr[0] ); ctr[0] += 1; ctr[0] = bswap_64( ctr[0] );\ + ((ak_uint64 *) outptr)[0] = yaout[0] ^ ((ak_uint64 *) inptr)[0];\ + outptr++; inptr++;\ + } + + #define acpkm_block128 {\ + nkey.encrypt( &nkey.key, ctr, yaout );\ + ctr[0] = bswap_64( ctr[0] ); ctr[0] += 1; ctr[0] = bswap_64( ctr[0] );\ + if( ctr[0] == 0 ) { \ + ctr[1] = bswap_64( ctr[0] ); ctr[1] += 1; ctr[1] = bswap_64( ctr[0] );\ + }\ + ((ak_uint64 *) outptr)[0] = yaout[0] ^ ((ak_uint64 *) inptr)[0];\ + ((ak_uint64 *) outptr)[1] = yaout[1] ^ ((ak_uint64 *) inptr)[1];\ + outptr += 2; inptr += 2;\ + } +#endif + +/* ----------------------------------------------------------------------------------------------- */ +/*! Р’ режиме ACPKM для шифрования используется операция гаммирования - операция сложения + открытого (зашифровываемого) текста СЃ гаммой, вырабатываемой шифром, РїРѕ модулю РґРІР°. + Поэтому, для зашифрования Рё расшифрования информациии используется РѕРґРЅР° Рё та Р¶Рµ функция. + + Р’ процессе шифрования исходные данные разбиваются РЅР° секции фиксированной длины, после чего + каждая секция шифруется РЅР° своем ключе. Длина секции является параметром алгоритма Рё + РЅРµ должна превосходить величины, определяемой РѕРґРЅРѕР№ РёР· следующих технических характеристик + (опций) + + - `ackpm_section_magma_block_count`, + - `ackpm_section_kuznechik_block_count`. + + Значение синхропосылки `iv` копируется РІРѕ временную область памяти Рё, РІ С…РѕРґРµ выполнения + функции, РЅРµ изменяется. Повторный вызов функции ak_bckey_context_ctr_acpkm() СЃ нулевым + указатетем РЅР° синхропосылу, как РІ случае функции ak_bckey_context_ctr(), РЅРµ допускается. + + @param bkey Контекст ключа алгоритма блочного шифрования, + используемый для шифрования Рё порождения цепочки производных ключей. + @param in Указатель РЅР° область памяти, РіРґРµ хранятся входные + (зашифровываемые/расшифровываемые) данные + @param out Указатель РЅР° область памяти, РєСѓРґР° помещаются выходные + (расшифровываемые/зашифровываемые) данные; этот указатель может совпадать СЃ in + @param size Размер зашировываемых данных (РІ байтах). Длина зашифровываемых данных может + принимать любое значение, РЅРµ превосходящее \f$ 2^{\frac{8n}{2}-1}\f$, РіРґРµ \f$ n \f$ + длина блока алгоритма шифрования (8 или 16 байт). + + @param section_size Размер РѕРґРЅРѕР№ секции РІ байтах. Данная величина должна быть кратна длине блока + используемого алгоритма шифрования. + + @param iv имитовставка + @param iv_size длина имитовставки (РІ байтах) + + @return Р’ случае возникновения ошибки функция возвращает ее РєРѕРґ, РІ противном случае + возвращается \ref ak_error_ok (ноль) */ +/* ----------------------------------------------------------------------------------------------- */ + int ak_bckey_context_ctr_acpkm( ak_bckey bkey, ak_pointer in, ak_pointer out, size_t size, + size_t section_size, ak_pointer iv, size_t iv_size) +{ + struct bckey nkey; + int error = ak_error_ok; + ssize_t j = 0, sections = 0, tail = 0, seclen = 0, maxseclen = 0, mcount = 0; + ak_uint64 yaout[2], *inptr = (ak_uint64 *)in, *outptr = (ak_uint64 *)out, ctr[2] = { 0, 0 }; + + /* выполняем проверку размера входных данных */ + if( section_size%bkey->bsize != 0 ) + return ak_error_message( ak_error_wrong_block_cipher_length, + __func__ , "the length of section is not divided by block length" ); + /* проверяем целостность ключа */ + if( bkey->key.check_icode( &bkey->key ) != ak_true ) + return ak_error_message( ak_error_wrong_key_icode, __func__, + "incorrect integrity code of secret key value" ); + /* проверяем размер синхропосылки */ + if( iv == NULL ) return ak_error_message( ak_error_null_pointer, __func__, + "using null pointer to initialization vector" ); + if( iv_size < ( bkey->bsize >> 1 )) + return ak_error_message( ak_error_wrong_block_cipher_length, + __func__ , "the length of initialization vector is incorrect" ); + + /* получаем максимально РІРѕР·РјРѕР¶РЅСѓСЋ длину секции, количество сообщений РЅР° РѕРґРЅРѕРј ключе, + Р° также устанавливаем синхропосылку */ + switch( bkey->bsize ) { + case 8: + maxseclen = ak_libakrypt_get_option( "acpkm_section_magma_block_count" ); + mcount = ak_libakrypt_get_option( "magma_cipher_resource" )/maxseclen; + #ifdef LIBAKRYPT_LITTLE_ENDIAN + ctr[0] = ((ak_uint64 *)iv)[0] << 32; + #else + ctr[0] = ((ak_uint32 *)iv)[0]; + #endif + break; + case 16: + maxseclen = ak_libakrypt_get_option( "acpkm_section_kuznechik_block_count" ); + mcount = ak_libakrypt_get_option( "kuznechik_cipher_resource" )/maxseclen; + ctr[1] = ((ak_uint64 *) iv)[0]; + break; + default: return ak_error_message( ak_error_wrong_block_cipher, + __func__ , "incorrect block size of block cipher key" ); + } + /* проверяем, что пользователь определил длину секции РЅРµ очень большим значением */ + seclen = ( ssize_t )( section_size/bkey->bsize ); + if( seclen > maxseclen ) return ak_error_message( ak_error_wrong_length, __func__, + "section has very large length" ); + /* проверяем ресурс ключа перед использованием */ + if( bkey->key.resource.value.type != key_using_resource ) { /* РјС‹ пришли СЃСЋРґР° РІ первый раз */ + bkey->key.resource.value.type = key_using_resource; + bkey->key.resource.value.counter = mcount; /* здесь находится максимальное число сообщений, + которые РјРѕРіСѓС‚ быть зашифрованы РЅР° данном ключе */ + } else { + if( bkey->key.resource.value.counter < 1 ) + return ak_error_message( ak_error_low_key_resource, + __func__ , "low key using resource for block cipher key context" ); + else bkey->key.resource.value.counter--; + } + + /* теперь размножаем исходный ключ */ + if(( error = ak_bckey_context_create_and_set_bckey( &nkey, bkey )) != ak_error_ok ) + return ak_error_message( error, __func__, "incorrect key duplication" ); + /* Рё меняем ресурс для РїСЂРѕРёР·РІРѕРґРЅРѕРіРѕ ключа */ + nkey.key.resource.value.counter = maxseclen; + + /* дальнейшие криптографические действия применяются Рє РЅРѕРІРѕРјСѓ экземпляру ключа */ + sections = ( ssize_t )( size/section_size ); + tail = ( ssize_t )( size - ( size_t )( sections*seclen )*nkey.bsize ); + if( sections > 0 ) { + do{ + switch( nkey.bsize ) { /* обрабатываем РѕРґРЅСѓ секцию */ + case 8: for( j = 0; j < seclen; j++ ) acpkm_block64; break; + case 16: for( j = 0; j < seclen; j++ ) acpkm_block128; break; + default: ak_error_message( ak_error_wrong_block_cipher, + __func__ , "incorrect block size of block cipher key" ); + } + /* вычисляем следующий ключ */ + if(( error = ak_bckey_context_next_acpkm_key( &nkey )) != ak_error_ok ) { + ak_error_message_fmt( error, __func__, "incorrect key generation after %u sections", + (unsigned int) sections ); + goto labex; + } + } while( --sections > 0 ); + } /* конец обработки случая, РєРѕРіРґР° sections > 0 */ + + if( tail ) { /* теперь обрабатываем фрагмент данных, РЅРµ кратный длине секции */ + if(( seclen = tail/(ssize_t)( nkey.bsize )) > 0 ) { + switch( nkey.bsize ) { /* обрабатываем данные, кратные длине блока */ + case 8: for( j = 0; j < seclen; j++ ) acpkm_block64; break; + case 16: for( j = 0; j < seclen; j++ ) acpkm_block128; break; + default: ak_error_message( ak_error_wrong_block_cipher, + __func__ , "incorrect block size of block cipher key" ); + } + } + /* остался последний фрагмент, длина которого меньше длины блока + РІ качестве гаммы РјС‹ используем старшие байты */ + if(( tail -= seclen*(ssize_t)( nkey.bsize )) > 0 ) { + nkey.encrypt( &nkey.key, ctr, yaout ); + for( j = 0; j < tail; j++ ) ((ak_uint8 *) outptr)[j] = + ((ak_uint8 *)yaout)[(ssize_t)nkey.bsize-tail+j] ^ ((ak_uint8 *) inptr)[j]; + } + } + + labex: ak_bckey_context_destroy( &nkey ); + return error; +} + +/* ----------------------------------------------------------------------------------------------- */ + bool_t ak_bckey_test_acpkm( void ) +{ + struct bckey key; + int error = ak_error_ok, audit = ak_log_get_level(); + ak_uint8 skey[32] = { + 0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe, + 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00, 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88 + }; + ak_uint8 iv1[8] = { 0xf0, 0xce, 0xab, 0x90, 0x78, 0x56, 0x34, 0x12 }; + ak_uint8 iv2[4] = { 0x78, 0x56, 0x34, 0x12 }; + + ak_uint8 out[112], in1[112] = { + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, + 0x0a, 0xff, 0xee, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00, + 0x00, 0x0a, 0xff, 0xee, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, + 0x11, 0x00, 0x0a, 0xff, 0xee, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, + 0x22, 0x11, 0x00, 0x0a, 0xff, 0xee, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, + 0x33, 0x22, 0x11, 0x00, 0x0a, 0xff, 0xee, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, + 0x44, 0x33, 0x22, 0x11, 0x00, 0x0a, 0xff, 0xee, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 0x77, 0x66, 0x55 + }; + ak_uint8 out1[112] = { + 0xb8, 0xa1, 0xbd, 0x40, 0xa2, 0x5f, 0x7b, 0xd5, 0xdb, 0xd1, 0x0e, 0xc1, 0xbe, 0xd8, 0x95, 0xf1, + 0xe4, 0xde, 0x45, 0x3c, 0xb3, 0xe4, 0x3c, 0xf3, 0x5d, 0x3e, 0xa1, 0xf6, 0x33, 0xe7, 0xee, 0x85, + 0x00, 0xe8, 0x85, 0x5e, 0x27, 0x06, 0x17, 0x00, 0x55, 0x4c, 0x6f, 0x64, 0x8f, 0xeb, 0xce, 0x4b, + 0x46, 0x50, 0x80, 0xd0, 0xaf, 0x34, 0x48, 0x3e, 0x39, 0x94, 0xd0, 0x68, 0xf5, 0x4d, 0x7c, 0x58, + 0x6e, 0x89, 0x8a, 0x6b, 0x31, 0x6c, 0xfc, 0x1c, 0xe1, 0xec, 0xae, 0x86, 0x76, 0xf5, 0x30, 0xcf, + 0x3e, 0x16, 0x23, 0x34, 0x74, 0x3b, 0x4f, 0x0c, 0x46, 0x36, 0x36, 0x81, 0xec, 0x07, 0xfd, 0xdf, + 0x5d, 0xde, 0xd6, 0xfb, 0xe7, 0x21, 0xd2, 0x69, 0xd4, 0xc8, 0xfa, 0x82, 0xc2, 0xa9, 0x09, 0x64 + }; + ak_uint8 in2[56] = { + 0x00, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, /* РїРѕ сравнению СЃ текстом рекомендаций открытый */ + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, /* текст выведен РІ блоки РїРѕ 8 байт Рё развернут */ + 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00, /* РІ обратном РїРѕСЂСЏРґРєРµ, РїРѕ аналогии СЃРѕ СЃРїРѕСЃРѕР±РѕРј, */ + 0x0a, 0xff, 0xee, 0xcc, 0xbb, 0xaa, 0x99, 0x88, /* использованом РІ стандарте РЅР° блочные шифры */ + 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, + 0x00, 0x0a, 0xff, 0xee, 0xcc, 0xbb, 0xaa, 0x99, + 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22 + }; + ak_uint8 out2[56] = { + 0xab, 0x4c, 0x1e, 0xeb, 0xee, 0x1d, 0xb8, 0x2a, + 0xea, 0x94, 0x6b, 0xbd, 0xc4, 0x04, 0xe1, 0x68, + 0x6b, 0x5b, 0x2e, 0x6c, 0xaf, 0x67, 0x2c, 0xc7, + 0x2e, 0xb3, 0xf1, 0x70, 0x17, 0xb6, 0xaf, 0x0e, + 0x82, 0x13, 0xed, 0x9e, 0x14, 0x71, 0xae, 0xa1, + 0x6f, 0xec, 0x72, 0x06, 0x18, 0x67, 0xd4, 0xab, + 0xc1, 0x72, 0xca, 0x3f, 0x5b, 0xf1, 0xa2, 0x84 + }; + + /* 1. Выполняем тест для алгоритма Магма */ + if(( error = ak_bckey_context_create_magma( &key )) != ak_error_ok ) { + ak_error_message( error, __func__, "incorrect creation of magma secret key" ); + return ak_false; + } + if(( error = ak_bckey_context_set_key( &key, skey, sizeof( skey ))) != ak_error_ok ) { + ak_error_message( error, __func__, "incorrect assigning a key value" ); goto ex1; } + + if(( error = ak_bckey_context_ctr_acpkm( &key, in2, out, sizeof( in2 ), + 16, iv2, sizeof( iv2 ))) != ak_error_ok ) { + ak_error_message( error, __func__, "incorrect encryption of plain text" ); goto ex1; } + + if( memcmp( out, out2, sizeof( in2 )) != 0 ) { + ak_error_message( error = ak_error_not_equal_data, __func__, + "incorrect data comparizon after acpkm encryption with Magma cipher" ); goto ex1; } + /* расшифровываем */ + if(( error = ak_bckey_context_ctr_acpkm( &key, out2, out, sizeof( in2 ), + 16, iv2, sizeof( iv2 ))) != ak_error_ok ) { + ak_error_message( error, __func__, "incorrect encryption of plain text" ); goto ex1; } + + if( memcmp( out, in2, sizeof( in2 )) != 0 ) { + ak_error_message( error = ak_error_not_equal_data, __func__, + "incorrect data comparizon after acpkm decryption with Magma cipher" ); goto ex1; } + + if( audit >= ak_log_maximum ) ak_error_message( ak_error_ok, __func__ , + "encryption/decryption test for Magma is Ok" ); + ex1: ak_bckey_context_destroy( &key ); + if( error != ak_error_ok ) { + ak_error_message( ak_error_ok, __func__ , "acpkm mode test for Magma is wrong" ); + return ak_false; + } + + /* 2. Выполняем тест для алгоритма Кузнечик */ + if(( error = ak_bckey_context_create_kuznechik( &key )) != ak_error_ok ) { + ak_error_message( error, __func__, "incorrect creation of kuznechik secret key" ); + return ak_false; + } + if(( error = ak_bckey_context_set_key( &key, skey, sizeof( skey ))) != ak_error_ok ) { + ak_error_message( error, __func__, "incorrect assigning a key value" ); goto ex2; } + + if(( error = ak_bckey_context_ctr_acpkm( &key, in1, out, sizeof( in1 ), + 32, iv1, sizeof( iv1 ))) != ak_error_ok ) { + ak_error_message( error, __func__, "incorrect encryption of plain text" ); goto ex2; } + + if( memcmp( out, out1, sizeof( in1 )) != 0 ) { + ak_error_message( error = ak_error_not_equal_data, __func__, + "incorrect data comparizon after acpkm encryption with Kuznechik cipher" ); goto ex2; } + /* расшифровываем */ + if(( error = ak_bckey_context_ctr_acpkm( &key, out1, out, sizeof( out1 ), + 32, iv1, sizeof( iv1 ))) != ak_error_ok ) { + ak_error_message( error, __func__, "incorrect encryption of plain text" ); goto ex2; } + + if( memcmp( out, in1, sizeof( in1 )) != 0 ) { + ak_error_message( error = ak_error_not_equal_data, __func__, + "incorrect data comparizon after acpkm decryption with Kuznechik cipher" ); goto ex2; } + + if( audit >= ak_log_maximum ) ak_error_message( ak_error_ok, __func__ , + "encryption/decryption test for Kuznechik is Ok" ); + ex2: ak_bckey_context_destroy( &key ); + if( error != ak_error_ok ) { + ak_error_message( ak_error_ok, __func__ , "acpkm mode test for Kuznechik is wrong" ); + return ak_false; + } + + return ak_true; +} + +/* ----------------------------------------------------------------------------------------------- */ +/* ak_acpkm.c */ +/* ----------------------------------------------------------------------------------------------- */ diff --git a/source/ak_asn1.c b/source/ak_asn1.c index c284189a..46fcc096 100644 --- a/source/ak_asn1.c +++ b/source/ak_asn1.c @@ -2300,8 +2300,8 @@ Validity ::= SEQUENCE { Время, которое помещается РІ структуру `Validity`, приводится РёР· локального времени РІРѕ время РїРѕ Гринвичу. РџСЂРё чтении структуры должно производиться обратное преобразование. - \todo Согласно RFC 5280 даты РґРѕ 2050 РіРѕРґР° сохраняются как UTCTime, - даты, начиная СЃ 1 января 2050 РіРѕРґР° сохраняются как GeneralTime. + TODO: Согласно RFC 5280 даты РґРѕ 2050 РіРѕРґР° должны сохранятся как UTCTime (это сделано) + даты, начиная СЃ 1 января 2050 РіРѕРґР° должны сохранятся как GeneralTime. (это надо сделать) \param asn1 указатель РЅР° текущий уровень ASN.1 дерева. \param not_before начало временного интервала; локальное время, может быть получено @@ -2781,58 +2781,58 @@ Validity ::= SEQUENCE { /* ----------------------------------------------------------------------------------------------- */ int ak_asn1_context_export_to_pemfile( ak_asn1 asn, const char *filename, crypto_content_t type ) { - FILE *fp = NULL; ak_uint8 out[4]; + struct file ofile; int error = ak_error_ok; ak_uint8 *buffer = NULL, *ptr = NULL; size_t len = 0, cnt = 0, idx, blocks, tail; - /* получаем длину */ - if(( error = ak_asn1_context_evaluate_length( asn, &len )) != ak_error_ok ) - return ak_error_message( error, __func__, "incorrect evaluation total asn1 context length" ); + /* получаем длину */ + if(( error = ak_asn1_context_evaluate_length( asn, &len )) != ak_error_ok ) + return ak_error_message( error, __func__, "incorrect evaluation total asn1 context length" ); - /* кодируем/декодируем */ - blocks = len/3; - if(( tail = len - 3*blocks ) != 0 ) len = 3*(blocks+1); /* увеличиваем объем РґРѕ кратного трем - после декодирования переменная len СЃРЅРѕРІР° примет истинное значение */ - if(( ptr = buffer = malloc( len )) == NULL ) - return ak_error_message( ak_error_out_of_memory, __func__, + /* кодируем/декодируем */ + blocks = len/3; + if(( tail = len - 3*blocks ) != 0 ) len = 3*(blocks+1); /* увеличиваем объем РґРѕ кратного трем + после декодирования переменная len СЃРЅРѕРІР° примет истинное значение */ + if(( ptr = buffer = malloc( len )) == NULL ) + return ak_error_message( ak_error_out_of_memory, __func__, "incorrect memory allocation for der-sequence" ); - memset( buffer, 0, len ); - if(( error = ak_asn1_context_encode( asn, buffer, &len )) != ak_error_ok ) { - ak_error_message( error, __func__, "incorrect encoding of asn1 context" ); - goto lab2; - } + memset( buffer, 0, len ); + if(( error = ak_asn1_context_encode( asn, buffer, &len )) != ak_error_ok ) { + ak_error_message( error, __func__, "incorrect encoding of asn1 context" ); + goto lab2; + } - /* поскольку РјС‹ работаем только СЃ текстовыми символами, - то для сохранения данных используется стандартная библиотека */ - if(( fp = fopen( filename, "w" )) == NULL ) { - ak_error_message_fmt( error, __func__, "incorrect creation of %s", filename ); - goto lab2; - } + /* сохраняем закодированый буффер */ + if(( error = ak_file_create_to_write( &ofile, filename )) != ak_error_ok ) { + ak_error_message( error, __func__, "incorrect creation a file for secret key" ); + goto lab2; + } - fprintf( fp, "-----BEGIN %s-----\n", crypto_content_titles[type] ); - for( idx = 0; idx < blocks; idx++ ) { + ak_file_printf( &ofile, "-----BEGIN %s-----\n", crypto_content_titles[type] ); + + for( idx = 0; idx < blocks; idx++ ) { ak_base64_encodeblock( ptr, out, 3); - fprintf( fp, "%c%c%c%c", out[0], out[1], out[2], out[3] ); + ak_file_printf( &ofile, "%c%c%c%c", out[0], out[1], out[2], out[3] ); ptr += 3; if( ++cnt == 16 ) { /* 16С…4 = 64 символа РІ РѕРґРЅРѕР№ строке */ - fprintf( fp, "\n" ); + ak_file_printf( &ofile, "\n" ); cnt = 0; } - } - if( tail ) { - ak_base64_encodeblock( ptr, out, tail ); - fprintf( fp, "%c%c%c%c", out[0], out[1], out[2], out[3] ); - ++cnt; - fprintf( fp, "\n"); - } else - if(( cnt != 16 ) && ( cnt != 0 )) fprintf( fp, "\n"); + } + if( tail ) { + ak_base64_encodeblock( ptr, out, tail ); + ak_file_printf( &ofile, "%c%c%c%c", out[0], out[1], out[2], out[3] ); + ++cnt; + ak_file_printf( &ofile, "\n" ); + } else + if(( cnt != 16 ) && ( cnt != 0 )) ak_file_printf( &ofile, "\n" ); - fprintf( fp, "-----END %s-----\n", crypto_content_titles[type] ); - fclose( fp ); + ak_file_printf( &ofile, "-----END %s-----\n", crypto_content_titles[type] ); + ak_file_close( &ofile ); - lab2: free( buffer ); + lab2: free( buffer ); return error; } diff --git a/source/ak_bckey.c b/source/ak_bckey.c index cbc8aebb..e0303e7c 100644 --- a/source/ak_bckey.c +++ b/source/ak_bckey.c @@ -328,6 +328,50 @@ return error; } +/* ----------------------------------------------------------------------------------------------- */ +/*! @param bkey Контекст создаваемого ключа. + @param rkey Контекст ключа, значение которого дублируется. + + @return Р’ случае успеха возвращается значение \ref ak_error_ok. Р’ противном случае + возвращается РєРѕРґ ошибки. */ +/* ----------------------------------------------------------------------------------------------- */ + int ak_bckey_context_create_and_set_bckey( ak_bckey bkey, ak_bckey rkey ) +{ + ak_oid oid = NULL; + int error = ak_error_ok; + if( bkey == NULL ) return ak_error_message( ak_error_null_pointer, __func__, + "using null pointer to left block cipher context" ); + if( rkey == NULL ) return ak_error_message( ak_error_null_pointer, __func__, + "using null pointer to right block cipher context" ); + if(( oid = rkey->key.oid ) == NULL ) + return ak_error_message( ak_error_wrong_oid, __func__, + "using null pointer to internal oid in right block cipher context" ); + if( oid->func.create == NULL ) + return ak_error_message( ak_error_undefined_function, __func__, + "using null pointer to create function in right block cipher context" ); + /* создаем объект */ + if(( error = ((ak_function_bckey_create *)oid->func.create)( bkey )) != ak_error_ok ) + return ak_error_message( error, __func__, "incorrect creation of left block cipher context" ); + + /* присваиваем ключ */ + if(( error = rkey->key.unmask( &rkey->key )) != ak_error_ok ) { + ak_error_message( error, __func__, "incorrect unmasking block cipher context" ); + goto labex; + } + if(( error = ak_bckey_context_set_key( bkey, + rkey->key.key, rkey->key.key_size )) != ak_error_ok ) { + ak_error_message( error, __func__, "incorrect assigning a new key value" ); + } + rkey->key.set_mask( &rkey->key ); + + return error; + + labex: + ak_bckey_context_destroy( bkey ); + return error; +} + + /* ----------------------------------------------------------------------------------------------- */ /* теперь реализация режимов шифрования */ /* ----------------------------------------------------------------------------------------------- */ @@ -867,7 +911,7 @@ } /* ----------------------------------------------------------------------------------------------- */ - int ak_bckey_context_cfb( ak_bckey bkey, ak_pointer in, ak_pointer out, size_t size, + int ak_bckey_context_encrypt_cfb( ak_bckey bkey, ak_pointer in, ak_pointer out, size_t size, ak_pointer iv, size_t iv_size ) { ak_int64 blocks = (ak_int64)( size/bkey->bsize ), @@ -960,6 +1004,100 @@ return error; } +/* ----------------------------------------------------------------------------------------------- */ + int ak_bckey_context_decrypt_cfb( ak_bckey bkey, ak_pointer in, ak_pointer out, size_t size, + ak_pointer iv, size_t iv_size ) + { + ak_int64 blocks = (ak_int64)( size/bkey->bsize ), + tail = (ak_int64)( size%bkey->bsize ); + ak_uint8 *vecptr = NULL; + ak_uint64 yaout[2], *inptr = (ak_uint64 *)in, *outptr = (ak_uint64 *)out; + int error = ak_error_ok, oc = (int) ak_libakrypt_get_option( "openssl_compability" ); + unsigned long i = 0, z = iv_size / bkey->bsize; // РІРѕ сколько раз синхрпосылка длиннее блока + + if(( oc < 0 ) || ( oc > 1 )) return ak_error_message( ak_error_wrong_option, __func__, + "wrong value for \"openssl_compability\" option" ); + /* проверяем целостность ключа */ + if( bkey->key.check_icode( &bkey->key ) != ak_true ) + return ak_error_message( ak_error_wrong_key_icode, __func__, + "incorrect integrity code of secret key value" ); + /* уменьшаем значение ресурса ключа */ + if( bkey->key.resource.value.counter < ( blocks + ( tail > 0 ))) + return ak_error_message( ak_error_low_key_resource, + __func__ , "low resource of block cipher key" ); + else bkey->key.resource.value.counter -= ( blocks + ( tail > 0 )); + + /* выбираем, как вычислять синхропосылку проверяем флаг + флаг поднимается РїСЂРё вызове функции СЃ заданным значением синхропосылки Рё + всегда опускается РїСЂРё обработке данных, РЅРµ кратных длине блока */ + if(( iv == NULL ) || ( iv_size == 0 )) { /* запрос РЅР° использование внутреннего значения */ + + if( bkey->key.flags&ak_key_flag_not_ctr ) + return ak_error_message( ak_error_wrong_block_cipher_function, __func__ , + "function call with undefined value of initial vector" ); + } else { + + /* проверяем длину синхропосылки (если меньше длины блока, то плохо) + если больше, то нормально - лишнее просто РЅРµ используется */ + if( (iv_size % bkey->bsize) || (iv_size > 64) ) + return ak_error_message( ak_error_wrong_iv_length, __func__, + "incorrect length of initial value" ); + /* помещаем РІРѕ внутренний буффер значение синхропосылки */ + memcpy(bkey->ivector, iv, iv_size); + + /* поднимаем значение флага: синхропосылка установлена */ + bkey->key.flags = ( bkey->key.flags&( ~ak_key_flag_not_ctr ))^ak_key_flag_not_ctr; + } + + /* обработка РѕСЃРЅРѕРІРЅРѕРіРѕ массива данных (кратного длине блока) */ + switch( bkey->bsize ) { + case 8: /* шифр СЃ длиной блока 64 бита */ + while( blocks > 0 ) { + vecptr = (bkey->ivector + i*bkey->bsize); + bkey->encrypt( &bkey->key, vecptr, yaout ); + *outptr = *inptr ^ yaout[0]; + ((ak_uint64 *)vecptr)[0] = *inptr; + outptr++; inptr++; + if (++i == z) i = 0; + --blocks; + } + break; + + case 16: /* шифр СЃ длиной блока 128 Р±РёС‚ */ + while( blocks > 0 ) { + vecptr = (bkey->ivector + i*bkey->bsize ); + bkey->encrypt( &bkey->key, vecptr, yaout ); + *outptr = *inptr ^ yaout[0]; + ((ak_uint64 *)vecptr)[0] = *inptr; ++outptr; ++inptr; + *outptr = *inptr ^ yaout[1]; + ((ak_uint64 *)vecptr)[1] = *inptr; ++outptr; ++inptr; + if (++i == z) i = 0; + --blocks; + } + break; + + default: return ak_error_message( ak_error_wrong_block_cipher, + __func__ , "incorrect block size of block cipher key" ); + } + + /* обрабатываем С…РІРѕСЃС‚ сообщения */ + if( tail ) { + vecptr = (bkey->ivector + bkey->bsize * (i % (int)(iv_size / bkey->bsize))); + bkey->encrypt( &bkey->key, vecptr, yaout ); + for( i = 0; i < (unsigned long)tail; i++ ) + ( (ak_uint8*)outptr)[i] = ( (ak_uint8*)inptr )[i]^( (ak_uint8 *)yaout)[i]; + + /* запрещаем дальнейшее использование функции РЅР° данном значении синхропосылки, + поскольку обрабатываемые данные РЅРµ кратны длине блока. */ + memset( bkey->ivector, 0, sizeof( bkey->ivector )); + bkey->key.flags = bkey->key.flags&( ~ak_key_flag_not_ctr ); + /* перемаскируем ключ */ + if(( error = bkey->key.set_mask( &bkey->key )) != ak_error_ok ) + ak_error_message( error, __func__ , "wrong remasking of secret key" ); + } + return error; +} + /* ----------------------------------------------------------------------------------------------- */ /*! Функция вычисляет имитовставку РѕС‚ заданной области памяти фиксированного размера. Рспользуется алгоритм, который также называют OMAC1 diff --git a/source/ak_bckey.h b/source/ak_bckey.h index b6e20bf6..931f96c9 100644 --- a/source/ak_bckey.h +++ b/source/ak_bckey.h @@ -69,7 +69,7 @@ int ak_bckey_context_set_key_random( ak_bckey , ak_random ); /*! \brief Присвоение контексту ключа алгоритма блочного шифрования значения, выработанного РёР· пароля. */ int ak_bckey_context_set_key_from_password( ak_bckey , const ak_pointer , const size_t , - const ak_pointer , const size_t ); + const ak_pointer , const size_t ); /* ----------------------------------------------------------------------------------------------- */ /*! \brief Рнициализация ключа алгоритма блочного шифрования значением РґСЂСѓРіРѕРіРѕ ключа */ int ak_bckey_context_create_and_set_bckey( ak_bckey , ak_bckey ); @@ -84,10 +84,12 @@ int ak_bckey_context_decrypt_ecb( ak_bckey , ak_pointer , ak_pointer , size_t ); /*! \brief Зашифрование данных РІ режиме простой замены СЃ зацеплением РёР· ГОСТ Р 34.13-2015 (cipher block chaining, cbc). */ - int ak_bckey_context_encrypt_cbc( ak_bckey , ak_pointer , ak_pointer , size_t , ak_pointer , size_t ); + int ak_bckey_context_encrypt_cbc( ak_bckey , ak_pointer , ak_pointer , size_t , + ak_pointer , size_t ); /*! \brief Расшифрование данных РІ режиме простой замены СЃ зацеплением РёР· ГОСТ Р 34.13-2015 (cipher block chaining, cbc). */ - int ak_bckey_context_decrypt_cbc( ak_bckey , ak_pointer , ak_pointer , size_t , ak_pointer , size_t ); + int ak_bckey_context_decrypt_cbc( ak_bckey , ak_pointer , ak_pointer , size_t , + ak_pointer , size_t ); /*! \brief Шифрование данных РІ режиме гаммирования РёР· ГОСТ Р 34.13-2015 (counter mode, ctr). */ int ak_bckey_context_ctr( ak_bckey , ak_pointer , ak_pointer , size_t , ak_pointer , size_t ); @@ -96,15 +98,18 @@ int ak_bckey_context_ofb( ak_bckey , ak_pointer , ak_pointer , size_t , ak_pointer , size_t ); /*! \brief Шифрование данных РІ режиме гаммирования СЃ обратной СЃРІСЏР·СЊСЋ РїРѕ шифртексту (cipher feedback, cfb). */ - int ak_bckey_context_cfb( ak_bckey , ak_pointer , ak_pointer , size_t , ak_pointer , size_t ); - + int ak_bckey_context_encrypt_cfb( ak_bckey , ak_pointer , ak_pointer , size_t , + ak_pointer , size_t ); +/*! \brief Расшифрование данных РІ режиме гаммирования СЃ обратной СЃРІСЏР·СЊСЋ РїРѕ шифртексту + (cipher feedback, cfb). */ + int ak_bckey_context_decrypt_cfb( ak_bckey , ak_pointer , ak_pointer , size_t , + ak_pointer , size_t ); /*! \brief Шифрование данных РІ режиме CTR-ACPKM РёР· Р 1323565.1.017—2018. */ int ak_bckey_context_ctr_acpkm( ak_bckey , ak_pointer , ak_pointer , size_t , size_t , - ak_pointer , size_t ); + ak_pointer , size_t ); /*! \brief Вычисление имитовставки согласно ГОСТ Р 34.13-2015. */ int ak_bckey_context_cmac( ak_bckey , ak_pointer , const size_t , ak_pointer , const size_t ); - /* ----------------------------------------------------------------------------------------------- */ /*! \brief Выработка матрицы, соответствующей 16 тактам работы линейного региста СЃРґРІРёРіР°. */ void ak_bckey_context_kuznechik_generate_matrix( const linear_register , linear_matrix ); diff --git a/source/ak_kuznechik.c b/source/ak_kuznechik.c index 994dd18f..d0d34e4d 100644 --- a/source/ak_kuznechik.c +++ b/source/ak_kuznechik.c @@ -770,7 +770,6 @@ int error = ak_error_ok, audit = ak_log_get_level(), oc = (int) ak_libakrypt_get_option( "openssl_compability" ); - /* тестовый ключ РёР· ГОСТ Р 34.12-2015, приложение Рђ.1 */ /* тестовый ключ РёР· ГОСТ Р 34.13-2015, приложение Рђ.1 */ ak_uint8 key[32] = { 0xef,0xcd,0xab,0x89,0x67,0x45,0x23,0x01,0x10,0x32,0x54,0x76,0x98,0xba,0xdc,0xfe, @@ -858,6 +857,47 @@ 0x16, 0x76, 0x88, 0x06, 0x5a, 0x89, 0x5c, 0x63, 0x1a, 0x2d, 0x9a, 0x15, 0x60, 0xb6, 0x39, 0x70 }; + /* инициализационный вектор для режима гаммирования СЃ обратной СЃРІСЏР·СЊСЋ РїРѕ выходу (ofb) */ + ak_uint8 ivofb[32] = { + 0x12, 0x01, 0xf0, 0xe5, 0xd4, 0xc3, 0xb2, 0xa1, 0xf0, 0xce, 0xab, 0x90, 0x78, 0x56, 0x34, 0x12, + 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x90, 0x89, 0x78, 0x67, 0x56, 0x45, 0x34, 0x23 + }; + + /* значение синхропосылки для командной строки: + 1234567890abcef0a1b2c3d4e5f0011223344556677889901213141516171819 */ + ak_uint8 openssl_ivofb[32] = { + 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xce, 0xf0, 0xa1, 0xb2, 0xc3, 0xd4, 0xe5, 0xf0, 0x01, 0x12, + 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 0x89, 0x90, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19 + }; + + /* зашифрованный блок РёР· ГОСТ Р 34.13-2015, РїСЂРёР». Рђ.1.3*/ + ak_uint8 outofb[64] = { + 0x95, 0xbd, 0x7a, 0x89, 0x5e, 0x79, 0x1f, 0xff, 0x24, 0x2b, 0x84, 0xb1, 0x59, 0x0a, 0x80, 0x81, + 0xbf, 0x26, 0x93, 0x9d, 0x36, 0x21, 0xb5, 0x8f, 0xb4, 0xfa, 0x8c, 0x04, 0xa7, 0x47, 0x5b, 0xed, + 0x13, 0x8a, 0x28, 0x10, 0xfc, 0xe7, 0x0f, 0xc8, 0xb1, 0xb8, 0xa0, 0x3c, 0xac, 0x57, 0xa2, 0x66, + 0x50, 0x31, 0x90, 0xf6, 0x43, 0x22, 0x29, 0xa0, 0x60, 0x86, 0x13, 0x66, 0xc0, 0xbb, 0x3e, 0x20 + }; + ak_uint8 openssl_outofb[64] = { + 0x81, 0x80, 0x0a, 0x59, 0xb1, 0x84, 0x2b, 0x24, 0xff, 0x1f, 0x79, 0x5e, 0x89, 0x7a, 0xbd, 0x95, + 0xed, 0x5b, 0x47, 0xa7, 0x04, 0x8c, 0xfa, 0xb4, 0x8f, 0xb5, 0x21, 0x36, 0x9d, 0x93, 0x26, 0xbf, + 0x66, 0xa2, 0x57, 0xac, 0x3c, 0xa0, 0xb8, 0xb1, 0xc8, 0x0f, 0xe7, 0xfc, 0x10, 0x28, 0x8a, 0x13, + 0x20, 0x3e, 0xbb, 0xc0, 0x66, 0x13, 0x86, 0x60, 0xa0, 0x29, 0x22, 0x43, 0xf6, 0x90, 0x31, 0x50 + }; + + /* зашифрованный блок РёР· ГОСТ Р 34.13-2015, РїСЂРёР». Рђ.1.5 */ + ak_uint8 outcfb[64] = { + 0x95, 0xbd, 0x7a, 0x89, 0x5e, 0x79, 0x1f, 0xff, 0x24, 0x2b, 0x84, 0xb1, 0x59, 0x0a, 0x80, 0x81, + 0xbf, 0x26, 0x93, 0x9d, 0x36, 0x21, 0xb5, 0x8f, 0xb4, 0xfa, 0x8c, 0x04, 0xa7, 0x47, 0x5b, 0xed, + 0xb5, 0x38, 0xa2, 0x97, 0x4e, 0x26, 0x2d, 0x84, 0x38, 0x8d, 0xc6, 0x5c, 0xeb, 0xa8, 0xf2, 0x79, + 0xd1, 0xf4, 0xfb, 0x44, 0xdd, 0xd9, 0x5b, 0xc7, 0xe6, 0x2d, 0x92, 0x4e, 0xcd, 0xbe, 0xfe, 0x4f + }; + ak_uint8 openssl_outcfb[64] = { + 0x81, 0x80, 0x0a, 0x59, 0xb1, 0x84, 0x2b, 0x24, 0xff, 0x1f, 0x79, 0x5e, 0x89, 0x7a, 0xbd, 0x95, + 0xed, 0x5b, 0x47, 0xa7, 0x04, 0x8c, 0xfa, 0xb4, 0x8f, 0xb5, 0x21, 0x36, 0x9d, 0x93, 0x26, 0xbf, + 0x79, 0xf2, 0xa8, 0xeb, 0x5c, 0xc6, 0x8d, 0x38, 0x84, 0x2d, 0x26, 0x4e, 0x97, 0xa2, 0x38, 0xb5, + 0x4f, 0xfe, 0xbe, 0xcd, 0x4e, 0x92, 0x2d, 0xe6, 0xc7, 0x5b, 0xd9, 0xdd, 0x44, 0xfb, 0xf4, 0xd1 + }; + /* значение имитовставки согласно ГОСТ Р 34.13-2015 (раздел Рђ.1.6) */ ak_uint8 imito[8] = { /* 0x67, 0x9C, 0x74, 0x37, 0x5B, 0xB3, 0xDE, 0x4D - первая часть выработанного блока */ @@ -884,7 +924,9 @@ return ak_false; } + /* --------------------------------------------------------------------------- */ /* 1. Создаем контекст ключа алгоритма Кузнечик Рё устанавливаем значение ключа */ + /* --------------------------------------------------------------------------- */ if(( error = ak_bckey_context_create_kuznechik( &bkey )) != ak_error_ok ) { ak_error_message( error, __func__, "incorrect initialization of kuznechik secret key context"); return ak_false; @@ -897,7 +939,9 @@ goto exit; } + /* ------------------------------------------------------------------------------------------- */ /* 2. Проверяем независимую обработку блоков - режим простой замены согласно ГОСТ Р 34.12-2015 */ + /* ------------------------------------------------------------------------------------------- */ if(( error = ak_bckey_context_encrypt_ecb( &bkey, oc ? oc_in : in, myout, sizeof( in ))) != ak_error_ok ) { ak_error_message( error, __func__ , "wrong ecb mode encryption" ); @@ -926,7 +970,9 @@ if( audit >= ak_log_maximum ) ak_error_message( ak_error_ok, __func__ , "the ecb mode encryption/decryption test from GOST R 34.13-2015 is Ok" ); - /* 3. Проверяем режим гаммирования согласно ГОСТ Р 34.12-2015 */ + /* --------------------------------------------------------------------------- */ + /* 3. Проверяем режим гаммирования согласно ГОСТ Р 34.12-2015 */ + /* --------------------------------------------------------------------------- */ if(( error = ak_bckey_context_ctr( &bkey, oc ? oc_in : in, myout, sizeof( in ), oc ? oc_ivctr : ivctr, sizeof( ivctr ))) != ak_error_ok ) { ak_error_message( error, __func__ , "wrong counter mode encryption" ); @@ -942,7 +988,7 @@ if(( error = ak_bckey_context_ctr( &bkey, myout, myout, sizeof( outecb ), oc ? oc_ivctr : ivctr, sizeof( ivctr ))) != ak_error_ok ) { - ak_error_message( error, __func__ , "wrong ecb mode decryption" ); + ak_error_message( error, __func__ , "wrong counter mode decryption" ); result = ak_false; goto exit; } @@ -955,7 +1001,9 @@ if( audit >= ak_log_maximum ) ak_error_message( ak_error_ok, __func__ , "the counter mode encryption/decryption test from GOST R 34.13-2015 is Ok" ); - /* 4. Проверяем режим простой замены c зацеплением согласно ГОСТ Р 34.12-2015 */ + /* --------------------------------------------------------------------------- */ + /* 4. Проверяем режим простой замены c зацеплением согласно ГОСТ Р 34.12-2015 */ + /* --------------------------------------------------------------------------- */ if(( error = ak_bckey_context_encrypt_cbc( &bkey, oc ? oc_in : in, myout, sizeof( in ), oc ? openssl_ivcbc : ivcbc, sizeof( ivcbc ))) != ak_error_ok ) { ak_error_message( error, __func__ , "wrong cbc mode encryption" ); @@ -983,8 +1031,72 @@ if( audit >= ak_log_maximum ) ak_error_message( ak_error_ok, __func__ , "the cbc mode encryption/decryption test from GOST R 34.13-2015 is Ok" ); + /* -------------------------------------------------------------------------------------- */ + /* 5. Проверяем режим гаммирования c обратной СЃРІСЏР·СЊСЋ РїРѕ выходу согласно ГОСТ Р 34.12-2015 */ + /* -------------------------------------------------------------------------------------- */ + if(( error = ak_bckey_context_ofb( &bkey, oc ? oc_in : in, + myout, sizeof( in ), oc ? openssl_ivofb : ivofb, sizeof( ivofb ))) != ak_error_ok ) { + ak_error_message( error, __func__ , "wrong ofb mode encryption" ); + result = ak_false; + goto exit; + } + if( !ak_ptr_is_equal_with_log( myout, oc ? openssl_outofb : outofb, sizeof( outofb ))) { + ak_error_message( ak_error_not_equal_data, __func__ , + "the ofb mode encryption test from GOST R 34.13-2015 is wrong"); + result = ak_false; + goto exit; + } + + if(( error = ak_bckey_context_ofb( &bkey, oc ? openssl_outofb : outofb, + myout, sizeof( outofb ), oc ? openssl_ivofb : ivofb, sizeof( ivofb ))) != ak_error_ok ) { + ak_error_message( error, __func__ , "wrong ofb mode decryption" ); + result = ak_false; + goto exit; + } + if( !ak_ptr_is_equal_with_log( myout, oc ? oc_in : in, sizeof( in ))) { + ak_error_message( ak_error_not_equal_data, __func__ , + "the ofb mode decryption test from GOST R 34.13-2015 is wrong"); + result = ak_false; + goto exit; + } + if( audit >= ak_log_maximum ) ak_error_message( ak_error_ok, __func__ , + "the ofb mode encryption/decryption test from GOST R 34.13-2015 is Ok" ); + + /* -------------------------------------------------------------------------------------- */ + /* 6. Проверяем режим гаммирования c обратной СЃРІСЏР·СЊСЋ РїРѕ шифртексту */ + /* -------------------------------------------------------------------------------------- */ + if(( error = ak_bckey_context_encrypt_cfb( &bkey, oc ? oc_in : in, + myout, sizeof( in ), oc ? openssl_ivofb : ivofb, sizeof( ivofb ))) != ak_error_ok ) { + /* используемая синхропосылка совпадает СЃ вектором РёР· режима ofb */ + ak_error_message( error, __func__ , "wrong cfb mode encryption" ); + result = ak_false; + goto exit; + } + if( !ak_ptr_is_equal_with_log( myout, oc ? openssl_outcfb : outcfb, sizeof( outcfb ))) { + ak_error_message( ak_error_not_equal_data, __func__ , + "the cfb mode encryption test from GOST R 34.13-2015 is wrong"); + result = ak_false; + goto exit; + } + + if(( error = ak_bckey_context_decrypt_cfb( &bkey, oc ? openssl_outcfb : outcfb, + myout, sizeof( outcfb ), oc ? openssl_ivofb : ivofb, sizeof( ivofb ))) != ak_error_ok ) { + ak_error_message( error, __func__ , "wrong cfb mode decryption" ); + result = ak_false; + goto exit; + } + if( !ak_ptr_is_equal_with_log( myout, oc ? oc_in : in, sizeof( in ))) { + ak_error_message( ak_error_not_equal_data, __func__ , + "the cfb mode decryption test from GOST R 34.13-2015 is wrong"); + result = ak_false; + goto exit; + } + if( audit >= ak_log_maximum ) ak_error_message( ak_error_ok, __func__ , + "the cfb mode encryption/decryption test from GOST R 34.13-2015 is Ok" ); - /* 10. Тестируем режим выработки имитовставки (плоская реализация). */ + /* --------------------------------------------------------------------------- */ + /* 10. Тестируем режим выработки имитовставки (плоская реализация). */ + /* --------------------------------------------------------------------------- */ if(( error = ak_bckey_context_cmac( &bkey, oc ? oc_in : in, sizeof( in ), myout, 8 )) != ak_error_ok ) { ak_error_message( error, __func__ , "wrong cmac calculation" ); diff --git a/source/ak_libakrypt.c b/source/ak_libakrypt.c index 45ad3318..e6d42b67 100644 --- a/source/ak_libakrypt.c +++ b/source/ak_libakrypt.c @@ -180,11 +180,11 @@ // "incorrect testing of mgm mode for block ciphers" ); // return ak_false; // } -// if( ak_bckey_test_acpkm() != ak_true ) { -// ak_error_message( ak_error_get_value(), __func__ , -// "incorrect testing of acpkm encryption mode for block ciphers" ); -// return ak_false; -// } + if( ak_bckey_test_acpkm() != ak_true ) { + ak_error_message( ak_error_get_value(), __func__ , + "incorrect testing of acpkm encryption mode for block ciphers" ); + return ak_false; + } if( audit >= ak_log_maximum ) ak_error_message( ak_error_ok, __func__ , "testing block ciphers ended successfully" ); diff --git a/source/ak_magma.c b/source/ak_magma.c index 314f7b5c..639746fe 100644 --- a/source/ak_magma.c +++ b/source/ak_magma.c @@ -737,7 +737,20 @@ int ak_bckey_context_create_magma( ak_bckey bkey ) 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, 0x12 }; - /* зашифрованный блок РёР· ГОСТ Р 34.12-2015 */ + /* инициализационный вектор для режима гаммирования СЃ обратной СЃРІСЏР·СЊСЋ РїРѕ выходу + Рё РѕРЅ Р¶Рµ + инициализационный вектор для режима гаммирования СЃ обратной СЃРІСЏР·СЊСЋ РїРѕ шифртексту */ + ak_uint8 magma_ivofb[16] = { + 0xef, 0xcd, 0xab, 0x90, 0x78, 0x56, 0x34, 0x12, + 0xf1, 0xde, 0xbc, 0x0a, 0x89, 0x67, 0x45, 0x23, + }; + + ak_uint8 openssl_magma_ivofb[16] = { + 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, + 0x23, 0x45, 0x67, 0x89, 0x0a, 0xbc, 0xde, 0xf1, + }; + + /* зашифрованный блок РёР· ГОСТ Р 34.12-2015 для режима простой замены */ ak_uint8 magma_out_cbc[32] = { 0x19, 0x39, 0x68, 0xea, 0x5e, 0xb0, 0xd1, 0x96, 0xb9, 0x37, 0xb9, 0xab, 0x29, 0x61, 0xf7, 0xaf, @@ -751,6 +764,35 @@ int ak_bckey_context_create_magma( ak_bckey bkey ) 0x20, 0xb7, 0x8b, 0x1a, 0x7c, 0xd7, 0xe6, 0x67 }; + /* зашифрованный блок РёР· ГОСТ Р 34.12-2015 для режима гаммирования СЃ обратной СЃРІСЏР·СЊСЋ РїРѕ выходу */ + ak_uint8 magma_outofb[32] = { + 0x83, 0x3c, 0x90, 0x66, 0xe2, 0xe0, 0x37, 0xdb, + 0x9c, 0x08, 0x9a, 0x1f, 0x4c, 0x64, 0x46, 0x0d, + 0x7e, 0x32, 0x0e, 0x43, 0x62, 0x30, 0xf8, 0xa0, + 0x05, 0xdb, 0x4f, 0xbd, 0xb8, 0xef, 0x24, 0xc8 + }; + + ak_uint8 openssl_magma_outofb[32] = { + 0xdb, 0x37, 0xe0, 0xe2, 0x66, 0x90, 0x3c, 0x83, + 0x0d, 0x46, 0x64, 0x4c, 0x1f, 0x9a, 0x08, 0x9c, + 0xa0, 0xf8, 0x30, 0x62, 0x43, 0x0e, 0x32, 0x7e, + 0xc8, 0x24, 0xef, 0xb8, 0xbd, 0x4f, 0xdb, 0x05 + }; + + /* зашифрованный блок РёР· ГОСТ Р 34.12-2015 для режима гаммирования СЃ обратной СЃРІСЏР·СЊСЋ РїРѕ шифртексту */ + ak_uint8 magma_outcfb[32] = { + 0x83, 0x3c, 0x90, 0x66, 0xe2, 0xe0, 0x37, 0xdb, + 0x9c, 0x08, 0x9a, 0x1f, 0x4c, 0x64, 0x46, 0x0d, + 0x8b, 0xd3, 0x15, 0x53, 0x03, 0xd2, 0xbd, 0x24, + 0x05, 0x55, 0x07, 0x21, 0x14, 0x32, 0xc0, 0xbc + }; + ak_uint8 openssl_magma_outcfb[32] = { + 0xdb, 0x37, 0xe0, 0xe2, 0x66, 0x90, 0x3c, 0x83, + 0x0d, 0x46, 0x64, 0x4c, 0x1f, 0x9a, 0x08, 0x9c, + 0x24, 0xbd, 0xd2, 0x03, 0x53, 0x15, 0xd3, 0x8b, + 0xbc, 0xc0, 0x32, 0x14, 0x21, 0x07, 0x55, 0x05 + }; + /* значение имитовставки согласно ГОСТ Р 34.13-2015 (раздел Рђ.2.6) */ ak_uint8 imito[4] = { /* 0xbb, 0xc5, 0x20, 0x30 - первая часть выработанного блока */ @@ -792,7 +834,9 @@ int ak_bckey_context_create_magma( ak_bckey bkey ) } } + /* ------------------------------------------------------------------------ */ /* 1. Создаем контекст ключа алгоритма Магма Рё устанавливаем значение ключа */ + /* ------------------------------------------------------------------------ */ if(( error = ak_bckey_context_create_magma( &mkey )) != ak_error_ok ) { ak_error_message( error, __func__, "incorrect initialization of magma secret key context"); return ak_false; @@ -805,7 +849,9 @@ int ak_bckey_context_create_magma( ak_bckey bkey ) goto exit; } + /* ------------------------------------------------------------------------------------------- */ /* 2. Проверяем независимую обработку блоков - режим простой замены согласно ГОСТ Р 34.12-2015 */ + /* ------------------------------------------------------------------------------------------- */ if(( error = ak_bckey_context_encrypt_ecb( &mkey, oc ? openssl_magma_in : magma_in, myout, sizeof( magma_in ))) != ak_error_ok ) { ak_error_message( error, __func__ , "wrong ecb mode encryption" ); @@ -835,7 +881,9 @@ int ak_bckey_context_create_magma( ak_bckey bkey ) if( audit >= ak_log_maximum ) ak_error_message( ak_error_ok, __func__ , "the ecb mode encryption/decryption test from GOST R 34.13-2015 is Ok" ); - /* 3. Проверяем режим гаммирования согласно ГОСТ Р 34.12-2015 */ + /* ----------------------------------------------------------------- */ + /* 3. Проверяем режим гаммирования согласно ГОСТ Р 34.12-2015 */ + /* ----------------------------------------------------------------- */ if(( error = ak_bckey_context_ctr( &mkey, oc ? openssl_magma_in : magma_in, myout, sizeof( magma_in ), oc ? openssl_magma_ivctr : magma_ivctr, sizeof( magma_ivctr ))) != ak_error_ok ) { @@ -854,7 +902,7 @@ int ak_bckey_context_create_magma( ak_bckey bkey ) if(( error = ak_bckey_context_ctr( &mkey, oc ? openssl_magma_out_ctr : magma_out_ctr, myout, sizeof( magma_out_ecb ), oc ? openssl_magma_ivctr : magma_ivctr, sizeof( magma_ivctr ))) != ak_error_ok ) { - ak_error_message( error, __func__ , "wrong ecb mode decryption" ); + ak_error_message( error, __func__ , "wrong counter mode decryption" ); result = ak_false; goto exit; } @@ -868,7 +916,9 @@ int ak_bckey_context_create_magma( ak_bckey bkey ) "the counter mode encryption/decryption test from GOST R 34.13-2015 is Ok" ); - /* 4. Проверяем режим простой замены СЃ зацеплением (cbc) */ + /* ----------------------------------------------------------------- */ + /* 4. Проверяем режим простой замены СЃ зацеплением (cbc) */ + /* ----------------------------------------------------------------- */ if(( error = ak_bckey_context_encrypt_cbc( &mkey, oc ? openssl_magma_in : magma_in, myout, sizeof( magma_in ), oc ? openssl_magma_ivcbc : magma_ivcbc, sizeof( magma_ivcbc ))) != ak_error_ok ) { @@ -886,22 +936,91 @@ int ak_bckey_context_create_magma( ak_bckey bkey ) if(( error = ak_bckey_context_decrypt_cbc( &mkey, oc ? openssl_magma_out_cbc : magma_out_cbc, myout, sizeof( magma_in ), oc ? openssl_magma_ivcbc : magma_ivcbc, sizeof( magma_ivcbc ))) != ak_error_ok ) { - ak_error_message( error, __func__ , "wrong cbc mode encryption" ); + ak_error_message( error, __func__ , "wrong cbc mode decryption" ); result = ak_false; goto exit; } if( !ak_ptr_is_equal_with_log( myout, oc ? openssl_magma_in : magma_in, sizeof( magma_out_cbc ))) { ak_error_message( ak_error_not_equal_data, __func__ , - "the cbc mode encryption test from GOST R 34.13-2015 is wrong"); + "the cbc mode decryption test from GOST R 34.13-2015 is wrong"); result = ak_false; goto exit; } if( audit >= ak_log_maximum ) ak_error_message( ak_error_ok, __func__ , "the cbc mode encryption/decryption test from GOST R 34.13-2015 is Ok" ); + /* ----------------------------------------------------------------- */ + /* 5. Проверяем режим гаммирования СЃ обратной СЃРІСЏР·СЊСЋ РїРѕ выходу (ofb) */ + /* ----------------------------------------------------------------- */ + if(( error = ak_bckey_context_ofb( &mkey, oc ? openssl_magma_in : magma_in, + myout, sizeof( magma_in ), oc ? openssl_magma_ivofb : magma_ivofb, + sizeof( magma_ivofb ))) != ak_error_ok ) { + ak_error_message( error, __func__ , "wrong ofb mode encryption" ); + result = ak_false; + goto exit; + } + if( !ak_ptr_is_equal_with_log( myout, oc ? openssl_magma_outofb : + magma_outofb, sizeof( magma_outofb ))) { + ak_error_message( ak_error_not_equal_data, __func__ , + "the ofb mode encryption test from GOST R 34.13-2015 is wrong"); + result = ak_false; + goto exit; + } + if(( error = ak_bckey_context_ofb( &mkey, oc ? openssl_magma_outofb : magma_outofb, + myout, sizeof( magma_in ), oc ? openssl_magma_ivofb : magma_ivofb, + sizeof( magma_ivofb ))) != ak_error_ok ) { + ak_error_message( error, __func__ , "wrong ofb mode decryption" ); + result = ak_false; + goto exit; + } + if( !ak_ptr_is_equal_with_log( myout, oc ? openssl_magma_in : magma_in, sizeof( magma_outofb ))) { + ak_error_message( ak_error_not_equal_data, __func__ , + "the ofb mode decryption test from GOST R 34.13-2015 is wrong"); + result = ak_false; + goto exit; + } + if( audit >= ak_log_maximum ) ak_error_message( ak_error_ok, __func__ , + "the ofb mode encryption/decryption test from GOST R 34.13-2015 is Ok" ); + + + /* ----------------------------------------------------------------- */ + /* 6. Проверяем режим гаммирования СЃ обратной СЃРІСЏР·СЊСЋ РїРѕ выходу (cfb) */ + /* ----------------------------------------------------------------- */ + if(( error = ak_bckey_context_encrypt_cfb( &mkey, oc ? openssl_magma_in : magma_in, + myout, sizeof( magma_in ), oc ? openssl_magma_ivofb : magma_ivofb, /* синхропосылка РѕРґРЅР° Рё та Р¶Рµ */ + sizeof( magma_ivofb ))) != ak_error_ok ) { + ak_error_message( error, __func__ , "wrong cfb mode encryption" ); + result = ak_false; + goto exit; + } + if( !ak_ptr_is_equal_with_log( myout, oc ? openssl_magma_outcfb : + magma_outcfb, sizeof( magma_outcfb ))) { + ak_error_message( ak_error_not_equal_data, __func__ , + "the cfb mode encryption test from GOST R 34.13-2015 is wrong"); + result = ak_false; + goto exit; + } + if(( error = ak_bckey_context_decrypt_cfb( &mkey, oc ? openssl_magma_outcfb : magma_outcfb, + myout, sizeof( magma_outcfb ), oc ? openssl_magma_ivofb : magma_ivofb, + sizeof( magma_ivofb ))) != ak_error_ok ) { + ak_error_message( error, __func__ , "wrong cfb mode decryption" ); + result = ak_false; + goto exit; + } + if( !ak_ptr_is_equal_with_log( myout, oc ? openssl_magma_in : magma_in, sizeof( magma_in ))) { + ak_error_message( ak_error_not_equal_data, __func__ , + "the cfb mode decryption test from GOST R 34.13-2015 is wrong"); + result = ak_false; + goto exit; + } + if( audit >= ak_log_maximum ) ak_error_message( ak_error_ok, __func__ , + "the cfb mode encryption/decryption test from GOST R 34.13-2015 is Ok" ); + - /* 10. Тестируем режим выработки имитовставки (плоская реализация). */ + /* ----------------------------------------------------------------- */ + /* 10. Тестируем режим выработки имитовставки (плоская реализация). */ + /* ----------------------------------------------------------------- */ if(( error = ak_bckey_context_cmac( &mkey, oc ? openssl_magma_in : magma_in, sizeof( magma_in ), myout, 4 )) != ak_error_ok ) { ak_error_message( error, __func__ , "wrong cmac calculation" ); diff --git a/source/ak_sign.c b/source/ak_sign.c index dde91a19..a02950a1 100644 --- a/source/ak_sign.c +++ b/source/ak_sign.c @@ -159,7 +159,7 @@ } /* ----------------------------------------------------------------------------------------------- */ -/*! @todo Необходимо реализовать выработку контрольной СЃСѓРјРјС‹ для секретного ключа РРџ. */ +/* TODO: Необходимо реализовать выработку контрольной СЃСѓРјРјС‹ для секретного ключа РРџ. */ static int ak_signkey_context_set_icode_multiplicative( ak_skey skey ) { (void) skey; @@ -167,7 +167,7 @@ } /* ----------------------------------------------------------------------------------------------- */ -/*! @todo Необходимо реализовать проверку контрольной СЃСѓРјРјС‹ для секретного ключа РРџ. */ +/* TODO: Необходимо реализовать проверку контрольной СЃСѓРјРјС‹ для секретного ключа РРџ. */ static bool_t ak_signkey_context_check_icode_multiplicative( ak_skey skey ) { (void) skey; diff --git a/source/ak_tools.c b/source/ak_tools.c index 8647019c..3294f042 100644 --- a/source/ak_tools.c +++ b/source/ak_tools.c @@ -785,6 +785,36 @@ #endif } +/* ----------------------------------------------------------------------------------------------- */ + ssize_t ak_file_printf( ak_file outfile, const char *format, ... ) +{ + va_list args; + ssize_t result = 0; + va_start( args, format ); + + /* формируем строку (дублируем РєРѕРґ функции ak_snprintf) */ + #ifdef _MSC_VER + #if _MSC_VER > 1310 + _vsnprintf_s( ak_ptr_to_hexstr_static_buffer, + sizeof( ak_ptr_to_hexstr_static_buffer ), + sizeof( ak_ptr_to_hexstr_static_buffer ), format, args ); + #else + _vsnprintf( ak_ptr_to_hexstr_static_buffer, + sizeof( ak_ptr_to_hexstr_static_buffer ), format, args ); + #endif + #else + vsnprintf( ak_ptr_to_hexstr_static_buffer, + sizeof( ak_ptr_to_hexstr_static_buffer ), format, args ); + #endif + va_end( args ); + + /* выводим ее РІ файл как последовательность байт */ + result = ak_file_write( outfile, + ak_ptr_to_hexstr_static_buffer, + strlen( ak_ptr_to_hexstr_static_buffer )); + return result; +} + /* ----------------------------------------------------------------------------------------------- */ /*! \hidecallgraph \hidecallergraph */ diff --git a/source/ak_tools.h b/source/ak_tools.h index 65c589b5..be57844c 100644 --- a/source/ak_tools.h +++ b/source/ak_tools.h @@ -46,14 +46,14 @@ int ak_file_open_to_read( ak_file , const char * ); /*! \brief Функция создает файл СЃ правами РЅР° запись. */ int ak_file_create_to_write( ak_file , const char * ); -/*! \brief Функция открывает заданный файл СЃ правами запись (используется для дополнения существующих данных). */ - int ak_file_open_to_append( ak_file , const char * ); /*! \brief Функция закрывает файл СЃ заданным дескриптором. */ int ak_file_close( ak_file ); /*! \brief Функция считывает заданное количество байт РёР· файла. */ ssize_t ak_file_read( ak_file , ak_pointer , size_t ); /*! \brief Функция записывает заданное количество байт РІ файл. */ ssize_t ak_file_write( ak_file , ak_const_pointer , size_t ); +/*! \brief Функция записывает РІ файл строку символов. */ + ssize_t ak_file_printf( ak_file , const char * , ... ); /* ----------------------------------------------------------------------------------------------- */ /*! \brief Функция устанавливает значение опции СЃ заданным именем. */ diff --git a/tests/test-asn1-build.c b/tests/test-asn1-build.c index 0d931834..811ea725 100644 --- a/tests/test-asn1-build.c +++ b/tests/test-asn1-build.c @@ -141,6 +141,8 @@ } else printf(" Wrong\n"); ak_hash_context_destroy( &ctx ); +#else + result = EXIT_SUCCESS; #endif /* уничтожаем дерево Рё выходим */ diff --git a/tests/test-bckey04.c b/tests/test-bckey04.c index a1e8b316..115fa109 100644 --- a/tests/test-bckey04.c +++ b/tests/test-bckey04.c @@ -23,7 +23,24 @@ typedef int ( efunction )( ak_bckey , ak_pointer , ak_pointer , size_t , ak_pointer , size_t ); void test( char *, efunction *, ak_bckey ); + int ecb_fixed( ak_bckey bkey, ak_pointer in, ak_pointer out, + size_t size, ak_pointer iv, size_t ivsize ) { + (void) iv; + (void) ivsize; + return ak_bckey_context_encrypt_ecb( bkey, in, out, size ); + } + int acpkm_fixed( ak_bckey bkey, ak_pointer in, ak_pointer out, + size_t size, ak_pointer iv, size_t ivsize ) { + return ak_bckey_context_ctr_acpkm( bkey, in, out, size, 8192, iv, ivsize ); + /* выполнено равенство 8192 / 16 = 512, + РіРґРµ 16 длина блока, 512 = acpkm_section_kuznechik_block_count + это количество блоков для РѕРґРЅРѕРіРѕ ключа */ + } +/* -------------------------------------------------------------------------------------- */ + + +/* -------------------------------------------------------------------------------------- */ int main( void ) { struct bckey ctx; @@ -33,12 +50,14 @@ /* статический объект существует, РЅРѕ РѕРЅ требует инициализации */ printf("key create: %d\n", ak_bckey_context_create_kuznechik( &ctx )); - printf("key set value: %d\n", ak_bckey_context_set_key( &ctx, key, sizeof( key ))); + printf("key set value: %d\n\n", ak_bckey_context_set_key( &ctx, key, sizeof( key ))); - test( "CFB", ak_bckey_context_cfb, &ctx ); + test( "ECB", ecb_fixed, &ctx ); + test( "CFB", ak_bckey_context_encrypt_cfb, &ctx ); test( "OFB", ak_bckey_context_ofb, &ctx ); test( "CBC", ak_bckey_context_encrypt_cbc, &ctx ); test( "CTR", ak_bckey_context_ctr, &ctx ); + test( "ACPKM", acpkm_fixed, &ctx ); ak_bckey_context_destroy( &ctx ); return ak_libakrypt_destroy(); @@ -53,6 +72,7 @@ size_t size; double iter = 0, avg = 0; + printf("%s\t[16MB ", STR ); for( i = 16; i < 129; i += 8 ) { data = malloc( size = ( size_t ) i*1024*1024 ); memset( data, (ak_uint8)i+1, size ); @@ -60,16 +80,18 @@ timea = clock(); fun( ctx, data, data, size, iv, sizeof( iv )); timea = clock() - timea; - printf(" %3uMB: %s time: %fs, per 1MB = %fs, speed = %f MBs\n", (unsigned int)i, STR, +/* детальный вывод + printf(" %3uMB: %s time: %fs, per 1MB = %fs, speed = %3f MBs\n", (unsigned int)i, STR, (double) timea / (double) CLOCKS_PER_SEC, (double) timea / ( (double) CLOCKS_PER_SEC*i ), - (double) CLOCKS_PER_SEC*i / (double) timea ); + (double) CLOCKS_PER_SEC*i / (double) timea ); */ + printf("."); fflush(stdout); if( i > 16 ) { iter += 1; avg += (double) CLOCKS_PER_SEC*i / (double) timea; } free( data ); } - printf("average memory %s speed: %f MByte/sec\n\n", STR, avg/iter ); + printf(" 128MB] average memory speed: %12f MByte/sec\n", avg/iter ); } diff --git a/tests/test-bckey05-cfb.c b/tests/test-bckey05-cfb.c index 4109170a..1d6f7d0c 100644 --- a/tests/test-bckey05-cfb.c +++ b/tests/test-bckey05-cfb.c @@ -143,7 +143,7 @@ /* зашифровываем Рё расшифровываем всего четыре блока данных */ printf("Kuznechik\n"); - ak_bckey_context_cfb( &bkey, oc ? openssl_in : in, buf, sizeof( in ), + ak_bckey_context_encrypt_cfb( &bkey, oc ? openssl_in : in, buf, sizeof( in ), oc ? openssl_ivcfb : ivcfb, 32 ); printf("encrypted:\n"); for( i = 0; i < 4; i++ ) { @@ -165,7 +165,7 @@ /* зашифровываем Рё расшифровываем всего четыре блока данных */ printf("Magma\n"); - ak_bckey_context_cfb( &mkey, oc ? openssl_magma_in : magma_in, buf, sizeof( magma_in ), + ak_bckey_context_encrypt_cfb( &mkey, oc ? openssl_magma_in : magma_in, buf, sizeof( magma_in ), oc ? openssl_magma_ivcfb : magma_ivcfb, sizeof( magma_ivcfb )); printf("encrypted:\n"); for( i = 0; i < 4; i++ ) { -- GitLab