Move poly1305_get_tag() into poly1305.c, hide poly1305_init().
[tinc] / src / sptps.c
index 7be8cd8..b36079d 100644 (file)
@@ -1,6 +1,6 @@
 /*
     sptps.c -- Simple Peer-to-Peer Security
-    Copyright (C) 2011-2015 Guus Sliepen <guus@tinc-vpn.org>,
+    Copyright (C) 2011-2021 Guus Sliepen <guus@tinc-vpn.org>,
                   2010      Brandon L. Black <blblack@gmail.com>
 
     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 <openssl/evp.h>
 #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: