Home | History | Annotate | Line # | Download | only in xchacha20poly1305
      1 
      2 #include <assert.h>
      3 #include <limits.h>
      4 #include <stdint.h>
      5 #include <stdlib.h>
      6 #include <string.h>
      7 
      8 #include "core.h"
      9 #include "crypto_core_hchacha20.h"
     10 #include "crypto_onetimeauth_poly1305.h"
     11 #include "crypto_secretbox_xchacha20poly1305.h"
     12 #include "crypto_stream_chacha20.h"
     13 #include "private/common.h"
     14 #include "utils.h"
     15 
     16 #define crypto_secretbox_xchacha20poly1305_ZEROBYTES 32U
     17 
     18 int
     19 crypto_secretbox_xchacha20poly1305_detached(unsigned char *c,
     20                                             unsigned char *mac,
     21                                             const unsigned char *m,
     22                                             unsigned long long mlen,
     23                                             const unsigned char *n,
     24                                             const unsigned char *k)
     25 {
     26     crypto_onetimeauth_poly1305_state state;
     27     unsigned char                     block0[64U];
     28     unsigned char                     subkey[crypto_stream_chacha20_KEYBYTES];
     29     unsigned long long                i;
     30     unsigned long long                mlen0;
     31 
     32     crypto_core_hchacha20(subkey, n, k, NULL);
     33 
     34     if (((uintptr_t) c > (uintptr_t) m &&
     35          (uintptr_t) c - (uintptr_t) m < mlen) ||
     36         ((uintptr_t) m > (uintptr_t) c &&
     37          (uintptr_t) m - (uintptr_t) c < mlen)) { /* LCOV_EXCL_LINE */
     38         memmove(c, m, mlen);
     39         m = c;
     40     }
     41     memset(block0, 0U, crypto_secretbox_xchacha20poly1305_ZEROBYTES);
     42     COMPILER_ASSERT(64U >= crypto_secretbox_xchacha20poly1305_ZEROBYTES);
     43     mlen0 = mlen;
     44     if (mlen0 > 64U - crypto_secretbox_xchacha20poly1305_ZEROBYTES) {
     45         mlen0 = 64U - crypto_secretbox_xchacha20poly1305_ZEROBYTES;
     46     }
     47     for (i = 0U; i < mlen0; i++) {
     48         block0[i + crypto_secretbox_xchacha20poly1305_ZEROBYTES] = m[i];
     49     }
     50     crypto_stream_chacha20_xor(block0, block0,
     51                                mlen0 + crypto_secretbox_xchacha20poly1305_ZEROBYTES,
     52                                n + 16, subkey);
     53     COMPILER_ASSERT(crypto_secretbox_xchacha20poly1305_ZEROBYTES >=
     54                     crypto_onetimeauth_poly1305_KEYBYTES);
     55     crypto_onetimeauth_poly1305_init(&state, block0);
     56 
     57     for (i = 0U; i < mlen0; i++) {
     58         c[i] = block0[crypto_secretbox_xchacha20poly1305_ZEROBYTES + i];
     59     }
     60     sodium_memzero(block0, sizeof block0);
     61     if (mlen > mlen0) {
     62         crypto_stream_chacha20_xor_ic(c + mlen0, m + mlen0, mlen - mlen0,
     63                                       n + 16, 1U, subkey);
     64     }
     65     sodium_memzero(subkey, sizeof subkey);
     66 
     67     crypto_onetimeauth_poly1305_update(&state, c, mlen);
     68     crypto_onetimeauth_poly1305_final(&state, mac);
     69     sodium_memzero(&state, sizeof state);
     70 
     71     return 0;
     72 }
     73 
     74 int
     75 crypto_secretbox_xchacha20poly1305_easy(unsigned char *c,
     76                                         const unsigned char *m,
     77                                         unsigned long long mlen,
     78                                         const unsigned char *n,
     79                                         const unsigned char *k)
     80 {
     81     if (mlen > crypto_secretbox_xchacha20poly1305_MESSAGEBYTES_MAX) {
     82         sodium_misuse();
     83     }
     84     return crypto_secretbox_xchacha20poly1305_detached
     85         (c + crypto_secretbox_xchacha20poly1305_MACBYTES, c, m, mlen, n, k);
     86 }
     87 
     88 int
     89 crypto_secretbox_xchacha20poly1305_open_detached(unsigned char *m,
     90                                                  const unsigned char *c,
     91                                                  const unsigned char *mac,
     92                                                  unsigned long long clen,
     93                                                  const unsigned char *n,
     94                                                  const unsigned char *k)
     95 {
     96     unsigned char      block0[64U];
     97     unsigned char      subkey[crypto_stream_chacha20_KEYBYTES];
     98     unsigned long long i;
     99     unsigned long long mlen0;
    100 
    101     crypto_core_hchacha20(subkey, n, k, NULL);
    102     crypto_stream_chacha20(block0, crypto_stream_chacha20_KEYBYTES,
    103                            n + 16, subkey);
    104     if (crypto_onetimeauth_poly1305_verify(mac, c, clen, block0) != 0) {
    105         sodium_memzero(subkey, sizeof subkey);
    106         return -1;
    107     }
    108     if (m == NULL) {
    109         return 0;
    110     }
    111     if (((uintptr_t) c >= (uintptr_t) m &&
    112          (uintptr_t) c - (uintptr_t) m < clen) ||
    113         ((uintptr_t) m >= (uintptr_t) c &&
    114          (uintptr_t) m - (uintptr_t) c < clen)) { /* LCOV_EXCL_LINE */
    115         memmove(m, c, clen);
    116         c = m;
    117     }
    118     mlen0 = clen;
    119     if (mlen0 > 64U - crypto_secretbox_xchacha20poly1305_ZEROBYTES) {
    120         mlen0 = 64U - crypto_secretbox_xchacha20poly1305_ZEROBYTES;
    121     }
    122     for (i = 0U; i < mlen0; i++) {
    123         block0[crypto_secretbox_xchacha20poly1305_ZEROBYTES + i] = c[i];
    124     }
    125     crypto_stream_chacha20_xor(block0, block0,
    126                               crypto_secretbox_xchacha20poly1305_ZEROBYTES + mlen0,
    127                               n + 16, subkey);
    128     for (i = 0U; i < mlen0; i++) {
    129         m[i] = block0[i + crypto_secretbox_xchacha20poly1305_ZEROBYTES];
    130     }
    131     if (clen > mlen0) {
    132         crypto_stream_chacha20_xor_ic(m + mlen0, c + mlen0, clen - mlen0,
    133                                       n + 16, 1U, subkey);
    134     }
    135     sodium_memzero(subkey, sizeof subkey);
    136 
    137     return 0;
    138 }
    139 
    140 int
    141 crypto_secretbox_xchacha20poly1305_open_easy(unsigned char *m,
    142                                              const unsigned char *c,
    143                                              unsigned long long clen,
    144                                              const unsigned char *n,
    145                                              const unsigned char *k)
    146 {
    147     if (clen < crypto_secretbox_xchacha20poly1305_MACBYTES) {
    148         return -1;
    149     }
    150     return crypto_secretbox_xchacha20poly1305_open_detached
    151         (m, c + crypto_secretbox_xchacha20poly1305_MACBYTES, c,
    152          clen - crypto_secretbox_xchacha20poly1305_MACBYTES, n, k);
    153 }
    154 
    155 size_t
    156 crypto_secretbox_xchacha20poly1305_keybytes(void)
    157 {
    158     return crypto_secretbox_xchacha20poly1305_KEYBYTES;
    159 }
    160 
    161 size_t
    162 crypto_secretbox_xchacha20poly1305_noncebytes(void)
    163 {
    164     return crypto_secretbox_xchacha20poly1305_NONCEBYTES;
    165 }
    166 
    167 size_t
    168 crypto_secretbox_xchacha20poly1305_macbytes(void)
    169 {
    170     return crypto_secretbox_xchacha20poly1305_MACBYTES;
    171 }
    172 
    173 size_t
    174 crypto_secretbox_xchacha20poly1305_messagebytes_max(void)
    175 {
    176     return crypto_secretbox_xchacha20poly1305_MESSAGEBYTES_MAX;
    177 }
    178