aboutsummaryrefslogblamecommitdiffstats
path: root/src/libkeccak/state.h
blob: 4c2c1d81507fe84546650ad98d2befa8ecf01456 (plain) (tree)
1
2
3
4
5
6
7
8
9
10


                                              
                                                                     
   
                                                                       



                                                                              
                                                                  




                                                                           
                                                                        










                            
                   



   
                                                              
   
                                                                        



                              
                             
     
                

     


























                    
               











                                               













                                                           















                                                                                                         

                                                    
                                                
   

                                                             

                  
                                        



   



                                                                         
             









                                                                    
                                                           



                                                        















                                                                              
                                                                      






                                                                   








                                                                        




                                                                          

                                                  
   
                                                                          



                                                                                
                                                                 






















                                                                                         

                                                                     
 
               

                                             
      
                                 
                                  
               
                           
      
















                                                                                                  

                                               
   
                                                                          
















                                                                                                       
                                                                                 

                                                                            
                                                                                































                                                                                                       
                                                                 


                                                                 
      
 
/**
 * libkeccak – Keccak-family hashing library
 * 
 * Copyright © 2014, 2015  Mattias Andrée (maandree@member.fsf.org)
 * 
 * This library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this library.  If not, see <http://www.gnu.org/licenses/>.
 */
#ifndef LIBKECCAK_STATE_H
#define LIBKECCAK_STATE_H  1


#include "spec.h"

#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>



/**
 * Datastructure that describes the state of a hashing process
 * 
 * The `char`-size of the output hashsum is calculated by `(.n + 7) / 8`
 */
typedef struct libkeccak_state
{
  /**
   * The lanes (state/sponge)
   */
  int64_t S[25];
  
  /**
   * The bitrate
   */
  long r;
  
  /**
   * The capacity
   */
  long c;
  
  /**
   * The output size
   */
  long n;
  
  /**
   * The state size
   */
  long b;
  
  /**
   * The word size
   */
  long w;
  
  /**
   * The word mask
   */
  int64_t wmod;
  
  /**
   * ℓ, the binary logarithm of the word size
   */
  long l;
  
  /**
   * 12 + 2ℓ, the number of rounds
   */
  long nr;
  
  /**
   * Pointer for `M`
   */
  size_t mptr;
  
  /**
   * Size of `M`
   */
  size_t mlen;
  
  /**
   * Left over water to fill the sponge with at next update
   */
  char* M;
  
} libkeccak_state_t;



/**
 * Initialise a state according to hashing specifications
 * 
 * @param   state  The state that should be initialised
 * @param   spec   The specifications for the state
 * @return         Zero on success, -1 on error
 */
__attribute__((leaf, nonnull))
int libkeccak_state_initialise(libkeccak_state_t* restrict state, const libkeccak_spec_t* restrict spec);


/**
 * Reset a state according to hashing specifications
 * 
 * @param  state  The state that should be reset
 */
static inline __attribute__((nonnull, nothrow, unused))
void libkeccak_state_reset(libkeccak_state_t* restrict state)
{
  state->mptr = 0;
  memset(state->S, 0, sizeof(state->S));
}


/**
 * Release resources allocation for a state without wiping sensitive data
 * 
 * @param  state  The state that should be destroyed
 */
static inline
void libkeccak_state_fast_destroy(libkeccak_state_t* restrict state)
{
  if (state == NULL)
    return;
  free(state->M);
  state->M = NULL;
}


/**
 * Wipe data in the state's message wihout freeing any data
 * 
 * @param  state  The state that should be wipe
 */
__attribute__((leaf, nonnull, nothrow, optimize("-O0")))
void libkeccak_state_wipe_message(volatile libkeccak_state_t* restrict state);

/**
 * Wipe data in the state's sponge wihout freeing any data
 * 
 * @param  state  The state that should be wipe
 */
__attribute__((leaf, nonnull, nothrow, optimize("-O0")))
void libkeccak_state_wipe_sponge(volatile libkeccak_state_t* restrict state);

/**
 * Wipe sensitive data wihout freeing any data
 * 
 * @param  state  The state that should be wipe
 */
__attribute__((nonnull, nothrow, optimize("-O0")))
void libkeccak_state_wipe(volatile libkeccak_state_t* restrict state);


/**
 * Release resources allocation for a state and wipe sensitive data
 * 
 * @param  state  The state that should be destroyed
 */
