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




                                                               
                                                                       



                                                                              
                                                                  




                                                                           
                                                                        




                           


                   
   














                                       

























                                                           
                                                             



                                                            





                                                  





                                                             
 


                                              





















                                   






                                                            
                                               














                                                                 
                                               

















                                                                                





                                                                                      
                                                                                 
                                                               
 
                                                                 




                                                                             

                                                                        







                                                                                   



           
      
 
/**
 * libkeccak – Keccak-family hashing library
 * 
 * Copyright © 2014  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_SPEC_H
#define LIBKECCAK_SPEC_H  1


#include <limits.h>


/**
 * Message suffix for SHA3 hashing
 */
#define LIBKECCAK_SHA3_SUFFIX  "01"

/**
 * Message suffix for RawSHAKE hashing
 */
#define LIBKECCAK_RAWSHAKE_SUFFIX  "11"

/**
 * Message suffix for SHAKE hashing
 */
#define LIBKECCAK_SHAKE_SUFFIX  "1111"


/**
 * Invalid `libkeccak_spec_t.bitrate`: non-positive
 */
#define LIBKECCAK_SPEC_ERROR_BITRATE_NONPOSITIVE  1

/**
 * Invalid `libkeccak_spec_t.bitrate`: not a multiple of 8
 */
#define LIBKECCAK_SPEC_ERROR_BITRATE_MOD_8  2

/**
 * Invalid `libkeccak_spec_t.capacity`: non-positive
 */
#define LIBKECCAK_SPEC_ERROR_CAPACITY_NONPOSITIVE  3

/**
 * Invalid `libkeccak_spec_t.capacity`: not a multiple of 8
 */
#define LIBKECCAK_SPEC_ERROR_CAPACITY_MOD_8  4

/**
 * Invalid `libkeccak_spec_t.output`: non-positive
 */
#define LIBKECCAK_SPEC_ERROR_OUTPUT_NONPOSITIVE  5

/**
 * Invalid `libkeccak_spec_t` values: `.bitrate + `.capacity`
 * is greater 1600 which is the largest supported state size
 */
#define LIBKECCAK_SPEC_ERROR_STATE_TOO_LARGE  6

/**
 * Invalid `libkeccak_spec_t` values:
 * `.bitrate + `.capacity` is not a multiple of 25
 */
#define LIBKECCAK_SPEC_ERROR_STATE_MOD_25  7

/**
 * Invalid `libkeccak_spec_t` values: `.bitrate + `.capacity`
 * is a not a 2-potent multiple of 25
 */
#define LIBKECCAK_SPEC_ERROR_WORD_NON_2_POTENT  8



/**
 * Datastructure that describes the parameters
 * that should be used when hashing
 */
typedef struct libkeccak_spec
{
  /**
   * The bitrate
   */
  long bitrate;
  
  /**
   * The capacity
   */
  long capacity;
  
  /**
   * The output size
   */
  long output;
  
} libkeccak_spec_t;



/**
 * Fill in a `libkeccak_spec_t` for a SHA3-x hashing
 * 
 * @param  spec  The specifications datastructure to fill in
 * @param  x     The value of x in `SHA3-x`, the output size
 */
static inline __attribute__((nonnull, nothrow))
void libkeccak_spec_sha3(libkeccak_spec_t* restrict spec, long x)
{
  spec->bitrate = 1600 - 2 * x;
  spec->capacity = 2 * x;
  spec->output = x;
}


/**
 * Fill in a `libkeccak_spec_t` for a RawSHAKEx hashing
 * 
 * @param  spec  The specifications datastructure to fill in
 * @param  x     The value of x in `RawSHAKEx`, half the capacity
 * @param  d     The output size
 */
static inline __attribute__((nonnull, nothrow))
void libkeccak_spec_rawshake(libkeccak_spec_t* restrict spec, long x, long d)
{
  spec->bitrate = 1600 - 2 * x;
  spec->capacity = 2 * x;
  spec->output = d;
}


/**
 * Fill in a `libkeccak_spec_t` for a SHAKEx hashing
 * 
 * @param  spec:libkeccak_spec_t*  The specifications datastructure to fill in
 * @param  x:long                  The value of x in `SHAKEx`, half the capacity
 * @param  d:long                  The output size
 */
#define libkeccak_spec_shake  libkeccak_spec_rawshake


/**
 * Check for errors in a `libkeccak_spec_t`
 * 
 * @param   spec  The specifications datastructure to check
 * @return        Zero if error free, a `LIBKECCAK_SPEC_ERROR_*` if an error was found
 */
static inline __attribute__((nonnull, nothrow, unused, warn_unused_result, pure))
int libkeccak_spec_check(const libkeccak_spec_t* restrict spec)
{
  long state_size = spec->capacity + spec->bitrate, n_state_size;
  if (spec->bitrate <= 0)   return LIBKECCAK_SPEC_ERROR_BITRATE_NONPOSITIVE;
  if (spec->bitrate % 8)    return LIBKECCAK_SPEC_ERROR_BITRATE_MOD_8;
  if (spec->capacity <= 0)  return LIBKECCAK_SPEC_ERROR_CAPACITY_NONPOSITIVE;
  if (spec->capacity % 8)   return LIBKECCAK_SPEC_ERROR_CAPACITY_MOD_8;
  if (spec->output <= 0)    return LIBKECCAK_SPEC_ERROR_OUTPUT_NONPOSITIVE;
  if (state_size > 1600)    return LIBKECCAK_SPEC_ERROR_STATE_TOO_LARGE;
  if (state_size % 25)      return LIBKECCAK_SPEC_ERROR_STATE_MOD_25;
  state_size /= 25;
  
  /* This is a portable implementation of `(x & -x) != x` which assumes
   * two's complement, which of course is always satisfied by GCC, but anyway... */
  n_state_size = ((~state_size) ^ (LONG_MIN & ~LONG_MAX)) + 1;
  if ((state_size & n_state_size) != state_size)
    return LIBKECCAK_SPEC_ERROR_WORD_NON_2_POTENT;
  
  return 0;
}


#endif