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 "blapii.h"
18 #include <stddef.h>
19 #include "secerr.h"
20
21 #if defined(NSS_X86_OR_X64)
22 /* Intel X86 CPUs do unaligned loads and stores without complaint. */
23 #define COPY8B(to, from, ptr) \
24 HALFPTR(to) \
25 [0] = HALFPTR(from)[0]; \
26 HALFPTR(to) \
27 [1] = HALFPTR(from)[1];
28 #else
29 #define COPY8B(to, from, ptr) memcpy(to, from, 8)
30 #endif
31 #define COPY8BTOHALF(to, from) COPY8B(to, from, from)
32 #define COPY8BFROMHALF(to, from) COPY8B(to, from, to)
33
34 static void
DES_ECB(DESContext * cx,BYTE * out,const BYTE * in,unsigned int len)35 DES_ECB(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
36 {
37 while (len) {
38 DES_Do1Block(cx->ks0, in, out);
39 len -= 8;
40 in += 8;
41 out += 8;
42 }
43 }
44
45 static void
DES_EDE3_ECB(DESContext * cx,BYTE * out,const BYTE * in,unsigned int len)46 DES_EDE3_ECB(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
47 {
48 while (len) {
49 DES_Do1Block(cx->ks0, in, out);
50 len -= 8;
51 in += 8;
52 DES_Do1Block(cx->ks1, out, out);
53 DES_Do1Block(cx->ks2, out, out);
54 out += 8;
55 }
56 }
57
58 static void NO_SANITIZE_ALIGNMENT
DES_CBCEn(DESContext * cx,BYTE * out,const BYTE * in,unsigned int len)59 DES_CBCEn(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
60 {
61 const BYTE *bufend = in + len;
62 HALF vec[2];
63
64 while (in != bufend) {
65 COPY8BTOHALF(vec, in);
66 in += 8;
67 vec[0] ^= cx->iv[0];
68 vec[1] ^= cx->iv[1];
69 DES_Do1Block(cx->ks0, (BYTE *)vec, (BYTE *)cx->iv);
70 COPY8BFROMHALF(out, cx->iv);
71 out += 8;
72 }
73 }
74
75 static void NO_SANITIZE_ALIGNMENT
DES_CBCDe(DESContext * cx,BYTE * out,const BYTE * in,unsigned int len)76 DES_CBCDe(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
77 {
78 const BYTE *bufend;
79 HALF oldciphertext[2];
80 HALF plaintext[2];
81
82 for (bufend = in + len; in != bufend;) {
83 oldciphertext[0] = cx->iv[0];
84 oldciphertext[1] = cx->iv[1];
85 COPY8BTOHALF(cx->iv, in);
86 in += 8;
87 DES_Do1Block(cx->ks0, (BYTE *)cx->iv, (BYTE *)plaintext);
88 plaintext[0] ^= oldciphertext[0];
89 plaintext[1] ^= oldciphertext[1];
90 COPY8BFROMHALF(out, plaintext);
91 out += 8;
92 }
93 }
94
95 static void NO_SANITIZE_ALIGNMENT
DES_EDE3CBCEn(DESContext * cx,BYTE * out,const BYTE * in,unsigned int len)96 DES_EDE3CBCEn(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
97 {
98 const BYTE *bufend = in + len;
99 HALF vec[2];
100
101 while (in != bufend) {
102 COPY8BTOHALF(vec, in);
103 in += 8;
104 vec[0] ^= cx->iv[0];
105 vec[1] ^= cx->iv[1];
106 DES_Do1Block(cx->ks0, (BYTE *)vec, (BYTE *)cx->iv);
107 DES_Do1Block(cx->ks1, (BYTE *)cx->iv, (BYTE *)cx->iv);
108 DES_Do1Block(cx->ks2, (BYTE *)cx->iv, (BYTE *)cx->iv);
109 COPY8BFROMHALF(out, cx->iv);
110 out += 8;
111 }
112 }
113
114 static void NO_SANITIZE_ALIGNMENT
DES_EDE3CBCDe(DESContext * cx,BYTE * out,const BYTE * in,unsigned int len)115 DES_EDE3CBCDe(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
116 {
117 const BYTE *bufend;
118 HALF oldciphertext[2];
119 HALF plaintext[2];
120
121 for (bufend = in + len; in != bufend;) {
122 oldciphertext[0] = cx->iv[0];
123 oldciphertext[1] = cx->iv[1];
124 COPY8BTOHALF(cx->iv, in);
125 in += 8;
126 DES_Do1Block(cx->ks0, (BYTE *)cx->iv, (BYTE *)plaintext);
127 DES_Do1Block(cx->ks1, (BYTE *)plaintext, (BYTE *)plaintext);
128 DES_Do1Block(cx->ks2, (BYTE *)plaintext, (BYTE *)plaintext);
129 plaintext[0] ^= oldciphertext[0];
130 plaintext[1] ^= oldciphertext[1];
131 COPY8BFROMHALF(out, plaintext);
132 out += 8;
133 }
134 }
135
136 DESContext *
DES_AllocateContext(void)137 DES_AllocateContext(void)
138 {
139 return PORT_ZNew(DESContext);
140 }
141
142 SECStatus
DES_InitContext(DESContext * cx,const unsigned char * key,unsigned int keylen,const unsigned char * iv,int mode,unsigned int encrypt,unsigned int unused)143 DES_InitContext(DESContext *cx, const unsigned char *key, unsigned int keylen,
144 const unsigned char *iv, int mode, unsigned int encrypt,
145 unsigned int unused)
146 {
147 DESDirection opposite;
148 if (!cx) {
149 PORT_SetError(SEC_ERROR_INVALID_ARGS);
150 return SECFailure;
151 }
152 cx->direction = encrypt ? DES_ENCRYPT : DES_DECRYPT;
153 opposite = encrypt ? DES_DECRYPT : DES_ENCRYPT;
154 switch (mode) {
155 case NSS_DES: /* DES ECB */
156 DES_MakeSchedule(cx->ks0, key, cx->direction);
157 cx->worker = &DES_ECB;
158 break;
159
160 case NSS_DES_EDE3: /* DES EDE ECB */
161 cx->worker = &DES_EDE3_ECB;
162 if (encrypt) {
163 DES_MakeSchedule(cx->ks0, key, cx->direction);
164 DES_MakeSchedule(cx->ks1, key + 8, opposite);
165 DES_MakeSchedule(cx->ks2, key + 16, cx->direction);
166 } else {
167 DES_MakeSchedule(cx->ks2, key, cx->direction);
168 DES_MakeSchedule(cx->ks1, key + 8, opposite);
169 DES_MakeSchedule(cx->ks0, key + 16, cx->direction);
170 }
171 break;
172
173 case NSS_DES_CBC: /* DES CBC */
174 COPY8BTOHALF(cx->iv, iv);
175 cx->worker = encrypt ? &DES_CBCEn : &DES_CBCDe;
176 DES_MakeSchedule(cx->ks0, key, cx->direction);
177 break;
178
179 case NSS_DES_EDE3_CBC: /* DES EDE CBC */
180 COPY8BTOHALF(cx->iv, iv);
181 if (encrypt) {
182 cx->worker = &DES_EDE3CBCEn;
183 DES_MakeSchedule(cx->ks0, key, cx->direction);
184 DES_MakeSchedule(cx->ks1, key + 8, opposite);
185 DES_MakeSchedule(cx->ks2, key + 16, cx->direction);
186 } else {
187 cx->worker = &DES_EDE3CBCDe;
188 DES_MakeSchedule(cx->ks2, key, cx->direction);
189 DES_MakeSchedule(cx->ks1, key + 8, opposite);
190 DES_MakeSchedule(cx->ks0, key + 16, cx->direction);
191 }
192 break;
193
194 default:
195 PORT_SetError(SEC_ERROR_INVALID_ARGS);
196 return SECFailure;
197 }
198 return SECSuccess;
199 }
200
201 DESContext *
DES_CreateContext(const BYTE * key,const BYTE * iv,int mode,PRBool encrypt)202 DES_CreateContext(const BYTE *key, const BYTE *iv, int mode, PRBool encrypt)
203 {
204 DESContext *cx = PORT_ZNew(DESContext);
205 SECStatus rv = DES_InitContext(cx, key, 0, iv, mode, encrypt, 0);
206
207 if (rv != SECSuccess) {
208 PORT_ZFree(cx, sizeof *cx);
209 cx = NULL;
210 }
211 return cx;
212 }
213
214 void
DES_DestroyContext(DESContext * cx,PRBool freeit)215 DES_DestroyContext(DESContext *cx, PRBool freeit)
216 {
217 if (cx) {
218 memset(cx, 0, sizeof *cx);
219 if (freeit)
220 PORT_Free(cx);
221 }
222 }
223
224 SECStatus
DES_Encrypt(DESContext * cx,BYTE * out,unsigned int * outLen,unsigned int maxOutLen,const BYTE * in,unsigned int inLen)225 DES_Encrypt(DESContext *cx, BYTE *out, unsigned int *outLen,
226 unsigned int maxOutLen, const BYTE *in, unsigned int inLen)
227 {
228
229 if ((inLen % 8) != 0 || maxOutLen < inLen || !cx ||
230 cx->direction != DES_ENCRYPT) {
231 PORT_SetError(SEC_ERROR_INVALID_ARGS);
232 return SECFailure;
233 }
234
235 cx->worker(cx, out, in, inLen);
236 if (outLen)
237 *outLen = inLen;
238 return SECSuccess;
239 }
240
241 SECStatus
DES_Decrypt(DESContext * cx,BYTE * out,unsigned int * outLen,unsigned int maxOutLen,const BYTE * in,unsigned int inLen)242 DES_Decrypt(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_DECRYPT) {
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