File Coverage

src/mac/hmac_ct.c
Criterion Covered Total %
statement 0 53 0.0
branch 0 14 0.0
condition n/a
subroutine n/a
pod n/a
total 0 67 0.0


line stmt bran cond sub pod time code
1             /*
2             * Copyright (c) 2016 Thomas Pornin
3             *
4             * Permission is hereby granted, free of charge, to any person obtaining
5             * a copy of this software and associated documentation files (the
6             * "Software"), to deal in the Software without restriction, including
7             * without limitation the rights to use, copy, modify, merge, publish,
8             * distribute, sublicense, and/or sell copies of the Software, and to
9             * permit persons to whom the Software is furnished to do so, subject to
10             * the following conditions:
11             *
12             * The above copyright notice and this permission notice shall be
13             * included in all copies or substantial portions of the Software.
14             *
15             * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16             * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17             * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18             * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19             * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20             * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21             * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22             * SOFTWARE.
23             */
24              
25             #include "inner.h"
26              
27             static inline size_t
28 0           hash_size(const br_hash_class *dig)
29             {
30 0           return (unsigned)(dig->desc >> BR_HASHDESC_OUT_OFF)
31 0           & BR_HASHDESC_OUT_MASK;
32             }
33              
34             static inline size_t
35 0           block_size(const br_hash_class *dig)
36             {
37             unsigned ls;
38            
39 0           ls = (unsigned)(dig->desc >> BR_HASHDESC_LBLEN_OFF)
40             & BR_HASHDESC_LBLEN_MASK;
41 0           return (size_t)1 << ls;
42             }
43              
44             /* see bearssl.h */
45             size_t
46 0           br_hmac_outCT(const br_hmac_context *ctx,
47             const void *data, size_t len, size_t min_len, size_t max_len,
48             void *out)
49             {
50             /*
51             * Method implemented here is inspired from the descriptions on:
52             * https://www.imperialviolet.org/2013/02/04/luckythirteen.html
53             *
54             * Principle: we input bytes one by one. We use a MUX to push
55             * padding bytes instead of data bytes when appropriate. At each
56             * block limit, we get the current hash function state: this is
57             * a potential output, since we handle MD padding ourselves.
58             *
59             * be 1 for big-endian, 0 for little-endian
60             * po minimal MD padding length
61             * bs block size (always a power of 2)
62             * hlen hash output size
63             */
64              
65             const br_hash_class *dig;
66             br_hash_compat_context hc;
67             int be;
68             uint32_t po, bs;
69             uint32_t kr, km, kl, kz, u;
70             uint64_t count, ncount, bit_len;
71             unsigned char tmp1[64], tmp2[64];
72             size_t hlen;
73              
74             /*
75             * Copy the current hash context.
76             */
77 0           hc = ctx->dig;
78              
79             /*
80             * Get function-specific information.
81             */
82 0           dig = hc.vtable;
83 0           be = (dig->desc & BR_HASHDESC_MD_PADDING_BE) != 0;
84 0           po = 9;
85 0 0         if (dig->desc & BR_HASHDESC_MD_PADDING_128) {
86 0           po += 8;
87             }
88 0           bs = block_size(dig);
89 0           hlen = hash_size(dig);
90              
91             /*
92             * Get current input length and compute total bit length.
93             */
94 0           count = dig->state(&hc.vtable, tmp1);
95 0           bit_len = (count + (uint64_t)len) << 3;
96              
97             /*
98             * We can input the blocks that we are sure we will use.
99             * This offers better performance (no MUX for these blocks)
100             * and also ensures that the remaining lengths fit on 32 bits.
101             */
102 0           ncount = (count + (uint64_t)min_len) & ~(uint64_t)(bs - 1);
103 0 0         if (ncount > count) {
104             size_t zlen;
105              
106 0           zlen = (size_t)(ncount - count);
107 0           dig->update(&hc.vtable, data, zlen);
108 0           data = (const unsigned char *)data + zlen;
109 0           len -= zlen;
110 0           max_len -= zlen;
111 0           count = ncount;
112             }
113              
114             /*
115             * At that point:
116             * -- 'count' contains the number of bytes already processed
117             * (in total).
118             * -- We must input 'len' bytes. 'min_len' is unimportant: we
119             * used it to know how many full blocks we could process
120             * directly. Now only len and max_len matter.
121             *
122             * We compute kr, kl, kz and km.
123             * kr number of input bytes already in the current block
124             * km index of the first byte after the end of the last padding
125             * block, if length is max_len
126             * kz index of the last byte of the actual last padding block
127             * kl index of the start of the encoded length
128             *
129             * km, kz and kl are counted from the current offset in the
130             * input data.
131             */
132 0           kr = (uint32_t)count & (bs - 1);
133 0           kz = ((kr + (uint32_t)len + po + bs - 1) & ~(bs - 1)) - 1 - kr;
134 0           kl = kz - 7;
135 0           km = ((kr + (uint32_t)max_len + po + bs - 1) & ~(bs - 1)) - kr;
136              
137             /*
138             * We must now process km bytes. For index u from 0 to km-1:
139             * d is from data[] if u < max_len, 0x00 otherwise
140             * e is an encoded length byte or 0x00, depending on u
141             * The tests for d and e need not be constant-time, since
142             * they relate only to u and max_len, not to the actual length.
143             *
144             * Actual input length is then:
145             * d if u < len
146             * 0x80 if u == len
147             * 0x00 if u > len and u < kl
148             * e if u >= kl
149             *
150             * Hash state is obtained whenever we reach a full block. This
151             * is the result we want if and only if u == kz.
152             */
153 0           memset(tmp2, 0, sizeof tmp2);
154 0 0         for (u = 0; u < km; u ++) {
155             uint32_t v;
156             uint32_t d, e, x0, x1;
157             unsigned char x[1];
158              
159 0 0         d = (u < max_len) ? ((const unsigned char *)data)[u] : 0x00;
160 0           v = (kr + u) & (bs - 1);
161 0 0         if (v >= (bs - 8)) {
162             unsigned j;
163              
164 0           j = (v - (bs - 8)) << 3;
165 0 0         if (be) {
166 0           e = (uint32_t)(bit_len >> (56 - j));
167             } else {
168 0           e = (uint32_t)(bit_len >> j);
169             }
170 0           e &= 0xFF;
171             } else {
172 0           e = 0x00;
173             }
174 0           x0 = MUX(EQ(u, (uint32_t)len), 0x80, d);
175 0           x1 = MUX(LT(u, kl), 0x00, e);
176 0           x[0] = MUX(LE(u, (uint32_t)len), x0, x1);
177 0           dig->update(&hc.vtable, x, 1);
178 0 0         if (v == (bs - 1)) {
179 0           dig->state(&hc.vtable, tmp1);
180 0           CCOPY(EQ(u, kz), tmp2, tmp1, hlen);
181             }
182             }
183              
184             /*
185             * Inner hash output is in tmp2[]; we finish processing.
186             */
187 0           dig->init(&hc.vtable);
188 0           dig->set_state(&hc.vtable, ctx->kso, (uint64_t)bs);
189 0           dig->update(&hc.vtable, tmp2, hlen);
190 0           dig->out(&hc.vtable, tmp2);
191 0           memcpy(out, tmp2, ctx->out_len);
192 0           return ctx->out_len;
193             }