Skip to content

Commit

Permalink
poly1305: Replace dispatch! macro with manual dispatching.
Browse files Browse the repository at this point in the history
This will allow the NEON and fallback implementations to evolve
separately.

```
diff src/aead/poly1305/ffi_arm_neon.rs \
     src/aead/poly1305/ffi_fallback.rs
```
  • Loading branch information
briansmith committed Jan 22, 2025
1 parent a1c4623 commit 77f5acb
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 59 deletions.
88 changes: 29 additions & 59 deletions src/aead/poly1305.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// Copyright 2015-2016 Brian Smith.
// Portions Copyright (c) 2014, 2015, Google Inc.
// Copyright 2015-2025 Brian Smith.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
Expand All @@ -16,7 +15,12 @@
// TODO: enforce maximum input length.

use super::{Tag, TAG_LEN};
use crate::{c, cpu};
use crate::cpu;
#[cfg(all(target_arch = "arm", target_endian = "little"))]
use crate::cpu::GetFeature as _;

mod ffi_arm_neon;
mod ffi_fallback;

/// A Poly1305 key.
pub(super) struct Key {
Expand All @@ -33,12 +37,6 @@ impl Key {
}
}

pub struct Context {
state: poly1305_state,
#[allow(dead_code)]
cpu_features: cpu::Features,
}

