isap.c 5.18 KB
Newer Older
Robert Primas committed
1
#include <string.h>
2
#include <inttypes.h>
Robert Primas committed
3 4
#include "api.h"
#include "isap.h"
Enrico Pozzobon committed
5
#include "asconp.h"
6 7 8 9 10 11 12 13 14 15 16 17 18
#include "config.h"

forceinline void ABSORB_LANES(state_t *s, const uint8_t *src, uint64_t len)
{
    while (len >= 8)
    {
        // Absorb full lanes
        lane_t t0 = U64TOWORD(*(lane_t *)(src + 0));
        s->x[0] ^= t0.x;
        len -= ISAP_rH / 8;
        src += ISAP_rH / 8;
        P_sH;
    }
Robert Primas committed
19

20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
    if (len > 0)
    {
        // Absorb partial lane and padding
        size_t i;
        lane_t t0 = {0};
        for (i = 0; i < len; i++)
        {
            t0.b[7 - i] ^= *src;
            src++;
        }
        t0.b[7 - i] ^= 0x80;
        t0 = TOBI(t0);
        s->x[0] ^= t0.x;
        P_sH;
    }
    else
    {
        // Absorb padded empty lane
        s->b[0][7] ^= 0x80;
        P_sH;
    }
}
Robert Primas committed
42 43

/******************************************************************************/
44
/*                                 ISAP_RK                                    */
Robert Primas committed
45 46 47
/******************************************************************************/

void isap_rk(
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
    const uint8_t *k,
    const uint8_t *iv,
    const uint8_t *y,
    state_t *out,
    const size_t outlen)
{
    state_t state;
    state_t *s = &state;

    // Initialize
    s->l[0] = U64TOWORD(*(lane_t *)(k + 0));
    s->l[1] = U64TOWORD(*(lane_t *)(k + 8));
    s->l[2] = U64TOWORD(*(lane_t *)(iv + 0));
    s->x[3] = 0;
    s->x[4] = 0;
    P_sK;

    // Absorb Y, bit by bit
    for (size_t i = 0; i < 16; i++)
    {
        uint8_t y_byte = *y;
        s->b[0][7] ^= (y_byte & 0x80) << 0;
        P_sB;
        s->b[0][7] ^= (y_byte & 0x40) << 1;
        P_sB;
        s->b[0][7] ^= (y_byte & 0x20) << 2;
        P_sB;
        s->b[0][7] ^= (y_byte & 0x10) << 3;
        P_sB;
        s->b[0][7] ^= (y_byte & 0x08) << 4;
        P_sB;
        s->b[0][7] ^= (y_byte & 0x04) << 5;
        P_sB;
        s->b[0][7] ^= (y_byte & 0x02) << 6;
        P_sB;
        s->b[0][7] ^= (y_byte & 0x01) << 7;
        if (i != 15)
        {
            P_sB;
            y += 1;
        }
Robert Primas committed
89
    }
90 91 92 93 94 95 96 97

    // Squeeze K*
    P_sK;
    out->x[0] = s->x[0];
    out->x[1] = s->x[1];
    if (outlen > 16)
    {
        out->x[2] = s->x[2];
Robert Primas committed
98 99 100 101
    }
}

/******************************************************************************/
102
/*                                 ISAP_MAC                                   */
Robert Primas committed
103 104 105
/******************************************************************************/

void isap_mac(
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
    const uint8_t *k,
    const uint8_t *npub,
    const uint8_t *ad, uint64_t adlen,
    const uint8_t *c, uint64_t clen,
    uint8_t *tag)
{
    state_t state;
    state_t *s = &state;

    // Initialize
    s->l[0] = U64TOWORD(*(lane_t *)(npub + 0));
    s->l[1] = U64TOWORD(*(lane_t *)(npub + 8));
    s->l[2] = U64TOWORD(*(lane_t *)(ISAP_IV_A + 0));
    s->x[3] = 0;
    s->x[4] = 0;
    P_sH;

    // Absorb associated data
    ABSORB_LANES(s, ad, adlen);
Robert Primas committed
125 126

    // Domain seperation
127
    s->w[4][0] ^= 0x1UL;
Enrico Pozzobon committed
128

129 130 131 132 133 134 135
    // Absorb ciphertext
    ABSORB_LANES(s, c, clen);

    // Derive KA*
    s->l[0] = WORDTOU64(s->l[0]);
    s->l[1] = WORDTOU64(s->l[1]);
    isap_rk(k, ISAP_IV_KA, (const uint8_t *)(s->b), s, CRYPTO_KEYBYTES);
Robert Primas committed
136 137

    // Squeeze tag
138 139 140 141 142
    P_sH;
    lane_t t0 = WORDTOU64(s->l[0]);
    memcpy(tag + 0, t0.b, 8);
    t0 = WORDTOU64(s->l[1]);
    memcpy(tag + 8, t0.b, 8);
Robert Primas committed
143 144 145
}

/******************************************************************************/
146
/*                                 ISAP_ENC                                   */
Robert Primas committed
147 148 149
/******************************************************************************/

void isap_enc(
150 151 152 153 154 155 156 157
    const uint8_t *k,
    const uint8_t *npub,
    const uint8_t *m, uint64_t mlen,
    uint8_t *c)

{
    state_t state;
    state_t *s = &state;
Robert Primas committed
158 159

    // Init state
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
    isap_rk(k, ISAP_IV_KE, npub, s, ISAP_STATE_SZ - CRYPTO_NPUBBYTES);
    s->l[3] = U64TOWORD(*(lane_t *)(npub + 0));
    s->l[4] = U64TOWORD(*(lane_t *)(npub + 8));

    while (mlen >= ISAP_rH / 8)
    {
        // Encrypt full lanes
        P_sE;
        lane_t t0 = WORDTOU64(s->l[0]);
        *(uint64_t *)c = *(uint64_t *)m ^ t0.x;
        mlen -= ISAP_rH / 8;
        m += ISAP_rH / 8;
        c += ISAP_rH / 8;
    }

    if (mlen > 0)
    {
        // Encrypt partial lanes
        P_sE;
        lane_t t0 = WORDTOU64(s->l[0]);
        for (uint8_t i = 0; i < mlen; i++)
        {
            *c = *m ^ t0.b[i];
            m += 1;
            c += 1;
        }
Enrico Pozzobon committed
186
    }
187 188 189 190 191
}

/******************************************************************************/
/*                                Ascon-Hash                                  */
/******************************************************************************/
Enrico Pozzobon committed
192

193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
#if ENABLE_HASH == 1

int crypto_hash(uint8_t *out, const uint8_t *in, unsigned long long inlen)
{

    state_t state;
    state_t *s = &state;

    // Initialize
    s->l[0] = U64TOWORD(*(lane_t *)(ASCON_HASH_IV + 0));
    s->x[1] = 0;
    s->x[2] = 0;
    s->x[3] = 0;
    s->x[4] = 0;
    P_sH;

    // Absorb input
    ABSORB_LANES(s, in, inlen);

    for (size_t i = 0; i < 4; i++)
    {
        // Squeeze full lanes
        lane_t t0 = WORDTOU64(s->l[0]);
        *(uint64_t *)(out + 8 * i) = t0.x;
        if (i < 3)
        {
            P_sH;
        }
Robert Primas committed
221
    }
222 223

    return 0;
Robert Primas committed
224
}
225 226

#endif