ascon / ascon-c

Ascon - Lightweight Authenticated Encryption & Hashing
https://ascon.iaik.tugraz.at/
Creative Commons Zero v1.0 Universal
189 stars 31 forks source link

Feature request: alternate API interface for tag bytes #12

Closed JordanYates closed 7 months ago

JordanYates commented 7 months ago

Problem Statement

The ECRYPT benchmarking interface is great for some use-cases, but it does restrict the flexibility of ASCON in at least one large way. The requirement that the tag bytes always follow the ciphertext makes the following payload structure difficult to implement without shuffling bytes in memory after the encrypt call and before decrypt.

struct ascon_aead_payload {
    uint8_t associated_data[4];
    uint8_t nonce[16];
    uint8_t tag[16];
    uint8_t ciphertext[];
};

This is preferred over the tag following the ciphertext for a few reasons:

  1. Described by a valid C structure, no additional fields can be added after a variable length array.
  2. For procedural payload generation, it is easier to reserve the header in one go at the start instead of reserving part and needing to remember to subtract 16 from the space remaining everywhere it is checked (Example procedural API).

Proposed Solution

It would be great if the reference library exposed an additional API that took the location of the tag bytes as a pointer (And potentially removed nsec). If implemented, crypto_aead_encrypt could simply call the new API with tag_ptr = c + m_len. For example:

int ascon_aead_encrypt(unsigned char *c, unsigned long long *clen,
                        unsigned char *t,
                        const unsigned char *m, unsigned long long mlen,
                        const unsigned char *ad, unsigned long long adlen,
                        const unsigned char *npub, const unsigned char *k);

static inline 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 rc;
    (void)nsec;
    rc = ascon_aead_encrypt(c, clen, c + mlen, m, m_len, ad, adlen, npub, k);
    if (rc == 0) {
        *clen += 16;
    }
    return rc;
}

As far as I can tell, it is not currently possible to obtain this behaviour with the exposed library primitives. Hopefully I haven't missed a reason why this would be a terrible idea from a security perspective.

Thanks for releasing such a performant reference implementation 😄.

mschlaeffer commented 7 months ago

We are aware of this limitation in the ECRYPT benchmarking API and evaluated some workarounds internally. An additional API is a good idea to support both. Thanks for your suggestion!