Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(411)

Side by Side Diff: nss/mozilla/security/nss/lib/freebl/ctr.c

Issue 10919163: Add GCM, CTR, and CTS modes to AES. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/
Patch Set: Fix comments as rsleevi suggested, fix a 32-bit bug and miscellaneous issues Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
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/. */
4
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"
14
15 SECStatus
16 CTR_InitContext(CTRContext *ctr, void *context, freeblCipherFunc cipher,
17 const unsigned char *param, unsigned int blocksize)
18 {
19 const CK_AES_CTR_PARAMS *ctrParams = (const CK_AES_CTR_PARAMS *)param;
20
21 if (ctrParams->ulCounterBits == 0 ||
22 ctrParams->ulCounterBits > blocksize * PR_BITS_PER_BYTE) {
23 PORT_SetError(SEC_ERROR_INVALID_ARGS);
24 return SECFailure;
25 }
26
27 /* Invariant: 0 < ctr->bufPtr <= blocksize */
28 ctr->bufPtr = blocksize; /* no unused data in the buffer */
29 ctr->cipher = cipher;
30 ctr->context = context;
31 ctr->counterBits = ctrParams->ulCounterBits;
32 if (blocksize > sizeof(ctr->counter) ||
33 blocksize > sizeof(ctrParams->cb)) {
34 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
35 return SECFailure;
36 }
37 PORT_Memcpy(ctr->counter, ctrParams->cb, blocksize);
38 return SECSuccess;
39 }
40
41 CTRContext *
42 CTR_CreateContext(void *context, freeblCipherFunc cipher,
43 const unsigned char *param, unsigned int blocksize)
44 {
45 CTRContext *ctr;
46 SECStatus rv;
47
48 /* first fill in the Counter context */
49 ctr = PORT_ZNew(CTRContext);
50 if (ctr == NULL) {
51 return NULL;
52 }
53 rv = CTR_InitContext(ctr, context, cipher, param, blocksize);
54 if (rv != SECSuccess) {
55 CTR_DestroyContext(ctr, PR_TRUE);
56 ctr = NULL;
57 }
58 return ctr;
59 }
60
61 void
62 CTR_DestroyContext(CTRContext *ctr, PRBool freeit)
63 {
64 PORT_Memset(ctr, 0, sizeof(CTRContext));
65 if (freeit) {
66 PORT_Free(ctr);
67 }
68 }
69
70 /*
71 * Used by counter mode. Increment the counter block. Not all bits in the
72 * counter block are part of the counter, counterBits tells how many bits
73 * are part of the counter. The counter block is blocksize long. It's a
74 * big endian value.
75 *
76 * XXX Does not handle counter rollover.
77 */
78 static void
79 ctr_GetNextCtr(unsigned char *counter, unsigned int counterBits,
80 unsigned int blocksize)
81 {
82 unsigned char *counterPtr = counter + blocksize - 1;
83 unsigned char mask, count;
84
85 PORT_Assert(counterBits <= blocksize*PR_BITS_PER_BYTE);
86 while (counterBits >= PR_BITS_PER_BYTE) {
87 if (++(*(counterPtr--))) {
88 return;
89 }
90 counterBits -= PR_BITS_PER_BYTE;
91 }
92 if (counterBits == 0) {
93 return;
94 }
95 /* increment the final partial byte */
96 mask = (1 << counterBits)-1;
97 count = ++(*counterPtr) & mask;
98 *counterPtr = ((*counterPtr) & ~mask) | count;
99 return;
100 }
101
102 static void
103 ctr_xor(unsigned char *target, const unsigned char *x,
104 const unsigned char *y, unsigned int count)
105 {
106 unsigned int i;
107 for (i=0; i < count; i++) {
108 *target++ = *x++ ^ *y++;
109 }
110 }
111
112 SECStatus
113 CTR_Update(CTRContext *ctr, unsigned char *outbuf,
114 unsigned int *outlen, unsigned int maxout,
115 const unsigned char *inbuf, unsigned int inlen,
116 unsigned int blocksize)
117 {
118 unsigned int tmp;
119 SECStatus rv;
120
121 if (maxout < inlen) {
122 *outlen = inlen;
123 PORT_SetError(SEC_ERROR_OUTPUT_LEN);
124 return SECFailure;
125 }
126 *outlen = 0;
127 if (ctr->bufPtr != blocksize) {
128 unsigned int needed = PR_MIN(blocksize-ctr->bufPtr, inlen);
129 ctr_xor(outbuf, inbuf, ctr->buffer+ctr->bufPtr, needed);
130 ctr->bufPtr += needed;
131 outbuf += needed;
132 inbuf += needed;
133 *outlen += needed;
134 inlen -= needed;
135 if (inlen == 0) {
136 return SECSuccess;
137 }
138 PORT_Assert(ctr->bufPtr == blocksize);
139 }
140
141 while (inlen >= blocksize) {
142 rv = (*ctr->cipher)(ctr->context, ctr->buffer, &tmp, blocksize,
143 ctr->counter, blocksize, blocksize);
144 ctr_GetNextCtr(ctr->counter, ctr->counterBits, blocksize);
145 if (rv != SECSuccess) {
146 return SECFailure;
147 }
148 ctr_xor(outbuf, inbuf, ctr->buffer, blocksize);
149 outbuf += blocksize;
150 inbuf += blocksize;
151 *outlen += blocksize;
152 inlen -= blocksize;
153 }
154 if (inlen == 0) {
155 return SECSuccess;
156 }
157 rv = (*ctr->cipher)(ctr->context, ctr->buffer, &tmp, blocksize,
158 ctr->counter, blocksize, blocksize);
159 ctr_GetNextCtr(ctr->counter, ctr->counterBits, blocksize);
160 if (rv != SECSuccess) {
161 return SECFailure;
162 }
163 ctr_xor(outbuf, inbuf, ctr->buffer, inlen);
164 ctr->bufPtr = inlen;
165 *outlen += inlen;
166 return SECSuccess;
167 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698