Coverage Report

Created: 2023-03-26 07:33

/src/nettle/desCode.h
Line
Count
Source (jump to first uncovered line)
1
/* desCode.h
2
 *
3
 */
4
5
/*  des - fast & portable DES encryption & decryption.
6
 *  Copyright (C) 1992  Dana L. How
7
 *  Please see the file `descore.README' for the complete copyright notice.
8
 */
9
10
#include "des.h"
11
12
/* optional customization:
13
 * the idea here is to alter the code so it will still run correctly
14
 * on any machine,  but the quickest on the specific machine in mind.
15
 * note that these silly tweaks can give you a 15%-20% speed improvement
16
 * on the sparc -- it's probably even more significant on the 68000. */
17
18
/* take care of machines with incredibly few registers */
19
#if defined(i386)
20
#define REGISTER    /* only x, y, z will be declared register */
21
#else
22
#define REGISTER  register
23
#endif  /* i386 */
24
25
/* is auto inc/dec faster than 7bit unsigned indexing? */
26
#if defined(vax) || defined(mc68000)
27
#define FIXR    r += 32;
28
#define FIXS    s +=  8;
29
#define PREV(v,o) *--v
30
#define NEXT(v,o) *v++
31
#else
32
#define FIXR
33
#define FIXS
34
0
#define PREV(v,o) v[o]
35
0
#define NEXT(v,o) v[o]
36
#endif
37
38
/* if no machine type, default is indexing, 6 registers and cheap literals */
39
#if !defined(i386) && !defined(vax) && !defined(mc68000) && !defined(sparc)
40
#define vax
41
#endif
42
43
44
/* handle a compiler which can't reallocate registers */
45
/* The BYTE type is used as parameter for the encrypt/decrypt functions.
46
 * It's pretty bad to have the function prototypes depend on
47
 * a macro definition that the users of the function doesn't
48
 * know about. /Niels */
49
#if 0     /* didn't feel like deleting */
50
#define SREGFREE  ; s = (uint8_t *) D
51
#define DEST    s
52
#define D   m0
53
#define BYTE    uint32_t
54
#else
55
#define SREGFREE
56
#define DEST    d
57
#define D   d
58
#define BYTE    uint8_t
59
#endif
60
61
/* handle constants in the optimal way for 386 & vax */
62
/* 386: we declare 3 register variables (see above) and use 3 more variables;
63
 * vax: we use 6 variables, all declared register;
64
 * we assume address literals are cheap & unrestricted;
65
 * we assume immediate constants are cheap & unrestricted. */
66
#if defined(i386) || defined(vax)
67
#define MQ0  des_bigmap
68
#define MQ1 (des_bigmap +  64)
69
#define MQ2 (des_bigmap + 128)
70
#define MQ3 (des_bigmap + 192)
71
#define HQ0(z)        /*  z |= 0x01000000L; */
72
#define HQ2(z)        /*  z |= 0x03000200L; */
73
#define LQ0(z)  0xFCFC & z
74
#define LQ1(z)  0xFCFC & z
75
#define LQ2(z)  0xFCFC & z
76
#define LQ3(z)  0xFCFC & z
77
#define SQ  16
78
#define MS0  des_keymap 
79
#define MS1 (des_keymap +  64)
80
#define MS2 (des_keymap + 128)
81
#define MS3 (des_keymap + 192)
82
#define MS4 (des_keymap + 256)
83
#define MS5 (des_keymap + 320)
84
#define MS6 (des_keymap + 384)
85
#define MS7 (des_keymap + 448)
86
#define HS(z)
87
#define LS0(z)  0xFC & z
88
#define LS1(z)  0xFC & z
89
#define LS2(z)  0xFC & z
90
#define LS3(z)  0xFC & z
91
#define REGQUICK
92
#define SETQUICK
93
#define REGSMALL
94
#define SETSMALL
95
#endif  /* defined(i386) || defined(vax) */
96
97
/* handle constants in the optimal way for mc68000 */
98
/* in addition to the core 6 variables, we declare 3 registers holding constants
99
 * and 4 registers holding address literals.
100
 * at most 6 data values and 5 address values are actively used at once.
101
 * we assume address literals are so expensive we never use them;
102
 * we assume constant index offsets > 127 are expensive, so they are not used.
103
 * we assume all constants are expensive and put them in registers,
104
 * including shift counts greater than 8. */
105
#if defined(mc68000)
106
#define MQ0 m0
107
#define MQ1 m1
108
#define MQ2 m2
109
#define MQ3 m3
110
#define HQ0(z)
111
#define HQ2(z)
112
#define LQ0(z)  k0 & z
113
#define LQ1(z)  k0 & z
114
#define LQ2(z)  k0 & z
115
#define LQ3(z)  k0 & z
116
#define SQ  k1
117
#define MS0 m0
118
#define MS1 m0
119
#define MS2 m1
120
#define MS3 m1
121
#define MS4 m2
122
#define MS5 m2
123
#define MS6 m3
124
#define MS7 m3
125
#define HS(z) z |= k0;
126
#define LS0(z)  k1 & z
127
#define LS1(z)  k2 & z
128
#define LS2(z)  k1 & z
129
#define LS3(z)  k2 & z
130
#define REGQUICK        \
131
  register uint32_t k0, k1;   \
132
  register uint32_t *m0, *m1, *m2, *m3;
133
#define SETQUICK        \
134
  ; k0 = 0xFCFC       \
135
  ; k1 = 16       \
136
  /*k2 = 28 to speed up ROL */    \
137
  ; m0 = des_bigmap     \
138
  ; m1 = m0 + 64        \
139
  ; m2 = m1 + 64        \
140
  ; m3 = m2 + 64
141
#define REGSMALL        \
142
  register uint32_t k0, k1, k2;   \
143
  register uint32_t *m0, *m1, *m2, *m3;
144
#define SETSMALL        \
145
  ; k0 = 0x01000100L      \
146
  ; k1 = 0x0FC        \
147
  ; k2 = 0x1FC        \
148
  ; m0 = des_keymap     \
149
  ; m1 = m0 + 128       \
150
  ; m2 = m1 + 128       \
151
  ; m3 = m2 + 128
152
#endif  /* defined(mc68000) */
153
154
/* handle constants in the optimal way for sparc */
155
/* in addition to the core 6 variables, we either declare:
156
 * 4 registers holding address literals and 1 register holding a constant, or
157
 * 8 registers holding address literals.
158
 * up to 14 register variables are declared (sparc has %i0-%i5, %l0-%l7).
159
 * we assume address literals are so expensive we never use them;
160
 * we assume any constant with >10 bits is expensive and put it in a register,
161
 * and any other is cheap and is coded in-line. */
162
#if defined(sparc)
163
#define MQ0 m0
164
#define MQ1 m1
165
#define MQ2 m2
166
#define MQ3 m3
167
#define HQ0(z)
168
#define HQ2(z)
169
#define LQ0(z)  k0 & z
170
#define LQ1(z)  k0 & z
171
#define LQ2(z)  k0 & z
172
#define LQ3(z)  k0 & z
173
#define SQ  16
174
#define MS0 m0
175
#define MS1 m1
176
#define MS2 m2
177
#define MS3 m3
178
#define MS4 m4
179
#define MS5 m5
180
#define MS6 m6
181
#define MS7 m7
182
#define HS(z)
183
#define LS0(z)  0xFC & z
184
#define LS1(z)  0xFC & z
185
#define LS2(z)  0xFC & z
186
#define LS3(z)  0xFC & z
187
#define REGQUICK        \
188
  register uint32_t k0;     \
189
  register uint32_t *m0, *m1, *m2, *m3;
190
#define SETQUICK        \
191
  ; k0 = 0xFCFC       \
