crypto/internal/boring: use noescape and nocallback cgo directives

The new noescape and nocallback directives can be used instead of the C
wrapper functions that are there just to avoid some parameters being
escaped to the heap.

This CL also helps demonstrate the use of the new directives in real
code.

I've added some benchmarks to demonstrate that this CL doesn't
introduce new heap allocations when using boringcrypto:

```
goos: linux
goarch: amd64
pkg: crypto/aes
cpu: AMD EPYC 7763 64-Core Processor
BenchmarkGCMSeal-32    	 8378692	       143.3 ns/op	 111.65 MB/s	       0 B/op	       0 allocs/op
BenchmarkGCMOpen-32    	 8383038	       142.7 ns/op	 112.11 MB/s	       0 B/op	       0 allocs/op
```

Change-Id: Ifd775484eb9a105afc5c3d4e75a6c6655cbadc53
Reviewed-on: https://go-review.googlesource.com/c/go/+/525035
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Bryan Mills <bcmills@google.com>
Run-TryBot: Quim Muntal <quimmuntal@gmail.com>
Reviewed-by: Roland Shoemaker <roland@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
diff --git a/src/crypto/cipher/gcm_test.go b/src/crypto/cipher/gcm_test.go
index 3556146..7b9d185 100644
--- a/src/crypto/cipher/gcm_test.go
+++ b/src/crypto/cipher/gcm_test.go
@@ -654,3 +654,39 @@
 		}
 	}
 }
+
+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)
+		}
+	}
+}
diff --git a/src/crypto/internal/boring/aes.go b/src/crypto/internal/boring/aes.go
index 8819f57..9520bb0 100644
--- a/src/crypto/internal/boring/aes.go
+++ b/src/crypto/internal/boring/aes.go
@@ -7,40 +7,11 @@
 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 (
@@ -318,15 +289,16 @@
 		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)]
@@ -357,15 +329,16 @@
 		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