security/nss/lib/freebl/desblapi.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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/. */
    12 #ifdef FREEBL_NO_DEPEND
    13 #include "stubs.h"
    14 #endif
    16 #include "des.h"
    17 #include <stddef.h>
    18 #include "secerr.h"
    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)
    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 }
    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 }
    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];
    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 }
    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];
    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 }
   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];
   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 }
   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];
   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 }
   153 DESContext *
   154 DES_AllocateContext(void)
   155 {
   156     return PORT_ZNew(DESContext);
   157 }
   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;
   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;
   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;
   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;
   211     default:
   212 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
   213 	return SECFailure;
   214     }
   215     return SECSuccess;
   216 }
   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);
   224     if (rv != SECSuccess) {
   225     	PORT_ZFree(cx, sizeof *cx);
   226 	cx = NULL;
   227     }
   228     return cx;
   229 }
   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 }
   241 SECStatus
   242 DES_Encrypt(DESContext *cx, BYTE *out, unsigned int *outLen,
   243             unsigned int maxOutLen, const BYTE *in, unsigned int inLen)
   244 {
   246     if ((inLen % 8) != 0 || maxOutLen < inLen || !cx || 
   247         cx->direction != DES_ENCRYPT) {
   248     	PORT_SetError(SEC_ERROR_INVALID_ARGS);
   249 	return SECFailure;
   250     }
   252     cx->worker(cx, out, in, inLen);
   253     if (outLen)
   254 	*outLen = inLen;
   255     return SECSuccess;
   256 }
   258 SECStatus
   259 DES_Decrypt(DESContext *cx, BYTE *out, unsigned int *outLen,
   260             unsigned int maxOutLen, const BYTE *in, unsigned int inLen)
   261 {
   263     if ((inLen % 8) != 0 || maxOutLen < inLen || !cx || 
   264         cx->direction != DES_DECRYPT) {
   265     	PORT_SetError(SEC_ERROR_INVALID_ARGS);
   266 	return SECFailure;
   267     }
   269     cx->worker(cx, out, in, inLen);
   270     if (outLen)
   271 	*outLen = inLen;
   272     return SECSuccess;
   273 }

mercurial