192
  ; m0 = des_bigmap     \
193
  ; m1 = m0 + 64        \
194
  ; m2 = m1 + 64        \
195
  ; m3 = m2 + 64
196
#define REGSMALL        \
197
  register uint32_t *m0, *m1, *m2, *m3, *m4, *m5, *m6, *m7;
198
#define SETSMALL        \
199
  ; m0 = des_keymap     \
200
  ; m1 = m0 + 64        \
201
  ; m2 = m1 + 64        \
202
  ; m3 = m2 + 64        \
203
  ; m4 = m3 + 64        \
204
  ; m5 = m4 + 64        \
205
  ; m6 = m5 + 64        \
206
  ; m7 = m6 + 64
207
#endif  /* defined(sparc) */
208
209
210
/* some basic stuff */
211
212
/* generate addresses from a base and an index */
213
/* FIXME: This is used only as *ADD(msi,lsi(z)) or *ADD(mqi,lqi(z)).
214
 * Why not use plain indexing instead? /Niels */
215
0
#define ADD(b,x)  (uint32_t *) ((uint8_t *)b + (x))
216
217
/* low level rotate operations */
218
#define NOP(d,c,o)
219
0
#define ROL(d,c,o)  d = d << c | d >> o
220
0
#define ROR(d,c,o)  d = d >> c | d << o
221
0
#define ROL1(d)   ROL(d, 1, 31)
222
0
#define ROR1(d)   ROR(d, 1, 31)
223
224
/* elementary swap for doing IP/FP */
225
#define SWAP(x,y,m,b)       \
226
0
  z  = ((x >> b) ^ y) & m;    \
227
0
  x ^= z << b;        \
228
0
  y ^= z
229
230
231
/* the following macros contain all the important code fragments */
232
233
/* load input data, then setup special registers holding constants */
234
#define TEMPQUICK(LOAD)       \
235
  REGQUICK        \
236
  LOAD()          \
237
  SETQUICK
238
#define TEMPSMALL(LOAD)       \
239
0
  REGSMALL        \
240
0
  LOAD()          \
241
0
  SETSMALL
242
243
/* load data */
244
#define LOADDATA(x,y)       \
245
0
  FIXS          \
246
0
  y  = PREV(s, 7); y<<= 8;   \
247
0
  y |= PREV(s, 6); y<<= 8;   \
248
0
  y |= PREV(s, 5); y<<= 8;   \
249
0
  y |= PREV(s, 4);     \
250
0
  x  = PREV(s, 3); x<<= 8;   \
251
0
  x |= PREV(s, 2); x<<= 8;   \
252
0
  x |= PREV(s, 1); x<<= 8;   \
253
0
  x |= PREV(s, 0)        \
254
0
  SREGFREE
255
/* load data without initial permutation and put into efficient position */
256
#define LOADCORE()        \
257
  LOADDATA(x, y);       \
258
  ROR1(x);        \
259
  ROR1(y)
260
/* load data, do the initial permutation and put into efficient position */
261
#define LOADFIPS()        \
262
0
  LOADDATA(y, x);       \
263
0
  SWAP(x, y, 0x0F0F0F0FL, 004);   \
264
0
  SWAP(y, x, 0x0000FFFFL, 020);   \
265
0
  SWAP(x, y, 0x33333333L, 002);   \
266
0
  SWAP(y, x, 0x00FF00FFL, 010);   \
267
0
  ROR1(x);        \
268
0
  z  = (x ^ y) & 0x55555555L;   \
269
0
  y ^= z;         \
270
0
  x ^= z;         \
271
0
  ROR1(y)
272
273
274
/* core encryption/decryption operations */
275
/* S box mapping and P perm */
276
#define KEYMAPSMALL(x,z,mq0,mq1,hq,lq0,lq1,sq,ms0,ms1,ms2,ms3,hs,ls0,ls1,ls2,ls3)\
277
0
  hs(z)         \
