}
}
}
+
+func BenchmarkGCMSeal(b *testing.B) {
+ key, _ := hex.DecodeString("ab72c77b97cb5fe9a382d9fe81ffdbed")
+ nonce, _ := hex.DecodeString("54cc7dc2c37ec006bcc6d1db")
+ plaintext, _ := hex.DecodeString("f1cc3818e421876bb6b8bbd6c9")
+
+ aes, _ := aes.NewCipher(key)
+ aesgcm, _ := cipher.NewGCM(aes)
+
+ ciphertext := make([]byte, 32)
+ b.SetBytes(int64(len(plaintext)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _ = aesgcm.Seal(ciphertext[:0], nonce, plaintext, nil)
+ }
+}
+
+func BenchmarkGCMOpen(b *testing.B) {
+ key, _ := hex.DecodeString("ab72c77b97cb5fe9a382d9fe81ffdbed")
+ nonce, _ := hex.DecodeString("54cc7dc2c37ec006bcc6d1db")
+ plaintext, _ := hex.DecodeString("f1cc3818e421876bb6b8bbd6c9")
+
+ aes, _ := aes.NewCipher(key)
+ aesgcm, _ := cipher.NewGCM(aes)
+
+ ciphertext := aesgcm.Seal(nil, nonce, plaintext, nil)
+
+ b.SetBytes(int64(len(ciphertext)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := aesgcm.Open(plaintext[:0], nonce, ciphertext, nil)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
package boring
/*
-
#include "goboringcrypto.h"
-
-// These wrappers allocate out_len on the C stack, and check that it matches the expected
-// value, to avoid having to pass a pointer from Go, which would escape to the heap.
-
-int EVP_AEAD_CTX_seal_wrapper(const GO_EVP_AEAD_CTX *ctx, uint8_t *out,
- size_t exp_out_len,
- const uint8_t *nonce, size_t nonce_len,
- const uint8_t *in, size_t in_len,
- const uint8_t *ad, size_t ad_len) {
- size_t out_len;
- int ok = _goboringcrypto_EVP_AEAD_CTX_seal(ctx, out, &out_len, exp_out_len,
- nonce, nonce_len, in, in_len, ad, ad_len);
- if (out_len != exp_out_len) {
- return 0;
- }
- return ok;
-};
-
-int EVP_AEAD_CTX_open_wrapper(const GO_EVP_AEAD_CTX *ctx, uint8_t *out,
- size_t exp_out_len,
- const uint8_t *nonce, size_t nonce_len,
- const uint8_t *in, size_t in_len,
- const uint8_t *ad, size_t ad_len) {
- size_t out_len;
- int ok = _goboringcrypto_EVP_AEAD_CTX_open(ctx, out, &out_len, exp_out_len,
- nonce, nonce_len, in, in_len, ad, ad_len);
- if (out_len != exp_out_len) {
- return 0;
- }
- return ok;
-};
-
+#cgo noescape _goboringcrypto_EVP_AEAD_CTX_seal
+#cgo nocallback _goboringcrypto_EVP_AEAD_CTX_seal
+#cgo noescape _goboringcrypto_EVP_AEAD_CTX_open
+#cgo nocallback _goboringcrypto_EVP_AEAD_CTX_open
*/
import "C"
import (
panic("cipher: invalid buffer overlap")
}
- outLen := C.size_t(len(plaintext) + gcmTagSize)
- ok := C.EVP_AEAD_CTX_seal_wrapper(
+ var outLen C.size_t
+ expOutLen := C.size_t(len(plaintext) + gcmTagSize)
+ ok := C._goboringcrypto_EVP_AEAD_CTX_seal(
&g.ctx,
- (*C.uint8_t)(unsafe.Pointer(&dst[n])), outLen,
+ (*C.uint8_t)(unsafe.Pointer(&dst[n])), &outLen, expOutLen,
base(nonce), C.size_t(len(nonce)),
base(plaintext), C.size_t(len(plaintext)),
base(additionalData), C.size_t(len(additionalData)))
runtime.KeepAlive(g)
- if ok == 0 {
+ if ok == 0 || outLen != expOutLen {
panic(fail("EVP_AEAD_CTX_seal"))
}
return dst[:n+int(outLen)]
panic("cipher: invalid buffer overlap")
}
- outLen := C.size_t(len(ciphertext) - gcmTagSize)
- ok := C.EVP_AEAD_CTX_open_wrapper(
+ var outLen C.size_t
+ expOutLen := C.size_t(len(ciphertext) - gcmTagSize)
+ ok := C._goboringcrypto_EVP_AEAD_CTX_open(
&g.ctx,
- base(dst[n:]), outLen,
+ base(dst[n:]), &outLen, expOutLen,
base(nonce), C.size_t(len(nonce)),
base(ciphertext), C.size_t(len(ciphertext)),
base(additionalData), C.size_t(len(additionalData)))
runtime.KeepAlive(g)
- if ok == 0 {
+ if ok == 0 || outLen != expOutLen {
return nil, errOpen
}
return dst[:n+int(outLen)], nil