// Keep in sync with `poly1305_state` in ring-core/poly1305.h.
//
// The C code, in particular the way the `poly1305_aligned_state` functions
Expand All @@ -47,66 +45,38 @@ pub struct Context {
struct poly1305_state([u8; OPAQUE_LEN]);
const OPAQUE_LEN: usize = 512;

// Abstracts the dispatching logic that chooses the NEON implementation if and
// only if it would work.
macro_rules! dispatch {
( $features:expr =>
( $f:ident | $neon_f:ident )
( $( $p:ident : $t:ty ),+ )
( $( $a:expr ),+ ) ) => {
match () {
// BoringSSL uses `!defined(OPENSSL_APPLE)`.
#[cfg(all(all(target_arch = "arm", target_endian = "little"), any(target_os = "android", target_os = "linux")))]
() if cpu::arm::NEON.available($features) => {
prefixed_extern! {
fn $neon_f( $( $p : $t ),+ );
}
unsafe { $neon_f( $( $a ),+ ) }
}
() => {
prefixed_extern! {
fn $f( $( $p : $t ),+ );
}
unsafe { $f( $( $a ),+ ) }
}
}
}
pub(super) enum Context {
#[cfg(all(target_arch = "arm", target_endian = "little"))]
ArmNeon(ffi_arm_neon::State),
Fallback(ffi_fallback::State),
}

impl Context {
#[inline]
pub(super) fn from_key(Key { key_and_nonce }: Key, cpu_features: cpu::Features) -> Self {
let mut ctx = Self {
state: poly1305_state([0u8; OPAQUE_LEN]),
cpu_features,
};

dispatch!(
cpu_features =>
(CRYPTO_poly1305_init | CRYPTO_poly1305_init_neon)
(statep: &mut poly1305_state, key: &[u8; KEY_LEN])
(&mut ctx.state, &key_and_nonce));

ctx
pub(super) fn from_key(key: Key, cpu: cpu::Features) -> Self {
#[cfg(all(target_arch = "arm", target_endian = "little"))]
if let Some(cpu) = cpu.get_feature() {
return ffi_arm_neon::State::new_context(key, cpu);
}
let _: cpu::Features = cpu;
ffi_fallback::State::new_context(key)
}

#[inline(always)]
pub fn update(&mut self, input: &[u8]) {
dispatch!(
self.cpu_features =>
(CRYPTO_poly1305_update | CRYPTO_poly1305_update_neon)
(statep: &mut poly1305_state, input: *const u8, in_len: c::size_t)
(&mut self.state, input.as_ptr(), input.len()));
match self {
#[cfg(all(target_arch = "arm", target_endian = "little"))]
Self::ArmNeon(state) => state.update(input),
Self::Fallback(state) => state.update(input),
}
}

pub(super) fn finish(mut self) -> Tag {
let mut tag = Tag([0u8; TAG_LEN]);
dispatch!(
self.cpu_features =>
(CRYPTO_poly1305_finish | CRYPTO_poly1305_finish_neon)
(statep: &mut poly1305_state, mac: &mut [u8; TAG_LEN])
(&mut self.state, &mut tag.0));
tag
pub(super) fn finish(self) -> Tag {
match self {
#[cfg(all(target_arch = "arm", target_endian = "little"))]
Self::ArmNeon(state) => state.finish(),
Self::Fallback(state) => state.finish(),
}
}
}

Expand Down
63 changes: 63 additions & 0 deletions src/aead/poly1305/ffi_arm_neon.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright 2015-2025 Brian Smith.
// Portions Copyright (c) 2014, 2015, Google Inc.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

#![cfg(all(target_arch = "arm", target_endian = "little"))]

use super::{poly1305_state, Key, Tag, KEY_LEN, OPAQUE_LEN, TAG_LEN};
use crate::{c, cpu::arm::Neon};
use core::num::NonZeroUsize;

// XXX/TODO(MSRV): change to `pub(super)`.
pub(in super::super) struct State {
state: poly1305_state,
neon: Neon,
}

impl State {
pub(super) fn new_context(Key { key_and_nonce }: Key, neon: Neon) -> super::Context {
prefixed_extern! {
fn CRYPTO_poly1305_init_neon(state: &mut poly1305_state, key: &[u8; KEY_LEN]);
}
let mut r = Self {
state: poly1305_state([0u8; OPAQUE_LEN]),
neon,
};
unsafe { CRYPTO_poly1305_init_neon(&mut r.state, &key_and_nonce) }
super::Context::ArmNeon(r)
}

pub(super) fn update(&mut self, input: &[u8]) {
prefixed_extern! {
fn CRYPTO_poly1305_update_neon(
state: &mut poly1305_state,
input: *const u8,
in_len: c::NonZero_size_t);
}
if let Some(len) = NonZeroUsize::new(input.len()) {
let _: Neon = self.neon;
let input = input.as_ptr();
unsafe { CRYPTO_poly1305_update_neon(&mut self.state, input, len) }
}
}

pub(super) fn finish(mut self) -> Tag {
prefixed_extern! {
fn CRYPTO_poly1305_finish_neon(statep: &mut poly1305_state, mac: &mut [u8; TAG_LEN]);
}
let mut tag = Tag([0u8; TAG_LEN]);
unsafe { CRYPTO_poly1305_finish_neon(&mut self.state, &mut tag.0) }
tag
}
}
58 changes: 58 additions & 0 deletions src/aead/poly1305/ffi_fallback.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright 2015-2025 Brian Smith.
// Portions Copyright (c) 2014, 2015, Google Inc.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

use super::{poly1305_state, Key, Tag, KEY_LEN, OPAQUE_LEN, TAG_LEN};
use crate::c;
use core::num::NonZeroUsize;

// XXX/TODO(MSRV): change to `pub(super)`.
pub(in super::super) struct State {
state: poly1305_state,
}

impl State {
pub(super) fn new_context(Key { key_and_nonce }: Key) -> super::Context {
prefixed_extern! {
fn CRYPTO_poly1305_init(state: &mut poly1305_state, key: &[u8; KEY_LEN]);
}
let mut r = Self {
state: poly1305_state([0u8; OPAQUE_LEN]),
};
unsafe { CRYPTO_poly1305_init(&mut r.state, &key_and_nonce) }
super::Context::Fallback(r)
}

pub(super) fn update(&mut self, input: &[u8]) {
prefixed_extern! {
fn CRYPTO_poly1305_update(
state: &mut poly1305_state,
input: *const u8,
in_len: c::NonZero_size_t);
}
if let Some(len) = NonZeroUsize::new(input.len()) {
let input = input.as_ptr();
unsafe { CRYPTO_poly1305_update(&mut self.state, input, len) }
}
}

pub(super) fn finish(mut self) -> Tag {
prefixed_extern! {
fn CRYPTO_poly1305_finish(statep: &mut poly1305_state, mac: &mut [u8; TAG_LEN]);
}
let mut tag = Tag([0u8; TAG_LEN]);
unsafe { CRYPTO_poly1305_finish(&mut self.state, &mut tag.0) }
tag
}
}

0 comments on commit 77f5acb

Please sign in to comment.