From e2ec048a09889b2bf71e8bbfef9f0584ff7d69db Mon Sep 17 00:00:00 2001 From: Jakob Unterwurzacher Date: Sat, 4 Sep 2021 11:41:56 +0200 Subject: 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) --- internal/stupidgcm/chacha.c | 194 -------------------------------------------- 1 file changed, 194 deletions(-) delete mode 100644 internal/stupidgcm/chacha.c (limited to 'internal/stupidgcm/chacha.c') 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 -#include -//#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; -} -- cgit v1.2.3