Skip to content

Commit

Permalink
v1.0.0
Browse files Browse the repository at this point in the history
* develop:
  Add warning about cleanup to ascon_hash_[xof_]final() too
  Fix missing link to nonce define
  Finish explicitly writing doxygen header for all functions, including hashes
  Finish explicitly writing doxygen header for all aead functions
  Compile cleanup function into 1, start improving doxygen
  Bump version to v1.0.0, add changelog for it
  Fix code inspection warning about int->uint8 type conversion
  Fix zero-length array (albeit unused), minor readme fixes (updated example)
  Check project with static analyser (scan-build)
  Autoformat whole project
  Make all tests pass again after removal of total_length field from ctx
  Fix compilation errors in test suite, now to runtime errors
  Start fixing tests for removed total_length parameter
  Remove total_length parameter, as it's redundant (tests to be updated)
  Fix typos in docs and comments
  Add "ascon_" prefix to all files (mass renaming)
  Add encr/decr tests with updates of increasingly-larger amount bytes
  Add encr/decr tests with updates of 3 bytes
  • Loading branch information
TheMatjaz committed May 21, 2020
2 parents b87a96c + d58a2a6 commit c48eec7
Show file tree
Hide file tree
Showing 28 changed files with 2,244 additions and 924 deletions.
74 changes: 72 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,61 @@ and this project adheres to
*******************************************************************************


[1.0.0] - 2020-05-21
----------------------------------------

First stable version with all ciphers.


### Modified

- **Breaking** change from previous versions: removed `total_output_len`
parameters from the functions
- `ascon_aead*_encrypt()`
- `ascon_aead*_decrypt()`
- `ascon_aead*_encrypt_final()`
- `ascon_aead*_decrypt_final()`
and from the `ascon_bufstate_t` struct, making it 8 B smaller.
Why? TL;DR it's redundant.

The reasoning is that the user of the first two (offline processing)
already knows the length of the plaintext/ciphertext; the user of the second
two obtains the length of the processed chunks as return values so they
can simply sum the up - and anyhow the user known the length of all the
chunks provided to the cipher; those could be summed up to. In most of the
cases the argument was `NULL` in the function usage. For details on how to
obtain the total length, the example in the Readme should suffice.
- Renamed all files in `src` so they start with `ascon_`.


### Fixed

- Added more tests to cover more branching cases of the online-buffering
algorithm.
- Removal of some minor warnings after inspection with static analyser
(`scan-build`) and CLion code inspection tool.
- Typos
- Added missing _Known limitations_ paragraphs to the previous releases
in this Changelog.


### Known limitations

