Skip to content

Commit

Permalink
Use OpenSSL for Chacha20-Poly1305
Browse files Browse the repository at this point in the history
  • Loading branch information
dechamps committed Jan 6, 2018
1 parent bdeba3f commit 73d7ec1
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 72 deletions.
106 changes: 36 additions & 70 deletions src/chacha-poly1305/chacha-poly1305.c
Original file line number Diff line number Diff line change
@@ -1,103 +1,69 @@
#include "../system.h"

#include "../cipher.h"
#include "../xalloc.h"
#include <openssl/evp.h>

#include "chacha.h"
#include "chacha-poly1305.h"
#include "poly1305.h"
#include "../xalloc.h"

#define TAGLEN 16

struct chacha_poly1305_ctx {
struct chacha_ctx main_ctx, header_ctx;
EVP_CIPHER_CTX *evp_cipher_ctx;
};

chacha_poly1305_ctx_t *chacha_poly1305_init(void) {
chacha_poly1305_ctx_t *ctx = xzalloc(sizeof(*ctx));
ctx->evp_cipher_ctx = EVP_CIPHER_CTX_new();
return ctx;
}

void chacha_poly1305_exit(chacha_poly1305_ctx_t *ctx) {
EVP_CIPHER_CTX_free(ctx->evp_cipher_ctx);
free(ctx);
}

bool chacha_poly1305_set_key(chacha_poly1305_ctx_t *ctx, const void *key) {
chacha_keysetup(&ctx->main_ctx, key, 256);
chacha_keysetup(&ctx->header_ctx, key + 32, 256);
EVP_EncryptInit_ex(ctx->evp_cipher_ctx, EVP_chacha20_poly1305(), NULL, key, NULL);
return true;
}

static void put_u64(void *vp, uint64_t v) {
uint8_t *p = (uint8_t *) vp;

p[0] = (uint8_t)(v >> 56) & 0xff;
p[1] = (uint8_t)(v >> 48) & 0xff;
p[2] = (uint8_t)(v >> 40) & 0xff;
p[3] = (uint8_t)(v >> 32) & 0xff;
p[4] = (uint8_t)(v >> 24) & 0xff;
p[5] = (uint8_t)(v >> 16) & 0xff;
p[6] = (uint8_t)(v >> 8) & 0xff;
p[7] = (uint8_t) v & 0xff;
}

bool chacha_poly1305_encrypt(chacha_poly1305_ctx_t *ctx, uint64_t seqnr, const void *indata, size_t inlen, void *outdata, size_t *outlen) {
uint8_t seqbuf[8];
const uint8_t one[8] = { 1, 0, 0, 0, 0, 0, 0, 0 }; /* NB little-endian */
uint8_t poly_key[POLY1305_KEYLEN];

/*
* Run ChaCha20 once to generate the Poly1305 key. The IV is the
* packet sequence number.
*/
memset(poly_key, 0, sizeof(poly_key));
put_u64(seqbuf, seqnr);
chacha_ivsetup(&ctx->main_ctx, seqbuf, NULL);
chacha_encrypt_bytes(&ctx->main_ctx, poly_key, poly_key, sizeof(poly_key));

/* Set Chacha's block counter to 1 */
chacha_ivsetup(&ctx->main_ctx, seqbuf, one);

chacha_encrypt_bytes(&ctx->main_ctx, indata, outdata, inlen);
poly1305_auth(outdata + inlen, outdata, inlen, poly_key);

if(outlen) {
*outlen = inlen + POLY1305_TAGLEN;
int outlen_int;
unsigned char* outdata_char = outdata;
if(!EVP_EncryptUpdate(ctx->evp_cipher_ctx, outdata_char, &outlen_int, indata, inlen)) {
return false;
}

outdata_char += outlen_int;
if(!EVP_EncryptFinal_ex(ctx->evp_cipher_ctx, outdata_char, &outlen_int)) {
return false;
}
outdata_char += outlen_int;
if(!EVP_CIPHER_CTX_ctrl(ctx->evp_cipher_ctx, EVP_CTRL_AEAD_GET_TAG, TAGLEN, outdata_char)) {
return false;
}
outdata_char += TAGLEN;
if(outlen) *outlen = outdata_char - ((unsigned char*)outdata);
return true;
}

bool chacha_poly1305_decrypt(chacha_poly1305_ctx_t *ctx, uint64_t seqnr, const void *indata, size_t inlen, void *outdata, size_t *outlen) {
uint8_t seqbuf[8];
const uint8_t one[8] = { 1, 0, 0, 0, 0, 0, 0, 0 }; /* NB little-endian */
uint8_t expected_tag[POLY1305_TAGLEN], poly_key[POLY1305_KEYLEN];

/*
* Run ChaCha20 once to generate the Poly1305 key. The IV is the
* packet sequence number.
*/
memset(poly_key, 0, sizeof(poly_key));
put_u64(seqbuf, seqnr);
chacha_ivsetup(&ctx->main_ctx, seqbuf, NULL);
chacha_encrypt_bytes(&ctx->main_ctx, poly_key, poly_key, sizeof(poly_key));

/* Set Chacha's block counter to 1 */
chacha_ivsetup(&ctx->main_ctx, seqbuf, one);

/* Check tag before anything else */
inlen -= POLY1305_TAGLEN;
const uint8_t *tag = indata + inlen;

poly1305_auth(expected_tag, indata, inlen, poly_key);

if(memcmp(expected_tag, tag, POLY1305_TAGLEN)) {
inlen -= TAGLEN;
const unsigned char* indata_char = indata;
if(!EVP_CIPHER_CTX_ctrl(ctx->evp_cipher_ctx, EVP_CTRL_AEAD_SET_TAG, TAGLEN, indata_char + inlen)) {
return false;
}

chacha_encrypt_bytes(&ctx->main_ctx, indata, outdata, inlen);

if(outlen) {
*outlen = inlen;
int outlen_int;
unsigned char* outdata_char = outdata;
if(!EVP_DecryptUpdate(ctx->evp_cipher_ctx, outdata_char, &outlen_int, indata_char, inlen)) {
return false;
}

outdata_char += outlen_int;
if(!EVP_DecryptFinal_ex(ctx->evp_cipher_ctx, outdata_char, &outlen_int)) {
return false;
}
outdata_char += outlen_int;
if(outlen) *outlen = outdata_char - ((unsigned char*)outdata);
return true;

}
4 changes: 2 additions & 2 deletions src/sptps.c
Original file line number Diff line number Diff line change
Expand Up @@ -730,8 +730,8 @@ bool sptps_start(sptps_t *s, void *handle, bool initiator, bool datagram, ecdsa_
// Stop a SPTPS session.
bool sptps_stop(sptps_t *s) {
// Clean up any resources.
chacha_poly1305_exit(s->incipher);
chacha_poly1305_exit(s->outcipher);
if (s->incipher) chacha_poly1305_exit(s->incipher);
if (s->outcipher) chacha_poly1305_exit(s->outcipher);
ecdh_free(s->ecdh);
free(s->inbuf);
free(s->mykex);
Expand Down

0 comments on commit 73d7ec1

Please sign in to comment.