Commit 5ecb20e1 by Arne Deprez Committed by Sebastian Renner

forkae

parent a34b1718
/*
* Copyright (C) 2020 Southern Storm Software, Pty Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "aead-common.h"
int aead_check_tag
(unsigned char *plaintext, unsigned long long plaintext_len,
const unsigned char *tag1, const unsigned char *tag2,
unsigned size)
{
/* Set "accum" to -1 if the tags match, or 0 if they don't match */
int accum = 0;
while (size > 0) {
accum |= (*tag1++ ^ *tag2++);
--size;
}
accum = (accum - 1) >> 8;
/* Destroy the plaintext if the tag match failed */
while (plaintext_len > 0) {
*plaintext++ &= accum;
--plaintext_len;
}
/* If "accum" is 0, return -1, otherwise return 0 */
return ~accum;
}
int aead_check_tag_precheck
(unsigned char *plaintext, unsigned long long plaintext_len,
const unsigned char *tag1, const unsigned char *tag2,
unsigned size, int precheck)
{
/* Set "accum" to -1 if the tags match, or 0 if they don't match */
int accum = 0;
while (size > 0) {
accum |= (*tag1++ ^ *tag2++);
--size;
}
accum = ((accum - 1) >> 8) & precheck;
/* Destroy the plaintext if the tag match failed */
while (plaintext_len > 0) {
*plaintext++ &= accum;
--plaintext_len;
}
/* If "accum" is 0, return -1, otherwise return 0 */
return ~accum;
}
/*
* Copyright (C) 2020 Southern Storm Software, Pty Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef LWCRYPTO_AEAD_COMMON_H
#define LWCRYPTO_AEAD_COMMON_H
#include <stddef.h>
/**
* \file aead-common.h
* \brief Definitions that are common across AEAD schemes.
*
* AEAD stands for "Authenticated Encryption with Associated Data".
* It is a standard API pattern for securely encrypting and
* authenticating packets of data.
*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Encrypts and authenticates a packet with an AEAD scheme.
*
* \param c Buffer to receive the output.
* \param clen On exit, set to the length of the output which includes
* the ciphertext and the authentication tag.
* \param m Buffer that contains the plaintext message to encrypt.
* \param mlen Length of the plaintext message in bytes.
* \param ad Buffer that contains associated data to authenticate
* along with the packet but which does not need to be encrypted.
* \param adlen Length of the associated data in bytes.
* \param nsec Secret nonce - normally not used by AEAD schemes.
* \param npub Points to the public nonce for the packet.
* \param k Points to the key to use to encrypt the packet.
*
* \return 0 on success, or a negative value if there was an error in
* the parameters.
*/
typedef int (*aead_cipher_encrypt_t)
(unsigned char *c, unsigned long long *clen,
const unsigned char *m, unsigned long long mlen,
const unsigned char *ad, unsigned long long adlen,
const unsigned char *nsec,
const unsigned char *npub,
const unsigned char *k);
/**
* \brief Decrypts and authenticates a packet with an AEAD scheme.
*
* \param m Buffer to receive the plaintext message on output.
* \param mlen Receives the length of the plaintext message on output.
* \param nsec Secret nonce - normally not used by AEAD schemes.
* \param c Buffer that contains the ciphertext and authentication
* tag to decrypt.
* \param clen Length of the input data in bytes, which includes the
* ciphertext and the authentication tag.
* \param ad Buffer that contains associated data to authenticate
* along with the packet but which does not need to be encrypted.
* \param adlen Length of the associated data in bytes.
* \param npub Points to the public nonce for the packet.
* \param k Points to the key to use to decrypt the packet.
*
* \return 0 on success, -1 if the authentication tag was incorrect,
* or some other negative number if there was an error in the parameters.
*/
typedef int (*aead_cipher_decrypt_t)
(unsigned char *m, unsigned long long *mlen,
unsigned char *nsec,
const unsigned char *c, unsigned long long clen,
const unsigned char *ad, unsigned long long adlen,
const unsigned char *npub,
const unsigned char *k);
/**
* \brief Hashes a block of input data.
*
* \param out Buffer to receive the hash output.
* \param in Points to the input data to be hashed.
* \param inlen Length of the input data in bytes.
*
* \return Returns zero on success or -1 if there was an error in the
* parameters.
*/
typedef int (*aead_hash_t)
(unsigned char *out, const unsigned char *in, unsigned long long inlen);
/**
* \brief Initializes the state for a hashing operation.
*
* \param state Hash state to be initialized.
*/
typedef void (*aead_hash_init_t)(void *state);
/**
* \brief Updates a hash state with more input data.
*
* \param state Hash state to be updated.
* \param in Points to the input data to be incorporated into the state.
* \param inlen Length of the input data to be incorporated into the state.
*/
typedef void (*aead_hash_update_t)
(void *state, const unsigned char *in, unsigned long long inlen);
/**
* \brief Returns the final hash value from a hashing operation.
*
* \param Hash state to be finalized.
* \param out Points to the output buffer to receive the hash value.
*/
typedef void (*aead_hash_finalize_t)(void *state, unsigned char *out);
/**
* \brief Aborbs more input data into an XOF state.
*
* \param state XOF state to be updated.
* \param in Points to the input data to be absorbed into the state.
* \param inlen Length of the input data to be absorbed into the state.
*
* \sa ascon_xof_init(), ascon_xof_squeeze()
*/
typedef void (*aead_xof_absorb_t)
(void *state, const unsigned char *in, unsigned long long inlen);
/**
* \brief Squeezes output data from an XOF state.
*
* \param state XOF state to squeeze the output data from.
* \param out Points to the output buffer to receive the squeezed data.
* \param outlen Number of bytes of data to squeeze out of the state.
*/
typedef void (*aead_xof_squeeze_t)
(void *state, unsigned char *out, unsigned long long outlen);
/**
* \brief No special AEAD features.
*/
#define AEAD_FLAG_NONE 0x0000
/**
* \brief The natural byte order of the AEAD cipher is little-endian.
*
* If this flag is not present, then the natural byte order of the
* AEAD cipher should be assumed to be big-endian.
*
* The natural byte order may be useful when formatting packet sequence
* numbers as nonces. The application needs to know whether the sequence
* number should be packed into the leading or trailing bytes of the nonce.
*/
#define AEAD_FLAG_LITTLE_ENDIAN 0x0001
/**
* \brief Meta-information about an AEAD cipher.
*/
typedef struct
{
const char *name; /**< Name of the cipher */
unsigned key_len; /**< Length of the key in bytes */
unsigned nonce_len; /**< Length of the nonce in bytes */
unsigned tag_len; /**< Length of the tag in bytes */
unsigned flags; /**< Flags for extra features */
aead_cipher_encrypt_t encrypt; /**< AEAD encryption function */
aead_cipher_decrypt_t decrypt; /**< AEAD decryption function */
} aead_cipher_t;
/**
* \brief Meta-information about a hash algorithm that is related to an AEAD.
*
* Regular hash algorithms should provide the "hash", "init", "update",
* and "finalize" functions. Extensible Output Functions (XOF's) should
* proivde the "hash", "init", "absorb", and "squeeze" functions.
*/
typedef struct
{
const char *name; /**< Name of the hash algorithm */
size_t state_size; /**< Size of the incremental state structure */
unsigned hash_len; /**< Length of the hash in bytes */
unsigned flags; /**< Flags for extra features */
aead_hash_t hash; /**< All in one hashing function */
aead_hash_init_t init; /**< Incremental hash/XOF init function */
aead_hash_update_t update; /**< Incremental hash update function */
aead_hash_finalize_t finalize; /**< Incremental hash finalize function */
aead_xof_absorb_t absorb; /**< Incremental XOF absorb function */
aead_xof_squeeze_t squeeze; /**< Incremental XOF squeeze function */
} aead_hash_algorithm_t;
/**
* \brief Check an authentication tag in constant time.
*
* \param plaintext Points to the plaintext data.
* \param plaintext_len Length of the plaintext in bytes.
* \param tag1 First tag to compare.
* \param tag2 Second tag to compare.
* \param tag_len Length of the tags in bytes.
*
* \return Returns -1 if the tag check failed or 0 if the check succeeded.
*
* If the tag check fails, then the \a plaintext will also be zeroed to
* prevent it from being used accidentally by the application when the
* ciphertext was invalid.
*/
int aead_check_tag
(unsigned char *plaintext, unsigned long long plaintext_len,
const unsigned char *tag1, const unsigned char *tag2,
unsigned tag_len);
/**
* \brief Check an authentication tag in constant time with a previous check.
*
* \param plaintext Points to the plaintext data.
* \param plaintext_len Length of the plaintext in bytes.
* \param tag1 First tag to compare.
* \param tag2 Second tag to compare.
* \param tag_len Length of the tags in bytes.
* \param precheck Set to -1 if previous check succeeded or 0 if it failed.
*
* \return Returns -1 if the tag check failed or 0 if the check succeeded.
*
* If the tag check fails, then the \a plaintext will also be zeroed to
* prevent it from being used accidentally by the application when the
* ciphertext was invalid.
*
* This version can be used to incorporate other information about the
* correctness of the plaintext into the final result.
*/
int aead_check_tag_precheck
(unsigned char *plaintext, unsigned long long plaintext_len,
const unsigned char *tag1, const unsigned char *tag2,
unsigned tag_len, int precheck);
#ifdef __cplusplus
}
#endif
#endif
#define CRYPTO_KEYBYTES 16
#define CRYPTO_NSECBYTES 0
#define CRYPTO_NPUBBYTES 6
#define CRYPTO_ABYTES 16
#define CRYPTO_NOOVERLAP 1
#include "forkae.h"
int crypto_aead_encrypt
(unsigned char *c, unsigned long long *clen,
const unsigned char *m, unsigned long long mlen,
const unsigned char *ad, unsigned long long adlen,
const unsigned char *nsec,
const unsigned char *npub,
const unsigned char *k)
{
return forkae_paef_128_192_aead_encrypt
(c, clen, m, mlen, a, adlen, nsec, npub, k);
}
int crypto_aead_decrypt
(unsigned char *m, unsigned long long *mlen,
unsigned char *nsec,
const unsigned char *c, unsigned long long clen,
const unsigned char *ad, unsigned long long adlen,
const unsigned char *npub,
const unsigned char *k)
{
return forkae_paef_128_192_aead_decrypt
(m, mlen, nsec, c, clen, ad, adlen, npub, k);
}
/*
* Copyright (C) 2020 Southern Storm Software, Pty Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "forkae.h"
#include "internal-forkskinny.h"
#include "internal-util.h"
#include <string.h>
aead_cipher_t const forkae_paef_64_192_cipher = {
"PAEF-ForkSkinny-64-192",
FORKAE_PAEF_64_192_KEY_SIZE,
FORKAE_PAEF_64_192_NONCE_SIZE,
FORKAE_PAEF_64_192_TAG_SIZE,
AEAD_FLAG_NONE,
forkae_paef_64_192_aead_encrypt,
forkae_paef_64_192_aead_decrypt
};
aead_cipher_t const forkae_paef_128_192_cipher = {
"PAEF-ForkSkinny-128-192",
FORKAE_PAEF_128_192_KEY_SIZE,
FORKAE_PAEF_128_192_NONCE_SIZE,
FORKAE_PAEF_128_192_TAG_SIZE,
AEAD_FLAG_NONE,
forkae_paef_128_192_aead_encrypt,
forkae_paef_128_192_aead_decrypt
};
aead_cipher_t const forkae_paef_128_256_cipher = {
"PAEF-ForkSkinny-128-256",
FORKAE_PAEF_128_256_KEY_SIZE,
FORKAE_PAEF_128_256_NONCE_SIZE,
FORKAE_PAEF_128_256_TAG_SIZE,
AEAD_FLAG_NONE,
forkae_paef_128_256_aead_encrypt,
forkae_paef_128_256_aead_decrypt
};
aead_cipher_t const forkae_paef_128_288_cipher = {
"PAEF-ForkSkinny-128-288",
FORKAE_PAEF_128_288_KEY_SIZE,
FORKAE_PAEF_128_288_NONCE_SIZE,
FORKAE_PAEF_128_288_TAG_SIZE,
AEAD_FLAG_NONE,
forkae_paef_128_288_aead_encrypt,
forkae_paef_128_288_aead_decrypt
};
aead_cipher_t const forkae_saef_128_192_cipher = {
"SAEF-ForkSkinny-128-192",
FORKAE_SAEF_128_192_KEY_SIZE,
FORKAE_SAEF_128_192_NONCE_SIZE,
FORKAE_SAEF_128_192_TAG_SIZE,
AEAD_FLAG_NONE,
forkae_saef_128_192_aead_encrypt,
forkae_saef_128_192_aead_decrypt
};
aead_cipher_t const forkae_saef_128_256_cipher = {
"SAEF-ForkSkinny-128-256",
FORKAE_SAEF_128_256_KEY_SIZE,
FORKAE_SAEF_128_256_NONCE_SIZE,
FORKAE_SAEF_128_256_TAG_SIZE,
AEAD_FLAG_NONE,
forkae_saef_128_256_aead_encrypt,
forkae_saef_128_256_aead_decrypt
};
/* PAEF-ForkSkinny-64-192 */
#define FORKAE_ALG_NAME forkae_paef_64_192
#define FORKAE_BLOCK_SIZE 8
#define FORKAE_NONCE_SIZE FORKAE_PAEF_64_192_NONCE_SIZE
#define FORKAE_COUNTER_SIZE 2
#define FORKAE_TWEAKEY_SIZE 24
#define FORKAE_BLOCK_FUNC forkskinny_64_192
#include "internal-forkae-paef.h"
/* PAEF-ForkSkinny-128-192 */
#define FORKAE_ALG_NAME forkae_paef_128_192
#define FORKAE_BLOCK_SIZE 16
#define FORKAE_NONCE_SIZE FORKAE_PAEF_128_192_NONCE_SIZE
#define FORKAE_COUNTER_SIZE 2
#define FORKAE_TWEAKEY_SIZE 32
#define FORKAE_BLOCK_FUNC forkskinny_128_256
#include "internal-forkae-paef.h"
/* PAEF-ForkSkinny-128-256 */
#define FORKAE_ALG_NAME forkae_paef_128_256
#define FORKAE_BLOCK_SIZE 16
#define FORKAE_NONCE_SIZE FORKAE_PAEF_128_256_NONCE_SIZE
#define FORKAE_COUNTER_SIZE 2
#define FORKAE_TWEAKEY_SIZE 32
#define FORKAE_BLOCK_FUNC forkskinny_128_256
#include "internal-forkae-paef.h"
/* PAEF-ForkSkinny-128-288 */
#define FORKAE_ALG_NAME forkae_paef_128_288
#define FORKAE_BLOCK_SIZE 16
#define FORKAE_NONCE_SIZE FORKAE_PAEF_128_288_NONCE_SIZE
#define FORKAE_COUNTER_SIZE 7
#define FORKAE_TWEAKEY_SIZE 48
#define FORKAE_BLOCK_FUNC forkskinny_128_384
#include "internal-forkae-paef.h"
/* SAEF-ForkSkinny-128-192 */
#define FORKAE_ALG_NAME forkae_saef_128_192
#define FORKAE_BLOCK_SIZE 16
#define FORKAE_NONCE_SIZE FORKAE_SAEF_128_192_NONCE_SIZE
#define FORKAE_TWEAKEY_SIZE 32
#define FORKAE_TWEAKEY_REDUCED_SIZE 24
#define FORKAE_BLOCK_FUNC forkskinny_128_256
#include "internal-forkae-saef.h"
/* SAEF-ForkSkinny-128-256 */
#define FORKAE_ALG_NAME forkae_saef_128_256
#define FORKAE_BLOCK_SIZE 16
#define FORKAE_NONCE_SIZE FORKAE_SAEF_128_256_NONCE_SIZE
#define FORKAE_TWEAKEY_SIZE 32
#define FORKAE_TWEAKEY_REDUCED_SIZE 32
#define FORKAE_BLOCK_FUNC forkskinny_128_256
#include "internal-forkae-saef.h"
/*
* Copyright (C) 2020 Southern Storm Software, Pty Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef LW_INTERNAL_FORKSKINNY_H
#define LW_INTERNAL_FORKSKINNY_H
/**
* \file internal-forkskinny.h
* \brief ForkSkinny block cipher family.
*
* ForkSkinny is a modified version of the SKINNY block cipher that
* supports "forking": half-way through the rounds the cipher is
* forked in two different directions to produce two different outputs.
*
* References: https://www.esat.kuleuven.be/cosic/forkae/
*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Encrypts a block of plaintext with ForkSkinny-128-256.
*
* \param key 256-bit tweakey for ForkSkinny-128-256.
* \param output_left Left output block for the ciphertext, or NULL if
* the left output is not required.
* \param output_right Right output block for the authentication tag,
* or NULL if the right output is not required.
* \param input 128-bit input plaintext block.
*
* ForkSkinny-128-192 also uses this function with a padded tweakey.
*/
void forkskinny_128_256_encrypt
(const unsigned char key[32], unsigned char *output_left,
unsigned char *output_right, const unsigned char *input);
/**
* \brief Decrypts a block of ciphertext with ForkSkinny-128-256.
*
* \param key 256-bit tweakey for ForkSkinny-128-256.
* \param output_left Left output block, which is the plaintext.
* \param output_right Right output block for the authentication tag.
* \param input 128-bit input ciphertext block.
*
* Both output blocks will be populated; neither is optional.
*/
void forkskinny_128_256_decrypt
(const unsigned char key[32], unsigned char *output_left,
unsigned char *output_right, const unsigned char *input);
/**
* \brief Encrypts a block of plaintext with ForkSkinny-128-384.
*
* \param key 384-bit tweakey for ForkSkinny-128-384.
* \param output_left Left output block for the ciphertext, or NULL if
* the left output is not required.
* \param output_right Right output block for the authentication tag,
* or NULL if the right output is not required.
* \param input 128-bit input plaintext block.
*
* ForkSkinny-128-288 also uses this function with a padded tweakey.
*/
void forkskinny_128_384_encrypt
(const unsigned char key[48], unsigned char *output_left,
unsigned char *output_right, const unsigned char *input);
/**
* \brief Decrypts a block of ciphertext with ForkSkinny-128-384.
*
* \param key 384-bit tweakey for ForkSkinny-128-384.
* \param output_left Left output block, which is the plaintext.
* \param output_right Right output block for the authentication tag.
* \param input 128-bit input ciphertext block.
*
* Both output blocks will be populated; neither is optional.
*/
void forkskinny_128_384_decrypt
(const unsigned char key[48], unsigned char *output_left,
unsigned char *output_right, const unsigned char *input);
/**
* \brief Encrypts a block of input with ForkSkinny-64-192.
*
* \param key 192-bit tweakey for ForkSkinny-64-192.
* \param output_left First output block, or NULL if left is not required.
* \param output_right Second output block, or NULL if right is not required.
* \param input 64-bit input block.
*/
/**
* \brief Encrypts a block of plaintext with ForkSkinny-64-192.
*
* \param key 192-bit tweakey for ForkSkinny-64-192.
* \param output_left Left output block for the ciphertext, or NULL if
* the left output is not required.
* \param output_right Right output block for the authentication tag,
* or NULL if the right output is not required.
* \param input 64-bit input plaintext block.
*/
void forkskinny_64_192_encrypt
(const unsigned char key[24], unsigned char *output_left,
unsigned char *output_right, const unsigned char *input);
/**
* \brief Decrypts a block of ciphertext with ForkSkinny-64-192.
*
* \param key 192-bit tweakey for ForkSkinny-64-192.
* \param output_left Left output block, which is the plaintext.
* \param output_right Right output block for the authentication tag.
* \param input 64-bit input ciphertext block.
*
* Both output blocks will be populated; neither is optional.
*/
void forkskinny_64_192_decrypt
(const unsigned char key[24], unsigned char *output_left,
unsigned char *output_right, const unsigned char *input);
#ifdef __cplusplus
}
#endif
#endif
/*
* Copyright (C) 2020 Southern Storm Software, Pty Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.