- Because LibAscon is implemented with reuse of existing functions in mind,
in order to spare on code size and with the Init-Update-Digest paradigm,
which has some internal buffering, the cipher is about **4x slower** than the
[reference implementation (`ref`)](https://github.com/ascon/ascon-c).
- There is no architecture-specific optimisation, only a generic portable
implementation using mostly `uint64_t` data types.



[0.4.0] - 2020-05-20
----------------------------------------

Added Ascon80pq cipher, example in Readme.


### Added

- `ascon_aead128a_*` functions, working exactly as the `aead128` versions.
Expand All @@ -34,6 +84,16 @@ Added Ascon80pq cipher, example in Readme.
-` ASCON_COMPILE_HASH`


### Known limitations

- Because LibAscon is implemented with reuse of existing functions in mind,
in order to spare on code size and with the Init-Update-Digest paradigm,
which has some internal buffering, the cipher is about **4x slower** than the
[reference implementation (`ref`)](https://github.com/ascon/ascon-c).
- There is no architecture-specific optimisation, only a generic portable
implementation using mostly `uint64_t` data types.



[0.3.0] - 2020-05-20
----------------------------------------
Expand All @@ -53,6 +113,18 @@ Added Ascon128a cipher and macros to exclude some parts of the library.
-` ASCON_COMPILE_HASH`


### Known limitations

- Because LibAscon is implemented with reuse of existing functions in mind,
in order to spare on code size and with the Init-Update-Digest paradigm,
which has some internal buffering, the cipher is about **4x slower** than the
[reference implementation (`ref`)](https://github.com/ascon/ascon-c).
- There is no architecture-specific optimisation, only a generic portable
implementation using mostly `uint64_t` data types.
- The only AEAD algorithms implemented are Ascon128 and Ascon128a. Ascon80pq is
still to be done.



[0.2.0] - 2020-05-17
----------------------------------------
Expand Down Expand Up @@ -130,6 +202,4 @@ Initial version.
C implementation using mostly `uint64_t` data types.
- The only AEAD algorithm implemented is the Ascon128 AEAD. The Ascon128a and
Ascon80pq are still to be done.
- There is no NULL pointer check for the mandatory function parameters, thus
it will crash on improper usage.

32 changes: 14 additions & 18 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.6)
project(LibAscon
VERSION 0.4.0
VERSION 1.0.0
LANGUAGES C
DESCRIPTION
"Lightweight Authenticated Encryption & Hashing, \
Expand Down Expand Up @@ -45,35 +45,31 @@ set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} \
-O3 -Werror -fomit-frame-pointer -march=native -mtune=native \
-funroll-loops -flto")

# In any case remove unused functions from the linking process
# -fdata-sections -ffunction-sections required as build params
#add_link_options(-Wl,--gc-sections) # TODO this does not work on clang


# -----------------------------------------------------------------------------
# Source files
# -----------------------------------------------------------------------------
set(LIB_SRC_FILES_COMMON
src/internal.h
src/permutations.c
src/buffering.c)
src/ascon_internal.h
src/ascon_permutations.c
src/ascon_buffering.c)
set(LIB_SRC_FILES_128
${LIB_SRC_FILES_COMMON}
src/aead_common.c
src/aead128.c)
src/ascon_aead_common.c
src/ascon_aead128.c)
set(LIB_SRC_FILES_128a
${LIB_SRC_FILES_COMMON}
src/aead_common.c
src/aead128a.c)
src/ascon_aead_common.c
src/ascon_aead128a.c)
set(LIB_SRC_FILES_80pq
${LIB_SRC_FILES_COMMON}
src/aead_common.c
src/aead128.c
src/aead80pq.c
src/ascon_aead_common.c
src/ascon_aead128.c
src/ascon_aead80pq.c
)
set(LIB_SRC_FILES_HASH
${LIB_SRC_FILES_COMMON}
src/hash.c)
src/ascon_hash.c)
set(LIB_SRC_FILES_FULL
${LIB_SRC_FILES_COMMON}
${LIB_SRC_FILES_128}
Expand Down Expand Up @@ -127,7 +123,7 @@ add_library(asconhash STATIC ${LIB_SRC_FILES_HASH})
add_library(ascon SHARED ${LIB_SRC_FILES_FULL})
set_property(TARGET ascon PROPERTY POSITION_INDEPENDENT_CODE ON)

# Test runner executable, reuse the static libary instead of recompiling
# Test runner executable, reuse the static library instead of recompiling
# the source files
add_executable(testascon
$<TARGET_OBJECTS:asconfull>
Expand All @@ -145,7 +141,7 @@ set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES
"${CMAKE_BINARY_DIR}/vectors")

# Benchmark runner executable, reuse the static libary instead of recompiling
# Benchmark runner executable, reuse the static library instead of recompiling
# the source files
add_executable(benchmark
$<TARGET_OBJECTS:asconfull>
Expand Down
145 changes: 74 additions & 71 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
LibAscon - Lightweight Authenticated Encryption & Hashing
================================================================================

LibAscon is an ISO C11 library wrapping the
LibAscon is an ISO C11 cryptographic library wrapping the
[reference C implementation](https://github.com/ascon/ascon-c)
of the Ascon family of lightweight authenticated encryption schemes with
associated data (AEAD) and hashing functions, but it also includes
Expand Down Expand Up @@ -106,83 +106,86 @@ Usage example

```c
// Initialisation
// We need the key and the nonce, both 128 bits.
// Note: Ascon80pq uses longer keys
const uint8_t secret_key[ASCON_AEAD128_KEY_LEN] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6
};
const uint8_t unique_nonce[ASCON_AEAD_NONCE_LEN] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6
};
ascon_aead_ctx_t ctx;
ascon_aead128_init(&ctx, secret_key, unique_nonce);

// Now we feed any associated data into the cipher first
// Our data is fragmented into 2 parts, so we feed one at the time.
const char associated_data_pt1[] = "2 messages will foll";
const char associated_data_pt2[] = "ow, but they are both secret.";
ascon_aead128_assoc_data_update(&ctx, (uint8_t*) associated_data_pt1, strlen
(associated_data_pt1));
ascon_aead128_assoc_data_update(&ctx, (uint8_t*) associated_data_pt2, strlen
(associated_data_pt2));

// Next, we feed the plaintext, which is also fragmented in 2 parts.
const char plaintext_pt1[] = "Hello, I'm a secret mes";
const char plaintext_pt2[] = "sage and I should be encrypted!";
uint8_t buffer[100];
// The ciphertext is generated block-wise, so we need the return value
// to know how to offset the pointer to where the next ciphertext
// part should be written.
size_t ciphertext_len = 0;
ciphertext_len += ascon_aead128_encrypt_update(
&ctx, buffer + ciphertext_len,
(uint8_t*) plaintext_pt1, strlen(plaintext_pt1));
ciphertext_len += ascon_aead128_encrypt_update(
&ctx, buffer + ciphertext_len,
(uint8_t*) plaintext_pt2, strlen(plaintext_pt2));

// Finally, we wrap up the encryption and generate the tag.
// There may still be some trailing ciphertext to be produced.
// The tag length can be specified. ASCON_AEAD_TAG_MIN_SECURE_LEN is
// the minimum recommended (128 b)
uint8_t tag[ASCON_AEAD_TAG_MIN_SECURE_LEN];
ciphertext_len += ascon_aead128_encrypt_final(
&ctx, buffer + ciphertext_len,
NULL, tag, ASCON_AEAD_TAG_MIN_SECURE_LEN);
// Now the buffer contains our ciphertext, long ciphertext_len

// Now we can decrypt
ascon_aead128_init(&ctx, secret_key, unique_nonce);
ascon_aead128_assoc_data_update(&ctx, (uint8_t*) associated_data_pt1,
strlen(associated_data_pt1));
ascon_aead128_assoc_data_update(&ctx, (uint8_t*) associated_data_pt2,
strlen(associated_data_pt2));
// We perform the decryption in-place, in the same buffer where the
// ciphertext it: to do so, we pass the same pointer for plaintext
// and ciphertext
size_t plaintext_len = 0;
plaintext_len += ascon_aead128_decrypt_update(
&ctx, buffer,
buffer, ciphertext_len);
// The final decryption step automatically checks the tag
bool is_tag_valid = false;
plaintext_len += ascon_aead128_decrypt_final(
&ctx, buffer + plaintext_len,
NULL,
&is_tag_valid, tag,
ASCON_AEAD_TAG_MIN_SECURE_LEN);
printf("Tag is valid: %d\n", is_tag_valid); // Yes, it's valid :)
// The macros ASCON_TAG_OK=true and ASCON_TAG_INVALID=false are also
// available if you prefer them over booleans for is_tag_valid.
// We need the key and the nonce, both 128 bits.
// Note: Ascon80pq uses longer keys
const uint8_t secret_key[ASCON_AEAD128_KEY_LEN] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6
};
const uint8_t unique_nonce[ASCON_AEAD_NONCE_LEN] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6
};
ascon_aead_ctx_t ctx;
ascon_aead128_init(&ctx, secret_key, unique_nonce);

// Now we feed any associated data into the cipher first
// Our data is fragmented into 2 parts, so we feed one at the time.
const char associated_data_pt1[] = "2 messages will foll";
const char associated_data_pt2[] = "ow, but they are both secret.";
ascon_aead128_assoc_data_update(&ctx, (uint8_t*) associated_data_pt1, strlen
(associated_data_pt1));
ascon_aead128_assoc_data_update(&ctx, (uint8_t*) associated_data_pt2, strlen
(associated_data_pt2));

// Next, we feed the plaintext, which is also fragmented in 2 parts.
const char plaintext_pt1[] = "Hello, I'm a secret mes";
const char plaintext_pt2[] = "sage and I should be encrypted!";
uint8_t buffer[100];
// The ciphertext is generated block-wise, so we need the return value
// to know how to offset the pointer to where the next ciphertext
// part should be written.
size_t ciphertext_len = 0;
ciphertext_len += ascon_aead128_encrypt_update(
&ctx, buffer + ciphertext_len,
(uint8_t*) plaintext_pt1, strlen(plaintext_pt1));
ciphertext_len += ascon_aead128_encrypt_update(
&ctx, buffer + ciphertext_len,
(uint8_t*) plaintext_pt2, strlen(plaintext_pt2));

// Finally, we wrap up the encryption and generate the tag.
// There may still be some trailing ciphertext to be produced.
// The tag length can be specified. ASCON_AEAD_TAG_MIN_SECURE_LEN is
// the minimum recommended (128 b)
uint8_t tag[ASCON_AEAD_TAG_MIN_SECURE_LEN];
ciphertext_len += ascon_aead128_encrypt_final(
&ctx, buffer + ciphertext_len,
tag, ASCON_AEAD_TAG_MIN_SECURE_LEN);
// Now the buffer contains our ciphertext, long ciphertext_len

// Now we can decrypt
ascon_aead128_init(&ctx, secret_key, unique_nonce);
ascon_aead128_assoc_data_update(&ctx, (uint8_t*) associated_data_pt1,
strlen(associated_data_pt1));
ascon_aead128_assoc_data_update(&ctx, (uint8_t*) associated_data_pt2,
strlen(associated_data_pt2));
// We perform the decryption in-place, in the same buffer where the
// ciphertext it: to do so, we pass the same pointer for plaintext
// and ciphertext
size_t plaintext_len = 0;
plaintext_len += ascon_aead128_decrypt_update(
&ctx, buffer,
buffer, ciphertext_len);
// The final decryption step automatically checks the tag
bool is_tag_valid = false;
plaintext_len += ascon_aead128_decrypt_final(
&ctx, buffer + plaintext_len,
&is_tag_valid, tag, ASCON_AEAD_TAG_MIN_SECURE_LEN);
buffer[plaintext_len] = '\0'; // Null terminated, because it's text
printf("Decrypted msg: %s, tag is valid: %d\n", buffer, is_tag_valid);
// The macros ASCON_TAG_OK=true and ASCON_TAG_INVALID=false are also
// available if you prefer them over booleans for is_tag_valid.
```
For more use-cases, check the test suite.
Known limitations
----------------------------------------
- Because LibAscon is implemented with reuse of existing functions in mind,
in order to spare on code size, the cipher is about 4x slower than the
[reference implementation](https://github.com/ascon/ascon-c).
in order to spare on code size and with the Init-Update-Digest paradigm,
which has some internal buffering, the cipher is about **4x slower** than the
[reference implementation (`ref`)](https://github.com/ascon/ascon-c).
- There is no architecture-specific optimisation, only a generic portable
implementation using mostly `uint64_t` data types.
Expand Down
Loading

0 comments on commit c48eec7

Please sign in to comment.