-
Notifications
You must be signed in to change notification settings - Fork 258
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
stupidgcm: batch C calls in chacha20poly1305_seal
Go has a high overhead for each C call, so batch all openssl operations in the new C function chacha20poly1305_seal. Benchmark results: internal/speed$ go test -bench BenchmarkStupidXchacha -count 10 > old.txt internal/speed$ go test -bench BenchmarkStupidXchacha -count 10 > new.txt internal/speed$ benchstat old.txt new.txt name old time/op new time/op delta StupidXchacha-4 8.79µs ± 1% 7.25µs ± 1% -17.54% (p=0.000 n=10+10) name old speed new speed delta StupidXchacha-4 466MB/s ± 1% 565MB/s ± 1% +21.27% (p=0.000 n=10+10)
- Loading branch information
Showing
4 changed files
with
127 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
*.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
.PHONY: gcc | ||
gcc: | ||
gcc -Wall -Wextra -Wformat-security -Wconversion -lcrypto -c *.c | ||
|
||
.PHONY: format | ||
format: | ||
clang-format --style=WebKit -i *.c |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
#include <openssl/evp.h> | ||
#include <stdio.h> | ||
//#cgo pkg-config: libcrypto | ||
|
||
extern void panic1(void); | ||
|
||
static void panic(const char* const msg) | ||
{ | ||
fprintf(stderr, "panic in C code: %s\n", msg); | ||
__builtin_trap(); | ||
} | ||
|
||
// https://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption#Authenticated_Encryption_using_GCM_mode | ||
int chacha20poly1305_seal( | ||
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) | ||
{ | ||
// Create scratch space "context" | ||
EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new(); | ||
if (!ctx) { | ||
panic("EVP_CIPHER_CTX_new failed"); | ||
} | ||
|
||
// Set cipher | ||
if (EVP_EncryptInit_ex(ctx, EVP_chacha20_poly1305(), 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"); | ||
} | ||
|
||
// We only support 16-byte tags | ||
const int tagLen = 16; | ||
|
||
// Get MAC tag and append it to the ciphertext | ||
if (ciphertextLen + tagLen > ciphertextBufLen) { | ||
panic("tag overflows output buffer"); | ||
} | ||
if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, tagLen, ciphertext + plaintextLen) != 1) { | ||
panic("EVP_CTRL_AEAD_GET_TAG failed"); | ||
} | ||
ciphertextLen += tagLen; | ||
|
||
// Free scratch space | ||
EVP_CIPHER_CTX_free(ctx); | ||
|
||
return ciphertextLen; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters