/rust/registry/src/index.crates.io-1949cf8c6b5b557f/ring-0.17.14/crypto/poly1305/poly1305.c
Line  | Count  | Source  | 
1  |  | /* Copyright (c) 2014, Google Inc.  | 
2  |  |  *  | 
3  |  |  * Permission to use, copy, modify, and/or distribute this software for any  | 
4  |  |  * purpose with or without fee is hereby granted, provided that the above  | 
5  |  |  * copyright notice and this permission notice appear in all copies.  | 
6  |  |  *  | 
7  |  |  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES  | 
8  |  |  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF  | 
9  |  |  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY  | 
10  |  |  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES  | 
11  |  |  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION  | 
12  |  |  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN  | 
13  |  |  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */  | 
14  |  |  | 
15  |  | // This implementation of poly1305 is by Andrew Moon  | 
16  |  | // (https://github.com/floodyberry/poly1305-donna) and released as public  | 
17  |  | // domain.  | 
18  |  |  | 
19  |  | #include <ring-core/base.h>  | 
20  |  |  | 
21  |  | #include "../internal.h"  | 
22  |  | #include "ring-core/check.h"  | 
23  |  |  | 
24  |  | #if defined(__GNUC__) || defined(__clang__)  | 
25  |  | #pragma GCC diagnostic ignored "-Wsign-conversion"  | 
26  |  | #pragma GCC diagnostic ignored "-Wconversion"  | 
27  |  | #endif  | 
28  |  |  | 
29  | 0  | static uint64_t mul32x32_64(uint32_t a, uint32_t b) { return (uint64_t)a * b; } | 
30  |  |  | 
31  |  | // Keep in sync with `poly1305_state_st` in ffi_fallback.rs.  | 
32  |  | struct poly1305_state_st { | 
33  |  |   alignas(64) uint32_t r0;  | 
34  |  |   uint32_t r1, r2, r3, r4;  | 
35  |  |   uint32_t s1, s2, s3, s4;  | 
36  |  |   uint32_t h0, h1, h2, h3, h4;  | 
37  |  |   uint8_t key[16];  | 
38  |  | };  | 
39  |  |  | 
40  |  | // poly1305_blocks updates |state| given some amount of input data. This  | 
41  |  | // function may only be called with a |len| that is not a multiple of 16 at the  | 
42  |  | // end of the data. Otherwise the input must be buffered into 16 byte blocks.  | 
43  |  | static void poly1305_update(struct poly1305_state_st *state, const uint8_t *in,  | 
44  | 0  |                             size_t len) { | 
45  | 0  |   debug_assert_nonsecret((uintptr_t)state % 64 == 0);  | 
46  |  | 
  | 
47  | 0  |   uint32_t t0, t1, t2, t3;  | 
48  | 0  |   uint64_t t[5];  | 
49  | 0  |   uint32_t b;  | 
50  | 0  |   uint64_t c;  | 
51  | 0  |   size_t j;  | 
52  | 0  |   uint8_t mp[16];  | 
53  |  | 
  | 
54  | 0  |   if (len < 16) { | 
55  | 0  |     goto poly1305_donna_atmost15bytes;  | 
56  | 0  |   }  | 
57  |  |  | 
58  | 0  | poly1305_donna_16bytes:  | 
59  | 0  |   t0 = CRYPTO_load_u32_le(in);  | 
60  | 0  |   t1 = CRYPTO_load_u32_le(in + 4);  | 
61  | 0  |   t2 = CRYPTO_load_u32_le(in + 8);  | 
62  | 0  |   t3 = CRYPTO_load_u32_le(in + 12);  | 
63  |  | 
  | 
64  | 0  |   in += 16;  | 
65  | 0  |   len -= 16;  | 
66  |  | 
  | 
67  | 0  |   state->h0 += t0 & 0x3ffffff;  | 
68  | 0  |   state->h1 += ((((uint64_t)t1 << 32) | t0) >> 26) & 0x3ffffff;  | 
69  | 0  |   state->h2 += ((((uint64_t)t2 << 32) | t1) >> 20) & 0x3ffffff;  | 
70  | 0  |   state->h3 += ((((uint64_t)t3 << 32) | t2) >> 14) & 0x3ffffff;  | 
71  | 0  |   state->h4 += (t3 >> 8) | (1 << 24);  | 
72  |  | 
  | 
73  | 0  | poly1305_donna_mul:  | 
74  | 0  |   t[0] = mul32x32_64(state->h0, state->r0) + mul32x32_64(state->h1, state->s4) +  | 
75  | 0  |          mul32x32_64(state->h2, state->s3) + mul32x32_64(state->h3, state->s2) +  | 
76  | 0  |          mul32x32_64(state->h4, state->s1);  | 
77  | 0  |   t[1] = mul32x32_64(state->h0, state->r1) + mul32x32_64(state->h1, state->r0) +  | 
78  | 0  |          mul32x32_64(state->h2, state->s4) + mul32x32_64(state->h3, state->s3) +  | 
79  | 0  |          mul32x32_64(state->h4, state->s2);  | 
80  | 0  |   t[2] = mul32x32_64(state->h0, state->r2) + mul32x32_64(state->h1, state->r1) +  | 
81  | 0  |          mul32x32_64(state->h2, state->r0) + mul32x32_64(state->h3, state->s4) +  | 
82  | 0  |          mul32x32_64(state->h4, state->s3);  | 
83  | 0  |   t[3] = mul32x32_64(state->h0, state->r3) + mul32x32_64(state->h1, state->r2) +  | 
84  | 0  |          mul32x32_64(state->h2, state->r1) + mul32x32_64(state->h3, state->r0) +  | 
85  | 0  |          mul32x32_64(state->h4, state->s4);  | 
86  | 0  |   t[4] = mul32x32_64(state->h0, state->r4) + mul32x32_64(state->h1, state->r3) +  | 
87  | 0  |          mul32x32_64(state->h2, state->r2) + mul32x32_64(state->h3, state->r1) +  | 
88  | 0  |          mul32x32_64(state->h4, state->r0);  | 
89  |  | 
  | 
90  | 0  |   state->h0 = (uint32_t)t[0] & 0x3ffffff;  | 
91  | 0  |   c = (t[0] >> 26);  | 
92  | 0  |   t[1] += c;  | 
93  | 0  |   state->h1 = (uint32_t)t[1] & 0x3ffffff;  | 
94  | 0  |   b = (uint32_t)(t[1] >> 26);  | 
95  | 0  |   t[2] += b;  | 
96  | 0  |   state->h2 = (uint32_t)t[2] & 0x3ffffff;  | 
97  | 0  |   b = (uint32_t)(t[2] >> 26);  | 
98  | 0  |   t[3] += b;  | 
99  | 0  |   state->h3 = (uint32_t)t[3] & 0x3ffffff;  | 
100  | 0  |   b = (uint32_t)(t[3] >> 26);  | 
101  | 0  |   t[4] += b;  | 
102  | 0  |   state->h4 = (uint32_t)t[4] & 0x3ffffff;  | 
103  | 0  |   b = (uint32_t)(t[4] >> 26);  | 
104  | 0  |   state->h0 += b * 5;  | 
105  |  | 
  | 
106  | 0  |   if (len >= 16) { | 
107  | 0  |     goto poly1305_donna_16bytes;  | 
108  | 0  |   }  | 
109  |  |  | 
110  |  | // final bytes  | 
111  | 0  | poly1305_donna_atmost15bytes:  | 
112  | 0  |   if (!len) { | 
113  | 0  |     return;  | 
114  | 0  |   }  | 
115  |  |  | 
116  | 0  |   for (j = 0; j < len; j++) { | 
117  | 0  |     mp[j] = in[j];  | 
118  | 0  |   }  | 
119  | 0  |   mp[j++] = 1;  | 
120  | 0  |   for (; j < 16; j++) { | 
121  | 0  |     mp[j] = 0;  | 
122  | 0  |   }  | 
123  | 0  |   len = 0;  | 
124  |  | 
  | 
125  | 0  |   t0 = CRYPTO_load_u32_le(mp + 0);  | 
126  | 0  |   t1 = CRYPTO_load_u32_le(mp + 4);  | 
127  | 0  |   t2 = CRYPTO_load_u32_le(mp + 8);  | 
128  | 0  |   t3 = CRYPTO_load_u32_le(mp + 12);  | 
129  |  | 
  | 
130  | 0  |   state->h0 += t0 & 0x3ffffff;  | 
131  | 0  |   state->h1 += ((((uint64_t)t1 << 32) | t0) >> 26) & 0x3ffffff;  | 
132  | 0  |   state->h2 += ((((uint64_t)t2 << 32) | t1) >> 20) & 0x3ffffff;  | 
133  | 0  |   state->h3 += ((((uint64_t)t3 << 32) | t2) >> 14) & 0x3ffffff;  | 
134  | 0  |   state->h4 += (t3 >> 8);  | 
135  |  | 
  | 
136  | 0  |   goto poly1305_donna_mul;  | 
137  | 0  | }  | 
138  |  |  | 
139  | 0  | void CRYPTO_poly1305_init(struct poly1305_state_st *state, const uint8_t key[32]) { | 
140  | 0  |   debug_assert_nonsecret((uintptr_t)state % 64 == 0);  | 
141  |  | 
  | 
142  | 0  |   uint32_t t0, t1, t2, t3;  | 
143  |  | 
  | 
144  | 0  |   t0 = CRYPTO_load_u32_le(key + 0);  | 
145  | 0  |   t1 = CRYPTO_load_u32_le(key + 4);  | 
146  | 0  |   t2 = CRYPTO_load_u32_le(key + 8);  | 
147  | 0  |   t3 = CRYPTO_load_u32_le(key + 12);  | 
148  |  |  | 
149  |  |   // precompute multipliers  | 
150  | 0  |   state->r0 = t0 & 0x3ffffff;  | 
151  | 0  |   t0 >>= 26;  | 
152  | 0  |   t0 |= t1 << 6;  | 
153  | 0  |   state->r1 = t0 & 0x3ffff03;  | 
154  | 0  |   t1 >>= 20;  | 
155  | 0  |   t1 |= t2 << 12;  | 
156  | 0  |   state->r2 = t1 & 0x3ffc0ff;  | 
157  | 0  |   t2 >>= 14;  | 
158  | 0  |   t2 |= t3 << 18;  | 
159  | 0  |   state->r3 = t2 & 0x3f03fff;  | 
160  | 0  |   t3 >>= 8;  | 
161  | 0  |   state->r4 = t3 & 0x00fffff;  | 
162  |  | 
  | 
163  | 0  |   state->s1 = state->r1 * 5;  | 
164  | 0  |   state->s2 = state->r2 * 5;  | 
165  | 0  |   state->s3 = state->r3 * 5;  | 
166  | 0  |   state->s4 = state->r4 * 5;  | 
167  |  |  | 
168  |  |   // init state  | 
169  | 0  |   state->h0 = 0;  | 
170  | 0  |   state->h1 = 0;  | 
171  | 0  |   state->h2 = 0;  | 
172  | 0  |   state->h3 = 0;  | 
173  | 0  |   state->h4 = 0;  | 
174  |  | 
  | 
175  | 0  |   OPENSSL_memcpy(state->key, key + 16, sizeof(state->key));  | 
176  | 0  | }  | 
177  |  |  | 
178  |  | void CRYPTO_poly1305_update(struct poly1305_state_st *state, const uint8_t *in,  | 
179  | 0  |                             size_t in_len) { | 
180  |  |   // Work around a C language bug. See https://crbug.com/1019588.  | 
181  | 0  |   if (in_len == 0) { | 
182  | 0  |     return;  | 
183  | 0  |   }  | 
184  |  |  | 
185  | 0  |   poly1305_update(state, in, in_len);  | 
186  | 0  | }  | 
187  |  |  | 
188  | 0  | void CRYPTO_poly1305_finish(struct poly1305_state_st *state, uint8_t mac[16]) { | 
189  | 0  |   uint32_t g0, g1, g2, g3, g4;  | 
190  | 0  |   uint32_t b, nb;  | 
191  |  | 
  | 
192  | 0  |   b = state->h0 >> 26;  | 
193  | 0  |   state->h0 = state->h0 & 0x3ffffff;  | 
194  | 0  |   state->h1 += b;  | 
195  | 0  |   b = state->h1 >> 26;  | 
196  | 0  |   state->h1 = state->h1 & 0x3ffffff;  | 
197  | 0  |   state->h2 += b;  | 
198  | 0  |   b = state->h2 >> 26;  | 
199  | 0  |   state->h2 = state->h2 & 0x3ffffff;  | 
200  | 0  |   state->h3 += b;  | 
201  | 0  |   b = state->h3 >> 26;  | 
202  | 0  |   state->h3 = state->h3 & 0x3ffffff;  | 
203  | 0  |   state->h4 += b;  | 
204  | 0  |   b = state->h4 >> 26;  | 
205  | 0  |   state->h4 = state->h4 & 0x3ffffff;  | 
206  | 0  |   state->h0 += b * 5;  | 
207  |  | 
  | 
208  | 0  |   g0 = state->h0 + 5;  | 
209  | 0  |   b = g0 >> 26;  | 
210  | 0  |   g0 &= 0x3ffffff;  | 
211  | 0  |   g1 = state->h1 + b;  | 
212  | 0  |   b = g1 >> 26;  | 
213  | 0  |   g1 &= 0x3ffffff;  | 
214  | 0  |   g2 = state->h2 + b;  | 
215  | 0  |   b = g2 >> 26;  | 
216  | 0  |   g2 &= 0x3ffffff;  | 
217  | 0  |   g3 = state->h3 + b;  | 
218  | 0  |   b = g3 >> 26;  | 
219  | 0  |   g3 &= 0x3ffffff;  | 
220  | 0  |   g4 = state->h4 + b - (1 << 26);  | 
221  |  | 
  | 
222  | 0  |   b = (g4 >> 31) - 1;  | 
223  | 0  |   nb = ~b;  | 
224  | 0  |   state->h0 = (state->h0 & nb) | (g0 & b);  | 
225  | 0  |   state->h1 = (state->h1 & nb) | (g1 & b);  | 
226  | 0  |   state->h2 = (state->h2 & nb) | (g2 & b);  | 
227  | 0  |   state->h3 = (state->h3 & nb) | (g3 & b);  | 
228  | 0  |   state->h4 = (state->h4 & nb) | (g4 & b);  | 
229  |  | 
  | 
230  | 0  |   uint64_t f0 = ((state->h0) | (state->h1 << 26)) +  | 
231  | 0  |                 (uint64_t)CRYPTO_load_u32_le(&state->key[0]);  | 
232  | 0  |   uint64_t f1 = ((state->h1 >> 6) | (state->h2 << 20)) +  | 
233  | 0  |                 (uint64_t)CRYPTO_load_u32_le(&state->key[4]);  | 
234  | 0  |   uint64_t f2 = ((state->h2 >> 12) | (state->h3 << 14)) +  | 
235  | 0  |                 (uint64_t)CRYPTO_load_u32_le(&state->key[8]);  | 
236  | 0  |   uint64_t f3 = ((state->h3 >> 18) | (state->h4 << 8)) +  | 
237  | 0  |                 (uint64_t)CRYPTO_load_u32_le(&state->key[12]);  | 
238  |  | 
  | 
239  | 0  |   CRYPTO_store_u32_le(&mac[0], (uint32_t)f0);  | 
240  | 0  |   f1 += (f0 >> 32);  | 
241  | 0  |   CRYPTO_store_u32_le(&mac[4], (uint32_t)f1);  | 
242  | 0  |   f2 += (f1 >> 32);  | 
243  | 0  |   CRYPTO_store_u32_le(&mac[8], (uint32_t)f2);  | 
244  | 0  |   f3 += (f2 >> 32);  | 
245  | 0  |   CRYPTO_store_u32_le(&mac[12], (uint32_t)f3);  | 
246  | 0  | }  |