Home | History | Annotate | Line # | Download | only in sodium
      1 
      2 #include <stdint.h>
      3 #include <stdlib.h>
      4 #include <limits.h>
      5 #include <string.h>
      6 
      7 #include "core.h"
      8 #include "crypto_aead_chacha20poly1305.h"
      9 #include "crypto_onetimeauth_poly1305.h"
     10 #include "crypto_stream_chacha20.h"
     11 #include "crypto_verify_16.h"
     12 #include "randombytes.h"
     13 #include "utils.h"
     14 
     15 #include "private/common.h"
     16 
     17 static const unsigned char _pad0[16] = { 0 };
     18 
     19 int
     20 crypto_aead_chacha20poly1305_encrypt_detached(unsigned char *c,
     21                                               unsigned char *mac,
     22                                               unsigned long long *maclen_p,
     23                                               const unsigned char *m,
     24                                               unsigned long long mlen,
     25                                               const unsigned char *ad,
     26                                               unsigned long long adlen,
     27                                               const unsigned char *nsec,
     28                                               const unsigned char *npub,
     29                                               const unsigned char *k)
     30 {
     31     crypto_onetimeauth_poly1305_state state;
     32     unsigned char                     block0[64U];
     33     unsigned char                     slen[8U];
     34 
     35     (void) nsec;
     36     crypto_stream_chacha20(block0, sizeof block0, npub, k);
     37     crypto_onetimeauth_poly1305_init(&state, block0);
     38     sodium_memzero(block0, sizeof block0);
     39 
     40     crypto_onetimeauth_poly1305_update(&state, ad, adlen);
     41     STORE64_LE(slen, (uint64_t) adlen);
     42     crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
     43 
     44     crypto_stream_chacha20_xor_ic(c, m, mlen, npub, 1U, k);
     45 
     46     crypto_onetimeauth_poly1305_update(&state, c, mlen);
     47     STORE64_LE(slen, (uint64_t) mlen);
     48     crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
     49 
     50     crypto_onetimeauth_poly1305_final(&state, mac);
     51     sodium_memzero(&state, sizeof state);
     52 
     53     if (maclen_p != NULL) {
     54         *maclen_p = crypto_aead_chacha20poly1305_ABYTES;
     55     }
     56     return 0;
     57 }
     58 
     59 int
     60 crypto_aead_chacha20poly1305_encrypt(unsigned char *c,
     61                                      unsigned long long *clen_p,
     62                                      const unsigned char *m,
     63                                      unsigned long long mlen,
     64                                      const unsigned char *ad,
     65                                      unsigned long long adlen,
     66                                      const unsigned char *nsec,
     67                                      const unsigned char *npub,
     68                                      const unsigned char *k)
     69 {
     70     unsigned long long clen = 0ULL;
     71     int                ret;
     72 
     73     if (mlen > crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX) {
     74         sodium_misuse();
     75     }
     76     ret = crypto_aead_chacha20poly1305_encrypt_detached(c,
     77                                                         c + mlen, NULL,
     78                                                         m, mlen,
     79                                                         ad, adlen,
     80                                                         nsec, npub, k);
     81     if (clen_p != NULL) {
     82         if (ret == 0) {
     83             clen = mlen + crypto_aead_chacha20poly1305_ABYTES;
     84         }
     85         *clen_p = clen;
     86     }
     87     return ret;
     88 }
     89 
     90 int
     91 crypto_aead_chacha20poly1305_ietf_encrypt_detached(unsigned char *c,
     92                                                    unsigned char *mac,
     93                                                    unsigned long long *maclen_p,
     94                                                    const unsigned char *m,
     95                                                    unsigned long long mlen,
     96                                                    const unsigned char *ad,
     97                                                    unsigned long long adlen,
     98                                                    const unsigned char *nsec,
     99                                                    const unsigned char *npub,
    100                                                    const unsigned char *k)
    101 {
    102     crypto_onetimeauth_poly1305_state state;
    103     unsigned char                     block0[64U];
    104     unsigned char                     slen[8U];
    105 
    106     (void) nsec;
    107     crypto_stream_chacha20_ietf(block0, sizeof block0, npub, k);
    108     crypto_onetimeauth_poly1305_init(&state, block0);
    109     sodium_memzero(block0, sizeof block0);
    110 
    111     crypto_onetimeauth_poly1305_update(&state, ad, adlen);
    112     crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - adlen) & 0xf);
    113 
    114     crypto_stream_chacha20_ietf_xor_ic(c, m, mlen, npub, 1U, k);
    115 
    116     crypto_onetimeauth_poly1305_update(&state, c, mlen);
    117     crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - mlen) & 0xf);
    118 
    119     STORE64_LE(slen, (uint64_t) adlen);
    120     crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
    121 
    122     STORE64_LE(slen, (uint64_t) mlen);
    123     crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
    124 
    125     crypto_onetimeauth_poly1305_final(&state, mac);
    126     sodium_memzero(&state, sizeof state);
    127 
    128     if (maclen_p != NULL) {
    129         *maclen_p = crypto_aead_chacha20poly1305_ietf_ABYTES;
    130     }
    131     return 0;
    132 }
    133 
    134 int
    135 crypto_aead_chacha20poly1305_ietf_encrypt(unsigned char *c,
    136                                           unsigned long long *clen_p,
    137                                           const unsigned char *m,
    138                                           unsigned long long mlen,
    139                                           const unsigned char *ad,
    140                                           unsigned long long adlen,
    141                                           const unsigned char *nsec,
    142                                           const unsigned char *npub,
    143                                           const unsigned char *k)
    144 {
    145     unsigned long long clen = 0ULL;
    146     int                ret;
    147 
    148     if (mlen > crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX) {
    149         sodium_misuse();
    150     }
    151     ret = crypto_aead_chacha20poly1305_ietf_encrypt_detached(c,
    152                                                              c + mlen, NULL,
    153                                                              m, mlen,
    154                                                              ad, adlen,
    155                                                              nsec, npub, k);
    156     if (clen_p != NULL) {
    157         if (ret == 0) {
    158             clen = mlen + crypto_aead_chacha20poly1305_ietf_ABYTES;
    159         }
    160         *clen_p = clen;
    161     }
    162     return ret;
    163 }
    164 
    165 int
    166 crypto_aead_chacha20poly1305_decrypt_detached(unsigned char *m,
    167                                               unsigned char *nsec,
    168                                               const unsigned char *c,
    169                                               unsigned long long clen,
    170                                               const unsigned char *mac,
    171                                               const unsigned char *ad,
    172                                               unsigned long long adlen,
    173                                               const unsigned char *npub,
    174                                               const unsigned char *k)
    175 {
    176     crypto_onetimeauth_poly1305_state state;
    177     unsigned char                     block0[64U];
    178     unsigned char                     slen[8U];
    179     unsigned char                     computed_mac[crypto_aead_chacha20poly1305_ABYTES];
    180     unsigned long long                mlen;
    181     int                               ret;
    182 
    183     (void) nsec;
    184     crypto_stream_chacha20(block0, sizeof block0, npub, k);
    185     crypto_onetimeauth_poly1305_init(&state, block0);
    186     sodium_memzero(block0, sizeof block0);
    187 
    188     crypto_onetimeauth_poly1305_update(&state, ad, adlen);
    189     STORE64_LE(slen, (uint64_t) adlen);
    190     crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
    191 
    192     mlen = clen;
    193     crypto_onetimeauth_poly1305_update(&state, c, mlen);
    194     STORE64_LE(slen, (uint64_t) mlen);
    195     crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
    196 
    197     crypto_onetimeauth_poly1305_final(&state, computed_mac);
    198     sodium_memzero(&state, sizeof state);
    199 
    200     COMPILER_ASSERT(sizeof computed_mac == 16U);
    201     ret = crypto_verify_16(computed_mac, mac);
    202     sodium_memzero(computed_mac, sizeof computed_mac);
    203     if (m == NULL) {
    204         return ret;
    205     }
    206     if (ret != 0) {
    207         memset(m, 0, mlen);
    208         return -1;
    209     }
    210     crypto_stream_chacha20_xor_ic(m, c, mlen, npub, 1U, k);
    211 
    212     return 0;
    213 }
    214 
    215 int
    216 crypto_aead_chacha20poly1305_decrypt(unsigned char *m,
    217                                      unsigned long long *mlen_p,
    218                                      unsigned char *nsec,
    219                                      const unsigned char *c,
    220                                      unsigned long long clen,
    221                                      const unsigned char *ad,
    222                                      unsigned long long adlen,
    223                                      const unsigned char *npub,
    224                                      const unsigned char *k)
    225 {
    226     unsigned long long mlen = 0ULL;
    227     int                ret = -1;
    228 
    229     if (clen >= crypto_aead_chacha20poly1305_ABYTES) {
    230         ret = crypto_aead_chacha20poly1305_decrypt_detached
    231             (m, nsec,
    232              c, clen - crypto_aead_chacha20poly1305_ABYTES,
    233              c + clen - crypto_aead_chacha20poly1305_ABYTES,
    234              ad, adlen, npub, k);
    235     }
    236     if (mlen_p != NULL) {
    237         if (ret == 0) {
    238             mlen = clen - crypto_aead_chacha20poly1305_ABYTES;
    239         }
    240         *mlen_p = mlen;
    241     }
    242     return ret;
    243 }
    244 
    245 int
    246 crypto_aead_chacha20poly1305_ietf_decrypt_detached(unsigned char *m,
    247                                                    unsigned char *nsec,
    248                                                    const unsigned char *c,
    249                                                    unsigned long long clen,
    250                                                    const unsigned char *mac,
    251                                                    const unsigned char *ad,
    252                                                    unsigned long long adlen,
    253                                                    const unsigned char *npub,
    254                                                    const unsigned char *k)
    255 {
    256     crypto_onetimeauth_poly1305_state state;
    257     unsigned char                     block0[64U];
    258     unsigned char                     slen[8U];
    259     unsigned char                     computed_mac[crypto_aead_chacha20poly1305_ietf_ABYTES];
    260     unsigned long long                mlen;
    261     int                               ret;
    262 
    263     (void) nsec;
    264     crypto_stream_chacha20_ietf(block0, sizeof block0, npub, k);
    265     crypto_onetimeauth_poly1305_init(&state, block0);
    266     sodium_memzero(block0, sizeof block0);
    267 
    268     crypto_onetimeauth_poly1305_update(&state, ad, adlen);
    269     crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - adlen) & 0xf);
    270 
    271     mlen = clen;
    272     crypto_onetimeauth_poly1305_update(&state, c, mlen);
    273     crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - mlen) & 0xf);
    274 
    275     STORE64_LE(slen, (uint64_t) adlen);
    276     crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
    277 
    278     STORE64_LE(slen, (uint64_t) mlen);
    279     crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
    280 
    281     crypto_onetimeauth_poly1305_final(&state, computed_mac);
    282     sodium_memzero(&state, sizeof state);
    283 
    284     COMPILER_ASSERT(sizeof computed_mac == 16U);
    285     ret = crypto_verify_16(computed_mac, mac);
    286     sodium_memzero(computed_mac, sizeof computed_mac);
    287     if (m == NULL) {
    288         return ret;
    289     }
    290     if (ret != 0) {
    291         memset(m, 0, mlen);
    292         return -1;
    293     }
    294     crypto_stream_chacha20_ietf_xor_ic(m, c, mlen, npub, 1U, k);
    295 
    296     return 0;
    297 }
    298 
    299 int
    300 crypto_aead_chacha20poly1305_ietf_decrypt(unsigned char *m,
    301                                           unsigned long long *mlen_p,
    302                                           unsigned char *nsec,
    303                                           const unsigned char *c,
    304                                           unsigned long long clen,
    305                                           const unsigned char *ad,
    306                                           unsigned long long adlen,
    307                                           const unsigned char *npub,
    308                                           const unsigned char *k)
    309 {
    310     unsigned long long mlen = 0ULL;
    311     int                ret = -1;
    312 
    313     if (clen >= crypto_aead_chacha20poly1305_ietf_ABYTES) {
    314         ret = crypto_aead_chacha20poly1305_ietf_decrypt_detached
    315             (m, nsec,
    316              c, clen - crypto_aead_chacha20poly1305_ietf_ABYTES,
    317              c + clen - crypto_aead_chacha20poly1305_ietf_ABYTES,
    318              ad, adlen, npub, k);
    319     }
    320     if (mlen_p != NULL) {
    321         if (ret == 0) {
    322             mlen = clen - crypto_aead_chacha20poly1305_ietf_ABYTES;
    323         }
    324         *mlen_p = mlen;
    325     }
    326     return ret;
    327 }
    328 
    329 size_t
    330 crypto_aead_chacha20poly1305_ietf_keybytes(void)
    331 {
    332     return crypto_aead_chacha20poly1305_ietf_KEYBYTES;
    333 }
    334 
    335 size_t
    336 crypto_aead_chacha20poly1305_ietf_npubbytes(void)
    337 {
    338     return crypto_aead_chacha20poly1305_ietf_NPUBBYTES;
    339 }
    340 
    341 size_t
    342 crypto_aead_chacha20poly1305_ietf_nsecbytes(void)
    343 {
    344     return crypto_aead_chacha20poly1305_ietf_NSECBYTES;
    345 }
    346 
    347 size_t
    348 crypto_aead_chacha20poly1305_ietf_abytes(void)
    349 {
    350     return crypto_aead_chacha20poly1305_ietf_ABYTES;
    351 }
    352 
    353 size_t
    354 crypto_aead_chacha20poly1305_ietf_messagebytes_max(void)
    355 {
    356     return crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX;
    357 }
    358 
    359 void
    360 crypto_aead_chacha20poly1305_ietf_keygen(unsigned char k[crypto_aead_chacha20poly1305_ietf_KEYBYTES])
    361 {
    362     randombytes_buf(k, crypto_aead_chacha20poly1305_ietf_KEYBYTES);
    363 }
    364 
    365 size_t
    366 crypto_aead_chacha20poly1305_keybytes(void)
    367 {
    368     return crypto_aead_chacha20poly1305_KEYBYTES;
    369 }
    370 
    371 size_t
    372 crypto_aead_chacha20poly1305_npubbytes(void)
    373 {
    374     return crypto_aead_chacha20poly1305_NPUBBYTES;
    375 }
    376 
    377 size_t
    378 crypto_aead_chacha20poly1305_nsecbytes(void)
    379 {
    380     return crypto_aead_chacha20poly1305_NSECBYTES;
    381 }
    382 
    383 size_t
    384 crypto_aead_chacha20poly1305_abytes(void)
    385 {
    386     return crypto_aead_chacha20poly1305_ABYTES;
    387 }
    388 
    389 size_t
    390 crypto_aead_chacha20poly1305_messagebytes_max(void)
    391 {
    392     return crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX;
    393 }
    394 
    395 void
    396 crypto_aead_chacha20poly1305_keygen(unsigned char k[crypto_aead_chacha20poly1305_KEYBYTES])
    397 {
    398     randombytes_buf(k, crypto_aead_chacha20poly1305_KEYBYTES);
    399 }
    400