Chromium Code Reviews| Index: nss/mozilla/security/nss/lib/freebl/ctr.c |
| =================================================================== |
| --- nss/mozilla/security/nss/lib/freebl/ctr.c (revision 0) |
| +++ nss/mozilla/security/nss/lib/freebl/ctr.c (revision 0) |
| @@ -0,0 +1,154 @@ |
| +/* This Source Code Form is subject to the terms of the Mozilla Public |
| + * License, v. 2.0. If a copy of the MPL was not distributed with this |
| + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
| +/* $Id: gsm.c,v 1.27 2012/04/25 14:49:43 gerv%gerv.net Exp $ */ |
| + |
| +#ifdef FREEBL_NO_DEPEND |
| +#include "stubs.h" |
| +#endif |
| +#include "prtypes.h" |
| +#include "blapit.h" |
| +#include "blapii.h" |
| +#include "ctr.h" |
| +#include "pkcs11t.h" |
| +#include "secerr.h" |
| + |
| +SECStatus |
| +CTR_InitContext(CTRContext *ctr, void *context, freeblCipherFunc cipher, |
| + const unsigned char *param, unsigned int blocksize) |
| +{ |
| + const CK_AES_CTR_PARAMS *ctrParams = (const CK_AES_CTR_PARAMS *)param; |
| + |
| + ctr->bufPtr = blocksize; /* no unused data in the buffer */ |
| + ctr->cipher = cipher; |
| + ctr->context = context; |
| + ctr->counterBits = ctrParams->ulCounterBits; |
|
Ryan Sleevi
2012/09/11 19:34:30
s/= ctrParams/= ctrParams/ (extra space)
Ryan Sleevi
2012/09/11 19:34:30
It seems you should be checking here, instead of /
|
| + PORT_Memcpy(ctr->counter, ctrParams->cb, blocksize); |
| + return SECSuccess; |
| +} |
| + |
| +CTRContext * |
| +CTR_CreateContext(void *context, freeblCipherFunc cipher, |
| + const unsigned char *param, unsigned int blocksize) |
| +{ |
| + CTRContext *ctr; |
| + SECStatus rv; |
| + |
| + /* first fill in the Counter context */ |
| + ctr = PORT_ZNew(CTRContext); |
| + if (ctr == NULL) { |
| + return NULL; |
| + } |
| + rv = CTR_InitContext(ctr, context, cipher, param, blocksize); |
| + if (rv != SECSuccess) { |
| + CTR_DestroyContext(ctr, PR_TRUE); |
| + ctr = NULL; |
| + } |
| + return ctr; |
| +} |
| + |
| +void |
| +CTR_DestroyContext(CTRContext *ctr, PRBool freeit) |
| +{ |
| + PORT_Memset(ctr, 0, sizeof (CTRContext)); |
|
Ryan Sleevi
2012/09/11 19:34:30
Why the additional memset here?
In looking at the
wtc
2012/09/14 01:16:42
The form used here is also common. See, for exampl
rjrejyea
2012/09/19 21:43:40
That's a very good suggestion.
bob
|
| + if (freeit) { |
| + PORT_Free(ctr); |
| + } |
| +} |
| + |
| +/* |
| + * Used by counter mode. Increment the counter block. Not all bits in the |
| + * counter block are part of the counter, counter_bits tells how many bits |
| + * are part of the counter. The counter_block is block_size long. It's a |
| + * big endian value. |
| + */ |
| +static void |
| +ctr_GetNextCtr(unsigned char *counter, unsigned int counterBits, |
| + unsigned int blocksize) |
| +{ |
| + unsigned char *counterPtr = counter + blocksize - 1; |
| + unsigned char mask, count; |
| + |
| + PORT_Assert(counterBits <= blocksize*BITS_PER_BYTE); |
| + while (counterBits >= BITS_PER_BYTE) { |
| + if (++(*(counterPtr--))) { |
| + return; |
|
wtc
2012/09/19 22:19:33
Since counterBits is usually a multiple of 8, the
|
| + } |
| + counterBits -= BITS_PER_BYTE; |
| + } |
| + if (counterBits == 0) { |
| + return; |
| + } |
| + /* increment the final partial byte */ |
| + mask = (1 << counterBits)-1; |
| + count = (*counterPtr)++ & mask; |
| + *counterPtr = ((*counterPtr) & ~mask) | count; |
|
Ryan Sleevi
2012/09/11 19:34:30
This does not appear to handle counter rollover co
rjrejyea
2012/09/19 21:43:40
I was under the impression that the counter was su
Ryan Sleevi
2012/09/19 21:53:15
Sorry, this may have been read opposite of how I i
rjrejyea
2012/09/19 21:59:36
OK, so the bug here is that we need to store *coun
Ryan Sleevi
2012/09/19 22:06:21
Also, I didn't see the check here (or elsewhere) a
Ryan Sleevi
2012/09/19 22:09:42
I don't think that will be sufficient. *counterPtr
|
| + return; |
| +} |
| + |
| +static void |
| +ctr_xor(unsigned char *target, const unsigned char *x, |
| + const unsigned char *y, int count) |
| +{ |
| + int i; |
| + for (i=0; i < count; i++) { |
| + *target++ = *x++ ^ *y++; |
| + } |
| +} |
| + |
| +SECStatus |
| +CTR_Update(CTRContext *ctr, unsigned char *outbuf, |
| + unsigned int *outlen, unsigned int maxout, |
| + const unsigned char *inbuf, unsigned int inlen, |
| + unsigned int blocksize) |
| +{ |
| + unsigned char cipherblock[MAX_BLOCK_SIZE]; |
| + unsigned int tmp; |
| + SECStatus rv; |
| + |
| + if (maxout < inlen) { |
| + *outlen = inlen; |
| + PORT_SetError(SEC_ERROR_OUTPUT_LEN); |
| + return SECFailure; |
| + } |
| + *outlen = 0; |
| + if (ctr->bufPtr != blocksize) { |
| + int needed = PR_MIN(blocksize-ctr->bufPtr, inlen); |
| + ctr_xor(outbuf, inbuf, ctr->buffer+ctr->bufPtr, needed); |
| + ctr->bufPtr += needed; |
| + outbuf += needed; |
| + inbuf += needed; |
| + *outlen += needed; |
| + inlen -= needed; |
| + if (inlen == 0) { |
| + return SECSuccess; |
| + } |
| + } |
| + |
| + while (inlen >= blocksize) { |
| + rv = (*ctr->cipher)(ctr->context, cipherblock, &tmp, blocksize, |
| + ctr->counter, blocksize, blocksize); |
| + ctr_GetNextCtr(ctr->counter, ctr->counterBits, blocksize); |
| + if (rv != SECSuccess) { |
| + return SECFailure; |
| + } |
| + ctr_xor(outbuf, inbuf, cipherblock, blocksize); |
| + outbuf += blocksize; |
| + inbuf += blocksize; |
| + *outlen += blocksize; |
| + inlen -= blocksize; |
| + } |
| + if (inlen == 0) { |
| + return SECSuccess; |
| + } |
| + rv = (*ctr->cipher)(ctr->context, ctr->buffer, &tmp, blocksize, |
| + ctr->counter, blocksize, blocksize); |
| + ctr_GetNextCtr(ctr->counter, ctr->counterBits, blocksize); |
| + if (rv != SECSuccess) { |
| + return SECFailure; |
| + } |
| + ctr_xor(outbuf, inbuf, ctr->buffer, inlen); |
| + ctr->bufPtr = inlen; |
| + *outlen += inlen; |
| + return SECSuccess; |
| +} |
| Property changes on: nss/mozilla/security/nss/lib/freebl/ctr.c |
| ___________________________________________________________________ |
| Added: svn:eol-style |
| + LF |