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

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

mercurial