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