/*- * Copyright 2009 Colin Percival, 2011 ArtForz, 2013 Neisklar, * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * This file was originally written by Colin Percival as part of the Tarsnap * online backup system. */ #include "quark.h" #include #include #include #include #include "sha3/sph_blake.h" #include "sha3/sph_bmw.h" #include "sha3/sph_groestl.h" #include "sha3/sph_jh.h" #include "sha3/sph_keccak.h" #include "sha3/sph_skein.h" static __inline uint32_t be32dec(const void *pp) { const uint8_t *p = (uint8_t const *)pp; return ((uint32_t)(p[3]) + ((uint32_t)(p[2]) << 8) + ((uint32_t)(p[1]) << 16) + ((uint32_t)(p[0]) << 24)); } static __inline void be32enc(void *pp, uint32_t x) { uint8_t * p = (uint8_t *)pp; p[3] = x & 0xff; p[2] = (x >> 8) & 0xff; p[1] = (x >> 16) & 0xff; p[0] = (x >> 24) & 0xff; } static __inline uint32_t le32dec(const void *pp) { const uint8_t *p = (uint8_t const *)pp; return ((uint32_t)(p[0]) + ((uint32_t)(p[1]) << 8) + ((uint32_t)(p[2]) << 16) + ((uint32_t)(p[3]) << 24)); } static __inline void le32enc(void *pp, uint32_t x) { uint8_t * p = (uint8_t *)pp; p[0] = x & 0xff; p[1] = (x >> 8) & 0xff; p[2] = (x >> 16) & 0xff; p[3] = (x >> 24) & 0xff; } /* * Encode a length len/4 vector of (uint32_t) into a length len vector of * (unsigned char) in big-endian form. Assumes len is a multiple of 4. */ static void be32enc_vect(unsigned char *dst, const uint32_t *src, uint32_t len) { size_t i; for (i = 0; i < len / 4; i++) be32enc(dst + i * 4, src[i]); } /* * Decode a big-endian length len vector of (unsigned char) into a length * len/4 vector of (uint32_t). Assumes len is a multiple of 4. */ static void be32dec_vect(uint32_t *dst, const unsigned char *src, uint32_t len) { size_t i; for (i = 0; i < len / 4; i++) dst[i] = be32dec(src + i * 4); } void quark_hash(const char* input, char* output, uint32_t len) { sph_blake512_context ctx_blake; sph_bmw512_context ctx_bmw; sph_groestl512_context ctx_groestl; sph_jh512_context ctx_jh; sph_keccak512_context ctx_keccak; sph_skein512_context ctx_skein; uint32_t mask = 8; uint32_t zero = 0; uint32_t hashA[16], hashB[16]; sph_blake512_init(&ctx_blake); sph_blake512 (&ctx_blake, input, len); sph_blake512_close (&ctx_blake, hashA); //0 sph_bmw512_init(&ctx_bmw); sph_bmw512 (&ctx_bmw, hashA, 64); //0 sph_bmw512_close(&ctx_bmw, hashB); //1 if ((hashB[0] & mask) != zero) //1 { sph_groestl512_init(&ctx_groestl); sph_groestl512 (&ctx_groestl, hashB, 64); //1 sph_groestl512_close(&ctx_groestl, hashA); //2 } else { sph_skein512_init(&ctx_skein); sph_skein512 (&ctx_skein, hashB, 64); //1 sph_skein512_close(&ctx_skein, hashA); //2 } sph_groestl512_init(&ctx_groestl); sph_groestl512 (&ctx_groestl, hashA, 64); //2 sph_groestl512_close(&ctx_groestl, hashB); //3 sph_jh512_init(&ctx_jh); sph_jh512 (&ctx_jh, hashB, 64); //3 sph_jh512_close(&ctx_jh, hashA); //4 if ((hashA[0] & mask) != zero) //4 { sph_blake512_init(&ctx_blake); sph_blake512 (&ctx_blake, hashA, 64); // sph_blake512_close(&ctx_blake, hashB); //5 } else { sph_bmw512_init(&ctx_bmw); sph_bmw512 (&ctx_bmw, hashA, 64); //4 sph_bmw512_close(&ctx_bmw, hashB); //5 } sph_keccak512_init(&ctx_keccak); sph_keccak512 (&ctx_keccak,hashB, 64); //5 sph_keccak512_close(&ctx_keccak, hashA); //6 sph_skein512_init(&ctx_skein); sph_skein512 (&ctx_skein, hashA, 64); //6 sph_skein512_close(&ctx_skein, hashB); //7 if ((hashB[0] & mask) != zero) //7 { sph_keccak512_init(&ctx_keccak); sph_keccak512 (&ctx_keccak, hashB, 64); // sph_keccak512_close(&ctx_keccak, hashA); //8 } else { sph_jh512_init(&ctx_jh); sph_jh512 (&ctx_jh, hashB, 64); //7 sph_jh512_close(&ctx_jh, hashA); //8 } memcpy(output, hashA, 32); /* printf("result: "); for (ii=0; ii < 32; ii++) { printf ("%.2x",((uint8_t*)output)[ii]); } printf ("\n"); */ }