void hmac_whirlpool ( char *k, /* secret key */ int lk, /* length of the key in bytes */ char *d, /* input data. d pointer is guaranteed to be at least 32-bytes long */ int ld /* length of data in bytes */ ) { hmac_whirlpool_ctx hmac; char key[WHIRLPOOL_DIGESTSIZE]; /* If the key is longer than the hash algorithm block size, let key = whirlpool(key), as per HMAC specifications. */ if (lk > WHIRLPOOL_BLOCKSIZE) { WHIRLPOOL_CTX tctx; WHIRLPOOL_init (&tctx); WHIRLPOOL_add ((unsigned char *) k, lk * 8, &tctx); WHIRLPOOL_finalize (&tctx, (unsigned char *) key); k = key; lk = WHIRLPOOL_DIGESTSIZE; burn (&tctx, sizeof(tctx)); // Prevent leaks } hmac_whirlpool_internal(k, lk, d, ld, &hmac); /* Prevent leaks */ burn(&hmac, sizeof(hmac)); }
void ComputeBootloaderFingerprint (byte *bootLoaderBuf, unsigned int bootLoaderSize, byte* fingerprint) { // compute Whirlpool+SHA512 fingerprint of bootloader including MBR // we skip user configuration fields: // TC_BOOT_SECTOR_PIM_VALUE_OFFSET = 400 // TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_OFFSET = 402 // => TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_SIZE = 4 // TC_BOOT_SECTOR_USER_MESSAGE_OFFSET = 406 // => TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH = 24 // TC_BOOT_SECTOR_USER_CONFIG_OFFSET = 438 // // we have: TC_BOOT_SECTOR_USER_MESSAGE_OFFSET = TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_OFFSET + TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_SIZE WHIRLPOOL_CTX whirlpool; sha512_ctx sha2; WHIRLPOOL_init (&whirlpool); sha512_begin (&sha2); WHIRLPOOL_add (bootLoaderBuf, TC_BOOT_SECTOR_PIM_VALUE_OFFSET, &whirlpool); sha512_hash (bootLoaderBuf, TC_BOOT_SECTOR_PIM_VALUE_OFFSET, &sha2); WHIRLPOOL_add (bootLoaderBuf + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET + TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH, (TC_BOOT_SECTOR_USER_CONFIG_OFFSET - (TC_BOOT_SECTOR_USER_MESSAGE_OFFSET + TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH)), &whirlpool); sha512_hash (bootLoaderBuf + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET + TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH, (TC_BOOT_SECTOR_USER_CONFIG_OFFSET - (TC_BOOT_SECTOR_USER_MESSAGE_OFFSET + TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH)), &sha2); WHIRLPOOL_add (bootLoaderBuf + TC_BOOT_SECTOR_USER_CONFIG_OFFSET + 1, (TC_MAX_MBR_BOOT_CODE_SIZE - (TC_BOOT_SECTOR_USER_CONFIG_OFFSET + 1)), &whirlpool); sha512_hash (bootLoaderBuf + TC_BOOT_SECTOR_USER_CONFIG_OFFSET + 1, (TC_MAX_MBR_BOOT_CODE_SIZE - (TC_BOOT_SECTOR_USER_CONFIG_OFFSET + 1)), &sha2); WHIRLPOOL_add (bootLoaderBuf + TC_SECTOR_SIZE_BIOS, (bootLoaderSize - TC_SECTOR_SIZE_BIOS), &whirlpool); sha512_hash (bootLoaderBuf + TC_SECTOR_SIZE_BIOS, (bootLoaderSize - TC_SECTOR_SIZE_BIOS), &sha2); WHIRLPOOL_finalize (&whirlpool, fingerprint); sha512_end (&fingerprint [WHIRLPOOL_DIGESTSIZE], &sha2); }
void hmac_whirlpool_internal ( char *k, /* secret key */ int lk, /* length of the key in bytes */ char *d, /* input/output data. d pointer is guaranteed to be at least 64-bytes long */ int ld, /* length of input data in bytes */ hmac_whirlpool_ctx* hmac /* HMAC-Whirlpool context which holds temporary variables */ ) { WHIRLPOOL_CTX* ctx = &(hmac->ctx); char* buf = hmac->buf; int i; /**** Inner Digest ****/ WHIRLPOOL_init (ctx); /* Pad the key for inner digest */ for (i = 0; i < lk; ++i) buf[i] = (char) (k[i] ^ 0x36); for (i = lk; i < WHIRLPOOL_BLOCKSIZE; ++i) buf[i] = 0x36; WHIRLPOOL_add ((unsigned char *) buf, WHIRLPOOL_BLOCKSIZE * 8, ctx); WHIRLPOOL_add ((unsigned char *) d, ld * 8, ctx); WHIRLPOOL_finalize (ctx, (unsigned char *) d); /**** Outer Digest ****/ WHIRLPOOL_init (ctx); for (i = 0; i < lk; ++i) buf[i] = (char) (k[i] ^ 0x5C); for (i = lk; i < WHIRLPOOL_BLOCKSIZE; ++i) buf[i] = 0x5C; WHIRLPOOL_add ((unsigned char *) buf, WHIRLPOOL_BLOCKSIZE * 8, ctx); WHIRLPOOL_add ((unsigned char *) d, WHIRLPOOL_DIGESTSIZE * 8, ctx); WHIRLPOOL_finalize (ctx, (unsigned char *) d); }
void derive_key_whirlpool (char *pwd, int pwd_len, char *salt, int salt_len, uint32 iterations, char *dk, int dklen) { hmac_whirlpool_ctx hmac; char key[WHIRLPOOL_DIGESTSIZE]; int b, l, r; /* If the password is longer than the hash algorithm block size, let pwd = whirlpool(pwd), as per HMAC specifications. */ if (pwd_len > WHIRLPOOL_BLOCKSIZE) { WHIRLPOOL_CTX tctx; WHIRLPOOL_init (&tctx); WHIRLPOOL_add ((unsigned char *) pwd, pwd_len * 8, &tctx); WHIRLPOOL_finalize (&tctx, (unsigned char *) key); pwd = key; pwd_len = WHIRLPOOL_DIGESTSIZE; burn (&tctx, sizeof(tctx)); // Prevent leaks } if (dklen % WHIRLPOOL_DIGESTSIZE) { l = 1 + dklen / WHIRLPOOL_DIGESTSIZE; } else { l = dklen / WHIRLPOOL_DIGESTSIZE; } r = dklen - (l - 1) * WHIRLPOOL_DIGESTSIZE; /* first l - 1 blocks */ for (b = 1; b < l; b++) { derive_u_whirlpool (pwd, pwd_len, salt, salt_len, iterations, b, &hmac); memcpy (dk, hmac.u, WHIRLPOOL_DIGESTSIZE); dk += WHIRLPOOL_DIGESTSIZE; } /* last block */ derive_u_whirlpool (pwd, pwd_len, salt, salt_len, iterations, b, &hmac); memcpy (dk, hmac.u, r); /* Prevent possible leaks. */ burn (&hmac, sizeof(hmac)); burn (key, sizeof(key)); }
/* The random pool mixing function */ BOOL Randmix () { if (bRandmixEnabled) { unsigned char hashOutputBuffer [MAX_DIGESTSIZE]; WHIRLPOOL_CTX wctx; RMD160_CTX rctx; sha512_ctx sctx; sha256_ctx s256ctx; int poolIndex, digestIndex, digestSize; switch (HashFunction) { case RIPEMD160: digestSize = RIPEMD160_DIGESTSIZE; break; case SHA512: digestSize = SHA512_DIGESTSIZE; break; case SHA256: digestSize = SHA256_DIGESTSIZE; break; case WHIRLPOOL: digestSize = WHIRLPOOL_DIGESTSIZE; break; default: TC_THROW_FATAL_EXCEPTION; } if (RNG_POOL_SIZE % digestSize) TC_THROW_FATAL_EXCEPTION; for (poolIndex = 0; poolIndex < RNG_POOL_SIZE; poolIndex += digestSize) { /* Compute the message digest of the entire pool using the selected hash function. */ switch (HashFunction) { case RIPEMD160: RMD160Init(&rctx); RMD160Update(&rctx, pRandPool, RNG_POOL_SIZE); RMD160Final(hashOutputBuffer, &rctx); break; case SHA512: sha512_begin (&sctx); sha512_hash (pRandPool, RNG_POOL_SIZE, &sctx); sha512_end (hashOutputBuffer, &sctx); break; case SHA256: sha256_begin (&s256ctx); sha256_hash (pRandPool, RNG_POOL_SIZE, &s256ctx); sha256_end (hashOutputBuffer, &s256ctx); break; case WHIRLPOOL: WHIRLPOOL_init (&wctx); WHIRLPOOL_add (pRandPool, RNG_POOL_SIZE * 8, &wctx); WHIRLPOOL_finalize (&wctx, hashOutputBuffer); break; default: // Unknown/wrong ID TC_THROW_FATAL_EXCEPTION; } /* XOR the resultant message digest to the pool at the poolIndex position. */ for (digestIndex = 0; digestIndex < digestSize; digestIndex++) { pRandPool [poolIndex + digestIndex] ^= hashOutputBuffer [digestIndex]; } } /* Prevent leaks */ burn (hashOutputBuffer, MAX_DIGESTSIZE); switch (HashFunction) { case RIPEMD160: burn (&rctx, sizeof(rctx)); break; case SHA512: burn (&sctx, sizeof(sctx)); break; case SHA256: burn (&s256ctx, sizeof(s256ctx)); break; case WHIRLPOOL: burn (&wctx, sizeof(wctx)); break; default: // Unknown/wrong ID TC_THROW_FATAL_EXCEPTION; } } return TRUE; }
void Whirlpool::Init () { WHIRLPOOL_init ((WHIRLPOOL_CTX *) Context.Ptr()); }
/* The random pool mixing function */ BOOL Randmix () { if (bRandmixEnabled) { unsigned char hashOutputBuffer [MAX_DIGESTSIZE]; WHIRLPOOL_CTX wctx; gost_hash_ctx gctx; STRIBOG_CTX sctx; int poolIndex, digestIndex, digestSize; switch (HashFunction) { case WHIRLPOOL: digestSize = WHIRLPOOL_DIGESTSIZE; break; case STRIBOG: digestSize = STRIBOG_DIGESTSIZE; break; case GOSTHASH: digestSize = GOSTHASH_DIGESTSIZE; break; default: GST_THROW_FATAL_EXCEPTION; } if (RNG_POOL_SIZE % digestSize) GST_THROW_FATAL_EXCEPTION; for (poolIndex = 0; poolIndex < RNG_POOL_SIZE; poolIndex += digestSize) { /* Compute the message digest of the entire pool using the selected hash function. */ switch (HashFunction) { case WHIRLPOOL: WHIRLPOOL_init (&wctx); WHIRLPOOL_add (pRandPool, RNG_POOL_SIZE * 8, &wctx); WHIRLPOOL_finalize (&wctx, hashOutputBuffer); break; case STRIBOG: STRIBOG_init (&sctx); STRIBOG_add (&sctx, pRandPool, RNG_POOL_SIZE * 8); STRIBOG_finalize (&sctx, hashOutputBuffer); break; case GOSTHASH: GOSTHASH_init (&gctx); GOSTHASH_add (pRandPool, RNG_POOL_SIZE, &gctx); GOSTHASH_finalize (&gctx, hashOutputBuffer); break; default: // Unknown/wrong ID GST_THROW_FATAL_EXCEPTION; } /* XOR the resultant message digest to the pool at the poolIndex position. */ for (digestIndex = 0; digestIndex < digestSize; digestIndex++) { pRandPool [poolIndex + digestIndex] ^= hashOutputBuffer [digestIndex]; } } /* Prevent leaks */ burn (hashOutputBuffer, MAX_DIGESTSIZE); switch (HashFunction) { case WHIRLPOOL: burn (&wctx, sizeof(wctx)); break; case STRIBOG: burn (&sctx, sizeof(sctx)); break; case GOSTHASH: burn (&gctx, sizeof(gctx)); break; default: // Unknown/wrong ID GST_THROW_FATAL_EXCEPTION; } } return TRUE; }
void hmac_whirlpool ( char *k, /* secret key */ int lk, /* length of the key in bytes */ char *d, /* data */ int ld, /* length of data in bytes */ char *out, /* output buffer, at least "t" bytes */ int t ) { WHIRLPOOL_CTX ictx, octx; char iwhi[WHIRLPOOL_DIGESTSIZE], owhi[WHIRLPOOL_DIGESTSIZE]; char key[WHIRLPOOL_DIGESTSIZE]; char buf[WHIRLPOOL_BLOCKSIZE]; int i; /* If the key is longer than the hash algorithm block size, let key = whirlpool(key), as per HMAC specifications. */ if (lk > WHIRLPOOL_BLOCKSIZE) { WHIRLPOOL_CTX tctx; WHIRLPOOL_init (&tctx); WHIRLPOOL_add ((unsigned char *) k, lk * 8, &tctx); WHIRLPOOL_finalize (&tctx, (unsigned char *) key); k = key; lk = WHIRLPOOL_DIGESTSIZE; burn (&tctx, sizeof(tctx)); // Prevent leaks } /**** Inner Digest ****/ WHIRLPOOL_init (&ictx); /* Pad the key for inner digest */ for (i = 0; i < lk; ++i) buf[i] = (char) (k[i] ^ 0x36); for (i = lk; i < WHIRLPOOL_BLOCKSIZE; ++i) buf[i] = 0x36; WHIRLPOOL_add ((unsigned char *) buf, WHIRLPOOL_BLOCKSIZE * 8, &ictx); WHIRLPOOL_add ((unsigned char *) d, ld * 8, &ictx); WHIRLPOOL_finalize (&ictx, (unsigned char *) iwhi); /**** Outer Digest ****/ WHIRLPOOL_init (&octx); for (i = 0; i < lk; ++i) buf[i] = (char) (k[i] ^ 0x5C); for (i = lk; i < WHIRLPOOL_BLOCKSIZE; ++i) buf[i] = 0x5C; WHIRLPOOL_add ((unsigned char *) buf, WHIRLPOOL_BLOCKSIZE * 8, &octx); WHIRLPOOL_add ((unsigned char *) iwhi, WHIRLPOOL_DIGESTSIZE * 8, &octx); WHIRLPOOL_finalize (&octx, (unsigned char *) owhi); /* truncate and print the results */ t = t > WHIRLPOOL_DIGESTSIZE ? WHIRLPOOL_DIGESTSIZE : t; hmac_truncate (owhi, out, t); /* Prevent possible leaks. */ burn (&ictx, sizeof(ictx)); burn (&octx, sizeof(octx)); burn (owhi, sizeof(owhi)); burn (iwhi, sizeof(iwhi)); burn (buf, sizeof(buf)); burn (key, sizeof(key)); }