1 | // Copyright 2015-2025 Brian Smith. |
2 | // Portions Copyright (c) 2014, 2015, Google Inc. |
3 | // |
4 | // Permission to use, copy, modify, and/or distribute this software for any |
5 | // purpose with or without fee is hereby granted, provided that the above |
6 | // copyright notice and this permission notice appear in all copies. |
7 | // |
8 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES |
9 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
10 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY |
11 | // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
12 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
13 | // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
14 | // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | |
16 | use super::{Key, Tag, KEY_LEN, TAG_LEN}; |
17 | use crate::c; |
18 | use core::num::NonZeroUsize; |
19 | |
20 | // XXX/TODO(MSRV): change to `pub(super)`. |
21 | pub(in super::super) struct State { |
22 | state: poly1305_state_st, |
23 | } |
24 | |
25 | // Keep in sync with `poly1305_state_st` in poly1305.c |
26 | #[repr (C, align(64))] |
27 | struct poly1305_state_st { |
28 | r0: u32, |
29 | r1: u32, |
30 | r2: u32, |
31 | r3: u32, |
32 | r4: u32, |
33 | s1: u32, |
34 | s2: u32, |
35 | s3: u32, |
36 | s4: u32, |
37 | h0: u32, |
38 | h1: u32, |
39 | h2: u32, |
40 | h3: u32, |
41 | h4: u32, |
42 | key: [u8; 16], |
43 | } |
44 | |
45 | impl State { |
46 | pub(super) fn new_context(Key { key_and_nonce }: Key) -> super::Context { |
47 | prefixed_extern! { |
48 | fn CRYPTO_poly1305_init(state: &mut poly1305_state_st, key: &[u8; KEY_LEN]); |
49 | } |
50 | let mut r = Self { |
51 | state: poly1305_state_st { |
52 | r0: 0, |
53 | r1: 0, |
54 | r2: 0, |
55 | r3: 0, |
56 | r4: 0, |
57 | s1: 0, |
58 | s2: 0, |
59 | s3: 0, |
60 | s4: 0, |
61 | h0: 0, |
62 | h1: 0, |
63 | h2: 0, |
64 | h3: 0, |
65 | h4: 0, |
66 | key: [0u8; 16], |
67 | }, |
68 | }; |
69 | unsafe { CRYPTO_poly1305_init(&mut r.state, &key_and_nonce) } |
70 | super::Context::Fallback(r) |
71 | } |
72 | |
73 | // `input.len % BLOCK_LEN == 0` must be true for every call except the |
74 | // final one. |
75 | pub(super) fn update_internal(&mut self, input: &[u8]) { |
76 | prefixed_extern! { |
77 | fn CRYPTO_poly1305_update( |
78 | state: &mut poly1305_state_st, |
79 | input: *const u8, |
80 | in_len: c::NonZero_size_t); |
81 | } |
82 | if let Some(len) = NonZeroUsize::new(input.len()) { |
83 | let input = input.as_ptr(); |
84 | unsafe { CRYPTO_poly1305_update(&mut self.state, input, len) } |
85 | } |
86 | } |
87 | |
88 | pub(super) fn finish(mut self) -> Tag { |
89 | prefixed_extern! { |
90 | fn CRYPTO_poly1305_finish(statep: &mut poly1305_state_st, mac: &mut [u8; TAG_LEN]); |
91 | } |
92 | let mut tag = Tag([0u8; TAG_LEN]); |
93 | unsafe { CRYPTO_poly1305_finish(&mut self.state, &mut tag.0) } |
94 | tag |
95 | } |
96 | } |
97 | |