Project

General

Profile

gost_2_1.asm

sprin, 09/10/2013 12:39 AM

 
1
; 2013 год
2
; Шрифт: Lucida Console (10)
3

    
4
// Реализация алгоритма шифрования ГОСТ 28147-89 для MC P1.
5
// Режим шифрования данных - простая замена.
6

    
7
// Особенности:
8
// * входной буффер должен быть кратным 8 байтам
9
// * параметр "blocks_count" указывает количество блоков размером по 8 байт во входном буффере
10

    
11

    
12
// void mc_gost_encdec(int direction, unsigned int *key, unsigned int *buf, int blocks_count);
13

    
14

    
15

    
16
.alias	SP	39	/* Стек. (в алгоритме старшие 4 байта не сохраняются!)*/
17
.alias	DEC	0	/* Запрошена операция шифрования или расшифровывания */
18
.alias	AA	1	/* Ai */
19
.alias	BB	2	/* Bi */
20
.alias	KI	3	/* Ki */
21
.alias	BLK	4	/* Текущий номер блока */
22
.alias	IDX	5	/* Номер раунда */
23
.alias	SB	32	/* Sblock */
24

    
25

    
26
.global mc_gost_encdec
27

    
28
.data
29

    
30
.align 8
31

    
32
Sblock:
33
    /* Определяем тестовые S-блоки в соответствии с ГОСТ Р 34.11-94 (ГОСТ Р 34.11-94 устарел. С 1 января 2013 года надо использвать ГОСТ Р 34.11-2012)*/
34
    .quad 0x35F7C1B6E08D29A4
35
    .quad 0x95701832AFD6C4BE
36
    .quad 0xB9067CFE243AD185
37
    .quad 0x352BC64EF9801AD7
38
    .quad 0x2B30E9A48DF517B6
39
    .quad 0xEFC95863D1270AB4
40
    .quad 0xC2867EA095F314BD
41
    .quad 0xC8B6E3294A750DF1
42

    
43

    
44
.bss
45

    
46
.align 8
47

    
48
Keys:
49
    .long  0
50

    
51
.align 8
52

    
53
BufPtr:
54
    .long  0
55

    
56

    
57
.text
58

    
59
//====================================
60
    .alias gost_encdec.dec #SP,4	/* operation */
61
    .alias gost_encdec.key #SP,8	/* pointer keys */
62
    .alias gost_encdec.buf #SP,12	/* pointer buf */
63
    .alias gost_encdec.blk #SP,16	/* block count */
64
    .alias gost_encdec.old_r1 #SP,-8	; Из-за особенностей 'SETx' приходится брать все 8 байт
65
    .alias gost_encdec.old_r2 #SP,-16
66
    .alias gost_encdec.old_r3 #SP,-24
67
    .alias gost_encdec.old_r4 #SP,-32
68
    .alias gost_encdec.old_r5 #SP,-40
69
    .alias gost_encdec.old_r6 #SP,-48
70
    .alias gost_encdec.old_r7 #SP,-56
71

    
72
    .alias gost_encdec.stackb 56	; Количество байт под стек. #BP(#38) не используется.
73
    .alias gost_encdec.old_r1.newSP #SP,48
74
    .alias gost_encdec.old_r2.newSP #SP,40
75
    .alias gost_encdec.old_r3.newSP #SP,32
76
    .alias gost_encdec.old_r4.newSP #SP,24
77
    .alias gost_encdec.old_r5.newSP #SP,16
78
    .alias gost_encdec.old_r6.newSP #SP,8
79
    .alias gost_encdec.old_r7.newSP #SP
80

    
81
    .alias gost_encdec.RET.newSP #SP, gost_encdec.stackb	; Возврат из функции
82

    
83

    
84
mc_gost_encdec:
85
gost_encdec:
86

    
87
 SP13 :=        getq	#SP	; выделяем наш кадр стека. Часть 1 из 3
88

    
89
 dec :=         rdl	gost_encdec.dec		/* operation */
90
 key :=         rdl	gost_encdec.key		/* key */
91
 buf :=         rdl	gost_encdec.buf		/* buf */
92
 blk :=         rdl	gost_encdec.blk		/* block count */
93

    
94
	; Получение значений регистров
95
 old1 :=        getq	#DEC
96
 old2 :=        getq	#AA
97
 old3 :=        getq	#BB
98
 old4 :=        getq	#KI
99
 old5 :=        getq	#BLK
100
 old6 :=        getq	#IDX
101
 old7 :=        getq	#SB
102

    
103
 SP23 :=        subl	@SP13, gost_encdec.stackb	; выделяем наш кадр стека. Часть 2 из 3
104

    
105
                setl	#DEC, @dec
106
                wrl	@key, Keys
107
                setl	#BLK, @blk
108
                wrl	@buf, BufPtr
109

    
110
                setl	#SB, Sblock
111

    
112
                setl	#SP, @SP23	; выделяем наш кадр стека. Часть 3 из 3
113

    
114
	; Сохранение старых значений регистров в стеке
115
                wrq	@old1, gost_encdec.old_r1
116
                wrq	@old2, gost_encdec.old_r2
117
                wrq	@old3, gost_encdec.old_r3
118
                wrq	@old4, gost_encdec.old_r4
119
                wrq	@old5, gost_encdec.old_r5
120
                wrq	@old6, gost_encdec.old_r6
121
                wrq	@old7, gost_encdec.old_r7
122

    
123
                jmp	gost.next_block
124

    
125
complete
126

    
127
//====================================
128

    
129
gost.next_block:
130

    
131
 r1 :=          getl	#BLK
132
 r2 :=          subl	@r1, 1
133
                setl	#BLK, @r2
134

    
135
                je	@r1, gost.return
136
                jne	@r1, gost.fetch_block
137

    
138
complete
139

    
140
//====================================
141

    
142
gost.fetch_block:
143

    
144
 r1 :=          getl	#DEC
145

    
146
 r2 :=          rdl	BufPtr		/* указатель на буффер */
147
 r3 :=          addl	@r2, 4
148

    
149
 r4 :=          rdl	@r2		/* считывает два первых значения */
150
 r5 :=          rdl	@r3
151

    
152
                setl	#AA, @r4
153
                setl	#BB, @r5
154

    
155
                je	@r1, gost_enc.prologue
156
                jne	@r1, gost_dec.prologue
157

    
158
complete
159

    
160
//====================================
161

    
162
gost_enc.prologue:
163

    
164
                setl	#IDX, 0
165

    
166
                jmp	gost.load_key1_24
167

    
168
complete
169

    
170
//====================================
171

    
172
gost_dec.prologue:
173

    
174
                setl	#IDX, 31
175

    
176
                jmp	gost.load_key25_32
177

    
178
complete
179

    
180
//====================================
181

    
182
gost.load_key1_24:
183

    
184
 kp :=          rdl	Keys
185
 r1 :=          getl	#IDX
186

    
187
 r2 :=          and	@r1, 7		/* Ограничиваем i пределами [0..7] */
188
 r3 :=          slll	@r2, 2		/* Смещение до Ki */
189
 r4 :=          addl	@kp, @r3	/* Ki = kp + i*4 */
190
 r5 :=          rdl	@r4
191
                setl	#KI, @r5
192

    
193
                jmp	gost.round
194

    
195
complete
196

    
197
//====================================
198

    
199
gost.load_key25_32:
200

    
201
 kp :=          rdl	Keys
202
 r1 :=          getl	#IDX
203

    
204
 r2 :=          and	@r1, 7		/* Ограничиваем i пределами [7..0] */
205
 r3 :=          slll	@r2, 2		/* Смещение до Ki */
206
 r4 :=          addl	@kp, 7 * 4	/* Пермещаем указатель к последнему элементу */
207
 r5 :=          subl	@r4, @r3	/* Отсчитываем ключ с конца: Ki = kp - i*4 */
208
 r6 :=          rdl	@r5
209
                setl	#KI, @r6
210

    
211
                jmp	gost.round
212

    
213
complete
214

    
215
//====================================
216

    
217
gost.round:
218

    
219
 r1 :=          getl	#KI
220

    
221
	/* Сохраняем в коммутатор 8 значений Sblock */
222
 s0 :=          rdq	#SB
223
 s1 :=          rdq	#SB, 8
224
 s2 :=          rdq	#SB, 16
225

    
226
 axk :=         xor	@r1, #AA	/* Сложение Ai + Ki по mod 2 */
