/**
 * (C) 2007-18 - ntop.org and contributors
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not see see <http://www.gnu.org/licenses/>
 *
 */

/** Key files
 *
 *  Edge implements a very simple interface for getting instructions about
 *  rolling keys. 
 *
 *  Key definitions are written as individual files in <transform>/<sa>.key. The
 *  format of each key is a single line of hex nibbles as follows:
 *
 *  0102030405060708090a0b0c0d0e0f
 *
 *  Any external key exchange mechanism can receive the key data write it into
 *  the keyfiles.
 *
 *  To control which keys are active at what times the key control file is
 *  used. This is a single file which is periodically reread. It contains key
 *  definitions in chronological order with one line per key definition as
 *  follows:
 *
 *  <valid_from> <valid_until> <transform> <opaque>
 *
 *  edge reads the key control file periodically to get updates in policy. edge
 *  holds a number of keys in memory. Data can be decoded if it was encoded by
 *  any of the keys still in memory. By having at least 2 keys in memory it
 *  allows for clock skew and transmission delay when encoder and decoder roll
 *  keys at slightly different times. The amount of overlap in the valid time
 *  ranges provides the tolerance to timing skews in the system.
 *
 *  The keys have the same level of secrecy as any other user file. Existing
 *  UNIX permission systems can be used to provide access controls.
 *
 */

/** How Edge Uses The Key Schedule
 *
 *  Edge provides state space for a number of transform algorithms. Each
 *  transform uses its state space to store the SA information for its keys as
 *  found in the key file. When a packet is received the transform ID is in
 *  plain text. The packets is then sent to that transform for decoding. Each
 *  transform can store its SA numbers differently (or not at all). The
 *  transform code then finds the SA number, then finds the cipher (with key) in
 *  the state space and uses this to decode the packet.
 *
 *  To support this, as edge reads each key line, it passes it to the
 *  appropriate transform to parse the line and store the SA information in its
 *  state space.
 *
 *  When encoding a packet, edge has several transforms and potentially valid
 *  SAs to choose from. To keep track of which one to use for encoding edge does
 *  its own book-keeping as each key line is passed to the transform code: it
 *  stores a lookup of valid_from -> transform. When encoding a packet it then
 *  just calls the transform with the best valid_from in the table. The
 *  transform's own state space has all the SAs for its keys and the best of
 *  those is chosen.
 */

#if !defined( N2N_KEYFILE_H_ )
#define N2N_KEYFILE_H_


#include "n2n_wire.h"
#include <time.h>

#define N2N_MAX_KEYSIZE         256             /* bytes */
#define N2N_MAX_NUM_CIPHERSPECS 8
#define N2N_KEYPATH_SIZE        256
#define N2N_KEYFILE_LINESIZE    256

/** This structure stores an encryption cipher spec. */
struct n2n_cipherspec
{
    n2n_transform_t     t;                      /* N2N_TRANSFORM_ID_xxx for this spec. */
    time_t              valid_from;             /* Start using the key at this time. */
    time_t              valid_until;            /* Key is valid if time < valid_until. */
    uint16_t            opaque_size;            /* Size in bytes of key. */
    uint8_t             opaque[N2N_MAX_KEYSIZE];/* Key matter. */
};

typedef struct n2n_cipherspec n2n_cipherspec_t;


static const char * const DELIMITERS=" \t\n\r";


/** @return number of cipherspec items filled. */
int     n2n_read_keyfile( n2n_cipherspec_t * specs,     /* fill out this array of cipherspecs */
                          size_t numspecs,              /* number of slots in the array. */
                          const char * ctrlfile_path ); /* path to control file */

int     validCipherSpec( const n2n_cipherspec_t * k,
                         time_t now );

ssize_t  n2n_parse_hex( uint8_t * keyBuf, 
                        size_t keyMax, 
                        const char * textKey,
                        size_t textLen );

/*----------------------------------------------------------------------------*/

#endif /* #if !defined( N2N_KEYFILE_H_ ) */