278
0
  x ^= *ADD(ms3, ls3(z));      \
279
0
  z>>= 8;         \
280
0
  x ^= *ADD(ms2, ls2(z));      \
281
0
  z>>= 8;         \
282
0
  x ^= *ADD(ms1, ls1(z));      \
283
0
  z>>= 8;         \
284
0
  x ^= *ADD(ms0, ls0(z))
285
/* alternate version: use 64k of tables */
286
#define KEYMAPQUICK(x,z,mq0,mq1,hq,lq0,lq1,sq,ms0,ms1,ms2,ms3,hs,ls0,ls1,ls2,ls3)\
287
  hq(z)         \
288
  x ^= *ADD(mq0, lq0(z));     \
289
  z>>= sq;        \
290
  x ^= *ADD(mq1, lq1(z))
291
/* apply 24 key bits and do the odd  s boxes */
292
#define S7S1(x,y,z,r,m,KEYMAP,LOAD)   \
293
0
  z  = LOAD(r, m);     \
294
0
  z ^= y;         \
295
0
  KEYMAP(x,z,MQ0,MQ1,HQ0,LQ0,LQ1,SQ,MS0,MS1,MS2,MS3,HS,LS0,LS1,LS2,LS3)
296
/* apply 24 key bits and do the even s boxes */
297
#define S6S0(x,y,z,r,m,KEYMAP,LOAD)   \
298
0
  z  = LOAD(r, m);     \
299
0
  z ^= y;         \
300
0
  ROL(z, 4, 28);       \
301
0
  KEYMAP(x,z,MQ2,MQ3,HQ2,LQ2,LQ3,SQ,MS4,MS5,MS6,MS7,HS,LS0,LS1,LS2,LS3)
302
/* actual iterations.  equivalent except for UPDATE & swapping m and n */
303
#define ENCR(x,y,z,r,m,n,KEYMAP)    \
304
0
  S7S1(x,y,z,r,m,KEYMAP,NEXT);    \
305
0
  S6S0(x,y,z,r,n,KEYMAP,NEXT)
306
#define DECR(x,y,z,r,m,n,KEYMAP)    \
307
0
  S6S0(x,y,z,r,m,KEYMAP,PREV);    \
308
0
  S7S1(x,y,z,r,n,KEYMAP,PREV)
309
310
/* write out result in correct byte order */
311
#define SAVEDATA(x,y)       \
312
0
  NEXT(DEST, 0) = x; x>>= 8;    \
313
0
  NEXT(DEST, 1) = x; x>>= 8;    \
314
0
  NEXT(DEST, 2) = x; x>>= 8;    \
315
0
  NEXT(DEST, 3) = x;      \
316
0
  NEXT(DEST, 4) = y; y>>= 8;    \
317
0
  NEXT(DEST, 5) = y; y>>= 8;    \
318
0
  NEXT(DEST, 6) = y; y>>= 8;    \
319
0
  NEXT(DEST, 7) = y
320
/* write out result */
321
#define SAVECORE()        \
322
  ROL1(x);        \
323
  ROL1(y);        \
324
  SAVEDATA(y, x)
325
/* do final permutation and write out result */
326
#define SAVEFIPS()        \
327
0
  ROL1(x);        \
328
0
  z  = (x ^ y) & 0x55555555L;   \
329
0
  y ^= z;         \
330
0
  x ^= z;         \
331
0
  ROL1(y);        \
332
0
  SWAP(x, y, 0x00FF00FFL, 010);   \
333
0
  SWAP(y, x, 0x33333333L, 002);   \
334
0
  SWAP(x, y, 0x0000FFFFL, 020);   \
335
0
  SWAP(y, x, 0x0F0F0F0FL, 004);   \
336
0
  SAVEDATA(x, y)
337
338
339
/* the following macros contain the encryption/decryption skeletons */
340
341
#define ENCRYPT(NAME, TEMP, LOAD, KEYMAP, SAVE) \
342
            \
