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
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.
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 ***** */
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)
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]; \
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]; \
76 #define COPY8BTOHALF(to, from) COPY8B(to, from, from)
77 #define COPY8BFROMHALF(to, from) COPY8B(to, from, to)
80 DES_ECB(DESContext
*cx
, BYTE
*out
, const BYTE
*in
, unsigned int len
)
83 DES_Do1Block(cx
->ks0
, in
, out
);
91 DES_EDE3_ECB(DESContext
*cx
, BYTE
*out
, const BYTE
*in
, unsigned int len
)
94 DES_Do1Block(cx
->ks0
, in
, out
);
97 DES_Do1Block(cx
->ks1
, out
, out
);
98 DES_Do1Block(cx
->ks2
, out
, out
);
104 DES_CBCEn(DESContext
*cx
, BYTE
*out
, const BYTE
*in
, unsigned int len
)
106 const BYTE
* bufend
= in
+ len
;
109 while (in
!= bufend
) {
110 COPY8BTOHALF(vec
, in
);
114 DES_Do1Block( cx
->ks0
, (BYTE
*)vec
, (BYTE
*)cx
->iv
);
115 COPY8BFROMHALF(out
, cx
->iv
);
121 DES_CBCDe(DESContext
*cx
, BYTE
*out
, const BYTE
*in
, unsigned int len
)
124 HALF oldciphertext
[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
);
132 DES_Do1Block(cx
->ks0
, (BYTE
*)cx
->iv
, (BYTE
*)plaintext
);
133 plaintext
[0] ^= oldciphertext
[0];
134 plaintext
[1] ^= oldciphertext
[1];
135 COPY8BFROMHALF(out
, plaintext
);
141 DES_EDE3CBCEn(DESContext
*cx
, BYTE
*out
, const BYTE
*in
, unsigned int len
)
143 const BYTE
* bufend
= in
+ len
;
146 while (in
!= bufend
) {
147 COPY8BTOHALF(vec
, in
);
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
);
160 DES_EDE3CBCDe(DESContext
*cx
, BYTE
*out
, const BYTE
*in
, unsigned int len
)
163 HALF oldciphertext
[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
);
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
);
182 DES_AllocateContext(void)
184 return PORT_ZNew(DESContext
);
188 DES_InitContext(DESContext
*cx
, const unsigned char *key
, unsigned int keylen
,
189 const unsigned char *iv
, int mode
, unsigned int encrypt
,
192 DESDirection opposite
;
194 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
197 cx
->direction
= encrypt
? DES_ENCRYPT
: DES_DECRYPT
;
198 opposite
= encrypt
? DES_DECRYPT
: DES_ENCRYPT
;
200 case NSS_DES
: /* DES ECB */
201 DES_MakeSchedule( cx
->ks0
, key
, cx
->direction
);
202 cx
->worker
= &DES_ECB
;
205 case NSS_DES_EDE3
: /* DES EDE ECB */
206 cx
->worker
= &DES_EDE3_ECB
;
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
);
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
);
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
);
224 case NSS_DES_EDE3_CBC
: /* DES EDE CBC */
225 COPY8BTOHALF(cx
->iv
, iv
);
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
);
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
);
240 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
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
);
260 DES_DestroyContext(DESContext
*cx
, PRBool freeit
)
263 memset(cx
, 0, sizeof *cx
);
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
);
280 cx
->worker(cx
, out
, in
, inLen
);
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
);
297 cx
->worker(cx
, out
, in
, inLen
);