OLD | NEW |
| (Empty) |
1 /* | |
2 * desblapi.c | |
3 * | |
4 * core source file for DES-150 library | |
5 * Implement DES Modes of Operation and Triple-DES. | |
6 * Adapt DES-150 to blapi API. | |
7 * | |
8 * This Source Code Form is subject to the terms of the Mozilla Public | |
9 * License, v. 2.0. If a copy of the MPL was not distributed with this | |
10 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
11 | |
12 #ifdef FREEBL_NO_DEPEND | |
13 #include "stubs.h" | |
14 #endif | |
15 | |
16 #include "des.h" | |
17 #include <stddef.h> | |
18 #include "secerr.h" | |
19 | |
20 #if defined(NSS_X86_OR_X64) | |
21 /* Intel X86 CPUs do unaligned loads and stores without complaint. */ | |
22 #define COPY8B(to, from, ptr) \ | |
23 HALFPTR(to)[0] = HALFPTR(from)[0]; \ | |
24 HALFPTR(to)[1] = HALFPTR(from)[1]; | |
25 #elif defined(USE_MEMCPY) | |
26 #define COPY8B(to, from, ptr) memcpy(to, from, 8) | |
27 #else | |
28 #define COPY8B(to, from, ptr) \ | |
29 if (((ptrdiff_t)(ptr) & 0x3) == 0) { \ | |
30 HALFPTR(to)[0] = HALFPTR(from)[0]; \ | |
31 HALFPTR(to)[1] = HALFPTR(from)[1]; \ | |
32 } else if (((ptrdiff_t)(ptr) & 0x1) == 0) { \ | |
33 SHORTPTR(to)[0] = SHORTPTR(from)[0]; \ | |
34 SHORTPTR(to)[1] = SHORTPTR(from)[1]; \ | |
35 SHORTPTR(to)[2] = SHORTPTR(from)[2]; \ | |
36 SHORTPTR(to)[3] = SHORTPTR(from)[3]; \ | |
37 } else { \ | |
38 BYTEPTR(to)[0] = BYTEPTR(from)[0]; \ | |
39 BYTEPTR(to)[1] = BYTEPTR(from)[1]; \ | |
40 BYTEPTR(to)[2] = BYTEPTR(from)[2]; \ | |
41 BYTEPTR(to)[3] = BYTEPTR(from)[3]; \ | |
42 BYTEPTR(to)[4] = BYTEPTR(from)[4]; \ | |
43 BYTEPTR(to)[5] = BYTEPTR(from)[5]; \ | |
44 BYTEPTR(to)[6] = BYTEPTR(from)[6]; \ | |
45 BYTEPTR(to)[7] = BYTEPTR(from)[7]; \ | |
46 } | |
47 #endif | |
48 #define COPY8BTOHALF(to, from) COPY8B(to, from, from) | |
49 #define COPY8BFROMHALF(to, from) COPY8B(to, from, to) | |
50 | |
51 static void | |
52 DES_ECB(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len) | |
53 { | |
54 while (len) { | |
55 DES_Do1Block(cx->ks0, in, out); | |
56 len -= 8; | |
57 in += 8; | |
58 out += 8; | |
59 } | |
60 } | |
61 | |
62 static void | |
63 DES_EDE3_ECB(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len) | |
64 { | |
65 while (len) { | |
66 DES_Do1Block(cx->ks0, in, out); | |
67 len -= 8; | |
68 in += 8; | |
69 DES_Do1Block(cx->ks1, out, out); | |
70 DES_Do1Block(cx->ks2, out, out); | |
71 out += 8; | |
72 } | |
73 } | |
74 | |
75 static void | |
76 DES_CBCEn(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len) | |
77 { | |
78 const BYTE * bufend = in + len; | |
79 HALF vec[2]; | |
80 | |
81 while (in != bufend) { | |
82 COPY8BTOHALF(vec, in); | |
83 in += 8; | |
84 vec[0] ^= cx->iv[0]; | |
85 vec[1] ^= cx->iv[1]; | |
86 DES_Do1Block( cx->ks0, (BYTE *)vec, (BYTE *)cx->iv); | |
87 COPY8BFROMHALF(out, cx->iv); | |
88 out += 8; | |
89 } | |
90 } | |
91 | |
92 static void | |
93 DES_CBCDe(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len) | |
94 { | |
95 const BYTE * bufend; | |
96 HALF oldciphertext[2]; | |
97 HALF plaintext [2]; | |
98 | |
99 for (bufend = in + len; in != bufend; ) { | |
100 oldciphertext[0] = cx->iv[0]; | |
101 oldciphertext[1] = cx->iv[1]; | |
102 COPY8BTOHALF(cx->iv, in); | |
103 in += 8; | |
104 DES_Do1Block(cx->ks0, (BYTE *)cx->iv, (BYTE *)plaintext); | |
105 plaintext[0] ^= oldciphertext[0]; | |
106 plaintext[1] ^= oldciphertext[1]; | |
107 COPY8BFROMHALF(out, plaintext); | |
108 out += 8; | |
109 } | |
110 } | |
111 | |
112 static void | |
113 DES_EDE3CBCEn(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len) | |
114 { | |
115 const BYTE * bufend = in + len; | |
116 HALF vec[2]; | |
117 | |
118 while (in != bufend) { | |
119 COPY8BTOHALF(vec, in); | |
120 in += 8; | |
121 vec[0] ^= cx->iv[0]; | |
122 vec[1] ^= cx->iv[1]; | |
123 DES_Do1Block( cx->ks0, (BYTE *)vec, (BYTE *)cx->iv); | |
124 DES_Do1Block( cx->ks1, (BYTE *)cx->iv, (BYTE *)cx->iv); | |
125 DES_Do1Block( cx->ks2, (BYTE *)cx->iv, (BYTE *)cx->iv); | |
126 COPY8BFROMHALF(out, cx->iv); | |
127 out += 8; | |
128 } | |
129 } | |
130 | |
131 static void | |
132 DES_EDE3CBCDe(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len) | |
133 { | |
134 const BYTE * bufend; | |
135 HALF oldciphertext[2]; | |
136 HALF plaintext [2]; | |
137 | |
138 for (bufend = in + len; in != bufend; ) { | |
139 oldciphertext[0] = cx->iv[0]; | |
140 oldciphertext[1] = cx->iv[1]; | |
141 COPY8BTOHALF(cx->iv, in); | |
142 in += 8; | |
143 DES_Do1Block(cx->ks0, (BYTE *)cx->iv, (BYTE *)plaintext); | |
144 DES_Do1Block(cx->ks1, (BYTE *)plaintext, (BYTE *)plaintext); | |
145 DES_Do1Block(cx->ks2, (BYTE *)plaintext, (BYTE *)plaintext); | |
146 plaintext[0] ^= oldciphertext[0]; | |
147 plaintext[1] ^= oldciphertext[1]; | |
148 COPY8BFROMHALF(out, plaintext); | |
149 out += 8; | |
150 } | |
151 } | |
152 | |
153 DESContext * | |
154 DES_AllocateContext(void) | |
155 { | |
156 return PORT_ZNew(DESContext); | |
157 } | |
158 | |
159 SECStatus | |
160 DES_InitContext(DESContext *cx, const unsigned char *key, unsigned int keylen, | |
161 const unsigned char *iv, int mode, unsigned int encrypt, | |
162 unsigned int unused) | |
163 { | |
164 DESDirection opposite; | |
165 if (!cx) { | |
166 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
167 return SECFailure; | |
168 } | |
169 cx->direction = encrypt ? DES_ENCRYPT : DES_DECRYPT; | |
170 opposite = encrypt ? DES_DECRYPT : DES_ENCRYPT; | |
171 switch (mode) { | |
172 case NSS_DES: /* DES ECB */ | |
173 DES_MakeSchedule( cx->ks0, key, cx->direction); | |
174 cx->worker = &DES_ECB; | |
175 break; | |
176 | |
177 case NSS_DES_EDE3: /* DES EDE ECB */ | |
178 cx->worker = &DES_EDE3_ECB; | |
179 if (encrypt) { | |
180 DES_MakeSchedule(cx->ks0, key, cx->direction); | |
181 DES_MakeSchedule(cx->ks1, key + 8, opposite); | |
182 DES_MakeSchedule(cx->ks2, key + 16, cx->direction); | |
183 } else { | |
184 DES_MakeSchedule(cx->ks2, key, cx->direction); | |
185 DES_MakeSchedule(cx->ks1, key + 8, opposite); | |
186 DES_MakeSchedule(cx->ks0, key + 16, cx->direction); | |
187 } | |
188 break; | |
189 | |
190 case NSS_DES_CBC: /* DES CBC */ | |
191 COPY8BTOHALF(cx->iv, iv); | |
192 cx->worker = encrypt ? &DES_CBCEn : &DES_CBCDe; | |
193 DES_MakeSchedule(cx->ks0, key, cx->direction); | |
194 break; | |
195 | |
196 case NSS_DES_EDE3_CBC: /* DES EDE CBC */ | |
197 COPY8BTOHALF(cx->iv, iv); | |
198 if (encrypt) { | |
199 cx->worker = &DES_EDE3CBCEn; | |
200 DES_MakeSchedule(cx->ks0, key, cx->direction); | |
201 DES_MakeSchedule(cx->ks1, key + 8, opposite); | |
202 DES_MakeSchedule(cx->ks2, key + 16, cx->direction); | |
203 } else { | |
204 cx->worker = &DES_EDE3CBCDe; | |
205 DES_MakeSchedule(cx->ks2, key, cx->direction); | |
206 DES_MakeSchedule(cx->ks1, key + 8, opposite); | |
207 DES_MakeSchedule(cx->ks0, key + 16, cx->direction); | |
208 } | |
209 break; | |
210 | |
211 default: | |
212 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
213 return SECFailure; | |
214 } | |
215 return SECSuccess; | |
216 } | |
217 | |
218 DESContext * | |
219 DES_CreateContext(const BYTE * key, const BYTE *iv, int mode, PRBool encrypt) | |
220 { | |
221 DESContext *cx = PORT_ZNew(DESContext); | |
222 SECStatus rv = DES_InitContext(cx, key, 0, iv, mode, encrypt, 0); | |
223 | |
224 if (rv != SECSuccess) { | |
225 PORT_ZFree(cx, sizeof *cx); | |
226 cx = NULL; | |
227 } | |
228 return cx; | |
229 } | |
230 | |
231 void | |
232 DES_DestroyContext(DESContext *cx, PRBool freeit) | |
233 { | |
234 if (cx) { | |
235 memset(cx, 0, sizeof *cx); | |
236 if (freeit) | |
237 PORT_Free(cx); | |
238 } | |
239 } | |
240 | |
241 SECStatus | |
242 DES_Encrypt(DESContext *cx, BYTE *out, unsigned int *outLen, | |
243 unsigned int maxOutLen, const BYTE *in, unsigned int inLen) | |
244 { | |
245 | |
246 if ((inLen % 8) != 0 || maxOutLen < inLen || !cx || | |
247 cx->direction != DES_ENCRYPT) { | |
248 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
249 return SECFailure; | |
250 } | |
251 | |
252 cx->worker(cx, out, in, inLen); | |
253 if (outLen) | |
254 *outLen = inLen; | |
255 return SECSuccess; | |
256 } | |
257 | |
258 SECStatus | |
259 DES_Decrypt(DESContext *cx, BYTE *out, unsigned int *outLen, | |
260 unsigned int maxOutLen, const BYTE *in, unsigned int inLen) | |
261 { | |
262 | |
263 if ((inLen % 8) != 0 || maxOutLen < inLen || !cx || | |
264 cx->direction != DES_DECRYPT) { | |
265 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
266 return SECFailure; | |
267 } | |
268 | |
269 cx->worker(cx, out, in, inLen); | |
270 if (outLen) | |
271 *outLen = inLen; | |
272 return SECSuccess; | |
273 } | |
OLD | NEW |