227

    
228
 s3 :=          rdq	#SB, 24
229
 s4 :=          rdq	#SB, 32
230
 s5 :=          rdq	#SB, 40
231
 s6 :=          rdq	#SB, 48
232
 s7 :=          rdq	#SB, 56
233

    
234
	/* Разбиваем на 4-х битную подпоследовательность */
235
 r3 :=          slrl	@axk, 4
236
 r4 :=          slrl	@axk, 8
237
 r5 :=          slrl	@axk, 12
238
 r6 :=          slrl	@axk, 16
239
 r7 :=          slrl	@axk, 20
240
 r8 :=          slrl	@axk, 24
241
 r9 :=          slrl	@axk, 28
242
	/* Получаем индекс для каждой подпоследовательности */
243
 r10 :=         and	@axk, 0xf
244
 r11 :=         and	@r3, 0xf
245
 r12 :=         and	@r4, 0xf
246
 r13 :=         and	@r5, 0xf
247
 r14 :=         and	@r6, 0xf
248
 r15 :=         and	@r7, 0xf
249
 r16 :=         and	@r8, 0xf
250
 r17 :=         and	@r9, 0xf
251
	/* ...растягиваем, чтобы потом сдвигать вправо с кратностью по 4 бита */
252
 r18 :=         slll	@r10, 2
253
 r19 :=         slll	@r11, 2
254
 r20 :=         slll	@r12, 2
255
 r21 :=         slll	@r13, 2
256
 r22 :=         slll	@r14, 2
257
 r23 :=         slll	@r15, 2
258
 r24 :=         slll	@r16, 2
259
 r25 :=         slll	@r17, 2
260
	/* Получаем значение по индексу */
261
 r26 :=         slrq	@s0, @r18
262
 r27 :=         slrq	@s1, @r19
263
 r28 :=         slrq	@s2, @r20
264
 r29 :=         slrq	@s3, @r21
265
 r30 :=         slrq	@s4, @r22
266
 r31 :=         slrq	@s5, @r23
267
 r32 :=         slrq	@s6, @r24
268
 r33 :=         slrq	@s7, @r25
269

    
270
 r34 :=         and	@r26, 0xf
271
 r35 :=         and	@r27, 0xf
272
 r36 :=         and	@r28, 0xf
273
 r37 :=         and	@r29, 0xf
274
 r38 :=         and	@r30, 0xf
275
 r39 :=         and	@r31, 0xf
276
 r40 :=         and	@r32, 0xf
277
 r41 :=         and	@r33, 0xf
278
	/* Склеиваем подпоследовательности */
279
 r42 :=         slll	@r35, 4
280
 r43 :=         slll	@r36, 8
281
 r44 :=         slll	@r37, 12
282
 r45 :=         slll	@r38, 16
283
 r46 :=         slll	@r39, 20
284
 r47 :=         slll	@r40, 24
285
 r48 :=         slll	@r41, 28
286

    
287
;мин 3 такта
288
 r49 :=         or	@r34, @r42
289
 r50 :=         or	@r43, @r44
290
 r51 :=         or	@r45, @r46
291
 r52 :=         or	@r47, @r48
292
 r53 :=         or	@r49, @r50
293
 r54 :=         or	@r51, @r52
294
 r55 :=         or	@r53, @r54
295

    
296
 r61 :=         getl	#DEC
297

    
298
 r56 :=         roll	@r55, 11		/* Циклический сдвиг влево на 11 бит */
299
 r57 :=         getl	#BB
300
 r58 :=         xor	@r57, @r56		/* Bi ^ f(Ai,Ki) */
301
 r59 :=         setl	#BB, #AA		/* Bi+1 = Ai */
302
 r60 :=         setl	#AA, @r58		/* Ai+1 = Bi ^ f(Ai,Ki) */
303

    
304
 r62 :=         je	@r61, gost_enc.epilogue
305
 r63 :=         jne	@r61, gost_dec.epilogue
306

    
307
complete
308

    
309
//====================================
310

    
311
gost_enc.epilogue:
312

    
313
 r1 :=          getl	#IDX
314
 r2 :=          addl	@r1, 1
315
                setl	#IDX, @r2
316

    
317
 r3 :=          subl	@r2, 24
318
 r4 :=          subl	@r2, 32
