| 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 |