da5459
From c48714e522ea147e49b0d0dfddf58a9b47137055 Mon Sep 17 00:00:00 2001
da5459
From: =?UTF-8?q?Miloslav=20Trma=C4=8D?= <mitr@redhat.com>
da5459
Date: Thu, 20 Feb 2020 19:51:27 +0100
da5459
Subject: [PATCH 1/3] Update to github.com/mtrmac/gpgme v0.1.2
da5459
MIME-Version: 1.0
da5459
Content-Type: text/plain; charset=UTF-8
da5459
Content-Transfer-Encoding: 8bit
da5459
da5459
This fixes CVE-2020-8945 by incorporating proglottis/gpgme#23 .
da5459
da5459
Other changes included by the rebase:
da5459
- Support for gpgme_off_t (~no-op on Linux)
da5459
- Wrapping a few more GPGME functions (irrelevant if we don't call them)
da5459
da5459
Given how invasive the CVE fix is (affecting basically all binding
da5459
code), it seems safer to just update the package (and be verifiably
da5459
equivalent with upstream) than to backport and try to back out the few
da5459
other changes.
da5459
da5459
Performed by
da5459
$ go get github.com/mtrmac/gpgme@v0.1.2
da5459
$ make vendor
da5459
and manually backing out unrelated deletions of files (which Go 1.13 does
da5459
but Go 1.11, used for testing the old version, does not).
da5459
da5459
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
da5459
---
da5459
 go.mod                                        |   1 +
da5459
 go.sum                                        |   2 +
da5459
 vendor/github.com/mtrmac/gpgme/.appveyor.yml  |  40 ++
da5459
 vendor/github.com/mtrmac/gpgme/.travis.yml    |  32 ++
da5459
 vendor/github.com/mtrmac/gpgme/data.go        |  18 +-
da5459
 vendor/github.com/mtrmac/gpgme/go.mod         |   3 +
da5459
 vendor/github.com/mtrmac/gpgme/go_gpgme.c     |  22 ++
da5459
 vendor/github.com/mtrmac/gpgme/go_gpgme.h     |  12 +
da5459
 vendor/github.com/mtrmac/gpgme/gpgme.go       | 346 ++++++++++++++----
da5459
 .../mtrmac/gpgme/unset_agent_info.go          |  18 +
da5459
 .../mtrmac/gpgme/unset_agent_info_windows.go  |  14 +
da5459
 vendor/modules.txt                            |   2 +-
da5459
 12 files changed, 432 insertions(+), 78 deletions(-)
da5459
 create mode 100644 vendor/github.com/mtrmac/gpgme/.appveyor.yml
da5459
 create mode 100644 vendor/github.com/mtrmac/gpgme/.travis.yml
da5459
 create mode 100644 vendor/github.com/mtrmac/gpgme/go.mod
da5459
 create mode 100644 vendor/github.com/mtrmac/gpgme/unset_agent_info.go
da5459
 create mode 100644 vendor/github.com/mtrmac/gpgme/unset_agent_info_windows.go
da5459
da5459
diff --git a/vendor/github.com/mtrmac/gpgme/.appveyor.yml b/vendor/github.com/mtrmac/gpgme/.appveyor.yml
da5459
new file mode 100644
da5459
index 000000000..2fdc09ab5
da5459
--- /dev/null
da5459
+++ b/vendor/github.com/mtrmac/gpgme/.appveyor.yml
da5459
@@ -0,0 +1,40 @@
da5459
+---
da5459
+version: 0.{build}
da5459
+platform: x86
da5459
+branches:
da5459
+  only:
da5459
+    - master
da5459
+
da5459
+clone_folder: c:\gopath\src\github.com\proglottis\gpgme
da5459
+
da5459
+environment:   
da5459
+  GOPATH: c:\gopath
da5459
+  GOROOT: C:\go-x86
da5459
+  CGO_LDFLAGS: -LC:\gpg\lib
da5459
+  CGO_CFLAGS: -IC:\gpg\include
da5459
+  GPG_DIR: C:\gpg
da5459
+
da5459
+install:
da5459
+  - nuget install 7ZipCLI -ExcludeVersion
da5459
+  - set PATH=%appveyor_build_folder%\7ZipCLI\tools;%PATH%
da5459
+  - appveyor DownloadFile https://www.gnupg.org/ftp/gcrypt/binary/gnupg-w32-2.1.20_20170403.exe -FileName gnupg-w32-2.1.20_20170403.exe
da5459
+  - 7z x -o%GPG_DIR% gnupg-w32-2.1.20_20170403.exe
da5459
+  - copy "%GPG_DIR%\lib\libgpg-error.imp" "%GPG_DIR%\lib\libgpg-error.a"
da5459
+  - copy "%GPG_DIR%\lib\libassuan.imp" "%GPG_DIR%\lib\libassuan.a"
da5459
+  - copy "%GPG_DIR%\lib\libgpgme.imp" "%GPG_DIR%\lib\libgpgme.a"
da5459
+  - set PATH=%GOPATH%\bin;%GOROOT%\bin;%GPG_DIR%\bin;C:\MinGW\bin;%PATH%
da5459
+  - C:\cygwin\bin\sed -i 's/"GPG_AGENT_INFO"/"GPG_AGENT_INFO="/;s/C.unsetenv(v)/C.putenv(v)/' %APPVEYOR_BUILD_FOLDER%\gpgme.go
da5459
+
da5459
+test_script:
da5459
+  - go test -v github.com/proglottis/gpgme
da5459
+
da5459
+
da5459
+build_script:
da5459
+  - go build -o example_decrypt.exe -i %APPVEYOR_BUILD_FOLDER%\examples\decrypt.go
da5459
+  - go build -o example_encrypt.exe -i %APPVEYOR_BUILD_FOLDER%\examples\encrypt.go
da5459
+
da5459
+artifacts:
da5459
+  - path: example_decrypt.exe
da5459
+    name: decrypt example binary
da5459
+  - path: example_encrypt.exe
da5459
+    name: encrypt example binary
da5459
\ No newline at end of file
da5459
diff --git a/vendor/github.com/mtrmac/gpgme/.travis.yml b/vendor/github.com/mtrmac/gpgme/.travis.yml
da5459
new file mode 100644
da5459
index 000000000..619e33721
da5459
--- /dev/null
da5459
+++ b/vendor/github.com/mtrmac/gpgme/.travis.yml
da5459
@@ -0,0 +1,32 @@
da5459
+---
da5459
+language: go
da5459
+os:
da5459
+  - linux
da5459
+  - osx
da5459
+  - windows
da5459
+dist: xenial
da5459
+sudo: false
da5459
+
da5459
+go:
da5459
+  - 1.11
da5459
+  - 1.12
da5459
+  - 1.13
da5459
+
da5459
+addons:
da5459
+  apt:
da5459
+    packages:
da5459
+    - libgpgme11-dev
da5459
+  homebrew:
da5459
+    packages:
da5459
+    - gnupg
da5459
+    - gnupg@1.4
da5459
+    - gpgme
da5459
+    update: true
da5459
+
da5459
+matrix:
da5459
+  allow_failures:
da5459
+    - os: windows
da5459
+
da5459
+before_install:
da5459
+  - if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then choco install msys2; fi
da5459
+  - if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then choco install gpg4win; fi
da5459
diff --git a/vendor/github.com/mtrmac/gpgme/data.go b/vendor/github.com/mtrmac/gpgme/data.go
da5459
index eebc97263..eee32c032 100644
da5459
--- a/vendor/github.com/mtrmac/gpgme/data.go
da5459
+++ b/vendor/github.com/mtrmac/gpgme/data.go
da5459
@@ -50,25 +50,25 @@ func gogpgme_writefunc(handle, buffer unsafe.Pointer, size C.size_t) C.ssize_t {
da5459
 }
da5459
 
da5459
 //export gogpgme_seekfunc
da5459
-func gogpgme_seekfunc(handle unsafe.Pointer, offset C.off_t, whence C.int) C.off_t {
da5459
+func gogpgme_seekfunc(handle unsafe.Pointer, offset C.gpgme_off_t, whence C.int) C.gpgme_off_t {
da5459
 	d := callbackLookup(uintptr(handle)).(*Data)
da5459
 	n, err := d.s.Seek(int64(offset), int(whence))
da5459
 	if err != nil {
da5459
 		C.gpgme_err_set_errno(C.EIO)
da5459
 		return -1
da5459
 	}
da5459
-	return C.off_t(n)
da5459
+	return C.gpgme_off_t(n)
da5459
 }
da5459
 
da5459
 // The Data buffer used to communicate with GPGME
da5459
 type Data struct {
da5459
-	dh  C.gpgme_data_t
da5459
+	dh  C.gpgme_data_t // WARNING: Call runtime.KeepAlive(d) after ANY passing of d.dh to C
da5459
 	buf []byte
da5459
 	cbs C.struct_gpgme_data_cbs
da5459
 	r   io.Reader
da5459
 	w   io.Writer
da5459
 	s   io.Seeker
da5459
-	cbc uintptr
da5459
+	cbc uintptr // WARNING: Call runtime.KeepAlive(d) after ANY use of d.cbc in C (typically via d.dh)
da5459
 }
da5459
 
da5459
 func newData() *Data {
da5459
@@ -154,12 +154,14 @@ func (d *Data) Close() error {
da5459
 		callbackDelete(d.cbc)
da5459
 	}
da5459
 	_, err := C.gpgme_data_release(d.dh)
da5459
+	runtime.KeepAlive(d)
da5459
 	d.dh = nil
da5459
 	return err
da5459
 }
da5459
 
da5459
 func (d *Data) Write(p []byte) (int, error) {
da5459
 	n, err := C.gpgme_data_write(d.dh, unsafe.Pointer(&p[0]), C.size_t(len(p)))
da5459
+	runtime.KeepAlive(d)
da5459
 	if err != nil {
da5459
 		return 0, err
da5459
 	}
da5459
@@ -171,6 +173,7 @@ func (d *Data) Write(p []byte) (int, error) {
da5459
 
da5459
 func (d *Data) Read(p []byte) (int, error) {
da5459
 	n, err := C.gpgme_data_read(d.dh, unsafe.Pointer(&p[0]), C.size_t(len(p)))
da5459
+	runtime.KeepAlive(d)
da5459
 	if err != nil {
da5459
 		return 0, err
da5459
 	}
da5459
@@ -181,11 +184,14 @@ func (d *Data) Read(p []byte) (int, error) {
da5459
 }
da5459
 
da5459
 func (d *Data) Seek(offset int64, whence int) (int64, error) {
da5459
-	n, err := C.gpgme_data_seek(d.dh, C.off_t(offset), C.int(whence))
da5459
+	n, err := C.gogpgme_data_seek(d.dh, C.gpgme_off_t(offset), C.int(whence))
da5459
+	runtime.KeepAlive(d)
da5459
 	return int64(n), err
da5459
 }
da5459
 
da5459
 // Name returns the associated filename if any
da5459
 func (d *Data) Name() string {
da5459
-	return C.GoString(C.gpgme_data_get_file_name(d.dh))
da5459
+	res := C.GoString(C.gpgme_data_get_file_name(d.dh))
da5459
+	runtime.KeepAlive(d)
da5459
+	return res
da5459
 }
da5459
diff --git a/vendor/github.com/mtrmac/gpgme/go.mod b/vendor/github.com/mtrmac/gpgme/go.mod
da5459
new file mode 100644
da5459
index 000000000..3dd09c9fb
da5459
--- /dev/null
da5459
+++ b/vendor/github.com/mtrmac/gpgme/go.mod
da5459
@@ -0,0 +1,3 @@
da5459
+module github.com/mtrmac/gpgme
da5459
+
da5459
+go 1.11
da5459
diff --git a/vendor/github.com/mtrmac/gpgme/go_gpgme.c b/vendor/github.com/mtrmac/gpgme/go_gpgme.c
da5459
index b887574e0..00da3ab30 100644
da5459
--- a/vendor/github.com/mtrmac/gpgme/go_gpgme.c
da5459
+++ b/vendor/github.com/mtrmac/gpgme/go_gpgme.c
da5459
@@ -8,6 +8,28 @@ void gogpgme_set_passphrase_cb(gpgme_ctx_t ctx, gpgme_passphrase_cb_t cb, uintpt
da5459
 	gpgme_set_passphrase_cb(ctx, cb, (void *)handle);
da5459
 }
da5459
 
da5459
+gpgme_off_t gogpgme_data_seek(gpgme_data_t dh, gpgme_off_t offset, int whence) {
da5459
+	return gpgme_data_seek(dh, offset, whence);
da5459
+}
da5459
+
da5459
+gpgme_error_t gogpgme_op_assuan_transact_ext(
da5459
+		gpgme_ctx_t ctx,
da5459
+		char* cmd,
da5459
+		uintptr_t data_h,
da5459
+		uintptr_t inquiry_h,
da5459
+		uintptr_t status_h,
da5459
+		gpgme_error_t *operr
da5459
+	){
da5459
+	return gpgme_op_assuan_transact_ext(
da5459
+		ctx,
da5459
+		cmd,
da5459
+		(gpgme_assuan_data_cb_t)    gogpgme_assuan_data_callback,    (void *)data_h,
da5459
+		(gpgme_assuan_inquire_cb_t) gogpgme_assuan_inquiry_callback, (void *)inquiry_h,
da5459
+		(gpgme_assuan_status_cb_t)  gogpgme_assuan_status_callback,  (void *)status_h,
da5459
+		operr
da5459
+	);
da5459
+}
da5459
+
da5459
 unsigned int key_revoked(gpgme_key_t k) {
da5459
 	return k->revoked;
da5459
 }
da5459
diff --git a/vendor/github.com/mtrmac/gpgme/go_gpgme.h b/vendor/github.com/mtrmac/gpgme/go_gpgme.h
da5459
index a3678b127..d4826ab36 100644
da5459
--- a/vendor/github.com/mtrmac/gpgme/go_gpgme.h
da5459
+++ b/vendor/github.com/mtrmac/gpgme/go_gpgme.h
da5459
@@ -6,12 +6,24 @@
da5459
 
da5459
 #include <gpgme.h>
da5459
 
da5459
+/* GPGME_VERSION_NUMBER was introduced in 1.4.0 */
da5459
+#if !defined(GPGME_VERSION_NUMBER) || GPGME_VERSION_NUMBER < 0x010402
da5459
+typedef off_t gpgme_off_t; /* Introduced in 1.4.2 */
da5459
+#endif
da5459
+
da5459
 extern ssize_t gogpgme_readfunc(void *handle, void *buffer, size_t size);
da5459
 extern ssize_t gogpgme_writefunc(void *handle, void *buffer, size_t size);
da5459
 extern off_t gogpgme_seekfunc(void *handle, off_t offset, int whence);
da5459
 extern gpgme_error_t gogpgme_passfunc(void *hook, char *uid_hint, char *passphrase_info, int prev_was_bad, int fd);
da5459
 extern gpgme_error_t gogpgme_data_new_from_cbs(gpgme_data_t *dh, gpgme_data_cbs_t cbs, uintptr_t handle);
da5459
 extern void gogpgme_set_passphrase_cb(gpgme_ctx_t ctx, gpgme_passphrase_cb_t cb, uintptr_t handle);
da5459
+extern gpgme_off_t gogpgme_data_seek(gpgme_data_t dh, gpgme_off_t offset, int whence);
da5459
+
da5459
+extern gpgme_error_t gogpgme_op_assuan_transact_ext(gpgme_ctx_t ctx, char *cmd, uintptr_t data_h, uintptr_t inquiry_h , uintptr_t status_h, gpgme_error_t *operr);
da5459
+
da5459
+extern gpgme_error_t gogpgme_assuan_data_callback(void *opaque, void* data, size_t datalen );
da5459
+extern gpgme_error_t gogpgme_assuan_inquiry_callback(void *opaque, char* name, char* args);
da5459
+extern gpgme_error_t gogpgme_assuan_status_callback(void *opaque, char* status, char* args);
da5459
 
da5459
 extern unsigned int key_revoked(gpgme_key_t k);
da5459
 extern unsigned int key_expired(gpgme_key_t k);
da5459
diff --git a/vendor/github.com/mtrmac/gpgme/gpgme.go b/vendor/github.com/mtrmac/gpgme/gpgme.go
da5459
index 20aad737c..c19b9aebc 100644
da5459
--- a/vendor/github.com/mtrmac/gpgme/gpgme.go
da5459
+++ b/vendor/github.com/mtrmac/gpgme/gpgme.go
da5459
@@ -7,7 +7,6 @@ package gpgme
da5459
 // #include <gpgme.h>
da5459
 // #include "go_gpgme.h"
da5459
 import "C"
da5459
-
da5459
 import (
da5459
 	"fmt"
da5459
 	"io"
da5459
@@ -48,9 +47,8 @@ const (
da5459
 	ProtocolAssuan   Protocol = C.GPGME_PROTOCOL_ASSUAN
da5459
 	ProtocolG13      Protocol = C.GPGME_PROTOCOL_G13
da5459
 	ProtocolUIServer Protocol = C.GPGME_PROTOCOL_UISERVER
da5459
-	// ProtocolSpawn    Protocol = C.GPGME_PROTOCOL_SPAWN // Unavailable in 1.4.3
da5459
-	ProtocolDefault Protocol = C.GPGME_PROTOCOL_DEFAULT
da5459
-	ProtocolUnknown Protocol = C.GPGME_PROTOCOL_UNKNOWN
da5459
+	ProtocolDefault  Protocol = C.GPGME_PROTOCOL_DEFAULT
da5459
+	ProtocolUnknown  Protocol = C.GPGME_PROTOCOL_UNKNOWN
da5459
 )
da5459
 
da5459
 type PinEntryMode int
da5459
@@ -70,7 +68,6 @@ const (
da5459
 	EncryptNoEncryptTo EncryptFlag = C.GPGME_ENCRYPT_NO_ENCRYPT_TO
da5459
 	EncryptPrepare     EncryptFlag = C.GPGME_ENCRYPT_PREPARE
da5459
 	EncryptExceptSign  EncryptFlag = C.GPGME_ENCRYPT_EXPECT_SIGN
da5459
-	// EncryptNoCompress  EncryptFlag = C.GPGME_ENCRYPT_NO_COMPRESS // Unavailable in 1.4.3
da5459
 )
da5459
 
da5459
 type HashAlgo int
da5459
@@ -84,7 +81,6 @@ const (
da5459
 	KeyListModeExtern       KeyListMode = C.GPGME_KEYLIST_MODE_EXTERN
da5459
 	KeyListModeSigs         KeyListMode = C.GPGME_KEYLIST_MODE_SIGS
da5459
 	KeyListModeSigNotations KeyListMode = C.GPGME_KEYLIST_MODE_SIG_NOTATIONS
da5459
-	// KeyListModeWithSecret   KeyListMode = C.GPGME_KEYLIST_MODE_WITH_SECRET // Unavailable in 1.4.3
da5459
 	KeyListModeEphemeral    KeyListMode = C.GPGME_KEYLIST_MODE_EPHEMERAL
da5459
 	KeyListModeModeValidate KeyListMode = C.GPGME_KEYLIST_MODE_VALIDATE
da5459
 )
da5459
@@ -168,39 +164,60 @@ func EngineCheckVersion(p Protocol) error {
da5459
 }
da5459
 
da5459
 type EngineInfo struct {
da5459
-	info C.gpgme_engine_info_t
da5459
+	next            *EngineInfo
da5459
+	protocol        Protocol
da5459
+	fileName        string
da5459
+	homeDir         string
da5459
+	version         string
da5459
+	requiredVersion string
da5459
 }
da5459
 
da5459
-func (e *EngineInfo) Next() *EngineInfo {
da5459
-	if e.info.next == nil {
da5459
-		return nil
da5459
+func copyEngineInfo(info C.gpgme_engine_info_t) *EngineInfo {
da5459
+	res := &EngineInfo{
da5459
+		next:            nil,
da5459
+		protocol:        Protocol(info.protocol),
da5459
+		fileName:        C.GoString(info.file_name),
da5459
+		homeDir:         C.GoString(info.home_dir),
da5459
+		version:         C.GoString(info.version),
da5459
+		requiredVersion: C.GoString(info.req_version),
da5459
+	}
da5459
+	if info.next != nil {
da5459
+		res.next = copyEngineInfo(info.next)
da5459
 	}
da5459
-	return &EngineInfo{info: e.info.next}
da5459
+	return res
da5459
+}
da5459
+
da5459
+func (e *EngineInfo) Next() *EngineInfo {
da5459
+	return e.next
da5459
 }
da5459
 
da5459
 func (e *EngineInfo) Protocol() Protocol {
da5459
-	return Protocol(e.info.protocol)
da5459
+	return e.protocol
da5459
 }
da5459
 
da5459
 func (e *EngineInfo) FileName() string {
da5459
-	return C.GoString(e.info.file_name)
da5459
+	return e.fileName
da5459
 }
da5459
 
da5459
 func (e *EngineInfo) Version() string {
da5459
-	return C.GoString(e.info.version)
da5459
+	return e.version
da5459
 }
da5459
 
da5459
 func (e *EngineInfo) RequiredVersion() string {
da5459
-	return C.GoString(e.info.req_version)
da5459
+	return e.requiredVersion
da5459
 }
da5459
 
da5459
 func (e *EngineInfo) HomeDir() string {
da5459
-	return C.GoString(e.info.home_dir)
da5459
+	return e.homeDir
da5459
 }
da5459
 
da5459
 func GetEngineInfo() (*EngineInfo, error) {
da5459
-	info := &EngineInfo{}
da5459
-	return info, handleError(C.gpgme_get_engine_info(&info.info))
da5459
+	var cInfo C.gpgme_engine_info_t
da5459
+	err := handleError(C.gpgme_get_engine_info(&cInfo))
da5459
+	if err != nil {
da5459
+		return nil, err
da5459
+	}
da5459
+	return copyEngineInfo(cInfo), nil // It is up to the caller not to invalidate cInfo concurrently until this is done.
da5459
 }
da5459
 
da5459
 func SetEngineInfo(proto Protocol, fileName, homeDir string) error {
da5459
@@ -261,9 +278,9 @@ type Context struct {
da5459
 	KeyError error
da5459
 
da5459
 	callback Callback
da5459
-	cbc      uintptr
da5459
+	cbc      uintptr // WARNING: Call runtime.KeepAlive(c) after ANY use of c.cbc in C (typically via c.ctx)
da5459
 
da5459
-	ctx C.gpgme_ctx_t
da5459
+	ctx C.gpgme_ctx_t // WARNING: Call runtime.KeepAlive(c) after ANY passing of c.ctx to C
da5459
 }
da5459
 
da5459
 func New() (*Context, error) {
da5459
@@ -281,49 +298,68 @@ func (c *Context) Release() {
da5459
 		callbackDelete(c.cbc)
da5459
 	}
da5459
 	C.gpgme_release(c.ctx)
da5459
+	runtime.KeepAlive(c)
da5459
 	c.ctx = nil
da5459
 }
da5459
 
da5459
 func (c *Context) SetArmor(yes bool) {
da5459
 	C.gpgme_set_armor(c.ctx, cbool(yes))
da5459
+	runtime.KeepAlive(c)
da5459
 }
da5459
 
da5459
 func (c *Context) Armor() bool {
da5459
-	return C.gpgme_get_armor(c.ctx) != 0
da5459
+	res := C.gpgme_get_armor(c.ctx) != 0
da5459
+	runtime.KeepAlive(c)
da5459
+	return res
da5459
 }
da5459
 
da5459
 func (c *Context) SetTextMode(yes bool) {
da5459
 	C.gpgme_set_textmode(c.ctx, cbool(yes))
da5459
+	runtime.KeepAlive(c)
da5459
 }
da5459
 
da5459
 func (c *Context) TextMode() bool {
da5459
-	return C.gpgme_get_textmode(c.ctx) != 0
da5459
+	res := C.gpgme_get_textmode(c.ctx) != 0
da5459
+	runtime.KeepAlive(c)
da5459
+	return res
da5459
 }
da5459
 
da5459
 func (c *Context) SetProtocol(p Protocol) error {
da5459
-	return handleError(C.gpgme_set_protocol(c.ctx, C.gpgme_protocol_t(p)))
da5459
+	err := handleError(C.gpgme_set_protocol(c.ctx, C.gpgme_protocol_t(p)))
da5459
+	runtime.KeepAlive(c)
da5459
+	return err
da5459
 }
da5459
 
da5459
 func (c *Context) Protocol() Protocol {
da5459
-	return Protocol(C.gpgme_get_protocol(c.ctx))
da5459
+	res := Protocol(C.gpgme_get_protocol(c.ctx))
da5459
+	runtime.KeepAlive(c)
da5459
+	return res
da5459
 }
da5459
 
da5459
 func (c *Context) SetKeyListMode(m KeyListMode) error {
da5459
-	return handleError(C.gpgme_set_keylist_mode(c.ctx, C.gpgme_keylist_mode_t(m)))
da5459
+	err := handleError(C.gpgme_set_keylist_mode(c.ctx, C.gpgme_keylist_mode_t(m)))
da5459
+	runtime.KeepAlive(c)
da5459
+	return err
da5459
 }
da5459
 
da5459
 func (c *Context) KeyListMode() KeyListMode {
da5459
-	return KeyListMode(C.gpgme_get_keylist_mode(c.ctx))
da5459
+	res := KeyListMode(C.gpgme_get_keylist_mode(c.ctx))
da5459
+	runtime.KeepAlive(c)
da5459
+	return res
da5459
 }
da5459
 
da5459
 // Unavailable in 1.3.2:
da5459
 // func (c *Context) SetPinEntryMode(m PinEntryMode) error {
da5459
-// 	return handleError(C.gpgme_set_pinentry_mode(c.ctx, C.gpgme_pinentry_mode_t(m)))
da5459
+// 	err := handleError(C.gpgme_set_pinentry_mode(c.ctx, C.gpgme_pinentry_mode_t(m)))
da5459
+// 	runtime.KeepAlive(c)
da5459
+// 	return err
da5459
 // }
da5459
 
da5459
 // Unavailable in 1.3.2:
da5459
 // func (c *Context) PinEntryMode() PinEntryMode {
da5459
-// 	return PinEntryMode(C.gpgme_get_pinentry_mode(c.ctx))
da5459
+// 	res := PinEntryMode(C.gpgme_get_pinentry_mode(c.ctx))
da5459
+// 	runtime.KeepAlive(c)
da5459
+// 	return res
da5459
 // }
da5459
 
da5459
 func (c *Context) SetCallback(callback Callback) error {
da5459
@@ -340,11 +376,17 @@ func (c *Context) SetCallback(callback Callback) error {
da5459
 		c.cbc = 0
da5459
 		_, err = C.gogpgme_set_passphrase_cb(c.ctx, nil, 0)
da5459
 	}
da5459
+	runtime.KeepAlive(c)
da5459
 	return err
da5459
 }
da5459
 
da5459
 func (c *Context) EngineInfo() *EngineInfo {
da5459
-	return &EngineInfo{info: C.gpgme_ctx_get_engine_info(c.ctx)}
da5459
+	cInfo := C.gpgme_ctx_get_engine_info(c.ctx)
da5459
+	runtime.KeepAlive(c)
da5459
+	// NOTE: c must be live as long as we are accessing cInfo.
da5459
+	res := copyEngineInfo(cInfo)
da5459
+	runtime.KeepAlive(c) // for accesses to cInfo
da5459
+	return res
da5459
 }
da5459
 
da5459
 func (c *Context) SetEngineInfo(proto Protocol, fileName, homeDir string) error {
da5459
@@ -357,19 +399,23 @@ func (c *Context) SetEngineInfo(proto Protocol, fileName, homeDir string) error
da5459
 		chome = C.CString(homeDir)
da5459
 		defer C.free(unsafe.Pointer(chome))
da5459
 	}
da5459
-	return handleError(C.gpgme_ctx_set_engine_info(c.ctx, C.gpgme_protocol_t(proto), cfn, chome))
da5459
+	err := handleError(C.gpgme_ctx_set_engine_info(c.ctx, C.gpgme_protocol_t(proto), cfn, chome))
da5459
+	runtime.KeepAlive(c)
da5459
+	return err
da5459
 }
da5459
 
da5459
 func (c *Context) KeyListStart(pattern string, secretOnly bool) error {
da5459
 	cpattern := C.CString(pattern)
da5459
 	defer C.free(unsafe.Pointer(cpattern))
da5459
-	err := C.gpgme_op_keylist_start(c.ctx, cpattern, cbool(secretOnly))
da5459
-	return handleError(err)
da5459
+	err := handleError(C.gpgme_op_keylist_start(c.ctx, cpattern, cbool(secretOnly)))
da5459
+	runtime.KeepAlive(c)
da5459
+	return err
da5459
 }
da5459
 
da5459
 func (c *Context) KeyListNext() bool {
da5459
 	c.Key = newKey()
da5459
 	err := handleError(C.gpgme_op_keylist_next(c.ctx, &c.Key.k))
da5459
+	runtime.KeepAlive(c) // implies runtime.KeepAlive(c.Key)
da5459
 	if err != nil {
da5459
 		if e, ok := err.(Error); ok && e.Code() == ErrorEOF {
da5459
 			c.KeyError = nil
da5459
@@ -383,7 +429,9 @@ func (c *Context) KeyListNext() bool {
da5459
 }
da5459
 
da5459
 func (c *Context) KeyListEnd() error {
da5459
-	return handleError(C.gpgme_op_keylist_end(c.ctx))
da5459
+	err := handleError(C.gpgme_op_keylist_end(c.ctx))
da5459
+	runtime.KeepAlive(c)
da5459
+	return err
da5459
 }
da5459
 
da5459
 func (c *Context) GetKey(fingerprint string, secret bool) (*Key, error) {
da5459
@@ -391,7 +439,11 @@ func (c *Context) GetKey(fingerprint string, secret bool) (*Key, error) {
da5459
 	cfpr := C.CString(fingerprint)
da5459
 	defer C.free(unsafe.Pointer(cfpr))
da5459
 	err := handleError(C.gpgme_get_key(c.ctx, cfpr, &key.k, cbool(secret)))
da5459
-	if e, ok := err.(Error); key.k == nil && ok && e.Code() == ErrorEOF {
da5459
+	runtime.KeepAlive(c)
da5459
+	runtime.KeepAlive(key)
da5459
+	keyKIsNil := key.k == nil
da5459
+	runtime.KeepAlive(key)
da5459
+	if e, ok := err.(Error); keyKIsNil && ok && e.Code() == ErrorEOF {
da5459
 		return nil, fmt.Errorf("key %q not found", fingerprint)
da5459
 	}
da5459
 	if err != nil {
da5459
@@ -401,11 +453,19 @@ func (c *Context) GetKey(fingerprint string, secret bool) (*Key, error) {
da5459
 }
da5459
 
da5459
 func (c *Context) Decrypt(ciphertext, plaintext *Data) error {
da5459
-	return handleError(C.gpgme_op_decrypt(c.ctx, ciphertext.dh, plaintext.dh))
da5459
+	err := handleError(C.gpgme_op_decrypt(c.ctx, ciphertext.dh, plaintext.dh))
da5459
+	runtime.KeepAlive(c)
da5459
+	runtime.KeepAlive(ciphertext)
da5459
+	runtime.KeepAlive(plaintext)
da5459
+	return err
da5459
 }
da5459
 
da5459
 func (c *Context) DecryptVerify(ciphertext, plaintext *Data) error {
da5459
-	return handleError(C.gpgme_op_decrypt_verify(c.ctx, ciphertext.dh, plaintext.dh))
da5459
+	err := handleError(C.gpgme_op_decrypt_verify(c.ctx, ciphertext.dh, plaintext.dh))
da5459
+	runtime.KeepAlive(c)
da5459
+	runtime.KeepAlive(ciphertext)
da5459
+	runtime.KeepAlive(plaintext)
da5459
+	return err
da5459
 }
da5459
 
da5459
 type Signature struct {
da5459
@@ -432,10 +492,20 @@ func (c *Context) Verify(sig, signedText, plain *Data) (string, []Signature, err
da5459
 		plainPtr = plain.dh
da5459
 	}
da5459
 	err := handleError(C.gpgme_op_verify(c.ctx, sig.dh, signedTextPtr, plainPtr))
da5459
+	runtime.KeepAlive(c)
da5459
+	runtime.KeepAlive(sig)
da5459
+	if signedText != nil {
da5459
+		runtime.KeepAlive(signedText)
da5459
+	}
da5459
+	if plain != nil {
da5459
+		runtime.KeepAlive(plain)
da5459
+	}
da5459
 	if err != nil {
da5459
 		return "", nil, err
da5459
 	}
da5459
 	res := C.gpgme_op_verify_result(c.ctx)
da5459
+	runtime.KeepAlive(c)
da5459
+	// NOTE: c must be live as long as we are accessing res.
da5459
 	sigs := []Signature{}
da5459
 	for s := res.signatures; s != nil; s = s.next {
da5459
 		sig := Signature{
da5459
@@ -455,7 +525,9 @@ func (c *Context) Verify(sig, signedText, plain *Data) (string, []Signature, err
da5459
 		}
da5459
 		sigs = append(sigs, sig)
da5459
 	}
da5459
-	return C.GoString(res.file_name), sigs, nil
da5459
+	fileName := C.GoString(res.file_name)
da5459
+	runtime.KeepAlive(c) // for all accesses to res above
da5459
+	return fileName, sigs, nil
da5459
 }
da5459
 
da5459
 func (c *Context) Encrypt(recipients []*Key, flags EncryptFlag, plaintext, ciphertext *Data) error {
da5459
@@ -467,18 +539,116 @@ func (c *Context) Encrypt(recipients []*Key, flags EncryptFlag, plaintext, ciphe
da5459
 		*ptr = recipients[i].k
da5459
 	}
da5459
 	err := C.gpgme_op_encrypt(c.ctx, (*C.gpgme_key_t)(recp), C.gpgme_encrypt_flags_t(flags), plaintext.dh, ciphertext.dh)
da5459
+	runtime.KeepAlive(c)
da5459
+	runtime.KeepAlive(recipients)
da5459
+	runtime.KeepAlive(plaintext)
da5459
+	runtime.KeepAlive(ciphertext)
da5459
 	return handleError(err)
da5459
 }
da5459
 
da5459
 func (c *Context) Sign(signers []*Key, plain, sig *Data, mode SigMode) error {
da5459
 	C.gpgme_signers_clear(c.ctx)
da5459
+	runtime.KeepAlive(c)
da5459
 	for _, k := range signers {
da5459
-		if err := handleError(C.gpgme_signers_add(c.ctx, k.k)); err != nil {
da5459
+		err := handleError(C.gpgme_signers_add(c.ctx, k.k))
da5459
+		runtime.KeepAlive(c)
da5459
+		runtime.KeepAlive(k)
da5459
+		if err != nil {
da5459
 			C.gpgme_signers_clear(c.ctx)
da5459
+			runtime.KeepAlive(c)
da5459
 			return err
da5459
 		}
da5459
 	}
da5459
-	return handleError(C.gpgme_op_sign(c.ctx, plain.dh, sig.dh, C.gpgme_sig_mode_t(mode)))
da5459
+	err := handleError(C.gpgme_op_sign(c.ctx, plain.dh, sig.dh, C.gpgme_sig_mode_t(mode)))
da5459
+	runtime.KeepAlive(c)
da5459
+	runtime.KeepAlive(plain)
da5459
+	runtime.KeepAlive(sig)
da5459
+	return err
da5459
+}
da5459
+
da5459
+type AssuanDataCallback func(data []byte) error
da5459
+type AssuanInquireCallback func(name, args string) error
da5459
+type AssuanStatusCallback func(status, args string) error
da5459
+
da5459
+// AssuanSend sends a raw Assuan command to gpg-agent
da5459
+func (c *Context) AssuanSend(
da5459
+	cmd string,
da5459
+	data AssuanDataCallback,
da5459
+	inquiry AssuanInquireCallback,
da5459
+	status AssuanStatusCallback,
da5459
+) error {
da5459
+	var operr C.gpgme_error_t
da5459
+
da5459
+	dataPtr := callbackAdd(&data)
da5459
+	inquiryPtr := callbackAdd(&inquiry)
da5459
+	statusPtr := callbackAdd(&status)
da5459
+	cmdCStr := C.CString(cmd)
da5459
+	defer C.free(unsafe.Pointer(cmdCStr))
da5459
+	err := C.gogpgme_op_assuan_transact_ext(
da5459
+		c.ctx,
da5459
+		cmdCStr,
da5459
+		C.uintptr_t(dataPtr),
da5459
+		C.uintptr_t(inquiryPtr),
da5459
+		C.uintptr_t(statusPtr),
da5459
+		&operr,
da5459
+	)
da5459
+	runtime.KeepAlive(c)
da5459
+
da5459
+	if handleError(operr) != nil {
da5459
+		return handleError(operr)
da5459
+	}
da5459
+	return handleError(err)
da5459
+}
da5459
+
da5459
+//export gogpgme_assuan_data_callback
da5459
+func gogpgme_assuan_data_callback(handle unsafe.Pointer, data unsafe.Pointer, datalen C.size_t) C.gpgme_error_t {
da5459
+	c := callbackLookup(uintptr(handle)).(*AssuanDataCallback)
da5459
+	if *c == nil {
da5459
+		return 0
da5459
+	}
da5459
+	(*c)(C.GoBytes(data, C.int(datalen)))
da5459
+	return 0
da5459
+}
da5459
+
da5459
+//export gogpgme_assuan_inquiry_callback
da5459
+func gogpgme_assuan_inquiry_callback(handle unsafe.Pointer, cName *C.char, cArgs *C.char) C.gpgme_error_t {
da5459
+	name := C.GoString(cName)
da5459
+	args := C.GoString(cArgs)
da5459
+	c := callbackLookup(uintptr(handle)).(*AssuanInquireCallback)
da5459
+	if *c == nil {
da5459
+		return 0
da5459
+	}
da5459
+	(*c)(name, args)
da5459
+	return 0
da5459
+}
da5459
+
da5459
+//export gogpgme_assuan_status_callback
da5459
+func gogpgme_assuan_status_callback(handle unsafe.Pointer, cStatus *C.char, cArgs *C.char) C.gpgme_error_t {
da5459
+	status := C.GoString(cStatus)
da5459
+	args := C.GoString(cArgs)
da5459
+	c := callbackLookup(uintptr(handle)).(*AssuanStatusCallback)
da5459
+	if *c == nil {
da5459
+		return 0
da5459
+	}
da5459
+	(*c)(status, args)
da5459
+	return 0
da5459
+}
da5459
+
da5459
+// ExportModeFlags defines how keys are exported from Export
da5459
+type ExportModeFlags uint
da5459
+
da5459
+const (
da5459
+	ExportModeExtern  ExportModeFlags = C.GPGME_EXPORT_MODE_EXTERN
da5459
+	ExportModeMinimal ExportModeFlags = C.GPGME_EXPORT_MODE_MINIMAL
da5459
+)
da5459
+
da5459
+func (c *Context) Export(pattern string, mode ExportModeFlags, data *Data) error {
da5459
+	pat := C.CString(pattern)
da5459
+	defer C.free(unsafe.Pointer(pat))
da5459
+	err := handleError(C.gpgme_op_export(c.ctx, pat, C.gpgme_export_mode_t(mode), data.dh))
da5459
+	runtime.KeepAlive(c)
da5459
+	runtime.KeepAlive(data)
da5459
+	return err
da5459
 }
da5459
 
da5459
 // ImportStatusFlags describes the type of ImportStatus.Status. The C API in gpgme.h simply uses "unsigned".
da5459
@@ -517,10 +687,14 @@ type ImportResult struct {
da5459
 
da5459
 func (c *Context) Import(keyData *Data) (*ImportResult, error) {
da5459
 	err := handleError(C.gpgme_op_import(c.ctx, keyData.dh))
da5459
+	runtime.KeepAlive(c)
da5459
+	runtime.KeepAlive(keyData)
da5459
 	if err != nil {
da5459
 		return nil, err
da5459
 	}
da5459
 	res := C.gpgme_op_import_result(c.ctx)
da5459
+	runtime.KeepAlive(c)
da5459
+	// NOTE: c must be live as long as we are accessing res.
da5459
 	imports := []ImportStatus{}
da5459
 	for s := res.imports; s != nil; s = s.next {
da5459
 		imports = append(imports, ImportStatus{
da5459
@@ -529,7 +703,7 @@ func (c *Context) Import(keyData *Data) (*ImportResult, error) {
da5459
 			Status:      ImportStatusFlags(s.status),
da5459
 		})
da5459
 	}
da5459
-	return &ImportResult{
da5459
+	importResult := &ImportResult{
da5459
 		Considered:      int(res.considered),
da5459
 		NoUserID:        int(res.no_user_id),
da5459
 		Imported:        int(res.imported),
da5459
@@ -544,11 +718,13 @@ func (c *Context) Import(keyData *Data) (*ImportResult, error) {
da5459
 		SecretUnchanged: int(res.secret_unchanged),
da5459
 		NotImported:     int(res.not_imported),
da5459
 		Imports:         imports,
da5459
-	}, nil
da5459
+	}
da5459
+	runtime.KeepAlive(c) // for all accesses to res above
da5459
+	return importResult, nil
da5459
 }
da5459
 
da5459
 type Key struct {
da5459
-	k C.gpgme_key_t
da5459
+	k C.gpgme_key_t // WARNING: Call Runtime.KeepAlive(k) after ANY passing of k.k to C
da5459
 }
da5459
 
da5459
 func newKey() *Key {
da5459
@@ -559,85 +735,122 @@ func newKey() *Key {
da5459
 
da5459
 func (k *Key) Release() {
da5459
 	C.gpgme_key_release(k.k)
da5459
+	runtime.KeepAlive(k)
da5459
 	k.k = nil
da5459
 }
da5459
 
da5459
 func (k *Key) Revoked() bool {
da5459
-	return C.key_revoked(k.k) != 0
da5459
+	res := C.key_revoked(k.k) != 0
da5459
+	runtime.KeepAlive(k)
da5459
+	return res
da5459
 }
da5459
 
da5459
 func (k *Key) Expired() bool {
da5459
-	return C.key_expired(k.k) != 0
da5459
+	res := C.key_expired(k.k) != 0
da5459
+	runtime.KeepAlive(k)
da5459
+	return res
da5459
 }
da5459
 
da5459
 func (k *Key) Disabled() bool {
da5459
-	return C.key_disabled(k.k) != 0
da5459
+	res := C.key_disabled(k.k) != 0
da5459
+	runtime.KeepAlive(k)
da5459
+	return res
da5459
 }
da5459
 
da5459
 func (k *Key) Invalid() bool {
da5459
-	return C.key_invalid(k.k) != 0
da5459
+	res := C.key_invalid(k.k) != 0
da5459
+	runtime.KeepAlive(k)
da5459
+	return res
da5459
 }
da5459
 
da5459
 func (k *Key) CanEncrypt() bool {
da5459
-	return C.key_can_encrypt(k.k) != 0
da5459
+	res := C.key_can_encrypt(k.k) != 0
da5459
+	runtime.KeepAlive(k)
da5459
+	return res
da5459
 }
da5459
 
da5459
 func (k *Key) CanSign() bool {
da5459
-	return C.key_can_sign(k.k) != 0
da5459
+	res := C.key_can_sign(k.k) != 0
da5459
+	runtime.KeepAlive(k)
da5459
+	return res
da5459
 }
da5459
 
da5459
 func (k *Key) CanCertify() bool {
da5459
-	return C.key_can_certify(k.k) != 0
da5459
+	res := C.key_can_certify(k.k) != 0
da5459
+	runtime.KeepAlive(k)
da5459
+	return res
da5459
 }
da5459
 
da5459
 func (k *Key) Secret() bool {
da5459
-	return C.key_secret(k.k) != 0
da5459
+	res := C.key_secret(k.k) != 0
da5459
+	runtime.KeepAlive(k)
da5459
+	return res
da5459
 }
da5459
 
da5459
 func (k *Key) CanAuthenticate() bool {
da5459
-	return C.key_can_authenticate(k.k) != 0
da5459
+	res := C.key_can_authenticate(k.k) != 0
da5459
+	runtime.KeepAlive(k)
da5459
+	return res
da5459
 }
da5459
 
da5459
 func (k *Key) IsQualified() bool {
da5459
-	return C.key_is_qualified(k.k) != 0
da5459
+	res := C.key_is_qualified(k.k) != 0
da5459
+	runtime.KeepAlive(k)
da5459
+	return res
da5459
 }
da5459
 
da5459
 func (k *Key) Protocol() Protocol {
da5459
-	return Protocol(k.k.protocol)
da5459
+	res := Protocol(k.k.protocol)
da5459
+	runtime.KeepAlive(k)
da5459
+	return res
da5459
 }
da5459
 
da5459
 func (k *Key) IssuerSerial() string {
da5459
-	return C.GoString(k.k.issuer_serial)
da5459
+	res := C.GoString(k.k.issuer_serial)
da5459
+	runtime.KeepAlive(k)
da5459
+	return res
da5459
 }
da5459
 
da5459
 func (k *Key) IssuerName() string {
da5459
-	return C.GoString(k.k.issuer_name)
da5459
+	res := C.GoString(k.k.issuer_name)
da5459
+	runtime.KeepAlive(k)
da5459
+	return res
da5459
 }
da5459
 
da5459
 func (k *Key) ChainID() string {
da5459
-	return C.GoString(k.k.chain_id)
da5459
+	res := C.GoString(k.k.chain_id)
da5459
+	runtime.KeepAlive(k)
da5459
+	return res
da5459
 }
da5459
 
da5459
 func (k *Key) OwnerTrust() Validity {
da5459
-	return Validity(k.k.owner_trust)
da5459
+	res := Validity(k.k.owner_trust)
da5459
+	runtime.KeepAlive(k)
da5459
+	return res
da5459
 }
da5459
 
da5459
 func (k *Key) SubKeys() *SubKey {
da5459
-	if k.k.subkeys == nil {
da5459
+	subKeys := k.k.subkeys
da5459
+	runtime.KeepAlive(k)
da5459
+	if subKeys == nil {
da5459
 		return nil
da5459
 	}
da5459
-	return &SubKey{k: k.k.subkeys, parent: k}
da5459
+	return &SubKey{k: subKeys, parent: k} // The parent: k reference ensures subKeys remains valid
da5459
 }
da5459
 
da5459
 func (k *Key) UserIDs() *UserID {
da5459
-	if k.k.uids == nil {
da5459
+	uids := k.k.uids
da5459
+	runtime.KeepAlive(k)
da5459
+	if uids == nil {
da5459
 		return nil
da5459
 	}
da5459
-	return &UserID{u: k.k.uids, parent: k}
da5459
+	return &UserID{u: uids, parent: k} // The parent: k reference ensures uids remains valid
da5459
 }
da5459
 
da5459
 func (k *Key) KeyListMode() KeyListMode {
da5459
-	return KeyListMode(k.k.keylist_mode)
da5459
+	res := KeyListMode(k.k.keylist_mode)
da5459
+	runtime.KeepAlive(k)
da5459
+	return res
da5459
 }
da5459
 
da5459
 type SubKey struct {
da5459
@@ -737,12 +950,3 @@ func (u *UserID) Comment() string {
da5459
 func (u *UserID) Email() string {
da5459
 	return C.GoString(u.u.email)
da5459
 }
da5459
-
da5459
-// This is somewhat of a horrible hack. We need to unset GPG_AGENT_INFO so that gpgme does not pass --use-agent to GPG.
da5459
-// os.Unsetenv should be enough, but that only calls the underlying C library (which gpgme uses) if cgo is involved
da5459
-// - and cgo can't be used in tests. So, provide this helper for test initialization.
da5459
-func unsetenvGPGAgentInfo() {
da5459
-	v := C.CString("GPG_AGENT_INFO")
da5459
-	defer C.free(unsafe.Pointer(v))
da5459
-	C.unsetenv(v)
da5459
-}
da5459
diff --git a/vendor/github.com/mtrmac/gpgme/unset_agent_info.go b/vendor/github.com/mtrmac/gpgme/unset_agent_info.go
da5459
new file mode 100644
da5459
index 000000000..986aca59f
da5459
--- /dev/null
da5459
+++ b/vendor/github.com/mtrmac/gpgme/unset_agent_info.go
da5459
@@ -0,0 +1,18 @@
da5459
+// +build !windows
da5459
+
da5459
+package gpgme
da5459
+
da5459
+// #include <stdlib.h>
da5459
+import "C"
da5459
+import (
da5459
+	"unsafe"
da5459
+)
da5459
+
da5459
+// This is somewhat of a horrible hack. We need to unset GPG_AGENT_INFO so that gpgme does not pass --use-agent to GPG.
da5459
+// os.Unsetenv should be enough, but that only calls the underlying C library (which gpgme uses) if cgo is involved
da5459
+// - and cgo can't be used in tests. So, provide this helper for test initialization.
da5459
+func unsetenvGPGAgentInfo() {
da5459
+	v := C.CString("GPG_AGENT_INFO")
da5459
+	defer C.free(unsafe.Pointer(v))
da5459
+	C.unsetenv(v)
da5459
+}
da5459
diff --git a/vendor/github.com/mtrmac/gpgme/unset_agent_info_windows.go b/vendor/github.com/mtrmac/gpgme/unset_agent_info_windows.go
da5459
new file mode 100644
da5459
index 000000000..431ec86d3
da5459
--- /dev/null
da5459
+++ b/vendor/github.com/mtrmac/gpgme/unset_agent_info_windows.go
da5459
@@ -0,0 +1,14 @@
da5459
+package gpgme
da5459
+
da5459
+// #include <stdlib.h>
da5459
+import "C"
da5459
+import (
da5459
+	"unsafe"
da5459
+)
da5459
+
da5459
+// unsetenv is not available in mingw
da5459
+func unsetenvGPGAgentInfo() {
da5459
+	v := C.CString("GPG_AGENT_INFO=")
da5459
+	defer C.free(unsafe.Pointer(v))
da5459
+	C.putenv(v)
da5459
+}