security/nss/lib/freebl/desblapi.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /*
michael@0 2 * desblapi.c
michael@0 3 *
michael@0 4 * core source file for DES-150 library
michael@0 5 * Implement DES Modes of Operation and Triple-DES.
michael@0 6 * Adapt DES-150 to blapi API.
michael@0 7 *
michael@0 8 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 9 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 10 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 11
michael@0 12 #ifdef FREEBL_NO_DEPEND
michael@0 13 #include "stubs.h"
michael@0 14 #endif
michael@0 15
michael@0 16 #include "des.h"
michael@0 17 #include <stddef.h>
michael@0 18 #include "secerr.h"
michael@0 19
michael@0 20 #if defined(NSS_X86_OR_X64)
michael@0 21 /* Intel X86 CPUs do unaligned loads and stores without complaint. */
michael@0 22 #define COPY8B(to, from, ptr) \
michael@0 23 HALFPTR(to)[0] = HALFPTR(from)[0]; \
michael@0 24 HALFPTR(to)[1] = HALFPTR(from)[1];
michael@0 25 #elif defined(USE_MEMCPY)
michael@0 26 #define COPY8B(to, from, ptr) memcpy(to, from, 8)
michael@0 27 #else
michael@0 28 #define COPY8B(to, from, ptr) \
michael@0 29 if (((ptrdiff_t)(ptr) & 0x3) == 0) { \
michael@0 30 HALFPTR(to)[0] = HALFPTR(from)[0]; \
michael@0 31 HALFPTR(to)[1] = HALFPTR(from)[1]; \
michael@0 32 } else if (((ptrdiff_t)(ptr) & 0x1) == 0) { \
michael@0 33 SHORTPTR(to)[0] = SHORTPTR(from)[0]; \
michael@0 34 SHORTPTR(to)[1] = SHORTPTR(from)[1]; \
michael@0 35 SHORTPTR(to)[2] = SHORTPTR(from)[2]; \
michael@0 36 SHORTPTR(to)[3] = SHORTPTR(from)[3]; \
michael@0 37 } else { \
michael@0 38 BYTEPTR(to)[0] = BYTEPTR(from)[0]; \
michael@0 39 BYTEPTR(to)[1] = BYTEPTR(from)[1]; \
michael@0 40 BYTEPTR(to)[2] = BYTEPTR(from)[2]; \
michael@0 41 BYTEPTR(to)[3] = BYTEPTR(from)[3]; \
michael@0 42 BYTEPTR(to)[4] = BYTEPTR(from)[4]; \
michael@0 43 BYTEPTR(to)[5] = BYTEPTR(from)[5]; \
michael@0 44 BYTEPTR(to)[6] = BYTEPTR(from)[6]; \
michael@0 45 BYTEPTR(to)[7] = BYTEPTR(from)[7]; \
michael@0 46 }
michael@0 47 #endif
michael@0 48 #define COPY8BTOHALF(to, from) COPY8B(to, from, from)
michael@0 49 #define COPY8BFROMHALF(to, from) COPY8B(to, from, to)
michael@0 50
michael@0 51 static void
michael@0 52 DES_ECB(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
michael@0 53 {
michael@0 54 while (len) {
michael@0 55 DES_Do1Block(cx->ks0, in, out);
michael@0 56 len -= 8;
michael@0 57 in += 8;
michael@0 58 out += 8;
michael@0 59 }
michael@0 60 }
michael@0 61
michael@0 62 static void
michael@0 63 DES_EDE3_ECB(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
michael@0 64 {
michael@0 65 while (len) {
michael@0 66 DES_Do1Block(cx->ks0, in, out);
michael@0 67 len -= 8;
michael@0 68 in += 8;
michael@0 69 DES_Do1Block(cx->ks1, out, out);
michael@0 70 DES_Do1Block(cx->ks2, out, out);
michael@0 71 out += 8;
michael@0 72 }
michael@0 73 }
michael@0 74
michael@0 75 static void
michael@0 76 DES_CBCEn(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
michael@0 77 {
michael@0 78 const BYTE * bufend = in + len;
michael@0 79 HALF vec[2];
michael@0 80
michael@0 81 while (in != bufend) {
michael@0 82 COPY8BTOHALF(vec, in);
michael@0 83 in += 8;
michael@0 84 vec[0] ^= cx->iv[0];
michael@0 85 vec[1] ^= cx->iv[1];
michael@0 86 DES_Do1Block( cx->ks0, (BYTE *)vec, (BYTE *)cx->iv);
michael@0 87 COPY8BFROMHALF(out, cx->iv);
michael@0 88 out += 8;
michael@0 89 }
michael@0 90 }
michael@0 91
michael@0 92 static void
michael@0 93 DES_CBCDe(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
michael@0 94 {
michael@0 95 const BYTE * bufend;
michael@0 96 HALF oldciphertext[2];
michael@0 97 HALF plaintext [2];
michael@0 98
michael@0 99 for (bufend = in + len; in != bufend; ) {
michael@0 100 oldciphertext[0] = cx->iv[0];
michael@0 101 oldciphertext[1] = cx->iv[1];
michael@0 102 COPY8BTOHALF(cx->iv, in);
michael@0 103 in += 8;
michael@0 104 DES_Do1Block(cx->ks0, (BYTE *)cx->iv, (BYTE *)plaintext);
michael@0 105 plaintext[0] ^= oldciphertext[0];
michael@0 106 plaintext[1] ^= oldciphertext[1];
michael@0 107 COPY8BFROMHALF(out, plaintext);
michael@0 108 out += 8;
michael@0 109 }
michael@0 110 }
michael@0 111
michael@0 112 static void
michael@0 113 DES_EDE3CBCEn(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
michael@0 114 {
michael@0 115 const BYTE * bufend = in + len;
michael@0 116 HALF vec[2];
michael@0 117
michael@0 118 while (in != bufend) {
michael@0 119 COPY8BTOHALF(vec, in);
michael@0 120 in += 8;
michael@0 121 vec[0] ^= cx->iv[0];
michael@0 122 vec[1] ^= cx->iv[1];
michael@0 123 DES_Do1Block( cx->ks0, (BYTE *)vec, (BYTE *)cx->iv);
michael@0 124 DES_Do1Block( cx->ks1, (BYTE *)cx->iv, (BYTE *)cx->iv);
michael@0 125 DES_Do1Block( cx->ks2, (BYTE *)cx->iv, (BYTE *)cx->iv);
michael@0 126 COPY8BFROMHALF(out, cx->iv);
michael@0 127 out += 8;
michael@0 128 }
michael@0 129 }
michael@0 130
michael@0 131 static void
michael@0 132 DES_EDE3CBCDe(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
michael@0 133 {
michael@0 134 const BYTE * bufend;
michael@0 135 HALF oldciphertext[2];
michael@0 136 HALF plaintext [2];
michael@0 137
michael@0 138 for (bufend = in + len; in != bufend; ) {
michael@0 139 oldciphertext[0] = cx->iv[0];
michael@0 140 oldciphertext[1] = cx->iv[1];
michael@0 141 COPY8BTOHALF(cx->iv, in);
michael@0 142 in += 8;
michael@0 143 DES_Do1Block(cx->ks0, (BYTE *)cx->iv, (BYTE *)plaintext);
michael@0 144 DES_Do1Block(cx->ks1, (BYTE *)plaintext, (BYTE *)plaintext);
michael@0 145 DES_Do1Block(cx->ks2, (BYTE *)plaintext, (BYTE *)plaintext);
michael@0 146 plaintext[0] ^= oldciphertext[0];
michael@0 147 plaintext[1] ^= oldciphertext[1];
michael@0 148 COPY8BFROMHALF(out, plaintext);
michael@0 149 out += 8;
michael@0 150 }
michael@0 151 }
michael@0 152
michael@0 153 DESContext *
michael@0 154 DES_AllocateContext(void)
michael@0 155 {
michael@0 156 return PORT_ZNew(DESContext);
michael@0 157 }
michael@0 158
michael@0 159 SECStatus
michael@0 160 DES_InitContext(DESContext *cx, const unsigned char *key, unsigned int keylen,
michael@0 161 const unsigned char *iv, int mode, unsigned int encrypt,
michael@0 162 unsigned int unused)
michael@0 163 {
michael@0 164 DESDirection opposite;
michael@0 165 if (!cx) {
michael@0 166 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 167 return SECFailure;
michael@0 168 }
michael@0 169 cx->direction = encrypt ? DES_ENCRYPT : DES_DECRYPT;
michael@0 170 opposite = encrypt ? DES_DECRYPT : DES_ENCRYPT;
michael@0 171 switch (mode) {
michael@0 172 case NSS_DES: /* DES ECB */
michael@0 173 DES_MakeSchedule( cx->ks0, key, cx->direction);
michael@0 174 cx->worker = &DES_ECB;
michael@0 175 break;
michael@0 176
michael@0 177 case NSS_DES_EDE3: /* DES EDE ECB */
michael@0 178 cx->worker = &DES_EDE3_ECB;
michael@0 179 if (encrypt) {
michael@0 180 DES_MakeSchedule(cx->ks0, key, cx->direction);
michael@0 181 DES_MakeSchedule(cx->ks1, key + 8, opposite);
michael@0 182 DES_MakeSchedule(cx->ks2, key + 16, cx->direction);
michael@0 183 } else {
michael@0 184 DES_MakeSchedule(cx->ks2, key, cx->direction);
michael@0 185 DES_MakeSchedule(cx->ks1, key + 8, opposite);
michael@0 186 DES_MakeSchedule(cx->ks0, key + 16, cx->direction);
michael@0 187 }
michael@0 188 break;
michael@0 189
michael@0 190 case NSS_DES_CBC: /* DES CBC */
michael@0 191 COPY8BTOHALF(cx->iv, iv);
michael@0 192 cx->worker = encrypt ? &DES_CBCEn : &DES_CBCDe;
michael@0 193 DES_MakeSchedule(cx->ks0, key, cx->direction);
michael@0 194 break;
michael@0 195
michael@0 196 case NSS_DES_EDE3_CBC: /* DES EDE CBC */
michael@0 197 COPY8BTOHALF(cx->iv, iv);
michael@0 198 if (encrypt) {
michael@0 199 cx->worker = &DES_EDE3CBCEn;
michael@0 200 DES_MakeSchedule(cx->ks0, key, cx->direction);
michael@0 201 DES_MakeSchedule(cx->ks1, key + 8, opposite);
michael@0 202 DES_MakeSchedule(cx->ks2, key + 16, cx->direction);
michael@0 203 } else {
michael@0 204 cx->worker = &DES_EDE3CBCDe;
michael@0 205 DES_MakeSchedule(cx->ks2, key, cx->direction);
michael@0 206 DES_MakeSchedule(cx->ks1, key + 8, opposite);
michael@0 207 DES_MakeSchedule(cx->ks0, key + 16, cx->direction);
michael@0 208 }
michael@0 209 break;
michael@0 210
michael@0 211 default:
michael@0 212 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 213 return SECFailure;
michael@0 214 }
michael@0 215 return SECSuccess;
michael@0 216 }
michael@0 217
michael@0 218 DESContext *
michael@0 219 DES_CreateContext(const BYTE * key, const BYTE *iv, int mode, PRBool encrypt)
michael@0 220 {
michael@0 221 DESContext *cx = PORT_ZNew(DESContext);
michael@0 222 SECStatus rv = DES_InitContext(cx, key, 0, iv, mode, encrypt, 0);
michael@0 223
michael@0 224 if (rv != SECSuccess) {
michael@0 225 PORT_ZFree(cx, sizeof *cx);
michael@0 226 cx = NULL;
michael@0 227 }
michael@0 228 return cx;
michael@0 229 }
michael@0 230
michael@0 231 void
michael@0 232 DES_DestroyContext(DESContext *cx, PRBool freeit)
michael@0 233 {
michael@0 234 if (cx) {
michael@0 235 memset(cx, 0, sizeof *cx);
michael@0 236 if (freeit)
michael@0 237 PORT_Free(cx);
michael@0 238 }
michael@0 239 }
michael@0 240
michael@0 241 SECStatus
michael@0 242 DES_Encrypt(DESContext *cx, BYTE *out, unsigned int *outLen,
michael@0 243 unsigned int maxOutLen, const BYTE *in, unsigned int inLen)
michael@0 244 {
michael@0 245
michael@0 246 if ((inLen % 8) != 0 || maxOutLen < inLen || !cx ||
michael@0 247 cx->direction != DES_ENCRYPT) {
michael@0 248 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 249 return SECFailure;
michael@0 250 }
michael@0 251
michael@0 252 cx->worker(cx, out, in, inLen);
michael@0 253 if (outLen)
michael@0 254 *outLen = inLen;
michael@0 255 return SECSuccess;
michael@0 256 }
michael@0 257
michael@0 258 SECStatus
michael@0 259 DES_Decrypt(DESContext *cx, BYTE *out, unsigned int *outLen,
michael@0 260 unsigned int maxOutLen, const BYTE *in, unsigned int inLen)
michael@0 261 {
michael@0 262
michael@0 263 if ((inLen % 8) != 0 || maxOutLen < inLen || !cx ||
michael@0 264 cx->direction != DES_DECRYPT) {
michael@0 265 PORT_SetError(SEC_ERROR_INVALID_ARGS);
michael@0 266 return SECFailure;
michael@0 267 }
michael@0 268
michael@0 269 cx->worker(cx, out, in, inLen);
michael@0 270 if (outLen)
michael@0 271 *outLen = inLen;
michael@0 272 return SECSuccess;
michael@0 273 }

mercurial