Browse Source

Move the tag to the end for crypto_aead_chacha20poly1305

next
Frank Denis 10 years ago
parent
commit
eec0f78af6
  1. 44
      README.markdown
  2. 40
      src/libsodium/crypto_aead/chacha20poly1305/aead_chacha20poly1305.c
  3. 16
      src/libsodium/include/sodium/crypto_aead_chacha20poly1305.h
  4. 6
      test/default/aead_chacha20poly1305.c
  5. 6
      test/default/aead_chacha20poly1305.exp

44
README.markdown

@ -363,52 +363,50 @@ Additional Data (AEAD) construction, as documented in the
[nir-cfrg-chacha20-poly1305-04](http://tools.ietf.org/html/draft-nir-cfrg-chacha20-poly1305-04)
draft.
int crypto_secretbox_chacha20poly1305_ad(unsigned char *c,
int crypto_aead_chacha20poly1305_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 *n,
const unsigned char *nsec,
const unsigned char *npub,
const unsigned char *k);
This function encrypts the message `m` of length `mlen` with the key
`k` (whose size is `crypto_secretbox_chacha20poly1305_KEYBYTES` bytes)
and nonce `n` (whose size is `crypto_secretbox_chacha20poly1305_NONCEBYTES`).
`k` (whose size is `crypto_aead_chacha20poly1305_KEYBYTES` bytes)
and nonce `n` (whose size is `crypto_aead_chacha20poly1305_NPUBBYTES`).
`c` must be at least `mlen + crypto_secretbox_chacha20poly1305_ZEROBYTES` long.
`c` must be at least `mlen + crypto_aead_chacha20poly1305_ABYTES` long.
`nsec` should be NULL.
The function fills the first bytes of `c` with a tag authenticating both the
encrypted message and additional data `ad` whose length is `adlen` bytes.
The output of the previous function can be verified and decrypted using:
int crypto_secretbox_chacha20poly1305_ad_open(unsigned char *m,
const unsigned char *c,
unsigned long long clen,
const unsigned char *ad,
unsigned long long adlen,
const unsigned char *n,
const unsigned char *k);
int crypto_aead_chacha20poly1305_decrypt(unsigned char *m,
unsigned long long *mlen,
unsigned char *nsec,
const unsigned char *c,
unsigned long long clen,
const unsigned char *ad,
unsigned long long adlen,
const unsigned char *npub,
const unsigned char *k);
`clen` is the length of the ciphertext, as generated by the previous
function: it is equal to the length of the plaintext message +
`crypto_secretbox_chacha20poly1305_ZEROBYTES`.
`crypto_aead_chacha20poly1305_ABYTES`.
If the MAC can be verified, the plaintext is copied to `m` and the
function returns `0`.
If the verification fails, the function returns `-1`.
The length of the additional data can be `0`. Alternatively, the
`crypto_secretbox_chacha20poly1305()` and
`crypto_secretbox_chacha20poly1305_open()` variants can be used.
In order to be consistent with the `secretbox` API, the MAC is stored
*before* the encrypted message. This differs from the
draft on ChaCha20 and Poly1305 for IETF protocols, which stores the
MAC *after* the encrypted message.
The length of the additional data can be `0`.
However, the MAC is computed using the same algorithm, and can be
moved after message if interoperability with other implementations is required.
`nsec` should be NULL.
## Constants available as functions

40
src/libsodium/crypto_aead/chacha20poly1305/aead_chacha20poly1305.c

@ -35,17 +35,16 @@ crypto_aead_chacha20poly1305_encrypt(unsigned char *c,
crypto_onetimeauth_poly1305_state state;
unsigned char block0[64U];
unsigned char slen[8U];
#ifdef ULONG_LONG_MAX
if (mlen > ULONG_LONG_MAX - crypto_aead_chacha20poly1305_ZEROBYTES) {
if (mlen > ULONG_LONG_MAX - crypto_aead_chacha20poly1305_ABYTES) {
if (clen != NULL) {
*clen = 0ULL;
}
return -1;
}
#endif
crypto_stream_chacha20_xor_ic
(c + crypto_aead_chacha20poly1305_ZEROBYTES, m, mlen, npub, 1U, k);
#endif
crypto_stream_chacha20_xor_ic(c, m, mlen, npub, 1U, k);
crypto_stream_chacha20(block0, sizeof block0, npub, k);
crypto_onetimeauth_poly1305_init(&state, block0);
@ -55,16 +54,15 @@ crypto_aead_chacha20poly1305_encrypt(unsigned char *c,
_u64_le_from_ull(slen, adlen);
crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
crypto_onetimeauth_poly1305_update
(&state, c + crypto_aead_chacha20poly1305_ZEROBYTES, mlen);
crypto_onetimeauth_poly1305_update(&state, c, mlen);
_u64_le_from_ull(slen, mlen);
crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
crypto_onetimeauth_poly1305_final(&state, c);
crypto_onetimeauth_poly1305_final(&state, c + mlen);
sodium_memzero(&state, sizeof state);
if (clen != NULL) {
*clen = mlen + crypto_aead_chacha20poly1305_ZEROBYTES;
*clen = mlen + crypto_aead_chacha20poly1305_ABYTES;
}
return 0;
}
@ -83,13 +81,13 @@ crypto_aead_chacha20poly1305_decrypt(unsigned char *m,
crypto_onetimeauth_poly1305_state state;
unsigned char block0[64U];
unsigned char slen[8U];
unsigned char mac[crypto_aead_chacha20poly1305_MACBYTES];
unsigned char mac[crypto_aead_chacha20poly1305_ABYTES];
int ret;
if (mlen != NULL) {
*mlen = 0ULL;
}
if (clen < crypto_aead_chacha20poly1305_ZEROBYTES) {
if (clen < crypto_aead_chacha20poly1305_ABYTES) {
return -1;
}
crypto_stream_chacha20(block0, sizeof block0, npub, k);
@ -101,25 +99,24 @@ crypto_aead_chacha20poly1305_decrypt(unsigned char *m,
crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
crypto_onetimeauth_poly1305_update
(&state, c + crypto_aead_chacha20poly1305_ZEROBYTES,
clen - crypto_aead_chacha20poly1305_ZEROBYTES);
_u64_le_from_ull(slen, clen - crypto_aead_chacha20poly1305_ZEROBYTES);
(&state, c, clen - crypto_aead_chacha20poly1305_ABYTES);
_u64_le_from_ull(slen, clen - crypto_aead_chacha20poly1305_ABYTES);
crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen);
crypto_onetimeauth_poly1305_final(&state, mac);
sodium_memzero(&state, sizeof state);
ret = crypto_verify_16(mac, c);
ret = crypto_verify_16(mac,
c + clen - crypto_aead_chacha20poly1305_ABYTES);
sodium_memzero(mac, sizeof mac);
if (ret != 0) {
memset(m, 0, clen - crypto_aead_chacha20poly1305_ZEROBYTES);
memset(m, 0, clen - crypto_aead_chacha20poly1305_ABYTES);
return -1;
}
crypto_stream_chacha20_xor_ic
(m, c + crypto_aead_chacha20poly1305_ZEROBYTES,
clen - crypto_aead_chacha20poly1305_ZEROBYTES, npub, 1U, k);
(m, c, clen - crypto_aead_chacha20poly1305_ABYTES, npub, 1U, k);
if (mlen != NULL) {
*mlen = clen - crypto_aead_chacha20poly1305_ZEROBYTES;
*mlen = clen - crypto_aead_chacha20poly1305_ABYTES;
}
return 0;
}
@ -143,8 +140,3 @@ size_t
crypto_aead_chacha20poly1305_abytes(void) {
return crypto_aead_chacha20poly1305_ABYTES;
}
size_t
crypto_aead_chacha20poly1305_macbytes(void) {
return crypto_aead_chacha20poly1305_MACBYTES;
}

16
src/libsodium/include/sodium/crypto_aead_chacha20poly1305.h

@ -23,21 +23,7 @@ size_t crypto_aead_chacha20poly1305_nsecbytes(void);
SODIUM_EXPORT
size_t crypto_aead_chacha20poly1305_npubbytes(void);
#define crypto_aead_chacha20poly1305_ZEROBYTES 16U
SODIUM_EXPORT
size_t crypto_aead_chacha20poly1305_zerobytes(void);
#define crypto_aead_chacha20poly1305_BOXZEROBYTES 0U
SODIUM_EXPORT
size_t crypto_aead_chacha20poly1305_boxzerobytes(void);
#define crypto_aead_chacha20poly1305_MACBYTES \
(crypto_aead_chacha20poly1305_ZEROBYTES - \
crypto_aead_chacha20poly1305_BOXZEROBYTES)
SODIUM_EXPORT
size_t crypto_aead_chacha20poly1305_macbytes(void);
#define crypto_aead_chacha20poly1305_ABYTES 0U
#define crypto_aead_chacha20poly1305_ABYTES 16U
SODIUM_EXPORT
size_t crypto_aead_chacha20poly1305_abytes(void);

6
test/default/aead_chacha20poly1305.c

@ -23,7 +23,7 @@ static unsigned char ad[10U] = {
0x87, 0xe2, 0x29, 0xd4, 0x50, 0x08, 0x45, 0xa0, 0x79, 0xc0
};
static unsigned char c[10U + crypto_aead_chacha20poly1305_MACBYTES];
static unsigned char c[10U + crypto_aead_chacha20poly1305_ABYTES];
int main(void)
{
@ -34,7 +34,7 @@ int main(void)
crypto_aead_chacha20poly1305_encrypt(c, &clen, m, sizeof m, ad, sizeof ad,
NULL, nonce, firstkey);
if (clen != sizeof m + crypto_aead_chacha20poly1305_macbytes()) {
if (clen != sizeof m + crypto_aead_chacha20poly1305_abytes()) {
printf("clen is not properly set\n");
}
for (i = 0U; i < sizeof c; ++i) {
@ -50,7 +50,7 @@ int main(void)
nonce, firstkey) != 0) {
printf("crypto_aead_chacha20poly1305_decrypt() failed\n");
}
if (m2len != sizeof c - crypto_aead_chacha20poly1305_macbytes()) {
if (m2len != sizeof c - crypto_aead_chacha20poly1305_abytes()) {
printf("m2len is not properly set\n");
}
if (memcmp(m, m2, sizeof m) != 0) {

6
test/default/aead_chacha20poly1305.exp

@ -1,4 +1,4 @@
,0x67,0x7d,0xab,0xf4,0xe3,0xd2,0x4b,0x87
,0x6b,0xb2,0x84,0x75,0x38,0x96,0xe1,0xd6
,0xe3,0xe4,0x46,0xf7,0xed,0xe9,0xa1,0x9b
,0x62,0xa4
,0x62,0xa4,0x67,0x7d,0xab,0xf4,0xe3,0xd2
,0x4b,0x87,0x6b,0xb2,0x84,0x75,0x38,0x96
,0xe1,0xd6

Loading…
Cancel
Save