/src/nss/lib/freebl/cmac.c
| Line | Count | Source (jump to first uncovered line) | 
| 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 "rijndael.h" | 
| 10 |  | #include "blapi.h" | 
| 11 |  | #include "cmac.h" | 
| 12 |  | #include "secerr.h" | 
| 13 |  | #include "nspr.h" | 
| 14 |  |  | 
| 15 |  | struct CMACContextStr { | 
| 16 |  |     /* Information about the block cipher to use internally. The cipher should | 
| 17 |  |      * be placed in ECB mode so that we can use it to directly encrypt blocks. | 
| 18 |  |      * | 
| 19 |  |      * | 
| 20 |  |      * To add a new cipher, add an entry to CMACCipher, update CMAC_Init, | 
| 21 |  |      * cmac_Encrypt, and CMAC_Destroy methods to handle the new cipher, and | 
| 22 |  |      * add a new Context pointer to the cipher union with the correct type. */ | 
| 23 |  |     CMACCipher cipherType; | 
| 24 |  |     union { | 
| 25 |  |         AESContext *aes; | 
| 26 |  |     } cipher; | 
| 27 |  |     unsigned int blockSize; | 
| 28 |  |  | 
| 29 |  |     /* Internal keys which are conditionally used by the algorithm. Derived | 
| 30 |  |      * from encrypting the NULL block. We leave the storing of (and the | 
| 31 |  |      * cleanup of) the CMAC key to the underlying block cipher. */ | 
| 32 |  |     unsigned char k1[MAX_BLOCK_SIZE]; | 
| 33 |  |     unsigned char k2[MAX_BLOCK_SIZE]; | 
| 34 |  |  | 
| 35 |  |     /* When Update is called with data which isn't a multiple of the block | 
| 36 |  |      * size, we need a place to put it. HMAC handles this by passing it to | 
| 37 |  |      * the underlying hash function right away; we can't do that as the | 
| 38 |  |      * contract on the cipher object is different. */ | 
| 39 |  |     unsigned int partialIndex; | 
| 40 |  |     unsigned char partialBlock[MAX_BLOCK_SIZE]; | 
| 41 |  |  | 
| 42 |  |     /* Last encrypted block. This gets xor-ed with partialBlock prior to | 
| 43 |  |      * encrypting it. NIST defines this to be the empty string to begin. */ | 
| 44 |  |     unsigned char lastBlock[MAX_BLOCK_SIZE]; | 
| 45 |  | }; | 
| 46 |  |  | 
| 47 |  | static void | 
| 48 |  | cmac_ShiftLeftOne(unsigned char *out, const unsigned char *in, int length) | 
| 49 | 0 | { | 
| 50 | 0 |     int i = 0; | 
| 51 | 0 |     for (; i < length - 1; i++) { | 
| 52 | 0 |         out[i] = in[i] << 1; | 
| 53 | 0 |         out[i] |= in[i + 1] >> 7; | 
| 54 | 0 |     } | 
| 55 | 0 |     out[i] = in[i] << 1; | 
| 56 | 0 | } | 
| 57 |  |  | 
| 58 |  | static SECStatus | 
| 59 |  | cmac_Encrypt(CMACContext *ctx, unsigned char *output, | 
| 60 |  |              const unsigned char *input, | 
| 61 |  |              unsigned int inputLen) | 
| 62 | 0 | { | 
| 63 | 0 |     if (ctx->cipherType == CMAC_AES) { | 
| 64 | 0 |         unsigned int tmpOutputLen; | 
| 65 | 0 |         SECStatus rv = AES_Encrypt(ctx->cipher.aes, output, &tmpOutputLen, | 
| 66 | 0 |                                    ctx->blockSize, input, inputLen); | 
| 67 |  |  | 
| 68 |  |         /* Assumption: AES_Encrypt (when in ECB mode) always returns an | 
| 69 |  |          * output of length equal to blockSize (what was pass as the value | 
| 70 |  |          * of the maxOutputLen parameter). */ | 
| 71 | 0 |         PORT_Assert(tmpOutputLen == ctx->blockSize); | 
| 72 | 0 |         return rv; | 
| 73 | 0 |     } | 
| 74 |  |  | 
| 75 | 0 |     return SECFailure; | 
| 76 | 0 | } | 
| 77 |  |  | 
| 78 |  | /* NIST SP.800-38B, 6.1 Subkey Generation */ | 
| 79 |  | static SECStatus | 
| 80 |  | cmac_GenerateSubkeys(CMACContext *ctx) | 
| 81 | 0 | { | 
| 82 | 0 |     unsigned char null_block[MAX_BLOCK_SIZE] = { 0 }; | 
| 83 | 0 |     unsigned char L[MAX_BLOCK_SIZE]; | 
| 84 | 0 |     unsigned char v; | 
| 85 | 0 |     unsigned char i; | 
| 86 |  |  | 
| 87 |  |     /* Step 1: L = AES(key, null_block) */ | 
| 88 | 0 |     if (cmac_Encrypt(ctx, L, null_block, ctx->blockSize) != SECSuccess) { | 
| 89 | 0 |         return SECFailure; | 
| 90 | 0 |     } | 
| 91 |  |  | 
| 92 |  |     /* In the following, some effort has been made to be constant time. Rather | 
| 93 |  |      * than conditioning on the value of the MSB (of L or K1), we use the loop | 
| 94 |  |      * to build a mask for the conditional constant. */ | 
| 95 |  |  | 
| 96 |  |     /* Step 2: If MSB(L) = 0, K1 = L << 1. Else, K1 = (L << 1) ^ R_b. */ | 
| 97 | 0 |     cmac_ShiftLeftOne(ctx->k1, L, ctx->blockSize); | 
| 98 | 0 |     v = L[0] >> 7; | 
| 99 | 0 |     for (i = 1; i <= 7; i <<= 1) { | 
| 100 | 0 |         v |= (v << i); | 
| 101 | 0 |     } | 
| 102 | 0 |     ctx->k1[ctx->blockSize - 1] ^= (0x87 & v); | 
| 103 |  |  | 
| 104 |  |     /* Step 3: If MSB(K1) = 0, K2 = K1 << 1. Else, K2 = (K1 <, 1) ^ R_b. */ | 
| 105 | 0 |     cmac_ShiftLeftOne(ctx->k2, ctx->k1, ctx->blockSize); | 
| 106 | 0 |     v = ctx->k1[0] >> 7; | 
| 107 | 0 |     for (i = 1; i <= 7; i <<= 1) { | 
| 108 | 0 |         v |= (v << i); | 
| 109 | 0 |     } | 
| 110 | 0 |     ctx->k2[ctx->blockSize - 1] ^= (0x87 & v); | 
| 111 |  |  | 
| 112 |  |     /* Any intermediate value in the computation of the subkey shall be | 
| 113 |  |      * secret. */ | 
| 114 | 0 |     PORT_Memset(null_block, 0, MAX_BLOCK_SIZE); | 
| 115 | 0 |     PORT_Memset(L, 0, MAX_BLOCK_SIZE); | 
| 116 |  |  | 
| 117 |  |     /* Step 4: Return the values. */ | 
| 118 | 0 |     return SECSuccess; | 
| 119 | 0 | } | 
| 120 |  |  | 
| 121 |  | /* NIST SP.800-38B, 6.2 MAC Generation step 6 */ | 
| 122 |  | static SECStatus | 
| 123 |  | cmac_UpdateState(CMACContext *ctx) | 
| 124 | 0 | { | 
| 125 | 0 |     if (ctx == NULL || ctx->partialIndex != ctx->blockSize) { | 
| 126 | 0 |         PORT_SetError(SEC_ERROR_INVALID_ARGS); | 
| 127 | 0 |         return SECFailure; | 
| 128 | 0 |     } | 
| 129 |  |  | 
| 130 |  |     /* Step 6: C_i = CIPHER(key, C_{i-1} ^ M_i)  for 1 <= i <= n, and | 
| 131 |  |      *         C_0 is defined as the empty string. */ | 
| 132 |  |  | 
| 133 | 0 |     for (unsigned int index = 0; index < ctx->blockSize; index++) { | 
| 134 | 0 |         ctx->partialBlock[index] ^= ctx->lastBlock[index]; | 
| 135 | 0 |     } | 
| 136 |  | 
 | 
| 137 | 0 |     return cmac_Encrypt(ctx, ctx->lastBlock, ctx->partialBlock, ctx->blockSize); | 
| 138 | 0 | } | 
| 139 |  |  | 
| 140 |  | SECStatus | 
| 141 |  | CMAC_Init(CMACContext *ctx, CMACCipher type, | 
| 142 |  |           const unsigned char *key, unsigned int key_len) | 
| 143 | 0 | { | 
| 144 | 0 |     if (ctx == NULL) { | 
| 145 | 0 |         PORT_SetError(SEC_ERROR_NO_MEMORY); | 
| 146 | 0 |         return SECFailure; | 
| 147 | 0 |     } | 
| 148 |  |  | 
| 149 |  |     /* We only currently support AES-CMAC. */ | 
| 150 | 0 |     if (type != CMAC_AES) { | 
| 151 | 0 |         PORT_SetError(SEC_ERROR_INVALID_ARGS); | 
| 152 | 0 |         return SECFailure; | 
| 153 | 0 |     } | 
| 154 |  |  | 
| 155 | 0 |     PORT_Memset(ctx, 0, sizeof(*ctx)); | 
| 156 |  | 
 | 
| 157 | 0 |     ctx->blockSize = AES_BLOCK_SIZE; | 
| 158 | 0 |     ctx->cipherType = CMAC_AES; | 
| 159 | 0 |     ctx->cipher.aes = AES_CreateContext(key, NULL, NSS_AES, 1, key_len, | 
| 160 | 0 |                                         ctx->blockSize); | 
| 161 | 0 |     if (ctx->cipher.aes == NULL) { | 
| 162 | 0 |         return SECFailure; | 
| 163 | 0 |     } | 
| 164 |  |  | 
| 165 | 0 |     return CMAC_Begin(ctx); | 
| 166 | 0 | } | 
| 167 |  |  | 
| 168 |  | CMACContext * | 
| 169 |  | CMAC_Create(CMACCipher type, const unsigned char *key, | 
| 170 |  |             unsigned int key_len) | 
| 171 | 0 | { | 
| 172 | 0 |     CMACContext *result = PORT_New(CMACContext); | 
| 173 |  | 
 | 
| 174 | 0 |     if (CMAC_Init(result, type, key, key_len) != SECSuccess) { | 
| 175 | 0 |         CMAC_Destroy(result, PR_TRUE); | 
| 176 | 0 |         return NULL; | 
| 177 | 0 |     } | 
| 178 |  |  | 
| 179 | 0 |     return result; | 
| 180 | 0 | } | 
| 181 |  |  | 
| 182 |  | SECStatus | 
| 183 |  | CMAC_Begin(CMACContext *ctx) | 
| 184 | 0 | { | 
| 185 | 0 |     if (ctx == NULL) { | 
| 186 | 0 |         return SECFailure; | 
| 187 | 0 |     } | 
| 188 |  |  | 
| 189 |  |     /* Ensure that our blockSize is less than the maximum. When this fails, | 
| 190 |  |      * a cipher with a larger block size was added and MAX_BLOCK_SIZE needs | 
| 191 |  |      * to be updated accordingly. */ | 
| 192 | 0 |     PORT_Assert(ctx->blockSize <= MAX_BLOCK_SIZE); | 
| 193 |  | 
 | 
| 194 | 0 |     if (cmac_GenerateSubkeys(ctx) != SECSuccess) { | 
| 195 | 0 |         return SECFailure; | 
| 196 | 0 |     } | 
| 197 |  |  | 
| 198 |  |     /* Set the index to write partial blocks at to zero. This saves us from | 
| 199 |  |      * having to clear ctx->partialBlock. */ | 
| 200 | 0 |     ctx->partialIndex = 0; | 
| 201 |  |  | 
| 202 |  |     /* Step 5: Let C_0 = 0^b. */ | 
| 203 | 0 |     PORT_Memset(ctx->lastBlock, 0, ctx->blockSize); | 
| 204 |  | 
 | 
| 205 | 0 |     return SECSuccess; | 
| 206 | 0 | } | 
| 207 |  |  | 
| 208 |  | /* NIST SP.800-38B, 6.2 MAC Generation */ | 
| 209 |  | SECStatus | 
| 210 |  | CMAC_Update(CMACContext *ctx, const unsigned char *data, | 
| 211 |  |             unsigned int data_len) | 
| 212 | 0 | { | 
| 213 | 0 |     unsigned int data_index = 0; | 
| 214 | 0 |     if (ctx == NULL) { | 
| 215 | 0 |         PORT_SetError(SEC_ERROR_INVALID_ARGS); | 
| 216 | 0 |         return SECFailure; | 
| 217 | 0 |     } | 
| 218 |  |  | 
| 219 | 0 |     if (data == NULL || data_len == 0) { | 
| 220 | 0 |         return SECSuccess; | 
| 221 | 0 |     } | 
| 222 |  |  | 
| 223 |  |     /* Copy as many bytes from data into ctx->partialBlock as we can, up to | 
| 224 |  |      * the maximum of the remaining data and the remaining space in | 
| 225 |  |      * ctx->partialBlock. | 
| 226 |  |      * | 
| 227 |  |      * Note that we swap the order (encrypt *then* copy) because the last | 
| 228 |  |      * block is different from the rest. If we end on an even multiple of | 
| 229 |  |      * the block size, we have to be able to XOR it with K1. But we won't know | 
| 230 |  |      * that it is the last until CMAC_Finish is called (and by then, CMAC_Update | 
| 231 |  |      * has already returned). */ | 
| 232 | 0 |     while (data_index < data_len) { | 
| 233 | 0 |         if (ctx->partialIndex == ctx->blockSize) { | 
| 234 | 0 |             if (cmac_UpdateState(ctx) != SECSuccess) { | 
| 235 | 0 |                 return SECFailure; | 
| 236 | 0 |             } | 
| 237 |  |  | 
| 238 | 0 |             ctx->partialIndex = 0; | 
| 239 | 0 |         } | 
| 240 |  |  | 
| 241 | 0 |         unsigned int copy_len = data_len - data_index; | 
| 242 | 0 |         if (copy_len > (ctx->blockSize - ctx->partialIndex)) { | 
| 243 | 0 |             copy_len = ctx->blockSize - ctx->partialIndex; | 
| 244 | 0 |         } | 
| 245 |  | 
 | 
| 246 | 0 |         PORT_Memcpy(ctx->partialBlock + ctx->partialIndex, data + data_index, copy_len); | 
| 247 | 0 |         data_index += copy_len; | 
| 248 | 0 |         ctx->partialIndex += copy_len; | 
| 249 | 0 |     } | 
| 250 |  |  | 
| 251 | 0 |     return SECSuccess; | 
| 252 | 0 | } | 
| 253 |  |  | 
| 254 |  | /* NIST SP.800-38B, 6.2 MAC Generation */ | 
| 255 |  | SECStatus | 
| 256 |  | CMAC_Finish(CMACContext *ctx, unsigned char *result, | 
| 257 |  |             unsigned int *result_len, | 
| 258 |  |             unsigned int max_result_len) | 
| 259 | 0 | { | 
| 260 | 0 |     if (ctx == NULL || result == NULL || max_result_len == 0) { | 
| 261 | 0 |         PORT_SetError(SEC_ERROR_INVALID_ARGS); | 
| 262 | 0 |         return SECFailure; | 
| 263 | 0 |     } | 
| 264 |  |  | 
| 265 | 0 |     if (max_result_len > ctx->blockSize) { | 
| 266 |  |         /* This is a weird situation. The PKCS #11 soft tokencode passes | 
| 267 |  |          * sizeof(result) here, which is hard-coded as SFTK_MAX_MAC_LENGTH. | 
| 268 |  |          * This later gets truncated to min(SFTK_MAX_MAC_LENGTH, requested). */ | 
| 269 | 0 |         max_result_len = ctx->blockSize; | 
| 270 | 0 |     } | 
| 271 |  |  | 
| 272 |  |     /* Step 4: If M_n* is a complete block, M_n = K1 ^ M_n*. Else, | 
| 273 |  |      * M_n = K2 ^ (M_n* || 10^j). */ | 
| 274 | 0 |     if (ctx->partialIndex == ctx->blockSize) { | 
| 275 |  |         /* XOR in K1. */ | 
| 276 | 0 |         for (unsigned int index = 0; index < ctx->blockSize; index++) { | 
| 277 | 0 |             ctx->partialBlock[index] ^= ctx->k1[index]; | 
| 278 | 0 |         } | 
| 279 | 0 |     } else { | 
| 280 |  |         /* Use 10* padding on the partial block. */ | 
| 281 | 0 |         ctx->partialBlock[ctx->partialIndex++] = 0x80; | 
| 282 | 0 |         PORT_Memset(ctx->partialBlock + ctx->partialIndex, 0, | 
| 283 | 0 |                     ctx->blockSize - ctx->partialIndex); | 
| 284 | 0 |         ctx->partialIndex = ctx->blockSize; | 
| 285 |  |  | 
| 286 |  |         /* XOR in K2. */ | 
| 287 | 0 |         for (unsigned int index = 0; index < ctx->blockSize; index++) { | 
| 288 | 0 |             ctx->partialBlock[index] ^= ctx->k2[index]; | 
| 289 | 0 |         } | 
| 290 | 0 |     } | 
| 291 |  |  | 
| 292 |  |     /* Encrypt the block. */ | 
| 293 | 0 |     if (cmac_UpdateState(ctx) != SECSuccess) { | 
| 294 | 0 |         return SECFailure; | 
| 295 | 0 |     } | 
| 296 |  |  | 
| 297 |  |     /* Step 7 & 8: T = MSB_tlen(C_n); return T. */ | 
| 298 | 0 |     PORT_Memcpy(result, ctx->lastBlock, max_result_len); | 
| 299 | 0 |     if (result_len != NULL) { | 
| 300 | 0 |         *result_len = max_result_len; | 
| 301 | 0 |     } | 
| 302 | 0 |     return SECSuccess; | 
| 303 | 0 | } | 
| 304 |  |  | 
| 305 |  | void | 
| 306 |  | CMAC_Destroy(CMACContext *ctx, PRBool free_it) | 
| 307 | 0 | { | 
| 308 | 0 |     if (ctx == NULL) { | 
| 309 | 0 |         return; | 
| 310 | 0 |     } | 
| 311 |  |  | 
| 312 | 0 |     if (ctx->cipherType == CMAC_AES && ctx->cipher.aes != NULL) { | 
| 313 | 0 |         AES_DestroyContext(ctx->cipher.aes, PR_TRUE); | 
| 314 | 0 |     } | 
| 315 |  |  | 
| 316 |  |     /* Destroy everything in the context. This includes sensitive data in | 
| 317 |  |      * K1, K2, and lastBlock. */ | 
| 318 | 0 |     PORT_Memset(ctx, 0, sizeof(*ctx)); | 
| 319 |  | 
 | 
| 320 | 0 |     if (free_it == PR_TRUE) { | 
| 321 | 0 |         PORT_Free(ctx); | 
| 322 | 0 |     } | 
| 323 | 0 | } |