Clarify the ChaCha20-Poly1305 assembly functions' final parameters.
The memcpy of a pointer looks like a typo, though it isn't. Instead, transcribe what the functions expect into a union and let C fill it in. Change-Id: Iba4c824295e8908c5bda68ac35673040a8cff116 Reviewed-on: https://boringssl-review.googlesource.com/18744 Commit-Queue: David Benjamin <davidben@google.com> Commit-Queue: Adam Langley <agl@google.com> Reviewed-by: Adam Langley <agl@google.com> CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
This commit is contained in:
parent
b0c761eb76
commit
8d200744b4
@ -22,6 +22,7 @@
|
|||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
#include <openssl/mem.h>
|
#include <openssl/mem.h>
|
||||||
#include <openssl/poly1305.h>
|
#include <openssl/poly1305.h>
|
||||||
|
#include <openssl/type_check.h>
|
||||||
|
|
||||||
#include "../fipsmodule/cipher/internal.h"
|
#include "../fipsmodule/cipher/internal.h"
|
||||||
#include "../internal.h"
|
#include "../internal.h"
|
||||||
@ -30,7 +31,34 @@
|
|||||||
#define POLY1305_TAG_LEN 16
|
#define POLY1305_TAG_LEN 16
|
||||||
|
|
||||||
struct aead_chacha20_poly1305_ctx {
|
struct aead_chacha20_poly1305_ctx {
|
||||||
unsigned char key[32];
|
uint8_t key[32];
|
||||||
|
};
|
||||||
|
|
||||||
|
// For convenience (the x86_64 calling convention allows only six parameters in
|
||||||
|
// registers), the final parameter for the assembly functions is both an input
|
||||||
|
// and output parameter.
|
||||||
|
union open_data {
|
||||||
|
struct {
|
||||||
|
alignas(16) uint8_t key[32];
|
||||||
|
uint32_t counter;
|
||||||
|
uint8_t nonce[12];
|
||||||
|
} in;
|
||||||
|
struct {
|
||||||
|
uint8_t tag[POLY1305_TAG_LEN];
|
||||||
|
} out;
|
||||||
|
};
|
||||||
|
|
||||||
|
union seal_data {
|
||||||
|
struct {
|
||||||
|
alignas(16) uint8_t key[32];
|
||||||
|
uint32_t counter;
|
||||||
|
uint8_t nonce[12];
|
||||||
|
const uint8_t *extra_ciphertext;
|
||||||
|
size_t extra_ciphertext_len;
|
||||||
|
} in;
|
||||||
|
struct {
|
||||||
|
uint8_t tag[POLY1305_TAG_LEN];
|
||||||
|
} out;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(OPENSSL_X86_64) && !defined(OPENSSL_NO_ASM) && \
|
#if defined(OPENSSL_X86_64) && !defined(OPENSSL_NO_ASM) && \
|
||||||
@ -40,42 +68,42 @@ static int asm_capable(void) {
|
|||||||
return sse41_capable;
|
return sse41_capable;
|
||||||
}
|
}
|
||||||
|
|
||||||
// chacha20_poly1305_open is defined in chacha20_poly1305_x86_64.pl. It
|
OPENSSL_COMPILE_ASSERT(sizeof(union open_data) == 48, wrong_open_data_size);
|
||||||
// decrypts |plaintext_len| bytes from |ciphertext| and writes them to
|
OPENSSL_COMPILE_ASSERT(sizeof(union seal_data) == 48 + 8 + 8,
|
||||||
// |out_plaintext|. On entry, |aead_data| must contain the final 48 bytes of
|
wrong_seal_data_size);
|
||||||
// the initial ChaCha20 block, i.e. the key, followed by four zeros, followed
|
|
||||||
// by the nonce. On exit, it will contain the calculated tag value, which the
|
// chacha20_poly1305_open is defined in chacha20_poly1305_x86_64.pl. It decrypts
|
||||||
// caller must check.
|
// |plaintext_len| bytes from |ciphertext| and writes them to |out_plaintext|.
|
||||||
|
// Additional input parameters are passed in |aead_data->in|. On exit, it will
|
||||||
|
// write calculated tag value to |aead_data->out.tag|, which the caller must
|
||||||
|
// check.
|
||||||
extern void chacha20_poly1305_open(uint8_t *out_plaintext,
|
extern void chacha20_poly1305_open(uint8_t *out_plaintext,
|
||||||
const uint8_t *ciphertext,
|
const uint8_t *ciphertext,
|
||||||
size_t plaintext_len, const uint8_t *ad,
|
size_t plaintext_len, const uint8_t *ad,
|
||||||
size_t ad_len, uint8_t *aead_data);
|
size_t ad_len, union open_data *aead_data);
|
||||||
|
|
||||||
// chacha20_poly1305_open is defined in chacha20_poly1305_x86_64.pl. It
|
// chacha20_poly1305_open is defined in chacha20_poly1305_x86_64.pl. It encrypts
|
||||||
// encrypts |plaintext_len| bytes from |plaintext| and writes them to
|
// |plaintext_len| bytes from |plaintext| and writes them to |out_ciphertext|.
|
||||||
// |out_ciphertext|. On entry, |aead_data| must contain the final 48 bytes of
|
// Additional input parameters are passed in |aead_data->in|. The calculated tag
|
||||||
// the initial ChaCha20 block, i.e. the key, followed by four zeros, followed
|
// value is over the computed ciphertext concatenated with |extra_ciphertext|
|
||||||
// by the nonce. On exit, it will contain the calculated tag value, which the
|
// and written to |aead_data->out.tag|.
|
||||||
// caller must append to the ciphertext.
|
|
||||||
extern void chacha20_poly1305_seal(uint8_t *out_ciphertext,
|
extern void chacha20_poly1305_seal(uint8_t *out_ciphertext,
|
||||||
const uint8_t *plaintext,
|
const uint8_t *plaintext,
|
||||||
size_t plaintext_len, const uint8_t *ad,
|
size_t plaintext_len, const uint8_t *ad,
|
||||||
size_t ad_len, uint8_t *aead_data);
|
size_t ad_len, union seal_data *aead_data);
|
||||||
#else
|
#else
|
||||||
static int asm_capable(void) {
|
static int asm_capable(void) { return 0; }
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void chacha20_poly1305_open(uint8_t *out_plaintext,
|
static void chacha20_poly1305_open(uint8_t *out_plaintext,
|
||||||
const uint8_t *ciphertext,
|
const uint8_t *ciphertext,
|
||||||
size_t plaintext_len, const uint8_t *ad,
|
size_t plaintext_len, const uint8_t *ad,
|
||||||
size_t ad_len, uint8_t *aead_data) {}
|
size_t ad_len, union open_data *aead_data) {}
|
||||||
|
|
||||||
static void chacha20_poly1305_seal(uint8_t *out_ciphertext,
|
static void chacha20_poly1305_seal(uint8_t *out_ciphertext,
|
||||||
const uint8_t *plaintext,
|
const uint8_t *plaintext,
|
||||||
size_t plaintext_len, const uint8_t *ad,
|
size_t plaintext_len, const uint8_t *ad,
|
||||||
size_t ad_len, uint8_t *aead_data) {}
|
size_t ad_len, union seal_data *aead_data) {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int aead_chacha20_poly1305_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
|
static int aead_chacha20_poly1305_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
|
||||||
@ -212,22 +240,21 @@ static int aead_chacha20_poly1305_seal_scatter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
alignas(16) uint8_t tag[48 + 8 + 8];
|
union seal_data data;
|
||||||
|
|
||||||
if (asm_capable()) {
|
if (asm_capable()) {
|
||||||
OPENSSL_memcpy(tag, c20_ctx->key, 32);
|
OPENSSL_memcpy(data.in.key, c20_ctx->key, 32);
|
||||||
OPENSSL_memset(tag + 32, 0, 4);
|
data.in.counter = 0;
|
||||||
OPENSSL_memcpy(tag + 32 + 4, nonce, 12);
|
OPENSSL_memcpy(data.in.nonce, nonce, 12);
|
||||||
OPENSSL_memcpy(tag + 48, &out_tag, sizeof(out_tag));
|
data.in.extra_ciphertext = out_tag;
|
||||||
OPENSSL_memcpy(tag + 56, &extra_in_len, sizeof(extra_in_len));
|
data.in.extra_ciphertext_len = extra_in_len;
|
||||||
chacha20_poly1305_seal(out, in, in_len, ad, ad_len, tag);
|
chacha20_poly1305_seal(out, in, in_len, ad, ad_len, &data);
|
||||||
} else {
|
} else {
|
||||||
CRYPTO_chacha_20(out, in, in_len, c20_ctx->key, nonce, 1);
|
CRYPTO_chacha_20(out, in, in_len, c20_ctx->key, nonce, 1);
|
||||||
calc_tag(tag, c20_ctx, nonce, ad, ad_len, out, in_len,
|
calc_tag(data.out.tag, c20_ctx, nonce, ad, ad_len, out, in_len, out_tag,
|
||||||
out_tag, extra_in_len);
|
extra_in_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
OPENSSL_memcpy(out_tag + extra_in_len, tag, ctx->tag_len);
|
OPENSSL_memcpy(out_tag + extra_in_len, data.out.tag, ctx->tag_len);
|
||||||
*out_tag_len = extra_in_len + ctx->tag_len;
|
*out_tag_len = extra_in_len + ctx->tag_len;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -260,19 +287,18 @@ static int aead_chacha20_poly1305_open_gather(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
alignas(16) uint8_t tag[48];
|
union open_data data;
|
||||||
|
|
||||||
if (asm_capable()) {
|
if (asm_capable()) {
|
||||||
OPENSSL_memcpy(tag, c20_ctx->key, 32);
|
OPENSSL_memcpy(data.in.key, c20_ctx->key, 32);
|
||||||
OPENSSL_memset(tag + 32, 0, 4);
|
data.in.counter = 0;
|
||||||
OPENSSL_memcpy(tag + 32 + 4, nonce, 12);
|
OPENSSL_memcpy(data.in.nonce, nonce, 12);
|
||||||
chacha20_poly1305_open(out, in, in_len, ad, ad_len, tag);
|
chacha20_poly1305_open(out, in, in_len, ad, ad_len, &data);
|
||||||
} else {
|
} else {
|
||||||
calc_tag(tag, c20_ctx, nonce, ad, ad_len, in, in_len, NULL, 0);
|
calc_tag(data.out.tag, c20_ctx, nonce, ad, ad_len, in, in_len, NULL, 0);
|
||||||
CRYPTO_chacha_20(out, in, in_len, c20_ctx->key, nonce, 1);
|
CRYPTO_chacha_20(out, in, in_len, c20_ctx->key, nonce, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CRYPTO_memcmp(tag, in_tag, ctx->tag_len) != 0) {
|
if (CRYPTO_memcmp(data.out.tag, in_tag, ctx->tag_len) != 0) {
|
||||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
|
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user