blake2b.c (11739B)
1 /* 2 * blake2b.c - definitions for the blake2b hash function 3 * 4 * This Source Code Form is subject to the terms of the Mozilla Public 5 * License, v. 2.0. If a copy of the MPL was not distributed with this 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 7 8 #ifdef FREEBL_NO_DEPEND 9 #include "stubs.h" 10 #endif 11 12 #include "secerr.h" 13 #include "blapi.h" 14 #include "blake2b.h" 15 #include "crypto_primitives.h" 16 17 /** 18 * This contains the BLAKE2b initialization vectors. 19 */ 20 static const uint64_t iv[8] = { 21 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 0x3c6ef372fe94f82bULL, 22 0xa54ff53a5f1d36f1ULL, 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL, 23 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL 24 }; 25 26 /** 27 * This contains the table of permutations for blake2b compression function. 28 */ 29 static const uint8_t sigma[12][16] = { 30 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, 31 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, 32 { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 }, 33 { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 }, 34 { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 }, 35 { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 }, 36 { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 }, 37 { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 }, 38 { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 }, 39 { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 }, 40 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, 41 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } 42 }; 43 44 /** 45 * This function increments the blake2b ctx counter. 46 */ 47 void 48 blake2b_IncrementCounter(BLAKE2BContext* ctx, const uint64_t inc) 49 { 50 ctx->t[0] += inc; 51 ctx->t[1] += ctx->t[0] < inc; 52 } 53 54 /** 55 * This macro implements the blake2b mixing function which mixes two 8-byte 56 * words from the message into the hash. 57 */ 58 #define G(a, b, c, d, x, y) \ 59 a += b + x; \ 60 d = ROTR64(d ^ a, 32); \ 61 c += d; \ 62 b = ROTR64(b ^ c, 24); \ 63 a += b + y; \ 64 d = ROTR64(d ^ a, 16); \ 65 c += d; \ 66 b = ROTR64(b ^ c, 63) 67 68 #define ROUND(i) \ 69 G(v[0], v[4], v[8], v[12], m[sigma[i][0]], m[sigma[i][1]]); \ 70 G(v[1], v[5], v[9], v[13], m[sigma[i][2]], m[sigma[i][3]]); \ 71 G(v[2], v[6], v[10], v[14], m[sigma[i][4]], m[sigma[i][5]]); \ 72 G(v[3], v[7], v[11], v[15], m[sigma[i][6]], m[sigma[i][7]]); \ 73 G(v[0], v[5], v[10], v[15], m[sigma[i][8]], m[sigma[i][9]]); \ 74 G(v[1], v[6], v[11], v[12], m[sigma[i][10]], m[sigma[i][11]]); \ 75 G(v[2], v[7], v[8], v[13], m[sigma[i][12]], m[sigma[i][13]]); \ 76 G(v[3], v[4], v[9], v[14], m[sigma[i][14]], m[sigma[i][15]]) 77 78 /** 79 * The blake2b compression function which takes a full 128-byte chunk of the 80 * input message and mixes it into the ongoing ctx array, i.e., permute the 81 * ctx while xoring in the block of data. 82 */ 83 void 84 blake2b_Compress(BLAKE2BContext* ctx, const uint8_t* block) 85 { 86 size_t i; 87 uint64_t v[16], m[16]; 88 89 PORT_Memcpy(m, block, BLAKE2B_BLOCK_LENGTH); 90 #if !defined(IS_LITTLE_ENDIAN) 91 for (i = 0; i < 16; ++i) { 92 m[i] = FREEBL_HTONLL(m[i]); 93 } 94 #endif 95 96 PORT_Memcpy(v, ctx->h, 8 * 8); 97 PORT_Memcpy(v + 8, iv, 8 * 8); 98 99 v[12] ^= ctx->t[0]; 100 v[13] ^= ctx->t[1]; 101 v[14] ^= ctx->f; 102 103 ROUND(0); 104 ROUND(1); 105 ROUND(2); 106 ROUND(3); 107 ROUND(4); 108 ROUND(5); 109 ROUND(6); 110 ROUND(7); 111 ROUND(8); 112 ROUND(9); 113 ROUND(10); 114 ROUND(11); 115 116 for (i = 0; i < 8; i++) { 117 ctx->h[i] ^= v[i] ^ v[i + 8]; 118 } 119 } 120 121 /** 122 * This function can be used for both keyed and unkeyed version. 123 */ 124 BLAKE2BContext* 125 BLAKE2B_NewContext() 126 { 127 return PORT_ZNew(BLAKE2BContext); 128 } 129 130 /** 131 * Zero and free the context and can be used for both keyed and unkeyed version. 132 */ 133 void 134 BLAKE2B_DestroyContext(BLAKE2BContext* ctx, PRBool freeit) 135 { 136 PORT_Memset(ctx, 0, sizeof(*ctx)); 137 if (freeit) { 138 PORT_Free(ctx); 139 } 140 } 141 142 /** 143 * This function initializes blake2b ctx and can be used for both keyed and 144 * unkeyed version. It also checks ctx and sets error states. 145 */ 146 static SECStatus 147 blake2b_Begin(BLAKE2BContext* ctx, uint8_t outlen, const uint8_t* key, 148 size_t keylen) 149 { 150 if (!ctx) { 151 goto failure_noclean; 152 } 153 if (outlen == 0 || outlen > BLAKE2B512_LENGTH) { 154 goto failure; 155 } 156 if (key && keylen > BLAKE2B_KEY_SIZE) { 157 goto failure; 158 } 159 /* Note: key can be null if it's unkeyed. */ 160 if ((key == NULL && keylen > 0) || keylen > BLAKE2B_KEY_SIZE || 161 (key != NULL && keylen == 0)) { 162 goto failure; 163 } 164 165 /* Mix key size(keylen) and desired hash length(outlen) into h0 */ 166 uint64_t param = outlen ^ (keylen << 8) ^ (1 << 16) ^ (1 << 24); 167 PORT_Memcpy(ctx->h, iv, 8 * 8); 168 ctx->h[0] ^= param; 169 ctx->outlen = outlen; 170 171 /* This updates the context for only the keyed version */ 172 if (keylen > 0 && keylen <= BLAKE2B_KEY_SIZE && key) { 173 uint8_t block[BLAKE2B_BLOCK_LENGTH] = { 0 }; 174 PORT_Memcpy(block, key, keylen); 175 BLAKE2B_Update(ctx, block, BLAKE2B_BLOCK_LENGTH); 176 PORT_Memset(block, 0, BLAKE2B_BLOCK_LENGTH); 177 } 178 179 return SECSuccess; 180 181 failure: 182 PORT_Memset(ctx, 0, sizeof(*ctx)); 183 failure_noclean: 184 PORT_SetError(SEC_ERROR_INVALID_ARGS); 185 return SECFailure; 186 } 187 188 SECStatus 189 BLAKE2B_Begin(BLAKE2BContext* ctx) 190 { 191 return blake2b_Begin(ctx, BLAKE2B512_LENGTH, NULL, 0); 192 } 193 194 SECStatus 195 BLAKE2B_MAC_Begin(BLAKE2BContext* ctx, const PRUint8* key, const size_t keylen) 196 { 197 PORT_Assert(key != NULL); 198 if (!key) { 199 PORT_SetError(SEC_ERROR_INVALID_ARGS); 200 return SECFailure; 201 } 202 return blake2b_Begin(ctx, BLAKE2B512_LENGTH, (const uint8_t*)key, keylen); 203 } 204 205 static void 206 blake2b_IncrementCompress(BLAKE2BContext* ctx, size_t blockLength, 207 const unsigned char* input) 208 { 209 blake2b_IncrementCounter(ctx, blockLength); 210 blake2b_Compress(ctx, input); 211 } 212 213 /** 214 * This function updates blake2b ctx and can be used for both keyed and unkeyed 215 * version. 216 */ 217 SECStatus 218 BLAKE2B_Update(BLAKE2BContext* ctx, const unsigned char* in, 219 unsigned int inlen) 220 { 221 /* Nothing to do if there's nothing. */ 222 if (inlen == 0) { 223 return SECSuccess; 224 } 225 226 if (!ctx || !in) { 227 PORT_SetError(SEC_ERROR_INVALID_ARGS); 228 return SECFailure; 229 } 230 231 /* Is this a reused context? */ 232 if (ctx->f) { 233 PORT_SetError(SEC_ERROR_INVALID_ARGS); 234 return SECFailure; 235 } 236 237 size_t left = ctx->buflen; 238 PORT_Assert(left <= BLAKE2B_BLOCK_LENGTH); 239 size_t fill = BLAKE2B_BLOCK_LENGTH - left; 240 241 if (inlen > fill) { 242 if (ctx->buflen) { 243 /* There's some remaining data in ctx->buf that we have to prepend 244 * to in. */ 245 PORT_Memcpy(ctx->buf + left, in, fill); 246 ctx->buflen = 0; 247 blake2b_IncrementCompress(ctx, BLAKE2B_BLOCK_LENGTH, ctx->buf); 248 in += fill; 249 inlen -= fill; 250 } 251 while (inlen > BLAKE2B_BLOCK_LENGTH) { 252 blake2b_IncrementCompress(ctx, BLAKE2B_BLOCK_LENGTH, in); 253 in += BLAKE2B_BLOCK_LENGTH; 254 inlen -= BLAKE2B_BLOCK_LENGTH; 255 } 256 } 257 258 /* Store the remaining data from in in ctx->buf to process later. 259 * Note that ctx->buflen can be BLAKE2B_BLOCK_LENGTH. We can't process that 260 * here because we have to update ctx->f before compressing the last block. 261 */ 262 PORT_Assert(inlen <= BLAKE2B_BLOCK_LENGTH); 263 PORT_Memcpy(ctx->buf + ctx->buflen, in, inlen); 264 ctx->buflen += inlen; 265 266 return SECSuccess; 267 } 268 269 /** 270 * This function finalizes ctx, pads final block and stores hash. 271 * It can be used for both keyed and unkeyed version. 272 */ 273 SECStatus 274 BLAKE2B_End(BLAKE2BContext* ctx, unsigned char* out, 275 unsigned int* digestLen, size_t maxDigestLen) 276 { 277 size_t i; 278 unsigned int outlen = PR_MIN(BLAKE2B512_LENGTH, maxDigestLen); 279 280 /* Argument checks */ 281 if (!ctx || !out) { 282 PORT_SetError(SEC_ERROR_INVALID_ARGS); 283 return SECFailure; 284 } 285 286 /* Sanity check against outlen in context. */ 287 if (ctx->outlen < outlen) { 288 PORT_SetError(SEC_ERROR_INVALID_ARGS); 289 return SECFailure; 290 } 291 292 /* Is this a reused context? */ 293 if (ctx->f != 0) { 294 PORT_SetError(SEC_ERROR_INVALID_ARGS); 295 return SECFailure; 296 } 297 298 /* Process the remaining data from ctx->buf (padded with 0). */ 299 blake2b_IncrementCounter(ctx, ctx->buflen); 300 /* BLAKE2B_BLOCK_LENGTH - ctx->buflen can be 0. */ 301 PORT_Memset(ctx->buf + ctx->buflen, 0, BLAKE2B_BLOCK_LENGTH - ctx->buflen); 302 ctx->f = UINT64_MAX; 303 blake2b_Compress(ctx, ctx->buf); 304 305 /* Write out the blake2b context(ctx). */ 306 for (i = 0; i < outlen; ++i) { 307 out[i] = ctx->h[i / 8] >> ((i % 8) * 8); 308 } 309 310 if (digestLen) { 311 *digestLen = outlen; 312 } 313 314 return SECSuccess; 315 } 316 317 SECStatus 318 blake2b_HashBuf(uint8_t* output, const uint8_t* input, uint8_t outlen, 319 size_t inlen, const uint8_t* key, size_t keylen) 320 { 321 SECStatus rv = SECFailure; 322 BLAKE2BContext ctx = { { 0 } }; 323 324 if (inlen != 0) { 325 PORT_Assert(input != NULL); 326 if (input == NULL) { 327 PORT_SetError(SEC_ERROR_INVALID_ARGS); 328 goto done; 329 } 330 } 331 332 PORT_Assert(output != NULL); 333 if (output == NULL) { 334 PORT_SetError(SEC_ERROR_INVALID_ARGS); 335 goto done; 336 } 337 338 if (blake2b_Begin(&ctx, outlen, key, keylen) != SECSuccess) { 339 goto done; 340 } 341 342 if (BLAKE2B_Update(&ctx, input, inlen) != SECSuccess) { 343 goto done; 344 } 345 346 if (BLAKE2B_End(&ctx, output, NULL, outlen) != SECSuccess) { 347 goto done; 348 } 349 rv = SECSuccess; 350 351 done: 352 PORT_Memset(&ctx, 0, sizeof ctx); 353 return rv; 354 } 355 356 SECStatus 357 BLAKE2B_Hash(unsigned char* dest, const char* src) 358 { 359 return blake2b_HashBuf(dest, (const unsigned char*)src, BLAKE2B512_LENGTH, 360 PORT_Strlen(src), NULL, 0); 361 } 362 363 SECStatus 364 BLAKE2B_HashBuf(unsigned char* output, const unsigned char* input, PRUint32 inlen) 365 { 366 return blake2b_HashBuf(output, input, BLAKE2B512_LENGTH, inlen, NULL, 0); 367 } 368 369 SECStatus 370 BLAKE2B_MAC_HashBuf(unsigned char* output, const unsigned char* input, 371 unsigned int inlen, const unsigned char* key, 372 unsigned int keylen) 373 { 374 PORT_Assert(key != NULL); 375 if (!key && keylen <= BLAKE2B_KEY_SIZE) { 376 PORT_SetError(SEC_ERROR_INVALID_ARGS); 377 return SECFailure; 378 } 379 return blake2b_HashBuf(output, input, BLAKE2B512_LENGTH, inlen, key, keylen); 380 } 381 382 unsigned int 383 BLAKE2B_FlattenSize(BLAKE2BContext* ctx) 384 { 385 return sizeof(BLAKE2BContext); 386 } 387 388 SECStatus 389 BLAKE2B_Flatten(BLAKE2BContext* ctx, unsigned char* space) 390 { 391 PORT_Assert(space != NULL); 392 if (!space) { 393 PORT_SetError(SEC_ERROR_INVALID_ARGS); 394 return SECFailure; 395 } 396 PORT_Memcpy(space, ctx, sizeof(BLAKE2BContext)); 397 return SECSuccess; 398 } 399 400 BLAKE2BContext* 401 BLAKE2B_Resurrect(unsigned char* space, void* arg) 402 { 403 PORT_Assert(space != NULL); 404 if (!space) { 405 PORT_SetError(SEC_ERROR_INVALID_ARGS); 406 return NULL; 407 } 408 BLAKE2BContext* ctx = BLAKE2B_NewContext(); 409 if (ctx == NULL) { 410 PORT_SetError(SEC_ERROR_INVALID_ARGS); 411 return NULL; 412 } 413 414 PORT_Memcpy(ctx, space, sizeof(BLAKE2BContext)); 415 return ctx; 416 } 417 418 void 419 BLAKE2B_Clone(BLAKE2BContext* dest, BLAKE2BContext* src) 420 { 421 PORT_Assert(dest != NULL); 422 PORT_Assert(src != NULL); 423 if (!dest || !src) { 424 PORT_SetError(SEC_ERROR_INVALID_ARGS); 425 return; 426 } 427 PORT_Memcpy(dest, src, sizeof(BLAKE2BContext)); 428 }