X-Git-Url: http://tinc-vpn.org/git/browse?a=blobdiff_plain;f=src%2Fsptps.c;h=b36079d3d73b33472c4294ee9d5bda394cc0cc19;hb=refs%2Fheads%2Ffeature%2Falt-ciphersuite;hp=7be8cd8070ca5fc9ca0dd690d7e53b390459b1e4;hpb=ad2e8db4730e3c4355db2cea911422e7efd6a1ee;p=tinc diff --git a/src/sptps.c b/src/sptps.c index 7be8cd80..b36079d3 100644 --- a/src/sptps.c +++ b/src/sptps.c @@ -1,6 +1,6 @@ /* sptps.c -- Simple Peer-to-Peer Security - Copyright (C) 2011-2015 Guus Sliepen , + Copyright (C) 2011-2021 Guus Sliepen , 2010 Brandon L. Black This program is free software; you can redistribute it and/or modify @@ -20,7 +20,7 @@ #include "system.h" -#include "chacha-poly1305/chacha-poly1305.h" +#include "chacha-poly1305/chachapoly.h" #include "ecdh.h" #include "ecdsa.h" #include "prf.h" @@ -32,6 +32,8 @@ #include #endif +#define CIPHER_KEYLEN 64 + unsigned int sptps_replaywin = 16; /* @@ -113,23 +115,37 @@ static void free_sptps_key(sptps_key_t *key) { } static bool cipher_init(uint8_t suite, void **ctx, const sptps_key_t *keys, bool key_half) { - const uint8_t *key = key_half ? keys->key1 : keys->key0; + const uint8_t *key = key_half ? keys->key1 : keys->key0; switch(suite) { +#ifndef HAVE_OPENSSL + case SPTPS_CHACHA_POLY1305: - *ctx = chacha_poly1305_init(); - return ctx && chacha_poly1305_set_key(*ctx, key); + *ctx = malloc(sizeof(struct chachapoly_ctx)); + return *ctx && chachapoly_init(*ctx, key, 256) == CHACHAPOLY_OK; - case SPTPS_AES256_GCM: -#ifdef HAVE_OPENSSL +#else + + case SPTPS_CHACHA_POLY1305: +#ifdef EVP_F_EVP_AEAD_CTX_INIT + *ctx = malloc(sizeof(EVP_AEAD_CTX)); + + return *ctx && EVP_AEAD_CTX_init(*ctx, EVP_aead_chacha20_poly1305(), key + (key_half ? CIPHER_KEYLEN : 0), 32, 16, NULL); +#else *ctx = EVP_CIPHER_CTX_new(); - if(!ctx) { - return false; - } + return *ctx + && EVP_EncryptInit_ex(*ctx, EVP_chacha20_poly1305(), NULL, NULL, NULL) + && EVP_CIPHER_CTX_ctrl(*ctx, EVP_CTRL_GCM_SET_IVLEN, 12, NULL) + && EVP_EncryptInit_ex(*ctx, NULL, NULL, key, key + 32); +#endif + + case SPTPS_AES256_GCM: + *ctx = EVP_CIPHER_CTX_new(); - return EVP_EncryptInit_ex(*ctx, EVP_aes_256_gcm(), NULL, NULL, NULL) - && EVP_CIPHER_CTX_ctrl(*ctx, EVP_CTRL_AEAD_SET_IVLEN, 4, NULL) + return *ctx + && EVP_EncryptInit_ex(*ctx, EVP_aes_256_gcm(), NULL, NULL, NULL) + && EVP_CIPHER_CTX_ctrl(*ctx, EVP_CTRL_GCM_SET_IVLEN, 12, NULL) && EVP_EncryptInit_ex(*ctx, NULL, NULL, key, key + 32); #endif @@ -140,12 +156,22 @@ static bool cipher_init(uint8_t suite, void **ctx, const sptps_key_t *keys, bool static void cipher_exit(uint8_t suite, void *ctx) { switch(suite) { +#ifndef HAVE_OPENSSL + case SPTPS_CHACHA_POLY1305: - chacha_poly1305_exit(ctx); + free(ctx); break; +#else + + case SPTPS_CHACHA_POLY1305: +#ifdef EVP_F_EVP_AEAD_CTX_INIT + EVP_AEAD_CTX_cleanup(ctx); + free(ctx); + break; +#endif + case SPTPS_AES256_GCM: -#ifdef HAVE_OPENSSL EVP_CIPHER_CTX_free(ctx); break; #endif @@ -157,35 +183,31 @@ static void cipher_exit(uint8_t suite, void *ctx) { static bool cipher_encrypt(uint8_t suite, void *ctx, uint32_t seqno, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) { switch(suite) { - case SPTPS_CHACHA_POLY1305: - chacha_poly1305_encrypt(ctx, seqno, in, inlen, out, outlen); - return true; +#ifndef HAVE_OPENSSL - case SPTPS_AES256_GCM: -#ifdef HAVE_OPENSSL - { - if(!EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, (uint8_t *)&seqno)) { - return false; - } + case SPTPS_CHACHA_POLY1305: { + if(chachapoly_crypt(ctx, nonce, (void *)in, inlen, out, out + inlen, 16, 1) != CHACHAPOLY_OK) { + return false; + } - int outlen1 = 0, outlen2 = 0; + if(outlen) { + *outlen = inlen + 16; + } - if(!EVP_EncryptUpdate(ctx, out, &outlen1, in, (int)inlen)) { - return false; - } + return true; + } - if(!EVP_EncryptFinal_ex(ctx, out + outlen1, &outlen2)) { - return false; - } +#else - outlen1 += outlen2; + case SPTPS_CHACHA_POLY1305: +#ifdef EVP_F_EVP_AEAD_CTX_INIT + { + size_t outlen1; - if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, out + outlen1)) { + if(!EVP_AEAD_CTX_seal(ctx, out, &outlen1, inlen + 16, nonce, sizeof(nonce), in, inlen, NULL, 0)) { return false; } - outlen1 += 16; - if(outlen) { *outlen = outlen1; } @@ -193,6 +215,40 @@ static bool cipher_encrypt(uint8_t suite, void *ctx, uint32_t seqno, const uint8 return true; } +#endif + + case SPTPS_AES256_GCM: { + uint8_t nonce[12] = {seqno, seqno >> 8, seqno >> 16, seqno >> 24}; + + if(!EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, nonce)) { + return false; + } + + int outlen1 = 0, outlen2 = 0; + + if(!EVP_EncryptUpdate(ctx, out, &outlen1, in, (int)inlen)) { + return false; + } + + if(!EVP_EncryptFinal_ex(ctx, out + outlen1, &outlen2)) { + return false; + } + + outlen1 += outlen2; + + if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, out + outlen1)) { + return false; + } + + outlen1 += 16; + + if(outlen) { + *outlen = outlen1; + } + + return true; + } + #endif default: @@ -201,44 +257,74 @@ static bool cipher_encrypt(uint8_t suite, void *ctx, uint32_t seqno, const uint8 } static bool cipher_decrypt(uint8_t suite, void *ctx, uint32_t seqno, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) { - switch(suite) { - case SPTPS_CHACHA_POLY1305: - return chacha_poly1305_decrypt(ctx, seqno, in, inlen, out, outlen); + if(inlen < 16) { + return false; + } - case SPTPS_AES256_GCM: -#ifdef HAVE_OPENSSL - { - if(inlen < 16) { - return false; - } + inlen -= 16; - inlen -= 16; + switch(suite) { +#ifndef HAVE_OPENSSL - if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, (uint8_t *)&seqno)) { - return false; - } + case SPTPS_CHACHA_POLY1305: + if(chachapoly_crypt(ctx, nonce, (void *)in, inlen, out, (void *)(in + inlen), 16, 0) != CHACHAPOLY_OK) { + return false; + } - int outlen1 = 0, outlen2 = 0; + if(outlen) { + *outlen = inlen; + } - if(!EVP_DecryptUpdate(ctx, out, &outlen1, in, (int)inlen)) { - return false; - } + return true; - if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, (void *)(in + inlen))) { - return false; - } +#else - if(!EVP_DecryptFinal_ex(ctx, out + outlen1, &outlen2)) { + case SPTPS_CHACHA_POLY1305: +#ifdef EVP_F_EVP_AEAD_CTX_INIT + { + size_t outlen1; + + if(!EVP_AEAD_CTX_open(ctx, out, &outlen1, inlen, nonce, sizeof(nonce), in, inlen + 16, NULL, 0)) { return false; } if(outlen) { - *outlen = outlen1 + outlen2; + *outlen = outlen1; } return true; } +#endif + + case SPTPS_AES256_GCM: { + uint8_t nonce[12] = {seqno, seqno >> 8, seqno >> 16, seqno >> 24}; + + if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, nonce)) { + return false; + } + + int outlen1 = 0, outlen2 = 0; + + if(!EVP_DecryptUpdate(ctx, out, &outlen1, in, (int)inlen)) { + return false; + } + + if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, (void *)(in + inlen))) { + return false; + } + + if(!EVP_DecryptFinal_ex(ctx, out + outlen1, &outlen2)) { + return false; + } + + if(outlen) { + *outlen = outlen1 + outlen2; + } + + return true; + } + #endif default: