Import from 1.9a8 tarball
[mozilla-nss.git] / security / nss / lib / freebl / desblapi.c
blobb9b3288ac1bfb7505f0f70236275f66ab6ccdc69
1 /*
2 * desblapi.c
4 * core source file for DES-150 library
5 * Implement DES Modes of Operation and Triple-DES.
6 * Adapt DES-150 to blapi API.
8 * ***** BEGIN LICENSE BLOCK *****
9 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
11 * The contents of this file are subject to the Mozilla Public License Version
12 * 1.1 (the "License"); you may not use this file except in compliance with
13 * the License. You may obtain a copy of the License at
14 * http://www.mozilla.org/MPL/
16 * Software distributed under the License is distributed on an "AS IS" basis,
17 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
18 * for the specific language governing rights and limitations under the
19 * License.
21 * The Original Code is the DES-150 library.
23 * The Initial Developer of the Original Code is
24 * Nelson B. Bolyard, nelsonb@iname.com.
25 * Portions created by the Initial Developer are Copyright (C) 1990
26 * the Initial Developer. All Rights Reserved.
28 * Contributor(s):
30 * Alternatively, the contents of this file may be used under the terms of
31 * either the GNU General Public License Version 2 or later (the "GPL"), or
32 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
33 * in which case the provisions of the GPL or the LGPL are applicable instead
34 * of those above. If you wish to allow use of your version of this file only
35 * under the terms of either the GPL or the LGPL, and not to allow others to
36 * use your version of this file under the terms of the MPL, indicate your
37 * decision by deleting the provisions above and replace them with the notice
38 * and other provisions required by the GPL or the LGPL. If you do not delete
39 * the provisions above, a recipient may use your version of this file under
40 * the terms of any one of the MPL, the GPL or the LGPL.
42 * ***** END LICENSE BLOCK ***** */
44 #include "des.h"
45 #include <stddef.h>
46 #include "secerr.h"
48 #if defined(_X86_)
49 /* Intel X86 CPUs do unaligned loads and stores without complaint. */
50 #define COPY8B(to, from, ptr) \
51 HALFPTR(to)[0] = HALFPTR(from)[0]; \
52 HALFPTR(to)[1] = HALFPTR(from)[1];
53 #elif defined(USE_MEMCPY)
54 #define COPY8B(to, from, ptr) memcpy(to, from, 8)
55 #else
56 #define COPY8B(to, from, ptr) \
57 if (((ptrdiff_t)(ptr) & 0x3) == 0) { \
58 HALFPTR(to)[0] = HALFPTR(from)[0]; \
59 HALFPTR(to)[1] = HALFPTR(from)[1]; \
60 } else if (((ptrdiff_t)(ptr) & 0x1) == 0) { \
61 SHORTPTR(to)[0] = SHORTPTR(from)[0]; \
62 SHORTPTR(to)[1] = SHORTPTR(from)[1]; \
63 SHORTPTR(to)[2] = SHORTPTR(from)[2]; \
64 SHORTPTR(to)[3] = SHORTPTR(from)[3]; \
65 } else { \
66 BYTEPTR(to)[0] = BYTEPTR(from)[0]; \
67 BYTEPTR(to)[1] = BYTEPTR(from)[1]; \
68 BYTEPTR(to)[2] = BYTEPTR(from)[2]; \
69 BYTEPTR(to)[3] = BYTEPTR(from)[3]; \
70 BYTEPTR(to)[4] = BYTEPTR(from)[4]; \
71 BYTEPTR(to)[5] = BYTEPTR(from)[5]; \
72 BYTEPTR(to)[6] = BYTEPTR(from)[6]; \
73 BYTEPTR(to)[7] = BYTEPTR(from)[7]; \
75 #endif
76 #define COPY8BTOHALF(to, from) COPY8B(to, from, from)
77 #define COPY8BFROMHALF(to, from) COPY8B(to, from, to)
79 static void
80 DES_ECB(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
82 while (len) {
83 DES_Do1Block(cx->ks0, in, out);
84 len -= 8;
85 in += 8;
86 out += 8;
90 static void
91 DES_EDE3_ECB(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
93 while (len) {
94 DES_Do1Block(cx->ks0, in, out);
95 len -= 8;
96 in += 8;
97 DES_Do1Block(cx->ks1, out, out);
98 DES_Do1Block(cx->ks2, out, out);
99 out += 8;
103 static void
104 DES_CBCEn(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
106 const BYTE * bufend = in + len;
107 HALF vec[2];
109 while (in != bufend) {
110 COPY8BTOHALF(vec, in);
111 in += 8;
112 vec[0] ^= cx->iv[0];
113 vec[1] ^= cx->iv[1];
114 DES_Do1Block( cx->ks0, (BYTE *)vec, (BYTE *)cx->iv);
115 COPY8BFROMHALF(out, cx->iv);
116 out += 8;
120 static void
121 DES_CBCDe(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
123 const BYTE * bufend;
124 HALF oldciphertext[2];
125 HALF plaintext [2];
127 for (bufend = in + len; in != bufend; ) {
128 oldciphertext[0] = cx->iv[0];
129 oldciphertext[1] = cx->iv[1];
130 COPY8BTOHALF(cx->iv, in);
131 in += 8;
132 DES_Do1Block(cx->ks0, (BYTE *)cx->iv, (BYTE *)plaintext);
133 plaintext[0] ^= oldciphertext[0];
134 plaintext[1] ^= oldciphertext[1];
135 COPY8BFROMHALF(out, plaintext);
136 out += 8;
140 static void
141 DES_EDE3CBCEn(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
143 const BYTE * bufend = in + len;
144 HALF vec[2];
146 while (in != bufend) {
147 COPY8BTOHALF(vec, in);
148 in += 8;
149 vec[0] ^= cx->iv[0];
150 vec[1] ^= cx->iv[1];
151 DES_Do1Block( cx->ks0, (BYTE *)vec, (BYTE *)cx->iv);
152 DES_Do1Block( cx->ks1, (BYTE *)cx->iv, (BYTE *)cx->iv);
153 DES_Do1Block( cx->ks2, (BYTE *)cx->iv, (BYTE *)cx->iv);
154 COPY8BFROMHALF(out, cx->iv);
155 out += 8;
159 static void
160 DES_EDE3CBCDe(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
162 const BYTE * bufend;
163 HALF oldciphertext[2];
164 HALF plaintext [2];
166 for (bufend = in + len; in != bufend; ) {
167 oldciphertext[0] = cx->iv[0];
168 oldciphertext[1] = cx->iv[1];
169 COPY8BTOHALF(cx->iv, in);
170 in += 8;
171 DES_Do1Block(cx->ks0, (BYTE *)cx->iv, (BYTE *)plaintext);
172 DES_Do1Block(cx->ks1, (BYTE *)plaintext, (BYTE *)plaintext);
173 DES_Do1Block(cx->ks2, (BYTE *)plaintext, (BYTE *)plaintext);
174 plaintext[0] ^= oldciphertext[0];
175 plaintext[1] ^= oldciphertext[1];
176 COPY8BFROMHALF(out, plaintext);
177 out += 8;
181 DESContext *
182 DES_AllocateContext(void)
184 return PORT_ZNew(DESContext);
187 SECStatus
188 DES_InitContext(DESContext *cx, const unsigned char *key, unsigned int keylen,
189 const unsigned char *iv, int mode, unsigned int encrypt,
190 unsigned int unused)
192 DESDirection opposite;
193 if (!cx) {
194 PORT_SetError(SEC_ERROR_INVALID_ARGS);
195 return SECFailure;
197 cx->direction = encrypt ? DES_ENCRYPT : DES_DECRYPT;
198 opposite = encrypt ? DES_DECRYPT : DES_ENCRYPT;
199 switch (mode) {
200 case NSS_DES: /* DES ECB */
201 DES_MakeSchedule( cx->ks0, key, cx->direction);
202 cx->worker = &DES_ECB;
203 break;
205 case NSS_DES_EDE3: /* DES EDE ECB */
206 cx->worker = &DES_EDE3_ECB;
207 if (encrypt) {
208 DES_MakeSchedule(cx->ks0, key, cx->direction);
209 DES_MakeSchedule(cx->ks1, key + 8, opposite);
210 DES_MakeSchedule(cx->ks2, key + 16, cx->direction);
211 } else {
212 DES_MakeSchedule(cx->ks2, key, cx->direction);
213 DES_MakeSchedule(cx->ks1, key + 8, opposite);
214 DES_MakeSchedule(cx->ks0, key + 16, cx->direction);
216 break;
218 case NSS_DES_CBC: /* DES CBC */
219 COPY8BTOHALF(cx->iv, iv);
220 cx->worker = encrypt ? &DES_CBCEn : &DES_CBCDe;
221 DES_MakeSchedule(cx->ks0, key, cx->direction);
222 break;
224 case NSS_DES_EDE3_CBC: /* DES EDE CBC */
225 COPY8BTOHALF(cx->iv, iv);
226 if (encrypt) {
227 cx->worker = &DES_EDE3CBCEn;
228 DES_MakeSchedule(cx->ks0, key, cx->direction);
229 DES_MakeSchedule(cx->ks1, key + 8, opposite);
230 DES_MakeSchedule(cx->ks2, key + 16, cx->direction);
231 } else {
232 cx->worker = &DES_EDE3CBCDe;
233 DES_MakeSchedule(cx->ks2, key, cx->direction);
234 DES_MakeSchedule(cx->ks1, key + 8, opposite);
235 DES_MakeSchedule(cx->ks0, key + 16, cx->direction);
237 break;
239 default:
240 PORT_SetError(SEC_ERROR_INVALID_ARGS);
241 return SECFailure;
243 return SECSuccess;
246 DESContext *
247 DES_CreateContext(const BYTE * key, const BYTE *iv, int mode, PRBool encrypt)
249 DESContext *cx = PORT_ZNew(DESContext);
250 SECStatus rv = DES_InitContext(cx, key, 0, iv, mode, encrypt, 0);
252 if (rv != SECSuccess) {
253 PORT_ZFree(cx, sizeof *cx);
254 cx = NULL;
256 return cx;
259 void
260 DES_DestroyContext(DESContext *cx, PRBool freeit)
262 if (cx) {
263 memset(cx, 0, sizeof *cx);
264 if (freeit)
265 PORT_Free(cx);
269 SECStatus
270 DES_Encrypt(DESContext *cx, BYTE *out, unsigned int *outLen,
271 unsigned int maxOutLen, const BYTE *in, unsigned int inLen)
274 if (inLen < 0 || (inLen % 8) != 0 || maxOutLen < inLen || !cx ||
275 cx->direction != DES_ENCRYPT) {
276 PORT_SetError(SEC_ERROR_INVALID_ARGS);
277 return SECFailure;
280 cx->worker(cx, out, in, inLen);
281 if (outLen)
282 *outLen = inLen;
283 return SECSuccess;
286 SECStatus
287 DES_Decrypt(DESContext *cx, BYTE *out, unsigned int *outLen,
288 unsigned int maxOutLen, const BYTE *in, unsigned int inLen)
291 if (inLen < 0 || (inLen % 8) != 0 || maxOutLen < inLen || !cx ||
292 cx->direction != DES_DECRYPT) {
293 PORT_SetError(SEC_ERROR_INVALID_ARGS);
294 return SECFailure;
297 cx->worker(cx, out, in, inLen);
298 if (outLen)
299 *outLen = inLen;
300 return SECSuccess;