| 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 | |