319

    
320
 r5 :=          and	@r3, 0x80000000
321
                jne	@r5, gost.load_key1_24
322

    
323
 r6 :=          and	@r4, 0x80000000
324
 r7 :=          xor	@r5, @r6
325
                jne	@r7, gost.load_key25_32
326

    
327
 r8 :=          or	@r5, @r7
328

    
329
                je	@r8, gost.save_results		; Готово, далее сохраняем и берём следующие значения из буфера
330

    
331
complete
332

    
333
//====================================
334

    
335
gost_dec.epilogue:
336

    
337
 r1 :=          getl	#IDX
338
 r2 :=          subl	@r1, 1
339
                setl	#IDX, @r2
340

    
341
                je	@r1, gost.save_results		; Готово, далее сохраняем и берём следующие значения из буфера
342
                jne	@r1, gost_dec.epilogue.2
343

    
344
complete
345

    
346
gost_dec.epilogue.2:	; Убрали лишнее
347

    
348
 r1 :=          getl	#IDX
349

    
350
 r2 :=          subl	@r1, 24
351

    
352
 r4 :=          and	@r2, 0x80000000
353
                jne	@r4, gost.load_key1_24
354

    
355
                je	@r4, gost.load_key25_32
356
complete
357

    
358
/* ; Полный вариант
359
gost_dec.epilogue.2:
360

    
361
 r1 :=          getl	#IDX
362

    
363
 r2 :=          subl	@r1, 24
364
 r3 :=          subl	@r1, 32
365

    
366
 r4 :=          and	@r2, 0x80000000
367
                jne	@r4, gost.load_key1_24
368

    
369
 r5 :=          and	@r3, 0x80000000
370
 r6 :=          xor	@r5, @r4
371
                jne	@r6, gost.load_key25_32
372

    
373
                or	@r4, @r6	;Возможно это лишнее надо уточнить (без них на тестовом примере работает норамльно)
374
                je	gost.round	;Возможно это лишнее надо уточнить (без них на тестовом примере работает норамльно)
375

    
376
complete
377
*/
378

    
379
//====================================
380

    
381
gost.save_results:
382

    
383
 r1 :=          rdl	BufPtr
384

    
385
 r2 :=          addl	@r1, 4
386
 newp :=        addl	@r1, 8
387

    
388
 r3 :=          getl	#BB
389
 r4 :=          getl	#AA
390

    
391
                wrl	@r3, @r1	/* Сохраняем новые значения в буфере */
392
                wrl	@r4, @r2
393

    
394
                wrl	@newp, BufPtr	/* Сохраняем новый указатель */
395

    
396
                jmp	gost.next_block
397

    
398
complete
399

    
400
//====================================
401

    
402
gost.return:
403

    
404
 SP13 :=        getq	#SP	; убираем наш кадр стека. Часть 1 из 3
405

    
406
	; Восстановление старых значений индексных регистров. Часть 1 из 2
407
 old7 :=        rdq	gost_encdec.old_r7.newSP
408
 old6 :=        rdq	gost_encdec.old_r6.newSP
409
 old5 :=        rdq	gost_encdec.old_r5.newSP
410
 old4 :=        rdq	gost_encdec.old_r4.newSP
411
 old3 :=        rdq	gost_encdec.old_r3.newSP
412
 old2 :=        rdq	gost_encdec.old_r2.newSP
413
 old1 :=        rdq	gost_encdec.old_r1.newSP
414

    
415
 NP :=          rdl	gost_encdec.RET.newSP	; Следующий параграф. Часть 1 из 2
416

    
417
 SP23 :=        addl	@SP13, gost_encdec.stackb	; убираем наш кадр стека. Часть 2 из 3
418

    
419
	; Восстановление старых значений индексных регистров. Часть 2 из 2
420
                setq	#SB, @old7
421
                setq	#IDX, @old6
422
                setq	#BLK, @old5
423
                setq	#KI, @old4
424
                setq	#BB, @old3
425
                setq	#AA, @old2
426
                setq	#DEC, @old1
427

    
428
                setl	#SP, @SP23	; убираем наш кадр стека. Часть 3 из 3
429

    
430
                jmp	@NP	; Следующий параграф. Часть 2 из 2
431

    
432
complete
433

    
434
//====================================