Commit d560a00f by Rhys Weatherley Committed by Sebastian Renner

Updated implementations from Rhys

parent ba578844
/*
* Copyright (C) 2021 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_ASCON_AEAD_H
#define LWCRYPTO_ASCON_AEAD_H
#include <stddef.h>
/**
* \file ascon-aead.h
* \brief ASCON-128 encryption algorithm and related family members.
*
* The ASCON family consists of several related algorithms:
*
* \li ASCON-128 with a 128-bit key, a 128-bit nonce, a 128-bit authentication
* tag, and a block rate of 64 bits.
* \li ASCON-128a with a 128-bit key, a 128-bit nonce, a 128-bit authentication
* tag, and a block rate of 128 bits. This is faster than ASCON-128 but may
* not be as secure.
* \li ASCON-80pq with a 160-bit key, a 128-bit nonce, a 128-bit authentication
* tag, and a block rate of 64 bits. This is similar to ASCON-128 but has a
* 160-bit key instead which may be more resistant against quantum computers.
* \li ASCON-HASH and ASCON-HASHA with a 256-bit hash output.
* \li ASCON-XOF and ASCON-XOFA with extensible hash output (XOF mode).
*
* References: https://ascon.iaik.tugraz.at/
*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Size of the key for ASCON-128 and ASCON-128a.
*/
#define ASCON128_KEY_SIZE 16
/**
* \brief Size of the nonce for ASCON-128 and ASCON-128a.
*/
#define ASCON128_NONCE_SIZE 16
/**
* \brief Size of the authentication tag for ASCON-128 and ASCON-128a.
*/
#define ASCON128_TAG_SIZE 16
/**
* \brief Size of the key for ASCON-80pq.
*/
#define ASCON80PQ_KEY_SIZE 20
/**
* \brief Size of the nonce for ASCON-80pq.
*/
#define ASCON80PQ_NONCE_SIZE 16
/**
* \brief Size of the authentication tag for ASCON-80pq.
*/
#define ASCON80PQ_TAG_SIZE 16
/**
* \brief Encrypts and authenticates a packet with ASCON-128.
*
* \param c Buffer to receive the output.
* \param clen On exit, set to the length of the output which includes
* the ciphertext and the 16 byte 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 npub Points to the public nonce for the packet which must
* be 16 bytes in length.
* \param k Points to the 16 bytes of the key to use to encrypt the packet.
*
* \return 0 on success, or a negative value if there was an error in
* the parameters.
*
* \sa ascon128_aead_decrypt()
*/
int ascon128_aead_encrypt
(unsigned char *c, size_t *clen,
const unsigned char *m, size_t mlen,
const unsigned char *ad, size_t adlen,
const unsigned char *npub,
const unsigned char *k);
/**
* \brief Decrypts and authenticates a packet with ASCON-128.
*
* \param m Buffer to receive the plaintext message on output.
* \param mlen Receives the length of the plaintext message on output.
* \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 16 byte 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 which must
* be 16 bytes in length.
* \param k Points to the 16 bytes of 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.
*
* \sa ascon128_aead_encrypt()
*/
int ascon128_aead_decrypt
(unsigned char *m, size_t *mlen,
const unsigned char *c, size_t clen,
const unsigned char *ad, size_t adlen,
const unsigned char *npub,
const unsigned char *k);
/**
* \brief Encrypts and authenticates a packet with ASCON-128a.
*
* \param c Buffer to receive the output.
* \param clen On exit, set to the length of the output which includes
* the ciphertext and the 16 byte 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 npub Points to the public nonce for the packet which must
* be 16 bytes in length.
* \param k Points to the 16 bytes of the key to use to encrypt the packet.
*
* \return 0 on success, or a negative value if there was an error in
* the parameters.
*
* \sa ascon128a_aead_decrypt()
*/
int ascon128a_aead_encrypt
(unsigned char *c, size_t *clen,
const unsigned char *m, size_t mlen,
const unsigned char *ad, size_t adlen,
const unsigned char *npub,
const unsigned char *k);
/**
* \brief Decrypts and authenticates a packet with ASCON-128a.
*
* \param m Buffer to receive the plaintext message on output.
* \param mlen Receives the length of the plaintext message on output.
* \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 16 byte 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 which must
* be 16 bytes in length.
* \param k Points to the 16 bytes of 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.
*
* \sa ascon128a_aead_encrypt()
*/
int ascon128a_aead_decrypt
(unsigned char *m, size_t *mlen,
const unsigned char *c, size_t clen,
const unsigned char *ad, size_t adlen,
const unsigned char *npub,
const unsigned char *k);
/**
* \brief Encrypts and authenticates a packet with ASCON-80pq.
*
* \param c Buffer to receive the output.
* \param clen On exit, set to the length of the output which includes
* the ciphertext and the 16 byte 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 npub Points to the public nonce for the packet which must
* be 16 bytes in length.
* \param k Points to the 20 bytes of the key to use to encrypt the packet.
*
* \return 0 on success, or a negative value if there was an error in
* the parameters.
*
* \sa ascon80pq_aead_decrypt()
*/
int ascon80pq_aead_encrypt
(unsigned char *c, size_t *clen,
const unsigned char *m, size_t mlen,
const unsigned char *ad, size_t adlen,
const unsigned char *npub,
const unsigned char *k);
/**
* \brief Decrypts and authenticates a packet with ASCON-80pq.
*
* \param m Buffer to receive the plaintext message on output.
* \param mlen Receives the length of the plaintext message on output.
* \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 16 byte 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 which must
* be 16 bytes in length.
* \param k Points to the 20 bytes of 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.
*
* \sa ascon80pq_aead_encrypt()
*/
int ascon80pq_aead_decrypt
(unsigned char *m, size_t *mlen,
const unsigned char *c, size_t clen,
const unsigned char *ad, size_t adlen,
const unsigned char *npub,
const unsigned char *k);
#ifdef __cplusplus
}
#endif
#endif
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
);
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
);
#include "ascon128.h" #include "ascon-aead.h"
int crypto_aead_encrypt int crypto_aead_encrypt
(unsigned char *c, unsigned long long *clen, (unsigned char *c, unsigned long long *clen,
...@@ -9,8 +9,12 @@ int crypto_aead_encrypt ...@@ -9,8 +9,12 @@ int crypto_aead_encrypt
const unsigned char *npub, const unsigned char *npub,
const unsigned char *k) const unsigned char *k)
{ {
return ascon128a_aead_encrypt size_t len = 0;
(c, clen, m, mlen, ad, adlen, nsec, npub, k); int result = ascon128a_aead_encrypt
(c, &len, m, mlen, ad, adlen, npub, k);
(void)nsec;
*clen = len;
return result;
} }
int crypto_aead_decrypt int crypto_aead_decrypt
...@@ -21,6 +25,10 @@ int crypto_aead_decrypt ...@@ -21,6 +25,10 @@ int crypto_aead_decrypt
const unsigned char *npub, const unsigned char *npub,
const unsigned char *k) const unsigned char *k)
{ {
return ascon128a_aead_decrypt size_t len = 0;
(m, mlen, nsec, c, clen, ad, adlen, npub, k); int result = ascon128a_aead_decrypt
(m, &len, c, clen, ad, adlen, npub, k);
(void)nsec;
*mlen = len;
return result;
} }
#if defined(__AVR__) #if defined(__AVR__)
/*
* Copyright (C) 2021 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 <avr/io.h> #include <avr/io.h>
/* Automatically generated - do not edit */ /* Automatically generated - do not edit */
...@@ -49,287 +71,223 @@ ascon_permute: ...@@ -49,287 +71,223 @@ ascon_permute:
ldd r23,Z+7 ldd r23,Z+7
ldd r12,Z+15 ldd r12,Z+15
ldd r13,Z+31 ldd r13,Z+31
eor r23,r4 mov r14,r12
eor r4,r13 mov r15,r23
eor r18,r12 mov r24,r13
mov r14,r23 eor r14,r18
mov r15,r12 eor r15,r4
mov r24,r18 eor r24,r4
mov r25,r13 com r4
mov r16,r4 or r4,r13
com r14 eor r4,r14
eor r13,r12
or r13,r14
eor r13,r15
eor r18,r15
or r18,r12
eor r18,r24
com r15 com r15
com r24 and r12,r15
com r25
com r16
and r14,r12
and r15,r18
and r24,r13
and r25,r4
and r16,r23
eor r23,r15
eor r12,r24 eor r12,r24
eor r18,r25 or r23,r24
eor r13,r16 eor r23,r14
eor r4,r14 std Z+31,r23
eor r12,r23 std Z+39,r12
eor r23,r4 std Z+15,r13
eor r13,r18 std Z+23,r4
com r18
std Z+7,r23
std Z+15,r12
std Z+31,r13
std Z+39,r4
ldd r23,Z+6 ldd r23,Z+6
ldd r12,Z+14 ldd r12,Z+14
ldd r13,Z+30 ldd r13,Z+30
eor r23,r5 mov r14,r12
eor r5,r13 mov r15,r23
eor r19,r12 mov r24,r13
mov r14,r23 eor r14,r19
mov r15,r12 eor r15,r5
mov r24,r19 eor r24,r5
mov r25,r13 com r5
mov r16,r5 or r5,r13
com r14 eor r5,r14
eor r13,r12
or r13,r14
eor r13,r15
eor r19,r15
or r19,r12
eor r19,r24
com r15 com r15
com r24 and r12,r15
com r25
com r16
and r14,r12
and r15,r19
and r24,r13
and r25,r5
and r16,r23
eor r23,r15
eor r12,r24 eor r12,r24
eor r19,r25 or r23,r24
eor r13,r16 eor r23,r14
eor r5,r14 std Z+30,r23
eor r12,r23 std Z+38,r12
eor r23,r5 std Z+14,r13
eor r13,r19 std Z+22,r5
com r19
std Z+6,r23
std Z+14,r12
std Z+30,r13
std Z+38,r5
ldd r23,Z+5 ldd r23,Z+5
ldd r12,Z+13 ldd r12,Z+13
ldd r13,Z+29 ldd r13,Z+29
eor r23,r6 mov r14,r12
eor r6,r13 mov r15,r23
eor r20,r12 mov r24,r13
mov r14,r23 eor r14,r20
mov r15,r12 eor r15,r6
mov r24,r20 eor r24,r6
mov r25,r13 com r6
mov r16,r6 or r6,r13
com r14 eor r6,r14
eor r13,r12
or r13,r14
eor r13,r15
eor r20,r15
or r20,r12
eor r20,r24
com r15 com r15
com r24 and r12,r15
com r25
com r16
and r14,r12
and r15,r20
and r24,r13
and r25,r6
and r16,r23
eor r23,r15
eor r12,r24 eor r12,r24
eor r20,r25 or r23,r24
eor r13,r16 eor r23,r14
eor r6,r14 std Z+29,r23
eor r12,r23 std Z+37,r12
eor r23,r6 std Z+13,r13
eor r13,r20 std Z+21,r6
com r20
std Z+5,r23
std Z+13,r12
std Z+29,r13
std Z+37,r6
ldd r23,Z+4 ldd r23,Z+4
ldd r12,Z+12 ldd r12,Z+12
ldd r13,Z+28 ldd r13,Z+28
eor r23,r7 mov r14,r12
eor r7,r13 mov r15,r23
eor r21,r12 mov r24,r13
mov r14,r23 eor r14,r21
mov r15,r12 eor r15,r7
mov r24,r21 eor r24,r7
mov r25,r13 com r7
mov r16,r7 or r7,r13
com r14 eor r7,r14
eor r13,r12
or r13,r14
eor r13,r15
eor r21,r15
or r21,r12
eor r21,r24
com r15 com r15
com r24 and r12,r15
com r25
com r16
and r14,r12
and r15,r21
and r24,r13
and r25,r7
and r16,r23
eor r23,r15
eor r12,r24 eor r12,r24
eor r21,r25 or r23,r24
eor r13,r16 eor r23,r14
eor r7,r14 std Z+28,r23
eor r12,r23 std Z+36,r12
eor r23,r7 std Z+12,r13
eor r13,r21 std Z+20,r7
com r21
std Z+4,r23
std Z+12,r12
std Z+28,r13
std Z+36,r7
ldd r23,Z+3 ldd r23,Z+3
ldd r12,Z+11 ldd r12,Z+11
ldd r13,Z+27 ldd r13,Z+27
eor r23,r8 mov r14,r12
eor r8,r13 mov r15,r23
eor r26,r12 mov r24,r13
mov r14,r23 eor r14,r26
mov r15,r12 eor r15,r8
mov r24,r26 eor r24,r8
mov r25,r13 com r8
mov r16,r8 or r8,r13
com r14 eor r8,r14
eor r13,r12
or r13,r14
eor r13,r15
eor r26,r15
or r26,r12
eor r26,r24
com r15 com r15
com r24 and r12,r15
com r25
com r16
and r14,r12
and r15,r26
and r24,r13
and r25,r8
and r16,r23
eor r23,r15
eor r12,r24 eor r12,r24
eor r26,r25 or r23,r24
eor r13,r16 eor r23,r14
eor r8,r14 std Z+27,r23
eor r12,r23 std Z+35,r12
eor r23,r8 std Z+11,r13
eor r13,r26 std Z+19,r8
com r26
std Z+3,r23
std Z+11,r12
std Z+27,r13
std Z+35,r8
ldd r23,Z+2 ldd r23,Z+2
ldd r12,Z+10 ldd r12,Z+10
ldd r13,Z+26 ldd r13,Z+26
eor r23,r9 mov r14,r12
eor r9,r13 mov r15,r23
eor r27,r12 mov r24,r13
mov r14,r23 eor r14,r27
mov r15,r12 eor r15,r9
mov r24,r27 eor r24,r9
mov r25,r13 com r9
mov r16,r9 or r9,r13
com r14 eor r9,r14
eor r13,r12
or r13,r14
eor r13,r15
eor r27,r15
or r27,r12
eor r27,r24
com r15 com r15
com r24 and r12,r15
com r25
com r16
and r14,r12
and r15,r27
and r24,r13
and r25,r9
and r16,r23
eor r23,r15
eor r12,r24 eor r12,r24
eor r27,r25 or r23,r24
eor r13,r16 eor r23,r14
eor r9,r14 std Z+26,r23
eor r12,r23 std Z+34,r12
eor r23,r9 std Z+10,r13
eor r13,r27 std Z+18,r9
com r27
std Z+2,r23
std Z+10,r12
std Z+26,r13
std Z+34,r9
ldd r23,Z+1 ldd r23,Z+1
ldd r12,Z+9 ldd r12,Z+9
ldd r13,Z+25 ldd r13,Z+25
eor r23,r10 mov r14,r12
eor r10,r13 mov r15,r23
eor r2,r12 mov r24,r13
mov r14,r23 eor r14,r2
mov r15,r12 eor r15,r10
mov r24,r2 eor r24,r10
mov r25,r13 com r10
mov r16,r10 or r10,r13
com r14 eor r10,r14
eor r13,r12
or r13,r14
eor r13,r15
eor r2,r15
or r2,r12
eor r2,r24
com r15 com r15
com r24 and r12,r15
com r25
com r16
and r14,r12
and r15,r2
and r24,r13
and r25,r10
and r16,r23
eor r23,r15
eor r12,r24 eor r12,r24
eor r2,r25 or r23,r24
eor r13,r16 eor r23,r14
eor r10,r14 std Z+25,r23
eor r12,r23 std Z+33,r12
eor r23,r10 std Z+9,r13
eor r13,r2 std Z+17,r10
com r2
std Z+1,r23
std Z+9,r12
std Z+25,r13
std Z+33,r10
ld r23,Z ld r23,Z
ldd r12,Z+8 ldd r12,Z+8
ldd r13,Z+24 ldd r13,Z+24
eor r23,r11 mov r14,r12
eor r11,r13 mov r15,r23
eor r3,r12 mov r24,r13
mov r14,r23 eor r14,r3
mov r15,r12 eor r15,r11
mov r24,r3 eor r24,r11
mov r25,r13 com r11
mov r16,r11 or r11,r13
com r14 eor r11,r14
eor r13,r12
or r13,r14
eor r13,r15
eor r3,r15
or r3,r12
eor r3,r24
com r15 com r15
com r24 and r12,r15
com r25
com r16
and r14,r12
and r15,r3
and r24,r13
and r25,r11
and r16,r23
eor r23,r15
eor r12,r24 eor r12,r24
eor r3,r25 or r23,r24
eor r13,r16 eor r23,r14
eor r11,r14 std Z+24,r23
eor r12,r23 std Z+32,r12
eor r23,r11 std Z+8,r13
eor r13,r3 std Z+16,r11
com r3 movw r12,r18
st Z,r23 movw r14,r20
std Z+8,r12 movw r24,r26
std Z+24,r13 movw r16,r2
std Z+32,r11
ld r11,Z
ldd r10,Z+1
ldd r9,Z+2
ldd r8,Z+3
ldd r7,Z+4
ldd r6,Z+5
ldd r5,Z+6
ldd r4,Z+7
movw r12,r4
movw r14,r6
movw r24,r8
movw r16,r10
mov r0,r12 mov r0,r12
mov r12,r14 mov r12,r14
mov r14,r24 mov r14,r24
...@@ -369,79 +327,79 @@ ascon_permute: ...@@ -369,79 +327,79 @@ ascon_permute:
ror r12 ror r12
ror r0 ror r0
or r17,r0 or r17,r0
eor r12,r4 eor r12,r18
eor r13,r5 eor r13,r19
eor r14,r6 eor r14,r20
eor r15,r7 eor r15,r21
eor r24,r8 eor r24,r26
eor r25,r9 eor r25,r27
eor r16,r10 eor r16,r2
eor r17,r11 eor r17,r3
mov r23,r4 mov r23,r18
mov r0,r5 mov r0,r19
push r6 push r20
mov r4,r7 mov r18,r21
mov r5,r8 mov r19,r26
mov r6,r9 mov r20,r27
mov r7,r10 mov r21,r2
mov r8,r11 mov r26,r3
pop r11 pop r3
mov r10,r0 mov r2,r0
mov r9,r23 mov r27,r23
mov r0,r1 mov r0,r1
lsr r11 lsr r3
ror r10 ror r2
ror r9 ror r27
ror r8 ror r26
ror r7 ror r21
ror r6 ror r20
ror r5 ror r19
ror r4 ror r18
ror r0 ror r0
lsr r11 lsr r3
ror r10 ror r2
ror r9 ror r27
ror r8 ror r26
ror r7 ror r21
ror r6 ror r20
ror r5 ror r19
ror r4 ror r18
ror r0 ror r0
lsr r11 lsr r3
ror r10 ror r2
ror r9 ror r27
ror r8 ror r26
ror r7 ror r21
ror r6 ror r20
ror r5 ror r19
ror r4 ror r18
ror r0 ror r0
lsr r11 lsr r3
ror r10 ror r2
ror r9 ror r27
ror r8 ror r26
ror r7 ror r21
ror r6 ror r20
ror r5 ror r19
ror r4 ror r18
ror r0 ror r0
or r11,r0 or r3,r0
eor r4,r12 eor r18,r12
eor r5,r13 eor r19,r13
eor r6,r14 eor r20,r14
eor r7,r15 eor r21,r15
eor r8,r24 eor r26,r24
eor r9,r25 eor r27,r25
eor r10,r16 eor r2,r16
eor r11,r17 eor r3,r17
st Z,r11 st Z,r3
std Z+1,r10 std Z+1,r2
std Z+2,r9 std Z+2,r27
std Z+3,r8 std Z+3,r26
std Z+4,r7 std Z+4,r21
std Z+5,r6 std Z+5,r20
std Z+6,r5 std Z+6,r19
std Z+7,r4 std Z+7,r18
ldd r11,Z+8 ldd r11,Z+8
ldd r10,Z+9 ldd r10,Z+9
ldd r9,Z+10 ldd r9,Z+10
...@@ -525,6 +483,14 @@ ascon_permute: ...@@ -525,6 +483,14 @@ ascon_permute:
std Z+13,r6 std Z+13,r6
std Z+14,r5 std Z+14,r5
std Z+15,r4 std Z+15,r4
ldd r3,Z+16
ldd r2,Z+17
ldd r27,Z+18
ldd r26,Z+19
ldd r21,Z+20
ldd r20,Z+21
ldd r19,Z+22
ldd r18,Z+23
movw r12,r18 movw r12,r18
movw r14,r20 movw r14,r20
movw r24,r26 movw r24,r26
......
/* /*
* Copyright (C) 2020 Southern Storm Software, Pty Ltd. * Copyright (C) 2021 Southern Storm Software, Pty Ltd.
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * copy of this software and associated documentation files (the "Software"),
...@@ -22,7 +22,19 @@ ...@@ -22,7 +22,19 @@
#include "internal-ascon.h" #include "internal-ascon.h"
#if !defined(__AVR__) /* Determine which versions should be accelerated with assembly code */
#if defined(__AVR__)
#define ASCON_ASM_REGULAR 1
#define ASCON_ASM_SLICED 0
#elif defined(__ARM_ARCH_ISA_THUMB) && __ARM_ARCH == 7
#define ASCON_ASM_REGULAR 1
#define ASCON_ASM_SLICED 1
#else
#define ASCON_ASM_REGULAR 0
#define ASCON_ASM_SLICED 0
#endif
#if !ASCON_ASM_REGULAR
void ascon_permute(ascon_state_t *state, uint8_t first_round) void ascon_permute(ascon_state_t *state, uint8_t first_round)
{ {
...@@ -77,4 +89,120 @@ void ascon_permute(ascon_state_t *state, uint8_t first_round) ...@@ -77,4 +89,120 @@ void ascon_permute(ascon_state_t *state, uint8_t first_round)
#endif #endif
} }
#endif /* !__AVR__ */ #endif /* !ASCON_ASM_REGULAR */
#if ASCON_SLICED && !ASCON_ASM_SLICED
void ascon_to_sliced(ascon_state_t *state)
{
int index;
uint32_t high, low;
for (index = 0; index < 10; index += 2) {
high = be_load_word32(state->B + index * 4);
low = be_load_word32(state->B + index * 4 + 4);
ascon_separate(high);
ascon_separate(low);
state->W[index] = (high << 16) | (low & 0x0000FFFFU);
state->W[index + 1] = (high & 0xFFFF0000U) | (low >> 16);
}
}
void ascon_from_sliced(ascon_state_t *state)
{
int index;
uint32_t high, low;
for (index = 0; index < 10; index += 2) {
high = (state->W[index] >> 16) | (state->W[index + 1] & 0xFFFF0000U);
low = (state->W[index] & 0x0000FFFFU) | (state->W[index + 1] << 16);
ascon_combine(high);
ascon_combine(low);
be_store_word32(state->B + index * 4, high);
be_store_word32(state->B + index * 4 + 4, low);
}
}
void ascon_permute_sliced(ascon_state_t *state, uint8_t first_round)
{
static const unsigned char RC[12 * 2] = {
12, 12, 9, 12, 12, 9, 9, 9, 6, 12, 3, 12,
6, 9, 3, 9, 12, 6, 9, 6, 12, 3, 9, 3
};
const unsigned char *rc = RC + first_round * 2;
uint32_t t0, t1, t2, t3, t4;
/* Load the state into local variables */
uint32_t x0_e = state->W[0];
uint32_t x0_o = state->W[1];
uint32_t x1_e = state->W[2];
uint32_t x1_o = state->W[3];
uint32_t x2_e = state->W[4];
uint32_t x2_o = state->W[5];
uint32_t x3_e = state->W[6];
uint32_t x3_o = state->W[7];
uint32_t x4_e = state->W[8];
uint32_t x4_o = state->W[9];
/* Perform all permutation rounds */
while (first_round < 12) {
/* Add the round constants for this round to the state */
x2_e ^= rc[0];
x2_o ^= rc[1];
rc += 2;
/* Substitution layer */
#define ascon_sbox(x0, x1, x2, x3, x4) \
do { \
x0 ^= x4; x4 ^= x3; x2 ^= x1; \
t0 = ~x0; t1 = ~x1; t2 = ~x2; t3 = ~x3; t4 = ~x4; \
t0 &= x1; t1 &= x2; t2 &= x3; t3 &= x4; t4 &= x0; \
x0 ^= t1; x1 ^= t2; x2 ^= t3; x3 ^= t4; x4 ^= t0; \
x1 ^= x0; x0 ^= x4; x3 ^= x2; x2 = ~x2; \
} while (0)
ascon_sbox(x0_e, x1_e, x2_e, x3_e, x4_e);
ascon_sbox(x0_o, x1_o, x2_o, x3_o, x4_o);
/* Linear diffusion layer */
/* x0 ^= rightRotate19_64(x0) ^ rightRotate28_64(x0); */
t0 = x0_e ^ rightRotate4(x0_o);
t1 = x0_o ^ rightRotate5(x0_e);
x0_e ^= rightRotate9(t1);
x0_o ^= rightRotate10(t0);
/* x1 ^= rightRotate61_64(x1) ^ rightRotate39_64(x1); */
t0 = x1_e ^ rightRotate11(x1_e);
t1 = x1_o ^ rightRotate11(x1_o);
x1_e ^= rightRotate19(t1);
x1_o ^= rightRotate20(t0);
/* x2 ^= rightRotate1_64(x2) ^ rightRotate6_64(x2); */
t0 = x2_e ^ rightRotate2(x2_o);
t1 = x2_o ^ rightRotate3(x2_e);
x2_e ^= t1;
x2_o ^= rightRotate1(t0);
/* x3 ^= rightRotate10_64(x3) ^ rightRotate17_64(x3); */
t0 = x3_e ^ rightRotate3(x3_o);
t1 = x3_o ^ rightRotate4(x3_e);
x3_e ^= rightRotate5(t0);
x3_o ^= rightRotate5(t1);
/* x4 ^= rightRotate7_64(x4) ^ rightRotate41_64(x4); */
t0 = x4_e ^ rightRotate17(x4_e);
t1 = x4_o ^ rightRotate17(x4_o);
x4_e ^= rightRotate3(t1);
x4_o ^= rightRotate4(t0);
/* Move onto the next round */
++first_round;
}
/* Write the local variables back to the state */
state->W[0] = x0_e;
state->W[1] = x0_o;
state->W[2] = x1_e;
state->W[3] = x1_o;
state->W[4] = x2_e;
state->W[5] = x2_o;
state->W[6] = x3_e;
state->W[7] = x3_o;
state->W[8] = x4_e;
state->W[9] = x4_o;
}
#endif /* ASCON_SLICED */
/* /*
* Copyright (C) 2020 Southern Storm Software, Pty Ltd. * Copyright (C) 2021 Southern Storm Software, Pty Ltd.
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * copy of this software and associated documentation files (the "Software"),
...@@ -38,11 +38,36 @@ extern "C" { ...@@ -38,11 +38,36 @@ extern "C" {
#endif #endif
/** /**
* \brief Defined to 1 if the 32-bit sliced version of ASCON is preferred.
*/
#if !defined(__AVR__) && !defined(LW_UTIL_CPU_IS_64BIT)
#define ASCON_SLICED 1
#else
#define ASCON_SLICED 0
#endif
/**
* \brief Initialization vector for ASCON-128.
*/
#define ASCON128_IV 0x80400c0600000000ULL
/**
* \brief Initialization vector for ASCON-128a.
*/
#define ASCON128a_IV 0x80800c0800000000ULL
/**
* \brief Initialization vector for ASCON-80pq.
*/
#define ASCON80PQ_IV 0xa0400c06U
/**
* \brief Structure of the internal state of the ASCON permutation. * \brief Structure of the internal state of the ASCON permutation.
*/ */
typedef union typedef union
{ {
uint64_t S[5]; /**< Words of the state */ uint64_t S[5]; /**< 64-bit words of the state */
uint32_t W[10]; /**< 32-bit words of the state */
uint8_t B[40]; /**< Bytes of the state */ uint8_t B[40]; /**< Bytes of the state */
} ascon_state_t; } ascon_state_t;
...@@ -57,6 +82,237 @@ typedef union ...@@ -57,6 +82,237 @@ typedef union
*/ */
void ascon_permute(ascon_state_t *state, uint8_t first_round); void ascon_permute(ascon_state_t *state, uint8_t first_round);
#if ASCON_SLICED
/**
* \brief Converts an ASCON state from byte form into sliced form.
*
* \param state The ASCON state to be converted, in big-endian byte order
* on entry and in host byte order on exit.
*/
void ascon_to_sliced(ascon_state_t *state);
/**
* \brief Converts an ASCON state from sliced form into byte form.
*
* \param state The ASCON state to be converted, in host byte order
* on entry and in big-endian byte order on exit.
*/
void ascon_from_sliced(ascon_state_t *state);
/**
* \brief Permutes the ASCON state in sliced form.
*
* \param state The ASCON state to be permuted.
* \param first_round The first round (of 12) to be performed; 0, 4, or 6.
*
* The input and output \a state will be in host byte order.
*/
void ascon_permute_sliced(ascon_state_t *state, uint8_t first_round);
/** @cond ascon_bit_separation */
/* http://programming.sirrida.de/perm_fn.html#bit_permute_step */
#define ascon_bit_permute_step(_y, mask, shift) \
do { \
uint32_t y = (_y); \
uint32_t t = ((y >> (shift)) ^ y) & (mask); \
(_y) = (y ^ t) ^ (t << (shift)); \
} while (0)
/* Separates a 32-bit word into two 16-bit halves with all the even
* bits in the bottom half and all the odd bits in the top half.
*
* Permutation generated with "http://programming.sirrida.de/calcperm.php"
*
* P = [0 16 1 17 2 18 3 19 4 20 5 21 6 22 7 23 8 24
* 9 25 10 26 11 27 12 28 13 29 14 30 15 31]
*/
#define ascon_separate(x) \
do { \
ascon_bit_permute_step((x), 0x22222222, 1); \
ascon_bit_permute_step((x), 0x0c0c0c0c, 2); \
ascon_bit_permute_step((x), 0x00f000f0, 4); \
ascon_bit_permute_step((x), 0x0000ff00, 8); \
} while (0)
#define ascon_combine(x) \
do { \
ascon_bit_permute_step((x), 0x0000aaaa, 15); \
ascon_bit_permute_step((x), 0x0000cccc, 14); \
ascon_bit_permute_step((x), 0x0000f0f0, 12); \
ascon_bit_permute_step((x), 0x0000ff00, 8); \
} while (0)
/** @endcond */
/**
* \brief Sets data into the ASCON state in sliced form.
*
* \param state The ASCON state for the data to be absorbed into.
* \param data Points to 8 bytes of data in big-endian byte order to set.
* \param offset Offset of the 64-bit word within the state to set at,
* between 0 and 4.
*/
#define ascon_set_sliced(state, data, offset) \
do { \
ascon_state_t *s = (state); \
uint32_t high = be_load_word32((data)); \
uint32_t low = be_load_word32((data) + 4); \
ascon_separate(high); \
ascon_separate(low); \
s->W[(offset) * 2] = (high << 16) | (low & 0x0000FFFFU); \
s->W[(offset) * 2 + 1] = (high & 0xFFFF0000U) | (low >> 16); \
} while (0)
/**
* \brief Absorbs data into the ASCON state in sliced form.
*
* \param state The ASCON state for the data to be absorbed into.
* \param data Points to 8 bytes of data in big-endian byte order to absorb.
* \param offset Offset of the 64-bit word within the state to absorb at,
* between 0 and 4.
*/
#define ascon_absorb_sliced(state, data, offset) \
do { \
ascon_state_t *s = (state); \
uint32_t high = be_load_word32((data)); \
uint32_t low = be_load_word32((data) + 4); \
ascon_separate(high); \
ascon_separate(low); \
s->W[(offset) * 2] ^= (high << 16) | (low & 0x0000FFFFU); \
s->W[(offset) * 2 + 1] ^= (high & 0xFFFF0000U) | (low >> 16); \
} while (0)
/**
* \brief Absorbs 32 bits of data into the ASCON state in sliced form.
*
* \param state The ASCON state for the data to be absorbed into.
* \param data Points to 4 bytes of data in big-endian byte order to absorb.
* \param offset Offset of the 64-bit word within the state to absorb at,
* between 0 and 4.
*
* The data is absorbed into the low bits of the 64-bit word at \a offset.
*/
#define ascon_absorb32_low_sliced(state, data, offset) \
do { \
ascon_state_t *s = (state); \
uint32_t low = be_load_word32((data)); \
ascon_separate(low); \
s->W[(offset) * 2] ^= (low & 0x0000FFFFU); \
s->W[(offset) * 2 + 1] ^= (low >> 16); \
} while (0)
/**
* \brief Absorbs 32 bits of data into the ASCON state in sliced form.
*
* \param state The ASCON state for the data to be absorbed into.
* \param data Points to 4 bytes of data in big-endian byte order to absorb.
* \param offset Offset of the 64-bit word within the state to absorb at,
* between 0 and 4.
*
* The data is absorbed into the high bits of the 64-bit word at \a offset.
*/
#define ascon_absorb32_high_sliced(state, data, offset) \
do { \
ascon_state_t *s = (state); \
uint32_t high = be_load_word32((data)); \
ascon_separate(high); \
s->W[(offset) * 2] ^= (high << 16); \
s->W[(offset) * 2 + 1] ^= (high & 0xFFFF0000U); \
} while (0)
/**
* \brief Squeezes data from the ASCON state in sliced form.
*
* \param state The ASCON state to extract the data from.
* \param data Points to the 8 bytes to be extracted from the state.
* \param offset Offset of the 64-bit word within the state to extract,
* between 0 and 4.
*/
#define ascon_squeeze_sliced(state, data, offset) \
do { \
ascon_state_t *s = (state); \
uint32_t high, low; \
high = (s->W[(offset) * 2] >> 16) | \
(s->W[(offset) * 2 + 1] & 0xFFFF0000U); \
low = (s->W[(offset) * 2] & 0x0000FFFFU) | \
(s->W[(offset) * 2 + 1] << 16); \
ascon_combine(high); \
ascon_combine(low); \
be_store_word32((data), high); \
be_store_word32((data) + 4, low); \
} while (0)
/**
* \brief Encrypts data using the ASCON state in sliced form.
*
* \param state The ASCON state.
* \param c Points to 8 bytes of output ciphertext in big-endian byte order.
* \param m Points to 8 bytes of input plaintext in big-endian byte order.
* \param offset Offset of the 64-bit word within the state to absorb
* and squeeze at, between 0 and 4.
*/
#define ascon_encrypt_sliced(state, c, m, offset) \
do { \
ascon_state_t *s = (state); \
uint32_t high = be_load_word32((m)); \
uint32_t low = be_load_word32((m) + 4); \
ascon_separate(high); \
ascon_separate(low); \
s->W[(offset) * 2] ^= (high << 16) | (low & 0x0000FFFFU); \
s->W[(offset) * 2 + 1] ^= (high & 0xFFFF0000U) | (low >> 16); \
high = (s->W[(offset) * 2] >> 16) | \
(s->W[(offset) * 2 + 1] & 0xFFFF0000U); \
low = (s->W[(offset) * 2] & 0x0000FFFFU) | \
(s->W[(offset) * 2 + 1] << 16); \
ascon_combine(high); \
ascon_combine(low); \
be_store_word32((c), high); \
be_store_word32((c) + 4, low); \
} while (0)
/**
* \brief Decrypts data using the ASCON state in sliced form.
*
* \param state The ASCON state.
* \param m Points to 8 bytes of output plaintext in big-endian byte order.
* \param c Points to 8 bytes of input ciphertext in big-endian byte order.
* \param offset Offset of the 64-bit word within the state to absorb
* and squeeze at, between 0 and 4.
*/
#define ascon_decrypt_sliced(state, m, c, offset) \
do { \
ascon_state_t *s = (state); \
uint32_t high, low, high2, low2; \
high = be_load_word32((c)); \
low = be_load_word32((c) + 4); \
ascon_separate(high); \
ascon_separate(low); \
high2 = high ^ ((s->W[(offset) * 2] >> 16) | \
(s->W[(offset) * 2 + 1] & 0xFFFF0000U)); \
low2 = low ^ ((s->W[(offset) * 2] & 0x0000FFFFU) | \
(s->W[(offset) * 2 + 1] << 16)); \
s->W[(offset) * 2] = (high << 16) | (low & 0x0000FFFFU); \
s->W[(offset) * 2 + 1] = (high & 0xFFFF0000U) | (low >> 16); \
ascon_combine(high2); \
ascon_combine(low2); \
be_store_word32((m), high2); \
be_store_word32((m) + 4, low2); \
} while (0)
#endif /* ASCON_SLICED */
/**
* \def ascon_separator()
* \brief Absorbs the standard ASCON separator for switching between
* associated data and message payload.
*/
#if ASCON_SLICED
#define ascon_separator() (state.W[8] ^= 0x01)
#else
#define ascon_separator() (state.B[39] ^= 0x01)
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
......
/*
* Copyright (C) 2021 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 "internal-util.h"
int aead_check_tag
(unsigned char *plaintext, size_t plaintext_len,
const unsigned char *tag1, const unsigned char *tag2, size_t 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;
}
void aead_clean(void *buf, unsigned size)
{
/* Force the use of volatile so that we actually clear the memory.
* Otherwise the compiler might optimise the entire contents of this
* function away, which will not be secure.
*
* Even this may not work. Some platforms have bzero_explicit() or
* memset_s() that could be used in place of this implementation. */
volatile uint8_t *d = (volatile uint8_t *)buf;
while (size > 0) {
*d++ = 0;
--size;
}
}
/* /*
* Copyright (C) 2020 Southern Storm Software, Pty Ltd. * Copyright (C) 2021 Southern Storm Software, Pty Ltd.
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * copy of this software and associated documentation files (the "Software"),
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#ifndef LW_INTERNAL_UTIL_H #ifndef LW_INTERNAL_UTIL_H
#define LW_INTERNAL_UTIL_H #define LW_INTERNAL_UTIL_H
#include <stddef.h>
#include <stdint.h> #include <stdint.h>
/* Figure out how to inline functions using this C compiler */ /* Figure out how to inline functions using this C compiler */
...@@ -53,6 +54,13 @@ ...@@ -53,6 +54,13 @@
#error "Cannot determine the endianess of this platform" #error "Cannot determine the endianess of this platform"
#endif #endif
/* Determine if we are compiling for a 64-bit CPU */
#if defined(__x86_64) || defined(__x86_64__) || \
defined(__aarch64__) || defined(__ARM_ARCH_ISA_A64) || \
defined(_M_AMD64) || defined(_M_X64) || defined(_M_IA64)
#define LW_UTIL_CPU_IS_64BIT 1
#endif
/* Helper macros to load and store values while converting endian-ness */ /* Helper macros to load and store values while converting endian-ness */
/* Load a big-endian 32-bit word from a byte buffer */ /* Load a big-endian 32-bit word from a byte buffer */
...@@ -89,6 +97,11 @@ ...@@ -89,6 +97,11 @@
(ptr)[3] = (uint8_t)(_x >> 24); \ (ptr)[3] = (uint8_t)(_x >> 24); \
} while (0) } while (0)
/* Reverses the bytes in a 32-bit word */
#define reverse_word32(x) \
(((x) >> 24) | (((x) >> 8) & 0x0000FF00U) | \
(((x) << 8) & 0x00FF0000U) | ((x) << 24))
/* Load a big-endian 64-bit word from a byte buffer */ /* Load a big-endian 64-bit word from a byte buffer */
#define be_load_word64(ptr) \ #define be_load_word64(ptr) \
((((uint64_t)((ptr)[0])) << 56) | \ ((((uint64_t)((ptr)[0])) << 56) | \
...@@ -699,4 +712,52 @@ ...@@ -699,4 +712,52 @@
#define rightRotate6_8(a) (rightRotate_8((a), 6)) #define rightRotate6_8(a) (rightRotate_8((a), 6))
#define rightRotate7_8(a) (rightRotate_8((a), 7)) #define rightRotate7_8(a) (rightRotate_8((a), 7))
/**
* \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 size 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, size_t plaintext_len,
const unsigned char *tag1, const unsigned char *tag2, size_t size);
/**
* \brief Attempts to cleans a buffer that contains sensitive material.
*
* \param buf Points to the buffer to clear.
* \param size Size of the buffer to clear in bytes.
*/
void aead_clean(void *buf, unsigned size);
/**
* \brief Number of bytes to retrieve from the system TRNG each time
* we need to reseed application-level PRNG's.
*/
#define AEAD_SYSTEM_SEED_SIZE 32
/**
* \brief Gets data from the system TRNG to reseed application-level PRNG's.
*
* \param seed Points to the buffer to be populated with the system seed.
*
* \return Non-zero if \a seed has been filled with TRNG data or zero
* if there is no accessible TRNG on this system.
*
* The quality of the returned seed data may be very poor or may not
* distribute the entropy evenly throughout the returned \a seed buffer.
* The application should use a PRNG to hash the seed data into a more
* useful random sequence.
*/
int aead_random_get_system_seed(unsigned char seed[AEAD_SYSTEM_SEED_SIZE]);
#endif #endif
/*
* Copyright (C) 2021 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_ASCON_AEAD_H
#define LWCRYPTO_ASCON_AEAD_H
#include <stddef.h>
/**
* \file ascon-aead.h
* \brief ASCON-128 encryption algorithm and related family members.
*
* The ASCON family consists of several related algorithms:
*
* \li ASCON-128 with a 128-bit key, a 128-bit nonce, a 128-bit authentication
* tag, and a block rate of 64 bits.
* \li ASCON-128a with a 128-bit key, a 128-bit nonce, a 128-bit authentication
* tag, and a block rate of 128 bits. This is faster than ASCON-128 but may
* not be as secure.
* \li ASCON-80pq with a 160-bit key, a 128-bit nonce, a 128-bit authentication
* tag, and a block rate of 64 bits. This is similar to ASCON-128 but has a
* 160-bit key instead which may be more resistant against quantum computers.
* \li ASCON-HASH and ASCON-HASHA with a 256-bit hash output.
* \li ASCON-XOF and ASCON-XOFA with extensible hash output (XOF mode).
*
* References: https://ascon.iaik.tugraz.at/
*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Size of the key for ASCON-128 and ASCON-128a.
*/
#define ASCON128_KEY_SIZE 16
/**
* \brief Size of the nonce for ASCON-128 and ASCON-128a.
*/
#define ASCON128_NONCE_SIZE 16
/**
* \brief Size of the authentication tag for ASCON-128 and ASCON-128a.
*/
#define ASCON128_TAG_SIZE 16
/**
* \brief Size of the key for ASCON-80pq.
*/
#define ASCON80PQ_KEY_SIZE 20
/**
* \brief Size of the nonce for ASCON-80pq.
*/
#define ASCON80PQ_NONCE_SIZE 16
/**
* \brief Size of the authentication tag for ASCON-80pq.
*/
#define ASCON80PQ_TAG_SIZE 16
/**
* \brief Encrypts and authenticates a packet with ASCON-128.
*
* \param c Buffer to receive the output.
* \param clen On exit, set to the length of the output which includes
* the ciphertext and the 16 byte 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 npub Points to the public nonce for the packet which must
* be 16 bytes in length.
* \param k Points to the 16 bytes of the key to use to encrypt the packet.
*
* \return 0 on success, or a negative value if there was an error in
* the parameters.
*
* \sa ascon128_aead_decrypt()
*/
int ascon128_aead_encrypt
(unsigned char *c, size_t *clen,
const unsigned char *m, size_t mlen,
const unsigned char *ad, size_t adlen,
const unsigned char *npub,
const unsigned char *k);
/**
* \brief Decrypts and authenticates a packet with ASCON-128.
*
* \param m Buffer to receive the plaintext message on output.
* \param mlen Receives the length of the plaintext message on output.
* \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 16 byte 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 which must
* be 16 bytes in length.
* \param k Points to the 16 bytes of 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.
*
* \sa ascon128_aead_encrypt()
*/
int ascon128_aead_decrypt
(unsigned char *m, size_t *mlen,
const unsigned char *c, size_t clen,
const unsigned char *ad, size_t adlen,
const unsigned char *npub,
const unsigned char *k);
/**
* \brief Encrypts and authenticates a packet with ASCON-128a.
*
* \param c Buffer to receive the output.
* \param clen On exit, set to the length of the output which includes
* the ciphertext and the 16 byte 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 npub Points to the public nonce for the packet which must
* be 16 bytes in length.
* \param k Points to the 16 bytes of the key to use to encrypt the packet.
*
* \return 0 on success, or a negative value if there was an error in
* the parameters.
*
* \sa ascon128a_aead_decrypt()
*/
int ascon128a_aead_encrypt
(unsigned char *c, size_t *clen,
const unsigned char *m, size_t mlen,
const unsigned char *ad, size_t adlen,
const unsigned char *npub,
const unsigned char *k);
/**
* \brief Decrypts and authenticates a packet with ASCON-128a.
*
* \param m Buffer to receive the plaintext message on output.
* \param mlen Receives the length of the plaintext message on output.
* \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 16 byte 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 which must
* be 16 bytes in length.
* \param k Points to the 16 bytes of 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.
*
* \sa ascon128a_aead_encrypt()
*/
int ascon128a_aead_decrypt
(unsigned char *m, size_t *mlen,
const unsigned char *c, size_t clen,
const unsigned char *ad, size_t adlen,
const unsigned char *npub,
const unsigned char *k);
/**
* \brief Encrypts and authenticates a packet with ASCON-80pq.
*
* \param c Buffer to receive the output.
* \param clen On exit, set to the length of the output which includes
* the ciphertext and the 16 byte 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 npub Points to the public nonce for the packet which must
* be 16 bytes in length.
* \param k Points to the 20 bytes of the key to use to encrypt the packet.
*
* \return 0 on success, or a negative value if there was an error in
* the parameters.
*
* \sa ascon80pq_aead_decrypt()
*/
int ascon80pq_aead_encrypt
(unsigned char *c, size_t *clen,
const unsigned char *m, size_t mlen,
const unsigned char *ad, size_t adlen,
const unsigned char *npub,
const unsigned char *k);
/**
* \brief Decrypts and authenticates a packet with ASCON-80pq.
*
* \param m Buffer to receive the plaintext message on output.
* \param mlen Receives the length of the plaintext message on output.
* \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 16 byte 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 which must
* be 16 bytes in length.
* \param k Points to the 20 bytes of 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.
*
* \sa ascon80pq_aead_encrypt()
*/
int ascon80pq_aead_decrypt
(unsigned char *m, size_t *mlen,
const unsigned char *c, size_t clen,
const unsigned char *ad, size_t adlen,
const unsigned char *npub,
const unsigned char *k);
#ifdef __cplusplus
}
#endif
#endif
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
);
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
);
#include "ascon128.h" #include "ascon-aead.h"
int crypto_aead_encrypt int crypto_aead_encrypt
(unsigned char *c, unsigned long long *clen, (unsigned char *c, unsigned long long *clen,
...@@ -9,8 +9,12 @@ int crypto_aead_encrypt ...@@ -9,8 +9,12 @@ int crypto_aead_encrypt
const unsigned char *npub, const unsigned char *npub,
const unsigned char *k) const unsigned char *k)
{ {
return ascon128_aead_encrypt size_t len = 0;
(c, clen, m, mlen, ad, adlen, nsec, npub, k); int result = ascon128_aead_encrypt
(c, &len, m, mlen, ad, adlen, npub, k);
(void)nsec;
*clen = len;
return result;
} }
int crypto_aead_decrypt int crypto_aead_decrypt
...@@ -21,6 +25,10 @@ int crypto_aead_decrypt ...@@ -21,6 +25,10 @@ int crypto_aead_decrypt
const unsigned char *npub, const unsigned char *npub,
const unsigned char *k) const unsigned char *k)
{ {
return ascon128_aead_decrypt size_t len = 0;
(m, mlen, nsec, c, clen, ad, adlen, npub, k); int result = ascon128_aead_decrypt
(m, &len, c, clen, ad, adlen, npub, k);
(void)nsec;
*mlen = len;
return result;
} }
#if defined(__AVR__) #if defined(__AVR__)
/*
* Copyright (C) 2021 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 <avr/io.h> #include <avr/io.h>
/* Automatically generated - do not edit */ /* Automatically generated - do not edit */
...@@ -49,287 +71,223 @@ ascon_permute: ...@@ -49,287 +71,223 @@ ascon_permute:
ldd r23,Z+7 ldd r23,Z+7
ldd r12,Z+15 ldd r12,Z+15
ldd r13,Z+31 ldd r13,Z+31
eor r23,r4 mov r14,r12
eor r4,r13 mov r15,r23
eor r18,r12 mov r24,r13
mov r14,r23 eor r14,r18
mov r15,r12 eor r15,r4
mov r24,r18 eor r24,r4
mov r25,r13 com r4
mov r16,r4 or r4,r13
com r14 eor r4,r14
eor r13,r12
or r13,r14
eor r13,r15
eor r18,r15
or r18,r12
eor r18,r24
com r15 com r15
com r24 and r12,r15
com r25
com r16
and r14,r12
and r15,r18
and r24,r13
and r25,r4
and r16,r23
eor r23,r15
eor r12,r24 eor r12,r24
eor r18,r25 or r23,r24
eor r13,r16 eor r23,r14
eor r4,r14 std Z+31,r23
eor r12,r23 std Z+39,r12
eor r23,r4 std Z+15,r13
eor r13,r18 std Z+23,r4
com r18
std Z+7,r23
std Z+15,r12
std Z+31,r13
std Z+39,r4
ldd r23,Z+6 ldd r23,Z+6
ldd r12,Z+14 ldd r12,Z+14
ldd r13,Z+30 ldd r13,Z+30
eor r23,r5 mov r14,r12
eor r5,r13 mov r15,r23
eor r19,r12 mov r24,r13
mov r14,r23 eor r14,r19
mov r15,r12 eor r15,r5
mov r24,r19 eor r24,r5
mov r25,r13 com r5
mov r16,r5 or r5,r13
com r14 eor r5,r14
eor r13,r12
or r13,r14
eor r13,r15
eor r19,r15
or r19,r12
eor r19,r24
com r15 com r15
com r24 and r12,r15
com r25
com r16
and r14,r12
and r15,r19
and r24,r13
and r25,r5
and r16,r23
eor r23,r15
eor r12,r24 eor r12,r24
eor r19,r25 or r23,r24
eor r13,r16 eor r23,r14
eor r5,r14 std Z+30,r23
eor r12,r23 std Z+38,r12
eor r23,r5 std Z+14,r13
eor r13,r19 std Z+22,r5
com r19
std Z+6,r23
std Z+14,r12
std Z+30,r13
std Z+38,r5
ldd r23,Z+5 ldd r23,Z+5
ldd r12,Z+13 ldd r12,Z+13
ldd r13,Z+29 ldd r13,Z+29
eor r23,r6 mov r14,r12
eor r6,r13 mov r15,r23
eor r20,r12 mov r24,r13
mov r14,r23 eor r14,r20
mov r15,r12 eor r15,r6
mov r24,r20 eor r24,r6
mov r25,r13 com r6
mov r16,r6 or r6,r13
com r14 eor r6,r14
eor r13,r12
or r13,r14
eor r13,r15
eor r20,r15
or r20,r12
eor r20,r24
com r15 com r15
com r24 and r12,r15
com r25
com r16
and r14,r12
and r15,r20
and r24,r13
and r25,r6
and r16,r23
eor r23,r15
eor r12,r24 eor r12,r24
eor r20,r25 or r23,r24
eor r13,r16 eor r23,r14
eor r6,r14 std Z+29,r23
eor r12,r23 std Z+37,r12
eor r23,r6 std Z+13,r13
eor r13,r20 std Z+21,r6
com r20
std Z+5,r23
std Z+13,r12
std Z+29,r13
std Z+37,r6
ldd r23,Z+4 ldd r23,Z+4
ldd r12,Z+12 ldd r12,Z+12
ldd r13,Z+28 ldd r13,Z+28
eor r23,r7 mov r14,r12
eor r7,r13 mov r15,r23
eor r21,r12 mov r24,r13
mov r14,r23 eor r14,r21
mov r15,r12 eor r15,r7
mov r24,r21 eor r24,r7
mov r25,r13 com r7
mov r16,r7 or r7,r13
com r14 eor r7,r14
eor r13,r12
or r13,r14
eor r13,r15
eor r21,r15
or r21,r12
eor r21,r24
com r15 com r15
com r24 and r12,r15
com r25
com r16
and r14,r12
and r15,r21
and r24,r13
and r25,r7
and r16,r23
eor r23,r15
eor r12,r24 eor r12,r24
eor r21,r25 or r23,r24
eor r13,r16 eor r23,r14
eor r7,r14 std Z+28,r23
eor r12,r23 std Z+36,r12
eor r23,r7 std Z+12,r13
eor r13,r21 std Z+20,r7
com r21
std Z+4,r23
std Z+12,r12
std Z+28,r13
std Z+36,r7
ldd r23,Z+3 ldd r23,Z+3
ldd r12,Z+11 ldd r12,Z+11
ldd r13,Z+27 ldd r13,Z+27
eor r23,r8 mov r14,r12
eor r8,r13 mov r15,r23
eor r26,r12 mov r24,r13
mov r14,r23 eor r14,r26
mov r15,r12 eor r15,r8
mov r24,r26 eor r24,r8
mov r25,r13 com r8
mov r16,r8 or r8,r13
com r14 eor r8,r14
eor r13,r12
or r13,r14
eor r13,r15
eor r26,r15
or r26,r12
eor r26,r24
com r15 com r15
com r24 and r12,r15
com r25
com r16
and r14,r12
and r15,r26
and r24,r13
and r25,r8
and r16,r23
eor r23,r15
eor r12,r24 eor r12,r24
eor r26,r25 or r23,r24
eor r13,r16 eor r23,r14
eor r8,r14 std Z+27,r23
eor r12,r23 std Z+35,r12
eor r23,r8 std Z+11,r13
eor r13,r26 std Z+19,r8
com r26
std Z+3,r23
std Z+11,r12
std Z+27,r13
std Z+35,r8
ldd r23,Z+2 ldd r23,Z+2
ldd r12,Z+10 ldd r12,Z+10
ldd r13,Z+26 ldd r13,Z+26
eor r23,r9 mov r14,r12
eor r9,r13 mov r15,r23
eor r27,r12 mov r24,r13
mov r14,r23 eor r14,r27
mov r15,r12 eor r15,r9
mov r24,r27 eor r24,r9
mov r25,r13 com r9
mov r16,r9 or r9,r13
com r14 eor r9,r14
eor r13,r12
or r13,r14
eor r13,r15
eor r27,r15
or r27,r12
eor r27,r24
com r15 com r15
com r24 and r12,r15
com r25
com r16
and r14,r12
and r15,r27
and r24,r13
and r25,r9
and r16,r23
eor r23,r15
eor r12,r24 eor r12,r24
eor r27,r25 or r23,r24
eor r13,r16 eor r23,r14
eor r9,r14 std Z+26,r23
eor r12,r23 std Z+34,r12
eor r23,r9 std Z+10,r13
eor r13,r27 std Z+18,r9
com r27
std Z+2,r23
std Z+10,r12
std Z+26,r13
std Z+34,r9
ldd r23,Z+1 ldd r23,Z+1
ldd r12,Z+9 ldd r12,Z+9
ldd r13,Z+25 ldd r13,Z+25
eor r23,r10 mov r14,r12
eor r10,r13 mov r15,r23
eor r2,r12 mov r24,r13
mov r14,r23 eor r14,r2
mov r15,r12 eor r15,r10
mov r24,r2 eor r24,r10
mov r25,r13 com r10
mov r16,r10 or r10,r13
com r14 eor r10,r14
eor r13,r12
or r13,r14
eor r13,r15
eor r2,r15
or r2,r12
eor r2,r24
com r15 com r15
com r24 and r12,r15
com r25
com r16
and r14,r12
and r15,r2
and r24,r13
and r25,r10
and r16,r23
eor r23,r15
eor r12,r24 eor r12,r24
eor r2,r25 or r23,r24
eor r13,r16 eor r23,r14
eor r10,r14 std Z+25,r23
eor r12,r23 std Z+33,r12
eor r23,r10 std Z+9,r13
eor r13,r2 std Z+17,r10
com r2
std Z+1,r23
std Z+9,r12
std Z+25,r13
std Z+33,r10
ld r23,Z ld r23,Z
ldd r12,Z+8 ldd r12,Z+8
ldd r13,Z+24 ldd r13,Z+24
eor r23,r11 mov r14,r12
eor r11,r13 mov r15,r23
eor r3,r12 mov r24,r13
mov r14,r23 eor r14,r3
mov r15,r12 eor r15,r11
mov r24,r3 eor r24,r11
mov r25,r13 com r11
mov r16,r11 or r11,r13
com r14 eor r11,r14
eor r13,r12
or r13,r14
eor r13,r15
eor r3,r15
or r3,r12
eor r3,r24
com r15 com r15
com r24 and r12,r15
com r25
com r16
and r14,r12
and r15,r3
and r24,r13
and r25,r11
and r16,r23
eor r23,r15
eor r12,r24 eor r12,r24
eor r3,r25 or r23,r24
eor r13,r16 eor r23,r14
eor r11,r14 std Z+24,r23
eor r12,r23 std Z+32,r12
eor r23,r11 std Z+8,r13
eor r13,r3 std Z+16,r11
com r3 movw r12,r18
st Z,r23 movw r14,r20
std Z+8,r12 movw r24,r26
std Z+24,r13 movw r16,r2
std Z+32,r11
ld r11,Z
ldd r10,Z+1
ldd r9,Z+2
ldd r8,Z+3
ldd r7,Z+4
ldd r6,Z+5
ldd r5,Z+6
ldd r4,Z+7
movw r12,r4
movw r14,r6
movw r24,r8
movw r16,r10
mov r0,r12 mov r0,r12
mov r12,r14 mov r12,r14
mov r14,r24 mov r14,r24
...@@ -369,79 +327,79 @@ ascon_permute: ...@@ -369,79 +327,79 @@ ascon_permute:
ror r12 ror r12
ror r0 ror r0
or r17,r0 or r17,r0
eor r12,r4 eor r12,r18
eor r13,r5 eor r13,r19
eor r14,r6 eor r14,r20
eor r15,r7 eor r15,r21
eor r24,r8 eor r24,r26
eor r25,r9 eor r25,r27
eor r16,r10 eor r16,r2
eor r17,r11 eor r17,r3
mov r23,r4 mov r23,r18
mov r0,r5 mov r0,r19
push r6 push r20
mov r4,r7 mov r18,r21
mov r5,r8 mov r19,r26
mov r6,r9 mov r20,r27
mov r7,r10 mov r21,r2
mov r8,r11 mov r26,r3
pop r11 pop r3
mov r10,r0 mov r2,r0
mov r9,r23 mov r27,r23
mov r0,r1 mov r0,r1
lsr r11 lsr r3
ror r10 ror r2
ror r9 ror r27
ror r8 ror r26
ror r7 ror r21
ror r6 ror r20
ror r5 ror r19
ror r4 ror r18
ror r0 ror r0
lsr r11 lsr r3
ror r10 ror r2
ror r9 ror r27
ror r8 ror r26
ror r7 ror r21
ror r6 ror r20
ror r5 ror r19
ror r4 ror r18
ror r0 ror r0
lsr r11 lsr r3
ror r10 ror r2
ror r9 ror r27
ror r8 ror r26
ror r7 ror r21
ror r6 ror r20
ror r5 ror r19
ror r4 ror r18
ror r0 ror r0
lsr r11 lsr r3
ror r10 ror r2
ror r9 ror r27
ror r8 ror r26
ror r7 ror r21
ror r6 ror r20
ror r5 ror r19
ror r4 ror r18
ror r0 ror r0
or r11,r0 or r3,r0
eor r4,r12 eor r18,r12
eor r5,r13 eor r19,r13
eor r6,r14 eor r20,r14
eor r7,r15 eor r21,r15
eor r8,r24 eor r26,r24
eor r9,r25 eor r27,r25
eor r10,r16 eor r2,r16
eor r11,r17 eor r3,r17
st Z,r11 st Z,r3
std Z+1,r10 std Z+1,r2
std Z+2,r9 std Z+2,r27
std Z+3,r8 std Z+3,r26
std Z+4,r7 std Z+4,r21
std Z+5,r6 std Z+5,r20
std Z+6,r5 std Z+6,r19
std Z+7,r4 std Z+7,r18
ldd r11,Z+8 ldd r11,Z+8
ldd r10,Z+9 ldd r10,Z+9
ldd r9,Z+10 ldd r9,Z+10
...@@ -525,6 +483,14 @@ ascon_permute: ...@@ -525,6 +483,14 @@ ascon_permute:
std Z+13,r6 std Z+13,r6
std Z+14,r5 std Z+14,r5
std Z+15,r4 std Z+15,r4
ldd r3,Z+16
ldd r2,Z+17
ldd r27,Z+18
ldd r26,Z+19
ldd r21,Z+20
ldd r20,Z+21
ldd r19,Z+22
ldd r18,Z+23
movw r12,r18 movw r12,r18
movw r14,r20 movw r14,r20
movw r24,r26 movw r24,r26
......
/* /*
* Copyright (C) 2020 Southern Storm Software, Pty Ltd. * Copyright (C) 2021 Southern Storm Software, Pty Ltd.
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * copy of this software and associated documentation files (the "Software"),
...@@ -22,7 +22,19 @@ ...@@ -22,7 +22,19 @@
#include "internal-ascon.h" #include "internal-ascon.h"
#if !defined(__AVR__) /* Determine which versions should be accelerated with assembly code */
#if defined(__AVR__)
#define ASCON_ASM_REGULAR 1
#define ASCON_ASM_SLICED 0
#elif defined(__ARM_ARCH_ISA_THUMB) && __ARM_ARCH == 7
#define ASCON_ASM_REGULAR 1
#define ASCON_ASM_SLICED 1
#else
#define ASCON_ASM_REGULAR 0
#define ASCON_ASM_SLICED 0
#endif
#if !ASCON_ASM_REGULAR
void ascon_permute(ascon_state_t *state, uint8_t first_round) void ascon_permute(ascon_state_t *state, uint8_t first_round)
{ {
...@@ -77,4 +89,120 @@ void ascon_permute(ascon_state_t *state, uint8_t first_round) ...@@ -77,4 +89,120 @@ void ascon_permute(ascon_state_t *state, uint8_t first_round)
#endif #endif
} }
#endif /* !__AVR__ */ #endif /* !ASCON_ASM_REGULAR */
#if ASCON_SLICED && !ASCON_ASM_SLICED
void ascon_to_sliced(ascon_state_t *state)
{
int index;
uint32_t high, low;
for (index = 0; index < 10; index += 2) {
high = be_load_word32(state->B + index * 4);
low = be_load_word32(state->B + index * 4 + 4);
ascon_separate(high);
ascon_separate(low);
state->W[index] = (high << 16) | (low & 0x0000FFFFU);
state->W[index + 1] = (high & 0xFFFF0000U) | (low >> 16);
}
}
void ascon_from_sliced(ascon_state_t *state)
{
int index;
uint32_t high, low;
for (index = 0; index < 10; index += 2) {
high = (state->W[index] >> 16) | (state->W[index + 1] & 0xFFFF0000U);
low = (state->W[index] & 0x0000FFFFU) | (state->W[index + 1] << 16);
ascon_combine(high);
ascon_combine(low);
be_store_word32(state->B + index * 4, high);
be_store_word32(state->B + index * 4 + 4, low);
}
}
void ascon_permute_sliced(ascon_state_t *state, uint8_t first_round)
{
static const unsigned char RC[12 * 2] = {
12, 12, 9, 12, 12, 9, 9, 9, 6, 12, 3, 12,
6, 9, 3, 9, 12, 6, 9, 6, 12, 3, 9, 3
};
const unsigned char *rc = RC + first_round * 2;
uint32_t t0, t1, t2, t3, t4;
/* Load the state into local variables */
uint32_t x0_e = state->W[0];
uint32_t x0_o = state->W[1];
uint32_t x1_e = state->W[2];
uint32_t x1_o = state->W[3];
uint32_t x2_e = state->W[4];
uint32_t x2_o = state->W[5];
uint32_t x3_e = state->W[6];
uint32_t x3_o = state->W[7];
uint32_t x4_e = state->W[8];
uint32_t x4_o = state->W[9];
/* Perform all permutation rounds */
while (first_round < 12) {
/* Add the round constants for this round to the state */
x2_e ^= rc[0];
x2_o ^= rc[1];
rc += 2;
/* Substitution layer */
#define ascon_sbox(x0, x1, x2, x3, x4) \
do { \
x0 ^= x4; x4 ^= x3; x2 ^= x1; \
t0 = ~x0; t1 = ~x1; t2 = ~x2; t3 = ~x3; t4 = ~x4; \
t0 &= x1; t1 &= x2; t2 &= x3; t3 &= x4; t4 &= x0; \
x0 ^= t1; x1 ^= t2; x2 ^= t3; x3 ^= t4; x4 ^= t0; \
x1 ^= x0; x0 ^= x4; x3 ^= x2; x2 = ~x2; \
} while (0)
ascon_sbox(x0_e, x1_e, x2_e, x3_e, x4_e);
ascon_sbox(x0_o, x1_o, x2_o, x3_o, x4_o);
/* Linear diffusion layer */
/* x0 ^= rightRotate19_64(x0) ^ rightRotate28_64(x0); */
t0 = x0_e ^ rightRotate4(x0_o);
t1 = x0_o ^ rightRotate5(x0_e);
x0_e ^= rightRotate9(t1);
x0_o ^= rightRotate10(t0);
/* x1 ^= rightRotate61_64(x1) ^ rightRotate39_64(x1); */
t0 = x1_e ^ rightRotate11(x1_e);
t1 = x1_o ^ rightRotate11(x1_o);
x1_e ^= rightRotate19(t1);
x1_o ^= rightRotate20(t0);
/* x2 ^= rightRotate1_64(x2) ^ rightRotate6_64(x2); */
t0 = x2_e ^ rightRotate2(x2_o);
t1 = x2_o ^ rightRotate3(x2_e);
x2_e ^= t1;
x2_o ^= rightRotate1(t0);
/* x3 ^= rightRotate10_64(x3) ^ rightRotate17_64(x3); */
t0 = x3_e ^ rightRotate3(x3_o);
t1 = x3_o ^ rightRotate4(x3_e);
x3_e ^= rightRotate5(t0);
x3_o ^= rightRotate5(t1);
/* x4 ^= rightRotate7_64(x4) ^ rightRotate41_64(x4); */
t0 = x4_e ^ rightRotate17(x4_e);
t1 = x4_o ^ rightRotate17(x4_o);
x4_e ^= rightRotate3(t1);
x4_o ^= rightRotate4(t0);
/* Move onto the next round */
++first_round;
}
/* Write the local variables back to the state */
state->W[0] = x0_e;
state->W[1] = x0_o;
state->W[2] = x1_e;
state->W[3] = x1_o;
state->W[4] = x2_e;
state->W[5] = x2_o;
state->W[6] = x3_e;
state->W[7] = x3_o;
state->W[8] = x4_e;
state->W[9] = x4_o;
}
#endif /* ASCON_SLICED */
/* /*
* Copyright (C) 2020 Southern Storm Software, Pty Ltd. * Copyright (C) 2021 Southern Storm Software, Pty Ltd.
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * copy of this software and associated documentation files (the "Software"),
...@@ -38,11 +38,36 @@ extern "C" { ...@@ -38,11 +38,36 @@ extern "C" {
#endif #endif
/** /**
* \brief Defined to 1 if the 32-bit sliced version of ASCON is preferred.
*/
#if !defined(__AVR__) && !defined(LW_UTIL_CPU_IS_64BIT)
#define ASCON_SLICED 1
#else
#define ASCON_SLICED 0
#endif
/**
* \brief Initialization vector for ASCON-128.
*/
#define ASCON128_IV 0x80400c0600000000ULL
/**
* \brief Initialization vector for ASCON-128a.
*/
#define ASCON128a_IV 0x80800c0800000000ULL
/**
* \brief Initialization vector for ASCON-80pq.
*/
#define ASCON80PQ_IV 0xa0400c06U
/**
* \brief Structure of the internal state of the ASCON permutation. * \brief Structure of the internal state of the ASCON permutation.
*/ */
typedef union typedef union
{ {
uint64_t S[5]; /**< Words of the state */ uint64_t S[5]; /**< 64-bit words of the state */
uint32_t W[10]; /**< 32-bit words of the state */
uint8_t B[40]; /**< Bytes of the state */ uint8_t B[40]; /**< Bytes of the state */
} ascon_state_t; } ascon_state_t;
...@@ -57,6 +82,237 @@ typedef union ...@@ -57,6 +82,237 @@ typedef union
*/ */
void ascon_permute(ascon_state_t *state, uint8_t first_round); void ascon_permute(ascon_state_t *state, uint8_t first_round);
#if ASCON_SLICED
/**
* \brief Converts an ASCON state from byte form into sliced form.
*
* \param state The ASCON state to be converted, in big-endian byte order
* on entry and in host byte order on exit.
*/
void ascon_to_sliced(ascon_state_t *state);
/**
* \brief Converts an ASCON state from sliced form into byte form.
*
* \param state The ASCON state to be converted, in host byte order
* on entry and in big-endian byte order on exit.
*/
void ascon_from_sliced(ascon_state_t *state);
/**
* \brief Permutes the ASCON state in sliced form.
*
* \param state The ASCON state to be permuted.
* \param first_round The first round (of 12) to be performed; 0, 4, or 6.
*
* The input and output \a state will be in host byte order.
*/
void ascon_permute_sliced(ascon_state_t *state, uint8_t first_round);
/** @cond ascon_bit_separation */
/* http://programming.sirrida.de/perm_fn.html#bit_permute_step */
#define ascon_bit_permute_step(_y, mask, shift) \
do { \
uint32_t y = (_y); \
uint32_t t = ((y >> (shift)) ^ y) & (mask); \
(_y) = (y ^ t) ^ (t << (shift)); \
} while (0)
/* Separates a 32-bit word into two 16-bit halves with all the even
* bits in the bottom half and all the odd bits in the top half.
*
* Permutation generated with "http://programming.sirrida.de/calcperm.php"
*
* P = [0 16 1 17 2 18 3 19 4 20 5 21 6 22 7 23 8 24
* 9 25 10 26 11 27 12 28 13 29 14 30 15 31]
*/
#define ascon_separate(x) \
do { \
ascon_bit_permute_step((x), 0x22222222, 1); \
ascon_bit_permute_step((x), 0x0c0c0c0c, 2); \
ascon_bit_permute_step((x), 0x00f000f0, 4); \
ascon_bit_permute_step((x), 0x0000ff00, 8); \
} while (0)
#define ascon_combine(x) \
do { \
ascon_bit_permute_step((x), 0x0000aaaa, 15); \
ascon_bit_permute_step((x), 0x0000cccc, 14); \
ascon_bit_permute_step((x), 0x0000f0f0, 12); \
ascon_bit_permute_step((x), 0x0000ff00, 8); \
} while (0)
/** @endcond */
/**
* \brief Sets data into the ASCON state in sliced form.
*
* \param state The ASCON state for the data to be absorbed into.
* \param data Points to 8 bytes of data in big-endian byte order to set.
* \param offset Offset of the 64-bit word within the state to set at,
* between 0 and 4.
*/
#define ascon_set_sliced(state, data, offset) \
do { \
ascon_state_t *s = (state); \
uint32_t high = be_load_word32((data)); \
uint32_t low = be_load_word32((data) + 4); \
ascon_separate(high); \
ascon_separate(low); \
s->W[(offset) * 2] = (high << 16) | (low & 0x0000FFFFU); \
s->W[(offset) * 2 + 1] = (high & 0xFFFF0000U) | (low >> 16); \
} while (0)
/**
* \brief Absorbs data into the ASCON state in sliced form.
*
* \param state The ASCON state for the data to be absorbed into.
* \param data Points to 8 bytes of data in big-endian byte order to absorb.
* \param offset Offset of the 64-bit word within the state to absorb at,
* between 0 and 4.
*/
#define ascon_absorb_sliced(state, data, offset) \
do { \
ascon_state_t *s = (state); \
uint32_t high = be_load_word32((data)); \
uint32_t low = be_load_word32((data) + 4); \
ascon_separate(high); \
ascon_separate(low); \
s->W[(offset) * 2] ^= (high << 16) | (low & 0x0000FFFFU); \
s->W[(offset) * 2 + 1] ^= (high & 0xFFFF0000U) | (low >> 16); \
} while (0)
/**
* \brief Absorbs 32 bits of data into the ASCON state in sliced form.
*
* \param state The ASCON state for the data to be absorbed into.
* \param data Points to 4 bytes of data in big-endian byte order to absorb.
* \param offset Offset of the 64-bit word within the state to absorb at,
* between 0 and 4.
*
* The data is absorbed into the low bits of the 64-bit word at \a offset.
*/
#define ascon_absorb32_low_sliced(state, data, offset) \
do { \
ascon_state_t *s = (state); \
uint32_t low = be_load_word32((data)); \
ascon_separate(low); \
s->W[(offset) * 2] ^= (low & 0x0000FFFFU); \
s->W[(offset) * 2 + 1] ^= (low >> 16); \
} while (0)
/**
* \brief Absorbs 32 bits of data into the ASCON state in sliced form.
*
* \param state The ASCON state for the data to be absorbed into.
* \param data Points to 4 bytes of data in big-endian byte order to absorb.
* \param offset Offset of the 64-bit word within the state to absorb at,
* between 0 and 4.
*
* The data is absorbed into the high bits of the 64-bit word at \a offset.
*/
#define ascon_absorb32_high_sliced(state, data, offset) \
do { \
ascon_state_t *s = (state); \
uint32_t high = be_load_word32((data)); \
ascon_separate(high); \
s->W[(offset) * 2] ^= (high << 16); \
s->W[(offset) * 2 + 1] ^= (high & 0xFFFF0000U); \
} while (0)
/**
* \brief Squeezes data from the ASCON state in sliced form.
*
* \param state The ASCON state to extract the data from.
* \param data Points to the 8 bytes to be extracted from the state.
* \param offset Offset of the 64-bit word within the state to extract,
* between 0 and 4.
*/
#define ascon_squeeze_sliced(state, data, offset) \
do { \
ascon_state_t *s = (state); \
uint32_t high, low; \
high = (s->W[(offset) * 2] >> 16) | \
(s->W[(offset) * 2 + 1] & 0xFFFF0000U); \
low = (s->W[(offset) * 2] & 0x0000FFFFU) | \
(s->W[(offset) * 2 + 1] << 16); \
ascon_combine(high); \
ascon_combine(low); \
be_store_word32((data), high); \
be_store_word32((data) + 4, low); \
} while (0)
/**
* \brief Encrypts data using the ASCON state in sliced form.
*
* \param state The ASCON state.
* \param c Points to 8 bytes of output ciphertext in big-endian byte order.
* \param m Points to 8 bytes of input plaintext in big-endian byte order.
* \param offset Offset of the 64-bit word within the state to absorb
* and squeeze at, between 0 and 4.
*/
#define ascon_encrypt_sliced(state, c, m, offset) \
do { \
ascon_state_t *s = (state); \
uint32_t high = be_load_word32((m)); \
uint32_t low = be_load_word32((m) + 4); \
ascon_separate(high); \
ascon_separate(low); \
s->W[(offset) * 2] ^= (high << 16) | (low & 0x0000FFFFU); \
s->W[(offset) * 2 + 1] ^= (high & 0xFFFF0000U) | (low >> 16); \
high = (s->W[(offset) * 2] >> 16) | \
(s->W[(offset) * 2 + 1] & 0xFFFF0000U); \
low = (s->W[(offset) * 2] & 0x0000FFFFU) | \
(s->W[(offset) * 2 + 1] << 16); \
ascon_combine(high); \
ascon_combine(low); \
be_store_word32((c), high); \
be_store_word32((c) + 4, low); \
} while (0)
/**
* \brief Decrypts data using the ASCON state in sliced form.
*
* \param state The ASCON state.
* \param m Points to 8 bytes of output plaintext in big-endian byte order.
* \param c Points to 8 bytes of input ciphertext in big-endian byte order.
* \param offset Offset of the 64-bit word within the state to absorb
* and squeeze at, between 0 and 4.
*/
#define ascon_decrypt_sliced(state, m, c, offset) \
do { \
ascon_state_t *s = (state); \
uint32_t high, low, high2, low2; \
high = be_load_word32((c)); \
low = be_load_word32((c) + 4); \
ascon_separate(high); \
ascon_separate(low); \
high2 = high ^ ((s->W[(offset) * 2] >> 16) | \
(s->W[(offset) * 2 + 1] & 0xFFFF0000U)); \
low2 = low ^ ((s->W[(offset) * 2] & 0x0000FFFFU) | \
(s->W[(offset) * 2 + 1] << 16)); \
s->W[(offset) * 2] = (high << 16) | (low & 0x0000FFFFU); \
s->W[(offset) * 2 + 1] = (high & 0xFFFF0000U) | (low >> 16); \
ascon_combine(high2); \
ascon_combine(low2); \
be_store_word32((m), high2); \
be_store_word32((m) + 4, low2); \
} while (0)
#endif /* ASCON_SLICED */
/**
* \def ascon_separator()
* \brief Absorbs the standard ASCON separator for switching between
* associated data and message payload.
*/
#if ASCON_SLICED
#define ascon_separator() (state.W[8] ^= 0x01)
#else
#define ascon_separator() (state.B[39] ^= 0x01)
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
......
/*
* Copyright (C) 2021 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 "internal-util.h"
int aead_check_tag
(unsigned char *plaintext, size_t plaintext_len,
const unsigned char *tag1, const unsigned char *tag2, size_t 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;
}
void aead_clean(void *buf, unsigned size)
{
/* Force the use of volatile so that we actually clear the memory.
* Otherwise the compiler might optimise the entire contents of this
* function away, which will not be secure.
*
* Even this may not work. Some platforms have bzero_explicit() or
* memset_s() that could be used in place of this implementation. */
volatile uint8_t *d = (volatile uint8_t *)buf;
while (size > 0) {
*d++ = 0;
--size;
}
}
/* /*
* Copyright (C) 2020 Southern Storm Software, Pty Ltd. * Copyright (C) 2021 Southern Storm Software, Pty Ltd.
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * copy of this software and associated documentation files (the "Software"),
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#ifndef LW_INTERNAL_UTIL_H #ifndef LW_INTERNAL_UTIL_H
#define LW_INTERNAL_UTIL_H #define LW_INTERNAL_UTIL_H
#include <stddef.h>
#include <stdint.h> #include <stdint.h>
/* Figure out how to inline functions using this C compiler */ /* Figure out how to inline functions using this C compiler */
...@@ -53,6 +54,13 @@ ...@@ -53,6 +54,13 @@
#error "Cannot determine the endianess of this platform" #error "Cannot determine the endianess of this platform"
#endif #endif
/* Determine if we are compiling for a 64-bit CPU */
#if defined(__x86_64) || defined(__x86_64__) || \
defined(__aarch64__) || defined(__ARM_ARCH_ISA_A64) || \
defined(_M_AMD64) || defined(_M_X64) || defined(_M_IA64)
#define LW_UTIL_CPU_IS_64BIT 1
#endif
/* Helper macros to load and store values while converting endian-ness */ /* Helper macros to load and store values while converting endian-ness */
/* Load a big-endian 32-bit word from a byte buffer */ /* Load a big-endian 32-bit word from a byte buffer */
...@@ -89,6 +97,11 @@ ...@@ -89,6 +97,11 @@
(ptr)[3] = (uint8_t)(_x >> 24); \ (ptr)[3] = (uint8_t)(_x >> 24); \
} while (0) } while (0)
/* Reverses the bytes in a 32-bit word */
#define reverse_word32(x) \
(((x) >> 24) | (((x) >> 8) & 0x0000FF00U) | \
(((x) << 8) & 0x00FF0000U) | ((x) << 24))
/* Load a big-endian 64-bit word from a byte buffer */ /* Load a big-endian 64-bit word from a byte buffer */
#define be_load_word64(ptr) \ #define be_load_word64(ptr) \
((((uint64_t)((ptr)[0])) << 56) | \ ((((uint64_t)((ptr)[0])) << 56) | \
...@@ -699,4 +712,52 @@ ...@@ -699,4 +712,52 @@
#define rightRotate6_8(a) (rightRotate_8((a), 6)) #define rightRotate6_8(a) (rightRotate_8((a), 6))
#define rightRotate7_8(a) (rightRotate_8((a), 7)) #define rightRotate7_8(a) (rightRotate_8((a), 7))
/**
* \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 size 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, size_t plaintext_len,
const unsigned char *tag1, const unsigned char *tag2, size_t size);
/**
* \brief Attempts to cleans a buffer that contains sensitive material.
*
* \param buf Points to the buffer to clear.
* \param size Size of the buffer to clear in bytes.
*/
void aead_clean(void *buf, unsigned size);
/**
* \brief Number of bytes to retrieve from the system TRNG each time
* we need to reseed application-level PRNG's.
*/
#define AEAD_SYSTEM_SEED_SIZE 32
/**
* \brief Gets data from the system TRNG to reseed application-level PRNG's.
*
* \param seed Points to the buffer to be populated with the system seed.
*
* \return Non-zero if \a seed has been filled with TRNG data or zero
* if there is no accessible TRNG on this system.
*
* The quality of the returned seed data may be very poor or may not
* distribute the entropy evenly throughout the returned \a seed buffer.
* The application should use a PRNG to hash the seed data into a more
* useful random sequence.
*/
int aead_random_get_system_seed(unsigned char seed[AEAD_SYSTEM_SEED_SIZE]);
#endif #endif
/*
* Copyright (C) 2021 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_ASCON_AEAD_H
#define LWCRYPTO_ASCON_AEAD_H
#include <stddef.h>
/**
* \file ascon-aead.h
* \brief ASCON-128 encryption algorithm and related family members.
*
* The ASCON family consists of several related algorithms:
*
* \li ASCON-128 with a 128-bit key, a 128-bit nonce, a 128-bit authentication
* tag, and a block rate of 64 bits.
* \li ASCON-128a with a 128-bit key, a 128-bit nonce, a 128-bit authentication
* tag, and a block rate of 128 bits. This is faster than ASCON-128 but may
* not be as secure.
* \li ASCON-80pq with a 160-bit key, a 128-bit nonce, a 128-bit authentication
* tag, and a block rate of 64 bits. This is similar to ASCON-128 but has a
* 160-bit key instead which may be more resistant against quantum computers.
* \li ASCON-HASH and ASCON-HASHA with a 256-bit hash output.
* \li ASCON-XOF and ASCON-XOFA with extensible hash output (XOF mode).
*
* References: https://ascon.iaik.tugraz.at/
*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Size of the key for ASCON-128 and ASCON-128a.
*/
#define ASCON128_KEY_SIZE 16
/**
* \brief Size of the nonce for ASCON-128 and ASCON-128a.
*/
#define ASCON128_NONCE_SIZE 16
/**
* \brief Size of the authentication tag for ASCON-128 and ASCON-128a.
*/
#define ASCON128_TAG_SIZE 16
/**
* \brief Size of the key for ASCON-80pq.
*/
#define ASCON80PQ_KEY_SIZE 20
/**
* \brief Size of the nonce for ASCON-80pq.
*/
#define ASCON80PQ_NONCE_SIZE 16
/**
* \brief Size of the authentication tag for ASCON-80pq.
*/
#define ASCON80PQ_TAG_SIZE 16
/**
* \brief Encrypts and authenticates a packet with ASCON-128.
*
* \param c Buffer to receive the output.
* \param clen On exit, set to the length of the output which includes
* the ciphertext and the 16 byte 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 npub Points to the public nonce for the packet which must
* be 16 bytes in length.
* \param k Points to the 16 bytes of the key to use to encrypt the packet.
*
* \return 0 on success, or a negative value if there was an error in
* the parameters.
*
* \sa ascon128_aead_decrypt()
*/
int ascon128_aead_encrypt
(unsigned char *c, size_t *clen,
const unsigned char *m, size_t mlen,
const unsigned char *ad, size_t adlen,
const unsigned char *npub,
const unsigned char *k);
/**
* \brief Decrypts and authenticates a packet with ASCON-128.
*
* \param m Buffer to receive the plaintext message on output.
* \param mlen Receives the length of the plaintext message on output.
* \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 16 byte 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 which must
* be 16 bytes in length.
* \param k Points to the 16 bytes of 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.
*
* \sa ascon128_aead_encrypt()
*/
int ascon128_aead_decrypt
(unsigned char *m, size_t *mlen,
const unsigned char *c, size_t clen,
const unsigned char *ad, size_t adlen,
const unsigned char *npub,
const unsigned char *k);
/**
* \brief Encrypts and authenticates a packet with ASCON-128a.
*
* \param c Buffer to receive the output.
* \param clen On exit, set to the length of the output which includes
* the ciphertext and the 16 byte 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 npub Points to the public nonce for the packet which must
* be 16 bytes in length.
* \param k Points to the 16 bytes of the key to use to encrypt the packet.
*
* \return 0 on success, or a negative value if there was an error in
* the parameters.
*
* \sa ascon128a_aead_decrypt()
*/
int ascon128a_aead_encrypt
(unsigned char *c, size_t *clen,
const unsigned char *m, size_t mlen,
const unsigned char *ad, size_t adlen,
const unsigned char *npub,
const unsigned char *k);
/**
* \brief Decrypts and authenticates a packet with ASCON-128a.
*
* \param m Buffer to receive the plaintext message on output.
* \param mlen Receives the length of the plaintext message on output.
* \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 16 byte 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 which must
* be 16 bytes in length.
* \param k Points to the 16 bytes of 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.
*
* \sa ascon128a_aead_encrypt()
*/
int ascon128a_aead_decrypt
(unsigned char *m, size_t *mlen,
const unsigned char *c, size_t clen,
const unsigned char *ad, size_t adlen,
const unsigned char *npub,
const unsigned char *k);
/**
* \brief Encrypts and authenticates a packet with ASCON-80pq.
*
* \param c Buffer to receive the output.
* \param clen On exit, set to the length of the output which includes
* the ciphertext and the 16 byte 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 npub Points to the public nonce for the packet which must
* be 16 bytes in length.
* \param k Points to the 20 bytes of the key to use to encrypt the packet.
*
* \return 0 on success, or a negative value if there was an error in
* the parameters.
*
* \sa ascon80pq_aead_decrypt()
*/
int ascon80pq_aead_encrypt
(unsigned char *c, size_t *clen,
const unsigned char *m, size_t mlen,
const unsigned char *ad, size_t adlen,
const unsigned char *npub,
const unsigned char *k);
/**
* \brief Decrypts and authenticates a packet with ASCON-80pq.
*
* \param m Buffer to receive the plaintext message on output.
* \param mlen Receives the length of the plaintext message on output.
* \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 16 byte 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 which must
* be 16 bytes in length.
* \param k Points to the 20 bytes of 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.
*
* \sa ascon80pq_aead_encrypt()
*/
int ascon80pq_aead_decrypt
(unsigned char *m, size_t *mlen,
const unsigned char *c, size_t clen,
const unsigned char *ad, size_t adlen,
const unsigned char *npub,
const unsigned char *k);
#ifdef __cplusplus
}
#endif
#endif
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
);
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
);
#include "ascon128.h" #include "ascon-aead.h"
int crypto_aead_encrypt int crypto_aead_encrypt
(unsigned char *c, unsigned long long *clen, (unsigned char *c, unsigned long long *clen,
...@@ -9,8 +9,12 @@ int crypto_aead_encrypt ...@@ -9,8 +9,12 @@ int crypto_aead_encrypt
const unsigned char *npub, const unsigned char *npub,
const unsigned char *k) const unsigned char *k)
{ {
return ascon80pq_aead_encrypt size_t len = 0;
(c, clen, m, mlen, ad, adlen, nsec, npub, k); int result = ascon80pq_aead_encrypt
(c, &len, m, mlen, ad, adlen, npub, k);
(void)nsec;
*clen = len;
return result;
} }
int crypto_aead_decrypt int crypto_aead_decrypt
...@@ -21,6 +25,10 @@ int crypto_aead_decrypt ...@@ -21,6 +25,10 @@ int crypto_aead_decrypt
const unsigned char *npub, const unsigned char *npub,
const unsigned char *k) const unsigned char *k)
{ {
return ascon80pq_aead_decrypt size_t len = 0;
(m, mlen, nsec, c, clen, ad, adlen, npub, k); int result = ascon80pq_aead_decrypt
(m, &len, c, clen, ad, adlen, npub, k);
(void)nsec;
*mlen = len;
return result;
} }
#if defined(__AVR__) #if defined(__AVR__)
/*
* Copyright (C) 2021 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 <avr/io.h> #include <avr/io.h>
/* Automatically generated - do not edit */ /* Automatically generated - do not edit */
...@@ -49,287 +71,223 @@ ascon_permute: ...@@ -49,287 +71,223 @@ ascon_permute:
ldd r23,Z+7 ldd r23,Z+7
ldd r12,Z+15 ldd r12,Z+15
ldd r13,Z+31 ldd r13,Z+31
eor r23,r4 mov r14,r12
eor r4,r13 mov r15,r23
eor r18,r12 mov r24,r13
mov r14,r23 eor r14,r18
mov r15,r12 eor r15,r4
mov r24,r18 eor r24,r4
mov r25,r13 com r4
mov r16,r4 or r4,r13
com r14 eor r4,r14
eor r13,r12
or r13,r14
eor r13,r15
eor r18,r15
or r18,r12
eor r18,r24
com r15 com r15
com r24 and r12,r15
com r25
com r16
and r14,r12
and r15,r18
and r24,r13
and r25,r4
and r16,r23
eor r23,r15
eor r12,r24 eor r12,r24
eor r18,r25 or r23,r24
eor r13,r16 eor r23,r14
eor r4,r14 std Z+31,r23
eor r12,r23 std Z+39,r12
eor r23,r4 std Z+15,r13
eor r13,r18 std Z+23,r4
com r18
std Z+7,r23
std Z+15,r12
std Z+31,r13
std Z+39,r4
ldd r23,Z+6 ldd r23,Z+6
ldd r12,Z+14 ldd r12,Z+14
ldd r13,Z+30 ldd r13,Z+30
eor r23,r5 mov r14,r12
eor r5,r13 mov r15,r23
eor r19,r12 mov r24,r13
mov r14,r23 eor r14,r19
mov r15,r12 eor r15,r5
mov r24,r19 eor r24,r5
mov r25,r13 com r5
mov r16,r5 or r5,r13
com r14 eor r5,r14
eor r13,r12
or r13,r14
eor r13,r15
eor r19,r15
or r19,r12
eor r19,r24
com r15 com r15
com r24 and r12,r15
com r25
com r16
and r14,r12
and r15,r19
and r24,r13
and r25,r5
and r16,r23
eor r23,r15
eor r12,r24 eor r12,r24
eor r19,r25 or r23,r24
eor r13,r16 eor r23,r14
eor r5,r14 std Z+30,r23
eor r12,r23 std Z+38,r12
eor r23,r5 std Z+14,r13
eor r13,r19 std Z+22,r5
com r19
std Z+6,r23
std Z+14,r12
std Z+30,r13
std Z+38,r5
ldd r23,Z+5 ldd r23,Z+5
ldd r12,Z+13 ldd r12,Z+13
ldd r13,Z+29 ldd r13,Z+29
eor r23,r6 mov r14,r12
eor r6,r13 mov r15,r23
eor r20,r12 mov r24,r13
mov r14,r23 eor r14,r20
mov r15,r12 eor r15,r6
mov r24,r20 eor r24,r6
mov r25,r13 com r6
mov r16,r6 or r6,r13
com r14 eor r6,r14
eor r13,r12
or r13,r14
eor r13,r15
eor r20,r15
or r20,r12
eor r20,r24
com r15 com r15
com r24 and r12,r15
com r25
com r16
and r14,r12
and r15,r20
and r24,r13
and r25,r6
and r16,r23
eor r23,r15
eor r12,r24 eor r12,r24
eor r20,r25 or r23,r24
eor r13,r16 eor r23,r14
eor r6,r14 std Z+29,r23
eor r12,r23 std Z+37,r12
eor r23,r6 std Z+13,r13
eor r13,r20 std Z+21,r6
com r20
std Z+5,r23
std Z+13,r12
std Z+29,r13
std Z+37,r6
ldd r23,Z+4 ldd r23,Z+4
ldd r12,Z+12 ldd r12,Z+12
ldd r13,Z+28 ldd r13,Z+28
eor r23,r7 mov r14,r12
eor r7,r13 mov r15,r23
eor r21,r12 mov r24,r13
mov r14,r23 eor r14,r21
mov r15,r12 eor r15,r7
mov r24,r21 eor r24,r7
mov r25,r13 com r7
mov r16,r7 or r7,r13
com r14 eor r7,r14
eor r13,r12
or r13,r14
eor r13,r15
eor r21,r15
or r21,r12
eor r21,r24
com r15 com r15
com r24 and r12,r15
com r25
com r16
and r14,r12
and r15,r21
and r24,r13
and r25,r7
and r16,r23
eor r23,r15
eor r12,r24 eor r12,r24
eor r21,r25 or r23,r24
eor r13,r16 eor r23,r14
eor r7,r14 std Z+28,r23
eor r12,r23 std Z+36,r12
eor r23,r7 std Z+12,r13
eor r13,r21 std Z+20,r7
com r21
std Z+4,r23
std Z+12,r12
std Z+28,r13
std Z+36,r7
ldd r23,Z+3 ldd r23,Z+3
ldd r12,Z+11 ldd r12,Z+11
ldd r13,Z+27 ldd r13,Z+27
eor r23,r8 mov r14,r12
eor r8,r13 mov r15,r23
eor r26,r12 mov r24,r13
mov r14,r23 eor r14,r26
mov r15,r12 eor r15,r8
mov r24,r26 eor r24,r8
mov r25,r13 com r8
mov r16,r8 or r8,r13
com r14 eor r8,r14
eor r13,r12
or r13,r14
eor r13,r15
eor r26,r15
or r26,r12
eor r26,r24
com r15 com r15
com r24 and r12,r15
com r25
com r16
and r14,r12
and r15,r26
and r24,r13
and r25,r8
and r16,r23
eor r23,r15
eor r12,r24 eor r12,r24
eor r26,r25 or r23,r24
eor r13,r16 eor r23,r14
eor r8,r14 std Z+27,r23
eor r12,r23 std Z+35,r12
eor r23,r8 std Z+11,r13
eor r13,r26 std Z+19,r8
com r26
std Z+3,r23
std Z+11,r12
std Z+27,r13
std Z+35,r8
ldd r23,Z+2 ldd r23,Z+2
ldd r12,Z+10 ldd r12,Z+10
ldd r13,Z+26 ldd r13,Z+26
eor r23,r9 mov r14,r12
eor r9,r13 mov r15,r23
eor r27,r12 mov r24,r13
mov r14,r23 eor r14,r27
mov r15,r12 eor r15,r9
mov r24,r27 eor r24,r9
mov r25,r13 com r9
mov r16,r9 or r9,r13
com r14 eor r9,r14
eor r13,r12
or r13,r14
eor r13,r15
eor r27,r15
or r27,r12
eor r27,r24
com r15 com r15
com r24 and r12,r15
com r25
com r16
and r14,r12
and r15,r27
and r24,r13
and r25,r9
and r16,r23
eor r23,r15
eor r12,r24 eor r12,r24
eor r27,r25 or r23,r24
eor r13,r16 eor r23,r14
eor r9,r14 std Z+26,r23
eor r12,r23 std Z+34,r12
eor r23,r9 std Z+10,r13
eor r13,r27 std Z+18,r9
com r27
std Z+2,r23
std Z+10,r12
std Z+26,r13
std Z+34,r9
ldd r23,Z+1 ldd r23,Z+1
ldd r12,Z+9 ldd r12,Z+9
ldd r13,Z+25 ldd r13,Z+25
eor r23,r10 mov r14,r12
eor r10,r13 mov r15,r23
eor r2,r12 mov r24,r13
mov r14,r23 eor r14,r2
mov r15,r12 eor r15,r10
mov r24,r2 eor r24,r10
mov r25,r13 com r10
mov r16,r10 or r10,r13
com r14 eor r10,r14
eor r13,r12
or r13,r14
eor r13,r15
eor r2,r15
or r2,r12
eor r2,r24
com r15 com r15
com r24 and r12,r15
com r25
com r16
and r14,r12
and r15,r2
and r24,r13
and r25,r10
and r16,r23
eor r23,r15
eor r12,r24 eor r12,r24
eor r2,r25 or r23,r24
eor r13,r16 eor r23,r14
eor r10,r14 std Z+25,r23
eor r12,r23 std Z+33,r12
eor r23,r10 std Z+9,r13
eor r13,r2 std Z+17,r10
com r2
std Z+1,r23
std Z+9,r12
std Z+25,r13
std Z+33,r10
ld r23,Z ld r23,Z
ldd r12,Z+8 ldd r12,Z+8
ldd r13,Z+24 ldd r13,Z+24
eor r23,r11 mov r14,r12
eor r11,r13 mov r15,r23
eor r3,r12 mov r24,r13
mov r14,r23 eor r14,r3
mov r15,r12 eor r15,r11
mov r24,r3 eor r24,r11
mov r25,r13 com r11
mov r16,r11 or r11,r13
com r14 eor r11,r14
eor r13,r12
or r13,r14
eor r13,r15
eor r3,r15
or r3,r12
eor r3,r24
com r15 com r15
com r24 and r12,r15
com r25
com r16
and r14,r12
and r15,r3
and r24,r13
and r25,r11
and r16,r23
eor r23,r15
eor r12,r24 eor r12,r24
eor r3,r25 or r23,r24
eor r13,r16 eor r23,r14
eor r11,r14 std Z+24,r23
eor r12,r23 std Z+32,r12
eor r23,r11 std Z+8,r13
eor r13,r3 std Z+16,r11
com r3 movw r12,r18
st Z,r23 movw r14,r20
std Z+8,r12 movw r24,r26
std Z+24,r13 movw r16,r2
std Z+32,r11
ld r11,Z
ldd r10,Z+1
ldd r9,Z+2
ldd r8,Z+3
ldd r7,Z+4
ldd r6,Z+5
ldd r5,Z+6
ldd r4,Z+7
movw r12,r4
movw r14,r6
movw r24,r8
movw r16,r10
mov r0,r12 mov r0,r12
mov r12,r14 mov r12,r14
mov r14,r24 mov r14,r24
...@@ -369,79 +327,79 @@ ascon_permute: ...@@ -369,79 +327,79 @@ ascon_permute:
ror r12 ror r12
ror r0 ror r0
or r17,r0 or r17,r0
eor r12,r4 eor r12,r18
eor r13,r5 eor r13,r19
eor r14,r6 eor r14,r20
eor r15,r7 eor r15,r21
eor r24,r8 eor r24,r26
eor r25,r9 eor r25,r27
eor r16,r10 eor r16,r2
eor r17,r11 eor r17,r3
mov r23,r4 mov r23,r18
mov r0,r5 mov r0,r19
push r6 push r20
mov r4,r7 mov r18,r21
mov r5,r8 mov r19,r26
mov r6,r9 mov r20,r27
mov r7,r10 mov r21,r2
mov r8,r11 mov r26,r3
pop r11 pop r3
mov r10,r0 mov r2,r0
mov r9,r23 mov r27,r23
mov r0,r1 mov r0,r1
lsr r11 lsr r3
ror r10 ror r2
ror r9 ror r27
ror r8 ror r26
ror r7 ror r21
ror r6 ror r20
ror r5 ror r19
ror r4 ror r18
ror r0 ror r0
lsr r11 lsr r3
ror r10 ror r2
ror r9 ror r27
ror r8 ror r26
ror r7 ror r21
ror r6 ror r20
ror r5 ror r19
ror r4 ror r18
ror r0 ror r0
lsr r11 lsr r3
ror r10 ror r2
ror r9 ror r27
ror r8 ror r26
ror r7 ror r21
ror r6 ror r20
ror r5 ror r19
ror r4 ror r18
ror r0 ror r0
lsr r11 lsr r3
ror r10 ror r2
ror r9 ror r27
ror r8 ror r26
ror r7 ror r21
ror r6 ror r20
ror r5 ror r19
ror r4 ror r18
ror r0 ror r0
or r11,r0 or r3,r0
eor r4,r12 eor r18,r12
eor r5,r13 eor r19,r13
eor r6,r14 eor r20,r14
eor r7,r15 eor r21,r15
eor r8,r24 eor r26,r24
eor r9,r25 eor r27,r25
eor r10,r16 eor r2,r16
eor r11,r17 eor r3,r17
st Z,r11 st Z,r3
std Z+1,r10 std Z+1,r2
std Z+2,r9 std Z+2,r27
std Z+3,r8 std Z+3,r26
std Z+4,r7 std Z+4,r21
std Z+5,r6 std Z+5,r20
std Z+6,r5 std Z+6,r19
std Z+7,r4 std Z+7,r18
ldd r11,Z+8 ldd r11,Z+8
ldd r10,Z+9 ldd r10,Z+9
ldd r9,Z+10 ldd r9,Z+10
...@@ -525,6 +483,14 @@ ascon_permute: ...@@ -525,6 +483,14 @@ ascon_permute:
std Z+13,r6 std Z+13,r6
std Z+14,r5 std Z+14,r5
std Z+15,r4 std Z+15,r4
ldd r3,Z+16
ldd r2,Z+17
ldd r27,Z+18
ldd r26,Z+19
ldd r21,Z+20
ldd r20,Z+21
ldd r19,Z+22
ldd r18,Z+23
movw r12,r18 movw r12,r18
movw r14,r20 movw r14,r20
movw r24,r26 movw r24,r26
......
/* /*
* Copyright (C) 2020 Southern Storm Software, Pty Ltd. * Copyright (C) 2021 Southern Storm Software, Pty Ltd.
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * copy of this software and associated documentation files (the "Software"),
...@@ -22,7 +22,19 @@ ...@@ -22,7 +22,19 @@
#include "internal-ascon.h" #include "internal-ascon.h"
#if !defined(__AVR__) /* Determine which versions should be accelerated with assembly code */
#if defined(__AVR__)
#define ASCON_ASM_REGULAR 1
#define ASCON_ASM_SLICED 0
#elif defined(__ARM_ARCH_ISA_THUMB) && __ARM_ARCH == 7
#define ASCON_ASM_REGULAR 1
#define ASCON_ASM_SLICED 1
#else
#define ASCON_ASM_REGULAR 0
#define ASCON_ASM_SLICED 0
#endif
#if !ASCON_ASM_REGULAR
void ascon_permute(ascon_state_t *state, uint8_t first_round) void ascon_permute(ascon_state_t *state, uint8_t first_round)
{ {
...@@ -77,4 +89,120 @@ void ascon_permute(ascon_state_t *state, uint8_t first_round) ...@@ -77,4 +89,120 @@ void ascon_permute(ascon_state_t *state, uint8_t first_round)
#endif #endif
} }
#endif /* !__AVR__ */ #endif /* !ASCON_ASM_REGULAR */
#if ASCON_SLICED && !ASCON_ASM_SLICED
void ascon_to_sliced(ascon_state_t *state)
{
int index;
uint32_t high, low;
for (index = 0; index < 10; index += 2) {
high = be_load_word32(state->B + index * 4);
low = be_load_word32(state->B + index * 4 + 4);
ascon_separate(high);
ascon_separate(low);
state->W[index] = (high << 16) | (low & 0x0000FFFFU);
state->W[index + 1] = (high & 0xFFFF0000U) | (low >> 16);
}
}
void ascon_from_sliced(ascon_state_t *state)
{
int index;
uint32_t high, low;
for (index = 0; index < 10; index += 2) {
high = (state->W[index] >> 16) | (state->W[index + 1] & 0xFFFF0000U);
low = (state->W[index] & 0x0000FFFFU) | (state->W[index + 1] << 16);
ascon_combine(high);
ascon_combine(low);
be_store_word32(state->B + index * 4, high);
be_store_word32(state->B + index * 4 + 4, low);
}
}
void ascon_permute_sliced(ascon_state_t *state, uint8_t first_round)
{
static const unsigned char RC[12 * 2] = {
12, 12, 9, 12, 12, 9, 9, 9, 6, 12, 3, 12,
6, 9, 3, 9, 12, 6, 9, 6, 12, 3, 9, 3
};
const unsigned char *rc = RC + first_round * 2;
uint32_t t0, t1, t2, t3, t4;
/* Load the state into local variables */
uint32_t x0_e = state->W[0];
uint32_t x0_o = state->W[1];
uint32_t x1_e = state->W[2];
uint32_t x1_o = state->W[3];
uint32_t x2_e = state->W[4];
uint32_t x2_o = state->W[5];
uint32_t x3_e = state->W[6];
uint32_t x3_o = state->W[7];
uint32_t x4_e = state->W[8];
uint32_t x4_o = state->W[9];
/* Perform all permutation rounds */
while (first_round < 12) {
/* Add the round constants for this round to the state */
x2_e ^= rc[0];
x2_o ^= rc[1];
rc += 2;
/* Substitution layer */
#define ascon_sbox(x0, x1, x2, x3, x4) \
do { \
x0 ^= x4; x4 ^= x3; x2 ^= x1; \
t0 = ~x0; t1 = ~x1; t2 = ~x2; t3 = ~x3; t4 = ~x4; \
t0 &= x1; t1 &= x2; t2 &= x3; t3 &= x4; t4 &= x0; \
x0 ^= t1; x1 ^= t2; x2 ^= t3; x3 ^= t4; x4 ^= t0; \
x1 ^= x0; x0 ^= x4; x3 ^= x2; x2 = ~x2; \
} while (0)
ascon_sbox(x0_e, x1_e, x2_e, x3_e, x4_e);
ascon_sbox(x0_o, x1_o, x2_o, x3_o, x4_o);
/* Linear diffusion layer */
/* x0 ^= rightRotate19_64(x0) ^ rightRotate28_64(x0); */
t0 = x0_e ^ rightRotate4(x0_o);
t1 = x0_o ^ rightRotate5(x0_e);
x0_e ^= rightRotate9(t1);
x0_o ^= rightRotate10(t0);
/* x1 ^= rightRotate61_64(x1) ^ rightRotate39_64(x1); */
t0 = x1_e ^ rightRotate11(x1_e);
t1 = x1_o ^ rightRotate11(x1_o);
x1_e ^= rightRotate19(t1);
x1_o ^= rightRotate20(t0);
/* x2 ^= rightRotate1_64(x2) ^ rightRotate6_64(x2); */
t0 = x2_e ^ rightRotate2(x2_o);
t1 = x2_o ^ rightRotate3(x2_e);
x2_e ^= t1;
x2_o ^= rightRotate1(t0);
/* x3 ^= rightRotate10_64(x3) ^ rightRotate17_64(x3); */
t0 = x3_e ^ rightRotate3(x3_o);
t1 = x3_o ^ rightRotate4(x3_e);
x3_e ^= rightRotate5(t0);
x3_o ^= rightRotate5(t1);
/* x4 ^= rightRotate7_64(x4) ^ rightRotate41_64(x4); */
t0 = x4_e ^ rightRotate17(x4_e);
t1 = x4_o ^ rightRotate17(x4_o);
x4_e ^= rightRotate3(t1);
x4_o ^= rightRotate4(t0);
/* Move onto the next round */
++first_round;
}
/* Write the local variables back to the state */
state->W[0] = x0_e;
state->W[1] = x0_o;
state->W[2] = x1_e;
state->W[3] = x1_o;
state->W[4] = x2_e;
state->W[5] = x2_o;
state->W[6] = x3_e;
state->W[7] = x3_o;
state->W[8] = x4_e;
state->W[9] = x4_o;
}
#endif /* ASCON_SLICED */
/* /*
* Copyright (C) 2020 Southern Storm Software, Pty Ltd. * Copyright (C) 2021 Southern Storm Software, Pty Ltd.
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * copy of this software and associated documentation files (the "Software"),
...@@ -38,11 +38,36 @@ extern "C" { ...@@ -38,11 +38,36 @@ extern "C" {
#endif #endif
/** /**
* \brief Defined to 1 if the 32-bit sliced version of ASCON is preferred.
*/
#if !defined(__AVR__) && !defined(LW_UTIL_CPU_IS_64BIT)
#define ASCON_SLICED 1
#else
#define ASCON_SLICED 0
#endif
/**
* \brief Initialization vector for ASCON-128.
*/
#define ASCON128_IV 0x80400c0600000000ULL
/**
* \brief Initialization vector for ASCON-128a.
*/
#define ASCON128a_IV 0x80800c0800000000ULL
/**
* \brief Initialization vector for ASCON-80pq.
*/
#define ASCON80PQ_IV 0xa0400c06U
/**
* \brief Structure of the internal state of the ASCON permutation. * \brief Structure of the internal state of the ASCON permutation.
*/ */
typedef union typedef union
{ {
uint64_t S[5]; /**< Words of the state */ uint64_t S[5]; /**< 64-bit words of the state */
uint32_t W[10]; /**< 32-bit words of the state */
uint8_t B[40]; /**< Bytes of the state */ uint8_t B[40]; /**< Bytes of the state */
} ascon_state_t; } ascon_state_t;
...@@ -57,6 +82,237 @@ typedef union ...@@ -57,6 +82,237 @@ typedef union
*/ */
void ascon_permute(ascon_state_t *state, uint8_t first_round); void ascon_permute(ascon_state_t *state, uint8_t first_round);
#if ASCON_SLICED
/**
* \brief Converts an ASCON state from byte form into sliced form.
*
* \param state The ASCON state to be converted, in big-endian byte order
* on entry and in host byte order on exit.
*/
void ascon_to_sliced(ascon_state_t *state);
/**
* \brief Converts an ASCON state from sliced form into byte form.
*
* \param state The ASCON state to be converted, in host byte order
* on entry and in big-endian byte order on exit.
*/
void ascon_from_sliced(ascon_state_t *state);
/**
* \brief Permutes the ASCON state in sliced form.
*
* \param state The ASCON state to be permuted.
* \param first_round The first round (of 12) to be performed; 0, 4, or 6.
*
* The input and output \a state will be in host byte order.
*/
void ascon_permute_sliced(ascon_state_t *state, uint8_t first_round);
/** @cond ascon_bit_separation */
/* http://programming.sirrida.de/perm_fn.html#bit_permute_step */
#define ascon_bit_permute_step(_y, mask, shift) \
do { \
uint32_t y = (_y); \
uint32_t t = ((y >> (shift)) ^ y) & (mask); \
(_y) = (y ^ t) ^ (t << (shift)); \
} while (0)
/* Separates a 32-bit word into two 16-bit halves with all the even
* bits in the bottom half and all the odd bits in the top half.
*
* Permutation generated with "http://programming.sirrida.de/calcperm.php"
*
* P = [0 16 1 17 2 18 3 19 4 20 5 21 6 22 7 23 8 24
* 9 25 10 26 11 27 12 28 13 29 14 30 15 31]
*/
#define ascon_separate(x) \
do { \
ascon_bit_permute_step((x), 0x22222222, 1); \
ascon_bit_permute_step((x), 0x0c0c0c0c, 2); \
ascon_bit_permute_step((x), 0x00f000f0, 4); \
ascon_bit_permute_step((x), 0x0000ff00, 8); \
} while (0)
#define ascon_combine(x) \
do { \
ascon_bit_permute_step((x), 0x0000aaaa, 15); \
ascon_bit_permute_step((x), 0x0000cccc, 14); \
ascon_bit_permute_step((x), 0x0000f0f0, 12); \
ascon_bit_permute_step((x), 0x0000ff00, 8); \
} while (0)
/** @endcond */
/**
* \brief Sets data into the ASCON state in sliced form.
*
* \param state The ASCON state for the data to be absorbed into.
* \param data Points to 8 bytes of data in big-endian byte order to set.
* \param offset Offset of the 64-bit word within the state to set at,
* between 0 and 4.
*/
#define ascon_set_sliced(state, data, offset) \
do { \
ascon_state_t *s = (state); \
uint32_t high = be_load_word32((data)); \
uint32_t low = be_load_word32((data) + 4); \
ascon_separate(high); \
ascon_separate(low); \
s->W[(offset) * 2] = (high << 16) | (low & 0x0000FFFFU); \
s->W[(offset) * 2 + 1] = (high & 0xFFFF0000U) | (low >> 16); \
} while (0)
/**
* \brief Absorbs data into the ASCON state in sliced form.
*
* \param state The ASCON state for the data to be absorbed into.
* \param data Points to 8 bytes of data in big-endian byte order to absorb.
* \param offset Offset of the 64-bit word within the state to absorb at,
* between 0 and 4.
*/
#define ascon_absorb_sliced(state, data, offset) \
do { \
ascon_state_t *s = (state); \
uint32_t high = be_load_word32((data)); \
uint32_t low = be_load_word32((data) + 4); \
ascon_separate(high); \
ascon_separate(low); \
s->W[(offset) * 2] ^= (high << 16) | (low & 0x0000FFFFU); \
s->W[(offset) * 2 + 1] ^= (high & 0xFFFF0000U) | (low >> 16); \
} while (0)
/**
* \brief Absorbs 32 bits of data into the ASCON state in sliced form.
*
* \param state The ASCON state for the data to be absorbed into.
* \param data Points to 4 bytes of data in big-endian byte order to absorb.
* \param offset Offset of the 64-bit word within the state to absorb at,
* between 0 and 4.
*
* The data is absorbed into the low bits of the 64-bit word at \a offset.
*/
#define ascon_absorb32_low_sliced(state, data, offset) \
do { \
ascon_state_t *s = (state); \
uint32_t low = be_load_word32((data)); \
ascon_separate(low); \
s->W[(offset) * 2] ^= (low & 0x0000FFFFU); \
s->W[(offset) * 2 + 1] ^= (low >> 16); \
} while (0)
/**
* \brief Absorbs 32 bits of data into the ASCON state in sliced form.
*
* \param state The ASCON state for the data to be absorbed into.
* \param data Points to 4 bytes of data in big-endian byte order to absorb.
* \param offset Offset of the 64-bit word within the state to absorb at,
* between 0 and 4.
*
* The data is absorbed into the high bits of the 64-bit word at \a offset.
*/
#define ascon_absorb32_high_sliced(state, data, offset) \
do { \
ascon_state_t *s = (state); \
uint32_t high = be_load_word32((data)); \
ascon_separate(high); \
s->W[(offset) * 2] ^= (high << 16); \
s->W[(offset) * 2 + 1] ^= (high & 0xFFFF0000U); \
} while (0)
/**
* \brief Squeezes data from the ASCON state in sliced form.
*
* \param state The ASCON state to extract the data from.
* \param data Points to the 8 bytes to be extracted from the state.
* \param offset Offset of the 64-bit word within the state to extract,
* between 0 and 4.
*/
#define ascon_squeeze_sliced(state, data, offset) \
do { \
ascon_state_t *s = (state); \
uint32_t high, low; \
high = (s->W[(offset) * 2] >> 16) | \
(s->W[(offset) * 2 + 1] & 0xFFFF0000U); \
low = (s->W[(offset) * 2] & 0x0000FFFFU) | \
(s->W[(offset) * 2 + 1] << 16); \
ascon_combine(high); \
ascon_combine(low); \
be_store_word32((data), high); \
be_store_word32((data) + 4, low); \
} while (0)
/**
* \brief Encrypts data using the ASCON state in sliced form.
*
* \param state The ASCON state.
* \param c Points to 8 bytes of output ciphertext in big-endian byte order.
* \param m Points to 8 bytes of input plaintext in big-endian byte order.
* \param offset Offset of the 64-bit word within the state to absorb
* and squeeze at, between 0 and 4.
*/
#define ascon_encrypt_sliced(state, c, m, offset) \
do { \
ascon_state_t *s = (state); \
uint32_t high = be_load_word32((m)); \
uint32_t low = be_load_word32((m) + 4); \
ascon_separate(high); \
ascon_separate(low); \
s->W[(offset) * 2] ^= (high << 16) | (low & 0x0000FFFFU); \
s->W[(offset) * 2 + 1] ^= (high & 0xFFFF0000U) | (low >> 16); \
high = (s->W[(offset) * 2] >> 16) | \
(s->W[(offset) * 2 + 1] & 0xFFFF0000U); \
low = (s->W[(offset) * 2] & 0x0000FFFFU) | \
(s->W[(offset) * 2 + 1] << 16); \
ascon_combine(high); \
ascon_combine(low); \
be_store_word32((c), high); \
be_store_word32((c) + 4, low); \
} while (0)
/**
* \brief Decrypts data using the ASCON state in sliced form.
*
* \param state The ASCON state.
* \param m Points to 8 bytes of output plaintext in big-endian byte order.
* \param c Points to 8 bytes of input ciphertext in big-endian byte order.
* \param offset Offset of the 64-bit word within the state to absorb
* and squeeze at, between 0 and 4.
*/
#define ascon_decrypt_sliced(state, m, c, offset) \
do { \
ascon_state_t *s = (state); \
uint32_t high, low, high2, low2; \
high = be_load_word32((c)); \
low = be_load_word32((c) + 4); \
ascon_separate(high); \
ascon_separate(low); \
high2 = high ^ ((s->W[(offset) * 2] >> 16) | \
(s->W[(offset) * 2 + 1] & 0xFFFF0000U)); \
low2 = low ^ ((s->W[(offset) * 2] & 0x0000FFFFU) | \
(s->W[(offset) * 2 + 1] << 16)); \
s->W[(offset) * 2] = (high << 16) | (low & 0x0000FFFFU); \
s->W[(offset) * 2 + 1] = (high & 0xFFFF0000U) | (low >> 16); \
ascon_combine(high2); \
ascon_combine(low2); \
be_store_word32((m), high2); \
be_store_word32((m) + 4, low2); \
} while (0)
#endif /* ASCON_SLICED */
/**
* \def ascon_separator()
* \brief Absorbs the standard ASCON separator for switching between
* associated data and message payload.
*/
#if ASCON_SLICED
#define ascon_separator() (state.W[8] ^= 0x01)
#else
#define ascon_separator() (state.B[39] ^= 0x01)
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
......
/*
* Copyright (C) 2021 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 "internal-util.h"
int aead_check_tag
(unsigned char *plaintext, size_t plaintext_len,
const unsigned char *tag1, const unsigned char *tag2, size_t 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;
}
void aead_clean(void *buf, unsigned size)
{
/* Force the use of volatile so that we actually clear the memory.
* Otherwise the compiler might optimise the entire contents of this
* function away, which will not be secure.
*
* Even this may not work. Some platforms have bzero_explicit() or
* memset_s() that could be used in place of this implementation. */
volatile uint8_t *d = (volatile uint8_t *)buf;
while (size > 0) {
*d++ = 0;
--size;
}
}
/* /*
* Copyright (C) 2020 Southern Storm Software, Pty Ltd. * Copyright (C) 2021 Southern Storm Software, Pty Ltd.
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * copy of this software and associated documentation files (the "Software"),
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#ifndef LW_INTERNAL_UTIL_H #ifndef LW_INTERNAL_UTIL_H
#define LW_INTERNAL_UTIL_H #define LW_INTERNAL_UTIL_H
#include <stddef.h>
#include <stdint.h> #include <stdint.h>
/* Figure out how to inline functions using this C compiler */ /* Figure out how to inline functions using this C compiler */
...@@ -53,6 +54,13 @@ ...@@ -53,6 +54,13 @@
#error "Cannot determine the endianess of this platform" #error "Cannot determine the endianess of this platform"
#endif #endif
/* Determine if we are compiling for a 64-bit CPU */
#if defined(__x86_64) || defined(__x86_64__) || \
defined(__aarch64__) || defined(__ARM_ARCH_ISA_A64) || \
defined(_M_AMD64) || defined(_M_X64) || defined(_M_IA64)
#define LW_UTIL_CPU_IS_64BIT 1
#endif
/* Helper macros to load and store values while converting endian-ness */ /* Helper macros to load and store values while converting endian-ness */
/* Load a big-endian 32-bit word from a byte buffer */ /* Load a big-endian 32-bit word from a byte buffer */
...@@ -89,6 +97,11 @@ ...@@ -89,6 +97,11 @@
(ptr)[3] = (uint8_t)(_x >> 24); \ (ptr)[3] = (uint8_t)(_x >> 24); \
} while (0) } while (0)
/* Reverses the bytes in a 32-bit word */
#define reverse_word32(x) \
(((x) >> 24) | (((x) >> 8) & 0x0000FF00U) | \
(((x) << 8) & 0x00FF0000U) | ((x) << 24))
/* Load a big-endian 64-bit word from a byte buffer */ /* Load a big-endian 64-bit word from a byte buffer */
#define be_load_word64(ptr) \ #define be_load_word64(ptr) \
((((uint64_t)((ptr)[0])) << 56) | \ ((((uint64_t)((ptr)[0])) << 56) | \
...@@ -699,4 +712,52 @@ ...@@ -699,4 +712,52 @@
#define rightRotate6_8(a) (rightRotate_8((a), 6)) #define rightRotate6_8(a) (rightRotate_8((a), 6))
#define rightRotate7_8(a) (rightRotate_8((a), 7)) #define rightRotate7_8(a) (rightRotate_8((a), 7))
/**
* \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 size 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, size_t plaintext_len,
const unsigned char *tag1, const unsigned char *tag2, size_t size);
/**
* \brief Attempts to cleans a buffer that contains sensitive material.
*
* \param buf Points to the buffer to clear.
* \param size Size of the buffer to clear in bytes.
*/
void aead_clean(void *buf, unsigned size);
/**
* \brief Number of bytes to retrieve from the system TRNG each time
* we need to reseed application-level PRNG's.
*/
#define AEAD_SYSTEM_SEED_SIZE 32
/**
* \brief Gets data from the system TRNG to reseed application-level PRNG's.
*
* \param seed Points to the buffer to be populated with the system seed.
*
* \return Non-zero if \a seed has been filled with TRNG data or zero
* if there is no accessible TRNG on this system.
*
* The quality of the returned seed data may be very poor or may not
* distribute the entropy evenly throughout the returned \a seed buffer.
* The application should use a PRNG to hash the seed data into a more
* useful random sequence.
*/
int aead_random_get_system_seed(unsigned char seed[AEAD_SYSTEM_SEED_SIZE]);
#endif #endif
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
#define CRYPTO_KEYBYTES 16
#define CRYPTO_NSECBYTES 0
#define CRYPTO_NPUBBYTES 16
#define CRYPTO_ABYTES 16
#define CRYPTO_NOOVERLAP 1
#define CRYPTO_BYTES 32
/*
* Copyright (C) 2021 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_ASCON_AEAD_H
#define LWCRYPTO_ASCON_AEAD_H
#include <stddef.h>
/**
* \file ascon-aead.h
* \brief ASCON-128 encryption algorithm and related family members.
*
* The ASCON family consists of several related algorithms:
*
* \li ASCON-128 with a 128-bit key, a 128-bit nonce, a 128-bit authentication
* tag, and a block rate of 64 bits.
* \li ASCON-128a with a 128-bit key, a 128-bit nonce, a 128-bit authentication
* tag, and a block rate of 128 bits. This is faster than ASCON-128 but may
* not be as secure.
* \li ASCON-80pq with a 160-bit key, a 128-bit nonce, a 128-bit authentication
* tag, and a block rate of 64 bits. This is similar to ASCON-128 but has a
* 160-bit key instead which may be more resistant against quantum computers.
* \li ASCON-HASH and ASCON-HASHA with a 256-bit hash output.
* \li ASCON-XOF and ASCON-XOFA with extensible hash output (XOF mode).
*
* References: https://ascon.iaik.tugraz.at/
*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Size of the key for ASCON-128 and ASCON-128a.
*/
#define ASCON128_KEY_SIZE 16
/**
* \brief Size of the nonce for ASCON-128 and ASCON-128a.
*/
#define ASCON128_NONCE_SIZE 16
/**
* \brief Size of the authentication tag for ASCON-128 and ASCON-128a.
*/
#define ASCON128_TAG_SIZE 16
/**
* \brief Size of the key for ASCON-80pq.
*/
#define ASCON80PQ_KEY_SIZE 20
/**
* \brief Size of the nonce for ASCON-80pq.
*/
#define ASCON80PQ_NONCE_SIZE 16
/**
* \brief Size of the authentication tag for ASCON-80pq.
*/
#define ASCON80PQ_TAG_SIZE 16
/**
* \brief Encrypts and authenticates a packet with ASCON-128.
*
* \param c Buffer to receive the output.
* \param clen On exit, set to the length of the output which includes
* the ciphertext and the 16 byte 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 npub Points to the public nonce for the packet which must
* be 16 bytes in length.
* \param k Points to the 16 bytes of the key to use to encrypt the packet.
*
* \return 0 on success, or a negative value if there was an error in
* the parameters.
*
* \sa ascon128_aead_decrypt()
*/
int ascon128_aead_encrypt
(unsigned char *c, size_t *clen,
const unsigned char *m, size_t mlen,
const unsigned char *ad, size_t adlen,
const unsigned char *npub,
const unsigned char *k);
/**
* \brief Decrypts and authenticates a packet with ASCON-128.
*
* \param m Buffer to receive the plaintext message on output.
* \param mlen Receives the length of the plaintext message on output.
* \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 16 byte 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 which must
* be 16 bytes in length.
* \param k Points to the 16 bytes of 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.
*
* \sa ascon128_aead_encrypt()
*/
int ascon128_aead_decrypt
(unsigned char *m, size_t *mlen,
const unsigned char *c, size_t clen,
const unsigned char *ad, size_t adlen,
const unsigned char *npub,
const unsigned char *k);
/**
* \brief Encrypts and authenticates a packet with ASCON-128a.
*
* \param c Buffer to receive the output.
* \param clen On exit, set to the length of the output which includes
* the ciphertext and the 16 byte 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 npub Points to the public nonce for the packet which must
* be 16 bytes in length.
* \param k Points to the 16 bytes of the key to use to encrypt the packet.
*
* \return 0 on success, or a negative value if there was an error in
* the parameters.
*
* \sa ascon128a_aead_decrypt()
*/
int ascon128a_aead_encrypt
(unsigned char *c, size_t *clen,
const unsigned char *m, size_t mlen,
const unsigned char *ad, size_t adlen,
const unsigned char *npub,
const unsigned char *k);
/**
* \brief Decrypts and authenticates a packet with ASCON-128a.
*
* \param m Buffer to receive the plaintext message on output.
* \param mlen Receives the length of the plaintext message on output.
* \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 16 byte 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 which must
* be 16 bytes in length.
* \param k Points to the 16 bytes of 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.
*
* \sa ascon128a_aead_encrypt()
*/
int ascon128a_aead_decrypt
(unsigned char *m, size_t *mlen,
const unsigned char *c, size_t clen,
const unsigned char *ad, size_t adlen,
const unsigned char *npub,
const unsigned char *k);
/**
* \brief Encrypts and authenticates a packet with ASCON-80pq.
*
* \param c Buffer to receive the output.
* \param clen On exit, set to the length of the output which includes
* the ciphertext and the 16 byte 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 npub Points to the public nonce for the packet which must
* be 16 bytes in length.
* \param k Points to the 20 bytes of the key to use to encrypt the packet.
*
* \return 0 on success, or a negative value if there was an error in
* the parameters.
*
* \sa ascon80pq_aead_decrypt()
*/
int ascon80pq_aead_encrypt
(unsigned char *c, size_t *clen,
const unsigned char *m, size_t mlen,
const unsigned char *ad, size_t adlen,
const unsigned char *npub,
const unsigned char *k);
/**
* \brief Decrypts and authenticates a packet with ASCON-80pq.
*
* \param m Buffer to receive the plaintext message on output.
* \param mlen Receives the length of the plaintext message on output.
* \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 16 byte 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 which must
* be 16 bytes in length.
* \param k Points to the 20 bytes of 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.
*
* \sa ascon80pq_aead_encrypt()
*/
int ascon80pq_aead_decrypt
(unsigned char *m, size_t *mlen,
const unsigned char *c, size_t clen,
const unsigned char *ad, size_t adlen,
const unsigned char *npub,
const unsigned char *k);
#ifdef __cplusplus
}
#endif
#endif
/*
* Copyright (C) 2021 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 "ascon-hash.h"
#include <string.h>
int ascon_hash(unsigned char *out, const unsigned char *in, size_t inlen)
{
ascon_xof_state_t state;
ascon_hash_init(&state);
ascon_xof_absorb(&state, in, inlen);
ascon_xof_squeeze(&state, out, ASCON_HASH_SIZE);
return 0;
}
void ascon_hash_init(ascon_hash_state_t *state)
{
/* IV for ASCON-HASH after processing it with the permutation */
static unsigned char const hash_iv[40] = {
0xee, 0x93, 0x98, 0xaa, 0xdb, 0x67, 0xf0, 0x3d,
0x8b, 0xb2, 0x18, 0x31, 0xc6, 0x0f, 0x10, 0x02,
0xb4, 0x8a, 0x92, 0xdb, 0x98, 0xd5, 0xda, 0x62,
0x43, 0x18, 0x99, 0x21, 0xb8, 0xf8, 0xe3, 0xe8,
0x34, 0x8f, 0xa5, 0xc9, 0xd5, 0x25, 0xe1, 0x40
};
memcpy(state->s.state, hash_iv, sizeof(hash_iv));
state->s.count = 0;
state->s.mode = 0;
}
void ascon_hash_update
(ascon_hash_state_t *state, const unsigned char *in, size_t inlen)
{
ascon_xof_absorb(state, in, inlen);
}
void ascon_hash_finalize(ascon_hash_state_t *state, unsigned char *out)
{
ascon_xof_squeeze(state, out, ASCON_HASH_SIZE);
}
int ascon_hasha(unsigned char *out, const unsigned char *in, size_t inlen)
{
ascon_xof_state_t state;
ascon_hasha_init(&state);
ascon_xofa_absorb(&state, in, inlen);
ascon_xofa_squeeze(&state, out, ASCON_HASH_SIZE);
return 0;
}
void ascon_hasha_init(ascon_hash_state_t *state)
{
/* IV for ASCON-HASHA after processing it with the permutation */
static unsigned char const hash_iv[40] = {
0x01, 0x47, 0x01, 0x94, 0xfc, 0x65, 0x28, 0xa6,
0x73, 0x8e, 0xc3, 0x8a, 0xc0, 0xad, 0xff, 0xa7,
0x2e, 0xc8, 0xe3, 0x29, 0x6c, 0x76, 0x38, 0x4c,
0xd6, 0xf6, 0xa5, 0x4d, 0x7f, 0x52, 0x37, 0x7d,
0xa1, 0x3c, 0x42, 0xa2, 0x23, 0xbe, 0x8d, 0x87
};
memcpy(state->s.state, hash_iv, sizeof(hash_iv));
state->s.count = 0;
state->s.mode = 0;
}
void ascon_hasha_update
(ascon_hash_state_t *state, const unsigned char *in, size_t inlen)
{
ascon_xofa_absorb(state, in, inlen);
}
void ascon_hasha_finalize(ascon_hash_state_t *state, unsigned char *out)
{
ascon_xofa_squeeze(state, out, ASCON_HASH_SIZE);
}
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment