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

Side by Side Diff: nss/lib/freebl/hmacct.c

Issue 2078763002: Delete bundled copy of NSS and replace with README. (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/nss@master
Patch Set: Delete bundled copy of NSS and replace with README. Created 4 years, 6 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
« no previous file with comments | « nss/lib/freebl/hmacct.h ('k') | nss/lib/freebl/intel-aes.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
9 #include "secport.h"
10 #include "hasht.h"
11 #include "blapit.h"
12 #include "hmacct.h"
13 #include "secerr.h"
14
15 /* MAX_HASH_BIT_COUNT_BYTES is the maximum number of bytes in the hash's length
16 * field. (SHA-384/512 have 128-bit length.) */
17 #define MAX_HASH_BIT_COUNT_BYTES 16
18
19 /* Some utility functions are needed:
20 *
21 * These macros return the given value with the MSB copied to all the other
22 * bits. They use the fact that an arithmetic shift shifts-in the sign bit.
23 * However, this is not ensured by the C standard so you may need to replace
24 * them with something else on odd CPUs.
25 *
26 * Note: the argument to these macros must be an unsigned int.
27 * */
28 #define DUPLICATE_MSB_TO_ALL(x) ( (unsigned int)( (int)(x) >> (sizeof(int)*8-1) ) )
29 #define DUPLICATE_MSB_TO_ALL_8(x) ( (unsigned char)(DUPLICATE_MSB_TO_ALL(x)) )
30
31 /* constantTimeGE returns 0xff if a>=b and 0x00 otherwise, where a, b <
32 * MAX_UINT/2. */
33 static unsigned char
34 constantTimeGE(unsigned int a, unsigned int b)
35 {
36 a -= b;
37 return DUPLICATE_MSB_TO_ALL(~a);
38 }
39
40 /* constantTimeEQ8 returns 0xff if a==b and 0x00 otherwise. */
41 static unsigned char
42 constantTimeEQ8(unsigned char a, unsigned char b)
43 {
44 unsigned int c = a ^ b;
45 c--;
46 return DUPLICATE_MSB_TO_ALL_8(c);
47 }
48
49 /* MAC performs a constant time SSLv3/TLS MAC of |dataLen| bytes of |data|,
50 * where |dataLen| includes both the authenticated bytes and the MAC tag from
51 * the sender. |dataLen| must be >= the length of the MAC tag.
52 *
53 * |dataTotalLen| is >= |dataLen| and also accounts for any padding bytes
54 * that may follow the sender's MAC. (Only a single block of padding may
55 * follow in SSLv3, or up to 255 bytes in TLS.)
56 *
57 * Since the results of decryption are secret information (otherwise a
58 * padding-oracle is created), this function is constant-time with respect to
59 * |dataLen|.
60 *
61 * |header| contains either the 13-byte TLS header (containing the sequence
62 * number, record type etc), or it contains the SSLv3 header with the SSLv3
63 * padding bytes etc. */
64 static SECStatus
65 MAC(unsigned char *mdOut,
66 unsigned int *mdOutLen,
67 unsigned int mdOutMax,
68 const SECHashObject *hashObj,
69 const unsigned char *macSecret,
70 unsigned int macSecretLen,
71 const unsigned char *header,
72 unsigned int headerLen,
73 const unsigned char *data,
74 unsigned int dataLen,
75 unsigned int dataTotalLen,
76 unsigned char isSSLv3)
77 {
78 void *mdState = hashObj->create();
79 const unsigned int mdSize = hashObj->length;
80 const unsigned int mdBlockSize = hashObj->blocklength;
81 /* mdLengthSize is the number of bytes in the length field that terminates
82 * the hash.
83 *
84 * This assumes that hash functions with a 64 byte block size use a 64-bit
85 * length, and otherwise they use a 128-bit length. This is true of {MD5,
86 * SHA*} (which are all of the hash functions specified for use with TLS
87 * today). */
88 const unsigned int mdLengthSize = mdBlockSize == 64 ? 8 : 16;
89
90 const unsigned int sslv3PadLen = hashObj->type == HASH_AlgMD5 ? 48 : 40;
91
92 /* varianceBlocks is the number of blocks of the hash that we have to
93 * calculate in constant time because they could be altered by the
94 * padding value.
95 *
96 * In SSLv3, the padding must be minimal so the end of the plaintext
97 * varies by, at most, 15+20 = 35 bytes. (We conservatively assume that
98 * the MAC size varies from 0..20 bytes.) In case the 9 bytes of hash
99 * termination (0x80 + 64-bit length) don't fit in the final block, we
100 * say that the final two blocks can vary based on the padding.
101 *
102 * TLSv1 has MACs up to 48 bytes long (SHA-384) and the padding is not
103 * required to be minimal. Therefore we say that the final six blocks
104 * can vary based on the padding.
105 *
106 * Later in the function, if the message is short and there obviously
107 * cannot be this many blocks then varianceBlocks can be reduced. */
108 unsigned int varianceBlocks = isSSLv3 ? 2 : 6;
109 /* From now on we're dealing with the MAC, which conceptually has 13
110 * bytes of `header' before the start of the data (TLS) or 71/75 bytes
111 * (SSLv3) */
112 const unsigned int len = dataTotalLen + headerLen;
113 /* maxMACBytes contains the maximum bytes of bytes in the MAC, including
114 * |header|, assuming that there's no padding. */
115 const unsigned int maxMACBytes = len - mdSize - 1;
116 /* numBlocks is the maximum number of hash blocks. */
117 const unsigned int numBlocks =
118 (maxMACBytes + 1 + mdLengthSize + mdBlockSize - 1) / mdBlockSize;
119 /* macEndOffset is the index just past the end of the data to be
120 * MACed. */
121 const unsigned int macEndOffset = dataLen + headerLen - mdSize;
122 /* c is the index of the 0x80 byte in the final hash block that
123 * contains application data. */
124 const unsigned int c = macEndOffset % mdBlockSize;
125 /* indexA is the hash block number that contains the 0x80 terminating
126 * value. */
127 const unsigned int indexA = macEndOffset / mdBlockSize;
128 /* indexB is the hash block number that contains the 64-bit hash
129 * length, in bits. */
130 const unsigned int indexB = (macEndOffset + mdLengthSize) / mdBlockSize;
131 /* bits is the hash-length in bits. It includes the additional hash
132 * block for the masked HMAC key, or whole of |header| in the case of
133 * SSLv3. */
134 unsigned int bits;
135 /* In order to calculate the MAC in constant time we have to handle
136 * the final blocks specially because the padding value could cause the
137 * end to appear somewhere in the final |varianceBlocks| blocks and we
138 * can't leak where. However, |numStartingBlocks| worth of data can
139 * be hashed right away because no padding value can affect whether
140 * they are plaintext. */
141 unsigned int numStartingBlocks = 0;
142 /* k is the starting byte offset into the conceptual header||data where
143 * we start processing. */
144 unsigned int k = 0;
145 unsigned char lengthBytes[MAX_HASH_BIT_COUNT_BYTES];
146 /* hmacPad is the masked HMAC key. */
147 unsigned char hmacPad[HASH_BLOCK_LENGTH_MAX];
148 unsigned char firstBlock[HASH_BLOCK_LENGTH_MAX];
149 unsigned char macOut[HASH_LENGTH_MAX];
150 unsigned i, j;
151
152 /* For SSLv3, if we're going to have any starting blocks then we need
153 * at least two because the header is larger than a single block. */
154 if (numBlocks > varianceBlocks + (isSSLv3 ? 1 : 0)) {
155 numStartingBlocks = numBlocks - varianceBlocks;
156 k = mdBlockSize*numStartingBlocks;
157 }
158
159 bits = 8*macEndOffset;
160 hashObj->begin(mdState);
161 if (!isSSLv3) {
162 /* Compute the initial HMAC block. For SSLv3, the padding and
163 * secret bytes are included in |header| because they take more
164 * than a single block. */
165 bits += 8*mdBlockSize;
166 memset(hmacPad, 0, mdBlockSize);
167 PORT_Assert(macSecretLen <= sizeof(hmacPad));
168 memcpy(hmacPad, macSecret, macSecretLen);
169 for (i = 0; i < mdBlockSize; i++)
170 hmacPad[i] ^= 0x36;
171 hashObj->update(mdState, hmacPad, mdBlockSize);
172 }
173
174 j = 0;
175 memset(lengthBytes, 0, sizeof(lengthBytes));
176 if (mdLengthSize == 16) {
177 j = 8;
178 }
179 if (hashObj->type == HASH_AlgMD5) {
180 /* MD5 appends a little-endian length. */
181 for (i = 0; i < 4; i++) {
182 lengthBytes[i+j] = bits >> (8*i);
183 }
184 } else {
185 /* All other TLS hash functions use a big-endian length. */
186 for (i = 0; i < 4; i++) {
187 lengthBytes[4+i+j] = bits >> (8*(3-i));
188 }
189 }
190
191 if (k > 0) {
192 if (isSSLv3) {
193 /* The SSLv3 header is larger than a single block.
194 * overhang is the number of bytes beyond a single
195 * block that the header consumes: either 7 bytes
196 * (SHA1) or 11 bytes (MD5). */
197 const unsigned int overhang = headerLen-mdBlockSize;
198 hashObj->update(mdState, header, mdBlockSize);
199 memcpy(firstBlock, header + mdBlockSize, overhang);
200 memcpy(firstBlock + overhang, data, mdBlockSize-overhang);
201 hashObj->update(mdState, firstBlock, mdBlockSize);
202 for (i = 1; i < k/mdBlockSize - 1; i++) {
203 hashObj->update(mdState, data + mdBlockSize*i - overhang,
204 mdBlockSize);
205 }
206 } else {
207 /* k is a multiple of mdBlockSize. */
208 memcpy(firstBlock, header, 13);
209 memcpy(firstBlock+13, data, mdBlockSize-13);
210 hashObj->update(mdState, firstBlock, mdBlockSize);
211 for (i = 1; i < k/mdBlockSize; i++) {
212 hashObj->update(mdState, data + mdBlockSize*i - 13,
213 mdBlockSize);
214 }
215 }
216 }
217
218 memset(macOut, 0, sizeof(macOut));
219
220 /* We now process the final hash blocks. For each block, we construct
221 * it in constant time. If i == indexA then we'll include the 0x80
222 * bytes and zero pad etc. For each block we selectively copy it, in
223 * constant time, to |macOut|. */
224 for (i = numStartingBlocks; i <= numStartingBlocks+varianceBlocks; i++) {
225 unsigned char block[HASH_BLOCK_LENGTH_MAX];
226 unsigned char isBlockA = constantTimeEQ8(i, indexA);
227 unsigned char isBlockB = constantTimeEQ8(i, indexB);
228 for (j = 0; j < mdBlockSize; j++) {
229 unsigned char isPastC = isBlockA & constantTimeGE(j, c);
230 unsigned char isPastCPlus1 = isBlockA & constantTimeGE(j, c+1);
231 unsigned char b = 0;
232 if (k < headerLen) {
233 b = header[k];
234 } else if (k < dataTotalLen + headerLen) {
235 b = data[k-headerLen];
236 }
237 k++;
238
239 /* If this is the block containing the end of the
240 * application data, and we are at the offset for the
241 * 0x80 value, then overwrite b with 0x80. */
242 b = (b&~isPastC) | (0x80&isPastC);
243 /* If this the the block containing the end of the
244 * application data and we're past the 0x80 value then
245 * just write zero. */
246 b = b&~isPastCPlus1;
247 /* If this is indexB (the final block), but not
248 * indexA (the end of the data), then the 64-bit
249 * length didn't fit into indexA and we're having to
250 * add an extra block of zeros. */
251 b &= ~isBlockB | isBlockA;
252
253 /* The final bytes of one of the blocks contains the length. */
254 if (j >= mdBlockSize - mdLengthSize) {
255 /* If this is indexB, write a length byte. */
256 b = (b&~isBlockB) |
257 (isBlockB&lengthBytes[j-(mdBlockSize-mdLengthSize)]);
258 }
259 block[j] = b;
260 }
261
262 hashObj->update(mdState, block, mdBlockSize);
263 hashObj->end_raw(mdState, block, NULL, mdSize);
264 /* If this is indexB, copy the hash value to |macOut|. */
265 for (j = 0; j < mdSize; j++) {
266 macOut[j] |= block[j]&isBlockB;
267 }
268 }
269
270 hashObj->begin(mdState);
271
272 if (isSSLv3) {
273 /* We repurpose |hmacPad| to contain the SSLv3 pad2 block. */
274 for (i = 0; i < sslv3PadLen; i++)
275 hmacPad[i] = 0x5c;
276
277 hashObj->update(mdState, macSecret, macSecretLen);
278 hashObj->update(mdState, hmacPad, sslv3PadLen);
279 hashObj->update(mdState, macOut, mdSize);
280 } else {
281 /* Complete the HMAC in the standard manner. */
282 for (i = 0; i < mdBlockSize; i++)
283 hmacPad[i] ^= 0x6a;
284
285 hashObj->update(mdState, hmacPad, mdBlockSize);
286 hashObj->update(mdState, macOut, mdSize);
287 }
288
289 hashObj->end(mdState, mdOut, mdOutLen, mdOutMax);
290 hashObj->destroy(mdState, PR_TRUE);
291
292 return SECSuccess;
293 }
294
295 SECStatus
296 HMAC_ConstantTime(
297 unsigned char *result,
298 unsigned int *resultLen,
299 unsigned int maxResultLen,
300 const SECHashObject *hashObj,
301 const unsigned char *secret,
302 unsigned int secretLen,
303 const unsigned char *header,
304 unsigned int headerLen,
305 const unsigned char *body,
306 unsigned int bodyLen,
307 unsigned int bodyTotalLen)
308 {
309 if (hashObj->end_raw == NULL)
310 return SECFailure;
311 return MAC(result, resultLen, maxResultLen, hashObj, secret, secretLen,
312 header, headerLen, body, bodyLen, bodyTotalLen,
313 0 /* not SSLv3 */);
314 }
315
316 SECStatus
317 SSLv3_MAC_ConstantTime(
318 unsigned char *result,
319 unsigned int *resultLen,
320 unsigned int maxResultLen,
321 const SECHashObject *hashObj,
322 const unsigned char *secret,
323 unsigned int secretLen,
324 const unsigned char *header,
325 unsigned int headerLen,
326 const unsigned char *body,
327 unsigned int bodyLen,
328 unsigned int bodyTotalLen)
329 {
330 if (hashObj->end_raw == NULL)
331 return SECFailure;
332 return MAC(result, resultLen, maxResultLen, hashObj, secret, secretLen,
333 header, headerLen, body, bodyLen, bodyTotalLen,
334 1 /* SSLv3 */);
335 }
336
OLDNEW
« no previous file with comments | « nss/lib/freebl/hmacct.h ('k') | nss/lib/freebl/intel-aes.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698