aboutsummaryrefslogtreecommitdiff
path: root/internal/stupidgcm/chacha.c
diff options
context:
space:
mode:
authorJakob Unterwurzacher2021-09-04 11:41:56 +0200
committerJakob Unterwurzacher2021-09-07 18:14:05 +0200
commite2ec048a09889b2bf71e8bbfef9f0584ff7d69db (patch)
tree84bb1f8c709f8db3b2dd551c7c5343c0ffe44ed9 /internal/stupidgcm/chacha.c
parentbf572aef88963732849b8e5ae679e63c6be4aa46 (diff)
stupidgcm: introduce stupidAEADCommon and use for both chacha & gcm
Nice deduplication and brings the GCM decrypt speed up to par. internal/speed$ benchstat old new name old time/op new time/op delta StupidGCM-4 4.71µs ± 0% 4.66µs ± 0% -0.99% (p=0.008 n=5+5) StupidGCMDecrypt-4 5.77µs ± 1% 4.51µs ± 0% -21.80% (p=0.008 n=5+5) name old speed new speed delta StupidGCM-4 870MB/s ± 0% 879MB/s ± 0% +1.01% (p=0.008 n=5+5) StupidGCMDecrypt-4 710MB/s ± 1% 908MB/s ± 0% +27.87% (p=0.008 n=5+5)
Diffstat (limited to 'internal/stupidgcm/chacha.c')
-rw-r--r--internal/stupidgcm/chacha.c194
1 files changed, 0 insertions, 194 deletions
diff --git a/internal/stupidgcm/chacha.c b/internal/stupidgcm/chacha.c
deleted file mode 100644
index 05d68af..0000000
--- a/internal/stupidgcm/chacha.c
+++ /dev/null
@@ -1,194 +0,0 @@
-#include "chacha.h"
-#include <openssl/evp.h>
-#include <stdio.h>
-//#cgo pkg-config: libcrypto
-
-static void panic(const char* const msg)
-{
- fprintf(stderr, "panic in C code: %s\n", msg);
- __builtin_trap();
-}
-
-static const EVP_CIPHER* getEvpCipher(enum aeadType cipherId)
-{
- switch (cipherId) {
- case aeadTypeChacha:
- return EVP_chacha20_poly1305();
- case aeadTypeGcm:
- return EVP_aes_256_gcm();
- }
- panic("unknown cipherId");
- return NULL;
-}
-
-// We only support 16-byte tags
-static const int supportedTagLen = 16;
-
-// https://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption#Authenticated_Encryption_using_GCM_mode
-int aead_seal(
- const enum aeadType cipherId,
- const unsigned char* const plaintext,
- const int plaintextLen,
- const unsigned char* const authData,
- const int authDataLen,
- const unsigned char* const key,
- const int keyLen,
- const unsigned char* const iv,
- const int ivLen,
- unsigned char* const ciphertext,
- const int ciphertextBufLen)
-{
- const EVP_CIPHER* evpCipher = getEvpCipher(cipherId);
-
- // Create scratch space "ctx"
- EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
- if (!ctx) {
- panic("EVP_CIPHER_CTX_new failed");
- }
-
- // Set cipher
- if (EVP_EncryptInit_ex(ctx, evpCipher, NULL, NULL, NULL) != 1) {
- panic("EVP_EncryptInit_ex set cipher failed");
- }
-
- // Check keyLen by trying to set it (fails if keyLen != 32)
- if (EVP_CIPHER_CTX_set_key_length(ctx, keyLen) != 1) {
- panic("keyLen mismatch");
- }
-
- // Set IV length so we do not depend on the default
- if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, ivLen, NULL) != 1) {
- panic("EVP_CTRL_AEAD_SET_IVLEN failed");
- }
-
- // Set key and IV
- if (EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv) != 1) {
- panic("EVP_EncryptInit_ex set key & iv failed");
- }
-
- // Provide authentication data
- int outLen = 0;
- if (EVP_EncryptUpdate(ctx, NULL, &outLen, authData, authDataLen) != 1) {
- panic("EVP_EncryptUpdate authData failed");
- }
- if (outLen != authDataLen) {
- panic("EVP_EncryptUpdate authData: unexpected length");
- }
-
- // Encrypt "plaintext" into "ciphertext"
- if (plaintextLen > ciphertextBufLen) {
- panic("plaintext overflows output buffer");
- }
- if (EVP_EncryptUpdate(ctx, ciphertext, &outLen, plaintext, plaintextLen) != 1) {
- panic("EVP_EncryptUpdate ciphertext failed");
- }
- if (outLen != plaintextLen) {
- panic("EVP_EncryptUpdate ciphertext: unexpected length");
- }
- int ciphertextLen = outLen;
-
- // Finalise encryption
- // Normally ciphertext bytes may be written at this stage, but this does not occur in GCM mode
- if (EVP_EncryptFinal_ex(ctx, ciphertext + plaintextLen, &outLen) != 1) {
- panic("EVP_EncryptFinal_ex failed");
- }
- if (outLen != 0) {
- panic("EVP_EncryptFinal_ex: unexpected length");
- }
-
- // Get MAC tag and append it to the ciphertext
- if (ciphertextLen + supportedTagLen > ciphertextBufLen) {
- panic("tag overflows output buffer");
- }
- if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, supportedTagLen, ciphertext + plaintextLen) != 1) {
- panic("EVP_CTRL_AEAD_GET_TAG failed");
- }
- ciphertextLen += supportedTagLen;
-
- // Free scratch space
- EVP_CIPHER_CTX_free(ctx);
-
- return ciphertextLen;
-}
-
-int aead_open(
- const enum aeadType cipherId,
- const unsigned char* const ciphertext,
- const int ciphertextLen,
- const unsigned char* const authData,
- const int authDataLen,
- unsigned char* const tag,
- const int tagLen,
- const unsigned char* const key,
- const int keyLen,
- const unsigned char* const iv,
- const int ivLen,
- unsigned char* const plaintext,
- const int plaintextBufLen)
-{
- const EVP_CIPHER* evpCipher = getEvpCipher(cipherId);
-
- // Create scratch space "ctx"
- EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
- if (!ctx) {
- panic("EVP_CIPHER_CTX_new failed");
- }
-
- // Set cipher
- if (EVP_DecryptInit_ex(ctx, evpCipher, NULL, NULL, NULL) != 1) {
- panic("EVP_DecryptInit_ex set cipher failed");
- }
-
- // Check keyLen by trying to set it (fails if keyLen != 32)
- if (EVP_CIPHER_CTX_set_key_length(ctx, keyLen) != 1) {
- panic("keyLen mismatch");
- }
-
- // Set IV length so we do not depend on the default
- if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, ivLen, NULL) != 1) {
- panic("EVP_CTRL_AEAD_SET_IVLEN failed");
- }
-
- // Set key and IV
- if (EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv) != 1) {
- panic("EVP_DecryptInit_ex set key & iv failed");
- }
-
- // Provide authentication data
- int outLen = 0;
- if (EVP_DecryptUpdate(ctx, NULL, &outLen, authData, authDataLen) != 1) {
- panic("EVP_DecryptUpdate authData failed");
- }
- if (outLen != authDataLen) {
- panic("EVP_DecryptUpdate authData: unexpected length");
- }
-
- // Decrypt "ciphertext" into "plaintext"
- if (ciphertextLen > plaintextBufLen) {
- panic("ciphertextLen overflows output buffer");
- }
- if (EVP_DecryptUpdate(ctx, plaintext, &outLen, ciphertext, ciphertextLen) != 1) {
- panic("EVP_DecryptUpdate failed");
- }
- int plaintextLen = outLen;
-
- // Check tag
- if (tagLen != supportedTagLen) {
- panic("unsupported tag length");
- }
- if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, tagLen, tag) != 1) {
- panic("EVP_CTRL_AEAD_SET_TAG failed");
- }
- if (EVP_DecryptFinal_ex(ctx, plaintext + plaintextLen, &outLen) != 1) {
- // authentication failed
- return -1;
- }
- if (outLen != 0) {
- panic("EVP_EncryptFinal_ex: unexpected length");
- }
-
- /* Clean up */
- EVP_CIPHER_CTX_free(ctx);
-
- return plaintextLen;
-}