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