УДК 519.719.2
С. В. Дорохин1'2, С. С. Качкое1'3, А. А. Сидоренко1'3
1 Московский физико-технический институт (государственный университет)
2 АО «ПКК Миландр» 3АО «Интел»
Реализация блочного шифра «Кузнечик» с использованием векторных инструкций
Целыо данной работы является создание оптимизированной программной реализации блочного шифра ГОСТ Р 34.12 2015. известного как «Кузнечик». В ходе исследования был проведён анализ возможных средств улучшения скорости работы шифра. Основное внимание уделено использованию SIMD (Sirigle Instruction Múltiplo Data) инструкций и учёту строения Execution Engine процессоров Intel®Coro™. Отличительной особенностью статьи является то. что в ней представлены измерения скорости зашифрования и расшифрования в режимах ECB. СВС. CFB. OFB на процессорах четырёх различных поколений, в открытом доступе выложен исходный код высокоскоростной реализации. Предлагается использование 256-битных регистров yriirii для ускорения зашифрования и расшифрования в режиме ECB. расшифрования в режиме CFB.
Ключевые слова: ГОСТ Р 34.12 2015. высокоскоростная реализация. FSX-преобразование. блочный шифр. SSE. AVX.
S. V. Dorokhin1'2, S. S. Kachkov1'3, A. A. Sidorenko1'3
1 Moscow Institute of Physics and Technology (State University) 2JSC «Milandr» 3JSC «Intel»
Implementation of «Kuznyechik» cipher using vector
instructions
This paper is concentrated on the highly optimized implementation of block cipher COST R 34.12 2015 also known as Knznyechik. A comparative analysis of possible improvements is presented, with the SIMD (Single Instruction Multiple Data) instructions in focus. The publicly available information of Intel®Coro™ Execution Engine is taken into consideration. The key feature of the paper is that the cutting edge open source implementation is presented. The above implementation allows us to compare four modes of operation such as ECB. CBC. CFB and OFB. The results are given for four modern generations of Intel®Coro™ processor line. We also suggest using 256-bit yriirn registers and AVX2 instruction set to boost ECB mode encryption & decryption and CFB mode decryption.
Key words: COST R 34.12 2015. high-speed implementation. FSX-transforrii. block cipher. SSE. AVX.
1. Введение
«Кузнечик» представляет собой блочный шифр с размером блока 128 бит. Обозначим множество всевозможных двоичных строк длины в как У8. Алгоритм зашифрования сводится к последовательному применению следующих операций:
© Дорохип С. В.. Качков С. С., Сидоренко А. А.. 2018
© Федеральное государственное автономное образовательное учреждение высшего образования «Московский физико-техпический институт (государственный университет)». 2018
• Побитовая операция сложения по модулю 2: X[к](а) = к ® а, где к, а € Ут-
• Биективное нелинейное преобразование: Б (а) = Б(а15||...||а0) = п(а1б)||...||п(ао), где
аг € У8, символ ом || обозначена операция конкатенации, а п : У8 —У У8 — некоторая известная подстановка.
• Линейное преобразование: Ь : У128 — У128-
С учётом этих обозначений функции зашифрования Е(а) и расшифрования В(а), а € Ут-могут быть представлены в следующем виде:
Еиъ...,к10 (а) = X [кю ]ЬБХ [кд]...ЬБХ к]ЬБХ [кх](а): Вкъ... кю (а) = X [к1]Б-1Ь-1Х [к2]...Б-1Ь-1Х [к9]Б-1Ь-1Х [кю](а),
(1) (2)
к1 к1о
вычисляются также с помощью Х-, Б-, и Ь-преобразовапий и не оказывают существенного влияния на скорость работы шифра, поэтому в рамках статьи алгоритм развертывания ключа не обсуждается. Здесь и далее раундовые ключи предполагаются уже вычисленны-
Ь
РСЛОС (регистра сдвига с линейной обратной связью), показанного на рис. 1. Под умножением подразумевается умножение над полем Галуа по модулю неприводимого многочлена р(х) = х8 + х7 + х6 + х + 1, под аг подразумеваются байты одного блока.
Рис. 1. РСЛОС, реализующий ¿-преобразование
Такое решение является предпочтительным при аппаратной реализации шифра, однако
Ь
форме. Результат работы одного такта РСЛОС можно записать в виде
{ Сп-1 Сп-2 Сп-3 . . С2 С1 со \ (ап-Л
ап-2 1 о 0 . 0 0 0 ап-2
ап-3 = о 1 0 . 0 0 0 ап-3
а\ о о 0 . 1 0 0 а1
V а0
\ 0
о
о
о 1 о у
ао
где а* — новые компоненты вектора. Результат работы после к тактов:
( Сп-1 Сп-2 Сп-3 . . С2 С1 Со к / ап-А
ап-2 1 0 0 . 0 0 0 ап-2
ап-3 = 0 1 0 . 0 0 0 ап-3
а*1 0 0 0 . 1 0 0 а1
V а0 /
о
1 0 /
\ ао /
Применение L-преобразования в такой форме существенно быстрее, чем при моделировании РСЛОС. Однако профилирование программы при помощи утилиты callgrind показало, что на L-преобразование приходится приблизительно 75% времени исполнения программы.
2. Обзор существующих методов
Так как большую часть работы программы занимает L-преобразование, оптимизация операций зашифрования и расшифрования сводится к оптимизации умножения вектора на матрицу в конечном поле. Для ускорения этой операции общепринятым является использование таблиц предвычислений (LUT, Lookup Table).
2.1. Построение LUT
Особенностям построения таких таблиц уделено должное внимание в [2|. Для полноты изложения кратко приведем рассуждения из указанной статьи. Вычисляется матрица уравнения (3) для случая k = 16. Определим для г-го столбца полученной матрицы отображение Li(b) : V8 ^ Vi28 такое, что
Li(b) = Ci,i5 • b II Ci,i4 • b II ... Il Ci,0 • b, b G V8•
L
L(a) = Li5(ai5) Ф Li4(ai4) Ф ... Ф Li(ai) Ф Lo(ao).
LUT имеет размер 16x256, каждый элемент таблицы является блоком данных из 16 байт и строится по следующему принципу: LUT^jj] есть результат покомпонентого умножения j-ro байта исходного вектора на г-й столбец матрицы L-преобразования. Таким образом, для осуществления LS'-преобразования над блоком необходимо произвести сложения по модулю 2 всех 16 блоков из LUT.
2.2. Объединение S и L-преобразования
Определим теперь преобразование Li : V8 ^ Vi28, г = 0,..., 15 как
Li(b) = Ci,i5 • n(b)IIci,i4 • n(b)II... IIci,o • n(b),b G V8.
Тогда композицию L- и ^-преобразований можно представить в виде
LS(a) = L'i5(ai5) Ф L'i4(ai4) Ф ... Ф L0(ao),
то есть строится таблица предвы числений, по структуре аналогичная предыдущему пунк-
LS
не составляет труда реализовать все три базовые преобразования из (1) как одно LSX-преобразование (cnc_ls_tablc это LUT):
Листинг 5.1. LSX-прообразованио с использованном LUT
void Grasshopper :: ApplvLSX( Block& data, const Bloek& келг) {
ApplvX(data, key); Block tmp{ } ;
for (sizc_t i 0; i < block_sizc; i++)
ApplvX(tmp , cnc_ls_tablc f i ] f data fill); data tmp;
}
2.3. LUT для L-1S-1
Особенности построения LUT для обратного преобразования связаны с тем, что в уравнении (2) преобразование L применяется перед S. Решение этой проблемы может быть найдено в [2|. А именно, преобразуем это уравнение:
Dklt...,kio (a) = X [h]S-1L-1X [k2]...S-1L-1X [kg ]S-1L-1X [kw](a) =
= X [h]S-1L-1X [k2]...S-1L-1X [kg]S-1 L-1X [kio]S-1S(a). (4)
L
L-1X[ki]S-1(a) = L-1(S-1 (a) ® ki) = L-1(S-1(a)) ® L-1(ki) = L-1S-1(a) ® L-1(ki) =
= X [L-1(ki)]L-1 S-1(a). (5)
Применяя (5) к (4), получим
Dki,..., kw (a) = X [k1]S-1L-1X [k2]...S-1L-1X [kg ]S-1L-1X [kw]S-1S(a) = = X[k1]S-1(L-1X[k2]S-1)... (L-1X[kw]S-1)S(a) =
= X[k1 ]S-1(X[L-1(k2]L-1S-1)... (X[L-1(kw]L-1S-1)S(a). (6)
Таким образом, операция зашифрования также может быть сведена к объединенному L-1S-1 X-преобразованию, реализованному через LUT (в предположении, что значения L-1(ki) заданы). От операции зашифрования операция расшифрования отличается применением дополнительно подстановок S и S-1, поэтому расшифрование в режимах ЕСВ и СВС будет заведомо медленнее.
2.4. Использование векторных инструкций
Для дальнейшей оптимизации можно использовать 128-битные xmm регистры, размер которых совпадает с размером блока шифра. Однако дисассемблирование модифицированной таким образом программы показывает, что цикл, отвечающий за применение склеен-LSX
Листинг 5.2. Часть результата дизассемблирования цикла LSX-преобразования movzbl 0x3(%rsi), %еах
shl $0x4, %гах
xorps 0x3000(%rdx,%rax , 1) , %xmm0
Адрес A в памяти вычисляется по формуле A = B +1 * S + D, где B — базовое смещение, I _ индекс, S — масштаб (scale), D — смещение (displacement). В приведённом коде rdx
BD LUT 16-байтовые векторы хранятся друг за другом, приходится домножать смещение на
D
используя S, так как S Е {2, 4, 8} (см. [5]). Ещё одна оптимизация заключается в пред-вычислении смещений в начале цикла с тем, чтобы не исполнять в дальнейшем операцию
D
смещений также используются регистры xmm. Из блока данных посредством операций II и II НЕ с помощью маски выделяются отдельно чётные и нечётные байты. К полученным после применения II и II НЕ блокам применяются операции битового сдвига на 4 вправо (srli) и влево (slli) соответственно (см. рис. 2) с тем, чтобы считывать двубайтные блоки с отступом в 4 байта от начала (то есть кратные шестнадцати значения).
В [1| приведено описание этой модификации. В частности, указано, что следует учитывать особенности планировшика. В [4| упоминается, что, к примеру, микроархитектура Intel Sandy Bridge имеет в своём распоряжении 2 исполнительных устройства для вычисления
адреса (AGU address generation unit), а также 3 ALU (arithmetic and logic unit), способные производить операции над векторными регистрами. Чтобы помочь планировщику выполнять загрузки блока из таблицы и суммирование но модулю 2 с результатом параллельно, можно использовать чередование регистров в этих командах (подробное описание использованных функций можно найти в [6]):
Листинг 5.3. LS-иреобразование с использованном чередования регистров _ml28i veel = _mm_load_sil28(reinterpret castcconst__ml28i*>
(tablo- __ml28i (tablc- mm vec2 mm _ext.ract._epil6 (t.mp2 . 0)-0x0000 ) ) : = mm load sil28(reinterpret castcconst ml28i*> _ext.ract._epil6 (t.mpl . 0)-0xl000 )") ;
vocl = vec2 = mm mm xor SÏ128 ( xor SÏ128 ( [ veel [ vec2 , Cast.Block , Cast.Block ( tab! ( tab! mm mm extract, extract. _epil6 (t.mp2 . _epil6 (t.mpl . 1)—0x2000)): 1)—0x3000)):
veel = vec2 = mm mm xor SÏ128 ( xor SÏ128 ( [ veel [ vec2 , Cast.Block , Cast.Block ( tab! ( tab] mm mm extract, extract. _epil6 (t.mp2 . _epil6 (t.mpl . 2)—0x4000)): 2)—0x5000)):
veel = vec2 = data = mm mm mm xor SÏ128 ( xor SÏ128 ( xor si 128 ( [ veel [ vec2 [ veel , Cast.Block , Cast.Block . vec2 ) : ( tab] ( tab] mm mm extract, extract. _epil6 (t.mp2 . _epil6 (t.mpl . 7) —OxEOOO ) ) : 7) —OxFOOO ) ) :
ao a2 a4 a6 as aio ai2 a14
sl i
à i
ao 0x00 a2 0x00 a4 0x00 a6 0x00 a8 0x00 aio 0x00 a12 0x00 a 14 0x00
ao al a2 a3 a4 a5 a6 a7 a8 a9 a10 all a12 a13 a 14 a15 -> NAND
0x00 OxFF 0x00 OxFF 0x00 OxFF 0x00 OxFF 0x00 OxFF 0x00 OxFF 0x00 OxFF 0x00 OxFF
ao a2 a3 a4 a5 a6 a7 a8 a9 aio all a12 a13 a 14 a15 AND
0x00 al 0x00 a3 0x00 a5 0x00 a7 0x00 a9 0x00 ail 0x00 a13 0x00 a15
srli
ai аз a5 a7 a9 all a13 a15
Рис. 2. Предвычисление смещений
Предвычиеление инструкций, которое было описано на рис. 2:
Листинг 5.4. Результат дизассемблирования предвычисления смещений movdqa (% г s i), %xmml movdqa %mmil,%xmm0 p s г 1 q $ 0x4,xi ni n( I psllq $0x4,%xmml movdqa 0x1876(%rip),%xmm2 pand %mmi2,%xmm0 pextrw $0x0 ,%xmm0,%eax pand %mim2,%xmml 0xl000(%rdx,%rax ,1) ,%xmm2
Эти предварительные вычисления позволяют вычислять хог за две операции вместо трех, что особенно важно, учитывая, что каждое применение Ьб'Х-преобразовапия представляет собой 16 итераций:
Листинг 5.5. Операция хог для случая с прсдвычислониом
рехту $0x0 ,%хшт1,%еах
х о г р н (%гс1х ,%гах , 1) ,%хтт2
рехту $0x1 ,%хтт1,%еах
х о г р н 0x2000 (%Т(\Х ,%гах , 1) , с/схшт2
рехту $0x1 ,%хтт0,%еах
х о г р н 0x3000 (%гс1х ,%гах ,1) ,%хшт2
В статье [1] авторы пришли к заключению, что скорость работы «Кузнечика» в реализации с использованием xmm регистров достигла своего предела. Хороший сравнительный анализ много численных вариантов реализации шифра с использованием LUT различных размеров дан в [3]. Из этого анализа следует, что наибольшая скорость работы достигается именно с использованием xmm регистров и LUT размером 64 kB, описанной в этой статье. Примечательно, что реализация с использованием 256-битных регистров ymm и тем же LUT в 64 кБ по результатам этого анализа существенно проигрывает реализации на xmm регистрах.
3. Использование AVX2 в режимах ECB и CFB
II все-таки в отдельных случаях можно получить ускорение за счет использования больших по размеру регистров. Мы предлагаем обрабатывать сразу два блока данных в некоторых режимах шифрования, используя расширенные до 256 бит векторные регистры (расширение набора инструкций AVX2, поддерживаемое с Intel Haswell и AMD Excavator). Это возможно в тех случаях, когда шифрование (или расшифрование) текущего блока возможно производить независимо от предыдущего. В этой работе были реализованы следующие режимы работы шифра:
• ECB (Electronic Codebook)
• СВС (Cipher Block Chaining)
• CFB (Cipher Feedback)
• OFB (Output Feedback)
Данная оптимизация была осуществлена для шифрования и расшифрования в режиме ECB и для расшифрования в режиме CFB. Попытка использовать ymm регистры непосредственно внутри LSX-преобразовапия не приводит к желаемому ускорению, так как загрузка 128-битных блоков в половинки регистра ymm занимает слишком много времени. Поэтому успешно использовать AVX2 для всех режимов не удается. Предлагается следующая модификация для режима ECB: в половины 256-битного ymm регистра загружается по блоку открытого текста, применяется объединённое LSX-преобразовапие, аналогичное описанному в разделе 2.4. Различие заключается в том, что одним применением LSX-преобразования обрабатывается сразу два блока. Используются аналогичные предвычисления смещений с 256-битной маской (см. рис. 3), основанные на операциях II и НЕ II и битовых сдвигах на четыре бита.
Синим цветом показаны байты, относящиеся к смещению второго блока, srli и slli обозначают побитовый сдвиг на 4 бита вправо и влево соответственно. Два ymm регистра инициализируются в начале цикла и накапливают результат исполнения хог один для чётных, другой для нечётных байт. Ещё два ymm регистра необходимы, чтобы загружать
в них данные на каждой итерации, выполнять хог с накапливающими регистрами и сохранять в эти регистры промежуточный результат:
Листинг 5.6. Использование AVX2 в режиме ECB
data _nini256_insortil28 _si256 (data . table—_nini256_oxtract_opil6(tnip2
data _nini256_insortil28 _si256 (data . table—_nini256_oxtract_opil6(tnip2
vec2 _nini256_insortil28 _si256 (voc2 . table—_nini256_oxtract_opil6 (tnip2
vec2 _nini256_insortil28 _si256 (voc2 . table—_nini256_oxtract_opil6 (tnip2
vecl _nini256_insortil28 _si256 (vocl . table—_nini256_oxtract_opil6 (tmpl
vecl _nini256_insortil28 _si256 (vocl . table—_nini256_oxtract_opil6 (tmpl
vec3 _nini256_insortil28 _si256 (voc3 . table—_nini256_oxtract_opil6 (tmpl
vec3 _nini256_insortil28 _si256 (voc3 . table—_nini256_oxtract_opil6 (tmpl
data _nini256_xor_si256 (data . vec2): vecl _nini256_xor_si256 ( vecl . vec3 ):
В данном случае data и ved выступают в качестве накапливающих регистров для хог четных и нечетных байт соответсвенно. Такая схема позволяет учитывать особенности планировщика так же, как и в пункте 2.4. Однако Ьб'Х-преобразование ускорится заведомо меньше, чем в два раза, из-за расходов на загрузку блоков в ymm регистры и из-за охрани ченного количества AGU (не более 3 штук). Аналогичным образом ускоряется расшифрование. Такую же идею можно применить для расшифрования в режиме CFB.
Ы < A »4 • • |asj la KOI Iai41 1 1Ш - «4 я • « * lad laia| 1
ГдПЛ 4
а0 |охоо аг oxooj a 4 J o*oo a6 0x00 aa oimjajo oxoo 1 a j 210*00 J a jo* 001 ao OxOO a, OxOO a4 foxoo a6 0*00 a8 OxOO а10|о*оо a ^f0*00 Ia 1410x00i
а0 a, -.1 a4l a5 as a7 ae a9 a10 a11[a12|a13|a14|alsj a0 3! a: a3 a4[ a5 a6 a, a8 a9 aiolaii а1г|а1з|а14|а15|—►NAND
ОхОО J OxFF OxOO OxFF 0*00 jo*. Ff OxOO OxFF 0x00 Û*FF OAM OxFF ! OxOO Ox FF OxOO 0* FF ; 0x00 OxFF 0x00 OxFF oxoojOxFF 0x00 OKFF OxOO OxFF DxOO 0*FF OxOO OxFF 0x00 OxFF-1
a0|ai a* a3¡ a4| a5 as aB a9 ai0 au|a12|a13|a14¡a15; a0 a, a, a3 a4 1 a5 a6 a8 a9 aiolan а12|а1з|а14|ах5Н>- AND
oxoof OxOO аз oxoo I a 5 0x00 a, □ TOO а11|охоо|а1з|охоо[а15|охоо a, 0*00 a3 oxoo[ a5 OxOO a, 0x00 as ertolan
[ l*i| IM ТУ" I a»l Kil Täüi ы I |at| la3| ; a5| | a7 ! | a9| jan| Jg¡¡[ ТаТП
Рнс. 3. Предвычнсленне смещений для модификации с AVX2
4. Сравнительный анализ
В заключение приведем результаты для различных степеней оптимизации и различных процессоров (табл. 1, 2). Под baseline подразумевается реализация с ¿-преобразованием через сдвиговый регистр; with LUT — реализация, в которой L-преобразование выполнено
0)-0х0000, 0):
8) —0x0000 . 1):
1) —0x2000 . 0):
9) —0x2000 . 1):
0)-0х1000, 0):
8) —0x1000 . 1):
1)-0х3000, 0):
9) —0x3000 . 1):
при помощи LUT, но без использования xmm-рсгистров; LUT, хог аналогично, но пред-вычпсляется уже LS-преобразовапие, LSX объединено в одну функцию, для хог используется векторная инструкция; offset использование xmm регистров и предвычисления смещений; AVX2 описанная в пункте 3 модификация.
Т а б л и ц а 1
Скорость шифрования в режиме ECB, Мб/с
i3-4030u i5-52üüu i5-7200u i5-8250u
Baseline 6 8,8 10,2 11,4
With LUT 53 77 99 107
LUT, хог 69 99 131 139
Offset 79 113 135 142
AVX2 84 121 150 159
Т а б л и ц а 2
Скорость расшифрования в режиме CFB, Мб/с
i3-4030u i5-5200u i5-7200u i5-8250u
Baseline 5,2 8,7 10,2 9,4
With LUT 50 73 94 103
LUT, хог 73 105 131 145
Offset 80 118 135 150
AVX2 82 120 145 159
Более того, выбор компилятора тоже немаловажен. В работе [3] сравнивались результаты, полученные при комплияции с помощью Visual С++, Intel С++ и gee. Нами было установлено, что наибольшая скорость достигается при компиляции clang (см. рис. 4).
ECB СВС CFB OFB
Рис. 4. Сравнение скорости работы (МБ/с) при компиляции clang и gcc (13-4030)
5. Заключение
В данной статье подробно описаны известные на текущий момент методы оптимизации программной реализации блочного шифра «Кузнечик». Предложена модификация реализации для режимов ECB и OFB, использующая расширение набора инструкций AVX2. Данная модификация дает заметный прирост. Дальнейшее ускорение скорости работы шифра напрямую связано только с увеличением производительности процессоров и не может быть достигнуто программными методами (за исключением распараллеливания). Методы, описанные в этой статье и в [3], представляют собой программные модификации,
ведущие к максимальному приросту скорости зашифрования и расшифрования. Исходный код реализации доступен но ссылке [7]
Литература
1. Алексеев Е.К., Попов В.О.. Прохоров А.С.. Смышляев С.В., Comma Л.А. Об эксплуатационных качествах одного перспективного блочного шифра тина LSX /7 Математические вопросы криитографии. 2015. Т. 6, вып. 2. С. 6 17.
2. Бородин, М.А., Рыбкин А.С. Высокоскоростные ирохраммныс реализации блочнох'о шифра Кузнечик /7 Проблемы информационной безопасности. Компьютерные системы. 2014. Вып. 3. С. 67 73.
3. Рыбкин А.С. О программной реализации алгоритма Кузнечик на процессорах Intel /7 Математические вопросы криитографии. 2018. Т. 9, вып. 2. С. 117 127.
4. Intel@64 and IA-32 Architectures Optimization Reference Manual. Intel Corporation, 2016.
5. Intel@64 and IA-32 Architectures Software Developer's Manual. Intel Corporation, 2016.
6. Intel@Intrinsics Guide. URL: https://soft\varc.intcl.com/sitcs/landingpagc/IntrinsicsGuidc/
7. Авторская реализация. URL: https://github.com/svdprima/Grasshoppcr
References
1. Alekseev E.K.. Popov V.O., Prokhorov A.S.. Smyshlyaev S.V., Sonina L.A. On the performance of one perspective LSX-based block cipher. Mathematical Aspects of Cryptography. 2015. V. 6, I. 2. P. 6 17.
2. Borodin M.A., Rybkin A.S. High-Speed Software Implementation of Kuznyetehik block cipher. Information Security Problems. Computer Systems. 2014. N 3. P. 67-73.
3. Rybkin A.S. On software implementation of Kuznyechik on Intel CPUs. Mathematical Aspects of Cryptography. 2018. V. 9, I. 1. P. 117 127.
4. Intel@64 and IA-32 Architectures Optimization Reference Manual. Intel Corporation, 2016.
5. Intel@64 and IA-32 Architectures Software Developer's Manual. Intel Corporation, 2016.
6. Intel@Intrinsies Guide. URL: https://softwaxcintcl.com/sitcs/landingpagc/IntrinsicsGuidc/
7. Authors' code repository. URL: https://github.com/svdprima/Grasshopper
Поступила в редакцию 06.12.2018