static inline __attribute__((unused, optimize("-O0")))
void libkeccak_state_destroy(volatile libkeccak_state_t* restrict state)
{
  if (state == NULL)
    return;
  libkeccak_state_wipe(state);
  free(state->M);
  state->M = NULL;
}


/**
 * Wrapper for `libkeccak_state_initialise` that also allocates the states
 * 
 * @param   spec  The specifications for the state
 * @return        The state, `NULL` on error
 */
static inline __attribute__((nonnull, unused, warn_unused_result, malloc))
libkeccak_state_t* libkeccak_state_create(const libkeccak_spec_t* restrict spec)
{
  libkeccak_state_t* restrict state = malloc(sizeof(libkeccak_state_t));
  int saved_errno;
  if ((state == NULL) || libkeccak_state_initialise(state, spec))
    return saved_errno = errno, free(state), errno = saved_errno, NULL;
  return state;
}


/**
 * Wrapper for `libkeccak_state_fast_destroy` that also frees the allocation of the state
 * 
 * @param  state  The state that should be freed
 */
static inline __attribute__((unused))
void libkeccak_state_fast_free(libkeccak_state_t* restrict state)
{
  libkeccak_state_fast_destroy(state);
  free(state);
}


/**
 * Wrapper for `libkeccak_state_destroy` that also frees the allocation of the state
 * 
 * @param  state  The state that should be freed
 */
static inline __attribute__((unused, optimize("-O0")))
void libkeccak_state_free(volatile libkeccak_state_t* restrict state)
{
#ifdef __GNUC__
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wcast-qual"
#endif
  libkeccak_state_destroy(state);
  free((libkeccak_state_t*)state);
#ifdef __GNUC__
# pragma GCC diagnostic pop
#endif
}


/**
 * Make a copy of a state
 * 
 * @param   dest  The slot for the duplicate, must not be initialised (memory leak otherwise)
 * @param   src   The state to duplicate
 * @return        Zero on success, -1 on error
 */
__attribute__((leaf, nonnull))
int libkeccak_state_copy(libkeccak_state_t* restrict dest, const libkeccak_state_t* restrict src);


/**
 * A wrapper for `libkeccak_state_copy` that also allocates the duplicate
 * 
 * @param   src  The state to duplicate
 * @return       The duplicate, `NULL` on error
 */
static inline __attribute__((nonnull, unused, warn_unused_result, malloc))
libkeccak_state_t* libkeccak_state_duplicate(const libkeccak_state_t* restrict src)
{
  libkeccak_state_t* restrict dest = malloc(sizeof(libkeccak_state_t));
  int saved_errno;
  if ((dest == NULL) || libkeccak_state_copy(dest, src))
    return saved_errno = errno, libkeccak_state_free(dest), errno = saved_errno, NULL;
  return dest;
}


/**
 * Calculates the allocation size required for the second argument
 * of `libkeccak_state_marshal` (`char* restrict data)`)
 * 
 * @param   state  The state as it will be marshalled by a subsequent call to `libkeccak_state_marshal`
 * @return         The allocation size needed for the buffer to which the state will be marshalled
 */
static inline __attribute__((nonnull, nothrow, unused, warn_unused_result, pure))
size_t libkeccak_state_marshal_size(const libkeccak_state_t* restrict state)
{
  return sizeof(libkeccak_state_t) - sizeof(char*) + state->mptr * sizeof(char);
}


/**
 * Marshal a `libkeccak_state_t` into a buffer
 * 
 * @param   state  The state to marshal
 * @param   data   The output buffer
 * @return         The number of bytes stored to `data`
 */
__attribute__((leaf, nonnull, nothrow))
size_t libkeccak_state_marshal(const libkeccak_state_t* restrict state, char* restrict data);


/**
 * Unmarshal a `libkeccak_state_t` from a buffer
 * 
 * @param   state  The slot for the unmarshalled state, must not be initialised (memory leak otherwise)
 * @param   data   The input buffer
 * @return         The number of bytes read from `data`, 0 on error
 */
__attribute__((leaf, nonnull))
size_t libkeccak_state_unmarshal(libkeccak_state_t* restrict state, const char* restrict data);


/**
 * Gets the number of bytes the `libkeccak_state_t` stored
 * at the beginning of `data` occupies
 * 
 * @param   data  The data buffer
 * @return        The byte size of the stored state
 */
__attribute__((leaf, nonnull, nothrow, warn_unused_result, pure))
size_t libkeccak_state_unmarshal_skip(const char* restrict data);


#endif