3 * The des block cipher.
7 /* nettle, low-level cryptographics library
9 * Copyright (C) 2001 Niels Möller
11 * The nettle library is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation; either version 2.1 of the License, or (at your
14 * option) any later version.
16 * The nettle library is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
19 * License for more details.
21 * You should have received a copy of the GNU Lesser General Public License
22 * along with the nettle library; see the file COPYING.LIB. If not, write to
23 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
27 /* des - fast & portable DES encryption & decryption.
28 * Copyright (C) 1992 Dana L. How
29 * Please see the file `descore.README' for the complete copyright notice.
54 static ENCRYPT(DesSmallFipsEncrypt
,TEMPSMALL
, LOADFIPS
,KEYMAPSMALL
,SAVEFIPS
)
55 static DECRYPT(DesSmallFipsDecrypt
,TEMPSMALL
, LOADFIPS
,KEYMAPSMALL
,SAVEFIPS
)
57 /* If parity bits are used, keys should have odd parity. We use a
58 small table, to not waste any memory on this fairly obscure DES
63 { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 };
65 #define PARITY(x) (parity_16[(x)&0xf] ^ parity_16[((x)>>4) & 0xf])
68 des_check_parity(unsigned length
, const uint8_t *key
)
71 for (i
= 0; i
<length
; i
++)
79 des_fix_parity(unsigned length
, uint8_t *dst
,
83 for (i
= 0; i
<length
; i
++)
84 dst
[i
] = src
[i
] ^ PARITY(src
[i
]) ^ 1;
87 /* Weak and semiweak keys, excluding parity:
89 * 00 00 00 00 00 00 00 00
90 * 7f 7f 7f 7f 7f 7f 7f 7f
91 * 0f 0f 0f 0f 07 07 07 07
92 * 70 70 70 70 78 78 78 78
94 * 00 7f 00 7f 00 7f 00 7f
95 * 7f 00 7f 00 7f 00 7f 00
97 * 0f 70 0f 70 07 78 07 78
98 * 70 0f 70 0f 78 07 78 07
100 * 00 70 00 70 00 78 00 78
101 * 70 00 70 00 78 00 78 00
103 * 0f 7f 0f 7f 07 7f 07 7f
104 * 7f 0f 7f 0f 7f 07 7f 07
106 * 00 0f 00 0f 00 07 00 07
107 * 0f 00 0f 00 07 00 07 00
109 * 70 7f 70 7f 78 7f 78 7f
110 * 7f 70 7f 70 7f 78 7f 78
114 des_weak_p(const uint8_t *key
)
116 /* Hash function generated using gperf. */
117 static const unsigned char asso_values
[0x81] =
119 16, 9, 26, 26, 26, 26, 26, 26, 26, 26,
120 26, 26, 26, 26, 26, 6, 2, 26, 26, 26,
121 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
122 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
123 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
124 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
125 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
126 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
127 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
128 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
129 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
130 26, 26, 3, 1, 26, 26, 26, 26, 26, 26,
131 26, 26, 26, 26, 26, 26, 26, 0, 0
134 static const int8_t weak_key_hash
[26][4] =
136 /* 0 */ {0x7f,0x7f, 0x7f,0x7f},
137 /* 1 */ {0x7f,0x70, 0x7f,0x78},
138 /* 2 */ {0x7f,0x0f, 0x7f,0x07},
139 /* 3 */ {0x70,0x7f, 0x78,0x7f},
140 /* 4 */ {0x70,0x70, 0x78,0x78},
141 /* 5 */ {0x70,0x0f, 0x78,0x07},
142 /* 6 */ {0x0f,0x7f, 0x07,0x7f},
143 /* 7 */ {0x0f,0x70, 0x07,0x78},
144 /* 8 */ {0x0f,0x0f, 0x07,0x07},
145 /* 9 */ {0x7f,0x00, 0x7f,0x00},
146 /* 10 */ {-1,-1,-1,-1},
147 /* 11 */ {-1,-1,-1,-1},
148 /* 12 */ {0x70,0x00, 0x78,0x00},
149 /* 13 */ {-1,-1,-1,-1},
150 /* 14 */ {-1,-1,-1,-1},
151 /* 15 */ {0x0f,0x00, 0x07,0x00},
152 /* 16 */ {0x00,0x7f, 0x00,0x7f},
153 /* 17 */ {0x00,0x70, 0x00,0x78},
154 /* 18 */ {0x00,0x0f, 0x00,0x07},
155 /* 19 */ {-1,-1,-1,-1},
156 /* 20 */ {-1,-1,-1,-1},
157 /* 21 */ {-1,-1,-1,-1},
158 /* 22 */ {-1,-1,-1,-1},
159 /* 23 */ {-1,-1,-1,-1},
160 /* 24 */ {-1,-1,-1,-1},
161 /* 25 */ {0x00,0x00, 0x00,0x00}
164 int8_t k0
= key
[0] >> 1;
165 int8_t k1
= key
[1] >> 1;
167 unsigned hash
= asso_values
[k1
+ 1] + asso_values
[k0
];
168 const int8_t *candidate
= weak_key_hash
[hash
];
172 if (k0
!= candidate
[0]
173 || k1
!= candidate
[1])
176 if ( (key
[2] >> 1) != k0
177 || (key
[3] >> 1) != k1
)
182 if (k0
!= candidate
[2]
183 || k1
!= candidate
[3])
185 if ( (key
[6] >> 1) != k0
186 || (key
[7] >> 1) != k1
)
193 des_set_key(struct des_ctx
*ctx
, const uint8_t *key
)
195 register uint32_t n
, w
;
196 register char * b0
, * b1
;
197 char bits0
[56], bits1
[56];
201 /* explode the bits */
207 w
= (256 | *k
++) << 2;
216 /* put the bits in the correct places */
222 w
= (b1
[k
[ 0 ]] | b0
[k
[ 1 ]]) << 4;
223 w
|= (b1
[k
[ 2 ]] | b0
[k
[ 3 ]]) << 2;
224 w
|= b1
[k
[ 4 ]] | b0
[k
[ 5 ]];
226 w
|= (b1
[k
[ 6 ]] | b0
[k
[ 7 ]]) << 4;
227 w
|= (b1
[k
[ 8 ]] | b0
[k
[ 9 ]]) << 2;
228 w
|= b1
[k
[10 ]] | b0
[k
[11 ]];
230 w
|= (b1
[k
[12 ]] | b0
[k
[13 ]]) << 4;
231 w
|= (b1
[k
[14 ]] | b0
[k
[15 ]]) << 2;
232 w
|= b1
[k
[16 ]] | b0
[k
[17 ]];
234 w
|= (b1
[k
[18 ]] | b0
[k
[19 ]]) << 4;
235 w
|= (b1
[k
[20 ]] | b0
[k
[21 ]]) << 2;
236 w
|= b1
[k
[22 ]] | b0
[k
[23 ]];
240 w
= (b1
[k
[ 0+24]] | b0
[k
[ 1+24]]) << 4;
241 w
|= (b1
[k
[ 2+24]] | b0
[k
[ 3+24]]) << 2;
242 w
|= b1
[k
[ 4+24]] | b0
[k
[ 5+24]];
244 w
|= (b1
[k
[ 6+24]] | b0
[k
[ 7+24]]) << 4;
245 w
|= (b1
[k
[ 8+24]] | b0
[k
[ 9+24]]) << 2;
246 w
|= b1
[k
[10+24]] | b0
[k
[11+24]];
248 w
|= (b1
[k
[12+24]] | b0
[k
[13+24]]) << 4;
249 w
|= (b1
[k
[14+24]] | b0
[k
[15+24]]) << 2;
250 w
|= b1
[k
[16+24]] | b0
[k
[17+24]];
252 w
|= (b1
[k
[18+24]] | b0
[k
[19+24]]) << 4;
253 w
|= (b1
[k
[20+24]] | b0
[k
[21+24]]) << 2;
254 w
|= b1
[k
[22+24]] | b0
[k
[23+24]];
256 ROR(w
, 4, 28); /* could be eliminated */
263 return !des_weak_p (key
);
267 des_encrypt(const struct des_ctx
*ctx
,
268 unsigned length
, uint8_t *dst
,
271 assert(!(length
% DES_BLOCK_SIZE
));
275 DesSmallFipsEncrypt(dst
, ctx
->key
, src
);
276 length
-= DES_BLOCK_SIZE
;
277 src
+= DES_BLOCK_SIZE
;
278 dst
+= DES_BLOCK_SIZE
;
283 des_decrypt(const struct des_ctx
*ctx
,
284 unsigned length
, uint8_t *dst
,
287 assert(!(length
% DES_BLOCK_SIZE
));
291 DesSmallFipsDecrypt(dst
, ctx
->key
, src
);
292 length
-= DES_BLOCK_SIZE
;
293 src
+= DES_BLOCK_SIZE
;
294 dst
+= DES_BLOCK_SIZE
;