File: cryptonite_hash_prefix.c

package info (click to toggle)
haskell-cryptonite 0.30-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 3,372 kB
  • sloc: ansic: 22,009; haskell: 18,423; makefile: 8
file content (90 lines) | stat: -rw-r--r-- 3,471 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/*
 * Copyright (C) 2020 Olivier Chéron <olivier.cheron@gmail.com>
 *
 * 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 ``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 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.
 */

#include <cryptonite_hash_prefix.h>

void CRYPTONITE_HASHED(finalize_prefix)(struct HASHED_LOWER(ctx) *ctx, const uint8_t *data, uint32_t len, uint32_t n, uint8_t *out)
{
	uint64_t bits[HASHED(BITS_ELEMS)];
	uint8_t *p = (uint8_t *) &bits;
	uint32_t index, padidx, padlen, pos, out_mask;
	static const uint32_t cut_off = HASHED(BLOCK_SIZE) - sizeof(bits);

	/* Make sure n <= len */
	n += (len - n) & constant_time_lt(len, n);

	/* Initial index, based on current context state */
	index = CRYPTONITE_HASHED(get_index)(ctx);

	/* Final size after n bytes */
	CRYPTONITE_HASHED(incr_sz)(ctx, bits, n);

	/* Padding index and length */
	padidx = CRYPTONITE_HASHED(get_index)(ctx);
	padlen = HASHED(BLOCK_SIZE) + cut_off - padidx;
	padlen -= HASHED(BLOCK_SIZE) & constant_time_lt(padidx, cut_off);

	/* Initialize buffers because we will XOR into them */
	memset(ctx->buf + index, 0, HASHED(BLOCK_SIZE) - index);
	memset(out, 0, HASHED(DIGEST_SIZE));
	pos = 0;

	/* Iterate based on the full buffer length, regardless of n, and include
	 * the maximum overhead with padding and size bytes
	 */
	while (pos < len + HASHED(BLOCK_SIZE) + sizeof(bits)) {
		uint8_t b;

		/* Take as many bytes from the input buffer as possible */
		if (pos < len)
			b = *(data++) & (uint8_t) constant_time_lt(pos, n);
		else
			b = 0;

		/* First padding byte */
		b |= 0x80 & (uint8_t) constant_time_eq(pos, n);

		/* Size bytes are always at the end of a block */
		if (index >= cut_off)
			b |= p[index - cut_off] & (uint8_t) constant_time_ge(pos, n + padlen);

		/* Store this byte into the buffer */
		ctx->buf[index++] ^= b;
		pos++;

		/* Process a full block, at a boundary which is independent from n */
		if (index >= HASHED(BLOCK_SIZE)) {
			index = 0;
			HASHED_LOWER(do_chunk)(ctx, (void *) ctx->buf);
			memset(ctx->buf, 0, HASHED(BLOCK_SIZE));

			/* Try to store the result: this is a no-op except when we reach the
			 * actual size based on n, more iterations may continue after that
			 * when len is really larger
			 */
			out_mask = constant_time_eq(pos, n + padlen + sizeof(bits));
			CRYPTONITE_HASHED(select_digest)(ctx, out, out_mask);
		}
	}
}