// Copyright 2024 The BoringSSL Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Generates a hash function from init/update/final-style FFI functions. Rust
// doesn't accept function pointers as a generic arguments so this is the only
// mechanism to avoid duplicating the code.
//
// The name is prefixed with "unsafe_" because it contains unsafe blocks.
//
// Safety: see the "Safety" sections within about the requirements for the
// functions named in the macro parameters.
macro_rules! unsafe_iuf_algo {
    ($name:ident, $output_len:expr, $block_len:expr, $evp_md:ident, $one_shot:ident, $init:ident, $update:ident, $final_func:ident) => {
        impl Algorithm for $name {
            const OUTPUT_LEN: usize = $output_len as usize;
            const BLOCK_LEN: usize = $block_len as usize;

            fn get_md(_: sealed::SealedType) -> &'static MdRef {
                // Safety:
                // - this always returns a valid pointer to an EVP_MD.
                unsafe { MdRef::from_ptr(bssl_sys::$evp_md() as *mut _) }
            }

            fn hash_to_vec(input: &[u8]) -> Vec<u8> {
                Self::hash(input).as_slice().to_vec()
            }

            /// Create a new context for incremental hashing.
            fn new() -> Self {
                $name::new()
            }

            /// Hash the contents of `input`.
            fn update(&mut self, input: &[u8]) {
                self.update(input);
            }

            /// Finish the hashing and return the digest.
            fn digest_to_vec(self) -> alloc::vec::Vec<u8> {
                self.digest().to_vec()
            }
        }

        impl $name {
            /// Digest `input` in a single operation.
            pub fn hash(input: &[u8]) -> [u8; $output_len] {
                // Safety: it is assumed that `$one_shot` indeed writes
                // `$output_len` bytes.
                unsafe {
                    crate::with_output_array(|out, _| {
                        bssl_sys::$one_shot(input.as_ffi_ptr(), input.len(), out);
                    })
                }
            }

            /// Create a new context for incremental hashing.
            pub fn new() -> Self {
                unsafe {
                    Self {
                        ctx: crate::initialized_struct(|ctx| {
                            // Safety: type checking will ensure that `ctx` is the
                            // correct type for `$init` to write into.
                            bssl_sys::$init(ctx);
                        }),
                    }
                }
            }

            /// Hash the contents of `input`.
            pub fn update(&mut self, input: &[u8]) {
                // Safety: arguments point to a valid buffer.
                unsafe {
                    bssl_sys::$update(&mut self.ctx, input.as_ffi_void_ptr(), input.len());
                }
            }

            /// Finish the hashing and return the digest.
            pub fn digest(mut self) -> [u8; $output_len] {
                // Safety: it is assumed that `$final_func` indeed writes
                // `$output_len` bytes.
                unsafe {
                    crate::with_output_array(|out, _| {
                        bssl_sys::$final_func(out, &mut self.ctx);
                    })
                }
            }
        }

        impl From<$name> for [u8; $output_len] {
            fn from(ctx: $name) -> [u8; $output_len] {
                ctx.digest()
            }
        }

        impl From<$name> for alloc::vec::Vec<u8> {
            fn from(ctx: $name) -> alloc::vec::Vec<u8> {
                ctx.digest_to_vec()
            }
        }

        #[cfg(feature = "std")]
        impl std::io::Write for $name {
            fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
                self.update(buf);
                Ok(buf.len())
            }

            fn flush(&mut self) -> std::io::Result<()> {
                Ok(())
            }
        }
    };
}

macro_rules! aead_algo {
    ($name:ident, $evp_md:ident, $key_len:expr, $nonce_len:expr, $tag_len:expr) => {
        impl $name {
            /// Create a new AEAD context for the given key.
            pub fn new(key: &[u8; $key_len]) -> Self {
                // Safety: $evp_md is assumed to return a valid `EVP_MD`.
                unsafe { $name(EvpAead::new(key, { bssl_sys::$evp_md() })) }
            }
        }

        impl Aead for $name {
            type Tag = [u8; $tag_len];
            type Nonce = [u8; $nonce_len];

            fn seal(&self, nonce: &Self::Nonce, plaintext: &[u8], ad: &[u8]) -> Vec<u8> {
                self.0.seal(nonce, plaintext, ad)
            }

            fn seal_in_place(
                &self,
                nonce: &Self::Nonce,
                plaintext: &mut [u8],
                ad: &[u8],
            ) -> Self::Tag {
                self.0.seal_in_place(nonce, plaintext, ad)
            }

            fn open(&self, nonce: &Self::Nonce, ciphertext: &[u8], ad: &[u8]) -> Option<Vec<u8>> {
                self.0.open(nonce, ciphertext, ad)
            }

            fn open_in_place(
                &self,
                nonce: &Self::Nonce,
                ciphertext: &mut [u8],
                tag: &Self::Tag,
                ad: &[u8],
            ) -> Result<(), InvalidCiphertext> {
                self.0.open_in_place(nonce, ciphertext, tag, ad)
            }
        }
    };
}
