isap.c 5.18 KB
Newer Older
1 2
#include <string.h>
#include <inttypes.h>
Robert Primas committed
3 4 5
#include "api.h"
#include "isap.h"
#include "asconp.h"
6
#include "config.h"
Robert Primas committed
7

8 9 10 11 12 13 14 15 16 17 18
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 45 46 47

/******************************************************************************/
/*                                 ISAP_RK                                    */
/******************************************************************************/

void isap_rk(
48 49 50 51 52
    const uint8_t *k,
    const uint8_t *iv,
    const uint8_t *y,
    state_t *out,
    const size_t outlen)
Robert Primas committed
53
{
54 55
    state_t state;
    state_t *s = &state;
Robert Primas committed
56 57

    // Initialize
58 59 60 61 62
    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;
Robert Primas committed
63 64 65
    P_sK;

    // Absorb Y, bit by bit
66 67 68 69 70 71 72 73 74 75 76 77
    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;
Robert Primas committed
78
        P_sB;
79 80 81 82 83 84 85 86 87 88
        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
    // Squeeze K*
Robert Primas committed
92
    P_sK;
93 94 95 96 97
    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 103 104 105
    }
}

/******************************************************************************/
/*                                 ISAP_MAC                                   */
/******************************************************************************/

void isap_mac(
106 107 108 109 110
    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)
Robert Primas committed
111
{
112 113
    state_t state;
    state_t *s = &state;
Robert Primas committed
114 115

    // Initialize
116 117 118 119 120
    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;
Robert Primas committed
121 122
    P_sH;

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

126 127
    // Domain seperation
    s->w[4][0] ^= 0x1UL;
Robert Primas committed
128

129 130
    // Absorb ciphertext
    ABSORB_LANES(s, c, clen);
Robert Primas committed
131

132 133 134 135
    // 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
Robert Primas committed
138
    P_sH;
139 140 141 142
    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 147 148 149
}

/******************************************************************************/
/*                                 ISAP_ENC                                   */
/******************************************************************************/

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

Robert Primas committed
155
{
156 157 158 159 160 161 162 163 164
    state_t state;
    state_t *s = &state;

    // Init state
    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)
Robert Primas committed
165
    {
166
        // Encrypt full lanes
Robert Primas committed
167
        P_sE;
168 169 170
        lane_t t0 = WORDTOU64(s->l[0]);
        *(uint64_t *)c = *(uint64_t *)m ^ t0.x;
        mlen -= ISAP_rH / 8;
Robert Primas committed
171 172 173 174 175 176
        m += ISAP_rH / 8;
        c += ISAP_rH / 8;
    }

    if (mlen > 0)
    {
177
        // Encrypt partial lanes
Robert Primas committed
178
        P_sE;
179 180
        lane_t t0 = WORDTOU64(s->l[0]);
        for (uint8_t i = 0; i < mlen; i++)
Robert Primas committed
181
        {
182
            *c = *m ^ t0.b[i];
Robert Primas committed
183 184 185 186 187
            m += 1;
            c += 1;
        }
    }
}
188 189 190 191 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 221 222 223 224 225 226

/******************************************************************************/
/*                                Ascon-Hash                                  */
/******************************************************************************/

#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;
        }
    }

    return 0;
}

#endif