PageRenderTime 33ms CodeModel.GetById 10ms app.highlight 18ms RepoModel.GetById 2ms app.codeStats 0ms

/security/nss/lib/freebl/desblapi.c

http://github.com/zpao/v8monkey
C | 305 lines | 234 code | 28 blank | 43 comment | 42 complexity | 21c3b84cc92f9caff97cefdd71062217 MD5 | raw file
  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 * ***** BEGIN LICENSE BLOCK *****
  9 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 10 *
 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/
 15 *
 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.
 20 *
 21 * The Original Code is the DES-150 library.
 22 *
 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.
 27 *
 28 * Contributor(s):
 29 *
 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.
 41 *
 42 * ***** END LICENSE BLOCK ***** */
 43
 44#ifdef FREEBL_NO_DEPEND
 45#include "stubs.h"
 46#endif
 47
 48#include "des.h"
 49#include <stddef.h>
 50#include "secerr.h"
 51
 52#if defined(NSS_X86_OR_X64)
 53/* Intel X86 CPUs do unaligned loads and stores without complaint. */
 54#define COPY8B(to, from, ptr) \
 55    	HALFPTR(to)[0] = HALFPTR(from)[0]; \
 56    	HALFPTR(to)[1] = HALFPTR(from)[1]; 
 57#elif defined(USE_MEMCPY)
 58#define COPY8B(to, from, ptr) memcpy(to, from, 8)
 59#else
 60#define COPY8B(to, from, ptr) \
 61    if (((ptrdiff_t)(ptr) & 0x3) == 0) { \
 62    	HALFPTR(to)[0] = HALFPTR(from)[0]; \
 63    	HALFPTR(to)[1] = HALFPTR(from)[1]; \
 64    } else if (((ptrdiff_t)(ptr) & 0x1) == 0) { \
 65    	SHORTPTR(to)[0] = SHORTPTR(from)[0]; \
 66    	SHORTPTR(to)[1] = SHORTPTR(from)[1]; \
 67    	SHORTPTR(to)[2] = SHORTPTR(from)[2]; \
 68    	SHORTPTR(to)[3] = SHORTPTR(from)[3]; \
 69    } else { \
 70    	BYTEPTR(to)[0] = BYTEPTR(from)[0]; \
 71    	BYTEPTR(to)[1] = BYTEPTR(from)[1]; \
 72    	BYTEPTR(to)[2] = BYTEPTR(from)[2]; \
 73    	BYTEPTR(to)[3] = BYTEPTR(from)[3]; \
 74    	BYTEPTR(to)[4] = BYTEPTR(from)[4]; \
 75    	BYTEPTR(to)[5] = BYTEPTR(from)[5]; \
 76    	BYTEPTR(to)[6] = BYTEPTR(from)[6]; \
 77    	BYTEPTR(to)[7] = BYTEPTR(from)[7]; \
 78    } 
 79#endif
 80#define COPY8BTOHALF(to, from) COPY8B(to, from, from)
 81#define COPY8BFROMHALF(to, from) COPY8B(to, from, to)
 82
 83static void 
 84DES_ECB(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
 85{
 86    while (len) {
 87	DES_Do1Block(cx->ks0, in, out);
 88	len -= 8;
 89	in  += 8;
 90	out += 8;
 91    }
 92}
 93
 94static void 
 95DES_EDE3_ECB(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
 96{
 97    while (len) {
 98	DES_Do1Block(cx->ks0,  in, out);
 99	len -= 8;
100	in  += 8;
101	DES_Do1Block(cx->ks1, out, out);
102	DES_Do1Block(cx->ks2, out, out);
103	out += 8;
104    }
105}
106
107static void 
108DES_CBCEn(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
109{
110    const BYTE * bufend = in + len;
111    HALF  vec[2];
112
113    while (in != bufend) {
114	COPY8BTOHALF(vec, in);
115	in += 8;
116	vec[0] ^= cx->iv[0];
117	vec[1] ^= cx->iv[1];
118	DES_Do1Block( cx->ks0, (BYTE *)vec, (BYTE *)cx->iv);
119	COPY8BFROMHALF(out, cx->iv);
120	out += 8;
121    }
122}
123
124static void 
125DES_CBCDe(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
126{
127    const BYTE * bufend;
128    HALF oldciphertext[2];
129    HALF plaintext    [2];
130
131    for (bufend = in + len; in != bufend; ) {
132	oldciphertext[0] = cx->iv[0];
133	oldciphertext[1] = cx->iv[1];
134	COPY8BTOHALF(cx->iv, in);
135	in += 8;
136	DES_Do1Block(cx->ks0, (BYTE *)cx->iv, (BYTE *)plaintext);
137	plaintext[0] ^= oldciphertext[0];
138	plaintext[1] ^= oldciphertext[1];
139	COPY8BFROMHALF(out, plaintext);
140	out += 8;
141    }
142}
143
144static void 
145DES_EDE3CBCEn(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
146{
147    const BYTE * bufend = in + len;
148    HALF  vec[2];
149
150    while (in != bufend) {
151	COPY8BTOHALF(vec, in);
152	in += 8;
153	vec[0] ^= cx->iv[0];
154	vec[1] ^= cx->iv[1];
155	DES_Do1Block( cx->ks0, (BYTE *)vec,    (BYTE *)cx->iv);
156	DES_Do1Block( cx->ks1, (BYTE *)cx->iv, (BYTE *)cx->iv);
157	DES_Do1Block( cx->ks2, (BYTE *)cx->iv, (BYTE *)cx->iv);
158	COPY8BFROMHALF(out, cx->iv);
159	out += 8;
160    }
161}
162
163static void 
164DES_EDE3CBCDe(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
165{
166    const BYTE * bufend;
167    HALF oldciphertext[2];
168    HALF plaintext    [2];
169
170    for (bufend = in + len; in != bufend; ) {
171	oldciphertext[0] = cx->iv[0];
172	oldciphertext[1] = cx->iv[1];
173	COPY8BTOHALF(cx->iv, in);
174	in += 8;
175	DES_Do1Block(cx->ks0, (BYTE *)cx->iv,    (BYTE *)plaintext);
176	DES_Do1Block(cx->ks1, (BYTE *)plaintext, (BYTE *)plaintext);
177	DES_Do1Block(cx->ks2, (BYTE *)plaintext, (BYTE *)plaintext);
178	plaintext[0] ^= oldciphertext[0];
179	plaintext[1] ^= oldciphertext[1];
180	COPY8BFROMHALF(out, plaintext);
181	out += 8;
182    }
183}
184
185DESContext *
186DES_AllocateContext(void)
187{
188    return PORT_ZNew(DESContext);
189}
190
191SECStatus   
192DES_InitContext(DESContext *cx, const unsigned char *key, unsigned int keylen,
193	        const unsigned char *iv, int mode, unsigned int encrypt,
194	        unsigned int unused)
195{
196    DESDirection opposite;
197    if (!cx) {
198	PORT_SetError(SEC_ERROR_INVALID_ARGS);
199    	return SECFailure;
200    }
201    cx->direction = encrypt ? DES_ENCRYPT : DES_DECRYPT;
202    opposite      = encrypt ? DES_DECRYPT : DES_ENCRYPT;
203    switch (mode) {
204    case NSS_DES:	/* DES ECB */
205	DES_MakeSchedule( cx->ks0, key, cx->direction);
206	cx->worker = &DES_ECB;
207	break;
208
209    case NSS_DES_EDE3:	/* DES EDE ECB */
210	cx->worker = &DES_EDE3_ECB;
211	if (encrypt) {
212	    DES_MakeSchedule(cx->ks0, key,      cx->direction);
213	    DES_MakeSchedule(cx->ks1, key +  8, opposite);
214	    DES_MakeSchedule(cx->ks2, key + 16, cx->direction);
215	} else {
216	    DES_MakeSchedule(cx->ks2, key,      cx->direction);
217	    DES_MakeSchedule(cx->ks1, key +  8, opposite);
218	    DES_MakeSchedule(cx->ks0, key + 16, cx->direction);
219	}
220	break;
221
222    case NSS_DES_CBC:	/* DES CBC */
223	COPY8BTOHALF(cx->iv, iv);
224	cx->worker = encrypt ? &DES_CBCEn : &DES_CBCDe;
225	DES_MakeSchedule(cx->ks0, key, cx->direction);
226	break;
227
228    case NSS_DES_EDE3_CBC:	/* DES EDE CBC */
229	COPY8BTOHALF(cx->iv, iv);
230	if (encrypt) {
231	    cx->worker = &DES_EDE3CBCEn;
232	    DES_MakeSchedule(cx->ks0, key,      cx->direction);
233	    DES_MakeSchedule(cx->ks1, key +  8, opposite);
234	    DES_MakeSchedule(cx->ks2, key + 16, cx->direction);
235	} else {
236	    cx->worker = &DES_EDE3CBCDe;
237	    DES_MakeSchedule(cx->ks2, key,      cx->direction);
238	    DES_MakeSchedule(cx->ks1, key +  8, opposite);
239	    DES_MakeSchedule(cx->ks0, key + 16, cx->direction);
240	}
241	break;
242
243    default:
244	PORT_SetError(SEC_ERROR_INVALID_ARGS);
245	return SECFailure;
246    }
247    return SECSuccess;
248}
249
250DESContext *
251DES_CreateContext(const BYTE * key, const BYTE *iv, int mode, PRBool encrypt)
252{
253    DESContext *cx = PORT_ZNew(DESContext);
254    SECStatus rv   = DES_InitContext(cx, key, 0, iv, mode, encrypt, 0);
255
256    if (rv != SECSuccess) {
257    	PORT_ZFree(cx, sizeof *cx);
258	cx = NULL;
259    }
260    return cx;
261}
262
263void
264DES_DestroyContext(DESContext *cx, PRBool freeit)
265{
266    if (cx) {
267    	memset(cx, 0, sizeof *cx);
268	if (freeit)
269	    PORT_Free(cx);
270    }
271}
272
273SECStatus
274DES_Encrypt(DESContext *cx, BYTE *out, unsigned int *outLen,
275            unsigned int maxOutLen, const BYTE *in, unsigned int inLen)
276{
277
278    if (inLen < 0 || (inLen % 8) != 0 || maxOutLen < inLen || !cx || 
279        cx->direction != DES_ENCRYPT) {
280    	PORT_SetError(SEC_ERROR_INVALID_ARGS);
281	return SECFailure;
282    }
283
284    cx->worker(cx, out, in, inLen);
285    if (outLen)
286	*outLen = inLen;
287    return SECSuccess;
288}
289
290SECStatus
291DES_Decrypt(DESContext *cx, BYTE *out, unsigned int *outLen,
292            unsigned int maxOutLen, const BYTE *in, unsigned int inLen)
293{
294
295    if (inLen < 0 || (inLen % 8) != 0 || maxOutLen < inLen || !cx || 
296        cx->direction != DES_DECRYPT) {
297    	PORT_SetError(SEC_ERROR_INVALID_ARGS);
298	return SECFailure;
299    }
300
301    cx->worker(cx, out, in, inLen);
302    if (outLen)
303	*outLen = inLen;
304    return SECSuccess;
305}