343
void            \
344
NAME(REGISTER BYTE *D,        \
345
     REGISTER const uint32_t *r,    \
346
0
     REGISTER const uint8_t *s)     \
347
0
{           \
348
0
  register uint32_t x, y, z;    \
349
0
            \
350
0
  /* declare temps & load data */   \
351
0
  TEMP(LOAD);       \
352
0
            \
353
0
  /* do the 16 iterations */    \
354
0
  ENCR(x,y,z,r, 0, 1,KEYMAP);   \
355
0
  ENCR(y,x,z,r, 2, 3,KEYMAP);   \
356
0
  ENCR(x,y,z,r, 4, 5,KEYMAP);   \
357
0
  ENCR(y,x,z,r, 6, 7,KEYMAP);   \
358
0
  ENCR(x,y,z,r, 8, 9,KEYMAP);   \
359
0
  ENCR(y,x,z,r,10,11,KEYMAP);   \
360
0
  ENCR(x,y,z,r,12,13,KEYMAP);   \
361
0
  ENCR(y,x,z,r,14,15,KEYMAP);   \
362
0
  ENCR(x,y,z,r,16,17,KEYMAP);   \
363
0
  ENCR(y,x,z,r,18,19,KEYMAP);   \
364
0
  ENCR(x,y,z,r,20,21,KEYMAP);   \
365
0
  ENCR(y,x,z,r,22,23,KEYMAP);   \
366
0
  ENCR(x,y,z,r,24,25,KEYMAP);   \
367
0
  ENCR(y,x,z,r,26,27,KEYMAP);   \
368
0
  ENCR(x,y,z,r,28,29,KEYMAP);   \
369
0
  ENCR(y,x,z,r,30,31,KEYMAP);   \
370
0
            \
371
0
  /* save result */     \
372
0
  SAVE();         \
373
0
            \
374
0
  return;         \
375
0
}
376
377
#define DECRYPT(NAME, TEMP, LOAD, KEYMAP, SAVE) \
378
            \
379
void            \
380
NAME(REGISTER BYTE *D,        \
381
     REGISTER const uint32_t *r,    \
382
0
     REGISTER const uint8_t *s)     \
383
0
{           \
384
0
  register uint32_t x, y, z;    \
385
0
            \
386
0
  /* declare temps & load data */   \
387
0
  TEMP(LOAD);       \
388
0
            \
389
0
  /* do the 16 iterations */    \
390
0
  FIXR          \
391
0
  DECR(x,y,z,r,31,30,KEYMAP);   \
392
0
  DECR(y,x,z,r,29,28,KEYMAP);   \
393
0
  DECR(x,y,z,r,27,26,KEYMAP);   \
394
0
  DECR(y,x,z,r,25,24,KEYMAP);   \
395
0
  DECR(x,y,z,r,23,22,KEYMAP);   \
396
0
  DECR(y,x,z,r,21,20,KEYMAP);   \
397
0
  DECR(x,y,z,r,19,18,KEYMAP);   \
398
0
  DECR(y,x,z,r,17,16,KEYMAP);   \
399
0
  DECR(x,y,z,r,15,14,KEYMAP);   \
400
0
  DECR(y,x,z,r,13,12,KEYMAP);   \
401
0
  DECR(x,y,z,r,11,10,KEYMAP);   \
402
0
  DECR(y,x,z,r, 9, 8,KEYMAP);   \
403
0
  DECR(x,y,z,r, 7, 6,KEYMAP);   \
404
0
  DECR(y,x,z,r, 5, 4,KEYMAP);   \
405
0
  DECR(x,y,z,r, 3, 2,KEYMAP);   \
406
0
  DECR(y,x,z,r, 1, 0,KEYMAP);   \
407
0
            \
408
0
  /* save result */     \
409
0
  SAVE();         \
410
0
            \
411
0
  return;         \
412
0
}