security/nss/lib/freebl/ctr.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.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #ifdef FREEBL_NO_DEPEND
     6 #include "stubs.h"
     7 #endif
     8 #include "prtypes.h"
     9 #include "blapit.h"
    10 #include "blapii.h"
    11 #include "ctr.h"
    12 #include "pkcs11t.h"
    13 #include "secerr.h"
    15 #ifdef USE_HW_AES
    16 #include "intel-aes.h"
    17 #include "rijndael.h"
    18 #endif
    20 SECStatus
    21 CTR_InitContext(CTRContext *ctr, void *context, freeblCipherFunc cipher,
    22 		const unsigned char *param, unsigned int blocksize)
    23 {
    24     const CK_AES_CTR_PARAMS *ctrParams = (const CK_AES_CTR_PARAMS *)param;
    26     if (ctrParams->ulCounterBits == 0 ||
    27 	ctrParams->ulCounterBits > blocksize * PR_BITS_PER_BYTE) {
    28 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
    29 	return SECFailure;
    30     }
    32     /* Invariant: 0 < ctr->bufPtr <= blocksize */
    33     ctr->bufPtr = blocksize; /* no unused data in the buffer */
    34     ctr->cipher = cipher;
    35     ctr->context = context;
    36     ctr->counterBits = ctrParams->ulCounterBits;
    37     if (blocksize > sizeof(ctr->counter) ||
    38 	blocksize > sizeof(ctrParams->cb)) {
    39 	PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
    40 	return SECFailure;
    41     }
    42     PORT_Memcpy(ctr->counter, ctrParams->cb, blocksize);
    43     return SECSuccess;
    44 }
    46 CTRContext *
    47 CTR_CreateContext(void *context, freeblCipherFunc cipher,
    48 		  const unsigned char *param, unsigned int blocksize)
    49 {
    50     CTRContext *ctr;
    51     SECStatus rv;
    53     /* first fill in the Counter context */
    54     ctr = PORT_ZNew(CTRContext);
    55     if (ctr == NULL) {
    56 	return NULL;
    57     }
    58     rv = CTR_InitContext(ctr, context, cipher, param, blocksize);
    59     if (rv != SECSuccess) {
    60 	CTR_DestroyContext(ctr, PR_TRUE);
    61 	ctr = NULL;
    62     }
    63     return ctr;
    64 }
    66 void
    67 CTR_DestroyContext(CTRContext *ctr, PRBool freeit)
    68 {
    69     PORT_Memset(ctr, 0, sizeof(CTRContext));
    70     if (freeit) {
    71 	PORT_Free(ctr);
    72     }
    73 }
    75 /*
    76  * Used by counter mode. Increment the counter block. Not all bits in the
    77  * counter block are part of the counter, counterBits tells how many bits
    78  * are part of the counter. The counter block is blocksize long. It's a
    79  * big endian value.
    80  *
    81  * XXX Does not handle counter rollover.
    82  */
    83 static void
    84 ctr_GetNextCtr(unsigned char *counter, unsigned int counterBits,
    85 	       unsigned int blocksize)
    86 {
    87     unsigned char *counterPtr = counter + blocksize - 1;
    88     unsigned char mask, count;
    90     PORT_Assert(counterBits <= blocksize*PR_BITS_PER_BYTE);
    91     while (counterBits >= PR_BITS_PER_BYTE) {
    92 	if (++(*(counterPtr--))) {
    93 	    return;
    94 	}
    95 	counterBits -= PR_BITS_PER_BYTE;
    96     }
    97     if (counterBits == 0) {
    98 	return;
    99     }
   100     /* increment the final partial byte */
   101     mask = (1 << counterBits)-1;
   102     count = ++(*counterPtr) & mask;
   103     *counterPtr = ((*counterPtr) & ~mask) | count;
   104     return;
   105 }
   107 static void
   108 ctr_xor(unsigned char *target, const unsigned char *x,
   109 	const unsigned char *y, unsigned int count)
   110 {
   111     unsigned int i;
   112     for (i=0; i < count; i++) {
   113 	*target++ = *x++ ^ *y++;
   114     }
   115 }
   117 SECStatus
   118 CTR_Update(CTRContext *ctr, unsigned char *outbuf,
   119 	   unsigned int *outlen, unsigned int maxout,
   120 	   const unsigned char *inbuf, unsigned int inlen,
   121 	   unsigned int blocksize)
   122 {
   123     unsigned int tmp;
   124     SECStatus rv;
   126     if (maxout < inlen) {
   127 	*outlen = inlen;
   128 	PORT_SetError(SEC_ERROR_OUTPUT_LEN);
   129 	return SECFailure;
   130     }
   131     *outlen = 0;
   132     if (ctr->bufPtr != blocksize) {
   133 	unsigned int needed = PR_MIN(blocksize-ctr->bufPtr, inlen);
   134 	ctr_xor(outbuf, inbuf, ctr->buffer + ctr->bufPtr, needed);
   135 	ctr->bufPtr += needed;
   136 	outbuf += needed;
   137 	inbuf += needed;
   138 	*outlen += needed;
   139 	inlen -= needed;
   140 	if (inlen == 0) {
   141 	    return SECSuccess;
   142 	}
   143 	PORT_Assert(ctr->bufPtr == blocksize);
   144     }
   146     while (inlen >= blocksize) {
   147 	rv = (*ctr->cipher)(ctr->context, ctr->buffer, &tmp, blocksize,
   148 			ctr->counter, blocksize, blocksize);
   149 	ctr_GetNextCtr(ctr->counter, ctr->counterBits, blocksize);
   150 	if (rv != SECSuccess) {
   151 	    return SECFailure;
   152 	}
   153 	ctr_xor(outbuf, inbuf, ctr->buffer, blocksize);
   154 	outbuf += blocksize;
   155 	inbuf += blocksize;
   156 	*outlen += blocksize;
   157 	inlen -= blocksize;
   158     }
   159     if (inlen == 0) {
   160 	return SECSuccess;
   161     }
   162     rv = (*ctr->cipher)(ctr->context, ctr->buffer, &tmp, blocksize,
   163 			ctr->counter, blocksize, blocksize);
   164     ctr_GetNextCtr(ctr->counter, ctr->counterBits, blocksize);
   165     if (rv != SECSuccess) {
   166 	return SECFailure;
   167     }
   168     ctr_xor(outbuf, inbuf, ctr->buffer, inlen);
   169     ctr->bufPtr = inlen;
   170     *outlen += inlen;
   171     return SECSuccess;
   172 }
   174 #if defined(USE_HW_AES) && defined(_MSC_VER)
   175 SECStatus
   176 CTR_Update_HW_AES(CTRContext *ctr, unsigned char *outbuf,
   177 		  unsigned int *outlen, unsigned int maxout,
   178 		  const unsigned char *inbuf, unsigned int inlen,
   179 		  unsigned int blocksize)
   180 {
   181     unsigned int fullblocks;
   182     unsigned int tmp;
   183     SECStatus rv;
   185     if (maxout < inlen) {
   186 	*outlen = inlen;
   187 	PORT_SetError(SEC_ERROR_OUTPUT_LEN);
   188 	return SECFailure;
   189     }
   190     *outlen = 0;
   191     if (ctr->bufPtr != blocksize) {
   192 	unsigned int needed = PR_MIN(blocksize-ctr->bufPtr, inlen);
   193 	ctr_xor(outbuf, inbuf, ctr->buffer + ctr->bufPtr, needed);
   194 	ctr->bufPtr += needed;
   195 	outbuf += needed;
   196 	inbuf += needed;
   197 	*outlen += needed;
   198 	inlen -= needed;
   199 	if (inlen == 0) {
   200 	    return SECSuccess;
   201 	}
   202 	PORT_Assert(ctr->bufPtr == blocksize);
   203     }
   205     intel_aes_ctr_worker(((AESContext*)(ctr->context))->Nr)(
   206 	ctr, outbuf, outlen, maxout, inbuf, inlen, blocksize);
   207     /* XXX intel_aes_ctr_worker should set *outlen. */
   208     PORT_Assert(*outlen == 0);
   209     fullblocks = (inlen/blocksize)*blocksize;
   210     *outlen += fullblocks;
   211     outbuf += fullblocks;
   212     inbuf += fullblocks;
   213     inlen -= fullblocks;
   215     if (inlen == 0) {
   216 	return SECSuccess;
   217     }
   218     rv = (*ctr->cipher)(ctr->context, ctr->buffer, &tmp, blocksize,
   219 			ctr->counter, blocksize, blocksize);
   220     ctr_GetNextCtr(ctr->counter, ctr->counterBits, blocksize);
   221     if (rv != SECSuccess) {
   222 	return SECFailure;
   223     }
   224     ctr_xor(outbuf, inbuf, ctr->buffer, inlen);
   225     ctr->bufPtr = inlen;
   226     *outlen += inlen;
   227     return SECSuccess;
   228 }
   229 #endif

mercurial