Introduce a new crypto_secretstream_*() API
No high-level API yet, since there is no high-level AEAD API.
This commit is contained in:
parent
45f2759d86
commit
df7ad26328
@ -62,6 +62,7 @@ libsodium_la_SOURCES = \
|
||||
crypto_secretbox/crypto_secretbox.c \
|
||||
crypto_secretbox/crypto_secretbox_easy.c \
|
||||
crypto_secretbox/xsalsa20poly1305/secretbox_xsalsa20poly1305.c \
|
||||
crypto_secretstream/xchacha20poly1305/secretstream_xchacha20poly1305.c \
|
||||
crypto_shorthash/crypto_shorthash.c \
|
||||
crypto_shorthash/siphash24/shorthash_siphash24.c \
|
||||
crypto_shorthash/siphash24/ref/shorthash_siphash24_ref.c \
|
||||
|
@ -0,0 +1,235 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "core.h"
|
||||
#include "crypto_aead_xchacha20poly1305.h"
|
||||
#include "crypto_aead_chacha20poly1305.h"
|
||||
#include "crypto_core_hchacha20.h"
|
||||
#include "crypto_onetimeauth_poly1305.h"
|
||||
#include "crypto_secretstream_xchacha20poly1305.h"
|
||||
#include "randombytes.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "private/common.h"
|
||||
|
||||
#define crypto_secretstream_xchacha20poly1305_COUNTERBYTES 4U
|
||||
#define crypto_secretstream_xchacha20poly1305_INONCEBYTES 8U
|
||||
|
||||
static const unsigned char _pad0[16] = { 0 };
|
||||
|
||||
void
|
||||
crypto_secretstream_xchacha20poly1305_keygen
|
||||
(unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES])
|
||||
{
|
||||
randombytes_buf(k, crypto_secretstream_xchacha20poly1305_KEYBYTES);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_secretstream_xchacha20poly1305_init_push
|
||||
(crypto_secretstream_xchacha20poly1305_state *state,
|
||||
unsigned char out[crypto_secretstream_xchacha20poly1305_INITBYTES],
|
||||
const unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES])
|
||||
{
|
||||
randombytes_buf(out, crypto_core_hchacha20_INPUTBYTES +
|
||||
crypto_secretstream_xchacha20poly1305_INONCEBYTES);
|
||||
crypto_core_hchacha20(state->k, out, k, NULL);
|
||||
memcpy(state->nonce, out + crypto_core_hchacha20_INPUTBYTES,
|
||||
crypto_secretstream_xchacha20poly1305_INONCEBYTES);
|
||||
memset(state->nonce + crypto_secretstream_xchacha20poly1305_INONCEBYTES, 0,
|
||||
crypto_secretstream_xchacha20poly1305_COUNTERBYTES);
|
||||
memset(state->_pad, 0, sizeof state->_pad);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_secretstream_xchacha20poly1305_init_pull
|
||||
(crypto_secretstream_xchacha20poly1305_state *state,
|
||||
const unsigned char in[crypto_secretstream_xchacha20poly1305_INITBYTES],
|
||||
const unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES])
|
||||
{
|
||||
crypto_core_hchacha20(state->k, in, k, NULL);
|
||||
memcpy(state->nonce, in + crypto_core_hchacha20_INPUTBYTES,
|
||||
crypto_secretstream_xchacha20poly1305_INONCEBYTES);
|
||||
memset(state->nonce + crypto_secretstream_xchacha20poly1305_INONCEBYTES, 0,
|
||||
crypto_secretstream_xchacha20poly1305_COUNTERBYTES);
|
||||
memset(state->_pad, 0, sizeof state->_pad);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
crypto_secretstream_xchacha20poly1305_rekey
|
||||
(crypto_secretstream_xchacha20poly1305_state *state)
|
||||
{
|
||||
unsigned char new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES +
|
||||
crypto_secretstream_xchacha20poly1305_INONCEBYTES];
|
||||
|
||||
crypto_stream_chacha20_ietf(new_key_and_inonce, sizeof new_key_and_inonce,
|
||||
state->nonce, state->k);
|
||||
memcpy(state->k, new_key_and_inonce, sizeof state->k);
|
||||
memcpy(state->nonce, new_key_and_inonce + sizeof state->k,
|
||||
crypto_secretstream_xchacha20poly1305_INONCEBYTES);
|
||||
memset(state->nonce + crypto_secretstream_xchacha20poly1305_INONCEBYTES, 0,
|
||||
crypto_secretstream_xchacha20poly1305_COUNTERBYTES);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_secretstream_xchacha20poly1305_push
|
||||
(crypto_secretstream_xchacha20poly1305_state *state,
|
||||
unsigned char *out, unsigned long long *outlen_p,
|
||||
const unsigned char *m, unsigned long long mlen,
|
||||
const unsigned char *ad, unsigned long long adlen, unsigned char tag)
|
||||
{
|
||||
crypto_onetimeauth_poly1305_state poly1305_state;
|
||||
unsigned char block[64U];
|
||||
unsigned char slen[8U];
|
||||
unsigned char *c;
|
||||
unsigned char *mac;
|
||||
unsigned int i;
|
||||
|
||||
if (outlen_p != NULL) {
|
||||
*outlen_p = 0U;
|
||||
}
|
||||
if (mlen > crypto_secretstream_xchacha20poly1305_MESSAGESBYTES_MAX) {
|
||||
return -1;
|
||||
}
|
||||
crypto_stream_chacha20_ietf(block, sizeof block, state->nonce, state->k);
|
||||
crypto_onetimeauth_poly1305_init(&poly1305_state, block);
|
||||
sodium_memzero(block, sizeof block);
|
||||
|
||||
crypto_onetimeauth_poly1305_update(&poly1305_state, ad, adlen);
|
||||
crypto_onetimeauth_poly1305_update(&poly1305_state, _pad0,
|
||||
(0x10 - adlen) & 0xf);
|
||||
memset(block, 0, sizeof block);
|
||||
block[0] = tag;
|
||||
|
||||
crypto_stream_chacha20_ietf_xor_ic(block, block, sizeof block,
|
||||
state->nonce, 1U, state->k);
|
||||
crypto_onetimeauth_poly1305_update(&poly1305_state, block, sizeof block);
|
||||
out[0] = block[0];
|
||||
|
||||
c = out + (sizeof tag);
|
||||
crypto_stream_chacha20_ietf_xor_ic(c, m, mlen, state->nonce, 2U, state->k);
|
||||
crypto_onetimeauth_poly1305_update(&poly1305_state, c, mlen);
|
||||
crypto_onetimeauth_poly1305_update
|
||||
(&poly1305_state, _pad0, (0x10 - (sizeof block) + mlen) & 0xf);
|
||||
|
||||
STORE64_LE(slen, (uint64_t) adlen);
|
||||
crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen);
|
||||
STORE64_LE(slen, (sizeof block) + mlen);
|
||||
crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen);
|
||||
|
||||
mac = c + mlen;
|
||||
crypto_onetimeauth_poly1305_final(&poly1305_state, mac);
|
||||
sodium_memzero(&poly1305_state, sizeof poly1305_state);
|
||||
|
||||
for (i = 0U; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) {
|
||||
state->nonce[i] ^= mac[i];
|
||||
}
|
||||
sodium_increment(&state->nonce[crypto_secretstream_xchacha20poly1305_INONCEBYTES],
|
||||
crypto_secretstream_xchacha20poly1305_COUNTERBYTES);
|
||||
if ((tag & crypto_secretstream_xchacha20poly1305_TAG_REKEY) != 0 ||
|
||||
sodium_is_zero(&state->nonce[crypto_secretstream_xchacha20poly1305_INONCEBYTES],
|
||||
crypto_secretstream_xchacha20poly1305_COUNTERBYTES)) {
|
||||
crypto_secretstream_xchacha20poly1305_rekey(state);
|
||||
}
|
||||
if (outlen_p != NULL) {
|
||||
*outlen_p = crypto_secretstream_xchacha20poly1305_ABYTES + mlen;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_secretstream_xchacha20poly1305_pull
|
||||
(crypto_secretstream_xchacha20poly1305_state *state,
|
||||
unsigned char *m, unsigned long long *mlen_p, unsigned char *tag_p,
|
||||
const unsigned char *in, unsigned long long inlen,
|
||||
const unsigned char *ad, unsigned long long adlen)
|
||||
{
|
||||
crypto_onetimeauth_poly1305_state poly1305_state;
|
||||
unsigned char block[64U];
|
||||
unsigned char slen[8U];
|
||||
unsigned char mac[crypto_onetimeauth_poly1305_BYTES];
|
||||
const unsigned char *c;
|
||||
const unsigned char *stored_mac;
|
||||
unsigned long long mlen;
|
||||
unsigned int i;
|
||||
unsigned char tag;
|
||||
|
||||
if (mlen_p != NULL) {
|
||||
*mlen_p = 0U;
|
||||
}
|
||||
if (tag_p != NULL) {
|
||||
*tag_p = 0xff;
|
||||
}
|
||||
if (inlen < crypto_secretstream_xchacha20poly1305_ABYTES) {
|
||||
return -1;
|
||||
}
|
||||
mlen = inlen - crypto_secretstream_xchacha20poly1305_ABYTES;
|
||||
if (mlen > crypto_secretstream_xchacha20poly1305_MESSAGESBYTES_MAX) {
|
||||
return -1;
|
||||
}
|
||||
crypto_stream_chacha20_ietf(block, sizeof block, state->nonce, state->k);
|
||||
crypto_onetimeauth_poly1305_init(&poly1305_state, block);
|
||||
sodium_memzero(block, sizeof block);
|
||||
|
||||
crypto_onetimeauth_poly1305_update(&poly1305_state, ad, adlen);
|
||||
crypto_onetimeauth_poly1305_update(&poly1305_state, _pad0,
|
||||
(0x10 - adlen) & 0xf);
|
||||
|
||||
memset(block, 0, sizeof block);
|
||||
block[0] = in[0];
|
||||
crypto_stream_chacha20_ietf_xor_ic(block, block, sizeof block,
|
||||
state->nonce, 1U, state->k);
|
||||
tag = block[0];
|
||||
block[0] = in[0];
|
||||
crypto_onetimeauth_poly1305_update(&poly1305_state, block, sizeof block);
|
||||
|
||||
c = in + (sizeof tag);
|
||||
crypto_onetimeauth_poly1305_update(&poly1305_state, c, mlen);
|
||||
crypto_onetimeauth_poly1305_update
|
||||
(&poly1305_state, _pad0, (0x10 - (sizeof block) + mlen) & 0xf);
|
||||
|
||||
STORE64_LE(slen, (uint64_t) adlen);
|
||||
crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen);
|
||||
STORE64_LE(slen, (sizeof block) + mlen);
|
||||
crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen);
|
||||
|
||||
crypto_onetimeauth_poly1305_final(&poly1305_state, mac);
|
||||
sodium_memzero(&poly1305_state, sizeof poly1305_state);
|
||||
|
||||
stored_mac = c + mlen;
|
||||
if (sodium_memcmp(mac, stored_mac, sizeof mac) != 0) {
|
||||
sodium_memzero(mac, sizeof mac);
|
||||
return -1;
|
||||
}
|
||||
|
||||
crypto_stream_chacha20_ietf_xor_ic(m, c, mlen, state->nonce, 2U, state->k);
|
||||
for (i = 0U; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) {
|
||||
state->nonce[i] ^= mac[i];
|
||||
}
|
||||
sodium_increment(&state->nonce[crypto_secretstream_xchacha20poly1305_INONCEBYTES],
|
||||
crypto_secretstream_xchacha20poly1305_COUNTERBYTES);
|
||||
if ((tag & crypto_secretstream_xchacha20poly1305_TAG_REKEY) != 0 ||
|
||||
sodium_is_zero(&state->nonce[crypto_secretstream_xchacha20poly1305_INONCEBYTES],
|
||||
crypto_secretstream_xchacha20poly1305_COUNTERBYTES)) {
|
||||
crypto_secretstream_xchacha20poly1305_rekey(state);
|
||||
}
|
||||
if (mlen_p != NULL) {
|
||||
*mlen_p = mlen;
|
||||
}
|
||||
if (tag_p != NULL) {
|
||||
*tag_p = tag;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t
|
||||
crypto_secretstream_xchacha20poly1305_statebytes(void)
|
||||
{
|
||||
return sizeof(crypto_secretstream_xchacha20poly1305_state);
|
||||
}
|
@ -36,6 +36,7 @@ SODIUM_EXPORT = \
|
||||
sodium/crypto_secretbox.h \
|
||||
sodium/crypto_secretbox_xchacha20poly1305.h \
|
||||
sodium/crypto_secretbox_xsalsa20poly1305.h \
|
||||
sodium/crypto_secretstream_xchacha20poly1305.h \
|
||||
sodium/crypto_shorthash.h \
|
||||
sodium/crypto_shorthash_siphash24.h \
|
||||
sodium/crypto_sign.h \
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "sodium/crypto_scalarmult_curve25519.h"
|
||||
#include "sodium/crypto_secretbox.h"
|
||||
#include "sodium/crypto_secretbox_xsalsa20poly1305.h"
|
||||
#include "sodium/crypto_secretstream_xchacha20poly1305.h"
|
||||
#include "sodium/crypto_shorthash.h"
|
||||
#include "sodium/crypto_shorthash_siphash24.h"
|
||||
#include "sodium/crypto_sign.h"
|
||||
|
@ -0,0 +1,84 @@
|
||||
#ifndef crypto_secretstream_xchacha20poly1305_H
|
||||
#define crypto_secretstream_xchacha20poly1305_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "crypto_aead_xchacha20poly1305.h"
|
||||
#include "crypto_stream_chacha20.h"
|
||||
#include "export.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
# ifdef __GNUC__
|
||||
# pragma GCC diagnostic ignored "-Wlong-long"
|
||||
# endif
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define crypto_secretstream_xchacha20poly1305_ABYTES \
|
||||
(1U + crypto_aead_xchacha20poly1305_ietf_ABYTES)
|
||||
|
||||
#define crypto_secretstream_xchacha20poly1305_INITBYTES \
|
||||
crypto_aead_xchacha20poly1305_ietf_NPUBBYTES
|
||||
|
||||
#define crypto_secretstream_xchacha20poly1305_KEYBYTES \
|
||||
crypto_aead_xchacha20poly1305_ietf_KEYBYTES
|
||||
|
||||
#define crypto_secretstream_xchacha20poly1305_MESSAGESBYTES_MAX \
|
||||
((1ULL << 32) - 2ULL * 64ULL)
|
||||
|
||||
#define crypto_secretstream_xchacha20poly1305_TAG_MESSAGE 0x00
|
||||
#define crypto_secretstream_xchacha20poly1305_TAG_PUSH 0x01
|
||||
#define crypto_secretstream_xchacha20poly1305_TAG_REKEY 0x02
|
||||
|
||||
#define crypto_secretstream_xchacha20poly1305_TAG_FINAL \
|
||||
(crypto_secretstream_xchacha20poly1305_TAG_PUSH | \
|
||||
crypto_secretstream_xchacha20poly1305_TAG_REKEY)
|
||||
|
||||
typedef struct crypto_secretstream_xchacha20poly1305_state {
|
||||
unsigned char k[crypto_stream_chacha20_ietf_KEYBYTES];
|
||||
unsigned char nonce[crypto_stream_chacha20_ietf_NONCEBYTES];
|
||||
unsigned char _pad[8];
|
||||
} crypto_secretstream_xchacha20poly1305_state;
|
||||
|
||||
SODIUM_EXPORT
|
||||
size_t crypto_secretstream_xchacha20poly1305_statebytes(void);
|
||||
|
||||
SODIUM_EXPORT
|
||||
void crypto_secretstream_xchacha20poly1305_keygen
|
||||
(unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES]);
|
||||
|
||||
SODIUM_EXPORT
|
||||
int crypto_secretstream_xchacha20poly1305_init_push
|
||||
(crypto_secretstream_xchacha20poly1305_state *state,
|
||||
unsigned char out[crypto_secretstream_xchacha20poly1305_INITBYTES],
|
||||
const unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES]);
|
||||
|
||||
SODIUM_EXPORT
|
||||
int crypto_secretstream_xchacha20poly1305_init_pull
|
||||
(crypto_secretstream_xchacha20poly1305_state *state,
|
||||
const unsigned char in[crypto_secretstream_xchacha20poly1305_INITBYTES],
|
||||
const unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES]);
|
||||
|
||||
SODIUM_EXPORT
|
||||
void crypto_secretstream_xchacha20poly1305_rekey
|
||||
(crypto_secretstream_xchacha20poly1305_state *state);
|
||||
|
||||
SODIUM_EXPORT
|
||||
int crypto_secretstream_xchacha20poly1305_push
|
||||
(crypto_secretstream_xchacha20poly1305_state *state,
|
||||
unsigned char *out, unsigned long long *outlen_p,
|
||||
const unsigned char *m, unsigned long long mlen,
|
||||
const unsigned char *ad, unsigned long long adlen, unsigned char tag);
|
||||
|
||||
SODIUM_EXPORT
|
||||
int crypto_secretstream_xchacha20poly1305_pull
|
||||
(crypto_secretstream_xchacha20poly1305_state *state,
|
||||
unsigned char *m, unsigned long long *mlen_p, unsigned char *tag_p,
|
||||
const unsigned char *in, unsigned long long inlen,
|
||||
const unsigned char *ad, unsigned long long adlen);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user